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,7 @@
1
+ import type { MartinAdapter } from "../core/index.js";
2
+ export interface VerifierOnlyAdapterOptions {
3
+ workingDirectory?: string;
4
+ verifyTimeoutMs?: number;
5
+ label?: string;
6
+ }
7
+ export declare function createVerifierOnlyAdapter(options?: VerifierOnlyAdapterOptions): MartinAdapter;
@@ -0,0 +1,57 @@
1
+ import { readGitExecutionArtifacts, runVerification } from "./cli-bridge.js";
2
+ import { createAdapterCapabilities, normalizeUsage } from "./runtime-support.js";
3
+ export function createVerifierOnlyAdapter(options = {}) {
4
+ const workingDirectory = options.workingDirectory ?? process.cwd();
5
+ const verifyTimeoutMs = options.verifyTimeoutMs ?? 60_000;
6
+ return {
7
+ adapterId: "direct:verifier:verify-only",
8
+ kind: "direct-provider",
9
+ label: options.label ?? "Verifier-only adapter",
10
+ metadata: {
11
+ providerId: "verifier",
12
+ model: "verify-only",
13
+ transport: "cli",
14
+ capabilities: createAdapterCapabilities({
15
+ usageSettlement: true,
16
+ diffArtifacts: true
17
+ })
18
+ },
19
+ async execute(request) {
20
+ const verification = await runVerification(request.context.verificationPlan, workingDirectory, verifyTimeoutMs, request.context.verificationStack);
21
+ const execution = await readGitExecutionArtifacts(workingDirectory, 5_000);
22
+ const changedFiles = execution.changedFiles ?? [];
23
+ if (verification.passed) {
24
+ return {
25
+ status: "completed",
26
+ summary: changedFiles.length > 0
27
+ ? `Verifier-only run completed but modified files: ${changedFiles.join(", ")}`
28
+ : "Verifier-only run completed without file edits.",
29
+ usage: normalizeUsage({
30
+ actualUsd: 0,
31
+ tokensIn: 0,
32
+ tokensOut: 0,
33
+ provenance: "actual"
34
+ }),
35
+ verification,
36
+ execution
37
+ };
38
+ }
39
+ return {
40
+ status: "failed",
41
+ summary: "Verifier-only run failed.",
42
+ usage: normalizeUsage({
43
+ actualUsd: 0,
44
+ tokensIn: 0,
45
+ tokensOut: 0,
46
+ provenance: "actual"
47
+ }),
48
+ verification,
49
+ execution,
50
+ failure: {
51
+ message: verification.summary
52
+ }
53
+ };
54
+ }
55
+ };
56
+ }
57
+ //# sourceMappingURL=verifier-only.js.map
@@ -0,0 +1,12 @@
1
+ import type { Writable } from "node:stream";
2
+ export interface CliProcessResult {
3
+ exitCode: number;
4
+ stdout: string;
5
+ stderr: string;
6
+ }
7
+ export interface CliExitRuntime {
8
+ stdout: Writable;
9
+ stderr: Writable;
10
+ exit: (code: number) => void;
11
+ }
12
+ export declare function writeCliResultAndExit(result: CliProcessResult, runtime?: CliExitRuntime): Promise<void>;
@@ -0,0 +1,28 @@
1
+ export async function writeCliResultAndExit(result, runtime = {
2
+ stdout: process.stdout,
3
+ stderr: process.stderr,
4
+ exit: (code) => {
5
+ process.exit(code);
6
+ }
7
+ }) {
8
+ await Promise.all([
9
+ writeStream(runtime.stdout, result.stdout),
10
+ writeStream(runtime.stderr, result.stderr)
11
+ ]);
12
+ runtime.exit(result.exitCode);
13
+ }
14
+ function writeStream(stream, value) {
15
+ if (!value) {
16
+ return Promise.resolve();
17
+ }
18
+ return new Promise((resolve, reject) => {
19
+ stream.write(`${value}\n`, (error) => {
20
+ if (error) {
21
+ reject(error);
22
+ return;
23
+ }
24
+ resolve();
25
+ });
26
+ });
27
+ }
28
+ //# sourceMappingURL=exit.js.map
@@ -0,0 +1,5 @@
1
+ export declare function handleAnalyzeCommand(args: string[]): Promise<{
2
+ stdout: string;
3
+ stderr: string;
4
+ exitCode: number;
5
+ }>;
@@ -0,0 +1,58 @@
1
+ import { join } from "node:path";
2
+ import { analyzeRuns, buildReport, computeStats, createRlmClient, readRuns, renderMarkdown, writeReport } from "@martin/trace-intelligence";
3
+ export async function handleAnalyzeCommand(args) {
4
+ const maxRuns = parseIntFlag(args, "--runs") ?? 20;
5
+ const since = parseFlag(args, "--since");
6
+ const output = parseFlag(args, "--output");
7
+ const runsRoot = parseFlag(args, "--runs-root");
8
+ const noRlm = args.includes("--no-rlm");
9
+ const jsonOut = args.includes("--json");
10
+ try {
11
+ const runs = await readRuns({ maxRuns, since, runsRoot });
12
+ if (runs.length === 0) {
13
+ return {
14
+ exitCode: 0,
15
+ stdout: "",
16
+ stderr: "No runs found. Run martin-loop at least once to generate trace data."
17
+ };
18
+ }
19
+ const rlmClient = noRlm ? undefined : createRlmClient();
20
+ const analysis = await analyzeRuns(runs, noRlm ? { deterministicOnly: true } : { client: rlmClient });
21
+ const stats = computeStats(runs);
22
+ const report = buildReport(runs, analysis, stats);
23
+ if (jsonOut) {
24
+ return {
25
+ exitCode: 0,
26
+ stdout: JSON.stringify(report, null, 2),
27
+ stderr: ""
28
+ };
29
+ }
30
+ const jsonPath = output ? join(output) : "trace-report.json";
31
+ const mdPath = jsonPath.replace(/\.json$/, ".md");
32
+ const { jsonPath: writtenJson, mdPath: writtenMd } = await writeReport(report, {
33
+ jsonOutput: jsonPath,
34
+ mdOutput: mdPath
35
+ });
36
+ return {
37
+ exitCode: 0,
38
+ stdout: renderMarkdown(report),
39
+ stderr: `\nReports written:\n ${writtenJson}\n ${writtenMd}\n`
40
+ };
41
+ }
42
+ catch (err) {
43
+ const message = err instanceof Error ? err.message : String(err);
44
+ return { exitCode: 1, stdout: "", stderr: `Error: ${message}` };
45
+ }
46
+ }
47
+ function parseFlag(args, flag) {
48
+ const idx = args.indexOf(flag);
49
+ return idx >= 0 ? args[idx + 1] : undefined;
50
+ }
51
+ function parseIntFlag(args, flag) {
52
+ const val = parseFlag(args, flag);
53
+ if (val === undefined)
54
+ return undefined;
55
+ const n = parseInt(val, 10);
56
+ return isNaN(n) ? undefined : n;
57
+ }
58
+ //# sourceMappingURL=analyze.js.map
@@ -0,0 +1,34 @@
1
+ /**
2
+ * audit-log-verify.ts
3
+ *
4
+ * Implements `martin audit log-verify [--from ISO] [--to ISO]`.
5
+ *
6
+ * Walks every run directory in the Martin run store, verifies the Ed25519
7
+ * signature on each loop-record.json, and reports gaps, tamper evidence,
8
+ * and an overall PASS/FAIL verdict.
9
+ *
10
+ * Ed25519 verification is performed via verifyLoopRecordAttestation() from
11
+ * @martin/core — the same signing infrastructure used during run settlement.
12
+ */
13
+ export interface AuditLogVerifyOptions {
14
+ /** ISO 8601 date string — only verify runs created on or after this date */
15
+ from?: string;
16
+ /** ISO 8601 date string — only verify runs created on or before this date */
17
+ to?: string;
18
+ /** Override the default runs root directory */
19
+ runsRoot?: string;
20
+ }
21
+ export interface AuditLogVerifyResult {
22
+ runsRoot: string;
23
+ rangeFrom: string;
24
+ rangeTo: string;
25
+ eventsChecked: number;
26
+ signaturesFailed: number;
27
+ gaps: string[];
28
+ failures: Array<{
29
+ runId: string;
30
+ reason: string;
31
+ }>;
32
+ verdict: "PASS" | "FAIL";
33
+ }
34
+ export declare function runAuditLogVerify(options?: AuditLogVerifyOptions): Promise<AuditLogVerifyResult>;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * audit-log-verify.ts
3
+ *
4
+ * Implements `martin audit log-verify [--from ISO] [--to ISO]`.
5
+ *
6
+ * Walks every run directory in the Martin run store, verifies the Ed25519
7
+ * signature on each loop-record.json, and reports gaps, tamper evidence,
8
+ * and an overall PASS/FAIL verdict.
9
+ *
10
+ * Ed25519 verification is performed via verifyLoopRecordAttestation() from
11
+ * @martin/core — the same signing infrastructure used during run settlement.
12
+ */
13
+ import { readdir, readFile, stat } from "node:fs/promises";
14
+ import { join } from "node:path";
15
+ import { resolveRunsRoot, verifyLoopRecordAttestation } from "../../core/index.js";
16
+ export async function runAuditLogVerify(options = {}) {
17
+ const runsRoot = options.runsRoot ?? resolveRunsRoot(process.env);
18
+ const fromMs = options.from ? new Date(options.from).getTime() : 0;
19
+ const toMs = options.to ? new Date(options.to).getTime() : Date.now();
20
+ const rangeFrom = new Date(fromMs).toISOString();
21
+ const rangeTo = new Date(toMs).toISOString();
22
+ // Enumerate run directories — each is a directory named by loopId
23
+ let entries;
24
+ try {
25
+ entries = await readdir(runsRoot);
26
+ }
27
+ catch {
28
+ // Run store doesn't exist yet — zero runs is a valid "PASS" state
29
+ return {
30
+ runsRoot,
31
+ rangeFrom,
32
+ rangeTo,
33
+ eventsChecked: 0,
34
+ signaturesFailed: 0,
35
+ gaps: [],
36
+ failures: [],
37
+ verdict: "PASS",
38
+ };
39
+ }
40
+ const runDirs = [];
41
+ for (const entry of entries) {
42
+ const full = join(runsRoot, entry);
43
+ try {
44
+ const info = await stat(full);
45
+ if (info.isDirectory()) {
46
+ runDirs.push(full);
47
+ }
48
+ }
49
+ catch {
50
+ // skip unreadable entries
51
+ }
52
+ }
53
+ // Filter by date range using loop-record.json createdAt field
54
+ const inRangeDirs = [];
55
+ const gaps = [];
56
+ for (const runDir of runDirs) {
57
+ const recordPath = join(runDir, "loop-record.json");
58
+ try {
59
+ const raw = await readFile(recordPath, "utf8");
60
+ const record = JSON.parse(raw);
61
+ const createdMs = record.createdAt ? new Date(record.createdAt).getTime() : NaN;
62
+ if (isNaN(createdMs)) {
63
+ gaps.push(`${runDir}: missing or unparseable createdAt`);
64
+ continue;
65
+ }
66
+ if (createdMs >= fromMs && createdMs <= toMs) {
67
+ inRangeDirs.push(runDir);
68
+ }
69
+ }
70
+ catch {
71
+ gaps.push(`${runDir}: loop-record.json unreadable — possible gap in audit trail`);
72
+ }
73
+ }
74
+ // Verify each in-range run
75
+ const failures = [];
76
+ for (const runDir of inRangeDirs) {
77
+ const result = await verifyLoopRecordAttestation(runDir);
78
+ if (!result.ok) {
79
+ failures.push({
80
+ runId: runDir.split(/[\\/]/).pop() ?? runDir,
81
+ reason: result.reason ?? "signature verification failed",
82
+ });
83
+ }
84
+ }
85
+ const eventsChecked = inRangeDirs.length;
86
+ const signaturesFailed = failures.length;
87
+ const verdict = signaturesFailed === 0 && gaps.length === 0 ? "PASS" : "FAIL";
88
+ return {
89
+ runsRoot,
90
+ rangeFrom,
91
+ rangeTo,
92
+ eventsChecked,
93
+ signaturesFailed,
94
+ gaps,
95
+ failures,
96
+ verdict,
97
+ };
98
+ }
99
+ //# sourceMappingURL=audit-log-verify.js.map
@@ -0,0 +1,8 @@
1
+ export interface AuditCommandResult {
2
+ stdout: string;
3
+ stderr: string;
4
+ exitCode: number;
5
+ }
6
+ export declare function handleAuditCommand(args: string[], options?: {
7
+ cwd?: string;
8
+ }): Promise<AuditCommandResult>;
@@ -0,0 +1,199 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { generateAuditPackFromRunDirectory, verifyAuditPack } from "@martin/contracts/audit";
4
+ import { resolveRunsRoot } from "../../core/index.js";
5
+ export async function handleAuditCommand(args, options = {}) {
6
+ const subcommand = args[0];
7
+ try {
8
+ switch (subcommand) {
9
+ case "generate": {
10
+ const runId = parseFlag(args, "--run-id");
11
+ const output = parseFlag(args, "--output") ?? join(options.cwd ?? process.cwd(), "audit-pack");
12
+ if (!runId) {
13
+ return { stdout: "", stderr: "Missing --run-id", exitCode: 1 };
14
+ }
15
+ const result = await generateAuditPackFromRunDirectory({
16
+ runId,
17
+ runDir: join(resolveRunsRoot(process.env), runId),
18
+ outputDir: output,
19
+ generatedBy: "martin"
20
+ });
21
+ return {
22
+ stdout: JSON.stringify({
23
+ command: "audit.generate",
24
+ runId,
25
+ packPath: result.packPath,
26
+ manifest: result.manifest
27
+ }, null, 2),
28
+ stderr: "",
29
+ exitCode: 0
30
+ };
31
+ }
32
+ case "verify": {
33
+ const pack = parseFlag(args, "--pack");
34
+ if (!pack) {
35
+ return { stdout: "", stderr: "Missing --pack", exitCode: 1 };
36
+ }
37
+ const result = await verifyAuditPack(pack);
38
+ return formatVerificationResult(result);
39
+ }
40
+ case "show": {
41
+ const runId = parseFlag(args, "--run-id");
42
+ if (!runId) {
43
+ return { stdout: "", stderr: "Missing --run-id", exitCode: 1 };
44
+ }
45
+ const runsRoot = parseFlag(args, "--runs-root") ?? resolveRunsRoot(process.env);
46
+ const summary = await summarizeRunAudit(join(runsRoot, runId), runId);
47
+ return {
48
+ stdout: JSON.stringify({
49
+ command: "audit.show",
50
+ ...summary
51
+ }, null, 2),
52
+ stderr: "",
53
+ exitCode: 0
54
+ };
55
+ }
56
+ case "log-verify": {
57
+ const { runAuditLogVerify } = await import("./audit-log-verify.js");
58
+ const from = parseFlag(args, "--from");
59
+ const to = parseFlag(args, "--to");
60
+ const runsRoot = parseFlag(args, "--runs-root");
61
+ const result = await runAuditLogVerify({ from, to, runsRoot });
62
+ const output = JSON.stringify({
63
+ command: "audit.log-verify",
64
+ ...result,
65
+ }, null, 2);
66
+ if (result.verdict === "PASS") {
67
+ return { stdout: output, stderr: "", exitCode: 0 };
68
+ }
69
+ return { stdout: "", stderr: output, exitCode: 1 };
70
+ }
71
+ default:
72
+ return {
73
+ stdout: "",
74
+ stderr: [
75
+ "Usage: martin audit <subcommand> [options]",
76
+ "",
77
+ "Subcommands:",
78
+ " generate --run-id <id> --output <dir> Generate audit pack",
79
+ " verify --pack <dir> Verify audit pack manifest",
80
+ " show --run-id <id> [--runs-root <dir>] Summarize persisted run audit evidence",
81
+ " log-verify [--from ISO] [--to ISO] Verify Ed25519 signatures across run log"
82
+ ].join("\n"),
83
+ exitCode: 1
84
+ };
85
+ }
86
+ }
87
+ catch (error) {
88
+ const message = error instanceof Error ? error.message : String(error);
89
+ return { stdout: "", stderr: message, exitCode: 1 };
90
+ }
91
+ }
92
+ async function summarizeRunAudit(runDir, runId) {
93
+ const [contract, state, loop, ledger, attemptDirs] = await Promise.all([
94
+ readJsonIfExists(join(runDir, "contract.json")),
95
+ readJsonIfExists(join(runDir, "state.json")),
96
+ readJsonIfExists(join(runDir, "loop-record.json")),
97
+ readLedgerIfExists(join(runDir, "ledger.jsonl")),
98
+ readAttemptDirs(join(runDir, "artifacts"))
99
+ ]);
100
+ const eventKinds = ledger.reduce((counts, event) => {
101
+ const kind = typeof event.kind === "string" ? event.kind : "unknown";
102
+ counts[kind] = (counts[kind] ?? 0) + 1;
103
+ return counts;
104
+ }, {});
105
+ const loopRecord = isRecord(loop) ? loop : undefined;
106
+ const contractRecord = isRecord(contract) ? contract : undefined;
107
+ const stateRecord = isRecord(state) ? state : undefined;
108
+ const task = isRecord(loopRecord?.task)
109
+ ? loopRecord.task
110
+ : isRecord(contractRecord?.task)
111
+ ? contractRecord.task
112
+ : undefined;
113
+ return {
114
+ runId,
115
+ runDir,
116
+ status: asString(loopRecord?.status) ?? "unknown",
117
+ lifecycleState: asString(loopRecord?.lifecycleState) ?? asString(stateRecord?.phase) ?? null,
118
+ taskTitle: asString(task?.title) ?? null,
119
+ attempts: Array.isArray(loopRecord?.attempts) ? loopRecord.attempts.length : attemptDirs.length,
120
+ ledgerEvents: ledger.length,
121
+ eventKinds,
122
+ cost: isRecord(loopRecord?.cost) ? loopRecord.cost : null,
123
+ artifacts: {
124
+ hasContract: contract !== null,
125
+ hasState: state !== null,
126
+ hasLoopRecord: loop !== null,
127
+ attemptDirs
128
+ }
129
+ };
130
+ }
131
+ async function readJsonIfExists(path) {
132
+ try {
133
+ return JSON.parse(await readFile(path, "utf8"));
134
+ }
135
+ catch {
136
+ return null;
137
+ }
138
+ }
139
+ async function readLedgerIfExists(path) {
140
+ try {
141
+ const contents = await readFile(path, "utf8");
142
+ return contents
143
+ .trim()
144
+ .split(/\r?\n/u)
145
+ .filter(Boolean)
146
+ .map((line) => JSON.parse(line));
147
+ }
148
+ catch {
149
+ return [];
150
+ }
151
+ }
152
+ async function readAttemptDirs(path) {
153
+ try {
154
+ const entries = await readdir(path, { withFileTypes: true });
155
+ return entries
156
+ .filter((entry) => entry.isDirectory() && entry.name.startsWith("attempt-"))
157
+ .map((entry) => entry.name)
158
+ .sort();
159
+ }
160
+ catch {
161
+ return [];
162
+ }
163
+ }
164
+ function isRecord(value) {
165
+ return typeof value === "object" && value !== null && !Array.isArray(value);
166
+ }
167
+ function asString(value) {
168
+ return typeof value === "string" ? value : undefined;
169
+ }
170
+ function formatVerificationResult(result) {
171
+ if (result.ok) {
172
+ return {
173
+ stdout: JSON.stringify({
174
+ command: "audit.verify",
175
+ status: "passed",
176
+ manifest: result.manifest,
177
+ checkedFiles: result.checkedFiles.length
178
+ }, null, 2),
179
+ stderr: "",
180
+ exitCode: 0
181
+ };
182
+ }
183
+ return {
184
+ stdout: "",
185
+ stderr: JSON.stringify({
186
+ command: "audit.verify",
187
+ status: "failed",
188
+ failures: result.failures
189
+ }, null, 2),
190
+ exitCode: 1
191
+ };
192
+ }
193
+ function parseFlag(args, flag) {
194
+ const idx = args.indexOf(flag);
195
+ if (idx === -1 || idx >= args.length - 1)
196
+ return undefined;
197
+ return args[idx + 1];
198
+ }
199
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +1,5 @@
1
+ export declare function handleCorpusCommand(args: string[]): Promise<{
2
+ stdout: string;
3
+ stderr: string;
4
+ exitCode: number;
5
+ }>;
@@ -0,0 +1,60 @@
1
+ import { computeCorpusStats, loadCorpus, resolveEntry, resolveCorpusPath, saveCorpus } from "@martin/trace-intelligence";
2
+ export async function handleCorpusCommand(args) {
3
+ const subcommand = args[0];
4
+ const corpusPath = resolveCorpusPath();
5
+ try {
6
+ const corpus = await loadCorpus(corpusPath);
7
+ switch (subcommand) {
8
+ case "show":
9
+ case undefined: {
10
+ const stats = computeCorpusStats(corpus);
11
+ const lines = [
12
+ `Corpus: ${corpusPath}`,
13
+ `Entries: ${stats.totalEntries} (${stats.resolvedEntries} resolved, ${stats.activeEntries} open)`,
14
+ ""
15
+ ];
16
+ if (corpus.entries.length === 0) {
17
+ lines.push("No patterns in corpus yet. Run martin analyze to populate.");
18
+ }
19
+ else {
20
+ for (const entry of corpus.entries) {
21
+ const resolved = entry.resolved ? "[resolved]" : "[open] ";
22
+ lines.push(`${resolved} ${entry.fingerprint.slice(0, 12)} ${entry.kind} (${entry.severity}) — seen ${entry.occurrenceCount}x, ${entry.totalAffectedRuns} runs`);
23
+ }
24
+ }
25
+ return { exitCode: 0, stdout: lines.join("\n"), stderr: "" };
26
+ }
27
+ case "clear": {
28
+ const cleared = { ...corpus, entries: [], updatedAt: new Date().toISOString() };
29
+ await saveCorpus(cleared, corpusPath);
30
+ return { exitCode: 0, stdout: `Corpus cleared (${corpus.entries.length} entries removed).`, stderr: "" };
31
+ }
32
+ case "resolve": {
33
+ const fingerprint = args[1];
34
+ if (!fingerprint) {
35
+ return { exitCode: 1, stdout: "", stderr: "Usage: martin corpus resolve <fingerprint>" };
36
+ }
37
+ try {
38
+ const updated = resolveEntry(corpus, fingerprint);
39
+ await saveCorpus(updated, corpusPath);
40
+ return { exitCode: 0, stdout: `Entry ${fingerprint} marked as resolved.`, stderr: "" };
41
+ }
42
+ catch (resolveErr) {
43
+ const msg = resolveErr instanceof Error ? resolveErr.message : String(resolveErr);
44
+ return { exitCode: 1, stdout: "", stderr: msg };
45
+ }
46
+ }
47
+ default:
48
+ return {
49
+ exitCode: 1,
50
+ stdout: "",
51
+ stderr: `Unknown corpus subcommand: ${subcommand}\nUsage: martin corpus [show|clear|resolve <fingerprint>]`
52
+ };
53
+ }
54
+ }
55
+ catch (err) {
56
+ const message = err instanceof Error ? err.message : String(err);
57
+ return { exitCode: 1, stdout: "", stderr: `Error: ${message}` };
58
+ }
59
+ }
60
+ //# sourceMappingURL=corpus.js.map
@@ -0,0 +1,8 @@
1
+ export interface DoctorCommandResult {
2
+ stdout: string;
3
+ stderr: string;
4
+ exitCode: number;
5
+ }
6
+ export declare function handleDoctorCommand(args: string[], options?: {
7
+ cwd?: string;
8
+ }): Promise<DoctorCommandResult>;