@martinloop/mcp 0.3.8 → 0.3.9

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 (103) hide show
  1. package/README.md +148 -105
  2. package/dist/resources.js +148 -148
  3. package/dist/server.js +0 -0
  4. package/dist/tools/preflight.d.ts +0 -2
  5. package/dist/tools/preflight.js +2 -42
  6. package/dist/vendor/adapters/openai-compatible.js +6 -6
  7. package/dist/vendor/contracts/index.d.ts +0 -2
  8. package/dist/vendor/contracts/index.js +0 -2
  9. package/dist/vendor/core/index.d.ts +0 -2
  10. package/dist/vendor/core/index.js +0 -2
  11. package/package.json +86 -83
  12. package/server.json +21 -21
  13. package/LICENSE +0 -216
  14. package/dist/vendor/adapters/adapters/src/claude-cli.d.ts +0 -146
  15. package/dist/vendor/adapters/adapters/src/claude-cli.js +0 -1100
  16. package/dist/vendor/adapters/adapters/src/cli-bridge.d.ts +0 -103
  17. package/dist/vendor/adapters/adapters/src/cli-bridge.js +0 -569
  18. package/dist/vendor/adapters/adapters/src/codex-launcher.d.ts +0 -78
  19. package/dist/vendor/adapters/adapters/src/codex-launcher.js +0 -663
  20. package/dist/vendor/adapters/adapters/src/direct-provider.d.ts +0 -10
  21. package/dist/vendor/adapters/adapters/src/direct-provider.js +0 -40
  22. package/dist/vendor/adapters/adapters/src/index.d.ts +0 -8
  23. package/dist/vendor/adapters/adapters/src/index.js +0 -8
  24. package/dist/vendor/adapters/adapters/src/openai-compatible.d.ts +0 -62
  25. package/dist/vendor/adapters/adapters/src/openai-compatible.js +0 -306
  26. package/dist/vendor/adapters/adapters/src/runtime-support.d.ts +0 -17
  27. package/dist/vendor/adapters/adapters/src/runtime-support.js +0 -59
  28. package/dist/vendor/adapters/adapters/src/stub-agent-cli.d.ts +0 -8
  29. package/dist/vendor/adapters/adapters/src/stub-agent-cli.js +0 -40
  30. package/dist/vendor/adapters/adapters/src/stub-direct-provider.d.ts +0 -8
  31. package/dist/vendor/adapters/adapters/src/stub-direct-provider.js +0 -12
  32. package/dist/vendor/adapters/adapters/src/verifier-only.d.ts +0 -9
  33. package/dist/vendor/adapters/adapters/src/verifier-only.js +0 -63
  34. package/dist/vendor/adapters/contracts/src/context-graph.d.ts +0 -48
  35. package/dist/vendor/adapters/contracts/src/context-graph.js +0 -26
  36. package/dist/vendor/adapters/contracts/src/execution-policy.d.ts +0 -78
  37. package/dist/vendor/adapters/contracts/src/execution-policy.js +0 -43
  38. package/dist/vendor/adapters/contracts/src/governance.d.ts +0 -24
  39. package/dist/vendor/adapters/contracts/src/governance.js +0 -11
  40. package/dist/vendor/adapters/contracts/src/identity.d.ts +0 -29
  41. package/dist/vendor/adapters/contracts/src/identity.js +0 -30
  42. package/dist/vendor/adapters/contracts/src/index.d.ts +0 -412
  43. package/dist/vendor/adapters/contracts/src/index.js +0 -225
  44. package/dist/vendor/adapters/contracts/src/operator.d.ts +0 -19
  45. package/dist/vendor/adapters/contracts/src/operator.js +0 -11
  46. package/dist/vendor/adapters/contracts/src/trajectory.d.ts +0 -26
  47. package/dist/vendor/adapters/contracts/src/trajectory.js +0 -27
  48. package/dist/vendor/adapters/core/src/compiler.d.ts +0 -52
  49. package/dist/vendor/adapters/core/src/compiler.js +0 -52
  50. package/dist/vendor/adapters/core/src/context-graph.d.ts +0 -3
  51. package/dist/vendor/adapters/core/src/context-graph.js +0 -371
  52. package/dist/vendor/adapters/core/src/context-integrity.d.ts +0 -26
  53. package/dist/vendor/adapters/core/src/context-integrity.js +0 -80
  54. package/dist/vendor/adapters/core/src/grounding.d.ts +0 -38
  55. package/dist/vendor/adapters/core/src/grounding.js +0 -273
  56. package/dist/vendor/adapters/core/src/identity.d.ts +0 -20
  57. package/dist/vendor/adapters/core/src/identity.js +0 -86
  58. package/dist/vendor/adapters/core/src/index.d.ts +0 -186
  59. package/dist/vendor/adapters/core/src/index.js +0 -1495
  60. package/dist/vendor/adapters/core/src/leash.d.ts +0 -48
  61. package/dist/vendor/adapters/core/src/leash.js +0 -497
  62. package/dist/vendor/adapters/core/src/persistence/compiler.d.ts +0 -18
  63. package/dist/vendor/adapters/core/src/persistence/compiler.js +0 -34
  64. package/dist/vendor/adapters/core/src/persistence/index.d.ts +0 -10
  65. package/dist/vendor/adapters/core/src/persistence/index.js +0 -5
  66. package/dist/vendor/adapters/core/src/persistence/integrity.d.ts +0 -39
  67. package/dist/vendor/adapters/core/src/persistence/integrity.js +0 -252
  68. package/dist/vendor/adapters/core/src/persistence/ledger.d.ts +0 -23
  69. package/dist/vendor/adapters/core/src/persistence/ledger.js +0 -9
  70. package/dist/vendor/adapters/core/src/persistence/memory-store.d.ts +0 -63
  71. package/dist/vendor/adapters/core/src/persistence/memory-store.js +0 -115
  72. package/dist/vendor/adapters/core/src/persistence/runs-reader.d.ts +0 -66
  73. package/dist/vendor/adapters/core/src/persistence/runs-reader.js +0 -140
  74. package/dist/vendor/adapters/core/src/persistence/store.d.ts +0 -89
  75. package/dist/vendor/adapters/core/src/persistence/store.js +0 -125
  76. package/dist/vendor/adapters/core/src/persistence/trace-store.d.ts +0 -85
  77. package/dist/vendor/adapters/core/src/persistence/trace-store.js +0 -125
  78. package/dist/vendor/adapters/core/src/policy-compiler.d.ts +0 -2
  79. package/dist/vendor/adapters/core/src/policy-compiler.js +0 -195
  80. package/dist/vendor/adapters/core/src/policy.d.ts +0 -156
  81. package/dist/vendor/adapters/core/src/policy.js +0 -704
  82. package/dist/vendor/adapters/core/src/repo-analyzer.d.ts +0 -53
  83. package/dist/vendor/adapters/core/src/repo-analyzer.js +0 -263
  84. package/dist/vendor/adapters/core/src/rollback.d.ts +0 -15
  85. package/dist/vendor/adapters/core/src/rollback.js +0 -253
  86. package/dist/vendor/adapters/core/src/routing.d.ts +0 -82
  87. package/dist/vendor/adapters/core/src/routing.js +0 -336
  88. package/dist/vendor/adapters/core/src/test-integrity.d.ts +0 -64
  89. package/dist/vendor/adapters/core/src/test-integrity.js +0 -197
  90. package/dist/vendor/adapters/core/src/trajectory.d.ts +0 -18
  91. package/dist/vendor/adapters/core/src/trajectory.js +0 -295
  92. package/dist/vendor/contracts/delivery.d.ts +0 -47
  93. package/dist/vendor/contracts/delivery.js +0 -18
  94. package/dist/vendor/core/delivery/index.d.ts +0 -6
  95. package/dist/vendor/core/delivery/index.js +0 -4
  96. package/dist/vendor/core/delivery/message-client.d.ts +0 -18
  97. package/dist/vendor/core/delivery/message-client.js +0 -38
  98. package/dist/vendor/core/delivery/message-ledger.d.ts +0 -35
  99. package/dist/vendor/core/delivery/message-ledger.js +0 -97
  100. package/dist/vendor/core/delivery/message-schema.d.ts +0 -16
  101. package/dist/vendor/core/delivery/message-schema.js +0 -111
  102. package/dist/vendor/core/delivery/update-check.d.ts +0 -19
  103. package/dist/vendor/core/delivery/update-check.js +0 -107
