@opengsd/gsd-core 1.14.0 → 1.16.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 (551) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.opencode/plugins/gsd-core.js +85 -5
  4. package/README.ja-JP.md +3 -3
  5. package/README.ko-KR.md +3 -3
  6. package/README.pt-BR.md +3 -3
  7. package/README.zh-CN.md +3 -3
  8. package/agents/gsd-code-fixer.compact.md +7 -6
  9. package/agents/gsd-code-fixer.md +9 -8
  10. package/agents/gsd-code-reviewer.compact.md +5 -3
  11. package/agents/gsd-code-reviewer.md +8 -6
  12. package/agents/gsd-debug-session-manager.compact.md +17 -2
  13. package/agents/gsd-debug-session-manager.md +17 -2
  14. package/agents/gsd-debugger.md +3 -3
  15. package/agents/gsd-eval-auditor.compact.md +1 -1
  16. package/agents/gsd-eval-auditor.md +1 -1
  17. package/agents/gsd-executor.md +17 -12
  18. package/agents/gsd-intel-updater.compact.md +1 -1
  19. package/agents/gsd-intel-updater.md +1 -1
  20. package/agents/gsd-mempalace-curator.md +2 -2
  21. package/agents/gsd-phase-researcher.md +19 -11
  22. package/agents/gsd-plan-checker.md +15 -9
  23. package/agents/gsd-planner.md +15 -11
  24. package/agents/gsd-project-researcher.compact.md +1 -1
  25. package/agents/gsd-project-researcher.md +1 -1
  26. package/agents/gsd-research-synthesizer.compact.md +1 -1
  27. package/agents/gsd-research-synthesizer.md +1 -1
  28. package/agents/gsd-ui-auditor.compact.md +21 -30
  29. package/agents/gsd-ui-auditor.md +166 -37
  30. package/agents/gsd-ui-researcher.compact.md +1 -1
  31. package/agents/gsd-ui-researcher.md +1 -1
  32. package/agents/gsd-verifier.md +37 -14
  33. package/bin/install.js +764 -287
  34. package/commands/gsd/add-tests.md +6 -1
  35. package/commands/gsd/ai-integration-phase.md +6 -1
  36. package/commands/gsd/audit-fix.md +5 -0
  37. package/commands/gsd/audit-milestone.md +6 -1
  38. package/commands/gsd/autonomous.md +7 -2
  39. package/commands/gsd/capture.md +9 -5
  40. package/commands/gsd/code-review.md +7 -2
  41. package/commands/gsd/complete-milestone.md +4 -0
  42. package/commands/gsd/config.md +7 -3
  43. package/commands/gsd/debug.md +11 -7
  44. package/commands/gsd/discuss-phase.md +7 -3
  45. package/commands/gsd/docs-update.md +12 -7
  46. package/commands/gsd/eval-review.md +6 -1
  47. package/commands/gsd/execute-phase.md +12 -7
  48. package/commands/gsd/extract-learnings.md +5 -0
  49. package/commands/gsd/fast.md +4 -0
  50. package/commands/gsd/forensics.md +5 -1
  51. package/commands/gsd/graphify.md +10 -6
  52. package/commands/gsd/health.md +5 -0
  53. package/commands/gsd/help.md +7 -2
  54. package/commands/gsd/import.md +7 -3
  55. package/commands/gsd/inbox.md +5 -0
  56. package/commands/gsd/ingest-docs.md +5 -1
  57. package/commands/gsd/manager.md +6 -1
  58. package/commands/gsd/map-codebase.md +7 -3
  59. package/commands/gsd/mempalace-capture.md +12 -4
  60. package/commands/gsd/mempalace-recall.md +5 -1
  61. package/commands/gsd/milestone-summary.md +5 -1
  62. package/commands/gsd/mvp-phase.md +8 -3
  63. package/commands/gsd/new-milestone.md +6 -1
  64. package/commands/gsd/new-project.md +5 -0
  65. package/commands/gsd/next.md +6 -1
  66. package/commands/gsd/ns-context.md +4 -0
  67. package/commands/gsd/ns-ideate.md +4 -0
  68. package/commands/gsd/ns-manage.md +4 -0
  69. package/commands/gsd/ns-project.md +4 -0
  70. package/commands/gsd/ns-review.md +4 -0
  71. package/commands/gsd/ns-workflow.md +4 -0
  72. package/commands/gsd/onboard.md +6 -1
  73. package/commands/gsd/pause-work.md +5 -1
  74. package/commands/gsd/phase.md +8 -4
  75. package/commands/gsd/plan-phase.md +6 -1
  76. package/commands/gsd/plan-review-convergence.md +11 -7
  77. package/commands/gsd/pr-branch.md +4 -0
  78. package/commands/gsd/profile-user.md +5 -1
  79. package/commands/gsd/progress.md +7 -2
  80. package/commands/gsd/quick-batch.md +21 -9
  81. package/commands/gsd/quick.md +12 -7
  82. package/commands/gsd/review.md +7 -4
  83. package/commands/gsd/secure-phase.md +6 -1
  84. package/commands/gsd/ship.md +5 -0
  85. package/commands/gsd/sketch.md +7 -2
  86. package/commands/gsd/spec-phase.md +5 -1
  87. package/commands/gsd/spike.md +8 -3
  88. package/commands/gsd/surface.md +5 -1
  89. package/commands/gsd/thread.md +4 -0
  90. package/commands/gsd/ui-phase.md +6 -1
  91. package/commands/gsd/ui-review.md +6 -1
  92. package/commands/gsd/ultraplan-phase.md +5 -1
  93. package/commands/gsd/undo.md +5 -1
  94. package/commands/gsd/update.md +6 -2
  95. package/commands/gsd/validate-phase.md +6 -1
  96. package/commands/gsd/verify-work.md +6 -1
  97. package/commands/gsd/workspace.md +7 -3
  98. package/gsd-core/bin/gsd-tools.cjs +477 -78
  99. package/gsd-core/bin/lib/active-workstream-store.cjs +15 -0
  100. package/gsd-core/bin/lib/adr-parser.cjs +3 -1
  101. package/gsd-core/bin/lib/agent-install-check.cjs +4 -1
  102. package/gsd-core/bin/lib/audit.cjs +144 -42
  103. package/gsd-core/bin/lib/broken-windows.cjs +13 -13
  104. package/gsd-core/bin/lib/capability-activation.cjs +9 -4
  105. package/gsd-core/bin/lib/capability-registry.cjs +197 -222
  106. package/gsd-core/bin/lib/capability-validator.cjs +16 -1
  107. package/gsd-core/bin/lib/check-auto-mode.cjs +35 -0
  108. package/gsd-core/bin/lib/check-command-router.cjs +164 -1625
  109. package/gsd-core/bin/lib/cjs-command-router-adapter.cjs +13 -2
  110. package/gsd-core/bin/lib/cli-exit.cjs +12 -0
  111. package/gsd-core/bin/lib/codex-agent-toml.cjs +32 -33
  112. package/gsd-core/bin/lib/command-aliases.cjs +7 -0
  113. package/gsd-core/bin/lib/command-routing-hub.cjs +48 -1
  114. package/gsd-core/bin/lib/commands.cjs +343 -207
  115. package/gsd-core/bin/lib/complexity-trigger.cjs +8 -7
  116. package/gsd-core/bin/lib/config-loader.cjs +65 -4
  117. package/gsd-core/bin/lib/config.cjs +76 -19
  118. package/gsd-core/bin/lib/core-utils.cjs +6 -1
  119. package/gsd-core/bin/lib/coverage.cjs +4 -8
  120. package/gsd-core/bin/lib/decision-coverage-support.cjs +259 -0
  121. package/gsd-core/bin/lib/decisions.cjs +30 -14
  122. package/gsd-core/bin/lib/drift.cjs +177 -42
  123. package/gsd-core/bin/lib/frontmatter-fence.cjs +90 -0
  124. package/gsd-core/bin/lib/frontmatter-splice.cjs +494 -0
  125. package/gsd-core/bin/lib/frontmatter.cjs +426 -234
  126. package/gsd-core/bin/lib/gap-checker.cjs +72 -29
  127. package/gsd-core/bin/lib/gate-api-coverage-verify-pre.cjs +381 -0
  128. package/gsd-core/bin/lib/gate-args.cjs +53 -0
  129. package/gsd-core/bin/lib/gate-codebase-drift.cjs +285 -0
  130. package/gsd-core/bin/lib/gate-config.cjs +46 -0
  131. package/gsd-core/bin/lib/gate-context-drift.cjs +141 -0
  132. package/gsd-core/bin/lib/gate-decision-coverage-plan.cjs +169 -0
  133. package/gsd-core/bin/lib/gate-decision-coverage-verify.cjs +126 -0
  134. package/gsd-core/bin/lib/gate-evaluation-scope.cjs +555 -0
  135. package/gsd-core/bin/lib/gate-evidence.cjs +138 -0
  136. package/gsd-core/bin/lib/gate-exit.cjs +27 -0
  137. package/gsd-core/bin/lib/gate-gap-analysis-plan-post.cjs +61 -0
  138. package/gsd-core/bin/lib/gate-phase-context.cjs +170 -0
  139. package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +1 -1
  140. package/gsd-core/bin/lib/gate-predicate.cjs +165 -0
  141. package/gsd-core/bin/lib/gate-prohibition-enforcement.cjs +94 -0
  142. package/gsd-core/bin/lib/gate-schema-drift.cjs +165 -0
  143. package/gsd-core/bin/lib/gate-tdd-red-evidence.cjs +100 -0
  144. package/gsd-core/bin/lib/gate-tdd-review-checkpoint.cjs +182 -0
  145. package/gsd-core/bin/lib/gate-ui-plan.cjs +86 -0
  146. package/gsd-core/bin/lib/gate-ui-safety.cjs +80 -0
  147. package/gsd-core/bin/lib/gate-verdict.cjs +64 -0
  148. package/gsd-core/bin/lib/gate-verify-command-paths.cjs +78 -0
  149. package/gsd-core/bin/lib/gate-verify-failure-directions.cjs +41 -0
  150. package/gsd-core/bin/lib/graphify.cjs +10 -2
  151. package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +43 -47
  152. package/gsd-core/bin/lib/health-diagnostic.cjs +45 -8
  153. package/gsd-core/bin/lib/host-runtime-detection.cjs +9 -0
  154. package/gsd-core/bin/lib/init.cjs +364 -132
  155. package/gsd-core/bin/lib/install-engine.cjs +30 -33
  156. package/gsd-core/bin/lib/install-profiles.cjs +7 -4
  157. package/gsd-core/bin/lib/installer-migrations.cjs +8 -1
  158. package/gsd-core/bin/lib/io.cjs +122 -3
  159. package/gsd-core/bin/lib/loop-resolver.cjs +95 -0
  160. package/gsd-core/bin/lib/markdown-sectionizer.cjs +75 -1
  161. package/gsd-core/bin/lib/milestone.cjs +37 -6
  162. package/gsd-core/bin/lib/model-resolver.cjs +171 -62
  163. package/gsd-core/bin/lib/observability/event.cjs +1 -1
  164. package/gsd-core/bin/lib/observability/logger.cjs +46 -1
  165. package/gsd-core/bin/lib/pattern.cjs +10 -0
  166. package/gsd-core/bin/lib/phase-command-router.cjs +20 -5
  167. package/gsd-core/bin/lib/phase-estimation.cjs +5 -4
  168. package/gsd-core/bin/lib/phase-id-card.cjs +32 -0
  169. package/gsd-core/bin/lib/phase-id-display.cjs +78 -0
  170. package/gsd-core/bin/lib/phase-id.cjs +110 -8
  171. package/gsd-core/bin/lib/phase-lifecycle.cjs +9 -2
  172. package/gsd-core/bin/lib/phase-locator.cjs +29 -10
  173. package/gsd-core/bin/lib/phase-status.cjs +360 -0
  174. package/gsd-core/bin/lib/phase.cjs +489 -88
  175. package/gsd-core/bin/lib/plan-document.cjs +142 -20
  176. package/gsd-core/bin/lib/plan-drift-guard.cjs +5 -0
  177. package/gsd-core/bin/lib/planning-document.cjs +692 -0
  178. package/gsd-core/bin/lib/planning-inspect.cjs +60 -9
  179. package/gsd-core/bin/lib/planning-snapshot.cjs +18 -0
  180. package/gsd-core/bin/lib/planning-workspace.cjs +83 -55
  181. package/gsd-core/bin/lib/pr-branch-patterns.cjs +57 -0
  182. package/gsd-core/bin/lib/pristine-baseline.cjs +10 -0
  183. package/gsd-core/bin/lib/probe-core.cjs +7 -1
  184. package/gsd-core/bin/lib/profile-output.cjs +6 -3
  185. package/gsd-core/bin/lib/prohibition-enforcement.cjs +0 -55
  186. package/gsd-core/bin/lib/project-root.cjs +41 -2
  187. package/gsd-core/bin/lib/quick-batch-command-router.cjs +35 -9
  188. package/gsd-core/bin/lib/quick-batch-dispatch.cjs +11 -8
  189. package/gsd-core/bin/lib/real-home-guard.cjs +9 -1
  190. package/gsd-core/bin/lib/report-parser.cjs +269 -0
  191. package/gsd-core/bin/lib/review-lane-descriptor.cjs +10 -30
  192. package/gsd-core/bin/lib/review-reviewer-selection.cjs +2 -2
  193. package/gsd-core/bin/lib/roadmap-command-router.cjs +25 -19
  194. package/gsd-core/bin/lib/roadmap-parser.cjs +242 -15
  195. package/gsd-core/bin/lib/roadmap-upgrade.cjs +1653 -65
  196. package/gsd-core/bin/lib/roadmap.cjs +405 -88
  197. package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +373 -187
  198. package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +5 -2
  199. package/gsd-core/bin/lib/runtime-artifact-layout.cjs +57 -1
  200. package/gsd-core/bin/lib/runtime-homes.cjs +14 -7
  201. package/gsd-core/bin/lib/runtime-hooks-surface.cjs +522 -624
  202. package/gsd-core/bin/lib/runtime-name-policy.cjs +246 -21
  203. package/gsd-core/bin/lib/runtime-slash.cjs +47 -30
  204. package/gsd-core/bin/lib/shell-command-projection.cjs +47 -8
  205. package/gsd-core/bin/lib/smart-entry.cjs +19 -3
  206. package/gsd-core/bin/lib/stale-bake-guard.cjs +32 -48
  207. package/gsd-core/bin/lib/state-contract.cjs +15 -18
  208. package/gsd-core/bin/lib/state-document.cjs +100 -22
  209. package/gsd-core/bin/lib/state-transition.cjs +39 -2
  210. package/gsd-core/bin/lib/state.cjs +256 -105
  211. package/gsd-core/bin/lib/surface.cjs +19 -2
  212. package/gsd-core/bin/lib/tdd-red-evidence.cjs +48 -79
  213. package/gsd-core/bin/lib/uat-predicate.cjs +359 -38
  214. package/gsd-core/bin/lib/uat.cjs +432 -7
  215. package/gsd-core/bin/lib/ui-consideration-probe.cjs +15 -2
  216. package/gsd-core/bin/lib/ui-frontend-evidence.cjs +167 -40
  217. package/gsd-core/bin/lib/undo-commit-selection.cjs +131 -0
  218. package/gsd-core/bin/lib/vendor/README.md +31 -9
  219. package/gsd-core/bin/lib/vendor/saxes.cjs +1934 -0
  220. package/gsd-core/bin/lib/vendor/saxes.cjs.LICENSE.txt +92 -0
  221. package/gsd-core/bin/lib/vendor/tap-parser.cjs +8927 -0
  222. package/gsd-core/bin/lib/vendor/tap-parser.cjs.LICENSE.txt +152 -0
  223. package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
  224. package/gsd-core/bin/lib/verification.cjs +1378 -274
  225. package/gsd-core/bin/lib/verify-command-grounding.cjs +46 -2
  226. package/gsd-core/bin/lib/verify-command-router.cjs +18 -7
  227. package/gsd-core/bin/lib/verify.cjs +357 -531
  228. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +14 -6
  229. package/gsd-core/bin/lib/workstream-inventory.cjs +31 -21
  230. package/gsd-core/bin/lib/workstream-name-policy.cjs +31 -1
  231. package/gsd-core/bin/lib/workstream.cjs +11 -2
  232. package/gsd-core/bin/lib/worktree-base-ref.cjs +482 -73
  233. package/gsd-core/bin/lib/worktree-safety.cjs +784 -51
  234. package/gsd-core/bin/shared/config-defaults.manifest.json +8 -0
  235. package/gsd-core/bin/shared/config-schema.manifest.json +5 -0
  236. package/gsd-core/references/autonomous-smart-discuss.md +2 -1
  237. package/gsd-core/references/autonomous-ui-design-contract.md +3 -3
  238. package/gsd-core/references/checkpoints.md +5 -3
  239. package/gsd-core/references/edge-probe-fixtures/01-round-half-even/expected-coverage.json +28 -3
  240. package/gsd-core/references/edge-probe-fixtures/02-merge-intervals/expected-coverage.json +37 -4
  241. package/gsd-core/references/edge-probe-fixtures/03-truncate-graphemes/expected-coverage.json +28 -3
  242. package/gsd-core/references/edge-probe-fixtures/04-money-rounding/expected-coverage.json +28 -3
  243. package/gsd-core/references/edge-probe-fixtures/05-list-dedupe/expected-coverage.json +37 -4
  244. package/gsd-core/references/edge-probe-fixtures/06-resolved-mixed/expected-coverage.json +37 -4
  245. package/gsd-core/references/edge-probe.md +195 -21
  246. package/gsd-core/references/execute-mvp-tdd.md +5 -10
  247. package/gsd-core/references/execute-phase-between-wave-reset.md +10 -6
  248. package/gsd-core/references/execute-phase-response-language.md +1 -1
  249. package/gsd-core/references/execute-phase-wave-guard.md +22 -11
  250. package/gsd-core/references/gsd-run-resolver.md +1 -1
  251. package/gsd-core/references/loop-hook-dispatch.md +7 -1
  252. package/gsd-core/references/model-profiles.md +1 -1
  253. package/gsd-core/references/offer-next.md +1 -1
  254. package/gsd-core/references/phase-argument-parsing.md +9 -7
  255. package/gsd-core/references/phase-id-convention.md +28 -0
  256. package/gsd-core/references/planner-gap-closure.md +2 -0
  257. package/gsd-core/references/planner-load-graph-context.md +24 -13
  258. package/gsd-core/references/planner-verify-command-grounding.md +14 -0
  259. package/gsd-core/references/planning-config.md +12 -3
  260. package/gsd-core/references/spidr-splitting.md +1 -1
  261. package/gsd-core/references/tdd.md +37 -8
  262. package/gsd-core/references/ui-consideration-probe.md +10 -5
  263. package/gsd-core/references/verifier-phase-gates.md +5 -2
  264. package/gsd-core/references/verify-command-path-resolvability.md +10 -2
  265. package/gsd-core/references/verify-mvp-mode.md +2 -2
  266. package/gsd-core/references/workstream-flag.md +33 -3
  267. package/gsd-core/references/worktree-path-safety.md +321 -0
  268. package/gsd-core/templates/README.md +1 -1
  269. package/gsd-core/templates/UAT.md +17 -1
  270. package/gsd-core/templates/config.json +2 -11
  271. package/gsd-core/templates/verification-report.md +1 -1
  272. package/gsd-core/workflows/_runtime-launcher.snippet.sh +1 -1
  273. package/gsd-core/workflows/add-backlog.md +1 -1
  274. package/gsd-core/workflows/add-phase.md +8 -7
  275. package/gsd-core/workflows/add-tests.md +4 -3
  276. package/gsd-core/workflows/add-todo.md +6 -5
  277. package/gsd-core/workflows/ai-integration-phase.md +13 -4
  278. package/gsd-core/workflows/audit-fix.md +1 -1
  279. package/gsd-core/workflows/audit-milestone.md +4 -3
  280. package/gsd-core/workflows/audit-uat.md +1 -1
  281. package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +9 -18
  282. package/gsd-core/workflows/autonomous.md +43 -23
  283. package/gsd-core/workflows/check-todos.md +7 -6
  284. package/gsd-core/workflows/cleanup.md +2 -2
  285. package/gsd-core/workflows/code-review/steps/dispatch-fix.md +4 -3
  286. package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +20 -13
  287. package/gsd-core/workflows/code-review-fix.md +112 -25
  288. package/gsd-core/workflows/code-review.md +146 -135
  289. package/gsd-core/workflows/complete-milestone/detail/elaboration.md +4 -3
  290. package/gsd-core/workflows/complete-milestone.md +13 -8
  291. package/gsd-core/workflows/debug.md +32 -7
  292. package/gsd-core/workflows/diagnose-issues.md +3 -2
  293. package/gsd-core/workflows/discuss-phase/modes/advisor.md +1 -1
  294. package/gsd-core/workflows/discuss-phase/modes/chain.md +1 -1
  295. package/gsd-core/workflows/discuss-phase-assumptions.md +4 -3
  296. package/gsd-core/workflows/discuss-phase.md +4 -3
  297. package/gsd-core/workflows/do.md +2 -2
  298. package/gsd-core/workflows/docs-update.md +6 -5
  299. package/gsd-core/workflows/edit-phase.md +4 -3
  300. package/gsd-core/workflows/eval-review.md +14 -5
  301. package/gsd-core/workflows/execute-phase/detail/elaboration.md +2 -2
  302. package/gsd-core/workflows/execute-phase/steps/code-review-disposition.md +1019 -0
  303. package/gsd-core/workflows/execute-phase/steps/codebase-drift-gate.md +15 -4
  304. package/gsd-core/workflows/execute-phase/steps/completion-reconciliation.md +10 -7
  305. package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +37 -3
  306. package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +3 -1
  307. package/gsd-core/workflows/execute-phase/steps/partial-wave.md +2 -2
  308. package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +1 -1
  309. package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +1 -1
  310. package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +46 -9
  311. package/gsd-core/workflows/execute-phase/steps/protected-branch.md +1 -1
  312. package/gsd-core/workflows/execute-phase/steps/ready-wave-gate.md +37 -0
  313. package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +1 -1
  314. package/gsd-core/workflows/execute-phase/steps/regression-gate.md +2 -0
  315. package/gsd-core/workflows/execute-phase/steps/tdd-applicability-resolution.md +1 -1
  316. package/gsd-core/workflows/execute-phase/steps/threat-id-gate.md +28 -0
  317. package/gsd-core/workflows/execute-phase/steps/verify-phase-goal.md +187 -0
  318. package/gsd-core/workflows/execute-phase/steps/wave-post-gate-hooks.md +2 -3
  319. package/gsd-core/workflows/execute-phase/steps/worktree-base-check.md +25 -0
  320. package/gsd-core/workflows/execute-phase.md +96 -178
  321. package/gsd-core/workflows/execute-plan.md +18 -23
  322. package/gsd-core/workflows/explore.md +4 -4
  323. package/gsd-core/workflows/extract-learnings.md +4 -2
  324. package/gsd-core/workflows/fast.md +1 -1
  325. package/gsd-core/workflows/forensics.md +1 -1
  326. package/gsd-core/workflows/graduation.md +1 -1
  327. package/gsd-core/workflows/health.md +3 -2
  328. package/gsd-core/workflows/help/modes/full.compact.md +3 -3
  329. package/gsd-core/workflows/help/modes/full.md +5 -5
  330. package/gsd-core/workflows/help/modes/topic.md +15 -5
  331. package/gsd-core/workflows/import.md +4 -3
  332. package/gsd-core/workflows/inbox.md +2 -2
  333. package/gsd-core/workflows/ingest-docs.md +3 -3
  334. package/gsd-core/workflows/insert-phase.md +4 -3
  335. package/gsd-core/workflows/list-seeds.md +1 -1
  336. package/gsd-core/workflows/list-workspaces.md +1 -1
  337. package/gsd-core/workflows/manager.md +6 -4
  338. package/gsd-core/workflows/map-codebase.md +5 -4
  339. package/gsd-core/workflows/milestone-summary.md +3 -2
  340. package/gsd-core/workflows/mvp-phase.md +14 -14
  341. package/gsd-core/workflows/new-milestone.md +11 -11
  342. package/gsd-core/workflows/new-project/steps/auto-mode-config.md +3 -3
  343. package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +1 -1
  344. package/gsd-core/workflows/new-project.md +7 -7
  345. package/gsd-core/workflows/new-workspace.md +2 -2
  346. package/gsd-core/workflows/next.md +1 -1
  347. package/gsd-core/workflows/note.md +1 -1
  348. package/gsd-core/workflows/onboard.md +1 -1
  349. package/gsd-core/workflows/pause-work.md +2 -2
  350. package/gsd-core/workflows/plan-phase/detail/elaboration.md +1 -1
  351. package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +17 -5
  352. package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +1 -1
  353. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +1 -1
  354. package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +23 -5
  355. package/gsd-core/workflows/plan-phase.md +50 -24
  356. package/gsd-core/workflows/plan-review-convergence.md +21 -5
  357. package/gsd-core/workflows/plant-seed.md +62 -20
  358. package/gsd-core/workflows/pr-branch.md +113 -13
  359. package/gsd-core/workflows/profile-user.md +2 -2
  360. package/gsd-core/workflows/progress.md +19 -49
  361. package/gsd-core/workflows/quick/steps/plan-checker-loop.md +27 -0
  362. package/gsd-core/workflows/quick/steps/quick-verification.md +4 -4
  363. package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +30 -11
  364. package/gsd-core/workflows/quick-batch/steps/batch-init.md +1 -1
  365. package/gsd-core/workflows/quick-batch/steps/completion.md +1 -1
  366. package/gsd-core/workflows/quick-batch/steps/merge-wave.md +1 -1
  367. package/gsd-core/workflows/quick-batch/steps/planner-wave.md +1 -1
  368. package/gsd-core/workflows/quick-batch/steps/research-phase.md +1 -1
  369. package/gsd-core/workflows/quick-batch/steps/resume-mode.md +1 -1
  370. package/gsd-core/workflows/quick-batch/steps/verification-wave.md +9 -3
  371. package/gsd-core/workflows/quick-batch/steps/worktree-dispatch.md +1 -1
  372. package/gsd-core/workflows/quick-batch.md +15 -10
  373. package/gsd-core/workflows/quick.md +62 -39
  374. package/gsd-core/workflows/reapply-patches.md +9 -3
  375. package/gsd-core/workflows/remove-phase.md +3 -2
  376. package/gsd-core/workflows/remove-workspace.md +2 -2
  377. package/gsd-core/workflows/resume-project.md +3 -2
  378. package/gsd-core/workflows/review.md +33 -17
  379. package/gsd-core/workflows/scan.md +3 -2
  380. package/gsd-core/workflows/secure-phase.md +13 -13
  381. package/gsd-core/workflows/settings-advanced.md +30 -10
  382. package/gsd-core/workflows/settings-integrations.md +2 -3
  383. package/gsd-core/workflows/settings.md +4 -4
  384. package/gsd-core/workflows/ship.md +14 -13
  385. package/gsd-core/workflows/sketch-wrap-up.md +1 -1
  386. package/gsd-core/workflows/sketch.md +1 -1
  387. package/gsd-core/workflows/smart-entry.md +2 -2
  388. package/gsd-core/workflows/spec-phase.md +15 -5
  389. package/gsd-core/workflows/spike-wrap-up.md +1 -1
  390. package/gsd-core/workflows/spike.md +1 -1
  391. package/gsd-core/workflows/stats.md +1 -1
  392. package/gsd-core/workflows/sync-skills.md +5 -5
  393. package/gsd-core/workflows/thread.md +2 -2
  394. package/gsd-core/workflows/transition.md +13 -23
  395. package/gsd-core/workflows/ui-phase.md +48 -11
  396. package/gsd-core/workflows/ui-review.md +21 -6
  397. package/gsd-core/workflows/ultraplan-phase.md +3 -2
  398. package/gsd-core/workflows/undo.md +339 -20
  399. package/gsd-core/workflows/update.md +7 -7
  400. package/gsd-core/workflows/validate-phase.md +12 -13
  401. package/gsd-core/workflows/verify-work/detail/elaboration.md +43 -3
  402. package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +1 -1
  403. package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +5 -3
  404. package/gsd-core/workflows/verify-work.md +129 -55
  405. package/hooks/dist/gsd-agent-isolation-guard.js +32 -0
  406. package/hooks/dist/gsd-check-update-worker.js +8 -0
  407. package/hooks/dist/gsd-check-update.js +8 -0
  408. package/hooks/dist/gsd-context-monitor.js +31 -8
  409. package/hooks/dist/gsd-cursor-subagent-start.js +8 -0
  410. package/hooks/dist/gsd-secret-read-guard.js +161 -4
  411. package/hooks/dist/gsd-statusline.js +85 -20
  412. package/hooks/dist/gsd-update-banner.js +8 -0
  413. package/hooks/dist/gsd-validate-commit.sh +63 -4
  414. package/hooks/dist/gsd-windsurf-pre-write.js +11 -2
  415. package/hooks/dist/gsd-workflow-guard.js +5 -4
  416. package/hooks/dist/gsd-worktree-path-guard.js +6 -2
  417. package/hooks/dist/lib/cli-exit.js +12 -0
  418. package/hooks/dist/lib/git-probe.js +17 -1
  419. package/hooks/dist/lib/isolation-sentinel.js +2 -2
  420. package/hooks/gsd-agent-isolation-guard.js +32 -0
  421. package/hooks/gsd-check-update-worker.js +8 -0
  422. package/hooks/gsd-check-update.js +8 -0
  423. package/hooks/gsd-context-monitor.js +31 -8
  424. package/hooks/gsd-cursor-subagent-start.js +8 -0
  425. package/hooks/gsd-secret-read-guard.js +161 -4
  426. package/hooks/gsd-statusline.js +85 -20
  427. package/hooks/gsd-update-banner.js +8 -0
  428. package/hooks/gsd-validate-commit.sh +63 -4
  429. package/hooks/gsd-windsurf-pre-write.js +11 -2
  430. package/hooks/gsd-workflow-guard.js +5 -4
  431. package/hooks/gsd-worktree-path-guard.js +6 -2
  432. package/hooks/hooks.json +5 -5
  433. package/hooks/lib/cli-exit.js +12 -0
  434. package/hooks/lib/git-probe.js +17 -1
  435. package/hooks/lib/isolation-sentinel.js +2 -2
  436. package/package.json +22 -4
  437. package/scripts/build-hooks.js +15 -6
  438. package/scripts/changeset/parse.cjs +52 -4
  439. package/scripts/check-contract-drift.cjs +127 -11
  440. package/scripts/ci-timeout-report.cjs +770 -4
  441. package/scripts/command-contract-helpers.cjs +15 -8
  442. package/scripts/docs-guard-registry.cjs +34 -0
  443. package/scripts/gen-features.cjs +13 -8
  444. package/scripts/gen-hooks-cli-exit.cjs +12 -28
  445. package/scripts/gen-loop-host-contract.cjs +79 -1
  446. package/scripts/gen-platform-conformance-tier.cjs +187 -1
  447. package/scripts/gen-plugin-skills.cjs +87 -1
  448. package/scripts/gen-research-agents.cjs +24 -31
  449. package/scripts/gen-scripts-cli-exit.cjs +30 -3
  450. package/scripts/gen-test-timings.cjs +32 -7
  451. package/scripts/lib/cli-exit.cjs +12 -0
  452. package/scripts/lib/macos-conformance-tier.generated.cjs +34 -2
  453. package/scripts/lib/ndjson-reporter.cjs +31 -5
  454. package/scripts/lib/platform-conformance-tier.generated.cjs +45 -5
  455. package/scripts/lib/registration-ledger-preload.cjs +155 -0
  456. package/scripts/lib/vendor-bundle.cjs +59 -0
  457. package/scripts/lib/vendor-licenses/saxes-6.0.0.txt +64 -0
  458. package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +1 -1
  459. package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +1 -1
  460. package/scripts/lint-completion-predicate-drift.cjs +18 -19
  461. package/scripts/lint-descriptions.cjs +7 -3
  462. package/scripts/lint-docs-guard-registration.exempt-baseline.cjs +38 -1
  463. package/scripts/lint-eslint-glob-coverage.allowlist.json +20 -0
  464. package/scripts/lint-frontmatter-fence-drift.cjs +313 -0
  465. package/scripts/lint-frontmatter-scalar-broad-grep.cjs +122 -16
  466. package/scripts/lint-phase-arg-assignment.cjs +257 -0
  467. package/scripts/lint-phase-enumeration-drift.cjs +12 -8
  468. package/scripts/lint-phase-id-drift.cjs +319 -5
  469. package/scripts/lint-planning-document-positive-control.cjs +329 -0
  470. package/scripts/lint-pr-branch-pattern-drift.cjs +148 -0
  471. package/scripts/lint-response-language-coverage.cjs +3 -0
  472. package/scripts/lint-retired-runtime-name.cjs +619 -0
  473. package/scripts/lint-skill-deps.cjs +7 -3
  474. package/scripts/lint-state-write-path-drift.cjs +93 -0
  475. package/scripts/lint-test-file-count.allowlist.json +38 -9
  476. package/scripts/lint-test-file-count.cjs +34 -1
  477. package/scripts/lint-vendored-deps.cjs +41 -5
  478. package/scripts/lint-workflow-shellcheck-baseline.json +25 -10
  479. package/scripts/mutation-matrix.cjs +50 -5
  480. package/scripts/prompt-injection-scan.sh +4 -0
  481. package/scripts/release-tarball-smoke.cjs +194 -1
  482. package/scripts/require-issue-link-policy.cjs +6 -2
  483. package/scripts/sync-runtime-launcher.cjs +184 -2
  484. package/scripts/verify-npm-publish.cjs +76 -20
  485. package/skills/gsd-add-tests/SKILL.md +6 -1
  486. package/skills/gsd-ai-integration-phase/SKILL.md +6 -1
  487. package/skills/gsd-audit-fix/SKILL.md +5 -0
  488. package/skills/gsd-audit-milestone/SKILL.md +6 -1
  489. package/skills/gsd-autonomous/SKILL.md +7 -2
  490. package/skills/gsd-capture/SKILL.md +9 -5
  491. package/skills/gsd-code-review/SKILL.md +7 -2
  492. package/skills/gsd-complete-milestone/SKILL.md +4 -0
  493. package/skills/gsd-config/SKILL.md +8 -4
  494. package/skills/gsd-debug/SKILL.md +11 -7
  495. package/skills/gsd-discuss-phase/SKILL.md +7 -3
  496. package/skills/gsd-docs-update/SKILL.md +12 -7
  497. package/skills/gsd-eval-review/SKILL.md +6 -1
  498. package/skills/gsd-execute-phase/SKILL.md +12 -7
  499. package/skills/gsd-extract-learnings/SKILL.md +5 -0
  500. package/skills/gsd-fast/SKILL.md +4 -0
  501. package/skills/gsd-forensics/SKILL.md +5 -1
  502. package/skills/gsd-graphify/SKILL.md +10 -6
  503. package/skills/gsd-health/SKILL.md +5 -0
  504. package/skills/gsd-help/SKILL.md +7 -2
  505. package/skills/gsd-import/SKILL.md +7 -3
  506. package/skills/gsd-inbox/SKILL.md +5 -0
  507. package/skills/gsd-ingest-docs/SKILL.md +5 -1
  508. package/skills/gsd-manager/SKILL.md +6 -1
  509. package/skills/gsd-map-codebase/SKILL.md +7 -3
  510. package/skills/gsd-mempalace-capture/SKILL.md +12 -4
  511. package/skills/gsd-mempalace-recall/SKILL.md +5 -1
  512. package/skills/gsd-milestone-summary/SKILL.md +5 -1
  513. package/skills/gsd-mvp-phase/SKILL.md +8 -3
  514. package/skills/gsd-new-milestone/SKILL.md +6 -1
  515. package/skills/gsd-new-project/SKILL.md +5 -0
  516. package/skills/gsd-next/SKILL.md +6 -1
  517. package/skills/gsd-ns-context/SKILL.md +4 -0
  518. package/skills/gsd-ns-ideate/SKILL.md +4 -0
  519. package/skills/gsd-ns-manage/SKILL.md +4 -0
  520. package/skills/gsd-ns-project/SKILL.md +4 -0
  521. package/skills/gsd-ns-review/SKILL.md +4 -0
  522. package/skills/gsd-ns-workflow/SKILL.md +4 -0
  523. package/skills/gsd-onboard/SKILL.md +6 -1
  524. package/skills/gsd-pause-work/SKILL.md +5 -1
  525. package/skills/gsd-phase/SKILL.md +8 -4
  526. package/skills/gsd-plan-phase/SKILL.md +6 -1
  527. package/skills/gsd-plan-review-convergence/SKILL.md +10 -6
  528. package/skills/gsd-pr-branch/SKILL.md +4 -0
  529. package/skills/gsd-profile-user/SKILL.md +5 -1
  530. package/skills/gsd-progress/SKILL.md +7 -2
  531. package/skills/gsd-quick/SKILL.md +16 -10
  532. package/skills/gsd-quick-batch/SKILL.md +21 -9
  533. package/skills/gsd-review/SKILL.md +7 -4
  534. package/skills/gsd-review-backlog/SKILL.md +3 -2
  535. package/skills/gsd-secure-phase/SKILL.md +6 -1
  536. package/skills/gsd-ship/SKILL.md +5 -0
  537. package/skills/gsd-sketch/SKILL.md +7 -2
  538. package/skills/gsd-spec-phase/SKILL.md +5 -1
  539. package/skills/gsd-spike/SKILL.md +8 -3
  540. package/skills/gsd-surface/SKILL.md +5 -1
  541. package/skills/gsd-thread/SKILL.md +4 -0
  542. package/skills/gsd-ui-phase/SKILL.md +6 -1
  543. package/skills/gsd-ui-review/SKILL.md +6 -1
  544. package/skills/gsd-ultraplan-phase/SKILL.md +5 -1
  545. package/skills/gsd-undo/SKILL.md +5 -1
  546. package/skills/gsd-update/SKILL.md +6 -2
  547. package/skills/gsd-validate-phase/SKILL.md +6 -1
  548. package/skills/gsd-verify-work/SKILL.md +6 -1
  549. package/skills/gsd-workspace/SKILL.md +7 -3
  550. package/skills/gsd-workstreams/SKILL.md +6 -6
  551. package/vscode/package.json +1 -1
