@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
@@ -0,0 +1,83 @@
1
+ export declare const EXPLICIT_INTENT_RECOVERY_VERSION: 1;
2
+ export type ExplicitIntentRecoveryReasonV1 = 'exact-admission-accepted' | 'recovery-positional-overflow-eligible' | 'recovery-not-positional-overflow' | 'recovery-command-not-exact-first' | 'recovery-command-schema-ineligible' | 'recovery-unsafe-token' | 'recovery-multiple-explicit-commands' | 'recovery-target-not-unique' | 'recovery-canonical-admission-conflict';
3
+ export interface ExplicitIntentRecoveryBindingV1 {
4
+ readonly schemaVersion: typeof EXPLICIT_INTENT_RECOVERY_VERSION;
5
+ readonly originalSha256: string;
6
+ readonly originalByteLength: number;
7
+ readonly canonicalSha256: string;
8
+ readonly canonicalByteLength: number;
9
+ readonly commandId: string;
10
+ readonly targetKind: 'story-ref' | 'epic-ref' | 'target-ref';
11
+ readonly discardedTokenCount: number;
12
+ readonly receiptSha256: string;
13
+ readonly reasonCode: 'recovery-positional-overflow-eligible';
14
+ readonly publicSafe: true;
15
+ }
16
+ export type ExplicitIntentRecoveryResultV1 = {
17
+ readonly schemaVersion: typeof EXPLICIT_INTENT_RECOVERY_VERSION;
18
+ readonly kind: 'exact';
19
+ readonly reasonCode: 'exact-admission-accepted';
20
+ readonly publicSafe: true;
21
+ } | {
22
+ readonly schemaVersion: typeof EXPLICIT_INTENT_RECOVERY_VERSION;
23
+ readonly kind: 'canonicalized';
24
+ readonly canonicalArgs: string;
25
+ readonly binding: ExplicitIntentRecoveryBindingV1;
26
+ readonly publicSafe: true;
27
+ } | {
28
+ readonly schemaVersion: typeof EXPLICIT_INTENT_RECOVERY_VERSION;
29
+ readonly kind: 'confirmation-required' | 'rejected';
30
+ readonly reasonCode: Exclude<ExplicitIntentRecoveryReasonV1, 'exact-admission-accepted' | 'recovery-positional-overflow-eligible'>;
31
+ readonly candidateCount: number;
32
+ readonly publicSafe: true;
33
+ };
34
+ interface RecoveryAdmissionProjection {
35
+ readonly outcome: string;
36
+ readonly reason: string;
37
+ readonly selection?: {
38
+ readonly commandId: string;
39
+ readonly positionals: readonly string[];
40
+ readonly options: Readonly<Record<string, unknown>>;
41
+ };
42
+ }
43
+ interface RecoveryTokenProjection {
44
+ readonly value: string;
45
+ readonly whollyUnquoted: boolean;
46
+ }
47
+ interface RecoveryCommandProjection {
48
+ readonly id: string;
49
+ readonly aliases: readonly string[];
50
+ readonly number: number;
51
+ }
52
+ interface RecoverySchemaProjection {
53
+ readonly commandId: string;
54
+ readonly operation: {
55
+ readonly operations: readonly unknown[];
56
+ };
57
+ readonly options: readonly {
58
+ readonly required: boolean;
59
+ }[];
60
+ readonly positionals: readonly {
61
+ readonly kind: string;
62
+ readonly cardinality: string;
63
+ readonly required: boolean;
64
+ }[];
65
+ }
66
+ export interface ExplicitIntentRecoveryAuthority {
67
+ readonly input: string;
68
+ readonly exactAdmission: RecoveryAdmissionProjection;
69
+ readonly tokens: readonly RecoveryTokenProjection[] | null;
70
+ readonly commands: readonly RecoveryCommandProjection[];
71
+ readonly schemas: readonly RecoverySchemaProjection[];
72
+ readonly admitCanonical: (candidate: string) => RecoveryAdmissionProjection;
73
+ }
74
+ /**
75
+ * P224.02 exact-first recovery kernel.
76
+ *
77
+ * The caller supplies the exact parser, schema and lexer projections so this
78
+ * module stays pure and cannot become a second registry or parser. The result
79
+ * never contains discarded prose or the original input bytes.
80
+ */
81
+ export declare function recoverExplicitIntentWithAuthority(authority: ExplicitIntentRecoveryAuthority): ExplicitIntentRecoveryResultV1;
82
+ export declare function assertExplicitIntentRecoveryBindingV1(value: unknown, canonicalArgs?: string): asserts value is ExplicitIntentRecoveryBindingV1;
83
+ export {};
@@ -0,0 +1,187 @@
1
+ import { createHash } from 'node:crypto';
2
+ export const EXPLICIT_INTENT_RECOVERY_VERSION = 1;
3
+ function sha256(value) {
4
+ return createHash('sha256').update(value, 'utf8').digest('hex');
5
+ }
6
+ function rejected(kind, reasonCode, candidateCount = 0) {
7
+ return Object.freeze({
8
+ schemaVersion: EXPLICIT_INTENT_RECOVERY_VERSION,
9
+ kind,
10
+ reasonCode,
11
+ candidateCount: Math.max(0, Math.min(candidateCount, 16)),
12
+ publicSafe: true,
13
+ });
14
+ }
15
+ function commandForFirstToken(token, commands) {
16
+ if (!token.whollyUnquoted)
17
+ return undefined;
18
+ const normalized = token.value.replace(/^\*/, '').toLowerCase();
19
+ if (!token.value.startsWith('*') || !/^[a-z][a-z0-9?-]*$/.test(normalized))
20
+ return undefined;
21
+ return commands.find((command) => command.id === normalized || command.aliases.includes(normalized));
22
+ }
23
+ function isExplicitCommandToken(token, commands) {
24
+ if (!token.whollyUnquoted || !token.value.startsWith('*'))
25
+ return false;
26
+ const normalized = token.value.slice(1).toLowerCase();
27
+ return commands.some((command) => command.id === normalized || command.aliases.includes(normalized));
28
+ }
29
+ function recoverableTypedTarget(kind, value) {
30
+ const candidate = value.startsWith('@') ? value.slice(1) : value;
31
+ if (kind === 'story-ref') {
32
+ return /^(?:docs\/stories\/[A-Za-z0-9._/-]+\.story\.md|P\d+\.\d+|story-P\d+\.\d+)$/.test(candidate);
33
+ }
34
+ if (kind === 'epic-ref') {
35
+ return /^(?:docs\/epics\/epic-[A-Za-z0-9][A-Za-z0-9_-]*\.md|P\d+|epic-[A-Za-z0-9][A-Za-z0-9_-]*(?:\.md)?)$/i.test(candidate);
36
+ }
37
+ return /^(?:P\d+|EPIC-\d+)$/i.test(candidate)
38
+ || /^docs\/epics\/?$/.test(candidate)
39
+ || /^docs\/epics\/epic-[A-Za-z0-9][A-Za-z0-9_-]*\.md$/i.test(candidate);
40
+ }
41
+ /**
42
+ * P224.02 exact-first recovery kernel.
43
+ *
44
+ * The caller supplies the exact parser, schema and lexer projections so this
45
+ * module stays pure and cannot become a second registry or parser. The result
46
+ * never contains discarded prose or the original input bytes.
47
+ */
48
+ export function recoverExplicitIntentWithAuthority(authority) {
49
+ if (authority.exactAdmission.outcome === 'resolved') {
50
+ return Object.freeze({
51
+ schemaVersion: EXPLICIT_INTENT_RECOVERY_VERSION,
52
+ kind: 'exact',
53
+ reasonCode: 'exact-admission-accepted',
54
+ publicSafe: true,
55
+ });
56
+ }
57
+ if (authority.exactAdmission.outcome !== 'invalid_arguments'
58
+ || authority.exactAdmission.reason !== 'positional_overflow') {
59
+ return rejected('rejected', 'recovery-not-positional-overflow');
60
+ }
61
+ const tokens = authority.tokens;
62
+ if (!tokens || tokens.length < 3) {
63
+ return rejected('rejected', 'recovery-command-not-exact-first');
64
+ }
65
+ const command = commandForFirstToken(tokens[0], authority.commands);
66
+ if (!command)
67
+ return rejected('rejected', 'recovery-command-not-exact-first');
68
+ const schema = authority.schemas.find((item) => item.commandId === command.id);
69
+ const positional = schema?.positionals[0];
70
+ if (!schema
71
+ || schema.operation.operations.length > 0
72
+ || schema.options.some((option) => option.required)
73
+ || schema.positionals.length !== 1
74
+ || positional?.cardinality !== 'one'
75
+ || !['story-ref', 'epic-ref', 'target-ref'].includes(positional.kind)) {
76
+ return rejected('rejected', 'recovery-command-schema-ineligible');
77
+ }
78
+ if (tokens.slice(1).some((token) => isExplicitCommandToken(token, authority.commands))) {
79
+ return rejected('confirmation-required', 'recovery-multiple-explicit-commands');
80
+ }
81
+ // Recovery never discards quoted material or option-shaped tokens. Exact
82
+ // admission remains responsible for accepted options and quoted arguments.
83
+ if (tokens.slice(1).some((token) => !token.whollyUnquoted || token.value.startsWith('--')
84
+ || token.value.startsWith('*'))) {
85
+ return rejected('confirmation-required', 'recovery-unsafe-token');
86
+ }
87
+ const candidates = tokens.slice(1).flatMap((token) => {
88
+ if (!recoverableTypedTarget(positional.kind, token.value)) {
89
+ return [];
90
+ }
91
+ const canonicalArgs = `*${command.id} ${token.value}`;
92
+ const admission = authority.admitCanonical(canonicalArgs);
93
+ if (admission.outcome !== 'resolved'
94
+ || admission.selection?.commandId !== command.id
95
+ || admission.selection.positionals.length !== 1
96
+ || Object.keys(admission.selection.options).length !== 0)
97
+ return [];
98
+ return [{ canonicalArgs, target: admission.selection.positionals[0] }];
99
+ });
100
+ const unique = [...new Map(candidates.map((candidate) => [candidate.canonicalArgs, candidate])).values()];
101
+ if (unique.length !== 1) {
102
+ return rejected('confirmation-required', 'recovery-target-not-unique', unique.length);
103
+ }
104
+ const selected = unique[0];
105
+ const finalAdmission = authority.admitCanonical(selected.canonicalArgs);
106
+ if (finalAdmission.outcome !== 'resolved'
107
+ || finalAdmission.selection?.commandId !== command.id
108
+ || finalAdmission.selection.positionals[0] !== selected.target) {
109
+ return rejected('rejected', 'recovery-canonical-admission-conflict', 1);
110
+ }
111
+ const originalSha256 = sha256(authority.input);
112
+ const canonicalSha256 = sha256(selected.canonicalArgs);
113
+ const base = {
114
+ schemaVersion: EXPLICIT_INTENT_RECOVERY_VERSION,
115
+ originalSha256,
116
+ originalByteLength: Buffer.byteLength(authority.input, 'utf8'),
117
+ canonicalSha256,
118
+ canonicalByteLength: Buffer.byteLength(selected.canonicalArgs, 'utf8'),
119
+ commandId: command.id,
120
+ targetKind: positional.kind,
121
+ discardedTokenCount: tokens.length - 2,
122
+ reasonCode: 'recovery-positional-overflow-eligible',
123
+ publicSafe: true,
124
+ };
125
+ const receiptSha256 = sha256(`p224-explicit-intent-recovery-v1\0${JSON.stringify(base)}`);
126
+ return Object.freeze({
127
+ schemaVersion: EXPLICIT_INTENT_RECOVERY_VERSION,
128
+ kind: 'canonicalized',
129
+ canonicalArgs: selected.canonicalArgs,
130
+ binding: Object.freeze({ ...base, receiptSha256 }),
131
+ publicSafe: true,
132
+ });
133
+ }
134
+ export function assertExplicitIntentRecoveryBindingV1(value, canonicalArgs) {
135
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
136
+ throw new Error('EXPLICIT_INTENT_RECOVERY_BINDING_INVALID');
137
+ }
138
+ const candidate = value;
139
+ const expectedKeys = [
140
+ 'canonicalByteLength', 'canonicalSha256', 'commandId', 'discardedTokenCount',
141
+ 'originalByteLength', 'originalSha256', 'publicSafe', 'reasonCode',
142
+ 'receiptSha256', 'schemaVersion', 'targetKind',
143
+ ];
144
+ if (Object.keys(candidate).sort().join('\0') !== expectedKeys.sort().join('\0')
145
+ || candidate.schemaVersion !== EXPLICIT_INTENT_RECOVERY_VERSION
146
+ || !['story-ref', 'epic-ref', 'target-ref'].includes(String(candidate.targetKind))
147
+ || typeof candidate.commandId !== 'string'
148
+ || !/^[a-z][a-z0-9?-]{0,63}$/.test(candidate.commandId)
149
+ || typeof candidate.originalSha256 !== 'string'
150
+ || !/^[a-f0-9]{64}$/.test(candidate.originalSha256)
151
+ || typeof candidate.canonicalSha256 !== 'string'
152
+ || !/^[a-f0-9]{64}$/.test(candidate.canonicalSha256)
153
+ || typeof candidate.receiptSha256 !== 'string'
154
+ || !/^[a-f0-9]{64}$/.test(candidate.receiptSha256)
155
+ || !Number.isSafeInteger(candidate.originalByteLength)
156
+ || candidate.originalByteLength < 1
157
+ || !Number.isSafeInteger(candidate.canonicalByteLength)
158
+ || candidate.canonicalByteLength < 1
159
+ || !Number.isSafeInteger(candidate.discardedTokenCount)
160
+ || candidate.discardedTokenCount < 1
161
+ || candidate.discardedTokenCount > 512
162
+ || candidate.reasonCode !== 'recovery-positional-overflow-eligible'
163
+ || candidate.publicSafe !== true) {
164
+ throw new Error('EXPLICIT_INTENT_RECOVERY_BINDING_INVALID');
165
+ }
166
+ if (canonicalArgs !== undefined
167
+ && (candidate.canonicalByteLength !== Buffer.byteLength(canonicalArgs, 'utf8')
168
+ || candidate.canonicalSha256 !== sha256(canonicalArgs))) {
169
+ throw new Error('EXPLICIT_INTENT_RECOVERY_BINDING_CONFLICT');
170
+ }
171
+ const receiptBase = {
172
+ schemaVersion: candidate.schemaVersion,
173
+ originalSha256: candidate.originalSha256,
174
+ originalByteLength: candidate.originalByteLength,
175
+ canonicalSha256: candidate.canonicalSha256,
176
+ canonicalByteLength: candidate.canonicalByteLength,
177
+ commandId: candidate.commandId,
178
+ targetKind: candidate.targetKind,
179
+ discardedTokenCount: candidate.discardedTokenCount,
180
+ reasonCode: candidate.reasonCode,
181
+ publicSafe: candidate.publicSafe,
182
+ };
183
+ if (candidate.receiptSha256
184
+ !== sha256(`p224-explicit-intent-recovery-v1\0${JSON.stringify(receiptBase)}`)) {
185
+ throw new Error('EXPLICIT_INTENT_RECOVERY_BINDING_CONFLICT');
186
+ }
187
+ }
@@ -1,3 +1,4 @@
1
+ import { type ExplicitIntentRecoveryResultV1 } from './explicit-intent-recovery.js';
1
2
  export * from './input-envelope.js';
