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
package/dist/cli/index.js CHANGED
@@ -12,7 +12,11 @@
12
12
  * help Show this help message
13
13
  */
14
14
  import { parseArgs } from "node:util";
15
- const HELP = `Intent DNA CLI v1.7.0
15
+ import { getPackageVersion } from "./util/version.js";
16
+ import { WORKFLOW_ASSET_IDS } from "../templates/metadata.js";
17
+ const fallbackVersion = "unknown";
18
+ function helpText(version) {
19
+ return `Intent DNA CLI v${version}
16
20
 
17
21
  Usage: dna <command> [options]
18
22
 
@@ -30,8 +34,17 @@ Commands:
30
34
  evolve Preview epigenetic marker changes from persisted outcomes
31
35
  epigenetic Record outcomes, view markers and summaries
32
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
33
38
  context Inspect planning-only advisory context sources
34
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
35
48
 
36
49
  Options:
37
50
  --help, -h Show help for a command
@@ -42,11 +55,72 @@ Examples:
42
55
  dna guard --level strict Enterprise-grade guardrails
43
56
  dna guard --audit Show last 7 days of violation logs
44
57
  dna guard --remove Remove all guardrails
45
- dna init --template flutter-rewrite Create DNA config from template
58
+ dna init --template ${WORKFLOW_ASSET_IDS.default} Create DNA config from template
46
59
  dna init --template list List all available templates with namespaces
47
60
  dna init --register my.dna.yaml Register a custom template (checks namespace uniqueness)
48
61
  dna generate "Flutter app with behavior locking" Generate config prompt with schema spec
49
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
50
124
  dna sync Auto-detect .dna/config.yaml + environment, sync all
51
125
  dna sync .dna/config.yaml --target claude-md --inject CLAUDE.md --context work
52
126
  dna sync my.dna.json --target claude-md --inject CLAUDE.md --hooks .claude/hooks
@@ -69,38 +143,147 @@ Examples:
69
143
  dna evolve my_dna_id Preview marker changes without persisting
70
144
  dna evolve my_dna_id --apply Unsupported in this kernel; use sync --evolve for explicit mutation
71
145
  `;
146
+ }
72
147
  const COMMAND_HELP = {
73
- 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`,
74
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`,
75
- 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`,
76
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`,
77
- 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`,
78
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`,
79
236
  validate: `Usage: dna validate <files...> [--quiet]\n`,
80
237
  show: `Usage: dna show <files...> [--context <name>] [--json]\n`,
81
- 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`,
82
239
  };
83
240
  function commandHelp(command) {
84
241
  return command ? COMMAND_HELP[command] : undefined;
85
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
+ }
86
258
  async function main() {
87
259
  const args = process.argv.slice(2);
88
260
  const command = args[0];
261
+ const version = await getPackageVersion() ?? fallbackVersion;
262
+ const help = helpText(version);
263
+ if (command === "--version" || command === "-v") {
264
+ process.stdout.write(`${version}\n`);
265
+ return exitWith(0);
266
+ }
89
267
  if (!command || command === "--help" || command === "-h") {
90
- process.stderr.write(HELP);
91
- process.exit(0);
268
+ process.stderr.write(help);
269
+ return exitWith(0);
92
270
  }
93
271
  if (command === "help") {
94
- const help = commandHelp(args[1]);
95
- process.stderr.write(help ?? HELP);
96
- process.exit(0);
272
+ const commandSpecificHelp = commandHelp(args[1]);
273
+ process.stderr.write(commandSpecificHelp ?? help);
274
+ return exitWith(0);
97
275
  }
98
276
  // Parse remaining args (after command)
99
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
+ }
100
283
  if (rest.includes("--help") || rest.includes("-h")) {
101
- const help = commandHelp(command);
102
- process.stderr.write(help ?? HELP);
103
- process.exit(help ? 0 : 2);
284
+ const commandSpecificHelp = commandHelp(command);
285
+ process.stderr.write(commandSpecificHelp ?? help);
286
+ return exitWith(commandSpecificHelp ? 0 : 2);
104
287
  }