@@ -81,4 +81,20 @@ function reportIfUndetermined(hookName, probeLabel, result) {
81
81
  }
82
82
  }
83
83
 
84
- module.exports = { classifyGitProbe, reportIfUndetermined };
84
+ // Per-probe budget for the git probes of BLOCKING guards. A probe that times
85
+ // out fails OPEN (see reportIfUndetermined above), which is the same outcome
86
+ // as the host killing the hook — so a budget sized to git's ~0.1s typical run
87
+ // silently disables the gate on a starved host (a 2000ms budget was exceeded
88
+ // on a loaded Windows runner, #5180). Worst case for a guard that runs up to
89
+ // BLOCKING_GUARD_MAX_SEQUENTIAL_PROBES sequential probes:
90
+ // 3 x 5000ms + ~500ms node start/kill/reap = ~15.5s,
91
+ // inside the 120s host budget blocking guards are registered with (#3981).
92
+ const BLOCKING_GUARD_PROBE_TIMEOUT_MS = 5000;
93
+ const BLOCKING_GUARD_MAX_SEQUENTIAL_PROBES = 3;
94
+
95
+ module.exports = {
96
+ classifyGitProbe,
97
+ reportIfUndetermined,
98
+ BLOCKING_GUARD_PROBE_TIMEOUT_MS,
99
+ BLOCKING_GUARD_MAX_SEQUENTIAL_PROBES,
100
+ };
@@ -23,8 +23,8 @@
23
23
  // explicit fallback for the per-plan submodule-degrade override and shares
