ai-delivery-workflow 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +5 -6
  2. package/bin/ai-delivery.mjs +2 -24
  3. package/docs/CLI-PARAMETER-REFERENCE.zh-CN.md +6 -67
  4. package/docs/DUAL-REPOSITORY-WORKSPACE.zh-CN.md +1 -1
  5. package/docs/FILE-REFERENCE.zh-CN.md +6 -28
  6. package/docs/MAINTENANCE-VERIFICATION.zh-CN.md +2 -2
  7. package/docs/PROJECT-MANUAL.zh-CN.md +23 -38
  8. package/docs/STATE-CLI-MAINTENANCE.zh-CN.md +8 -10
  9. package/docs/STATE-CLI-USER-GUIDE.zh-CN.md +6 -16
  10. package/docs/agents/workflow-manager-acceptance-matrix.md +9 -15
  11. package/docs/agents/workflow-manager-current-state.md +12 -15
  12. package/lib/communication-confirmation.mjs +177 -0
  13. package/lib/delivery-state.mjs +59 -910
  14. package/lib/fs-utils.mjs +0 -16
  15. package/lib/project-bootstrap.mjs +288 -61
  16. package/lib/project-installer.mjs +49 -181
  17. package/lib/project-repair.mjs +217 -0
  18. package/lib/toml-hooks.mjs +2 -4
  19. package/lib/workflow-manager-governance.mjs +3 -47
  20. package/lib/workspace.mjs +2 -3
  21. package/package.json +2 -2
  22. package/skills/ai-delivery-bootstrap/SKILL.md +5 -1
  23. package/skills/ai-delivery-bootstrap/references/bootstrap-contract.md +1 -1
  24. package/skills/ai-delivery-checkpoint-task/SKILL.md +2 -4
  25. package/skills/ai-delivery-checkpoint-task/references/checkpoint-contract.md +4 -2
  26. package/skills/ai-delivery-checkpoint-task/scripts/hook-event.mjs +2 -8
  27. package/skills/ai-delivery-checkpoint-task/scripts/task-state.mjs +26 -46
  28. package/skills/ai-delivery-close-version/SKILL.md +13 -10
  29. package/skills/ai-delivery-close-version/references/version-closeout-contract.md +2 -1
  30. package/skills/ai-delivery-define-product/SKILL.md +6 -3
  31. package/skills/ai-delivery-design-architecture/SKILL.md +10 -5
  32. package/skills/ai-delivery-design-architecture/assets/architecture-template/architecture-gate.yaml +2 -0
  33. package/skills/ai-delivery-design-architecture/assets/architecture-template/prototype-architecture-validation.yaml +2 -0
  34. package/skills/ai-delivery-design-architecture/references/architecture-contract.md +4 -0
  35. package/skills/ai-delivery-design-experience/SKILL.md +8 -6
  36. package/skills/ai-delivery-design-experience/assets/experience-template/product-prototype-reconciliation.yaml +2 -0
  37. package/skills/ai-delivery-design-experience/assets/experience-template/ui-handoff.yaml +3 -0
  38. package/skills/ai-delivery-design-experience/references/experience-contract.md +3 -13
  39. package/skills/ai-delivery-design-experience/references/prototype-management-contract.md +1 -1
  40. package/skills/ai-delivery-design-tests/SKILL.md +4 -0
  41. package/skills/ai-delivery-develop-iteration/SKILL.md +6 -1
  42. package/skills/ai-delivery-develop-iteration/assets/development-template/candidate-manifest.yaml +2 -0
  43. package/skills/ai-delivery-execute-work-package/SKILL.md +4 -2
  44. package/skills/ai-delivery-orchestrate/SKILL.md +7 -7
  45. package/skills/ai-delivery-orchestrate/assets/codebase-template/AGENTS.md +14 -0
  46. package/skills/ai-delivery-orchestrate/assets/codebase-template/CODEBASE_GUIDE.md +124 -0
  47. package/skills/ai-delivery-orchestrate/assets/codebase-template/docs/CODEBASE_INDEX.md +87 -0
  48. package/skills/ai-delivery-orchestrate/assets/communication-template/confirmation-examples.yaml +67 -0
  49. package/skills/ai-delivery-orchestrate/assets/communication-template/confirmation-summary.yaml +42 -0
  50. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/iterations/ITER-0001/02-solution-design/product-impact-assessment.yaml +42 -0
  51. package/skills/ai-delivery-orchestrate/assets/project-template/.workflow/tools/hooks/hook-event.mjs +2 -8
  52. package/skills/ai-delivery-orchestrate/assets/project-template/AGENTS.md +4 -5
  53. package/skills/ai-delivery-orchestrate/references/codebase-document-contract.md +91 -0
  54. package/skills/ai-delivery-orchestrate/references/communication-confirmation-contract.md +52 -0
  55. package/skills/ai-delivery-orchestrate/references/formal-state-contract.md +11 -20
  56. package/skills/ai-delivery-orchestrate/references/product-impact-assessment-contract.md +87 -0
  57. package/skills/ai-delivery-orchestrate/references/workflow-model.md +1 -3
  58. package/skills/ai-delivery-orchestrate/scripts/confirmation-state.mjs +30 -0
  59. package/skills/ai-delivery-orchestrate-release/SKILL.md +3 -1
  60. package/skills/ai-delivery-plan-iteration/SKILL.md +6 -1
  61. package/skills/ai-delivery-prepare-platform/SKILL.md +1 -1
  62. package/skills/ai-delivery-prepare-release/SKILL.md +2 -0
  63. package/skills/ai-delivery-prepare-release/assets/release-template/release-manifest.yaml +0 -2
  64. package/skills/ai-delivery-review-change/SKILL.md +3 -1
  65. package/skills/ai-delivery-validate-artifacts/SKILL.md +10 -7
  66. package/skills/ai-delivery-validate-artifacts/references/artifact-contract.md +2 -1
  67. package/skills/ai-delivery-verify-candidate/SKILL.md +5 -2
  68. package/skills/ai-delivery-verify-candidate/references/candidate-verification-contract.md +1 -1
  69. package/docs/PROTOTYPE-MIGRATION.zh-CN.md +0 -164
  70. package/docs/VIEWER-MAINTENANCE.zh-CN.md +0 -150
  71. package/docs/VIEWER-USER-GUIDE.zh-CN.md +0 -113
  72. package/lib/project-migration.mjs +0 -1193
  73. package/lib/prototype-migration.mjs +0 -713
  74. package/skills/ai-delivery-design-experience/assets/experience-template/LEGACY-COMPATIBILITY.md +0 -16
  75. package/skills/ai-delivery-design-experience/assets/experience-template/canvas-catalog.csv +0 -1
  76. package/skills/ai-delivery-design-experience/assets/experience-template/canvas-pages.csv +0 -1
  77. package/skills/ai-delivery-design-experience/assets/experience-template/page-catalog.csv +0 -1
  78. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-file-terminals.csv +0 -1
  79. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-files.csv +0 -1
  80. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-manifest.yaml +0 -76
  81. package/skills/ai-delivery-design-experience/assets/experience-template/prototype-set.yaml +0 -24
@@ -14,7 +14,6 @@ export const HOOK_EVENTS = [
14
14
  ];
15
15
 
16
16
  const HOOK_COMMAND = "node .workflow/tools/hooks/hook-event.mjs";
17
- const LEGACY_HOOK_COMMAND = "node .ai-delivery/hooks/hook-event.mjs";
18
17
 
