@ornexus/neocortex 4.60.73 → 4.60.75

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 (269) hide show
  1. package/dist/release-source.json +1 -1
  2. package/dist/sbom.cdx.json +1216 -1210
  3. package/install.ps1 +1 -1
  4. package/install.sh +1 -1
  5. package/package.json +2 -2
  6. package/packages/client/dist/adapters/adapter-registry.js +1 -108
  7. package/packages/client/dist/adapters/antigravity-adapter.js +2 -77
  8. package/packages/client/dist/adapters/claude-code-adapter.js +3 -79
  9. package/packages/client/dist/adapters/codex-adapter.js +2 -80
  10. package/packages/client/dist/adapters/cursor-adapter.js +4 -115
  11. package/packages/client/dist/adapters/gemini-adapter.js +2 -71
  12. package/packages/client/dist/adapters/grok-adapter.js +2 -42
  13. package/packages/client/dist/adapters/index.js +1 -22
  14. package/packages/client/dist/adapters/platform-detector.js +1 -212
  15. package/packages/client/dist/adapters/target-adapter.js +0 -12
  16. package/packages/client/dist/adapters/vscode-adapter.js +2 -72
  17. package/packages/client/dist/agent/refresh-stubs.js +2 -417
  18. package/packages/client/dist/agent/update-agent-yaml.js +1 -102
  19. package/packages/client/dist/agent/update-description.js +1 -251
  20. package/packages/client/dist/cache/crypto-utils.js +1 -78
  21. package/packages/client/dist/cache/encrypted-cache.d.ts +27 -0
  22. package/packages/client/dist/cache/encrypted-cache.js +1 -108
  23. package/packages/client/dist/cache/in-memory-asset-cache.js +1 -73
  24. package/packages/client/dist/cache/index.js +1 -13
  25. package/packages/client/dist/cache/protected-pi-boundary.js +1 -44
  26. package/packages/client/dist/checkpoint/checkpoint-client-reader.js +2 -127
  27. package/packages/client/dist/checkpoint/index.js +1 -11
  28. package/packages/client/dist/checkpoint/shared-checkpoint-types.js +1 -32
  29. package/packages/client/dist/cli.js +5 -358
  30. package/packages/client/dist/commands/activate.js +8 -394
  31. package/packages/client/dist/commands/architecture-answers.js +7 -274
  32. package/packages/client/dist/commands/architecture-memory-terminal.js +4 -253
  33. package/packages/client/dist/commands/architecture-non-ui-continuation.js +1 -100
  34. package/packages/client/dist/commands/architecture-root-binding.js +1 -51
  35. package/packages/client/dist/commands/cache-status.js +2 -112
  36. package/packages/client/dist/commands/config.js +1 -88
  37. package/packages/client/dist/commands/doctor.js +2 -635
  38. package/packages/client/dist/commands/invoke.d.ts +38 -1
  39. package/packages/client/dist/commands/invoke.js +143 -7200
  40. package/packages/client/dist/commands/legacy-epic-terminal.js +1 -71
  41. package/packages/client/dist/commands/legacy-story-branch.js +1 -96
  42. package/packages/client/dist/commands/legacy-story-pr.js +1 -276
  43. package/packages/client/dist/commands/mutation-qa-checkpoint.js +5 -285
  44. package/packages/client/dist/commands/mutation-qa-gate.js +1 -54
  45. package/packages/client/dist/commands/mutation-qa-git.js +1 -41
  46. package/packages/client/dist/commands/mutation-qa-policy.js +1 -102
  47. package/packages/client/dist/commands/mutation-qa-run.js +3 -219
  48. package/packages/client/dist/commands/mutation-qa-verdict.js +1 -149
  49. package/packages/client/dist/commands/mutation-qa.js +1 -220
  50. package/packages/client/dist/commands/native-agent.js +2 -136
  51. package/packages/client/dist/commands/planning-diagnosis.js +1 -43
  52. package/packages/client/dist/commands/planning-generation.js +1 -53
  53. package/packages/client/dist/commands/planning-memory.js +1 -40
  54. package/packages/client/dist/commands/planning-research.js +1 -42
  55. package/packages/client/dist/commands/private-session.js +1 -75
  56. package/packages/client/dist/commands/property-qa.js +1 -139
  57. package/packages/client/dist/commands/qa-control.js +1 -16
  58. package/packages/client/dist/commands/qa-scan-browser-launch.js +1 -55
  59. package/packages/client/dist/commands/qa-scan-browser-route.js +1 -28
  60. package/packages/client/dist/commands/qa-scan-capture.js +5 -663
  61. package/packages/client/dist/commands/qa-scan-discovery.js +3 -376
  62. package/packages/client/dist/commands/qa-scan-review.js +5 -826
  63. package/packages/client/dist/commands/qa-synthetic-backend-capture.js +1 -266
  64. package/packages/client/dist/commands/qa-synthetic-backend-review.js +1 -297
  65. package/packages/client/dist/commands/qa-synthetic-backend.js +2 -340
  66. package/packages/client/dist/commands/qa-synthetic-broker-port.js +1 -85
  67. package/packages/client/dist/commands/qa-synthetic-browser.js +1 -39
  68. package/packages/client/dist/commands/refactor-characterization.js +21 -671
  69. package/packages/client/dist/commands/refactor-commit.js +13 -399
  70. package/packages/client/dist/commands/refactor-control.js +3 -142
  71. package/packages/client/dist/commands/refactor-cpp-assertions.js +3 -93
  72. package/packages/client/dist/commands/refactor-review.js +5 -283
  73. package/packages/client/dist/commands/refactor-root.js +7 -588
  74. package/packages/client/dist/commands/refresh-memory.js +3 -156
  75. package/packages/client/dist/commands/shared-architecture-non-ui.js +1 -24
  76. package/packages/client/dist/commands/story-checkpoint.js +1 -171
  77. package/packages/client/dist/config/host-auth-broker.d.ts +31 -0
  78. package/packages/client/dist/config/host-auth-broker.js +1 -0
  79. package/packages/client/dist/config/host-auth-reference.d.ts +32 -0
  80. package/packages/client/dist/config/host-auth-reference.js +1 -0
  81. package/packages/client/dist/config/profile-directory.js +1 -13
  82. package/packages/client/dist/config/resolver-selection.js +1 -278
  83. package/packages/client/dist/config/secure-config.js +12 -281
  84. package/packages/client/dist/config.js +2 -223
  85. package/packages/client/dist/constants.js +1 -25
  86. package/packages/client/dist/context/context-collector.js +2 -222
  87. package/packages/client/dist/context/context-sanitizer.js +1 -145
  88. package/packages/client/dist/continuity/autonomous-governance.js +1 -285
  89. package/packages/client/dist/continuity/continuity-client-state-store.js +1 -1587
  90. package/packages/client/dist/continuity/invoke-hooks.js +1 -129
  91. package/packages/client/dist/continuity/migrations/001-initial-schema.js +2 -12
  92. package/packages/client/dist/continuity/migrations/002-processing-output-summary-indexes.js +2 -12
  93. package/packages/client/dist/continuity/migrations/003-headless-execution-attempts.js +2 -12
  94. package/packages/client/dist/continuity/migrations/004-outbox-delivery-state.js +2 -12
  95. package/packages/client/dist/continuity/migrations/005-bounded-headless-queue.js +2 -12
  96. package/packages/client/dist/continuity/migrations/006-native-agent-dispatches.js +2 -10
  97. package/packages/client/dist/continuity/native-agent-store.js +1 -69
  98. package/packages/client/dist/continuity/native-agent-types.d.ts +11 -0
  99. package/packages/client/dist/continuity/native-agent-types.js +1 -90
  100. package/packages/client/dist/continuity/outbox.js +1 -117
  101. package/packages/client/dist/continuity/runner-bootstrap-policy.js +1 -172
  102. package/packages/client/dist/continuity/sqlite-store.js +81 -2612
  103. package/packages/client/dist/effects/invoke-effect-gateways.js +1 -62
  104. package/packages/client/dist/errors/error-messages.d.ts +3 -0
  105. package/packages/client/dist/errors/error-messages.js +2 -228
  106. package/packages/client/dist/errors/frontmatter-diagnostics.js +1 -125
  107. package/packages/client/dist/evidence/collector.js +1 -347
  108. package/packages/client/dist/evidence/index.js +1 -1
  109. package/packages/client/dist/evidence/types.js +0 -2
  110. package/packages/client/dist/fs/atomic-state-replace.js +1 -152
  111. package/packages/client/dist/generated/command-registry.generated.js +1 -4076
  112. package/packages/client/dist/generated/public-projections.generated.js +1 -149
  113. package/packages/client/dist/git/direct-yolo-c01-retry.js +4 -138
  114. package/packages/client/dist/git/direct-yolo-checkpoint.d.ts +11 -1
  115. package/packages/client/dist/git/direct-yolo-checkpoint.js +4 -1234
  116. package/packages/client/dist/git/epic-operational-state.js +2 -672
  117. package/packages/client/dist/git/git-lifecycle-step-ids.js +1 -14
  118. package/packages/client/dist/git/git-lifecycle-store.d.ts +23 -0
  119. package/packages/client/dist/git/git-lifecycle-store.js +10 -1981
  120. package/packages/client/dist/git/legacy-story-branch-checkpoint.js +9 -259
  121. package/packages/client/dist/git/legacy-story-branch-setup.js +4 -348
  122. package/packages/client/dist/git/legacy-story-pr.js +70 -3538
  123. package/packages/client/dist/git/secure-filesystem-boundary.js +5 -182
  124. package/packages/client/dist/graph-retrieval/pre-command-hook.js +1 -284
  125. package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.js +1 -237
  126. package/packages/client/dist/i18n/first-run.js +2 -60
  127. package/packages/client/dist/index.d.ts +2 -0
  128. package/packages/client/dist/index.js +1 -47
  129. package/packages/client/dist/invocation/invoke-input.js +1 -24
  130. package/packages/client/dist/license/host-auth-recovery.d.ts +158 -0
  131. package/packages/client/dist/license/host-auth-recovery.js +1 -0
  132. package/packages/client/dist/license/index.js +1 -5
  133. package/packages/client/dist/license/license-client.d.ts +10 -1
  134. package/packages/client/dist/license/license-client.js +1 -304
  135. package/packages/client/dist/machine/fingerprint.js +2 -163
  136. package/packages/client/dist/machine/index.js +1 -5
  137. package/packages/client/dist/memory/project-memory-path-scope.js +1 -62
  138. package/packages/client/dist/memory/project-memory-writer.js +40 -1007
  139. package/packages/client/dist/memory/shared-project-memory-types.js +2 -253
  140. package/packages/client/dist/migrations/epic-lifecycle-backfill.js +3 -1060
  141. package/packages/client/dist/migrations/project-identity-capability.js +1 -50
  142. package/packages/client/dist/migrations/project-identity.js +7 -493
  143. package/packages/client/dist/migrations/state-json.js +4 -393
  144. package/packages/client/dist/policy/architecture-policy.js +2 -184
  145. package/packages/client/dist/policy/index.js +1 -7
  146. package/packages/client/dist/policy/shared-policy-types.js +0 -38
  147. package/packages/client/dist/policy/subagent-approval-policy.js +1 -55
  148. package/packages/client/dist/private-execution/clean-baseline.js +2 -279
  149. package/packages/client/dist/private-execution/codex-executor.js +4 -574
  150. package/packages/client/dist/private-execution/codex-host-runtime.js +1 -137
  151. package/packages/client/dist/private-execution/codex-lifecycle-guard.js +1 -97
  152. package/packages/client/dist/private-execution/codex-scoped-permissions.js +1 -128
  153. package/packages/client/dist/private-execution/delivery.js +13 -410
  154. package/packages/client/dist/private-execution/diagnosis-root-review.js +2 -294
  155. package/packages/client/dist/private-execution/frozen-handoff.js +6 -19
  156. package/packages/client/dist/private-execution/implementation-validation.js +2 -106
  157. package/packages/client/dist/private-execution/isolated-admission.js +23 -1432
  158. package/packages/client/dist/private-execution/isolated-session.js +5 -725
  159. package/packages/client/dist/private-execution/isolated-workspace.js +1 -122
  160. package/packages/client/dist/private-execution/pact-consumer-runtime.js +3 -409
  161. package/packages/client/dist/private-execution/pact-test-source.js +1 -258
  162. package/packages/client/dist/private-execution/pact-toolchain.js +3 -290
  163. package/packages/client/dist/private-execution/pact-write-set.js +1 -172
  164. package/packages/client/dist/private-execution/planning-diagnosis-checkpoint.js +5 -406
  165. package/packages/client/dist/private-execution/planning-generation-checkpoint.js +5 -462
  166. package/packages/client/dist/private-execution/planning-memory-checkpoint.js +3 -139
  167. package/packages/client/dist/private-execution/planning-research-checkpoint.js +4 -325
  168. package/packages/client/dist/private-execution/private-report-store.js +1 -42
  169. package/packages/client/dist/private-execution/property-test-candidate.js +1 -103
  170. package/packages/client/dist/private-execution/property-test-choices.js +3 -147
  171. package/packages/client/dist/private-execution/property-test-plan.js +7 -271
  172. package/packages/client/dist/private-execution/property-test-review.js +4 -258
  173. package/packages/client/dist/private-execution/property-test-runtime.js +9 -372
  174. package/packages/client/dist/private-execution/property-test-source.js +1 -139
  175. package/packages/client/dist/private-execution/root-checkpoint.js +1 -80
  176. package/packages/client/dist/private-execution/root-memory-git-evidence.js +3 -135
  177. package/packages/client/dist/private-execution/root-memory-recovery.js +1 -93
  178. package/packages/client/dist/private-execution/root-memory-request.js +1 -29
  179. package/packages/client/dist/private-execution/root-memory-scope.js +1 -178
  180. package/packages/client/dist/private-execution/root-memory-writer.js +1 -102
  181. package/packages/client/dist/private-execution/session-lease.js +1 -63
  182. package/packages/client/dist/private-execution/shared-private-admission-types.js +1 -50
  183. package/packages/client/dist/private-execution/shared-project-validation.js +1 -66
  184. package/packages/client/dist/private-execution/shared-root-memory-types.js +1 -61
  185. package/packages/client/dist/private-execution/ux-source-validation.js +1 -372
  186. package/packages/client/dist/private-execution/ux-write-set.js +2 -191
  187. package/packages/client/dist/registry/registry-reconciliation.js +1 -234
  188. package/packages/client/dist/resilience/circuit-breaker.js +1 -170
  189. package/packages/client/dist/resilience/degradation-manager.js +1 -164
  190. package/packages/client/dist/resilience/freshness-indicator.js +1 -100
  191. package/packages/client/dist/resilience/index.js +1 -8
  192. package/packages/client/dist/resilience/recovery-detector.js +1 -74
  193. package/packages/client/dist/resolvers/asset-resolver.js +0 -13
  194. package/packages/client/dist/resolvers/local-resolver.js +8 -255
  195. package/packages/client/dist/resolvers/remote-resolver.js +1 -233
  196. package/packages/client/dist/runner/binary.js +1 -404
  197. package/packages/client/dist/runner/cli.js +17 -1571
  198. package/packages/client/dist/runner/epic-background-dispatcher.d.ts +61 -0
  199. package/packages/client/dist/runner/epic-background-dispatcher.js +1 -0
  200. package/packages/client/dist/runner/headless/adapters.js +1 -49
  201. package/packages/client/dist/runner/headless/background-root.d.ts +65 -0
  202. package/packages/client/dist/runner/headless/background-root.js +1 -0
  203. package/packages/client/dist/runner/headless/claude-code-adapter.js +1 -79
  204. package/packages/client/dist/runner/headless/continuous-story-workspace.js +11 -1628
  205. package/packages/client/dist/runner/headless/epic-git-reconciliation-inventory.js +1 -69
  206. package/packages/client/dist/runner/headless/epic-merge-candidate-qa.d.ts +1 -1
  207. package/packages/client/dist/runner/headless/epic-merge-candidate-qa.js +2 -110
  208. package/packages/client/dist/runner/headless/epic-terminal-git-cli-adapter.d.ts +2 -0
  209. package/packages/client/dist/runner/headless/epic-terminal-git-cli-adapter.js +10 -1236
  210. package/packages/client/dist/runner/headless/epic-terminal-git-runner.d.ts +27 -2
  211. package/packages/client/dist/runner/headless/epic-terminal-git-runner.js +2 -318
  212. package/packages/client/dist/runner/headless/fake-adapter.js +1 -62
  213. package/packages/client/dist/runner/headless/managed-environment-cleanup.d.ts +95 -0
  214. package/packages/client/dist/runner/headless/managed-environment-cleanup.js +1 -0
  215. package/packages/client/dist/runner/headless/managed-profile.js +1 -132
  216. package/packages/client/dist/runner/headless/opencode-adapter.js +2 -145
  217. package/packages/client/dist/runner/headless/prepared-story-bundle.js +1 -43
  218. package/packages/client/dist/runner/headless/resolver.js +1 -231
  219. package/packages/client/dist/runner/headless/run-yolo.js +1 -885
  220. package/packages/client/dist/runner/headless/run-yoloop.d.ts +1 -0
  221. package/packages/client/dist/runner/headless/run-yoloop.js +2 -2574
  222. package/packages/client/dist/runner/headless/types.js +2 -574
  223. package/packages/client/dist/runner/local-console.js +13 -396
  224. package/packages/client/dist/runner/portal-sync-worker.js +1 -1487
  225. package/packages/client/dist/runner/project-identity.js +1 -106
  226. package/packages/client/dist/runner/scheduler.js +7 -995
  227. package/packages/client/dist/runner-cli.js +2 -18
  228. package/packages/client/dist/state/invocation-shape.js +1 -13
  229. package/packages/client/dist/state/project-state-snapshot.d.ts +7 -0
  230. package/packages/client/dist/state/project-state-snapshot.js +1 -1731
  231. package/packages/client/dist/state/state-json-repair.js +3 -785
  232. package/packages/client/dist/state/structural-dag-projection.js +1 -118
  233. package/packages/client/dist/telemetry/index.js +1 -5
  234. package/packages/client/dist/telemetry/offline-queue.js +1 -131
  235. package/packages/client/dist/tier/index.js +1 -5
  236. package/packages/client/dist/tier/tier-aware-client.js +1 -405
  237. package/packages/client/dist/types/index.js +1 -38
  238. package/packages/client/dist/version.js +1 -27
  239. package/packages/client/dist/yolo/change-evidence-collector.d.ts +21 -1
  240. package/packages/client/dist/yolo/change-evidence-collector.js +1 -126
  241. package/packages/client/dist/yolo/invoke-envelope-capability.js +1 -62
  242. package/packages/client/dist/yolo/spec-envelope-collector.js +5 -184
  243. package/packages/client/dist/yoloop/discovery-hook.js +2 -300
  244. package/packages/client/dist/yoloop/index.js +1 -8
  245. package/packages/client/dist/yoloop/invoke-hooks.js +12 -669
  246. package/packages/client/dist/yoloop/shared-discover-epics.js +1 -1007
  247. package/packages/client/dist/yoloop/shared-yoloop-types.js +1 -33
  248. package/packages/client/dist/yoloop/target-normalization.js +1 -180
  249. package/packages/client/dist/yoloop/yoloop-client-state-store.js +1 -1920
  250. package/packages/shared/dist/invocation/explicit-intent-recovery.d.ts +83 -0
  251. package/packages/shared/dist/invocation/explicit-intent-recovery.js +187 -0
  252. package/packages/shared/dist/invocation/index.d.ts +7 -0
  253. package/packages/shared/dist/invocation/index.js +22 -0
  254. package/packages/shared/dist/yolo/change-evidence.js +1 -1
  255. package/packages/shared/dist/yoloop/epic-terminal-git.js +144 -2
  256. package/targets-stubs/antigravity/gemini.md +1 -1
  257. package/targets-stubs/antigravity/skill/SKILL.md +1 -1
  258. package/targets-stubs/claude-code/neocortex-root.agent.yaml +1 -1
  259. package/targets-stubs/claude-code/neocortex-root.md +2 -2
  260. package/targets-stubs/claude-code/neocortex.agent.yaml +1 -1
  261. package/targets-stubs/claude-code/neocortex.md +2 -2
  262. package/targets-stubs/codex/AGENTS.md +24 -21
  263. package/targets-stubs/codex/README.md +6 -1
  264. package/targets-stubs/codex/neocortex.toml +7 -2
  265. package/targets-stubs/cursor/agent.md +2 -2
  266. package/targets-stubs/gemini-cli/agent.md +2 -2
  267. package/targets-stubs/opencode/neocortex-root.md +16 -1
  268. package/targets-stubs/opencode/neocortex.md +6 -0
  269. package/targets-stubs/vscode/neocortex.agent.md +2 -2