24
24
  // the exact same atomic-write implementation.
25
25
  //
26
- // Sentinel path: `<cwd>/.gsd/dispatch-isolation-sentinel.json`. `.gsd` is
27
- // gitignored (root `.gitignore`'s bare `.gsd` entry matches at any depth),
26
+ // Sentinel path: `<cwd>/.gsd/dispatch-isolation-sentinel.json`. The writer
27
+ // seeds `.gsd/.gitignore` so this stays ignored in user projects too,
28
28
  // and lives inside the checkout that ran the workflow — concurrent worktrees
29
29
  // of the same repo are separate directories on disk, so each gets its own
30
30
  // sentinel with no cross-worktree collision, no lock file needed.
@@ -60,6 +60,14 @@
60
60
 
61
61
  'use strict';
62
62
 
63
+ // #5183: Node's on-disk compile cache, so later runs reuse V8's compiled code
64
+ // for unchanged modules. Only as the entry (a test require() is unaffected),
65
+ // skipped under V8 coverage, optional (Bun stubs it), and never fatal.
66
+ // NODE_DISABLE_COMPILE_CACHE (any value) turns it off.
67
+ if (require.main === module && !process.env.NODE_V8_COVERAGE) {
68
+ try { require('node:module').enableCompileCache?.(); } catch { /* optimization only */ }
69
+ }
70
+
63
71
  const fs = require('fs');
