@martinloop/mcp 0.1.4 → 0.2.5

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 (74) hide show
  1. package/README.md +138 -135
  2. package/dist/discovery-metadata.d.ts +16 -0
  3. package/dist/discovery-metadata.js +62 -0
  4. package/dist/discovery-support.d.ts +62 -0
  5. package/dist/discovery-support.js +224 -0
  6. package/dist/package-version.d.ts +1 -0
  7. package/dist/package-version.js +3 -0
  8. package/dist/prompts.d.ts +13 -0
  9. package/dist/prompts.js +455 -0
  10. package/dist/resources.d.ts +29 -0
  11. package/dist/resources.js +575 -0
  12. package/dist/server-validation.d.ts +2 -3
  13. package/dist/server-validation.js +295 -87
  14. package/dist/server.d.ts +76 -7
  15. package/dist/server.js +1135 -247
  16. package/dist/tools/doctor.js +14 -6
  17. package/dist/tools/get-attempt.d.ts +15 -0
  18. package/dist/tools/get-attempt.js +15 -0
  19. package/dist/tools/get-run.d.ts +24 -0
  20. package/dist/tools/get-run.js +23 -0
  21. package/dist/tools/get-status.d.ts +11 -0
  22. package/dist/tools/get-status.js +12 -2
  23. package/dist/tools/get-verification-results.d.ts +14 -0
  24. package/dist/tools/get-verification-results.js +14 -0
  25. package/dist/tools/inspect-loop.d.ts +9 -0
  26. package/dist/tools/inspect-loop.js +11 -2
  27. package/dist/tools/list-runs.d.ts +29 -0
  28. package/dist/tools/list-runs.js +24 -0
  29. package/dist/tools/preflight.js +7 -2
  30. package/dist/tools/run-dossier.d.ts +41 -0
  31. package/dist/tools/run-dossier.js +41 -0
  32. package/dist/tools/run-loop.d.ts +19 -0
  33. package/dist/tools/run-loop.js +41 -3
  34. package/dist/tools/run-store.d.ts +57 -3
  35. package/dist/tools/run-store.js +404 -53
  36. package/dist/tools/tool-errors.d.ts +37 -0
  37. package/dist/tools/tool-errors.js +170 -0
  38. package/dist/tools/tool-response.d.ts +16 -0
  39. package/dist/tools/tool-response.js +34 -0
  40. package/dist/tools/tool-support.d.ts +92 -2
  41. package/dist/tools/tool-support.js +358 -63
  42. package/dist/tools/triage-runs.d.ts +33 -0
  43. package/dist/tools/triage-runs.js +138 -0
  44. package/dist/vendor/adapters/claude-cli.js +0 -1
  45. package/dist/vendor/adapters/cli-bridge.js +0 -1
  46. package/dist/vendor/adapters/direct-provider.js +0 -1
  47. package/dist/vendor/adapters/index.js +0 -1
  48. package/dist/vendor/adapters/runtime-support.js +0 -1
  49. package/dist/vendor/adapters/stub-agent-cli.js +0 -1
  50. package/dist/vendor/adapters/stub-direct-provider.js +0 -1
  51. package/dist/vendor/adapters/verifier-only.js +0 -1
  52. package/dist/vendor/contracts/governance.js +0 -1
  53. package/dist/vendor/contracts/index.d.ts +2 -0
  54. package/dist/vendor/contracts/index.js +1 -1
  55. package/dist/vendor/contracts/operator.d.ts +19 -0
  56. package/dist/vendor/contracts/operator.js +11 -0
  57. package/dist/vendor/core/compiler.js +0 -1
  58. package/dist/vendor/core/context-integrity.js +0 -1
  59. package/dist/vendor/core/grounding.js +0 -1
  60. package/dist/vendor/core/index.js +1 -2
  61. package/dist/vendor/core/leash.js +19 -12
  62. package/dist/vendor/core/persistence/compiler.js +0 -1
  63. package/dist/vendor/core/persistence/index.js +0 -1
  64. package/dist/vendor/core/persistence/ledger.js +0 -1
  65. package/dist/vendor/core/persistence/runs-reader.js +0 -1
  66. package/dist/vendor/core/persistence/store.js +0 -1
  67. package/dist/vendor/core/policy.js +0 -1
  68. package/dist/vendor/core/red-blue/red-phase.d.ts +64 -0
  69. package/dist/vendor/core/red-blue/red-phase.js +135 -0
  70. package/dist/vendor/core/red-blue/risk-tiers.d.ts +22 -0
  71. package/dist/vendor/core/red-blue/risk-tiers.js +32 -0
  72. package/dist/vendor/core/rollback.js +2 -3
  73. package/package.json +10 -3
  74. package/server.json +2 -2