@@ -1,89 +0,0 @@
1
- import type { LoopBudget, LoopRecord, LoopTask, MachineState } from "../../../../contracts/index.js";
2
- import { type LedgerEvent } from "./ledger.js";
3
- export interface RunContract {
4
- runId: string;
5
- workspaceId: string;
6
- projectId: string;
7
- task: LoopTask;
8
- budget: LoopBudget;
9
- createdAt: string;
10
- metadata?: Record<string, string>;
11
- }
12
- export interface AttemptArtifacts {
13
- /** Compiled PromptPacket written as compiled-context.json */
14
- compiledContext: unknown;
15
- /** Structured verification evidence captured from the authoritative MartinLoop verifier (optional) */
16
- verification?: unknown;
17
- /** Unified diff string from the patch (optional) */
18
- diff?: string;
19
- /** Raw verifier command output (optional) */
20
- verifierOutput?: string;
21
- /** Grounding scan result (optional) */
22
- groundingScan?: unknown;
23
- /** Safety leash artifact captured for a blocked or escalated attempt (optional) */
24
- leash?: unknown;
25
- /** Patch score artifact captured for Phase 10 patch-truth decisions (optional) */
26
- patchScore?: unknown;
27
- /** Patch keep/discard/escalate decision artifact (optional) */
28
- patchDecision?: unknown;
29
- /** Rollback boundary captured before an attempt mutates the repo (optional) */
30
- rollbackBoundary?: unknown;
31
- /** Rollback restore outcome captured after discard/escalation/failure (optional) */
32
- rollbackOutcome?: unknown;
33
- }
34
- /**
35
- * RunStore isolates all filesystem persistence from orchestration logic.
36
- * runMartin accepts an optional store; when provided, every lifecycle event
37
- * is durably written before the run proceeds to the next step.
38
- */
39
- export interface RunStore {
40
- /**
41
- * Optional runs root hint for filesystem-backed stores.
42
- * Orchestration should prefer this over recomputing the default home store.
43
- */
44
- runsRoot?: string;
45
- /**
46
- * Write contract.json for a new run. Called once at run start.
47
- * The contract is immutable after this point.
48
- */
49
- initRun(contract: RunContract): Promise<void>;
50
- /**
51
- * Overwrite state.json with the current MachineState.
52
- * Called on every phase transition.
53
- */
54
- updateState(runId: string, state: MachineState): Promise<void>;
55
- /**
56
- * Append one event line to ledger.jsonl. Append-only — never rewrites.
57
- */
58
- appendLedger(runId: string, event: LedgerEvent): Promise<void>;
59
- /**
60
- * Write artifacts for a completed attempt to artifacts/attempt-<n>/.
61
- */
62
- writeAttemptArtifacts(runId: string, attemptIndex: number, artifacts: AttemptArtifacts): Promise<void>;
63
- /**
64
- * Persist the latest canonical loop record snapshot when the caller has one.
65
- * Optional to avoid breaking custom RunStore implementations.
66
- */
67
- writeLoopRecord?(runId: string, loop: LoopRecord): Promise<void>;
68
- }
69
- export declare function resolveRunsRoot(env?: NodeJS.ProcessEnv): string;
70
- export declare function runDir(runsRoot: string, runId: string): string;
71
- export declare function artifactDir(runsRoot: string, runId: string, attemptIndex: number): string;
72
- /**
73
- * Filesystem-backed RunStore. Writes to:
74
- * <runsRoot>/<runId>/contract.json
75
- * <runsRoot>/<runId>/state.json
76
- * <runsRoot>/<runId>/ledger.jsonl
77
- * <runsRoot>/<runId>/artifacts/attempt-<n>/compiled-context.json
78
- * <runsRoot>/<runId>/artifacts/attempt-<n>/diff.patch (if diff provided)
79
- * <runsRoot>/<runId>/artifacts/attempt-<n>/verifier-output.txt (if provided)
80
- * <runsRoot>/<runId>/artifacts/attempt-<n>/grounding-scan.json (if provided)
81
- * <runsRoot>/<runId>/artifacts/attempt-<n>/leash.json (if leash provided)
82
- * <runsRoot>/<runId>/artifacts/attempt-<n>/patch-score.json (if patchScore provided)
83
- * <runsRoot>/<runId>/artifacts/attempt-<n>/patch-decision.json (if patchDecision provided)
84
- * <runsRoot>/<runId>/artifacts/attempt-<n>/rollback-boundary.json (if rollbackBoundary provided)
85
- * <runsRoot>/<runId>/artifacts/attempt-<n>/rollback-outcome.json (if rollbackOutcome provided)
86
- */
87
- export declare function createFileRunStore(options?: {
88
- runsRoot?: string;
89
- }): RunStore;
@@ -1,125 +0,0 @@
1
- /// <reference types="node" />
2
- import { appendFile, mkdir, readFile, writeFile } from "node:fs/promises";
3
- import { homedir } from "node:os";
4
- import { join } from "node:path";
5
- import { writeReceiptIntegrityMaterial } from "./integrity.js";
6
- // ─── FileRunStore implementation ─────────────────────────────────────────────
7
- const RUN_INDEX_FILENAME = "run-index.ndjson";
8
- export function resolveRunsRoot(env = process.env) {
9
- return env["MARTIN_RUNS_DIR"]?.trim() ??
10
- join(homedir(), ".martin", "runs");
11
- }
12
- export function runDir(runsRoot, runId) {
13
- return join(runsRoot, runId);
14
- }
15
- export function artifactDir(runsRoot, runId, attemptIndex) {
16
- return join(runsRoot, runId, "artifacts", `attempt-${String(attemptIndex).padStart(3, "0")}`);
17
- }
18
- /**
19
- * Filesystem-backed RunStore. Writes to:
20
- * <runsRoot>/<runId>/contract.json
21
- * <runsRoot>/<runId>/state.json
22
- * <runsRoot>/<runId>/ledger.jsonl
23
- * <runsRoot>/<runId>/artifacts/attempt-<n>/compiled-context.json
24
- * <runsRoot>/<runId>/artifacts/attempt-<n>/diff.patch (if diff provided)
25
- * <runsRoot>/<runId>/artifacts/attempt-<n>/verifier-output.txt (if provided)
26
- * <runsRoot>/<runId>/artifacts/attempt-<n>/grounding-scan.json (if provided)
27
- * <runsRoot>/<runId>/artifacts/attempt-<n>/leash.json (if leash provided)
28
- * <runsRoot>/<runId>/artifacts/attempt-<n>/patch-score.json (if patchScore provided)
29
- * <runsRoot>/<runId>/artifacts/attempt-<n>/patch-decision.json (if patchDecision provided)
30
- * <runsRoot>/<runId>/artifacts/attempt-<n>/rollback-boundary.json (if rollbackBoundary provided)
31
- * <runsRoot>/<runId>/artifacts/attempt-<n>/rollback-outcome.json (if rollbackOutcome provided)
32
- */
33
- export function createFileRunStore(options = {}) {
34
- const runsRoot = options.runsRoot ?? resolveRunsRoot();
35
- return {
36
- runsRoot,
37
- async initRun(contract) {
38
- const dir = runDir(runsRoot, contract.runId);
39
- await mkdir(dir, { recursive: true });
40
- await writeJsonFile(join(dir, "contract.json"), contract);
41
- },
42
- async updateState(runId, state) {
43
- const dir = runDir(runsRoot, runId);
44
- await mkdir(dir, { recursive: true });
45
- await writeJsonFile(join(dir, "state.json"), state);
46
- },
47
- async appendLedger(runId, event) {
48
- const dir = runDir(runsRoot, runId);
49
- await mkdir(dir, { recursive: true });
50
- await appendFile(join(dir, "ledger.jsonl"), `${JSON.stringify(event)}\n`, "utf8");
51
- },
52
- async writeAttemptArtifacts(runId, attemptIndex, artifacts) {
53
- const dir = artifactDir(runsRoot, runId, attemptIndex);
54
- await mkdir(dir, { recursive: true });
55
- await writeJsonFile(join(dir, "compiled-context.json"), artifacts.compiledContext);
56
- if (artifacts.verification !== undefined) {
57
- await writeJsonFile(join(dir, "verification.json"), artifacts.verification);
58
- }
59
- if (artifacts.diff !== undefined) {
60
- await writeFile(join(dir, "diff.patch"), artifacts.diff, "utf8");
61
- }
62
- if (artifacts.verifierOutput !== undefined) {
63
- await writeFile(join(dir, "verifier-output.txt"), artifacts.verifierOutput, "utf8");
64
- }
65
- if (artifacts.groundingScan !== undefined) {
66
- await writeJsonFile(join(dir, "grounding-scan.json"), artifacts.groundingScan);
67
- }
68
- if (artifacts.leash !== undefined) {
69
- await writeJsonFile(join(dir, "leash.json"), artifacts.leash);
70
- }
71
- if (artifacts.patchScore !== undefined) {
72
- await writeJsonFile(join(dir, "patch-score.json"), artifacts.patchScore);
73
- }
74
- if (artifacts.patchDecision !== undefined) {
75
- await writeJsonFile(join(dir, "patch-decision.json"), artifacts.patchDecision);
76
- }
77
- if (artifacts.rollbackBoundary !== undefined) {
78
- await writeJsonFile(join(dir, "rollback-boundary.json"), artifacts.rollbackBoundary);
79
- }
80
- if (artifacts.rollbackOutcome !== undefined) {
81
- await writeJsonFile(join(dir, "rollback-outcome.json"), artifacts.rollbackOutcome);
82
- }
83
- },
84
- async writeLoopRecord(runId, loop) {
85
- const dir = runDir(runsRoot, runId);
86
- await mkdir(dir, { recursive: true });
87
- await writeJsonFile(join(dir, "loop-record.json"), loop);
88
- await appendRunIndexRecord(runsRoot, loop);
89
- const ledgerRaw = await readFile(join(dir, "ledger.jsonl"), "utf8").catch(() => "");
90
- const ledgerEntries = ledgerRaw
91
- .split(/\r?\n/u)
92
- .map((line) => line.trim())
93
- .filter(Boolean)
94
- .map((line) => JSON.parse(line));
95
- await writeReceiptIntegrityMaterial({
96
- runId,
97
- runsRoot,
98
- loopRecord: loop,
99
- ledgerEntries,
100
- scope: loop.receiptScope ??
101
- {
102
- ...(loop.task.repoRoot ? { repoRoot: loop.task.repoRoot } : {}),
103
- ...(loop.task.repoRoot ? { workingDirectory: loop.task.repoRoot } : {}),
104
- runsRoot
105
- },
106
- signedAt: loop.updatedAt
107
- });
108
- }
109
- };
110
- }
111
- // ─── Helpers ─────────────────────────────────────────────────────────────────
112
- async function writeJsonFile(path, value) {
113
- await writeFile(path, `${JSON.stringify(value, null, 2)}\n`, "utf8");
114
- }
115
- async function appendRunIndexRecord(runsRoot, loop) {
116
- const line = JSON.stringify({
117
- loopId: loop.loopId,
118
- workspaceId: loop.workspaceId,
119
- projectId: loop.projectId,
120
- status: loop.status,
121
- lifecycleState: loop.lifecycleState,
122
- updatedAt: loop.updatedAt
123
- });
124
- await appendFile(join(runsRoot, RUN_INDEX_FILENAME), `${line}\n`, "utf8");
125
- }
@@ -1,85 +0,0 @@
1
- /**
2
- * Append-Only Trace Store
3
- *
4
- * Aggregates run data over time to build institutional memory. Every governed
5
- * run's routing decision, cost, failure class, and outcome is appended to a
6
- * local JSONL trace file. Data is NEVER overwritten — only appended.
7
- *
8
- * The trace store feeds:
9
- * - classifyRoute() with historicalDirectSuccessRate from real past runs
10
- * - Cost prediction models with actual spend data
11
- * - Failure pattern detection across runs
12
- * - Team analytics and optimization recommendations
13
- *
14
- * Storage: `<runsRoot>/_martin/trace-log.jsonl` (one JSON object per line)
15
- */
16
- export interface TraceEntry {
17
- /** ISO-8601 timestamp */
18
- timestamp: string;
19
- /** Unique loop identifier */
20
- loopId: string;
21
- /** The objective that was governed */
22
- objective: string;
23
- /** Which engine executed the run */
24
- engine: string;
25
- /** Route selected by classifyRoute */
26
- selectedRoute: "direct" | "manager" | "consensus";
27
- /** Route classifier confidence (0-1) */
28
- routeConfidence: number;
29
- /** Budget allocated (USD) */
30
- budgetUsd: number;
31
- /** Actual spend (USD) */
32
- actualCostUsd: number;
33
- /** Pre-work burn percentage */
34
- preWorkBurnPct: number;
35
- /** Number of attempts */
36
- attempts: number;
37
- /** Final loop status */
38
- status: string;
39
- /** Final lifecycle state */
40
- lifecycleState: string;
41
- /** Failure class of last attempt (if failed) */
42
- failureClass?: string;
43
- /** Whether verification passed */
44
- verificationPassed: boolean;
45
- /** Number of files changed */
46
- filesChanged: number;
47
- /** Working directory (hashed for privacy) */
48
- workspaceHash: string;
49
- }
50
- export interface TraceAggregation {
51
- totalRuns: number;
52
- directRuns: number;
53
- managerRuns: number;
54
- consensusRuns: number;
55
- directSuccessRate: number;
56
- managerSuccessRate: number;
57
- averageCostUsd: number;
58
- averagePreWorkBurnPct: number;
59
- totalSpendUsd: number;
60
- totalSavedUsd: number;
61
- topFailureClasses: Array<{
62
- failureClass: string;
63
- count: number;
64
- }>;
65
- averageAttemptsPerRun: number;
66
- lastUpdated: string;
67
- }
68
- /**
69
- * Append a trace entry to the local trace store. Never overwrites.
70
- */
71
- export declare function appendTraceEntry(runsRoot: string, entry: TraceEntry): Promise<void>;
72
- /**
73
- * Read all trace entries from the local trace store.
74
- */
75
- export declare function readTraceEntries(runsRoot: string): Promise<TraceEntry[]>;
76
- /**
77
- * Aggregate trace entries into summary statistics.
78
- * Used by classifyRoute() to get historicalDirectSuccessRate.
79
- */
80
- export declare function aggregateTraces(entries: TraceEntry[]): TraceAggregation;
81
- /**
82
- * Get the historical direct success rate for use in route classification.
83
- * Returns undefined if insufficient data (< 5 runs).
84
- */
85
- export declare function getHistoricalDirectSuccessRate(runsRoot: string): Promise<number | undefined>;
@@ -1,125 +0,0 @@
1
- /**
2
- * Append-Only Trace Store
3
- *
4
- * Aggregates run data over time to build institutional memory. Every governed
5
- * run's routing decision, cost, failure class, and outcome is appended to a
6
- * local JSONL trace file. Data is NEVER overwritten — only appended.
7
- *
8
- * The trace store feeds:
9
- * - classifyRoute() with historicalDirectSuccessRate from real past runs
10
- * - Cost prediction models with actual spend data
11
- * - Failure pattern detection across runs
12
- * - Team analytics and optimization recommendations
13
- *
14
- * Storage: `<runsRoot>/_martin/trace-log.jsonl` (one JSON object per line)
15
- */
16
- import { appendFile, mkdir, readFile } from "node:fs/promises";
17
- import { join, resolve } from "node:path";
18
- const TRACE_DIRECTORY = "_martin";
19
- const TRACE_FILENAME = "trace-log.jsonl";
20
- function resolveTracePath(runsRoot) {
21
- return join(resolve(runsRoot), TRACE_DIRECTORY, TRACE_FILENAME);
22
- }
23
- /**
24
- * Append a trace entry to the local trace store. Never overwrites.
25
- */
26
- export async function appendTraceEntry(runsRoot, entry) {
27
- const tracePath = resolveTracePath(runsRoot);
28
- await mkdir(join(resolve(runsRoot), TRACE_DIRECTORY), { recursive: true });
29
- const line = JSON.stringify(entry) + "\n";
30
- await appendFile(tracePath, line, "utf8");
31
- }
32
- /**
33
- * Read all trace entries from the local trace store.
34
- */
35
- export async function readTraceEntries(runsRoot) {
36
- const tracePath = resolveTracePath(runsRoot);
37
- try {
38
- const raw = await readFile(tracePath, "utf8");
39
- return raw
40
- .split("\n")
41
- .filter((line) => line.trim().length > 0)
42
- .map((line) => {
43
- try {
44
- return JSON.parse(line);
45
- }
46
- catch {
47
- return null;
48
- }
49
- })
50
- .filter((entry) => entry !== null);
51
- }
52
- catch {
53
- return [];
54
- }
55
- }
56
- /**
57
- * Aggregate trace entries into summary statistics.
58
- * Used by classifyRoute() to get historicalDirectSuccessRate.
59
- */
60
- export function aggregateTraces(entries) {
61
- if (entries.length === 0) {
62
- return {
63
- totalRuns: 0,
64
- directRuns: 0,
65
- managerRuns: 0,
66
- consensusRuns: 0,
67
- directSuccessRate: 0,
68
- managerSuccessRate: 0,
69
- averageCostUsd: 0,
70
- averagePreWorkBurnPct: 0,
71
- totalSpendUsd: 0,
72
- totalSavedUsd: 0,
73
- topFailureClasses: [],
74
- averageAttemptsPerRun: 0,
75
- lastUpdated: new Date().toISOString()
76
- };
77
- }
78
- const direct = entries.filter((e) => e.selectedRoute === "direct");
79
- const manager = entries.filter((e) => e.selectedRoute === "manager");
80
- const consensus = entries.filter((e) => e.selectedRoute === "consensus");
81
- const directSuccesses = direct.filter((e) => e.status === "completed" && e.verificationPassed);
82
- const managerSuccesses = manager.filter((e) => e.status === "completed" && e.verificationPassed);
83
- const totalCost = entries.reduce((sum, e) => sum + e.actualCostUsd, 0);
84
- const totalBudget = entries.reduce((sum, e) => sum + e.budgetUsd, 0);
85
- const totalAttempts = entries.reduce((sum, e) => sum + e.attempts, 0);
86
- const totalBurnPct = entries.reduce((sum, e) => sum + e.preWorkBurnPct, 0);
87
- // Count failure classes
88
- const failureCounts = new Map();
89
- for (const entry of entries) {
90
- if (entry.failureClass) {
91
- failureCounts.set(entry.failureClass, (failureCounts.get(entry.failureClass) ?? 0) + 1);
92
- }
93
- }
94
- const topFailureClasses = [...failureCounts.entries()]
95
- .map(([failureClass, count]) => ({ failureClass, count }))
96
- .sort((a, b) => b.count - a.count)
97
- .slice(0, 10);
98
- return {
99
- totalRuns: entries.length,
100
- directRuns: direct.length,
101
- managerRuns: manager.length,
102
- consensusRuns: consensus.length,
103
- directSuccessRate: direct.length > 0 ? directSuccesses.length / direct.length : 0,
104
- managerSuccessRate: manager.length > 0 ? managerSuccesses.length / manager.length : 0,
105
- averageCostUsd: Math.round((totalCost / entries.length) * 100) / 100,
106
- averagePreWorkBurnPct: Math.round(totalBurnPct / entries.length),
107
- totalSpendUsd: Math.round(totalCost * 100) / 100,
108
- totalSavedUsd: Math.round((totalBudget - totalCost) * 100) / 100,
109
- topFailureClasses,
110
- averageAttemptsPerRun: Math.round((totalAttempts / entries.length) * 10) / 10,
111
- lastUpdated: entries[entries.length - 1]?.timestamp ?? new Date().toISOString()
112
- };
113
- }
114
- /**
115
- * Get the historical direct success rate for use in route classification.
116
- * Returns undefined if insufficient data (< 5 runs).
117
- */
118
- export async function getHistoricalDirectSuccessRate(runsRoot) {
119
- const entries = await readTraceEntries(runsRoot);
120
- const directRuns = entries.filter((e) => e.selectedRoute === "direct");
121
- if (directRuns.length < 5)
122
- return undefined;
123
- const successes = directRuns.filter((e) => e.status === "completed" && e.verificationPassed);
124
- return successes.length / directRuns.length;
125
- }
@@ -1,2 +0,0 @@
1
- import { type ExecutionPolicy, type ExecutionPolicyCompileInput } from "../../../contracts/index.js";
2
- export declare function compileExecutionPolicy(input: ExecutionPolicyCompileInput): ExecutionPolicy;
@@ -1,195 +0,0 @@
1
- import { cloneExecutionPolicy } from "../../../contracts/index.js";
2
- export function compileExecutionPolicy(input) {
3
- const provenance = [];
4
- const budget = {
5
- maxUsd: resolveBudgetField("maxUsd", input, provenance),
6
- softLimitUsd: resolveBudgetField("softLimitUsd", input, provenance),
7
- maxIterations: resolveBudgetField("maxIterations", input, provenance),
8
- maxTokens: resolveBudgetField("maxTokens", input, provenance)
9
- };
10
- if (budget.softLimitUsd >= budget.maxUsd) {
11
- budget.softLimitUsd = Math.round(budget.maxUsd * 0.75 * 100) / 100;
12
- provenance.push({
13
- field: "budget.softLimitUsd",
14
- source: "config",
15
- value: String(budget.softLimitUsd)
16
- });
17
- }
18
- const governance = {
19
- policyProfile: resolveEnumField({
20
- field: "governance.policyProfile",
21
- defaultsTo: input.defaults.policyProfile,
22
- configValue: input.config?.policyProfile,
23
- requestValue: input.request.policyProfile,
24
- allowed: ["strict", "balanced", "overnight", "debug"],
25
- provenance
26
- }),
27
- telemetryDestination: resolveEnumField({
28
- field: "governance.telemetryDestination",
29
- defaultsTo: input.defaults.telemetryDestination,
30
- configValue: input.config?.governance?.telemetryDestination,
31
- requestValue: input.request.telemetryDestination,
32
- allowed: ["local-only", "control-plane"],
33
- provenance
34
- }),
35
- destructiveActionPolicy: resolveEnumField({
36
- field: "governance.destructiveActionPolicy",
37
- defaultsTo: input.defaults.destructiveActionPolicy,
38
- configValue: input.config?.governance?.destructiveActionPolicy,
39
- allowed: ["never", "approval", "allowed"],
40
- provenance
41
- })
42
- };
43
- const verificationPlan = resolveVerificationPlan(input, provenance);
44
- const task = {
45
- verificationPlan
46
- };
47
- if (input.request.mutationMode) {
48
- task.mutationMode = input.request.mutationMode;
49
- provenance.push({
50
- field: "task.mutationMode",
51
- source: "request",
52
- value: input.request.mutationMode
53
- });
54
- }
55
- if (input.request.repoRoot) {
56
- task.repoRoot = input.request.repoRoot;
57
- provenance.push({
58
- field: "task.repoRoot",
59
- source: "request",
60
- value: input.request.repoRoot
61
- });
62
- }
63
- if ((input.request.allowedPaths?.length ?? 0) > 0) {
64
- const allowedPaths = input.request.allowedPaths ?? [];
65
- task.allowedPaths = [...allowedPaths];
66
- provenance.push({
67
- field: "task.allowedPaths",
68
- source: "request",
69
- value: allowedPaths.join(", ")
70
- });
71
- }
72
- if ((input.request.deniedPaths?.length ?? 0) > 0) {
73
- const deniedPaths = input.request.deniedPaths ?? [];
74
- task.deniedPaths = [...deniedPaths];
75
- provenance.push({
76
- field: "task.deniedPaths",
77
- source: "request",
78
- value: deniedPaths.join(", ")
79
- });
80
- }
81
- if ((input.request.acceptanceCriteria?.length ?? 0) > 0) {
82
- const acceptanceCriteria = input.request.acceptanceCriteria ?? [];
83
- task.acceptanceCriteria = [...acceptanceCriteria];
84
- provenance.push({
85
- field: "task.acceptanceCriteria",
86
- source: "request",
87
- value: acceptanceCriteria.join(", ")
88
- });
89
- }
90
- if (input.request.approvalPolicy) {
91
- task.approvalPolicy = { ...input.request.approvalPolicy };
92
- provenance.push({
93
- field: "task.approvalPolicy",
94
- source: "request",
95
- value: JSON.stringify(input.request.approvalPolicy)
96
- });
97
- }
98
- return cloneExecutionPolicy({
99
- configPath: input.configPath,
100
- budget,
101
- governance,
102
- task,
103
- provenance
104
- });
105
- }
106
- function resolveBudgetField(field, input, provenance) {
107
- if (input.request.budgetOverrides?.[field]) {
108
- const value = input.request.budget[field];
109
- provenance.push({
110
- field: `budget.${String(field)}`,
111
- source: "request",
112
- value: String(value)
113
- });
114
- return value;
115
- }
116
- const configValue = input.config?.budget?.[field];
117
- if (typeof configValue === "number" && Number.isFinite(configValue)) {
118
- provenance.push({
119
- field: `budget.${String(field)}`,
120
- source: "config",
121
- value: String(configValue)
122
- });
123
- return configValue;
124
- }
125
- const value = input.defaults.budget[field];
126
- provenance.push({
127
- field: `budget.${String(field)}`,
128
- source: "default",
129
- value: String(value)
130
- });
131
- return value;
132
- }
133
- function resolveVerificationPlan(input, provenance) {
134
- const requestVerificationPlan = normalizeStringList(input.request.verificationPlan);
135
- if (requestVerificationPlan.length > 0) {
136
- provenance.push({
137
- field: "task.verificationPlan",
138
- source: "request",
139
- value: requestVerificationPlan.join(", ")
140
- });
141
- return requestVerificationPlan;
142
- }
143
- const configVerificationPlan = normalizeStringList(input.config?.governance?.verifierRules);
144
- if (configVerificationPlan.length > 0) {
145
- provenance.push({
146
- field: "task.verificationPlan",
147
- source: "config",
148
- value: configVerificationPlan.join(", ")
149
- });
150
- return configVerificationPlan;
151
- }
152
- const defaultVerificationPlan = normalizeStringList(input.defaults.verifierRules);
153
- provenance.push({
154
- field: "task.verificationPlan",
155
- source: "default",
156
- value: defaultVerificationPlan.join(", ")
157
- });
158
- return defaultVerificationPlan;
159
- }
160
- function resolveEnumField(input) {
161
- const normalizedRequest = normalizeEnumCandidate(input.requestValue, input.allowed);
162
- if (normalizedRequest) {
163
- input.provenance.push({
164
- field: input.field,
165
- source: "request",
166
- value: normalizedRequest
167
- });
168
- return normalizedRequest;
169
- }
170
- const normalizedConfig = normalizeEnumCandidate(input.configValue, input.allowed);
171
- if (normalizedConfig) {
172
- input.provenance.push({
173
- field: input.field,
174
- source: "config",
175
- value: normalizedConfig
176
- });
177
- return normalizedConfig;
178
- }
179
- input.provenance.push({
180
- field: input.field,
181
- source: "default",
182
- value: input.defaultsTo
183
- });
184
- return input.defaultsTo;
185
- }
186
- function normalizeEnumCandidate(value, allowed) {
187
- if (typeof value !== "string") {
188
- return undefined;
189
- }
190
- const trimmed = value.trim();
191
- return allowed.find((candidate) => candidate === trimmed);
192
- }
193
- function normalizeStringList(values) {
194
- return (values ?? []).map((value) => value.trim()).filter(Boolean);
195
- }