intentdna 1.7.4 → 1.8.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 (152) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/LICENSE +201 -0
  4. package/README.md +143 -194
  5. package/dist/assets/candidates.d.ts +124 -0
  6. package/dist/assets/candidates.js +1249 -0
  7. package/dist/assets/catalog.d.ts +101 -0
  8. package/dist/assets/catalog.js +311 -0
  9. package/dist/assets/evidence.d.ts +93 -0
  10. package/dist/assets/evidence.js +391 -0
  11. package/dist/assets/index.d.ts +4 -0
  12. package/dist/assets/index.js +4 -0
  13. package/dist/assets/metadata.d.ts +19 -0
  14. package/dist/assets/metadata.js +227 -0
  15. package/dist/cli/commands/assets.d.ts +65 -0
  16. package/dist/cli/commands/assets.js +2871 -0
  17. package/dist/cli/commands/auth.d.ts +322 -0
  18. package/dist/cli/commands/auth.js +1592 -0
  19. package/dist/cli/commands/cloud-auth-guidance.d.ts +2 -0
  20. package/dist/cli/commands/cloud-auth-guidance.js +4 -0
  21. package/dist/cli/commands/cloud.d.ts +1359 -0
  22. package/dist/cli/commands/cloud.js +8364 -0
  23. package/dist/cli/commands/evolve.js +18 -2
  24. package/dist/cli/commands/generate.js +25 -2
  25. package/dist/cli/commands/guard.d.ts +1 -1
  26. package/dist/cli/commands/guard.js +1 -1
  27. package/dist/cli/commands/guide.d.ts +15 -0
  28. package/dist/cli/commands/guide.js +1747 -0
  29. package/dist/cli/commands/init.d.ts +12 -0
  30. package/dist/cli/commands/init.js +95 -60
  31. package/dist/cli/commands/org.d.ts +16 -0
  32. package/dist/cli/commands/org.js +2393 -0
  33. package/dist/cli/commands/release.d.ts +59 -0
  34. package/dist/cli/commands/release.js +716 -0
  35. package/dist/cli/commands/report.d.ts +82 -0
  36. package/dist/cli/commands/report.js +1516 -0
  37. package/dist/cli/commands/run.d.ts +6 -1
  38. package/dist/cli/commands/run.js +95 -26
  39. package/dist/cli/commands/sync.d.ts +8 -1
  40. package/dist/cli/commands/sync.js +436 -141
  41. package/dist/cli/commands/templates.d.ts +64 -0
  42. package/dist/cli/commands/templates.js +2151 -1
  43. package/dist/cli/commands/workflow.d.ts +26 -0
  44. package/dist/cli/commands/workflow.js +3053 -0
  45. package/dist/cli/index.js +719 -42
  46. package/dist/compiler/cascade.js +4 -9
  47. package/dist/compiler/compile.js +1 -0
  48. package/dist/governance/evidence-capture-attribution.d.ts +12 -0
  49. package/dist/governance/evidence-capture-attribution.js +46 -0
  50. package/dist/governance/index.d.ts +2 -0
  51. package/dist/governance/index.js +1 -0
  52. package/dist/hooks/cli.d.ts +6 -0
  53. package/dist/hooks/cli.js +168 -12
  54. package/dist/hooks/enforce.d.ts +1 -0
  55. package/dist/hooks/protocol.d.ts +1 -1
  56. package/dist/hooks/protocol.js +1 -1
  57. package/dist/hooks/state.d.ts +41 -0
  58. package/dist/hooks/state.js +126 -2
  59. package/dist/index.d.ts +3 -0
  60. package/dist/index.js +3 -0
  61. package/dist/mcp/tools-state.js +2 -0
  62. package/dist/organization/index.d.ts +121 -0
  63. package/dist/organization/index.js +413 -0
  64. package/dist/runtime/claude-sync-target.d.ts +49 -0
  65. package/dist/runtime/claude-sync-target.js +280 -0
  66. package/dist/runtime/codex-adapter.d.ts +254 -0
  67. package/dist/runtime/codex-adapter.js +1204 -0
  68. package/dist/runtime/codex-sync-target.d.ts +33 -0
  69. package/dist/runtime/codex-sync-target.js +241 -0
  70. package/dist/runtime/index.d.ts +8 -0
  71. package/dist/runtime/index.js +4 -0
  72. package/dist/runtime/output-artifact-registry.d.ts +1 -1
  73. package/dist/runtime/output-artifact-registry.js +2 -0
  74. package/dist/runtime/settings-adapter.d.ts +1 -1
  75. package/dist/runtime/settings-adapter.js +1 -1
  76. package/dist/runtime/skill-adapter.d.ts +5 -1
  77. package/dist/runtime/skill-adapter.js +120 -34
  78. package/dist/runtime/sync-artifact-registry.d.ts +99 -0
  79. package/dist/runtime/sync-artifact-registry.js +194 -0
  80. package/dist/runtime/sync-target-plan.d.ts +45 -0
  81. package/dist/runtime/sync-target-plan.js +19 -0
  82. package/dist/schema/controller-registry.d.ts +8 -1
  83. package/dist/schema/controller-registry.js +8 -0
  84. package/dist/schema/types.d.ts +35 -23
  85. package/dist/schema/types.js +10 -1
  86. package/dist/schema/validate.js +22 -22
  87. package/dist/schema/validators/controllers.js +38 -20
  88. package/dist/schema/workflow-authoring-contract.d.ts +29 -0
  89. package/dist/schema/workflow-authoring-contract.js +109 -0
  90. package/dist/schema/yaml-parser.js +18 -0
  91. package/dist/templates/api-backend.dna.yaml +19 -0
  92. package/dist/templates/brainstorming-first.dna.yaml +19 -0
  93. package/dist/templates/code-cleanup.dna.yaml +19 -0
  94. package/dist/templates/code-review-pipeline.dna.yaml +18 -0
  95. package/dist/templates/documentation-writer.dna.yaml +19 -0
  96. package/dist/templates/flutter-behavior-lock.dna.yaml +19 -0
  97. package/dist/templates/flutter-refactoring-rescue.dna.yaml +19 -0
  98. package/dist/templates/flutter-rewrite-diagnosis-review.dna.yaml +210 -0
  99. package/dist/templates/flutter-rewrite-fix-review-loop.dna.yaml +260 -0
  100. package/dist/templates/flutter-rewrite-new.dna.yaml +506 -0
  101. package/dist/templates/flutter-rewrite.dna.yaml +20 -0
  102. package/dist/templates/frontend-quality.dna.yaml +19 -0
  103. package/dist/templates/full-pipeline.dna.yaml +20 -0
  104. package/dist/templates/marketplace.d.ts +92 -0
  105. package/dist/templates/marketplace.js +502 -0
  106. package/dist/templates/metadata.d.ts +25 -0
  107. package/dist/templates/metadata.js +136 -3
  108. package/dist/templates/mobile-dev.dna.yaml +19 -0
  109. package/dist/templates/multi-agent-handoff-coordination.dna.yaml +156 -0
  110. package/dist/templates/multi-perspective-review.dna.yaml +19 -0
  111. package/dist/templates/persistent-executor.dna.yaml +19 -0
  112. package/dist/templates/qa-loop.dna.yaml +18 -0
  113. package/dist/templates/release-evidence-gate.dna.yaml +131 -0
  114. package/dist/templates/requirements-gate.dna.yaml +19 -0
  115. package/dist/templates/research-orchestration.dna.yaml +19 -0
  116. package/dist/templates/root-cause-analysis.dna.yaml +19 -0
  117. package/dist/templates/safe-refactoring.dna.yaml +321 -0
  118. package/dist/templates/secure-dev.dna.yaml +19 -0
  119. package/dist/templates/subagent-parallel.dna.yaml +19 -0
  120. package/dist/templates/systematic-debugging.dna.yaml +19 -0
  121. package/dist/templates/tdd-strict.dna.yaml +19 -0
  122. package/dist/templates/ui-visual-regression-qa.dna.yaml +133 -0
  123. package/dist/templates/workflow-author.dna.yaml +302 -0
  124. package/dist/templates/workflow-blocked-scope-triage.dna.yaml +242 -0
  125. package/dist/templates/workflow-completion-audit.dna.yaml +254 -0
  126. package/dist/templates/workflow-cross-boundary-resource-approval.dna.yaml +249 -0
  127. package/dist/templates/workflow-evidence-review.dna.yaml +198 -0
  128. package/dist/templates/workflow-module-inventory.dna.yaml +257 -0
  129. package/dist/templates/workflow-runtime-smoke-review.dna.yaml +252 -0
  130. package/dist/templates/workflow-verification-command-routing.dna.yaml +278 -0
  131. package/dist/workflow/authoring-packet.d.ts +67 -0
  132. package/dist/workflow/authoring-packet.js +218 -0
  133. package/dist/workflow/draft.d.ts +159 -0
  134. package/dist/workflow/draft.js +800 -0
  135. package/dist/workflow/index.d.ts +3 -0
  136. package/dist/workflow/index.js +3 -0
  137. package/dist/workflow/suggestion-review.d.ts +65 -0
  138. package/dist/workflow/suggestion-review.js +245 -0
  139. package/package.json +1 -1
  140. package/spec/README.md +15 -48
  141. package/spec/codex-adapter-contract.md +176 -0
  142. package/spec/sync-target-plan.md +158 -0
  143. package/spec/workflow-capability-ir.md +153 -0
  144. package/spec/agent-dispatch-fix.md +0 -116
  145. package/spec/control-plane-convergence-handoff-2026-04-24.md +0 -432
  146. package/spec/flutter-rewrite-template-optimization.md +0 -301
  147. package/spec/foundation-hardening.md +0 -178
  148. package/spec/hooks-infra-harness-hardening.md +0 -741
  149. package/spec/multi-config.md +0 -172
  150. package/spec/parallel-isolation.md +0 -268
  151. package/spec/template-version-namespace-fix.md +0 -653
  152. package/spec/workflow-pipeline.md +0 -101
