intentdna 1.7.5 → 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 +703 -36
  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 +5 -0
  53. package/dist/hooks/cli.js +149 -5
  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
package/dist/cli/index.js CHANGED
@@ -13,6 +13,7 @@
13
13
  */
14
14
  import { parseArgs } from "node:util";
15
15
  import { getPackageVersion } from "./util/version.js";
16
+ import { WORKFLOW_ASSET_IDS } from "../templates/metadata.js";
16
17
  const fallbackVersion = "unknown";
17
18
  function helpText(version) {
18
19
  return `Intent DNA CLI v${version}
@@ -33,8 +34,17 @@ Commands:
33
34
  evolve Preview epigenetic marker changes from persisted outcomes
34
35
  epigenetic Record outcomes, view markers and summaries
35
36
  feedback Build local kernel report (--days <N>, --json, --package, --evolve preview, --dna-id <id>)
37
+ report Package and stage local runtime evidence for hidden transport
36
38
  context Inspect planning-only advisory context sources
37
39
  templates Template management (deploy to global install)
40
+ assets Read-only workflow asset inventory and evidence links
41
+ workflow External-agent workflow authoring packet, routes, evidence suggestions, and legacy scaffold preview
42
+ org Local organization/project asset bindings and review
43
+ guide Show the workflow governance route and next commands
44
+ quickstart Show the shortest local route: choose, init, sync, run, sign, verify
45
+ release Plan deploy gates for web/public surfaces
46
+ cloud Check, bootstrap, and plan SaaS backend deployment (Supabase)
47
+ auth Manage CLI API token authentication for cloud features
38
48
 
39
49
  Options:
40
50
  --help, -h Show help for a command
@@ -45,11 +55,72 @@ Examples:
45
55
  dna guard --level strict Enterprise-grade guardrails
46
56
  dna guard --audit Show last 7 days of violation logs
47
57
  dna guard --remove Remove all guardrails
48
- dna init --template flutter-rewrite Create DNA config from template
58
+ dna init --template ${WORKFLOW_ASSET_IDS.default} Create DNA config from template
49
59
  dna init --template list List all available templates with namespaces
50
60
  dna init --register my.dna.yaml Register a custom template (checks namespace uniqueness)
51
61
  dna generate "Flutter app with behavior locking" Generate config prompt with schema spec
52
62
  dna generate "Secure API backend" --match Find matching templates
63
+ dna assets library Browse workflow assets by readiness and next command
64
+ dna assets candidates ${WORKFLOW_ASSET_IDS.default} Find workflow candidates from dogfood evidence
65
+ dna assets lineage ${WORKFLOW_ASSET_IDS.default} Explain origin, cascade, evidence, and evolution route
66
+ dna assets lifecycle ${WORKFLOW_ASSET_IDS.default} Show cascade/evidence/evolution lifecycle
67
+ dna assets list List workflow assets compiled from templates
68
+ dna assets inspect ${WORKFLOW_ASSET_IDS.default} --evidence Inspect a workflow asset and evidence links
69
+ dna assets evidence ${WORKFLOW_ASSET_IDS.default} Summarize dogfood progress JSON for an asset
70
+ dna org intake "Mobile rewrite team" --asset ${WORKFLOW_ASSET_IDS.default} --sync-target codex
71
+ dna org init --name "My Org" --project "Mobile Rewrite" --asset ${WORKFLOW_ASSET_IDS.default} --sync-target codex
72
+ dna org review Review local organization asset bindings and next actions
73
+ dna org receipt --json Emit local org review receipt projection input
74
+ dna org rollout Review sync/downstream rollout readiness
75
+ dna release deploy-plan Decide whether Vercel deploy + URL verification is required
76
+ dna release deploy-plan apps/online/src/main.ts --json
77
+ dna cloud status --json Check Supabase cloud config without network access
78
+ dna cloud env-manifest --secrets-check <json> --vercel-env-check <json> Classify local env with saved remote evidence overlay
79
+ dna cloud vercel-env-plan --json Plan browser-safe Vercel env setup for online Supabase projection
80
+ dna cloud vercel-env-check --json Check Vercel production public Supabase env presence
81
+ dna cloud credential-check --secrets-check <json> --vercel-env-check <json> Include saved remote evidence without rerunning checks
82
+ dna cloud rollout-pack --secrets-check <json> --vercel-env-check <json> Include saved remote evidence without rerunning checks
83
+ dna cloud production-evidence --secrets-check <json> --vercel-env-check <json> Include saved remote evidence in production evidence
84
+ dna cloud vercel-env-apply --dry-run --json Preview guarded Vercel public Supabase env writes
85
+ dna cloud secrets-plan --json Plan guarded Supabase Function secret setup
86
+ dna cloud secrets-apply --dry-run --json Preview guarded Supabase Function secret writes
87
+ dna cloud secrets-check --json Check Supabase Function secret names without reading values
88
+ dna cloud credential-check --json Summarize Supabase live credential readiness gates
89
+ dna cloud handoff --json Build a redacted Supabase operator credential handoff packet
90
+ dna cloud runbook --json Build a redacted Supabase/Vercel production operator runbook
91
+ dna cloud operator-checklist --json Build a concise local-only operator checklist for SaaS launch blockers
92
+ dna cloud production-evidence --json Aggregate Supabase production evidence without mutation
93
+ dna cloud edge-check --json Run local Supabase Edge Function typechecks without deploy
94
+ dna cloud contract-check --json Verify local Supabase artifact contracts before live deploy
95
+ dna cloud function-health --json Probe deployed Supabase Edge Functions with OPTIONS only
96
+ dna cloud deploy-plan --json Plan Supabase live deployment without network access
97
+ dna cloud deploy-execute --dry-run --json Preview guarded Supabase deployment execution
98
+ dna cloud smoke-plan --json Plan post-deploy cloud ingestion smoke without network access
99
+ dna cloud smoke-execute --dry-run --json Preview guarded post-deploy ingestion smoke execution
100
+ dna cloud smoke-receipt-check --receipt <path> --json Check a saved live smoke receipt locally
101
+ dna cloud bootstrap --admin-user-id <uuid> --admin-email me@example.com --org "My Org" --project "IntentDNA" --json
102
+ dna auth status --json Check local CLI API token status
103
+ dna auth token set <token> --json Store a CLI API token outside the project repo
104
+ dna auth user-jwt set <jwt> --json Store Supabase user JWT for account onboarding commands
105
+ dna auth bootstrap-account --org "My Org" --project "IntentDNA" --dry-run --json Create/reuse account org/project before CLI token onboarding
106
+ dna auth onboard --dry-run --json Preview project discovery plus CLI API token issuance
107
+ dna auth issue-token --project-id <uuid> --dry-run --json Preview Supabase user JWT token issuance
108
+ dna auth projects --dry-run --json Preview account project discovery through Supabase user JWT
109
+ dna auth tokens list --dry-run --json Preview account API token listing through Supabase user JWT
110
+ dna report package Write .dna/reports/latest-report-package.json
111
+ dna report push --dry-run --json Preview hidden evidence transport envelope
112
+ dna report sign --json Sign a local report package into an ingest envelope and print envelope_path
113
+ dna report verify .dna/reports/ingest/report-ingest.json --json
114
+ dna report receipts --project-id <uuid> --dry-run --json Preview cloud receipt projection listing
115
+ dna quickstart --asset ${WORKFLOW_ASSET_IDS.default} --sync-target codex
116
+ dna guide --asset ${WORKFLOW_ASSET_IDS.default} --name "Samuel AI Lab" --project "Mobile Rewrite" --goal "Rewrite module with logic equivalence"
117
+ dna workflow examples List workflow draft examples
118
+ dna workflow authoring-packet "Create a code review workflow" --json
119
+ dna workflow intake "Rewrite module with logic equivalence" Recommend reuse or authoring path
120
+ dna workflow suggestions ${WORKFLOW_ASSET_IDS.default} Suggest human-reviewed improvements from evidence
121
+ dna workflow mine ${WORKFLOW_ASSET_IDS.default} Mine candidate workflow assets from evidence
122
+ dna workflow draft "Rewrite module with logic equivalence" --example rewrite_governance --strictness high # scaffold fallback only
123
+ dna assets adoption workflow-evidence-review
53
124
  dna sync Auto-detect .dna/config.yaml + environment, sync all
54
125
  dna sync .dna/config.yaml --target claude-md --inject CLAUDE.md --context work
55
126
  dna sync my.dna.json --target claude-md --inject CLAUDE.md --hooks .claude/hooks
@@ -74,19 +145,116 @@ Examples:
74
145
  `;
75
146
  }