64
72
  const path = require('path');
65
73
  const os = require('os');
@@ -337,6 +345,30 @@ function resolveRegistryIsolation(cwd, configPath) {
337
345
  if (!useWorktrees) isolation = 'none';
338
346
  }
339
347
 
348
+ // #4734: a harness worktree can never be created in a directory that is not
349
+ // a git repository (or a repository with no commits) — git's definitive
350
+ // exit-128 answer on `rev-parse HEAD`. Demanding the isolation flag there
351
+ // blocked every flag-less dispatch the moment the sentinel went stale, on a
352
+ // root where no worktree can exist. Degrade to 'none' exactly like the
353
+ // use_worktrees opt-out above; the classification is owned by
354
+ // `classifyGitHead` (worktree-base-ref.cjs) — the same single owner the
355
+ // base-check's degrade decision uses — and ambiguous or failed resolutions
356
+ // keep the conservative (enforce) default, matching that check's own
357
+ // fail-closed treatment of the same classes.
358
+ if (isolation === 'harness-worktree') {
359
+ try {
360
+ ensureRuntimeBuild();
361
+ const { classifyGitHead } = require('../gsd-core/bin/lib/worktree-base-ref.cjs');
362
+ if (classifyGitHead({ cwd }).status === 'definitive-absence') {
363
+ isolation = 'none';
364
+ }
365
+ } catch {
366
+ // Unbuilt or unreadable runtime library — keep the conservative
367
+ // (enforce) default rather than silently disabling the guard, same
368
+ // posture as the ladder fallback above.
369
+ }
370
+ }
371
+
340
372
  return { isolation, harnessFlag };
