fix(tasks): separate completion from archive readiness (#1791)

* fix(tasks): separate completion from archive readiness

* fix(tasks): clarify optional workflow follow-up

* fix(tasks): keep profile-aware archive handoff and sync generated surfaces

Rebased onto main: the apply template now reports tracked completion
through the existing optional-workflow ARCHIVE_HANDOFF (#1775), so
profiles without the archive workflow still get the CLI fallback.
Regenerates the skills/ mirror and parity hashes, and syncs the
docs-lab spec-driven reference with the updated tasks instruction (#1952).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Clay Good <hi@claygood.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Marzx13
2026-10-01 20:42:13 +00:00
committed by GitHub
co-authored by Claude Opus 5.5 Clay Good
parent 3a34ea309d
commit 7056a58056
8 changed files with 89 additions and 17 deletions
@@ -361,17 +361,22 @@ Before writing tasks, check design.md for Open Questions. If any of them
would change what gets built, resolve them with the user first - do not
bake an unstated assumption into the task list.
**IMPORTANT: Follow the template below exactly.** The apply phase parses
**IMPORTANT: Follow the template below for tracked tasks.** The apply phase parses
checkbox format to track progress. A box holding only `x` counts as done,
upper or lower case and with any spacing, so `- [ x]` is done too. Every
other marker, including `- [~]`, `- [-]` and an empty `- []`, reads as
unfinished. A line with no checkbox is not tracked at all.
Guidelines:
- Group related tasks under ## numbered headings
- Each task MUST be a checkbox: `- [ ] X.Y Task description`
- Group related tracked tasks under ## numbered headings
- Each tracked task MUST be a checkbox: `- [ ] X.Y Task description`
- Tasks should be small enough to complete in one session
- Order tasks by dependency (what must be done first?)
- Track implementation and verification work that can be completed before
archive. If the requested workflow includes archive or work that requires
this change to be archived, preserve those steps as plain bullets in an
optional `## Workflow follow-up` section at the end of tasks.md. These
bullets are reference information outside tracked task progress.
- Each task MUST state how to verify completion (a test, command,
observable behavior, or delivered artifact). Put the verification in
that task's checkbox description. Use a separate verification task only
@@ -401,6 +406,14 @@ Example:
- [ ] 2.3 Document the export API in docs/export.md and verify the documented command runs as written
```
When applicable, append workflow follow-up as plain bullets, for example:
```
## Workflow follow-up
- Archive the change after the project's review requirements are satisfied.
- Verify the archived result.
```
Reference specs for what needs to be built, design for how to build it.
````
+16 -3
View File
@@ -195,17 +195,22 @@ artifacts:
would change what gets built, resolve them with the user first - do not
bake an unstated assumption into the task list.
**IMPORTANT: Follow the template below exactly.** The apply phase parses
**IMPORTANT: Follow the template below for tracked tasks.** The apply phase parses
checkbox format to track progress. A box holding only `x` counts as done,
upper or lower case and with any spacing, so `- [ x]` is done too. Every
other marker, including `- [~]`, `- [-]` and an empty `- []`, reads as
unfinished. A line with no checkbox is not tracked at all.
Guidelines:
- Group related tasks under ## numbered headings
- Each task MUST be a checkbox: `- [ ] X.Y Task description`
- Group related tracked tasks under ## numbered headings
- Each tracked task MUST be a checkbox: `- [ ] X.Y Task description`
- Tasks should be small enough to complete in one session
- Order tasks by dependency (what must be done first?)
- Track implementation and verification work that can be completed before
archive. If the requested workflow includes archive or work that requires
this change to be archived, preserve those steps as plain bullets in an
optional `## Workflow follow-up` section at the end of tasks.md. These
bullets are reference information outside tracked task progress.
- Each task MUST state how to verify completion (a test, command,
observable behavior, or delivered artifact). Put the verification in
that task's checkbox description. Use a separate verification task only
@@ -235,6 +240,14 @@ artifacts:
- [ ] 2.3 Document the export API in docs/export.md and verify the documented command runs as written
```
When applicable, append workflow follow-up as plain bullets, for example:
```
## Workflow follow-up
- Archive the change after the project's review requirements are satisfied.
- Verify the archived result.
```
Reference specs for what needs to be built, design for how to build it.
requires:
- specs
+4 -3
View File
@@ -65,7 +65,7 @@ In both branches, never create the root as a side effect: do not run `openspec i
- If `state: "blocked"`: show the message and pause implementation.
- If `missingArtifacts` is non-empty: suggest using `/openspec-continue-change` to create them.
- Otherwise, follow the CLI instruction to create or repair the schema-configured tracking file from existing planning artifacts. Do not assume another artifact is ready or start implementation while blocked.
- If `state: "all_done"`: congratulate, suggest archive
- If `state: "all_done"`: report that all tracked tasks are complete and suggest review or verification as appropriate before archiving
- Otherwise: proceed to implementation
Treat `context` as a required prompt-level input. Read and consider it, and
@@ -124,7 +124,7 @@ In both branches, never create the root as a side effect: do not run `openspec i
Display:
- Tasks completed this session
- Overall progress: "N/M tasks complete"
- If all done: suggest archive
- If all done: report that tracked tasks are complete and suggest review or verification as appropriate before archiving
- If paused: explain why and wait for guidance
**Output During Implementation**
@@ -155,7 +155,8 @@ Working on task 4/7: <task description>
- [x] Task 2
...
All tasks complete! You can archive this change with `/openspec-archive-change`.
All tracked tasks are complete. Review or verify the change as appropriate
before archiving. You can archive this change with `/openspec-archive-change`.
```
**Output On Pause (Issue Encountered)**
+1 -1
View File
@@ -672,7 +672,7 @@ export async function generateApplyInstructions(
total > 0
) {
state = 'all_done';
instruction = 'All tasks are complete! This change is ready to be archived.\nConsider running tests and reviewing the changes before archiving.';
instruction = 'All tracked tasks are complete.\nReview or verify the change as appropriate before archiving.';
} else if (!tracksFile) {
// No tracking file configured in schema - ready to apply
state = 'ready';
+4 -3
View File
@@ -84,7 +84,7 @@ ${PROJECT_ROOT_GUARD}
- If \`state: "blocked"\`: show the message and pause implementation.
- If \`missingArtifacts\` is non-empty: ${BLOCKED_STATE_HANDOFF}
- Otherwise, follow the CLI instruction to create or repair the schema-configured tracking file from existing planning artifacts. Do not assume another artifact is ready or start implementation while blocked.
- If \`state: "all_done"\`: congratulate, suggest archive
- If \`state: "all_done"\`: report that all tracked tasks are complete and suggest review or verification as appropriate before archiving
- Otherwise: proceed to implementation
Treat \`context\` as a required prompt-level input. Read and consider it, and
@@ -143,7 +143,7 @@ ${PROJECT_ROOT_GUARD}
Display:
- Tasks completed this session
- Overall progress: "N/M tasks complete"
- If all done: suggest archive
- If all done: report that tracked tasks are complete and suggest review or verification as appropriate before archiving
- If paused: explain why and wait for guidance
**Output During Implementation**
@@ -174,7 +174,8 @@ Working on task 4/7: <task description>
- [x] Task 2
...
All tasks complete! ${ARCHIVE_HANDOFF}
All tracked tasks are complete. Review or verify the change as appropriate
before archiving. ${ARCHIVE_HANDOFF}
\`\`\`
**Output On Pause (Issue Encountered)**
+15 -1
View File
@@ -1246,9 +1246,23 @@ operations:
});
expect(result.exitCode).toBe(0);
expect(result.stdout).toContain('complete ✓');
expect(result.stdout).toContain('ready to be archived');
expect(result.stdout).toContain('All tracked tasks are complete');
expect(result.stdout).toContain('as appropriate before archiving');
expect(result.stdout).not.toContain('ready to be archived');
expect(result.stdout).toContain('### Project Context (required instruction input)');
expect(result.stdout).toContain('### Operation Guidance (advisory)');
const jsonResult = await runCLI(
['instructions', 'apply', '--change', 'done-apply', '--json'],
{ cwd: tempDir }
);
expect(jsonResult.exitCode).toBe(0);
expect(jsonResult.stderr).toBe('');
const json = JSON.parse(jsonResult.stdout);
expect(json.state).toBe('all_done');
expect(json.progress).toEqual({ total: 2, complete: 2, remaining: 0 });
expect(json.instruction).toContain('All tracked tasks are complete');
});
it('uses spec-driven schema apply configuration', async () => {
+23
View File
@@ -21,6 +21,7 @@ import { getCommandContents } from '../../../src/core/shared/skill-generation.js
import { MAX_CONTEXT_SIZE } from '../../../src/core/project-config.js';
import { resolveOptionalWorkflows } from '../../../src/core/templates/optional-workflow.js';
import { ALL_WORKFLOWS } from '../../../src/core/profiles.js';
import { parseTaskLines } from '../../../src/utils/task-progress.js';
// Templates carry optional-workflow conditionals; a body only means anything
// once resolved against a workflow set. Unless a test says otherwise, these are
@@ -117,6 +118,28 @@ describe('default proposal guidance', () => {
});
describe('default task guidance', () => {
it('keeps tracked tasks within the pre-archive workflow (#1790)', () => {
const tasks = defaultSchema.artifacts.find(artifact => artifact.id === 'tasks');
expect(tasks).toBeDefined();
expect(tasks!.instruction).toMatch(
/Track implementation and verification work that can be completed before\s+archive/
);
expect(tasks!.instruction).toMatch(
/preserve those steps as plain bullets in an\s+optional `## Workflow follow-up` section at the end of tasks.md/
);
const examples = [...tasks!.instruction.matchAll(/```\s*([\s\S]*?)```/g)];
expect(examples).toHaveLength(2);
const implementation = examples[0][1];
const followUp = examples[1][1];
expect(followUp).toContain('## Workflow follow-up');
expect(followUp).toContain('- Verify the archived result.');
expect(parseTaskLines(followUp)).toEqual([]);
expect(parseTaskLines(`${implementation}\n${followUp}`)).toEqual(
parseTaskLines(implementation)
);
});
it('requires a concrete verification method in each task (#345)', () => {
const tasks = defaultSchema.artifacts.find(artifact => artifact.id === 'tasks');
expect(tasks).toBeDefined();
@@ -79,14 +79,14 @@ const EXPECTED_FUNCTION_HASHES: Record<string, string> = {
getExploreSkillTemplate: 'c1fddb294758004936add586f5826694cb06175cff935b75fd3a8d92332332e6',
getNewChangeSkillTemplate: '0e5035b7b42198afc430206a1dbc9579096650ef0813d85e837d5a6cd0b98a85',
getContinueChangeSkillTemplate: 'c2c8a0ba7f8c8fc7b174793832cd50f7c404eb8e1f7d49c47000993d621633b6',
getApplyChangeSkillTemplate: 'a6a9aa080ba062045533b33a71ad9358d9d5fef1756616f3feac7dea64aba289',
getApplyChangeSkillTemplate: 'c4f02c29137e19b34bf1dc59146941b8c920214aa2cf3ce80ae7f1b982e976fc',
getFfChangeSkillTemplate: 'd091600476a815ba99f69b446bcd46af5bf73d1c2810215a0c6196937d019cf6',
getSyncSpecsSkillTemplate: 'bc80fe9b07eaa289e5eb8a3ce65eb7df722a16d864e37283c678220712e4f230',
getOnboardSkillTemplate: '84258a06c0ca88de708a23dd74e9a17efe11eff63a071b3864c781dcd5a0a4b7',
getOpsxExploreCommandTemplate: '5d11f8ecb4c457140a3e874a8bf7aa72674e922e698c208832b1f34d3c617719',
getOpsxNewCommandTemplate: '6d504fef1e0d4ced7c423f4cc9d9d2cee11b1a6224edf685e06a3f0757e0ebff',
getOpsxContinueCommandTemplate: '241c50f97d5d681412d456d6b982743c3a5babeb77017fc8099c418bcf0d92df',
getOpsxApplyCommandTemplate: '21ccc013710ffb9f3a93ede9f9fb7e3eecaac292fcb3f3be30e2562cae9c4127',
getOpsxApplyCommandTemplate: '9b733946aa7216b45d084bb5affd7071086db6f91282c3666731a17543825ff1',
getOpsxFfCommandTemplate: '743a7304c7efc84aa87f556154c034e1e0e561c276c51870a30ada58f33eb9af',
getArchiveChangeSkillTemplate: '04a029782fc4137971fad6f54cfda3685d7e0b835b06565f9a509b4878093099',
getBulkArchiveChangeSkillTemplate: '44dbd3c7a347e5f8339b2141393f2ac36017527cce251483fe70f2059c1e286e',
@@ -107,7 +107,7 @@ const EXPECTED_GENERATED_SKILL_CONTENT_HASHES: Record<string, string> = {
'openspec-explore': '7d80caf9cd25a2565ba190b1297f1631c7f2c2db5e614597b4284abc0118ea70',
'openspec-new-change': '27e09d43785953827efc9a98bb9d6cf06db48fe6abe7e1c049409fe5b5061323',
'openspec-continue-change': '1f92fad53022270e96f8ea34de75f7c12c08225edd5a9e8f4e864b63b5ef79c5',
'openspec-apply-change': '4bcd8c1dc3d0d86a2e4c605fc60d6ee54e0e0433f248c1d602c12927935e6963',
'openspec-apply-change': '991a1d4687f1c8c7147d8c3b68cf14e9c515c6c53bb026356dac3b80e909b827',
'openspec-ff-change': 'a7ab656d46f04d45dff0c8888df4a126a2e62288b7336f7445bce4d1715055f5',
'openspec-sync-specs': '3909936a236a21a9a6d5bf495f90b396b3b68fc9220d7b2c1894668653beb2e4',
'openspec-archive-change': '5f0d131a885dcdcd9ba2172ea9a42bc6748125e24b8c4eecb7c86f1a4aea83af',
@@ -1267,6 +1267,13 @@ describe('apply skill/command shared instruction core', () => {
expect(getApplyChangeSkillTemplate().instructions).toBe(core);
expect(getOpsxApplyCommandTemplate().content).toBe(core);
});
it('keeps task completion distinct from archive readiness (#1790)', () => {
const core = getApplyInstructions();
expect(core).toContain('All tracked tasks are complete');
expect(core).toMatch(/Review or verify the change as appropriate\s+before archiving/);
expect(core).not.toContain('All tasks complete! You can archive');
});
});
describe('workflow guidance matches the packaged templates (#1138)', () => {