76
147
  const COMMAND_HELP = {
77
- sync: `Usage: dna sync [files...] [options]\n\nOptions:\n --mode auto|plugin|bin Sync mode (default: auto)\n --dry-run Print planned outputs without writing files\n --post-summary Print registry-backed output summary\n --target <target> Markdown target for injection\n --inject <path> File to inject markdown into\n --agents <dir> Generate agent files\n --skills <dir> Generate skill files\n --workflow <dir> Generate workflow shell scripts\n --settings <path> Write hook settings in bin mode\n --lock <path> Write lock file (default .dna/lock)\n`,
148
+ cloud: `Usage: dna cloud status [--auth-config-dir <dir>] [--secrets-check <path>] [--vercel-env-check <path>] [--json]
149
+ dna cloud daily-report [--auth-config-dir <dir>] [--secrets-check <path>] [--vercel-env-check <path>] [--json]
150
+ dna cloud env-manifest [--secrets-check <path>] [--vercel-env-check <path>] [--json]
151
+ dna cloud vercel-env-plan [--json]
152
+ dna cloud vercel-env-check [--json]
153
+ dna cloud vercel-env-apply [--dry-run] [--yes] [--json]
154
+ dna cloud secrets-plan [--json]
155
+ dna cloud secrets-apply [--dry-run] [--yes] [--json]
156
+ dna cloud secrets-check [--json]
157
+ dna cloud credential-check [--endpoint <url>] [--secrets-check <path>] [--vercel-env-check <path>] [--json]
158
+ dna cloud handoff [--endpoint <url>] [--secrets-check <path>] [--vercel-env-check <path>] [--json]
159
+ dna cloud runbook [--endpoint <url>] [--secrets-check <path>] [--vercel-env-check <path>] [--output <path>] [--json]
160
+ dna cloud operator-checklist [--endpoint <url>] [--deployment-url <url>] [--secrets-check <path>] [--vercel-env-check <path>] [--json]
161
+ dna cloud production-evidence [--endpoint <url>] [--deployment-url <url>] [--receipt <path>] [--secrets-check <path>] [--vercel-env-check <path>] [--json]
162
+ dna cloud contract-check [--json]
163
+ dna cloud edge-check [--json]
164
+ dna cloud function-health [--endpoint <url>] [--json]
165
+ dna cloud deploy-plan [--secrets-check <path>] [--vercel-env-check <path>] [--json]
166
+ dna cloud deploy-execute [--dry-run] [--yes] [--json]
167
+ dna cloud smoke-plan [--endpoint <url>] [--json]
168
+ dna cloud smoke-execute [--endpoint <url>] [--dry-run] [--yes] [--json]
169
+ dna cloud smoke-receipt-check --receipt <path> [--json]
170
+ dna cloud rollout-pack [--endpoint <url>] [--secrets-check <path>] [--vercel-env-check <path>] [--json]
171
+ dna cloud bootstrap [options]
172
+
173
+ Subcommands:
174
+ daily-report Emit the manager daily status packet from manager_brief without network or mutation
175
+ env-manifest Classify browser, CLI, Supabase operator, server-secret, and manual confirmation env
176
+ vercel-env-plan Plan browser-safe Vercel production env setup without writing values
177
+ vercel-env-check Check Vercel production env presence without reading values or writing env
178
+ vercel-env-apply Execute guarded Vercel public Supabase env writes only with --yes
179
+ secrets-plan Plan guarded Supabase Function secret setup without writing secrets
180
+ secrets-apply Execute guarded Supabase Function secret writes only with --yes
181
+ secrets-check Check Supabase Function secret names without reading values or writing secrets
182
+ credential-check Summarize live Supabase/Vercel/CLI credential readiness gates
183
+ handoff Build a redacted Supabase operator credential handoff packet
184
+ runbook Build a redacted Supabase/Vercel production operator runbook
185
+ operator-checklist Build a local-only checklist of user/operator inputs, commands, and verification gates
186
+ production-evidence Aggregate contract, deploy, health, smoke, rollout, secrets, and online production evidence without mutation
187
+ contract-check Verify local migration/function contracts
188
+ edge-check Run local Deno typechecks for Supabase Edge Functions
189
+ function-health Probe deployed Supabase Edge Functions with OPTIONS requests only
190
+ deploy-execute Execute guarded Supabase link/db push/secrets/functions only with --yes
191
+ smoke-receipt-check Check a saved live smoke receipt locally before production evidence aggregation
192
+
193
+ Boundaries:
194
+ - Supabase SaaS configuration checks preserve local runtime truth; local planning commands perform no network request unless the subcommand explicitly says it is a read-only live check
195
+ - daily-report is manager status evidence only; it does not deploy, upload, set secrets, execute workflows, or create runtime authority
196
+ - performs no network request for local-only planning/status commands
197
+ - env-manifest and credential-check print placement/readiness guidance and masked previews only; do not write env files
198
+ - vercel-env-plan lists Vercel env/deploy/evidence commands but does not write env values, deploy, or read secrets
199
+ - vercel-env-check runs a read-only Vercel production env presence check and omits env values from output
200
+ - vercel-env-apply requires --yes before writing Vercel env
201
+ - secrets-plan lists Supabase Function secret commands but does not set secrets
202
+ - secrets-apply requires --yes before writing Supabase Function secrets
203
+ - secrets-check reads Supabase Function secret names only; it does not print real secrets, set secrets, upload reports, or grant runtime authority
204
+ - handoff does not print real secrets
205
+ - runbook does not run them, deploy online, or write files unless --output is explicit
206
+ - operator-checklist condenses user/operator blockers and commands
207
+ - status, daily-report, env-manifest, deploy-plan, credential-check, handoff, runbook, operator-checklist, rollout-pack, and production-evidence may read supplied --secrets-check and --vercel-env-check artifacts locally instead of rerunning remote checks
208
+ - production-evidence aggregates local checks, remote secret-name checks or a supplied secrets-check artifact, Vercel env-name checks or a supplied vercel-env-check artifact, unauthenticated function health, supplied live smoke receipt, and online deployment URL
209
+ - smoke-receipt-check reads one local receipt JSON only
210
+ - contract-check does not run Supabase or Deno
211
+ - edge-check does not link Supabase, deploy functions, set secrets, or validate live credentials
212
+ - function-health sends no auth and performs no upload, publish, migration, or secret mutation
213
+ - deploy-execute requires --yes before mutating Supabase
214
+ - deploy-plan does not run migrations, deploy functions, set secrets, execute bootstrap SQL, or smoke-test upload
215
+ - rollout-pack does not run deployment, create accounts, or upload reports
216
+ - smoke-plan does not run report upload or perform a network request
217
+ - Service role keys are server-only; token peppers are also server-only and are never accepted as browser or CLI client configuration
218
+ - API tokens are the CLI auth path, not MCP authorization
219
+ `,
220
+ sync: `Usage: dna sync [status|doctor|remove] [files...] [options]\n\nSubcommands:\n status Show registry-tracked sync artifacts and drift posture\n doctor Check whether registry-tracked artifacts still match last sync\n remove Remove safe hash-matching IntentDNA-owned/diagnostic artifacts from the registry\n\nOptions:\n --mode auto|plugin|bin Sync mode (default: auto)\n --dry-run Print planned outputs without writing files; with remove, preview removals\n --post-summary Print registry-backed output summary after sync\n --json Print status/doctor JSON to stdout\n --project-dir <path> Read/write local sync configs and artifacts in another project directory\n --target <target> Markdown target for injection\n --inject <path> File to inject markdown into\n --agents <dir> Generate agent files\n --skills <dir> Generate skill files\n --workflow <dir> Generate workflow shell scripts\n --settings <path> Write hook settings in bin mode\n --codex Generate Codex CLI instruction, plugin, fallback hook, and evidence artifacts\n --codex-install-mode <mode> plugin_scoped|project_fallback|managed|none (default project_fallback)\n --codex-dogfood Probe codex exec --json and attach diagnostic evidence\n --lock <path> Write lock file (default .dna/lock)\n --remove Legacy explicit-target removal; requires --inject/--agents/--skills/--workflow/--codex\n`,
78
221
  verify: `Usage: dna verify [--lock <path>] [--stats] [--health] [--strict]\n\nOptions:\n --health Comprehensive installation health check\n --stats Show hook call statistics\n --strict Require valid RuntimeDecisionEvent enterprise evidence\n --lock <path> Lock file path (default .dna/lock)\n`,
79
- templates: `Usage: dna templates <list|show|deploy>\n\nSubcommands:\n list List built-in and project templates\n show <name> Show template metadata and YAML\n deploy Copy local templates to global install\n`,
222
+ templates: `Usage: dna templates <list|marketplace|manage|sources|show|publish|publications|revoke|deploy> [name] [--json] [--project-dir <path>]\n\nSubcommands:\n list List built-in and project templates with marketplace visibility/harness metadata\n marketplace Export a shared intentdna.template_marketplace_catalog.v1 catalog\n manage [name] Show template management view: tags/details/marketplace/step index plus full YAML\n sources [reference] Review external workflow/skill references that may be translated into DNA templates\n show <name> Show template metadata, marketplace metadata, and YAML\n publish Publish an org-private template through Supabase using a local receipt evidence file\n publications List org-private template publications through Supabase as read-only projection\n revoke Mark one org-private template publication unpublished through Supabase metadata\n deploy Copy local templates to global install\n\nOptions:\n --json Print manage/sources/marketplace/publish/publications/revoke JSON to stdout\n --project-dir <path> Include project-local .dna/templates from another project directory\n --output <path> For marketplace: write catalog JSON for online/static import\n --source-dir <path> Scan a reference workflow/skill directory (repeatable)\n --focus all|refresh|gaps For sources list: all references, existing-template refreshes, or uncovered gaps\n --candidate For sources <reference>: print a read-only candidate template YAML preview\n --save-template <name> With --candidate, save the preview as project-local .dna/templates/<name>.dna.yaml\n --org <org> For publish/publications/revoke: organization id/slug/name\n --project <project> For publish/publications/revoke: project id/slug/name\n --template <name> For publish/publications: template name filter\n --publication-id <id> For revoke: org-private template publication id from dna templates publications\n --reason <text> For revoke: optional human reason stored in request metadata\n --receipt <path> For publish: intentdna.org_review_receipt.v1 or intentdna.report_ingest_receipt.v1 evidence file\n --endpoint <url> For publish/publications/revoke: Supabase Edge Function endpoint override\n --auth-config-dir <dir> Read CLI API token config from a specific directory for isolated template publication checks\n --dry-run For publish/publications/revoke: validate request without network upload\n`,
223
+ assets: `Usage: dna assets <list|library|candidates|lineage|show|inspect|status|review|governance|lifecycle|adoption|suggestions|diff|evidence> [name] [--evidence] [--json]\n\nSubcommands:\n list List template-backed workflow assets\n library Browse workflow assets by readiness with evidence/governance next commands\n candidates [name] Find candidate workflow assets to extract or promote from dogfood evidence\n lineage <name> Explain origin, cascade, evidence, and human-reviewed evolution route\n lifecycle <name> Show cascade, evidence, suggestion, draft, review, adoption, bind, and sync lifecycle\n show <name> Show workflow asset summary\n inspect <name> Show workflows, controllers, roles, steps, and optional evidence links\n status [name] Show read-only management, evidence, and project configuration posture\n review Show manager-facing asset health summary and next actions\n governance <name> Explain cascade inheritance and preview-first evolution for an asset\n adoption <name> Show adoption readiness checks and the safe adoption path\n suggestions <name> Suggest human-reviewed workflow improvements from evidence\n diff <from> <to> Compare two workflow assets for manager review before adoption\n evidence <name> Summarize registered dogfood progress JSON for a workflow asset\n\nOptions:\n --evidence Include registered evidence/reference links\n --project-dir <path> Read project-local workflow assets and configs from another project directory\n --json Print JSON to stdout\n`,
224
+ workflow: `Usage: dna workflow <examples|authoring-packet|intake|route|suggestions|mine|draft|edit-plan|review-suggestion|improve-from-suggestions|from-candidate> [description] [--example <id>] [--strictness standard|high] [--json|--yaml]\n\nSubcommands:\n examples List draft examples\n authoring-packet [goal] Emit the C3 packet for external-agent workflow authoring; no intent modeling or mutation\n intake <description> Review a workflow request and recommend reuse or authoring path\n route <description> Show the personal no-canvas route: describe, author, validate, run; use --org for organization rollout gates\n suggestions <asset> Suggest human-reviewed workflow improvements from evidence without mutation\n mine [asset] Find candidate workflow assets or follow-up drafts from real evidence\n draft <description> Clone a built-in example as a scaffold fallback; structure is not derived from the goal\n edit-plan <instruction> Preview a workflow edit without writing DNA or runtime files\n review-suggestion Persist accept/reject/defer for an evidence-backed suggestion\n improve-from-suggestions Build a reviewable edit plan from an accepted asset suggestion\n from-candidate <id> Act on a dogfood-backed candidate without copying a long command\n\nOptions:\n --name <org> Organization name for --org route planning\n --project <project> Project name for --org route planning\n --sync-target <target> Runtime surface for --org route planning, such as codex or claude\n --org Include organization binding, configure, rollout, sync, deploy, improve, and evolution gates\n --from-template <name> Source workflow asset for route/edit/candidate commands\n --workflow <id> Select a workflow inside a multi-workflow asset template such as fix or behavior-lock\n --suggestion <id> Suggestion id such as template-model-verifier or template-blocked-triage\n --decision <decision> For review-suggestion: accept|reject|defer\n --save-template <name> Save a draft/scaffold as .dna/templates/<name>.dna.yaml for human review and asset inspection\n --project-dir <path> Read/write workflow assets in another project directory\n --force Overwrite an existing saved workflow asset draft\n --operation <op> Optional override; otherwise auto-chosen from the instruction\n --target-step <id> Optional override; otherwise auto-chosen from the edit\n --role <role> Optional override; otherwise auto-chosen/defaulted from the edit\n\nExamples:\n dna workflow examples\n dna workflow authoring-packet "Create a code review workflow" --json\n dna workflow intake "Rewrite module with logic equivalence"\n dna workflow route "Rewrite module with logic equivalence"\n dna workflow route "Rewrite module with logic equivalence" --org --name "Project Admin" --project "Mobile Rewrite" --sync-target codex\n dna workflow suggestions ${WORKFLOW_ASSET_IDS.default} --json\n dna workflow mine ${WORKFLOW_ASSET_IDS.default} --json\n dna workflow draft "Rewrite module with logic equivalence" --example rewrite_governance --strictness high # scaffold fallback only\n dna workflow draft "Rewrite module with logic equivalence" --save-template team-rewrite-flow # scaffold fallback only\n dna workflow edit-plan "Add equivalence verifier after rewrite" --from-template team-rewrite-flow --save-template team-rewrite-flow-v2\n dna workflow review-suggestion --from-template ${WORKFLOW_ASSET_IDS.default} --workflow fix --suggestion template-model-verifier --decision accept\n dna workflow improve-from-suggestions --from-template ${WORKFLOW_ASSET_IDS.default} --workflow fix --suggestion template-model-verifier --save-template ${WORKFLOW_ASSET_IDS.default}-v2\n dna workflow from-candidate extract-diagnosis-review-${WORKFLOW_ASSET_IDS.default} --from-template ${WORKFLOW_ASSET_IDS.default} --save-template ${WORKFLOW_ASSET_IDS.rewriteDiagnosisReview}\n`,
225
+ org: `Usage: dna org <intake|configure-plan|route|rollout|init|bind|status|review|receipt> [description] [options]\n\nSubcommands:\n intake [description] Plan organization/project setup and asset binding without writing files\n configure-plan List explicit dna init commands for declared assets missing project config\n route Show the organization operating route and rollout readiness without syncing\n rollout Review sync/downstream rollout readiness without syncing (alias-compatible with route)\n init Create local .dna/org.yaml with organization/project bindings\n bind Add or update a workflow asset binding for a project\n status Show local organization, projects, assets, sync targets, and evidence totals\n review Show manager-facing gaps and next actions\n receipt Emit intentdna.org_review_receipt.v1 from local org review and rollout data\n\nOptions:\n --name <organization> Organization name for intake or init\n --project <project> Project name/id for intake, init, or bind\n --asset <asset> Bind a workflow asset such as ${WORKFLOW_ASSET_IDS.default}\n --status <status> planned|active|paused for org bind (default planned)\n --sync-target <target> Declare a target such as codex or claude\n --project-dir <path> Read/write organization state in a different project directory\n --apply For configure-plan only: create missing .dna/configs from declared assets\n --json Print JSON to stdout\n\nBoundaries:\n - org receipt is local projection evidence only; cloud_authority=false\n - internal_ready candidates are adoption candidates, not org-private SaaS visibility\n - No online org auth, permissions, backend persistence, or cloud storage is implied\n\nExamples:\n dna org intake "Mobile rewrite team" --asset ${WORKFLOW_ASSET_IDS.default} --sync-target codex\n dna org configure-plan\n dna org configure-plan --apply\n dna org route\n dna org rollout\n dna org receipt --json\n dna org init --name "My Org" --project "Mobile Rewrite" --asset ${WORKFLOW_ASSET_IDS.default} --sync-target codex\n dna org bind --asset team-rewrite-flow-v2 --status active --sync-target codex\n dna org review\n`,
226
+ release: `Usage: dna release <deploy-plan|evidence> [files...] [--json]\n\nSubcommands:\n deploy-plan Read changed files and decide whether Vercel and/or Supabase release verification is required\n evidence Record deploy-plan, deployed URL, checked routes, and cloud checks as intentdna.release_evidence.v1\n\nOptions:\n --json Print JSON to stdout\n --output <path> For evidence: write release evidence JSON (default .dna/release/latest-release-evidence.json)\n --deployment-url <url> For evidence: deployed URL captured from Vercel CLI stdout when web routes changed\n --checked-route <route> For evidence: route verified on the deployed URL (repeatable or comma-separated)\n --checked-cloud-check <id> For evidence: cloud check completed, such as cloud-contract-check or cloud-edge-check (repeatable or comma-separated)\n --dry-run For evidence: do not write the evidence file\n\nBoundaries:\n - CLI/core/runtime/docs/wiki changes do not require Vercel deployment by themselves\n - Web/public surfaces require Vercel CLI deploy only when reviewers or users need a deployed URL\n - Supabase SaaS surfaces require cloud contract, Edge Function, deploy-plan, remote secret-name presence, Vercel public env presence, function health, and live ingest-smoke evidence before production release claims\n - Deployment is separate from org rollout and runtime sync\n - A web deploy is not complete until the deployed URL is opened or fetched and verified\n - A cloud deploy is not complete until Supabase migrations/functions/secrets, Vercel public env presence, and ingestion smoke evidence are recorded\n - Release evidence records supplied checks; it does not run build, deploy, URL verification, Supabase commands, sync, or policy enforcement\n\nExamples:\n dna release deploy-plan\n dna release deploy-plan apps/online/src/main.ts\n dna release deploy-plan src/cli/index.ts --json\n dna release deploy-plan supabase/functions/ingest-report/index.ts --json\n dna release evidence apps/online/src/main.ts --deployment-url https://intentdna.vercel.app --checked-route / --checked-route '/?mode=public' --checked-route '/?mode=public&embed=1' --checked-route /runtime --checked-route /templates --checked-route /readiness --json\n dna release evidence supabase/functions/ingest-report/index.ts --checked-cloud-check cloud-contract-check --checked-cloud-check cloud-edge-check --checked-cloud-check cloud-deploy-plan --checked-cloud-check cloud-function-health --checked-cloud-check cloud-secrets-check --checked-cloud-check cloud-vercel-env-check --checked-cloud-check cloud-ingest-smoke --json\n`,
227
+ auth: `Usage: dna auth status [--auth-config-dir <dir>] [--json]\n dna auth token set <token> [--auth-config-dir <dir>] [--json]\n dna auth token clear [--auth-config-dir <dir>] [--json]\n dna auth user-jwt status [--auth-config-dir <dir>] [--json]\n dna auth user-jwt set <jwt> [--auth-config-dir <dir>] [--json]\n dna auth user-jwt clear [--auth-config-dir <dir>] [--json]\n dna auth bootstrap-account [--org <name>] [--project <name>] [options]\n dna auth onboard [--project-id <id>] [options]\n dna auth issue-token --project-id <id> [options]\n dna auth projects [options]\n dna auth tokens list [options]\n dna auth tokens revoke <token-id> [--yes] [options]\n\nSubcommands:\n status Show local CLI API token status without network validation\n token set <token> Store a CLI API token in user config outside the project repository\n token clear Remove the stored CLI API token; idempotent if already absent\n user-jwt status Show local Supabase user JWT account bridge status without network validation\n user-jwt set <jwt> Store a Supabase user JWT for account onboarding commands outside the project repository\n user-jwt clear Remove the stored Supabase user JWT; idempotent if already absent\n bootstrap-account Create/reuse Supabase account org/project with a user JWT; token issuance remains dna auth onboard\n onboard Discover account projects, select one safely, issue a CLI API token, and store it locally\n issue-token Call Supabase issue-api-token with a user JWT and store the issued CLI token\n projects Call Supabase list-projects with a user JWT for account onboarding projection\n tokens list Call Supabase manage-api-tokens to list API token metadata only\n tokens revoke <token-id> Revoke an API token after explicit --yes confirmation\n\nOptions:\n --org <name> Organization name for account bootstrap\n --project <name> Project name for account bootstrap\n --org-slug <slug> Optional organization slug for account bootstrap\n --project-slug <slug> Optional project slug for account bootstrap\n --project-hint <path> Optional local project hint stored as account bootstrap metadata\n --project-id <id> Supabase projects.id for issue-token or token filtering\n --organization-id <id> Optional organization id to cross-check or filter\n --token-id <id> API token id for revoke or filtering\n --include-revoked Include revoked API token metadata in tokens list\n --limit <n> Maximum token summaries to request, capped at 100\n --user-jwt <jwt> Supabase user access token override; env or dna auth user-jwt set can also supply it\n --endpoint <url> Edge Function URL; defaults from INTENTDNA_CLOUD_URL\n --auth-config-dir <dir> Read/write CLI API token and user JWT config in a specific directory for isolated local checks\n --token-name <name> Display name for the issued CLI token\n --scope <scope> Requested scope; repeatable or comma-separated, defaults to report:ingest\n --expires-at <iso> Optional token expiry timestamp\n --dry-run Build the request without making a network call or storing a token\n --yes Required before live dna auth tokens revoke mutates account auth state\n --json Print JSON to stdout\n\nBoundaries:\n - CLI ingestion auth uses IntentDNA API tokens, not MCP authorization\n - dna auth bootstrap-account is an onboarding mutation only; it does not issue CLI tokens, upload reports, publish templates, or run workflows\n - dna auth onboard is a CLI onboarding convenience over projects plus issue-token; it does not guess between multiple projects\n - Supabase user JWTs are account onboarding credentials for projects, issue-token, and token management; they are not CLI ingestion API tokens\n - User JWTs are stored only by explicit dna auth user-jwt set and output uses masked previews only\n - Token status is local until cloud token verification exists\n - Raw tokens are not printed after set or issue-token; token list/revoke never prints raw tokens or token hashes\n - Service role keys are server-only and rejected as CLI/user tokens when detected\n - Auth state and account projections do not grant runtime allow/warn/block/validate authority\n\nExamples:\n dna auth status --json\n dna auth token set idna_example_token --json\n dna auth token set idna_example_token --auth-config-dir /tmp/intentdna-auth --json\n dna auth status --auth-config-dir /tmp/intentdna-auth --json\n dna auth token clear --json\n dna auth user-jwt status --json\n dna auth user-jwt set eyJhbGciOi... --json\n dna auth user-jwt clear --json\n dna auth bootstrap-account --org "My Org" --project "IntentDNA" --dry-run --json\n dna auth bootstrap-account --org "My Org" --project "IntentDNA" --json\n dna auth onboard --dry-run --json\n dna auth onboard --project-id 00000000-0000-4000-8000-000000000000 --json\n dna auth issue-token --project-id 00000000-0000-4000-8000-000000000000 --dry-run --json\n dna auth issue-token --project-id 00000000-0000-4000-8000-000000000000 --token-name "Laptop CLI" --json\n dna auth projects --dry-run --json\n dna auth tokens list --project-id 00000000-0000-4000-8000-000000000000 --dry-run --json\n dna auth tokens revoke token_123 --yes --json\n`,
228
+ report: `Usage: dna report <package|push|sign|verify|upload|receipts> [envelope-path] [--days <N>] [--session-id <id>] [--dna-id <id>] [--package <path>] [--output <path>] [--endpoint <url>] [--auth-config-dir <dir>] [--json] [--dry-run]\n\nSubcommands:\n package Build and write a local intentdna.report_package.v1 evidence package\n push Stage the same package into a local hidden-transport outbox envelope\n sign Wrap an existing or freshly built package in intentdna.report_ingest_envelope.v1 with envelope_path\n verify <envelope-path> Verify a local signed envelope and emit intentdna.report_ingest_receipt.v1\n upload <envelope-path> Upload a verified signed envelope/package to cloud ingestion with a CLI API token\n receipts List cloud receipt projections through Supabase user JWT account auth\n\nOptions:\n --days <N> Days to look back (default 7)\n --session-id <id> Filter evidence by session id\n --dna-id <id> Include DNA id for marker preview resolution\n --include-marker-preview Include preview-only marker changes\n --project-dir <path> Read evidence from another project directory\n --package <path> For sign: existing intentdna.report_package.v1 to wrap instead of rebuilding\n --output <path> Package output for package/push; envelope output for sign\n --actor <id> Local actor id recorded in the signed ingest envelope\n --visibility <mode> runtime-local|personal|internal for local projection metadata\n --redaction-policy-version <id> Local redaction policy version recorded in the envelope\n --endpoint <url> For push: future metadata only; upload/receipts Edge Function endpoint override\n --auth-config-dir <dir> Read CLI API token/user JWT config from a specific directory for isolated local upload/receipt checks\n --user-jwt <jwt> For receipts: Supabase user access token override\n --organization-id <id> For receipts: optional organization filter/cross-check\n --project-id <id> For receipts: required Supabase project id\n --status <status> For receipts: verified|pending|rejected\n --limit <n> For receipts: maximum receipt summaries to request, capped at 100\n --dry-run Preview package/push/sign/upload/receipts without writing upload network state; upload/receipts dry-run performs no network request\n --json Print JSON to stdout\n\nBoundaries:\n - dna report package/push/sign/verify/upload/receipts does not execute workflows or enforce policy\n - push stages a local outbox envelope only; network_performed is always false in this lane\n - sign and verify are local verifier trust evidence only, not cloud trusted ingestion\n - upload sends signed evidence to cloud ingestion, but runtime_authority remains false\n - receipts lists read-only account projections with a Supabase user JWT; it does not upload reports or read storage object contents\n - Report upload uses IntentDNA CLI API tokens; receipt listing uses Supabase user JWT account credentials\n - Online may import/project packages and receipts later, but dna-hook remains runtime truth\n - MCP remains hidden transport, not a visible product entry\n\nExamples:\n dna report package\n dna report package --days 1 --json\n dna report push --dry-run --json\n dna report push --endpoint https://example.com/api/intentdna/evidence\n dna report sign --json\n dna report verify "$(dna report sign --json | node -pe 'JSON.parse(require("fs").readFileSync(0,"utf8")).envelope_path')" --json\n dna report sign --package .dna/reports/latest-report-package.json --output .dna/reports/ingest/local-envelope.json --json\n dna report verify .dna/reports/ingest/local-envelope.json --json\n dna report upload .dna/reports/ingest/local-envelope.json --json\n dna report upload .dna/reports/ingest/local-envelope.json --endpoint https://example.supabase.co/functions/v1/ingest-report --auth-config-dir /tmp/intentdna-auth --dry-run --json\n dna report receipts --project-id 00000000-0000-4000-8000-000000000000 --dry-run --json\n dna report receipts --project-id 00000000-0000-4000-8000-000000000000 --status verified --limit 10 --json\n`,
229
+ guide: `Usage: dna guide [asset] [--asset <name>] [--name <org>] [--project <project>] [--goal <workflow>] [--sync-target <target>] [--brief] [--json]\n\nShows the current workflow governance route: organization setup, external-agent authoring/validated asset editing, asset governance, runtime sync, evidence review, and manager review.\n\nOptions:\n --asset <name> Focus the guide on a workflow asset (default prefers ${WORKFLOW_ASSET_IDS.default})\n --name <org> Organization/workspace name to use in suggested setup commands\n --project <project> Project name to use in suggested commands\n --goal <workflow> Natural-language workflow goal for intake/authoring-packet commands\n --sync-target <target> Runtime surface such as codex or claude for suggested commands\n --project-dir <path> Read organization state and project-local assets from another project directory\n --brief Print the current stage, current command, checkpoints, and near next steps only\n --json Print JSON to stdout\n\nBoundaries:\n - dna CLI/core/runtime owns product behavior and governance decisions\n - Claude Code and Codex are runtime surfaces/adapters\n - Dashboard is read-only projection\n - Obsidian/wiki is internal project memory, not product runtime\n - Web/public surface changes require Vercel CLI deploy + deployed URL verification\n`,
230
+ quickstart: `Usage: dna quickstart [asset] [--asset <name>] [--sync-target <target>] [--project-dir <path>] [--json]\n\nShows the shortest local route for getting value without Online or Supabase: choose a workflow asset, initialize local dna, preview sync, sync the harness, run in the harness, package/sign/verify local evidence, then inspect sync status.\n\nOptions:\n --asset <name> Workflow asset to start from (default prefers ${WORKFLOW_ASSET_IDS.default})\n --sync-target <target> Runtime surface such as codex or claude for suggested commands\n --project-dir <path> Read organization state and project-local assets from another project directory\n --json Print a concise intentdna.local_quickstart.v1 packet\n\nBoundaries:\n - quickstart is read-only guidance; it does not initialize, sync, run workflows, sign reports, upload reports, or deploy anything\n - local dna/dna-hook remain runtime truth\n - Online, marketplace, and Supabase do not execute workflows or make allow/warn/block/validate decisions\n - MCP remains hidden transport\n`,
80
231
  context: `Usage: dna context <index|search|doc> [query|id] [files...]\n\nSubcommands:\n index List explicitly declared planning-only advisory context sources\n search <query> Search source metadata\n doc <id> Read a local file/doc source body\n`,
81
- run: `Usage: dna run --dna <file> --workflow <name> --task <id> [options]\n\nOptions:\n --dry-run Print execution plan only\n --permission-mode <mode> Claude permission mode (default: default)\n`,
232
+ run: `Usage: dna run --dna <file> --workflow <name> --task <id> [options]\n\nOptions:\n --dry-run Print execution plan only\n --permission-mode <mode> Claude permission mode (default: default)\n --project-dir <path> Run and write project-scoped agents, IR, state, and logs in another project directory\n`,
82
233
  compile: `Usage: dna compile <files...> [--target claude-sdk] [--context <name>] [--output <path>] [--ir]\n`,
234
+ evolve: `Usage: dna evolve <dna-id> [--store-dir <path>] [--preview] [--apply]\n\nPreview self-evolution marker changes from recorded outcomes. This command is read-only; it never writes markers or runtime artifacts.\n\nOptions:\n --store-dir <path> Evolution store directory (default .dna/evolution)\n --preview Explicit preview flag; preview is the default behavior\n --apply Rejected in this kernel; use reviewed dna sync --evolve for mutation\n\nRoute:\n 1. Record outcomes: dna epigenetic record <dna-id> --action <action> --genes <gene[,gene]> --feedback '[{\"gene\":\"quality\",\"effect\":\"helped\"}]'\n 2. Inspect outcomes: dna epigenetic summary <dna-id>\n 3. Preview marker changes: dna evolve <dna-id>\n 4. Mutate only after review: dna sync --evolve\n\nBoundaries:\n - No outcomes means no evidence to evolve\n - dna evolve is preview-only and does not create missing outcome or marker directories\n - Marker mutation is allowed only through explicit reviewed sync/evolve gates\n`,
235
+ epigenetic: `Usage: dna epigenetic <record|summary|markers> <dna-id> [options]\n\nSubcommands:\n record Record an execution outcome for self-evolution\n summary Show outcome summary for a DNA id\n markers Show persisted epigenetic markers\n\nOptions:\n --store-dir <path> Evolution store directory (default .dna/evolution)\n --action <action> Action name for record\n --success Mark record outcome as success (default true)\n --genes <a,b> Active genes for record\n --feedback <json> Constraint feedback JSON array\n --json Print JSON for summary or markers\n\nExamples:\n dna epigenetic record template_flutter_rewrite --action fix-loop --genes quality --feedback '[{\"gene\":\"quality\",\"effect\":\"helped\"}]'\n dna epigenetic summary template_flutter_rewrite\n dna epigenetic markers template_flutter_rewrite\n`,
83
236
  validate: `Usage: dna validate <files...> [--quiet]\n`,
84
237
  show: `Usage: dna show <files...> [--context <name>] [--json]\n`,
85
- init: `Usage: dna init [--template <name>|--template list|--register <path>|--upgrade <name>]\n`,
238
+ init: `Usage: dna init [--template <name>|--template list|--register <path>|--upgrade <name>] [--project-dir <path>]\n`,
86
239
  };
