martin-loop 0.1.1 → 0.1.3

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 (62) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +331 -58
  3. package/dist/bin/martin-loop.js +12 -8
  4. package/dist/index.d.ts +21 -8
  5. package/dist/index.js +31 -9
  6. package/dist/vendor/adapters/claude-cli.d.ts +89 -0
  7. package/dist/vendor/adapters/claude-cli.js +555 -0
  8. package/dist/vendor/adapters/cli-bridge.d.ts +28 -0
  9. package/dist/vendor/adapters/cli-bridge.js +127 -0
  10. package/dist/vendor/adapters/direct-provider.d.ts +10 -0
  11. package/dist/vendor/adapters/direct-provider.js +41 -0
  12. package/dist/vendor/adapters/index.d.ts +5 -0
  13. package/dist/vendor/adapters/index.js +5 -0
  14. package/dist/vendor/adapters/runtime-support.d.ts +14 -0
  15. package/dist/vendor/adapters/runtime-support.js +52 -0
  16. package/dist/vendor/adapters/stub-agent-cli.d.ts +8 -0
  17. package/dist/vendor/adapters/stub-agent-cli.js +41 -0
  18. package/dist/vendor/adapters/stub-direct-provider.d.ts +8 -0
  19. package/dist/vendor/adapters/stub-direct-provider.js +10 -0
  20. package/dist/vendor/cli/bin/martin.js +19 -0
  21. package/dist/vendor/cli/index.d.ts +39 -0
  22. package/dist/vendor/cli/index.js +634 -0
  23. package/dist/vendor/cli/persistence.d.ts +34 -0
  24. package/dist/vendor/cli/persistence.js +71 -0
  25. package/dist/vendor/contracts/governance.d.ts +21 -0
  26. package/dist/vendor/contracts/governance.js +12 -0
  27. package/dist/vendor/contracts/index.d.ts +330 -0
  28. package/dist/vendor/contracts/index.js +203 -0
  29. package/dist/vendor/core/compiler.d.ts +50 -0
  30. package/dist/vendor/core/compiler.js +47 -0
  31. package/dist/vendor/core/grounding.d.ts +37 -0
  32. package/dist/vendor/core/grounding.js +270 -0
  33. package/dist/vendor/core/index.d.ts +145 -0
  34. package/dist/vendor/core/index.js +1099 -0
  35. package/dist/vendor/core/leash.d.ts +48 -0
  36. package/dist/vendor/core/leash.js +408 -0
  37. package/dist/vendor/core/persistence/compiler.d.ts +18 -0
  38. package/dist/vendor/core/persistence/compiler.js +35 -0
  39. package/dist/vendor/core/persistence/index.d.ts +6 -0
  40. package/dist/vendor/core/persistence/index.js +4 -0
  41. package/dist/vendor/core/persistence/ledger.d.ts +23 -0
  42. package/dist/vendor/core/persistence/ledger.js +10 -0
  43. package/dist/vendor/core/persistence/store.d.ts +77 -0
  44. package/dist/vendor/core/persistence/store.js +84 -0
  45. package/dist/vendor/core/policy.d.ts +126 -0
  46. package/dist/vendor/core/policy.js +625 -0
  47. package/dist/vendor/core/rollback.d.ts +11 -0
  48. package/dist/vendor/core/rollback.js +219 -0
  49. package/docs/oss/EXAMPLES.md +126 -0
  50. package/docs/oss/OSS-BOUNDARY-REPORT.json +113 -0
  51. package/docs/oss/OSS-BOUNDARY-REPORT.md +48 -0
  52. package/docs/oss/QUICKSTART.md +135 -0
  53. package/docs/{README.md → oss/README.md} +17 -13
  54. package/docs/oss/RELEASE-SURFACE-REPORT.json +45 -0
  55. package/docs/oss/RELEASE-SURFACE-REPORT.md +35 -0
  56. package/package.json +27 -35
  57. package/dist/bin/martin-loop.js.map +0 -1
  58. package/dist/index.js.map +0 -1
  59. package/docs/EXAMPLES.md +0 -96
  60. package/docs/QUICKSTART.md +0 -127
  61. package/docs/release/CLAIM-TO-CAPABILITY.md +0 -19
  62. /package/dist/{bin/martin-loop.d.ts → vendor/cli/bin/martin.d.ts} +0 -0
