@ornexus/neocortex 4.60.67 → 4.60.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/dist/release-source.json +1 -1
  2. package/dist/sbom.cdx.json +1194 -1194
  3. package/install.sh +1 -1
  4. package/package.json +2 -2
  5. package/packages/client/dist/adapters/adapter-registry.js +108 -1
  6. package/packages/client/dist/adapters/antigravity-adapter.js +77 -2
  7. package/packages/client/dist/adapters/claude-code-adapter.js +79 -3
  8. package/packages/client/dist/adapters/codex-adapter.js +80 -2
  9. package/packages/client/dist/adapters/cursor-adapter.js +115 -4
  10. package/packages/client/dist/adapters/gemini-adapter.js +71 -2
  11. package/packages/client/dist/adapters/grok-adapter.js +42 -2
  12. package/packages/client/dist/adapters/index.js +22 -1
  13. package/packages/client/dist/adapters/platform-detector.js +212 -1
  14. package/packages/client/dist/adapters/target-adapter.js +12 -0
  15. package/packages/client/dist/adapters/vscode-adapter.js +72 -2
  16. package/packages/client/dist/agent/refresh-stubs.js +417 -2
  17. package/packages/client/dist/agent/update-agent-yaml.js +102 -1
  18. package/packages/client/dist/agent/update-description.js +251 -1
  19. package/packages/client/dist/cache/crypto-utils.js +78 -1
  20. package/packages/client/dist/cache/encrypted-cache.js +108 -1
  21. package/packages/client/dist/cache/in-memory-asset-cache.js +73 -1
  22. package/packages/client/dist/cache/index.js +13 -1
  23. package/packages/client/dist/cache/protected-pi-boundary.js +44 -1
  24. package/packages/client/dist/checkpoint/checkpoint-client-reader.js +127 -2
  25. package/packages/client/dist/checkpoint/index.js +11 -1
  26. package/packages/client/dist/checkpoint/shared-checkpoint-types.js +32 -1
  27. package/packages/client/dist/cli.js +290 -3
  28. package/packages/client/dist/commands/activate.js +394 -8
  29. package/packages/client/dist/commands/architecture-answers.js +274 -7
  30. package/packages/client/dist/commands/architecture-memory-terminal.js +253 -4
  31. package/packages/client/dist/commands/architecture-non-ui-continuation.js +100 -1
  32. package/packages/client/dist/commands/architecture-root-binding.js +51 -1
  33. package/packages/client/dist/commands/cache-status.js +112 -2
  34. package/packages/client/dist/commands/config.js +88 -1
  35. package/packages/client/dist/commands/doctor.js +635 -2
  36. package/packages/client/dist/commands/invoke.js +7140 -142
  37. package/packages/client/dist/commands/legacy-epic-terminal.js +71 -1
  38. package/packages/client/dist/commands/legacy-story-branch.js +96 -1
  39. package/packages/client/dist/commands/legacy-story-pr.js +276 -1
  40. package/packages/client/dist/commands/mutation-qa-checkpoint.js +285 -5
  41. package/packages/client/dist/commands/mutation-qa-gate.js +54 -1
  42. package/packages/client/dist/commands/mutation-qa-git.js +41 -1
  43. package/packages/client/dist/commands/mutation-qa-policy.js +102 -1
  44. package/packages/client/dist/commands/mutation-qa-run.js +219 -3
  45. package/packages/client/dist/commands/mutation-qa-verdict.js +149 -1
  46. package/packages/client/dist/commands/mutation-qa.js +220 -1
  47. package/packages/client/dist/commands/native-agent.js +136 -2
  48. package/packages/client/dist/commands/planning-diagnosis.js +43 -1
  49. package/packages/client/dist/commands/planning-generation.js +53 -1
  50. package/packages/client/dist/commands/planning-memory.js +40 -1
  51. package/packages/client/dist/commands/planning-research.js +42 -1
  52. package/packages/client/dist/commands/private-session.js +75 -1
  53. package/packages/client/dist/commands/property-qa.js +139 -1
  54. package/packages/client/dist/commands/qa-control.js +16 -1
  55. package/packages/client/dist/commands/qa-scan-browser-launch.js +55 -1
  56. package/packages/client/dist/commands/qa-scan-browser-route.js +28 -1
  57. package/packages/client/dist/commands/qa-scan-capture.js +663 -5
  58. package/packages/client/dist/commands/qa-scan-discovery.js +376 -3
  59. package/packages/client/dist/commands/qa-scan-review.js +826 -5
  60. package/packages/client/dist/commands/qa-synthetic-backend-capture.js +266 -1
  61. package/packages/client/dist/commands/qa-synthetic-backend-review.js +297 -1
  62. package/packages/client/dist/commands/qa-synthetic-backend.js +340 -2
  63. package/packages/client/dist/commands/qa-synthetic-broker-port.js +85 -1
  64. package/packages/client/dist/commands/qa-synthetic-browser.js +39 -1
  65. package/packages/client/dist/commands/refactor-characterization.js +671 -21
  66. package/packages/client/dist/commands/refactor-commit.js +399 -13
  67. package/packages/client/dist/commands/refactor-control.js +142 -3
  68. package/packages/client/dist/commands/refactor-cpp-assertions.js +93 -3
  69. package/packages/client/dist/commands/refactor-review.js +283 -5
  70. package/packages/client/dist/commands/refactor-root.js +588 -7
  71. package/packages/client/dist/commands/refresh-memory.js +156 -3
  72. package/packages/client/dist/commands/shared-architecture-non-ui.js +24 -1
  73. package/packages/client/dist/commands/story-checkpoint.js +171 -1
  74. package/packages/client/dist/config/profile-directory.js +13 -1
  75. package/packages/client/dist/config/resolver-selection.js +278 -1
  76. package/packages/client/dist/config/secure-config.js +281 -12
  77. package/packages/client/dist/config.js +223 -2
  78. package/packages/client/dist/constants.js +25 -1
  79. package/packages/client/dist/context/context-collector.js +222 -2
  80. package/packages/client/dist/context/context-sanitizer.js +145 -1
  81. package/packages/client/dist/continuity/autonomous-governance.js +285 -1
  82. package/packages/client/dist/continuity/continuity-client-state-store.js +1587 -1
  83. package/packages/client/dist/continuity/invoke-hooks.js +129 -1
  84. package/packages/client/dist/continuity/migrations/001-initial-schema.js +12 -2
  85. package/packages/client/dist/continuity/migrations/002-processing-output-summary-indexes.js +12 -2
  86. package/packages/client/dist/continuity/migrations/003-headless-execution-attempts.js +12 -2
  87. package/packages/client/dist/continuity/migrations/004-outbox-delivery-state.js +12 -2
  88. package/packages/client/dist/continuity/migrations/005-bounded-headless-queue.js +12 -2
  89. package/packages/client/dist/continuity/migrations/006-native-agent-dispatches.js +10 -2
  90. package/packages/client/dist/continuity/native-agent-store.js +69 -1
  91. package/packages/client/dist/continuity/native-agent-types.js +90 -1
  92. package/packages/client/dist/continuity/outbox.js +117 -1
  93. package/packages/client/dist/continuity/runner-bootstrap-policy.js +172 -1
  94. package/packages/client/dist/continuity/sqlite-store.js +2536 -81
  95. package/packages/client/dist/effects/invoke-effect-gateways.js +62 -1
  96. package/packages/client/dist/errors/error-messages.js +228 -2
  97. package/packages/client/dist/errors/frontmatter-diagnostics.js +125 -1
  98. package/packages/client/dist/evidence/collector.js +347 -1
  99. package/packages/client/dist/evidence/index.js +1 -1
  100. package/packages/client/dist/evidence/types.js +2 -0
  101. package/packages/client/dist/fs/atomic-state-replace.js +152 -1
  102. package/packages/client/dist/generated/command-registry.generated.js +4076 -1
  103. package/packages/client/dist/generated/public-projections.generated.js +149 -1
  104. package/packages/client/dist/git/direct-yolo-c01-retry.js +138 -4
  105. package/packages/client/dist/git/direct-yolo-checkpoint.js +1234 -4
  106. package/packages/client/dist/git/git-lifecycle-step-ids.js +14 -1
  107. package/packages/client/dist/git/git-lifecycle-store.js +1938 -9
  108. package/packages/client/dist/git/legacy-story-branch-checkpoint.js +259 -9
  109. package/packages/client/dist/git/legacy-story-branch-setup.js +348 -4
  110. package/packages/client/dist/git/legacy-story-pr.js +3538 -70
  111. package/packages/client/dist/git/secure-filesystem-boundary.js +182 -5
  112. package/packages/client/dist/graph-retrieval/pre-command-hook.js +284 -1
  113. package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.js +237 -1
  114. package/packages/client/dist/i18n/first-run.js +60 -2
  115. package/packages/client/dist/index.js +47 -1
  116. package/packages/client/dist/invocation/invoke-input.js +24 -1
  117. package/packages/client/dist/license/index.js +5 -1
  118. package/packages/client/dist/license/license-client.js +304 -1
  119. package/packages/client/dist/machine/fingerprint.js +163 -2
  120. package/packages/client/dist/machine/index.js +5 -1
  121. package/packages/client/dist/memory/project-memory-path-scope.js +62 -1
  122. package/packages/client/dist/memory/project-memory-writer.js +1007 -40
  123. package/packages/client/dist/memory/shared-project-memory-types.js +253 -2
  124. package/packages/client/dist/migrations/project-identity-capability.js +50 -1
  125. package/packages/client/dist/migrations/project-identity.js +493 -7
  126. package/packages/client/dist/migrations/state-json.js +344 -4
  127. package/packages/client/dist/policy/architecture-policy.js +184 -2
  128. package/packages/client/dist/policy/index.js +7 -1
  129. package/packages/client/dist/policy/shared-policy-types.js +38 -0
  130. package/packages/client/dist/policy/subagent-approval-policy.js +55 -1
  131. package/packages/client/dist/private-execution/clean-baseline.js +279 -2
  132. package/packages/client/dist/private-execution/codex-executor.js +574 -4
  133. package/packages/client/dist/private-execution/codex-host-runtime.js +137 -1
  134. package/packages/client/dist/private-execution/codex-lifecycle-guard.js +97 -1
  135. package/packages/client/dist/private-execution/codex-scoped-permissions.js +128 -1
  136. package/packages/client/dist/private-execution/delivery.js +410 -13
  137. package/packages/client/dist/private-execution/diagnosis-root-review.js +294 -2
  138. package/packages/client/dist/private-execution/frozen-handoff.js +19 -6
  139. package/packages/client/dist/private-execution/implementation-validation.js +106 -2
  140. package/packages/client/dist/private-execution/isolated-admission.js +1432 -23
  141. package/packages/client/dist/private-execution/isolated-session.js +725 -5
  142. package/packages/client/dist/private-execution/isolated-workspace.js +122 -1
  143. package/packages/client/dist/private-execution/pact-consumer-runtime.js +409 -3
  144. package/packages/client/dist/private-execution/pact-test-source.js +258 -1
  145. package/packages/client/dist/private-execution/pact-toolchain.js +290 -3
  146. package/packages/client/dist/private-execution/pact-write-set.js +172 -1
  147. package/packages/client/dist/private-execution/planning-diagnosis-checkpoint.js +406 -5
  148. package/packages/client/dist/private-execution/planning-generation-checkpoint.js +462 -5
  149. package/packages/client/dist/private-execution/planning-memory-checkpoint.js +139 -3
  150. package/packages/client/dist/private-execution/planning-research-checkpoint.js +325 -4
  151. package/packages/client/dist/private-execution/private-report-store.js +42 -1
  152. package/packages/client/dist/private-execution/property-test-candidate.js +103 -1
  153. package/packages/client/dist/private-execution/property-test-choices.js +147 -3
  154. package/packages/client/dist/private-execution/property-test-plan.js +271 -7
  155. package/packages/client/dist/private-execution/property-test-review.js +258 -4
  156. package/packages/client/dist/private-execution/property-test-runtime.js +372 -9
  157. package/packages/client/dist/private-execution/property-test-source.js +139 -1
  158. package/packages/client/dist/private-execution/root-checkpoint.js +80 -1
  159. package/packages/client/dist/private-execution/root-memory-git-evidence.js +135 -3
  160. package/packages/client/dist/private-execution/root-memory-recovery.js +93 -1
  161. package/packages/client/dist/private-execution/root-memory-request.js +29 -1
  162. package/packages/client/dist/private-execution/root-memory-scope.js +178 -1
  163. package/packages/client/dist/private-execution/root-memory-writer.js +102 -1
  164. package/packages/client/dist/private-execution/session-lease.js +63 -1
  165. package/packages/client/dist/private-execution/shared-private-admission-types.js +50 -1
  166. package/packages/client/dist/private-execution/shared-project-validation.js +66 -1
  167. package/packages/client/dist/private-execution/shared-root-memory-types.js +61 -1
  168. package/packages/client/dist/private-execution/ux-source-validation.js +372 -1
  169. package/packages/client/dist/private-execution/ux-write-set.js +191 -2
  170. package/packages/client/dist/resilience/circuit-breaker.js +170 -1
  171. package/packages/client/dist/resilience/degradation-manager.js +164 -1
  172. package/packages/client/dist/resilience/freshness-indicator.js +100 -1
  173. package/packages/client/dist/resilience/index.js +8 -1
  174. package/packages/client/dist/resilience/recovery-detector.js +74 -1
  175. package/packages/client/dist/resolvers/asset-resolver.js +13 -0
  176. package/packages/client/dist/resolvers/local-resolver.js +255 -8
  177. package/packages/client/dist/resolvers/remote-resolver.js +233 -1
  178. package/packages/client/dist/runner/binary.js +404 -1
  179. package/packages/client/dist/runner/cli.js +1571 -17
  180. package/packages/client/dist/runner/headless/adapters.js +49 -1
  181. package/packages/client/dist/runner/headless/claude-code-adapter.js +79 -1
  182. package/packages/client/dist/runner/headless/continuous-story-workspace.js +1628 -11
  183. package/packages/client/dist/runner/headless/epic-git-reconciliation-inventory.js +69 -1
  184. package/packages/client/dist/runner/headless/epic-merge-candidate-qa.js +110 -2
  185. package/packages/client/dist/runner/headless/epic-terminal-git-cli-adapter.js +1236 -8
  186. package/packages/client/dist/runner/headless/epic-terminal-git-runner.js +318 -2
  187. package/packages/client/dist/runner/headless/fake-adapter.js +62 -1
  188. package/packages/client/dist/runner/headless/managed-profile.js +132 -1
  189. package/packages/client/dist/runner/headless/opencode-adapter.js +145 -2
  190. package/packages/client/dist/runner/headless/prepared-story-bundle.js +43 -1
  191. package/packages/client/dist/runner/headless/resolver.js +231 -1
  192. package/packages/client/dist/runner/headless/run-yolo.js +885 -1
  193. package/packages/client/dist/runner/headless/run-yoloop.js +2574 -2
  194. package/packages/client/dist/runner/headless/types.js +574 -2
  195. package/packages/client/dist/runner/local-console.js +396 -13
  196. package/packages/client/dist/runner/portal-sync-worker.js +1487 -1
  197. package/packages/client/dist/runner/project-identity.js +106 -1
  198. package/packages/client/dist/runner/scheduler.js +995 -7
  199. package/packages/client/dist/runner-cli.js +18 -2
  200. package/packages/client/dist/state/invocation-shape.js +13 -1
  201. package/packages/client/dist/state/project-state-snapshot.js +1677 -1
  202. package/packages/client/dist/state/state-json-repair.js +785 -3
  203. package/packages/client/dist/state/structural-dag-projection.js +118 -1
  204. package/packages/client/dist/telemetry/index.js +5 -1
  205. package/packages/client/dist/telemetry/offline-queue.js +131 -1
  206. package/packages/client/dist/tier/index.js +5 -1
  207. package/packages/client/dist/tier/tier-aware-client.js +405 -1
  208. package/packages/client/dist/types/index.js +38 -1
  209. package/packages/client/dist/version.js +27 -1
  210. package/packages/client/dist/yolo/change-evidence-collector.js +126 -1
  211. package/packages/client/dist/yolo/invoke-envelope-capability.js +62 -1
  212. package/packages/client/dist/yolo/spec-envelope-collector.js +185 -5
  213. package/packages/client/dist/yoloop/discovery-hook.js +300 -2
  214. package/packages/client/dist/yoloop/index.js +8 -1
  215. package/packages/client/dist/yoloop/invoke-hooks.js +669 -12
  216. package/packages/client/dist/yoloop/shared-discover-epics.js +1007 -1
  217. package/packages/client/dist/yoloop/shared-yoloop-types.js +33 -1
  218. package/packages/client/dist/yoloop/target-normalization.js +180 -1
  219. package/packages/client/dist/yoloop/yoloop-client-state-store.js +1723 -1
  220. package/targets-stubs/antigravity/gemini.md +1 -1
  221. package/targets-stubs/antigravity/skill/SKILL.md +1 -1
  222. package/targets-stubs/claude-code/neocortex-root.agent.yaml +1 -1
  223. package/targets-stubs/claude-code/neocortex-root.md +2 -2
  224. package/targets-stubs/claude-code/neocortex.agent.yaml +1 -1
  225. package/targets-stubs/claude-code/neocortex.md +2 -2
  226. package/targets-stubs/codex/AGENTS.md +1 -1
  227. package/targets-stubs/cursor/agent.md +2 -2
  228. package/targets-stubs/gemini-cli/agent.md +2 -2
  229. package/targets-stubs/opencode/neocortex-root.md +1 -1
  230. package/targets-stubs/vscode/neocortex.agent.md +2 -2