2
3
  export * from './project-identity-migration.js';
3
4
  export * from './state-projection.js';
@@ -5,6 +6,7 @@ export * from './strict-effect-receipt.js';
5
6
  export * from './public-diagnostics.js';
6
7
  export * from './recovery-route-compiler.js';
7
8
  export * from './executable-policy-recovery.js';
9
+ export * from './explicit-intent-recovery.js';
8
10
  export declare const EXACT_INVOCATION_POLICY: "p205-exact-invocation-v1";
9
11
  export declare const INVOCATION_SCHEMA_VERSION: "p205-invocation-schema-v1";
10
12
  export declare const INVOCATION_LIMITS: Readonly<{
@@ -147,6 +149,11 @@ type LexResult = {
147
149
  };
148
150
  export declare function lexInvocationEnvelope(input: string): LexResult;
149
151
  export declare function admitInvocation(input: string, options?: InvocationAdmissionOptions): InvocationAdmissionResultV1;
152
+ /**
153
+ * P224.02 public exact-first recovery facade. It reuses this module's single
154
+ * registry, schema, lexer and admission authority instead of duplicating policy.
155
+ */
156
+ export declare function recoverExplicitInvocation(input: string, options?: InvocationAdmissionOptions): ExplicitIntentRecoveryResultV1;
150
157
  export interface InvocationAdmissionReceiptV1 {
151
158
  readonly schemaVersion: 1;
152
159
  readonly policy: typeof EXACT_INVOCATION_POLICY;
@@ -10,6 +10,7 @@ import { COMMAND_REGISTRY_CHECKSUM, COMMAND_REGISTRY_VERSION, GENERATED_SHARED_C
10
10
  import { GENERATED_INVOCATION_SCHEMA_MANIFEST, GENERATED_INVOCATION_SCHEMAS, } from '../generated/invocation-schema.generated.js';
11
11
  import { canonicalizeCommandRegistryJcs } from '../command-registry-contract.js';
12
12
  import { CONTINUITY_GOAL_OPERATION_IDS } from '../continuity/goal-operation-authority.js';
13
+ import { recoverExplicitIntentWithAuthority, } from './explicit-intent-recovery.js';
13
14
  export * from './input-envelope.js';
14
15
  export * from './project-identity-migration.js';
15
16
  export * from './state-projection.js';
@@ -17,6 +18,7 @@ export * from './strict-effect-receipt.js';
17
18
  export * from './public-diagnostics.js';
18
19
  export * from './recovery-route-compiler.js';
19
20
  export * from './executable-policy-recovery.js';
21
+ export * from './explicit-intent-recovery.js';
20
22
  export const EXACT_INVOCATION_POLICY = 'p205-exact-invocation-v1';
21
23
  export const INVOCATION_SCHEMA_VERSION = 'p205-invocation-schema-v1';
22
24
  export const INVOCATION_LIMITS = Object.freeze({
@@ -598,6 +600,26 @@ export function admitInvocation(input, options = {}) {
598
600
  return reject('invalid_arguments', uiUxReview, lexed.tokens.length, bytes);
599
601
  return resolved(command, operation.operationId, parsed, uiUxReview, lexed.tokens.length, bytes);
600
602
  }
603
+ /**
604
+ * P224.02 public exact-first recovery facade. It reuses this module's single
605
+ * registry, schema, lexer and admission authority instead of duplicating policy.
606
+ */
607
+ export function recoverExplicitInvocation(input, options = {}) {
608
+ const exactAdmission = admitInvocation(input, options);
609
+ const lexed = lexInvocationEnvelope(input);
610
+ return recoverExplicitIntentWithAuthority({
611
+ input,
612
+ exactAdmission,
613
+ tokens: lexed.ok ? lexed.tokens : null,
614
+ commands: commands.map((command) => ({
615
+ id: command.id,
616
+ aliases: command.aliases,
617
+ number: command.number,
618
+ })),
619
+ schemas: invocationSchemas,
620
+ admitCanonical: (candidate) => admitInvocation(candidate, options),
621
+ });
622
+ }
601
623
  function resolved(command, operationId, parsed, uiUxReview, tokenCount, bytes) {
602
624
  const selection = freeze({
603
625
  commandId: command.id,
@@ -1,7 +1,7 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { posix } from 'node:path';
3
3
  const SHA = /^[a-f0-9]{40}(?:[a-f0-9]{24})?$/;
4
- const PATH = /^[A-Za-z0-9_.-][A-Za-z0-9_./ -]{0,239}$/;
4
+ const PATH = /^[A-Za-z0-9_.\[\]-][A-Za-z0-9_./ \[\]-]{0,239}$/;
5
5
  const UNSAFE = /(^|\/)(?:\.env(?:\.|$)|secrets?|credentials?|private-prompts?|customer-data)(?:\/|$)|(?:token|password|license[_-]?key|secret)[=:]/i;
6
6
  function digest(paths) {
7
7
  return createHash('sha256').update(JSON.stringify(paths)).digest('hex');
@@ -1,4 +1,17 @@
1
1
  /** Public contracts and pure safety decisions for epic-owned terminal Git. */
2
+ import { createHash } from 'node:crypto';
3
+ /**
4
+ * P205 complete-gate budgets are declared in config/release-gates.v2.json and
5
+ * mirrored here so installed clients keep the same closed runtime bounds.
6
+ * release-gates.test.mjs prevents either side from drifting independently.
7
+ */
8
+ export const P205_RELEASE_GATE_BUDGETS = Object.freeze({
9
+ completeGateWorstCaseMs: 45 * 60 * 1000,
10
+ cancellationGraceMs: 5 * 60 * 1000,
11
+ aggregateValidityMs: 2 * 60 * 60 * 1000,
12
+ terminalWorkflowMaxDurationMs: 2 * 60 * 60 * 1000,
13
+ });
14
+ export const P205_ROOT_INVOKE_TIMEOUT_MS = P205_RELEASE_GATE_BUDGETS.completeGateWorstCaseMs + P205_RELEASE_GATE_BUDGETS.cancellationGraceMs;
2
15
  export const EPIC_TERMINAL_GIT_REASON_CODES = Object.freeze({
3
16
  READY: 'epic-terminal-git-ready',
4
17
  ALREADY_COMPLETE: 'epic-terminal-git-already-complete',
@@ -38,6 +51,96 @@ export const EPIC_TERMINAL_GIT_REASON_CODES = Object.freeze({
38
51
  PR_BASE_GUARD_UNVERIFIABLE: 'epic-terminal-pr-base-guard-unverifiable',
39
52
  PR_MERGE_QUEUE_LOCAL_GATE_REQUIRED: 'epic-terminal-pr-merge-queue-local-gate-required',
40
53
  });
54
+ export function epicHeadReconciliationRangeDigest(lastAcceptedCheckpointHeadSha, executionHeadSha, reconciliationCommitShas) {
55
+ return createHash('sha256').update([
56
+ 'epic-head-reconciliation-range-v1',
57
+ lastAcceptedCheckpointHeadSha,
58
+ executionHeadSha,
59
+ ...reconciliationCommitShas,
60
+ ].join('\0')).digest('hex');
61
+ }
62
+ export function epicHeadReconciliationPathsDigest(paths) {
63
+ return createHash('sha256').update(paths.join('\0')).digest('hex');
64
+ }
65
+ export function epicHeadReconciliationInputDigest(value) {
66
+ return createHash('sha256').update(JSON.stringify({
67
+ schemaVersion: value.schemaVersion,
68
+ kind: value.kind,
69
+ producer: value.producer,
70
+ epicId: value.epicId,
71
+ executionBranch: value.executionBranch,
72
+ originBranch: value.originBranch,
73
+ graphRevision: value.graphRevision,
74
+ originHeadSha: value.originHeadSha,
75
+ lastAcceptedCheckpointHeadSha: value.lastAcceptedCheckpointHeadSha,
76
+ executionHeadSha: value.executionHeadSha,
77
+ acceptedCheckpointIds: value.acceptedCheckpointIds,
78
+ acceptedCheckpointHeads: value.acceptedCheckpointHeads,
79
+ reconciliationCommitShas: value.reconciliationCommitShas,
80
+ commitRangeDigest: value.commitRangeDigest,
81
+ changedPaths: value.changedPaths,
82
+ changedPathsDigest: value.changedPathsDigest,
83
+ allowedWriteSet: value.allowedWriteSet,
84
+ allowedWriteSetDigest: value.allowedWriteSetDigest,
85
+ aggregateReceiptRef: value.aggregateReceiptRef,
86
+ aggregateManifestDigest: value.aggregateManifestDigest,
87
+ aggregateResultDigest: value.aggregateResultDigest,
88
+ producedAt: value.producedAt,
89
+ revalidatedAt: value.revalidatedAt,
90
+ publicSafe: value.publicSafe,
91
+ })).digest('hex');
92
+ }
93
+ export function validateEpicHeadReconciliationReceipt(value, expected) {
94
+ if (!value || value.schemaVersion !== 1 || value.kind !== 'epic_head_reconciliation'
95
+ || value.producer !== 'client-p205-head-reconciliation-v1' || value.publicSafe !== true
96
+ || !nonEmpty(value.epicId) || !nonEmpty(value.executionBranch) || !nonEmpty(value.originBranch)
97
+ || !Array.isArray(value.acceptedCheckpointIds) || !Array.isArray(value.acceptedCheckpointHeads)
98
+ || !Array.isArray(value.reconciliationCommitShas) || !Array.isArray(value.changedPaths)
99
+ || !Array.isArray(value.allowedWriteSet)
100
+ || value.epicId !== expected.epicId || value.executionBranch !== expected.executionBranch
101
+ || value.originBranch !== expected.originBranch || value.graphRevision !== expected.graphRevision
102
+ || value.originHeadSha !== expected.originHeadSha || value.executionHeadSha !== expected.executionHeadSha
103
+ || value.lastAcceptedCheckpointHeadSha !== expected.acceptedCheckpointHeads.at(-1)
104
+ || !sameOrdered(value.acceptedCheckpointIds, expected.acceptedCheckpointIds)
105
+ || !sameOrdered(value.acceptedCheckpointHeads, expected.acceptedCheckpointHeads)
106
+ || value.aggregateReceiptRef !== expected.aggregateQaReceipt.receiptRef
107
+ || value.aggregateManifestDigest !== expected.aggregateQaReceipt.manifestDigest
108
+ || value.aggregateResultDigest !== expected.aggregateQaReceipt.resultDigest
109
+ || !nonEmpty(value.aggregateReceiptRef) || !isHash(value.aggregateManifestDigest)
110
+ || !isHash(value.aggregateResultDigest) || !nonEmpty(value.producedAt) || !nonEmpty(value.revalidatedAt)
111
+ || value.acceptedCheckpointIds.length === 0 || value.acceptedCheckpointIds.length > 2_048
112
+ || value.acceptedCheckpointIds.some((id) => !nonEmpty(id) || id.length > 240)
113
+ || value.reconciliationCommitShas.length > 2_048
114
+ || value.changedPaths.length > 2_048
115
+ || value.allowedWriteSet.length === 0 || value.allowedWriteSet.length > 2_048
116
+ || (value.lastAcceptedCheckpointHeadSha !== value.executionHeadSha
117
+ && (value.reconciliationCommitShas.length === 0 || value.changedPaths.length === 0))
118
+ || (value.lastAcceptedCheckpointHeadSha === value.executionHeadSha
119
+ && (value.reconciliationCommitShas.length !== 0 || value.changedPaths.length !== 0))
120
+ || !isFullSha(value.originHeadSha) || !isFullSha(value.lastAcceptedCheckpointHeadSha)
121
+ || !isFullSha(value.executionHeadSha) || !isHash(value.graphRevision)
122
+ || value.acceptedCheckpointHeads.some((sha) => !isFullSha(sha))
123
+ || value.reconciliationCommitShas.some((sha) => !isFullSha(sha))
124
+ || !sameOrdered(value.changedPaths, [...new Set(value.changedPaths)].sort())
125
+ || !sameOrdered(value.allowedWriteSet, [...new Set(value.allowedWriteSet)].sort())
126
+ || value.changedPaths.some((path) => !safeRepositoryPath(path))
127
+ || value.allowedWriteSet.some((path) => !safeWriteScope(path))
128
+ || value.changedPaths.some((path) => !value.allowedWriteSet.some((scope) => writeScopeCovers(scope, path)))
129
+ || value.commitRangeDigest !== epicHeadReconciliationRangeDigest(value.lastAcceptedCheckpointHeadSha, value.executionHeadSha, value.reconciliationCommitShas)
130
+ || value.changedPathsDigest !== epicHeadReconciliationPathsDigest(value.changedPaths)
131
+ || value.allowedWriteSetDigest !== epicHeadReconciliationPathsDigest(value.allowedWriteSet)
132
+ || value.inputDigest !== epicHeadReconciliationInputDigest(value)
133
+ || !isHash(value.commitRangeDigest) || !isHash(value.changedPathsDigest)
134
+ || !isHash(value.allowedWriteSetDigest) || !isHash(value.inputDigest))
135
+ return false;
136
+ const producedAt = Date.parse(value.producedAt);
137
+ const revalidatedAt = Date.parse(value.revalidatedAt);
138
+ const now = Date.parse(expected.nowIso);
139
+ return Number.isFinite(producedAt) && Number.isFinite(revalidatedAt) && Number.isFinite(now)
140
+ && revalidatedAt >= producedAt
141
+ && now - revalidatedAt <= P205_RELEASE_GATE_BUDGETS.aggregateValidityMs
142
+ && revalidatedAt - now <= P205_RELEASE_GATE_BUDGETS.cancellationGraceMs;
143
+ }
41
144
  export function validateEpicTerminalGitDirective(directive, actual) {
42
145
  const reasons = [];
43
146
  if (!nonEmpty(directive.originBranch))
@@ -76,8 +179,8 @@ export function validateEpicTerminalGitDirective(directive, actual) {
76
179
  || !directive.localGates.receiptRefs.includes(aggregate.receiptRef)) {
77
180
  reasons.push(EPIC_TERMINAL_GIT_REASON_CODES.AGGREGATE_QA_REQUIRED);
78
181
  }
79
- else if (!Number.isFinite(Date.parse(aggregate.checkedAt)) || actual.nowIso && (Date.parse(actual.nowIso) - Date.parse(aggregate.checkedAt) > 30 * 60 * 1000
80
- || Date.parse(aggregate.checkedAt) - Date.parse(actual.nowIso) > 5 * 60 * 1000)) {
182
+ else if (!Number.isFinite(Date.parse(aggregate.checkedAt)) || actual.nowIso && (Date.parse(actual.nowIso) - Date.parse(aggregate.checkedAt) > P205_RELEASE_GATE_BUDGETS.aggregateValidityMs
183
+ || Date.parse(aggregate.checkedAt) - Date.parse(actual.nowIso) > P205_RELEASE_GATE_BUDGETS.cancellationGraceMs)) {
81
184
  reasons.push(EPIC_TERMINAL_GIT_REASON_CODES.AGGREGATE_QA_STALE);
82
185
  }
83
186
  const originBinding = actual.originBinding;
@@ -90,6 +193,24 @@ export function validateEpicTerminalGitDirective(directive, actual) {
90
193
  || !Number.isFinite(Date.parse(originBinding.capturedAt))) {
91
194
  reasons.push(EPIC_TERMINAL_GIT_REASON_CODES.ORIGIN_BINDING_REQUIRED);
92
195
  }
196
+ const directedReconciliation = directive.localGates?.headReconciliationReceipt;
197
+ const actualReconciliation = actual.headReconciliationReceipt;
198
+ if (directedReconciliation && (!actualReconciliation || !originBinding || !aggregate
199
+ || directedReconciliation.inputDigest !== actualReconciliation.inputDigest
200
+ || !validateEpicHeadReconciliationReceipt(actualReconciliation, {
201
+ epicId: directive.epicId,
202
+ executionBranch: directive.executionBranch,
203
+ originBranch: directive.originBranch,
204
+ graphRevision: directive.graphRevision,
205
+ originHeadSha: originBinding.originHeadSha,
206
+ executionHeadSha: actual.executionHeadSha,
207
+ acceptedCheckpointIds: actual.acceptedCheckpointIds,
208
+ acceptedCheckpointHeads: actualReconciliation.acceptedCheckpointHeads,
209
+ aggregateQaReceipt: aggregate,
210
+ nowIso: actual.nowIso ?? new Date(0).toISOString(),
211
+ }))) {
212
+ reasons.push(EPIC_TERMINAL_GIT_REASON_CODES.AGGREGATE_QA_REQUIRED);
213
+ }
93
214
  if (actual.writerLeaseActive)
94
215
  reasons.push(EPIC_TERMINAL_GIT_REASON_CODES.LEASE_ACTIVE);
95
216
  if (!sameSet(directive.storyCheckpointIds, actual.acceptedCheckpointIds)) {
@@ -220,6 +341,9 @@ function nonEmpty(value) {
220
341
  function isSha(value) {
221
342
  return /^[a-f0-9]{7,64}$/i.test(value);
222
343
  }
344
+ function isFullSha(value) {
345
+ return /^[a-f0-9]{40,64}$/i.test(value);
346
+ }
223
347
  function isHash(value) {
224
348
  return typeof value === 'string' && /^[a-f0-9]{64}$/i.test(value);
225
349
  }
@@ -229,3 +353,21 @@ function unique(values) {
229
353
  function sameSet(left, right) {
230
354
  return left.length === right.length && [...left].sort().every((item, index) => item === [...right].sort()[index]);
231
355
  }
356
+ function sameOrdered(left, right) {
357
+ return left.length === right.length && left.every((item, index) => item === right[index]);
358
+ }
359
+ function safeRepositoryPath(value) {
360
+ return safeWriteScope(value) && !value.endsWith('/');
361
+ }
362
+ function safeWriteScope(value) {
363
+ if (typeof value !== 'string' || value.length === 0 || value.length > 512
364
+ || value.startsWith('/') || value.startsWith('-') || value.includes('\\')
365
+ || value.includes('\0') || value.includes('//'))
366
+ return false;
367
+ const parts = value.replace(/\/$/, '').split('/');
368
+ return parts.length > 0 && parts.every((part) => part.length > 0 && part !== '.' && part !== '..')
369
+ && parts[0] !== '.git';
370
+ }
371
+ function writeScopeCovers(scope, path) {
372
+ return scope === path || scope.endsWith('/') && path.startsWith(scope);
373
+ }
@@ -1,4 +1,4 @@
1
- # 🧠 Neocortex v4.60.73 | OrNexus Team
1
+ # 🧠 Neocortex v4.60.75 | OrNexus Team
2
2
 
3
3
  This project uses Neocortex, a Development Orchestrator.
4
4
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex
3
- description: "🧠 Neocortex v4.60.73 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.60.75 | OrNexus Team"
4
4
  ---
5
5
 
6
6
  <!--
@@ -4,7 +4,7 @@ agent:
4
4
  name: 'Neocortex Root Agent'
5
5
  title: 'Development Orchestrator (Root)'
6
6
  icon: '>'
7
- version: '4.60.73'
7
+ version: '4.60.75'
8
8
  architecture: 'thin-client'
9
9
  module: stand-alone
10
10
  hasSidecar: false
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex-root
3
- description: "🧠 Neocortex Root Agent v4.60.73 | OrNexus Team"
3
+ description: "🧠 Neocortex Root Agent v4.60.75 | OrNexus Team"
4
4
  model: opus
5
5
  color: blue
6
6
  tools:
@@ -108,7 +108,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
108
108
  ┌────────────────────────────────────────────────────────────┐
109
109
  │ │
110
110
  │ ####### N E O C O R T E X │
111
- │ ### ######## v4.60.73 │
111
+ │ ### ######## v4.60.75 │
112
112
  │ ######### ##### │
113
113
  │ ## ############## Development Orchestrator │
114
114
  │ ## ### ###### ## OrNexus Team │
@@ -4,7 +4,7 @@ agent:
4
4
  name: 'Neocortex'
5
5
  title: 'Development Orchestrator'
6
6
  icon: '>'
7
- version: '4.60.73'
7
+ version: '4.60.75'
8
8
  architecture: 'thin-client'
9
9
  module: stand-alone
10
10
  hasSidecar: false
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: neocortex
3
- description: "🧠 Neocortex v4.60.73 | OrNexus Team"
3
+ description: "🧠 Neocortex v4.60.75 | OrNexus Team"
4
4
  model: opus
5
5
  color: blue
6
6
  permissionMode: bypassPermissions
@@ -104,7 +104,7 @@ SEMPRE que este agente for invocado, imprima o banner abaixo como PRIMEIRO outpu
104
104
  ┌────────────────────────────────────────────────────────────┐
105
105
  │ │
106
106
  │ ####### N E O C O R T E X │
107
- │ ### ######## v4.60.73 │
107
+ │ ### ######## v4.60.75 │
108
108
  │ ######### ##### │
109
109
  │ ## ############## Development Orchestrator │
110
110
  │ ## ### ###### ## OrNexus Team │