105
288
  switch (command) {
106
289
  case "sync": {
@@ -119,24 +302,39 @@ async function main() {
119
302
  "workflow-name": { type: "string" },
120
303
  skills: { type: "string" },
121
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 },
122
308
  lock: { type: "string", default: ".dna/lock" },
123
309
  remove: { type: "boolean", default: false },
124
310
  mode: { type: "string", default: "auto" },
125
311
  plugin: { type: "boolean" },
126
312
  "dry-run": { type: "boolean", default: false },
127
313
  "post-summary": { type: "boolean", default: false },
314
+ "project-dir": { type: "string" },
315
+ json: { type: "boolean", default: false },
128
316
  },
129
317
  allowPositionals: true,
130
318
  strict: false,
131
319
  });
320
+ const syncSubcommands = new Set(["status", "doctor", "remove"]);
321
+ const syncAction = syncSubcommands.has(positionals[0] ?? "")
322
+ ? positionals.shift()
323
+ : undefined;
132
324
  const mode = values.mode;
133
325
  if (!["auto", "plugin", "bin"].includes(mode)) {
134
326
  process.stderr.write(`Error: --mode must be one of: auto, plugin, bin\n`);
135
- 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);
136
333
  }
137
334
  const { runSync } = await import("./commands/sync.js");
138
335
  const code = await runSync({
139
336
  files: positionals,
337
+ action: syncAction === "remove" ? "remove-registry" : syncAction,
140
338
  target: values.target,
141
339
  inject: values.inject,
142
340
  context: values.context,
@@ -150,13 +348,18 @@ async function main() {
150
348
  skillsDir: values.skills,
151
349
  settingsPath: values.settings,
152
350
  lockFile: values.lock,
351
+ codex: values.codex,
352
+ codexInstallMode: codexInstallMode,
353
+ codexDogfood: values["codex-dogfood"],
153
354
  remove: values.remove,
154
355
  mode: mode,
155
356
  plugin: values.plugin,
156
357
  dryRun: values["dry-run"],
157
358
  postSummary: values["post-summary"],
359
+ projectDir: values["project-dir"],
360
+ json: values.json,
158
361
  });
159
- process.exit(code);
362
+ return exitWith(code);
160
363
  break;
161
364
  }
162
365
  case "verify": {
@@ -178,7 +381,7 @@ async function main() {
178
381
  health: verifyValues.health,
179
382
  strict: verifyValues.strict,
180
383
  });
181
- process.exit(code);
384
+ return exitWith(code);
182
385
  break;
183
386
  }
184
387
  case "run": {
@@ -196,6 +399,7 @@ async function main() {
196
399
  "permission-mode": { type: "string" },
197
400
  agents: { type: "string" },
198
401
  hooks: { type: "string" },
402
+ "project-dir": { type: "string" },
199
403
  },
200
404
  allowPositionals: true,
201
405
  strict: false,
@@ -224,8 +428,9 @@ async function main() {
224
428
  permissionMode: runValues["permission-mode"],
225
429
  agentsDir: runValues.agents,
226
430
  hooksDir: runValues.hooks,
431
+ projectDir: runValues["project-dir"],
227
432
  });
228
- process.exit(code);
433
+ return exitWith(code);
229
434
  break;
230
435
  }
231
436
  case "import": {
@@ -244,7 +449,7 @@ async function main() {
244
449
  output: importValues.output,
245
450
  format: importValues.format ?? "yaml",
246
451
  });
247
- process.exit(code);
452
+ return exitWith(code);
248
453
  break;
249
454
  }
250
455
  case "validate": {
@@ -261,7 +466,7 @@ async function main() {
261
466
  files: positionals,
262
467
  quiet: values.quiet,
263
468
  });
264
- process.exit(code);
469
+ return exitWith(code);
265
470
  break;
266
471
  }
267
472
  case "compile": {
@@ -284,7 +489,7 @@ async function main() {
284
489
  output: values.output,
285
490
  ir: values.ir,
286
491
  });
287
- process.exit(code);
492
+ return exitWith(code);
288
493
  break;
289
494
  }
290
495
  case "generate": {
@@ -303,7 +508,7 @@ async function main() {
303
508
  output: genValues.output,
304
509
  match: genValues.match,
305
510
  });
306
- process.exit(code);
511
+ return exitWith(code);
307
512
  break;
308
513
  }
309
514
  case "show": {
@@ -322,7 +527,7 @@ async function main() {
322
527
  context: values.context,
323
528
  json: values.json,
324
529
  });
325
- process.exit(code);
530
+ return exitWith(code);
326
531
  break;
327
532
  }
