docs(skills): address AI Usage review comments

Extract the specification version from the skill in the template test,
check the exact placeholder badge URL, and drop duplicate marker and
old-format assertions.

Clarify the highest-level rule and table-header language, remove the
duplicate n/a rule, make the placeholder badge symmetric, and document
how to migrate an old Human and Agent Roles section.
This commit is contained in:
turtle1999
2026-10-19 13:30:25 +08:00
parent 31d8674d5e
commit f24ef669af
3 changed files with 27 additions and 25 deletions
+6 -7
View File
@@ -18,7 +18,7 @@ This skill defines what a deepseek-harness PR description contains, how to write
The description uses four second-level headings, in this order: `## Motivation`, `## Changes`, `## Testing`, and `## AI Usage`.
Write all headings and labels, such as **Interface changes**, **Behavior changes**, **Test design**, and **Test entries**, in English. Write the rest of the description in Chinese unless a human asked for another language for this PR.
Write fixed section headings and labels, such as **Interface changes**, **Behavior changes**, **Test design**, and **Test entries**, in English. Write table headers and the rest of the description in the PR description's language, Chinese unless a human asked for another language.
### Motivation
@@ -131,7 +131,7 @@ Stages appear in a fixed order; each stage pairs an English name with a Chinese
### Badge URLs
The AI-DECLARATION block pins specification version 0.1.2. Use the badge for the highest level among the stage rows; a stage with n/a 暂不适用 does not affect the highest level.
The AI-DECLARATION block pins specification version 0.1.2. Use the badge URL for the level selected in [Section format](#section-format); the badges follow [AI-DECLARATION](https://ai-declaration.md).
| Level | Badge URL |
|---|---|
@@ -141,7 +141,7 @@ The AI-DECLARATION block pins specification version 0.1.2. Use the badge for the
| copilot 人工把关 | `https://img.shields.io/badge/䷼%20AI--DECLARATION-copilot-fee2e2?labelColor=fee2e2` |
| auto 模型自主 | `https://img.shields.io/badge/䷼%20AI--DECLARATION-auto-ede9fe?labelColor=ede9fe` |
When the upstream specification changes, update this version and the version link in the declaration block together.
When the upstream specification changes, update every version reference in this skill and the PR template.
### Section format
@@ -161,10 +161,9 @@ The section starts with the AI-DECLARATION block, followed by one table row per
| <stage English name> <stage Chinese name> | <level English name> <level Chinese name> | <AI involvement> | <description> |
```
- The badge level is the highest level among the stage rows; ignore rows with n/a 暂不适用.
- The badge level is the level with the most AI involvement among the stage rows; ignore rows with n/a 暂不适用. This follows the [specification's rule](https://ai-declaration.md) that the global level is the highest declared level.
- Keep the `ai-declaration` markers so an existing declaration can be replaced in place without duplicating it.
- Write the description in the PR description's language, in one or two sentences of at most 80 Chinese characters or 40 English words. State who made which decisions: name one or two representative decisions, and give only a count for the rest.
- Write `—` for the AI involvement of a stage with n/a 暂不适用.
- State the description as settled fact, without hedges such as "not seen in the session" or "pending author confirmation".
- Refer to people as the author or a reviewer, never by username. Leave out judgments, session times, session ids, direct quotes, and the running or handling of checks and CI (local skips, hooks, reruns, unrelated failures).
@@ -201,5 +200,5 @@ Filled in from the session and review records of #6013:
## Creating and updating the description
1. Write the description to a file that git ignores, such as `.artifacts/pr/body.md`. Create the PR with `gh pr create --body-file <file>`, or update it with `gh pr edit <number> --body-file <file>`; when the description embeds a GIF, follow [record-browser-gif](../record-browser-gif/SKILL.md) and use `--attach`.
2. Before an update, save the current description with `gh pr view <number> --json body --jq .body`, and change only the sections that need it: keep content and media the author wrote, replace only the contents of an existing `ai-declaration` block, and remove statements that no longer match the code.
3. After writing, read the description back and confirm that all four sections are present and that AI Usage matches the current code and review state.
2. Before an update, save the current description with `gh pr view <number> --json body --jq .body`, and change only the sections that need it: keep content and media the author wrote, replace only the contents of an existing `ai-declaration` block, and remove statements that no longer match the code. When the description still has the old `## Human and Agent Roles` heading, replace that heading and its level line with `## AI Usage` and the block; keep only one AI Usage section.
3. After writing, read the description back and confirm that all four sections are present, that AI Usage matches the current code and review state, and that no old `## Human and Agent Roles` section remains.
+20 -17
View File
@@ -218,10 +218,6 @@ test('keeps the pull request template aligned with the dsh-pr-description skill'
'## AI Usage',
])
assert.doesNotMatch(source, /^### /m)
assert.doesNotMatch(source, /<ins>/)
const usageSection = source.slice(source.indexOf('## AI Usage'))
assert.ok(usageSection.includes('<!-- ai-declaration:start -->'), 'the AI declaration block is in AI Usage')
assert.ok(usageSection.includes('| 阶段 | 级别 | AI 参与度 | 决策记录 |'), 'the role table is in AI Usage')
assert.match(source, /^## Motivation\n\n<!-- [^\n]*Fixes #N[^\n]* -->$/m, 'the template prompts for an Issue reference')
assert.match(source, /- <!-- [^\n]+ -->\n\n <details>\n <summary>Proof<\/summary>/)
assert.equal(source.match(/<details>/g)?.length, 1)
@@ -230,7 +226,7 @@ test('keeps the pull request template aligned with the dsh-pr-description skill'
const stagesSection = skill.match(/^### Stages and criteria\n([\s\S]*?)(?=^### )/m)?.[1]
assert.ok(stagesSection, 'the skill has a Stages and criteria section')
const skillStages = [...stagesSection.matchAll(/^\*\*(.+?)\*\*:/gm)].map(([, stage]) => stage)
assert.ok(skillStages.length > 0, 'the skill lists role stages')
assert.ok(skillStages.length > 0, 'the skill lists stages')
for (const stage of skillStages) {
assert.match(stage, /^[a-z]+ [\u4e00-\u9fff]+$/, `stage name pairs one English word with a Chinese name: ${stage}`)
}
@@ -255,7 +251,11 @@ test('keeps the pull request template aligned with the dsh-pr-description skill'
`the skill has the ${level} badge URL`,
)
}
assert.ok(skill.includes('[v0.1.2](https://ai-declaration.md/en/0.1.2)'), 'the skill pins the specification version')
const specVersion = skill.match(/pins specification version (\d+\.\d+\.\d+)/)?.[1]
assert.ok(specVersion, 'the skill pins the specification version')
const versionLink = `[v${specVersion}](https://ai-declaration.md/en/${specVersion})`
assert.ok(skill.includes(versionLink), 'the skill links the pinned specification version')
assert.ok(source.includes(versionLink), 'the template links the pinned specification version')
const sectionFormat = skill.match(/^### Section format\n[\s\S]*?```markdown\n([\s\S]*?)```/m)?.[1]
assert.ok(sectionFormat, 'the skill shows the section format')
@@ -268,7 +268,8 @@ test('keeps the pull request template aligned with the dsh-pr-description skill'
assert.match(markdown, /^## AI Usage$/m, `the ${label} uses the AI Usage heading`)
assert.match(markdown, /^<!-- ai-declaration:start -->$/m, `the ${label} starts the declaration block`)
assert.match(markdown, /^<!-- ai-declaration:end -->$/m, `the ${label} ends the declaration block`)
assert.ok(markdown.includes('| 阶段 | 级别 | AI 参与度 | 决策记录 |'), `the ${label} shows the role table header`)
assert.ok(markdown.includes('| 阶段 | 级别 | AI 参与度 | 决策记录 |'), `the ${label} shows the stage table header`)
assert.ok(markdown.includes(versionLink), `the ${label} uses the pinned specification version`)
}
const exampleRows = [...example.matchAll(/^\| .+? \| ([a-z]+) [^|]+ \| (\d+)% \| .+$/gm)]
assert.ok(exampleRows.length > 0, 'the example has stage rows')
@@ -282,18 +283,20 @@ test('keeps the pull request template aligned with the dsh-pr-description skill'
assert.ok(declarationBlock, 'the template has one ordered AI declaration block')
assert.equal(source.match(/<!-- ai-declaration:start -->/g)?.length, 1)
assert.equal(source.match(/<!-- ai-declaration:end -->/g)?.length, 1)
assert.match(
declarationBlock,
/^\[!\[AI-DECLARATION: 待填级别\]\(https:\/\/img\.shields\.io\/badge\/[^)]+\)\]\(https:\/\/ai-declaration\.md\)$/m,
'the block has the badge link',
assert.ok(
declarationBlock.includes(
'[![AI-DECLARATION: 待填级别](https://img.shields.io/badge/䷼%20AI--DECLARATION-待填级别-e5e7eb?labelColor=e5e7eb)](https://ai-declaration.md)',
),
'the block has the placeholder badge link',
)
assert.match(
declarationBlock,
/^\*\*AI declaration\*\* \(\[v0\.1\.2\]\(https:\/\/ai-declaration\.md\/en\/0\.1\.2\)\): `待填级别`$/m,
assert.ok(
declarationBlock.includes(`**AI declaration** (${versionLink}): \`待填级别\``),
'the block pins the declaration',
)
assert.ok(source.includes('| 阶段 | 级别 | AI 参与度 | 决策记录 |'), 'the template has the role table header')
const usageSection = source.slice(source.indexOf('## AI Usage'))
assert.ok(usageSection.includes('<!-- ai-declaration:start -->'), 'the AI declaration block is in AI Usage')
assert.ok(usageSection.includes('| 阶段 | 级别 | AI 参与度 | 决策记录 |'), 'the stage table is in AI Usage')
assert.ok(source.includes('|:--|:--|--:|:--|'), 'the template right-aligns AI involvement')
assert.deepEqual(
[...source.matchAll(/^\| (.+?) \| (?:待填级别|n\/a 暂不适用) \| (?:\?%|—) \| .+$/gm)].map(([, stage]) => stage),
@@ -311,8 +314,8 @@ test('keeps the pull request template aligned with the dsh-pr-description skill'
['template', source],
['skill', skill],
]) {
assert.doesNotMatch(text, /Human and Agent Roles/, `${label} has no old heading`)
assert.doesNotMatch(text, /autonomy/i, `${label} has no old autonomy term`)
assert.doesNotMatch(text, /^## Human and Agent Roles$/m, `${label} has no old heading`)
assert.doesNotMatch(text, /^Levels and Agent autonomy:/m, `${label} has no old level line`)
assert.doesNotMatch(text, /<ins>/, `${label} has no old underline markup`)
}
})
+1 -1
View File
@@ -20,7 +20,7 @@
## AI Usage
<!-- ai-declaration:start -->
[![AI-DECLARATION: 待填级别](https://img.shields.io/badge/䷼%20AI--DECLARATION-待填级别-lightgrey)](https://ai-declaration.md)
[![AI-DECLARATION: 待填级别](https://img.shields.io/badge/䷼%20AI--DECLARATION-待填级别-e5e7eb?labelColor=e5e7eb)](https://ai-declaration.md)
**AI declaration** ([v0.1.2](https://ai-declaration.md/en/0.1.2)): `待填级别`
<!-- ai-declaration:end -->