@@ -1,2 +1,318 @@
1
- import{createHash as G}from"node:crypto";import{EPIC_TERMINAL_GIT_REASON_CODES as x,classifyGitReconciliationCandidate as w,validateEpicTerminalGitDirective as N}from"../../../../shared/dist/yoloop/epic-terminal-git.js";import{p205TransientAuthorityMatchesAggregate as q}from"../../git/git-lifecycle-store.js";import{verifiedEpicMergeCandidateReceipt as _}from"./epic-merge-candidate-qa.js";async function O(e,o,t){const c=await o.inspectReconciliation(e);if(!c.ok)return{ok:!1,reconciliationReceipts:[],preservedDecisions:[],reasonCodes:[c.reasonCode],publicSafe:!0};const a=await E({idempotencyKey:e.idempotencyKey,enabled:!0,dryRun:e.dryRun},c.candidates,o,t),l=await o.persistReconciliation({epicId:e.epicId,reconciliationReceipts:a.receipts,preservedDecisions:a.preserved}),h=R([...a.reasonCodes,...l.ok?[]:[l.reasonCode]]);return{ok:a.ok&&l.ok,reconciliationReceipts:a.receipts,preservedDecisions:a.preserved,reasonCodes:h,publicSafe:!0}}async function T(e,o,t,c){const a=t();if(!o.prepareLifecycleEvidence)return m(e,{ok:!1,reasonCode:"epic-aggregate-qa-producer-required",retryEligible:!1,externalPolicy:!1},a);const l=c?{ok:!0,originBindingCaptured:!1,aggregateQaRecorded:!0,p205Authority:c}:await o.prepareLifecycleEvidence({epicId:e.epicId,nowIso:a});if(!l.ok)return m(e,l,a);if(!l.p205Authority)return m(e,{ok:!1,reasonCode:"epic-aggregate-qa-authority-required",retryEligible:!1,externalPolicy:!1},a);const h=await o.inspect(e);if(!h.ok)return m(e,h,a);const r=h.snapshot;if(!q(l.p205Authority,r.executionHeadSha,e.graphRevision))return m(e,{ok:!1,reasonCode:"epic-aggregate-qa-authority-binding-mismatch",retryEligible:!1,externalPolicy:!1},a);const p=N(e,{...r,nowIso:a});if(!p.ready)return y(!1,f(e,r,a,{strategy:e.strategy==="single_pr"?"single_pr":"direct",physicalStatus:"blocked_local_or_repo",retryEligible:p.reasonCodes.some(n=>n.endsWith("mismatch")||n.endsWith("active")),reasonCodes:p.reasonCodes}),[],[],p.reasonCodes);if(p.reasonCodes.includes(x.ALREADY_COMPLETE)&&r.existingReceipt){const n=await o.verifyTerminalReceipt(e,r.existingReceipt,a);if(!n.ok)return y(!1,r.existingReceipt,[],[],[n.reasonCode]);const k=_(n.candidateAuthority,{mergeSha:r.existingReceipt.mergeSha,originHeadSha:r.existingReceipt.baseSha,executionHeadSha:r.existingReceipt.executionHeadSha,graphRevision:e.graphRevision});if(!k)return y(!1,r.existingReceipt,[],[],["epic-merge-candidate-authority-required"]);const B={...r.existingReceipt,candidateQa:k,...n.providerGuard?{providerGuard:n.providerGuard}:{}},S=await E({idempotencyKey:e.idempotencyKey,enabled:e.reconcile.enabled,dryRun:e.reconcile.dryRun},r.reconciliationCandidates,o,t),b=await o.persist({terminalReceipt:B,reconciliationReceipts:S.receipts,preservedDecisions:S.preserved}),A=R([...p.reasonCodes,...S.reasonCodes,...b.ok?[]:[b.reasonCode]]);return y(b.ok&&S.ok,B,S.receipts,S.preserved,A)}let i;const s=await o.prepareMergeObject({originBranch:e.originBranch,executionBranch:e.executionBranch,originHeadSha:r.originHeadSha,executionHeadSha:r.executionHeadSha,graphRevision:e.graphRevision,nowIso:a,message:[`merge(${e.epicId}): integrate ${e.executionBranch} into ${e.originBranch}`,"",`Neocortex-Epic: ${e.epicId}`,`Neocortex-Origin-Branch: ${e.originBranch}`,`Neocortex-Execution-Branch: ${e.executionBranch}`,`Neocortex-Execution-Head: ${r.executionHeadSha}`,`Neocortex-Origin-Base: ${r.originHeadSha}`,`Neocortex-Graph-Revision: ${e.graphRevision}`,`Neocortex-Aggregate-QA: ${e.localGates.aggregateQaReceipt.receiptRef}`,`Neocortex-Idempotency: ${e.idempotencyKey}`].join(`
2
- `)});if(!s.ok)return i=f(e,r,a,{strategy:"direct",physicalStatus:"blocked_local_or_repo",retryEligible:s.retryEligible,reasonCodes:[s.reasonCode]}),await o.persist({terminalReceipt:i,reconciliationReceipts:[],preservedDecisions:[]}),y(!1,i,[],[],i.reasonCodes);const d=_(s.candidateAuthority,{originHeadSha:r.originHeadSha,executionHeadSha:r.executionHeadSha,mergeSha:s.mergeSha,graphRevision:e.graphRevision});if(!d)return m(e,{ok:!1,reasonCode:"epic-merge-candidate-authority-required",retryEligible:!1,externalPolicy:!1},a);if(e.strategy!=="single_pr"){const n=await o.pushMergeObject({epicId:e.epicId,originBranch:e.originBranch,executionBranch:e.executionBranch,executionHeadSha:r.executionHeadSha,expectedOriginSha:r.originHeadSha,mergeSha:s.mergeSha,graphRevision:e.graphRevision,candidateAuthority:s.candidateAuthority,storyCheckpointIds:e.storyCheckpointIds,aggregateQaReceipt:e.localGates.aggregateQaReceipt,nowIso:t()});n.ok?i=f(e,r,a,{strategy:"direct",mergeSha:s.mergeSha,pushedSha:n.pushedSha,candidateQa:d,physicalStatus:"pushed",retryEligible:!1,reasonCodes:[x.READY],completedAt:t()}):e.strategy==="direct_or_single_pr"&&n.externalPolicy?i=await I(e,r,o,a,t,d,s.candidateAuthority):i=f(e,r,a,{strategy:"direct",mergeSha:s.mergeSha,physicalStatus:n.externalPolicy?"denied_external_gate":"blocked_local_or_repo",retryEligible:n.retryEligible,reasonCodes:[n.reasonCode,...n.retryEligible?[x.RETRY_ELIGIBLE]:[]]})}else i=await I(e,r,o,a,t,d,s.candidateAuthority);const u=i.physicalStatus==="pushed"?await o.verifyTerminalReceipt(e,i,t()):null;if(u&&!u.ok){const n=f(e,r,a,{...i,physicalStatus:"blocked_local_or_repo",retryEligible:u.retryEligible,reasonCodes:[u.reasonCode]});return await o.persist({terminalReceipt:n,reconciliationReceipts:[],preservedDecisions:[]}),y(!1,n,[],[],n.reasonCodes)}if(u?.ok){const n=_(u.candidateAuthority,{mergeSha:i.mergeSha,originHeadSha:i.baseSha,executionHeadSha:i.executionHeadSha,graphRevision:e.graphRevision});if(!n)return y(!1,i,[],[],["epic-merge-candidate-authority-required"]);i={...i,candidateQa:n,...u.providerGuard?{providerGuard:u.providerGuard}:{}}}const g=i.physicalStatus==="pushed"?await E({idempotencyKey:e.idempotencyKey,enabled:e.reconcile.enabled,dryRun:e.reconcile.dryRun},r.reconciliationCandidates,o,t):{ok:!0,receipts:[],preserved:[],reasonCodes:[]},C=await o.persist({terminalReceipt:i,reconciliationReceipts:g.receipts,preservedDecisions:g.preserved}),H=R([...i.reasonCodes,...g.reasonCodes,...C.ok?[]:[C.reasonCode]]);return y(i.physicalStatus==="pushed"&&g.ok&&C.ok,i,g.receipts,g.preserved,H)}async function I(e,o,t,c,a,l,h){const r=await t.ensureSingleEpicPullRequest({epicId:e.epicId,originBranch:e.originBranch,executionBranch:e.executionBranch,expectedStoryHeadSha:o.executionHeadSha,expectedPullRequestHeadSha:l.mergeSha,candidateQa:l,candidateAuthority:h,idempotencyKey:e.idempotencyKey});if(!r.ok)return f(e,o,c,{strategy:"single_pr",physicalStatus:r.externalPolicy?"denied_external_gate":"blocked_local_or_repo",retryEligible:r.retryEligible,reasonCodes:[r.reasonCode]});const p=await t.mergeEpicPullRequest({prNumber:r.prNumber,originBranch:e.originBranch,executionBranch:e.executionBranch,expectedStoryHeadSha:o.executionHeadSha,expectedPullRequestHeadSha:l.mergeSha,expectedOriginHeadSha:o.originHeadSha,candidateQa:l,candidateAuthority:h,nowIso:a()});return p.ok?f(e,o,c,{strategy:"single_pr",prNumber:r.prNumber,mergeSha:p.mergeSha,pushedSha:p.pushedSha,candidateQa:l,providerGuard:p.providerGuard,physicalStatus:"pushed",retryEligible:!1,reasonCodes:[x.READY],completedAt:a()}):f(e,o,c,{strategy:"single_pr",prNumber:r.prNumber,physicalStatus:p.externalPolicy?"denied_external_gate":"blocked_local_or_repo",retryEligible:p.retryEligible,reasonCodes:[p.reasonCode,...p.retryEligible?[x.RETRY_ELIGIBLE]:[]]})}async function E(e,o,t,c){if(!e.enabled)return{ok:!0,receipts:[],preserved:[],reasonCodes:[]};const a=[],l=[],h=[];let r=!0;const p=new Set,i={pull_request:0,local_branch:1,remote_branch:2};for(const s of[...o].sort((d,u)=>i[d.kind]-i[u.kind]||d.resourceId.localeCompare(u.resourceId))){const d=w(s);if(h.push(...d.reasonCodes),d.action==="preserve"){l.push(d);continue}if(s.kind!=="pull_request"&&p.has(s.branchName)){l.push({...d,action:"preserve",reasonCodes:["git-resource-related-pr-close-pending"]}),h.push("git-resource-related-pr-close-pending");continue}const u=`reconciliation:v2:${G("sha256").update([s.resourceId,d.action].join("\0")).digest("hex")}`,g=await t.applyReconciliation(s,d,e.dryRun);if(!g.ok){r=!1,s.kind==="pull_request"&&p.add(s.branchName),h.push(g.reasonCode),a.push({schemaVersion:1,resourceId:s.resourceId,action:d.action,outcome:"failed",idempotencyKey:u,reasonCodes:[g.reasonCode],recordedAt:c(),publicSafe:!0});continue}a.push({schemaVersion:1,resourceId:s.resourceId,action:d.action,outcome:g.outcome,idempotencyKey:u,reasonCodes:d.reasonCodes,recordedAt:c(),publicSafe:!0})}return{ok:r,receipts:a,preserved:l,reasonCodes:R(h)}}function f(e,o,t,c){return Object.freeze({schemaVersion:1,epicId:e.epicId,executionBranch:e.executionBranch,originBranch:e.originBranch,baseSha:o.originHeadSha,executionHeadSha:o.executionHeadSha,localGateReceiptRefs:e.localGates.receiptRefs,idempotencyKey:e.idempotencyKey,attemptStartedAt:t,publicSafe:!0,...c})}function m(e,o,t){const c="0".repeat(40),a={schemaVersion:1,epicId:e.epicId,executionBranch:e.executionBranch,originBranch:e.originBranch,baseSha:c,executionHeadSha:e.expectedExecutionHeadSha,strategy:e.strategy==="single_pr"?"single_pr":"direct",physicalStatus:o.externalPolicy?"denied_external_gate":"blocked_local_or_repo",localGateReceiptRefs:e.localGates.receiptRefs,idempotencyKey:e.idempotencyKey,attemptStartedAt:t,retryEligible:o.retryEligible,reasonCodes:[o.reasonCode],publicSafe:!0};return y(!1,a,[],[],a.reasonCodes)}function y(e,o,t,c,a){return{ok:e,receipt:o,reconciliationReceipts:t,preservedDecisions:c,reasonCodes:R(a),publicSafe:!0}}function R(e){return[...new Set(e)]}export{O as executeEpicGitReconciliation,T as executeEpicTerminalGit};
1
+ /**
2
+ * Root-owned terminal epic Git executor. Effects are adapter-injected so tests
3
+ * never mutate real refs or provider resources.
4
+ */
5
+ import { createHash } from 'node:crypto';
6
+ import { EPIC_TERMINAL_GIT_REASON_CODES, classifyGitReconciliationCandidate, validateEpicTerminalGitDirective, } from '../../../../shared/dist/yoloop/epic-terminal-git.js';
7
+ import { p205TransientAuthorityMatchesAggregate, } from '../../git/git-lifecycle-store.js';
8
+ import { verifiedEpicMergeCandidateReceipt, } from './epic-merge-candidate-qa.js';
9
+ /** Run the same fail-closed reconciler at start/resume or explicit audit. */
10
+ export async function executeEpicGitReconciliation(directive, adapter, now) {
11
+ const inspected = await adapter.inspectReconciliation(directive);
12
+ if (!inspected.ok) {
13
+ return { ok: false, reconciliationReceipts: [], preservedDecisions: [], reasonCodes: [inspected.reasonCode], publicSafe: true };
14
+ }
15
+ const reconciliation = await reconcileCandidates({
16
+ idempotencyKey: directive.idempotencyKey,
17
+ enabled: true,
18
+ dryRun: directive.dryRun,
19
+ }, inspected.candidates, adapter, now);
20
+ const persisted = await adapter.persistReconciliation({
21
+ epicId: directive.epicId,
22
+ reconciliationReceipts: reconciliation.receipts,
23
+ preservedDecisions: reconciliation.preserved,
24
+ });
25
+ const reasonCodes = unique([...reconciliation.reasonCodes, ...(persisted.ok ? [] : [persisted.reasonCode])]);
26
+ return {
27
+ ok: reconciliation.ok && persisted.ok,
28
+ reconciliationReceipts: reconciliation.receipts,
29
+ preservedDecisions: reconciliation.preserved,
30
+ reasonCodes,
31
+ publicSafe: true,
32
+ };
33
+ }
34
+ export async function executeEpicTerminalGit(directive, adapter, now, preparedAuthority) {
35
+ const startedAt = now();
36
+ if (!adapter.prepareLifecycleEvidence) {
37
+ return failedBeforeSnapshot(directive, {
38
+ ok: false, reasonCode: 'epic-aggregate-qa-producer-required', retryEligible: false, externalPolicy: false,
39
+ }, startedAt);
40
+ }
41
+ const produced = preparedAuthority
42
+ ? { ok: true, originBindingCaptured: false, aggregateQaRecorded: true, p205Authority: preparedAuthority }
43
+ : await adapter.prepareLifecycleEvidence({ epicId: directive.epicId, nowIso: startedAt });
44
+ if (!produced.ok)
45
+ return failedBeforeSnapshot(directive, produced, startedAt);
46
+ if (!produced.p205Authority) {
47
+ return failedBeforeSnapshot(directive, {
48
+ ok: false, reasonCode: 'epic-aggregate-qa-authority-required', retryEligible: false, externalPolicy: false,
49
+ }, startedAt);
50
+ }
51
+ const inspected = await adapter.inspect(directive);
52
+ if (!inspected.ok)
53
+ return failedBeforeSnapshot(directive, inspected, startedAt);
54
+ const snapshot = inspected.snapshot;
55
+ if (!p205TransientAuthorityMatchesAggregate(produced.p205Authority, snapshot.executionHeadSha, directive.graphRevision)) {
56
+ return failedBeforeSnapshot(directive, {
57
+ ok: false, reasonCode: 'epic-aggregate-qa-authority-binding-mismatch', retryEligible: false, externalPolicy: false,
58
+ }, startedAt);
59
+ }
60
+ const readiness = validateEpicTerminalGitDirective(directive, { ...snapshot, nowIso: startedAt });
61
+ if (!readiness.ready) {
62
+ return terminalResult(false, baseReceipt(directive, snapshot, startedAt, {
63
+ strategy: directive.strategy === 'single_pr' ? 'single_pr' : 'direct',
64
+ physicalStatus: 'blocked_local_or_repo',
65
+ retryEligible: readiness.reasonCodes.some((code) => code.endsWith('mismatch') || code.endsWith('active')),
66
+ reasonCodes: readiness.reasonCodes,
67
+ }), [], [], readiness.reasonCodes);
68
+ }
69
+ if (readiness.reasonCodes.includes(EPIC_TERMINAL_GIT_REASON_CODES.ALREADY_COMPLETE) && snapshot.existingReceipt) {
70
+ const verified = await adapter.verifyTerminalReceipt(directive, snapshot.existingReceipt, startedAt);
71
+ if (!verified.ok)
72
+ return terminalResult(false, snapshot.existingReceipt, [], [], [verified.reasonCode]);
73
+ const candidateQa = verifiedEpicMergeCandidateReceipt(verified.candidateAuthority, {
74
+ mergeSha: snapshot.existingReceipt.mergeSha, originHeadSha: snapshot.existingReceipt.baseSha,
75
+ executionHeadSha: snapshot.existingReceipt.executionHeadSha, graphRevision: directive.graphRevision,
76
+ });
77
+ if (!candidateQa)
78
+ return terminalResult(false, snapshot.existingReceipt, [], [], ['epic-merge-candidate-authority-required']);
79
+ const verifiedReceipt = {
80
+ ...snapshot.existingReceipt, candidateQa,
81
+ ...(verified.providerGuard ? { providerGuard: verified.providerGuard } : {}),
82
+ };
83
+ const reconciliation = await reconcileCandidates({ idempotencyKey: directive.idempotencyKey, enabled: directive.reconcile.enabled, dryRun: directive.reconcile.dryRun }, snapshot.reconciliationCandidates, adapter, now);
84
+ const persisted = await adapter.persist({
85
+ terminalReceipt: verifiedReceipt,
86
+ reconciliationReceipts: reconciliation.receipts,
87
+ preservedDecisions: reconciliation.preserved,
88
+ });
89
+ const reasons = unique([...readiness.reasonCodes, ...reconciliation.reasonCodes, ...(persisted.ok ? [] : [persisted.reasonCode])]);
90
+ return terminalResult(persisted.ok && reconciliation.ok, verifiedReceipt, reconciliation.receipts, reconciliation.preserved, reasons);
91
+ }
92
+ let receipt;
93
+ const prepared = await adapter.prepareMergeObject({
94
+ originBranch: directive.originBranch,
95
+ executionBranch: directive.executionBranch,
96
+ originHeadSha: snapshot.originHeadSha,
97
+ executionHeadSha: snapshot.executionHeadSha,
98
+ graphRevision: directive.graphRevision,
99
+ nowIso: startedAt,
100
+ message: [
101
+ `merge(${directive.epicId}): integrate ${directive.executionBranch} into ${directive.originBranch}`,
102
+ '',
103
+ `Neocortex-Epic: ${directive.epicId}`,
104
+ `Neocortex-Origin-Branch: ${directive.originBranch}`,
105
+ `Neocortex-Execution-Branch: ${directive.executionBranch}`,
106
+ `Neocortex-Execution-Head: ${snapshot.executionHeadSha}`,
107
+ `Neocortex-Origin-Base: ${snapshot.originHeadSha}`,
108
+ `Neocortex-Graph-Revision: ${directive.graphRevision}`,
109
+ `Neocortex-Aggregate-QA: ${directive.localGates.aggregateQaReceipt.receiptRef}`,
110
+ `Neocortex-Idempotency: ${directive.idempotencyKey}`,
111
+ ].join('\n'),
112
+ });
113
+ if (!prepared.ok) {
114
+ receipt = baseReceipt(directive, snapshot, startedAt, {
115
+ strategy: 'direct',
116
+ physicalStatus: 'blocked_local_or_repo',
117
+ retryEligible: prepared.retryEligible,
118
+ reasonCodes: [prepared.reasonCode],
119
+ });
120
+ await adapter.persist({ terminalReceipt: receipt, reconciliationReceipts: [], preservedDecisions: [] });
121
+ return terminalResult(false, receipt, [], [], receipt.reasonCodes);
122
+ }
123
+ const candidateQa = verifiedEpicMergeCandidateReceipt(prepared.candidateAuthority, {
124
+ originHeadSha: snapshot.originHeadSha, executionHeadSha: snapshot.executionHeadSha,
125
+ mergeSha: prepared.mergeSha, graphRevision: directive.graphRevision,
126
+ });
127
+ if (!candidateQa)
128
+ return failedBeforeSnapshot(directive, {
129
+ ok: false, reasonCode: 'epic-merge-candidate-authority-required', retryEligible: false, externalPolicy: false,
130
+ }, startedAt);
131
+ if (directive.strategy !== 'single_pr') {
132
+ const pushed = await adapter.pushMergeObject({
133
+ epicId: directive.epicId,
134
+ originBranch: directive.originBranch,
135
+ executionBranch: directive.executionBranch,
136
+ executionHeadSha: snapshot.executionHeadSha,
137
+ expectedOriginSha: snapshot.originHeadSha,
138
+ mergeSha: prepared.mergeSha,
139
+ graphRevision: directive.graphRevision,
140
+ candidateAuthority: prepared.candidateAuthority,
141
+ storyCheckpointIds: directive.storyCheckpointIds,
142
+ aggregateQaReceipt: directive.localGates.aggregateQaReceipt,
143
+ nowIso: now(),
144
+ });
145
+ if (pushed.ok) {
146
+ receipt = baseReceipt(directive, snapshot, startedAt, {
147
+ strategy: 'direct', mergeSha: prepared.mergeSha, pushedSha: pushed.pushedSha, candidateQa,
148
+ physicalStatus: 'pushed', retryEligible: false,
149
+ reasonCodes: [EPIC_TERMINAL_GIT_REASON_CODES.READY], completedAt: now(),
150
+ });
151
+ }
152
+ else if (directive.strategy === 'direct_or_single_pr' && pushed.externalPolicy) {
153
+ receipt = await executePullRequestFallback(directive, snapshot, adapter, startedAt, now, candidateQa, prepared.candidateAuthority);
154
+ }
155
+ else {
156
+ receipt = baseReceipt(directive, snapshot, startedAt, {
157
+ strategy: 'direct', mergeSha: prepared.mergeSha,
158
+ physicalStatus: pushed.externalPolicy ? 'denied_external_gate' : 'blocked_local_or_repo',
159
+ retryEligible: pushed.retryEligible,
160
+ reasonCodes: [pushed.reasonCode, ...(pushed.retryEligible ? [EPIC_TERMINAL_GIT_REASON_CODES.RETRY_ELIGIBLE] : [])],
161
+ });
162
+ }
163
+ }
164
+ else {
165
+ receipt = await executePullRequestFallback(directive, snapshot, adapter, startedAt, now, candidateQa, prepared.candidateAuthority);
166
+ }
167
+ const verified = receipt.physicalStatus === 'pushed'
168
+ ? await adapter.verifyTerminalReceipt(directive, receipt, now())
169
+ : null;
170
+ if (verified && !verified.ok) {
171
+ const failedReceipt = baseReceipt(directive, snapshot, startedAt, {
172
+ ...receipt,
173
+ physicalStatus: 'blocked_local_or_repo',
174
+ retryEligible: verified.retryEligible,
175
+ reasonCodes: [verified.reasonCode],
176
+ });
177
+ await adapter.persist({ terminalReceipt: failedReceipt, reconciliationReceipts: [], preservedDecisions: [] });
178
+ return terminalResult(false, failedReceipt, [], [], failedReceipt.reasonCodes);
179
+ }
180
+ if (verified?.ok) {
181
+ const accepted = verifiedEpicMergeCandidateReceipt(verified.candidateAuthority, {
182
+ mergeSha: receipt.mergeSha, originHeadSha: receipt.baseSha,
183
+ executionHeadSha: receipt.executionHeadSha, graphRevision: directive.graphRevision,
184
+ });
185
+ if (!accepted)
186
+ return terminalResult(false, receipt, [], [], ['epic-merge-candidate-authority-required']);
187
+ receipt = {
188
+ ...receipt, candidateQa: accepted,
189
+ ...(verified.providerGuard ? { providerGuard: verified.providerGuard } : {}),
190
+ };
191
+ }
192
+ const reconciliation = receipt.physicalStatus === 'pushed'
193
+ ? await reconcileCandidates({ idempotencyKey: directive.idempotencyKey, enabled: directive.reconcile.enabled, dryRun: directive.reconcile.dryRun }, snapshot.reconciliationCandidates, adapter, now)
194
+ : { ok: true, receipts: [], preserved: [], reasonCodes: [] };
195
+ const persisted = await adapter.persist({
196
+ terminalReceipt: receipt,
197
+ reconciliationReceipts: reconciliation.receipts,
198
+ preservedDecisions: reconciliation.preserved,
199
+ });
200
+ const reasons = unique([...receipt.reasonCodes, ...reconciliation.reasonCodes, ...(persisted.ok ? [] : [persisted.reasonCode])]);
201
+ return terminalResult(receipt.physicalStatus === 'pushed' && reconciliation.ok && persisted.ok, receipt, reconciliation.receipts, reconciliation.preserved, reasons);
202
+ }
203
+ async function executePullRequestFallback(directive, snapshot, adapter, startedAt, now, candidateQa, candidateAuthority) {
204
+ const pr = await adapter.ensureSingleEpicPullRequest({
205
+ epicId: directive.epicId,
206
+ originBranch: directive.originBranch,
207
+ executionBranch: directive.executionBranch,
208
+ expectedStoryHeadSha: snapshot.executionHeadSha,
209
+ expectedPullRequestHeadSha: candidateQa.mergeSha,
210
+ candidateQa,
211
+ candidateAuthority,
212
+ idempotencyKey: directive.idempotencyKey,
213
+ });
214
+ if (!pr.ok)
215
+ return baseReceipt(directive, snapshot, startedAt, {
216
+ strategy: 'single_pr', physicalStatus: pr.externalPolicy ? 'denied_external_gate' : 'blocked_local_or_repo',
217
+ retryEligible: pr.retryEligible, reasonCodes: [pr.reasonCode],
218
+ });
219
+ const merged = await adapter.mergeEpicPullRequest({
220
+ prNumber: pr.prNumber,
221
+ originBranch: directive.originBranch,
222
+ executionBranch: directive.executionBranch,
223
+ expectedStoryHeadSha: snapshot.executionHeadSha,
224
+ expectedPullRequestHeadSha: candidateQa.mergeSha,
225
+ expectedOriginHeadSha: snapshot.originHeadSha,
226
+ candidateQa, candidateAuthority, nowIso: now(),
227
+ });
228
+ if (!merged.ok)
229
+ return baseReceipt(directive, snapshot, startedAt, {
230
+ strategy: 'single_pr', prNumber: pr.prNumber,
231
+ physicalStatus: merged.externalPolicy ? 'denied_external_gate' : 'blocked_local_or_repo',
232
+ retryEligible: merged.retryEligible,
233
+ reasonCodes: [merged.reasonCode, ...(merged.retryEligible ? [EPIC_TERMINAL_GIT_REASON_CODES.RETRY_ELIGIBLE] : [])],
234
+ });
235
+ return baseReceipt(directive, snapshot, startedAt, {
236
+ strategy: 'single_pr', prNumber: pr.prNumber, mergeSha: merged.mergeSha, pushedSha: merged.pushedSha, candidateQa,
237
+ providerGuard: merged.providerGuard,
238
+ physicalStatus: 'pushed', retryEligible: false,
239
+ reasonCodes: [EPIC_TERMINAL_GIT_REASON_CODES.READY], completedAt: now(),
240
+ });
241
+ }
242
+ async function reconcileCandidates(directive, candidates, adapter, now) {
243
+ if (!directive.enabled)
244
+ return { ok: true, receipts: [], preserved: [], reasonCodes: [] };
245
+ const receipts = [];
246
+ const preserved = [];
247
+ const reasons = [];
248
+ let ok = true;
249
+ const failedPrBranches = new Set();
250
+ const order = { pull_request: 0, local_branch: 1, remote_branch: 2 };
251
+ for (const candidate of [...candidates].sort((a, b) => order[a.kind] - order[b.kind] || a.resourceId.localeCompare(b.resourceId))) {
252
+ const decision = classifyGitReconciliationCandidate(candidate);
253
+ reasons.push(...decision.reasonCodes);
254
+ if (decision.action === 'preserve') {
255
+ preserved.push(decision);
256
+ continue;
257
+ }
258
+ if (candidate.kind !== 'pull_request' && failedPrBranches.has(candidate.branchName)) {
259
+ preserved.push({ ...decision, action: 'preserve', reasonCodes: ['git-resource-related-pr-close-pending'] });
260
+ reasons.push('git-resource-related-pr-close-pending');
261
+ continue;
262
+ }
263
+ // Stable across start/resume/terminal directives; no long branch name or
264
+ // unbounded parent id can overflow the public receipt schema.
265
+ const receiptKey = `reconciliation:v2:${createHash('sha256').update([candidate.resourceId, decision.action].join('\0')).digest('hex')}`;
266
+ const applied = await adapter.applyReconciliation(candidate, decision, directive.dryRun);
267
+ if (!applied.ok) {
268
+ ok = false;
269
+ if (candidate.kind === 'pull_request')
270
+ failedPrBranches.add(candidate.branchName);
271
+ reasons.push(applied.reasonCode);
272
+ receipts.push({
273
+ schemaVersion: 1, resourceId: candidate.resourceId, action: decision.action,
274
+ outcome: 'failed', idempotencyKey: receiptKey,
275
+ reasonCodes: [applied.reasonCode], recordedAt: now(), publicSafe: true,
276
+ });
277
+ continue;
278
+ }
279
+ receipts.push({
280
+ schemaVersion: 1, resourceId: candidate.resourceId, action: decision.action,
281
+ outcome: applied.outcome, idempotencyKey: receiptKey,
282
+ reasonCodes: decision.reasonCodes, recordedAt: now(), publicSafe: true,
283
+ });
284
+ }
285
+ return { ok, receipts, preserved, reasonCodes: unique(reasons) };
286
+ }
287
+ function baseReceipt(directive, snapshot, startedAt, override) {
288
+ return Object.freeze({
289
+ schemaVersion: 1,
290
+ epicId: directive.epicId,
291
+ executionBranch: directive.executionBranch,
292
+ originBranch: directive.originBranch,
293
+ baseSha: snapshot.originHeadSha,
294
+ executionHeadSha: snapshot.executionHeadSha,
295
+ localGateReceiptRefs: directive.localGates.receiptRefs,
296
+ idempotencyKey: directive.idempotencyKey,
297
+ attemptStartedAt: startedAt,
298
+ publicSafe: true,
299
+ ...override,
300
+ });
301
+ }
302
+ function failedBeforeSnapshot(directive, failure, startedAt) {
303
+ const placeholder = '0'.repeat(40);
304
+ const receipt = {
305
+ schemaVersion: 1, epicId: directive.epicId, executionBranch: directive.executionBranch, originBranch: directive.originBranch,
306
+ baseSha: placeholder, executionHeadSha: directive.expectedExecutionHeadSha, strategy: directive.strategy === 'single_pr' ? 'single_pr' : 'direct',
307
+ physicalStatus: failure.externalPolicy ? 'denied_external_gate' : 'blocked_local_or_repo',
308
+ localGateReceiptRefs: directive.localGates.receiptRefs, idempotencyKey: directive.idempotencyKey,
309
+ attemptStartedAt: startedAt, retryEligible: failure.retryEligible, reasonCodes: [failure.reasonCode], publicSafe: true,
310
+ };
311
+ return terminalResult(false, receipt, [], [], receipt.reasonCodes);
312
+ }
313
+ function terminalResult(ok, receipt, reconciliationReceipts, preservedDecisions, reasonCodes) {
314
+ return { ok, receipt, reconciliationReceipts, preservedDecisions, reasonCodes: unique(reasonCodes), publicSafe: true };
315
+ }
316
+ function unique(values) {
317
+ return [...new Set(values)];
318
+ }
@@ -1 +1,62 @@
1
- import{HEADLESS_REASON_CODES as i,adapterAvailabilitySuccess as u,createRejectedExecutionResult as s,hashPublicValue as n,redaction as d,renderHeadlessPrompt as c,validateHeadlessAdapterExecutionInput as p}from"./types.js";function m(t="fake"){return{id:t,displayName:t==="test"?"Headless Test Adapter":"Headless Fake Adapter",async checkAvailability(){return u(t,"neocortex-headless-fake","Fake headless adapter is available for deterministic tests.")},buildInvocation(r){const a=p(r,t);return a.ok?{ok:!0,invocation:{adapterId:t,commandName:"neocortex-headless-fake",args:[a.input.promptKind,a.input.targetRef],promptHash:a.promptHash,...a.input.modelId?{modelId:a.input.modelId}:{},timeoutMs:a.input.timeoutMs??600*1e3,publicSafe:!0},publicSafe:!0}:a},async execute(r,a){const e=p(r,t);if(!e.ok)return s(t,t,e);const o=c(e.input);return{status:"completed",adapterId:t,runtimeId:t,...e.input.modelId?{modelId:e.input.modelId}:{},...e.input.runtimeSource?{runtimeSource:e.input.runtimeSource}:{},reasonCode:i.EXECUTION_COMPLETED,reasonCodes:[i.EXECUTION_COMPLETED,i.RECEIPT_REDACTED],exitCode:0,signal:null,durationMs:0,counts:{prompts:1,syntheticRuns:1},hashes:{prompt:n(o),receipt:n(`${t}:${e.input.targetRef}:${e.input.modelId??""}`)},publicSummary:"Fake headless adapter completed deterministic public-safe execution.",redactionSummary:[d("prompt","prompt_body",n(o))],relativePaths:[e.input.targetRef],...e.input.receipt?{receipt:e.input.receipt}:{},publicSafe:!0}}}}export{m as createFakeHeadlessAdapter};
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * P190.04 -- deterministic fake headless adapter for tests.
6
+ */
7
+ import { HEADLESS_REASON_CODES, adapterAvailabilitySuccess, createRejectedExecutionResult, hashPublicValue, redaction, renderHeadlessPrompt, validateHeadlessAdapterExecutionInput, } from './types.js';
8
+ export function createFakeHeadlessAdapter(id = 'fake') {
9
+ return {
10
+ id,
11
+ displayName: id === 'test' ? 'Headless Test Adapter' : 'Headless Fake Adapter',
12
+ async checkAvailability() {
13
+ return adapterAvailabilitySuccess(id, 'neocortex-headless-fake', 'Fake headless adapter is available for deterministic tests.');
14
+ },
15
+ buildInvocation(input) {
16
+ const validation = validateHeadlessAdapterExecutionInput(input, id);
17
+ if (!validation.ok)
18
+ return validation;
19
+ return {
20
+ ok: true,
21
+ invocation: {
22
+ adapterId: id,
23
+ commandName: 'neocortex-headless-fake',
24
+ args: [validation.input.promptKind, validation.input.targetRef],
25
+ promptHash: validation.promptHash,
26
+ ...(validation.input.modelId ? { modelId: validation.input.modelId } : {}),
27
+ timeoutMs: validation.input.timeoutMs ?? 10 * 60 * 1000,
28
+ publicSafe: true,
29
+ },
30
+ publicSafe: true,
31
+ };
32
+ },
33
+ async execute(input, _options) {
34
+ const validation = validateHeadlessAdapterExecutionInput(input, id);
35
+ if (!validation.ok)
36
+ return createRejectedExecutionResult(id, id, validation);
37
+ const prompt = renderHeadlessPrompt(validation.input);
38
+ return {
39
+ status: 'completed',
40
+ adapterId: id,
41
+ runtimeId: id,
42
+ ...(validation.input.modelId ? { modelId: validation.input.modelId } : {}),
43
+ ...(validation.input.runtimeSource ? { runtimeSource: validation.input.runtimeSource } : {}),
44
+ reasonCode: HEADLESS_REASON_CODES.EXECUTION_COMPLETED,
45
+ reasonCodes: [HEADLESS_REASON_CODES.EXECUTION_COMPLETED, HEADLESS_REASON_CODES.RECEIPT_REDACTED],
46
+ exitCode: 0,
47
+ signal: null,
48
+ durationMs: 0,
49
+ counts: { prompts: 1, syntheticRuns: 1 },
50
+ hashes: {
51
+ prompt: hashPublicValue(prompt),
52
+ receipt: hashPublicValue(`${id}:${validation.input.targetRef}:${validation.input.modelId ?? ''}`),
53
+ },
54
+ publicSummary: 'Fake headless adapter completed deterministic public-safe execution.',
55
+ redactionSummary: [redaction('prompt', 'prompt_body', hashPublicValue(prompt))],
56
+ relativePaths: [validation.input.targetRef],
57
+ ...(validation.input.receipt ? { receipt: validation.input.receipt } : {}),
58
+ publicSafe: true,
59
+ };
60
+ },
61
+ };
62
+ }
@@ -1 +1,132 @@
1
- import{lstatSync as E,readFileSync as g}from"node:fs";import{homedir as p}from"node:os";import{join as t}from"node:path";import{getSubagentApprovalPolicy as h}from"../../config.js";import{HEADLESS_REASON_CODES as i,boundPublicSummary as l,hashPublicValue as f,redaction as v}from"./types.js";const s="[P201-EV-HEADLESS]",m=96*1024;function M(o,e){const r=P(o,e);for(const n of r){let a;try{a=E(n)}catch(u){if(u.code==="ENOENT")continue;return d()}if(a.isSymbolicLink()||!a.isFile()||a.size<=0||a.size>m)return d();try{const u=g(n,"utf8");return y(o,u)?b(o,e):d()}catch{return d()}}return c(i.MANAGED_PROFILE_MISSING,"Managed neocortex profile was not found in a trusted host location.")}function C(o,e,r){return{status:"failed",adapterId:o,runtimeId:e.runtimeId,...e.modelId?{modelId:e.modelId}:{},...e.runtimeSource?{runtimeSource:e.runtimeSource}:{},reasonCode:r.reasonCode,reasonCodes:[r.reasonCode,i.RECEIPT_REDACTED],durationMs:0,counts:{governedPreflightDenials:1},hashes:{governanceEvidence:f(s)},publicSummary:r.publicSummary,redactionSummary:[v("managedProfile","managed_profile","value-denied")],relativePaths:[e.targetRef],...e.receipt?{receipt:e.receipt}:{},publicSafe:!0}}function D(o){return{...o,counts:{...o.counts,governedPreflightPasses:1},hashes:{...o.hashes,governanceEvidence:f(s)},publicSummary:l(`${o.publicSummary} ${s}`)}}function P(o,e){const r=[];e.cwd&&r.push(o==="claude-code"?t(e.cwd,".claude","agents","neocortex","neocortex.md"):t(e.cwd,".opencode","agents","neocortex.md"));const n=S(e.env);if(!n)return r;if(o==="claude-code")r.push(t(n,".claude","agents","neocortex","neocortex.md"));else{const a=e.env?.OPENCODE_HOME||t(e.env?.XDG_CONFIG_HOME||t(n,".config"),"opencode");r.push(t(a,"agents","neocortex.md")),r.push(t(n,".opencode","agents","neocortex.md"))}return Array.from(new Set(r))}function S(o){const e=o?o.HOME||o.USERPROFILE:p();return e&&!/[\r\n\0]/.test(e)?e:void 0}function y(o,e){return Buffer.byteLength(e)>m?!1:o==="claude-code"?/^---\r?\n[\s\S]*?^name:\s*neocortex\s*$[\s\S]*?^permissionMode:\s*bypassPermissions\s*$[\s\S]*?^disallowedTools:\s*Agent,\s*Task\s*$[\s\S]*?^---\s*$/m.test(e)&&e.includes("Child depth is bounded to one.")&&e.includes("Never pass the original root invocation"):/^---\r?\n[\s\S]*?^name:\s*neocortex\s*$[\s\S]*?^mode:\s*subagent\s*$[\s\S]*?^\s+"\*":\s*allow\s*$[\s\S]*?^\s+task:\s*deny\s*$[\s\S]*?^---\s*$/m.test(e)&&e.includes("Never pass the original root invocation")&&e.includes("root OpenCode agent remains the yoloop owner")}function b(o,e){try{const r=S(e.env),n=h({...r?{configFilePath:t(r,".neocortex","config.json")}:{},platformTarget:o,hostPolicy:e.approvalHostPolicy}).resolution;return n.requestedMode!=="max"||n.effectiveMode!=="max"?c(i.APPROVAL_POLICY_MISMATCH,"Managed max profile did not match the effective subagent approval policy."):{ok:!0,publicSafe:!0}}catch{return c(i.APPROVAL_POLICY_INVALID,"Managed subagent approval policy could not be validated safely.")}}function c(o,e){return{ok:!1,reasonCode:o,publicSummary:l(`${e} ${s}`),publicSafe:!0}}function d(){return c(i.MANAGED_PROFILE_INVALID,"Managed neocortex profile failed bounded identity, approval, or isolation validation.")}export{s as GOVERNED_HEADLESS_EVIDENCE,C as governedPreflightFailureResult,M as preflightManagedHeadlessProfile,D as withGovernedHeadlessEvidence};
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * P201.12 -- fixed-path managed profile and effective policy preflight.
6
+ */
7
+ import { lstatSync, readFileSync } from 'node:fs';
8
+ import { homedir } from 'node:os';
9
+ import { join } from 'node:path';
10
+ import { getSubagentApprovalPolicy } from '../../config.js';
11
+ import { HEADLESS_REASON_CODES, boundPublicSummary, hashPublicValue, redaction, } from './types.js';
12
+ export const GOVERNED_HEADLESS_EVIDENCE = '[P201-EV-HEADLESS]';
13
+ const MAX_PROFILE_BYTES = 96 * 1024;
14
+ export function preflightManagedHeadlessProfile(adapterId, options) {
15
+ const candidates = managedProfileCandidates(adapterId, options);
16
+ for (const candidate of candidates) {
17
+ let stat;
18
+ try {
19
+ stat = lstatSync(candidate);
20
+ }
21
+ catch (error) {
22
+ if (error.code === 'ENOENT')
23
+ continue;
24
+ return invalidProfile();
25
+ }
26
+ if (stat.isSymbolicLink() || !stat.isFile() || stat.size <= 0 || stat.size > MAX_PROFILE_BYTES) {
27
+ return invalidProfile();
28
+ }
29
+ try {
30
+ const content = readFileSync(candidate, 'utf8');
31
+ if (!isGovernedProfile(adapterId, content))
32
+ return invalidProfile();
33
+ return validateEffectiveApprovalPolicy(adapterId, options);
34
+ }
35
+ catch {
36
+ return invalidProfile();
37
+ }
38
+ }
39
+ return failure(HEADLESS_REASON_CODES.MANAGED_PROFILE_MISSING, 'Managed neocortex profile was not found in a trusted host location.');
40
+ }
41
+ export function governedPreflightFailureResult(adapterId, input, preflight) {
42
+ return {
43
+ status: 'failed',
44
+ adapterId,
45
+ runtimeId: input.runtimeId,
46
+ ...(input.modelId ? { modelId: input.modelId } : {}),
47
+ ...(input.runtimeSource ? { runtimeSource: input.runtimeSource } : {}),
48
+ reasonCode: preflight.reasonCode,
49
+ reasonCodes: [preflight.reasonCode, HEADLESS_REASON_CODES.RECEIPT_REDACTED],
50
+ durationMs: 0,
51
+ counts: { governedPreflightDenials: 1 },
52
+ hashes: { governanceEvidence: hashPublicValue(GOVERNED_HEADLESS_EVIDENCE) },
53
+ publicSummary: preflight.publicSummary,
54
+ redactionSummary: [redaction('managedProfile', 'managed_profile', 'value-denied')],
55
+ relativePaths: [input.targetRef],
56
+ ...(input.receipt ? { receipt: input.receipt } : {}),
57
+ publicSafe: true,
58
+ };
59
+ }
60
+ export function withGovernedHeadlessEvidence(result) {
61
+ return {
62
+ ...result,
63
+ counts: { ...result.counts, governedPreflightPasses: 1 },
64
+ hashes: { ...result.hashes, governanceEvidence: hashPublicValue(GOVERNED_HEADLESS_EVIDENCE) },
65
+ publicSummary: boundPublicSummary(`${result.publicSummary} ${GOVERNED_HEADLESS_EVIDENCE}`),
66
+ };
67
+ }
68
+ function managedProfileCandidates(adapterId, options) {
69
+ const candidates = [];
70
+ if (options.cwd) {
71
+ candidates.push(adapterId === 'claude-code'
72
+ ? join(options.cwd, '.claude', 'agents', 'neocortex', 'neocortex.md')
73
+ : join(options.cwd, '.opencode', 'agents', 'neocortex.md'));
74
+ }
75
+ const home = trustedHome(options.env);
76
+ if (!home)
77
+ return candidates;
78
+ if (adapterId === 'claude-code') {
79
+ candidates.push(join(home, '.claude', 'agents', 'neocortex', 'neocortex.md'));
80
+ }
81
+ else {
82
+ const configHome = options.env?.OPENCODE_HOME
83
+ || join(options.env?.XDG_CONFIG_HOME || join(home, '.config'), 'opencode');
84
+ candidates.push(join(configHome, 'agents', 'neocortex.md'));
85
+ candidates.push(join(home, '.opencode', 'agents', 'neocortex.md'));
86
+ }
87
+ return Array.from(new Set(candidates));
88
+ }
89
+ function trustedHome(env) {
90
+ const candidate = env ? env.HOME || env.USERPROFILE : homedir();
91
+ return candidate && !/[\r\n\0]/.test(candidate) ? candidate : undefined;
92
+ }
93
+ function isGovernedProfile(adapterId, content) {
94
+ if (Buffer.byteLength(content) > MAX_PROFILE_BYTES)
95
+ return false;
96
+ if (adapterId === 'claude-code') {
97
+ return /^---\r?\n[\s\S]*?^name:\s*neocortex\s*$[\s\S]*?^permissionMode:\s*bypassPermissions\s*$[\s\S]*?^disallowedTools:\s*Agent,\s*Task\s*$[\s\S]*?^---\s*$/m.test(content)
98
+ && content.includes('Child depth is bounded to one.')
99
+ && content.includes('Never pass the original root invocation');
100
+ }
101
+ return /^---\r?\n[\s\S]*?^name:\s*neocortex\s*$[\s\S]*?^mode:\s*subagent\s*$[\s\S]*?^\s+"\*":\s*allow\s*$[\s\S]*?^\s+task:\s*deny\s*$[\s\S]*?^---\s*$/m.test(content)
102
+ && content.includes('Never pass the original root invocation')
103
+ && content.includes('root OpenCode agent remains the yoloop owner');
104
+ }
105
+ function validateEffectiveApprovalPolicy(adapterId, options) {
106
+ try {
107
+ const home = trustedHome(options.env);
108
+ const resolution = getSubagentApprovalPolicy({
109
+ ...(home ? { configFilePath: join(home, '.neocortex', 'config.json') } : {}),
110
+ platformTarget: adapterId,
111
+ hostPolicy: options.approvalHostPolicy,
112
+ }).resolution;
113
+ if (resolution.requestedMode !== 'max' || resolution.effectiveMode !== 'max') {
114
+ return failure(HEADLESS_REASON_CODES.APPROVAL_POLICY_MISMATCH, 'Managed max profile did not match the effective subagent approval policy.');
115
+ }
116
+ return { ok: true, publicSafe: true };
117
+ }
118
+ catch {
119
+ return failure(HEADLESS_REASON_CODES.APPROVAL_POLICY_INVALID, 'Managed subagent approval policy could not be validated safely.');
120
+ }
121
+ }
122
+ function failure(reasonCode, summary) {
123
+ return {
124
+ ok: false,
125
+ reasonCode,
126
+ publicSummary: boundPublicSummary(`${summary} ${GOVERNED_HEADLESS_EVIDENCE}`),
127
+ publicSafe: true,
128
+ };
129
+ }
130
+ function invalidProfile() {
131
+ return failure(HEADLESS_REASON_CODES.MANAGED_PROFILE_INVALID, 'Managed neocortex profile failed bounded identity, approval, or isolation validation.');
132
+ }