19
18
  function hookBlock(event, newline) {
20
19
  return [
@@ -102,9 +101,8 @@ export function mergeHookConfig(existing, { force = false } = {}) {
102
101
  const newline = existing.includes("\r\n") ? "\r\n" : "\n";
103
102
  let text = existing.trimEnd();
104
103
  const actions = [];
105
- if (text.includes(LEGACY_HOOK_COMMAND)) {
106
- text = text.replaceAll(LEGACY_HOOK_COMMAND, HOOK_COMMAND);
107
- actions.push("migrate AI delivery Hook command into .workflow/tools");
104
+ if (text.includes("node .ai-delivery/hooks/hook-event.mjs")) {
105
+ throw new Error("Unsupported legacy Hook command; remove the .ai-delivery handler before installing the current Hook.");
108
106
  }
109
107
  if (force) {
110
108
  const refreshed = removeDeliveryHandlerBlocks(text);
@@ -24,7 +24,6 @@ export const WORKFLOW_MANAGER_GOVERNANCE_SCHEMA_VERSION = "workflow-manager.gove
24
24
  const RELATIONS_FILE = ".workflow/control/relations.yaml";
25
25
  const SETTINGS_FILE = ".workflow/config/manager-settings.json";
26
26
  const RECEIPTS_ROOT = ".workflow/control/receipts";
27
- const EVENTS_FILE = ".workflow/control/events/workflow-manager-events.jsonl";
28
27
  const SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,191}$/;
29
28
  const SAFE_ENTITY_TYPE = /^[a-z][a-z0-9-]{0,63}$/;
30
29
  const RELATION_TYPES = new Set([
@@ -59,18 +58,6 @@ function contained(root, relative) {
59
58
  return absolute;
60
59
  }
61
60
 
62
- function atomicWrite(file, content) {
63
- fs.mkdirSync(path.dirname(file), { recursive: true });
64
- const temporary = `${file}.${process.pid}.${crypto.randomUUID()}.tmp`;
65
- fs.writeFileSync(temporary, content, { encoding: "utf8", flag: "wx" });
66
- try {
67
- fs.renameSync(temporary, file);
68
- } catch (error) {
69
- fs.rmSync(temporary, { force: true });
70
- throw error;
71
- }
72
- }
73
-
74
61
  function requireHuman(actor) {
75
62
  if (!/^human:[A-Za-z0-9._@/-]+$/.test(String(actor || ""))) {
76
63
  throw new Error("Governed confirmation requires actor human:<identity>");
@@ -92,16 +79,13 @@ function receiptFiles(root) {
92
79
 
93
80
  function replay(root, action, input, subject = null) {
94
81
  if (!input.idempotency_key) return null;
95
- const legacyRequestChecksum = checksum({ action, input });
96
- const governedRequestChecksum = workflowManagerRequestChecksum(action, input, subject);
82
+ const expectedRequestChecksum = workflowManagerRequestChecksum(action, input, subject);
97
83
  for (const file of receiptFiles(root)) {
98
84
  try {
99
85
  const receipt = JSON.parse(fs.readFileSync(file, "utf8"));
100
86
  if (receipt.action !== action || receipt.idempotency_key !== input.idempotency_key) continue;
101
- const legacy = receipt.request_checksum === legacyRequestChecksum;
102
- const governed = receipt.request_checksum === governedRequestChecksum
103
- && (receipt.subject ?? null) === subject;
104
- if (!legacy && !governed) {
87
+ if (receipt.request_checksum !== expectedRequestChecksum
88
+ || (receipt.subject ?? null) !== subject) {
105
89
  throw new Error("Idempotency key was already used for a different request");
106
90
  }
107
91
  return receipt;
@@ -112,34 +96,6 @@ function replay(root, action, input, subject = null) {
112
96
  return null;
113
97
  }
114
98
 
115
- function record(root, action, input, detail = {}) {
116
- const timestamp = new Date().toISOString();
117
- const receipt = {
118
- schema_version: 1,
119
- receipt_id: `WMG-${crypto.randomUUID()}`,
120
- action,
121
- actor: input.actor,
122
- idempotency_key: input.idempotency_key || null,
123
- request_checksum: checksum({ action, input }),
124
- applied_at: timestamp,
125
- ...detail,
126
- };
127
- receipt.receipt_checksum = checksum(receipt);
128
- atomicWrite(contained(root, `${RECEIPTS_ROOT}/${receipt.receipt_id}.json`), `${JSON.stringify(receipt, null, 2)}\n`);
129
- const event = {
130
- schema_version: 1,
131
- event_id: `WME-${crypto.randomUUID()}`,
132
- type: `workflow-manager.${action}`,
133
- occurred_at: timestamp,
134
- receipt_id: receipt.receipt_id,
135
- subject: detail.subject || null,
136
- };
137
- const eventFile = contained(root, EVENTS_FILE);
138
- fs.mkdirSync(path.dirname(eventFile), { recursive: true });
139
- fs.appendFileSync(eventFile, `${JSON.stringify(event)}\n`, "utf8");
140
- return { receipt, event };
141
- }
142
-
143
99
  function relationsDocument(root) {
144
100
  const file = contained(root, RELATIONS_FILE);
145
101
  if (!fs.existsSync(file)) return { file, document: { schema_version: 1, revision: 0, relations: [] }, checksum: null };
package/lib/workspace.mjs CHANGED
@@ -4,7 +4,6 @@ import { spawnSync } from "node:child_process";
4
4
  import { parse as parseYaml, stringify as stringifyYaml } from "./yaml-runtime.mjs";
5
5
 
6
6
  export const WORKSPACE_CONFIG = path.join(".workflow", "config", "workspace.yaml");
7
- export const LEGACY_WORKSPACE_CONFIG = path.join(".ai-delivery", "workspace.yaml");
8
7
 
9
8
  function toPosix(value) {
10
9
  return value.replaceAll("\\", "/");
@@ -114,7 +113,7 @@ function initializeWorkflowRepository(workspaceRoot, branch, remote, heads, acti
114
113
  const current = gitBranch(workspaceRoot);
115
114
  if (current !== branch) {
116
115
  if (gitHasCommit(workspaceRoot)) {
117
- throw new Error(`Existing workflow repository must already use ${branch}; automatic migration is not supported.`);
116
+ throw new Error(`Existing workflow repository must already use ${branch}; automatic branch changes are not supported.`);
118
117
  }
119
118
  if (!dryRun) runGit(workspaceRoot, ["symbolic-ref", "HEAD", `refs/heads/${branch}`]);
120
119
  }
@@ -172,7 +171,7 @@ export function validateCodePath(workspaceRoot, codePath = "code") {
172
171
  if (!normalized || normalized.includes("/") || normalized === "." || normalized === "..") {
173
172
  throw new Error("Code path must be a relative direct child directory.");
174
173
  }
175
- if (new Set([".git", ".workflow", ".ai-delivery", ".agents", ".codex"]).has(normalized)) {
174
+ if (new Set([".git", ".workflow", ".agents", ".codex"]).has(normalized)) {
176
175
  throw new Error(`Reserved code path: ${normalized}`);
177
176
  }
178
177
  const absolute = path.resolve(workspaceRoot, normalized);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-delivery-workflow",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Project-scoped Codex skills and hooks for artifact-driven AI software delivery",
5
5
  "type": "module",
6
6
  "repository": {
@@ -22,7 +22,7 @@
22
22
  "skills"
23
23
  ],
24
24
  "scripts": {
25
- "test": "node --test verification/*.test.mjs",
25
+ "test": "node --test --test-concurrency=4 verification/*.test.mjs",
26
26
  "manager:build": "npm --prefix manager run build",
27
27
  "skills:validate": "node bin/validate-skills.mjs",
28
28
  "audit:generate": "node audit/generate-all.mjs",
@@ -44,7 +44,7 @@ The first product question is the safe stopping point. Do not invent the initial
44
44
  - `codebase-uninitialized`: use packaged `ai-delivery bootstrap`, review the repository baseline, inventory, context index, and adoption assessment, then invoke `$ai-delivery-define-product` to distinguish observed behavior from intended product behavior.
45
45
  - `workflow-interrupted`: do not write bootstrap artifacts. If `runtime.next_action_owner` is `user`, return the recorded `next_action` as the single business question and perform no recovery, activation, checkpoint, task, artifact, or Git mutation. If it is `external`, report the recorded wait condition without mutation. Only an `agent`-owned next action may invoke `$ai-delivery-checkpoint-task recover`, reconcile reality, inspect the pending Evolution queue without applying changes mid-task, and continue `recommended_task_id`. When required input arrives, transfer ownership with both `--next-action-owner agent` and a new idempotent `--next-action`.
46
46
  - `workflow-ready`: when a queued task is recommended, first apply the same `next_action_owner` boundary; activate it through `$ai-delivery-checkpoint-task` only when the owner is `agent`. Otherwise use the reported specialist skill or `$ai-delivery-orchestrate` to derive the next development node. Treat `release-ready` versions as completed development evidence, not implicit release intent. Route to `$ai-delivery-orchestrate-release` only when the user explicitly requests a release.
47
- - `workflow-inconsistent`: stop automatic mutation, run the available project/package doctor internally, report exact conflicts, and obtain a repair decision. An installed project must use packaged `upgrade --dry-run` for managed installation drift and `migrate --dry-run` for legacy schema, task grouping, anchor, or archive conflicts rather than repeat `init`. Structural migration copies legacy-root workflow material, adds explicit task attempts, and preserves lifecycle and scope facts; grouping ambiguities require a source-checksum-bound `--decisions` document with a `human:` actor and rationale. Route an approved premature-archive correction through packaged `repair --invalidate-archive` with a human actor, reason, RCA evidence, and recovery evidence; the original archive remains immutable. Use `upgrade --force` only when the user explicitly approves replacing the reported managed files.
47
+ - `workflow-inconsistent`: stop automatic mutation, run the available project/package doctor internally, report exact conflicts, and obtain an explicit repair decision. Use `upgrade --dry-run` for current managed installation drift; malformed current state, missing anchors, archive conflicts, and checksum drift fail closed until repaired through the governed current-state interface. Use `upgrade --force` only when the user explicitly approves replacing the reported managed files.
48
48
 
49
49
  ## Brownfield Rules
50
50
 
@@ -52,6 +52,10 @@ Treat repository scans as observations, not approved product or architecture tru
52
52
 
53
53
  Do not replace existing product, architecture, test, or release baselines. Keep the project-state report and related observations outside the formal artifact registry while they remain working drafts, preserve every timestamped bootstrap run, and update only the `.workflow/delivery/bootstrap/latest.yaml` pointer.
54
54
 
55
+ ### Codebase Handbook Discovery
56
+
57
+ For the configured nested code repository, inspect `AGENTS.md`, `CODEBASE_GUIDE.md`, and `docs/CODEBASE_INDEX.md` as read-only maintainer documents. The report records `observed`, `approved`, or `stale`; missing files are a warning, while malformed, path-invalid, symlink, or sensitive-content findings fail closed. Compare each declared `source_commit` with the code repository HEAD. Never infer an approved rule from the generated inventory, and never overwrite these files during bootstrap or upgrade.
58
+
55
59
  ## Resume Boundary
56
60
 
57
61
  Codex lifecycle Hooks provide audit and heartbeat data only. Versioned Evolution Hooks may return `pass`, `warn`, or an approved `block`, but they never select or complete tasks and never mutate formal workflow state. A bootstrap report may recommend recovery, but `$ai-delivery-checkpoint-task` remains authoritative for task order, dependency readiness, worktree reconciliation, and idempotent continuation. Route pending feedback and extension evaluation to `$ai-delivery-evolve-workflow` only at a task, version, or explicit review safe point.
@@ -28,7 +28,7 @@ After installation, `node .workflow/tools/bootstrap/bootstrap.mjs inspect` is th
28
28
 
29
29
  `ai-delivery bootstrap <project-root>` may initialize only `empty-uninitialized` and `codebase-uninitialized` projects through the project-scoped installer. Preserve existing code and configuration. On partial or conflicting installation, return `workflow-inconsistent` without writes. `--force` is allowed only after explicit user approval.
30
30
 
31
- For an installed legacy or conflicting state, keep Bootstrap read-only. Use packaged `migrate --dry-run` to report schema conversion, semantic task groups and ambiguities, state/archive conflicts, verified anchors, and exact file changes. A legacy root migration copies `delivery/`, `control/`, and `standards/` into `.workflow/` while preserving source bytes; flat task shards gain explicit attempts with checksummed rollback backups. Resolve grouping ambiguities only through a checksum-bound `--decisions` document with a `human:` actor and rationale. Migration must not activate or close tasks, infer completion, change scope, or rewrite legacy events. Incorrect archives require the separate packaged `repair --invalidate-archive` forward transaction with an explicit human actor, reason, RCA evidence, and recovery evidence; the original archive bytes remain authoritative history.
31
+ For an installed or conflicting state, keep Bootstrap read-only and return `workflow-inconsistent` with the failing path and remediation. Use the packaged `repair --invalidate-archive` forward transaction only for an explicitly identified archive integrity defect; it records a human actor, reason, RCA evidence, and recovery evidence without rewriting immutable history.
32
32
 
33
33
  For an uninitialized project, generate repository inventory and context artifacts from the first read-only scan snapshot. Do not let installer-generated `AGENTS.md`, `.gitignore`, Hook, skill, standard, or delivery files contaminate the observed pre-install codebase baseline.
34
34
 
@@ -11,10 +11,6 @@ Treat explicit task snapshots as authoritative. Treat Hook events as an audit tr
11
11
 
12
12
  Write portable task state to `.workflow/control/tasks/<task-id>.yaml` and `.workflow/control/checkpoints/<task-id>/<checkpoint-id>.yaml`. Keep only PID, heartbeat, temporary locks, raw Hook events, and unshared context under ignored `.workflow/delivery/runtime/`. Keep durable node documents under `.workflow/iterations/<iteration-id>/<node-id>/`; runtime snapshots never replace registered delivery artifacts. Resolve code branch and commit from `.workflow/config/workspace.yaml` and the nested code repository.
13
13
 
14
- ## Legacy Node Boundary
15
-
16
- Legacy development nodes are read-only compatibility. `inspect` remains a strictly read-only diagnosis path for historical tasks. `init`, `activate`, `checkpoint`, `finish`, and `archive-version` reject legacy task targets before mutation or Hook dispatch; `recover` refuses to materialize them and `publish` refuses to share them. New tasks use only the `development-seven-node` route, while `R00-release-request` through `R10-release-archive` remain writable.
17
-
18
14
  ## Start Or Resume
19
15
 
20
16
  1. Locate the project root and shared state root.
@@ -64,6 +60,8 @@ Checkpoint after every externally meaningful milestone, before a long command, a
64
60
 
65
61
  Use shared shards and the newest shared checkpoint as the portable recovery source. If local runtime is absent and `next_action_owner` is `agent`, `recover` restores it from shared state. For `user` or `external`, report the wait state without hydration; after the input arrives, `activate` performs the atomic hydration and owner transfer. If local and shared revisions or semantic checksums differ, stop for reconciliation. Inspect both Git repositories before resuming. Report pending `.workflow/delivery/runtime/evolution/pending/` events, but defer their evaluation until the recovered task reaches a safe point.
66
62
 
63
+ Confirmation waits persist the summary path, question identity, frontier round, and an idempotent next action. `user` and `external` ownership remains strict zero-mutation wait until explicit input transfer.
64
+
67
65
  Generate a compact recovery report from snapshots, checkpoints, Hook events, Git, and workspace state. Return active work and failed tasks in `retryable_task_ids` by default; use `--include-closed` only when completed or abandoned details are required for an explicit audit. For each iteration, report total, completed, closed, remaining, active, retryable, queued, dependency-ready, and waiting tasks plus one deterministic `recommended_task_id`. Prefer an interrupted or active task, then the lowest-sequence failed task requiring `activate --new-attempt --phase repair`, then the lowest-sequence queued task whose dependencies are all `completed`. Resume only idempotent steps. Re-read production and external systems before any deployment recovery; never replay production deployment automatically.
68
66
 
69
67
  ## Hook Boundary
@@ -34,7 +34,7 @@ Keep `.workflow/delivery/runtime/` local and ignored. Persist durable stage outp
34
34
 
35
35
  `task-state.mjs` is the only runtime-state writer. Do not directly edit task JSON, checkpoint JSON, active-task markers, recovery output, or archive indexes. Formal workflow and artifact state belong to `.workflow/tools/state/state.mjs`; do not edit its YAML or JSONL streams directly.
36
36
 
37
- Legacy development nodes are read-only compatibility. `inspect` remains read-only for historical task diagnosis. `init`, `activate`, `checkpoint`, `finish`, and `archive-version` reject legacy task targets before mutation or Hook dispatch; `recover` does not hydrate them and `publish` does not share them. New task contracts use only the `development-seven-node` route, while `R00-release-request` through `R10-release-archive` remain writable.
37
+ Task contracts use the current `development-seven-node` route or the independent `R00-release-request` through `R10-release-archive` release route. `inspect` is read-only diagnosis; `init`, `activate`, `checkpoint`, `finish`, `recover`, `archive-version`, and `publish` operate only on current task contracts.
38
38
 
39
39
  When the installed Evolution CLI exists, `init`, `activate`, `checkpoint`, `finish`, and `archive-version` emit idempotent schema 1 `task.before`, `task.after`, and `task.failed` events. An approved blocking `task.before` result stops the task command before mutation. Hook dispatch failures otherwise fail open as warnings and never replace checkpoint state as the completion authority.
40
40
 
@@ -75,7 +75,9 @@ For an installed dual-repository project, `task-state.mjs` resolves `code_branch
75
75
 
76
76
  `blockers` represents current unresolved blockers. A `blocked` update replaces that list; any transition to another status clears it. Historical blocker text remains available in prior checkpoints and events.
77
77
 
78
- `next_action_owner` is required in persisted state and has exactly three values: `agent`, `user`, or `external`; only a truly absent field in a legacy snapshot defaults to `agent`, while explicit null, empty, boolean, numeric, or unknown values are invalid. `user` and `external` are zero-mutation wait states. `recover` may report shared wait state but must not hydrate local task or resume files for it. After the required input arrives, `activate` requires both `--next-action-owner agent` and a new idempotent `--next-action`; it may atomically hydrate a missing local runtime snapshot from the matching shared shard and transfer ownership in the same transition. Same-revision local and shared content must have identical semantic checksums. Evidence arrays are ordered sets: replaying an already recorded `--evidence` value does not append a duplicate.
78
+ `next_action_owner` is required in persisted state and has exactly three values: `agent`, `user`, or `external`; explicit null, empty, boolean, numeric, or unknown values are invalid. `user` and `external` are zero-mutation wait states. `recover` may report shared wait state but must not hydrate local task or resume files for it. After the required input arrives, `activate` requires both `--next-action-owner agent` and a new idempotent `--next-action`; it may atomically hydrate a missing local runtime snapshot from the matching shared shard and transfer ownership in the same transition. Same-revision local and shared content must have identical semantic checksums. Evidence arrays are ordered sets: replaying an already recorded `--evidence` value does not append a duplicate.
79
+
80
+ When waiting on a confirmation frontier, persist the summary path, `question_id`, `frontier_round`, and summary checksum in checkpoint evidence. Repeated answers are idempotent; superseding a decision appends a new record and never overwrites prior confirmation.
79
81
 
80
82
  Pass `--state-root` when worktrees must write to one shared primary state directory. Pass `--worktree` during init so the script writes a local `.workflow/delivery/runtime/active-task.json` marker pointing to that state root. Later `checkpoint`, `finish`, and `recover` commands automatically use the marker's shared state root.
81
83
 
@@ -144,15 +144,9 @@ function enforceFrontendGuard(projectRoot, input) {
144
144
  }
145
145
 
146
146
  try {
147
- const currentProjectFile = findUp(process.cwd(), path.join(".workflow", "delivery", "project.yaml"));
148
- const legacyProjectFile = currentProjectFile
149
- ? null
150
- : findUp(process.cwd(), path.join("delivery", "project.yaml"));
151
- const projectFile = currentProjectFile || legacyProjectFile;
147
+ const projectFile = findUp(process.cwd(), path.join(".workflow", "delivery", "project.yaml"));
152
148
  if (!projectFile) process.exit(0);
153
- const projectRoot = currentProjectFile
154
- ? path.dirname(path.dirname(path.dirname(projectFile)))
155
- : path.dirname(path.dirname(projectFile));
149
+ const projectRoot = path.dirname(path.dirname(path.dirname(projectFile)));
156
150
  const markerFile = path.join(projectRoot, ".workflow", "delivery", "runtime", "active-task.json");
157
151
  const marker = fs.existsSync(markerFile) ? JSON.parse(fs.readFileSync(markerFile, "utf8")) : null;
158
152
  const raw = await readStdin();
@@ -42,19 +42,13 @@ const REPEATABLE_ARGS = new Set([
42
42
  "completed-step", "blocker", "evidence", "depends-on", "acceptance", "finding-json",
43
43
  "change-set-json",
44
44
  ]);
45
- const LEGACY_DEVELOPMENT_NODE_IDS = new Set([
46
- "01-product-discovery",
47
- "02-product-definition",
48
- "03-architecture-initial",
49
- "04-experience-design",
50
- "05-architecture-reconcile",
51
- "06-platform-preparation",
52
- "07-iteration-planning",
53
- "08-test-design",
54
- "09-development",
55
- "10-change-review",
56
- "11-candidate-verification",
57
- "12-version-closeout",
45
+ const VALID_NODE_IDS = new Set([
46
+ "00-bootstrap", "01-product-shaping", "02-solution-design", "03-delivery-readiness",
47
+ "04-implementation", "05-candidate-assurance", "06-version-closeout",
48
+ "R00-release-request", "R01-version-selection", "R02-release-eligibility", "R03-material-aggregation",
49
+ "R04-release-candidate", "R05-release-verification", "R06-release-preparation", "R07-production-approval",
50
+ "R08-production-deployment", "R09-production-verification", "R10-release-archive",
51
+ "development", "implementation", "planning", "test", "review",
58
52
  ]);
59
53
 
60
54
  function parseArgs(argv) {
@@ -83,10 +77,8 @@ function requireValue(args, key) {
83
77
  return value;
84
78
  }
85
79
 
86
- function assertNotLegacyDevelopmentNode(node) {
87
- if (LEGACY_DEVELOPMENT_NODE_IDS.has(node)) {
88
- throw new Error(`Legacy workflow node is read-only: ${node}`);
89
- }
80
+ function assertCurrentNode(node) {
81
+ if (!VALID_NODE_IDS.has(node)) throw new Error(`Unsupported workflow node: ${node}`);
90
82
  return node;
91
83
  }
92
84
 
@@ -720,7 +712,7 @@ function repairChangesSinceBaseline(workflowRoot, baseline) {
720
712
  }
721
713
 
722
714
  function writeSharedTask(runtime, workflowRoot, task) {
723
- assertNotLegacyDevelopmentNode(task.node);
715
+ assertCurrentNode(task.node);
724
716
  const sharedFile = sharedTaskFile(workflowRoot, task.task_id);
725
717
  let previousRevision = 0;
726
718
  if (fs.existsSync(sharedFile)) {
@@ -786,25 +778,15 @@ function normalizeTask(task) {
786
778
  task[key] = [...new Set(task[key])];
787
779
  }
788
780
  task.sequence = parseSequence(task.sequence);
789
- task.next_action_owner = parseNextActionOwner(task.next_action_owner);
790
- task.responsibility = task.responsibility || task.skill || "agent";
781
+ task.next_action_owner = parseNextActionOwner(task.next_action_owner, undefined);
782
+ if (!task.responsibility) throw new Error(`Task ${task.task_id || "unknown"} is missing responsibility.`);
791
783
  task.derived_from = task.derived_from || null;
792
784
  task.supersedes = task.supersedes || null;
793
- if (!Array.isArray(task.attempts)) {
794
- const legacyNumber = Number(task.attempt || 0);
795
- task.attempts = legacyNumber > 0 && (task.started_at || task.status !== "queued")
796
- ? [normalizeAttempt(task.task_id, {
797
- number: legacyNumber,
798
- status: projectedTaskStatus(task.status, "attempt"),
799
- started_at: task.started_at || task.created_at || null,
800
- finished_at: CLOSED_STATUS.has(task.status) ? task.finished_at || task.updated_at || null : null,
801
- }, legacyNumber)]
802
- : [];
803
- } else {
804
- task.attempts = task.attempts.map((attempt, index) => normalizeAttempt(task.task_id, attempt, index + 1));
785
+ if (Object.prototype.hasOwnProperty.call(task, "attempt") || !Array.isArray(task.attempts)) {
786
+ throw new Error(`Task ${task.task_id || "unknown"} must use canonical attempts.`);
805
787
  }
788
+ task.attempts = task.attempts.map((attempt, index) => normalizeAttempt(task.task_id, attempt, index + 1));
806
789
  task.change_sets = Array.isArray(task.change_sets) ? task.change_sets.map((item) => normalizeChangeSet(item)) : [];
807
- task.attempt = task.attempts.at(-1)?.number || 0;
808
790
  return task;
809
791
  }
810
792
 
@@ -852,7 +834,6 @@ function startAttempt(task, phase, timestamp) {
852
834
  time_entries: [],
853
835
  }, number);
854
836
  task.attempts.push(attempt);
855
- task.attempt = number;
856
837
  return attempt;
857
838
  }
858
839
 
@@ -1379,7 +1360,7 @@ function summarizeIteration(tasks, iterationId) {
1379
1360
  function commandInit(args) {
1380
1361
  const taskId = sanitizeId(requireValue(args, "task-id"));
1381
1362
  const iterationId = sanitizeId(requireValue(args, "iteration-id"));
1382
- const node = assertNotLegacyDevelopmentNode(requireValue(args, "node"));
1363
+ const node = assertCurrentNode(requireValue(args, "node"));
1383
1364
  const { projectRoot, stateRoot, workflowRoot, runtime } = statePaths(args);
1384
1365
  return withTaskLock(runtime, `version.${iterationId}`, () => withTaskLock(runtime, taskId, () => {
1385
1366
  if (fs.existsSync(archivedTaskIndexFile(runtime, taskId))) {
@@ -1424,6 +1405,7 @@ function commandInit(args) {
1424
1405
  const candidateContract = normalizeTask({
1425
1406
  ...(existing || {}),
1426
1407
  ...contractFields,
1408
+ attempts: existing?.attempts || [],
1427
1409
  next_action_owner: existing?.next_action_owner || "agent",
1428
1410
  });
1429
1411
  if (existing) {
@@ -1459,7 +1441,6 @@ function commandInit(args) {
1459
1441
  ...contractFields,
1460
1442
  status,
1461
1443
  sequence: parseSequence(args.sequence ?? existing?.sequence),
1462
- attempt: 0,
1463
1444
  attempts: [],
1464
1445
  change_sets: [],
1465
1446
  input_artifacts: args["input-artifact"] || existing?.input_artifacts || [],
@@ -1486,7 +1467,7 @@ function commandInit(args) {
1486
1467
  clearTaskMarker(task);
1487
1468
  appendEvent(runtime, taskId, "task-initialized", {
1488
1469
  status: task.status,
1489
- attempt: task.attempt,
1470
+ attempt_count: task.attempts.length,
1490
1471
  derived_from: task.derived_from,
1491
1472
  supersedes: task.supersedes,
1492
1473
  });
@@ -1557,7 +1538,6 @@ function commandActivate(args) {
1557
1538
  phase.status = "active";
1558
1539
  phase.finished_at = null;
1559
1540
  }
1560
- task.attempt = attempt.number;
1561
1541
  task.started_at ||= timestamp;
1562
1542
  task.updated_at = timestamp;
1563
1543
  task.finished_at = null;
@@ -1573,7 +1553,7 @@ function commandActivate(args) {
1573
1553
  });
1574
1554
  appendEvent(runtime, taskId, "task-activated", {
1575
1555
  status,
1576
- attempt: task.attempt,
1556
+ attempt_count: task.attempts.length,
1577
1557
  attempt_id: attempt.attempt_id,
1578
1558
  phase: attempt.phases.at(-1)?.phase || null,
1579
1559
  new_attempt: newAttempt,
@@ -1627,7 +1607,7 @@ function commandUpdate(args, finish = false) {
1627
1607
  writeResume(runtime, task);
1628
1608
  appendEvent(runtime, taskId, finish ? "task-finished" : "task-checkpointed", {
1629
1609
  status,
1630
- attempt: attempt.number,
1610
+ attempt_number: attempt.number,
1631
1611
  attempt_id: attempt.attempt_id,
1632
1612
  phase: attempt.phases.at(-1)?.phase || null,
1633
1613
  });
@@ -1696,7 +1676,7 @@ function commandArchiveVersion(args) {
1696
1676
  .map((name) => normalizeTask(JSON.parse(fs.readFileSync(path.join(tasksDir, name), "utf8"))))
1697
1677
  .filter((task) => task.iteration_id === iterationId);
1698
1678
  if (!tasks.length) throw new Error(`No tasks found for version: ${iterationId}`);
1699
- for (const task of tasks) assertNotLegacyDevelopmentNode(task.node);
1679
+ for (const task of tasks) assertCurrentNode(task.node);
1700
1680
  const sharedById = new Map(readSharedTasks(workflowRoot, stateRoot).map((task) => [task.task_id, task]));
1701
1681
  for (const task of tasks) {
1702
1682
  const shared = sharedById.get(task.task_id);
@@ -1795,7 +1775,7 @@ function commandRecover(args) {
1795
1775
  const reportableTasks = selectedTasks
1796
1776
  .filter((task) => !requested || task.task_id === requested)
1797
1777
  .filter((task) => includeClosed || !RECOVERY_COMPLETE_STATUS.has(task.status));
1798
- for (const task of reportableTasks) assertNotLegacyDevelopmentNode(task.node);
1778
+ for (const task of reportableTasks) assertCurrentNode(task.node);
1799
1779
  for (const task of reportableTasks) {
1800
1780
  if (missingLocalTaskIds.has(task.task_id)) atomicWrite(taskFile(runtime, task.task_id), task);
1801
1781
  }
@@ -1853,7 +1833,7 @@ function commandPublish(args) {
1853
1833
  const checkpointDirectory = path.join(workflowRoot, "control", "checkpoints", taskId);
1854
1834
  if (!fs.existsSync(sharedFile)) throw new Error(`Shared task state not found: ${taskId}`);
1855
1835
  const shared = JSON.parse(fs.readFileSync(sharedFile, "utf8"));
1856
- assertNotLegacyDevelopmentNode(shared.node);
1836
+ assertCurrentNode(shared.node);
1857
1837
 
1858
1838
  const repository = gitState(stateRoot);
1859
1839
  if (!repository.repository || path.resolve(repository.root).toLowerCase() !== path.resolve(stateRoot).toLowerCase()) {
@@ -1978,7 +1958,7 @@ function assertWritableEvolutionTarget(args, command) {
1978
1958
  if (!new Set(["init", "activate", "checkpoint", "finish", "archive-version"]).has(command)) return;
1979
1959
  if (command === "init") {
1980
1960
  const node = args.node && args.node !== true ? String(args.node) : null;
1981
- if (node) assertNotLegacyDevelopmentNode(node);
1961
+ if (node) assertCurrentNode(node);
1982
1962
  return;
1983
1963
  }
1984
1964
  const { runtime, workflowRoot, stateRoot } = statePaths(args);
@@ -1990,14 +1970,14 @@ function assertWritableEvolutionTarget(args, command) {
1990
1970
  if (!iterationId || !fs.existsSync(tasksDir)) return;
1991
1971
  for (const name of fs.readdirSync(tasksDir).filter((item) => item.endsWith(".json"))) {
1992
1972
  const task = normalizeTask(JSON.parse(fs.readFileSync(path.join(tasksDir, name), "utf8")));
1993
- if (task.iteration_id === iterationId) assertNotLegacyDevelopmentNode(task.node);
1973
+ if (task.iteration_id === iterationId) assertCurrentNode(task.node);
1994
1974
  }
1995
1975
  return;
1996
1976
  }
1997
1977
  const taskId = args["task-id"] && args["task-id"] !== true ? sanitizeId(args["task-id"]) : null;
1998
1978
  if (!taskId) return;
1999
1979
  const task = taskSources(runtime, workflowRoot, stateRoot, taskId).task;
2000
- if (task) assertNotLegacyDevelopmentNode(task.node);
1980
+ if (task) assertCurrentNode(task.node);
2001
1981
  }
2002
1982
 
2003
1983
  function dispatchTaskEvolution(context, phase, result = null, error = null) {
@@ -11,24 +11,27 @@ Finish one planned version and stop before release. Never start a release from t
11
11
 
12
12
  1. Recover or initialize the `06-version-closeout` task through `$ai-delivery-checkpoint-task`.
13
13
  2. Run `node .workflow/tools/state/state.mjs verify --history`.
14
- 3. Require a passing immutable candidate, a completed Candidate Assurance receipt for that same candidate, closed version tasks, complete requirement/test/material traceability, and no unresolved blocking defect.
14
+ 3. Require a passing immutable candidate, a completed Candidate Assurance receipt for that same candidate, a resolved or superseded product impact assessment bound to the candidate, closed version tasks, complete requirement/test/material traceability, and no unresolved blocking defect.
15
15
  4. Read the preceding version lineage and Git policy. Require the candidate to descend from the current `line/<product-id>` head, except for the first version.
16
16
 
17
17
  ## Close The Version
18
18
 
19
19
  1. Read `.workflow/config/workspace.yaml`; verify the candidate in the configured code repository and populate `repo_id`, `code_commit`, `source_path`, and SHA-256.
20
- 2. Freeze the candidate commit and create code `version-ready/<version-id>/rN`. Never move or replace an existing Tag; increment `rN` only for a newly verified replacement candidate.
21
- 3. Fast-forward code `line/<product-id>` to the tagged commit. Never advance code `main` here.
22
- 4. Copy the closeout assets into `.workflow/iterations/<version-id>/06-version-closeout/`, populate the code Tag identity, and compute the final manifest SHA-256.
23
- 5. Register the immutable closeout semantic revision directly as `release-ready` with the formal state CLI, and complete `06-version-closeout` with that registered artifact as evidence. Do not register a draft and mutate its status in place.
24
- 6. Commit all version workflow materials and create immutable workflow `workflow-ready/<version-id>/rN` at that exact workflow commit. Record the workflow commit, workflow Tag, and manifest checksum in the lineage index without rewriting the tagged manifest.
25
- 7. Verify both Tags and the manifest checksum. Inspect the current development scope revision, then run `state.mjs transition --expected-scope-revision <revision> --event version-closed --iteration-id <version-id> --artifact-id <closeout-artifact-id>` to update the audited cumulative development identity. Never edit `latest_line_version_id` directly.
26
- 8. Run `state.mjs snapshot create --id <version-id> --reason version-boundary`, then `state.mjs verify --history --since-anchor`. The first trusted anchor performs a full-history audit before creation; later anchors validate the suffix from the previous anchor.
27
- 9. Archive tasks with `task-state.mjs archive-version --version-status release-ready --candidate-id <candidate-id> --evidence <closeout-artifact-id>`. The command must first obtain `snapshot references` from the formal-state CLI and fail before writing if the anchor, scope, or candidate is missing. Verify that the version manifest references checksummed task summaries, complete attempt values, scope, candidate, Gate decisions, and the version-boundary anchor; then checkpoint the Git, anchor, and archive evidence and finish the task.
28
- 10. Invoke `$ai-delivery-evolve-workflow evaluate --safe-point version --iteration-id <version-id>`. Record trial results and decisions, but never use an Evolution result as release intent.
20
+ 2. Validate the candidate's codebase handbook and navigation index at the exact code commit. Record their status, checksums, owner, last review, and any stale/invalid findings in closeout evidence; require repair or explicit maintainer acceptance before marking documentation evidence complete.
21
+ 3. Freeze the candidate commit and create code `version-ready/<version-id>/rN`. Never move or replace an existing Tag; increment `rN` only for a newly verified replacement candidate.
22
+ 4. Fast-forward code `line/<product-id>` to the tagged commit. Never advance code `main` here.
23
+ 5. Copy the closeout assets into `.workflow/iterations/<version-id>/06-version-closeout/`, populate the code Tag identity, and compute the final manifest SHA-256.
24
+ 6. Register the immutable closeout semantic revision directly as `release-ready` with the formal state CLI, and complete `06-version-closeout` with that registered artifact as evidence. Do not register a draft and mutate its status in place.
25
+ 7. Commit all version workflow materials and create immutable workflow `workflow-ready/<version-id>/rN` at that exact workflow commit. Record the workflow commit, workflow Tag, and manifest checksum in the lineage index without rewriting the tagged manifest.
26
+ 8. Verify both Tags and the manifest checksum. Inspect the current development scope revision, then run `state.mjs transition --expected-scope-revision <revision> --event version-closed --iteration-id <version-id> --artifact-id <closeout-artifact-id>` to update the audited cumulative development identity. Never edit `latest_line_version_id` directly.
27
+ 9. Run `state.mjs snapshot create --id <version-id> --reason version-boundary`, then `state.mjs verify --history --since-anchor`. The first trusted anchor performs a full-history audit before creation; later anchors validate the suffix from the previous anchor.
28
+ 10. Archive tasks with `task-state.mjs archive-version --version-status release-ready --candidate-id <candidate-id> --evidence <closeout-artifact-id>`. The command must first obtain `snapshot references` from the formal-state CLI and fail before writing if the anchor, scope, or candidate is missing. Verify that the version manifest references checksummed task summaries, complete attempt values, scope, candidate, Gate decisions, and the version-boundary anchor; then checkpoint the Git, anchor, and archive evidence and finish the task.
29
+ 11. Invoke `$ai-delivery-evolve-workflow evaluate --safe-point version --iteration-id <version-id>`. Record trial results and decisions, but never use an Evolution result as release intent.
29
30
 
30
31
  ## Stop Boundary
31
32
 
32
33
  Report the release-ready version, code Tag, workflow Tag, manifest checksum, cumulative line head, archived task count, and next planned version. Stop and wait for either the next version iteration or an explicit user release request. Do not invoke release orchestration implicitly.
33
34
 
34
35
  Read [version-closeout-contract.md](references/version-closeout-contract.md) before writing outputs.
36
+
37
+ Before closeout, validate the confirmation summary and ensure confirmed product, architecture, standard, and risk decisions have authority references and matching checksums. Deferred or open decisions remain visible in closeout evidence. Closing a version does not imply release intent.
@@ -4,6 +4,7 @@
4
4
 
5
5
  - planned version ID, product ID, predecessor version, and iteration plan;
6
6
  - immutable candidate ID, commit, artifact digest, and passing verification decision;
7
+ - resolved or superseded `product-impact-assessment.yaml` bound to the candidate and the aligned product baseline;
7
8
  - complete closed-task summary and unresolved-risk statement;
8
9
  - current `line/<product-id>` head and applicable standards baseline.
9
10
 
@@ -17,4 +18,4 @@ After Candidate Assurance has completed for the same immutable candidate, the `r
17
18
 
18
19
  ## Failure rules
19
20
 
20
- Block closeout for active tasks, mutable candidates, failed verification, missing materials, Git divergence, an existing tag resolving to another commit, or a candidate that does not include a synchronized production hotfix. Mark affected candidates `stale`; never edit a previously closed version.
21
+ Block closeout for active tasks, mutable candidates, failed verification, missing materials, an unresolved or checksum-drifted product impact assessment, Git divergence, an existing tag resolving to another commit, or a candidate that does not include a synchronized production hotfix. Mark affected candidates `stale`; never edit a previously closed version.
@@ -24,7 +24,7 @@ This Skill owns `01-product-shaping`. Discovery, product definition, and prototy
24
24
 
25
25
  ## Preflight
26
26
 
27
- Read the project state, artifact registry, applicable standards, and existing product baseline. For a change, identify the affected terms, terminals, features, stories, and acceptance criteria before editing. In prototype-reconciliation mode also read the complete adjustment log, requirement change set, formal UI confirmation, exact Prototype revision and checksum, normalized Page and Review Scene catalogs, UI Mapping, and bidirectional product coverage.
27
+ Read the project state, artifact registry, applicable standards, existing product baseline, and the current `confirmation-summary.yaml`. For a change, identify the affected terms, terminals, features, stories, and acceptance criteria before editing. In prototype-reconciliation mode also read the shared `product-impact-assessment.yaml`, complete adjustment log, requirement change set, formal UI confirmation, exact Prototype revision and checksum, normalized Page and Review Scene catalogs, UI Mapping, and bidirectional product coverage. Facts discovered from the repository remain `observed_fact`; only the business sponsor confirms product intent, scope, terminology, priority, risk acceptance, or Gate decisions.
28
28
 
29
29
  ## Run Discovery
30
30
 
@@ -34,6 +34,8 @@ Read the project state, artifact registry, applicable standards, and existing pr
34
34
  4. Produce the discovery baseline and run completeness and contradiction checks.
35
35
  5. Submit discovery Gate A for human approval. Do not start product definition while Gate A is rejected or incomplete.
36
36
 
37
+ After each answer, append a structured confirmation record, recompute the frontier, and persist exactly one idempotent user-owned next action when another decision is required. Before Gate A or Gate B, produce a shared-understanding summary and link every confirmed business decision and domain term to its owning product artifact. Do not save the conversation transcript.
38
+
37
39
  ## Define The Product
38
40
 
39
41
  1. Define the product specification, capability structure, business flows, user stories, acceptance criteria, non-functional requirements, and business priority.
@@ -59,6 +61,7 @@ Required outputs:
59
61
  - `acceptance-criteria.csv`;
60
62
  - traceability association CSV files;
61
63
  - `product-baseline.yaml` with versions and item-level approval state.
64
+ - `confirmation-summary.yaml` with the current frontier, confirmed/rejected/deferred decisions, authority references, and shared-understanding result.
62
65
 
63
66
  In prototype-reconciliation mode also produce the terminal requirement change set, bidirectional product coverage, product artifact delta, and `product-prototype-reconciliation.yaml`.
64
67
 
@@ -68,12 +71,12 @@ Use the schemas and controlled values in [product-contract.md](references/produc
68
71
 
69
72
  Run this mode only after the candidate Prototype revision is approved for every visual or interactive Page and Review Scene and all of its adjustments are terminal.
70
73
 
71
- 1. Review every row in `requirement-change-set.csv`; classify it as approved, rejected, or requiring clarification. Do not approve a requirement merely because the prototype implements it.
74
+ 1. Review the shared `product-impact-assessment.yaml` first. Confirm that every `product-update-required` or `clarification-required` finding has a user-owned question, affected stable IDs, and a return reason. Review every row in `requirement-change-set.csv`; classify it as approved, rejected, or requiring clarification. Do not approve a requirement merely because the prototype implements it.
72
75
  2. Verify both directions of `prototype-product-coverage.csv`: every prototype behavior must resolve to an approved feature/story/acceptance criterion, and every visual product behavior must resolve to a prototype element or justified `not-applicable` row.
73
76
  3. Apply approved added, modified, retired, or superseded requirements to a new product baseline version. Preserve stable IDs for modifications and retire IDs instead of reusing them.
74
77
  4. Re-run Gate B for every changed product artifact and record exact approval evidence. When nothing changes, retain the existing baseline and record an `aligned` no-change decision.
75
78
  5. Write `product-prototype-reconciliation.yaml` with the input/output product baseline checksums, prototype/formal-UI checksums, terminal and terminology checks, requirement-change closure, stale artifacts, and required prototype revalidation.
76
- 6. Return rejected prototype behavior to experience for removal. Return an updated baseline to experience, mark the affected Page and Review Scene revisions stale, and require their staged re-approval in a new Prototype revision. Repeat until the receipt is `status: valid`, `decision: aligned`, and every requirement change is terminal.
79
+ 6. Return rejected prototype behavior to experience for removal. Return an updated baseline to experience, resolve the shared impact assessment, mark the affected Page and Review Scene revisions stale, and require their staged re-approval in a new Prototype revision. Repeat until the receipt is `status: valid`, `decision: aligned`, every requirement change is terminal, and every product impact assessment is `resolved` or `superseded`.
77
80
 
78
81
  ## Handoff
79
82
 
@@ -23,28 +23,31 @@ This Skill shares `02-solution-design` with `$ai-delivery-design-experience`. In
23
23
 
24
24
  ## Preflight
25
25
 
26
- Read the approved product baseline, business glossary, terminal matrix, feature catalog, applicable standards, and prior architecture decisions. Reject incomplete or inconsistent inputs instead of guessing product scope.
26
+ Read the approved product baseline, business glossary, terminal matrix, feature catalog, applicable standards, prior architecture decisions, the current `confirmation-summary.yaml`, and the configured code repository's `AGENTS.md`, `CODEBASE_GUIDE.md`, and relevant `docs/CODEBASE_INDEX.md` entries. Read [product-impact-assessment-contract.md](../ai-delivery-orchestrate/references/product-impact-assessment-contract.md) before classifying a design discovery. Treat handbook content and confirmation summaries as context/traceability only: architecture artifacts and decisions remain the sole authority for boundaries and dependency rules. Reject missing, stale, malformed, or conflicting references instead of guessing product scope; record a draft remediation when documentation is incomplete.
27
27
 
28
28
  ## Initial Mode
29
29
 
30
- 1. Convert non-functional requirements into measurable quality scenarios and budgets.
30
+ 1. Convert non-functional requirements into measurable quality scenarios and budgets. If a new budget, constraint, or tradeoff changes product scope, priority, risk acceptance, terminology, terminal coverage, or acceptance, create `product-impact-assessment.yaml` before continuing.
31
31
  2. Define system context, application and component boundaries, terminal implementation strategies, data ownership, authentication and authorization, security controls, deployment topology, observability, and operational constraints.
32
32
  3. Select technology stacks with exact supported versions, package and build tools, repository layout, dependency policy, and required commands.
33
33
  4. Draft APIs, events, data contracts, migration strategy, test seams, and delivery constraints.
34
34
  5. Record only decisions that are costly to reverse and based on real tradeoffs.
35
- 6. Submit major decisions for human approval before experience design proceeds.
35
+ 6. Classify each discovery with the shared assessment. `no-impact` and `architecture-only` require evidence; `product-update-required` and `clarification-required` return to `01-product-shaping` and block the architecture handoff until product reconciliation is valid.
36
+ 7. Submit major decisions for human approval before experience design proceeds.
36
37
 
37
38
  Major decisions include platforms, paid services, security or privacy boundaries, hard-to-reverse data or infrastructure choices, material cost/performance/schedule tradeoffs, and deviations from approved product scope.
38
39
 
39
40
  ## Reconcile Mode
40
41
 
41
- 1. Read the experience baseline, `ui-handoff.yaml`, both staged Gate receipts (`UX-VS` and `UX-UI`), aligned `product-prototype-reconciliation.yaml` receipt, experience/requirement change sets, interaction contract, design tokens, framework selection, component-state matrix, page-component map, the exact immutable Prototype revision and checksum, its source and review-bundle checksums, the normalized terminal, Page, Review Scene, trigger-condition, route, and UI Mapping catalogs, review/impact records, traceability, and source confirmation. Verify every exact identity/checksum and require the handoff to be complete and free of stale references. Reject a missing or conflicting reference; never infer a relationship from a file name or catalog order.
42
+ 1. Read the experience baseline, `ui-handoff.yaml`, both staged Gate receipts (`UX-VS` and `UX-UI`), the aligned `product-prototype-reconciliation.yaml` receipt, the shared `product-impact-assessment.yaml`, experience/requirement change sets, interaction contract, design tokens, framework selection, component-state matrix, page-component map, the exact immutable Prototype revision and checksum, its source and review-bundle checksums, the normalized terminal, Page, Review Scene, trigger-condition, route, and UI Mapping catalogs, review/impact records, traceability, and source confirmation. Verify every exact identity/checksum and require the handoff to be complete and free of stale references. Reject a missing or conflicting reference; never infer a relationship from a file name or catalog order.
42
43
  2. Resolve every affected Page, Review Scene, UI component, frontend source, and acceptance ID through the pinned UI Mapping. Verify that the selected UI framework/version is compatible with the architecture stack and dependency policy, and that every mapped interaction, state, permission, query, upload, real-time behavior, failure mode, responsive rule, and accessibility requirement is technically supported. Use stable change, terminal, Page, Review Scene, prototype-element, UI Mapping, component, frontend-source, and acceptance IDs in findings.
43
44
  3. Write one `prototype-architecture-validation.yaml` for the Prototype revision with the UI handoff identity/checksum, Prototype revision and UI Mapping checksums, all consumed artifact versions/checksums, exact architecture baseline version/checksum, implementability decision, affected changes/Pages/Review Scenes/mappings/components/acceptance criteria, issues, and return node. An accepted receipt uses `status: valid`; a `changes-required` receipt uses `status: invalid`. Accept the handoff only when the receipt passes, then advance accepted experience changes from `formal-ui-confirmed` to `architecture-accepted` and `ready-for-development` through the state CLI.
44
- 4. Return product or experience defects to their producer. Do not silently weaken approved behavior or edit the frozen prototype.
45
+ 4. Wrap any product-affecting architecture finding in `product-impact-assessment.yaml`. Return `product-update-required` and `clarification-required` to `01-product-shaping`; return experience defects to their producer. Do not silently weaken approved behavior, edit the frozen prototype, or continue with an unresolved assessment.
45
46
  5. Finalize APIs, data access, events, component boundaries, test seams, deployment requirements, and implementation constraints.
46
47
  6. Reopen human approval only when reconciliation creates or changes a major decision.
47
48
 
49
+ For each new architecture decision, append a confirmation record with factual evidence, alternatives, recommendation, user decision, impact, and owning architecture artifact. Ask only frontier decisions that are not answerable from the environment. A confirmed record never substitutes for the architecture Gate.
50
+
48
51
  ## Outputs
49
52
 
50
53
  Produce one versioned architecture baseline containing:
@@ -61,6 +64,8 @@ Produce one versioned architecture baseline containing:
61
64
  - prototype architecture validation receipt in reconcile mode;
62
65
  - UI framework/dependency acceptance and exact `ui-handoff.yaml` receipt in reconcile mode;
63
66
  - final test seams and component impact map.
67
+ - handbook review evidence: exact code commit, files/sections consulted, stale or missing findings, and maintainer confirmation required for any promoted rule.
68
+ - confirmation summary and decision-to-architecture artifact traceability.
64
69
 
65
70
  Do not require DDD constructs. Use business terms from the product manual and provide explicit mappings for unavoidable technical names.
66
71