@@ -0,0 +1,1747 @@
1
+ /**
2
+ * dna guide - product route navigator for workflow governance.
3
+ */
4
+ import { activeEvidenceFollowupReviewRoute, buildWorkflowAssetCandidateBacklog, buildWorkflowAssetEvidenceIndex, listWorkflowAssets, } from "../../assets/index.js";
5
+ import { readOrganizationProfile, reviewOrganization } from "../../organization/index.js";
6
+ import { WORKFLOW_ASSET_IDS, WORKFLOW_SUGGESTION_IDS } from "../../templates/metadata.js";
7
+ const LOCAL_REPORT_PACKAGE_PATH = ".dna/reports/latest-report-package.json";
8
+ const LOCAL_REPORT_ENVELOPE_PATH = ".dna/reports/ingest/local-envelope.json";
9
+ const LOCAL_REPORT_SIGN_COMMAND = `dna report sign --package ${LOCAL_REPORT_PACKAGE_PATH} --output ${LOCAL_REPORT_ENVELOPE_PATH} --json`;
10
+ const LOCAL_REPORT_VERIFY_COMMAND = `dna report verify ${LOCAL_REPORT_ENVELOPE_PATH} --json`;
11
+ function preferredAsset(assets, name) {
12
+ if (name)
13
+ return assets.find((asset) => asset.name === name);
14
+ return assets.find((asset) => asset.name === WORKFLOW_ASSET_IDS.default) ?? assets[0];
15
+ }
16
+ function syncTargets(review) {
17
+ if (!review)
18
+ return [];
19
+ return [...new Set(review.projects.flatMap((project) => project.syncTargets))];
20
+ }
21
+ function syncCommand(targets) {
22
+ return targets.some((target) => target === "codex" || target === "codex_cli") ? "dna sync --codex" : "dna sync";
23
+ }
24
+ function syncDryRunCommand(targets) {
25
+ return `${syncCommand(targets)} --dry-run`;
26
+ }
27
+ function commandQuote(value) {
28
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
29
+ }
30
+ function routeInputs(opts) {
31
+ return contextualRouteInputs(opts);
32
+ }
33
+ function contextualRouteInputs(opts, profile) {
34
+ const project = profile?.projects[0];
35
+ return {
36
+ organizationName: opts.name?.trim() || profile?.organization.name || "My Org",
37
+ projectName: opts.project?.trim() || project?.name || "My Project",
38
+ workflowGoal: opts.goal?.trim() || "Rewrite module with logic equivalence",
39
+ syncTarget: opts.syncTarget?.trim() || project?.syncTargets[0] || "codex",
40
+ };
41
+ }
42
+ function saveTemplateName(assetName, suffix) {
43
+ return `${assetName}-${suffix}`;
44
+ }
45
+ function templateIdForAsset(assetName) {
46
+ return `template_${assetName.replaceAll("-", "_")}`;
47
+ }
48
+ function evolutionPreviewCommand(assetName, asset) {
49
+ return asset?.evolution.previewCommand ?? `dna evolve ${asset?.dnaId ?? templateIdForAsset(assetName)}`;
50
+ }
51
+ function evidenceDraftSuggestionId(evidence) {
52
+ if (!evidence)
53
+ return undefined;
54
+ const active = evidence.modules.filter((module) => module.verdict !== "PASS" ||
55
+ !module.moduleComplete ||
56
+ module.remainingCount > 0 ||
57
+ module.newRedCount > 0);
58
+ const modelFocused = active.some((module) => /model|behavior lock|placeholder|assert/i.test(`${module.nextRoundFocus ?? ""} ${module.failureReason ?? ""}`));
59
+ if (modelFocused)
60
+ return WORKFLOW_SUGGESTION_IDS.modelVerifier;
61
+ if (evidence.modules.some((module) => module.blockedCount > 0))
62
+ return WORKFLOW_SUGGESTION_IDS.blockedTriage;
63
+ return undefined;
64
+ }
65
+ function suggestionDraftCommand(assetName, evidence) {
66
+ const suggestionId = evidenceDraftSuggestionId(evidence);
67
+ if (!suggestionId)
68
+ return undefined;
69
+ if (suggestionId === WORKFLOW_SUGGESTION_IDS.blockedTriage)
70
+ return `dna assets adoption ${WORKFLOW_ASSET_IDS.blockedScopeTriage}`;
71
+ return `dna workflow review-suggestion --from-template ${assetName} --workflow fix --suggestion ${suggestionId} --decision accept`;
72
+ }
73
+ function suggestionAcceptedDraftCommand(assetName, evidence) {
74
+ const suggestionId = evidenceDraftSuggestionId(evidence);
75
+ if (!suggestionId || suggestionId === WORKFLOW_SUGGESTION_IDS.blockedTriage)
76
+ return undefined;
77
+ return `dna workflow improve-from-suggestions --from-template ${assetName} --workflow fix --suggestion ${suggestionId} --save-template ${assetName}-v2`;
78
+ }
79
+ function guideActiveCandidate(candidate) {
80
+ if (!candidate)
81
+ return undefined;
82
+ return {
83
+ id: candidate.id,
84
+ type: candidate.type,
85
+ priority: candidate.priority,
86
+ title: candidate.title,
87
+ candidateAssetName: candidate.candidateAssetName,
88
+ sourceAsset: candidate.sourceAsset,
89
+ evidence: candidate.evidence,
90
+ nextCommand: candidate.nextCommand,
91
+ actionKind: candidate.action.kind,
92
+ actionPath: candidate.actionPath,
93
+ mutationBoundary: candidate.mutationBoundary,
94
+ plainLanguage: candidate.plainLanguage,
95
+ continuityBoundary: candidate.continuityBoundary,
96
+ };
97
+ }
98
+ function activeCandidateCommand(candidate) {
99
+ if (!candidate || candidate.type !== "active_evidence_followup")
100
+ return undefined;
101
+ return candidate.nextCommand;
102
+ }
103
+ function activeCandidateCurrentCommand(candidate, route) {
104
+ if (!candidate || candidate.type !== "active_evidence_followup")
105
+ return undefined;
106
+ return route?.currentCommand ?? candidate.nextCommand;
107
+ }
108
+ function activeCandidateWrites(candidate, route) {
109
+ if (route)
110
+ return route.currentWrites;
111
+ return candidate?.actionKind !== undefined && candidate.actionKind !== "review";
112
+ }
113
+ function currentJourneyId(stage) {
114
+ if (stage === "organization_setup")
115
+ return "organization";
116
+ if (stage === "asset_configuration" || stage === "evidence_review")
117
+ return "asset_library";
118
+ if (stage === "asset_binding" || stage === "manager_review")
119
+ return "manager_review";
120
+ return "runtime_distribution";
121
+ }
122
+ function journeyStatus(params) {
123
+ if (params.id === params.current)
124
+ return "current";
125
+ if (params.id === "organization")
126
+ return params.hasOrganization ? "ready" : "current";
127
+ if (params.id === "asset_library")
128
+ return params.hasOrganization ? "ready" : "blocked";
129
+ if (params.id === "workflow_authoring")
130
+ return "ready";
131
+ if (params.id === "manager_review")
132
+ return params.hasOrganization ? "ready" : "blocked";
133
+ if (params.id === "runtime_distribution")
134
+ return params.readyForRuntime ? "ready" : "blocked";
135
+ if (params.id === "improvement_loop")
136
+ return params.evidenceOpen ? "current" : "later";
137
+ return "later";
138
+ }
139
+ function journeySteps(params) {
140
+ const project = commandQuote(params.inputs.projectName);
141
+ const organization = commandQuote(params.inputs.organizationName);
142
+ const goal = commandQuote(params.inputs.workflowGoal);
143
+ const current = currentJourneyId(params.recommendation.stage);
144
+ const hasOrganization = params.state.organization.configured;
145
+ const assetConfigured = params.state.asset?.configured === true;
146
+ const evidenceOpen = evidenceGate(params.state.evidence) === "open";
147
+ const readyForRuntime = params.recommendation.stage === "runtime_sync";
148
+ const status = (id) => journeyStatus({
149
+ id,
150
+ current,
151
+ hasOrganization,
152
+ assetConfigured,
153
+ evidenceOpen,
154
+ readyForRuntime,
155
+ });
156
+ const sync = syncCommand(params.targets.length > 0 ? params.targets : [params.inputs.syncTarget]);
157
+ const improvementCommand = activeCandidateCurrentCommand(params.activeCandidate, params.activeCandidateRoute)
158
+ ?? suggestionDraftCommand(params.assetName, params.evidence)
159
+ ?? `dna assets suggestions ${params.assetName}`;
160
+ const improvementWrites = activeCandidateCurrentCommand(params.activeCandidate, params.activeCandidateRoute) !== undefined
161
+ ? activeCandidateWrites(params.activeCandidate, params.activeCandidateRoute)
162
+ : false;
163
+ return [
164
+ {
165
+ id: "organization",
166
+ label: "Create the governed workspace",
167
+ command: `dna org intake ${project} --name ${organization} --asset ${params.assetName} --sync-target ${params.inputs.syncTarget}`,
168
+ purpose: "Represent the organization, project, workflow asset, and sync target before rollout or runtime install.",
169
+ owner: "manager",
170
+ writes: false,
171
+ status: status("organization"),
172
+ answers: "Where does this workflow asset live, who owns it, and which runtime target can receive it?",
173
+ next: hasOrganization ? "Review asset posture and configuration." : "Run the reviewed dna org init command from org intake.",
174
+ },
175
+ {
176
+ id: "asset_library",
177
+ label: "Choose or improve a workflow asset",
178
+ command: `dna assets lifecycle ${params.assetName}`,
179
+ purpose: "Inspect lineage, cascade, evidence, candidates, suggestions, adoption, and sync posture in one place.",
180
+ owner: "dna_core",
181
+ writes: false,
182
+ status: status("asset_library"),
183
+ answers: "Is there a reusable workflow asset, what evidence backs it, and what version should be reviewed next?",
184
+ next: assetConfigured ? "Move to manager review or evidence triage." : "Use dna org configure-plan before rollout or sync.",
185
+ },
186
+ {
187
+ id: "workflow_authoring",
188
+ label: "Describe or edit the workflow without a canvas",
189
+ command: `dna workflow route ${goal} --name ${organization} --project ${project} --sync-target ${params.inputs.syncTarget}`,
190
+ purpose: "Turn natural language into reuse, draft, edit-plan, diff, adoption, organization, rollout, and sync steps.",
191
+ owner: "user",
192
+ writes: false,
193
+ status: status("workflow_authoring"),
194
+ answers: "How do I create or adjust a workflow through text, examples, operations, and reviewable versions?",
195
+ next: `Save reviewed drafts with --save-template, then compare with dna assets diff ${params.assetName} ${params.assetName}-v2.`,
196
+ },
197
+ {
198
+ id: "manager_review",
199
+ label: "Review system status before action",
200
+ command: "dna org review",
201
+ purpose: "Show configured assets, evidence gates, sync readiness, blockers, release gate, and manager next commands.",
202
+ owner: "manager",
203
+ writes: false,
204
+ status: status("manager_review"),
205
+ answers: "Can this workflow be adopted, configured, rolled out, synced, or should evidence be handled first?",
206
+ next: evidenceOpen ? "Close or triage evidence before rollout." : "Use dna org rollout when manager gates are clear.",
207
+ },
208
+ {
209
+ id: "runtime_distribution",
210
+ label: "Sync only after rollout is ready",
211
+ command: "dna org rollout",
212
+ purpose: `Review target-level readiness before running ${sync}; deploy web/public surfaces only through release deploy-plan.`,
213
+ owner: "runtime",
214
+ writes: false,
215
+ status: status("runtime_distribution"),
216
+ answers: "Which targets are ready, partial, or blocked, and what sync command is allowed now?",
217
+ next: readyForRuntime ? `${sync}, then run runtime smoke review.` : "Resolve org rollout blockers before sync.",
218
+ },
219
+ {
220
+ id: "improvement_loop",
221
+ label: "Feed dogfood evidence back into assets",
222
+ command: improvementCommand,
223
+ purpose: "Convert repeated dogfood/runtime findings into human-reviewed workflow suggestions, drafts, diffs, and adoption paths.",
224
+ owner: "dna_core",
225
+ writes: improvementWrites,
226
+ status: status("improvement_loop"),
227
+ answers: "What should be improved from real runs without automatically mutating policy?",
228
+ next: "Accept a suggestion into a draft version, review diff/adoption, bind it, then rollout again.",
229
+ },
230
+ ];
231
+ }
232
+ function operatingPaths(params) {
233
+ const goal = commandQuote(params.inputs.workflowGoal);
234
+ const project = commandQuote(params.inputs.projectName);
235
+ const organization = commandQuote(params.inputs.organizationName);
236
+ const evidenceOpen = evidenceGate(params.state.evidence) === "open";
237
+ const hasOrganization = params.state.organization.configured;
238
+ const activeCommand = activeCandidateCurrentCommand(params.activeCandidate, params.activeCandidateRoute);
239
+ const currentStage = params.recommendation.stage;
240
+ const assetStatus = evidenceOpen || currentStage === "asset_configuration" ? "current" : "ready";
241
+ const managerStatus = hasOrganization ? currentStage === "asset_binding" || currentStage === "manager_review" ? "current" : "ready" : "blocked";
242
+ return [
243
+ {
244
+ id: "user_path",
245
+ label: "User path",
246
+ command: `dna workflow route ${goal} --name ${organization} --project ${project} --sync-target ${params.inputs.syncTarget}`,
247
+ purpose: "Let users describe, draft, edit, review, distribute, and improve workflows without a canvas.",
248
+ owner: "user",
249
+ writes: false,
250
+ status: "ready",
251
+ surface: "workflow_route",
252
+ source: "workflow_route.userPath",
253
+ answers: "What do I want this workflow to do, and should I reuse, draft, or edit a governed asset?",
254
+ handoff: `When a workflow asset is selected or drafted, continue with dna assets lifecycle ${params.assetName}.`,
255
+ boundary: "No canvas, dashboard write-back, Obsidian mutation, or harness-specific setup is required.",
256
+ },
257
+ {
258
+ id: "asset_path",
259
+ label: "Asset path",
260
+ command: `dna assets lifecycle ${params.assetName}`,
261
+ purpose: "Manage the workflow asset through governance, evidence, version shaping, manager review, binding, rollout, sync, and release gates.",
262
+ owner: "dna_core",
263
+ writes: false,
264
+ status: assetStatus,
265
+ surface: "asset_lifecycle",
266
+ source: "assets_lifecycle.assetPath",
267
+ answers: "What asset version is safe to review next, and which gates block rollout or sync?",
268
+ handoff: activeCommand
269
+ ? `Current dogfood evidence should continue through the reviewed follow-up route: ${activeCommand}.`
270
+ : "When the asset version is reviewable, continue with dna org review.",
271
+ boundary: "Templates carry workflow shape; shared governance gates stay in dna CLI/core/runtime.",
272
+ },
273
+ {
274
+ id: "manager_path",
275
+ label: "Manager path",
276
+ command: "dna org review",
277
+ purpose: "Let managers review system state, evidence gates, configured assets, rollout readiness, runtime sync, and release gate.",
278
+ owner: "manager",
279
+ writes: false,
280
+ status: managerStatus,
281
+ surface: "organization_review",
282
+ source: "org_review.managerPath",
283
+ answers: "Can this system roll out, sync, or release now, and what must be handled first?",
284
+ handoff: evidenceOpen ? `Return to ${activeCommand ?? `dna assets suggestions ${params.assetName}`} before rollout or sync.` : "Use dna org rollout before runtime sync.",
285
+ boundary: "Manager review is read-only; rollout, sync, and Vercel deployment remain explicit downstream actions.",
286
+ },
287
+ ];
288
+ }
289
+ function knowledgeLinks() {
290
+ return [
291
+ {
292
+ id: "product_skeleton",
293
+ label: "IntentDNA product skeleton",
294
+ path: "wiki/IntentDNA Product Skeleton.md",
295
+ role: "internal_memory",
296
+ status: "active",
297
+ useFor: "Recover the current project route, product objects, boundaries, operating paths, and next gaps.",
298
+ boundary: "Obsidian/wiki is project memory only; it does not define runtime state, policy truth, or dashboard authority.",
299
+ },
300
+ {
301
+ id: "product_spine_doc",
302
+ label: "Product spine reference",
303
+ path: "docs/archive/2026H1/references/intentdna-product-spine.md",
304
+ role: "reference",
305
+ status: "active",
306
+ useFor: "Audit the long-form product route, execution lanes, drift risks, and completion direction.",
307
+ boundary: "Reference docs guide implementation choices; executable behavior must still live in dna CLI/core/runtime.",
308
+ },
309
+ {
310
+ id: "workflow_route",
311
+ label: "Workflow governance route note",
312
+ path: "wiki/IntentDNA Workflow Governance Route.md",
313
+ role: "internal_memory",
314
+ status: "active",
315
+ useFor: "Recover how user_path, asset_path, and manager_path connect in project work.",
316
+ boundary: "Route notes explain the spine; commands and tests remain authoritative for product behavior.",
317
+ },
318
+ {
319
+ id: "flutter_rewrite_asset",
320
+ label: "Flutter rewrite workflow asset note",
321
+ path: "wiki/Flutter Rewrite Workflow Asset.md",
322
+ role: "internal_memory",
323
+ status: "active",
324
+ useFor: "Connect dogfood learning back to reusable workflow assets and template improvements.",
325
+ boundary: "The note summarizes dogfood; canonical evidence remains in the dogfood project and dna asset evidence index.",
326
+ },
327
+ {
328
+ id: "dogfood_evidence",
329
+ label: "Flutter rewrite dogfood evidence",
330
+ path: "/Users/samuel/lawark/lwk_flutter_v2-rewrite/.dna/fix-progress",
331
+ role: "dogfood_evidence",
332
+ status: "reference",
333
+ useFor: "Mine real run evidence for workflow candidates, blocked modules, and improvement suggestions.",
334
+ boundary: "Dogfood evidence informs workflow assets; OMC/Claude logs are not product architecture or governance truth.",
335
+ },
336
+ ];
337
+ }
338
+ function foundationSteps(params) {
339
+ const sync = syncCommand(params.targets.length > 0 ? params.targets : [params.inputs.syncTarget]);
340
+ const evidence = params.state.evidence;
341
+ const evidenceStatus = evidenceGate(evidence);
342
+ const assetConfigured = params.state.asset?.configured === true;
343
+ const hasOrganization = params.state.organization.configured;
344
+ const configuredSignal = assetConfigured ? "asset configured" : "asset not configured";
345
+ const evidenceSignal = evidence
346
+ ? `${evidence.pass}/${evidence.modules} PASS, blocked=${evidence.blocked}, remaining=${evidence.remaining}`
347
+ : "no evidence index";
348
+ const cascadeSignal = params.state.asset
349
+ ? `cascade=${params.state.asset.cascade}`
350
+ : "cascade=unknown";
351
+ const evolutionSignal = params.state.asset
352
+ ? `evolution=${params.state.asset.evolution}`
353
+ : "evolution=unknown";
354
+ return [
355
+ {
356
+ id: "workflow_assets",
357
+ label: "Workflow assets",
358
+ command: `dna assets lifecycle ${params.assetName}`,
359
+ purpose: "Turn useful work methods into governed assets before organization binding, rollout, or runtime sync.",
360
+ owner: "dna_core",
361
+ writes: false,
362
+ status: "ready",
363
+ signal: configuredSignal,
364
+ next: "Use lifecycle, lineage, candidates, diff, and adoption to manage asset versions.",
365
+ },
366
+ {
367
+ id: "cascade_compiler",
368
+ label: "Cascade compiler",
369
+ command: `dna assets governance ${params.assetName}`,
370
+ purpose: "Compile inherited layers and explain winning constraints before edits, sync, or evolution mutation.",
371
+ owner: "dna_core",
372
+ writes: false,
373
+ status: params.state.asset ? "ready" : "blocked",
374
+ signal: cascadeSignal,
375
+ next: "Keep cascade decisions in dna core; adapters only receive compiled runtime artifacts.",
376
+ },
377
+ {
378
+ id: "evolution_preview",
379
+ label: "Self-evolution preview",
380
+ command: evolutionPreviewCommand(params.assetName, params.asset),
381
+ purpose: "Preview outcome-derived marker changes without automatically mutating workflow policy.",
382
+ owner: "dna_core",
383
+ writes: false,
384
+ status: evidenceStatus === "open" ? "blocked" : "ready",
385
+ signal: evolutionSignal,
386
+ next: evidenceStatus === "open"
387
+ ? "Resolve or convert active dogfood evidence into a reviewed draft before marker mutation."
388
+ : "Review marker preview before any explicit evolve/sync mutation.",
389
+ },
390
+ {
391
+ id: "verification_routing",
392
+ label: "Verification command routing",
393
+ command: `dna assets adoption ${WORKFLOW_ASSET_IDS.verificationCommandRouting}`,
394
+ purpose: "Choose the authoritative command root, scope, and machine-readable evidence path before completion or rollout decisions.",
395
+ owner: "dna_core",
396
+ writes: false,
397
+ status: "ready",
398
+ signal: "wrong-root and weak verification are governed before evidence review",
399
+ next: "Use verification routing when tests/analyze/build commands could run from the wrong root, wrong package, or weak partial scope.",
400
+ },
401
+ {
402
+ id: "evidence_gate",
403
+ label: "Evidence gate",
404
+ command: `dna assets evidence ${params.assetName}`,
405
+ purpose: "Use dogfood/runtime evidence to block premature rollout, sync, or evolution mutation.",
406
+ owner: "dna_core",
407
+ writes: false,
408
+ status: evidenceStatus === "open" ? "open" : evidenceStatus === "clear" ? "ready" : "blocked",
409
+ signal: evidenceSignal,
410
+ next: evidenceStatus === "open"
411
+ ? `Run dna assets candidates ${params.assetName} or dna assets suggestions ${params.assetName}.`
412
+ : "Keep evidence attached to review packets and manager gates.",
413
+ },
414
+ {
415
+ id: "organization_rollout",
416
+ label: "Organization rollout",
417
+ command: "dna org rollout",
418
+ purpose: "Let managers review configured assets, active bindings, target readiness, and blockers before sync.",
419
+ owner: "manager",
420
+ writes: false,
421
+ status: hasOrganization ? "ready" : "blocked",
422
+ signal: hasOrganization ? `sync_targets=${params.state.organization.syncTargets.join(",") || "none"}` : "organization missing",
423
+ next: hasOrganization ? "Use rollout before runtime sync." : "Create the organization route first.",
424
+ },
425
+ {
426
+ id: "runtime_adapter",
427
+ label: "Runtime adapter",
428
+ command: sync,
429
+ purpose: "Install Codex, Claude, or future harness artifacts as thin adapter mappings from dna governance truth.",
430
+ owner: "runtime",
431
+ writes: true,
432
+ status: hasOrganization && assetConfigured && evidenceStatus !== "open" ? "ready" : "blocked",
433
+ signal: `target=${params.targets.length > 0 ? params.targets.join(",") : params.inputs.syncTarget}`,
434
+ next: "Do not put workflow semantics into adapters; keep allow/warn/block/evidence decisions in dna core.",
435
+ },
436
+ {
437
+ id: "release_gate",
438
+ label: "Vercel release gate",
439
+ command: "dna release deploy-plan",
440
+ purpose: "Deploy and verify public web surfaces only when changed files require a deployed URL.",
441
+ owner: "release",
442
+ writes: false,
443
+ status: "ready",
444
+ signal: "deploy only for web/public surfaces",
445
+ next: "Run Vercel CLI deploy and deployed URL verification only when deploy-plan opens the gate.",
446
+ },
447
+ {
448
+ id: "knowledge_base",
449
+ label: "Internal knowledge base",
450
+ command: "wiki/IntentDNA Product Skeleton.md",
451
+ purpose: "Use Obsidian/wiki for project memory and thought capture, not as product runtime or governance truth.",
452
+ owner: "internal_memory",
453
+ writes: false,
454
+ status: "reference",
455
+ signal: "Obsidian/wiki is internal memory",
456
+ next: "Keep product behavior in dna CLI/core/runtime and link wiki notes back to code-backed routes.",
457
+ },
458
+ ];
459
+ }
460
+ function localQuickstartSteps(assetName, targets, inputs) {
461
+ const intendedTargets = targets.length > 0 ? targets : [inputs.syncTarget];
462
+ const sync = syncCommand(intendedTargets);
463
+ const syncDryRun = syncDryRunCommand(intendedTargets);
464
+ const harness = intendedTargets.some((target) => target === "codex" || target === "codex_cli")
465
+ ? "Run the workflow in Codex using the synced project instructions and hooks"
466
+ : intendedTargets.some((target) => target === "claude" || target === "claude_code")
467
+ ? "Run the workflow in Claude Code using the synced project instructions and hooks"
468
+ : "Run the workflow in the selected harness using the synced project instructions and hooks";
469
+ return [
470
+ {
471
+ id: "choose_template",
472
+ label: "Choose template",
473
+ command: `dna templates show ${assetName}`,
474
+ purpose: "Inspect purpose, fit, supported harnesses, install route, and evidence posture before writing project config.",
475
+ owner: "user",
476
+ writes: false,
477
+ acceptance: "User can identify why this workflow asset fits the project before initialization.",
478
+ verification: {
479
+ command: `dna templates show ${assetName}`,
480
+ expected: "Template output shows purpose, supported harnesses, install command, and evidence posture.",
481
+ evidence: "Marketplace metadata is inspectable before any project files are written.",
482
+ },
483
+ boundary: "Marketplace/template metadata helps selection only; it does not approve, install, or execute the workflow.",
484
+ },
485
+ {
486
+ id: "init_template",
487
+ label: "Initialize local DNA config",
488
+ command: `dna init --template ${assetName}`,
489
+ purpose: "Create local .dna configuration from the selected workflow asset so the project has runtime input.",
490
+ owner: "dna_core",
491
+ writes: true,
492
+ acceptance: `.dna/configs/${assetName}.yaml exists with source template metadata.`,
493
+ verification: {
494
+ command: `test -f .dna/configs/${assetName}.yaml`,
495
+ expected: "Exit code 0 and local config file exists.",
496
+ evidence: "Project has a local DNA config derived from the selected template.",
497
+ },
498
+ boundary: "Initialization is local file setup and does not require Online, Supabase, or cloud credentials.",
499
+ },
500
+ {
501
+ id: "sync_dry_run",
502
+ label: "Preview runtime sync",
503
+ command: syncDryRun,
504
+ purpose: "Show planned harness artifacts before writing instructions, hooks, skills, plugins, or registry entries.",
505
+ owner: "runtime",
506
+ writes: false,
507
+ acceptance: "Dry-run output explains planned files without mutating the project.",
508
+ verification: {
509
+ command: syncDryRun,
510
+ expected: "Output is a dry-run plan and .dna/compiled/ir.json is not written.",
511
+ evidence: "User can review harness artifact changes before mutation.",
512
+ },
513
+ boundary: "Dry-run is distribution preview only; it does not run the workflow or make allow/warn/block/validate decisions.",
514
+ },
515
+ {
516
+ id: "sync_runtime",
517
+ label: "Sync runtime artifacts",
518
+ command: sync,
519
+ purpose: "Install the reviewed local DNA artifacts into the selected harness surface.",
520
+ owner: "runtime",
521
+ writes: true,
522
+ acceptance: "Sync completes and registry-backed status/doctor can inspect IntentDNA-owned artifacts.",
523
+ verification: {
524
+ command: "dna sync status --json",
525
+ expected: "schema_version=intentdna.sync_status.v1 with totals.missing=0 and totals.drifted=0.",
526
+ evidence: "IntentDNA-owned harness artifacts are registry-tracked and locally inspectable.",
527
+ },
528
+ boundary: "Sync installs and injects artifacts only; workflow execution remains in the harness and governance remains local.",
529
+ },
530
+ {
531
+ id: "run_harness",
532
+ label: "Run workflow in harness",
533
+ command: harness,
534
+ purpose: "Use Codex, Claude Code, or another synced harness to perform the actual AI work method.",
535
+ owner: "user",
536
+ writes: true,
537
+ acceptance: "Harness run produces local runtime evidence that can be packaged by dna report commands.",
538
+ verification: {
539
+ command: "dna report package --json",
540
+ expected: "status=written after local runtime evidence exists; empty packages stay local and honest.",
541
+ evidence: "Local report packaging is the evidence handoff; Online and marketplace do not execute the workflow.",
542
+ },
543
+ boundary: "Online and marketplace do not execute workflows; dna-hook/local runtime evidence remains runtime truth.",
544
+ },
545
+ {
546
+ id: "package_report",
547
+ label: "Package local evidence",
548
+ command: "dna report package --json",
549
+ purpose: "Collect local runtime evidence into a reviewable report package before signing or optional upload.",
550
+ owner: "dna_core",
551
+ writes: true,
552
+ acceptance: "Command returns status=written with package.schema_version=intentdna.report_package.v1 and writes .dna/reports/latest-report-package.json.",
553
+ verification: {
554
+ command: "dna report package --json",
555
+ expected: "mode=intentdna_report_package_result, status=written, package.schema_version=intentdna.report_package.v1.",
556
+ evidence: "A local report package exists without network upload or cloud authority.",
557
+ },
558
+ boundary: "Packaging reads local evidence only; it does not upload, execute workflows, or grant runtime authority.",
559
+ },
560
+ {
561
+ id: "sign_report",
562
+ label: "Sign local evidence",
563
+ command: LOCAL_REPORT_SIGN_COMMAND,
564
+ purpose: "Wrap the just-written local report package in a signed ingest envelope for local verification or optional future upload.",
565
+ owner: "dna_core",
566
+ writes: true,
567
+ acceptance: `Command returns intentdna.report_ingest_envelope.v1 and writes ${LOCAL_REPORT_ENVELOPE_PATH} without printing secrets.`,
568
+ verification: {
569
+ command: LOCAL_REPORT_SIGN_COMMAND,
570
+ expected: "schema_version=intentdna.report_ingest_envelope.v1, package_ref.path points at the latest local report package, and transport.network_performed=false.",
571
+ evidence: "Signed local envelope is bound to the explicit package artifact and ready for local verification or optional future upload.",
572
+ },
573
+ boundary: "Signing is local verifier evidence only; it does not create cloud trust or backend state.",
574
+ },
575
+ {
576
+ id: "verify_report",
577
+ label: "Verify signed evidence",
578
+ command: LOCAL_REPORT_VERIFY_COMMAND,
579
+ purpose: "Verify the signed envelope and package hash before treating evidence as review input.",
580
+ owner: "dna_core",
581
+ writes: false,
582
+ acceptance: "Receipt is intentdna.report_ingest_receipt.v1 with runtime_authority=false and trusted_cloud_ingestion=false.",
583
+ verification: {
584
+ command: LOCAL_REPORT_VERIFY_COMMAND,
585
+ expected: "status=verified, runtime_authority=false, trusted_cloud_ingestion=false.",
586
+ evidence: "Local envelope integrity is proven while cloud trust remains explicitly false.",
587
+ },
588
+ boundary: "Verification proves local envelope integrity, not cloud ingestion, org approval, or runtime policy authority.",
589
+ },
590
+ {
591
+ id: "sync_status",
592
+ label: "Inspect synced artifacts",
593
+ command: "dna sync status --json",
594
+ purpose: "List registry-tracked IntentDNA artifacts and confirm the local install remains inspectable.",
595
+ owner: "dna_core",
596
+ writes: false,
597
+ acceptance: "Status reports registry artifacts without modifying project files.",
598
+ verification: {
599
+ command: "dna sync status --json",
600
+ expected: "totals.artifacts>0 after sync, totals.missing=0, totals.drifted=0.",
601
+ evidence: "Local registry can explain what IntentDNA installed.",
602
+ },
603
+ boundary: "Status is local artifact projection only; it is not online readiness or workflow approval.",
604
+ },
605
+ {
606
+ id: "sync_doctor",
607
+ label: "Check sync drift",
608
+ command: "dna sync doctor --json",
609
+ purpose: "Detect missing or drifted IntentDNA-owned artifacts before rerun, cleanup, or review.",
610
+ owner: "dna_core",
611
+ writes: false,
612
+ acceptance: "Doctor reports missing and drifted counts for registry-backed artifacts.",
613
+ verification: {
614
+ command: "dna sync doctor --json",
615
+ expected: "ok=true with totals.missing=0 and totals.drifted=0 on a clean local sync.",
616
+ evidence: "Drift/missing checks are local and registry-backed.",
617
+ },
618
+ boundary: "Doctor checks local files only and does not overwrite user-owned configuration.",
619
+ },
620
+ {
621
+ id: "sync_remove_preview",
622
+ label: "Preview safe cleanup",
623
+ command: "dna sync remove --dry-run",
624
+ purpose: "Show which hash-matching IntentDNA-owned or diagnostic artifacts can be removed safely.",
625
+ owner: "dna_core",
626
+ writes: false,
627
+ acceptance: "Dry-run prints a removal plan and leaves the registry plus project files in place.",
628
+ verification: {
629
+ command: "dna sync remove --dry-run",
630
+ expected: "Prints a dry-run registry remove plan and leaves .dna/sync/registry.json in place.",
631
+ evidence: "Cleanup remains preview-first and preserves user-owned or merge-preserve files.",
632
+ },
633
+ boundary: "Removal stays conservative; user-owned and merge-preserve surfaces are skipped unless proven safe.",
634
+ },
635
+ ];
636
+ }
637
+ function spinePhases(assetName, targets, inputs, asset) {
638
+ const intendedTargets = targets.length > 0 ? targets : [inputs.syncTarget];
639
+ const sync = syncCommand(intendedTargets);
640
+ const goal = commandQuote(inputs.workflowGoal);
641
+ const project = commandQuote(inputs.projectName);
642
+ const organization = commandQuote(inputs.organizationName);
643
+ return [
644
+ {
645
+ id: "describe",
646
+ label: "Describe workflow naturally",
647
+ command: `dna workflow intake ${goal}`,
648
+ purpose: "Start from the user's working method and decide reuse versus draft before any canvas, YAML, or runtime install.",
649
+ owner: "user",
650
+ writes: false,
651
+ },
652
+ {
653
+ id: "lock",
654
+ label: "Lock behavior as evidence",
655
+ command: "dna assets adoption flutter-behavior-lock",
656
+ purpose: "Use a behavior-lock workflow to capture source behavior as docs/tests before risky rewrite or refactor work.",
657
+ owner: "dna_core",
658
+ writes: false,
659
+ requiredWhen: "risky_rewrite_or_refactor",
660
+ },
661
+ {
662
+ id: "asset",
663
+ label: "Choose or inspect workflow asset",
664
+ command: `dna assets lineage ${assetName}`,
665
+ purpose: "Reuse a proven asset when possible, or use lineage to understand the asset before drafting the next version.",
666
+ owner: "dna_core",
667
+ writes: false,
668
+ },
669
+ {
670
+ id: "cascade",
671
+ label: "Review cascade and governance",
672
+ command: `dna assets governance ${assetName}`,
673
+ purpose: "Check inherited layers, winning constraints, evidence posture, and preview-first evolution before editing or rollout.",
674
+ owner: "dna_core",
675
+ writes: false,
676
+ },
677
+ {
678
+ id: "edit",
679
+ label: "Edit or draft workflow asset",
680
+ command: `dna workflow edit-plan "Describe the reviewed workflow change" --from-template ${assetName} --save-template ${assetName}-v2`,
681
+ purpose: "Adjust steps, roles, boundaries, handoffs, and verifiers through a reviewable edit plan instead of drawing a canvas.",
682
+ owner: "dna_core",
683
+ writes: true,
684
+ },
685
+ {
686
+ id: "review",
687
+ label: "Review asset version",
688
+ command: `dna assets diff ${assetName} ${assetName}-v2`,
689
+ purpose: "Let a manager review workflow and governance changes before organization binding or rollout.",
690
+ owner: "manager",
691
+ writes: false,
692
+ },
693
+ {
694
+ id: "verify",
695
+ label: "Route verification command",
696
+ command: `dna assets adoption ${WORKFLOW_ASSET_IDS.verificationCommandRouting}`,
697
+ purpose: "Plan and review the authoritative command root/scope before accepting verification evidence for completion, rollout, or sync.",
698
+ owner: "dna_core",
699
+ writes: false,
700
+ requiredWhen: "verification_root_or_scope_is_ambiguous",
701
+ },
702
+ {
703
+ id: "organize",
704
+ label: "Bind asset to organization",
705
+ command: `dna org bind --asset ${assetName}-v2 --status active --sync-target ${inputs.syncTarget}`,
706
+ purpose: "Record the accepted asset version in the organization route before runtime distribution.",
707
+ owner: "manager",
708
+ writes: true,
709
+ },
710
+ {
711
+ id: "configure",
712
+ label: "Configure declared assets",
713
+ command: "dna org configure-plan",
714
+ purpose: "Review or apply explicit dna init commands for organization-declared assets missing project config.",
715
+ owner: "dna_core",
716
+ writes: false,
717
+ },
718
+ {
719
+ id: "rollout",
720
+ label: "Review rollout readiness",
721
+ command: "dna org rollout",
722
+ purpose: "Show ready and blocked assets by target before downstream sync or team distribution.",
723
+ owner: "manager",
724
+ writes: false,
725
+ },
726
+ {
727
+ id: "sync",
728
+ label: "Sync to runtime surface",
729
+ command: sync,
730
+ purpose: "Install generated instructions, hooks, skills, or Codex artifacts while keeping governance decisions in dna core.",
731
+ owner: "runtime",
732
+ writes: true,
733
+ },
734
+ {
735
+ id: "deploy",
736
+ label: "Deploy public surface when changed",
737
+ command: "dna release deploy-plan",
738
+ purpose: "Plan Vercel CLI deployment and deployed URL verification only when web, dashboard, blog, or public review surfaces changed.",
739
+ owner: "release",
740
+ writes: false,
741
+ requiredWhen: "web_public_surface_changed",
742
+ },
743
+ {
744
+ id: "improve",
745
+ label: "Feed dogfood evidence back",
746
+ command: `dna assets suggestions ${assetName}`,
747
+ purpose: "Turn repeated run evidence into human-reviewed improvement suggestions before drafting the next asset version.",
748
+ owner: "dna_core",
749
+ writes: false,
750
+ },
751
+ {
752
+ id: "evolve",
753
+ label: "Preview self-evolution",
754
+ command: evolutionPreviewCommand(assetName, asset),
755
+ purpose: "Preview marker changes from recorded outcomes; mutation remains explicit through dna sync --evolve after review.",
756
+ owner: "dna_core",
757
+ writes: false,
758
+ requiredWhen: "execution_outcomes_recorded",
759
+ },
760
+ ];
761
+ }
762
+ function routeSteps(assetName, targets, inputs, evidence, asset, activeCandidate, activeCandidateRoute) {
763
+ const sync = syncCommand(targets);
764
+ const goal = commandQuote(inputs.workflowGoal);
765
+ const project = commandQuote(inputs.projectName);
766
+ const organization = commandQuote(inputs.organizationName);
767
+ const draftSuggestionCommand = activeCandidateCurrentCommand(activeCandidate, activeCandidateRoute)
768
+ ?? suggestionDraftCommand(assetName, evidence)
769
+ ?? `dna assets suggestions ${assetName}`;
770
+ const evolveCommand = evolutionPreviewCommand(assetName, asset);
771
+ return [
772
+ {
773
+ id: "library",
774
+ label: "Browse workflow assets",
775
+ command: "dna assets library",
776
+ purpose: "Choose a proven, ready, or draft workflow asset before configuring or syncing it.",
777
+ },
778
+ {
779
+ id: "behavior-lock",
780
+ label: "Review behavior-lock asset",
781
+ command: "dna assets adoption flutter-behavior-lock",
782
+ purpose: "Promote the dogfood-proven pattern of locking behavior as evidence before risky rewrite or refactor work.",
783
+ },
784
+ {
785
+ id: "lineage",
786
+ label: "Understand asset lineage",
787
+ command: `dna assets lineage ${assetName}`,
788
+ purpose: "See the asset origin, cascade inheritance, evidence, and human-reviewed evolution route.",
789
+ },
790
+ {
791
+ id: "lifecycle",
792
+ label: "See governance lifecycle",
793
+ command: `dna assets lifecycle ${assetName}`,
794
+ purpose: "Connect cascade, dogfood evidence, suggestions, reviewed drafts, adoption, org binding, and sync in one route.",
795
+ },
796
+ {
797
+ id: "candidates",
798
+ label: "Find workflow candidates",
799
+ command: `dna assets candidates ${assetName}`,
800
+ purpose: "Turn dogfood evidence into a candidate backlog for promoting or extracting reusable workflow assets.",
801
+ },
802
+ {
803
+ id: "evidence-review-asset",
804
+ label: "Review evidence workflow asset",
805
+ command: "dna assets adoption workflow-evidence-review",
806
+ purpose: "Reuse the built-in evidence review workflow instead of drafting duplicate per-source evidence-review templates.",
807
+ },
808
+ {
809
+ id: "verification-routing-asset",
810
+ label: "Review verification routing workflow asset",
811
+ command: `dna assets adoption ${WORKFLOW_ASSET_IDS.verificationCommandRouting}`,
812
+ purpose: "Reuse the built-in verification routing workflow before treating a test/analyze/build result as authoritative evidence.",
813
+ },
814
+ {
815
+ id: "blocked-scope-asset",
816
+ label: "Review blocked-scope workflow asset",
817
+ command: `dna assets adoption ${WORKFLOW_ASSET_IDS.blockedScopeTriage}`,
818
+ purpose: "Reuse the built-in blocked, skipped, removed, infra, or deferred scope triage workflow before manager review or rollout.",
819
+ },
820
+ {
821
+ id: "completion-audit-asset",
822
+ label: "Review completion audit workflow asset",
823
+ command: "dna assets adoption workflow-completion-audit",
824
+ purpose: "Reuse the built-in completion audit workflow before claiming PASS, adoption, rollout, evolution mutation, or sync.",
825
+ },
826
+ {
827
+ id: "runtime-smoke-asset",
828
+ label: "Review runtime smoke workflow asset",
829
+ command: "dna assets adoption workflow-runtime-smoke-review",
830
+ purpose: "Reuse the built-in runtime smoke workflow after sync or rollout before wider distribution.",
831
+ },
832
+ {
833
+ id: "intake",
834
+ label: "Review workflow request",
835
+ command: `dna workflow intake ${goal}`,
836
+ purpose: "Turn a natural-language workflow request into a reuse-vs-author decision before writing templates or syncing runtime.",
837
+ },
838
+ {
839
+ id: "org-intake",
840
+ label: "Plan organization setup",
841
+ command: `dna org intake ${project} --name ${organization} --asset ${assetName} --sync-target ${inputs.syncTarget}`,
842
+ purpose: "Review the organization/project, asset binding, and sync target before writing .dna/org.yaml.",
843
+ },
844
+ {
845
+ id: "organization",
846
+ label: "Create organization/project",
847
+ command: `dna org init --name ${organization} --project ${project} --asset ${assetName} --sync-target ${inputs.syncTarget}`,
848
+ purpose: "Declare where workflow assets live and which runtime targets will receive them.",
849
+ },
850
+ {
851
+ id: "draft",
852
+ label: "Author workflow",
853
+ command: `dna workflow authoring-packet ${goal} --json`,
854
+ purpose: "Give an external agent the C3 contract for interview, YAML authoring, deterministic validation, and explicit human save.",
855
+ scaffoldFallback: `dna workflow draft ${goal} --example rewrite_governance --strictness high --save-template ${saveTemplateName(assetName, "draft")}`,
856
+ },
857
+ {
858
+ id: "edit",
859
+ label: "Edit workflow by operation",
860
+ command: `dna workflow edit-plan "Add equivalence verifier after rewrite" --from-template ${assetName} --operation add_verifier --target-step rewrite --save-template ${assetName}-v2`,
861
+ purpose: "Preview step insertion, verifier changes, boundary tightening, splits, or role replacement before mutation.",
862
+ },
863
+ {
864
+ id: "governance",
865
+ label: "Review asset governance",
866
+ command: `dna assets governance ${assetName}`,
867
+ purpose: "Check cascade inheritance and preview-first evolution before distributing or mutating the asset.",
868
+ },
869
+ {
870
+ id: "diff",
871
+ label: "Review version diff",
872
+ command: `dna assets diff ${assetName} ${assetName}-v2`,
873
+ purpose: "Compare workflow and governance changes before configuring the proposed asset version.",
874
+ },
875
+ {
876
+ id: "adoption",
877
+ label: "Review adoption readiness",
878
+ command: `dna assets adoption ${assetName}-v2`,
879
+ purpose: "Check workflow, controller, cascade, evolution, evidence, and project configuration readiness before adoption.",
880
+ },
881
+ {
882
+ id: "bind",
883
+ label: "Bind accepted asset version",
884
+ command: `dna org bind --asset ${assetName}-v2 --status active --sync-target codex`,
885
+ purpose: "Adopt the reviewed asset version in the organization profile before runtime sync.",
886
+ },
887
+ {
888
+ id: "configure",
889
+ label: "Configure organization assets",
890
+ command: "dna org configure-plan",
891
+ purpose: "Show explicit project configuration commands for declared assets before rollout or sync.",
892
+ },
893
+ {
894
+ id: "rollout",
895
+ label: "Review rollout readiness",
896
+ command: "dna org rollout",
897
+ purpose: "Show which organization assets are ready to sync or blocked before downstream distribution.",
898
+ },
899
+ {
900
+ id: "sync",
901
+ label: "Sync to runtime surface",
902
+ command: sync,
903
+ purpose: "Install generated instructions, hooks, skills, or Codex artifacts while keeping governance in dna core.",
904
+ },
905
+ {
906
+ id: "evidence",
907
+ label: "Check evidence",
908
+ command: `dna assets evidence ${assetName}`,
909
+ purpose: "Review dogfood/runtime evidence without treating chat history or Obsidian as product truth.",
910
+ },
911
+ {
912
+ id: "suggestions",
913
+ label: "Review improvement suggestions",
914
+ command: `dna assets suggestions ${assetName}`,
915
+ purpose: "Turn dogfood evidence into human-reviewed workflow/template improvement candidates without mutating policy.",
916
+ },
917
+ {
918
+ id: "improve",
919
+ label: "Review improvement suggestion",
920
+ command: draftSuggestionCommand,
921
+ purpose: "Record the K4 accept/reject/defer receipt before any improve-from-suggestions draft, adoption, rollout, or sync.",
922
+ },
923
+ {
924
+ id: "evolution-preview",
925
+ label: "Preview self-evolution",
926
+ command: evolveCommand,
927
+ purpose: "Review outcome-derived marker changes without persisting them; explicit mutation stays behind dna sync --evolve.",
928
+ },
929
+ {
930
+ id: "review",
931
+ label: "Manager review",
932
+ command: "dna org review",
933
+ purpose: "See declared assets, configured assets, sync targets, missing setup, and evidence totals.",
934
+ },
935
+ ];
936
+ }
937
+ function entrypoints(assetName, targets, inputs) {
938
+ const intendedTargets = targets.length > 0 ? targets : [inputs.syncTarget];
939
+ const sync = syncCommand(intendedTargets);
940
+ const goal = commandQuote(inputs.workflowGoal);
941
+ const project = commandQuote(inputs.projectName);
942
+ const organization = commandQuote(inputs.organizationName);
943
+ return [
944
+ {
945
+ id: "author_workflow",
946
+ label: "Describe or edit a workflow",
947
+ command: `dna workflow route ${goal} --name ${organization} --project ${project} --sync-target ${inputs.syncTarget}`,
948
+ purpose: "Use natural language to choose reuse versus draft, then route edits through reviewable asset versions.",
949
+ owner: "user",
950
+ writes: false,
951
+ when: "You know the work method but do not want a canvas or harness-specific setup.",
952
+ outcome: "A no-canvas authoring route with draft, edit, review, organization, rollout, sync, deploy, and improvement gates.",
953
+ },
954
+ {
955
+ id: "setup_organization",
956
+ label: "Create or update organization route",
957
+ command: `dna org intake ${project} --name ${organization} --asset ${assetName} --sync-target ${inputs.syncTarget}`,
958
+ purpose: "Plan organization/project/asset/sync-target binding before writing .dna/org.yaml.",
959
+ owner: "manager",
960
+ writes: false,
961
+ when: "A team or project needs a governed place to adopt workflow assets.",
962
+ outcome: "A reviewed organization setup command, followed by configure-plan, rollout, and review.",
963
+ },
964
+ {
965
+ id: "manage_assets",
966
+ label: "Manage workflow assets",
967
+ command: `dna assets lifecycle ${assetName}`,
968
+ purpose: "Inspect lineage, cascade, evidence, suggestions, version review, adoption, organization binding, and sync in one lifecycle.",
969
+ owner: "dna_core",
970
+ writes: false,
971
+ when: "You need to understand or improve an existing workflow asset.",
972
+ outcome: "A reviewable asset-management path instead of hidden harness logic.",
973
+ },
974
+ {
975
+ id: "manager_review",
976
+ label: "Review system status",
977
+ command: "dna org review",
978
+ purpose: "Show organization assets, configuration gaps, evidence gates, sync readiness, and manager next actions.",
979
+ owner: "manager",
980
+ writes: false,
981
+ when: "A manager needs to decide whether the system can roll out or needs more work.",
982
+ outcome: "A read-only manager summary with blockers, ready assets, and next commands.",
983
+ },
984
+ {
985
+ id: "runtime_distribution",
986
+ label: "Prepare runtime distribution",
987
+ command: "dna org rollout",
988
+ purpose: `Check target-level readiness before running ${sync}.`,
989
+ owner: "runtime",
990
+ writes: false,
991
+ when: "Accepted assets should be distributed to Codex, Claude, or another runtime surface.",
992
+ outcome: "A ready/partial/blocked rollout plan; sync only after gates pass.",
993
+ },
994
+ ];
995
+ }
996
+ function personaPaths(assetName, targets, inputs) {
997
+ const intendedTargets = targets.length > 0 ? targets : [inputs.syncTarget];
998
+ const sync = syncCommand(intendedTargets);
999
+ const syncDryRun = syncDryRunCommand(intendedTargets);
1000
+ const goal = commandQuote(inputs.workflowGoal);
1001
+ const project = commandQuote(inputs.projectName);
1002
+ const organization = commandQuote(inputs.organizationName);
1003
+ return [
1004
+ {
1005
+ id: "developer",
1006
+ label: "Developer local quickstart",
1007
+ question: "How do I run one governed workflow in my local project?",
1008
+ firstCommands: [
1009
+ `dna templates show ${assetName}`,
1010
+ `dna init --template ${assetName}`,
1011
+ syncDryRun,
1012
+ sync,
1013
+ "dna report package --json",
1014
+ LOCAL_REPORT_SIGN_COMMAND,
1015
+ LOCAL_REPORT_VERIFY_COMMAND,
1016
+ ],
1017
+ acceptance: "A selected workflow asset is initialized, synced into the harness, run in Codex or Claude Code, then packaged, signed, and verified locally.",
1018
+ boundary: "Local dna/dna-hook remain runtime truth; Online, marketplace, and Supabase do not execute workflows or decide allow/warn/block/validate.",
1019
+ blockedBy: [],
1020
+ },
1021
+ {
1022
+ id: "team_lead_manager",
1023
+ label: "Team lead or manager rollout review",
1024
+ question: "Which workflow assets are active, stale, blocked, or ready to roll out?",
1025
+ firstCommands: [
1026
+ `dna org intake ${project} --name ${organization} --asset ${assetName} --sync-target ${inputs.syncTarget}`,
1027
+ "dna org review",
1028
+ `dna assets lifecycle ${assetName}`,
1029
+ "dna org rollout",
1030
+ ],
1031
+ acceptance: "Manager can see organization scope, asset posture, evidence gaps, rollout blockers, and the next local command before any sync.",
1032
+ boundary: "Manager review is read-only local organization evidence; it is not authenticated org-private SaaS visibility and does not install files.",
1033
+ blockedBy: [],
1034
+ },
1035
+ {
1036
+ id: "template_author",
1037
+ label: "Template author asset lifecycle",
1038
+ question: "How do I turn a repeated AI work method into a reusable workflow asset?",
1039
+ firstCommands: [
1040
+ `dna workflow intake ${goal} --json`,
1041
+ `dna workflow route ${goal} --name ${organization} --project ${project} --sync-target ${inputs.syncTarget}`,
1042
+ `dna workflow authoring-packet ${goal} --json`,
1043
+ `dna workflow draft ${goal} --json # scaffold fallback only`,
1044
+ `dna workflow edit-plan --from-template ${assetName} "Describe the reviewed workflow change" --json`,
1045
+ `dna assets governance ${assetName} --json`,
1046
+ ],
1047
+ acceptance: "Author can move from work-method description through external-agent YAML authoring and dna validate to reviewable asset/version evidence without bypassing adoption, diff, or rollout gates.",
1048
+ boundary: "Marketplace publication distributes workflow assets and install plans; it does not approve, install, execute, or replace the runtime workflow.",
1049
+ blockedBy: [],
1050
+ },
1051
+ {
1052
+ id: "security_admin",
1053
+ label: "Security or admin authority check",
1054
+ question: "Where are authority, secrets, audit, and cloud trust boundaries?",
1055
+ firstCommands: [
1056
+ "dna cloud credential-check --json",
1057
+ "dna cloud contract-check --json",
1058
+ "dna cloud edge-check --json",
1059
+ "dna cloud deploy-plan --json",
1060
+ "dna cloud smoke-plan --json",
1061
+ ],
1062
+ acceptance: "Admin can distinguish local verifier evidence from trusted cloud ingestion and see which live deployment inputs remain gated.",
1063
+ boundary: "Supabase is auth, persistence, storage, transport, and audit, not governance authority; secrets stay server-side and never in browser-facing code.",
1064
+ blockedBy: [
1065
+ "server-only Supabase/Vercel secrets",
1066
+ "bootstrap admin/org/project inputs",
1067
+ "billing and retention acknowledgement",
1068
+ "live users/orgs for RLS and receipt smoke",
1069
+ ],
1070
+ },
1071
+ ];
1072
+ }
1073
+ function nextCommands(params) {
1074
+ const commands = [params.recommendation.command];
1075
+ const project = commandQuote(params.inputs.projectName);
1076
+ const goal = commandQuote(params.inputs.workflowGoal);
1077
+ const evidenceOpen = params.evidence
1078
+ ? params.evidence.totals.continue > 0 ||
1079
+ params.evidence.totals.requestChanges > 0 ||
1080
+ params.evidence.totals.blocked > 0 ||
1081
+ params.evidence.totals.remaining > 0
1082
+ : false;
1083
+ if (!params.hasOrganization) {
1084
+ commands.push("dna assets library", "dna assets adoption flutter-behavior-lock", `dna assets lineage ${params.assetName}`, `dna assets lifecycle ${params.assetName}`, `dna assets candidates ${params.assetName}`, "dna assets lineage workflow-evidence-review", "dna assets adoption workflow-evidence-review", `dna assets adoption ${WORKFLOW_ASSET_IDS.verificationCommandRouting}`, `dna workflow intake ${goal}`, `dna workflow authoring-packet ${goal} --json`, `dna org intake ${project} --name ${commandQuote(params.inputs.organizationName)} --asset ${params.assetName} --sync-target ${params.inputs.syncTarget}`, `dna workflow draft ${goal} --example rewrite_governance --strictness high --save-template ${saveTemplateName(params.assetName, "draft")} # scaffold fallback only`, `dna assets governance ${params.assetName}`);
1085
+ return [...new Set(commands)];
1086
+ }
1087
+ if (evidenceOpen) {
1088
+ const suggestionReview = suggestionDraftCommand(params.assetName, params.evidence);
1089
+ const acceptedDraft = suggestionAcceptedDraftCommand(params.assetName, params.evidence);
1090
+ const activePathCommands = params.activeCandidateRoute?.reviewCommands
1091
+ .filter((command) => command !== params.recommendation.command)
1092
+ ?? params.activeCandidate?.actionPath
1093
+ .map((step) => step.command)
1094
+ .filter((command) => command !== params.recommendation.command)
1095
+ ?? [];
1096
+ commands.push(...activePathCommands, `dna assets lineage ${params.assetName}`, `dna assets governance ${params.assetName}`, `dna assets candidates ${params.assetName}`, "dna assets adoption flutter-behavior-lock", `dna assets adoption ${WORKFLOW_ASSET_IDS.verificationCommandRouting}`, `dna assets evidence ${params.assetName}`, suggestionReview ?? `dna assets suggestions ${params.assetName}`, ...(acceptedDraft ? [acceptedDraft] : []), "dna org rollout", "dna org review");
1097
+ if (!params.assetConfigured) {
1098
+ commands.push("dna org configure-plan");
1099
+ return [...new Set(commands)];
1100
+ }
1101
+ return [...new Set(commands)];
1102
+ }
1103
+ if (!params.assetConfigured) {
1104
+ commands.push("dna org configure-plan", "dna org configure-plan --apply", `dna assets lineage ${params.assetName}`, `dna assets governance ${params.assetName}`, `dna assets adoption ${params.assetName}`, "dna org rollout", "dna org review");
1105
+ return [...new Set(commands)];
1106
+ }
1107
+ const suggestionReview = suggestionDraftCommand(params.assetName, params.evidence);
1108
+ const acceptedDraft = suggestionAcceptedDraftCommand(params.assetName, params.evidence);
1109
+ commands.push(`dna assets lineage ${params.assetName}`, `dna assets governance ${params.assetName}`, `dna assets candidates ${params.assetName}`, `dna assets evidence ${params.assetName}`, suggestionReview ?? `dna assets suggestions ${params.assetName}`, ...(acceptedDraft ? [acceptedDraft] : []), "dna org rollout", syncCommand(params.targets), "dna org review");
1110
+ return [...new Set(commands)];
1111
+ }
1112
+ function evidenceGate(evidence) {
1113
+ if (!evidence)
1114
+ return "unknown";
1115
+ return evidence.continue > 0 || evidence.blocked > 0 || evidence.remaining > 0 ? "open" : "clear";
1116
+ }
1117
+ function buildTrack(params) {
1118
+ const checkpoints = [
1119
+ `organization=${params.state.organization.configured ? "configured" : "missing"}`,
1120
+ `asset=${params.state.asset?.configured ? "configured" : "not_configured"}`,
1121
+ `evidence=${evidenceGate(params.state.evidence)}`,
1122
+ `sync_targets=${params.state.organization.syncTargets.length > 0 ? params.state.organization.syncTargets.join(",") : "none"}`,
1123
+ ];
1124
+ if (params.state.evidence) {
1125
+ checkpoints.push(`dogfood=${params.state.evidence.pass}/${params.state.evidence.modules} PASS remaining=${params.state.evidence.remaining}`);
1126
+ }
1127
+ return {
1128
+ asset: params.assetName,
1129
+ currentStage: params.recommendation.stage,
1130
+ currentCommand: params.recommendation.command,
1131
+ currentWrites: params.recommendation.writes,
1132
+ evidenceGate: evidenceGate(params.state.evidence),
1133
+ checkpoints,
1134
+ afterCurrent: params.nextCommands.filter((command) => command !== params.recommendation.command).slice(0, 4),
1135
+ activeCandidate: params.activeCandidate,
1136
+ activeCandidateRoute: params.activeCandidateRoute,
1137
+ };
1138
+ }
1139
+ function quickstartRecommendation(firstStep) {
1140
+ return {
1141
+ stage: "local_quickstart",
1142
+ label: "Start the local no-cloud quickstart",
1143
+ command: firstStep.command,
1144
+ reason: "quickstart is intentionally scoped to the shortest local route: choose a workflow asset, initialize dna, sync the harness, run locally, then package/sign/verify local evidence.",
1145
+ writes: firstStep.writes,
1146
+ };
1147
+ }
1148
+ function quickstartCommands(steps) {
1149
+ return steps.map((step) => step.command);
1150
+ }
1151
+ function buildQuickstartReview(guide, syncTarget) {
1152
+ return {
1153
+ schema_version: "intentdna.local_quickstart.v1",
1154
+ mode: "local_quickstart",
1155
+ projectDir: guide.state.projectDir,
1156
+ asset: guide.track.asset,
1157
+ syncTarget,
1158
+ commandEffects: {
1159
+ read_only_guidance: true,
1160
+ mutation_performed: false,
1161
+ network_performed: false,
1162
+ online_required: false,
1163
+ cloud_required: false,
1164
+ runtime_authority: false,
1165
+ initializes_project: false,
1166
+ syncs_harness: false,
1167
+ signs_or_uploads_evidence: false,
1168
+ },
1169
+ current: guide.recommendation,
1170
+ warnings: guide.state.warnings,
1171
+ steps: guide.localQuickstart,
1172
+ nextCommands: guide.localQuickstart.map((step) => step.command),
1173
+ acceptance: [
1174
+ "Local route works without Online, Supabase, live credentials, or browser auth.",
1175
+ "User can choose a workflow asset, initialize local dna, preview sync, sync runtime artifacts, run in the harness, then package/sign/verify evidence locally.",
1176
+ "No secrets are printed and no online/cloud authority is introduced.",
1177
+ "dna sync remains install/distribution only; workflow execution happens in Codex, Claude Code, or the selected harness.",
1178
+ ],
1179
+ verificationGates: [
1180
+ "dna templates show <asset>",
1181
+ "dna init --template <asset>",
1182
+ "dna sync --dry-run or dna sync --codex --dry-run",
1183
+ "dna sync or dna sync --codex",
1184
+ "dna report package --json",
1185
+ LOCAL_REPORT_SIGN_COMMAND,
1186
+ LOCAL_REPORT_VERIFY_COMMAND,
1187
+ "dna sync status --json",
1188
+ "dna sync doctor --json",
1189
+ "dna sync remove --dry-run",
1190
+ ],
1191
+ boundaries: [
1192
+ "local dna and dna-hook remain runtime truth.",
1193
+ "Online is optional projection and does not execute workflows or make allow/warn/block/validate decisions.",
1194
+ "Marketplace/template metadata helps selection only; it does not approve, install, execute, or replace runtime workflows.",
1195
+ "Supabase is not required for this quickstart and is not governance authority.",
1196
+ "MCP remains hidden transport, not a product UI step.",
1197
+ ],
1198
+ outOfScope: [
1199
+ "Live Supabase deployment, cloud upload, receipt smoke, account onboarding, or org-private publishing.",
1200
+ "Adopting, binding, rolling out, replacing, or deleting workflow assets.",
1201
+ `Reviewing unfinished dogfood follow-up drafts such as ${WORKFLOW_ASSET_IDS.rewriteActiveFollowup}.`,
1202
+ "Vercel deployment or public web release evidence unless web/public files changed.",
1203
+ ],
1204
+ };
1205
+ }
1206
+ function buildBriefReview(guide) {
1207
+ const active = guide.track.activeCandidate;
1208
+ return {
1209
+ schema_version: "intentdna.route_guide_brief.v1",
1210
+ mode: "route_guide_brief",
1211
+ projectDir: guide.state.projectDir,
1212
+ asset: guide.track.asset,
1213
+ current: guide.recommendation,
1214
+ state: {
1215
+ organization_configured: guide.state.organization.configured,
1216
+ organization_name: guide.state.organization.name,
1217
+ asset_configured: guide.state.asset?.configured,
1218
+ sync_targets: guide.state.organization.syncTargets,
1219
+ evidence: guide.state.evidence,
1220
+ warnings: guide.state.warnings,
1221
+ },
1222
+ checkpoints: guide.track.checkpoints,
1223
+ afterCurrent: guide.track.afterCurrent,
1224
+ activeCandidate: active ? {
1225
+ id: active.id,
1226
+ candidateAssetName: active.candidateAssetName,
1227
+ sourceAsset: active.sourceAsset,
1228
+ evidence: active.evidence,
1229
+ nextCommand: active.nextCommand,
1230
+ plainLanguage: active.plainLanguage,
1231
+ continuityBoundary: active.continuityBoundary,
1232
+ mutationBoundary: active.mutationBoundary,
1233
+ } : undefined,
1234
+ localQuickstart: guide.localQuickstart.map((step) => ({
1235
+ id: step.id,
1236
+ label: step.label,
1237
+ command: step.command,
1238
+ writes: step.writes,
1239
+ })),
1240
+ nextCommands: guide.nextCommands.slice(0, 8),
1241
+ boundaries: [
1242
+ "dna CLI/core/runtime owns product behavior and governance decisions.",
1243
+ "Local quickstart works without Online or Supabase credentials.",
1244
+ "Online and marketplace do not execute workflows or make allow/warn/block/validate decisions.",
1245
+ "Supabase is not required for local quickstart and is not governance authority.",
1246
+ "MCP remains hidden transport, not a product UI step.",
1247
+ ],
1248
+ };
1249
+ }
1250
+ function assetBindingStatus(review, assetName) {
1251
+ if (!review)
1252
+ return "missing";
1253
+ for (const project of review.profile.projects) {
1254
+ const binding = project.assets.find((entry) => entry.asset === assetName);
1255
+ if (binding)
1256
+ return binding.status;
1257
+ }
1258
+ return "missing";
1259
+ }
1260
+ function buildRecommendation(params) {
1261
+ if (!params.hasOrganization) {
1262
+ return {
1263
+ stage: "organization_setup",
1264
+ label: "Create the organization/project profile first",
1265
+ command: `dna org init --name ${commandQuote(params.inputs.organizationName)} --project ${commandQuote(params.inputs.projectName)} --asset ${params.assetName} --sync-target ${params.inputs.syncTarget}`,
1266
+ reason: "There is no .dna/org.yaml yet, so assets and sync targets have nowhere to be governed.",
1267
+ writes: true,
1268
+ };
1269
+ }
1270
+ if (params.evidence && (params.evidence.continue > 0 || params.evidence.blocked > 0 || params.evidence.remaining > 0)) {
1271
+ const activeCommand = activeCandidateCurrentCommand(params.activeCandidate, params.activeCandidateRoute);
1272
+ return {
1273
+ stage: "evidence_review",
1274
+ label: params.activeCandidateRoute?.status === "draft_reviewable"
1275
+ ? "Review the unfinished-work draft before adoption"
1276
+ : params.activeCandidateRoute?.status === "draft_structural_drift"
1277
+ ? "Repair the unfinished-work draft before adoption"
1278
+ : activeCommand
1279
+ ? "Save or inspect unfinished dogfood work before rollout or sync"
1280
+ : "Review dogfood evidence before changing or syncing the asset",
1281
+ command: activeCommand ?? `dna assets suggestions ${params.assetName}`,
1282
+ reason: params.activeCandidateRoute
1283
+ ? `Dogfood evidence still has continue=${params.evidence.continue}, blocked=${params.evidence.blocked}, remaining=${params.evidence.remaining}; ${params.activeCandidateRoute.reason}`
1284
+ : activeCommand
1285
+ ? `Dogfood evidence still has continue=${params.evidence.continue}, blocked=${params.evidence.blocked}, remaining=${params.evidence.remaining}; save it as reviewed unfinished work first.`
1286
+ : `Dogfood evidence still has continue=${params.evidence.continue}, blocked=${params.evidence.blocked}, remaining=${params.evidence.remaining}.`,
1287
+ writes: activeCommand ? activeCandidateWrites(params.activeCandidate, params.activeCandidateRoute) : false,
1288
+ };
1289
+ }
1290
+ if (!params.assetConfigured) {
1291
+ return {
1292
+ stage: "asset_configuration",
1293
+ label: "Review organization configuration plan",
1294
+ command: "dna org configure-plan",
1295
+ reason: "The organization exists, but at least one declared asset has not been materialized into this project yet.",
1296
+ writes: false,
1297
+ };
1298
+ }
1299
+ if (params.bindingStatus !== "active" || params.targets.length === 0) {
1300
+ return {
1301
+ stage: "asset_binding",
1302
+ label: "Bind the accepted asset version before sync",
1303
+ command: `dna org bind --asset ${params.assetName} --status active --sync-target ${params.inputs.syncTarget}`,
1304
+ reason: params.bindingStatus === "missing"
1305
+ ? "The project has a configured asset, but the organization profile has not adopted it."
1306
+ : "The organization binding is not active or has no sync target yet.",
1307
+ writes: true,
1308
+ };
1309
+ }
1310
+ if (params.targets.length > 0) {
1311
+ return {
1312
+ stage: "runtime_sync",
1313
+ label: "Sync the reviewed asset to the runtime surface",
1314
+ command: syncCommand(params.targets),
1315
+ reason: "Organization, asset configuration, active binding, and sync target are present.",
1316
+ writes: true,
1317
+ };
1318
+ }
1319
+ return {
1320
+ stage: "manager_review",
1321
+ label: "Review organization status",
1322
+ command: "dna org review",
1323
+ reason: "No higher-priority setup, evidence, or sync action was detected.",
1324
+ writes: false,
1325
+ };
1326
+ }
1327
+ async function buildGuide(opts) {
1328
+ const projectDir = opts.projectDir ?? process.cwd();
1329
+ const [profile, assets] = await Promise.all([
1330
+ readOrganizationProfile({ projectDir }),
1331
+ listWorkflowAssets({ projectDir }),
1332
+ ]);
1333
+ const inputs = contextualRouteInputs(opts, profile.profile);
1334
+ const review = profile.profile ? await reviewOrganization({ projectDir }) : undefined;
1335
+ const selected = preferredAsset(assets, opts.asset);
1336
+ const assetName = selected?.name ?? opts.asset ?? WORKFLOW_ASSET_IDS.default;
1337
+ const targets = syncTargets(review);
1338
+ const [evidence, candidateBacklog] = selected
1339
+ ? await Promise.all([
1340
+ buildWorkflowAssetEvidenceIndex(selected.name, { projectDir }),
1341
+ buildWorkflowAssetCandidateBacklog({ name: selected.name, projectDir }),
1342
+ ])
1343
+ : [undefined, undefined];
1344
+ const activeCandidate = guideActiveCandidate(candidateBacklog?.candidates.find((candidate) => candidate.type === "active_evidence_followup")
1345
+ ?? candidateBacklog?.candidates[0]);
1346
+ const activeCandidateRoute = activeCandidate?.type === "active_evidence_followup"
1347
+ ? activeEvidenceFollowupReviewRoute(activeCandidate.sourceAsset, assets, evidence)
1348
+ : undefined;
1349
+ const evidenceSummary = evidence ? {
1350
+ modules: evidence.totals.modules,
1351
+ pass: evidence.totals.pass,
1352
+ continue: evidence.totals.continue,
1353
+ blocked: evidence.totals.blocked,
1354
+ remaining: evidence.totals.remaining,
1355
+ source: evidence.sourceDescription,
1356
+ } : undefined;
1357
+ const localQuickstartTargets = opts.quickstart ? [inputs.syncTarget] : targets;
1358
+ const localQuickstart = localQuickstartSteps(assetName, localQuickstartTargets, inputs);
1359
+ const routeRecommendation = buildRecommendation({
1360
+ hasOrganization: profile.profile !== undefined,
1361
+ assetName,
1362
+ assetConfigured: selected?.status.configured ?? false,
1363
+ targets,
1364
+ bindingStatus: assetBindingStatus(review, assetName),
1365
+ evidence: evidenceSummary,
1366
+ inputs,
1367
+ activeCandidate,
1368
+ activeCandidateRoute,
1369
+ });
1370
+ const recommendation = opts.quickstart
1371
+ ? quickstartRecommendation(localQuickstart[0])
1372
+ : routeRecommendation;
1373
+ const warnings = [];
1374
+ if (opts.asset && !selected)
1375
+ warnings.push(`Requested asset is not in the catalog: ${opts.asset}`);
1376
+ if (!profile.profile)
1377
+ warnings.push("No organization profile yet; start with dna org init.");
1378
+ if (selected && !selected.status.configured)
1379
+ warnings.push(`Asset ${selected.name} is available but not configured in this project.`);
1380
+ const state = {
1381
+ projectDir,
1382
+ organization: {
1383
+ profilePath: profile.path,
1384
+ configured: profile.profile !== undefined,
1385
+ name: profile.profile?.organization.name,
1386
+ projects: review?.totals.projects ?? 0,
1387
+ syncTargets: targets,
1388
+ },
1389
+ asset: selected ? {
1390
+ name: selected.name,
1391
+ displayName: selected.displayName,
1392
+ configured: selected.status.configured,
1393
+ cascade: selected.status.cascadePosture,
1394
+ evolution: selected.status.evolutionPosture,
1395
+ evidence: selected.status.evidencePosture,
1396
+ } : undefined,
1397
+ evidence: evidenceSummary,
1398
+ warnings,
1399
+ };
1400
+ const route = routeSteps(assetName, targets, inputs, evidence, selected, activeCandidate, activeCandidateRoute);
1401
+ const commands = opts.quickstart
1402
+ ? quickstartCommands(localQuickstart)
1403
+ : nextCommands({
1404
+ hasOrganization: profile.profile !== undefined,
1405
+ assetName,
1406
+ assetConfigured: selected?.status.configured ?? false,
1407
+ targets,
1408
+ recommendation,
1409
+ inputs,
1410
+ evidence,
1411
+ activeCandidate,
1412
+ activeCandidateRoute,
1413
+ });
1414
+ return {
1415
+ mode: "route_guide",
1416
+ state,
1417
+ recommendation,
1418
+ track: buildTrack({
1419
+ assetName,
1420
+ state,
1421
+ recommendation,
1422
+ nextCommands: commands,
1423
+ activeCandidate,
1424
+ activeCandidateRoute,
1425
+ }),
1426
+ boundaries: [
1427
+ "dna CLI/core/runtime owns product behavior and governance decisions.",
1428
+ "Claude Code, Codex, and future harnesses are runtime surfaces and adapters.",
1429
+ "Dashboard is read-only projection, not a workflow builder or policy source.",
1430
+ "Obsidian/wiki is internal project memory and route recovery, not product runtime.",
1431
+ "Web/public surface changes require Vercel CLI deployment and deployed URL verification.",
1432
+ ],
1433
+ journey: journeySteps({
1434
+ assetName,
1435
+ targets,
1436
+ inputs,
1437
+ state,
1438
+ recommendation,
1439
+ evidence,
1440
+ activeCandidate,
1441
+ activeCandidateRoute,
1442
+ }),
1443
+ operatingPaths: operatingPaths({
1444
+ assetName,
1445
+ inputs,
1446
+ state,
1447
+ recommendation,
1448
+ activeCandidate,
1449
+ activeCandidateRoute,
1450
+ }),
1451
+ knowledgeLinks: knowledgeLinks(),
1452
+ foundation: foundationSteps({
1453
+ assetName,
1454
+ targets,
1455
+ inputs,
1456
+ state,
1457
+ asset: selected,
1458
+ }),
1459
+ localQuickstart,
1460
+ entrypoints: entrypoints(assetName, targets, inputs),
1461
+ personaPaths: personaPaths(assetName, targets, inputs),
1462
+ spine: spinePhases(assetName, targets, inputs, selected),
1463
+ route,
1464
+ nextCommands: commands,
1465
+ };
1466
+ }
1467
+ function quickstartSyncTarget(guide, opts) {
1468
+ return opts.syncTarget?.trim() || guide.state.organization.syncTargets[0] || "codex";
1469
+ }
1470
+ function writeBriefGuide(guide) {
1471
+ process.stderr.write("IntentDNA current track\n");
1472
+ process.stderr.write(`Project: ${guide.state.projectDir}\n`);
1473
+ process.stderr.write(`Focus asset: ${guide.track.asset}\n`);
1474
+ process.stderr.write(`Current stage: ${guide.track.currentStage}\n`);
1475
+ process.stderr.write(`Current command: ${guide.track.currentCommand}\n`);
1476
+ process.stderr.write(`Why: ${guide.recommendation.reason}\n`);
1477
+ process.stderr.write(`Writes: ${guide.track.currentWrites ? "yes" : "no"}\n`);
1478
+ process.stderr.write(`Spine: ${guide.spine.map((step) => step.id).join(" -> ")}\n`);
1479
+ if (guide.state.evidence) {
1480
+ process.stderr.write(`Dogfood: ${guide.state.evidence.pass}/${guide.state.evidence.modules} PASS, continue=${guide.state.evidence.continue}, blocked=${guide.state.evidence.blocked}, remaining=${guide.state.evidence.remaining}\n`);
1481
+ }
1482
+ process.stderr.write("\nCheckpoints:\n");
1483
+ for (const checkpoint of guide.track.checkpoints)
1484
+ process.stderr.write(` - ${checkpoint}\n`);
1485
+ process.stderr.write("\nDo now:\n");
1486
+ process.stderr.write(` - ${guide.track.currentCommand}\n`);
1487
+ process.stderr.write("\nPersona onboarding:\n");
1488
+ for (const path of guide.personaPaths) {
1489
+ process.stderr.write(` - ${path.id}: ${path.label}\n`);
1490
+ process.stderr.write(` asks: ${path.question}\n`);
1491
+ process.stderr.write(` first: ${path.firstCommands[0]}\n`);
1492
+ process.stderr.write(` accept: ${path.acceptance}\n`);
1493
+ process.stderr.write(` boundary: ${path.boundary}\n`);
1494
+ if (path.blockedBy.length > 0)
1495
+ process.stderr.write(` blocked_by: ${path.blockedBy.join("; ")}\n`);
1496
+ }
1497
+ if (guide.track.afterCurrent.length > 0) {
1498
+ process.stderr.write("\nAfter that:\n");
1499
+ for (const command of guide.track.afterCurrent)
1500
+ process.stderr.write(` - ${command}\n`);
1501
+ }
1502
+ process.stderr.write("\nLocal quickstart:\n");
1503
+ for (const step of guide.localQuickstart) {
1504
+ process.stderr.write(` - ${step.id}: ${step.command}\n`);
1505
+ process.stderr.write(` writes: ${step.writes ? "yes" : "no"}\n`);
1506
+ process.stderr.write(` accept: ${step.acceptance}\n`);
1507
+ process.stderr.write(` verify: ${step.verification.command}\n`);
1508
+ process.stderr.write(` expect: ${step.verification.expected}\n`);
1509
+ process.stderr.write(` boundary: ${step.boundary}\n`);
1510
+ }
1511
+ if (guide.track.activeCandidate) {
1512
+ const candidate = guide.track.activeCandidate;
1513
+ process.stderr.write("\nActive candidate:\n");
1514
+ process.stderr.write(` - ${candidate.id}: ${candidate.candidateAssetName}\n`);
1515
+ process.stderr.write(" kind: saved unfinished-work draft; source asset is preserved\n");
1516
+ process.stderr.write(` evidence: ${candidate.evidence}\n`);
1517
+ process.stderr.write(` next: ${candidate.nextCommand}\n`);
1518
+ if (candidate.plainLanguage) {
1519
+ process.stderr.write(" plain meaning:\n");
1520
+ process.stderr.write(` label: ${candidate.plainLanguage.label}\n`);
1521
+ process.stderr.write(` purpose: ${candidate.plainLanguage.purpose}\n`);
1522
+ process.stderr.write(` improvement: ${candidate.plainLanguage.workflowImprovement}\n`);
1523
+ process.stderr.write(" preserves:\n");
1524
+ for (const item of candidate.plainLanguage.preserves)
1525
+ process.stderr.write(` - ${item}\n`);
1526
+ process.stderr.write(" required before use:\n");
1527
+ for (const item of candidate.plainLanguage.requiredBeforeUse)
1528
+ process.stderr.write(` - ${item}\n`);
1529
+ }
1530
+ process.stderr.write(` boundary: ${candidate.mutationBoundary}\n`);
1531
+ if (candidate.continuityBoundary)
1532
+ process.stderr.write(` continuity: ${candidate.continuityBoundary}\n`);
1533
+ }
1534
+ process.stderr.write("\nBoundaries:\n");
1535
+ process.stderr.write(" - dna owns governance behavior; harnesses are runtime surfaces.\n");
1536
+ process.stderr.write(" - Local quickstart works without Online or Supabase credentials.\n");
1537
+ process.stderr.write(" - Obsidian/wiki is internal project memory, not product runtime.\n");
1538
+ process.stderr.write(" - Dashboard stays read-only projection.\n");
1539
+ process.stderr.write(" - Vercel runs only when dna release deploy-plan opens the deploy gate.\n");
1540
+ }
1541
+ function writeQuickstart(review) {
1542
+ process.stderr.write("IntentDNA local quickstart\n");
1543
+ process.stderr.write(`Project: ${review.projectDir}\n`);
1544
+ process.stderr.write(`Asset: ${review.asset}\n`);
1545
+ process.stderr.write(`Sync target: ${review.syncTarget}\n`);
1546
+ process.stderr.write("Command effects: read-only guidance, no files written, no network, no runtime authority\n");
1547
+ process.stderr.write(`Current command: ${review.current.command}\n`);
1548
+ process.stderr.write(`Why: ${review.current.reason}\n`);
1549
+ process.stderr.write(`Writes: ${review.current.writes ? "yes" : "no"}\n`);
1550
+ if (review.warnings.length > 0) {
1551
+ process.stderr.write("\nWarnings:\n");
1552
+ for (const warning of review.warnings)
1553
+ process.stderr.write(` - ${warning}\n`);
1554
+ }
1555
+ process.stderr.write("\nSteps:\n");
1556
+ for (const step of review.steps) {
1557
+ process.stderr.write(` ${step.id}. ${step.label}\n`);
1558
+ process.stderr.write(` ${step.command}\n`);
1559
+ process.stderr.write(` owner=${step.owner} writes=${step.writes ? "yes" : "no"}\n`);
1560
+ process.stderr.write(` accept: ${step.acceptance}\n`);
1561
+ process.stderr.write(` verify: ${step.verification.command}\n`);
1562
+ process.stderr.write(` expect: ${step.verification.expected}\n`);
1563
+ process.stderr.write(` boundary: ${step.boundary}\n`);
1564
+ }
1565
+ process.stderr.write("\nAcceptance:\n");
1566
+ for (const item of review.acceptance)
1567
+ process.stderr.write(` - ${item}\n`);
1568
+ process.stderr.write("\nBoundaries:\n");
1569
+ for (const boundary of review.boundaries)
1570
+ process.stderr.write(` - ${boundary}\n`);
1571
+ process.stderr.write("\nOut of scope:\n");
1572
+ for (const item of review.outOfScope)
1573
+ process.stderr.write(` - ${item}\n`);
1574
+ }
1575
+ function writeActiveCandidate(candidate) {
1576
+ if (!candidate)
1577
+ return;
1578
+ process.stderr.write("\nActive candidate:\n");
1579
+ process.stderr.write(` id: ${candidate.id}\n`);
1580
+ process.stderr.write(` type: ${candidate.type}\n`);
1581
+ process.stderr.write(` priority: ${candidate.priority}\n`);
1582
+ process.stderr.write(` saved draft: ${candidate.candidateAssetName} (unfinished work; source asset is preserved)\n`);
1583
+ process.stderr.write(` evidence: ${candidate.evidence}\n`);
1584
+ process.stderr.write(` next: ${candidate.nextCommand}\n`);
1585
+ process.stderr.write(` action: ${candidate.actionKind}\n`);
1586
+ if (candidate.plainLanguage) {
1587
+ process.stderr.write(" plain meaning:\n");
1588
+ process.stderr.write(` label: ${candidate.plainLanguage.label}\n`);
1589
+ process.stderr.write(` purpose: ${candidate.plainLanguage.purpose}\n`);
1590
+ process.stderr.write(` improvement: ${candidate.plainLanguage.workflowImprovement}\n`);
1591
+ process.stderr.write(" preserves:\n");
1592
+ for (const item of candidate.plainLanguage.preserves)
1593
+ process.stderr.write(` - ${item}\n`);
1594
+ process.stderr.write(" required before use:\n");
1595
+ for (const item of candidate.plainLanguage.requiredBeforeUse)
1596
+ process.stderr.write(` - ${item}\n`);
1597
+ }
1598
+ process.stderr.write(` boundary: ${candidate.mutationBoundary}\n`);
1599
+ if (candidate.continuityBoundary)
1600
+ process.stderr.write(` continuity: ${candidate.continuityBoundary}\n`);
1601
+ process.stderr.write(" action path:\n");
1602
+ for (const step of candidate.actionPath) {
1603
+ process.stderr.write(` - ${step.id}: ${step.status} writes=${step.writes ? "yes" : "no"} command=${step.command}\n`);
1604
+ }
1605
+ }
1606
+ function writeGuide(guide) {
1607
+ process.stderr.write("IntentDNA route guide\n");
1608
+ process.stderr.write(`Project: ${guide.state.projectDir}\n`);
1609
+ process.stderr.write(`Organization profile: ${guide.state.organization.configured ? "configured" : "missing"} (${guide.state.organization.profilePath})\n`);
1610
+ if (guide.state.organization.name)
1611
+ process.stderr.write(`Organization: ${guide.state.organization.name}\n`);
1612
+ process.stderr.write(`Sync targets: ${guide.state.organization.syncTargets.length > 0 ? guide.state.organization.syncTargets.join(", ") : "none"}\n`);
1613
+ if (guide.state.asset) {
1614
+ const label = guide.state.asset.displayName ? `${guide.state.asset.name} (${guide.state.asset.displayName})` : guide.state.asset.name;
1615
+ process.stderr.write(`Focus asset: ${label}\n`);
1616
+ process.stderr.write(`Asset configured: ${guide.state.asset.configured ? "yes" : "no"}\n`);
1617
+ process.stderr.write(`Cascade: ${guide.state.asset.cascade}\n`);
1618
+ process.stderr.write(`Evolution: ${guide.state.asset.evolution}\n`);
1619
+ process.stderr.write(`Evidence: ${guide.state.asset.evidence}\n`);
1620
+ }
1621
+ else {
1622
+ process.stderr.write("Focus asset: unavailable\n");
1623
+ }
1624
+ if (guide.state.evidence) {
1625
+ process.stderr.write(`Evidence modules: ${guide.state.evidence.modules} pass=${guide.state.evidence.pass} continue=${guide.state.evidence.continue} blocked=${guide.state.evidence.blocked} remaining=${guide.state.evidence.remaining}\n`);
1626
+ }
1627
+ process.stderr.write("\nStart here:\n");
1628
+ for (const entry of guide.entrypoints) {
1629
+ process.stderr.write(` ${entry.id}. ${entry.label}\n`);
1630
+ process.stderr.write(` ${entry.command}\n`);
1631
+ process.stderr.write(` when: ${entry.when}\n`);
1632
+ process.stderr.write(` outcome: ${entry.outcome}\n`);
1633
+ process.stderr.write(` owner=${entry.owner} writes=${entry.writes ? "yes" : "no"}\n`);
1634
+ }
1635
+ process.stderr.write("\nPersona onboarding:\n");
1636
+ for (const path of guide.personaPaths) {
1637
+ process.stderr.write(` ${path.id}. ${path.label}\n`);
1638
+ process.stderr.write(` asks: ${path.question}\n`);
1639
+ process.stderr.write(" first commands:\n");
1640
+ for (const command of path.firstCommands)
1641
+ process.stderr.write(` - ${command}\n`);
1642
+ process.stderr.write(` accept: ${path.acceptance}\n`);
1643
+ process.stderr.write(` boundary: ${path.boundary}\n`);
1644
+ if (path.blockedBy.length > 0)
1645
+ process.stderr.write(` blocked_by: ${path.blockedBy.join("; ")}\n`);
1646
+ }
1647
+ process.stderr.write("\nSimple path:\n");
1648
+ for (const step of guide.journey) {
1649
+ process.stderr.write(` ${step.id}. ${step.label}\n`);
1650
+ process.stderr.write(` status=${step.status} owner=${step.owner} writes=${step.writes ? "yes" : "no"}\n`);
1651
+ process.stderr.write(` ${step.command}\n`);
1652
+ process.stderr.write(` answers: ${step.answers}\n`);
1653
+ process.stderr.write(` next: ${step.next}\n`);
1654
+ }
1655
+ process.stderr.write("\nOperating paths:\n");
1656
+ for (const path of guide.operatingPaths) {
1657
+ process.stderr.write(` ${path.id}. ${path.label}\n`);
1658
+ process.stderr.write(` status=${path.status} owner=${path.owner} writes=${path.writes ? "yes" : "no"} source=${path.source}\n`);
1659
+ process.stderr.write(` ${path.command}\n`);
1660
+ process.stderr.write(` answers: ${path.answers}\n`);
1661
+ process.stderr.write(` handoff: ${path.handoff}\n`);
1662
+ process.stderr.write(` boundary: ${path.boundary}\n`);
1663
+ }
1664
+ process.stderr.write("\nKnowledge links:\n");
1665
+ for (const link of guide.knowledgeLinks) {
1666
+ process.stderr.write(` ${link.id}. ${link.label}\n`);
1667
+ process.stderr.write(` role=${link.role} status=${link.status}\n`);
1668
+ process.stderr.write(` ${link.path}\n`);
1669
+ process.stderr.write(` use: ${link.useFor}\n`);
1670
+ process.stderr.write(` boundary: ${link.boundary}\n`);
1671
+ }
1672
+ writeActiveCandidate(guide.track.activeCandidate);
1673
+ process.stderr.write("\nGovernance foundation:\n");
1674
+ for (const step of guide.foundation) {
1675
+ process.stderr.write(` ${step.id}. ${step.label}\n`);
1676
+ process.stderr.write(` status=${step.status} owner=${step.owner} writes=${step.writes ? "yes" : "no"}\n`);
1677
+ process.stderr.write(` ${step.command}\n`);
1678
+ process.stderr.write(` signal: ${step.signal}\n`);
1679
+ process.stderr.write(` next: ${step.next}\n`);
1680
+ }
1681
+ process.stderr.write("\nLocal quickstart:\n");
1682
+ for (const step of guide.localQuickstart) {
1683
+ process.stderr.write(` ${step.id}. ${step.label}\n`);
1684
+ process.stderr.write(` owner=${step.owner} writes=${step.writes ? "yes" : "no"}\n`);
1685
+ process.stderr.write(` ${step.command}\n`);
1686
+ process.stderr.write(` accept: ${step.acceptance}\n`);
1687
+ process.stderr.write(` verify: ${step.verification.command}\n`);
1688
+ process.stderr.write(` expect: ${step.verification.expected}\n`);
1689
+ process.stderr.write(` evidence: ${step.verification.evidence}\n`);
1690
+ process.stderr.write(` boundary: ${step.boundary}\n`);
1691
+ }
1692
+ process.stderr.write("\nRecommended next step:\n");
1693
+ process.stderr.write(` Stage: ${guide.recommendation.stage}\n`);
1694
+ process.stderr.write(` Action: ${guide.recommendation.label}\n`);
1695
+ process.stderr.write(` Command: ${guide.recommendation.command}\n`);
1696
+ process.stderr.write(` Reason: ${guide.recommendation.reason}\n`);
1697
+ process.stderr.write(` Writes: ${guide.recommendation.writes ? "yes" : "no"}\n`);
1698
+ if (guide.state.warnings.length > 0) {
1699
+ process.stderr.write("\nWarnings:\n");
1700
+ for (const warning of guide.state.warnings)
1701
+ process.stderr.write(` - ${warning}\n`);
1702
+ }
1703
+ process.stderr.write("\nBoundaries:\n");
1704
+ for (const boundary of guide.boundaries)
1705
+ process.stderr.write(` - ${boundary}\n`);
1706
+ process.stderr.write("\nProduct spine:\n");
1707
+ for (const phase of guide.spine) {
1708
+ const requiredWhen = phase.requiredWhen ? ` required_when=${phase.requiredWhen}` : "";
1709
+ process.stderr.write(` ${phase.id}. ${phase.label}\n`);
1710
+ process.stderr.write(` ${phase.command}\n`);
1711
+ process.stderr.write(` ${phase.purpose}\n`);
1712
+ process.stderr.write(` owner=${phase.owner} writes=${phase.writes ? "yes" : "no"}${requiredWhen}\n`);
1713
+ }
1714
+ process.stderr.write("\nRoute:\n");
1715
+ for (const step of guide.route) {
1716
+ process.stderr.write(` ${step.id}. ${step.label}\n`);
1717
+ process.stderr.write(` ${step.command}\n`);
1718
+ if (step.scaffoldFallback)
1719
+ process.stderr.write(` scaffold fallback: ${step.scaffoldFallback}\n`);
1720
+ process.stderr.write(` ${step.purpose}\n`);
1721
+ }
1722
+ process.stderr.write("\nNext commands:\n");
1723
+ for (const command of guide.nextCommands)
1724
+ process.stderr.write(` - ${command}\n`);
1725
+ }
1726
+ export async function runGuide(opts) {
1727
+ const guide = await buildGuide(opts);
1728
+ if (opts.quickstart) {
1729
+ const quickstart = buildQuickstartReview(guide, quickstartSyncTarget(guide, opts));
1730
+ if (opts.json) {
1731
+ process.stdout.write(JSON.stringify(quickstart, null, 2) + "\n");
1732
+ return 0;
1733
+ }
1734
+ writeQuickstart(quickstart);
1735
+ return 0;
1736
+ }
1737
+ if (opts.json) {
1738
+ process.stdout.write(JSON.stringify(opts.brief ? buildBriefReview(guide) : guide, null, 2) + "\n");
1739
+ return 0;
1740
+ }
1741
+ if (opts.brief) {
1742
+ writeBriefGuide(guide);
1743
+ return 0;
1744
+ }
1745
+ writeGuide(guide);
1746
+ return 0;
1747
+ }