87
240
  function commandHelp(command) {
88
241
  return command ? COMMAND_HELP[command] : undefined;
89
242
  }
243
+ function authConfigDirOption(values) {
244
+ return values["auth-config-dir"] ?? values["config-dir"];
245
+ }
246
+ function unsupportedGlobalOption(args) {
247
+ return args.find((arg) => arg === "--cwd" || arg.startsWith("--cwd="));
248
+ }
249
+ function waitForDrain(stream) {
250
+ if (!stream.writableNeedDrain)
251
+ return Promise.resolve();
252
+ return new Promise((resolveDrain) => stream.once("drain", resolveDrain));
253
+ }
254
+ async function exitWith(code) {
255
+ process.exitCode = code;
256
+ await Promise.all([waitForDrain(process.stdout), waitForDrain(process.stderr)]);
257
+ }
90
258
  async function main() {
91
259
  const args = process.argv.slice(2);
92
260
  const command = args[0];
@@ -94,23 +262,28 @@ async function main() {
94
262
  const help = helpText(version);
95
263
  if (command === "--version" || command === "-v") {
96
264
  process.stdout.write(`${version}\n`);
97
- process.exit(0);
265
+ return exitWith(0);
98
266
  }
99
267
  if (!command || command === "--help" || command === "-h") {
100
268
  process.stderr.write(help);
101
- process.exit(0);
269
+ return exitWith(0);
102
270
  }
103
271
  if (command === "help") {
104
272
  const commandSpecificHelp = commandHelp(args[1]);
105
273
  process.stderr.write(commandSpecificHelp ?? help);
106
- process.exit(0);
274
+ return exitWith(0);
107
275
  }
108
276
  // Parse remaining args (after command)
109
277
  const rest = args.slice(1);
278
+ const unsupportedOption = unsupportedGlobalOption(rest);
279
+ if (unsupportedOption) {
280
+ process.stderr.write(`Error: ${unsupportedOption} is not a supported dna option. Run dna from the target directory, or use --project-dir where the command supports it.\n`);
281
+ return exitWith(2);
282
+ }
110
283
  if (rest.includes("--help") || rest.includes("-h")) {
111
284
  const commandSpecificHelp = commandHelp(command);
112
285
  process.stderr.write(commandSpecificHelp ?? help);
113
- process.exit(commandSpecificHelp ? 0 : 2);
286
+ return exitWith(commandSpecificHelp ? 0 : 2);
114
287
  }
115
288
  switch (command) {
116
289
  case "sync": {
@@ -129,24 +302,39 @@ async function main() {
129
302
  "workflow-name": { type: "string" },
130
303
  skills: { type: "string" },
131
304
  settings: { type: "string" },
305
+ codex: { type: "boolean", default: false },
306
+ "codex-install-mode": { type: "string", default: "project_fallback" },
307
+ "codex-dogfood": { type: "boolean", default: false },
132
308
  lock: { type: "string", default: ".dna/lock" },
133
309
  remove: { type: "boolean", default: false },
134
310
  mode: { type: "string", default: "auto" },
135
311
  plugin: { type: "boolean" },
136
312
  "dry-run": { type: "boolean", default: false },
137
313
  "post-summary": { type: "boolean", default: false },
314
+ "project-dir": { type: "string" },
315
+ json: { type: "boolean", default: false },
138
316
  },
139
317
  allowPositionals: true,
140
318
  strict: false,
141
319
  });
320
+ const syncSubcommands = new Set(["status", "doctor", "remove"]);
321
+ const syncAction = syncSubcommands.has(positionals[0] ?? "")
322
+ ? positionals.shift()
323
+ : undefined;
142
324
  const mode = values.mode;
143
325
  if (!["auto", "plugin", "bin"].includes(mode)) {
144
326
  process.stderr.write(`Error: --mode must be one of: auto, plugin, bin\n`);
145
- process.exit(2);
327
+ return exitWith(2);
328
+ }
329
+ const codexInstallMode = values["codex-install-mode"];
330
+ if (!["plugin_scoped", "project_fallback", "managed", "none"].includes(codexInstallMode)) {
331
+ process.stderr.write(`Error: --codex-install-mode must be one of: plugin_scoped, project_fallback, managed, none\n`);
332
+ return exitWith(2);
146
333
  }
147
334
  const { runSync } = await import("./commands/sync.js");
148
335
  const code = await runSync({
149
336
  files: positionals,
337
+ action: syncAction === "remove" ? "remove-registry" : syncAction,
150
338
  target: values.target,
151
339
  inject: values.inject,
152
340
  context: values.context,
@@ -160,13 +348,18 @@ async function main() {
160
348
  skillsDir: values.skills,
161
349
  settingsPath: values.settings,
162
350
  lockFile: values.lock,
351
+ codex: values.codex,
352
+ codexInstallMode: codexInstallMode,
353
+ codexDogfood: values["codex-dogfood"],
163
354
  remove: values.remove,
164
355
  mode: mode,
165
356
  plugin: values.plugin,
166
357
  dryRun: values["dry-run"],
167
358
  postSummary: values["post-summary"],
359
+ projectDir: values["project-dir"],
360
+ json: values.json,
168
361
  });
169
- process.exit(code);
362
+ return exitWith(code);
170
363
  break;
171
364
  }
172
365
  case "verify": {
@@ -188,7 +381,7 @@ async function main() {
188
381
  health: verifyValues.health,
189
382
  strict: verifyValues.strict,
190
383
  });
191
- process.exit(code);
384
+ return exitWith(code);
192
385
  break;
193
386
  }
194
387
  case "run": {
@@ -206,6 +399,7 @@ async function main() {
206
399
  "permission-mode": { type: "string" },
207
400
  agents: { type: "string" },
208
401
  hooks: { type: "string" },
402
+ "project-dir": { type: "string" },
209
403
  },
210
404
  allowPositionals: true,
211
405
  strict: false,
@@ -234,8 +428,9 @@ async function main() {
234
428
  permissionMode: runValues["permission-mode"],
235
429
  agentsDir: runValues.agents,
236
430
  hooksDir: runValues.hooks,
431
+ projectDir: runValues["project-dir"],
237
432
  });
238
- process.exit(code);
433
+ return exitWith(code);
239
434
  break;
240
435
  }