328
533
  case "init": {
@@ -335,6 +540,8 @@ async function main() {
335
540
  template: { type: "string" },
336
541
  register: { type: "string" },
337
542
  upgrade: { type: "string" },
543
+ "project-dir": { type: "string" },
544
+ json: { type: "boolean", default: false },
338
545
  },
339
546
  allowPositionals: true,
340
547
  strict: false,
@@ -347,8 +554,10 @@ async function main() {
347
554
  template: values.template,
348
555
  register: values.register,
349
556
  upgrade: values.upgrade,
557
+ projectDir: values["project-dir"],
558
+ json: values.json,
350
559
  });
351
- process.exit(code);
560
+ return exitWith(code);
352
561
  break;
353
562
  }
354
563
  case "evolve": {
@@ -369,7 +578,7 @@ async function main() {
369
578
  apply: values.apply,
370
579
  storeDir: values["store-dir"],
371
580
  });
372
- process.exit(code);
581
+ return exitWith(code);
373
582
  break;
374
583
  }
375
584
  case "epigenetic": {
@@ -400,7 +609,7 @@ async function main() {
400
609
  feedback: epiValues.feedback,
401
610
  json: epiValues.json,
402
611
  });
403
- process.exit(code);
612
+ return exitWith(code);
404
613
  break;
405
614
  }
406
615
  case "guard": {
@@ -417,14 +626,14 @@ async function main() {
417
626
  const guardLevel = guardValues.level;
418
627
  if (!["standard", "yolo", "strict"].includes(guardLevel)) {
419
628
  process.stderr.write(`Error: unknown level '${guardLevel}'. Available: standard, yolo, strict\n`);
420
- process.exit(2);
629
+ return exitWith(2);
421
630
  }
422
631
  const code = await runGuard({
423
632
  level: guardLevel,
424
633
  audit: guardValues.audit,
425
634
  remove: guardValues.remove,
426
635
  });
427
- process.exit(code);
636
+ return exitWith(code);
428
637
  break;
429
638
  }
430
639
  case "setup": {
@@ -440,7 +649,7 @@ async function main() {
440
649
  const setupScope = setupValues.scope;
441
650
  if (setupScope !== "user" && setupScope !== "project") {
442
651
  process.stderr.write(`Error: --scope must be 'user' or 'project', got '${setupScope}'\n`);
443
- process.exit(2);
652
+ return exitWith(2);
444
653
  }
445
654
  const { runSetup } = await import("./commands/setup.js");
446
655
  const code = await runSetup({
@@ -448,7 +657,7 @@ async function main() {
448
657
  yes: setupValues.yes,
449
658
  upgrade: setupValues.upgrade,
450
659
  });
451
- process.exit(code);
660
+ return exitWith(code);
452
661
  break;
453
662
  }
454
663
  case "context": {
@@ -467,7 +676,7 @@ async function main() {
467
676
  id: subcommand === "doc" ? positionals[0] : undefined,
468
677
  files: subcommand === "index" ? positionals : positionals.slice(1),
469
678
  });
470
- process.exit(code);
679
+ return exitWith(code);
471
680
  break;
472
681
  }
473
682
  case "feedback": {
@@ -490,35 +699,503 @@ async function main() {
490
699
  packageReport: fbValues.package,
491
700
  dnaId: fbValues["dna-id"],
492
701
  });
493
- 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);
494
774
  break;
495
775
  }
496
776
  case "templates": {
497
777
  const subcommand = rest[0] ?? "list";
498
- 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");
499
804
  if (subcommand === "list") {
500
- const code = await runTemplatesList();
501
- 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);
502
840
  }
503
841
  if (subcommand === "show") {
504
- const code = await runTemplatesShow({ name: rest[1] ?? "" });
505
- 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);
506
889
  }
507
890
  if (subcommand === "deploy") {
508
891
  const code = await runTemplatesDeploy();
509
- process.exit(code);
892
+ return exitWith(code);
510
893
  }
511
894
  process.stderr.write(COMMAND_HELP.templates);
512
- 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);
513
1190
  break;
514
1191
  }
515
1192
  default:
516
1193
  process.stderr.write(`Unknown command: ${command}\n\n`);
517
- process.stderr.write(HELP);
518
- process.exit(2);
1194
+ process.stderr.write(help);
1195
+ return exitWith(2);
519
1196
  }
520
1197
  }
521
1198
  main().catch((err) => {
522
1199
  process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}\n`);
523
- process.exit(1);
1200
+ return exitWith(1);
524
1201
  });