@ornexus/neocortex 4.60.66 → 4.60.68

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 (236) hide show
  1. package/dist/release-source.json +1 -1
  2. package/dist/sbom.cdx.json +1598 -1640
  3. package/install.ps1 +1 -1
  4. package/install.sh +2 -1
  5. package/package.json +10 -7
  6. package/packages/client/dist/adapters/adapter-registry.js +108 -1
  7. package/packages/client/dist/adapters/antigravity-adapter.js +77 -2
  8. package/packages/client/dist/adapters/claude-code-adapter.js +79 -3
  9. package/packages/client/dist/adapters/codex-adapter.js +80 -2
  10. package/packages/client/dist/adapters/cursor-adapter.js +115 -4
  11. package/packages/client/dist/adapters/gemini-adapter.js +71 -2
  12. package/packages/client/dist/adapters/grok-adapter.js +42 -2
  13. package/packages/client/dist/adapters/index.js +22 -1
  14. package/packages/client/dist/adapters/platform-detector.js +212 -1
  15. package/packages/client/dist/adapters/target-adapter.js +12 -0
  16. package/packages/client/dist/adapters/vscode-adapter.js +72 -2
  17. package/packages/client/dist/agent/refresh-stubs.js +417 -2
  18. package/packages/client/dist/agent/update-agent-yaml.js +102 -1
  19. package/packages/client/dist/agent/update-description.js +251 -1
  20. package/packages/client/dist/cache/crypto-utils.js +78 -1
  21. package/packages/client/dist/cache/encrypted-cache.js +108 -1
  22. package/packages/client/dist/cache/in-memory-asset-cache.js +73 -1
  23. package/packages/client/dist/cache/index.js +13 -1
  24. package/packages/client/dist/cache/protected-pi-boundary.js +44 -1
  25. package/packages/client/dist/checkpoint/checkpoint-client-reader.js +127 -2
  26. package/packages/client/dist/checkpoint/index.js +11 -1
  27. package/packages/client/dist/checkpoint/shared-checkpoint-types.js +32 -1
  28. package/packages/client/dist/cli.js +303 -3
  29. package/packages/client/dist/commands/activate.js +394 -8
  30. package/packages/client/dist/commands/architecture-answers.js +274 -7
  31. package/packages/client/dist/commands/architecture-memory-terminal.js +253 -4
  32. package/packages/client/dist/commands/architecture-non-ui-continuation.js +100 -1
  33. package/packages/client/dist/commands/architecture-root-binding.js +51 -1
  34. package/packages/client/dist/commands/cache-status.js +112 -2
  35. package/packages/client/dist/commands/config.js +88 -1
  36. package/packages/client/dist/commands/doctor.d.ts +135 -0
  37. package/packages/client/dist/commands/doctor.js +635 -0
  38. package/packages/client/dist/commands/invoke.d.ts +18 -0
  39. package/packages/client/dist/commands/invoke.js +7140 -142
  40. package/packages/client/dist/commands/legacy-epic-terminal.js +71 -1
  41. package/packages/client/dist/commands/legacy-story-branch.js +96 -1
  42. package/packages/client/dist/commands/legacy-story-pr.js +276 -1
  43. package/packages/client/dist/commands/mutation-qa-checkpoint.js +285 -5
  44. package/packages/client/dist/commands/mutation-qa-gate.js +54 -1
  45. package/packages/client/dist/commands/mutation-qa-git.js +41 -1
  46. package/packages/client/dist/commands/mutation-qa-policy.js +102 -1
  47. package/packages/client/dist/commands/mutation-qa-run.js +219 -3
  48. package/packages/client/dist/commands/mutation-qa-verdict.js +149 -1
  49. package/packages/client/dist/commands/mutation-qa.js +220 -1
  50. package/packages/client/dist/commands/native-agent.js +136 -2
  51. package/packages/client/dist/commands/planning-diagnosis.js +43 -1
  52. package/packages/client/dist/commands/planning-generation.js +53 -1
  53. package/packages/client/dist/commands/planning-memory.js +40 -1
  54. package/packages/client/dist/commands/planning-research.js +42 -1
  55. package/packages/client/dist/commands/private-session.js +75 -1
  56. package/packages/client/dist/commands/property-qa.js +139 -1
  57. package/packages/client/dist/commands/qa-control.js +16 -1
  58. package/packages/client/dist/commands/qa-scan-browser-launch.js +55 -1
  59. package/packages/client/dist/commands/qa-scan-browser-route.js +28 -1
  60. package/packages/client/dist/commands/qa-scan-capture.js +663 -5
  61. package/packages/client/dist/commands/qa-scan-discovery.js +376 -3
  62. package/packages/client/dist/commands/qa-scan-review.js +826 -5
  63. package/packages/client/dist/commands/qa-synthetic-backend-capture.js +266 -1
  64. package/packages/client/dist/commands/qa-synthetic-backend-review.js +297 -1
  65. package/packages/client/dist/commands/qa-synthetic-backend.js +340 -2
  66. package/packages/client/dist/commands/qa-synthetic-broker-port.js +85 -1
  67. package/packages/client/dist/commands/qa-synthetic-browser.js +39 -1
  68. package/packages/client/dist/commands/refactor-characterization.js +671 -21
  69. package/packages/client/dist/commands/refactor-commit.js +399 -13
  70. package/packages/client/dist/commands/refactor-control.js +142 -3
  71. package/packages/client/dist/commands/refactor-cpp-assertions.js +93 -3
  72. package/packages/client/dist/commands/refactor-review.js +283 -5
  73. package/packages/client/dist/commands/refactor-root.js +588 -7
  74. package/packages/client/dist/commands/refresh-memory.js +156 -3
  75. package/packages/client/dist/commands/shared-architecture-non-ui.js +24 -1
  76. package/packages/client/dist/commands/story-checkpoint.js +171 -1
  77. package/packages/client/dist/config/profile-directory.js +13 -1
  78. package/packages/client/dist/config/resolver-selection.js +278 -1
  79. package/packages/client/dist/config/secure-config.js +281 -12
  80. package/packages/client/dist/config.js +223 -2
  81. package/packages/client/dist/constants.js +25 -1
  82. package/packages/client/dist/context/context-collector.js +222 -2
  83. package/packages/client/dist/context/context-sanitizer.js +145 -1
  84. package/packages/client/dist/continuity/autonomous-governance.js +285 -1
  85. package/packages/client/dist/continuity/continuity-client-state-store.js +1587 -1
  86. package/packages/client/dist/continuity/invoke-hooks.js +129 -1
  87. package/packages/client/dist/continuity/migrations/001-initial-schema.js +12 -2
  88. package/packages/client/dist/continuity/migrations/002-processing-output-summary-indexes.js +12 -2
  89. package/packages/client/dist/continuity/migrations/003-headless-execution-attempts.js +12 -2
  90. package/packages/client/dist/continuity/migrations/004-outbox-delivery-state.js +12 -2
  91. package/packages/client/dist/continuity/migrations/005-bounded-headless-queue.js +12 -2
  92. package/packages/client/dist/continuity/migrations/006-native-agent-dispatches.js +10 -2
  93. package/packages/client/dist/continuity/native-agent-store.js +69 -1
  94. package/packages/client/dist/continuity/native-agent-types.js +90 -1
  95. package/packages/client/dist/continuity/outbox.js +117 -1
  96. package/packages/client/dist/continuity/runner-bootstrap-policy.js +172 -1
  97. package/packages/client/dist/continuity/sqlite-store.js +2536 -81
  98. package/packages/client/dist/effects/invoke-effect-gateways.js +62 -1
  99. package/packages/client/dist/errors/error-messages.js +228 -2
  100. package/packages/client/dist/errors/frontmatter-diagnostics.js +125 -1
  101. package/packages/client/dist/evidence/collector.js +347 -1
  102. package/packages/client/dist/evidence/index.js +1 -1
  103. package/packages/client/dist/evidence/types.js +2 -0
  104. package/packages/client/dist/fs/atomic-state-replace.js +152 -1
  105. package/packages/client/dist/generated/command-registry.generated.js +4076 -1
  106. package/packages/client/dist/generated/public-projections.generated.js +149 -1
  107. package/packages/client/dist/git/direct-yolo-c01-retry.js +138 -4
  108. package/packages/client/dist/git/direct-yolo-checkpoint.js +1234 -4
  109. package/packages/client/dist/git/git-lifecycle-step-ids.js +14 -1
  110. package/packages/client/dist/git/git-lifecycle-store.js +1938 -9
  111. package/packages/client/dist/git/legacy-story-branch-checkpoint.js +259 -9
  112. package/packages/client/dist/git/legacy-story-branch-setup.js +348 -4
  113. package/packages/client/dist/git/legacy-story-pr.js +3538 -70
  114. package/packages/client/dist/git/secure-filesystem-boundary.js +182 -5
  115. package/packages/client/dist/graph-retrieval/pre-command-hook.js +284 -1
  116. package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.js +237 -1
  117. package/packages/client/dist/i18n/first-run.js +60 -2
  118. package/packages/client/dist/index.js +47 -1
  119. package/packages/client/dist/invocation/invoke-input.js +24 -1
  120. package/packages/client/dist/license/index.js +5 -1
  121. package/packages/client/dist/license/license-client.js +304 -1
  122. package/packages/client/dist/machine/fingerprint.js +163 -2
  123. package/packages/client/dist/machine/index.js +5 -1
  124. package/packages/client/dist/memory/project-memory-path-scope.js +62 -1
  125. package/packages/client/dist/memory/project-memory-writer.js +1007 -40
  126. package/packages/client/dist/memory/shared-project-memory-types.js +253 -2
  127. package/packages/client/dist/migrations/project-identity-capability.js +50 -1
  128. package/packages/client/dist/migrations/project-identity.js +493 -7
  129. package/packages/client/dist/migrations/state-json.js +344 -4
  130. package/packages/client/dist/policy/architecture-policy.js +184 -2
  131. package/packages/client/dist/policy/index.js +7 -1
  132. package/packages/client/dist/policy/shared-policy-types.js +38 -0
  133. package/packages/client/dist/policy/subagent-approval-policy.js +55 -1
  134. package/packages/client/dist/private-execution/clean-baseline.js +279 -2
  135. package/packages/client/dist/private-execution/codex-executor.js +574 -4
  136. package/packages/client/dist/private-execution/codex-host-runtime.js +137 -1
  137. package/packages/client/dist/private-execution/codex-lifecycle-guard.js +97 -1
  138. package/packages/client/dist/private-execution/codex-scoped-permissions.js +128 -1
  139. package/packages/client/dist/private-execution/delivery.js +410 -13
  140. package/packages/client/dist/private-execution/diagnosis-root-review.js +294 -2
  141. package/packages/client/dist/private-execution/frozen-handoff.js +19 -6
  142. package/packages/client/dist/private-execution/implementation-validation.js +106 -2
  143. package/packages/client/dist/private-execution/isolated-admission.js +1432 -23
  144. package/packages/client/dist/private-execution/isolated-session.js +725 -5
  145. package/packages/client/dist/private-execution/isolated-workspace.js +122 -1
  146. package/packages/client/dist/private-execution/pact-consumer-runtime.js +409 -3
  147. package/packages/client/dist/private-execution/pact-test-source.js +258 -1
  148. package/packages/client/dist/private-execution/pact-toolchain.js +290 -3
  149. package/packages/client/dist/private-execution/pact-write-set.js +172 -1
  150. package/packages/client/dist/private-execution/planning-diagnosis-checkpoint.js +406 -5
  151. package/packages/client/dist/private-execution/planning-generation-checkpoint.js +462 -5
  152. package/packages/client/dist/private-execution/planning-memory-checkpoint.js +139 -3
  153. package/packages/client/dist/private-execution/planning-research-checkpoint.js +325 -4
  154. package/packages/client/dist/private-execution/private-report-store.js +42 -1
  155. package/packages/client/dist/private-execution/property-test-candidate.js +103 -1
  156. package/packages/client/dist/private-execution/property-test-choices.js +147 -3
  157. package/packages/client/dist/private-execution/property-test-plan.js +271 -7
  158. package/packages/client/dist/private-execution/property-test-review.js +258 -4
  159. package/packages/client/dist/private-execution/property-test-runtime.js +372 -9
  160. package/packages/client/dist/private-execution/property-test-source.js +139 -1
  161. package/packages/client/dist/private-execution/root-checkpoint.js +80 -1
  162. package/packages/client/dist/private-execution/root-memory-git-evidence.js +135 -3
  163. package/packages/client/dist/private-execution/root-memory-recovery.js +93 -1
  164. package/packages/client/dist/private-execution/root-memory-request.js +29 -1
  165. package/packages/client/dist/private-execution/root-memory-scope.js +178 -1
  166. package/packages/client/dist/private-execution/root-memory-writer.js +102 -1
  167. package/packages/client/dist/private-execution/session-lease.js +63 -1
  168. package/packages/client/dist/private-execution/shared-private-admission-types.js +50 -1
  169. package/packages/client/dist/private-execution/shared-project-validation.js +66 -1
  170. package/packages/client/dist/private-execution/shared-root-memory-types.js +61 -1
  171. package/packages/client/dist/private-execution/ux-source-validation.js +372 -1
  172. package/packages/client/dist/private-execution/ux-write-set.js +191 -2
  173. package/packages/client/dist/resilience/circuit-breaker.js +170 -1
  174. package/packages/client/dist/resilience/degradation-manager.js +164 -1
  175. package/packages/client/dist/resilience/freshness-indicator.js +100 -1
  176. package/packages/client/dist/resilience/index.js +8 -1
  177. package/packages/client/dist/resilience/recovery-detector.js +74 -1
  178. package/packages/client/dist/resolvers/asset-resolver.js +13 -0
  179. package/packages/client/dist/resolvers/local-resolver.js +255 -8
  180. package/packages/client/dist/resolvers/remote-resolver.js +233 -1
  181. package/packages/client/dist/runner/binary.js +404 -1
  182. package/packages/client/dist/runner/cli.js +1571 -17
  183. package/packages/client/dist/runner/headless/adapters.js +49 -1
  184. package/packages/client/dist/runner/headless/claude-code-adapter.js +79 -1
  185. package/packages/client/dist/runner/headless/continuous-story-workspace.js +1628 -11
  186. package/packages/client/dist/runner/headless/epic-git-reconciliation-inventory.js +69 -1
  187. package/packages/client/dist/runner/headless/epic-merge-candidate-qa.js +110 -2
  188. package/packages/client/dist/runner/headless/epic-terminal-git-cli-adapter.js +1236 -8
  189. package/packages/client/dist/runner/headless/epic-terminal-git-runner.js +318 -2
  190. package/packages/client/dist/runner/headless/fake-adapter.js +62 -1
  191. package/packages/client/dist/runner/headless/managed-profile.js +132 -1
  192. package/packages/client/dist/runner/headless/opencode-adapter.js +145 -2
  193. package/packages/client/dist/runner/headless/prepared-story-bundle.js +43 -1
  194. package/packages/client/dist/runner/headless/resolver.js +231 -1
  195. package/packages/client/dist/runner/headless/run-yolo.js +885 -1
  196. package/packages/client/dist/runner/headless/run-yoloop.d.ts +4 -1
  197. package/packages/client/dist/runner/headless/run-yoloop.js +2574 -2
  198. package/packages/client/dist/runner/headless/types.js +574 -2
  199. package/packages/client/dist/runner/local-console.js +396 -13
  200. package/packages/client/dist/runner/portal-sync-worker.js +1487 -1
  201. package/packages/client/dist/runner/project-identity.js +106 -1
  202. package/packages/client/dist/runner/scheduler.js +995 -7
  203. package/packages/client/dist/runner-cli.js +18 -2
  204. package/packages/client/dist/state/invocation-shape.js +13 -1
  205. package/packages/client/dist/state/project-state-snapshot.js +1677 -1
  206. package/packages/client/dist/state/state-json-repair.js +785 -3
  207. package/packages/client/dist/state/structural-dag-projection.js +118 -1
  208. package/packages/client/dist/telemetry/index.js +5 -1
  209. package/packages/client/dist/telemetry/offline-queue.js +131 -1
  210. package/packages/client/dist/tier/index.js +5 -1
  211. package/packages/client/dist/tier/tier-aware-client.js +405 -1
  212. package/packages/client/dist/types/index.js +38 -1
  213. package/packages/client/dist/version.js +27 -1
  214. package/packages/client/dist/yolo/change-evidence-collector.js +126 -1
  215. package/packages/client/dist/yolo/invoke-envelope-capability.js +62 -1
  216. package/packages/client/dist/yolo/spec-envelope-collector.js +185 -5
  217. package/packages/client/dist/yoloop/discovery-hook.js +300 -2
  218. package/packages/client/dist/yoloop/index.js +8 -1
  219. package/packages/client/dist/yoloop/invoke-hooks.js +669 -12
  220. package/packages/client/dist/yoloop/shared-discover-epics.js +1007 -1
  221. package/packages/client/dist/yoloop/shared-yoloop-types.js +33 -1
  222. package/packages/client/dist/yoloop/target-normalization.js +180 -1
  223. package/packages/client/dist/yoloop/yoloop-client-state-store.js +1723 -1
  224. package/packages/shared/dist/compatibility/index.js +476 -0
  225. package/packages/shared/dist/yoloop/release-blocked.js +653 -0
  226. package/targets-stubs/antigravity/gemini.md +1 -1
  227. package/targets-stubs/antigravity/skill/SKILL.md +3 -2
  228. package/targets-stubs/claude-code/neocortex-root.agent.yaml +1 -1
  229. package/targets-stubs/claude-code/neocortex-root.md +5 -5
  230. package/targets-stubs/claude-code/neocortex.agent.yaml +1 -1
  231. package/targets-stubs/claude-code/neocortex.md +8 -9
  232. package/targets-stubs/codex/AGENTS.md +3 -3
  233. package/targets-stubs/cursor/agent.md +4 -3
  234. package/targets-stubs/gemini-cli/agent.md +5 -4
  235. package/targets-stubs/opencode/neocortex-root.md +3 -3
  236. package/targets-stubs/vscode/neocortex.agent.md +5 -4
