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.
- package/CODE_OF_CONDUCT.md +32 -0
- package/LICENSE +21 -21
- package/README.md +307 -398
- package/demo/seeded-workspace/README.md +35 -35
- package/demo/seeded-workspace/TASKS.md +29 -29
- package/demo/seeded-workspace/martin.config.yaml +11 -11
- package/demo/seeded-workspace/package.json +8 -8
- package/demo/seeded-workspace/src/invoice-summary.js +11 -11
- package/demo/seeded-workspace/test/invoice-summary.test.js +20 -20
- package/dist/bin/martin-loop.js +0 -0
- package/dist/vendor/adapters/counter.d.ts +1 -0
- package/dist/vendor/adapters/counter.js +4 -0
- package/dist/vendor/adapters/git-baseline.d.ts +50 -0
- package/dist/vendor/adapters/git-baseline.js +233 -0
- package/dist/vendor/adapters/openrouter-adapter.d.ts +15 -0
- package/dist/vendor/adapters/openrouter-adapter.js +302 -0
- package/dist/vendor/adapters/usage.d.ts +48 -0
- package/dist/vendor/adapters/usage.js +66 -0
- package/dist/vendor/cli/bin/exit.d.ts +12 -0
- package/dist/vendor/cli/bin/exit.js +28 -0
- package/dist/vendor/cli/commands/analyze.d.ts +5 -0
- package/dist/vendor/cli/commands/analyze.js +58 -0
- package/dist/vendor/cli/commands/audit-log-verify.d.ts +34 -0
- package/dist/vendor/cli/commands/audit-log-verify.js +99 -0
- package/dist/vendor/cli/commands/audit.d.ts +8 -0
- package/dist/vendor/cli/commands/audit.js +199 -0
- package/dist/vendor/cli/commands/corpus.d.ts +5 -0
- package/dist/vendor/cli/commands/corpus.js +60 -0
- package/dist/vendor/cli/commands/doctor.d.ts +8 -0
- package/dist/vendor/cli/commands/doctor.js +219 -0
- package/dist/vendor/cli/commands/explain.d.ts +17 -0
- package/dist/vendor/cli/commands/explain.js +176 -0
- package/dist/vendor/cli/commands/export.d.ts +5 -0
- package/dist/vendor/cli/commands/export.js +60 -0
- package/dist/vendor/cli/commands/governance.d.ts +8 -0
- package/dist/vendor/cli/commands/governance.js +95 -0
- package/dist/vendor/cli/commands/improve.d.ts +18 -0
- package/dist/vendor/cli/commands/improve.js +396 -0
- package/dist/vendor/cli/commands/init.d.ts +8 -0
- package/dist/vendor/cli/commands/init.js +281 -0
- package/dist/vendor/cli/commands/migration.d.ts +8 -0
- package/dist/vendor/cli/commands/migration.js +67 -0
- package/dist/vendor/cli/commands/prior.d.ts +23 -0
- package/dist/vendor/cli/commands/prior.js +145 -0
- package/dist/vendor/cli/commands/resume.d.ts +21 -0
- package/dist/vendor/cli/commands/resume.js +73 -0
- package/dist/vendor/cli/commands/verify.d.ts +6 -0
- package/dist/vendor/cli/commands/verify.js +43 -0
- package/dist/vendor/cli/research/public-corpus.d.ts +43 -0
- package/dist/vendor/cli/research/public-corpus.js +151 -0
- package/dist/vendor/cli/ui/error-card.d.ts +38 -0
- package/dist/vendor/cli/ui/error-card.js +103 -0
- package/dist/vendor/cli/ui/mission-brief.d.ts +41 -0
- package/dist/vendor/cli/ui/mission-brief.js +173 -0
- package/dist/vendor/cli/ui/summary-card.d.ts +34 -0
- package/dist/vendor/cli/ui/summary-card.js +102 -0
- package/dist/vendor/contracts/audit.d.ts +46 -0
- package/dist/vendor/contracts/audit.js +360 -0
- package/dist/vendor/contracts/post-phase15.d.ts +240 -0
- package/dist/vendor/contracts/post-phase15.js +166 -0
- package/dist/vendor/core/agent/mandates.d.ts +46 -0
- package/dist/vendor/core/agent/mandates.js +178 -0
- package/dist/vendor/core/agent/receipts.d.ts +38 -0
- package/dist/vendor/core/agent/receipts.js +131 -0
- package/dist/vendor/core/agent/signing.d.ts +17 -0
- package/dist/vendor/core/agent/signing.js +91 -0
- package/dist/vendor/core/attestation/sign.d.ts +25 -0
- package/dist/vendor/core/attestation/sign.js +216 -0
- package/dist/vendor/core/autonomy/autonomous-promotion.d.ts +120 -0
- package/dist/vendor/core/autonomy/autonomous-promotion.js +346 -0
- package/dist/vendor/core/autonomy/envelope-v2.d.ts +29 -0
- package/dist/vendor/core/autonomy/envelope-v2.js +60 -0
- package/dist/vendor/core/autonomy/envelope.d.ts +17 -0
- package/dist/vendor/core/autonomy/envelope.js +27 -0
- package/dist/vendor/core/autonomy/escalation-ledger.d.ts +20 -0
- package/dist/vendor/core/autonomy/escalation-ledger.js +18 -0
- package/dist/vendor/core/autonomy/resume.d.ts +15 -0
- package/dist/vendor/core/autonomy/resume.js +23 -0
- package/dist/vendor/core/circuit/circuit-breaker.d.ts +60 -0
- package/dist/vendor/core/circuit/circuit-breaker.js +143 -0
- package/dist/vendor/core/context-distillation.d.ts +3 -0
- package/dist/vendor/core/context-distillation.js +44 -0
- package/dist/vendor/core/context-flow/compile-context.d.ts +8 -0
- package/dist/vendor/core/context-flow/compile-context.js +111 -0
- package/dist/vendor/core/context-flow/entities.d.ts +2 -0
- package/dist/vendor/core/context-flow/entities.js +44 -0
- package/dist/vendor/core/context-flow/evaluate-policy.d.ts +2 -0
- package/dist/vendor/core/context-flow/evaluate-policy.js +42 -0
- package/dist/vendor/core/context-flow/index.d.ts +11 -0
- package/dist/vendor/core/context-flow/index.js +24 -0
- package/dist/vendor/core/context-flow/labels.d.ts +3 -0
- package/dist/vendor/core/context-flow/labels.js +17 -0
- package/dist/vendor/core/context-flow/normalizer.d.ts +9 -0
- package/dist/vendor/core/context-flow/normalizer.js +69 -0
- package/dist/vendor/core/context-flow/profiles.d.ts +33 -0
- package/dist/vendor/core/context-flow/profiles.js +36 -0
- package/dist/vendor/core/context-flow/redaction.d.ts +1 -0
- package/dist/vendor/core/context-flow/redaction.js +6 -0
- package/dist/vendor/core/context-flow/sensitivity.d.ts +2 -0
- package/dist/vendor/core/context-flow/sensitivity.js +27 -0
- package/dist/vendor/core/context-flow/sync-preview.d.ts +2 -0
- package/dist/vendor/core/context-flow/sync-preview.js +22 -0
- package/dist/vendor/core/context-flow/token-estimator.d.ts +3 -0
- package/dist/vendor/core/context-flow/token-estimator.js +13 -0
- package/dist/vendor/core/context-flow/types.d.ts +91 -0
- package/dist/vendor/core/context-flow/types.js +2 -0
- package/dist/vendor/core/context-utility.d.ts +47 -0
- package/dist/vendor/core/context-utility.js +405 -0
- package/dist/vendor/core/cost/pipeline.d.ts +92 -0
- package/dist/vendor/core/cost/pipeline.js +141 -0
- package/dist/vendor/core/cost/tagged-cost.d.ts +27 -0
- package/dist/vendor/core/cost/tagged-cost.js +55 -0
- package/dist/vendor/core/cost-governor.d.ts +2 -0
- package/dist/vendor/core/cost-governor.js +50 -0
- package/dist/vendor/core/cve/cve-check.d.ts +80 -0
- package/dist/vendor/core/cve/cve-check.js +172 -0
- package/dist/vendor/core/digital-twin/index.d.ts +27 -0
- package/dist/vendor/core/digital-twin/index.js +90 -0
- package/dist/vendor/core/drift/drift-graph.d.ts +47 -0
- package/dist/vendor/core/drift/drift-graph.js +100 -0
- package/dist/vendor/core/drift/objective-lock.d.ts +69 -0
- package/dist/vendor/core/drift/objective-lock.js +88 -0
- package/dist/vendor/core/drift/scope.d.ts +46 -0
- package/dist/vendor/core/drift/scope.js +102 -0
- package/dist/vendor/core/drift/signature-lock.d.ts +48 -0
- package/dist/vendor/core/drift/signature-lock.js +202 -0
- package/dist/vendor/core/drift/stale-proof-gate.d.ts +21 -0
- package/dist/vendor/core/drift/stale-proof-gate.js +19 -0
- package/dist/vendor/core/eval/known-bad-world-runner.d.ts +24 -0
- package/dist/vendor/core/eval/known-bad-world-runner.js +256 -0
- package/dist/vendor/core/evidence/claim-audit.d.ts +18 -0
- package/dist/vendor/core/evidence/claim-audit.js +89 -0
- package/dist/vendor/core/exit-intelligence.d.ts +2 -0
- package/dist/vendor/core/exit-intelligence.js +58 -0
- package/dist/vendor/core/explain/formatter.d.ts +42 -0
- package/dist/vendor/core/explain/formatter.js +171 -0
- package/dist/vendor/core/explain/timeline.d.ts +29 -0
- package/dist/vendor/core/explain/timeline.js +213 -0
- package/dist/vendor/core/failure-taxonomy.d.ts +2 -0
- package/dist/vendor/core/failure-taxonomy.js +76 -0
- package/dist/vendor/core/gateway/index.d.ts +10 -0
- package/dist/vendor/core/gateway/index.js +12 -0
- package/dist/vendor/core/gateway/registry.d.ts +40 -0
- package/dist/vendor/core/gateway/registry.js +97 -0
- package/dist/vendor/core/gateway/transport.d.ts +31 -0
- package/dist/vendor/core/gateway/transport.js +82 -0
- package/dist/vendor/core/gateway/vault.d.ts +19 -0
- package/dist/vendor/core/gateway/vault.js +29 -0
- package/dist/vendor/core/graph/adapters.d.ts +43 -0
- package/dist/vendor/core/graph/adapters.js +91 -0
- package/dist/vendor/core/graph/hotspots.d.ts +22 -0
- package/dist/vendor/core/graph/hotspots.js +30 -0
- package/dist/vendor/core/graph/index.d.ts +1 -0
- package/dist/vendor/core/graph/index.js +2 -0
- package/dist/vendor/core/honey/honey-tokens.d.ts +32 -0
- package/dist/vendor/core/honey/honey-tokens.js +44 -0
- package/dist/vendor/core/index.d.ts +2 -2
- package/dist/vendor/core/index.js +38 -12
- package/dist/vendor/core/learning/bayesian-update.d.ts +31 -0
- package/dist/vendor/core/learning/bayesian-update.js +60 -0
- package/dist/vendor/core/learning/prior-sets.d.ts +42 -0
- package/dist/vendor/core/learning/prior-sets.js +111 -0
- package/dist/vendor/core/learning/promotion-gate.d.ts +17 -0
- package/dist/vendor/core/learning/promotion-gate.js +23 -0
- package/dist/vendor/core/leash/blast-radius.d.ts +42 -0
- package/dist/vendor/core/leash/blast-radius.js +156 -0
- package/dist/vendor/core/leash/policy-leash.d.ts +31 -0
- package/dist/vendor/core/leash/policy-leash.js +117 -0
- package/dist/vendor/core/memo/memo.d.ts +63 -0
- package/dist/vendor/core/memo/memo.js +97 -0
- package/dist/vendor/core/memory/learning-pipeline.d.ts +154 -0
- package/dist/vendor/core/memory/learning-pipeline.js +391 -0
- package/dist/vendor/core/memory/palace.d.ts +84 -0
- package/dist/vendor/core/memory/palace.js +379 -0
- package/dist/vendor/core/merge/ast-merge.d.ts +22 -0
- package/dist/vendor/core/merge/ast-merge.js +350 -0
- package/dist/vendor/core/merge/text-merge.d.ts +12 -0
- package/dist/vendor/core/merge/text-merge.js +182 -0
- package/dist/vendor/core/otel/tracer.d.ts +45 -0
- package/dist/vendor/core/otel/tracer.js +116 -0
- package/dist/vendor/core/parallel/parallel-attempts.d.ts +28 -0
- package/dist/vendor/core/parallel/parallel-attempts.js +41 -0
- package/dist/vendor/core/parallel/scorer.d.ts +24 -0
- package/dist/vendor/core/parallel/scorer.js +65 -0
- package/dist/vendor/core/pattern-detection.d.ts +64 -0
- package/dist/vendor/core/pattern-detection.js +108 -0
- package/dist/vendor/core/persistence/checkpoint.d.ts +44 -0
- package/dist/vendor/core/persistence/checkpoint.js +156 -0
- package/dist/vendor/core/persistence/cleanup.d.ts +22 -0
- package/dist/vendor/core/persistence/cleanup.js +131 -0
- package/dist/vendor/core/persistence/index.d.ts +2 -0
- package/dist/vendor/core/persistence/index.js +1 -0
- package/dist/vendor/core/persistence/runs-reader.d.ts +52 -0
- package/dist/vendor/core/persistence/runs-reader.js +84 -0
- package/dist/vendor/core/persistence/store.d.ts +6 -1
- package/dist/vendor/core/persistence/store.js +5 -0
- package/dist/vendor/core/policy/file-touch-quota.d.ts +60 -0
- package/dist/vendor/core/policy/file-touch-quota.js +105 -0
- package/dist/vendor/core/policy/policy-loader.d.ts +30 -0
- package/dist/vendor/core/policy/policy-loader.js +170 -0
- package/dist/vendor/core/policy/policy-schema.d.ts +55 -0
- package/dist/vendor/core/policy/policy-schema.js +78 -0
- package/dist/vendor/core/probe/probe.d.ts +49 -0
- package/dist/vendor/core/probe/probe.js +115 -0
- package/dist/vendor/core/proof/patch-proof.d.ts +58 -0
- package/dist/vendor/core/proof/patch-proof.js +84 -0
- package/dist/vendor/core/proof/semantic-probe.d.ts +25 -0
- package/dist/vendor/core/proof/semantic-probe.js +82 -0
- package/dist/vendor/core/recovery/failure-mode-runner.d.ts +29 -0
- package/dist/vendor/core/recovery/failure-mode-runner.js +39 -0
- package/dist/vendor/core/red-blue/red-phase.d.ts +64 -0
- package/dist/vendor/core/red-blue/red-phase.js +141 -0
- package/dist/vendor/core/red-blue/risk-tiers.d.ts +22 -0
- package/dist/vendor/core/red-blue/risk-tiers.js +33 -0
- package/dist/vendor/core/replay/replay.d.ts +85 -0
- package/dist/vendor/core/replay/replay.js +109 -0
- package/dist/vendor/core/router/engine.d.ts +54 -0
- package/dist/vendor/core/router/engine.js +131 -0
- package/dist/vendor/core/router/index.d.ts +1 -0
- package/dist/vendor/core/router/index.js +2 -0
- package/dist/vendor/core/router/trust-calibration.d.ts +57 -0
- package/dist/vendor/core/router/trust-calibration.js +127 -0
- package/dist/vendor/core/run-martin.d.ts +2 -0
- package/dist/vendor/core/run-martin.js +287 -0
- package/dist/vendor/core/security/cve-scanner.d.ts +62 -0
- package/dist/vendor/core/security/cve-scanner.js +178 -0
- package/dist/vendor/core/sentinel/efficiency-sentinel.d.ts +29 -0
- package/dist/vendor/core/sentinel/efficiency-sentinel.js +30 -0
- package/dist/vendor/core/sentinel/progress-guard.d.ts +35 -0
- package/dist/vendor/core/sentinel/progress-guard.js +46 -0
- package/dist/vendor/core/siem/siem-emitter.d.ts +49 -0
- package/dist/vendor/core/siem/siem-emitter.js +157 -0
- package/dist/vendor/core/strategy/attempt-brief.d.ts +22 -0
- package/dist/vendor/core/strategy/attempt-brief.js +89 -0
- package/dist/vendor/core/summarize/diff-summary.d.ts +35 -0
- package/dist/vendor/core/summarize/diff-summary.js +204 -0
- package/dist/vendor/core/surface-signals.d.ts +21 -0
- package/dist/vendor/core/surface-signals.js +139 -0
- package/dist/vendor/core/truth/truth-wall.d.ts +51 -0
- package/dist/vendor/core/truth/truth-wall.js +69 -0
- package/dist/vendor/core/truth-spine.d.ts +26 -0
- package/dist/vendor/core/truth-spine.js +62 -0
- package/dist/vendor/core/types.d.ts +115 -0
- package/dist/vendor/core/types.js +2 -0
- package/dist/vendor/core/verification/tiered-verify.d.ts +17 -0
- package/dist/vendor/core/verification/tiered-verify.js +29 -0
- package/dist/vendor/core/verifier-pyramid.d.ts +32 -0
- package/dist/vendor/core/verifier-pyramid.js +111 -0
- package/dist/vendor/core/workflow-artifacts.d.ts +99 -0
- package/dist/vendor/core/workflow-artifacts.js +668 -0
- package/dist/vendor/core/wrap/supervised-run.d.ts +96 -0
- package/dist/vendor/core/wrap/supervised-run.js +178 -0
- package/docs/assets/cli-animated.svg +139 -0
- package/docs/assets/cli-static.svg +34 -0
- package/docs/assets/github-hero-v2.svg +23 -0
- package/docs/assets/martin-raplph.png.jpg +0 -0
- package/docs/assets/martinloop-logo.png +0 -0
- package/docs/assets/nvidia-inception-program-light.png +0 -0
- package/docs/assets/nvidia-inception-program.png +0 -0
- package/docs/assets/phase3c-sidesidebyside-demo.html +228 -0
- package/docs/assets/side-by-side.svg +134 -0
- package/docs/oss/CLAUDE-CODE-WALKTHROUGH.md +142 -142
- package/docs/oss/EXAMPLES.md +134 -134
- package/docs/oss/OSS-BOUNDARY-REPORT.json +1 -1
- package/docs/oss/OSS-BOUNDARY-REPORT.md +1 -1
- package/docs/oss/QUICKSTART.md +170 -165
- package/docs/oss/RALPH-LOOP-SAFETY.md +113 -113
- package/docs/oss/README.md +96 -96
- package/docs/oss/RELEASE-SURFACE-REPORT.json +2 -1
- package/docs/oss/RELEASE-SURFACE-REPORT.md +2 -1
- package/package.json +130 -58
- package/docs/distribution/DIRECTORY-SUBMISSIONS.md +0 -89
- package/docs/distribution/INTEGRATION-OUTREACH.md +0 -61
- package/docs/distribution/UNDER-3-CHALLENGE.md +0 -65
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { signFileAttestation } from "../attestation/sign.js";
|
|
5
|
+
const AUTONOMOUS_PROMOTION_FILE = "autonomous-promotion.json";
|
|
6
|
+
export function classifyAutonomySurface(path) {
|
|
7
|
+
const normalized = normalizePath(path);
|
|
8
|
+
const protectedRules = [
|
|
9
|
+
"packages/core/src/leash.ts",
|
|
10
|
+
"packages/core/src/policy.ts",
|
|
11
|
+
"packages/core/src/grounding.ts",
|
|
12
|
+
"packages/cli/src/index.ts"
|
|
13
|
+
];
|
|
14
|
+
if (protectedRules.includes(normalized)) {
|
|
15
|
+
return {
|
|
16
|
+
path: normalized,
|
|
17
|
+
surface: "protected",
|
|
18
|
+
matchedRule: normalized
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const protectedPrefixes = [
|
|
22
|
+
"packages/core/src/leash/",
|
|
23
|
+
"packages/core/src/policy/",
|
|
24
|
+
"packages/core/src/grounding/",
|
|
25
|
+
"packages/core/src/security/",
|
|
26
|
+
"packages/core/src/attestation/",
|
|
27
|
+
"packages/core/src/safety/",
|
|
28
|
+
"packages/core/src/sentinel/",
|
|
29
|
+
"packages/contracts/src/",
|
|
30
|
+
"packages/mcp/src/",
|
|
31
|
+
"docs/release/",
|
|
32
|
+
"docs/security/",
|
|
33
|
+
"docs/handoffs/",
|
|
34
|
+
".planning/",
|
|
35
|
+
"scripts/"
|
|
36
|
+
];
|
|
37
|
+
const matchedProtectedPrefix = protectedPrefixes.find((rule) => normalized.startsWith(rule));
|
|
38
|
+
if (matchedProtectedPrefix) {
|
|
39
|
+
return {
|
|
40
|
+
path: normalized,
|
|
41
|
+
surface: "protected",
|
|
42
|
+
matchedRule: `${matchedProtectedPrefix}**`
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (normalized === "martin.config.example.yaml") {
|
|
46
|
+
return {
|
|
47
|
+
path: normalized,
|
|
48
|
+
surface: "trusted_config",
|
|
49
|
+
matchedRule: "martin.config.example.yaml"
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (normalized.startsWith("packages/core/src/memory/")) {
|
|
53
|
+
return {
|
|
54
|
+
path: normalized,
|
|
55
|
+
surface: "trusted_code",
|
|
56
|
+
matchedRule: "packages/core/src/memory/**"
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (normalized.startsWith("packages/trace-intelligence/src/")) {
|
|
60
|
+
return {
|
|
61
|
+
path: normalized,
|
|
62
|
+
surface: "trusted_code",
|
|
63
|
+
matchedRule: "packages/trace-intelligence/src/**"
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
path: normalized,
|
|
68
|
+
surface: "heuristic",
|
|
69
|
+
matchedRule: "default"
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export function classifyAutonomySurfaceSet(paths) {
|
|
73
|
+
const surfaces = paths.map(classifyAutonomySurface);
|
|
74
|
+
if (surfaces.length === 0) {
|
|
75
|
+
return { surfaceClass: "heuristic", surfaces };
|
|
76
|
+
}
|
|
77
|
+
if (surfaces.some((surface) => surface.surface === "protected")) {
|
|
78
|
+
return { surfaceClass: "protected", surfaces };
|
|
79
|
+
}
|
|
80
|
+
if (surfaces.some((surface) => surface.surface === "heuristic")) {
|
|
81
|
+
return { surfaceClass: "heuristic", surfaces };
|
|
82
|
+
}
|
|
83
|
+
if (surfaces.some((surface) => surface.surface === "trusted_code")) {
|
|
84
|
+
return { surfaceClass: "trusted_code", surfaces };
|
|
85
|
+
}
|
|
86
|
+
return { surfaceClass: "trusted_config", surfaces };
|
|
87
|
+
}
|
|
88
|
+
export function evaluateAutonomyTripwires(input) {
|
|
89
|
+
const surfaceSet = classifyAutonomySurfaceSet(input.changedFiles);
|
|
90
|
+
const surfaces = surfaceSet.surfaces;
|
|
91
|
+
const reasonCodes = [];
|
|
92
|
+
if (surfaces.some((surface) => surface.surface === "protected")) {
|
|
93
|
+
reasonCodes.push("protected_surface");
|
|
94
|
+
}
|
|
95
|
+
if (!input.diffVerified) {
|
|
96
|
+
reasonCodes.push("unverifiable_diff");
|
|
97
|
+
}
|
|
98
|
+
if (!input.rollbackProofPresent) {
|
|
99
|
+
reasonCodes.push("missing_rollback_proof");
|
|
100
|
+
}
|
|
101
|
+
if (!input.attestationMatches) {
|
|
102
|
+
reasonCodes.push("attestation_mismatch");
|
|
103
|
+
}
|
|
104
|
+
if (input.repeatedGroundingCount >= 2) {
|
|
105
|
+
reasonCodes.push("repeated_grounding");
|
|
106
|
+
}
|
|
107
|
+
if (!input.verifierImproved) {
|
|
108
|
+
reasonCodes.push("verifier_no_improvement");
|
|
109
|
+
}
|
|
110
|
+
if (input.budgetPressure === "critical") {
|
|
111
|
+
reasonCodes.push("budget_pressure_escalation");
|
|
112
|
+
}
|
|
113
|
+
const uniqueReasonCodes = unique(reasonCodes);
|
|
114
|
+
const events = uniqueReasonCodes.map(buildTripwireEvent);
|
|
115
|
+
const failed = uniqueReasonCodes.length > 0;
|
|
116
|
+
return {
|
|
117
|
+
status: failed ? "fail_closed" : "pass",
|
|
118
|
+
decision: failed ? "human_escalation" : "continue",
|
|
119
|
+
sideEffectsAllowed: !failed,
|
|
120
|
+
reasonCodes: uniqueReasonCodes,
|
|
121
|
+
surfaces,
|
|
122
|
+
surfaceClass: surfaceSet.surfaceClass,
|
|
123
|
+
events
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
export function evaluateAutonomousPromotion(input) {
|
|
127
|
+
const tripwire = evaluateAutonomyTripwires(input);
|
|
128
|
+
if (tripwire.status === "fail_closed") {
|
|
129
|
+
if (shouldRouteFailClosedToRollbackOnly(tripwire.reasonCodes, input.rollbackReady)) {
|
|
130
|
+
return {
|
|
131
|
+
verdict: "rollback_only",
|
|
132
|
+
sideEffectsAllowed: true,
|
|
133
|
+
reasonCodes: [...tripwire.reasonCodes],
|
|
134
|
+
tripwire
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
verdict: "human_escalation",
|
|
139
|
+
sideEffectsAllowed: false,
|
|
140
|
+
reasonCodes: [...tripwire.reasonCodes],
|
|
141
|
+
tripwire
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
if (tripwire.surfaceClass === "heuristic" && input.requestedMode === "promote") {
|
|
145
|
+
return {
|
|
146
|
+
verdict: "human_escalation",
|
|
147
|
+
sideEffectsAllowed: false,
|
|
148
|
+
reasonCodes: ["untrusted_surface"],
|
|
149
|
+
tripwire
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
if (input.requestedMode === "rollback") {
|
|
153
|
+
if (!input.rollbackReady) {
|
|
154
|
+
return {
|
|
155
|
+
verdict: "human_escalation",
|
|
156
|
+
sideEffectsAllowed: false,
|
|
157
|
+
reasonCodes: ["rollback_not_ready"],
|
|
158
|
+
tripwire
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
verdict: "rollback_only",
|
|
163
|
+
sideEffectsAllowed: true,
|
|
164
|
+
reasonCodes: ["rollback_requested"],
|
|
165
|
+
tripwire
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
if (input.requestedMode === "shadow") {
|
|
169
|
+
return {
|
|
170
|
+
verdict: "shadow_only",
|
|
171
|
+
sideEffectsAllowed: false,
|
|
172
|
+
reasonCodes: ["shadow_requested"],
|
|
173
|
+
tripwire
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
if (!input.rollbackReady) {
|
|
177
|
+
return {
|
|
178
|
+
verdict: "human_escalation",
|
|
179
|
+
sideEffectsAllowed: false,
|
|
180
|
+
reasonCodes: ["rollback_not_ready"],
|
|
181
|
+
tripwire
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
if (!input.shadowEvidencePasses || input.holdoutEvidencePasses !== true) {
|
|
185
|
+
return {
|
|
186
|
+
verdict: "shadow_only",
|
|
187
|
+
sideEffectsAllowed: false,
|
|
188
|
+
reasonCodes: ["shadow_evidence_pending"],
|
|
189
|
+
tripwire
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
if (normalizeConfidence(input.confidenceScore) < confidenceThresholdForSurface(tripwire.surfaceClass)) {
|
|
193
|
+
return {
|
|
194
|
+
verdict: "shadow_only",
|
|
195
|
+
sideEffectsAllowed: false,
|
|
196
|
+
reasonCodes: ["shadow_evidence_pending"],
|
|
197
|
+
tripwire
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
verdict: "promote",
|
|
202
|
+
sideEffectsAllowed: true,
|
|
203
|
+
reasonCodes: [],
|
|
204
|
+
tripwire
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
export function buildAutonomousPromotionArtifact(input) {
|
|
208
|
+
const decision = evaluateAutonomousPromotion(input);
|
|
209
|
+
const evidenceHash = sha256(canonicalStringify(input.evidence));
|
|
210
|
+
const confidenceScore = normalizeConfidence(input.confidenceScore);
|
|
211
|
+
const holdoutEvidencePasses = input.holdoutEvidencePasses ?? false;
|
|
212
|
+
const priorSuccessfulPromotions = input.priorSuccessfulPromotions ?? 0;
|
|
213
|
+
const unsignedArtifact = {
|
|
214
|
+
schemaVersion: "martin.autonomous-promotion.v1",
|
|
215
|
+
runId: input.runId,
|
|
216
|
+
attemptId: input.attemptId,
|
|
217
|
+
createdAt: input.createdAt,
|
|
218
|
+
requestedMode: input.requestedMode,
|
|
219
|
+
surfaceClass: decision.tripwire.surfaceClass,
|
|
220
|
+
confidenceScore,
|
|
221
|
+
shadowEvidencePasses: input.shadowEvidencePasses,
|
|
222
|
+
holdoutEvidencePasses,
|
|
223
|
+
rollbackReady: input.rollbackReady,
|
|
224
|
+
attestationVerified: input.attestationMatches,
|
|
225
|
+
priorSuccessfulPromotions,
|
|
226
|
+
diffHash: input.evidence.diffHash ?? null,
|
|
227
|
+
beforeArtifactHash: input.evidence.beforeArtifactHash ?? null,
|
|
228
|
+
afterArtifactHash: input.evidence.afterArtifactHash ?? null,
|
|
229
|
+
rollbackBoundaryRef: input.evidence.rollbackBoundaryRef ?? null,
|
|
230
|
+
improvementResultPath: input.evidence.improvementResultPath ?? null,
|
|
231
|
+
promotionPolicyVerdict: decision.verdict,
|
|
232
|
+
tripwireVerdict: decision.tripwire.status,
|
|
233
|
+
finalDisposition: decision.verdict,
|
|
234
|
+
verdict: decision.verdict,
|
|
235
|
+
sideEffectsAllowed: decision.sideEffectsAllowed,
|
|
236
|
+
reasonCodes: decision.reasonCodes,
|
|
237
|
+
changedFiles: input.changedFiles.map(normalizePath),
|
|
238
|
+
surfaces: decision.tripwire.surfaces,
|
|
239
|
+
evidence: input.evidence,
|
|
240
|
+
evidenceHash,
|
|
241
|
+
tripwire: decision.tripwire
|
|
242
|
+
};
|
|
243
|
+
const signature = {
|
|
244
|
+
algorithm: "sha256",
|
|
245
|
+
keyId: "deterministic-local-sha256",
|
|
246
|
+
signedAt: input.createdAt,
|
|
247
|
+
signature: `sha256:${sha256(canonicalStringify(unsignedArtifact))}`
|
|
248
|
+
};
|
|
249
|
+
return {
|
|
250
|
+
...unsignedArtifact,
|
|
251
|
+
signature
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
export async function persistAutonomousPromotionArtifact(input) {
|
|
255
|
+
await mkdir(input.root, { recursive: true });
|
|
256
|
+
const path = join(input.root, AUTONOMOUS_PROMOTION_FILE);
|
|
257
|
+
await writeFile(path, `${canonicalPrettyStringify(input.artifact)}\n`, "utf8");
|
|
258
|
+
const attestationOptions = {
|
|
259
|
+
now: input.artifact.createdAt,
|
|
260
|
+
...(input.martinHome ? { martinHome: input.martinHome } : {})
|
|
261
|
+
};
|
|
262
|
+
const attestation = await signFileAttestation(path, attestationOptions);
|
|
263
|
+
return {
|
|
264
|
+
fileName: AUTONOMOUS_PROMOTION_FILE,
|
|
265
|
+
path,
|
|
266
|
+
artifact: input.artifact,
|
|
267
|
+
attestation
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
function normalizePath(value) {
|
|
271
|
+
return value.replace(/\\/g, "/").replace(/^\.\//u, "");
|
|
272
|
+
}
|
|
273
|
+
function sha256(value) {
|
|
274
|
+
return createHash("sha256").update(value, "utf8").digest("hex");
|
|
275
|
+
}
|
|
276
|
+
function unique(values) {
|
|
277
|
+
return [...new Set(values)];
|
|
278
|
+
}
|
|
279
|
+
function normalizeConfidence(value) {
|
|
280
|
+
if (typeof value !== "number" || Number.isNaN(value)) {
|
|
281
|
+
return 1;
|
|
282
|
+
}
|
|
283
|
+
return Math.max(0, Math.min(1, value));
|
|
284
|
+
}
|
|
285
|
+
function confidenceThresholdForSurface(surface) {
|
|
286
|
+
switch (surface) {
|
|
287
|
+
case "trusted_config":
|
|
288
|
+
return 0.8;
|
|
289
|
+
case "trusted_code":
|
|
290
|
+
return 0.9;
|
|
291
|
+
case "heuristic":
|
|
292
|
+
case "protected":
|
|
293
|
+
return 1;
|
|
294
|
+
default:
|
|
295
|
+
return 1;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
function buildTripwireEvent(reasonCode) {
|
|
299
|
+
const triggerReason = {
|
|
300
|
+
protected_surface: "candidate touched a permanently human-controlled surface",
|
|
301
|
+
untrusted_surface: "candidate requested autonomous promotion outside trusted surfaces",
|
|
302
|
+
unverifiable_diff: "canonical diff hash could not be verified",
|
|
303
|
+
missing_rollback_proof: "rollback proof or rollback boundary linkage is missing",
|
|
304
|
+
attestation_mismatch: "diff or artifact attestation did not match expected evidence",
|
|
305
|
+
repeated_grounding: "grounding failures repeated across the autonomy attempt",
|
|
306
|
+
verifier_no_improvement: "verifier reported no measurable improvement",
|
|
307
|
+
budget_pressure_escalation: "budget pressure reached the fail-closed escalation threshold"
|
|
308
|
+
};
|
|
309
|
+
return {
|
|
310
|
+
severity: "critical",
|
|
311
|
+
reasonCode,
|
|
312
|
+
triggerReason: triggerReason[reasonCode],
|
|
313
|
+
actionTaken: "block_and_escalate"
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
function shouldRouteFailClosedToRollbackOnly(reasonCodes, rollbackReady) {
|
|
317
|
+
if (!rollbackReady) {
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
const escalationOnly = new Set([
|
|
321
|
+
"protected_surface",
|
|
322
|
+
"untrusted_surface",
|
|
323
|
+
"missing_rollback_proof",
|
|
324
|
+
"attestation_mismatch",
|
|
325
|
+
"budget_pressure_escalation"
|
|
326
|
+
]);
|
|
327
|
+
return reasonCodes.length > 0 && reasonCodes.every((reason) => !escalationOnly.has(reason));
|
|
328
|
+
}
|
|
329
|
+
function canonicalStringify(value) {
|
|
330
|
+
return JSON.stringify(sortCanonical(value));
|
|
331
|
+
}
|
|
332
|
+
function canonicalPrettyStringify(value) {
|
|
333
|
+
return JSON.stringify(sortCanonical(value), null, 2);
|
|
334
|
+
}
|
|
335
|
+
function sortCanonical(value) {
|
|
336
|
+
if (Array.isArray(value)) {
|
|
337
|
+
return value.map(sortCanonical);
|
|
338
|
+
}
|
|
339
|
+
if (!value || typeof value !== "object") {
|
|
340
|
+
return value;
|
|
341
|
+
}
|
|
342
|
+
return Object.fromEntries(Object.entries(value)
|
|
343
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
344
|
+
.map(([key, nested]) => [key, sortCanonical(nested)]));
|
|
345
|
+
}
|
|
346
|
+
//# sourceMappingURL=autonomous-promotion.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ApprovalPolicy, ExecutionProfile } from "../../contracts/index.js";
|
|
2
|
+
export interface AutonomyEnvelopeV2Input {
|
|
3
|
+
taskId: string;
|
|
4
|
+
taskFamily: string;
|
|
5
|
+
requestedSurfaces: string[];
|
|
6
|
+
allowedSurfaces: string[];
|
|
7
|
+
verificationPlan: string[];
|
|
8
|
+
commands?: string[];
|
|
9
|
+
changedFiles?: string[];
|
|
10
|
+
allowedPaths?: string[];
|
|
11
|
+
deniedPaths?: string[];
|
|
12
|
+
executionProfile?: ExecutionProfile;
|
|
13
|
+
allowedNetworkDomains?: string[];
|
|
14
|
+
approvalPolicy?: ApprovalPolicy;
|
|
15
|
+
requiresHumanApproval?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface AutonomyEnvelopeV2Decision {
|
|
18
|
+
taskId: string;
|
|
19
|
+
taskFamily: string;
|
|
20
|
+
decision: "admit" | "escalate";
|
|
21
|
+
envelopeStatus: "in_envelope" | "escalation_required" | "out_of_envelope";
|
|
22
|
+
sideEffectsAllowed: boolean;
|
|
23
|
+
zeroSideEffectsBeforeEscalation: boolean;
|
|
24
|
+
reasons: string[];
|
|
25
|
+
blockedSurfaces: Array<"command" | "filesystem" | "dependency">;
|
|
26
|
+
allowedClaimWording: string;
|
|
27
|
+
nonClaims: string[];
|
|
28
|
+
}
|
|
29
|
+
export declare function evaluateAutonomyEnvelopeV2(input: AutonomyEnvelopeV2Input): AutonomyEnvelopeV2Decision;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { evaluateChangeApprovalLeash, evaluateFilesystemLeash, evaluateVerificationLeash } from "../leash.js";
|
|
2
|
+
export function evaluateAutonomyEnvelopeV2(input) {
|
|
3
|
+
const reasons = [];
|
|
4
|
+
const allowedSurfaceSet = new Set(input.allowedSurfaces);
|
|
5
|
+
const blockedSurfaces = [];
|
|
6
|
+
const verificationCommands = [...input.verificationPlan, ...(input.commands ?? [])];
|
|
7
|
+
if (input.requestedSurfaces.some((surface) => !allowedSurfaceSet.has(surface))) {
|
|
8
|
+
reasons.push("requested surface outside autonomy envelope");
|
|
9
|
+
}
|
|
10
|
+
if (input.requiresHumanApproval) {
|
|
11
|
+
reasons.push("human approval required");
|
|
12
|
+
}
|
|
13
|
+
const commandDecision = evaluateVerificationLeash({
|
|
14
|
+
verificationPlan: verificationCommands,
|
|
15
|
+
...(input.executionProfile ? { executionProfile: input.executionProfile } : {}),
|
|
16
|
+
...(input.allowedNetworkDomains ? { allowedNetworkDomains: input.allowedNetworkDomains } : {})
|
|
17
|
+
});
|
|
18
|
+
if (commandDecision.blocked) {
|
|
19
|
+
reasons.push("verification command leash blocked one or more commands");
|
|
20
|
+
blockedSurfaces.push("command");
|
|
21
|
+
}
|
|
22
|
+
const filesystemDecision = evaluateFilesystemLeash({
|
|
23
|
+
changedFiles: input.changedFiles ?? [],
|
|
24
|
+
...(input.allowedPaths ? { allowedPaths: input.allowedPaths } : {}),
|
|
25
|
+
...(input.deniedPaths ? { deniedPaths: input.deniedPaths } : {})
|
|
26
|
+
});
|
|
27
|
+
if (filesystemDecision.blocked) {
|
|
28
|
+
reasons.push("filesystem leash blocked one or more changed files");
|
|
29
|
+
blockedSurfaces.push("filesystem");
|
|
30
|
+
}
|
|
31
|
+
const dependencyDecision = evaluateChangeApprovalLeash({
|
|
32
|
+
changedFiles: input.changedFiles ?? [],
|
|
33
|
+
...(input.executionProfile ? { executionProfile: input.executionProfile } : {}),
|
|
34
|
+
approvalPolicy: input.approvalPolicy
|
|
35
|
+
});
|
|
36
|
+
if (dependencyDecision.blocked) {
|
|
37
|
+
reasons.push("dependency or config approval is required");
|
|
38
|
+
blockedSurfaces.push("dependency");
|
|
39
|
+
}
|
|
40
|
+
const uniqueBlockedSurfaces = [...new Set(blockedSurfaces)];
|
|
41
|
+
const envelopeStatus = reasons.length === 0
|
|
42
|
+
? "in_envelope"
|
|
43
|
+
: input.requestedSurfaces.some((surface) => !allowedSurfaceSet.has(surface))
|
|
44
|
+
? "out_of_envelope"
|
|
45
|
+
: "escalation_required";
|
|
46
|
+
const decision = reasons.length === 0 ? "admit" : "escalate";
|
|
47
|
+
return {
|
|
48
|
+
taskId: input.taskId,
|
|
49
|
+
taskFamily: input.taskFamily,
|
|
50
|
+
decision,
|
|
51
|
+
envelopeStatus,
|
|
52
|
+
sideEffectsAllowed: decision === "admit",
|
|
53
|
+
zeroSideEffectsBeforeEscalation: decision === "escalate",
|
|
54
|
+
reasons,
|
|
55
|
+
blockedSurfaces: uniqueBlockedSurfaces,
|
|
56
|
+
allowedClaimWording: "Autonomous inside operating envelope v2 with fail-closed escalation before file, network, or dependency side effects outside the envelope.",
|
|
57
|
+
nonClaims: ["unqualified autonomous", "no-boundary autonomy", "human-free operation on every task"]
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=envelope-v2.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface AutonomyEnvelopeInput {
|
|
2
|
+
taskId: string;
|
|
3
|
+
requestedSurfaces: string[];
|
|
4
|
+
allowedSurfaces: string[];
|
|
5
|
+
verificationPlan: string[];
|
|
6
|
+
commands: string[];
|
|
7
|
+
requiresHumanApproval: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface AutonomyEnvelopeDecision {
|
|
10
|
+
taskId: string;
|
|
11
|
+
decision: "admit" | "escalate";
|
|
12
|
+
sideEffectsAllowed: boolean;
|
|
13
|
+
reasons: string[];
|
|
14
|
+
allowedClaimWording: string;
|
|
15
|
+
nonClaims: string[];
|
|
16
|
+
}
|
|
17
|
+
export declare function evaluateAutonomyEnvelope(input: AutonomyEnvelopeInput): AutonomyEnvelopeDecision;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { evaluateVerificationLeash } from "../leash.js";
|
|
2
|
+
export function evaluateAutonomyEnvelope(input) {
|
|
3
|
+
const reasons = [];
|
|
4
|
+
const allowedSurfaceSet = new Set(input.allowedSurfaces);
|
|
5
|
+
if (input.requestedSurfaces.some((surface) => !allowedSurfaceSet.has(surface))) {
|
|
6
|
+
reasons.push("requested surface outside autonomy envelope");
|
|
7
|
+
}
|
|
8
|
+
if (input.requiresHumanApproval) {
|
|
9
|
+
reasons.push("human approval required");
|
|
10
|
+
}
|
|
11
|
+
const leash = evaluateVerificationLeash({
|
|
12
|
+
verificationPlan: [...input.verificationPlan, ...input.commands]
|
|
13
|
+
});
|
|
14
|
+
if (!leash.allowed) {
|
|
15
|
+
reasons.push("verification command leash blocked one or more commands");
|
|
16
|
+
}
|
|
17
|
+
const decision = reasons.length === 0 ? "admit" : "escalate";
|
|
18
|
+
return {
|
|
19
|
+
taskId: input.taskId,
|
|
20
|
+
decision,
|
|
21
|
+
sideEffectsAllowed: decision === "admit",
|
|
22
|
+
reasons,
|
|
23
|
+
allowedClaimWording: "Autonomous inside the declared operating envelope only, with escalation before side effects for out-of-envelope work.",
|
|
24
|
+
nonClaims: ["unqualified autonomous", "no-boundary autonomy"]
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=envelope.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type AutonomyEnvelopeV2Decision, type AutonomyEnvelopeV2Input } from "./envelope-v2.js";
|
|
2
|
+
export interface AutonomyEscalationLedgerEntry extends AutonomyEnvelopeV2Decision {
|
|
3
|
+
}
|
|
4
|
+
export interface AutonomyEscalationLedger {
|
|
5
|
+
ledgerId: "autonomy-envelope-v2";
|
|
6
|
+
generatedAt: string;
|
|
7
|
+
entries: AutonomyEscalationLedgerEntry[];
|
|
8
|
+
summary: {
|
|
9
|
+
totalTasks: number;
|
|
10
|
+
admittedTasks: number;
|
|
11
|
+
escalatedTasks: number;
|
|
12
|
+
zeroSideEffectEscalations: number;
|
|
13
|
+
};
|
|
14
|
+
allowedClaimWording: string;
|
|
15
|
+
nonClaims: string[];
|
|
16
|
+
}
|
|
17
|
+
export declare function buildAutonomyEscalationLedger(input: {
|
|
18
|
+
generatedAt?: string;
|
|
19
|
+
tasks: AutonomyEnvelopeV2Input[];
|
|
20
|
+
}): AutonomyEscalationLedger;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { evaluateAutonomyEnvelopeV2 } from "./envelope-v2.js";
|
|
2
|
+
export function buildAutonomyEscalationLedger(input) {
|
|
3
|
+
const entries = input.tasks.map((task) => evaluateAutonomyEnvelopeV2(task));
|
|
4
|
+
return {
|
|
5
|
+
ledgerId: "autonomy-envelope-v2",
|
|
6
|
+
generatedAt: input.generatedAt ?? new Date().toISOString(),
|
|
7
|
+
entries,
|
|
8
|
+
summary: {
|
|
9
|
+
totalTasks: entries.length,
|
|
10
|
+
admittedTasks: entries.filter((entry) => entry.decision === "admit").length,
|
|
11
|
+
escalatedTasks: entries.filter((entry) => entry.decision === "escalate").length,
|
|
12
|
+
zeroSideEffectEscalations: entries.filter((entry) => entry.zeroSideEffectsBeforeEscalation).length
|
|
13
|
+
},
|
|
14
|
+
allowedClaimWording: "Autonomous inside operating envelope v2 with fail-closed escalation before side effects outside the envelope.",
|
|
15
|
+
nonClaims: ["unqualified autonomous", "human-free operation on every task"]
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=escalation-ledger.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface AutonomyResumeInput {
|
|
2
|
+
taskId: string;
|
|
3
|
+
checkpointState: "clean" | "workspace_modified" | "checkpoint_missing";
|
|
4
|
+
outOfEnvelope: boolean;
|
|
5
|
+
sideEffectsDetected: boolean;
|
|
6
|
+
force: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface AutonomyResumeDecision {
|
|
9
|
+
taskId: string;
|
|
10
|
+
decision: "resume" | "resume_with_force" | "escalate";
|
|
11
|
+
reasons: string[];
|
|
12
|
+
allowedClaimWording: string;
|
|
13
|
+
nonClaims: string[];
|
|
14
|
+
}
|
|
15
|
+
export declare function evaluateAutonomyResume(input: AutonomyResumeInput): AutonomyResumeDecision;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function evaluateAutonomyResume(input) {
|
|
2
|
+
const reasons = [];
|
|
3
|
+
if (input.checkpointState === "workspace_modified" && !input.force) {
|
|
4
|
+
reasons.push("workspace modified since checkpoint");
|
|
5
|
+
}
|
|
6
|
+
if (input.checkpointState === "checkpoint_missing") {
|
|
7
|
+
reasons.push("checkpoint missing");
|
|
8
|
+
}
|
|
9
|
+
if (input.outOfEnvelope) {
|
|
10
|
+
reasons.push("task moved outside the autonomy envelope");
|
|
11
|
+
}
|
|
12
|
+
if (input.sideEffectsDetected) {
|
|
13
|
+
reasons.push("side effects detected before safe resume");
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
taskId: input.taskId,
|
|
17
|
+
decision: reasons.length === 0 ? (input.force && input.checkpointState === "workspace_modified" ? "resume_with_force" : "resume") : "escalate",
|
|
18
|
+
reasons,
|
|
19
|
+
allowedClaimWording: "Pause and resume are bounded by checkpoint integrity and envelope checks before a run continues autonomously.",
|
|
20
|
+
nonClaims: ["unbounded autonomous recovery", "resume without integrity checks"]
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=resume.js.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export type CircuitState = "CLOSED" | "OPEN" | "HALF_OPEN";
|
|
2
|
+
export interface CircuitBreakerConfig {
|
|
3
|
+
/** Number of consecutive failures before opening the circuit. Default: 3 */
|
|
4
|
+
failureThreshold: number;
|
|
5
|
+
/** Time in OPEN state before transitioning to HALF_OPEN (ms). Default: 60000 */
|
|
6
|
+
cooldownMs: number;
|
|
7
|
+
/** Sliding window for failure counting (ms). Default: 300000 (5 minutes) */
|
|
8
|
+
windowMs: number;
|
|
9
|
+
}
|
|
10
|
+
export interface CircuitBreakerState {
|
|
11
|
+
state: CircuitState;
|
|
12
|
+
failureCount: number;
|
|
13
|
+
lastFailureTime?: string;
|
|
14
|
+
openedAt?: string;
|
|
15
|
+
adapterId: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class CircuitBreaker {
|
|
18
|
+
private readonly config;
|
|
19
|
+
private readonly adapterId;
|
|
20
|
+
private state;
|
|
21
|
+
private failureCount;
|
|
22
|
+
private lastFailureTime?;
|
|
23
|
+
private openedAt?;
|
|
24
|
+
constructor(adapterId: string, config?: Partial<CircuitBreakerConfig>);
|
|
25
|
+
/**
|
|
26
|
+
* Returns the current circuit breaker state snapshot.
|
|
27
|
+
*/
|
|
28
|
+
getState(): CircuitBreakerState;
|
|
29
|
+
/**
|
|
30
|
+
* Returns true if a call should be allowed through.
|
|
31
|
+
* - CLOSED: always allowed
|
|
32
|
+
* - HALF_OPEN: one probe call allowed
|
|
33
|
+
* - OPEN: blocked unless cooldown has elapsed (transitions to HALF_OPEN)
|
|
34
|
+
*/
|
|
35
|
+
canCall(now?: Date): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Record a successful adapter call.
|
|
38
|
+
* HALF_OPEN → CLOSED on success.
|
|
39
|
+
*/
|
|
40
|
+
recordSuccess(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Record a failed adapter call.
|
|
43
|
+
* CLOSED: increments failure count; if threshold reached, opens circuit.
|
|
44
|
+
* HALF_OPEN: re-opens circuit (probe failed).
|
|
45
|
+
*/
|
|
46
|
+
recordFailure(now?: Date): void;
|
|
47
|
+
/**
|
|
48
|
+
* Manually reset the circuit breaker to CLOSED state.
|
|
49
|
+
*/
|
|
50
|
+
reset(): void;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Serializes a CircuitBreaker instance to a JSON string.
|
|
54
|
+
*/
|
|
55
|
+
export declare function serializeState(breaker: CircuitBreaker): string;
|
|
56
|
+
/**
|
|
57
|
+
* Deserializes a JSON string back into a CircuitBreaker instance.
|
|
58
|
+
* Restores internal state including failure count, timestamps, and state.
|
|
59
|
+
*/
|
|
60
|
+
export declare function deserializeState(json: string, configOverride?: Partial<CircuitBreakerConfig>): CircuitBreaker;
|