@@ -1,126 +1 @@
1
- import { execFileSync } from 'node:child_process';
2
- import { realpathSync } from 'node:fs';
3
- import { createYoloChangeEvidence } from '../../../shared/dist/yolo/change-evidence.js';
4
- import { readGitLifecycleRuntimeSync } from '../git/git-lifecycle-store.js';
5
- /** Reacquire only an expired setup lease for this exact story through P207's CAS boundary. */
6
- export async function reconcileYoloChangeEvidenceLease(options) {
7
- let lease;
8
- try {
9
- lease = readGitLifecycleRuntimeSync(options.projectRoot, { required: true })
10
- .epics[options.epicId]?.branch_lease;
11
- }
12
- catch (error) {
13
- // C01 can legitimately precede first-use sidecar materialization. Only
14
- // that exact absence falls through to the existing remote/base evidence.
15
- if (error instanceof Error && error.message === 'git-lifecycle-runtime-missing')
16
- return;
17
- throw new Error('yolo-change-evidence-unavailable');
18
- }
19
- if (lease === null || lease === undefined)
20
- return;
21
- if (typeof lease !== 'object' || Array.isArray(lease)
22
- || lease.ownerStoryId !== options.storyId
23
- || typeof lease.expiresAt !== 'string') {
24
- throw new Error('yolo-change-evidence-unavailable');
25
- }
26
- const expiry = Date.parse(lease.expiresAt);
27
- if (!Number.isFinite(expiry))
28
- throw new Error('yolo-change-evidence-unavailable');
29
- if (expiry > Date.now())
30
- return;
31
- if (typeof lease.sessionId !== 'string'
32
- || !/^setup-[a-f0-9]{64}$/.test(lease.sessionId)
33
- || lease.idempotencyKey !== lease.sessionId) {
34
- throw new Error('yolo-change-evidence-unavailable');
35
- }
36
- const { prepareDirectYoloSetup } = await import('../git/direct-yolo-checkpoint.js');
37
- const result = await prepareDirectYoloSetup(options);
38
- if (!result.ok || result.value.storyId !== options.storyId
39
- || result.value.epicId !== options.epicId
40
- || Date.parse(result.value.leaseExpiresAt) <= Date.now()) {
41
- throw new Error('yolo-change-evidence-unavailable');
42
- }
43
- }
44
- function git(root, args) {
45
- try {
46
- return execFileSync('git', ['-C', root, ...args], {
47
- encoding: 'utf8', timeout: 3_000, maxBuffer: 1024 * 1024, stdio: ['ignore', 'pipe', 'ignore'],
48
- });
49
- }
50
- catch {
51
- throw new Error('yolo-change-evidence-unavailable');
52
- }
53
- }
54
- export function collectYoloChangeEvidence(options) {
55
- if (!/^[A-Za-z0-9][A-Za-z0-9_./-]{0,119}$/.test(options.defaultBranch)
56
- || options.defaultBranch.includes('..'))
57
- throw new Error('yolo-change-evidence-unavailable');
58
- const repositoryRoot = git(options.projectRoot, ['rev-parse', '--show-toplevel']).trim();
59
- if (realpathSync(repositoryRoot) !== realpathSync(options.projectRoot))
60
- throw new Error('yolo-change-evidence-unavailable');
61
- const headSha = git(options.projectRoot, ['rev-parse', 'HEAD']).trim();
62
- if (headSha !== options.expectedHeadSha)
63
- throw new Error('yolo-change-evidence-stale');
64
- let baseSha;
65
- let activeStoryLease = false;
66
- let executionBranch = null;
67
- if (options.storyId && options.epicId) {
68
- try {
69
- const runtime = readGitLifecycleRuntimeSync(options.projectRoot);
70
- const epic = runtime.epics[options.epicId];
71
- const lease = epic?.branch_lease;
72
- const currentBranch = git(options.projectRoot, ['symbolic-ref', '--quiet', '--short', 'HEAD']).trim();
73
- if (epic?.branch_mode === 'epic' && epic.execution_branch === currentBranch) {
74
- executionBranch = currentBranch;
75
- }
76
- if (lease && typeof lease === 'object' && !Array.isArray(lease)) {
77
- const item = lease;
78
- if (item.ownerStoryId !== options.storyId
79
- || typeof item.expiresAt !== 'string' || Date.parse(item.expiresAt) <= Date.now()
80
- || executionBranch === null) {
81
- throw new Error('yolo-change-evidence-unavailable');
82
- }
83
- activeStoryLease = true;
84
- }
85
- }
86
- catch {
87
- throw new Error('yolo-change-evidence-unavailable');
88
- }
89
- }
90
- if (activeStoryLease) {
91
- // Before the root C08 commit, the setup lease owns the current checkout.
92
- // Earlier epic commits are not part of this story's implementation diff.
93
- // A manually pre-committed change cannot satisfy the staged C08 checkpoint.
94
- baseSha = headSha;
95
- }
96
- else {
97
- // Before C01 has acquired a story lease, compare this epic checkout with
98
- // its published tip. Historical epic commits are not new story changes,
99
- // while local unpushed commits must remain visible to the evidence gate.
100
- const remoteLine = executionBranch === null ? '' : git(options.projectRoot, [
101
- 'ls-remote', '--heads', 'origin', `refs/heads/${executionBranch}`,
102
- ]).trim();
103
- if (remoteLine) {
104
- const match = /^([a-f0-9]{40})\trefs\/heads\/([^\n]+)$/.exec(remoteLine);
105
- if (!match || match[2] !== executionBranch
106
- || git(options.projectRoot, ['merge-base', 'HEAD', match[1]]).trim() !== match[1]) {
107
- throw new Error('yolo-change-evidence-unavailable');
108
- }
109
- baseSha = match[1];
110
- }
111
- else {
112
- try {
113
- baseSha = git(options.projectRoot, ['merge-base', 'HEAD', options.defaultBranch]).trim();
114
- }
115
- catch {
116
- baseSha = git(options.projectRoot, ['merge-base', 'HEAD', `refs/remotes/origin/${options.defaultBranch}`]).trim();
117
- }
118
- }
119
- }
120
- const tracked = git(options.projectRoot, ['diff', '--name-only', '-z', baseSha, '--']).split('\0').filter(Boolean);
121
- const untracked = git(options.projectRoot, ['ls-files', '--others', '--exclude-standard', '-z']).split('\0').filter(Boolean);
122
- const evidence = createYoloChangeEvidence({ baseSha, headSha, changedPaths: [...tracked, ...untracked] });
123
- if (git(options.projectRoot, ['rev-parse', 'HEAD']).trim() !== headSha)
124
- throw new Error('yolo-change-evidence-stale');
125
- return evidence;
126
- }
1
+ import{execFileSync as E,spawnSync as h}from"node:child_process";import{realpathSync as y}from"node:fs";import{createYoloChangeEvidence as A}from"../../../shared/dist/yolo/change-evidence.js";import{readGitLifecycleRuntimeSync as g}from"../git/git-lifecycle-store.js";class p extends Error{diagnostic;constructor(t){super("yolo-change-evidence-unavailable"),this.name="YoloChangeEvidenceUnavailableError",this.diagnostic=Object.freeze({...t})}}function z(e){return e instanceof p?e.diagnostic:void 0}const c=Object.freeze({repair:"not-attempted",recollectionCount:0});function I(e){return e==="lease-owner-mismatch"||e==="lease-invalid-or-nonsetup"||e==="direct-yolo-writer-active"?"resolve-lease-conflict":e==="base-ref-missing"||e==="base-observation-unavailable"||e==="base-object-missing"||e==="base-not-ancestor"||e==="diff-read-unavailable"?"restore-verified-base-evidence":e==="execution-branch-mismatch"||e.startsWith("direct-yolo-")?"inspect-repository-binding":"none"}function r(e,t,i=c,o=i.repair){throw new p({reason:e,baseSource:t,repair:o,recollectionCount:i.recollectionCount,fallbackAction:I(e),publicSafe:!0})}async function $(e){let t;try{t=g(e.projectRoot,{required:!0})}catch(b){if(b instanceof Error&&b.message==="git-lifecycle-runtime-missing")return c;r("runtime-state-unavailable","none")}const i=t.epics[e.epicId]?.branch_lease;if(i==null)return c;(typeof i!="object"||Array.isArray(i))&&r("lease-invalid-or-nonsetup","active-story-lease",c,"not-eligible"),i.ownerStoryId!==e.storyId&&r("lease-owner-mismatch","active-story-lease",c,"not-eligible"),typeof i.expiresAt!="string"&&r("lease-invalid-or-nonsetup","active-story-lease",c,"not-eligible");const o=Date.parse(i.expiresAt);if(Number.isFinite(o)||r("lease-invalid-or-nonsetup","active-story-lease",c,"not-eligible"),o>Date.now())return c;(typeof i.sessionId!="string"||!/^setup-[a-f0-9]{64}$/.test(i.sessionId)||i.idempotencyKey!==i.sessionId)&&r("lease-invalid-or-nonsetup","active-story-lease",c,"not-eligible");const{prepareDirectYoloSetup:n}=await import("../git/direct-yolo-checkpoint.js"),a=await n({...e,expiredSetupRecovery:{schemaVersion:1,expectedRuntimeRevision:t.revision,expectedLease:Object.freeze({...i})}});return a.ok||r(a.reasonCode,"active-story-lease",c,"not-eligible"),(a.value.storyId!==e.storyId||a.value.epicId!==e.epicId||Date.parse(a.value.leaseExpiresAt)<=Date.now())&&r("lease-invalid-or-nonsetup","active-story-lease",c,"not-eligible"),Object.freeze({repair:"applied",recollectionCount:1})}function f(e,t,i,o,n){try{return E("git",["-C",e,...t],{encoding:"utf8",timeout:3e3,maxBuffer:1024*1024,stdio:["ignore","pipe","ignore"]})}catch{r(i,o,n)}}function x(e,t,i){const o=h("git",["-C",e,"show-ref","--verify","--quiet",t],{timeout:3e3,stdio:"ignore"});if(o.status===0)return!0;if(o.status===1)return!1;r("base-observation-unavailable","none",i)}function C(e,t,i,o){const n=h("git",["-C",e,"cat-file","-e",`${t}^{commit}`],{timeout:3e3,stdio:"ignore"});if(n.status===0)return!0;if(n.status===1||n.status===128)return!1;r("base-observation-unavailable",i,o)}function H(e){const t=e.reconciliation??c;(!/^[A-Za-z0-9][A-Za-z0-9_./-]{0,119}$/.test(e.defaultBranch)||e.defaultBranch.includes(".."))&&r("invalid-default-branch","none",t);let i;try{i=f(e.projectRoot,["rev-parse","--show-toplevel"],"repository-root-mismatch","none",t).trim(),y(i)!==y(e.projectRoot)&&r("repository-root-mismatch","none",t)}catch(l){if(l instanceof p)throw l;r("repository-root-mismatch","none",t)}const o=f(e.projectRoot,["rev-parse","HEAD"],"base-observation-unavailable","none",t).trim();if(o!==e.expectedHeadSha)throw new Error("yolo-change-evidence-stale");let n,a="none",b=!1,m=null;if(e.storyId&&e.epicId){let l;try{l=g(e.projectRoot)}catch{r("runtime-state-unavailable","none",t)}const s=l.epics[e.epicId],u=s?.branch_lease,d=f(e.projectRoot,["symbolic-ref","--quiet","--short","HEAD"],"execution-branch-mismatch","none",t).trim();if(s?.branch_mode==="epic"&&s.execution_branch===d&&(m=d),u&&typeof u=="object"&&!Array.isArray(u)){const v=u;v.ownerStoryId!==e.storyId&&r("lease-owner-mismatch","active-story-lease",t,"not-eligible"),(typeof v.expiresAt!="string"||!Number.isFinite(Date.parse(v.expiresAt))||Date.parse(v.expiresAt)<=Date.now())&&r("lease-invalid-or-nonsetup","active-story-lease",t,"not-eligible"),m===null&&r("execution-branch-mismatch","active-story-lease",t,"not-eligible"),b=!0}}if(b)n=o,a="active-story-lease";else{const l=m===null?"":f(e.projectRoot,["ls-remote","--heads","origin",`refs/heads/${m}`],"base-observation-unavailable","published-execution-branch",t).trim();if(l){a="published-execution-branch";const s=/^([a-f0-9]{40})\trefs\/heads\/([^\n]+)$/.exec(l);(!s||s[2]!==m)&&r("base-observation-unavailable",a,t),C(e.projectRoot,s[1],a,t)||r("base-object-missing",a,t),h("git",["-C",e.projectRoot,"merge-base","--is-ancestor",s[1],"HEAD"],{timeout:3e3,stdio:"ignore"}).status!==0&&r("base-not-ancestor",a,t),n=s[1]}else{const s=`refs/heads/${e.defaultBranch}`,u=`refs/remotes/origin/${e.defaultBranch}`,d=x(e.projectRoot,s,t)?s:x(e.projectRoot,u,t)?u:null;d||r("base-ref-missing","none",t),a=d===s?"local-default-branch":"remote-default-branch",n=f(e.projectRoot,["merge-base","HEAD",d],"base-not-ancestor",a,t).trim()}}const R=f(e.projectRoot,["diff","--name-only","-z",n,"--"],"diff-read-unavailable",a,t).split("\0").filter(Boolean),j=f(e.projectRoot,["ls-files","--others","--exclude-standard","-z"],"diff-read-unavailable",a,t).split("\0").filter(Boolean),w=A({baseSha:n,headSha:o,changedPaths:[...R,...j]});if(f(e.projectRoot,["rev-parse","HEAD"],"base-observation-unavailable",a,t).trim()!==o)throw new Error("yolo-change-evidence-stale");return w}export{p as YoloChangeEvidenceUnavailableError,H as collectYoloChangeEvidence,$ as reconcileYoloChangeEvidenceLease,z as yoloChangeEvidenceDiagnostic};
@@ -1,62 +1 @@
1
- import { YOLO_INVOKE_ENVELOPE_CAPABILITY } from '../../../shared/dist/yolo/spec-envelope.js';
2
- const MAX_CAPABILITY_RESPONSE_BYTES = 16 * 1024;
3
- const PUBLIC_VERSION = /^[0-9]{1,6}\.[0-9]{1,6}\.[0-9]{1,6}(?:-[A-Za-z0-9.-]{1,40})?$/;
4
- function result(supported, reason, serverVersion) {
5
- return Object.freeze({
6
- supported,
7
- capability: YOLO_INVOKE_ENVELOPE_CAPABILITY,
8
- reason,
9
- ...(serverVersion && PUBLIC_VERSION.test(serverVersion) ? { serverVersion } : {}),
10
- publicSafe: true,
11
- });
12
- }
13
- /**
14
- * Non-mutating, fail-closed compatibility probe for targeted YOLO requests.
15
- * Older strict servers must be rejected before local release-gate execution.
16
- */
17
- export async function probeYoloInvokeEnvelopeCapability(serverUrl, fetcher = globalThis.fetch) {
18
- if (!fetcher)
19
- return result(false, 'fetch-unavailable');
20
- const controller = new AbortController();
21
- const timeout = setTimeout(() => controller.abort(), 5_000);
22
- timeout.unref?.();
23
- try {
24
- const response = await fetcher(`${serverUrl.replace(/\/+$/, '')}/api/v1/health`, {
25
- method: 'GET',
26
- headers: { accept: 'application/json' },
27
- signal: controller.signal,
28
- });
29
- if (!response.ok)
30
- return result(false, 'http-rejected');
31
- const raw = await response.text();
32
- if (Buffer.byteLength(raw, 'utf8') > MAX_CAPABILITY_RESPONSE_BYTES) {
33
- return result(false, 'response-too-large');
34
- }
35
- let parsed;
36
- try {
37
- parsed = JSON.parse(raw);
38
- }
39
- catch {
40
- return result(false, 'response-invalid');
41
- }
42
- if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
43
- return result(false, 'response-invalid');
44
- }
45
- const record = parsed;
46
- const capabilities = record.capabilities;
47
- const serverVersion = typeof record.version === 'string' ? record.version : undefined;
48
- if (!Array.isArray(capabilities)
49
- || capabilities.some((value) => typeof value !== 'string' || value.length > 80)) {
50
- return result(false, 'response-invalid', serverVersion);
51
- }
52
- return capabilities.includes(YOLO_INVOKE_ENVELOPE_CAPABILITY)
53
- ? result(true, 'supported', serverVersion)
54
- : result(false, 'capability-missing', serverVersion);
55
- }
56
- catch {
57
- return result(false, 'request-failed');
58
- }
59
- finally {
60
- clearTimeout(timeout);
61
- }
62
- }
1
+ import{YOLO_INVOKE_ENVELOPE_CAPABILITY as u}from"../../../shared/dist/yolo/spec-envelope.js";const y=16*1024,b=/^[0-9]{1,6}\.[0-9]{1,6}\.[0-9]{1,6}(?:-[A-Za-z0-9.-]{1,40})?$/;function e(n,a,t){return Object.freeze({supported:n,capability:u,reason:a,...t&&b.test(t)?{serverVersion:t}:{},publicSafe:!0})}async function h(n,a=globalThis.fetch){if(!a)return e(!1,"fetch-unavailable");const t=new AbortController,l=setTimeout(()=>t.abort(),5e3);l.unref?.();try{const c=await a(`${n.replace(/\/+$/,"")}/api/v1/health`,{method:"GET",headers:{accept:"application/json"},signal:t.signal});if(!c.ok)return e(!1,"http-rejected");const f=await c.text();if(Buffer.byteLength(f,"utf8")>y)return e(!1,"response-too-large");let r;try{r=JSON.parse(f)}catch{return e(!1,"response-invalid")}if(!r||typeof r!="object"||Array.isArray(r))return e(!1,"response-invalid");const i=r,s=i.capabilities,o=typeof i.version=="string"?i.version:void 0;return!Array.isArray(s)||s.some(p=>typeof p!="string"||p.length>80)?e(!1,"response-invalid",o):s.includes(u)?e(!0,"supported",o):e(!1,"capability-missing",o)}catch{return e(!1,"request-failed")}finally{clearTimeout(l)}}export{h as probeYoloInvokeEnvelopeCapability};
@@ -1,184 +1,5 @@
1
- import { execFileSync } from 'node:child_process';
2
- import { existsSync, readFileSync, realpathSync, statSync } from 'node:fs';
3
- import { join, sep } from 'node:path';
4
- import { createYoloSpecEnvelopeV1, YOLO_SPEC_MAX_ARTIFACTS, } from '../../../shared/dist/yolo/spec-envelope.js';
5
- import { inspectFrontmatterContext } from '../../../shared/dist/frontmatter-context-contract.js';
6
- const TEMPLATE_PATHS = [
7
- 'core/templates/specs/feature-spec-template.md',
8
- 'core/templates/specs/architecture-spec-template.md',
9
- 'core/templates/specs/contract-spec-template.md',
10
- 'core/templates/specs/story-spec-template.md',
11
- 'core/templates/specs/traceability-matrix-template.md',
12
- ];
13
- const REFERENCE_PATH = /(?:^|[\s([`'";])((?:docs\/(?:stories|epics|specs|architecture|examples)\/|core\/templates\/specs\/)[A-Za-z0-9_./-]+\.(?:md|mdx|feature))(?:$|[\s)\]`'",;])/gm;
14
- const STORY_ID = /^[A-Za-z][A-Za-z0-9_-]*(?:\.[A-Za-z0-9_-]+)+$/;
15
- // Resource-safety stop only. Ordinary envelope sizing belongs to the existing
16
- // invoke request guardrail, not to a smaller 64/128 KiB document policy.
17
- const YOLO_SPEC_LOCAL_SOURCE_SAFETY_LIMIT_BYTES = 16 * 1024 * 1024;
18
- /** Resolve only an explicit story target. Inline YOLO text intentionally has no match. */
19
- export function extractTargetedYoloStoryId(args) {
20
- const pathMatches = [...args.matchAll(/(?:^|\s)@?docs\/stories\/([A-Za-z][A-Za-z0-9_-]*(?:\.[A-Za-z0-9_-]+)+)\.story\.md(?=\s|$)/g)]
21
- .map((match) => match[1]);
22
- const tokenMatches = args.trim().split(/\s+/).slice(1)
23
- .map((token) => token.replace(/^@/, ''))
24
- .filter((token) => STORY_ID.test(token));
25
- const matches = [...new Set([...pathMatches, ...tokenMatches])];
26
- return matches.length === 1 ? matches[0] : null;
27
- }
28
- function artifactKind(path) {
29
- if (path.startsWith('core/templates/'))
30
- return 'template';
31
- if (path.startsWith('docs/epics/'))
32
- return 'epic';
33
- if (path.startsWith('docs/stories/') && path.endsWith('.story.md'))
34
- return 'story';
35
- if (path.endsWith('.rtm.md'))
36
- return 'traceability';
37
- if (path.toLowerCase().includes('adr'))
38
- return 'adr';
39
- if (path.toLowerCase().includes('contract'))
40
- return 'contract';
41
- if (path.toLowerCase().includes('nfr'))
42
- return 'nfr';
43
- if (path.endsWith('.feature'))
44
- return 'bdd';
45
- if (path.toLowerCase().includes('traceability'))
46
- return 'traceability';
47
- if (path.startsWith('docs/examples/'))
48
- return 'example';
49
- return 'spec';
50
- }
51
- function selectedReferencePaths(story) {
52
- return [...new Set([...story.matchAll(REFERENCE_PATH)].map((match) => match[1]).filter((path) => Boolean(path)))].sort();
53
- }
54
- function safeSource(root, path) {
55
- const rootReal = realpathSync(root);
56
- let fileReal;
57
- try {
58
- fileReal = realpathSync(join(rootReal, path));
59
- }
60
- catch {
61
- throw new Error('yolo-spec-envelope-required');
62
- }
63
- if (!fileReal.startsWith(`${rootReal}${sep}`))
64
- throw new Error('yolo-spec-envelope-path-out-of-scope');
65
- const sourceStat = statSync(fileReal);
66
- if (!sourceStat.isFile())
67
- throw new Error('yolo-spec-envelope-unsafe');
68
- if (sourceStat.size > YOLO_SPEC_LOCAL_SOURCE_SAFETY_LIMIT_BYTES)
69
- throw new Error('yolo-spec-envelope-too-large');
70
- return readFileSync(fileReal, 'utf8');
71
- }
72
- function publicMarkdown(source, kind) {
73
- const context = kind === 'story' ? 'story-target' : 'epic-target';
74
- const inspected = inspectFrontmatterContext(source, { context, explicitlySelected: true });
75
- if (inspected.status === 'malformed' || inspected.status === 'oversized')
76
- throw new Error('yolo-spec-envelope-unsafe');
77
- if (inspected.status === 'absent')
78
- return source;
79
- const match = source.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/);
80
- if (!match)
81
- throw new Error('yolo-spec-envelope-unsafe');
82
- const fields = Object.entries(inspected.metadata).map(([key, value]) => `${key}: ${JSON.stringify(value)}`);
83
- return `---\n${fields.join('\n')}\n---\n${source.slice(match[0].length)}`;
84
- }
85
- function readHeadSha(root) {
86
- try {
87
- return execFileSync('git', ['-C', root, 'rev-parse', 'HEAD'], {
88
- encoding: 'utf8', timeout: 2_000, stdio: ['ignore', 'pipe', 'ignore'],
89
- }).trim();
90
- }
91
- catch {
92
- throw new Error('yolo-spec-envelope-stale');
93
- }
94
- }
95
- export function collectYoloSpecEnvelope(options) {
96
- const targetPath = `docs/stories/${options.storyId}.story.md`;
97
- const epicPath = `docs/epics/epic-${options.epicId}.md`;
98
- const initialHead = options.headSha ?? readHeadSha(options.projectRoot);
99
- const story = publicMarkdown(safeSource(options.projectRoot, targetPath), 'story');
100
- const epic = publicMarkdown(safeSource(options.projectRoot, epicPath), 'epic');
101
- const artifacts = [
102
- { kind: 'story', path: targetPath, content: story },
103
- { kind: 'epic', path: epicPath, content: epic },
104
- ];
105
- const coreStoryReferences = new Set([
106
- `docs/stories/${options.storyId}.spec.md`,
107
- `docs/stories/${options.storyId}.tasks.md`,
108
- `docs/stories/${options.storyId}.rtm.md`,
109
- ]);
110
- // Older stories may not link to their own SDD files. Bind physically present
111
- // siblings to the same HEAD/content checks as explicitly referenced files.
112
- const selectedReferences = [...new Set([
113
- ...selectedReferencePaths(story),
114
- ...[...coreStoryReferences].filter((path) => existsSync(join(options.projectRoot, path))),
115
- ])].sort();
116
- const prioritizedReferences = [
117
- ...selectedReferences.filter((path) => coreStoryReferences.has(path)),
118
- ...selectedReferences.filter((path) => !coreStoryReferences.has(path)),
119
- ];
120
- let omittedReferences = 0;
121
- for (const path of prioritizedReferences) {
122
- if (path === targetPath || path === epicPath || !existsSync(join(options.projectRoot, path)))
123
- continue;
124
- // A foreign story/epic is a target conflict, never optional context. The
125
- // byte budget must not turn a prior target-mismatch denial into admission.
126
- if ((path.startsWith('docs/stories/') && path.endsWith('.story.md'))
127
- || path.startsWith('docs/epics/'))
128
- throw new Error('yolo-spec-envelope-target-mismatch');
129
- const content = safeSource(options.projectRoot, path);
130
- if (artifacts.length >= YOLO_SPEC_MAX_ARTIFACTS) {
131
- if (coreStoryReferences.has(path))
132
- throw new Error('yolo-spec-envelope-too-large');
133
- omittedReferences += 1;
134
- continue;
135
- }
136
- artifacts.push({ kind: artifactKind(path), path, content });
137
- }
138
- // Templates and non-core references are supporting context. Preserve the
139
- // story's own SDD artifacts and signal omissions without exposing paths.
140
- if (omittedReferences)
141
- options.onOmittedReferences?.(omittedReferences);
142
- for (const path of TEMPLATE_PATHS) {
143
- if (path === targetPath || path === epicPath || selectedReferences.includes(path)
144
- || !existsSync(join(options.projectRoot, path)))
145
- continue;
146
- const content = safeSource(options.projectRoot, path);
147
- if (artifacts.length >= YOLO_SPEC_MAX_ARTIFACTS)
148
- continue;
149
- artifacts.push({ kind: artifactKind(path), path, content });
150
- }
151
- const envelope = createYoloSpecEnvelopeV1({
152
- storyId: options.storyId,
153
- epicId: options.epicId,
154
- targetPath,
155
- inputSha256: options.inputSha256,
156
- headSha: initialHead,
157
- collectedAt: options.collectedAt ?? new Date().toISOString(),
158
- artifacts,
159
- });
160
- const finalHead = options.headSha ?? readHeadSha(options.projectRoot);
161
- if (initialHead !== finalHead
162
- || publicMarkdown(safeSource(options.projectRoot, targetPath), 'story') !== story
163
- || publicMarkdown(safeSource(options.projectRoot, epicPath), 'epic') !== epic
164
- || artifacts.some((artifact) => artifact.kind !== 'story' && artifact.kind !== 'epic'
165
- && safeSource(options.projectRoot, artifact.path) !== artifact.content)) {
166
- throw new Error('yolo-spec-envelope-stale');
167
- }
168
- return envelope;
169
- }
170
- /**
171
- * Reissue a precollected physical snapshot with a fresh bounded transport time.
172
- * The caller still performs the final disk/HEAD collection and digest comparison.
173
- */
174
- export function refreshPrecollectedYoloSpecEnvelope(envelope, collectedAt = new Date().toISOString()) {
175
- return createYoloSpecEnvelopeV1({
176
- storyId: envelope.storyId,
177
- epicId: envelope.epicId,
178
- targetPath: envelope.targetPath,
179
- inputSha256: envelope.inputSha256,
180
- headSha: envelope.sourceRevision.headSha,
181
- collectedAt,
182
- artifacts: envelope.artifacts.map(({ kind, path, content }) => ({ kind, path, content })),
183
- });
184
- }
1
+ import{execFileSync as _}from"node:child_process";import{existsSync as u,readFileSync as j,realpathSync as y,statSync as x}from"node:fs";import{join as l,sep as $}from"node:path";import{createYoloSpecEnvelopeV1 as S,YOLO_SPEC_MAX_ARTIFACTS as w}from"../../../shared/dist/yolo/spec-envelope.js";import{inspectFrontmatterContext as v}from"../../../shared/dist/frontmatter-context-contract.js";const C=["core/templates/specs/feature-spec-template.md","core/templates/specs/architecture-spec-template.md","core/templates/specs/contract-spec-template.md","core/templates/specs/story-spec-template.md","core/templates/specs/traceability-matrix-template.md"],O=/(?:^|[\s([`'";])((?:docs\/(?:stories|epics|specs|architecture|examples)\/|core\/templates\/specs\/)[A-Za-z0-9_./-]+\.(?:md|mdx|feature))(?:$|[\s)\]`'",;])/gm,P=/^[A-Za-z][A-Za-z0-9_-]*(?:\.[A-Za-z0-9_-]+)+$/,T=16*1024*1024;function F(e){const r=[...e.matchAll(/(?:^|\s)@?docs\/stories\/([A-Za-z][A-Za-z0-9_-]*(?:\.[A-Za-z0-9_-]+)+)\.story\.md(?=\s|$)/g)].map(c=>c[1]),s=e.trim().split(/\s+/).slice(1).map(c=>c.replace(/^@/,"")).filter(c=>P.test(c)),o=[...new Set([...r,...s])];return o.length===1?o[0]:null}function R(e){return e.startsWith("core/templates/")?"template":e.startsWith("docs/epics/")?"epic":e.startsWith("docs/stories/")&&e.endsWith(".story.md")?"story":e.endsWith(".rtm.md")?"traceability":e.toLowerCase().includes("adr")?"adr":e.toLowerCase().includes("contract")?"contract":e.toLowerCase().includes("nfr")?"nfr":e.endsWith(".feature")?"bdd":e.toLowerCase().includes("traceability")?"traceability":e.startsWith("docs/examples/")?"example":"spec"}function W(e){return[...new Set([...e.matchAll(O)].map(r=>r[1]).filter(r=>!!r))].sort()}function a(e,r){const s=y(e);let o;try{o=y(l(s,r))}catch{throw new Error("yolo-spec-envelope-required")}if(!o.startsWith(`${s}${$}`))throw new Error("yolo-spec-envelope-path-out-of-scope");const c=x(o);if(!c.isFile())throw new Error("yolo-spec-envelope-unsafe");if(c.size>T)throw new Error("yolo-spec-envelope-too-large");return j(o,"utf8")}function d(e,r){const o=v(e,{context:r==="story"?"story-target":"epic-target",explicitlySelected:!0});if(o.status==="malformed"||o.status==="oversized")throw new Error("yolo-spec-envelope-unsafe");if(o.status==="absent")return e;const c=e.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/);if(!c)throw new Error("yolo-spec-envelope-unsafe");return`---
2
+ ${Object.entries(o.metadata).map(([n,i])=>`${n}: ${JSON.stringify(i)}`).join(`
3
+ `)}
4
+ ---
5
+ ${e.slice(c[0].length)}`}function E(e){try{return _("git",["-C",e,"rev-parse","HEAD"],{encoding:"utf8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).trim()}catch{throw new Error("yolo-spec-envelope-stale")}}function Z(e){const r=`docs/stories/${e.storyId}.story.md`,s=`docs/epics/epic-${e.epicId}.md`,o=e.headSha??E(e.projectRoot),c=d(a(e.projectRoot,r),"story"),p=d(a(e.projectRoot,s),"epic"),n=[{kind:"story",path:r,content:c},{kind:"epic",path:s,content:p}],i=new Set([`docs/stories/${e.storyId}.spec.md`,`docs/stories/${e.storyId}.tasks.md`,`docs/stories/${e.storyId}.rtm.md`]),f=[...new Set([...W(c),...[...i].filter(t=>u(l(e.projectRoot,t)))])].sort(),g=[...f.filter(t=>i.has(t)),...f.filter(t=>!i.has(t))];let m=0;for(const t of g){if(t===r||t===s||!u(l(e.projectRoot,t)))continue;if(t.startsWith("docs/stories/")&&t.endsWith(".story.md")||t.startsWith("docs/epics/"))throw new Error("yolo-spec-envelope-target-mismatch");const h=a(e.projectRoot,t);if(n.length>=w){if(i.has(t))throw new Error("yolo-spec-envelope-too-large");m+=1;continue}n.push({kind:R(t),path:t,content:h})}m&&e.onOmittedReferences?.(m);for(const t of C){if(t===r||t===s||f.includes(t)||!u(l(e.projectRoot,t)))continue;const h=a(e.projectRoot,t);n.length>=w||n.push({kind:R(t),path:t,content:h})}const A=S({storyId:e.storyId,epicId:e.epicId,targetPath:r,inputSha256:e.inputSha256,headSha:o,collectedAt:e.collectedAt??new Date().toISOString(),artifacts:n}),I=e.headSha??E(e.projectRoot);if(o!==I||d(a(e.projectRoot,r),"story")!==c||d(a(e.projectRoot,s),"epic")!==p||n.some(t=>t.kind!=="story"&&t.kind!=="epic"&&a(e.projectRoot,t.path)!==t.content))throw new Error("yolo-spec-envelope-stale");return A}function H(e,r=new Date().toISOString()){return S({storyId:e.storyId,epicId:e.epicId,targetPath:e.targetPath,inputSha256:e.inputSha256,headSha:e.sourceRevision.headSha,collectedAt:r,artifacts:e.artifacts.map(({kind:s,path:o,content:c})=>({kind:s,path:o,content:c}))})}export{Z as collectYoloSpecEnvelope,F as extractTargetedYoloStoryId,H as refreshPrecollectedYoloSpecEnvelope};