@@ -1 +1,1677 @@
1
- import{createHash as H}from"node:crypto";import{analyzeDependencyDag as I,StructuralDagError as y}from"./structural-dag-projection.js";import{classifyInvocationShapeV2 as O}from"./invocation-shape.js";const U=12,J=16,k=["active","archived","rolled-back","synthetic","orphan"],Q=new Set(["in-progress","branch-ready","diagnose","research","write-spec","create-tasks","implemented","refactor-suggest-done","property-tests-emitted","tests-validated","qa-gate-passed","memory-updated","committed","synced","pr-created","pr-reviewed","partial"]),n=(r,e,t={})=>({commandId:r,stateProjectionPolicy:e,...t}),A=Object.freeze({status:n("status","full"),"arch-plan":n("arch-plan","full"),"arch-prd":n("arch-prd","full"),"arch-architecture":n("arch-architecture","epic-targeted",{structuralRequired:!0}),"arch-api-contracts":n("arch-api-contracts","epic-targeted",{structuralRequired:!0}),"arch-api-integrations":n("arch-api-integrations","epic-targeted",{structuralRequired:!0}),"arch-database":n("arch-database","epic-targeted",{structuralRequired:!0}),"arch-security":n("arch-security","epic-targeted",{structuralRequired:!0}),"arch-design-system":n("arch-design-system","epic-targeted",{structuralRequired:!0}),"arch-ux-design":n("arch-ux-design","epic-targeted",{structuralRequired:!0}),"arch-performance":n("arch-performance","epic-targeted",{structuralRequired:!0}),"arch-testing":n("arch-testing","epic-targeted",{structuralRequired:!0}),"arch-infrastructure":n("arch-infrastructure","epic-targeted",{structuralRequired:!0}),"arch-review":n("arch-review","epic-targeted",{structuralRequired:!0}),"arch-fitness-functions":n("arch-fitness-functions","epic-targeted",{structuralRequired:!0}),"create-epic":n("create-epic","epic-summary"),"idea-diagnose":n("idea-diagnose","full"),"idea-research":n("idea-research","epic-targeted",{structuralRequired:!0}),"generate-epic":n("generate-epic","epic-targeted",{structuralRequired:!0}),exec:n("exec","story-targeted",{structuralRequired:!0}),yolo:n("yolo","story-targeted",{structuralRequired:!0}),"yolo-inline":n("yolo-inline","story-targeted",{structuralRequired:!0}),epic:n("epic","epic-targeted",{structuralRequired:!0}),"setup-branch":n("setup-branch","story-targeted",{structuralRequired:!0}),diagnose:n("diagnose","adaptive-targeted"),"diagnose-inline":n("diagnose-inline","full"),research:n("research","adaptive-targeted"),"research-inline":n("research-inline","full"),"write-spec":n("write-spec","story-targeted",{structuralRequired:!0}),"create-tasks":n("create-tasks","story-targeted",{structuralRequired:!0}),implement:n("implement","story-targeted",{structuralRequired:!0}),commit:n("commit","story-targeted",{structuralRequired:!0}),"commit-push":n("commit","story-targeted",{structuralRequired:!0}),sync:n("sync","story-targeted",{structuralRequired:!0}),"sync-main":n("sync","story-targeted",{structuralRequired:!0}),"create-pr":n("create-pr","story-targeted",{structuralRequired:!0}),review:n("review","story-targeted"),"review-pr":n("review","story-targeted"),merge:n("merge","story-targeted",{structuralRequired:!0}),"merge-pr":n("merge","story-targeted",{structuralRequired:!0}),"fix-blocked":n("fix-blocked","story-targeted"),"finalize-epic":n("finalize-epic","epic-targeted"),"resolve-conflicts":n("resolve-conflicts","story-targeted"),"update-memory":n("update-memory","full"),"update-project-memory":n("update-memory","story-targeted",{structuralRequired:!0}),refactor:n("refactor","adaptive-targeted"),"refactor-suggest":n("refactor","story-targeted",{structuralRequired:!0}),cleanup:n("cleanup","full"),audit:n("audit","full"),"tech-debt":n("tech-debt","full"),menu:n("menu","full"),plans:n("plans","full"),billing:n("billing","full"),subscribe:n("subscribe","full"),"qa-scan":n("qa-scan","full"),yoloop:n("yoloop","yoloop-targeted",{structuralRequired:!0}),"migrate-state":n("migrate-state","full"),"migrate-project-id":n("migrate-project-id","full"),"policy-audit":n("policy-audit","full"),"mutation-test":n("mutation-test","full"),"sync-openapi":n("sync-openapi","full"),"generate-pacts":n("generate-pacts","full"),"verify-pacts":n("verify-pacts","full"),"property-test":n("property-test","full"),"property-tests":n("property-test","story-targeted",{structuralRequired:!0}),"chaos-plan":n("chaos-plan","full"),"ui-ux-review":n("ui-ux-review","adaptive-targeted"),"solyd-system":n("solyd-system","adaptive-targeted"),goal:n("goal","continuity-scoped"),loop:n("loop","continuity-scoped"),jobs:n("jobs","continuity-scoped"),runner:n("runner","continuity-scoped"),"goal-tick":n("goal-tick","continuity-scoped"),"loop-tick":n("loop-tick","continuity-scoped"),"validate-tests":n("validate-tests","story-targeted",{structuralRequired:!0}),"qa-gate":n("qa-gate","story-targeted",{structuralRequired:!0})}),X=Object.freeze({st:"status",arquitetura:"arch-plan",architecture:"arch-plan",arch:"arch-plan",prd:"arch-prd","product-requirements":"arch-prd","arch-doc":"arch-architecture","tech-architecture":"arch-architecture","api-contracts":"arch-api-contracts","api-contract":"arch-api-contracts","api-integrations":"arch-api-integrations","api-int":"arch-api-integrations","database-schema":"arch-database","db-schema":"arch-database",db:"arch-database","cyber-security":"arch-security",security:"arch-security",sec:"arch-security","design-system":"arch-design-system",ds:"arch-design-system","atomic-design":"arch-design-system","ux-design":"arch-ux-design",ux:"arch-ux-design",wireframes:"arch-ux-design",wireframe:"arch-ux-design","user-flows":"arch-ux-design",performance:"arch-performance",perf:"arch-performance","capacity-planning":"arch-performance",capacity:"arch-performance","arch-perf":"arch-performance","performance-strategy":"arch-performance","testing-strategy":"arch-testing","test-plan":"arch-testing","test-strategy":"arch-testing","arch-test":"arch-testing",infrastructure:"arch-infrastructure",infra:"arch-infrastructure","deploy-plan":"arch-infrastructure",deployment:"arch-infrastructure","arch-infra":"arch-infrastructure","arch-deploy":"arch-infrastructure","review-consolidation":"arch-review",consolidation:"arch-review","architecture-review":"arch-review","arch-consolidation":"arch-review",fitness:"arch-fitness-functions","fitness-functions":"arch-fitness-functions",archfit:"arch-fitness-functions","arch-fit":"arch-fitness-functions","fit-funcs":"arch-fitness-functions","criar-epic":"create-epic",planejamento:"create-epic","idea-diag":"idea-diagnose","idea-pesq":"idea-research","gerar-epic":"generate-epic",executar:"exec",pipeline:"exec","parallel-epic":"epic",setup:"setup-branch",branch:"setup-branch",diag:"diagnose",diagnostico:"diagnose",c02:"diagnose",pesquisar:"research",pesq:"research","research-fix":"research",c03:"research",spec:"write-spec",especificacao:"write-spec",c04:"write-spec",tasks:"create-tasks",tarefas:"create-tasks",c05:"create-tasks",impl:"implement",implementar:"implement",c06:"implement",push:"commit",commit_push:"commit",cp:"commit",c07:"commit",sincronizar:"sync",c08:"sync",pr:"create-pr",c09:"create-pr",revisar:"review",c11:"review",mesclar:"merge",c12:"merge",fix:"fix-blocked",corrigir:"fix-blocked",finalizar:"finalize-epic",conflitos:"resolve-conflicts",memoria:"update-memory",refactoring:"refactor",refact:"refactor",refac:"refactor",rf:"refactor","cleanup-code":"refactor","code-cleanup":"refactor","code-quality":"refactor","improve-code":"refactor",modernize:"refactor",modernization:"refactor",legacy:"refactor","legacy-code":"refactor","debt-pay":"refactor","pay-debt":"refactor","debt-reduction":"refactor","smell-fix":"refactor","fix-smells":"refactor","code-smells":"refactor",strangler:"refactor","strangler-fig":"refactor",limpar:"cleanup",limpeza:"cleanup",auditar:"audit",auditoria:"audit",debt:"tech-debt",debts:"tech-debt","debt-list":"tech-debt","tech-debts":"tech-debt",td:"tech-debt",help:"menu",ajuda:"menu","?":"menu",commands:"menu",cmds:"menu",planos:"plans",pricing:"plans",bill:"billing",subscription:"billing",sub:"billing",upgrade:"subscribe",checkout:"subscribe",qa:"qa-scan","qa-test":"qa-scan","visual-qa":"qa-scan","e2e-scan":"qa-scan",troubleshoot:"qa-scan","debug-ui":"qa-scan",scan:"qa-scan",a11y:"qa-scan",accessibility:"qa-scan",wcag:"qa-scan","auto-yolo":"yoloop","epic-runner":"yoloop","story-runner":"yoloop","loop-yolo":"yoloop","auto-epic":"yoloop",migrate:"migrate-state","state-migrate":"migrate-state","schema-migrate":"migrate-state",policy:"policy-audit","audit-policy":"policy-audit","policy-history":"policy-audit",policies:"policy-audit",mutation:"mutation-test",stryker:"mutation-test","kill-mutants":"mutation-test","openapi-sync":"sync-openapi","api-sync":"sync-openapi","spec-sync":"sync-openapi","regen-openapi":"sync-openapi",pacts:"generate-pacts","gen-pacts":"generate-pacts","regen-pacts":"generate-pacts","create-pacts":"generate-pacts","verify-pact":"verify-pacts","pact-verify":"verify-pacts","check-pacts":"verify-pacts","pact-check":"verify-pacts",property:"property-test",pbt:"property-test",proptest:"property-test","invariant-test":"property-test",chaos:"chaos-plan",gameday:"chaos-plan","resilience-test":"chaos-plan","ux-review":"ui-ux-review","design-review":"ui-ux-review","visual-review":"ui-ux-review","product-polish":"ui-ux-review","security-system":"solyd-system","authorized-security":"solyd-system","sec-system":"solyd-system",goals:"goal","durable-goal":"goal","continuity-goal":"goal",loops:"loop","durable-loop":"loop","continuity-loop":"loop",job:"jobs","continuity-jobs":"jobs","neocortex-runner":"runner","continuity-runner":"runner"}),ee=Object.freeze({1:"status",3:"arch-plan",4:"arch-prd",5:"arch-architecture",6:"arch-api-contracts",7:"arch-api-integrations",8:"arch-database",9:"arch-security",10:"arch-design-system",11:"arch-ux-design",12:"arch-performance",13:"arch-testing",14:"arch-infrastructure",15:"arch-review",16:"arch-fitness-functions",17:"create-epic",18:"idea-diagnose",19:"idea-research",20:"generate-epic",21:"exec",22:"yolo",23:"epic",24:"setup-branch",25:"diagnose",26:"research",27:"write-spec",28:"create-tasks",29:"implement",30:"commit",31:"sync",32:"create-pr",33:"review",34:"merge",35:"fix-blocked",36:"finalize-epic",37:"resolve-conflicts",38:"update-memory",39:"refactor",40:"cleanup",41:"audit",42:"tech-debt",43:"menu",44:"plans",45:"billing",46:"subscribe",47:"qa-scan",48:"yoloop",49:"migrate-state",50:"policy-audit",51:"mutation-test",52:"sync-openapi",53:"generate-pacts",54:"verify-pacts",55:"property-test",56:"chaos-plan",57:"ui-ux-review",58:"solyd-system",59:"goal",60:"loop",61:"jobs",62:"runner"});function d(r,e=120){if(typeof r!="string")return;const t=r.trim();if(t)return t.replace(/[^a-z0-9_.:-]+/gi,"_").slice(0,e)}function w(r,e=120){if(typeof r!="string")return;const t=r.trim(),i=d(r,e);return i===t?i:void 0}function T(r){if(typeof r!="string")return;const e=r.trim();if(!(!e||e.length>240||!/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(e)||e.includes("..")||e.includes("//")||e.includes("@{")||e.endsWith("/")||e.endsWith(".")||e.split("/").some(t=>!t||t.startsWith(".")||t.endsWith(".lock"))))return e}function te(r){if(typeof r!="string")return;const e=r.replace(/\\/g,"/");if(!(!e||e.length>240||e.startsWith("/")||/^[A-Za-z]:/.test(e)||e.includes("..")||e.includes("//")||e.split("/").includes(".")||!/^[A-Za-z0-9._/:@#-]+$/.test(e)))return e}function S(r){if(r===void 0||!Array.isArray(r)||r.length>128)return;const e=r.map(te);if(!e.some(t=>t===void 0))return[...new Set(e)].sort((t,i)=>t.localeCompare(i,"en"))}function re(r){return typeof r=="string"&&Q.has(r.trim().toLowerCase().replace(/_/g,"-"))}function C(r,e){const t={};for(const i of e){const c=r[i];typeof c=="string"||typeof c=="boolean"||typeof c=="number"&&Number.isFinite(c)?t[i]=c:Array.isArray(c)&&c.every(o=>typeof o=="string")&&(t[i]=[...c])}return t}function ie(r,e){const t=e.checkpoint;if(!h(t)||t.schemaVersion!==1||t.storyId!==r||t.epicId!==e.epic_id||!T(t.branch)||typeof t.baseSha!="string"||!/^[0-9a-f]{7,64}$/i.test(t.baseSha)||typeof t.headSha!="string"||!/^[0-9a-f]{7,64}$/i.test(t.headSha)||t.baseSha===t.headSha||!w(t.idempotencyKey)||typeof t.recordedAt!="string"||!Number.isFinite(Date.parse(t.recordedAt))||!Array.isArray(t.commits)||t.commits.length===0||t.commits.length>256||t.commits.some(c=>typeof c!="string"||!/^[0-9a-f]{7,64}$/i.test(c))||!Array.isArray(t.receiptRefs)||t.receiptRefs.length===0||t.receiptRefs.length>256||t.receiptRefs.some(c=>typeof c!="string"||c.length>240||c.includes("..")||!/^[A-Za-z0-9._:/#\-[\]]+$/.test(c))||!h(t.qaReceipt)||t.qaReceipt.kind!=="story_qa_evidence"||t.qaReceipt.producer!=="local-yolo-tdd"||!["passed","blocked"].includes(String(t.qaVerdict))||!["approved","changes-requested","pending"].includes(String(t.reviewVerdict))||(t.reviewVerdict==="pending"?t.reviewReceipt!==void 0:!h(t.reviewReceipt)))return;const i=C(t,["schemaVersion","storyId","epicId","branch","baseSha","headSha","idempotencyKey","dispatchId","bundleId","bundleDigest","graphRevision","claimRevision","qaVerdict","reviewVerdict","recordedAt","commits","receiptRefs"]);return i.qaReceipt=C(t.qaReceipt,["schemaVersion","kind","producer","evidenceVersion","storyId","epicId","contract","command","manifestDigest","gateIds","resultDigest","baseSha","headSha","bundleDigest","graphRevision","sourceEvidenceDigest","verdict","checkedAt","receiptRef"]),h(t.reviewReceipt)&&(i.reviewReceipt=C(t.reviewReceipt,["schemaVersion","kind","producer","storyId","epicId","baseSha","headSha","bundleDigest","graphRevision","sourceEvidenceDigest","qaReceiptRef","verdict","reviewedAt","receiptRef"])),i}function ce(r,e){const t=e.checkpoint_verification;if(!(!h(t)||t.schemaVersion!==1||t.kind!=="story_checkpoint_physical_verification"||t.producer!=="client-p205-transient-v1"||t.publicSafe!==!0||t.storyId!==r||t.epicId!==e.epic_id||!["verified","rejected"].includes(String(t.verdict))))return C(t,["schemaVersion","kind","producer","storyId","epicId","branch","baseSha","headSha","aggregateHeadSha","commitBodyDigest","changedPathsDigest","claimVerification","effectiveClaimRevision","command","manifestDigest","gateIds","resultDigest","graphRevision","executionEvidenceDigest","sourceEvidenceDigest","verifiedAt","verdict","reasonCodes","publicSafe"])}function M(r,e){const t=e.scheduling_checkpoint_evidence,i=new Set(["schemaVersion","kind","producer","storyId","epicId","branch","baseSha","headSha","graphRevision","effectiveClaimRevision","sourceEvidenceDigest","verifiedAt","reasonCodes","integrationAuthorized","publicSafe"]);if(!(!h(t)||Object.keys(t).some(c=>!i.has(c))||t.schemaVersion!==1||t.kind!=="story_scheduling_checkpoint_evidence"||t.producer!=="client-git-physical-v1"||t.publicSafe!==!0||t.integrationAuthorized!==!1||t.storyId!==r||t.epicId!==e.epic_id||!T(t.branch)||typeof t.baseSha!="string"||!/^[0-9a-f]{40,64}$/i.test(t.baseSha)||typeof t.headSha!="string"||!/^[0-9a-f]{40,64}$/i.test(t.headSha)||typeof t.graphRevision!="string"||!/^[0-9a-f]{64}$/i.test(t.graphRevision)||typeof t.effectiveClaimRevision!="string"||!/^[0-9a-f]{64}$/i.test(t.effectiveClaimRevision)||typeof t.sourceEvidenceDigest!="string"||!/^[0-9a-f]{64}$/i.test(t.sourceEvidenceDigest)||typeof t.verifiedAt!="string"||!Number.isFinite(Date.parse(t.verifiedAt))||!Array.isArray(t.reasonCodes)||t.reasonCodes.length!==1||t.reasonCodes[0]!=="checkpoint-git-scheduling-verified"))return C(t,[...i])}function oe(r,e){const t={...e},i=M(r,e);return i?(t.scheduling_checkpoint_evidence=i,delete t.checkpoint,delete t.checkpoint_verification):delete t.scheduling_checkpoint_evidence,t}function h(r){return r!==null&&typeof r=="object"&&!Array.isArray(r)}function _(...r){const e=new Set,t=[];for(const i of r)for(const c of i??[]){const o=d(c,80);if(!(!o||e.has(o))&&(e.add(o),t.push(o),t.length>=J))return t}return t}function ne(r){return r.trim().replace(/^@?\*/,"").replace(/^@/,"").toLowerCase()}function se(r){return r.trim().split(/\s+/,1)[0]??""}function z(r){if(/^@epic-P[0-9]{1,12}$/.test(r.trim()))return A.epic;const e=se(r);if(!e)return A.menu;const t=ne(e),i=ee[t]??X[t]??t;return A[i]??null}function ae(r,e,t,i="full-compatible",c=["full-state"]){return{kind:"full",commandId:t?.commandId??null,stateProjectionPolicy:t?.stateProjectionPolicy??null,projectionMode:i,trigger:r,targetEpicId:null,targetStoryId:null,includedStoryCount:Object.keys(e.stories).length,includedEpicCount:Object.keys(e.epics).length,omittedStoryCount:0,omittedEpicCount:0,reason:"full-state",reasonCodes:_(c)}}function ze(r,e,t,i="full-compatible",c=["full-state"]){const o=ae(r,e,t,i,c);return v({...e,scope:o},e,o)}function de(r){const[e]=r.trim().split(/\s+/,1);return e?/^[A-Z]?\d+(?:\.\d+)+$/i.test(e.replace(/^@/,""))||/(?:^|\/)[A-Z]?\d+(?:\.\d+)+\.story\.md$/i.test(e.replace(/^@/,"")):!1}function F(r){const e=r.match(/(?:^|[/@\s])([A-Z]?\d+(?:\.\d+)+)\.story\.md\b/i);return e?.[1]?e[1]:r.match(/(?:^|\s|@)([A-Z]?\d+(?:\.\d+)+)(?=$|\s)/i)?.[1]??null}function ue(r){const e=r.trim(),t=e.search(/\s/);return t===-1?"":e.slice(t).trim()}function q(r){return ue(r).split(/\s+/).map(e=>e.replace(/^@/,"").replace(/^['"]|['"]$/g,"")).filter(e=>e.length>0&&!e.startsWith("-"))}function Fe(r){return q(r)[0]??null}function P(r,e){const i=r.replace(/^@/,"").replace(/^epic-/i,"").replace(/\.md$/i,""),c=[i,i.toUpperCase(),/^p\d+$/i.test(i)?`P${i.replace(/^p/i,"")}`:null,/^\d+$/.test(i)?`P${i}`:null].filter(o=>typeof o=="string"&&o.length>0);for(const o of c)if(e.epics[o])return o;return null}function le(r,e){const t=r.match(/(?:^|[/@\s])epic-(P?\d+)\.md\b/i);return t?.[1]?P(t[1],e):null}function R(r,e){const t=r.trim().match(/^@epic-(P[0-9]{1,12})$/);if(t)return P(t[1],e);const i=le(r,e);if(i)return i;for(const c of q(r)){if(/^[A-Z]?\d+(?:\.\d+)+$/i.test(c))continue;const o=P(c,e);if(o)return o}return null}function pe(r,e){const t=R(r,e);if(t)return t;const i=e.yoloop,c=i?.state?.currentSession?.currentEpicId;if(typeof c=="string"&&e.epics[c])return c;const o=i?.lock?.currentEpicId??i?.lock?.epicId;return typeof o=="string"&&e.epics[o]?o:null}function fe(r){const e=r.match(/(?:^|[/@\s])epic-(P?\d+)\.md\b/i)?.[1];if(e)return/^P/i.test(e)?e.toUpperCase():`P${e}`;for(const t of q(r)){if(/^P\d+$/i.test(t))return t.toUpperCase();if(/^\d+$/.test(t))return`P${t}`}return null}function j(r,e){if(typeof r.epic_id=="string"&&r.epic_id.length>0)return r.epic_id;const t=e.split(".").slice(0,-1).join(".");return t.length>0?t:null}function L(r){return typeof r=="string"&&["done","completed","merged","cancelled","canceled","abandoned"].includes(r.toLowerCase())}function x(r,e,t){if(t.has(r))return;const i=e.stories[r];if(!i)return;t.add(r);const c=i.depends_on;if(Array.isArray(c))for(const o of c)typeof o=="string"&&x(o,e,t)}function ye(r,e){const t=I(e.stories,[r]),i={};for(const c of t.orderedIds){const o=e.stories[c];o&&(i[c]=o)}return i}function $(r,e,t=[]){const i={};for(const c of t)e.epics[c]&&(i[c]=e.epics[c]);for(const[c,o]of Object.entries(r)){const s=j(o,c);s&&e.epics[s]&&(i[s]=e.epics[s])}return i}function me(r,e,t){if(t.has(r))return;const i=e.epics[r];if(!i)return;t.add(r);const c=i.depends_on;if(Array.isArray(c))for(const o of c)typeof o=="string"&&o.length>0&&me(o,e,t)}function V(r,e,t){const i=I(t.epics,[r]),c=new Set(i.orderedIds);for(const[s,a]of Object.entries(e)){const u=j(a,s);u&&t.epics[u]&&c.add(u)}const o={};for(const s of[...c].sort((a,u)=>a.localeCompare(u,"en"))){const a=t.epics[s];a&&(o[s]=s===r?a:K(s,a))}return o}function G(r,e,t){const i=e.stories;if(!Array.isArray(i)||i.some(s=>typeof s!="string"||s.length===0))throw new y("STRUCTURAL_DEPENDENCY_MISSING",{nodes:0,edges:0,malformedStoryMemberships:1});const c=I(t.stories,i),o={};for(const s of c.orderedIds){const a=t.stories[s];a&&(o[s]=j(a,s)===r?oe(s,a):Y(s,a))}return o}function ge(r,e,t){const i=[...e.stories].sort((s,a)=>s.localeCompare(a,"en")),c=Object.entries(t).filter(([s,a])=>j(a,s)===r).map(([s])=>s).sort((s,a)=>s.localeCompare(a,"en")),o=H("sha256").update(`target-epic-coverage-v1\0${JSON.stringify({targetEpicId:r,declaredStoryIds:i,includedStoryIds:c})}`).digest("hex");return{schemaVersion:"TargetEpicCoverage/1.0",targetEpicId:r,declaredStoryIds:i,includedStoryIds:c,membershipSha256:o,publicSafe:!0}}function Y(r,e){const t=Array.isArray(e.depends_on)?[...new Set(e.depends_on.filter(m=>typeof m=="string"&&m.length>0))].sort((m,E)=>m.localeCompare(E,"en")):[],i={id:d(e.id)??r,...d(e.epic_id)?{epic_id:d(e.epic_id)}:{},...d(e.status,40)?{status:d(e.status,40)}:{},depends_on:t},c=M(r,e);if(!re(e.status))return{...i,...c?{scheduling_checkpoint_evidence:c}:{}};const o=e.source==="create-epic"||e.source==="discovered"?e.source:void 0,s=T(e.branch_name),a=w(e.last_step,120),u=Array.isArray(e.steps_completed)&&e.steps_completed.length<=64?e.steps_completed.map(m=>w(m,120)):[],l=u.length>0&&u.every(m=>m!==void 0)?u:void 0,f=typeof e.pr_number=="number"&&Number.isSafeInteger(e.pr_number)&&e.pr_number>0?e.pr_number:void 0,p=ie(r,e),g=p?ce(r,e):void 0;return{...i,...o?{source:o}:{},...s?{branch_name:s}:{},...a?{last_step:a}:{},...l?{steps_completed:l}:{},...f?{pr_number:f}:{},...p?{checkpoint:p}:{},...g?{checkpoint_verification:g}:{},...c?{scheduling_checkpoint_evidence:c}:{},...S(e.files_to_modify)!==void 0?{files_to_modify:S(e.files_to_modify)}:{},...S(e.contracts)!==void 0?{contracts:S(e.contracts)}:{},...S(e.contract_refs)!==void 0?{contract_refs:S(e.contract_refs)}:{},...S(e.shared_surfaces)!==void 0?{shared_surfaces:S(e.shared_surfaces)}:{}}}function K(r,e){const t=Array.isArray(e.stories)?[...new Set(e.stories.filter(c=>typeof c=="string"&&c.length>0))].sort((c,o)=>c.localeCompare(o,"en")):[],i=Array.isArray(e.depends_on)?[...new Set(e.depends_on.filter(c=>typeof c=="string"&&c.length>0))].sort((c,o)=>c.localeCompare(o,"en")):[];return{id:d(e.id)??r,...d(e.status,40)?{status:d(e.status,40)}:{},...d(e.lifecycle_classification,40)?{lifecycle_classification:d(e.lifecycle_classification,40)}:{},stories:t,depends_on:i}}function he(r,e,t){const i=I(e.stories),c=I(e.epics),o=Object.fromEntries(i.orderedIds.map(u=>[u,Y(u,e.stories[u])])),s=Object.fromEntries(c.orderedIds.map(u=>[u,K(u,e.epics[u])])),a={kind:"projected",commandId:t.commandId,stateProjectionPolicy:t.stateProjectionPolicy,projectionMode:"yoloop-discovery",trigger:r,targetEpicId:null,targetStoryId:null,includedStoryCount:i.orderedIds.length,includedEpicCount:c.orderedIds.length,omittedStoryCount:0,omittedEpicCount:0,reason:"targeted-invocation",reasonCodes:_(["structural-required","yoloop-discovery",`structural-edges-${i.edgeCount+c.edgeCount}`,"content-fields-omitted"])};return v({...e,stories:o,epics:s,scope:a},e,a)}function be(r,e){const t=new Set,i=r.stories;if(Array.isArray(i))for(const o of i)typeof o=="string"&&x(o,e,t);const c={};for(const o of t){const s=e.stories[o];s&&(c[o]=s)}return c}function _e(r){const e={};for(const[t,i]of Object.entries(r.epics))e[t]={id:d(i.id)??t,...d(i.status)?{status:d(i.status)}:{},...k.includes(i.lifecycle_classification)?{lifecycle_classification:i.lifecycle_classification}:{},...typeof i.total_stories=="number"&&Number.isFinite(i.total_stories)?{total_stories:i.total_stories}:{},...typeof i.completed_stories=="number"&&Number.isFinite(i.completed_stories)?{completed_stories:i.completed_stories}:{}};return e}function W(r){const e={};for(const t of Object.values(r)){const i=d(t.status,40)??"unknown";e[i]=(e[i]??0)+1}return e}function Se(r){const e=Object.fromEntries(k.map(t=>[t,0]));for(const t of Object.values(r)){const i=k.includes(t.lifecycle_classification)?t.lifecycle_classification:"active";e[i]=(e[i]??0)+1}return e}function N(r,e){if(!e)return!0;const t=r.epics[e];return t?!k.includes(t.lifecycle_classification)||t.lifecycle_classification==="active":!0}function Z(r){for(const e of["last_updated","updated_at","completed_at","created_at","discovered_at"]){const t=r[e];if(typeof t!="string")continue;const i=Date.parse(t);if(Number.isFinite(i))return i}return 0}function je(r){return Object.entries(r.stories).map(([e,t])=>({id:e,story:t,timestamp:Z(t)})).sort((e,t)=>t.timestamp-e.timestamp||e.id.localeCompare(t.id)).slice(0,U).map(({id:e,story:t})=>({id:e,...d(t.epic_id)?{epicId:d(t.epic_id)}:{},...d(t.status,40)?{status:d(t.status,40)}:{},...d(t.last_step??t.lastStep)?{lastStep:d(t.last_step??t.lastStep)}:{},...d(t.last_updated??t.updated_at??t.completed_at??t.created_at)?{lastUpdated:d(t.last_updated??t.updated_at??t.completed_at??t.created_at)}:{}}))}function ve(r){const e=r.current_session;if(!e)return;const t={activeEpicId:d(e.active_epic_id)??null,activeStoryId:d(e.active_story_id)??null,activeStepId:d(e.active_step_id)??null,sessionId:d(e.session_id)??null,startedAt:d(e.started_at)??null};return Object.values(t).some(i=>i!=null)?t:void 0}function Ie(r){const e=r.yoloop;if(!h(e))return;const t=h(e.state)?e.state:void 0,i=h(t?.currentSession)?t.currentSession:void 0,c=h(e.lock)?e.lock:void 0,o={...typeof e.active=="boolean"?{active:e.active}:{},currentEpicId:d(i?.currentEpicId??e.currentEpicId)??null,currentStoryId:d(i?.currentStoryId??e.currentStoryId)??null,sessionId:d(i?.sessionId??e.sessionId)??null,lockEpicId:d(c?.currentEpicId??c?.epicId)??null};return Object.keys(o).length>0?o:void 0}function ke(r){const e=r.continuity;if(!h(e))return;const t=Array.isArray(e.reasonCodes)?e.reasonCodes.filter(i=>typeof i=="string"):void 0;return{present:!0,activeJobId:d(e.activeJobId??e.jobId)??null,activeGoalId:d(e.activeGoalId??e.goalId)??null,activeLoopId:d(e.activeLoopId??e.loopId)??null,...t&&t.length>0?{reasonCodes:_(t)}:{}}}function Ce(r,e,t){const i=d(e?.activeStoryId),c=d(e?.activeEpicId),o=d(e?.activeStepId),s=i&&r.stories[i]?j(r.stories[i],i):null;if((i||c||o)&&N(r,c??s))return{epicId:c??null,storyId:i??null,stepId:o??null};const a=d(t?.currentStoryId),u=d(t?.currentEpicId??t?.lockEpicId);if((a||u)&&N(r,u))return{epicId:u??null,storyId:a??null,stepId:null};const l=Object.entries(r.stories).map(([f,p])=>({id:f,story:p,timestamp:Z(p)})).filter(({id:f,story:p})=>!L(p.status)&&N(r,j(p,f))).sort((f,p)=>p.timestamp-f.timestamp||f.id.localeCompare(p.id))[0];return l?{epicId:j(l.story,l.id),storyId:l.id,stepId:d(l.story.last_step??l.story.lastStep)??null}:{epicId:null,storyId:null,stepId:null}}function Ee(r,e){const t=W(r.stories),i=W(r.epics),c=Se(r.epics),o=Object.values(r.epics).filter(g=>(k.includes(g.lifecycle_classification)?g.lifecycle_classification:"active")==="active"&&!L(g.status)).length,s=ve(r),a=Ie(r),u=ke(r),l=Ce(r,s,a),f=je(r),p=_(e.reasonCodes,["state-summary-attached","state-summary-bounded",`projection-${e.projectionMode??e.kind}`,e.stateProjectionPolicy?`policy-${e.stateProjectionPolicy}`:"policy-unknown",f.length>=U?"recent-stories-capped":"recent-stories-bounded",l.storyId||l.epicId?"active-ref-derived":"active-ref-empty",a?"yoloop-session-present":"yoloop-session-absent",u?"continuity-session-present":"continuity-session-absent"]);return{schemaVersion:1,totals:{stories:Object.keys(r.stories).length,epics:Object.keys(r.epics).length,storyStatus:t,epicStatus:i,epicLifecycle:c,activeEpics:o,blockedStories:t.blocked??0},active:l,blockedCount:t.blocked??0,recentStories:f,...s?{currentSession:s}:{},...a?{currentYoloopSession:a}:{},...u?{currentContinuitySession:u}:{},projection:{commandId:e.commandId??null,stateProjectionPolicy:e.stateProjectionPolicy??null,projectionMode:e.projectionMode,scopeKind:e.kind,includedStoryCount:e.includedStoryCount,includedEpicCount:e.includedEpicCount??Object.keys(r.epics).length,omittedStoryCount:e.omittedStoryCount,omittedEpicCount:e.omittedEpicCount,reason:e.reason},reasonCodes:p,publicSafe:!0}}function v(r,e,t){return{...r,stateSummary:Ee(e,t)}}function Re(r,e,t){const i={};for(const o of Object.keys(e.epics))i[o]={id:o};const c={kind:"projected",commandId:t.commandId,stateProjectionPolicy:t.stateProjectionPolicy,projectionMode:"summary-only",trigger:r,targetEpicId:null,targetStoryId:null,includedStoryCount:0,includedEpicCount:Object.keys(i).length,omittedStoryCount:Object.keys(e.stories).length,omittedEpicCount:0,reason:"epic-summary",reasonCodes:["epic-summary","stories-omitted","epic-stubs-only"]};return v({...e,stories:{},epics:i,scope:c},e,c)}function b(r,e,t,i=["summary-only","stories-omitted"],c="summary-only"){const o=_e(e),s={kind:"projected",commandId:t.commandId,stateProjectionPolicy:t.stateProjectionPolicy,projectionMode:c,trigger:r,targetEpicId:null,targetStoryId:null,includedStoryCount:0,includedEpicCount:Object.keys(o).length,omittedStoryCount:Object.keys(e.stories).length,omittedEpicCount:Math.max(0,Object.keys(e.epics).length-Object.keys(o).length),reason:"summary-only",reasonCodes:_(i)};return v({...e,stories:{},epics:o,scope:s},e,s)}function D(r,e,t,i,c,o){const s=e.stories[i];if(!s)throw new y("STRUCTURAL_TARGET_NOT_FOUND",{stories:Object.keys(e.stories).length,epics:Object.keys(e.epics).length,targetKind:"story"});const a=j(s,i);if(!a)throw new y("STRUCTURAL_TARGET_NOT_FOUND",{stories:Object.keys(e.stories).length,epics:Object.keys(e.epics).length,targetKind:"epic"});const u=e.epics[a];if(!u)throw new y("STRUCTURAL_TARGET_NOT_FOUND",{stories:Object.keys(e.stories).length,epics:Object.keys(e.epics).length,targetKind:"epic"});const l=c==="yolo-story",f=l?G(a,u,e):ye(i,e),p=l?V(a,f,e):$(f,e);if(!f[i]||!p[a])throw new y("STRUCTURAL_TARGET_NOT_FOUND",{stories:Object.keys(f).length,epics:Object.keys(p).length,targetKind:"story"});const g={kind:"projected",commandId:t.commandId,stateProjectionPolicy:t.stateProjectionPolicy,projectionMode:c,trigger:r,targetEpicId:a,targetStoryId:i,includedStoryCount:Object.keys(f).length,includedEpicCount:Object.keys(p).length,omittedStoryCount:Math.max(0,Object.keys(e.stories).length-Object.keys(f).length),omittedEpicCount:Math.max(0,Object.keys(e.epics).length-Object.keys(p).length),reason:"targeted-invocation",reasonCodes:_(o,l?["epic-graph-authority-complete"]:[])};return v({...e,stories:f,epics:p,scope:g},e,g)}function B(r,e,t,i,c,o){const s=e.epics[i];if(!s)throw new y("STRUCTURAL_TARGET_NOT_FOUND",{stories:Object.keys(e.stories).length,epics:Object.keys(e.epics).length,targetKind:"epic"});const a=be(s,e),u=$(a,e,[i]);if(!u[i])throw new y("STRUCTURAL_TARGET_NOT_FOUND",{stories:Object.keys(a).length,epics:Object.keys(u).length,targetKind:"epic"});const l={kind:"projected",commandId:t.commandId,stateProjectionPolicy:t.stateProjectionPolicy,projectionMode:c,trigger:r,targetEpicId:i,targetStoryId:null,includedStoryCount:Object.keys(a).length,includedEpicCount:Object.keys(u).length,omittedStoryCount:Math.max(0,Object.keys(e.stories).length-Object.keys(a).length),omittedEpicCount:Math.max(0,Object.keys(e.epics).length-Object.keys(u).length),reason:"targeted-invocation",reasonCodes:_(o)};return v({...e,stories:a,epics:u,scope:l},e,l)}function Oe(r,e,t){const i=fe(r),c=R(r,e);if(i&&!c)throw new y("STRUCTURAL_TARGET_NOT_FOUND",{stories:Object.keys(e.stories).length,epics:Object.keys(e.epics).length,targetKind:"epic"});const o=pe(r,e),s=O({commandId:t.commandId,explicitYoloopEpicId:c,sessionYoloopEpicId:c?null:o});if(s==="yoloop-discovery")return he(r,e,t);if(!o||s!=="yoloop-target"&&s!=="yoloop-session")throw new y("STRUCTURAL_TARGET_NOT_FOUND",{stories:Object.keys(e.stories).length,epics:Object.keys(e.epics).length,targetKind:"epic"});const a=e.epics[o];if(!a)throw new y("STRUCTURAL_TARGET_NOT_FOUND",{stories:Object.keys(e.stories).length,epics:Object.keys(e.epics).length,targetKind:"epic"});const u=G(o,a,e),l=V(o,u,e);if(!l[o])throw new y("STRUCTURAL_TARGET_NOT_FOUND",{stories:Object.keys(u).length,epics:Object.keys(l).length,targetKind:"epic"});const f=s,p={kind:"projected",commandId:t.commandId,stateProjectionPolicy:t.stateProjectionPolicy,projectionMode:f,trigger:r,targetEpicId:o,targetStoryId:null,targetEpicCoverage:ge(o,a,u),includedStoryCount:Object.keys(u).length,includedEpicCount:Object.keys(l).length,omittedStoryCount:Math.max(0,Object.keys(e.stories).length-Object.keys(u).length),omittedEpicCount:Math.max(0,Object.keys(e.epics).length-Object.keys(l).length),reason:"targeted-invocation",reasonCodes:["structural-required",f,"yoloop-targeted"]};return v({...e,stories:u,epics:l,scope:p},e,p)}function Ae(r,e){const t={};for(const[i,c]of Object.entries(r.epics)){const o=Array.isArray(c.stories)?c.stories.filter(s=>typeof s=="string"&&e.has(s)):[];t[i]={id:d(c.id)??i,...d(c.status,40)?{status:d(c.status,40)}:{},...typeof c.total_stories=="number"&&Number.isFinite(c.total_stories)?{total_stories:c.total_stories}:{},...typeof c.completed_stories=="number"&&Number.isFinite(c.completed_stories)?{completed_stories:c.completed_stories}:{},...o.length>0?{stories:o}:{},...o.length>0&&Array.isArray(c.depends_on)?{depends_on:c.depends_on.filter(s=>typeof s=="string"&&s.length>0)}:{},...o.length>0&&(c.branch_mode==="epic"||c.branch_mode==="story")?{branch_mode:c.branch_mode}:{},...o.length>0&&typeof c.execution_branch=="string"?{execution_branch:c.execution_branch}:{},...o.length>0&&typeof c.origin_branch=="string"?{origin_branch:c.origin_branch}:{},...o.length>0&&(c.branch_lease===null||typeof c.branch_lease=="object")?{branch_lease:c.branch_lease}:{},...o.length>0&&(c.origin_binding===null||typeof c.origin_binding=="object")?{origin_binding:c.origin_binding}:{},...o.length>0&&(c.aggregate_qa_receipt===null||typeof c.aggregate_qa_receipt=="object")?{aggregate_qa_receipt:c.aggregate_qa_receipt}:{}}}return t}function we(r){return r.stateSummary?.totals.stories??(r.scope?.includedStoryCount??Object.keys(r.stories).length)+(r.scope?.omittedStoryCount??0)}function Te(r){return r.stateSummary?.totals.epics??(r.scope?.includedEpicCount??Object.keys(r.epics).length)+(r.scope?.omittedEpicCount??0)}function qe(r,e){if(r.stateSummary)return{...r.stateSummary,projection:{...r.stateSummary.projection,scopeKind:"projected",projectionMode:e.projectionMode,includedStoryCount:e.includedStoryCount,includedEpicCount:e.includedEpicCount??r.stateSummary.projection.includedEpicCount,omittedStoryCount:e.omittedStoryCount,omittedEpicCount:e.omittedEpicCount,reason:"body-size"},reasonCodes:_(r.stateSummary.reasonCodes,["payload-size-guardrail","state-summary-preserved","nonessential-state-degraded"])}}function Le(r){const e=r.scope,t=new Set,i=e?.projectionMode==="structural-required"||e?.projectionMode==="yolo-story"||e?.projectionMode==="yoloop-target"||e?.projectionMode==="yoloop-session"||e?.projectionMode==="yoloop-discovery";if(i)for(const m of Object.keys(r.stories))t.add(m);else e?.targetStoryId&&x(e.targetStoryId,r,t);const c={};for(const m of t){const E=r.stories[m];E&&(c[m]=E)}const o=Ae(r,t),s=Object.keys(c).length,a=Object.keys(o).length,u=Math.max(0,we(r)-s),l=Math.max(0,Te(r)-a),f=i?e?.projectionMode??"structural-required":e?.projectionMode==="yolo-story"?"yolo-story":"summary-only",p={kind:"projected",commandId:e?.commandId??null,stateProjectionPolicy:e?.stateProjectionPolicy??null,projectionMode:f,targetEpicId:e?.targetEpicId??null,targetStoryId:e?.targetStoryId??null,...e?.targetEpicCoverage?{targetEpicCoverage:e.targetEpicCoverage}:{},includedStoryCount:s,includedEpicCount:a,omittedStoryCount:u,omittedEpicCount:l,reason:"body-size",reasonCodes:_(e?.reasonCodes,["payload-size-guardrail",t.size>0?"structural-targets-preserved":"stories-omitted","epics-stubbed","state-summary-preserved","redundant-trigger-omitted"])},g=qe(r,p);return{...r,stories:c,epics:o,scope:p,...g?{stateSummary:g}:{}}}function Pe(r,e){const t=r.trim(),i=z(t);try{if(!i){if(de(t)){const o=n("story-reference","story-targeted"),s=F(t);if(s)return D(t,e,o,s,"targeted-story",["story-reference-targeted"])}return b(t,e,n("unknown","adaptive-targeted"),["unknown-command-summary-only"])}if(i.stateProjectionPolicy==="epic-summary")return Re(t,e,i);if(i.stateProjectionPolicy==="yoloop-targeted")return Oe(t,e,i);const c=F(t);if(i.stateProjectionPolicy==="story-targeted"){if(c){const s=O({commandId:i.commandId,targetStoryId:c})==="yolo-story";return D(t,e,i,c,s?"yolo-story":i.structuralRequired?"structural-required":"targeted-story",[s?"yolo-story":i.structuralRequired?"structural-required":"targeted-story"])}if(i.commandId==="yolo"||i.commandId==="yolo-inline"){const o=O({commandId:i.commandId});return b(t,e,i,["yolo-inline","stories-omitted","historical-content-omitted"],o??"yolo-inline")}return i.commandId==="commit"&&/^\*?(?:commit|commit-push)$/i.test(t)?b(t,e,i,["working-tree-commit","stories-omitted","historical-content-omitted"]):i.structuralRequired?(()=>{throw new y("STRUCTURAL_TARGET_NOT_FOUND",{stories:Object.keys(e.stories).length,epics:Object.keys(e.epics).length,targetKind:"story"})})():b(t,e,i,["story-target-missing-summary-only"])}if(i.stateProjectionPolicy==="adaptive-targeted"){if(c&&e.stories[c])return D(t,e,i,c,"targeted-story",["adaptive-story-targeted"]);const o=R(t,e);return o?B(t,e,i,o,"targeted-epic",["adaptive-epic-targeted"]):b(t,e,i,["adaptive-summary-only","target-unresolved-summary-only"])}if(i.stateProjectionPolicy==="epic-targeted"){if(i.commandId.startsWith("arch-")&&/(?:^|\s)epic-arch\s*$/i.test(t)&&e.archPlan?.execution?.currentStageCommand===i.commandId)return b(t,e,i,["architecture-root-delegated"]);const o=R(t,e);return o?B(t,e,i,o,i.structuralRequired?"structural-required":"targeted-epic",[i.structuralRequired?"structural-required":"targeted-epic"]):i.structuralRequired?(()=>{throw new y("STRUCTURAL_TARGET_NOT_FOUND",{stories:Object.keys(e.stories).length,epics:Object.keys(e.epics).length,targetKind:"epic"})})():b(t,e,i,["epic-target-missing-summary-only"])}return i.stateProjectionPolicy==="continuity-scoped"?b(t,e,i,["continuity-scoped-summary-only"]):b(t,e,i,["policy-full-summary-only"])}catch(c){if(c instanceof y)throw c;if(i?.structuralRequired)throw new y("STRUCTURAL_DEPENDENCY_MISSING",{stories:Object.keys(e.stories).length,epics:Object.keys(e.epics).length,projectionErrors:1});return b(t,e,i??n("unknown","adaptive-targeted"),["projection-error-summary-only"])}}const xe=new Set(["yolo-story","yolo-inline","yoloop-target","yoloop-session","yoloop-discovery"]);function Ne(r){let e=0;for(const t of[r.stories,r.epics])for(const i of Object.values(t))Array.isArray(i.depends_on)&&(e+=i.depends_on.filter(c=>typeof c=="string").length);return e}function $e(r,e){const t=z(r.trim());if(!t||!["yolo","yolo-inline","yoloop"].includes(t.commandId))return null;try{const i=Pe(r,e),c=i.scope?.projectionMode;if(!c||!xe.has(c))throw new y("STRUCTURAL_DEPENDENCY_MISSING",{stories:Object.keys(i.stories).length,epics:Object.keys(i.epics).length,projectionShapeErrors:1});return Object.freeze({ok:!0,version:2,shape:c,snapshot:i,included:{epics:i.scope?.includedEpicCount??Object.keys(i.epics).length,stories:i.scope?.includedStoryCount??Object.keys(i.stories).length,edges:Ne(i)},omitted:{epics:i.scope?.omittedEpicCount??0,stories:i.scope?.omittedStoryCount??0},cycleCount:0})}catch(i){if(!(i instanceof y))throw i;return Object.freeze({ok:!1,code:i.code,publicDetails:i.publicDetails})}}export{Le as degradeStateSnapshotForPayloadLimit,Pe as projectStateSnapshotForInvoke,$e as projectStateSnapshotResultV2ForInvoke};
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * Pure request-scoped projection helpers for invoke state snapshots.
6
+ */
7
+ import { createHash } from 'node:crypto';
8
+ import { analyzeDependencyDag, StructuralDagError, } from './structural-dag-projection.js';
9
+ import { classifyInvocationShapeV2 } from './invocation-shape.js';
10
+ const RECENT_STORY_LIMIT = 12;
11
+ const REASON_CODE_LIMIT = 16;
12
+ const EPIC_LIFECYCLE_CLASSIFICATIONS = ['active', 'archived', 'rolled-back', 'synthetic', 'orphan'];
13
+ // Publish-safe shadow of packages/shared/src/yoloop/status-policy.ts. The
14
+ // standalone client tarball cannot take a runtime dependency on @neocortex/shared.
15
+ const YOLOOP_ACTIVE_STORY_STATUS_SET = new Set([
16
+ 'in-progress', 'branch-ready', 'diagnose', 'research', 'write-spec',
17
+ 'create-tasks', 'implemented', 'refactor-suggest-done',
18
+ 'property-tests-emitted', 'tests-validated', 'qa-gate-passed',
19
+ 'memory-updated', 'committed', 'synced', 'pr-created', 'pr-reviewed',
20
+ 'partial',
21
+ ]);
22
+ const policy = (commandId, stateProjectionPolicy, options = {}) => ({
23
+ commandId,
24
+ stateProjectionPolicy,
25
+ ...options,
26
+ });
27
+ // P198.03: local publish-safe shadow of the P198.01 shared command-context
28
+ // projection policies. The published CLI does not ship `packages/shared/dist`, so
29
+ // this file must not add a runtime `@neocortex/shared` import until packaging is
30
+ // changed. Keep ids/aliases/numbers aligned with the public command registry.
31
+ const COMMAND_POLICY_BY_ID = Object.freeze({
32
+ status: policy('status', 'full'),
33
+ 'arch-plan': policy('arch-plan', 'full'),
34
+ 'arch-prd': policy('arch-prd', 'full'),
35
+ 'arch-architecture': policy('arch-architecture', 'epic-targeted', { structuralRequired: true }),
36
+ 'arch-api-contracts': policy('arch-api-contracts', 'epic-targeted', { structuralRequired: true }),
37
+ 'arch-api-integrations': policy('arch-api-integrations', 'epic-targeted', { structuralRequired: true }),
38
+ 'arch-database': policy('arch-database', 'epic-targeted', { structuralRequired: true }),
39
+ 'arch-security': policy('arch-security', 'epic-targeted', { structuralRequired: true }),
40
+ 'arch-design-system': policy('arch-design-system', 'epic-targeted', { structuralRequired: true }),
41
+ 'arch-ux-design': policy('arch-ux-design', 'epic-targeted', { structuralRequired: true }),
42
+ 'arch-performance': policy('arch-performance', 'epic-targeted', { structuralRequired: true }),
43
+ 'arch-testing': policy('arch-testing', 'epic-targeted', { structuralRequired: true }),
44
+ 'arch-infrastructure': policy('arch-infrastructure', 'epic-targeted', { structuralRequired: true }),
45
+ 'arch-review': policy('arch-review', 'epic-targeted', { structuralRequired: true }),
46
+ 'arch-fitness-functions': policy('arch-fitness-functions', 'epic-targeted', { structuralRequired: true }),
47
+ 'create-epic': policy('create-epic', 'epic-summary'),
48
+ 'idea-diagnose': policy('idea-diagnose', 'full'),
49
+ 'idea-research': policy('idea-research', 'epic-targeted', { structuralRequired: true }),
50
+ 'generate-epic': policy('generate-epic', 'epic-targeted', { structuralRequired: true }),
51
+ exec: policy('exec', 'story-targeted', { structuralRequired: true }),
52
+ yolo: policy('yolo', 'story-targeted', { structuralRequired: true }),
53
+ 'yolo-inline': policy('yolo-inline', 'story-targeted', { structuralRequired: true }),
54
+ epic: policy('epic', 'epic-targeted', { structuralRequired: true }),
55
+ 'setup-branch': policy('setup-branch', 'story-targeted', { structuralRequired: true }),
56
+ diagnose: policy('diagnose', 'adaptive-targeted'),
57
+ 'diagnose-inline': policy('diagnose-inline', 'full'),
58
+ research: policy('research', 'adaptive-targeted'),
59
+ 'research-inline': policy('research-inline', 'full'),
60
+ 'write-spec': policy('write-spec', 'story-targeted', { structuralRequired: true }),
61
+ 'create-tasks': policy('create-tasks', 'story-targeted', { structuralRequired: true }),
62
+ implement: policy('implement', 'story-targeted', { structuralRequired: true }),
63
+ commit: policy('commit', 'story-targeted', { structuralRequired: true }),
64
+ 'commit-push': policy('commit', 'story-targeted', { structuralRequired: true }),
65
+ sync: policy('sync', 'story-targeted', { structuralRequired: true }),
66
+ 'sync-main': policy('sync', 'story-targeted', { structuralRequired: true }),
67
+ 'create-pr': policy('create-pr', 'story-targeted', { structuralRequired: true }),
68
+ review: policy('review', 'story-targeted'),
69
+ 'review-pr': policy('review', 'story-targeted'),
70
+ merge: policy('merge', 'story-targeted', { structuralRequired: true }),
71
+ 'merge-pr': policy('merge', 'story-targeted', { structuralRequired: true }),
72
+ 'fix-blocked': policy('fix-blocked', 'story-targeted'),
73
+ 'finalize-epic': policy('finalize-epic', 'epic-targeted'),
74
+ 'resolve-conflicts': policy('resolve-conflicts', 'story-targeted'),
75
+ 'update-memory': policy('update-memory', 'full'),
76
+ 'update-project-memory': policy('update-memory', 'story-targeted', { structuralRequired: true }),
77
+ refactor: policy('refactor', 'adaptive-targeted'),
78
+ 'refactor-suggest': policy('refactor', 'story-targeted', { structuralRequired: true }),
79
+ cleanup: policy('cleanup', 'full'),
80
+ audit: policy('audit', 'full'),
81
+ 'tech-debt': policy('tech-debt', 'full'),
82
+ menu: policy('menu', 'full'),
83
+ plans: policy('plans', 'full'),
84
+ billing: policy('billing', 'full'),
85
+ subscribe: policy('subscribe', 'full'),
86
+ 'qa-scan': policy('qa-scan', 'full'),
87
+ yoloop: policy('yoloop', 'yoloop-targeted', { structuralRequired: true }),
88
+ 'migrate-state': policy('migrate-state', 'full'),
89
+ 'migrate-project-id': policy('migrate-project-id', 'full'),
90
+ 'policy-audit': policy('policy-audit', 'full'),
91
+ 'mutation-test': policy('mutation-test', 'full'),
92
+ 'sync-openapi': policy('sync-openapi', 'full'),
93
+ 'generate-pacts': policy('generate-pacts', 'full'),
94
+ 'verify-pacts': policy('verify-pacts', 'full'),
95
+ 'property-test': policy('property-test', 'full'),
96
+ 'property-tests': policy('property-test', 'story-targeted', { structuralRequired: true }),
97
+ 'chaos-plan': policy('chaos-plan', 'full'),
98
+ 'ui-ux-review': policy('ui-ux-review', 'adaptive-targeted'),
99
+ 'solyd-system': policy('solyd-system', 'adaptive-targeted'),
100
+ goal: policy('goal', 'continuity-scoped'),
101
+ loop: policy('loop', 'continuity-scoped'),
102
+ jobs: policy('jobs', 'continuity-scoped'),
103
+ runner: policy('runner', 'continuity-scoped'),
104
+ 'goal-tick': policy('goal-tick', 'continuity-scoped'),
105
+ 'loop-tick': policy('loop-tick', 'continuity-scoped'),
106
+ 'validate-tests': policy('validate-tests', 'story-targeted', { structuralRequired: true }),
107
+ 'qa-gate': policy('qa-gate', 'story-targeted', { structuralRequired: true }),
108
+ });
109
+ const COMMAND_ALIAS_TO_ID = Object.freeze({
110
+ st: 'status',
111
+ arquitetura: 'arch-plan',
112
+ architecture: 'arch-plan',
113
+ arch: 'arch-plan',
114
+ prd: 'arch-prd',
115
+ 'product-requirements': 'arch-prd',
116
+ 'arch-doc': 'arch-architecture',
117
+ 'tech-architecture': 'arch-architecture',
118
+ 'api-contracts': 'arch-api-contracts',
119
+ 'api-contract': 'arch-api-contracts',
120
+ 'api-integrations': 'arch-api-integrations',
121
+ 'api-int': 'arch-api-integrations',
122
+ 'database-schema': 'arch-database',
123
+ 'db-schema': 'arch-database',
124
+ db: 'arch-database',
125
+ 'cyber-security': 'arch-security',
126
+ security: 'arch-security',
127
+ sec: 'arch-security',
128
+ 'design-system': 'arch-design-system',
129
+ ds: 'arch-design-system',
130
+ 'atomic-design': 'arch-design-system',
131
+ 'ux-design': 'arch-ux-design',
132
+ ux: 'arch-ux-design',
133
+ wireframes: 'arch-ux-design',
134
+ wireframe: 'arch-ux-design',
135
+ 'user-flows': 'arch-ux-design',
136
+ performance: 'arch-performance',
137
+ perf: 'arch-performance',
138
+ 'capacity-planning': 'arch-performance',
139
+ capacity: 'arch-performance',
140
+ 'arch-perf': 'arch-performance',
141
+ 'performance-strategy': 'arch-performance',
142
+ 'testing-strategy': 'arch-testing',
143
+ 'test-plan': 'arch-testing',
144
+ 'test-strategy': 'arch-testing',
145
+ 'arch-test': 'arch-testing',
146
+ infrastructure: 'arch-infrastructure',
147
+ infra: 'arch-infrastructure',
148
+ 'deploy-plan': 'arch-infrastructure',
149
+ deployment: 'arch-infrastructure',
150
+ 'arch-infra': 'arch-infrastructure',
151
+ 'arch-deploy': 'arch-infrastructure',
152
+ 'review-consolidation': 'arch-review',
153
+ consolidation: 'arch-review',
154
+ 'architecture-review': 'arch-review',
155
+ 'arch-consolidation': 'arch-review',
156
+ fitness: 'arch-fitness-functions',
157
+ 'fitness-functions': 'arch-fitness-functions',
158
+ archfit: 'arch-fitness-functions',
159
+ 'arch-fit': 'arch-fitness-functions',
160
+ 'fit-funcs': 'arch-fitness-functions',
161
+ 'criar-epic': 'create-epic',
162
+ planejamento: 'create-epic',
163
+ 'idea-diag': 'idea-diagnose',
164
+ 'idea-pesq': 'idea-research',
165
+ 'gerar-epic': 'generate-epic',
166
+ executar: 'exec',
167
+ pipeline: 'exec',
168
+ 'parallel-epic': 'epic',
169
+ setup: 'setup-branch',
170
+ branch: 'setup-branch',
171
+ diag: 'diagnose',
172
+ diagnostico: 'diagnose',
173
+ c02: 'diagnose',
174
+ pesquisar: 'research',
175
+ pesq: 'research',
176
+ 'research-fix': 'research',
177
+ c03: 'research',
178
+ spec: 'write-spec',
179
+ especificacao: 'write-spec',
180
+ c04: 'write-spec',
181
+ tasks: 'create-tasks',
182
+ tarefas: 'create-tasks',
183
+ c05: 'create-tasks',
184
+ impl: 'implement',
185
+ implementar: 'implement',
186
+ c06: 'implement',
187
+ push: 'commit',
188
+ 'commit_push': 'commit',
189
+ cp: 'commit',
190
+ c07: 'commit',
191
+ sincronizar: 'sync',
192
+ c08: 'sync',
193
+ pr: 'create-pr',
194
+ c09: 'create-pr',
195
+ revisar: 'review',
196
+ c11: 'review',
197
+ mesclar: 'merge',
198
+ c12: 'merge',
199
+ fix: 'fix-blocked',
200
+ corrigir: 'fix-blocked',
201
+ finalizar: 'finalize-epic',
202
+ conflitos: 'resolve-conflicts',
203
+ memoria: 'update-memory',
204
+ refactoring: 'refactor',
205
+ refact: 'refactor',
206
+ refac: 'refactor',
207
+ rf: 'refactor',
208
+ 'cleanup-code': 'refactor',
209
+ 'code-cleanup': 'refactor',
210
+ 'code-quality': 'refactor',
211
+ 'improve-code': 'refactor',
212
+ modernize: 'refactor',
213
+ modernization: 'refactor',
214
+ legacy: 'refactor',
215
+ 'legacy-code': 'refactor',
216
+ 'debt-pay': 'refactor',
217
+ 'pay-debt': 'refactor',
218
+ 'debt-reduction': 'refactor',
219
+ 'smell-fix': 'refactor',
220
+ 'fix-smells': 'refactor',
221
+ 'code-smells': 'refactor',
222
+ strangler: 'refactor',
223
+ 'strangler-fig': 'refactor',
224
+ limpar: 'cleanup',
225
+ limpeza: 'cleanup',
226
+ auditar: 'audit',
227
+ auditoria: 'audit',
228
+ debt: 'tech-debt',
229
+ debts: 'tech-debt',
230
+ 'debt-list': 'tech-debt',
231
+ 'tech-debts': 'tech-debt',
232
+ td: 'tech-debt',
233
+ help: 'menu',
234
+ ajuda: 'menu',
235
+ '?': 'menu',
236
+ commands: 'menu',
237
+ cmds: 'menu',
238
+ planos: 'plans',
239
+ pricing: 'plans',
240
+ bill: 'billing',
241
+ subscription: 'billing',
242
+ sub: 'billing',
243
+ upgrade: 'subscribe',
244
+ checkout: 'subscribe',
245
+ qa: 'qa-scan',
246
+ 'qa-test': 'qa-scan',
247
+ 'visual-qa': 'qa-scan',
248
+ 'e2e-scan': 'qa-scan',
249
+ troubleshoot: 'qa-scan',
250
+ 'debug-ui': 'qa-scan',
251
+ scan: 'qa-scan',
252
+ a11y: 'qa-scan',
253
+ accessibility: 'qa-scan',
254
+ wcag: 'qa-scan',
255
+ 'auto-yolo': 'yoloop',
256
+ 'epic-runner': 'yoloop',
257
+ 'story-runner': 'yoloop',
258
+ 'loop-yolo': 'yoloop',
259
+ 'auto-epic': 'yoloop',
260
+ migrate: 'migrate-state',
261
+ 'state-migrate': 'migrate-state',
262
+ 'schema-migrate': 'migrate-state',
263
+ policy: 'policy-audit',
264
+ 'audit-policy': 'policy-audit',
265
+ 'policy-history': 'policy-audit',
266
+ policies: 'policy-audit',
267
+ mutation: 'mutation-test',
268
+ stryker: 'mutation-test',
269
+ 'kill-mutants': 'mutation-test',
270
+ 'openapi-sync': 'sync-openapi',
271
+ 'api-sync': 'sync-openapi',
272
+ 'spec-sync': 'sync-openapi',
273
+ 'regen-openapi': 'sync-openapi',
274
+ pacts: 'generate-pacts',
275
+ 'gen-pacts': 'generate-pacts',
276
+ 'regen-pacts': 'generate-pacts',
277
+ 'create-pacts': 'generate-pacts',
278
+ 'verify-pact': 'verify-pacts',
279
+ 'pact-verify': 'verify-pacts',
280
+ 'check-pacts': 'verify-pacts',
281
+ 'pact-check': 'verify-pacts',
282
+ property: 'property-test',
283
+ pbt: 'property-test',
284
+ proptest: 'property-test',
285
+ 'invariant-test': 'property-test',
286
+ chaos: 'chaos-plan',
287
+ gameday: 'chaos-plan',
288
+ 'resilience-test': 'chaos-plan',
289
+ 'ux-review': 'ui-ux-review',
290
+ 'design-review': 'ui-ux-review',
291
+ 'visual-review': 'ui-ux-review',
292
+ 'product-polish': 'ui-ux-review',
293
+ 'security-system': 'solyd-system',
294
+ 'authorized-security': 'solyd-system',
295
+ 'sec-system': 'solyd-system',
296
+ goals: 'goal',
297
+ 'durable-goal': 'goal',
298
+ 'continuity-goal': 'goal',
299
+ loops: 'loop',
300
+ 'durable-loop': 'loop',
301
+ 'continuity-loop': 'loop',
302
+ job: 'jobs',
303
+ 'continuity-jobs': 'jobs',
304
+ 'neocortex-runner': 'runner',
305
+ 'continuity-runner': 'runner',
306
+ });
307
+ const COMMAND_NUMBER_TO_ID = Object.freeze({
308
+ '1': 'status',
309
+ '3': 'arch-plan',
310
+ '4': 'arch-prd',
311
+ '5': 'arch-architecture',
312
+ '6': 'arch-api-contracts',
313
+ '7': 'arch-api-integrations',
314
+ '8': 'arch-database',
315
+ '9': 'arch-security',
316
+ '10': 'arch-design-system',
317
+ '11': 'arch-ux-design',
318
+ '12': 'arch-performance',
319
+ '13': 'arch-testing',
320
+ '14': 'arch-infrastructure',
321
+ '15': 'arch-review',
322
+ '16': 'arch-fitness-functions',
323
+ '17': 'create-epic',
324
+ '18': 'idea-diagnose',
325
+ '19': 'idea-research',
326
+ '20': 'generate-epic',
327
+ '21': 'exec',
328
+ '22': 'yolo',
329
+ '23': 'epic',
330
+ '24': 'setup-branch',
331
+ '25': 'diagnose',
332
+ '26': 'research',
333
+ '27': 'write-spec',
334
+ '28': 'create-tasks',
335
+ '29': 'implement',
336
+ '30': 'commit',
337
+ '31': 'sync',
338
+ '32': 'create-pr',
339
+ '33': 'review',
340
+ '34': 'merge',
341
+ '35': 'fix-blocked',
342
+ '36': 'finalize-epic',
343
+ '37': 'resolve-conflicts',
344
+ '38': 'update-memory',
345
+ '39': 'refactor',
346
+ '40': 'cleanup',
347
+ '41': 'audit',
348
+ '42': 'tech-debt',
349
+ '43': 'menu',
350
+ '44': 'plans',
351
+ '45': 'billing',
352
+ '46': 'subscribe',
353
+ '47': 'qa-scan',
354
+ '48': 'yoloop',
355
+ '49': 'migrate-state',
356
+ '50': 'policy-audit',
357
+ '51': 'mutation-test',
358
+ '52': 'sync-openapi',
359
+ '53': 'generate-pacts',
360
+ '54': 'verify-pacts',
361
+ '55': 'property-test',
362
+ '56': 'chaos-plan',
363
+ '57': 'ui-ux-review',
364
+ '58': 'solyd-system',
365
+ '59': 'goal',
366
+ '60': 'loop',
367
+ '61': 'jobs',
368
+ '62': 'runner',
369
+ });
370
+ function safeToken(value, maxLength = 120) {
371
+ if (typeof value !== 'string')
372
+ return undefined;
373
+ const trimmed = value.trim();
374
+ if (!trimmed)
375
+ return undefined;
376
+ return trimmed.replace(/[^a-z0-9_.:-]+/gi, '_').slice(0, maxLength);
377
+ }
378
+ function safeCanonicalToken(value, maxLength = 120) {
379
+ if (typeof value !== 'string')
380
+ return undefined;
381
+ const trimmed = value.trim();
382
+ const safe = safeToken(value, maxLength);
383
+ return safe === trimmed ? safe : undefined;
384
+ }
385
+ function safeGitRef(value) {
386
+ if (typeof value !== 'string')
387
+ return undefined;
388
+ const trimmed = value.trim();
389
+ if (!trimmed || trimmed.length > 240 || !/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(trimmed)
390
+ || trimmed.includes('..') || trimmed.includes('//') || trimmed.includes('@{')
391
+ || trimmed.endsWith('/') || trimmed.endsWith('.')
392
+ || trimmed.split('/').some((part) => !part || part.startsWith('.') || part.endsWith('.lock')))
393
+ return undefined;
394
+ return trimmed;
395
+ }
396
+ function safeWriteRef(value) {
397
+ if (typeof value !== 'string')
398
+ return undefined;
399
+ const normalized = value.replace(/\\/g, '/');
400
+ if (!normalized || normalized.length > 240 || normalized.startsWith('/')
401
+ || /^[A-Za-z]:/.test(normalized) || normalized.includes('..') || normalized.includes('//')
402
+ || normalized.split('/').includes('.') || !/^[A-Za-z0-9._/:@#-]+$/.test(normalized))
403
+ return undefined;
404
+ return normalized;
405
+ }
406
+ function safeWriteRefs(value) {
407
+ if (value === undefined)
408
+ return undefined;
409
+ if (!Array.isArray(value) || value.length > 128)
410
+ return undefined;
411
+ const refs = value.map(safeWriteRef);
412
+ if (refs.some((ref) => ref === undefined))
413
+ return undefined;
414
+ return [...new Set(refs)].sort((left, right) => left.localeCompare(right, 'en'));
415
+ }
416
+ function isActiveYoloopStory(status) {
417
+ return typeof status === 'string'
418
+ && YOLOOP_ACTIVE_STORY_STATUS_SET.has(status.trim().toLowerCase().replace(/_/g, '-'));
419
+ }
420
+ function pickPublicScalarFields(value, allowlist) {
421
+ const result = {};
422
+ for (const key of allowlist) {
423
+ const field = value[key];
424
+ if (typeof field === 'string' || typeof field === 'boolean'
425
+ || typeof field === 'number' && Number.isFinite(field))
426
+ result[key] = field;
427
+ else if (Array.isArray(field) && field.every((item) => typeof item === 'string'))
428
+ result[key] = [...field];
429
+ }
430
+ return result;
431
+ }
432
+ function publicResumeCheckpoint(storyId, story) {
433
+ const value = story.checkpoint;
434
+ if (!isRecord(value) || value.schemaVersion !== 1 || value.storyId !== storyId
435
+ || value.epicId !== story.epic_id || !safeGitRef(value.branch)
436
+ || typeof value.baseSha !== 'string' || !/^[0-9a-f]{7,64}$/i.test(value.baseSha)
437
+ || typeof value.headSha !== 'string' || !/^[0-9a-f]{7,64}$/i.test(value.headSha)
438
+ || value.baseSha === value.headSha || !safeCanonicalToken(value.idempotencyKey)
439
+ || typeof value.recordedAt !== 'string' || !Number.isFinite(Date.parse(value.recordedAt))
440
+ || !Array.isArray(value.commits) || value.commits.length === 0 || value.commits.length > 256
441
+ || value.commits.some((sha) => typeof sha !== 'string' || !/^[0-9a-f]{7,64}$/i.test(sha))
442
+ || !Array.isArray(value.receiptRefs) || value.receiptRefs.length === 0 || value.receiptRefs.length > 256
443
+ || value.receiptRefs.some((ref) => typeof ref !== 'string' || ref.length > 240 || ref.includes('..')
444
+ || !/^[A-Za-z0-9._:/#\-[\]]+$/.test(ref))
445
+ || !isRecord(value.qaReceipt) || value.qaReceipt.kind !== 'story_qa_evidence'
446
+ || value.qaReceipt.producer !== 'local-yolo-tdd'
447
+ || !['passed', 'blocked'].includes(String(value.qaVerdict))
448
+ || !['approved', 'changes-requested', 'pending'].includes(String(value.reviewVerdict)))
449
+ return undefined;
450
+ if (value.reviewVerdict === 'pending' ? value.reviewReceipt !== undefined : !isRecord(value.reviewReceipt))
451
+ return undefined;
452
+ // collectStateSnapshot already validated field values. Re-project the exact
453
+ // public allowlist so later hooks or synthetic callers cannot append content.
454
+ const result = pickPublicScalarFields(value, [
455
+ 'schemaVersion', 'storyId', 'epicId', 'branch', 'baseSha', 'headSha',
456
+ 'idempotencyKey', 'dispatchId', 'bundleId', 'bundleDigest', 'graphRevision',
457
+ 'claimRevision', 'qaVerdict', 'reviewVerdict', 'recordedAt', 'commits',
458
+ 'receiptRefs',
459
+ ]);
460
+ result.qaReceipt = pickPublicScalarFields(value.qaReceipt, [
461
+ 'schemaVersion', 'kind', 'producer', 'evidenceVersion', 'storyId', 'epicId',
462
+ 'contract', 'command', 'manifestDigest', 'gateIds', 'resultDigest', 'baseSha',
463
+ 'headSha', 'bundleDigest', 'graphRevision', 'sourceEvidenceDigest', 'verdict',
464
+ 'checkedAt', 'receiptRef',
465
+ ]);
466
+ if (isRecord(value.reviewReceipt)) {
467
+ result.reviewReceipt = pickPublicScalarFields(value.reviewReceipt, [
468
+ 'schemaVersion', 'kind', 'producer', 'storyId', 'epicId', 'baseSha',
469
+ 'headSha', 'bundleDigest', 'graphRevision', 'sourceEvidenceDigest',
470
+ 'qaReceiptRef', 'verdict', 'reviewedAt', 'receiptRef',
471
+ ]);
472
+ }
473
+ return result;
474
+ }
475
+ function publicCheckpointVerification(storyId, story) {
476
+ const value = story.checkpoint_verification;
477
+ if (!isRecord(value) || value.schemaVersion !== 1
478
+ || value.kind !== 'story_checkpoint_physical_verification'
479
+ || value.producer !== 'client-p205-transient-v1' || value.publicSafe !== true
480
+ || value.storyId !== storyId || value.epicId !== story.epic_id
481
+ || !['verified', 'rejected'].includes(String(value.verdict)))
482
+ return undefined;
483
+ return pickPublicScalarFields(value, [
484
+ 'schemaVersion', 'kind', 'producer', 'storyId', 'epicId', 'branch',
485
+ 'baseSha', 'headSha', 'aggregateHeadSha', 'commitBodyDigest',
486
+ 'changedPathsDigest', 'claimVerification', 'effectiveClaimRevision',
487
+ 'command', 'manifestDigest', 'gateIds', 'resultDigest', 'graphRevision',
488
+ 'executionEvidenceDigest', 'sourceEvidenceDigest', 'verifiedAt', 'verdict',
489
+ 'reasonCodes', 'publicSafe',
490
+ ]);
491
+ }
492
+ function publicSchedulingCheckpointEvidence(storyId, story) {
493
+ const value = story.scheduling_checkpoint_evidence;
494
+ const allowed = new Set([
495
+ 'schemaVersion', 'kind', 'producer', 'storyId', 'epicId', 'branch', 'baseSha', 'headSha',
496
+ 'graphRevision', 'effectiveClaimRevision', 'sourceEvidenceDigest', 'verifiedAt', 'reasonCodes',
497
+ 'integrationAuthorized', 'publicSafe',
498
+ ]);
499
+ if (!isRecord(value) || Object.keys(value).some((key) => !allowed.has(key))
500
+ || value.schemaVersion !== 1 || value.kind !== 'story_scheduling_checkpoint_evidence'
501
+ || value.producer !== 'client-git-physical-v1' || value.publicSafe !== true
502
+ || value.integrationAuthorized !== false || value.storyId !== storyId || value.epicId !== story.epic_id
503
+ || !safeGitRef(value.branch) || typeof value.baseSha !== 'string' || !/^[0-9a-f]{40,64}$/i.test(value.baseSha)
504
+ || typeof value.headSha !== 'string' || !/^[0-9a-f]{40,64}$/i.test(value.headSha)
505
+ || typeof value.graphRevision !== 'string' || !/^[0-9a-f]{64}$/i.test(value.graphRevision)
506
+ || typeof value.effectiveClaimRevision !== 'string' || !/^[0-9a-f]{64}$/i.test(value.effectiveClaimRevision)
507
+ || typeof value.sourceEvidenceDigest !== 'string' || !/^[0-9a-f]{64}$/i.test(value.sourceEvidenceDigest)
508
+ || typeof value.verifiedAt !== 'string' || !Number.isFinite(Date.parse(value.verifiedAt))
509
+ || !Array.isArray(value.reasonCodes) || value.reasonCodes.length !== 1
510
+ || value.reasonCodes[0] !== 'checkpoint-git-scheduling-verified')
511
+ return undefined;
512
+ return pickPublicScalarFields(value, [...allowed]);
513
+ }
514
+ function projectSchedulingLane(storyId, story) {
515
+ const projected = { ...story };
516
+ const evidence = publicSchedulingCheckpointEvidence(storyId, story);
517
+ if (evidence) {
518
+ projected.scheduling_checkpoint_evidence = evidence;
519
+ delete projected.checkpoint;
520
+ delete projected.checkpoint_verification;
521
+ }
522
+ else {
523
+ delete projected.scheduling_checkpoint_evidence;
524
+ }
525
+ return projected;
526
+ }
527
+ function isRecord(value) {
528
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
529
+ }
530
+ function safeReasonCodes(...groups) {
531
+ const seen = new Set();
532
+ const reasonCodes = [];
533
+ for (const group of groups) {
534
+ for (const reasonCode of group ?? []) {
535
+ const safe = safeToken(reasonCode, 80);
536
+ if (!safe || seen.has(safe))
537
+ continue;
538
+ seen.add(safe);
539
+ reasonCodes.push(safe);
540
+ if (reasonCodes.length >= REASON_CODE_LIMIT)
541
+ return reasonCodes;
542
+ }
543
+ }
544
+ return reasonCodes;
545
+ }
546
+ function normalizeCommandToken(input) {
547
+ return input.trim().replace(/^@?\*/, '').replace(/^@/, '').toLowerCase();
548
+ }
549
+ function leadingCommandToken(input) {
550
+ return input.trim().split(/\s+/, 1)[0] ?? '';
551
+ }
552
+ function resolveCommandProjectionPolicy(args) {
553
+ // The exact published @epic-P{N} spelling is a one-token command and its
554
+ // own target. It must receive the same structural projection as *epic.
555
+ if (/^@epic-P[0-9]{1,12}$/.test(args.trim()))
556
+ return COMMAND_POLICY_BY_ID.epic;
557
+ const token = leadingCommandToken(args);
558
+ if (!token)
559
+ return COMMAND_POLICY_BY_ID.menu;
560
+ const normalized = normalizeCommandToken(token);
561
+ const commandId = COMMAND_NUMBER_TO_ID[normalized]
562
+ ?? COMMAND_ALIAS_TO_ID[normalized]
563
+ ?? normalized;
564
+ return COMMAND_POLICY_BY_ID[commandId] ?? null;
565
+ }
566
+ function createFullScope(trigger, snapshot, commandPolicy, projectionMode = 'full-compatible', reasonCodes = ['full-state']) {
567
+ return {
568
+ kind: 'full',
569
+ commandId: commandPolicy?.commandId ?? null,
570
+ stateProjectionPolicy: commandPolicy?.stateProjectionPolicy ?? null,
571
+ projectionMode,
572
+ trigger,
573
+ targetEpicId: null,
574
+ targetStoryId: null,
575
+ includedStoryCount: Object.keys(snapshot.stories).length,
576
+ includedEpicCount: Object.keys(snapshot.epics).length,
577
+ omittedStoryCount: 0,
578
+ omittedEpicCount: 0,
579
+ reason: 'full-state',
580
+ reasonCodes: safeReasonCodes(reasonCodes),
581
+ };
582
+ }
583
+ function fullSnapshot(trigger, snapshot, commandPolicy, projectionMode = 'full-compatible', reasonCodes = ['full-state']) {
584
+ const scope = createFullScope(trigger, snapshot, commandPolicy, projectionMode, reasonCodes);
585
+ return withStateSummary({
586
+ ...snapshot,
587
+ scope,
588
+ }, snapshot, scope);
589
+ }
590
+ function firstTokenIsStoryReference(args) {
591
+ const [firstToken] = args.trim().split(/\s+/, 1);
592
+ if (!firstToken)
593
+ return false;
594
+ return (/^[A-Z]?\d+(?:\.\d+)+$/i.test(firstToken.replace(/^@/, '')) ||
595
+ /(?:^|\/)[A-Z]?\d+(?:\.\d+)+\.story\.md$/i.test(firstToken.replace(/^@/, '')));
596
+ }
597
+ function extractStoryId(args) {
598
+ const storyFileMatch = args.match(/(?:^|[/@\s])([A-Z]?\d+(?:\.\d+)+)\.story\.md\b/i);
599
+ if (storyFileMatch?.[1])
600
+ return storyFileMatch[1];
601
+ const storyIdMatch = args.match(/(?:^|\s|@)([A-Z]?\d+(?:\.\d+)+)(?=$|\s)/i);
602
+ return storyIdMatch?.[1] ?? null;
603
+ }
604
+ function triggerRemainder(args) {
605
+ const trimmed = args.trim();
606
+ const firstWhitespace = trimmed.search(/\s/);
607
+ return firstWhitespace === -1 ? '' : trimmed.slice(firstWhitespace).trim();
608
+ }
609
+ function positionalTokens(args) {
610
+ return triggerRemainder(args)
611
+ .split(/\s+/)
612
+ .map((token) => token.replace(/^@/, '').replace(/^['"]|['"]$/g, ''))
613
+ .filter((token) => token.length > 0 && !token.startsWith('-'));
614
+ }
615
+ function firstPositionalArg(args) {
616
+ return positionalTokens(args)[0] ?? null;
617
+ }
618
+ function resolveEpicId(candidate, snapshot) {
619
+ const normalized = candidate.replace(/^@/, '').replace(/^epic-/i, '');
620
+ const withoutExtension = normalized.replace(/\.md$/i, '');
621
+ const candidates = [
622
+ withoutExtension,
623
+ withoutExtension.toUpperCase(),
624
+ /^p\d+$/i.test(withoutExtension)
625
+ ? `P${withoutExtension.replace(/^p/i, '')}`
626
+ : null,
627
+ /^\d+$/.test(withoutExtension) ? `P${withoutExtension}` : null,
628
+ ].filter((entry) => typeof entry === 'string' && entry.length > 0);
629
+ for (const entry of candidates) {
630
+ if (snapshot.epics[entry])
631
+ return entry;
632
+ }
633
+ return null;
634
+ }
635
+ function extractEpicIdFromCanonicalFile(args, snapshot) {
636
+ const match = args.match(/(?:^|[/@\s])epic-(P?\d+)\.md\b/i);
637
+ if (!match?.[1])
638
+ return null;
639
+ return resolveEpicId(match[1], snapshot);
640
+ }
641
+ function extractTargetEpicId(args, snapshot) {
642
+ const directEpic = args.trim().match(/^@epic-(P[0-9]{1,12})$/);
643
+ if (directEpic)
644
+ return resolveEpicId(directEpic[1], snapshot);
645
+ const fromFile = extractEpicIdFromCanonicalFile(args, snapshot);
646
+ if (fromFile)
647
+ return fromFile;
648
+ for (const token of positionalTokens(args)) {
649
+ if (/^[A-Z]?\d+(?:\.\d+)+$/i.test(token))
650
+ continue;
651
+ const fromToken = resolveEpicId(token, snapshot);
652
+ if (fromToken)
653
+ return fromToken;
654
+ }
655
+ return null;
656
+ }
657
+ function extractYoloopTargetEpicId(args, snapshot) {
658
+ const fromTarget = extractTargetEpicId(args, snapshot);
659
+ if (fromTarget)
660
+ return fromTarget;
661
+ const yoloop = snapshot.yoloop;
662
+ const sessionEpicId = yoloop?.state?.currentSession?.currentEpicId;
663
+ if (typeof sessionEpicId === 'string' && snapshot.epics[sessionEpicId]) {
664
+ return sessionEpicId;
665
+ }
666
+ const lockEpicId = yoloop?.lock?.currentEpicId ?? yoloop?.lock?.epicId;
667
+ if (typeof lockEpicId === 'string' && snapshot.epics[lockEpicId]) {
668
+ return lockEpicId;
669
+ }
670
+ return null;
671
+ }
672
+ function explicitYoloopEpicCandidate(args) {
673
+ const fromFile = args.match(/(?:^|[/@\s])epic-(P?\d+)\.md\b/i)?.[1];
674
+ if (fromFile)
675
+ return /^P/i.test(fromFile) ? fromFile.toUpperCase() : `P${fromFile}`;
676
+ for (const token of positionalTokens(args)) {
677
+ if (/^P\d+$/i.test(token))
678
+ return token.toUpperCase();
679
+ if (/^\d+$/.test(token))
680
+ return `P${token}`;
681
+ }
682
+ return null;
683
+ }
684
+ function storyEpicId(story, storyId) {
685
+ if (typeof story.epic_id === 'string' && story.epic_id.length > 0) {
686
+ return story.epic_id;
687
+ }
688
+ const derived = storyId.split('.').slice(0, -1).join('.');
689
+ return derived.length > 0 ? derived : null;
690
+ }
691
+ function isTerminalStoryStatus(status) {
692
+ return typeof status === 'string' && ['done', 'completed', 'merged', 'cancelled', 'canceled', 'abandoned'].includes(status.toLowerCase());
693
+ }
694
+ function addStoryAndDependencies(storyId, snapshot, includedStoryIds) {
695
+ if (includedStoryIds.has(storyId))
696
+ return;
697
+ const story = snapshot.stories[storyId];
698
+ if (!story)
699
+ return;
700
+ includedStoryIds.add(storyId);
701
+ const dependsOn = story.depends_on;
702
+ if (!Array.isArray(dependsOn))
703
+ return;
704
+ for (const dependencyId of dependsOn) {
705
+ if (typeof dependencyId === 'string') {
706
+ addStoryAndDependencies(dependencyId, snapshot, includedStoryIds);
707
+ }
708
+ }
709
+ }
710
+ function buildProjectedStories(targetStoryId, snapshot) {
711
+ const analysis = analyzeDependencyDag(snapshot.stories, [targetStoryId]);
712
+ const projectedStories = {};
713
+ for (const storyId of analysis.orderedIds) {
714
+ const story = snapshot.stories[storyId];
715
+ if (story) {
716
+ projectedStories[storyId] = story;
717
+ }
718
+ }
719
+ return projectedStories;
720
+ }
721
+ function buildProjectedEpics(projectedStories, snapshot, requiredEpicIds = []) {
722
+ const projectedEpics = {};
723
+ for (const epicId of requiredEpicIds) {
724
+ if (snapshot.epics[epicId]) {
725
+ projectedEpics[epicId] = snapshot.epics[epicId];
726
+ }
727
+ }
728
+ for (const [storyId, story] of Object.entries(projectedStories)) {
729
+ const epicId = storyEpicId(story, storyId);
730
+ if (epicId && snapshot.epics[epicId]) {
731
+ projectedEpics[epicId] = snapshot.epics[epicId];
732
+ }
733
+ }
734
+ return projectedEpics;
735
+ }
736
+ function addEpicAndDependencies(epicId, snapshot, includedEpicIds) {
737
+ if (includedEpicIds.has(epicId))
738
+ return;
739
+ const epic = snapshot.epics[epicId];
740
+ if (!epic)
741
+ return;
742
+ includedEpicIds.add(epicId);
743
+ const dependsOn = epic.depends_on;
744
+ if (!Array.isArray(dependsOn))
745
+ return;
746
+ for (const dependencyId of dependsOn) {
747
+ if (typeof dependencyId === 'string' && dependencyId.length > 0) {
748
+ addEpicAndDependencies(dependencyId, snapshot, includedEpicIds);
749
+ }
750
+ }
751
+ }
752
+ function buildProjectedYoloopEpics(targetEpicId, projectedStories, snapshot) {
753
+ const epicAnalysis = analyzeDependencyDag(snapshot.epics, [targetEpicId]);
754
+ const requiredEpicIds = new Set(epicAnalysis.orderedIds);
755
+ for (const [storyId, story] of Object.entries(projectedStories)) {
756
+ const parentEpicId = storyEpicId(story, storyId);
757
+ if (parentEpicId && snapshot.epics[parentEpicId])
758
+ requiredEpicIds.add(parentEpicId);
759
+ }
760
+ const projectedEpics = {};
761
+ for (const epicId of [...requiredEpicIds].sort((left, right) => left.localeCompare(right, 'en'))) {
762
+ const epic = snapshot.epics[epicId];
763
+ if (!epic)
764
+ continue;
765
+ projectedEpics[epicId] = epicId === targetEpicId ? epic : compactStructuralEpic(epicId, epic);
766
+ }
767
+ return projectedEpics;
768
+ }
769
+ function buildProjectedYoloopStories(targetEpicId, targetEpic, snapshot) {
770
+ const storyIds = targetEpic.stories;
771
+ if (!Array.isArray(storyIds)
772
+ || storyIds.some((storyId) => typeof storyId !== 'string' || storyId.length === 0)) {
773
+ throw new StructuralDagError('STRUCTURAL_DEPENDENCY_MISSING', {
774
+ nodes: 0,
775
+ edges: 0,
776
+ malformedStoryMemberships: 1,
777
+ });
778
+ }
779
+ const analysis = analyzeDependencyDag(snapshot.stories, storyIds);
780
+ const projectedStories = {};
781
+ for (const storyId of analysis.orderedIds) {
782
+ const story = snapshot.stories[storyId];
783
+ if (story) {
784
+ projectedStories[storyId] = storyEpicId(story, storyId) === targetEpicId
785
+ ? projectSchedulingLane(storyId, story)
786
+ : compactStructuralStory(storyId, story);
787
+ }
788
+ }
789
+ return projectedStories;
790
+ }
791
+ function buildTargetEpicCoverage(targetEpicId, targetEpic, projectedStories) {
792
+ const declaredStoryIds = [...targetEpic.stories]
793
+ .sort((left, right) => left.localeCompare(right, 'en'));
794
+ const includedStoryIds = Object.entries(projectedStories)
795
+ .filter(([storyId, story]) => storyEpicId(story, storyId) === targetEpicId)
796
+ .map(([storyId]) => storyId)
797
+ .sort((left, right) => left.localeCompare(right, 'en'));
798
+ const membershipSha256 = createHash('sha256')
799
+ .update(`target-epic-coverage-v1\0${JSON.stringify({ targetEpicId, declaredStoryIds, includedStoryIds })}`)
800
+ .digest('hex');
801
+ return {
802
+ schemaVersion: 'TargetEpicCoverage/1.0',
803
+ targetEpicId,
804
+ declaredStoryIds,
805
+ includedStoryIds,
806
+ membershipSha256,
807
+ publicSafe: true,
808
+ };
809
+ }
810
+ function compactStructuralStory(storyId, story) {
811
+ const dependsOn = Array.isArray(story.depends_on)
812
+ ? [...new Set(story.depends_on.filter((value) => typeof value === 'string' && value.length > 0))]
813
+ .sort((left, right) => left.localeCompare(right, 'en'))
814
+ : [];
815
+ const compact = {
816
+ id: safeToken(story.id) ?? storyId,
817
+ ...(safeToken(story.epic_id) ? { epic_id: safeToken(story.epic_id) } : {}),
818
+ ...(safeToken(story.status, 40) ? { status: safeToken(story.status, 40) } : {}),
819
+ depends_on: dependsOn,
820
+ };
821
+ const schedulingEvidence = publicSchedulingCheckpointEvidence(storyId, story);
822
+ if (!isActiveYoloopStory(story.status)) {
823
+ return { ...compact, ...(schedulingEvidence ? { scheduling_checkpoint_evidence: schedulingEvidence } : {}) };
824
+ }
825
+ const source = story.source === 'create-epic' || story.source === 'discovered'
826
+ ? story.source : undefined;
827
+ const branchName = safeGitRef(story.branch_name);
828
+ const lastStep = safeCanonicalToken(story.last_step, 120);
829
+ const steps = Array.isArray(story.steps_completed) && story.steps_completed.length <= 64
830
+ ? story.steps_completed.map((step) => safeCanonicalToken(step, 120))
831
+ : [];
832
+ const validSteps = steps.length > 0 && steps.every((step) => step !== undefined)
833
+ ? steps : undefined;
834
+ const prNumber = typeof story.pr_number === 'number' && Number.isSafeInteger(story.pr_number)
835
+ && story.pr_number > 0 ? story.pr_number : undefined;
836
+ const checkpoint = publicResumeCheckpoint(storyId, story);
837
+ const checkpointVerification = checkpoint ? publicCheckpointVerification(storyId, story) : undefined;
838
+ return {
839
+ ...compact,
840
+ ...(source ? { source } : {}),
841
+ ...(branchName ? { branch_name: branchName } : {}),
842
+ ...(lastStep ? { last_step: lastStep } : {}),
843
+ ...(validSteps ? { steps_completed: validSteps } : {}),
844
+ ...(prNumber ? { pr_number: prNumber } : {}),
845
+ ...(checkpoint ? { checkpoint } : {}),
846
+ ...(checkpointVerification ? { checkpoint_verification: checkpointVerification } : {}),
847
+ ...(schedulingEvidence ? { scheduling_checkpoint_evidence: schedulingEvidence } : {}),
848
+ ...(safeWriteRefs(story.files_to_modify) !== undefined
849
+ ? { files_to_modify: safeWriteRefs(story.files_to_modify) } : {}),
850
+ ...(safeWriteRefs(story.contracts) !== undefined
851
+ ? { contracts: safeWriteRefs(story.contracts) } : {}),
852
+ ...(safeWriteRefs(story.contract_refs) !== undefined
853
+ ? { contract_refs: safeWriteRefs(story.contract_refs) } : {}),
854
+ ...(safeWriteRefs(story.shared_surfaces) !== undefined
855
+ ? { shared_surfaces: safeWriteRefs(story.shared_surfaces) } : {}),
856
+ };
857
+ }
858
+ function compactStructuralEpic(epicId, epic) {
859
+ const stories = Array.isArray(epic.stories)
860
+ ? [...new Set(epic.stories.filter((value) => typeof value === 'string' && value.length > 0))]
861
+ .sort((left, right) => left.localeCompare(right, 'en'))
862
+ : [];
863
+ const dependsOn = Array.isArray(epic.depends_on)
864
+ ? [...new Set(epic.depends_on.filter((value) => typeof value === 'string' && value.length > 0))]
865
+ .sort((left, right) => left.localeCompare(right, 'en'))
866
+ : [];
867
+ return {
868
+ id: safeToken(epic.id) ?? epicId,
869
+ ...(safeToken(epic.status, 40) ? { status: safeToken(epic.status, 40) } : {}),
870
+ ...(safeToken(epic.lifecycle_classification, 40)
871
+ ? { lifecycle_classification: safeToken(epic.lifecycle_classification, 40) }
872
+ : {}),
873
+ stories,
874
+ depends_on: dependsOn,
875
+ };
876
+ }
877
+ function buildYoloopDiscoveryProjection(trigger, snapshot, commandPolicy) {
878
+ const storyAnalysis = analyzeDependencyDag(snapshot.stories);
879
+ const epicAnalysis = analyzeDependencyDag(snapshot.epics);
880
+ const projectedStories = Object.fromEntries(storyAnalysis.orderedIds.map((storyId) => [
881
+ storyId,
882
+ compactStructuralStory(storyId, snapshot.stories[storyId]),
883
+ ]));
884
+ const projectedEpics = Object.fromEntries(epicAnalysis.orderedIds.map((epicId) => [
885
+ epicId,
886
+ compactStructuralEpic(epicId, snapshot.epics[epicId]),
887
+ ]));
888
+ const scope = {
889
+ kind: 'projected',
890
+ commandId: commandPolicy.commandId,
891
+ stateProjectionPolicy: commandPolicy.stateProjectionPolicy,
892
+ projectionMode: 'yoloop-discovery',
893
+ trigger,
894
+ targetEpicId: null,
895
+ targetStoryId: null,
896
+ includedStoryCount: storyAnalysis.orderedIds.length,
897
+ includedEpicCount: epicAnalysis.orderedIds.length,
898
+ omittedStoryCount: 0,
899
+ omittedEpicCount: 0,
900
+ reason: 'targeted-invocation',
901
+ reasonCodes: safeReasonCodes([
902
+ 'structural-required',
903
+ 'yoloop-discovery',
904
+ `structural-edges-${storyAnalysis.edgeCount + epicAnalysis.edgeCount}`,
905
+ 'content-fields-omitted',
906
+ ]),
907
+ };
908
+ return withStateSummary({
909
+ ...snapshot,
910
+ stories: projectedStories,
911
+ epics: projectedEpics,
912
+ scope,
913
+ }, snapshot, scope);
914
+ }
915
+ function buildProjectedTargetEpicStories(targetEpic, snapshot) {
916
+ const includedStoryIds = new Set();
917
+ const storyIds = targetEpic.stories;
918
+ if (Array.isArray(storyIds)) {
919
+ for (const storyId of storyIds) {
920
+ if (typeof storyId === 'string') {
921
+ addStoryAndDependencies(storyId, snapshot, includedStoryIds);
922
+ }
923
+ }
924
+ }
925
+ const projectedStories = {};
926
+ for (const storyId of includedStoryIds) {
927
+ const story = snapshot.stories[storyId];
928
+ if (story) {
929
+ projectedStories[storyId] = story;
930
+ }
931
+ }
932
+ return projectedStories;
933
+ }
934
+ function buildEpicStubs(snapshot) {
935
+ const projectedEpics = {};
936
+ for (const [epicId, epic] of Object.entries(snapshot.epics)) {
937
+ projectedEpics[epicId] = {
938
+ id: safeToken(epic.id) ?? epicId,
939
+ ...(safeToken(epic.status) ? { status: safeToken(epic.status) } : {}),
940
+ ...(EPIC_LIFECYCLE_CLASSIFICATIONS.includes(epic.lifecycle_classification)
941
+ ? { lifecycle_classification: epic.lifecycle_classification }
942
+ : {}),
943
+ ...(typeof epic.total_stories === 'number' && Number.isFinite(epic.total_stories)
944
+ ? { total_stories: epic.total_stories }
945
+ : {}),
946
+ ...(typeof epic.completed_stories === 'number' && Number.isFinite(epic.completed_stories)
947
+ ? { completed_stories: epic.completed_stories }
948
+ : {}),
949
+ };
950
+ }
951
+ return projectedEpics;
952
+ }
953
+ function countStatuses(records) {
954
+ const counts = {};
955
+ for (const record of Object.values(records)) {
956
+ const status = safeToken(record.status, 40) ?? 'unknown';
957
+ counts[status] = (counts[status] ?? 0) + 1;
958
+ }
959
+ return counts;
960
+ }
961
+ function countEpicLifecycles(records) {
962
+ const counts = Object.fromEntries(EPIC_LIFECYCLE_CLASSIFICATIONS.map((classification) => [classification, 0]));
963
+ for (const record of Object.values(records)) {
964
+ const classification = EPIC_LIFECYCLE_CLASSIFICATIONS.includes(record.lifecycle_classification)
965
+ ? record.lifecycle_classification
966
+ : 'active';
967
+ counts[classification] = (counts[classification] ?? 0) + 1;
968
+ }
969
+ return counts;
970
+ }
971
+ function isActiveEpicLifecycle(snapshot, epicId) {
972
+ if (!epicId)
973
+ return true;
974
+ const epic = snapshot.epics[epicId];
975
+ if (!epic)
976
+ return true;
977
+ return !EPIC_LIFECYCLE_CLASSIFICATIONS.includes(epic.lifecycle_classification) || epic.lifecycle_classification === 'active';
978
+ }
979
+ function sortableStoryTimestamp(story) {
980
+ for (const key of ['last_updated', 'updated_at', 'completed_at', 'created_at', 'discovered_at']) {
981
+ const value = story[key];
982
+ if (typeof value !== 'string')
983
+ continue;
984
+ const parsed = Date.parse(value);
985
+ if (Number.isFinite(parsed))
986
+ return parsed;
987
+ }
988
+ return 0;
989
+ }
990
+ function recentStories(snapshot) {
991
+ return Object.entries(snapshot.stories)
992
+ .map(([id, story]) => ({ id, story, timestamp: sortableStoryTimestamp(story) }))
993
+ .sort((left, right) => right.timestamp - left.timestamp || left.id.localeCompare(right.id))
994
+ .slice(0, RECENT_STORY_LIMIT)
995
+ .map(({ id, story }) => ({
996
+ id,
997
+ ...(safeToken(story.epic_id) ? { epicId: safeToken(story.epic_id) } : {}),
998
+ ...(safeToken(story.status, 40) ? { status: safeToken(story.status, 40) } : {}),
999
+ ...(safeToken(story.last_step ?? story.lastStep) ? { lastStep: safeToken(story.last_step ?? story.lastStep) } : {}),
1000
+ ...(safeToken(story.last_updated ?? story.updated_at ?? story.completed_at ?? story.created_at)
1001
+ ? { lastUpdated: safeToken(story.last_updated ?? story.updated_at ?? story.completed_at ?? story.created_at) }
1002
+ : {}),
1003
+ }));
1004
+ }
1005
+ function currentSessionRef(snapshot) {
1006
+ const session = snapshot.current_session;
1007
+ if (!session)
1008
+ return undefined;
1009
+ const ref = {
1010
+ activeEpicId: safeToken(session.active_epic_id) ?? null,
1011
+ activeStoryId: safeToken(session.active_story_id) ?? null,
1012
+ activeStepId: safeToken(session.active_step_id) ?? null,
1013
+ sessionId: safeToken(session.session_id) ?? null,
1014
+ startedAt: safeToken(session.started_at) ?? null,
1015
+ };
1016
+ return Object.values(ref).some((value) => value !== null && value !== undefined) ? ref : undefined;
1017
+ }
1018
+ function yoloopSessionRef(snapshot) {
1019
+ const yoloop = snapshot.yoloop;
1020
+ if (!isRecord(yoloop))
1021
+ return undefined;
1022
+ const state = isRecord(yoloop.state) ? yoloop.state : undefined;
1023
+ const currentSession = isRecord(state?.currentSession) ? state.currentSession : undefined;
1024
+ const lock = isRecord(yoloop.lock) ? yoloop.lock : undefined;
1025
+ const ref = {
1026
+ ...(typeof yoloop.active === 'boolean' ? { active: yoloop.active } : {}),
1027
+ currentEpicId: safeToken(currentSession?.currentEpicId ?? yoloop.currentEpicId) ?? null,
1028
+ currentStoryId: safeToken(currentSession?.currentStoryId ?? yoloop.currentStoryId) ?? null,
1029
+ sessionId: safeToken(currentSession?.sessionId ?? yoloop.sessionId) ?? null,
1030
+ lockEpicId: safeToken(lock?.currentEpicId ?? lock?.epicId) ?? null,
1031
+ };
1032
+ return Object.keys(ref).length > 0 ? ref : undefined;
1033
+ }
1034
+ function continuitySessionRef(snapshot) {
1035
+ const continuity = snapshot.continuity;
1036
+ if (!isRecord(continuity))
1037
+ return undefined;
1038
+ const reasonCodes = Array.isArray(continuity.reasonCodes)
1039
+ ? continuity.reasonCodes.filter((entry) => typeof entry === 'string')
1040
+ : undefined;
1041
+ return {
1042
+ present: true,
1043
+ activeJobId: safeToken(continuity.activeJobId ?? continuity.jobId) ?? null,
1044
+ activeGoalId: safeToken(continuity.activeGoalId ?? continuity.goalId) ?? null,
1045
+ activeLoopId: safeToken(continuity.activeLoopId ?? continuity.loopId) ?? null,
1046
+ ...(reasonCodes && reasonCodes.length > 0 ? { reasonCodes: safeReasonCodes(reasonCodes) } : {}),
1047
+ };
1048
+ }
1049
+ function deriveActiveRef(snapshot, session, yoloop) {
1050
+ const sessionStoryId = safeToken(session?.activeStoryId);
1051
+ const sessionEpicId = safeToken(session?.activeEpicId);
1052
+ const sessionStepId = safeToken(session?.activeStepId);
1053
+ const sessionStoryEpicId = sessionStoryId && snapshot.stories[sessionStoryId]
1054
+ ? storyEpicId(snapshot.stories[sessionStoryId], sessionStoryId)
1055
+ : null;
1056
+ if ((sessionStoryId || sessionEpicId || sessionStepId) && isActiveEpicLifecycle(snapshot, sessionEpicId ?? sessionStoryEpicId)) {
1057
+ return {
1058
+ epicId: sessionEpicId ?? null,
1059
+ storyId: sessionStoryId ?? null,
1060
+ stepId: sessionStepId ?? null,
1061
+ };
1062
+ }
1063
+ const yoloopStoryId = safeToken(yoloop?.currentStoryId);
1064
+ const yoloopEpicId = safeToken(yoloop?.currentEpicId ?? yoloop?.lockEpicId);
1065
+ if ((yoloopStoryId || yoloopEpicId) && isActiveEpicLifecycle(snapshot, yoloopEpicId)) {
1066
+ return {
1067
+ epicId: yoloopEpicId ?? null,
1068
+ storyId: yoloopStoryId ?? null,
1069
+ stepId: null,
1070
+ };
1071
+ }
1072
+ const latestNonTerminal = Object.entries(snapshot.stories)
1073
+ .map(([id, story]) => ({ id, story, timestamp: sortableStoryTimestamp(story) }))
1074
+ .filter(({ id, story }) => !isTerminalStoryStatus(story.status) && isActiveEpicLifecycle(snapshot, storyEpicId(story, id)))
1075
+ .sort((left, right) => right.timestamp - left.timestamp || left.id.localeCompare(right.id))[0];
1076
+ if (latestNonTerminal) {
1077
+ return {
1078
+ epicId: storyEpicId(latestNonTerminal.story, latestNonTerminal.id),
1079
+ storyId: latestNonTerminal.id,
1080
+ stepId: safeToken(latestNonTerminal.story.last_step ?? latestNonTerminal.story.lastStep) ?? null,
1081
+ };
1082
+ }
1083
+ return { epicId: null, storyId: null, stepId: null };
1084
+ }
1085
+ function buildStateSummary(sourceSnapshot, scope) {
1086
+ const storyStatus = countStatuses(sourceSnapshot.stories);
1087
+ const epicStatus = countStatuses(sourceSnapshot.epics);
1088
+ const epicLifecycle = countEpicLifecycles(sourceSnapshot.epics);
1089
+ const activeEpics = Object.values(sourceSnapshot.epics).filter((epic) => {
1090
+ const lifecycle = EPIC_LIFECYCLE_CLASSIFICATIONS.includes(epic.lifecycle_classification)
1091
+ ? epic.lifecycle_classification
1092
+ : 'active';
1093
+ return lifecycle === 'active' && !isTerminalStoryStatus(epic.status);
1094
+ }).length;
1095
+ const session = currentSessionRef(sourceSnapshot);
1096
+ const yoloop = yoloopSessionRef(sourceSnapshot);
1097
+ const continuity = continuitySessionRef(sourceSnapshot);
1098
+ const active = deriveActiveRef(sourceSnapshot, session, yoloop);
1099
+ const recent = recentStories(sourceSnapshot);
1100
+ const reasonCodes = safeReasonCodes(scope.reasonCodes, [
1101
+ 'state-summary-attached',
1102
+ 'state-summary-bounded',
1103
+ `projection-${scope.projectionMode ?? scope.kind}`,
1104
+ scope.stateProjectionPolicy ? `policy-${scope.stateProjectionPolicy}` : 'policy-unknown',
1105
+ recent.length >= RECENT_STORY_LIMIT ? 'recent-stories-capped' : 'recent-stories-bounded',
1106
+ active.storyId || active.epicId ? 'active-ref-derived' : 'active-ref-empty',
1107
+ yoloop ? 'yoloop-session-present' : 'yoloop-session-absent',
1108
+ continuity ? 'continuity-session-present' : 'continuity-session-absent',
1109
+ ]);
1110
+ return {
1111
+ schemaVersion: 1,
1112
+ totals: {
1113
+ stories: Object.keys(sourceSnapshot.stories).length,
1114
+ epics: Object.keys(sourceSnapshot.epics).length,
1115
+ storyStatus,
1116
+ epicStatus,
1117
+ epicLifecycle,
1118
+ activeEpics,
1119
+ blockedStories: storyStatus.blocked ?? 0,
1120
+ },
1121
+ active,
1122
+ blockedCount: storyStatus.blocked ?? 0,
1123
+ recentStories: recent,
1124
+ ...(session ? { currentSession: session } : {}),
1125
+ ...(yoloop ? { currentYoloopSession: yoloop } : {}),
1126
+ ...(continuity ? { currentContinuitySession: continuity } : {}),
1127
+ projection: {
1128
+ commandId: scope.commandId ?? null,
1129
+ stateProjectionPolicy: scope.stateProjectionPolicy ?? null,
1130
+ projectionMode: scope.projectionMode,
1131
+ scopeKind: scope.kind,
1132
+ includedStoryCount: scope.includedStoryCount,
1133
+ includedEpicCount: scope.includedEpicCount ?? Object.keys(sourceSnapshot.epics).length,
1134
+ omittedStoryCount: scope.omittedStoryCount,
1135
+ omittedEpicCount: scope.omittedEpicCount,
1136
+ reason: scope.reason,
1137
+ },
1138
+ reasonCodes,
1139
+ publicSafe: true,
1140
+ };
1141
+ }
1142
+ function withStateSummary(projected, sourceSnapshot, scope) {
1143
+ return {
1144
+ ...projected,
1145
+ stateSummary: buildStateSummary(sourceSnapshot, scope),
1146
+ };
1147
+ }
1148
+ function buildCreateEpicProjection(trigger, snapshot, commandPolicy) {
1149
+ const projectedEpics = {};
1150
+ for (const epicId of Object.keys(snapshot.epics)) {
1151
+ projectedEpics[epicId] = { id: epicId };
1152
+ }
1153
+ const scope = {
1154
+ kind: 'projected',
1155
+ commandId: commandPolicy.commandId,
1156
+ stateProjectionPolicy: commandPolicy.stateProjectionPolicy,
1157
+ projectionMode: 'summary-only',
1158
+ trigger,
1159
+ targetEpicId: null,
1160
+ targetStoryId: null,
1161
+ includedStoryCount: 0,
1162
+ includedEpicCount: Object.keys(projectedEpics).length,
1163
+ omittedStoryCount: Object.keys(snapshot.stories).length,
1164
+ omittedEpicCount: 0,
1165
+ reason: 'epic-summary',
1166
+ reasonCodes: ['epic-summary', 'stories-omitted', 'epic-stubs-only'],
1167
+ };
1168
+ return withStateSummary({
1169
+ ...snapshot,
1170
+ stories: {},
1171
+ epics: projectedEpics,
1172
+ scope,
1173
+ }, snapshot, scope);
1174
+ }
1175
+ function buildSummaryOnlyProjection(trigger, snapshot, commandPolicy, reasonCodes = ['summary-only', 'stories-omitted'], projectionMode = 'summary-only') {
1176
+ const projectedEpics = buildEpicStubs(snapshot);
1177
+ const scope = {
1178
+ kind: 'projected',
1179
+ commandId: commandPolicy.commandId,
1180
+ stateProjectionPolicy: commandPolicy.stateProjectionPolicy,
1181
+ projectionMode,
1182
+ trigger,
1183
+ targetEpicId: null,
1184
+ targetStoryId: null,
1185
+ includedStoryCount: 0,
1186
+ includedEpicCount: Object.keys(projectedEpics).length,
1187
+ omittedStoryCount: Object.keys(snapshot.stories).length,
1188
+ omittedEpicCount: Math.max(0, Object.keys(snapshot.epics).length - Object.keys(projectedEpics).length),
1189
+ reason: 'summary-only',
1190
+ reasonCodes: safeReasonCodes(reasonCodes),
1191
+ };
1192
+ return withStateSummary({
1193
+ ...snapshot,
1194
+ stories: {},
1195
+ epics: projectedEpics,
1196
+ scope,
1197
+ }, snapshot, scope);
1198
+ }
1199
+ function buildStoryProjection(trigger, snapshot, commandPolicy, targetStoryId, projectionMode, reasonCodes) {
1200
+ const targetStory = snapshot.stories[targetStoryId];
1201
+ if (!targetStory) {
1202
+ throw new StructuralDagError('STRUCTURAL_TARGET_NOT_FOUND', {
1203
+ stories: Object.keys(snapshot.stories).length,
1204
+ epics: Object.keys(snapshot.epics).length,
1205
+ targetKind: 'story',
1206
+ });
1207
+ }
1208
+ const targetEpicId = storyEpicId(targetStory, targetStoryId);
1209
+ if (!targetEpicId) {
1210
+ throw new StructuralDagError('STRUCTURAL_TARGET_NOT_FOUND', {
1211
+ stories: Object.keys(snapshot.stories).length,
1212
+ epics: Object.keys(snapshot.epics).length,
1213
+ targetKind: 'epic',
1214
+ });
1215
+ }
1216
+ const targetEpic = snapshot.epics[targetEpicId];
1217
+ if (!targetEpic) {
1218
+ throw new StructuralDagError('STRUCTURAL_TARGET_NOT_FOUND', {
1219
+ stories: Object.keys(snapshot.stories).length,
1220
+ epics: Object.keys(snapshot.epics).length,
1221
+ targetKind: 'epic',
1222
+ });
1223
+ }
1224
+ // Direct *yolo needs the same epic topology seen by *yoloop so a standalone
1225
+ // invocation can bootstrap the canonical P207 graph epoch. Other story
1226
+ // commands remain dependency-scoped. Stories outside the owning epic are
1227
+ // retained only as compact structural dependencies by the yoloop projector.
1228
+ const yoloEpicGraph = projectionMode === 'yolo-story';
1229
+ const projectedStories = yoloEpicGraph
1230
+ ? buildProjectedYoloopStories(targetEpicId, targetEpic, snapshot)
1231
+ : buildProjectedStories(targetStoryId, snapshot);
1232
+ const projectedEpics = yoloEpicGraph
1233
+ ? buildProjectedYoloopEpics(targetEpicId, projectedStories, snapshot)
1234
+ : buildProjectedEpics(projectedStories, snapshot);
1235
+ if (!projectedStories[targetStoryId] || !projectedEpics[targetEpicId]) {
1236
+ throw new StructuralDagError('STRUCTURAL_TARGET_NOT_FOUND', {
1237
+ stories: Object.keys(projectedStories).length,
1238
+ epics: Object.keys(projectedEpics).length,
1239
+ targetKind: 'story',
1240
+ });
1241
+ }
1242
+ const scope = {
1243
+ kind: 'projected',
1244
+ commandId: commandPolicy.commandId,
1245
+ stateProjectionPolicy: commandPolicy.stateProjectionPolicy,
1246
+ projectionMode,
1247
+ trigger,
1248
+ targetEpicId,
1249
+ targetStoryId,
1250
+ includedStoryCount: Object.keys(projectedStories).length,
1251
+ includedEpicCount: Object.keys(projectedEpics).length,
1252
+ omittedStoryCount: Math.max(0, Object.keys(snapshot.stories).length - Object.keys(projectedStories).length),
1253
+ omittedEpicCount: Math.max(0, Object.keys(snapshot.epics).length - Object.keys(projectedEpics).length),
1254
+ reason: 'targeted-invocation',
1255
+ reasonCodes: safeReasonCodes(reasonCodes, yoloEpicGraph ? ['epic-graph-authority-complete'] : []),
1256
+ };
1257
+ return withStateSummary({
1258
+ ...snapshot,
1259
+ stories: projectedStories,
1260
+ epics: projectedEpics,
1261
+ scope,
1262
+ }, snapshot, scope);
1263
+ }
1264
+ function buildTargetedEpicProjection(trigger, snapshot, commandPolicy, targetEpicId, projectionMode, reasonCodes) {
1265
+ const targetEpic = snapshot.epics[targetEpicId];
1266
+ if (!targetEpic) {
1267
+ throw new StructuralDagError('STRUCTURAL_TARGET_NOT_FOUND', {
1268
+ stories: Object.keys(snapshot.stories).length,
1269
+ epics: Object.keys(snapshot.epics).length,
1270
+ targetKind: 'epic',
1271
+ });
1272
+ }
1273
+ const projectedStories = buildProjectedTargetEpicStories(targetEpic, snapshot);
1274
+ const projectedEpics = buildProjectedEpics(projectedStories, snapshot, [targetEpicId]);
1275
+ if (!projectedEpics[targetEpicId]) {
1276
+ throw new StructuralDagError('STRUCTURAL_TARGET_NOT_FOUND', {
1277
+ stories: Object.keys(projectedStories).length,
1278
+ epics: Object.keys(projectedEpics).length,
1279
+ targetKind: 'epic',
1280
+ });
1281
+ }
1282
+ const scope = {
1283
+ kind: 'projected',
1284
+ commandId: commandPolicy.commandId,
1285
+ stateProjectionPolicy: commandPolicy.stateProjectionPolicy,
1286
+ projectionMode,
1287
+ trigger,
1288
+ targetEpicId,
1289
+ targetStoryId: null,
1290
+ includedStoryCount: Object.keys(projectedStories).length,
1291
+ includedEpicCount: Object.keys(projectedEpics).length,
1292
+ omittedStoryCount: Math.max(0, Object.keys(snapshot.stories).length - Object.keys(projectedStories).length),
1293
+ omittedEpicCount: Math.max(0, Object.keys(snapshot.epics).length - Object.keys(projectedEpics).length),
1294
+ reason: 'targeted-invocation',
1295
+ reasonCodes: safeReasonCodes(reasonCodes),
1296
+ };
1297
+ return withStateSummary({
1298
+ ...snapshot,
1299
+ stories: projectedStories,
1300
+ epics: projectedEpics,
1301
+ scope,
1302
+ }, snapshot, scope);
1303
+ }
1304
+ function buildYoloopProjection(trigger, snapshot, commandPolicy) {
1305
+ const explicitCandidate = explicitYoloopEpicCandidate(trigger);
1306
+ const explicitTargetEpicId = extractTargetEpicId(trigger, snapshot);
1307
+ if (explicitCandidate && !explicitTargetEpicId) {
1308
+ throw new StructuralDagError('STRUCTURAL_TARGET_NOT_FOUND', {
1309
+ stories: Object.keys(snapshot.stories).length,
1310
+ epics: Object.keys(snapshot.epics).length,
1311
+ targetKind: 'epic',
1312
+ });
1313
+ }
1314
+ const targetEpicId = extractYoloopTargetEpicId(trigger, snapshot);
1315
+ const shape = classifyInvocationShapeV2({
1316
+ commandId: commandPolicy.commandId,
1317
+ explicitYoloopEpicId: explicitTargetEpicId,
1318
+ sessionYoloopEpicId: explicitTargetEpicId ? null : targetEpicId,
1319
+ });
1320
+ if (shape === 'yoloop-discovery')
1321
+ return buildYoloopDiscoveryProjection(trigger, snapshot, commandPolicy);
1322
+ if (!targetEpicId || (shape !== 'yoloop-target' && shape !== 'yoloop-session')) {
1323
+ throw new StructuralDagError('STRUCTURAL_TARGET_NOT_FOUND', {
1324
+ stories: Object.keys(snapshot.stories).length,
1325
+ epics: Object.keys(snapshot.epics).length,
1326
+ targetKind: 'epic',
1327
+ });
1328
+ }
1329
+ const targetEpic = snapshot.epics[targetEpicId];
1330
+ if (!targetEpic) {
1331
+ throw new StructuralDagError('STRUCTURAL_TARGET_NOT_FOUND', {
1332
+ stories: Object.keys(snapshot.stories).length,
1333
+ epics: Object.keys(snapshot.epics).length,
1334
+ targetKind: 'epic',
1335
+ });
1336
+ }
1337
+ const projectedStories = buildProjectedYoloopStories(targetEpicId, targetEpic, snapshot);
1338
+ const projectedEpics = buildProjectedYoloopEpics(targetEpicId, projectedStories, snapshot);
1339
+ if (!projectedEpics[targetEpicId]) {
1340
+ throw new StructuralDagError('STRUCTURAL_TARGET_NOT_FOUND', {
1341
+ stories: Object.keys(projectedStories).length,
1342
+ epics: Object.keys(projectedEpics).length,
1343
+ targetKind: 'epic',
1344
+ });
1345
+ }
1346
+ const projectionMode = shape;
1347
+ const scope = {
1348
+ kind: 'projected',
1349
+ commandId: commandPolicy.commandId,
1350
+ stateProjectionPolicy: commandPolicy.stateProjectionPolicy,
1351
+ projectionMode,
1352
+ trigger,
1353
+ targetEpicId,
1354
+ targetStoryId: null,
1355
+ targetEpicCoverage: buildTargetEpicCoverage(targetEpicId, targetEpic, projectedStories),
1356
+ includedStoryCount: Object.keys(projectedStories).length,
1357
+ includedEpicCount: Object.keys(projectedEpics).length,
1358
+ omittedStoryCount: Math.max(0, Object.keys(snapshot.stories).length - Object.keys(projectedStories).length),
1359
+ omittedEpicCount: Math.max(0, Object.keys(snapshot.epics).length - Object.keys(projectedEpics).length),
1360
+ reason: 'targeted-invocation',
1361
+ reasonCodes: ['structural-required', projectionMode, 'yoloop-targeted'],
1362
+ };
1363
+ return withStateSummary({
1364
+ ...snapshot,
1365
+ stories: projectedStories,
1366
+ epics: projectedEpics,
1367
+ scope,
1368
+ }, snapshot, scope);
1369
+ }
1370
+ function buildPayloadGuardrailEpics(snapshot, retainedStoryIds) {
1371
+ const projectedEpics = {};
1372
+ for (const [epicId, epic] of Object.entries(snapshot.epics)) {
1373
+ const retainedEpicStories = Array.isArray(epic.stories)
1374
+ ? epic.stories.filter((storyId) => typeof storyId === 'string' && retainedStoryIds.has(storyId))
1375
+ : [];
1376
+ projectedEpics[epicId] = {
1377
+ id: safeToken(epic.id) ?? epicId,
1378
+ ...(safeToken(epic.status, 40) ? { status: safeToken(epic.status, 40) } : {}),
1379
+ ...(typeof epic.total_stories === 'number' && Number.isFinite(epic.total_stories)
1380
+ ? { total_stories: epic.total_stories }
1381
+ : {}),
1382
+ ...(typeof epic.completed_stories === 'number' && Number.isFinite(epic.completed_stories)
1383
+ ? { completed_stories: epic.completed_stories }
1384
+ : {}),
1385
+ ...(retainedEpicStories.length > 0 ? { stories: retainedEpicStories } : {}),
1386
+ ...(retainedEpicStories.length > 0 && Array.isArray(epic.depends_on)
1387
+ ? { depends_on: epic.depends_on.filter((value) => typeof value === 'string' && value.length > 0) }
1388
+ : {}),
1389
+ ...(retainedEpicStories.length > 0 && (epic.branch_mode === 'epic' || epic.branch_mode === 'story')
1390
+ ? { branch_mode: epic.branch_mode }
1391
+ : {}),
1392
+ ...(retainedEpicStories.length > 0 && typeof epic.execution_branch === 'string'
1393
+ ? { execution_branch: epic.execution_branch }
1394
+ : {}),
1395
+ ...(retainedEpicStories.length > 0 && typeof epic.origin_branch === 'string'
1396
+ ? { origin_branch: epic.origin_branch }
1397
+ : {}),
1398
+ ...(retainedEpicStories.length > 0 && (epic.branch_lease === null || typeof epic.branch_lease === 'object')
1399
+ ? { branch_lease: epic.branch_lease }
1400
+ : {}),
1401
+ ...(retainedEpicStories.length > 0 && (epic.origin_binding === null || typeof epic.origin_binding === 'object')
1402
+ ? { origin_binding: epic.origin_binding }
1403
+ : {}),
1404
+ ...(retainedEpicStories.length > 0 && (epic.aggregate_qa_receipt === null || typeof epic.aggregate_qa_receipt === 'object')
1405
+ ? { aggregate_qa_receipt: epic.aggregate_qa_receipt }
1406
+ : {}),
1407
+ };
1408
+ }
1409
+ return projectedEpics;
1410
+ }
1411
+ function sourceStoryTotal(snapshot) {
1412
+ return snapshot.stateSummary?.totals.stories
1413
+ ?? ((snapshot.scope?.includedStoryCount ?? Object.keys(snapshot.stories).length) + (snapshot.scope?.omittedStoryCount ?? 0));
1414
+ }
1415
+ function sourceEpicTotal(snapshot) {
1416
+ return snapshot.stateSummary?.totals.epics
1417
+ ?? ((snapshot.scope?.includedEpicCount ?? Object.keys(snapshot.epics).length) + (snapshot.scope?.omittedEpicCount ?? 0));
1418
+ }
1419
+ function updateStateSummaryForPayloadGuardrail(snapshot, scope) {
1420
+ if (!snapshot.stateSummary)
1421
+ return undefined;
1422
+ return {
1423
+ ...snapshot.stateSummary,
1424
+ projection: {
1425
+ ...snapshot.stateSummary.projection,
1426
+ scopeKind: 'projected',
1427
+ projectionMode: scope.projectionMode,
1428
+ includedStoryCount: scope.includedStoryCount,
1429
+ includedEpicCount: scope.includedEpicCount ?? snapshot.stateSummary.projection.includedEpicCount,
1430
+ omittedStoryCount: scope.omittedStoryCount,
1431
+ omittedEpicCount: scope.omittedEpicCount,
1432
+ reason: 'body-size',
1433
+ },
1434
+ reasonCodes: safeReasonCodes(snapshot.stateSummary.reasonCodes, ['payload-size-guardrail', 'state-summary-preserved', 'nonessential-state-degraded']),
1435
+ };
1436
+ }
1437
+ /**
1438
+ * P198.04 -- deterministic post-assembly state degradation.
1439
+ *
1440
+ * This helper is intentionally pure and request-only. It removes historical story
1441
+ * bodies that are not structural for the already-projected request, converts the
1442
+ * epic map to public stubs, keeps `stateSummary`, and preserves structural-required
1443
+ * story/yolo/yoloop target state instead of silently corrupting it.
1444
+ */
1445
+ export function degradeStateSnapshotForPayloadLimit(snapshot) {
1446
+ const scope = snapshot.scope;
1447
+ const retainedStoryIds = new Set();
1448
+ const preserveProjectedStructuralStories = scope?.projectionMode === 'structural-required'
1449
+ || scope?.projectionMode === 'yolo-story'
1450
+ || scope?.projectionMode === 'yoloop-target'
1451
+ || scope?.projectionMode === 'yoloop-session'
1452
+ || scope?.projectionMode === 'yoloop-discovery';
1453
+ if (preserveProjectedStructuralStories) {
1454
+ for (const storyId of Object.keys(snapshot.stories)) {
1455
+ retainedStoryIds.add(storyId);
1456
+ }
1457
+ }
1458
+ else if (scope?.targetStoryId) {
1459
+ addStoryAndDependencies(scope.targetStoryId, snapshot, retainedStoryIds);
1460
+ }
1461
+ const projectedStories = {};
1462
+ for (const storyId of retainedStoryIds) {
1463
+ const story = snapshot.stories[storyId];
1464
+ if (story)
1465
+ projectedStories[storyId] = story;
1466
+ }
1467
+ const projectedEpics = buildPayloadGuardrailEpics(snapshot, retainedStoryIds);
1468
+ const includedStoryCount = Object.keys(projectedStories).length;
1469
+ const includedEpicCount = Object.keys(projectedEpics).length;
1470
+ const omittedStoryCount = Math.max(0, sourceStoryTotal(snapshot) - includedStoryCount);
1471
+ const omittedEpicCount = Math.max(0, sourceEpicTotal(snapshot) - includedEpicCount);
1472
+ const projectionMode = preserveProjectedStructuralStories
1473
+ ? scope?.projectionMode ?? 'structural-required'
1474
+ : scope?.projectionMode === 'yolo-story'
1475
+ ? 'yolo-story'
1476
+ : 'summary-only';
1477
+ const nextScope = {
1478
+ kind: 'projected',
1479
+ commandId: scope?.commandId ?? null,
1480
+ stateProjectionPolicy: scope?.stateProjectionPolicy ?? null,
1481
+ projectionMode,
1482
+ targetEpicId: scope?.targetEpicId ?? null,
1483
+ targetStoryId: scope?.targetStoryId ?? null,
1484
+ ...(scope?.targetEpicCoverage ? { targetEpicCoverage: scope.targetEpicCoverage } : {}),
1485
+ includedStoryCount,
1486
+ includedEpicCount,
1487
+ omittedStoryCount,
1488
+ omittedEpicCount,
1489
+ reason: 'body-size',
1490
+ reasonCodes: safeReasonCodes(scope?.reasonCodes, [
1491
+ 'payload-size-guardrail',
1492
+ retainedStoryIds.size > 0 ? 'structural-targets-preserved' : 'stories-omitted',
1493
+ 'epics-stubbed',
1494
+ 'state-summary-preserved',
1495
+ 'redundant-trigger-omitted',
1496
+ ]),
1497
+ };
1498
+ const stateSummary = updateStateSummaryForPayloadGuardrail(snapshot, nextScope);
1499
+ return {
1500
+ ...snapshot,
1501
+ stories: projectedStories,
1502
+ epics: projectedEpics,
1503
+ scope: nextScope,
1504
+ ...(stateSummary ? { stateSummary } : {}),
1505
+ };
1506
+ }
1507
+ /**
1508
+ * Return a request-scoped state snapshot for invoke commands.
1509
+ *
1510
+ * The function is intentionally pure. Structural uncertainty fails closed;
1511
+ * callers must surface the public code instead of sending a full-state fallback.
1512
+ */
1513
+ export function projectStateSnapshotForInvoke(args, snapshot) {
1514
+ const trigger = args.trim();
1515
+ const commandPolicy = resolveCommandProjectionPolicy(trigger);
1516
+ try {
1517
+ if (!commandPolicy) {
1518
+ if (firstTokenIsStoryReference(trigger)) {
1519
+ const storyReferencePolicy = policy('story-reference', 'story-targeted');
1520
+ const targetStoryId = extractStoryId(trigger);
1521
+ if (targetStoryId) {
1522
+ return buildStoryProjection(trigger, snapshot, storyReferencePolicy, targetStoryId, 'targeted-story', ['story-reference-targeted']);
1523
+ }
1524
+ }
1525
+ return buildSummaryOnlyProjection(trigger, snapshot, policy('unknown', 'adaptive-targeted'), ['unknown-command-summary-only']);
1526
+ }
1527
+ if (commandPolicy.stateProjectionPolicy === 'epic-summary') {
1528
+ return buildCreateEpicProjection(trigger, snapshot, commandPolicy);
1529
+ }
1530
+ if (commandPolicy.stateProjectionPolicy === 'yoloop-targeted') {
1531
+ return buildYoloopProjection(trigger, snapshot, commandPolicy);
1532
+ }
1533
+ const targetStoryId = extractStoryId(trigger);
1534
+ if (commandPolicy.stateProjectionPolicy === 'story-targeted') {
1535
+ if (targetStoryId) {
1536
+ const invocationShape = classifyInvocationShapeV2({ commandId: commandPolicy.commandId, targetStoryId });
1537
+ const yoloStory = invocationShape === 'yolo-story';
1538
+ return buildStoryProjection(trigger, snapshot, commandPolicy, targetStoryId, yoloStory ? 'yolo-story' : commandPolicy.structuralRequired ? 'structural-required' : 'targeted-story', [yoloStory ? 'yolo-story' : commandPolicy.structuralRequired ? 'structural-required' : 'targeted-story']);
1539
+ }
1540
+ if (commandPolicy.commandId === 'yolo' || commandPolicy.commandId === 'yolo-inline') {
1541
+ const invocationShape = classifyInvocationShapeV2({ commandId: commandPolicy.commandId });
1542
+ return buildSummaryOnlyProjection(trigger, snapshot, commandPolicy, ['yolo-inline', 'stories-omitted', 'historical-content-omitted'], invocationShape ?? 'yolo-inline');
1543
+ }
1544
+ // Commit without a story is an exact root working-tree workflow. It
1545
+ // needs no story graph, but a malformed or unknown target must not gain
1546
+ // this summary-only escape from structural target validation.
1547
+ if (commandPolicy.commandId === 'commit' && /^\*?(?:commit|commit-push)$/i.test(trigger)) {
1548
+ return buildSummaryOnlyProjection(trigger, snapshot, commandPolicy, ['working-tree-commit', 'stories-omitted', 'historical-content-omitted']);
1549
+ }
1550
+ return commandPolicy.structuralRequired
1551
+ ? (() => {
1552
+ throw new StructuralDagError('STRUCTURAL_TARGET_NOT_FOUND', {
1553
+ stories: Object.keys(snapshot.stories).length,
1554
+ epics: Object.keys(snapshot.epics).length,
1555
+ targetKind: 'story',
1556
+ });
1557
+ })()
1558
+ : buildSummaryOnlyProjection(trigger, snapshot, commandPolicy, ['story-target-missing-summary-only']);
1559
+ }
1560
+ if (commandPolicy.stateProjectionPolicy === 'adaptive-targeted') {
1561
+ if (targetStoryId && snapshot.stories[targetStoryId]) {
1562
+ return buildStoryProjection(trigger, snapshot, commandPolicy, targetStoryId, 'targeted-story', ['adaptive-story-targeted']);
1563
+ }
1564
+ const targetEpicId = extractTargetEpicId(trigger, snapshot);
1565
+ if (targetEpicId) {
1566
+ return buildTargetedEpicProjection(trigger, snapshot, commandPolicy, targetEpicId, 'targeted-epic', ['adaptive-epic-targeted']);
1567
+ }
1568
+ return buildSummaryOnlyProjection(trigger, snapshot, commandPolicy, ['adaptive-summary-only', 'target-unresolved-summary-only']);
1569
+ }
1570
+ if (commandPolicy.stateProjectionPolicy === 'epic-targeted') {
1571
+ // The root *arch-plan pipeline delegates its current stage with the
1572
+ // internal marker `epic-arch`. It has no user-selected epic yet; keep
1573
+ // this exact marker only when the bounded root checkpoint names the
1574
+ // same stage. The server still verifies the accounting receipt.
1575
+ if (commandPolicy.commandId.startsWith('arch-')
1576
+ && /(?:^|\s)epic-arch\s*$/i.test(trigger)
1577
+ && snapshot.archPlan?.execution?.currentStageCommand === commandPolicy.commandId) {
1578
+ return buildSummaryOnlyProjection(trigger, snapshot, commandPolicy, ['architecture-root-delegated']);
1579
+ }
1580
+ const targetEpicId = extractTargetEpicId(trigger, snapshot);
1581
+ if (targetEpicId) {
1582
+ return buildTargetedEpicProjection(trigger, snapshot, commandPolicy, targetEpicId, commandPolicy.structuralRequired ? 'structural-required' : 'targeted-epic', [commandPolicy.structuralRequired ? 'structural-required' : 'targeted-epic']);
1583
+ }
1584
+ return commandPolicy.structuralRequired
1585
+ ? (() => {
1586
+ throw new StructuralDagError('STRUCTURAL_TARGET_NOT_FOUND', {
1587
+ stories: Object.keys(snapshot.stories).length,
1588
+ epics: Object.keys(snapshot.epics).length,
1589
+ targetKind: 'epic',
1590
+ });
1591
+ })()
1592
+ : buildSummaryOnlyProjection(trigger, snapshot, commandPolicy, ['epic-target-missing-summary-only']);
1593
+ }
1594
+ if (commandPolicy.stateProjectionPolicy === 'continuity-scoped') {
1595
+ return buildSummaryOnlyProjection(trigger, snapshot, commandPolicy, ['continuity-scoped-summary-only']);
1596
+ }
1597
+ return buildSummaryOnlyProjection(trigger, snapshot, commandPolicy, ['policy-full-summary-only']);
1598
+ }
1599
+ catch (error) {
1600
+ if (error instanceof StructuralDagError)
1601
+ throw error;
1602
+ if (commandPolicy?.structuralRequired) {
1603
+ throw new StructuralDagError('STRUCTURAL_DEPENDENCY_MISSING', {
1604
+ stories: Object.keys(snapshot.stories).length,
1605
+ epics: Object.keys(snapshot.epics).length,
1606
+ projectionErrors: 1,
1607
+ });
1608
+ }
1609
+ return buildSummaryOnlyProjection(trigger, snapshot, commandPolicy ?? policy('unknown', 'adaptive-targeted'), ['projection-error-summary-only']);
1610
+ }
1611
+ }
1612
+ const V2_INVOCATION_SHAPES = new Set([
1613
+ 'yolo-story',
1614
+ 'yolo-inline',
1615
+ 'yoloop-target',
1616
+ 'yoloop-session',
1617
+ 'yoloop-discovery',
1618
+ ]);
1619
+ function projectedEdgeCount(snapshot) {
1620
+ let edges = 0;
1621
+ for (const collection of [snapshot.stories, snapshot.epics]) {
1622
+ for (const entry of Object.values(collection)) {
1623
+ if (Array.isArray(entry.depends_on)) {
1624
+ edges += entry.depends_on.filter((value) => typeof value === 'string').length;
1625
+ }
1626
+ }
1627
+ }
1628
+ return edges;
1629
+ }
1630
+ /**
1631
+ * Versioned result contract for the five structural YOLO/yoloop shapes.
1632
+ * Other command families retain their existing projection policy and return
1633
+ * null because they are outside StateProjectionV2's closed shape union.
1634
+ */
1635
+ export function projectStateSnapshotResultV2ForInvoke(args, snapshot) {
1636
+ const commandPolicy = resolveCommandProjectionPolicy(args.trim());
1637
+ if (!commandPolicy
1638
+ || !['yolo', 'yolo-inline', 'yoloop'].includes(commandPolicy.commandId)) {
1639
+ return null;
1640
+ }
1641
+ try {
1642
+ const projected = projectStateSnapshotForInvoke(args, snapshot);
1643
+ const shape = projected.scope?.projectionMode;
1644
+ if (!shape || !V2_INVOCATION_SHAPES.has(shape)) {
1645
+ throw new StructuralDagError('STRUCTURAL_DEPENDENCY_MISSING', {
1646
+ stories: Object.keys(projected.stories).length,
1647
+ epics: Object.keys(projected.epics).length,
1648
+ projectionShapeErrors: 1,
1649
+ });
1650
+ }
1651
+ return Object.freeze({
1652
+ ok: true,
1653
+ version: 2,
1654
+ shape,
1655
+ snapshot: projected,
1656
+ included: {
1657
+ epics: projected.scope?.includedEpicCount ?? Object.keys(projected.epics).length,
1658
+ stories: projected.scope?.includedStoryCount ?? Object.keys(projected.stories).length,
1659
+ edges: projectedEdgeCount(projected),
1660
+ },
1661
+ omitted: {
1662
+ epics: projected.scope?.omittedEpicCount ?? 0,
1663
+ stories: projected.scope?.omittedStoryCount ?? 0,
1664
+ },
1665
+ cycleCount: 0,
1666
+ });
1667
+ }
1668
+ catch (error) {
1669
+ if (!(error instanceof StructuralDagError))
1670
+ throw error;
1671
+ return Object.freeze({
1672
+ ok: false,
1673
+ code: error.code,
1674
+ publicDetails: error.publicDetails,
1675
+ });
1676
+ }
1677
+ }