martin-loop 0.1.5 → 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 (274) hide show
  1. package/CODE_OF_CONDUCT.md +32 -0
  2. package/LICENSE +21 -21
  3. package/README.md +307 -398
  4. package/demo/seeded-workspace/README.md +35 -35
  5. package/demo/seeded-workspace/TASKS.md +29 -29
  6. package/demo/seeded-workspace/martin.config.yaml +11 -11
  7. package/demo/seeded-workspace/package.json +8 -8
  8. package/demo/seeded-workspace/src/invoice-summary.js +11 -11
  9. package/demo/seeded-workspace/test/invoice-summary.test.js +20 -20
  10. package/dist/bin/martin-loop.js +0 -0
  11. package/dist/vendor/adapters/counter.d.ts +1 -0
  12. package/dist/vendor/adapters/counter.js +4 -0
  13. package/dist/vendor/adapters/git-baseline.d.ts +50 -0
  14. package/dist/vendor/adapters/git-baseline.js +233 -0
  15. package/dist/vendor/adapters/openrouter-adapter.d.ts +15 -0
  16. package/dist/vendor/adapters/openrouter-adapter.js +302 -0
  17. package/dist/vendor/adapters/usage.d.ts +48 -0
  18. package/dist/vendor/adapters/usage.js +66 -0
  19. package/dist/vendor/cli/bin/exit.d.ts +12 -0
  20. package/dist/vendor/cli/bin/exit.js +28 -0
  21. package/dist/vendor/cli/commands/analyze.d.ts +5 -0
  22. package/dist/vendor/cli/commands/analyze.js +58 -0
  23. package/dist/vendor/cli/commands/audit-log-verify.d.ts +34 -0
  24. package/dist/vendor/cli/commands/audit-log-verify.js +99 -0
  25. package/dist/vendor/cli/commands/audit.d.ts +8 -0
  26. package/dist/vendor/cli/commands/audit.js +199 -0
  27. package/dist/vendor/cli/commands/corpus.d.ts +5 -0
  28. package/dist/vendor/cli/commands/corpus.js +60 -0
  29. package/dist/vendor/cli/commands/doctor.d.ts +8 -0
  30. package/dist/vendor/cli/commands/doctor.js +219 -0
  31. package/dist/vendor/cli/commands/explain.d.ts +17 -0
  32. package/dist/vendor/cli/commands/explain.js +176 -0
  33. package/dist/vendor/cli/commands/export.d.ts +5 -0
  34. package/dist/vendor/cli/commands/export.js +60 -0
  35. package/dist/vendor/cli/commands/governance.d.ts +8 -0
  36. package/dist/vendor/cli/commands/governance.js +95 -0
  37. package/dist/vendor/cli/commands/improve.d.ts +18 -0
  38. package/dist/vendor/cli/commands/improve.js +396 -0
  39. package/dist/vendor/cli/commands/init.d.ts +8 -0
  40. package/dist/vendor/cli/commands/init.js +281 -0
  41. package/dist/vendor/cli/commands/migration.d.ts +8 -0
  42. package/dist/vendor/cli/commands/migration.js +67 -0
  43. package/dist/vendor/cli/commands/prior.d.ts +23 -0
  44. package/dist/vendor/cli/commands/prior.js +145 -0
  45. package/dist/vendor/cli/commands/resume.d.ts +21 -0
  46. package/dist/vendor/cli/commands/resume.js +73 -0
  47. package/dist/vendor/cli/commands/verify.d.ts +6 -0
  48. package/dist/vendor/cli/commands/verify.js +43 -0
  49. package/dist/vendor/cli/research/public-corpus.d.ts +43 -0
  50. package/dist/vendor/cli/research/public-corpus.js +151 -0
  51. package/dist/vendor/cli/ui/error-card.d.ts +38 -0
  52. package/dist/vendor/cli/ui/error-card.js +103 -0
  53. package/dist/vendor/cli/ui/mission-brief.d.ts +41 -0
  54. package/dist/vendor/cli/ui/mission-brief.js +173 -0
  55. package/dist/vendor/cli/ui/summary-card.d.ts +34 -0
  56. package/dist/vendor/cli/ui/summary-card.js +102 -0
  57. package/dist/vendor/contracts/audit.d.ts +46 -0
  58. package/dist/vendor/contracts/audit.js +360 -0
  59. package/dist/vendor/contracts/post-phase15.d.ts +240 -0
  60. package/dist/vendor/contracts/post-phase15.js +166 -0
  61. package/dist/vendor/core/agent/mandates.d.ts +46 -0
  62. package/dist/vendor/core/agent/mandates.js +178 -0
  63. package/dist/vendor/core/agent/receipts.d.ts +38 -0
  64. package/dist/vendor/core/agent/receipts.js +131 -0
  65. package/dist/vendor/core/agent/signing.d.ts +17 -0
  66. package/dist/vendor/core/agent/signing.js +91 -0
  67. package/dist/vendor/core/attestation/sign.d.ts +25 -0
  68. package/dist/vendor/core/attestation/sign.js +216 -0
  69. package/dist/vendor/core/autonomy/autonomous-promotion.d.ts +120 -0
  70. package/dist/vendor/core/autonomy/autonomous-promotion.js +346 -0
  71. package/dist/vendor/core/autonomy/envelope-v2.d.ts +29 -0
  72. package/dist/vendor/core/autonomy/envelope-v2.js +60 -0
  73. package/dist/vendor/core/autonomy/envelope.d.ts +17 -0
  74. package/dist/vendor/core/autonomy/envelope.js +27 -0
  75. package/dist/vendor/core/autonomy/escalation-ledger.d.ts +20 -0
  76. package/dist/vendor/core/autonomy/escalation-ledger.js +18 -0
  77. package/dist/vendor/core/autonomy/resume.d.ts +15 -0
  78. package/dist/vendor/core/autonomy/resume.js +23 -0
  79. package/dist/vendor/core/circuit/circuit-breaker.d.ts +60 -0
  80. package/dist/vendor/core/circuit/circuit-breaker.js +143 -0
  81. package/dist/vendor/core/context-distillation.d.ts +3 -0
  82. package/dist/vendor/core/context-distillation.js +44 -0
  83. package/dist/vendor/core/context-flow/compile-context.d.ts +8 -0
  84. package/dist/vendor/core/context-flow/compile-context.js +111 -0
  85. package/dist/vendor/core/context-flow/entities.d.ts +2 -0
  86. package/dist/vendor/core/context-flow/entities.js +44 -0
  87. package/dist/vendor/core/context-flow/evaluate-policy.d.ts +2 -0
  88. package/dist/vendor/core/context-flow/evaluate-policy.js +42 -0
  89. package/dist/vendor/core/context-flow/index.d.ts +11 -0
  90. package/dist/vendor/core/context-flow/index.js +24 -0
  91. package/dist/vendor/core/context-flow/labels.d.ts +3 -0
  92. package/dist/vendor/core/context-flow/labels.js +17 -0
  93. package/dist/vendor/core/context-flow/normalizer.d.ts +9 -0
  94. package/dist/vendor/core/context-flow/normalizer.js +69 -0
  95. package/dist/vendor/core/context-flow/profiles.d.ts +33 -0
  96. package/dist/vendor/core/context-flow/profiles.js +36 -0
  97. package/dist/vendor/core/context-flow/redaction.d.ts +1 -0
  98. package/dist/vendor/core/context-flow/redaction.js +6 -0
  99. package/dist/vendor/core/context-flow/sensitivity.d.ts +2 -0
  100. package/dist/vendor/core/context-flow/sensitivity.js +27 -0
  101. package/dist/vendor/core/context-flow/sync-preview.d.ts +2 -0
  102. package/dist/vendor/core/context-flow/sync-preview.js +22 -0
  103. package/dist/vendor/core/context-flow/token-estimator.d.ts +3 -0
  104. package/dist/vendor/core/context-flow/token-estimator.js +13 -0
  105. package/dist/vendor/core/context-flow/types.d.ts +91 -0
  106. package/dist/vendor/core/context-flow/types.js +2 -0
  107. package/dist/vendor/core/context-utility.d.ts +47 -0
  108. package/dist/vendor/core/context-utility.js +405 -0
  109. package/dist/vendor/core/cost/pipeline.d.ts +92 -0
  110. package/dist/vendor/core/cost/pipeline.js +141 -0
  111. package/dist/vendor/core/cost/tagged-cost.d.ts +27 -0
  112. package/dist/vendor/core/cost/tagged-cost.js +55 -0
  113. package/dist/vendor/core/cost-governor.d.ts +2 -0
  114. package/dist/vendor/core/cost-governor.js +50 -0
  115. package/dist/vendor/core/cve/cve-check.d.ts +80 -0
  116. package/dist/vendor/core/cve/cve-check.js +172 -0
  117. package/dist/vendor/core/digital-twin/index.d.ts +27 -0
  118. package/dist/vendor/core/digital-twin/index.js +90 -0
  119. package/dist/vendor/core/drift/drift-graph.d.ts +47 -0
  120. package/dist/vendor/core/drift/drift-graph.js +100 -0
  121. package/dist/vendor/core/drift/objective-lock.d.ts +69 -0
  122. package/dist/vendor/core/drift/objective-lock.js +88 -0
  123. package/dist/vendor/core/drift/scope.d.ts +46 -0
  124. package/dist/vendor/core/drift/scope.js +102 -0
  125. package/dist/vendor/core/drift/signature-lock.d.ts +48 -0
  126. package/dist/vendor/core/drift/signature-lock.js +202 -0
  127. package/dist/vendor/core/drift/stale-proof-gate.d.ts +21 -0
  128. package/dist/vendor/core/drift/stale-proof-gate.js +19 -0
  129. package/dist/vendor/core/eval/known-bad-world-runner.d.ts +24 -0
  130. package/dist/vendor/core/eval/known-bad-world-runner.js +256 -0
  131. package/dist/vendor/core/evidence/claim-audit.d.ts +18 -0
  132. package/dist/vendor/core/evidence/claim-audit.js +89 -0
  133. package/dist/vendor/core/exit-intelligence.d.ts +2 -0
  134. package/dist/vendor/core/exit-intelligence.js +58 -0
  135. package/dist/vendor/core/explain/formatter.d.ts +42 -0
  136. package/dist/vendor/core/explain/formatter.js +171 -0
  137. package/dist/vendor/core/explain/timeline.d.ts +29 -0
  138. package/dist/vendor/core/explain/timeline.js +213 -0
  139. package/dist/vendor/core/failure-taxonomy.d.ts +2 -0
  140. package/dist/vendor/core/failure-taxonomy.js +76 -0
  141. package/dist/vendor/core/gateway/index.d.ts +10 -0
  142. package/dist/vendor/core/gateway/index.js +12 -0
  143. package/dist/vendor/core/gateway/registry.d.ts +40 -0
  144. package/dist/vendor/core/gateway/registry.js +97 -0
  145. package/dist/vendor/core/gateway/transport.d.ts +31 -0
  146. package/dist/vendor/core/gateway/transport.js +82 -0
  147. package/dist/vendor/core/gateway/vault.d.ts +19 -0
  148. package/dist/vendor/core/gateway/vault.js +29 -0
  149. package/dist/vendor/core/graph/adapters.d.ts +43 -0
  150. package/dist/vendor/core/graph/adapters.js +91 -0
  151. package/dist/vendor/core/graph/hotspots.d.ts +22 -0
  152. package/dist/vendor/core/graph/hotspots.js +30 -0
  153. package/dist/vendor/core/graph/index.d.ts +1 -0
  154. package/dist/vendor/core/graph/index.js +2 -0
  155. package/dist/vendor/core/honey/honey-tokens.d.ts +32 -0
  156. package/dist/vendor/core/honey/honey-tokens.js +44 -0
  157. package/dist/vendor/core/index.d.ts +2 -2
  158. package/dist/vendor/core/index.js +38 -12
  159. package/dist/vendor/core/learning/bayesian-update.d.ts +31 -0
  160. package/dist/vendor/core/learning/bayesian-update.js +60 -0
  161. package/dist/vendor/core/learning/prior-sets.d.ts +42 -0
  162. package/dist/vendor/core/learning/prior-sets.js +111 -0
  163. package/dist/vendor/core/learning/promotion-gate.d.ts +17 -0
  164. package/dist/vendor/core/learning/promotion-gate.js +23 -0
  165. package/dist/vendor/core/leash/blast-radius.d.ts +42 -0
  166. package/dist/vendor/core/leash/blast-radius.js +156 -0
  167. package/dist/vendor/core/leash/policy-leash.d.ts +31 -0
  168. package/dist/vendor/core/leash/policy-leash.js +117 -0
  169. package/dist/vendor/core/memo/memo.d.ts +63 -0
  170. package/dist/vendor/core/memo/memo.js +97 -0
  171. package/dist/vendor/core/memory/learning-pipeline.d.ts +154 -0
  172. package/dist/vendor/core/memory/learning-pipeline.js +391 -0
  173. package/dist/vendor/core/memory/palace.d.ts +84 -0
  174. package/dist/vendor/core/memory/palace.js +379 -0
  175. package/dist/vendor/core/merge/ast-merge.d.ts +22 -0
  176. package/dist/vendor/core/merge/ast-merge.js +350 -0
  177. package/dist/vendor/core/merge/text-merge.d.ts +12 -0
  178. package/dist/vendor/core/merge/text-merge.js +182 -0
  179. package/dist/vendor/core/otel/tracer.d.ts +45 -0
  180. package/dist/vendor/core/otel/tracer.js +116 -0
  181. package/dist/vendor/core/parallel/parallel-attempts.d.ts +28 -0
  182. package/dist/vendor/core/parallel/parallel-attempts.js +41 -0
  183. package/dist/vendor/core/parallel/scorer.d.ts +24 -0
  184. package/dist/vendor/core/parallel/scorer.js +65 -0
  185. package/dist/vendor/core/pattern-detection.d.ts +64 -0
  186. package/dist/vendor/core/pattern-detection.js +108 -0
  187. package/dist/vendor/core/persistence/checkpoint.d.ts +44 -0
  188. package/dist/vendor/core/persistence/checkpoint.js +156 -0
  189. package/dist/vendor/core/persistence/cleanup.d.ts +22 -0
  190. package/dist/vendor/core/persistence/cleanup.js +131 -0
  191. package/dist/vendor/core/persistence/index.d.ts +2 -0
  192. package/dist/vendor/core/persistence/index.js +1 -0
  193. package/dist/vendor/core/persistence/runs-reader.d.ts +52 -0
  194. package/dist/vendor/core/persistence/runs-reader.js +84 -0
  195. package/dist/vendor/core/persistence/store.d.ts +6 -1
  196. package/dist/vendor/core/persistence/store.js +5 -0
  197. package/dist/vendor/core/policy/file-touch-quota.d.ts +60 -0
  198. package/dist/vendor/core/policy/file-touch-quota.js +105 -0
  199. package/dist/vendor/core/policy/policy-loader.d.ts +30 -0
  200. package/dist/vendor/core/policy/policy-loader.js +170 -0
  201. package/dist/vendor/core/policy/policy-schema.d.ts +55 -0
  202. package/dist/vendor/core/policy/policy-schema.js +78 -0
  203. package/dist/vendor/core/probe/probe.d.ts +49 -0
  204. package/dist/vendor/core/probe/probe.js +115 -0
  205. package/dist/vendor/core/proof/patch-proof.d.ts +58 -0
  206. package/dist/vendor/core/proof/patch-proof.js +84 -0
  207. package/dist/vendor/core/proof/semantic-probe.d.ts +25 -0
  208. package/dist/vendor/core/proof/semantic-probe.js +82 -0
  209. package/dist/vendor/core/recovery/failure-mode-runner.d.ts +29 -0
  210. package/dist/vendor/core/recovery/failure-mode-runner.js +39 -0
  211. package/dist/vendor/core/red-blue/red-phase.d.ts +64 -0
  212. package/dist/vendor/core/red-blue/red-phase.js +141 -0
  213. package/dist/vendor/core/red-blue/risk-tiers.d.ts +22 -0
  214. package/dist/vendor/core/red-blue/risk-tiers.js +33 -0
  215. package/dist/vendor/core/replay/replay.d.ts +85 -0
  216. package/dist/vendor/core/replay/replay.js +109 -0
  217. package/dist/vendor/core/router/engine.d.ts +54 -0
  218. package/dist/vendor/core/router/engine.js +131 -0
  219. package/dist/vendor/core/router/index.d.ts +1 -0
  220. package/dist/vendor/core/router/index.js +2 -0
  221. package/dist/vendor/core/router/trust-calibration.d.ts +57 -0
  222. package/dist/vendor/core/router/trust-calibration.js +127 -0
  223. package/dist/vendor/core/run-martin.d.ts +2 -0
  224. package/dist/vendor/core/run-martin.js +287 -0
  225. package/dist/vendor/core/security/cve-scanner.d.ts +62 -0
  226. package/dist/vendor/core/security/cve-scanner.js +178 -0
  227. package/dist/vendor/core/sentinel/efficiency-sentinel.d.ts +29 -0
  228. package/dist/vendor/core/sentinel/efficiency-sentinel.js +30 -0
  229. package/dist/vendor/core/sentinel/progress-guard.d.ts +35 -0
  230. package/dist/vendor/core/sentinel/progress-guard.js +46 -0
  231. package/dist/vendor/core/siem/siem-emitter.d.ts +49 -0
  232. package/dist/vendor/core/siem/siem-emitter.js +157 -0
  233. package/dist/vendor/core/strategy/attempt-brief.d.ts +22 -0
  234. package/dist/vendor/core/strategy/attempt-brief.js +89 -0
  235. package/dist/vendor/core/summarize/diff-summary.d.ts +35 -0
  236. package/dist/vendor/core/summarize/diff-summary.js +204 -0
  237. package/dist/vendor/core/surface-signals.d.ts +21 -0
  238. package/dist/vendor/core/surface-signals.js +139 -0
  239. package/dist/vendor/core/truth/truth-wall.d.ts +51 -0
  240. package/dist/vendor/core/truth/truth-wall.js +69 -0
  241. package/dist/vendor/core/truth-spine.d.ts +26 -0
  242. package/dist/vendor/core/truth-spine.js +62 -0
  243. package/dist/vendor/core/types.d.ts +115 -0
  244. package/dist/vendor/core/types.js +2 -0
  245. package/dist/vendor/core/verification/tiered-verify.d.ts +17 -0
  246. package/dist/vendor/core/verification/tiered-verify.js +29 -0
  247. package/dist/vendor/core/verifier-pyramid.d.ts +32 -0
  248. package/dist/vendor/core/verifier-pyramid.js +111 -0
  249. package/dist/vendor/core/workflow-artifacts.d.ts +99 -0
  250. package/dist/vendor/core/workflow-artifacts.js +668 -0
  251. package/dist/vendor/core/wrap/supervised-run.d.ts +96 -0
  252. package/dist/vendor/core/wrap/supervised-run.js +178 -0
  253. package/docs/assets/cli-animated.svg +139 -0
  254. package/docs/assets/cli-static.svg +34 -0
  255. package/docs/assets/github-hero-v2.svg +23 -0
  256. package/docs/assets/martin-raplph.png.jpg +0 -0
  257. package/docs/assets/martinloop-logo.png +0 -0
  258. package/docs/assets/nvidia-inception-program-light.png +0 -0
  259. package/docs/assets/nvidia-inception-program.png +0 -0
  260. package/docs/assets/phase3c-sidesidebyside-demo.html +228 -0
  261. package/docs/assets/side-by-side.svg +134 -0
  262. package/docs/oss/CLAUDE-CODE-WALKTHROUGH.md +142 -142
  263. package/docs/oss/EXAMPLES.md +134 -134
  264. package/docs/oss/OSS-BOUNDARY-REPORT.json +1 -1
  265. package/docs/oss/OSS-BOUNDARY-REPORT.md +1 -1
  266. package/docs/oss/QUICKSTART.md +170 -165
  267. package/docs/oss/RALPH-LOOP-SAFETY.md +113 -113
  268. package/docs/oss/README.md +96 -96
  269. package/docs/oss/RELEASE-SURFACE-REPORT.json +2 -1
  270. package/docs/oss/RELEASE-SURFACE-REPORT.md +2 -1
  271. package/package.json +130 -58
  272. package/docs/distribution/DIRECTORY-SUBMISSIONS.md +0 -89
  273. package/docs/distribution/INTEGRATION-OUTREACH.md +0 -61
  274. package/docs/distribution/UNDER-3-CHALLENGE.md +0 -65