341
373
  }
342
374
 
@@ -9,6 +9,14 @@
9
9
 
10
10
  'use strict';
11
11
 
12
+ // #5183: Node's on-disk compile cache, so later runs reuse V8's compiled code
13
+ // for unchanged modules. Only as the entry (a test require() is unaffected),
14
+ // skipped under V8 coverage, optional (Bun stubs it), and never fatal.
15
+ // NODE_DISABLE_COMPILE_CACHE (any value) turns it off.
16
+ if (require.main === module && !process.env.NODE_V8_COVERAGE) {
17
+ try { require('node:module').enableCompileCache?.(); } catch { /* optimization only */ }
18
+ }
19
+
12
20
  const fs = require('fs');
13
21
  const path = require('path');
14
22
 
@@ -3,6 +3,14 @@
3
3
  // Check for GSD updates in background, write result to cache
4
4
  // Called by SessionStart hook - runs once per session
5
5
 
6
+ // #5183: Node's on-disk compile cache, so later runs reuse V8's compiled code
7
+ // for unchanged modules. Only as the entry (a test require() is unaffected),
8
+ // skipped under V8 coverage, optional (Bun stubs it), and never fatal.
9
+ // NODE_DISABLE_COMPILE_CACHE (any value) turns it off.
10
+ if (require.main === module && !process.env.NODE_V8_COVERAGE) {
11
+ try { require('node:module').enableCompileCache?.(); } catch { /* optimization only */ }
12
+ }
13
+
6
14
  const fs = require('fs');
7
15
  const path = require('path');
8
16
  const os = require('os');
@@ -201,6 +201,29 @@ function writeSentinel(target, payload) {
201
201
  } catch (e) { /* best effort — see above */ }
202
202
  }
203
203
 
204
+ // The calendar day the CRITICAL auto-record writes into STATE.md (#4905): the
205
+ // operator's LOCAL day through the clock seam, which honors GSD_NOW_MS under
206
+ // GSD_TEST_MODE, like every other date GSD stamps into planning files. The
207
+ // clock is compiled into gsd-core/bin/lib/, so it is reached through the
208
+ // self-healing build seam (#3582). If the library is missing and cannot
209
+ // self-build, the host's local day stands in — still never the UTC day.
210
+ function localDayStamp() {
211
+ try {
212
+ const { ensureRuntimeBuild } = require('../gsd-core/bin/ensure-runtime-build.cjs');
213
+ ensureRuntimeBuild();
214
+ return require('../gsd-core/bin/lib/clock.cjs').realClock.localToday();
215
+ } catch {
216
+ const now = new Date();
217
+ return [now.getFullYear(), String(now.getMonth() + 1).padStart(2, '0'), String(now.getDate()).padStart(2, '0')].join('-');
218
+ }
219
+ }
220
+
221
+ // The Stopped At breadcrumb for /gsd:resume-work (#1974). usedPct is coerced to
222
+ // a safe number in case the bridge file is malformed.
223
+ function criticalStoppedAt(usedPct) {
224
+ return `context exhaustion at ${Number(usedPct) || 0}% (${localDayStamp()})`;
225
+ }
226
+
204
227
  let input = '';
205
228
  // Assigned by main(); the handler below clears it. Declared out here rather
206
229
  // than inside main() because the handler closes over it.
