simt-dev 0.6.2 → 0.7.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 (170) hide show
  1. package/CHANGELOG.md +83 -1
  2. package/README.md +46 -17
  3. package/agents/simt-agent.md +84 -0
  4. package/bin/simt.mjs +19 -6
  5. package/docs/decisions/ADR-009-skill-layout.md +1 -1
  6. package/docs/decisions/ADR-086-the-stable-prefix-comes-first-and-the-lock-records-both-digests.md +1 -1
  7. package/docs/decisions/ADR-100-a-staged-diff-is-the-last-gate-before-history-and-it-runs-inside-the-tool.md +94 -0
  8. package/docs/decisions/ADR-101-a-file-lease-belongs-to-one-session-and-the-pre-edit-hook-refuses-another.md +95 -0
  9. package/docs/decisions/ADR-102-the-two-queued-review-rows-are-closed-by-ruling.md +49 -0
  10. package/docs/decisions/ADR-103-co-projected-duplicates-merge-down.md +74 -0
  11. package/docs/decisions/ADR-104-the-pre-tool-use-policy-reads-the-command-the-way-a-shell-reads-it.md +76 -0
  12. package/docs/decisions/ADR-105-the-json-ceiling-shrinks-arrays-and-never-cuts-bytes.md +44 -0
  13. package/docs/decisions/ADR-106-the-harness-hook-runs-through-a-repo-shim.md +46 -0
  14. package/docs/decisions/ADR-107-an-install-can-name-one-harness-and-the-skipped-ones-are-named.md +51 -0
  15. package/docs/decisions/ADR-108-an-adoption-builds-the-index-and-a-command-refreshes-it-on-read.md +59 -0
  16. package/docs/decisions/ADR-109-simt-dev-is-its-own-consumer-and-the-guards-that-kept-it-from-being-one-are-retired.md +47 -0
  17. package/docs/decisions/ADR-110-the-lock-file-follows-the-manifest-name-and-the-old-name-is-read-until-the-next-write.md +43 -0
  18. package/docs/decisions/ADR-111-the-tool-ships-one-agent-rendered-per-harness-and-installs-it-with-init-and-a-command.md +75 -0
  19. package/docs/decisions/ADR-112-the-registry-is-what-simt-dev-ships-and-a-repo-owns-its-own-skills.md +81 -0
  20. package/docs/decisions/ADR-113-a-pre-push-that-carries-only-documentation-skips-the-test-gate-and-says-so.md +87 -0
  21. package/docs/decisions/ADR-114-the-bench-pairs-at-the-task-level-a-missing-cost-is-not-zero-and-an-unasked-cross-group-compare-is-refused.md +74 -0
  22. package/docs/decisions/ADR-115-the-index-stamps-its-schema-version-migrates-older-databases-in-place-and-serves-newer-ones-from-a-sidecar.md +69 -0
  23. package/docs/decisions/ADR-116-rust-support-reaches-the-example-path-the-indent-and-the-bench-runner.md +100 -0
  24. package/docs/decisions/README.md +53 -0
  25. package/package.json +4 -2
  26. package/rules/core.md +2 -2
  27. package/rules/mdc/preview-postflight.mdc +5 -6
  28. package/rules/mdc/test-gate.mdc +2 -0
  29. package/rules/stacks/android.md +10 -11
  30. package/rules/stacks/cloudflare-workers.md +1 -1
  31. package/rules/stacks/connectiq.md +2 -2
  32. package/rules/stacks/container.md +2 -0
  33. package/rules/stacks/dart.md +1 -1
  34. package/rules/stacks/deno.md +1 -1
  35. package/rules/stacks/dotnet.md +1 -1
  36. package/rules/stacks/elixir.md +1 -1
  37. package/rules/stacks/go.md +1 -1
  38. package/rules/stacks/jvm.md +4 -3
  39. package/rules/stacks/node.md +2 -2
  40. package/rules/stacks/python.md +7 -6
  41. package/rules/stacks/react-native.md +3 -5
  42. package/rules/stacks/react-web.md +9 -9
  43. package/rules/stacks/ruby.md +1 -1
  44. package/rules/stacks/rust.md +1 -1
  45. package/rules/stacks/swift.md +1 -1
  46. package/rules/stacks/typescript.md +2 -2
  47. package/rules/stacks/uv.md +3 -2
  48. package/skills/simt-commands/SKILL.md +70 -0
  49. package/src/advice/advice.mjs +7 -3
  50. package/src/agenthooks/decide.mjs +238 -15
  51. package/src/agenthooks/opencode.mjs +72 -0
  52. package/src/agenthooks/policy.mjs +81 -5
  53. package/src/agenthooks/prompt.mjs +6 -2
  54. package/src/agenthooks/render.mjs +186 -19
  55. package/src/agenthooks/shell.mjs +523 -0
  56. package/src/agenthooks/shim.mjs +55 -0
  57. package/src/agents/render.mjs +277 -0
  58. package/src/argv.mjs +62 -9
  59. package/src/bench/ablate.mjs +31 -14
  60. package/src/bench/mine.mjs +48 -1
  61. package/src/bench/probes.mjs +5 -6
  62. package/src/bench/report.mjs +243 -80
  63. package/src/bench/run.mjs +12 -11
  64. package/src/bench/variants.mjs +112 -40
  65. package/src/brief/assemble.mjs +6 -0
  66. package/src/ci/workflow.mjs +16 -7
  67. package/src/commands/agent.mjs +206 -0
  68. package/src/commands/agenthook.mjs +133 -17
  69. package/src/commands/bench.mjs +2 -1
  70. package/src/commands/ci.mjs +28 -3
  71. package/src/commands/compare.mjs +8 -7
  72. package/src/commands/completions.mjs +27 -0
  73. package/src/commands/decide.mjs +20 -6
  74. package/src/commands/doctor.mjs +367 -0
  75. package/src/commands/evidence.mjs +13 -3
  76. package/src/commands/explain.mjs +52 -0
  77. package/src/commands/gate.mjs +85 -19
  78. package/src/commands/graph.mjs +18 -5
  79. package/src/commands/help.mjs +96 -26
  80. package/src/commands/hooks.mjs +258 -67
  81. package/src/commands/ignore.mjs +152 -0
  82. package/src/commands/impact.mjs +4 -2
  83. package/src/commands/index.mjs +69 -102
  84. package/src/commands/init.mjs +239 -37
  85. package/src/commands/lease.mjs +304 -0
  86. package/src/commands/lessons.mjs +77 -9
  87. package/src/commands/map.mjs +33 -18
  88. package/src/commands/mcp.mjs +2 -2
  89. package/src/commands/pack.mjs +9 -0
  90. package/src/commands/plan.mjs +13 -1
  91. package/src/commands/plugin.mjs +17 -2
  92. package/src/commands/prbody.mjs +45 -0
  93. package/src/commands/repoindex.mjs +4 -0
  94. package/src/commands/rules.mjs +219 -105
  95. package/src/commands/shared.mjs +36 -5
  96. package/src/commands/skills.mjs +329 -206
  97. package/src/commands/skillscompile.mjs +8 -7
  98. package/src/commands/skillsinstall.mjs +112 -30
  99. package/src/commands/slice.mjs +712 -0
  100. package/src/commands/status.mjs +62 -0
  101. package/src/commands/sync.mjs +146 -36
  102. package/src/commands/tests.mjs +5 -2
  103. package/src/commands/undo.mjs +114 -0
  104. package/src/commands/upgrade.mjs +103 -9
  105. package/src/commands/why.mjs +10 -4
  106. package/src/compare/hooksstate.mjs +23 -1
  107. package/src/compare/learn.mjs +82 -57
  108. package/src/compare/parallel.mjs +50 -0
  109. package/src/compare/row.mjs +26 -1
  110. package/src/completions.mjs +196 -0
  111. package/src/decisions/dir.mjs +84 -0
  112. package/src/decisions/index.mjs +109 -11
  113. package/src/diff.mjs +254 -0
  114. package/src/distill/distill.mjs +3 -1
  115. package/src/ecosystem/node-runner.mjs +144 -0
  116. package/src/explain.mjs +270 -0
  117. package/src/federation/config.mjs +44 -0
  118. package/src/graph/load.mjs +52 -24
  119. package/src/hooks/capability.mjs +14 -1
  120. package/src/hooks/dispatcher.mjs +441 -9
  121. package/src/hooks/gates.mjs +14 -3
  122. package/src/hooks/resolve.mjs +23 -3
  123. package/src/hooks/shim.mjs +12 -7
  124. package/src/identity.mjs +67 -14
  125. package/src/ignore.mjs +133 -0
  126. package/src/index/extract.mjs +192 -11
  127. package/src/index/persist.mjs +372 -55
  128. package/src/index/store.mjs +263 -60
  129. package/src/index/tests.mjs +6 -35
  130. package/src/journal.mjs +545 -0
  131. package/src/kernel/card.mjs +37 -12
  132. package/src/kernel/checks.mjs +44 -9
  133. package/src/kernel/variants.mjs +27 -16
  134. package/src/lease.mjs +195 -0
  135. package/src/ledger/index.mjs +91 -25
  136. package/src/mcp/resources.mjs +5 -3
  137. package/src/mcp/server.mjs +86 -13
  138. package/src/mcp/tools.mjs +340 -264
  139. package/src/memory/decide.mjs +98 -38
  140. package/src/memory/lessons.mjs +180 -33
  141. package/src/name.mjs +9 -0
  142. package/src/output/index.mjs +82 -12
  143. package/src/package-version.mjs +49 -1
  144. package/src/packs/manage.mjs +13 -4
  145. package/src/plan/index.mjs +37 -8
  146. package/src/plan/template.mjs +27 -5
  147. package/src/plugins.mjs +33 -8
  148. package/src/prbody.mjs +253 -0
  149. package/src/projection/baselines.mjs +1 -1
  150. package/src/projection/disclosure.mjs +2 -2
  151. package/src/projection/loaders.mjs +41 -1
  152. package/src/projection/lock.mjs +21 -14
  153. package/src/projection/manifest.mjs +82 -21
  154. package/src/projection/markers.mjs +43 -3
  155. package/src/projection/mdc.mjs +34 -7
  156. package/src/projection/project.mjs +162 -18
  157. package/src/projection/rules.mjs +54 -3
  158. package/src/projection/shared.mjs +4 -1
  159. package/src/projection/surfaces.mjs +9 -1
  160. package/src/repo-root.mjs +69 -0
  161. package/src/resolve/body.mjs +4 -0
  162. package/src/resolve/fingerprint.mjs +5 -0
  163. package/src/resolve/local.mjs +58 -0
  164. package/src/review/critic.mjs +4 -2
  165. package/src/secrets.mjs +374 -0
  166. package/src/state.mjs +76 -0
  167. package/src/status.mjs +157 -0
  168. package/src/toolwords.mjs +5 -0
  169. package/src/tsconfig.mjs +39 -99
  170. package/templates/plan/tracker.json +1 -1