@@ -0,0 +1,84 @@
1
+ /// <reference types="node" />
2
+ import { appendFile, mkdir, writeFile } from "node:fs/promises";
3
+ import { homedir } from "node:os";
4
+ import { join } from "node:path";
5
+ // ─── FileRunStore implementation ─────────────────────────────────────────────
6
+ export function resolveRunsRoot(env = process.env) {
7
+ return env["MARTIN_RUNS_DIR"]?.trim() ??
8
+ join(homedir(), ".martin", "runs");
9
+ }
10
+ export function runDir(runsRoot, runId) {
11
+ return join(runsRoot, runId);
12
+ }
13
+ export function artifactDir(runsRoot, runId, attemptIndex) {
14
+ return join(runsRoot, runId, "artifacts", `attempt-${String(attemptIndex).padStart(3, "0")}`);
15
+ }
16
+ /**
17
+ * Filesystem-backed RunStore. Writes to:
18
+ * <runsRoot>/<runId>/contract.json
19
+ * <runsRoot>/<runId>/state.json
20
+ * <runsRoot>/<runId>/ledger.jsonl
21
+ * <runsRoot>/<runId>/artifacts/attempt-<n>/compiled-context.json
22
+ * <runsRoot>/<runId>/artifacts/attempt-<n>/diff.patch (if diff provided)
23
+ * <runsRoot>/<runId>/artifacts/attempt-<n>/verifier-output.txt (if provided)
24
+ * <runsRoot>/<runId>/artifacts/attempt-<n>/grounding-scan.json (if provided)
25
+ * <runsRoot>/<runId>/artifacts/attempt-<n>/leash.json (if leash provided)
26
+ * <runsRoot>/<runId>/artifacts/attempt-<n>/patch-score.json (if patchScore provided)
27
+ * <runsRoot>/<runId>/artifacts/attempt-<n>/patch-decision.json (if patchDecision provided)
28
+ * <runsRoot>/<runId>/artifacts/attempt-<n>/rollback-boundary.json (if rollbackBoundary provided)
29
+ * <runsRoot>/<runId>/artifacts/attempt-<n>/rollback-outcome.json (if rollbackOutcome provided)
30
+ */
31
+ export function createFileRunStore(options = {}) {
32
+ const runsRoot = options.runsRoot ?? resolveRunsRoot();
33
+ return {
34
+ async initRun(contract) {
35
+ const dir = runDir(runsRoot, contract.runId);
36
+ await mkdir(dir, { recursive: true });
37
+ await writeJsonFile(join(dir, "contract.json"), contract);
38
+ },
39
+ async updateState(runId, state) {
40
+ const dir = runDir(runsRoot, runId);
41
+ await mkdir(dir, { recursive: true });
42
+ await writeJsonFile(join(dir, "state.json"), state);
43
+ },
44
+ async appendLedger(runId, event) {
45
+ const dir = runDir(runsRoot, runId);
46
+ await mkdir(dir, { recursive: true });
47
+ await appendFile(join(dir, "ledger.jsonl"), `${JSON.stringify(event)}\n`, "utf8");
48
+ },
49
+ async writeAttemptArtifacts(runId, attemptIndex, artifacts) {
50
+ const dir = artifactDir(runsRoot, runId, attemptIndex);
51
+ await mkdir(dir, { recursive: true });
52
+ await writeJsonFile(join(dir, "compiled-context.json"), artifacts.compiledContext);
53
+ if (artifacts.diff !== undefined) {
54
+ await writeFile(join(dir, "diff.patch"), artifacts.diff, "utf8");
55
+ }
56
+ if (artifacts.verifierOutput !== undefined) {
57
+ await writeFile(join(dir, "verifier-output.txt"), artifacts.verifierOutput, "utf8");
58
+ }
59
+ if (artifacts.groundingScan !== undefined) {
60
+ await writeJsonFile(join(dir, "grounding-scan.json"), artifacts.groundingScan);
61
+ }
62
+ if (artifacts.leash !== undefined) {
63
+ await writeJsonFile(join(dir, "leash.json"), artifacts.leash);
64
+ }
65
+ if (artifacts.patchScore !== undefined) {
66
+ await writeJsonFile(join(dir, "patch-score.json"), artifacts.patchScore);
67
+ }
68
+ if (artifacts.patchDecision !== undefined) {
69
+ await writeJsonFile(join(dir, "patch-decision.json"), artifacts.patchDecision);
70
+ }
71
+ if (artifacts.rollbackBoundary !== undefined) {
72
+ await writeJsonFile(join(dir, "rollback-boundary.json"), artifacts.rollbackBoundary);
73
+ }
74
+ if (artifacts.rollbackOutcome !== undefined) {
75
+ await writeJsonFile(join(dir, "rollback-outcome.json"), artifacts.rollbackOutcome);
76
+ }
77
+ }
78
+ };
79
+ }
80
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
81
+ async function writeJsonFile(path, value) {
82
+ await writeFile(path, `${JSON.stringify(value, null, 2)}\n`, "utf8");
83
+ }
84
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1,126 @@
1
+ import type { BudgetPreflightEstimate, CostProvenance, EvidenceVector, FailureClass, InterventionType, LoopAttempt, LoopBudget, LoopCost, LoopLifecycleState, LoopStatus, PatchDecisionArtifact, PatchScore, PolicyPhase } from "../contracts/index.js";
2
+ export interface FailureAssessment {
3
+ failureClass: FailureClass;
4
+ rationale: string;
5
+ retryable: boolean;
6
+ recommendedIntervention: InterventionType;
7
+ }
8
+ export interface CostGovernorState {
9
+ pressure: "healthy" | "soft_limit" | "hard_limit";
10
+ shouldStop: boolean;
11
+ remainingBudgetUsd: number;
12
+ remainingIterations: number;
13
+ remainingTokens: number;
14
+ recommendedIntervention?: InterventionType;
15
+ }
16
+ export interface ExitDecision {
17
+ shouldExit: boolean;
18
+ lifecycleState: LoopLifecycleState;
19
+ status: LoopStatus;
20
+ reason: string;
21
+ }
22
+ export interface MartinAdapterResultLike {
23
+ status: "completed" | "failed";
24
+ summary: string;
25
+ usage?: {
26
+ actualUsd: number;
27
+ estimatedUsd?: number;
28
+ tokensIn: number;
29
+ tokensOut: number;
30
+ provenance?: CostProvenance;
31
+ };
32
+ verification: {
33
+ passed: boolean;
34
+ summary: string;
35
+ };
36
+ failure?: {
37
+ message: string;
38
+ classHint?: FailureClass;
39
+ };
40
+ }
41
+ /**
42
+ * Maps a PolicyPhase to the LoopLifecycleState used in events and persistence.
43
+ * FailureClass remains a thin output label — policy reads EvidenceVector, not the label.
44
+ */
45
+ export declare function policyPhaseToLifecycleState(phase: PolicyPhase): LoopLifecycleState;
46
+ /**
47
+ * Determines the next PolicyPhase given the current phase and last result.
48
+ * This is the explicit typed transition table — no implicit fallthrough.
49
+ */
50
+ export declare function nextPolicyPhase(current: PolicyPhase, result: MartinAdapterResultLike, costState: CostGovernorState, retryCount: number): PolicyPhase;
51
+ export declare function classifyFailure(input: {
52
+ attempts: LoopAttempt[];
53
+ result: MartinAdapterResultLike;
54
+ }): FailureAssessment;
55
+ export declare function evaluateCostGovernor(input: {
56
+ budget: LoopBudget;
57
+ cost: LoopCost;
58
+ attemptsUsed: number;
59
+ }): CostGovernorState;
60
+ export declare function inferExit(input: {
61
+ loop: {
62
+ budget: LoopBudget;
63
+ cost: LoopCost;
64
+ attempts: LoopAttempt[];
65
+ };
66
+ lastResult: MartinAdapterResultLike;
67
+ lastFailure?: FailureAssessment;
68
+ costState: CostGovernorState;
69
+ canSwitchAdapter?: boolean;
70
+ }): ExitDecision;
71
+ export interface BudgetPreflightInput {
72
+ promptCharCount: number;
73
+ attemptCount: number;
74
+ remainingBudgetUsd: number;
75
+ perAttemptCapUsd?: number;
76
+ pricePerMTokenUsd?: number;
77
+ }
78
+ export interface BudgetPreflightDecision {
79
+ allowed: boolean;
80
+ reason: string;
81
+ estimate: BudgetPreflightEstimate;
82
+ }
83
+ export declare function evaluateBudgetPreflight(input: BudgetPreflightInput): BudgetPreflightDecision;
84
+ export interface EvidenceVectorInput {
85
+ compilerOutput?: string;
86
+ testOutput?: string;
87
+ diff?: string;
88
+ previousDiff?: string;
89
+ forbiddenTouchedFiles?: string[];
90
+ missingSymbols?: string[];
91
+ actualUsd?: number;
92
+ previousVerifierScore?: number;
93
+ verifierScore?: number;
94
+ retryCountForSurface?: number;
95
+ }
96
+ export declare function computeEvidenceVector(input: EvidenceVectorInput): EvidenceVector;
97
+ export type RecoveryRecipe = "narrow_prompt_targeted_files" | "failing_tests_only" | "force_repo_anatomy_slices" | "tighten_allowlist_reduce_patch" | "strategy_swap" | "abort_safety_violation" | "downgrade_model" | "escalate_human";
98
+ export interface RecoveryDecision {
99
+ recipe: RecoveryRecipe;
100
+ rationale: string;
101
+ intervention: InterventionType;
102
+ }
103
+ export interface PatchDecisionInput {
104
+ verificationPassed: boolean;
105
+ previousVerifierScore?: number;
106
+ verifierScore?: number;
107
+ groundingViolationCount?: number;
108
+ safetyViolationCount?: number;
109
+ scopeViolationCount?: number;
110
+ changedFileCount?: number;
111
+ diffNovelty?: number;
112
+ diffStats?: {
113
+ filesChanged: number;
114
+ addedLines: number;
115
+ deletedLines: number;
116
+ };
117
+ costUsd?: number;
118
+ humanApprovalRequired?: boolean;
119
+ summary?: string;
120
+ }
121
+ export interface EvaluatedPatchDecision extends PatchDecisionArtifact {
122
+ score: PatchScore;
123
+ }
124
+ export declare function selectRecoveryRecipe(evidence: EvidenceVector): RecoveryDecision;
125
+ export declare function evaluatePatchDecision(input: PatchDecisionInput): EvaluatedPatchDecision;
126
+ export declare function scorePatchDecision(input: PatchDecisionInput): PatchScore;