martin-loop 0.1.4 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (286) hide show
  1. package/CODE_OF_CONDUCT.md +32 -0
  2. package/README.md +172 -227
  3. package/demo/seeded-workspace/README.md +35 -0
  4. package/demo/seeded-workspace/TASKS.md +29 -0
  5. package/demo/seeded-workspace/martin.config.yaml +11 -0
  6. package/demo/seeded-workspace/package.json +8 -0
  7. package/demo/seeded-workspace/src/invoice-summary.js +11 -0
  8. package/demo/seeded-workspace/test/invoice-summary.test.js +20 -0
  9. package/dist/bin/martin-loop.js +0 -0
  10. package/dist/vendor/adapters/claude-cli.d.ts +19 -4
  11. package/dist/vendor/adapters/claude-cli.js +55 -24
  12. package/dist/vendor/adapters/cli-bridge.d.ts +1 -0
  13. package/dist/vendor/adapters/cli-bridge.js +154 -28
  14. package/dist/vendor/adapters/counter.d.ts +1 -0
  15. package/dist/vendor/adapters/counter.js +4 -0
  16. package/dist/vendor/adapters/git-baseline.d.ts +50 -0
  17. package/dist/vendor/adapters/git-baseline.js +233 -0
  18. package/dist/vendor/adapters/index.d.ts +1 -0
  19. package/dist/vendor/adapters/index.js +1 -0
  20. package/dist/vendor/adapters/openrouter-adapter.d.ts +15 -0
  21. package/dist/vendor/adapters/openrouter-adapter.js +302 -0
  22. package/dist/vendor/adapters/usage.d.ts +48 -0
  23. package/dist/vendor/adapters/usage.js +66 -0
  24. package/dist/vendor/adapters/verifier-only.d.ts +7 -0
  25. package/dist/vendor/adapters/verifier-only.js +57 -0
  26. package/dist/vendor/cli/bin/exit.d.ts +12 -0
  27. package/dist/vendor/cli/bin/exit.js +28 -0
  28. package/dist/vendor/cli/commands/analyze.d.ts +5 -0
  29. package/dist/vendor/cli/commands/analyze.js +58 -0
  30. package/dist/vendor/cli/commands/audit-log-verify.d.ts +34 -0
  31. package/dist/vendor/cli/commands/audit-log-verify.js +99 -0
  32. package/dist/vendor/cli/commands/audit.d.ts +8 -0
  33. package/dist/vendor/cli/commands/audit.js +199 -0
  34. package/dist/vendor/cli/commands/corpus.d.ts +5 -0
  35. package/dist/vendor/cli/commands/corpus.js +60 -0
  36. package/dist/vendor/cli/commands/doctor.d.ts +8 -0
  37. package/dist/vendor/cli/commands/doctor.js +219 -0
  38. package/dist/vendor/cli/commands/explain.d.ts +17 -0
  39. package/dist/vendor/cli/commands/explain.js +176 -0
  40. package/dist/vendor/cli/commands/export.d.ts +5 -0
  41. package/dist/vendor/cli/commands/export.js +60 -0
  42. package/dist/vendor/cli/commands/governance.d.ts +8 -0
  43. package/dist/vendor/cli/commands/governance.js +95 -0
  44. package/dist/vendor/cli/commands/improve.d.ts +18 -0
  45. package/dist/vendor/cli/commands/improve.js +396 -0
  46. package/dist/vendor/cli/commands/init.d.ts +8 -0
  47. package/dist/vendor/cli/commands/init.js +281 -0
  48. package/dist/vendor/cli/commands/migration.d.ts +8 -0
  49. package/dist/vendor/cli/commands/migration.js +67 -0
  50. package/dist/vendor/cli/commands/prior.d.ts +23 -0
  51. package/dist/vendor/cli/commands/prior.js +145 -0
  52. package/dist/vendor/cli/commands/resume.d.ts +21 -0
  53. package/dist/vendor/cli/commands/resume.js +73 -0
  54. package/dist/vendor/cli/commands/verify.d.ts +6 -0
  55. package/dist/vendor/cli/commands/verify.js +43 -0
  56. package/dist/vendor/cli/index.d.ts +6 -1
  57. package/dist/vendor/cli/index.js +124 -7
  58. package/dist/vendor/cli/research/public-corpus.d.ts +43 -0
  59. package/dist/vendor/cli/research/public-corpus.js +151 -0
  60. package/dist/vendor/cli/ui/error-card.d.ts +38 -0
  61. package/dist/vendor/cli/ui/error-card.js +103 -0
  62. package/dist/vendor/cli/ui/mission-brief.d.ts +41 -0
  63. package/dist/vendor/cli/ui/mission-brief.js +173 -0
  64. package/dist/vendor/cli/ui/summary-card.d.ts +34 -0
  65. package/dist/vendor/cli/ui/summary-card.js +102 -0
  66. package/dist/vendor/contracts/audit.d.ts +46 -0
  67. package/dist/vendor/contracts/audit.js +360 -0
  68. package/dist/vendor/contracts/index.d.ts +3 -1
  69. package/dist/vendor/contracts/post-phase15.d.ts +240 -0
  70. package/dist/vendor/contracts/post-phase15.js +166 -0
  71. package/dist/vendor/core/agent/mandates.d.ts +46 -0
  72. package/dist/vendor/core/agent/mandates.js +178 -0
  73. package/dist/vendor/core/agent/receipts.d.ts +38 -0
  74. package/dist/vendor/core/agent/receipts.js +131 -0
  75. package/dist/vendor/core/agent/signing.d.ts +17 -0
  76. package/dist/vendor/core/agent/signing.js +91 -0
  77. package/dist/vendor/core/attestation/sign.d.ts +25 -0
  78. package/dist/vendor/core/attestation/sign.js +216 -0
  79. package/dist/vendor/core/autonomy/autonomous-promotion.d.ts +120 -0
  80. package/dist/vendor/core/autonomy/autonomous-promotion.js +346 -0
  81. package/dist/vendor/core/autonomy/envelope-v2.d.ts +29 -0
  82. package/dist/vendor/core/autonomy/envelope-v2.js +60 -0
  83. package/dist/vendor/core/autonomy/envelope.d.ts +17 -0
  84. package/dist/vendor/core/autonomy/envelope.js +27 -0
  85. package/dist/vendor/core/autonomy/escalation-ledger.d.ts +20 -0
  86. package/dist/vendor/core/autonomy/escalation-ledger.js +18 -0
  87. package/dist/vendor/core/autonomy/resume.d.ts +15 -0
  88. package/dist/vendor/core/autonomy/resume.js +23 -0
  89. package/dist/vendor/core/circuit/circuit-breaker.d.ts +60 -0
  90. package/dist/vendor/core/circuit/circuit-breaker.js +143 -0
  91. package/dist/vendor/core/compiler.d.ts +2 -0
  92. package/dist/vendor/core/compiler.js +10 -4
  93. package/dist/vendor/core/context-distillation.d.ts +3 -0
  94. package/dist/vendor/core/context-distillation.js +44 -0
  95. package/dist/vendor/core/context-flow/compile-context.d.ts +8 -0
  96. package/dist/vendor/core/context-flow/compile-context.js +111 -0
  97. package/dist/vendor/core/context-flow/entities.d.ts +2 -0
  98. package/dist/vendor/core/context-flow/entities.js +44 -0
  99. package/dist/vendor/core/context-flow/evaluate-policy.d.ts +2 -0
  100. package/dist/vendor/core/context-flow/evaluate-policy.js +42 -0
  101. package/dist/vendor/core/context-flow/index.d.ts +11 -0
  102. package/dist/vendor/core/context-flow/index.js +24 -0
  103. package/dist/vendor/core/context-flow/labels.d.ts +3 -0
  104. package/dist/vendor/core/context-flow/labels.js +17 -0
  105. package/dist/vendor/core/context-flow/normalizer.d.ts +9 -0
  106. package/dist/vendor/core/context-flow/normalizer.js +69 -0
  107. package/dist/vendor/core/context-flow/profiles.d.ts +33 -0
  108. package/dist/vendor/core/context-flow/profiles.js +36 -0
  109. package/dist/vendor/core/context-flow/redaction.d.ts +1 -0
  110. package/dist/vendor/core/context-flow/redaction.js +6 -0
  111. package/dist/vendor/core/context-flow/sensitivity.d.ts +2 -0
  112. package/dist/vendor/core/context-flow/sensitivity.js +27 -0
  113. package/dist/vendor/core/context-flow/sync-preview.d.ts +2 -0
  114. package/dist/vendor/core/context-flow/sync-preview.js +22 -0
  115. package/dist/vendor/core/context-flow/token-estimator.d.ts +3 -0
  116. package/dist/vendor/core/context-flow/token-estimator.js +13 -0
  117. package/dist/vendor/core/context-flow/types.d.ts +91 -0
  118. package/dist/vendor/core/context-flow/types.js +2 -0
  119. package/dist/vendor/core/context-integrity.d.ts +26 -0
  120. package/dist/vendor/core/context-integrity.js +56 -0
  121. package/dist/vendor/core/context-utility.d.ts +47 -0
  122. package/dist/vendor/core/context-utility.js +405 -0
  123. package/dist/vendor/core/cost/pipeline.d.ts +92 -0
  124. package/dist/vendor/core/cost/pipeline.js +141 -0
  125. package/dist/vendor/core/cost/tagged-cost.d.ts +27 -0
  126. package/dist/vendor/core/cost/tagged-cost.js +55 -0
  127. package/dist/vendor/core/cost-governor.d.ts +2 -0
  128. package/dist/vendor/core/cost-governor.js +50 -0
  129. package/dist/vendor/core/cve/cve-check.d.ts +80 -0
  130. package/dist/vendor/core/cve/cve-check.js +172 -0
  131. package/dist/vendor/core/digital-twin/index.d.ts +27 -0
  132. package/dist/vendor/core/digital-twin/index.js +90 -0
  133. package/dist/vendor/core/drift/drift-graph.d.ts +47 -0
  134. package/dist/vendor/core/drift/drift-graph.js +100 -0
  135. package/dist/vendor/core/drift/objective-lock.d.ts +69 -0
  136. package/dist/vendor/core/drift/objective-lock.js +88 -0
  137. package/dist/vendor/core/drift/scope.d.ts +46 -0
  138. package/dist/vendor/core/drift/scope.js +102 -0
  139. package/dist/vendor/core/drift/signature-lock.d.ts +48 -0
  140. package/dist/vendor/core/drift/signature-lock.js +202 -0
  141. package/dist/vendor/core/drift/stale-proof-gate.d.ts +21 -0
  142. package/dist/vendor/core/drift/stale-proof-gate.js +19 -0
  143. package/dist/vendor/core/eval/known-bad-world-runner.d.ts +24 -0
  144. package/dist/vendor/core/eval/known-bad-world-runner.js +256 -0
  145. package/dist/vendor/core/evidence/claim-audit.d.ts +18 -0
  146. package/dist/vendor/core/evidence/claim-audit.js +89 -0
  147. package/dist/vendor/core/exit-intelligence.d.ts +2 -0
  148. package/dist/vendor/core/exit-intelligence.js +58 -0
  149. package/dist/vendor/core/explain/formatter.d.ts +42 -0
  150. package/dist/vendor/core/explain/formatter.js +171 -0
  151. package/dist/vendor/core/explain/timeline.d.ts +29 -0
  152. package/dist/vendor/core/explain/timeline.js +213 -0
  153. package/dist/vendor/core/failure-taxonomy.d.ts +2 -0
  154. package/dist/vendor/core/failure-taxonomy.js +76 -0
  155. package/dist/vendor/core/gateway/index.d.ts +10 -0
  156. package/dist/vendor/core/gateway/index.js +12 -0
  157. package/dist/vendor/core/gateway/registry.d.ts +40 -0
  158. package/dist/vendor/core/gateway/registry.js +97 -0
  159. package/dist/vendor/core/gateway/transport.d.ts +31 -0
  160. package/dist/vendor/core/gateway/transport.js +82 -0
  161. package/dist/vendor/core/gateway/vault.d.ts +19 -0
  162. package/dist/vendor/core/gateway/vault.js +29 -0
  163. package/dist/vendor/core/graph/adapters.d.ts +43 -0
  164. package/dist/vendor/core/graph/adapters.js +91 -0
  165. package/dist/vendor/core/graph/hotspots.d.ts +22 -0
  166. package/dist/vendor/core/graph/hotspots.js +30 -0
  167. package/dist/vendor/core/graph/index.d.ts +1 -0
  168. package/dist/vendor/core/graph/index.js +2 -0
  169. package/dist/vendor/core/honey/honey-tokens.d.ts +32 -0
  170. package/dist/vendor/core/honey/honey-tokens.js +44 -0
  171. package/dist/vendor/core/index.d.ts +7 -4
  172. package/dist/vendor/core/index.js +222 -64
  173. package/dist/vendor/core/learning/bayesian-update.d.ts +31 -0
  174. package/dist/vendor/core/learning/bayesian-update.js +60 -0
  175. package/dist/vendor/core/learning/prior-sets.d.ts +42 -0
  176. package/dist/vendor/core/learning/prior-sets.js +111 -0
  177. package/dist/vendor/core/learning/promotion-gate.d.ts +17 -0
  178. package/dist/vendor/core/learning/promotion-gate.js +23 -0
  179. package/dist/vendor/core/leash/blast-radius.d.ts +42 -0
  180. package/dist/vendor/core/leash/blast-radius.js +156 -0
  181. package/dist/vendor/core/leash/policy-leash.d.ts +31 -0
  182. package/dist/vendor/core/leash/policy-leash.js +117 -0
  183. package/dist/vendor/core/memo/memo.d.ts +63 -0
  184. package/dist/vendor/core/memo/memo.js +97 -0
  185. package/dist/vendor/core/memory/learning-pipeline.d.ts +154 -0
  186. package/dist/vendor/core/memory/learning-pipeline.js +391 -0
  187. package/dist/vendor/core/memory/palace.d.ts +84 -0
  188. package/dist/vendor/core/memory/palace.js +379 -0
  189. package/dist/vendor/core/merge/ast-merge.d.ts +22 -0
  190. package/dist/vendor/core/merge/ast-merge.js +350 -0
  191. package/dist/vendor/core/merge/text-merge.d.ts +12 -0
  192. package/dist/vendor/core/merge/text-merge.js +182 -0
  193. package/dist/vendor/core/otel/tracer.d.ts +45 -0
  194. package/dist/vendor/core/otel/tracer.js +116 -0
  195. package/dist/vendor/core/parallel/parallel-attempts.d.ts +28 -0
  196. package/dist/vendor/core/parallel/parallel-attempts.js +41 -0
  197. package/dist/vendor/core/parallel/scorer.d.ts +24 -0
  198. package/dist/vendor/core/parallel/scorer.js +65 -0
  199. package/dist/vendor/core/pattern-detection.d.ts +64 -0
  200. package/dist/vendor/core/pattern-detection.js +108 -0
  201. package/dist/vendor/core/persistence/checkpoint.d.ts +44 -0
  202. package/dist/vendor/core/persistence/checkpoint.js +156 -0
  203. package/dist/vendor/core/persistence/cleanup.d.ts +22 -0
  204. package/dist/vendor/core/persistence/cleanup.js +131 -0
  205. package/dist/vendor/core/persistence/index.d.ts +2 -0
  206. package/dist/vendor/core/persistence/index.js +1 -0
  207. package/dist/vendor/core/persistence/runs-reader.d.ts +52 -0
  208. package/dist/vendor/core/persistence/runs-reader.js +84 -0
  209. package/dist/vendor/core/persistence/store.d.ts +6 -1
  210. package/dist/vendor/core/persistence/store.js +5 -0
  211. package/dist/vendor/core/policy/file-touch-quota.d.ts +60 -0
  212. package/dist/vendor/core/policy/file-touch-quota.js +105 -0
  213. package/dist/vendor/core/policy/policy-loader.d.ts +30 -0
  214. package/dist/vendor/core/policy/policy-loader.js +170 -0
  215. package/dist/vendor/core/policy/policy-schema.d.ts +55 -0
  216. package/dist/vendor/core/policy/policy-schema.js +78 -0
  217. package/dist/vendor/core/policy.d.ts +6 -0
  218. package/dist/vendor/core/probe/probe.d.ts +49 -0
  219. package/dist/vendor/core/probe/probe.js +115 -0
  220. package/dist/vendor/core/proof/patch-proof.d.ts +58 -0
  221. package/dist/vendor/core/proof/patch-proof.js +84 -0
  222. package/dist/vendor/core/proof/semantic-probe.d.ts +25 -0
  223. package/dist/vendor/core/proof/semantic-probe.js +82 -0
  224. package/dist/vendor/core/recovery/failure-mode-runner.d.ts +29 -0
  225. package/dist/vendor/core/recovery/failure-mode-runner.js +39 -0
  226. package/dist/vendor/core/red-blue/red-phase.d.ts +64 -0
  227. package/dist/vendor/core/red-blue/red-phase.js +141 -0
  228. package/dist/vendor/core/red-blue/risk-tiers.d.ts +22 -0
  229. package/dist/vendor/core/red-blue/risk-tiers.js +33 -0
  230. package/dist/vendor/core/replay/replay.d.ts +85 -0
  231. package/dist/vendor/core/replay/replay.js +109 -0
  232. package/dist/vendor/core/router/engine.d.ts +54 -0
  233. package/dist/vendor/core/router/engine.js +131 -0
  234. package/dist/vendor/core/router/index.d.ts +1 -0
  235. package/dist/vendor/core/router/index.js +2 -0
  236. package/dist/vendor/core/router/trust-calibration.d.ts +57 -0
  237. package/dist/vendor/core/router/trust-calibration.js +127 -0
  238. package/dist/vendor/core/run-martin.d.ts +2 -0
  239. package/dist/vendor/core/run-martin.js +287 -0
  240. package/dist/vendor/core/security/cve-scanner.d.ts +62 -0
  241. package/dist/vendor/core/security/cve-scanner.js +178 -0
  242. package/dist/vendor/core/sentinel/efficiency-sentinel.d.ts +29 -0
  243. package/dist/vendor/core/sentinel/efficiency-sentinel.js +30 -0
  244. package/dist/vendor/core/sentinel/progress-guard.d.ts +35 -0
  245. package/dist/vendor/core/sentinel/progress-guard.js +46 -0
  246. package/dist/vendor/core/siem/siem-emitter.d.ts +49 -0
  247. package/dist/vendor/core/siem/siem-emitter.js +157 -0
  248. package/dist/vendor/core/strategy/attempt-brief.d.ts +22 -0
  249. package/dist/vendor/core/strategy/attempt-brief.js +89 -0
  250. package/dist/vendor/core/summarize/diff-summary.d.ts +35 -0
  251. package/dist/vendor/core/summarize/diff-summary.js +204 -0
  252. package/dist/vendor/core/surface-signals.d.ts +21 -0
  253. package/dist/vendor/core/surface-signals.js +139 -0
  254. package/dist/vendor/core/truth/truth-wall.d.ts +51 -0
  255. package/dist/vendor/core/truth/truth-wall.js +69 -0
  256. package/dist/vendor/core/truth-spine.d.ts +26 -0
  257. package/dist/vendor/core/truth-spine.js +62 -0
  258. package/dist/vendor/core/types.d.ts +115 -0
  259. package/dist/vendor/core/types.js +2 -0
  260. package/dist/vendor/core/verification/tiered-verify.d.ts +17 -0
  261. package/dist/vendor/core/verification/tiered-verify.js +29 -0
  262. package/dist/vendor/core/verifier-pyramid.d.ts +32 -0
  263. package/dist/vendor/core/verifier-pyramid.js +111 -0
  264. package/dist/vendor/core/workflow-artifacts.d.ts +99 -0
  265. package/dist/vendor/core/workflow-artifacts.js +668 -0
  266. package/dist/vendor/core/wrap/supervised-run.d.ts +96 -0
  267. package/dist/vendor/core/wrap/supervised-run.js +178 -0
  268. package/docs/assets/cli-animated.svg +139 -0
  269. package/docs/assets/cli-static.svg +34 -0
  270. package/docs/assets/github-hero-v2.svg +23 -0
  271. package/docs/assets/martin-raplph.png.jpg +0 -0
  272. package/docs/assets/martinloop-logo.png +0 -0
  273. package/docs/assets/nvidia-inception-program-light.png +0 -0
  274. package/docs/assets/nvidia-inception-program.png +0 -0
  275. package/docs/assets/phase3c-sidesidebyside-demo.html +228 -0
  276. package/docs/assets/side-by-side.svg +134 -0
  277. package/docs/oss/CLAUDE-CODE-WALKTHROUGH.md +142 -0
  278. package/docs/oss/EXAMPLES.md +9 -1
  279. package/docs/oss/OSS-BOUNDARY-REPORT.json +109 -113
  280. package/docs/oss/OSS-BOUNDARY-REPORT.md +48 -48
  281. package/docs/oss/QUICKSTART.md +39 -4
  282. package/docs/oss/RALPH-LOOP-SAFETY.md +113 -0
  283. package/docs/oss/README.md +7 -4
  284. package/docs/oss/RELEASE-SURFACE-REPORT.json +46 -45
  285. package/docs/oss/RELEASE-SURFACE-REPORT.md +36 -35
  286. package/package.json +129 -49