@@ -1,13 +1,18 @@
1
- import { emit } from '../output/index.mjs';
2
- import { parse } from '../argv.mjs';
3
- import { CLI, MANIFEST_FILE } from '../name.mjs';
1
+ import { emit, fail, jsonFailMode } from '../output/index.mjs';
2
+ import { parse, rawJsonFlag } from '../argv.mjs';
3
+ import { CLI, MANIFEST_FILE, STATE_DIR } from '../name.mjs';
4
+ import { SESSION_ENV } from '../agenthooks/policy.mjs';
4
5
  import { DEFAULT_DIRECTORIES, DEFAULT_TEMPLATE } from '../plan/template.mjs';
5
6
 
6
7
  const COMMANDS = `${CLI} init [path] adopt or scaffold a repo into the ecosystem
7
8
  (dry-run unless --yes; conflicts block without
8
9
  --accept-conflicts; in place unless --backup;
9
10
  never commits or pushes)
10
- ${CLI} doctor classify a repo and check config health
11
+ ${CLI} doctor [--fix] classify a repo and check config health (with --fix:
12
+ apply the remedies flagged safe and list the rest;
13
+ dry-run unless --yes)
14
+ ${CLI} status --line one line from the last check, for prompts and tmux
15
+ (as of the last check; STALE after new commits)
11
16
  ${CLI} check the gate: projection drift, manifest validity, policy
12
17
  ${CLI} sync [--yes] regenerate the projection (idempotent)
13
18
  (prints the plan and exits 1 on drift without --yes,
@@ -42,6 +47,7 @@ ${CLI} rules list the rule catalogue (--root marks what applies to a
42
47
  ${CLI} rules show <id> one rule body
43
48
  ${CLI} rules why <id|ADR-NNN> the decision that settled it, and whether it is still in force
44
49
  (--all prints every ruling, not the first two)
50
+ ${CLI} rules decisions every known decision, shipped and repo, and which layer each came from
45
51
  ${CLI} hooks install [--yes] install the shared dispatcher; report what it would run
46
52
  (dry-run unless --yes; refuses to take over routing git
47
53
  already uses, and --yes is that consent)
@@ -53,28 +59,62 @@ ${CLI} agent-hook <event> the entry point a harness calls: pre-tool-use dec
53
59
  (reads one JSON payload on stdin and answers in that
54
60
  harness's dialect; exit 2 blocks; needs --harness)
55
61
  ${CLI} agent-hooks install write this repo's policies into the harnesses that
56
- read a hooks file
62
+ read a hooks file (--harness <id> writes one, not all)
57
63
  (dry-run unless --yes; merges into the file, keeps every
58
64
  key it does not own; Codex needs the hook trusted)
59
65
  ${CLI} agent-hooks status what each harness will run, and what is not trusted yet
60
- ${CLI} plugin <claude|gemini|cursor> generate a harness package from the same tables
61
- (dry-run unless --yes; writes a self-contained runtime, the
62
- hooks and MCP registration, and for cursor the kernel rules;
63
- the skill registry is workspace data and is not shipped)
66
+ ${CLI} agents install write the Simt-Agent into the harnesses that read an
67
+ agents file (--harness <id> writes one, not all; dry-run
68
+ unless --yes; markdown with a frontmatter the harness
69
+ documents, TOML for Codex)
70
+ ${CLI} agents status what each harness carries, and what is not installed yet
71
+ ${CLI} plugin <claude|gemini|cursor|opencode> generate a harness package from the same tables
72
+ (dry-run unless --yes; writes a self-contained runtime, the
73
+ hooks and MCP registration, and for cursor the kernel rules;
74
+ the skill registry is workspace data and is not shipped)
75
+ ${CLI} completions <shell> print a bash, zsh or fish completion script
76
+ (generated from the command registry, so every command
77
+ completes; deterministic bytes; stdout only - redirect
78
+ or source it)
64
79
  ${CLI} plan status count tracker rows
65
80
  (${MANIFEST_FILE} key plans when set, otherwise
66
81
  the ${DEFAULT_TEMPLATE} template:
67
82
  ${DEFAULT_DIRECTORIES.join(' and ')})
68
83
  ${CLI} plan next [<id>] one ready slice's section, or the one named; ~1 KB
69
84
  ${CLI} plan done <id> [<sha>] mark one row; dry-run unless --yes
85
+ ${CLI} slice start <id> give a slice its own worktree and branch, preload the
86
+ brief, and mark the row started (dry-run unless
87
+ --yes; the worktree is ${STATE_DIR}/local/worktrees/<id>
88
+ on branch slice/<id>, the brief ${STATE_DIR}/local/briefs/<id>.md
89
+ beside it; --session <id> leases the slice)
90
+ ${CLI} slice finish <id> run the pre-commit gates, commit what is staged with a
91
+ Conventional subject from the row's title, then record
92
+ the SHA and the --test command on the row (dry-run
93
+ unless --yes; --type picks the type, default feat;
94
+ refuses unless HEAD is the slice branch; gates the
95
+ ledger already proves for this tree are not re-run)
96
+ ${CLI} slice abandon <id> remove the worktree, delete the branch, and return
97
+ the row to ready (dry-run unless --yes; refuses from
98
+ inside the worktree)
99
+ ${CLI} lease [<paths>...] claim files for one session and a TTL, or list the
100
+ claims (dry-run unless --yes; the session is --session
101
+ <id> or ${SESSION_ENV}; a pre-edit hook refuses an edit
102
+ to a path another session holds — ADR-101;
103
+ release and renew end and extend your own claims)
70
104
  ${CLI} graph lint check the skill registry against the skills on disk
71
105
  (byte counts, dangling edges, unresolvable variants)
72
106
  ${CLI} ci simt-dev's own .github files: create or refresh them
73
107
  (dry-run unless --yes; refreshes the templates' own copies
74
108
  and no repository else's)
109
+ ${CLI} ignore [--yes] render the one .simtignore list into .cursorignore,
110
+ .aiderignore, .geminiignore and Claude's
111
+ permissions.deny Read(...) entries (dry-run unless
112
+ --yes; --diff prints the plan as unified diffs; the
113
+ Claude settings file is merged, never replaced)
75
114
  ${CLI} compare org-wide matrix across every sibling repo
76
115
  (read-only; exits non-zero on defects, not on
77
- repos that have not adopted yet)
116
+ repos that have not adopted yet;
117
+ --concurrency <n> caps the rows built at once)
78
118
  ${CLI} index rebuild the local file index from git blob hashes
79
119
  ${CLI} why [path] what governs a file: a decision whose Affects line names
80
120
  it, a rule whose scope matches it, a skill, a gate
@@ -93,23 +133,36 @@ ${CLI} map [--task "<text>"] [--level outline|names|signatures]
93
133
  --budget bytes (default 2048; 0 is unlimited). outline
94
134
  is paths, names adds exports, signatures adds the line.
95
135
  --recall reports gold-file recall@10 on mined tasks
136
+ ${CLI} pr-body [--base <ref>] a pull request body: the evidence block for this tree,
137
+ the decision records the diff touches, the gate
138
+ state from the last check, and the residual risk
139
+ in ADR-008 vocabulary (read-only; the exit code
140
+ never carries the verdict)
96
141
  ${CLI} evidence the runs recorded against the tree on disk
97
142
  ${CLI} evidence check <file> a commit message that claims a run this tree does not
98
143
  have: a warning, or a block when gates.evidence is "block"
99
- ${CLI} lessons list deterministic lesson candidates in .simt/lessons.jsonl
100
- and promoted lessons in docs/lessons/*.md
144
+ ${CLI} lessons list deterministic lesson candidates in .simt/local/lessons.jsonl
145
+ and promoted lessons in docs/lessons/*.md (reads nothing else)
146
+ ${CLI} lessons capture scan the ledger and git history for new candidates (the write half of list)
101
147
  ${CLI} lessons review [<id>] promote a lesson candidate to docs/lessons/NNNN-<slug>.md
102
148
  (dry-run unless --yes; writes Appendix A frontmatter)
149
+ ${CLI} explain <CODE> what a check finding means: the decision behind it, how
150
+ to fix it, and a concrete trigger (DRIFT, UNMANAGED,
151
+ PACK-DIGEST-MISMATCH, ...; case-insensitive)
103
152
  ${CLI} decide [<title>] scaffold an ADR with the next free number, a Status: line,
104
153
  a rulings skeleton, and structured simt-affects +
105
154
  simt-supersedes frontmatter (dry-run unless --yes;
106
155
  --check lints ADRs for prose-only partial supersessions)
156
+ ${CLI} undo restore the last journaled set of writes, but only
157
+ when every file in it is untouched since (dry-run
158
+ unless --yes; a touched file refuses the whole undo
159
+ and nothing is restored)
107
160
  ${CLI} local doctor probe configured local model endpoints (chat and embed)
108
161
  (reads local in ${MANIFEST_FILE}; opens no socket when
109
162
  unset; refuses non-loopback URLs without --allow-remote)
110
163
  ${CLI} distill <skill|doc> a budgeted proposal summary of a skill body or doc,
111
164
  every claim citing the source line range it rests on
112
- (writes .simt/distilled/<digest>.md; a proposal a
165
+ (writes .simt/local/distilled/<digest>.md; a proposal a
113
166
  human merges - never projected or committed;
114
167
  deterministic outline by default; --local proposes
115
168
  from the configured chat model instead; the cache is
@@ -119,7 +172,7 @@ ${CLI} review [--local] an ADR-008 verdict skeleton for the staged diff,
119
172
  (deterministic without --local: the brief and its
120
173
  governing ids only; --local proposes from the
121
174
  configured chat model and writes
122
- .simt/reviews/<digest>.md — a proposal a human
175
+ .simt/local/reviews/<digest>.md — a proposal a human
123
176
  reads, verified against the verdict vocabulary and
124
177
  the brief's ids; advisory always, never a gate)
125
178
  ${CLI} shared plan what a workspace's repeated rules cost to carry
@@ -159,10 +212,10 @@ ${CLI} bench probes [--yes] 12 synthetic rule-compliance probes with determin
159
212
  (dry-run unless --yes; grades git state, transcript and ledger,
160
213
  and reports compliance per arm)
161
214
  ${CLI} bench variants [--yes] evaluate simt-variants rule slots on the canary suite and lock
162
- winning variants in simt-dev.lock.json (dry-run unless --yes;
215
+ winning variants in simt.lock.json (dry-run unless --yes;
163
216
  re-opens when model or harness changes)
164
217
  ${CLI} bench critic precision and recall of the local critic over a labelled
165
- set of historical diffs (.simt/critic-labels.jsonl;
218
+ set of historical diffs (.simt/local/critic-labels.jsonl;
166
219
  overrides --labels; labels are human-written verdicts
167
220
  under ADR-008; the critic is advisory until precision
168
221
  reaches 0.8 on 30 labelled diffs)
@@ -192,6 +245,9 @@ const FLAGS = `--json structured output (compact; one document,
192
245
  --task "<text>" the task text used for capability resolution
193
246
  --paths <globs> comma-separated path globs used for path resolution
194
247
  --root <path> repository root (default: cwd)
248
+ --base <ref> pr-body: the ref the body diffs against
249
+ (default: origin/main, then main; falls back to the
250
+ worktree diff against HEAD when neither exists)
195
251
  --out <path> plugin: where the generated package lands (required)
196
252
  --surfaces <ids> comma-separated editors to write rule files for;
197
253
  "" means AGENTS.md only (default: every surface,
@@ -199,9 +255,22 @@ const FLAGS = `--json structured output (compact; one document,
199
255
  --workspace <path> where the skill sources live; "off" declines it
200
256
  (default: SIMT_DEV_WORKSPACE, then the user config
201
257
  file, then the sibling heuristic if it verifies)
258
+ --registry <path> which skill registry to read (skills commands and
259
+ graph lint; default: SIMT_REGISTRY, then the checkout's
260
+ own graph/skills.graph.json, then the one member of the
261
+ workspace that holds one)
262
+ --concurrency <n> compare: rows built at once (default 4, or
263
+ SIMT_CONCURRENCY; order-preserving whatever it is)
202
264
  --dry-run report what would change, change nothing
203
265
  --yes assume yes; required in automation, never prompts
204
266
  --check report drift and write nothing (sync, ci)
267
+ --diff print the plan as unified diffs (every writer;
268
+ changes nothing about what the run writes)
269
+ --line status: print the one-line gate summary from the last
270
+ check (the only mode status has)
271
+ --fix doctor: apply the remedies flagged safe (local,
272
+ idempotent, journaled); list the rest (dry-run
273
+ unless --yes)
205
274
  --frozen check: the lock must match this projection; an output
206
275
  change no input change explains fails the gate
207
276
  --explain sync: name each line dropped as already inferable, with
@@ -238,8 +307,10 @@ const FLAGS = `--json structured output (compact; one document,
238
307
  --reps <n> bench run: repetitions per task and arm (default: 3)
239
308
  --regrade <run> bench run: re-grade a stored run from its archived agent patch
240
309
  --compare <a> <b> bench report: compare two arms with deltas and p-values
241
- --test <cmd> plan done: the test command that closes the row
310
+ --test <cmd> plan done / slice finish: the test command that closes the row
242
311
  --state <name> plan done: target state (default: Complete)
312
+ --type <name> slice finish: the Conventional Commits type (default: feat)
313
+ --ttl <seconds> lease: how long a claim lasts (default: 3600)
243
314
  --level <name> map: detail level (outline, names, signatures)
244
315
  --supersedes <spec> decide: superseded ADR or ruling (ADR-NNN or ADR-NNN:<ruling>[:<kind>]; repeatable)
245
316
  --source <spec> pack new: where the pack's bytes come from
@@ -268,9 +339,12 @@ const PRINCIPLES = `design rules:
268
339
  bounded output one fact per line, fixed field order, explicit TRUNCATED lines`;
269
340
 
270
341
  export async function help(argv) {
271
- const { ok, value } = parse(argv);
272
- if (!ok) return value.code;
273
- const { flags } = value;
342
+ const parsed = parse(argv);
343
+ if (!parsed.ok) {
344
+ jsonFailMode(rawJsonFlag(argv));
345
+ return fail(parsed.error.message, parsed.error.code);
346
+ }
347
+ const { flags } = parsed.value;
274
348
  if (flags.version) {
275
349
  emit((await version()).trim());
276
350
  return 0;
@@ -300,10 +374,6 @@ export async function help(argv) {
300
374
  }
301
375
 
302
376
  async function version() {
303
- const { readFile } = await import('node:fs/promises');
304
- const { fileURLToPath } = await import('node:url');
305
- const { dirname, join } = await import('node:path');
306
- const root = join(dirname(fileURLToPath(import.meta.url)), '..');
307
- const pkg = JSON.parse(await readFile(join(root, '..', 'package.json'), 'utf8'));
308
- return `simt-dev ${pkg.version}\n`;
377
+ const { describeVersion } = await import('../package-version.mjs');
378
+ return `${describeVersion()}\n`;
309
379
  }