241
436
  case "import": {
@@ -254,7 +449,7 @@ async function main() {
254
449
  output: importValues.output,
255
450
  format: importValues.format ?? "yaml",
256
451
  });
257
- process.exit(code);
452
+ return exitWith(code);
258
453
  break;
259
454
  }
260
455
  case "validate": {
@@ -271,7 +466,7 @@ async function main() {
271
466
  files: positionals,
272
467
  quiet: values.quiet,
273
468
  });
274
- process.exit(code);
469
+ return exitWith(code);
275
470
  break;
276
471
  }
277
472
  case "compile": {
@@ -294,7 +489,7 @@ async function main() {
294
489
  output: values.output,
295
490
  ir: values.ir,
296
491
  });
297
- process.exit(code);
492
+ return exitWith(code);
298
493
  break;
299
494
  }
300
495
  case "generate": {
@@ -313,7 +508,7 @@ async function main() {
313
508
  output: genValues.output,
314
509
  match: genValues.match,
315
510
  });
316
- process.exit(code);
511
+ return exitWith(code);
317
512
  break;
318
513
  }
319
514
  case "show": {
@@ -332,7 +527,7 @@ async function main() {
332
527
  context: values.context,
333
528
  json: values.json,
334
529
  });
335
- process.exit(code);
530
+ return exitWith(code);
336
531
  break;
