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
@@ -0,0 +1,379 @@
1
+ import { createHash } from "node:crypto";
2
+ import { appendFile, mkdir, readFile, readdir, writeFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { resolveMartinHome } from "../attestation/sign.js";
5
+ import { loadActiveLearningHeuristics, runPromotionPipeline } from "./learning-pipeline.js";
6
+ // ─── Stop words for relevance scoring ────────────────────────────────────────
7
+ const STOP_WORDS = new Set([
8
+ "a",
9
+ "an",
10
+ "and",
11
+ "are",
12
+ "for",
13
+ "from",
14
+ "into",
15
+ "keep",
16
+ "loop",
17
+ "not",
18
+ "the",
19
+ "this",
20
+ "that",
21
+ "with",
22
+ "without"
23
+ ]);
24
+ // ─── Public API ───────────────────────────────────────────────────────────────
25
+ export function resolveMemoryRoot(env = process.env) {
26
+ return env["MARTIN_MEMORY_DIR"]?.trim() || join(resolveMartinHome(), "memory");
27
+ }
28
+ export function createFileLoopMemoryStore(options = {}) {
29
+ const memoryRoot = options.memoryRoot ?? resolveMemoryRoot();
30
+ return {
31
+ async recall(input) {
32
+ const wingKey = buildWingKey(input.workspaceId, input.projectId);
33
+ const wingPath = join(memoryRoot, slugifyKey(wingKey));
34
+ const roomNames = await safeReaddir(wingPath);
35
+ const activeHeuristics = await loadActiveLearningHeuristics(memoryRoot);
36
+ if (roomNames.length === 0) {
37
+ return undefined;
38
+ }
39
+ const queryTokens = buildQueryTokens(input.objective, input.focus, input.previousAttempts);
40
+ const lastAttempt = input.previousAttempts.at(-1);
41
+ const scoredEntries = [];
42
+ for (const roomName of roomNames) {
43
+ if (roomName === "wing.json") {
44
+ continue;
45
+ }
46
+ const drawers = await readDrawersFile(join(wingPath, roomName, "drawers.jsonl"));
47
+ for (const drawer of drawers) {
48
+ const { score, reason } = scoreDrawer(drawer, queryTokens, lastAttempt, activeHeuristics.recallScoring);
49
+ if (score <= 0) {
50
+ continue;
51
+ }
52
+ scoredEntries.push({
53
+ drawerId: drawer.drawerId,
54
+ roomKey: drawer.roomKey,
55
+ lesson: drawer.lesson,
56
+ content: drawer.content,
57
+ sourceRunId: drawer.sourceRunId,
58
+ ...(drawer.sourceAttemptIndex !== undefined
59
+ ? { sourceAttemptIndex: drawer.sourceAttemptIndex }
60
+ : {}),
61
+ score,
62
+ reason
63
+ });
64
+ }
65
+ }
66
+ const entries = scoredEntries
67
+ .sort((left, right) => right.score - left.score)
68
+ .slice(0, Math.max(1, input.limit ?? 3));
69
+ if (entries.length === 0) {
70
+ return undefined;
71
+ }
72
+ if (input.currentRunId && input.currentAttemptIndex !== undefined) {
73
+ await persistRecallAudit({
74
+ memoryRoot,
75
+ wingKey,
76
+ runId: input.currentRunId,
77
+ attemptIndex: input.currentAttemptIndex,
78
+ entries
79
+ });
80
+ }
81
+ return {
82
+ wingKey,
83
+ recalledAt: new Date().toISOString(),
84
+ entries
85
+ };
86
+ },
87
+ async recordLoop(input) {
88
+ const wingKey = buildWingKey(input.loop.workspaceId, input.loop.projectId);
89
+ const wingPath = join(memoryRoot, slugifyKey(wingKey));
90
+ const drawers = buildMemoryDrawers(input);
91
+ const grouped = new Map();
92
+ for (const drawer of drawers) {
93
+ const bucket = grouped.get(drawer.roomKey) ?? [];
94
+ bucket.push(drawer);
95
+ grouped.set(drawer.roomKey, bucket);
96
+ }
97
+ await mkdir(wingPath, { recursive: true });
98
+ await writeJsonFile(join(wingPath, "wing.json"), {
99
+ wingKey,
100
+ workspaceId: input.loop.workspaceId,
101
+ projectId: input.loop.projectId,
102
+ roomCount: grouped.size,
103
+ updatedAt: input.loop.updatedAt
104
+ });
105
+ for (const [roomKey, roomDrawers] of grouped.entries()) {
106
+ const roomPath = join(wingPath, slugifyKey(roomKey));
107
+ const previousDrawers = await readDrawersFile(join(roomPath, "drawers.jsonl"));
108
+ await mkdir(roomPath, { recursive: true });
109
+ await writeJsonFile(join(roomPath, "room.json"), {
110
+ wingKey,
111
+ roomKey,
112
+ roomTitle: roomDrawers[0]?.roomTitle ?? roomKey,
113
+ roomType: roomDrawers[0]?.outcome === "failure" ? "failure" : "outcome",
114
+ drawerCount: previousDrawers.length + roomDrawers.length,
115
+ lastRunId: input.loop.loopId,
116
+ updatedAt: input.loop.updatedAt
117
+ });
118
+ const payload = roomDrawers.map((drawer) => JSON.stringify(drawer)).join("\n");
119
+ await appendFile(join(roomPath, "drawers.jsonl"), `${payload}\n`, "utf8");
120
+ }
121
+ return {
122
+ roomCount: grouped.size,
123
+ drawerCount: drawers.length
124
+ };
125
+ },
126
+ async recordPriorLearning(input) {
127
+ // Phase 30 — Guarded Promotion Pipeline
128
+ // Runs the full shadow → holdout → approval gate pipeline before any
129
+ // heuristic insight is promoted to active status. Fail-open: any error
130
+ // keeps existing heuristics active and appends to audit log only.
131
+ const auditPath = join(memoryRoot, "prior-learning-audit.jsonl");
132
+ try {
133
+ const candidateId = `cand_${createHash("sha256")
134
+ .update(JSON.stringify({ ...input, ts: Date.now() }))
135
+ .digest("hex")
136
+ .slice(0, 16)}`;
137
+ const existingScores = Array.isArray(input["existingScores"])
138
+ ? input["existingScores"]
139
+ : [];
140
+ const candidateScores = Array.isArray(input["candidateScores"])
141
+ ? input["candidateScores"]
142
+ : [];
143
+ const holdoutExistingScores = Array.isArray(input["holdoutExistingScores"])
144
+ ? input["holdoutExistingScores"]
145
+ : [];
146
+ const holdoutCandidateScores = Array.isArray(input["holdoutCandidateScores"])
147
+ ? input["holdoutCandidateScores"]
148
+ : [];
149
+ const candidate = {
150
+ candidateId,
151
+ sourceRunId: typeof input["sourceRunId"] === "string" ? input["sourceRunId"] : "unknown",
152
+ heuristicFamily: typeof input["heuristicFamily"] === "string" ? input["heuristicFamily"] : "recall_scoring",
153
+ description: typeof input["description"] === "string" ? input["description"] : "Prior learning candidate",
154
+ payload: input,
155
+ status: "pending_shadow",
156
+ createdAt: new Date().toISOString()
157
+ };
158
+ const result = await runPromotionPipeline({
159
+ candidate,
160
+ existingScores,
161
+ candidateScores,
162
+ holdoutExistingScores,
163
+ holdoutCandidateScores,
164
+ pipelineRoot: memoryRoot
165
+ });
166
+ const auditEntry = JSON.stringify({
167
+ candidateId,
168
+ promoted: result.promoted,
169
+ reason: result.reason,
170
+ timestamp: new Date().toISOString()
171
+ });
172
+ await appendFile(auditPath, `${auditEntry}\n`, "utf8");
173
+ }
174
+ catch {
175
+ // Fail-open: append raw input to audit log, never block the caller
176
+ const fallbackEntry = JSON.stringify({ ...input, timestamp: new Date().toISOString() });
177
+ await appendFile(auditPath, `${fallbackEntry}\n`, "utf8");
178
+ }
179
+ }
180
+ };
181
+ }
182
+ function buildMemoryDrawers(input) {
183
+ const wingKey = buildWingKey(input.loop.workspaceId, input.loop.projectId);
184
+ const createdAt = input.loop.updatedAt;
185
+ const drawers = input.loop.attempts.map((attempt) => {
186
+ const failureClass = attempt.failureClass;
187
+ const roomKey = failureClass ? `failure/${failureClass}` : "outcome/completion";
188
+ const roomTitle = failureClass
189
+ ? `Failure · ${failureClass}`
190
+ : "Outcome · completion";
191
+ const lesson = failureClass
192
+ ? `A similar loop hit ${failureClass}${attempt.intervention ? ` and required ${attempt.intervention}` : ""}. Reuse that narrower recovery before widening scope or changing model.`
193
+ : `A similar loop completed without widening scope. Reuse the same narrow, verifier-first shape before trying a broader patch.`;
194
+ const content = [
195
+ input.loop.task.title,
196
+ input.loop.task.objective,
197
+ attempt.summary,
198
+ attempt.verifierSummary
199
+ ]
200
+ .filter((value) => Boolean(value?.trim()))
201
+ .join(" ");
202
+ return {
203
+ drawerId: buildDrawerId(input.loop.loopId, roomKey, attempt.index, createdAt),
204
+ wingKey,
205
+ roomKey,
206
+ roomTitle,
207
+ workspaceId: input.loop.workspaceId,
208
+ projectId: input.loop.projectId,
209
+ sourceRunId: input.loop.loopId,
210
+ sourceAttemptIndex: attempt.index,
211
+ outcome: failureClass ? "failure" : "completion",
212
+ ...(failureClass ? { failureClass } : {}),
213
+ ...(attempt.intervention ? { intervention: attempt.intervention } : {}),
214
+ tags: compact([
215
+ failureClass,
216
+ attempt.intervention,
217
+ ...extractPathTags(input.loop.task.allowedPaths)
218
+ ]),
219
+ tokens: buildDrawerTokens(content, failureClass, attempt.intervention),
220
+ lesson,
221
+ content,
222
+ createdAt
223
+ };
224
+ });
225
+ const runRoomKey = input.status === "completed" ? "outcome/completed" : "outcome/exited";
226
+ const runLesson = input.status === "completed"
227
+ ? `A prior loop finished inside the declared contract. Prefer the same bounded route before widening files, network, or dependency scope.`
228
+ : `A prior loop exited in ${input.lifecycleState}. Preserve the guardrail and avoid forcing a fake completion.`;
229
+ const runContent = [
230
+ input.loop.task.title,
231
+ input.loop.task.objective,
232
+ input.reason
233
+ ]
234
+ .filter((value) => Boolean(value?.trim()))
235
+ .join(" ");
236
+ drawers.push({
237
+ drawerId: buildDrawerId(input.loop.loopId, runRoomKey, 0, createdAt),
238
+ wingKey,
239
+ roomKey: runRoomKey,
240
+ roomTitle: input.status === "completed" ? "Outcome · completed" : "Outcome · exited",
241
+ workspaceId: input.loop.workspaceId,
242
+ projectId: input.loop.projectId,
243
+ sourceRunId: input.loop.loopId,
244
+ outcome: input.status === "completed" ? "completion" : "exit",
245
+ tags: compact([
246
+ input.status,
247
+ input.lifecycleState,
248
+ ...extractPathTags(input.loop.task.allowedPaths)
249
+ ]),
250
+ tokens: buildDrawerTokens(runContent, undefined, undefined),
251
+ lesson: runLesson,
252
+ content: runContent,
253
+ createdAt
254
+ });
255
+ return drawers;
256
+ }
257
+ function scoreDrawer(drawer, queryTokens, lastAttempt, heuristics) {
258
+ const reasons = [];
259
+ let score = 0;
260
+ if (lastAttempt?.failureClass && drawer.failureClass === lastAttempt.failureClass) {
261
+ score += heuristics.failureClassWeight;
262
+ reasons.push("matched failure class");
263
+ }
264
+ if (lastAttempt?.intervention && drawer.intervention === lastAttempt.intervention) {
265
+ score += heuristics.interventionWeight;
266
+ reasons.push("matched intervention");
267
+ }
268
+ const overlap = countIntersection(queryTokens, drawer.tokens);
269
+ if (overlap > 0) {
270
+ score += overlap * heuristics.tokenOverlapWeight;
271
+ reasons.push("matched objective tokens");
272
+ }
273
+ if (drawer.outcome === "completion") {
274
+ score += heuristics.completionWeight;
275
+ reasons.push("completion memory");
276
+ }
277
+ return {
278
+ score,
279
+ reason: reasons.join(" and ")
280
+ };
281
+ }
282
+ function buildQueryTokens(objective, focus, attempts) {
283
+ const lastAttempt = attempts.at(-1);
284
+ return uniqueTokens([
285
+ ...tokenize(objective),
286
+ ...tokenize(focus),
287
+ ...tokenize(lastAttempt?.summary ?? ""),
288
+ ...(lastAttempt?.failureClass ? [lastAttempt.failureClass] : []),
289
+ ...(lastAttempt?.intervention ? [lastAttempt.intervention] : [])
290
+ ]);
291
+ }
292
+ function buildDrawerTokens(content, failureClass, intervention) {
293
+ return uniqueTokens([
294
+ ...tokenize(content),
295
+ ...(failureClass ? [failureClass] : []),
296
+ ...(intervention ? [intervention] : [])
297
+ ]);
298
+ }
299
+ function tokenize(value) {
300
+ return (value.toLowerCase().match(/[a-z0-9_/-]{3,}/g) ?? []).filter((token) => !STOP_WORDS.has(token));
301
+ }
302
+ function uniqueTokens(values) {
303
+ return [...new Set(values.filter((value) => value.trim().length > 0))];
304
+ }
305
+ function countIntersection(left, right) {
306
+ const rightSet = new Set(right);
307
+ return left.filter((token) => rightSet.has(token)).length;
308
+ }
309
+ function extractPathTags(paths) {
310
+ return compact((paths ?? [])
311
+ .map((path) => path.split(/[\\/]/u)[0])
312
+ .filter((segment) => Boolean(segment && segment !== "**" && segment.trim().length > 0)));
313
+ }
314
+ function buildWingKey(workspaceId, projectId) {
315
+ return `${workspaceId}::${projectId}`;
316
+ }
317
+ function buildDrawerId(runId, roomKey, attemptIndex, createdAt) {
318
+ return createHash("sha256")
319
+ .update(`${runId}:${roomKey}:${String(attemptIndex)}:${createdAt}`)
320
+ .digest("hex")
321
+ .slice(0, 16);
322
+ }
323
+ function slugifyKey(value) {
324
+ return value
325
+ .replace(/::/g, "--")
326
+ .replace(/[^a-zA-Z0-9]+/g, "-")
327
+ .replace(/^-+|-+$/g, "")
328
+ .toLowerCase();
329
+ }
330
+ async function readDrawersFile(filePath) {
331
+ try {
332
+ const raw = await readFile(filePath, "utf8");
333
+ return raw
334
+ .split(/\r?\n/u)
335
+ .map((line) => line.trim())
336
+ .filter(Boolean)
337
+ .map((line) => JSON.parse(line));
338
+ }
339
+ catch {
340
+ return [];
341
+ }
342
+ }
343
+ async function safeReaddir(directory) {
344
+ try {
345
+ return await readdir(directory);
346
+ }
347
+ catch {
348
+ return [];
349
+ }
350
+ }
351
+ async function persistRecallAudit(input) {
352
+ const wingPath = join(input.memoryRoot, slugifyKey(input.wingKey));
353
+ await mkdir(wingPath, { recursive: true });
354
+ const recalledAt = new Date().toISOString();
355
+ const payload = input.entries
356
+ .map((entry) => JSON.stringify({
357
+ recallId: createHash("sha256")
358
+ .update(`${input.runId}:${String(input.attemptIndex)}:${entry.drawerId}:${recalledAt}`)
359
+ .digest("hex")
360
+ .slice(0, 16),
361
+ wingKey: input.wingKey,
362
+ roomKey: entry.roomKey,
363
+ drawerId: entry.drawerId,
364
+ runId: input.runId,
365
+ attemptIndex: input.attemptIndex,
366
+ recallScore: entry.score,
367
+ recallReason: entry.reason,
368
+ recalledAt
369
+ }))
370
+ .join("\n");
371
+ await appendFile(join(wingPath, "recalls.jsonl"), `${payload}\n`, "utf8");
372
+ }
373
+ async function writeJsonFile(path, value) {
374
+ await writeFile(path, `${JSON.stringify(value, null, 2)}\n`, "utf8");
375
+ }
376
+ function compact(values) {
377
+ return values.filter((value) => Boolean(value?.trim()));
378
+ }
379
+ //# sourceMappingURL=palace.js.map
@@ -0,0 +1,22 @@
1
+ export type MergeType = "ast" | "text" | "trivial";
2
+ export type ConflictType = "same_function_body" | "delete_vs_modify" | "symbol_conflict";
3
+ export interface MergeResult {
4
+ conflict: boolean;
5
+ conflictType?: ConflictType;
6
+ conflictReport?: string;
7
+ mergedDiff?: string;
8
+ mergeType: MergeType;
9
+ tsMorphError?: boolean;
10
+ }
11
+ export interface MergeArtifact {
12
+ runId: string;
13
+ patchA: string;
14
+ patchB: string;
15
+ result: MergeResult;
16
+ producedAt: string;
17
+ }
18
+ export declare function astMerge(baseSource: string, patchA: string, patchB: string, options?: {
19
+ filePath?: string;
20
+ runId?: string;
21
+ }): MergeResult;
22
+ export declare function buildMergeArtifact(runId: string, patchA: string, patchB: string, result: MergeResult): MergeArtifact;