@@ -5,12 +5,15 @@ import { evaluateChangeApprovalLeash, evaluateFilesystemLeash, evaluateSecretLea
5
5
  import { buildRepoGroundingIndex, loadOrBuildRepoGroundingIndex, queryRepoGroundingIndex, scanPatchForGroundingViolations } from "./grounding.js";
6
6
  import { captureRollbackBoundary, restoreRollbackBoundary } from "./rollback.js";
7
7
  import { compilePromptPacket } from "./compiler.js";
8
- import { makeLedgerEvent } from "./persistence/index.js";
8
+ import { makeLedgerEvent, resolveRunsRoot, runDir } from "./persistence/index.js";
9
+ import { runContextIntegrityPrecheck } from "./context-integrity.js";
9
10
  export { classifyFailure, computeEvidenceVector, evaluatePatchDecision, evaluateCostGovernor, evaluateBudgetPreflight, inferExit, nextPolicyPhase, policyPhaseToLifecycleState, scorePatchDecision, selectRecoveryRecipe, evaluateVerificationLeash, evaluateFilesystemLeash, evaluateChangeApprovalLeash, evaluateSecretLeash, resolveExecutionProfile, redactSecretsFromText, buildRepoGroundingIndex, loadOrBuildRepoGroundingIndex, queryRepoGroundingIndex, scanPatchForGroundingViolations, captureRollbackBoundary, restoreRollbackBoundary };
11
+ // ─── Context Integrity Pre-gate ──────────────────────────────────────────────
12
+ export { runContextIntegrityPrecheck } from "./context-integrity.js";
10
13
  // ─── Prompt packet compiler ──────────────────────────────────────────────────
11
14
  export { compilePromptPacket } from "./compiler.js";
12
15
  // ─── Persistence (RunStore, LedgerEvent, FileRunStore) ──────────────────────
13
- export { createFileRunStore, makeLedgerEvent, resolveRunsRoot } from "./persistence/index.js";
16
+ export { createFileRunStore, makeLedgerEvent, readAllLoopRecords, readLatestLoopRecord, readLatestLoopRecordFromFile, readLoopRecordsFromFile, resolveRunsRoot } from "./persistence/index.js";
14
17
  export { compileAndPersistContext } from "./persistence/index.js";
15
18
  /**
16
19
  * Admission gate — must pass before any attempt is executed.
@@ -126,6 +129,7 @@ export async function runMartin(input) {
126
129
  runId: loop.loopId,
127
130
  payload: { workspaceId: input.workspaceId, projectId: input.projectId }
128
131
  }));
132
+ await persistLoopRecordIfSupported(input.store, loop);
129
133
  }
130
134
  const DEFAULT_FALLBACK_MODELS = [
131
135
  "claude-haiku-4-5",
@@ -136,6 +140,7 @@ export async function runMartin(input) {
136
140
  let currentAdapterIndex = 0;
137
141
  let currentAdapter = adapterChain[currentAdapterIndex] ?? input.adapter;
138
142
  let useCompressedContext = false;
143
+ const isVerifyOnly = input.task.mutationMode === "verify_only";
139
144
  const executionProfile = resolveExecutionProfile({
140
145
  executionProfile: input.task.executionProfile,
141
146
  allowedNetworkDomains: input.task.allowedNetworkDomains
@@ -153,7 +158,8 @@ export async function runMartin(input) {
153
158
  shouldExit: true,
154
159
  lifecycleState: "human_escalation",
155
160
  status: "exited",
156
- reason
161
+ reason,
162
+ ...classifySafetyLeashExit(leashDecision, "verifier")
157
163
  };
158
164
  if (input.store) {
159
165
  await input.store.appendLedger(loop.loopId, makeLedgerEvent({
@@ -169,15 +175,13 @@ export async function runMartin(input) {
169
175
  await input.store.appendLedger(loop.loopId, makeLedgerEvent({
170
176
  kind: "run.exited",
171
177
  runId: loop.loopId,
172
- payload: {
173
- lifecycleState: leashExitDecision.lifecycleState,
174
- status: leashExitDecision.status,
175
- reason: leashExitDecision.reason
176
- }
178
+ payload: createRunExitPayload(leashExitDecision)
177
179
  }));
178
180
  }
181
+ const finalizedLoop = finalizeLoop(loop, leashExitDecision, now(), idFactory);
182
+ await persistLoopRecordIfSupported(input.store, finalizedLoop);
179
183
  return {
180
- loop: finalizeLoop(loop, leashExitDecision, now(), idFactory),
184
+ loop: finalizedLoop,
181
185
  decision: leashExitDecision
182
186
  };
183
187
  }
@@ -193,7 +197,8 @@ export async function runMartin(input) {
193
197
  shouldExit: true,
194
198
  lifecycleState: "human_escalation",
195
199
  status: "exited",
196
- reason: secretDecision.reason ?? "Safety leash blocked secret-like values in the runtime context."
200
+ reason: secretDecision.reason ?? "Safety leash blocked secret-like values in the runtime context.",
201
+ ...classifySafetyLeashExit(secretDecision, "secret")
197
202
  };
198
203
  if (input.store) {
199
204
  await input.store.appendLedger(loop.loopId, makeLedgerEvent({
@@ -208,15 +213,13 @@ export async function runMartin(input) {
208
213
  await input.store.appendLedger(loop.loopId, makeLedgerEvent({
209
214
  kind: "run.exited",
210
215
  runId: loop.loopId,
211
- payload: {
212
- lifecycleState: secretExitDecision.lifecycleState,
213
- status: secretExitDecision.status,
214
- reason: secretExitDecision.reason
215
- }
216
+ payload: createRunExitPayload(secretExitDecision)
216
217
  }));
217
218
  }
219
+ const finalizedLoop = finalizeLoop(loop, secretExitDecision, now(), idFactory);
220
+ await persistLoopRecordIfSupported(input.store, finalizedLoop);
218
221
  return {
219
- loop: finalizeLoop(loop, secretExitDecision, now(), idFactory),
222
+ loop: finalizedLoop,
220
223
  decision: secretExitDecision
221
224
  };
222
225
  }
@@ -254,20 +257,52 @@ export async function runMartin(input) {
254
257
  await input.store.appendLedger(loop.loopId, makeLedgerEvent({
255
258
  kind: "run.exited",
256
259
  runId: loop.loopId,
257
- payload: {
258
- lifecycleState: preflightExitDecision.lifecycleState,
259
- status: preflightExitDecision.status,
260
- reason: preflightExitDecision.reason
261
- }
260
+ payload: createRunExitPayload(preflightExitDecision)
262
261
  }));
263
262
  }
263
+ const finalizedLoop = finalizeLoop(loop, preflightExitDecision, now(), idFactory);
264
+ await persistLoopRecordIfSupported(input.store, finalizedLoop);
264
265
  return {
265
- loop: finalizeLoop(loop, preflightExitDecision, now(), idFactory),
266
+ loop: finalizedLoop,
266
267
  decision: preflightExitDecision
267
268
  };
268
269
  }
269
270
  // GATHER → ADMIT: run admission control before executing
270
271
  currentPhase = "ADMIT";
272
+ // T05: Context Integrity Pre-gate — blocks authority inversion / injection before reasoning
273
+ const contextPrecheck = await runContextIntegrityPrecheck(loop.loopId, loop.attempts.length + 1, runDir(resolveRunsRoot(), loop.loopId), {
274
+ userPrompt: distilled.focus,
275
+ history: loop.attempts.map(a => a.summary).join("\n")
276
+ });
277
+ if (contextPrecheck.verdict === "context_poisoning_block") {
278
+ currentPhase = "ABORT";
279
+ const poisoningExitDecision = {
280
+ shouldExit: true,
281
+ lifecycleState: "human_escalation",
282
+ status: "exited",
283
+ reason: "Context Integrity Pre-gate: context poisoning attempt detected.",
284
+ failureClass: "safety_leash_blocked",
285
+ safetySurface: "context_integrity",
286
+ reasonCode: "context_poisoning_blocked"
287
+ };
288
+ if (input.store) {
289
+ await input.store.appendLedger(loop.loopId, makeLedgerEvent({
290
+ kind: "safety.violations_found",
291
+ runId: loop.loopId,
292
+ payload: {
293
+ verdict: contextPrecheck.verdict,
294
+ signals: contextPrecheck.detectedSignals,
295
+ source: "context_integrity_pregate"
296
+ }
297
+ }));
298
+ }
299
+ const finalizedLoop = finalizeLoop(loop, poisoningExitDecision, now(), idFactory);
300
+ await persistLoopRecordIfSupported(input.store, finalizedLoop);
301
+ return {
302
+ loop: finalizedLoop,
303
+ decision: poisoningExitDecision
304
+ };
305
+ }
271
306
  const admissionDecision = evaluateAttemptPolicy({
272
307
  request: {
273
308
  loopId: loop.loopId,
@@ -315,15 +350,13 @@ export async function runMartin(input) {
315
350
  await input.store.appendLedger(loop.loopId, makeLedgerEvent({
316
351
  kind: "run.exited",
317
352
  runId: loop.loopId,
318
- payload: {
319
- lifecycleState: exitDecision.lifecycleState,
320
- status: exitDecision.status,
321
- reason: exitDecision.reason
322
- }
353
+ payload: createRunExitPayload(exitDecision)
323
354
  }));
324
355
  }
356
+ const finalizedLoop = finalizeLoop(loop, exitDecision, now(), idFactory);
357
+ await persistLoopRecordIfSupported(input.store, finalizedLoop);
325
358
  return {
326
- loop: finalizeLoop(loop, exitDecision, now(), idFactory),
359
+ loop: finalizedLoop,
327
360
  decision: exitDecision
328
361
  };
329
362
  }
@@ -361,6 +394,7 @@ export async function runMartin(input) {
361
394
  objective: loop.task.objective,
362
395
  verificationPlan: loop.task.verificationPlan,
363
396
  ...(loop.task.verificationStack ? { verificationStack: loop.task.verificationStack } : {}),
397
+ ...(loop.task.mutationMode ? { mutationMode: loop.task.mutationMode } : {}),
364
398
  ...(loop.task.repoRoot ? { repoRoot: loop.task.repoRoot } : {}),
365
399
  ...(loop.task.allowedPaths ? { allowedPaths: loop.task.allowedPaths } : {}),
366
400
  ...(loop.task.deniedPaths ? { deniedPaths: loop.task.deniedPaths } : {}),
@@ -539,6 +573,92 @@ export async function runMartin(input) {
539
573
  // returned a non-empty list. A repoRoot alone is insufficient — git may fail (e.g. not
540
574
  // a git repo) and silently return [], which would falsely trigger no_code_change.
541
575
  const changedFileEvidenceAvailable = result.execution?.changedFiles !== undefined || changedFiles.length > 0;
576
+ if (isVerifyOnly && changedFiles.length > 0) {
577
+ const patchDecision = evaluatePatchDecision({
578
+ verificationPassed: result.verification.passed,
579
+ previousVerifierScore,
580
+ verifierScore: result.verification.passed ? 1 : 0,
581
+ scopeViolationCount: changedFiles.length,
582
+ changedFileCount: changedFiles.length,
583
+ diffNovelty: 1,
584
+ diffStats: result.execution?.diffStats,
585
+ costUsd: getUsageUsd(result.usage),
586
+ summary: result.summary
587
+ });
588
+ const verifyOnlyExitDecision = {
589
+ shouldExit: true,
590
+ lifecycleState: "human_escalation",
591
+ status: "exited",
592
+ reason: "Verify-only mode forbids file changes.",
593
+ failureClass: "safety_leash_blocked",
594
+ safetySurface: "filesystem",
595
+ reasonCode: "verify_only_write_attempt"
596
+ };
597
+ const rollbackOutcome = await restoreRollbackBoundary({
598
+ repoRoot: request.context.repoRoot,
599
+ boundary: rollbackBoundary,
600
+ restoredAt: attemptCompletedAt,
601
+ decision: patchDecision.decision
602
+ });
603
+ if (input.store) {
604
+ const verifyOnlyViolation = {
605
+ kind: "path_not_allowed",
606
+ message: `Verify-only mode forbids changed files: ${changedFiles.join(", ")}`,
607
+ file: changedFiles[0]
608
+ };
609
+ await input.store.writeAttemptArtifacts(loop.loopId, currentAttemptIndex, {
610
+ compiledContext,
611
+ leash: createLeashArtifact({
612
+ surface: "filesystem",
613
+ reason: verifyOnlyExitDecision.reason,
614
+ violations: [verifyOnlyViolation]
615
+ }, currentAttemptIndex),
616
+ patchScore: patchDecision.score,
617
+ patchDecision: toPatchDecisionArtifact(patchDecision),
618
+ ...(rollbackBoundary ? { rollbackBoundary } : {}),
619
+ ...(rollbackOutcome ? { rollbackOutcome } : {})
620
+ });
621
+ await input.store.appendLedger(loop.loopId, makeLedgerEvent({
622
+ kind: "safety.violations_found",
623
+ runId: loop.loopId,
624
+ attemptIndex: currentAttemptIndex,
625
+ payload: {
626
+ surface: "filesystem",
627
+ blocked: true,
628
+ attemptIndex: currentAttemptIndex,
629
+ violations: [
630
+ {
631
+ kind: "path_not_allowed",
632
+ message: verifyOnlyExitDecision.reason,
633
+ files: changedFiles
634
+ }
635
+ ]
636
+ }
637
+ }));
638
+ await input.store.appendLedger(loop.loopId, makeLedgerEvent({
639
+ kind: "attempt.discarded",
640
+ runId: loop.loopId,
641
+ attemptIndex: currentAttemptIndex,
642
+ payload: {
643
+ decision: patchDecision.decision,
644
+ reason: patchDecision.summary,
645
+ reasonCodes: patchDecision.reasonCodes,
646
+ score: patchDecision.score.score
647
+ }
648
+ }));
649
+ await input.store.appendLedger(loop.loopId, makeLedgerEvent({
650
+ kind: "run.exited",
651
+ runId: loop.loopId,
652
+ payload: createRunExitPayload(verifyOnlyExitDecision)
653
+ }));
654
+ }
655
+ const finalizedLoop = finalizeLoop(loop, verifyOnlyExitDecision, now(), idFactory);
656
+ await persistLoopRecordIfSupported(input.store, finalizedLoop);
657
+ return {
658
+ loop: finalizedLoop,
659
+ decision: verifyOnlyExitDecision
660
+ };
661
+ }
542
662
  const filesystemDecision = evaluateFilesystemLeash({
543
663
  repoRoot: request.context.repoRoot,
544
664
  changedFiles,
@@ -561,7 +681,8 @@ export async function runMartin(input) {
561
681
  shouldExit: true,
562
682
  lifecycleState: "human_escalation",
563
683
  status: "exited",
564
- reason: filesystemDecision.reason ?? "Safety leash blocked filesystem changes."
684
+ reason: filesystemDecision.reason ?? "Safety leash blocked filesystem changes.",
685
+ ...classifySafetyLeashExit(filesystemDecision, "filesystem")
565
686
  };
566
687
  const rollbackOutcome = await restoreRollbackBoundary({
567
688
  repoRoot: request.context.repoRoot,
@@ -603,15 +724,13 @@ export async function runMartin(input) {
603
724
  await input.store.appendLedger(loop.loopId, makeLedgerEvent({
604
725
  kind: "run.exited",
605
726
  runId: loop.loopId,
606
- payload: {
607
- lifecycleState: filesystemExitDecision.lifecycleState,
608
- status: filesystemExitDecision.status,
609
- reason: filesystemExitDecision.reason
610
- }
727
+ payload: createRunExitPayload(filesystemExitDecision)
611
728
  }));
612
729
  }
730
+ const finalizedLoop = finalizeLoop(loop, filesystemExitDecision, now(), idFactory);
731
+ await persistLoopRecordIfSupported(input.store, finalizedLoop);
613
732
  return {
614
- loop: finalizeLoop(loop, filesystemExitDecision, now(), idFactory),
733
+ loop: finalizedLoop,
615
734
  decision: filesystemExitDecision
616
735
  };
617
736
  }
@@ -638,7 +757,8 @@ export async function runMartin(input) {
638
757
  lifecycleState: "human_escalation",
639
758
  status: "exited",
640
759
  reason: changeApprovalDecision.reason ??
641
- "Safety leash blocked dependency or migration changes that require approval."
760
+ "Safety leash blocked dependency or migration changes that require approval.",
761
+ ...classifySafetyLeashExit(changeApprovalDecision, "dependency")
642
762
  };
643
763
  const rollbackOutcome = await restoreRollbackBoundary({
644
764
  repoRoot: request.context.repoRoot,
@@ -681,15 +801,13 @@ export async function runMartin(input) {
681
801
  await input.store.appendLedger(loop.loopId, makeLedgerEvent({
682
802
  kind: "run.exited",
683
803
  runId: loop.loopId,
684
- payload: {
685
- lifecycleState: approvalExitDecision.lifecycleState,
686
- status: approvalExitDecision.status,
687
- reason: approvalExitDecision.reason
688
- }
804
+ payload: createRunExitPayload(approvalExitDecision)
689
805
  }));
690
806
  }
807
+ const finalizedLoop = finalizeLoop(loop, approvalExitDecision, now(), idFactory);
808
+ await persistLoopRecordIfSupported(input.store, finalizedLoop);
691
809
  return {
692
- loop: finalizeLoop(loop, approvalExitDecision, now(), idFactory),
810
+ loop: finalizedLoop,
693
811
  decision: approvalExitDecision
694
812
  };
695
813
  }
@@ -728,8 +846,8 @@ export async function runMartin(input) {
728
846
  previousVerifierScore,
729
847
  verifierScore: result.verification.passed ? 1 : 0,
730
848
  groundingViolationCount: groundingScanResult?.violations.length ?? 0,
731
- changedFileCount: changedFileEvidenceAvailable ? changedFiles.length : undefined,
732
- diffNovelty: changedFileEvidenceAvailable ? (changedFiles.length > 0 ? 1 : 0) : undefined,
849
+ changedFileCount: !isVerifyOnly && changedFileEvidenceAvailable ? changedFiles.length : undefined,
850
+ diffNovelty: !isVerifyOnly && changedFileEvidenceAvailable ? (changedFiles.length > 0 ? 1 : 0) : undefined,
733
851
  diffStats: result.execution?.diffStats,
734
852
  costUsd: getUsageUsd(result.usage),
735
853
  summary: result.summary
@@ -822,15 +940,13 @@ export async function runMartin(input) {
822
940
  await input.store.appendLedger(loop.loopId, makeLedgerEvent({
823
941
  kind: "run.exited",
824
942
  runId: loop.loopId,
825
- payload: {
826
- lifecycleState: patchExitDecision.lifecycleState,
827
- status: patchExitDecision.status,
828
- reason: patchExitDecision.reason
829
- }
943
+ payload: createRunExitPayload(patchExitDecision)
830
944
  }));
831
945
  }
946
+ const finalizedLoop = finalizeLoop(loop, patchExitDecision, now(), idFactory);
947
+ await persistLoopRecordIfSupported(input.store, finalizedLoop);
832
948
  return {
833
- loop: finalizeLoop(loop, patchExitDecision, now(), idFactory),
949
+ loop: finalizedLoop,
834
950
  decision: patchExitDecision
835
951
  };
836
952
  }
@@ -870,15 +986,13 @@ export async function runMartin(input) {
870
986
  await input.store.appendLedger(loop.loopId, makeLedgerEvent({
871
987
  kind: "run.exited",
872
988
  runId: loop.loopId,
873
- payload: {
874
- lifecycleState: decision.lifecycleState,
875
- status: decision.status,
876
- reason: decision.reason
877
- }
989
+ payload: createRunExitPayload(decision)
878
990
  }));
879
991
  }
992
+ const finalizedLoop = finalizeLoop(loop, decision, now(), idFactory);
993
+ await persistLoopRecordIfSupported(input.store, finalizedLoop);
880
994
  return {
881
- loop: finalizeLoop(loop, decision, now(), idFactory),
995
+ loop: finalizedLoop,
882
996
  decision
883
997
  };
884
998
  }
@@ -893,23 +1007,64 @@ export async function runMartin(input) {
893
1007
  await input.store.appendLedger(loop.loopId, makeLedgerEvent({
894
1008
  kind: "run.exited",
895
1009
  runId: loop.loopId,
896
- payload: {
897
- lifecycleState: decision.lifecycleState,
898
- status: decision.status,
899
- reason: decision.reason
900
- }
1010
+ payload: createRunExitPayload(decision)
901
1011
  }));
902
1012
  }
1013
+ const finalizedLoop = finalizeLoop(loop, decision, now(), idFactory);
1014
+ await persistLoopRecordIfSupported(input.store, finalizedLoop);
903
1015
  return {
904
- loop: finalizeLoop(loop, decision, now(), idFactory),
1016
+ loop: finalizedLoop,
905
1017
  decision
906
1018
  };
907
1019
  }
1020
+ function createRunExitPayload(decision) {
1021
+ return {
1022
+ lifecycleState: decision.lifecycleState,
1023
+ status: decision.status,
1024
+ reason: decision.reason,
1025
+ ...(decision.failureClass ? { failureClass: decision.failureClass } : {}),
1026
+ ...(decision.safetySurface ? { safetySurface: decision.safetySurface } : {}),
1027
+ ...(decision.reasonCode ? { reasonCode: decision.reasonCode } : {})
1028
+ };
1029
+ }
1030
+ function classifySafetyLeashExit(decision, safetySurface = decision.surface) {
1031
+ return {
1032
+ failureClass: "safety_leash_blocked",
1033
+ safetySurface,
1034
+ reasonCode: safetyLeashReasonCode(decision, safetySurface)
1035
+ };
1036
+ }
1037
+ function safetyLeashReasonCode(decision, safetySurface) {
1038
+ const kind = decision.violations[0]?.kind;
1039
+ switch (kind) {
1040
+ case "command_blocked":
1041
+ return safetySurface === "verifier" ? "destructive_verifier_command" : "command_blocked";
1042
+ case "network_blocked":
1043
+ return safetySurface === "verifier" ? "verifier_network_blocked" : "network_access_blocked";
1044
+ case "secret_value":
1045
+ return "secret_context_value";
1046
+ case "path_denied":
1047
+ case "protected_path":
1048
+ return "protected_surface_write";
1049
+ case "path_not_allowed":
1050
+ return "surface_write_not_allowed";
1051
+ case "path_outside_repo":
1052
+ return "outside_repo_write";
1053
+ case "dependency_approval_required":
1054
+ return "dependency_approval_required";
1055
+ case "migration_approval_required":
1056
+ return "migration_approval_required";
1057
+ case "config_change_approval_required":
1058
+ return "config_change_approval_required";
1059
+ default:
1060
+ return `${safetySurface}_safety_block`;
1061
+ }
1062
+ }
908
1063
  function finalizeLoop(loop, decision, timestamp, idFactory) {
909
1064
  const finalized = appendLoopEvent(loop, {
910
1065
  type: "run.completed",
911
1066
  lifecycleState: decision.lifecycleState,
912
- payload: { status: decision.status, reason: decision.reason }
1067
+ payload: createRunExitPayload(decision)
913
1068
  }, { now: timestamp, idFactory });
914
1069
  return {
915
1070
  ...finalized,
@@ -918,6 +1073,9 @@ function finalizeLoop(loop, decision, timestamp, idFactory) {
918
1073
  updatedAt: timestamp
919
1074
  };
920
1075
  }
1076
+ async function persistLoopRecordIfSupported(store, loop) {
1077
+ await store?.writeLoopRecord?.(loop.loopId, loop);
1078
+ }
921
1079
  function getAdapterTransport(adapter) {
922
1080
  return adapter.metadata.transport ?? (adapter.kind === "agent-cli" ? "cli" : "http");
923
1081
  }
@@ -934,7 +1092,7 @@ function getUsageProvenance(usage) {
934
1092
  return "actual";
935
1093
  }
936
1094
  function resolveChangedFiles(result, repoRoot) {
937
- if (result.execution?.changedFiles?.length) {
1095
+ if (result.execution?.changedFiles !== undefined) {
938
1096
  return result.execution.changedFiles;
939
1097
  }
940
1098
  if (!repoRoot) {
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Applies a single-step Bayesian update to a prior probability.
3
+ *
4
+ * Formula: posterior = (prior * likelihood) / normalizing_constant
5
+ *
6
+ * The normalizing constant ensures the result stays in [0, 1]:
7
+ * Z = prior * likelihood + (1 - prior) * (1 - likelihood)
8
+ *
9
+ * This is the standard Beta-Bernoulli update for binary outcomes.
10
+ * - likelihood > 0.5 → positive evidence → posterior increases
11
+ * - likelihood < 0.5 → negative evidence → posterior decreases
12
+ * - likelihood = 0.5 → no information → posterior unchanged
13
+ *
14
+ * @param prior Current prior probability (0.0 – 1.0)
15
+ * @param likelihood Likelihood of observation given the hypothesis (0.0 – 1.0)
16
+ * @returns Updated posterior probability (0.0 – 1.0)
17
+ */
18
+ export declare function updatePriorBayesian(prior: number, likelihood: number): number;
19
+ /**
20
+ * Applies a Bayesian update to a PriorSet's individual symbol priors
21
+ * using confidence deltas from the hypothesis ledger.
22
+ *
23
+ * confidenceDelta > 0 → validated evidence → likelihood = 0.5 + delta/2
24
+ * confidenceDelta < 0 → invalidated evidence → likelihood = 0.5 + delta/2
25
+ *
26
+ * @param priors Symbol → prior probability map
27
+ * @param symbol The specific symbol to update
28
+ * @param confidenceDelta From hypothesis ledger (−1.0 to +1.0)
29
+ * @returns New priors map with updated value for symbol
30
+ */
31
+ export declare function updateSymbolPrior(priors: Record<string, number>, symbol: string, confidenceDelta: number): Record<string, number>;
@@ -0,0 +1,60 @@
1
+ // ─── Bayesian Update ─────────────────────────────────────────────────────────
2
+ /**
3
+ * Applies a single-step Bayesian update to a prior probability.
4
+ *
5
+ * Formula: posterior = (prior * likelihood) / normalizing_constant
6
+ *
7
+ * The normalizing constant ensures the result stays in [0, 1]:
8
+ * Z = prior * likelihood + (1 - prior) * (1 - likelihood)
9
+ *
10
+ * This is the standard Beta-Bernoulli update for binary outcomes.
11
+ * - likelihood > 0.5 → positive evidence → posterior increases
12
+ * - likelihood < 0.5 → negative evidence → posterior decreases
13
+ * - likelihood = 0.5 → no information → posterior unchanged
14
+ *
15
+ * @param prior Current prior probability (0.0 – 1.0)
16
+ * @param likelihood Likelihood of observation given the hypothesis (0.0 – 1.0)
17
+ * @returns Updated posterior probability (0.0 – 1.0)
18
+ */
19
+ export function updatePriorBayesian(prior, likelihood) {
20
+ if (prior < 0 || prior > 1)
21
+ throw new Error(`prior must be in [0, 1], got ${prior}`);
22
+ if (likelihood < 0 || likelihood > 1)
23
+ throw new Error(`likelihood must be in [0, 1], got ${likelihood}`);
24
+ // P(H|E) = P(E|H) * P(H) / P(E)
25
+ // P(E) = P(E|H)*P(H) + P(E|¬H)*P(¬H)
26
+ const pEgivenH = likelihood;
27
+ const pEgivenNotH = 1 - likelihood;
28
+ const pH = prior;
29
+ const pNotH = 1 - prior;
30
+ const pE = pEgivenH * pH + pEgivenNotH * pNotH;
31
+ // Avoid division by zero (shouldn't happen with valid inputs)
32
+ if (pE === 0)
33
+ return prior;
34
+ return (pEgivenH * pH) / pE;
35
+ }
36
+ /**
37
+ * Applies a Bayesian update to a PriorSet's individual symbol priors
38
+ * using confidence deltas from the hypothesis ledger.
39
+ *
40
+ * confidenceDelta > 0 → validated evidence → likelihood = 0.5 + delta/2
41
+ * confidenceDelta < 0 → invalidated evidence → likelihood = 0.5 + delta/2
42
+ *
43
+ * @param priors Symbol → prior probability map
44
+ * @param symbol The specific symbol to update
45
+ * @param confidenceDelta From hypothesis ledger (−1.0 to +1.0)
46
+ * @returns New priors map with updated value for symbol
47
+ */
48
+ export function updateSymbolPrior(priors, symbol, confidenceDelta) {
49
+ const currentPrior = priors[symbol] ?? 0.5;
50
+ // Map confidenceDelta (−1..+1) to likelihood (0..1)
51
+ // delta=+1.0 → likelihood=1.0 (strong positive evidence)
52
+ // delta=0.0 → likelihood=0.5 (no information)
53
+ // delta=−1.0 → likelihood=0.0 (strong negative evidence)
54
+ const likelihood = Math.max(0, Math.min(1, 0.5 + confidenceDelta / 2));
55
+ return {
56
+ ...priors,
57
+ [symbol]: updatePriorBayesian(currentPrior, likelihood)
58
+ };
59
+ }
60
+ //# sourceMappingURL=bayesian-update.js.map
@@ -0,0 +1,42 @@
1
+ export type PromotionGate = "development" | "backtest" | "shadow" | "live";
2
+ export interface PriorSet {
3
+ priorSetId: string;
4
+ taskClass: string;
5
+ version: number;
6
+ confidence: number;
7
+ priors: Record<string, number>;
8
+ lastUpdatedAt: string;
9
+ promotionGate: PromotionGate;
10
+ sampleCount: number;
11
+ }
12
+ export interface PriorStore {
13
+ priorSets: PriorSet[];
14
+ }
15
+ export interface CreatePriorSetInput {
16
+ priorSetId: string;
17
+ taskClass: string;
18
+ priors: Record<string, number>;
19
+ }
20
+ export declare function createPriorSet(input: CreatePriorSetInput): PriorSet;
21
+ export declare function loadPriorStore(storeDir: string): Promise<PriorStore>;
22
+ export declare function savePriorStore(store: PriorStore, storeDir: string): Promise<void>;
23
+ /**
24
+ * Promotes a PriorSet to the next gate in the sequence.
25
+ * Gates must advance sequentially: development → backtest → shadow → live.
26
+ * Throws if the target gate is not the immediate next gate.
27
+ */
28
+ export declare function promotePriorSet(priorSetId: string, targetGate: PromotionGate, storeDir: string): Promise<PriorSet>;
29
+ /**
30
+ * Rolls back a PriorSet to the previous gate.
31
+ * Rollback is always available from any gate above development.
32
+ * Throws if already at development.
33
+ */
34
+ export declare function rollbackPriorSet(priorSetId: string, storeDir: string): Promise<PriorSet>;
35
+ /**
36
+ * Returns all PriorSets from the store.
37
+ */
38
+ export declare function listPriorSets(storeDir: string): Promise<PriorSet[]>;
39
+ /**
40
+ * Returns a single PriorSet by ID, or null if not found.
41
+ */
42
+ export declare function getPriorSet(priorSetId: string, storeDir: string): Promise<PriorSet | null>;