337
532
  }
338
533
  case "init": {
@@ -345,6 +540,8 @@ async function main() {
345
540
  template: { type: "string" },
346
541
  register: { type: "string" },
347
542
  upgrade: { type: "string" },
543
+ "project-dir": { type: "string" },
544
+ json: { type: "boolean", default: false },
348
545
  },
349
546
  allowPositionals: true,
350
547
  strict: false,
@@ -357,8 +554,10 @@ async function main() {
357
554
  template: values.template,
358
555
  register: values.register,
359
556
  upgrade: values.upgrade,
557
+ projectDir: values["project-dir"],
558
+ json: values.json,
360
559
  });
361
- process.exit(code);
560
+ return exitWith(code);
362
561
  break;
363
562
  }
364
563
  case "evolve": {
@@ -379,7 +578,7 @@ async function main() {
379
578
  apply: values.apply,
380
579
  storeDir: values["store-dir"],
381
580
  });
382
- process.exit(code);
581
+ return exitWith(code);
383
582
  break;
384
583
  }
385
584
  case "epigenetic": {
@@ -410,7 +609,7 @@ async function main() {
410
609
  feedback: epiValues.feedback,
411
610
  json: epiValues.json,
412
611
  });
413
- process.exit(code);
612
+ return exitWith(code);
414
613
  break;