@@ -464,9 +487,7 @@ const handleStdinEnd = () => {
464
487
  // Using __dirname makes this work on Claude Code, OpenCode, Gemini,
465
488
  // Kilo, etc. without hardcoding ~/.claude/.
466
489
  const gsdTools = path.join(__dirname, '..', 'gsd-core', 'bin', 'gsd-tools.cjs');
467
- // Coerce usedPct to a safe number in case bridge file is malformed
468
- const safeUsedPct = Number(usedPct) || 0;
469
- const stoppedAt = `context exhaustion at ${safeUsedPct}% (${new Date().toISOString().split('T')[0]})`;
490
+ const stoppedAt = criticalStoppedAt(usedPct);
470
491
  spawn(
471
492
  process.execPath,
472
493
  [gsdTools, 'state', 'record-session', '--stopped-at', stoppedAt],
@@ -560,8 +581,10 @@ if (require.main === module) {
560
581
  main();
561
582
  }
562
583
 
563
- // Exported for the #4285 property test only. The two constants ride along so a
564
- // test asserts the fallback pair against the SOURCE of truth rather than
565
- // re-hardcoding 35/25 — a test carrying its own copy of the defaults would stay
566
- // green if the constants were edited.
567
- module.exports = { resolveThresholds, WARNING_THRESHOLD, CRITICAL_THRESHOLD };
584
+ // Exported for tests only. resolveThresholds and the two constants serve the
585
+ // #4285 property test; the constants ride along so a test asserts the fallback
586
+ // pair against the SOURCE of truth rather than re-hardcoding 35/25 — a test
587
+ // carrying its own copy of the defaults would stay green if the constants were
588
+ // edited. criticalStoppedAt lets the #4905 test pin the breadcrumb's day
589
+ // without waiting on the detached record-session writer (#3726).
590
+ module.exports = { resolveThresholds, WARNING_THRESHOLD, CRITICAL_THRESHOLD, criticalStoppedAt };
@@ -53,6 +53,14 @@
53
53
 
54
54
  'use strict';
55
55
 
56
+ // #5183: Node's on-disk compile cache, so later runs reuse V8's compiled code
57
+ // for unchanged modules. Only as the entry (a test require() is unaffected),
58
+ // skipped under V8 coverage, optional (Bun stubs it), and never fatal.
59
+ // NODE_DISABLE_COMPILE_CACHE (any value) turns it off.
60
+ if (require.main === module && !process.env.NODE_V8_COVERAGE) {
61
+ try { require('node:module').enableCompileCache?.(); } catch { /* optimization only */ }
62
+ }
63
+
56
64
  const fs = require('fs');
57
65
  const path = require('path');
58
66
  const os = require('os');
@@ -61,7 +61,13 @@
61
61
  // segment's operands — `[ -f .env ]` and `ls .env*` are existence checks
62
62
  // GSD's own agents run — while `cp`/`mv`/`ln`/`git` are deliberately NOT
63
63
  // exempt (`cp .env x && cat x` launders the name; `git show HEAD:.env`
64
- // reads). A shell interpreter (bash/sh/zsh/dash/ksh/su) has its script scanned
64
+ // reads). Narrower carve-outs exempt single operand POSITIONS that are
65
+ // names, never contents, and keep checking the rest of the segment: the
66
+ // `--env-file` value under a container runtime (#4639), the pathspecs of
67
+ // `git check-ignore` / `git ls-files` / `git rm --cached`, and the
68
+ // destination of a one-source `cp`/`mv` (#4856). The #4856 carve-outs
69
+ // fail closed: an option they do not list withdraws them from the segment.
70
+ // A shell interpreter (bash/sh/zsh/dash/ksh/su) has its script scanned
65
71
  // whether it arrives via `-c '…'`, a `<( )` file operand, a heredoc /
66
72
  // here-string, or a pipe from a knowable `echo`/`printf` source
67
73
  // (`echo cat .env | bash`); `eval` scans its joined operands; `source`/`.`
@@ -86,7 +92,16 @@
86
92
  // on plain commands, without arming the compound-`cd` prompt". Writes to
87
93
  // secret files are out of scope (Write/Edit were never gated). Commands
88
94
  // over 1 MiB are denied outright (`command-too-large`) rather than
89
- // scanned partially or waved through.
95
+ // scanned partially or waved through. (#4639 adds one more, by design: the
96
+ // value of `--env-file` under a container runtime is exempt, so the
97
+ // container's own command can print the interpolated environment
98
+ // (`alpine printenv`, `docker compose config`) — the same exposure class
99
+ // as the pre-existing volume-mount gap (`-v .env:/s`); the flag's value
100
+ // itself is a name, never contents. #4856 adds another: the `cp`/`mv`
101
+ // destination exemption can move a link prepared under a non-secret name
102
+ // onto a secret name (`ln -s .env.example l && mv l .env`), so a later
103
+ // edit of `.env` lands in the link target — a write redirection, the
104
+ // out-of-scope write class, not a read.)
90
105
  //
91
106
  // Triggers on: Read, Grep, Bash tool calls (Kimi: ReadFile, Grep, Shell)
92
107
  // Action: BLOCK (decision: 'block', exit 2) — codes secret-read |
@@ -127,6 +142,66 @@ const NON_READING_COMMANDS = new Set([
127
142
  'basename', 'dirname', 'realpath', 'file', 'echo', 'printf',
128
143
  ]);
129
144
 
145
+ // #4639: container runtimes take `--env-file <file>` — the runtime opens the
146
+ // file itself, interpolates it into the container environment, and returns
147
+ // nothing to the agent, so the flag's VALUE is a name, never contents. The
148
+ // same category NON_READING_COMMANDS encodes, expressed as a flag value. Only
149
+ // the flag's value under these runtimes is exempt; every other operand in the
150
+ // segment is still checked, so the carve-out cannot launder a read.
151
+ const CONTAINER_RUNTIMES = new Set(['docker', 'docker-compose', 'podman', 'nerdctl']);
152
+ const ENV_FILE_FLAG_RE = /^--env-file(=|$)/;
153
+
154
+ // #4856: git subcommands that report or drop a path's ignore / tracking
155
+ // status and never print the file, so their pathspec operands are names —
156
+ // the category NON_READING_COMMANDS encodes. Each carries the closed set of
157
+ // its NO-VALUE options (from `git <subcommand> -h`, git 2.49). Any other
158
+ // option withdraws the exemption from the whole segment, so an option value
159
+ // is never mistaken for a pathspec: `-X <file>` reads the file, and
160
+ // `--pathspec-from-file=<file>` echoes its lines in the "did not match"
161
+ // error. `requires` names the option without which the subcommand stays
162
+ // checked (#4856 scopes `git rm` to `--cached`).
163
+ const GIT_PATHSPEC_SUBCOMMANDS = new Map([
164
+ ['check-ignore', {
165
+ flags: new Set(['-q', '--quiet', '-v', '--verbose', '--stdin', '-z', '-n', '--non-matching', '--no-index', '--index']),
166
+ }],
167
+ ['ls-files', {
168
+ flags: new Set([
169
+ '-z', '-t', '-v', '-f', '-c', '--cached', '-d', '--deleted', '-m', '--modified', '-o', '--others',
170
+ '-i', '--ignored', '-s', '--stage', '-k', '--killed', '-u', '--unmerged', '--directory', '--eol',
171
+ '--no-empty-directory', '--resolve-undo', '--exclude-standard', '--full-name',
172
+ '--recurse-submodules', '--error-unmatch', '--abbrev', '--debug', '--deduplicate', '--sparse',
173
+ ]),
174
+ }],
175
+ ['rm', {
176
+ flags: new Set(['--cached', '-f', '--force', '-n', '--dry-run', '-q', '--quiet', '-r', '--ignore-unmatch', '--sparse']),
177
+ requires: '--cached',
178
+ }],
179
+ ]);
180
+
181
+ // git's global options (its own usage line, git 2.49), needed to locate the
182
+ // subcommand. A value option consumes the next word unless written
183
+ // `--opt=value`; an option in neither set fails closed, so a value is never
184
+ // read as the subcommand (`git -C ls-files show HEAD:.env` runs `show`).
185
+ const GIT_GLOBAL_VALUE_OPTIONS = new Set(['-C', '-c', '--git-dir', '--work-tree', '--namespace', '--config-env']);
186
+ const GIT_GLOBAL_FLAGS = new Set([
187
+ '-p', '--paginate', '-P', '--no-pager', '--no-replace-objects', '--no-lazy-fetch',
188
+ '--no-optional-locks', '--no-advice', '--bare',
189
+ ]);
190
+
191
+ // #4856: `cp`/`mv` write their destination and never print it, so a secret
192
+ // name that is ONLY the destination of a one-source copy or move is a name
193
+ // (`cp .env.example .env`). The exemption holds for exactly two operands
194
+ // behind options from this closed set; anything else keeps the whole segment
195
+ // checked — `-t`/`--target-directory` (every operand becomes a source), a
196
+ // backup (`-b`, `--backup`, `-S`: the old secret survives as `.env~`, a name
197
+ // the predicate does not classify), a link (`-l`, `-s`) or `--exchange`
198
+ // (the destination shares or swaps the secret). Options must precede the
199
+ // operands: a trailing one is an option under GNU getopt's permutation but
200
+ // an operand under POSIXLY_CORRECT (`cp a .env -f` then copies `.env` INTO
201
+ // `-f/`), so which word is the destination would hang on an environment
202
+ // the hook cannot see.
203
+ const COPY_NAME_ONLY_FLAGS = new Set(['-f', '--force', '-i', '--interactive', '-n', '--no-clobber', '-v', '--verbose']);
204
+
130
205
  // Shell interpreters that run a script from `-c`, a file operand, or stdin
131
206
  // (heredoc / here-string / piped `echo`|`printf`). `su` is here for its `-c`
132
207
  // form (`su [user] -c 'cmd'`); a bare `su user` resolves to file mode, which
@@ -700,6 +775,86 @@ function resolveCommand(words) {
700
775
  return { base: lastSegment(words[idx].text).toLowerCase(), operands: words.slice(idx + 1) };
701
776
  }
702
777
 
778
+ // Operand indices the segment's command consumes as a NAME, never as
779
+ // CONTENTS (#4639, #4856). Only these positions skip the operand check;
780
+ // every other operand is still checked, so a carve-out cannot launder a read
781
+ // elsewhere in the segment.
782
+ function nameOnlyOperandIndices(base, operands) {
783
+ if (CONTAINER_RUNTIMES.has(base)) return envFileValueIndices(operands);
784
+ if (base === 'git') return gitPathspecIndices(operands);
785
+ if (base === 'cp' || base === 'mv') return copyDestinationIndices(operands);
786
+ return new Set();
787
+ }
788
+
789
+ // #4639: the `--env-file` word, plus the next operand for the bare flag
790
+ // (`--env-file=<value>` is a single word).
791
+ function envFileValueIndices(operands) {
792
+ const exempt = new Set();
793
+ for (let k = 0; k < operands.length; k++) {
794
+ if (!ENV_FILE_FLAG_RE.test(operands[k].text)) continue;
795
+ exempt.add(k);
796
+ if (!operands[k].text.includes('=')) exempt.add(++k);
797
+ }
798
+ return exempt;
799
+ }
800
+
801
+ // True when `text` is a listed long option, or a short cluster (`-co`) whose
802
+ // every letter is listed. `--opt=value`, an abbreviation, or a cluster
803
+ // holding a value option (`-ciX`) is not.
804
+ function isListedFlag(text, flags) {
805
+ if (text.startsWith('--')) return flags.has(text);
806
+ return /^-[A-Za-z]+$/.test(text) && [...text.slice(1)].every((ch) => flags.has(`-${ch}`));
807
+ }
808
+
809
+ // Index of git's subcommand past its global options, or -1 when an option
810
+ // outside GIT_GLOBAL_VALUE_OPTIONS / GIT_GLOBAL_FLAGS precedes it.
811
+ function gitSubcommandIndex(operands) {
812
+ for (let k = 0; k < operands.length; k++) {
813
+ const t = operands[k].text;
814
+ if (!t.startsWith('-')) return k;
815
+ if (GIT_GLOBAL_VALUE_OPTIONS.has(t)) { k++; continue; }
816
+ if (GIT_GLOBAL_FLAGS.has(t)) continue;
817
+ const eq = t.indexOf('=');
818
+ const isLongValueForm = t.startsWith('--') && eq !== -1 && GIT_GLOBAL_VALUE_OPTIONS.has(t.slice(0, eq));
819
+ if (!isLongValueForm) return -1;
820
+ }
821
+ return -1;
822
+ }
823
+
824
+ // #4856: the pathspec operands of a GIT_PATHSPEC_SUBCOMMANDS invocation. git
825
+ // permutes options, so one may follow a pathspec; after `--` every word is a
826
+ // pathspec. The subcommand is matched case-sensitively, as git looks it up.
827
+ function gitPathspecIndices(operands) {
828
+ const sub = gitSubcommandIndex(operands);
829
+ const spec = sub === -1 ? undefined : GIT_PATHSPEC_SUBCOMMANDS.get(operands[sub].text);
830
+ if (!spec) return new Set();
831
+ const pathspecs = new Set();
832
+ let required = spec.requires === undefined;
833
+ let endOfOptions = false;
834
+ for (let k = sub + 1; k < operands.length; k++) {
835
+ const t = operands[k].text;
836
+ if (endOfOptions || !t.startsWith('-') || t === '-') pathspecs.add(k);
837
+ else if (t === '--') endOfOptions = true;
838
+ else if (!isListedFlag(t, spec.flags)) return new Set();
839
+ else if (t === spec.requires) required = true;
840
+ }
841
+ return required ? pathspecs : new Set();
842
+ }
843
+
844
+ // #4856: the destination of a one-source `cp`/`mv` (see COPY_NAME_ONLY_FLAGS).
845
+ function copyDestinationIndices(operands) {
846
+ const positional = [];
847
+ let endOfOptions = false;
848
+ for (let k = 0; k < operands.length; k++) {
849
+ const t = operands[k].text;
850
+ if (endOfOptions || !t.startsWith('-') || t === '-') positional.push(k);
851
+ else if (positional.length) return new Set(); // an option or `--` after an operand
852
+ else if (t === '--') endOfOptions = true;
853
+ else if (!isListedFlag(t, COPY_NAME_ONLY_FLAGS)) return new Set();
854
+ }
855
+ return positional.length === 2 ? new Set([positional[1]]) : new Set();
856
+ }
857
+
703
858
  // The statically-knowable stdin a segment writes: `echo`/`printf` operands
704
859
  // joined by a space (for `echo`, leading `-neE` flags dropped). Any other
705
860
  // source (`cat gen.sh | bash`, `curl … | sh`) is not knowable → null.
@@ -840,8 +995,10 @@ function findSecretRead(command, depth) {
840
995
 
841
996
  if (NON_READING_COMMANDS.has(base)) continue;
842
997
 
843
- for (const w of operands) {
844
- if (namesSecret(normalizeOperand(w.text))) return w.text;
998
+ const nameOnly = nameOnlyOperandIndices(base, operands);
999
+ for (let k = 0; k < operands.length; k++) {
1000
+ if (nameOnly.has(k)) continue;
1001
+ if (namesSecret(normalizeOperand(operands[k].text))) return operands[k].text;
845
1002
  }
846
1003
  }
847
1004
  return null;
@@ -3,6 +3,14 @@
3
3
  // Claude Code Statusline - GSD Edition
4
4
  // Shows: model | current task (or GSD state) | directory | context usage
5
5
 
6
+ // #5183: Node's on-disk compile cache, so later runs reuse V8's compiled code
7
+ // for unchanged modules. Only as the entry (a test require() is unaffected),
8
+ // skipped under V8 coverage, optional (Bun stubs it), and never fatal.
9
+ // NODE_DISABLE_COMPILE_CACHE (any value) turns it off.
10
+ if (require.main === module && !process.env.NODE_V8_COVERAGE) {
11
+ try { require('node:module').enableCompileCache?.(); } catch { /* optimization only */ }
12
+ }
13
+
6
14
  const fs = require('fs');
7
15
  const path = require('path');
8
16
  const os = require('os');
@@ -42,6 +50,11 @@ if (require.main === module) {
42
50
  const { isSemverNewer } = require('../gsd-core/bin/lib/semver-compare.cjs');
43
51
  const { PACKAGE_NAME, updateCacheFileName } = require('../gsd-core/bin/lib/package-identity.cjs');
44
52
  const { normalizeStateStatus } = require('../gsd-core/bin/lib/state-document.cjs');
53
+ const { locateFrontmatterFence } = require('../gsd-core/bin/lib/frontmatter-fence.cjs');
54
+ const {
55
+ renderBracketPhaseDisplay,
56
+ renderBracketMilestoneDisplay,
57
+ } = require('../gsd-core/bin/lib/phase-id-display.cjs');
45
58
  // #2850: reuse the existing workstream resolution seams rather than
46
59
  // re-implementing CLI>env>store precedence or path construction inline.
47
60
  // peekActiveWorkstream is the read-only sibling of the store-tier lookup
@@ -246,13 +259,12 @@ function readGsdState(dir, opts = {}) {
246
259
  function parseStateMd(content) {
247
260
  const state = {};
248
261
 
249
- // YAML frontmatter between --- markers (anchored at file start).
250
- // #2754: \r?\n (not literal \n) so a CRLF STATE.md (Windows-authored) parses
251
- // identically to LF — pre-fix the literal-\n fence dropped the ENTIRE block.
252
- // Mirrors the CRLF-safe extractFrontmatter in src/frontmatter.cts.
253
- const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
254
- if (fmMatch) {
255
- const fm = fmMatch[1];
262
+ // YAML frontmatter: the block the one fence owner finds (`locateFrontmatterFence`), so a
263
+ // CRLF STATE.md (#2754), a BOM, and a `---` inside a value read exactly as every other
264
+ // STATE.md reader reads them (found while implementing #5105).
265
+ const fence = locateFrontmatterFence(content);
266
+ if (fence && fence.closed) {
267
+ const fm = content.slice(fence.openEnd, fence.bodyEnd);
256
268
  // Top-level scalar key: value
257
269
  for (const line of fm.split(/\r?\n/)) {
258
270
  const m = line.match(/^(\w+):\s*(.+)/);
@@ -359,16 +371,26 @@ function renderProgressBar(percent) {
359
371
  * Progress bar is opt-in: appended to the milestone segment only when
360
372
  * progress.percent is present in frontmatter; absent → empty string.
361
373
  */
362
- function formatGsdState(s) {
374
+ function formatGsdState(s, opts = {}) {
363
375
  // #2850: workstream mode with nothing resolvable — an observable signal,
364
376
  // never silent emptiness (distinguishes from "GSD isn't installed here").
365
377
  if (s.noActiveWorkstream) return NO_ACTIVE_WORKSTREAM_LABEL;
366
378
 
367
379
  const parts = [];
380
+ const bracket = opts.convention === 'bracket';
381
+ const bracketMilestone = bracket
382
+ ? renderBracketMilestoneDisplay(s.milestone, opts.projectCode)
383
+ : null;
384
+ const phaseLabel = (phase) => {
385
+ const display = bracket
386
+ ? renderBracketPhaseDisplay(s.milestone, phase, opts.projectCode)
387
+ : null;
388
+ return display ?? `Phase ${phase}`;
389
+ };
368
390
 
369
391
  // Milestone segment: version + name + (opt-in) progress bar
370
392
  if (s.milestone || s.milestoneName) {
371
- const ver = s.milestone || '';
393
+ const ver = bracketMilestone ?? s.milestone ?? '';
372
394
  const name = (s.milestoneName && s.milestoneName !== 'milestone') ? s.milestoneName : '';
373
395
  const bar = renderProgressBar(s.percent);
374
396
  const pieces = [ver, name, bar].filter(Boolean);
@@ -384,7 +406,8 @@ function formatGsdState(s) {
384
406
  // stage = whichever lifecycle status was written by the orchestrator
385
407
  // (discussing / planning / executing / verifying)
386
408
  const stage = s.status || '';
387
- parts.push(stage ? `Phase ${s.activePhase} ${stage}` : `Phase ${s.activePhase}`);
409
+ const phase = phaseLabel(s.activePhase);
410
+ parts.push(stage ? `${phase} ${stage}` : phase);
388
411
  } else if (s.nextAction && phasesStr) {
389
412
  // Scene 2: idle + a recommended next command is visible to the user.
390
413
  // Surfaces "what to run next" without the user opening STATE.md.
@@ -402,9 +425,16 @@ function formatGsdState(s) {
402
425
  // earlier so no existing project's status-line changes shape.
403
426
  if (s.status) parts.push(s.status);
404
427
  if (s.phaseNum && s.phaseTotal) {
428
+ const bracketPhase = bracket
429
+ ? renderBracketPhaseDisplay(s.milestone, s.phaseNum, opts.projectCode)
430
+ : null;
405
431
  const phase = s.phaseName
406
- ? `${s.phaseName} (${s.phaseNum}/${s.phaseTotal})`
407
- : `ph ${s.phaseNum}/${s.phaseTotal}`;
432
+ ? bracketPhase
433
+ ? `${bracketPhase} ${s.phaseName} (${s.phaseNum}/${s.phaseTotal})`
434
+ : `${s.phaseName} (${s.phaseNum}/${s.phaseTotal})`
435
+ : bracketPhase
436
+ ? `${bracketPhase} (${s.phaseNum}/${s.phaseTotal})`
437
+ : `ph ${s.phaseNum}/${s.phaseTotal}`;
408
438
  parts.push(phase);
409
439
  }
410
440
  }
@@ -490,17 +520,24 @@ function shortGsdStatus(status) {
490
520
  * default format — and collapses narrative statuses via shortGsdStatus().
491
521
  * The default "full" format is untouched.
492
522
  */
493
- function formatGsdStateCompact(s) {
523
+ function formatGsdStateCompact(s, opts = {}) {
494
524
  // #2850: mirrors formatGsdState's observable "nothing resolvable" signal.
495
525
  if (s.noActiveWorkstream) return NO_ACTIVE_WORKSTREAM_LABEL;
496
526
 
497
527
  const parts = [];
528
+ const bracket = opts.convention === 'bracket';
529
+ const bracketMilestone = bracket
530
+ ? renderBracketMilestoneDisplay(s.milestone, opts.projectCode)
531
+ : null;
498
532
 
499
- if (s.milestone) parts.push(s.milestone);
533
+ if (s.milestone) parts.push(bracketMilestone ?? s.milestone);
500
534
 
501
535
  const phaseId = s.activePhase || s.phaseNum;
502
536
  if (phaseId) {
503
- parts.push(s.phaseTotal ? `P${phaseId}/${s.phaseTotal}` : `P${phaseId}`);
537
+ const bracketPhase = bracket
538
+ ? renderBracketPhaseDisplay(s.milestone, phaseId, opts.projectCode)
539
+ : null;
540
+ parts.push(bracketPhase ?? (s.phaseTotal ? `P${phaseId}/${s.phaseTotal}` : `P${phaseId}`));
504
541
  }
505
542
 
506
543
  // Scene exclusivity mirrors formatGsdState's if/else chain: an in-flight
@@ -747,7 +784,7 @@ function formatStateFreshness(fresh) {
747
784
  * entry points — this collapses both onto one resolver.
748
785
  *
749
786
  * @param {object} cfg — parsed .planning/config.json (readGsdConfig())
750
- * @returns {{ showLastCommand: boolean, position: 'end'|'front', stateFormat: 'full'|'compact', showGit: boolean, showStateFreshness: boolean }}
787
+ * @returns {{ showLastCommand: boolean, position: 'end'|'front', stateFormat: 'full'|'compact', showGit: boolean, showStateFreshness: boolean, convention: string|null, projectCode: string|null }}
751
788
  */
752
789
  function resolveStatuslineOptions(cfg) {
753
790
  const showLastCommand = getConfigValue(cfg, 'statusline.show_last_command') === true;
@@ -759,7 +796,22 @@ function resolveStatuslineOptions(cfg) {
759
796
  const stateFormat = getConfigValue(cfg, 'statusline.state_format') === 'compact' ? 'compact' : 'full';
760
797
  const showGit = getConfigValue(cfg, 'statusline.show_git') === true;
761
798
  const showStateFreshness = getConfigValue(cfg, 'statusline.show_state_freshness') === true;
762
- return { showLastCommand, position, stateFormat, showGit, showStateFreshness };
799
+ const convention = getConfigValue(cfg, 'phase_id_convention') === 'bracket'
800
+ ? 'bracket'
801
+ : null;
802
+ const projectCodeValue = getConfigValue(cfg, 'project_code');
803
+ const projectCode = typeof projectCodeValue === 'string' && projectCodeValue !== ''
804
+ ? projectCodeValue
805
+ : null;
806
+ return {
807
+ showLastCommand,
808
+ position,
809
+ stateFormat,
810
+ showGit,
811
+ showStateFreshness,
812
+ convention,
813
+ projectCode,
814
+ };
763
815
  }
764
816
 
765
817
  // --- stdin ------------------------------------------------------------------
@@ -934,7 +986,9 @@ function runStatusline() {
934
986
  // freshness git spawn here would spend a subprocess on discarded output.
935
987
  if (!task) {
936
988
  const state = readGsdState(dir, { stateFreshness: options.showStateFreshness }) || {};
937
- gsdStateStr = options.stateFormat === 'compact' ? formatGsdStateCompact(state) : formatGsdState(state);
989
+ gsdStateStr = options.stateFormat === 'compact'
990
+ ? formatGsdStateCompact(state, options)
991
+ : formatGsdState(state, options);
938
992
  }
939
993
 
940
994
  // Output
@@ -1042,6 +1096,7 @@ module.exports = {
1042
1096
  STATE_HEAD_ADVISORY_COMMITS, isValidStateHeadStamp,
1043
1097
  readStateHeadCommits, parseRevListCounts, deriveStateFreshness,
1044
1098
  formatStateFreshness, resolveStatuslineOptions,
1099
+ renderBracketPhaseDisplay, renderBracketMilestoneDisplay,
1045
1100
  };
1046
1101
 
1047
1102
  /**
@@ -1059,7 +1114,15 @@ function renderStatusline(data) {
1059
1114
  // key from reaching only one of them.
1060
1115
  let lastCmdSuffix = '';
1061
1116
  let gitSuffix = '';
1062
- let options = { showLastCommand: false, position: 'end', stateFormat: 'full', showGit: false, showStateFreshness: false };
1117
+ let options = {
1118
+ showLastCommand: false,
1119
+ position: 'end',
1120
+ stateFormat: 'full',
1121
+ showGit: false,
1122
+ showStateFreshness: false,
1123
+ convention: null,
1124
+ projectCode: null,
1125
+ };
1063
1126
  try {
1064
1127
  const cfg = readGsdConfig(dir);
1065
1128
  options = resolveStatuslineOptions(cfg);
@@ -1075,7 +1138,9 @@ function renderStatusline(data) {
1075
1138
  } catch (e) { /* swallow */ }
1076
1139
 
1077
1140
  const state = readGsdState(dir, { stateFreshness: options.showStateFreshness }) || {};
1078
- const gsdStateStr = options.stateFormat === 'compact' ? formatGsdStateCompact(state) : formatGsdState(state);
1141
+ const gsdStateStr = options.stateFormat === 'compact'
1142
+ ? formatGsdStateCompact(state, options)
1143
+ : formatGsdState(state, options);
1079
1144
  const middle = gsdStateStr ? `\x1b[2m${gsdStateStr}\x1b[0m` : null;
1080
1145
  return composeStatusline({ model, ctx: '', middle, dirname, lastCmdSuffix, gitSuffix, position: options.position });
1081
1146
  }
@@ -12,6 +12,14 @@
12
12
 
13
13
  'use strict';
14
14
 
15
+ // #5183: Node's on-disk compile cache, so later runs reuse V8's compiled code
16
+ // for unchanged modules. Only as the entry (a test require() is unaffected),
17
+ // skipped under V8 coverage, optional (Bun stubs it), and never fatal.
18
+ // NODE_DISABLE_COMPILE_CACHE (any value) turns it off.
19
+ if (require.main === module && !process.env.NODE_V8_COVERAGE) {
20
+ try { require('node:module').enableCompileCache?.(); } catch { /* optimization only */ }
21
+ }
22
+
15
23
  const fs = require('fs');
16
24
  const path = require('path');
17
25
  const os = require('os');