@@ -0,0 +1,97 @@
1
+ import { getTracer } from "../otel/tracer.js";
2
+ export class McpServerRegistry {
3
+ servers = new Map();
4
+ constructor(initialServers = []) {
5
+ for (const server of initialServers) {
6
+ this.register(server);
7
+ }
8
+ }
9
+ register(server) {
10
+ if (!server.id || !server.url) {
11
+ throw new Error(`Invalid MCP server configuration for: ${server.name}`);
12
+ }
13
+ this.servers.set(server.id, server);
14
+ }
15
+ unregister(serverId) {
16
+ return this.servers.delete(serverId);
17
+ }
18
+ getServer(serverId) {
19
+ return this.servers.get(serverId);
20
+ }
21
+ listServers() {
22
+ return Array.from(this.servers.values());
23
+ }
24
+ evaluateToolPolicy(attempt) {
25
+ const tracer = getTracer();
26
+ const span = tracer.startSpan("martin.gateway_policy", {
27
+ "tool.name": attempt.toolName,
28
+ "server.id": attempt.serverId,
29
+ "context.loop": attempt.context.loopId
30
+ });
31
+ const finish = (decision) => {
32
+ tracer.endSpan(span, decision.action === "deny" ? "ERROR" : "OK");
33
+ return decision;
34
+ };
35
+ const server = this.getServer(attempt.serverId);
36
+ if (!server) {
37
+ return finish({
38
+ action: "deny",
39
+ reason: `Server ID '${attempt.serverId}' not registered.`
40
+ });
41
+ }
42
+ if (server.trustTier === "untrusted" &&
43
+ attempt.context.executionProfile === "ci_safe") {
44
+ return finish({
45
+ action: "deny",
46
+ reason: "Untrusted MCP servers are disabled under ci_safe profile."
47
+ });
48
+ }
49
+ // Direct blocklist
50
+ if (this.matchesPattern(attempt.toolName, server.blockedTools)) {
51
+ return finish({
52
+ action: "deny",
53
+ reason: `Tool '${attempt.toolName}' is blocked by server policy.`
54
+ });
55
+ }
56
+ // Allowlist
57
+ if (server.allowedTools.length > 0 &&
58
+ !this.matchesPattern(attempt.toolName, server.allowedTools)) {
59
+ return finish({
60
+ action: "deny",
61
+ reason: `Tool '${attempt.toolName}' is not in the server allowlist.`
62
+ });
63
+ }
64
+ // Dangerous patterns require dry-run ("simulate") if not strongly verified
65
+ if (server.trustTier !== "system") {
66
+ const stringifiedArgs = JSON.stringify(attempt.args);
67
+ if (stringifiedArgs.includes("rm -rf") ||
68
+ stringifiedArgs.includes("drop table")) {
69
+ return finish({
70
+ action: "simulate",
71
+ mockResponse: {
72
+ success: true,
73
+ stdout: "",
74
+ stderr: "DRY-RUN: Command intercepted and skipped."
75
+ }
76
+ });
77
+ }
78
+ }
79
+ return finish({ action: "allow" });
80
+ }
81
+ matchesPattern(tool, patterns) {
82
+ for (const p of patterns) {
83
+ if (p === "*")
84
+ return true;
85
+ if (p.endsWith("*")) {
86
+ const prefix = p.slice(0, -1);
87
+ if (tool.startsWith(prefix))
88
+ return true;
89
+ }
90
+ else if (p === tool) {
91
+ return true;
92
+ }
93
+ }
94
+ return false;
95
+ }
96
+ }
97
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1,31 @@
1
+ import type { McpServerConfig } from "./registry.js";
2
+ import type { McpTokenVault } from "./vault.js";
3
+ export interface JsonRpcRequest {
4
+ jsonrpc: "2.0";
5
+ id: string | number;
6
+ method: string;
7
+ params?: unknown;
8
+ }
9
+ export interface JsonRpcResponse<T = unknown> {
10
+ jsonrpc: "2.0";
11
+ id: string | number;
12
+ result?: T;
13
+ error?: {
14
+ code: number;
15
+ message: string;
16
+ data?: unknown;
17
+ };
18
+ }
19
+ export declare class McpTransportError extends Error {
20
+ readonly status?: number | undefined;
21
+ readonly data?: unknown | undefined;
22
+ constructor(message: string, status?: number | undefined, data?: unknown | undefined);
23
+ }
24
+ export declare class McpHttpTransport {
25
+ private readonly vault?;
26
+ constructor(vault?: McpTokenVault | undefined);
27
+ /**
28
+ * Dispatches a raw JSON-RPC 2.0 request to an external MCP HTTP server.
29
+ */
30
+ executeCommand<T = unknown>(server: McpServerConfig, method: string, params: Record<string, unknown>, requestId: string): Promise<T>;
31
+ }
@@ -0,0 +1,82 @@
1
+ export class McpTransportError extends Error {
2
+ status;
3
+ data;
4
+ constructor(message, status, data) {
5
+ super(message);
6
+ this.status = status;
7
+ this.data = data;
8
+ this.name = "McpTransportError";
9
+ }
10
+ }
11
+ export class McpHttpTransport {
12
+ vault;
13
+ constructor(vault) {
14
+ this.vault = vault;
15
+ }
16
+ /**
17
+ * Dispatches a raw JSON-RPC 2.0 request to an external MCP HTTP server.
18
+ */
19
+ async executeCommand(server, method, params, requestId) {
20
+ const payload = {
21
+ jsonrpc: "2.0",
22
+ id: requestId,
23
+ method,
24
+ params
25
+ };
26
+ const headers = new Headers({
27
+ "Content-Type": "application/json",
28
+ "User-Agent": "Martin-Loop-Gateway/0.1.0"
29
+ });
30
+ if (server.headers) {
31
+ for (const [key, value] of Object.entries(server.headers)) {
32
+ headers.set(key, value);
33
+ }
34
+ }
35
+ if (this.vault) {
36
+ const dynamicHeaders = await this.vault.resolveHeaders(server.id);
37
+ for (const [key, value] of Object.entries(dynamicHeaders)) {
38
+ headers.set(key, value);
39
+ }
40
+ }
41
+ try {
42
+ // 30s timeout so the loop doesn't hang indefinitely on a bad server
43
+ const controller = new AbortController();
44
+ const timeout = setTimeout(() => controller.abort(), 30000);
45
+ const response = await fetch(server.url, {
46
+ method: "POST",
47
+ headers,
48
+ body: JSON.stringify(payload),
49
+ signal: controller.signal
50
+ });
51
+ clearTimeout(timeout);
52
+ if (!response.ok) {
53
+ throw new McpTransportError(`HTTP Error ${response.status}: Failed to reach MCP Server '${server.id}'`, response.status);
54
+ }
55
+ const rawJson = await response.text();
56
+ let rpcResponse;
57
+ try {
58
+ rpcResponse = JSON.parse(rawJson);
59
+ }
60
+ catch {
61
+ throw new McpTransportError(`Invalid JSON received from MCP Server '${server.id}'`);
62
+ }
63
+ if (rpcResponse.error) {
64
+ throw new McpTransportError(`MCP Server Internal Error: ${rpcResponse.error.message}`, undefined, rpcResponse.error.data);
65
+ }
66
+ // JSON-RPC 2.0 requires `result` to exist on success
67
+ if (rpcResponse.result === undefined) {
68
+ throw new McpTransportError(`Malformed JSON-RPC response from '${server.id}': Missing result.`);
69
+ }
70
+ return rpcResponse.result;
71
+ }
72
+ catch (e) {
73
+ if (e instanceof McpTransportError) {
74
+ throw e;
75
+ }
76
+ const err = e;
77
+ const errMessage = err.name === "AbortError" ? "Request Timeout" : err.message;
78
+ throw new McpTransportError(`Network error dispatching to MCP Server '${server.id}': ${errMessage}`);
79
+ }
80
+ }
81
+ }
82
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1,19 @@
1
+ export interface McpTokenVault {
2
+ /**
3
+ * Resolves authentication headers for a given server dynamically.
4
+ * Can be implemented via OAuth, Secret Managers, or static config.
5
+ */
6
+ resolveHeaders(serverId: string): Promise<Record<string, string>>;
7
+ }
8
+ export declare class StaticTokenVault implements McpTokenVault {
9
+ private readonly staticHeaders;
10
+ constructor(staticHeaders: Map<string, Record<string, string>>);
11
+ resolveHeaders(serverId: string): Promise<Record<string, string>>;
12
+ }
13
+ export declare class OAuthProxyVault implements McpTokenVault {
14
+ private readonly oauthTokenEndpoint;
15
+ private readonly clientId;
16
+ private readonly clientSecret;
17
+ constructor(oauthTokenEndpoint: string, clientId: string, clientSecret: string);
18
+ resolveHeaders(serverId: string): Promise<Record<string, string>>;
19
+ }
@@ -0,0 +1,29 @@
1
+ export class StaticTokenVault {
2
+ staticHeaders;
3
+ constructor(staticHeaders) {
4
+ this.staticHeaders = staticHeaders;
5
+ }
6
+ async resolveHeaders(serverId) {
7
+ return this.staticHeaders.get(serverId) ?? {};
8
+ }
9
+ }
10
+ export class OAuthProxyVault {
11
+ oauthTokenEndpoint;
12
+ clientId;
13
+ clientSecret;
14
+ constructor(oauthTokenEndpoint, clientId, clientSecret) {
15
+ this.oauthTokenEndpoint = oauthTokenEndpoint;
16
+ this.clientId = clientId;
17
+ this.clientSecret = clientSecret;
18
+ }
19
+ async resolveHeaders(serverId) {
20
+ // Basic dynamic OAuth token fetch simulation for multi-tenant isolation
21
+ // Without actually making real un-mocked requests that could crash tests
22
+ const token = Buffer.from(`${this.clientId}:${this.clientSecret}-${serverId}`).toString("base64");
23
+ return {
24
+ Authorization: `Bearer ${token}`,
25
+ "X-Martin-Scope": "dynamic-vault"
26
+ };
27
+ }
28
+ }
29
+ //# sourceMappingURL=vault.js.map
@@ -0,0 +1,43 @@
1
+ import type { RepoHotspot } from "./hotspots.js";
2
+ export interface MartinGraphAdapter {
3
+ queryRegressions(targetFiles: string[], objective: string): Promise<RepoHotspot[]>;
4
+ ingestRun(record: unknown): Promise<void>;
5
+ }
6
+ /**
7
+ * Abstract interface to ensure the system can hot-swap external graph engines
8
+ * (like Neo4j) without rewriting the core calculation logic when workspace scale grows.
9
+ */
10
+ export declare abstract class AbstractGraphStore implements MartinGraphAdapter {
11
+ abstract queryRegressions(targetFiles: string[], objective: string): Promise<RepoHotspot[]>;
12
+ abstract ingestRun(record: unknown): Promise<void>;
13
+ }
14
+ export declare class JsonAdjacencyGraphAdapter extends AbstractGraphStore {
15
+ private readonly adjacencyFilePath;
16
+ constructor(adjacencyFilePath: string);
17
+ queryRegressions(targetFiles: string[], _objective: string): Promise<RepoHotspot[]>;
18
+ ingestRun(_record: unknown): Promise<void>;
19
+ }
20
+ /**
21
+ * GitBlameGraphAdapter
22
+ *
23
+ * Derives repository hotspots from live git history — no static JSON file required.
24
+ *
25
+ * For each target file, runs `git log --oneline --follow -- <file>` to count
26
+ * how many commits have touched it. Files with a commit count >= the configured
27
+ * threshold are returned as hotspots. The regression count is the git commit count,
28
+ * which is a reliable, repo-native signal of churn / instability.
29
+ *
30
+ * Fail-open: any git error (not a repo, file not tracked, git not installed) returns
31
+ * an empty result for that file — never throws.
32
+ */
33
+ export declare class GitBlameGraphAdapter extends AbstractGraphStore {
34
+ private readonly repoRoot;
35
+ /** Files with >= this many commits are classified as hotspots. Default: 5 */
36
+ private readonly commitThreshold;
37
+ constructor(repoRoot: string,
38
+ /** Files with >= this many commits are classified as hotspots. Default: 5 */
39
+ commitThreshold?: number);
40
+ queryRegressions(targetFiles: string[], _objective: string): Promise<RepoHotspot[]>;
41
+ ingestRun(_record: unknown): Promise<void>;
42
+ private countCommits;
43
+ }
@@ -0,0 +1,91 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promises as fs } from "node:fs";
3
+ import { promisify } from "node:util";
4
+ const execFileAsync = promisify(execFile);
5
+ /**
6
+ * Abstract interface to ensure the system can hot-swap external graph engines
7
+ * (like Neo4j) without rewriting the core calculation logic when workspace scale grows.
8
+ */
9
+ export class AbstractGraphStore {
10
+ }
11
+ export class JsonAdjacencyGraphAdapter extends AbstractGraphStore {
12
+ adjacencyFilePath;
13
+ constructor(adjacencyFilePath) {
14
+ super();
15
+ this.adjacencyFilePath = adjacencyFilePath;
16
+ }
17
+ async queryRegressions(targetFiles, _objective) {
18
+ try {
19
+ const data = await fs.readFile(this.adjacencyFilePath, "utf8");
20
+ const adjacencyList = JSON.parse(data);
21
+ const hotspots = [];
22
+ for (const file of targetFiles) {
23
+ if (adjacencyList[file] && adjacencyList[file].regressionCount > 0) {
24
+ hotspots.push(adjacencyList[file]);
25
+ }
26
+ }
27
+ return hotspots;
28
+ }
29
+ catch {
30
+ // If the adjacency file does not exist yet, or parsing fails, return empty context natively
31
+ return [];
32
+ }
33
+ }
34
+ async ingestRun(_record) {
35
+ // In a real execution, we parse the record for "verification_failed" events
36
+ // and upsert the files into the JSON map.
37
+ // Stubbed for standard interface completion.
38
+ }
39
+ }
40
+ /**
41
+ * GitBlameGraphAdapter
42
+ *
43
+ * Derives repository hotspots from live git history — no static JSON file required.
44
+ *
45
+ * For each target file, runs `git log --oneline --follow -- <file>` to count
46
+ * how many commits have touched it. Files with a commit count >= the configured
47
+ * threshold are returned as hotspots. The regression count is the git commit count,
48
+ * which is a reliable, repo-native signal of churn / instability.
49
+ *
50
+ * Fail-open: any git error (not a repo, file not tracked, git not installed) returns
51
+ * an empty result for that file — never throws.
52
+ */
53
+ export class GitBlameGraphAdapter extends AbstractGraphStore {
54
+ repoRoot;
55
+ commitThreshold;
56
+ constructor(repoRoot,
57
+ /** Files with >= this many commits are classified as hotspots. Default: 5 */
58
+ commitThreshold = 5) {
59
+ super();
60
+ this.repoRoot = repoRoot;
61
+ this.commitThreshold = commitThreshold;
62
+ }
63
+ async queryRegressions(targetFiles, _objective) {
64
+ const hotspots = [];
65
+ for (const file of targetFiles) {
66
+ const count = await this.countCommits(file);
67
+ if (count >= this.commitThreshold) {
68
+ hotspots.push({
69
+ file,
70
+ regressionCount: count,
71
+ associatedTaskTypes: ["churn", "high-frequency-change"]
72
+ });
73
+ }
74
+ }
75
+ return hotspots;
76
+ }
77
+ async ingestRun(_record) {
78
+ // Live adapter — reads directly from git history, no ingest needed.
79
+ }
80
+ async countCommits(file) {
81
+ try {
82
+ const { stdout } = await execFileAsync("git", ["log", "--oneline", "--follow", "--", file], { cwd: this.repoRoot });
83
+ return stdout.trim().split("\n").filter(Boolean).length;
84
+ }
85
+ catch {
86
+ // git not available, file not tracked, or not inside a git repo — safe fallback
87
+ return 0;
88
+ }
89
+ }
90
+ }
91
+ //# sourceMappingURL=adapters.js.map
@@ -0,0 +1,22 @@
1
+ import type { LoopMemoryStore } from "../memory/palace.js";
2
+ import type { MartinGraphAdapter } from "./adapters.js";
3
+ export interface RepoHotspot {
4
+ file: string;
5
+ regressionCount: number;
6
+ lastFailureClass?: string;
7
+ associatedTaskTypes: string[];
8
+ }
9
+ export interface GraphContextAssembly {
10
+ hotspotsDetected: RepoHotspot[];
11
+ suggestedContextAdditions: string[];
12
+ }
13
+ export declare class MartinGraph {
14
+ private readonly memoryStore?;
15
+ private readonly graphAdapter?;
16
+ constructor(memoryStore?: LoopMemoryStore | undefined, graphAdapter?: MartinGraphAdapter | undefined);
17
+ /**
18
+ * Translates a raw array of memory briefs into a structural hotspot map identifying
19
+ * files that frequently fail verification or cause rollbacks.
20
+ */
21
+ assembleHotspotContext(targetFiles: string[], objective: string): Promise<GraphContextAssembly>;
22
+ }
@@ -0,0 +1,30 @@
1
+ export class MartinGraph {
2
+ memoryStore;
3
+ graphAdapter;
4
+ constructor(memoryStore, graphAdapter) {
5
+ this.memoryStore = memoryStore;
6
+ this.graphAdapter = graphAdapter;
7
+ }
8
+ /**
9
+ * Translates a raw array of memory briefs into a structural hotspot map identifying
10
+ * files that frequently fail verification or cause rollbacks.
11
+ */
12
+ async assembleHotspotContext(targetFiles, objective) {
13
+ if (!this.memoryStore && !this.graphAdapter) {
14
+ return { hotspotsDetected: [], suggestedContextAdditions: [] };
15
+ }
16
+ try {
17
+ // Pull real statistics from the underlying database / persistence layer
18
+ const hotspots = this.graphAdapter
19
+ ? await this.graphAdapter.queryRegressions(targetFiles, objective)
20
+ : [];
21
+ const riskyFiles = hotspots.filter((h) => h.regressionCount > 2);
22
+ const suggestedContextAdditions = riskyFiles.map((h) => `CRITICAL: The file '${h.file}' has regressed ${h.regressionCount} times in similar past tasks. Double-check types and imports before patching.`);
23
+ return { hotspotsDetected: hotspots, suggestedContextAdditions };
24
+ }
25
+ catch {
26
+ return { hotspotsDetected: [], suggestedContextAdditions: [] };
27
+ }
28
+ }
29
+ }
30
+ //# sourceMappingURL=hotspots.js.map
@@ -0,0 +1 @@
1
+ export * from "./hotspots.js";
@@ -0,0 +1,2 @@
1
+ export * from "./hotspots.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,32 @@
1
+ export interface HoneyTokenSet {
2
+ runId: string;
3
+ tokens: string[];
4
+ }
5
+ export interface Patch {
6
+ patchId: string;
7
+ diff: string;
8
+ changedFiles: string[];
9
+ }
10
+ export interface HoneyTokenViolation {
11
+ trapId: "T13";
12
+ severity: "block";
13
+ description: string;
14
+ matchedToken: string;
15
+ }
16
+ /**
17
+ * Generates 3 HMAC-derived canary symbols per run.
18
+ *
19
+ * Properties:
20
+ * - Deterministic: same runId + secret always produces same tokens
21
+ * - Isolated: different runIds produce different tokens (no cross-run reuse)
22
+ * - Format: __martin_canary_{hmac_prefix}__
23
+ */
24
+ export declare function generateHoneyTokenSet(runId: string, secret: string): HoneyTokenSet;
25
+ /**
26
+ * Scans a patch diff for any honey token references.
27
+ * Pure string grep — zero model calls, zero API cost.
28
+ *
29
+ * Returns T13 GroundingViolation if a canary token appears in the patch,
30
+ * null if the patch is clean.
31
+ */
32
+ export declare function scanPatchForHoneyTokens(patch: Patch, tokens: HoneyTokenSet): HoneyTokenViolation | null;
@@ -0,0 +1,44 @@
1
+ import { createHmac } from "node:crypto";
2
+ // ─── Token Generation ─────────────────────────────────────────────────────────
3
+ /**
4
+ * Generates 3 HMAC-derived canary symbols per run.
5
+ *
6
+ * Properties:
7
+ * - Deterministic: same runId + secret always produces same tokens
8
+ * - Isolated: different runIds produce different tokens (no cross-run reuse)
9
+ * - Format: __martin_canary_{hmac_prefix}__
10
+ */
11
+ export function generateHoneyTokenSet(runId, secret) {
12
+ const tokens = [];
13
+ for (let i = 0; i < 3; i++) {
14
+ const hmac = createHmac("sha256", secret)
15
+ .update(`${runId}:canary:${i}`)
16
+ .digest("hex");
17
+ // Use a deterministic 16-char prefix per slot to keep tokens distinct
18
+ const prefix = hmac.slice(i * 8, i * 8 + 16);
19
+ tokens.push(`__martin_canary_${prefix}__`);
20
+ }
21
+ return { runId, tokens };
22
+ }
23
+ // ─── Scan ─────────────────────────────────────────────────────────────────────
24
+ /**
25
+ * Scans a patch diff for any honey token references.
26
+ * Pure string grep — zero model calls, zero API cost.
27
+ *
28
+ * Returns T13 GroundingViolation if a canary token appears in the patch,
29
+ * null if the patch is clean.
30
+ */
31
+ export function scanPatchForHoneyTokens(patch, tokens) {
32
+ for (const token of tokens.tokens) {
33
+ if (patch.diff.includes(token)) {
34
+ return {
35
+ trapId: "T13",
36
+ severity: "block",
37
+ description: `Honey token reference detected in patch ${patch.patchId} — instant rejection.`,
38
+ matchedToken: token
39
+ };
40
+ }
41
+ }
42
+ return null;
43
+ }
44
+ //# sourceMappingURL=honey-tokens.js.map
@@ -13,8 +13,8 @@ export { runContextIntegrityPrecheck } from "./context-integrity.js";
13
13
  export type { ContextIntegrityPrecheck, ContextIntegrityVerdict } from "./context-integrity.js";
14
14
  export { compilePromptPacket } from "./compiler.js";
15
15
  export type { PromptPacket, CompilerAdapterRequest } from "./compiler.js";
16
- export { createFileRunStore, makeLedgerEvent, resolveRunsRoot } from "./persistence/index.js";
17
- export type { AttemptArtifacts, LedgerEvent, LedgerEventKind, RunContract, RunStore } from "./persistence/index.js";
16
+ export { createFileRunStore, makeLedgerEvent, readAllLoopRecords, readLatestLoopRecord, readLatestLoopRecordFromFile, readLoopRecordsFromFile, resolveRunsRoot } from "./persistence/index.js";
17
+ export type { AttemptArtifacts, LedgerEvent, LedgerEventKind, LoopAttemptRecord, LoopRunRecord, RunContract, RunStore } from "./persistence/index.js";
18
18
  export { compileAndPersistContext } from "./persistence/index.js";
19
19
  export type { CompileResult } from "./persistence/index.js";
20
20
  export interface MartinAdapterRequest {