415
614
  }
416
615
  case "guard": {
@@ -427,14 +626,14 @@ async function main() {
427
626
  const guardLevel = guardValues.level;
428
627
  if (!["standard", "yolo", "strict"].includes(guardLevel)) {
429
628
  process.stderr.write(`Error: unknown level '${guardLevel}'. Available: standard, yolo, strict\n`);
430
- process.exit(2);
629
+ return exitWith(2);
431
630
  }
432
631
  const code = await runGuard({
433
632
  level: guardLevel,
434
633
  audit: guardValues.audit,
435
634
  remove: guardValues.remove,
436
635
  });
437
- process.exit(code);
636
+ return exitWith(code);
438
637
  break;
439
638
  }
440
639
  case "setup": {
@@ -450,7 +649,7 @@ async function main() {
450
649
  const setupScope = setupValues.scope;
451
650
  if (setupScope !== "user" && setupScope !== "project") {
452
651
  process.stderr.write(`Error: --scope must be 'user' or 'project', got '${setupScope}'\n`);
453
- process.exit(2);
652
+ return exitWith(2);
454
653
  }
455
654
  const { runSetup } = await import("./commands/setup.js");
456
655
  const code = await runSetup({
@@ -458,7 +657,7 @@ async function main() {
458
657
  yes: setupValues.yes,
459
658
  upgrade: setupValues.upgrade,
460
659
  });
461
- process.exit(code);
660
+ return exitWith(code);
462
661
  break;
463
662
  }
464
663
  case "context": {
@@ -477,7 +676,7 @@ async function main() {
477
676
  id: subcommand === "doc" ? positionals[0] : undefined,
478
677
  files: subcommand === "index" ? positionals : positionals.slice(1),
479
678
  });
480
- process.exit(code);
679
+ return exitWith(code);
481
680
  break;
482
681
  }
483
682
  case "feedback": {
@@ -500,35 +699,503 @@ async function main() {
500
699
  packageReport: fbValues.package,
501
700
  dnaId: fbValues["dna-id"],
502
701
  });
503
- process.exit(code);
702
+ return exitWith(code);
703
+ break;
704
+ }
705
+ case "report": {
706
+ const subcommand = rest[0] ?? "package";
707
+ if (subcommand !== "package" && subcommand !== "push" && subcommand !== "sign" && subcommand !== "verify" && subcommand !== "upload" && subcommand !== "receipts") {
708
+ process.stderr.write(COMMAND_HELP.report);
709
+ return exitWith(2);
710
+ }
711
+ const reportRest = rest.slice(1);
712
+ const { values: reportValues, positionals: reportPositionals } = parseArgs({
713
+ args: reportRest,
714
+ options: {
715
+ days: { type: "string", short: "d", default: "7" },
716
+ "session-id": { type: "string" },
717
+ "dna-id": { type: "string" },
718
+ "include-marker-preview": { type: "boolean", default: false },
719
+ "project-dir": { type: "string" },
720
+ package: { type: "string" },
721
+ output: { type: "string", short: "o" },
722
+ actor: { type: "string" },
723
+ visibility: { type: "string" },
724
+ "redaction-policy-version": { type: "string" },
725
+ endpoint: { type: "string" },
726
+ "auth-config-dir": { type: "string" },
727
+ "config-dir": { type: "string" },
728
+ "user-jwt": { type: "string" },
729
+ "organization-id": { type: "string" },
730
+ "project-id": { type: "string" },
731
+ status: { type: "string" },
732
+ limit: { type: "string" },
733
+ json: { type: "boolean", default: false },
734
+ "dry-run": { type: "boolean", default: false },
735
+ },
736
+ allowPositionals: true,
737
+ strict: false,
738
+ });
739
+ const visibility = reportValues.visibility;
740
+ if (visibility && !["runtime-local", "personal", "internal"].includes(visibility)) {
741
+ process.stderr.write("Error: --visibility must be one of: runtime-local, personal, internal\n");
742
+ return exitWith(2);
743
+ }
744
+ const receiptStatus = reportValues.status;
745
+ if (receiptStatus && !["verified", "pending", "rejected"].includes(receiptStatus)) {
746
+ process.stderr.write("Error: --status must be one of: verified, pending, rejected\n");
747
+ return exitWith(2);
748
+ }
749
+ const { runReport } = await import("./commands/report.js");
750
+ const code = await runReport({
751
+ action: subcommand,
752
+ projectDir: reportValues["project-dir"],
753
+ days: parseInt(reportValues.days, 10) || 7,
754
+ sessionId: reportValues["session-id"],
755
+ dnaId: reportValues["dna-id"],
756
+ includeMarkerPreview: reportValues["include-marker-preview"],
757
+ output: reportValues.output,
758
+ packagePath: reportValues.package,
759
+ envelopePath: reportPositionals[0],
760
+ actor: reportValues.actor,
761
+ visibility: visibility,
762
+ redactionPolicyVersion: reportValues["redaction-policy-version"],
763
+ endpoint: reportValues.endpoint,
764
+ configDir: authConfigDirOption(reportValues),
765
+ userJwt: reportValues["user-jwt"],
766
+ organizationId: reportValues["organization-id"],
767
+ projectId: reportValues["project-id"],
768
+ status: receiptStatus,
769
+ limit: reportValues.limit ? parseInt(reportValues.limit, 10) : undefined,
770
+ json: reportValues.json,
771
+ dryRun: reportValues["dry-run"],
772
+ });
773
+ return exitWith(code);
504
774
  break;
505
775
  }
506
776
  case "templates": {
507
777
  const subcommand = rest[0] ?? "list";
508
- const { runTemplatesDeploy, runTemplatesList, runTemplatesShow } = await import("./commands/templates.js");
778
+ const templateRest = rest.slice(1);
779
+ const { values: templateValues, positionals: templatePositionals } = parseArgs({
780
+ args: templateRest,
781
+ options: {
782
+ json: { type: "boolean", default: false },
783
+ "project-dir": { type: "string" },
784
+ "source-dir": { type: "string", multiple: true },
785
+ output: { type: "string", short: "o" },
786
+ focus: { type: "string", default: "all" },
787
+ candidate: { type: "boolean", default: false },
788
+ "save-template": { type: "string" },
789
+ org: { type: "string" },
790
+ project: { type: "string" },
791
+ template: { type: "string" },
792
+ "publication-id": { type: "string" },
793
+ reason: { type: "string" },
794
+ receipt: { type: "string" },
795
+ endpoint: { type: "string" },
796
+ "auth-config-dir": { type: "string" },
797
+ "config-dir": { type: "string" },
798
+ "dry-run": { type: "boolean", default: false },
799
+ },
800
+ allowPositionals: true,
801
+ strict: false,
802
+ });
803
+ const { runTemplatesDeploy, runTemplatesList, runTemplatesManage, runTemplatesMarketplace, runTemplatesPublications, runTemplatesPublish, runTemplatesRevoke, runTemplatesShow, runTemplatesSources } = await import("./commands/templates.js");
509
804
  if (subcommand === "list") {
510
- const code = await runTemplatesList();
511
- process.exit(code);
805
+ const code = await runTemplatesList({ projectDir: templateValues["project-dir"] });
806
+ return exitWith(code);
807
+ }
808
+ if (subcommand === "marketplace") {
809
+ const code = await runTemplatesMarketplace({
810
+ projectDir: templateValues["project-dir"],
811
+ output: templateValues.output,
812
+ json: templateValues.json,
813
+ });
814
+ return exitWith(code);
815
+ }
816
+ if (subcommand === "manage") {
817
+ const code = await runTemplatesManage({
818
+ name: templatePositionals[0],
819
+ projectDir: templateValues["project-dir"],
820
+ json: templateValues.json,
821
+ });
822
+ return exitWith(code);
823
+ }
824
+ if (subcommand === "sources") {
825
+ const focus = templateValues.focus;
826
+ if (!["all", "refresh", "gaps"].includes(focus)) {
827
+ process.stderr.write("Error: --focus must be one of: all, refresh, gaps\n");
828
+ return exitWith(2);
829
+ }
830
+ const code = await runTemplatesSources({
831
+ sourceId: templatePositionals[0],
832
+ projectDir: templateValues["project-dir"],
833
+ sourceDirs: templateValues["source-dir"],
834
+ focus: focus,
835
+ candidate: templateValues.candidate,
836
+ saveTemplate: templateValues["save-template"],
837
+ json: templateValues.json,
838
+ });
839
+ return exitWith(code);
512
840
  }
513
841
  if (subcommand === "show") {
514
- const code = await runTemplatesShow({ name: rest[1] ?? "" });
515
- process.exit(code);
842
+ const code = await runTemplatesShow({
843
+ name: templatePositionals[0] ?? "",
844
+ projectDir: templateValues["project-dir"],
845
+ json: templateValues.json,
846
+ });
847
+ return exitWith(code);
848
+ }
849
+ if (subcommand === "publish") {
850
+ const code = await runTemplatesPublish({
851
+ org: templateValues.org,
852
+ project: templateValues.project,
853
+ template: templateValues.template,
854
+ receipt: templateValues.receipt,
855
+ endpoint: templateValues.endpoint,
856
+ projectDir: templateValues["project-dir"],
857
+ configDir: authConfigDirOption(templateValues),
858
+ dryRun: templateValues["dry-run"],
859
+ json: templateValues.json,
860
+ });
861
+ return exitWith(code);
862
+ }
863
+ if (subcommand === "publications") {
864
+ const code = await runTemplatesPublications({
865
+ org: templateValues.org,
866
+ project: templateValues.project,
867
+ template: templateValues.template,
868
+ endpoint: templateValues.endpoint,
869
+ projectDir: templateValues["project-dir"],
870
+ configDir: authConfigDirOption(templateValues),
871
+ dryRun: templateValues["dry-run"],
872
+ json: templateValues.json,
873
+ });
874
+ return exitWith(code);
875
+ }
876
+ if (subcommand === "revoke") {
877
+ const code = await runTemplatesRevoke({
878
+ org: templateValues.org,
879
+ project: templateValues.project,
880
+ publicationId: templateValues["publication-id"],
881
+ reason: templateValues.reason,
882
+ endpoint: templateValues.endpoint,
883
+ projectDir: templateValues["project-dir"],
884
+ configDir: authConfigDirOption(templateValues),
885
+ dryRun: templateValues["dry-run"],
886
+ json: templateValues.json,
887
+ });
888
+ return exitWith(code);
516
889
  }
517
890
  if (subcommand === "deploy") {
518
891
  const code = await runTemplatesDeploy();
519
- process.exit(code);
892
+ return exitWith(code);
520
893
  }
521
894
  process.stderr.write(COMMAND_HELP.templates);
522
- process.exit(2);
895
+ return exitWith(2);
896
+ break;
897
+ }
898
+ case "assets": {
899
+ const subcommand = rest[0] ?? "list";
900
+ const assetRest = rest.slice(1);
901
+ const { values: assetValues, positionals: assetPositionals } = parseArgs({
902
+ args: assetRest,
903
+ options: {
904
+ evidence: { type: "boolean", default: false },
905
+ "project-dir": { type: "string" },
906
+ json: { type: "boolean", default: false },
907
+ },
908
+ allowPositionals: true,
909
+ strict: false,
910
+ });
911
+ const { runAssets } = await import("./commands/assets.js");
912
+ const code = await runAssets({
913
+ subcommand,
914
+ name: assetPositionals[0],
915
+ compareTo: assetPositionals[1],
916
+ evidence: assetValues.evidence,
917
+ projectDir: assetValues["project-dir"],
918
+ json: assetValues.json,
919
+ });
920
+ return exitWith(code);
921
+ break;
922
+ }
923
+ case "workflow": {
924
+ const subcommand = rest[0] ?? "draft";
925
+ const workflowRest = rest.slice(1);
926
+ const { values: workflowValues, positionals: workflowPositionals } = parseArgs({
927
+ args: workflowRest,
928
+ options: {
929
+ example: { type: "string", default: "rewrite_governance" },
930
+ strictness: { type: "string", default: "standard" },
931
+ operation: { type: "string" },
932
+ "target-step": { type: "string" },
933
+ role: { type: "string" },
934
+ suggestion: { type: "string" },
935
+ decision: { type: "string" },
936
+ workflow: { type: "string" },
937
+ "from-template": { type: "string" },
938
+ "save-template": { type: "string" },
939
+ name: { type: "string" },
940
+ project: { type: "string" },
941
+ "sync-target": { type: "string" },
942
+ "project-dir": { type: "string" },
943
+ force: { type: "boolean", default: false },
944
+ org: { type: "boolean", default: false },
945
+ json: { type: "boolean", default: false },
946
+ yaml: { type: "boolean", default: false },
947
+ },
948
+ allowPositionals: true,
949
+ strict: false,
950
+ });
951
+ const { runWorkflow } = await import("./commands/workflow.js");
952
+ const code = await runWorkflow({
953
+ subcommand,
954
+ goal: workflowPositionals.length > 0 ? workflowPositionals.join(" ") : undefined,
955
+ example: workflowValues.example,
956
+ strictness: workflowValues.strictness,
957
+ operation: workflowValues.operation,
958
+ targetStep: workflowValues["target-step"],
959
+ role: workflowValues.role,
960
+ suggestion: workflowValues.suggestion,
961
+ decision: workflowValues.decision,
962
+ workflow: workflowValues.workflow,
963
+ fromTemplate: workflowValues["from-template"],
964
+ saveTemplate: workflowValues["save-template"],
965
+ name: workflowValues.name,
966
+ project: workflowValues.project,
967
+ syncTarget: workflowValues["sync-target"],
968
+ projectDir: workflowValues["project-dir"],
969
+ force: workflowValues.force,
970
+ org: workflowValues.org,
971
+ json: workflowValues.json,
972
+ yaml: workflowValues.yaml,
973
+ });
974
+ return exitWith(code);
975
+ break;
976
+ }
977
+ case "org": {
978
+ const subcommand = rest[0] ?? "status";
979
+ const orgRest = rest.slice(1);
980
+ const { values: orgValues, positionals: orgPositionals } = parseArgs({
981
+ args: orgRest,
982
+ options: {
983
+ name: { type: "string" },
984
+ project: { type: "string" },
985
+ asset: { type: "string" },
986
+ status: { type: "string" },
987
+ "sync-target": { type: "string" },
988
+ "project-dir": { type: "string" },
989
+ apply: { type: "boolean", default: false },
990
+ json: { type: "boolean", default: false },
991
+ },
992
+ allowPositionals: true,
993
+ strict: false,
994
+ });
995
+ const { runOrg } = await import("./commands/org.js");
996
+ const code = await runOrg({
997
+ subcommand,
998
+ description: orgPositionals.join(" "),
999
+ name: orgValues.name,
1000
+ project: orgValues.project,
1001
+ asset: orgValues.asset,
1002
+ status: orgValues.status,
1003
+ syncTarget: orgValues["sync-target"],
1004
+ projectDir: orgValues["project-dir"],
1005
+ apply: orgValues.apply,
1006
+ json: orgValues.json,
1007
+ });
1008
+ return exitWith(code);
1009
+ break;
1010
+ }
1011
+ case "quickstart":
1012
+ case "guide": {
1013
+ const { values: guideValues, positionals: guidePositionals } = parseArgs({
1014
+ args: rest,
1015
+ options: {
1016
+ asset: { type: "string" },
1017
+ name: { type: "string" },
1018
+ project: { type: "string" },
1019
+ goal: { type: "string" },
1020
+ "sync-target": { type: "string" },
1021
+ "project-dir": { type: "string" },
1022
+ brief: { type: "boolean", default: false },
1023
+ json: { type: "boolean", default: false },
1024
+ },
1025
+ allowPositionals: true,
1026
+ strict: false,
1027
+ });
1028
+ const { runGuide } = await import("./commands/guide.js");
1029
+ const code = await runGuide({
1030
+ asset: guideValues.asset ?? guidePositionals[0],
1031
+ name: guideValues.name,
1032
+ project: guideValues.project,
1033
+ goal: guideValues.goal,
1034
+ syncTarget: guideValues["sync-target"],
1035
+ projectDir: guideValues["project-dir"],
1036
+ brief: command === "quickstart" ? true : guideValues.brief,
1037
+ json: guideValues.json,
1038
+ quickstart: command === "quickstart",
1039
+ });
1040
+ return exitWith(code);
1041
+ break;
1042
+ }
1043
+ case "release": {
1044
+ const subcommand = rest[0] ?? "deploy-plan";
1045
+ const releaseRest = rest.slice(1);
1046
+ const { values: releaseValues, positionals: releasePositionals } = parseArgs({
1047
+ args: releaseRest,
1048
+ options: {
1049
+ json: { type: "boolean", default: false },
1050
+ output: { type: "string", short: "o" },
1051
+ "deployment-url": { type: "string" },
1052
+ "checked-route": { type: "string", multiple: true },
1053
+ "checked-cloud-check": { type: "string", multiple: true },
1054
+ "dry-run": { type: "boolean", default: false },
1055
+ },
1056
+ allowPositionals: true,
1057
+ strict: false,
1058
+ });
1059
+ const { runRelease } = await import("./commands/release.js");
1060
+ const code = await runRelease({
1061
+ subcommand,
1062
+ files: releasePositionals,
1063
+ json: releaseValues.json,
1064
+ output: releaseValues.output,
1065
+ deploymentUrl: releaseValues["deployment-url"],
1066
+ checkedRoute: releaseValues["checked-route"],
1067
+ checkedCloudCheck: releaseValues["checked-cloud-check"],
1068
+ dryRun: releaseValues["dry-run"],
1069
+ });
1070
+ return exitWith(code);
1071
+ break;
1072
+ }
1073
+ case "cloud": {
1074
+ const subcommand = rest[0] ?? "status";
1075
+ const cloudRest = rest.slice(1);
1076
+ const { values: cloudValues } = parseArgs({
1077
+ args: cloudRest,
1078
+ options: {
1079
+ "admin-user-id": { type: "string" },
1080
+ "admin-email": { type: "string" },
1081
+ org: { type: "string" },
1082
+ project: { type: "string" },
1083
+ "project-hint": { type: "string" },
1084
+ "token-name": { type: "string" },
1085
+ "token-pepper": { type: "string" },
1086
+ "expires-at": { type: "string" },
1087
+ template: { type: "string" },
1088
+ receipt: { type: "string" },
1089
+ "secrets-check": { type: "string" },
1090
+ "vercel-env-check": { type: "string" },
1091
+ endpoint: { type: "string" },
1092
+ "auth-config-dir": { type: "string" },
1093
+ "config-dir": { type: "string" },
1094
+ "deployment-url": { type: "string" },
1095
+ output: { type: "string", short: "o" },
1096
+ "dry-run": { type: "boolean", default: false },
1097
+ yes: { type: "boolean", default: false },
1098
+ json: { type: "boolean", default: false },
1099
+ },
1100
+ allowPositionals: true,
1101
+ strict: false,
1102
+ });
1103
+ const { runCloud } = await import("./commands/cloud.js");
1104
+ const code = await runCloud({
1105
+ subcommand,
1106
+ json: cloudValues.json,
1107
+ adminUserId: cloudValues["admin-user-id"],
1108
+ adminEmail: cloudValues["admin-email"],
1109
+ orgName: cloudValues.org,
1110
+ projectName: cloudValues.project,
1111
+ projectHint: cloudValues["project-hint"],
1112
+ tokenName: cloudValues["token-name"],
1113
+ tokenPepper: cloudValues["token-pepper"],
1114
+ expiresAt: cloudValues["expires-at"],
1115
+ templateName: cloudValues.template,
1116
+ receiptPath: cloudValues.receipt,
1117
+ secretsCheckPath: cloudValues["secrets-check"],
1118
+ vercelEnvCheckPath: cloudValues["vercel-env-check"],
1119
+ endpoint: cloudValues.endpoint,
1120
+ configDir: authConfigDirOption(cloudValues),
1121
+ deploymentUrl: cloudValues["deployment-url"],
1122
+ output: cloudValues.output,
1123
+ dryRun: cloudValues["dry-run"],
1124
+ yes: cloudValues.yes,
1125
+ });
1126
+ return exitWith(code);
1127
+ break;
1128
+ }
1129
+ case "auth": {
1130
+ const subcommand = rest[0] ?? "status";
1131
+ const hasTokenAction = subcommand === "token" || subcommand === "tokens";
1132
+ const hasUserJwtAction = subcommand === "user-jwt";
1133
+ const authRest = hasTokenAction || hasUserJwtAction ? rest.slice(2) : rest.slice(1);
1134
+ const tokenAction = hasTokenAction ? rest[1] : undefined;
1135
+ const userJwtAction = hasUserJwtAction ? rest[1] : undefined;
1136
+ const { values: authValues, positionals: authPositionals } = parseArgs({
1137
+ args: authRest,
1138
+ options: {
1139
+ "user-jwt": { type: "string" },
1140
+ endpoint: { type: "string" },
1141
+ org: { type: "string" },
1142
+ project: { type: "string" },
1143
+ "org-slug": { type: "string" },
1144
+ "project-slug": { type: "string" },
1145
+ "project-hint": { type: "string" },
1146
+ "project-id": { type: "string" },
1147
+ "organization-id": { type: "string" },
1148
+ "token-id": { type: "string" },
1149
+ "token-name": { type: "string" },
1150
+ scope: { type: "string", multiple: true },
1151
+ "expires-at": { type: "string" },
1152
+ "include-revoked": { type: "boolean", default: false },
1153
+ limit: { type: "string" },
1154
+ "auth-config-dir": { type: "string" },
1155
+ "config-dir": { type: "string" },
1156
+ "dry-run": { type: "boolean", default: false },
1157
+ yes: { type: "boolean", default: false },
1158
+ json: { type: "boolean", default: false },
1159
+ },
1160
+ allowPositionals: true,
1161
+ strict: false,
1162
+ });
1163
+ const { runAuth } = await import("./commands/auth.js");
1164
+ const code = await runAuth({
1165
+ subcommand,
1166
+ tokenAction,
1167
+ userJwtAction,
1168
+ token: authPositionals[0],
1169
+ tokenId: authValues["token-id"] ?? (subcommand === "tokens" ? authPositionals[0] : undefined),
1170
+ userJwt: authValues["user-jwt"] ?? (subcommand === "user-jwt" ? authPositionals[0] : undefined),
1171
+ endpoint: authValues.endpoint,
1172
+ orgName: authValues.org,
1173
+ projectName: authValues.project,
1174
+ orgSlug: authValues["org-slug"],
1175
+ projectSlug: authValues["project-slug"],
1176
+ projectHint: authValues["project-hint"],
1177
+ projectId: authValues["project-id"],
1178
+ organizationId: authValues["organization-id"],
1179
+ tokenName: authValues["token-name"],
1180
+ scopes: authValues.scope,
1181
+ expiresAt: authValues["expires-at"],
1182
+ includeRevoked: authValues["include-revoked"],
1183
+ limit: authValues.limit ? Number(authValues.limit) : undefined,
1184
+ configDir: authConfigDirOption(authValues),
1185
+ dryRun: authValues["dry-run"],
1186
+ yes: authValues.yes,
1187
+ json: authValues.json,
1188
+ });
1189
+ return exitWith(code);
523
1190
  break;
524
1191
  }
525
1192
  default:
526
1193
  process.stderr.write(`Unknown command: ${command}\n\n`);
527
1194
  process.stderr.write(help);
528
- process.exit(2);
1195
+ return exitWith(2);
529
1196
  }
530
1197
  }
531
1198
  main().catch((err) => {
532
1199
  process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}\n`);
533
- process.exit(1);
1200
+ return exitWith(1);
534
1201
  });