@@ -23,11 +23,12 @@ export async function martinDoctorTool(input) {
23
23
  }
24
24
  warnings.push(...runStore.warnings);
25
25
  const status = warnings.length === 0 ? "ok" : "degraded";
26
+ const summary = status === "ok"
27
+ ? `Doctor passed: ${runStore.loopCount} run(s) visible in ${runsRoot}.`
28
+ : `Doctor found ${warnings.length} issue(s); review warnings before live execution.`;
26
29
  return {
27
30
  status,
28
- summary: status === "ok"
29
- ? `Doctor passed: ${runStore.loopCount} run(s) visible in ${runsRoot}.`
30
- : `Doctor found ${warnings.length} issue(s); review warnings before live execution.`,
31
+ summary,
31
32
  server: {
32
33
  name: "martin-loop",
33
34
  nodeVersion: process.version,
@@ -41,8 +42,16 @@ export async function martinDoctorTool(input) {
41
42
  liveMode: executionMode.liveMode
42
43
  },
43
44
  engines: {
44
- claude,
45
- codex
45
+ claude: {
46
+ available: claude.available,
47
+ detail: claude.detail,
48
+ ...(claude.resolvedPath ? { resolvedPath: claude.resolvedPath } : {})
49
+ },
50
+ codex: {
51
+ available: codex.available,
52
+ detail: codex.detail,
53
+ ...(codex.resolvedPath ? { resolvedPath: codex.resolvedPath } : {})
54
+ }
46
55
  },
47
56
  ...(input.engine ? { requestedEngine: input.engine } : {}),
48
57
  runStore: {
@@ -53,4 +62,3 @@ export async function martinDoctorTool(input) {
53
62
  warnings
54
63
  };
55
64
  }
56
- //# sourceMappingURL=doctor.js.map
@@ -0,0 +1,15 @@
1
+ import { buildAttemptSummary, buildLoopPreview } from "./tool-support.js";
2
+ export interface MartinGetAttemptInput {
3
+ file?: string;
4
+ loopId?: string;
5
+ runsDir?: string;
6
+ attemptIndex?: number;
7
+ }
8
+ export interface MartinGetAttemptOutput {
9
+ source: string;
10
+ sourceKind: "file" | "loop_id" | "latest" | "runs_root";
11
+ loop: ReturnType<typeof buildLoopPreview>;
12
+ attempt: ReturnType<typeof buildAttemptSummary>;
13
+ warnings: string[];
14
+ }
15
+ export declare function martinGetAttemptTool(input: MartinGetAttemptInput): Promise<MartinGetAttemptOutput>;
@@ -0,0 +1,15 @@
1
+ import { buildAttemptArtifactsReference, buildAttemptSummary, buildLoopPreview } from "./tool-support.js";
2
+ import { loadAttemptFromLoop } from "./run-store.js";
3
+ export async function martinGetAttemptTool(input) {
4
+ const { detail, attempt } = await loadAttemptFromLoop(input);
5
+ const artifacts = detail.canonicalRunDirectory
6
+ ? await buildAttemptArtifactsReference(detail.runsRoot, detail.loop.loopId, attempt.index)
7
+ : undefined;
8
+ return {
9
+ source: detail.source,
10
+ sourceKind: detail.sourceKind,
11
+ loop: buildLoopPreview(detail.loop),
12
+ attempt: buildAttemptSummary(attempt, artifacts),
13
+ warnings: detail.warnings
14
+ };
15
+ }
@@ -0,0 +1,24 @@
1
+ import { buildArtifactSummary, buildBudgetSnapshot, buildCostSnapshot, buildLoopPreview, buildVerificationSummary } from "./tool-support.js";
2
+ export interface MartinGetRunInput {
3
+ file?: string;
4
+ loopId?: string;
5
+ runsDir?: string;
6
+ latest?: boolean;
7
+ }
8
+ export interface MartinGetRunOutput {
9
+ source: string;
10
+ sourceKind: "file" | "loop_id" | "latest" | "runs_root";
11
+ loop: ReturnType<typeof buildLoopPreview>;
12
+ budget: ReturnType<typeof buildBudgetSnapshot>;
13
+ cost: ReturnType<typeof buildCostSnapshot>;
14
+ verification: ReturnType<typeof buildVerificationSummary>;
15
+ artifacts: ReturnType<typeof buildArtifactSummary>;
16
+ inspection: {
17
+ runsRoot: string;
18
+ canonicalRunDirectory?: string;
19
+ canonicalLoopRecordPath?: string;
20
+ ledgerPath?: string;
21
+ };
22
+ warnings: string[];
23
+ }
24
+ export declare function martinGetRunTool(input: MartinGetRunInput): Promise<MartinGetRunOutput>;
@@ -0,0 +1,23 @@
1
+ import { buildArtifactSummary, buildBudgetSnapshot, buildCostSnapshot, buildLoopPreview, buildVerificationSummary } from "./tool-support.js";
2
+ import { loadDetailedLoopRecord, readLedgerEvents } from "./run-store.js";
3
+ export async function martinGetRunTool(input) {
4
+ const detail = await loadDetailedLoopRecord(input);
5
+ const ledgerEvents = await readLedgerEvents(detail);
6
+ const verification = buildVerificationSummary(detail.loop, ledgerEvents);
7
+ return {
8
+ source: detail.source,
9
+ sourceKind: detail.sourceKind,
10
+ loop: buildLoopPreview(detail.loop),
11
+ budget: buildBudgetSnapshot(detail.loop.budget),
12
+ cost: buildCostSnapshot(detail.loop.cost),
13
+ verification,
14
+ artifacts: buildArtifactSummary(detail.loop),
15
+ inspection: {
16
+ runsRoot: detail.runsRoot,
17
+ ...(detail.canonicalRunDirectory ? { canonicalRunDirectory: detail.canonicalRunDirectory } : {}),
18
+ ...(detail.canonicalLoopRecordPath ? { canonicalLoopRecordPath: detail.canonicalLoopRecordPath } : {}),
19
+ ...(detail.ledgerPath ? { ledgerPath: detail.ledgerPath } : {})
20
+ },
21
+ warnings: [...detail.warnings, ...verification.warnings]
22
+ };
23
+ }
@@ -1,3 +1,4 @@
1
+ import { type LoopPreview } from "./tool-support.js";
1
2
  export interface GetStatusInput {
2
3
  /** JSON-serialized LoopRecord. */
3
4
  loopJson?: string;
@@ -11,6 +12,7 @@ export interface GetStatusInput {
11
12
  latest?: boolean;
12
13
  }
13
14
  export interface GetStatusOutput {
15
+ source: string;
14
16
  loopId: string;
15
17
  status: string;
16
18
  lifecycleState: string;
@@ -22,5 +24,14 @@ export interface GetStatusOutput {
22
24
  remainingBudgetUsd: number;
23
25
  remainingIterations: number;
24
26
  remainingTokens: number;
27
+ budget: {
28
+ maxUsd: number;
29
+ softLimitUsd: number;
30
+ maxIterations: number;
31
+ maxTokens: number;
32
+ };
33
+ inspection: {
34
+ loop: LoopPreview;
35
+ };
25
36
  }
26
37
  export declare function getStatusTool(input: GetStatusInput): Promise<GetStatusOutput>;
@@ -1,5 +1,6 @@
1
1
  import { evaluateCostGovernor } from "../vendor/core/index.js";
2
2
  import { loadLoopRecordForStatus } from "./run-store.js";
3
+ import { buildLoopPreview } from "./tool-support.js";
3
4
  export async function getStatusTool(input) {
4
5
  const resolved = await loadLoopRecordForStatus(input);
5
6
  const loop = resolved.loop;
@@ -14,6 +15,7 @@ export async function getStatusTool(input) {
14
15
  attemptsUsed: loop.attempts.length
15
16
  });
16
17
  return {
18
+ source: resolved.source,
17
19
  loopId: loop.loopId,
18
20
  status: loop.status,
19
21
  lifecycleState: loop.lifecycleState,
@@ -24,7 +26,15 @@ export async function getStatusTool(input) {
24
26
  shouldStop: costState.shouldStop,
25
27
  remainingBudgetUsd: costState.remainingBudgetUsd,
26
28
  remainingIterations: costState.remainingIterations,
27
- remainingTokens: costState.remainingTokens
29
+ remainingTokens: costState.remainingTokens,
30
+ budget: {
31
+ maxUsd: loop.budget.maxUsd,
32
+ softLimitUsd: loop.budget.softLimitUsd,
33
+ maxIterations: loop.budget.maxIterations,
34
+ maxTokens: loop.budget.maxTokens
35
+ },
36
+ inspection: {
37
+ loop: buildLoopPreview(loop)
38
+ }
28
39
  };
29
40
  }
30
- //# sourceMappingURL=get-status.js.map
@@ -0,0 +1,14 @@
1
+ import { buildLoopPreview, buildVerificationSummary } from "./tool-support.js";
2
+ export interface MartinGetVerificationResultsInput {
3
+ file?: string;
4
+ loopId?: string;
5
+ runsDir?: string;
6
+ }
7
+ export interface MartinGetVerificationResultsOutput {
8
+ source: string;
9
+ sourceKind: "file" | "loop_id" | "latest" | "runs_root";
10
+ loop: ReturnType<typeof buildLoopPreview>;
11
+ verification: ReturnType<typeof buildVerificationSummary>;
12
+ warnings: string[];
13
+ }
14
+ export declare function martinGetVerificationResultsTool(input: MartinGetVerificationResultsInput): Promise<MartinGetVerificationResultsOutput>;
@@ -0,0 +1,14 @@
1
+ import { buildLoopPreview, buildVerificationSummary } from "./tool-support.js";
2
+ import { loadDetailedLoopRecord, readLedgerEvents } from "./run-store.js";
3
+ export async function martinGetVerificationResultsTool(input) {
4
+ const detail = await loadDetailedLoopRecord(input);
5
+ const ledgerEvents = await readLedgerEvents(detail);
6
+ const verification = buildVerificationSummary(detail.loop, ledgerEvents);
7
+ return {
8
+ source: detail.source,
9
+ sourceKind: detail.sourceKind,
10
+ loop: buildLoopPreview(detail.loop),
11
+ verification,
12
+ warnings: [...detail.warnings, ...verification.warnings]
13
+ };
14
+ }
@@ -1,4 +1,5 @@
1
1
  import { type PortfolioSnapshot } from "../vendor/contracts/index.js";
2
+ import { type LoopPreview } from "./tool-support.js";
2
3
  export interface InspectLoopInput {
3
4
  /** Optional path to a JSON, JSONL, or run-store directory under the Martin runs root. */
4
5
  file?: string;
@@ -9,5 +10,13 @@ export interface InspectLoopOutput {
9
10
  source: string;
10
11
  loopCount: number;
11
12
  portfolio: PortfolioSnapshot;
13
+ latestRun?: LoopPreview;
14
+ recentRuns: LoopPreview[];
15
+ statusBreakdown: Record<string, number>;
16
+ lifecycleBreakdown: Record<string, number>;
17
+ inspection: {
18
+ sourceKind: "file" | "runs_root";
19
+ };
20
+ warnings: string[];
12
21
  }
13
22
  export declare function inspectLoopTool(input: InspectLoopInput): Promise<InspectLoopOutput>;
@@ -1,12 +1,21 @@
1
1
  import { buildPortfolioSnapshot } from "../vendor/contracts/index.js";
2
2
  import { loadLoopRecordsForInspect } from "./run-store.js";
3
+ import { buildLoopCollectionSummary } from "./tool-support.js";
3
4
  export async function inspectLoopTool(input) {
4
5
  const inspection = await loadLoopRecordsForInspect(input);
5
6
  const loops = inspection.loops;
7
+ const summary = buildLoopCollectionSummary(inspection.loops);
6
8
  return {
7
9
  source: inspection.source,
8
10
  loopCount: loops.length,
9
- portfolio: buildPortfolioSnapshot(loops)
11
+ portfolio: buildPortfolioSnapshot(loops),
12
+ ...(summary.latestRun ? { latestRun: summary.latestRun } : {}),
13
+ recentRuns: summary.recentRuns,
14
+ statusBreakdown: summary.statusBreakdown,
15
+ lifecycleBreakdown: summary.lifecycleBreakdown,
16
+ inspection: {
17
+ sourceKind: input.file ? "file" : "runs_root"
18
+ },
19
+ warnings: inspection.warnings
10
20
  };
11
21
  }
12
- //# sourceMappingURL=inspect-loop.js.map
@@ -0,0 +1,29 @@
1
+ import { buildLoopPreview } from "./tool-support.js";
2
+ export interface MartinListRunsInput {
3
+ runsDir?: string;
4
+ limit?: number;
5
+ status?: string;
6
+ lifecycleState?: string;
7
+ adapterId?: string;
8
+ model?: string;
9
+ updatedAfter?: string;
10
+ }
11
+ export interface MartinListRunsOutput {
12
+ source: string;
13
+ runsRoot: string;
14
+ filters: {
15
+ limit: number;
16
+ status?: string;
17
+ lifecycleState?: string;
18
+ adapterId?: string;
19
+ model?: string;
20
+ updatedAfter?: string;
21
+ };
22
+ loopCount: number;
23
+ latestRun?: ReturnType<typeof buildLoopPreview>;
24
+ recentRuns: Array<ReturnType<typeof buildLoopPreview>>;
25
+ statusBreakdown: Record<string, number>;
26
+ lifecycleBreakdown: Record<string, number>;
27
+ warnings: string[];
28
+ }
29
+ export declare function martinListRunsTool(input: MartinListRunsInput): Promise<MartinListRunsOutput>;
@@ -0,0 +1,24 @@
1
+ import { buildLoopCollectionSummary, buildLoopPreview } from "./tool-support.js";
2
+ import { listLoopRecords } from "./run-store.js";
3
+ export async function martinListRunsTool(input) {
4
+ const result = await listLoopRecords(input);
5
+ const summary = buildLoopCollectionSummary(result.loops);
6
+ return {
7
+ source: result.source,
8
+ runsRoot: result.runsRoot,
9
+ filters: {
10
+ limit: input.limit ?? 20,
11
+ ...(input.status ? { status: input.status } : {}),
12
+ ...(input.lifecycleState ? { lifecycleState: input.lifecycleState } : {}),
13
+ ...(input.adapterId ? { adapterId: input.adapterId } : {}),
14
+ ...(input.model ? { model: input.model } : {}),
15
+ ...(input.updatedAfter ? { updatedAfter: input.updatedAfter } : {})
16
+ },
17
+ loopCount: result.loops.length,
18
+ ...(summary.latestRun ? { latestRun: summary.latestRun } : {}),
19
+ recentRuns: result.loops.map((loop) => buildLoopPreview(loop)),
20
+ statusBreakdown: summary.statusBreakdown,
21
+ lifecycleBreakdown: summary.lifecycleBreakdown,
22
+ warnings: result.warnings
23
+ };
24
+ }
@@ -58,7 +58,13 @@ export async function martinPreflightTool(input) {
58
58
  },
59
59
  execution: {
60
60
  requestedEngine: engine,
61
- engineAvailability,
61
+ engineAvailability: {
62
+ available: engineAvailability.available,
63
+ detail: engineAvailability.detail,
64
+ ...(engineAvailability.resolvedPath
65
+ ? { resolvedPath: engineAvailability.resolvedPath }
66
+ : {})
67
+ },
62
68
  runsRoot: resolveRunsRoot(process.env),
63
69
  pathScope: {
64
70
  repoRoot: workingDirectory,
@@ -73,4 +79,3 @@ export async function martinPreflightTool(input) {
73
79
  }
74
80
  };
75
81
  }
76
- //# sourceMappingURL=preflight.js.map
@@ -0,0 +1,41 @@
1
+ import { buildArtifactSummary, buildBudgetSnapshot, buildCostSnapshot, buildEventSummaries, buildLoopPreview, buildVerificationSummary } from "./tool-support.js";
2
+ export interface MartinRunDossierInput {
3
+ file?: string;
4
+ loopId?: string;
5
+ runsDir?: string;
6
+ latest?: boolean;
7
+ }
8
+ export interface MartinRunDossierOutput {
9
+ source: string;
10
+ sourceKind: "file" | "loop_id" | "latest" | "runs_root";
11
+ loop: ReturnType<typeof buildLoopPreview>;
12
+ budget: ReturnType<typeof buildBudgetSnapshot>;
13
+ cost: ReturnType<typeof buildCostSnapshot>;
14
+ attempts: Array<{
15
+ index: number;
16
+ attemptId?: string;
17
+ adapterId?: string;
18
+ model?: string;
19
+ failureClass?: string;
20
+ intervention?: string;
21
+ startedAt?: string;
22
+ completedAt?: string;
23
+ summary?: string;
24
+ artifactFiles: string[];
25
+ }>;
26
+ verification: ReturnType<typeof buildVerificationSummary>;
27
+ artifacts: ReturnType<typeof buildArtifactSummary>;
28
+ recentEvents: ReturnType<typeof buildEventSummaries>;
29
+ related: {
30
+ resources: string[];
31
+ prompts: string[];
32
+ };
33
+ inspection: {
34
+ runsRoot: string;
35
+ canonicalRunDirectory?: string;
36
+ canonicalLoopRecordPath?: string;
37
+ ledgerPath?: string;
38
+ };
39
+ warnings: string[];
40
+ }
41
+ export declare function martinRunDossierTool(input: MartinRunDossierInput): Promise<MartinRunDossierOutput>;
@@ -0,0 +1,41 @@
1
+ import { buildArtifactSummary, buildBudgetSnapshot, buildCostSnapshot, buildEventSummaries, buildLoopPreview, buildSuggestedPromptNames, buildSuggestedResourceUris, buildVerificationSummary } from "./tool-support.js";
2
+ import { loadDetailedLoopRecord, readAttemptArtifactFiles, readLedgerEvents } from "./run-store.js";
3
+ export async function martinRunDossierTool(input) {
4
+ const detail = await loadDetailedLoopRecord(input);
5
+ const ledgerEvents = await readLedgerEvents(detail);
6
+ const verification = buildVerificationSummary(detail.loop, ledgerEvents);
7
+ const attempts = await Promise.all(detail.loop.attempts.map(async (attempt) => ({
8
+ index: attempt.index,
9
+ ...(attempt.attemptId ? { attemptId: attempt.attemptId } : {}),
10
+ ...(attempt.adapterId ? { adapterId: attempt.adapterId } : {}),
11
+ ...(attempt.model ? { model: attempt.model } : {}),
12
+ ...(attempt.failureClass ? { failureClass: attempt.failureClass } : {}),
13
+ ...(attempt.intervention ? { intervention: attempt.intervention } : {}),
14
+ ...(attempt.startedAt ? { startedAt: attempt.startedAt } : {}),
15
+ ...(attempt.completedAt ? { completedAt: attempt.completedAt } : {}),
16
+ ...(attempt.summary ? { summary: attempt.summary } : {}),
17
+ artifactFiles: await readAttemptArtifactFiles(detail, attempt.index)
18
+ })));
19
+ return {
20
+ source: detail.source,
21
+ sourceKind: detail.sourceKind,
22
+ loop: buildLoopPreview(detail.loop),
23
+ budget: buildBudgetSnapshot(detail.loop.budget),
24
+ cost: buildCostSnapshot(detail.loop.cost),
25
+ attempts,
26
+ verification,
27
+ artifacts: buildArtifactSummary(detail.loop),
28
+ recentEvents: buildEventSummaries(detail.loop, 8),
29
+ related: {
30
+ resources: buildSuggestedResourceUris(detail.loop.loopId),
31
+ prompts: buildSuggestedPromptNames()
32
+ },
33
+ inspection: {
34
+ runsRoot: detail.runsRoot,
35
+ ...(detail.canonicalRunDirectory ? { canonicalRunDirectory: detail.canonicalRunDirectory } : {}),
36
+ ...(detail.canonicalLoopRecordPath ? { canonicalLoopRecordPath: detail.canonicalLoopRecordPath } : {}),
37
+ ...(detail.ledgerPath ? { ledgerPath: detail.ledgerPath } : {})
38
+ },
39
+ warnings: [...detail.warnings, ...verification.warnings]
40
+ };
41
+ }
@@ -1,3 +1,5 @@
1
+ import { type LoopBudget } from "../vendor/contracts/index.js";
2
+ import { buildArtifactSummary, buildVerificationSummary, buildLoopPreview, type MartinEngine } from "./tool-support.js";
1
3
  export interface RunLoopInput {
2
4
  objective: string;
3
5
  workingDirectory?: string;
@@ -20,5 +22,22 @@ export interface RunLoopOutput {
20
22
  costUsd: number;
21
23
  verificationPassed: boolean;
22
24
  loopId: string;
25
+ pressure: string;
26
+ shouldStop: boolean;
27
+ remainingBudgetUsd: number;
28
+ remainingIterations: number;
29
+ remainingTokens: number;
30
+ engine: MartinEngine;
31
+ workingDirectory: string;
32
+ budget: LoopBudget;
33
+ inspection: {
34
+ runsRoot: string;
35
+ runDirectory: string;
36
+ loopRecordPath: string;
37
+ ledgerPath: string;
38
+ loop: ReturnType<typeof buildLoopPreview>;
39
+ verification: ReturnType<typeof buildVerificationSummary>;
40
+ artifacts: ReturnType<typeof buildArtifactSummary>;
41
+ };
23
42
  }
24
43
  export declare function runLoopTool(input: RunLoopInput): Promise<RunLoopOutput>;
@@ -1,13 +1,24 @@
1
1
  import { createClaudeCliAdapter, createCodexCliAdapter, createStubDirectProviderAdapter } from "../vendor/adapters/index.js";
2
- import { createFileRunStore, resolveRunsRoot, runMartin } from "../vendor/core/index.js";
2
+ import { createFileRunStore, evaluateCostGovernor, resolveRunsRoot, runMartin } from "../vendor/core/index.js";
3
3
  import { DEFAULT_BUDGET } from "../vendor/contracts/index.js";
4
4
  import { normalizeSafePathPatterns, resolveSafeRepoRoot } from "../server-validation.js";
5
+ import { MartinToolError } from "./tool-errors.js";
6
+ import { buildArtifactSummary, buildVerificationSummary, buildLoopPreview, buildRunRecordPaths, getEngineAvailability, resolveExecutionMode } from "./tool-support.js";
5
7
  export async function runLoopTool(input) {
6
8
  const workingDirectory = resolveSafeRepoRoot(input.workingDirectory);
7
9
  const engine = input.engine ?? "claude";
8
10
  const model = input.model;
9
11
  const allowedPaths = normalizeSafePathPatterns(input.allowedPaths, "allowedPaths");
10
12
  const deniedPaths = normalizeSafePathPatterns(input.deniedPaths, "deniedPaths");
13
+ const executionMode = resolveExecutionMode();
14
+ const engineAvailability = getEngineAvailability(engine);
15
+ if (executionMode.liveMode && !engineAvailability.available) {
16
+ throw new MartinToolError("engine_unavailable", `Engine '${engine}' is not available on PATH.`, {
17
+ category: "environment",
18
+ suggestion: "Install the requested CLI or set MARTIN_LIVE=false for stub execution.",
19
+ retryable: false
20
+ });
21
+ }
11
22
  const adapter = process.env.MARTIN_LIVE === "false"
12
23
  ? createStubDirectProviderAdapter({ label: "Stub adapter (MARTIN_LIVE=false)", providerId: "stub", model: "stub" })
13
24
  : engine === "codex"
@@ -44,6 +55,20 @@ export async function runLoopTool(input) {
44
55
  });
45
56
  const lastAttempt = result.loop.attempts.at(-1);
46
57
  const verificationPassed = lastAttempt !== undefined && result.decision.lifecycleState === "completed";
58
+ const costState = evaluateCostGovernor({
59
+ budget: result.loop.budget,
60
+ cost: {
61
+ actualUsd: result.loop.cost.actualUsd,
62
+ avoidedUsd: result.loop.cost.avoidedUsd ?? 0,
63
+ tokensIn: result.loop.cost.tokensIn,
64
+ tokensOut: result.loop.cost.tokensOut
65
+ },
66
+ attemptsUsed: result.loop.attempts.length
67
+ });
68
+ const runsRoot = resolveRunsRoot(process.env);
69
+ const recordPaths = buildRunRecordPaths(runsRoot, result.loop.loopId);
70
+ const verification = buildVerificationSummary(result.loop);
71
+ const artifacts = buildArtifactSummary(result.loop);
47
72
  return {
48
73
  status: result.loop.status,
49
74
  lifecycleState: result.decision.lifecycleState,
@@ -51,7 +76,20 @@ export async function runLoopTool(input) {
51
76
  attempts: result.loop.attempts.length,
52
77
  costUsd: result.loop.cost.actualUsd,
53
78
  verificationPassed,
54
- loopId: result.loop.loopId
79
+ loopId: result.loop.loopId,
80
+ pressure: costState.pressure,
81
+ shouldStop: costState.shouldStop,
82
+ remainingBudgetUsd: costState.remainingBudgetUsd,
83
+ remainingIterations: costState.remainingIterations,
84
+ remainingTokens: costState.remainingTokens,
85
+ engine,
86
+ workingDirectory,
87
+ budget,
88
+ inspection: {
89
+ ...recordPaths,
90
+ loop: buildLoopPreview(result.loop),
91
+ verification,
92
+ artifacts
93
+ }
55
94
  };
56
95
  }
57
- //# sourceMappingURL=run-loop.js.map
@@ -1,12 +1,44 @@
1
- import { type LoopRunRecord } from "../vendor/core/index.js";
1
+ import { type LedgerEvent } from "../vendor/core/index.js";
2
+ import type { InspectableLoopRecord } from "./tool-support.js";
2
3
  export interface InspectLoopSource {
3
4
  source: string;
4
- loops: LoopRunRecord[];
5
+ loops: InspectableLoopRecord[];
6
+ warnings: string[];
5
7
  }
6
8
  export interface StatusLoopSource {
7
9
  source: string;
8
- loop: LoopRunRecord;
10
+ loop: InspectableLoopRecord;
9
11
  }
12
+ export interface DetailedLoopSource {
13
+ source: string;
14
+ sourceKind: "file" | "loop_id" | "latest" | "runs_root";
15
+ runsRoot: string;
16
+ loop: InspectableLoopRecord;
17
+ warnings: string[];
18
+ canonicalRunDirectory?: string;
19
+ canonicalLoopRecordPath?: string;
20
+ ledgerPath?: string;
21
+ }
22
+ export interface LoopListInput {
23
+ runsDir?: string;
24
+ limit?: number;
25
+ status?: string;
26
+ lifecycleState?: string;
27
+ adapterId?: string;
28
+ model?: string;
29
+ updatedAfter?: string;
30
+ }
31
+ export interface LoopListResult {
32
+ source: string;
33
+ runsRoot: string;
34
+ loops: InspectableLoopRecord[];
35
+ warnings: string[];
36
+ }
37
+ export type LedgerEventsWithDiagnostics = LedgerEvent[] & {
38
+ warnings?: string[];
39
+ unreadable?: boolean;
40
+ ledgerPath?: string;
41
+ };
10
42
  export declare function loadLoopRecordsForInspect(input: {
11
43
  file?: string;
12
44
  runsDir?: string;
@@ -18,3 +50,25 @@ export declare function loadLoopRecordForStatus(input: {
18
50
  runsDir?: string;
19
51
  latest?: boolean;
20
52
  }): Promise<StatusLoopSource>;
53
+ export declare function listLoopRecords(input: LoopListInput): Promise<LoopListResult>;
54
+ export declare function loadDetailedLoopRecord(input: {
55
+ file?: string;
56
+ loopId?: string;
57
+ runsDir?: string;
58
+ latest?: boolean;
59
+ }): Promise<DetailedLoopSource>;
60
+ export declare function loadAttemptFromLoop(input: {
61
+ file?: string;
62
+ loopId?: string;
63
+ runsDir?: string;
64
+ attemptIndex?: number;
65
+ }): Promise<{
66
+ detail: DetailedLoopSource;
67
+ attempt: InspectableLoopRecord["attempts"][number];
68
+ }>;
69
+ export declare function readLedgerEvents(detail: DetailedLoopSource): Promise<LedgerEventsWithDiagnostics>;
70
+ export declare function readAttemptArtifactFiles(detail: DetailedLoopSource, attemptIndex: number): Promise<string[]>;
71
+ export declare function readAllLoopRecordsSafely(runsRoot: string): Promise<{
72
+ loops: InspectableLoopRecord[];
73
+ warnings: string[];
74
+ }>;