zob-harness 0.9.0 → 0.9.2
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/.pi/capabilities/zob-public-runtime-capabilities.json +16 -17
- package/.pi/extensions/zob-harness/index.ts +1 -1
- package/.pi/extensions/zob-harness/src/domains/autonomy/autonomous-runtime/dry-run.ts +1107 -0
- package/.pi/extensions/zob-harness/src/domains/autonomy/autonomous-runtime/report-writers.ts +325 -0
- package/.pi/extensions/zob-harness/src/domains/autonomy/autonomous-runtime/smoke-run.ts +1286 -0
- package/.pi/extensions/zob-harness/src/domains/autonomy/autonomous-runtime/types.ts +30 -0
- package/.pi/extensions/zob-harness/src/domains/autonomy/autonomous-runtime/validation.ts +184 -0
- package/.pi/extensions/zob-harness/src/domains/autonomy/autonomous-runtime.ts +4 -2912
- package/.pi/extensions/zob-harness/src/domains/compute/compute-profile.ts +2 -1
- package/.pi/extensions/zob-harness/src/domains/coms/coms-v2/registry.ts +24 -3
- package/.pi/extensions/zob-harness/src/domains/coms/coms-v2/types.ts +1 -0
- package/.pi/extensions/zob-harness/src/domains/coms/coms-v2/zpeer.ts +5 -3
- package/.pi/extensions/zob-harness/src/domains/delegation/child-runner.ts +28 -3
- package/.pi/extensions/zob-harness/src/domains/goal/goal-todos/constants.ts +19 -0
- package/.pi/extensions/zob-harness/src/domains/goal/goal-todos/formatting.ts +148 -0
- package/.pi/extensions/zob-harness/src/domains/goal/goal-todos/normalize.ts +476 -0
- package/.pi/extensions/zob-harness/src/domains/goal/goal-todos/operations.ts +393 -0
- package/.pi/extensions/zob-harness/src/domains/goal/goal-todos/parsing.ts +277 -0
- package/.pi/extensions/zob-harness/src/domains/goal/goal-todos/reducer.ts +110 -0
- package/.pi/extensions/zob-harness/src/domains/goal/goal-todos.ts +6 -1429
- package/.pi/extensions/zob-harness/src/domains/governance/governed-requests.ts +3 -1
- package/.pi/extensions/zob-harness/src/domains/governance/merge-queue.ts +3 -1
- package/.pi/extensions/zob-harness/src/domains/governance/sandbox/helpers.ts +124 -0
- package/.pi/extensions/zob-harness/src/domains/governance/sandbox/runners.ts +444 -0
- package/.pi/extensions/zob-harness/src/domains/governance/sandbox/simulation.ts +569 -0
- package/.pi/extensions/zob-harness/src/domains/governance/sandbox/types.ts +127 -0
- package/.pi/extensions/zob-harness/src/domains/governance/sandbox/validation.ts +273 -0
- package/.pi/extensions/zob-harness/src/domains/governance/sandbox.ts +4 -1508
- package/.pi/extensions/zob-harness/src/domains/governance/worker-pool.ts +3 -1
- package/.pi/extensions/zob-harness/src/domains/governance/workspace-claims.ts +3 -1
- package/.pi/extensions/zob-harness/src/domains/orchestration/room.ts +8 -2
- package/.pi/extensions/zob-harness/src/domains/promotion/coms.ts +8 -1
- package/.pi/extensions/zob-harness/src/runtime/commands/autonomy.ts +188 -0
- package/.pi/extensions/zob-harness/src/runtime/commands/compute.ts +165 -0
- package/.pi/extensions/zob-harness/src/runtime/commands/daemon.ts +191 -0
- package/.pi/extensions/zob-harness/src/runtime/commands/delegates.ts +47 -0
- package/.pi/extensions/zob-harness/src/runtime/commands/goal.ts +70 -0
- package/.pi/extensions/zob-harness/src/runtime/commands/intent.ts +383 -0
- package/.pi/extensions/zob-harness/src/runtime/commands/misc.ts +229 -0
- package/.pi/extensions/zob-harness/src/runtime/commands/project-dna.ts +130 -0
- package/.pi/extensions/zob-harness/src/runtime/commands/types.ts +3 -0
- package/.pi/extensions/zob-harness/src/runtime/commands/zcommit.ts +145 -0
- package/.pi/extensions/zob-harness/src/runtime/commands/zlive.ts +1606 -0
- package/.pi/extensions/zob-harness/src/runtime/commands/zmode.ts +42 -0
- package/.pi/extensions/zob-harness/src/runtime/commands.ts +26 -3109
- package/.pi/extensions/zob-harness/src/runtime/events.ts +67 -33
- package/.pi/extensions/zob-harness/src/runtime/goal-runtime/commands.ts +194 -0
- package/.pi/extensions/zob-harness/src/runtime/goal-runtime/events.ts +81 -0
- package/.pi/extensions/zob-harness/src/runtime/goal-runtime/state.ts +662 -0
- package/.pi/extensions/zob-harness/src/runtime/goal-runtime/tools.ts +1005 -0
- package/.pi/extensions/zob-harness/src/runtime/goal-runtime.ts +5 -1949
- package/.pi/extensions/zob-harness/src/runtime/tools-delegation/helpers.ts +786 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-delegation/register.ts +1120 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-delegation/types.ts +77 -0
- package/.pi/extensions/zob-harness/src/runtime/tools-delegation.ts +1 -1904
- package/.pi/extensions/zob-harness/src/runtime/zob-intro.ts +46 -15
- package/.pi/factories/project-dna/batch-manifest.json +1 -1
- package/.pi/factories/project-dna/pilot-manifest.json +1 -1
- package/.pi/factories/project-dna/smoke-manifest.json +1 -1
- package/README.md +29 -8
- package/package.json +14 -5
- package/scripts/git-ops/commit-policy-smoke.mjs +33 -6
- package/scripts/goal-todo/child-goal-ref-smoke.mjs +30 -3
- package/scripts/goal-todo/handoff-static-smoke.mjs +31 -3
- package/scripts/harness-intake/lib/cli-io.mjs +89 -0
- package/scripts/harness-intake/lib/constants.mjs +59 -0
- package/scripts/harness-intake/lib/infer-spec.mjs +127 -0
- package/scripts/harness-intake/lib/profiles.mjs +458 -0
- package/scripts/harness-intake/lib/run-init.mjs +307 -0
- package/scripts/harness-intake/lib/scan.mjs +266 -0
- package/scripts/harness-intake/lib/tmux.mjs +92 -0
- package/scripts/harness-intake/lib/validate.mjs +152 -0
- package/scripts/harness-intake/lib.mjs +8 -1521
- package/scripts/harness-switch/static-smoke.mjs +1 -1
- package/scripts/model-catalog/validate-economy.mjs +3 -1
- package/scripts/model-catalog/validate.mjs +3 -1
- package/scripts/project-dna/scan/scan.mjs +5 -2
- package/scripts/project-dna/scan/validate-scan-artifacts.mjs +3 -1
- package/scripts/project-dna/validation/validate-ontology.mjs +3 -1
- package/scripts/project-dna/validation/validate-scaffold.mjs +2 -2
- package/scripts/zagent-static-smoke.mjs +30 -2
- package/scripts/zpeer-local-e2e-smoke.mjs +18 -0
- package/scripts/zpeer-static-smoke.mjs +40 -5
- package/scripts/zteam-hot-add/smoke.mjs +30 -2
|
@@ -0,0 +1,1107 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { buildCapabilityIndex, buildReuseScoutReport } from "../../delegation/capabilities.js";
|
|
4
|
+
import { selectFactoryForDemands } from "../../factory/factory-selector.js";
|
|
5
|
+
import { evaluateStrictBudgetDispatchGate } from "../../governance/budget-policy.js";
|
|
6
|
+
import { evaluateBudgetPreflightDryRun } from "../../telemetry/chronicle.js";
|
|
7
|
+
import { buildBrainLookupResult, buildContextPack, buildDefaultContextScope, validateContextPack, validateContextScope } from "../../context/context-gbrain.js";
|
|
8
|
+
import { evaluateModelRoutingDispatchGate, evaluateModelRoutingDryRun } from "../../models/model-routing.js";
|
|
9
|
+
import { sha256 } from "../../../core/utils/hashing.js";
|
|
10
|
+
import { safeFileStem } from "../../../core/utils/paths.js";
|
|
11
|
+
import { isRecord } from "../../../core/utils/records.js";
|
|
12
|
+
import type { AutonomousApplyPolicy, AutonomousBudgetProfile, AutonomousLevel, AutonomousRisk, AutonomousRuntimeDryRunInput } from "./types.js";
|
|
13
|
+
|
|
14
|
+
export const FORBIDDEN_BODY_KEYS = new Set(["task", "prompt", "output", "body", "content", "patch", "diff", "raw", "messages", "conversationHistory"]);
|
|
15
|
+
export const AMBIGUOUS_PATTERNS = [/\bstuff\b/i, /\bsomething\b/i, /\bwhatever\b/i, /\bfix it\b/i, /\bmake it better\b/i, /\betc\.?\b/i];
|
|
16
|
+
export const SECRET_PATTERNS = [/\.env\b/i, /api[_-]?key/i, /secret/i, /password/i, /token/i, /private[_-]?key/i, /ssh[_-]?key/i];
|
|
17
|
+
export const DEFAULT_AUTONOMOUS_FORBIDDEN_PATHS = [".env", ".env.*", "secrets", "raw-conversation-history", "node_modules", "dist", "build"];
|
|
18
|
+
export const UNSAFE_AUTONOMOUS_ALLOWED_SEGMENTS = new Set(["node_modules", "dist", "build", "secrets", "raw-conversation-history"]);
|
|
19
|
+
export const AUTONOMOUS_CURRENT_SOURCE_FINGERPRINT_FILES = [
|
|
20
|
+
"package.json",
|
|
21
|
+
"tsconfig.json",
|
|
22
|
+
"scripts/harness-smoke.mjs",
|
|
23
|
+
"docs/AUTONOMY_FACTORY_AGENT_DETAILED_PLAN.md",
|
|
24
|
+
".pi/budget-policy.json",
|
|
25
|
+
".pi/model-routing.json",
|
|
26
|
+
".pi/daemon-policy.json",
|
|
27
|
+
".pi/teams/zob-core.json",
|
|
28
|
+
".pi/extensions/zob-harness/index.ts",
|
|
29
|
+
".pi/extensions/zob-harness/src/domains/autonomy/autonomous-runtime.ts",
|
|
30
|
+
".pi/extensions/zob-harness/src/domains/autonomy/autonomy-readiness.ts",
|
|
31
|
+
".pi/extensions/zob-harness/src/runtime/tools-autonomous.ts",
|
|
32
|
+
".pi/extensions/zob-harness/src/runtime/schemas.ts",
|
|
33
|
+
".pi/extensions/zob-harness/src/domains/factory/run.ts",
|
|
34
|
+
".pi/extensions/zob-harness/src/domains/models/model-routing.ts",
|
|
35
|
+
".pi/extensions/zob-harness/src/domains/governance/budget-policy.ts",
|
|
36
|
+
".pi/extensions/zob-harness/src/domains/autonomy/daemon-policy.ts",
|
|
37
|
+
".pi/extensions/zob-harness/src/domains/coms/mission-control.ts",
|
|
38
|
+
".pi/extensions/zob-harness/src/domains/governance/sandbox.ts",
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
export function hasForbiddenBodyKeys(value: unknown): boolean {
|
|
42
|
+
if (!value || typeof value !== "object") return false;
|
|
43
|
+
if (Array.isArray(value)) return value.some(hasForbiddenBodyKeys);
|
|
44
|
+
return Object.entries(value as Record<string, unknown>).some(([key, child]) => FORBIDDEN_BODY_KEYS.has(key) || hasForbiddenBodyKeys(child));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function stableStrings(values: string[] | undefined): string[] {
|
|
48
|
+
return [...new Set((values ?? []).filter((value) => typeof value === "string" && value.trim().length > 0).map((value) => value.trim()))].sort();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function normalizeAutonomousSpecPath(value: string): string {
|
|
52
|
+
return value.trim().replace(/\\+/g, "/").replace(/\/+/g, "/").replace(/^\.\//, "").replace(/\/+$/, "");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function isBroadAutonomousAllowedPath(value: string): boolean {
|
|
56
|
+
const normalized = normalizeAutonomousSpecPath(value);
|
|
57
|
+
return normalized === "" || normalized === "." || normalized === "/" || normalized === "*" || normalized === "**" || normalized === "~" || normalized === "~/";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function forbiddenPatternBase(value: string): string {
|
|
61
|
+
return normalizeAutonomousSpecPath(value)
|
|
62
|
+
.replace(/\/\*\*$/, "")
|
|
63
|
+
.replace(/\/\*$/, "")
|
|
64
|
+
.replace(/\.\*$/, "");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function pathConflict(left: string, right: string): boolean {
|
|
68
|
+
const a = forbiddenPatternBase(left).toLowerCase();
|
|
69
|
+
const b = forbiddenPatternBase(right).toLowerCase();
|
|
70
|
+
if (!a || !b) return false;
|
|
71
|
+
return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function unsafeAllowedPathReason(value: string, forbiddenPaths: string[]): string | undefined {
|
|
75
|
+
const normalized = normalizeAutonomousSpecPath(value);
|
|
76
|
+
const lower = normalized.toLowerCase();
|
|
77
|
+
if (value.includes("\0")) return "allowed_path_contains_nul_byte";
|
|
78
|
+
if (isBroadAutonomousAllowedPath(value)) return "allowed_path_too_broad";
|
|
79
|
+
if (lower.startsWith("/") || lower.startsWith("~/") || /^[a-z]:\//i.test(lower)) return "allowed_path_must_be_repo_relative";
|
|
80
|
+
if (lower.split("/").includes("..")) return "allowed_path_must_not_traverse_parent";
|
|
81
|
+
const segments = lower.split("/").filter(Boolean);
|
|
82
|
+
if (segments.some((segment) => segment === ".env" || segment.startsWith(".env."))) return "allowed_path_references_secret_path";
|
|
83
|
+
if (segments.some((segment) => UNSAFE_AUTONOMOUS_ALLOWED_SEGMENTS.has(segment))) return "allowed_path_references_forbidden_segment";
|
|
84
|
+
if (forbiddenPaths.some((forbidden) => pathConflict(normalized, forbidden))) return "allowed_path_conflicts_with_forbidden_path";
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function validateAutonomousSpecPathGate(allowedPaths: string[], forbiddenPaths: string[]): string[] {
|
|
89
|
+
if (allowedPaths.length === 0) return ["allowed_paths_required_before_execution"];
|
|
90
|
+
return allowedPaths.flatMap((allowedPath) => {
|
|
91
|
+
const reason = unsafeAllowedPathReason(allowedPath, forbiddenPaths);
|
|
92
|
+
return reason ? [reason] : [];
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function hashes(values: string[]): string[] {
|
|
97
|
+
return values.map((value) => sha256(value)).sort();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function defaultAutonomousAllowedActions(applyPolicy: AutonomousApplyPolicy): string[] {
|
|
101
|
+
const base = ["read_repo", "context_lookup", "select_factory", "run_factory_smoke", "run_factory_pilot", "run_factory_batch", "post_run_validation", "post_run_oracle"];
|
|
102
|
+
return applyPolicy === "auto_apply_in_scope"
|
|
103
|
+
? [...base, "sandbox_edit", "apply_in_scope", "post_apply_validation", "post_apply_oracle"]
|
|
104
|
+
: base;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function inferAutonomousLevel(applyPolicy: AutonomousApplyPolicy): AutonomousLevel {
|
|
108
|
+
return applyPolicy === "auto_apply_in_scope" ? "L6" : "L4";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function capabilityFactories(capabilityIndex: Record<string, unknown>): Record<string, unknown>[] {
|
|
112
|
+
const capabilities = Array.isArray(capabilityIndex.capabilities) ? capabilityIndex.capabilities.filter(isRecord) : [];
|
|
113
|
+
return capabilities.filter((capability) => capability.kind === "factory");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function textSignals(...values: string[]): string[] {
|
|
117
|
+
const text = values.join("\n").toLowerCase();
|
|
118
|
+
const signals: string[] = [];
|
|
119
|
+
const add = (condition: boolean, signal: string): void => {
|
|
120
|
+
if (condition) signals.push(signal);
|
|
121
|
+
};
|
|
122
|
+
add(/\b(code review|review code|review changes|oracle matrix|security review|qa review|correctness|architecture)\b/.test(text), "code_review");
|
|
123
|
+
add(/\b(budget|cost|costs|cap|caps|preflight|strict budget|max runs|max cost|parallel children)\b/.test(text), "budget_preflight");
|
|
124
|
+
add(/\b(roadmap|lot|lots|milestone|unchecked item|execution queue)\b/.test(text), "roadmap_lots");
|
|
125
|
+
add(/\b(opencode|pattern|patterns|canonizer|canonical|taxonomy|workflow rules|quality gates)\b/.test(text), "opencode_patterns");
|
|
126
|
+
add(/\b(projectdna|project dna|project-dna|knowledge graph|code knowledge|context pack|repo scan|reference project)\b/.test(text), "project_dna");
|
|
127
|
+
add(/\b(new factory|create factory|generate factory|factory scaffold|quarantine|factory-forge|forge)\b/.test(text), "factory_forge");
|
|
128
|
+
return [...new Set(signals)].sort();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function scoreFactoryCandidate(factory: Record<string, unknown>, signals: string[]): Record<string, unknown> {
|
|
132
|
+
const id = typeof factory.id === "string" ? factory.id : "unknown";
|
|
133
|
+
const reasonCodes: string[] = [];
|
|
134
|
+
let score = 0;
|
|
135
|
+
const add = (condition: boolean, points: number, reason: string): void => {
|
|
136
|
+
if (condition) {
|
|
137
|
+
score += points;
|
|
138
|
+
reasonCodes.push(reason);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
add(id === "code-review-matrix" && signals.includes("code_review"), 8, "signal:code_review");
|
|
142
|
+
add(id === "budget-preflight-dry-run" && signals.includes("budget_preflight"), 8, "signal:budget_preflight");
|
|
143
|
+
add(id === "roadmap-smoke-lots" && signals.includes("roadmap_lots"), 8, "signal:roadmap_lots");
|
|
144
|
+
add(id === "opencode-pattern-canonizer" && signals.includes("opencode_patterns"), 8, "signal:opencode_patterns");
|
|
145
|
+
add(id === "project-dna" && signals.includes("project_dna"), 8, "signal:project_dna");
|
|
146
|
+
add(id === "factory-forge" && signals.includes("factory_forge"), 8, "signal:factory_forge");
|
|
147
|
+
const metadata = isRecord(factory.metadata) ? factory.metadata : {};
|
|
148
|
+
const manifests = Array.isArray(metadata.manifests) ? metadata.manifests.filter((item): item is string => typeof item === "string") : [];
|
|
149
|
+
add(manifests.includes("smoke-manifest.json"), 1, "manifest:smoke");
|
|
150
|
+
add(manifests.includes("pilot-manifest.json"), 1, "manifest:pilot");
|
|
151
|
+
add(manifests.includes("batch-manifest.json"), 1, "manifest:batch");
|
|
152
|
+
const confidence = Math.max(0, Math.min(0.99, score / 12));
|
|
153
|
+
return {
|
|
154
|
+
kind: "factory",
|
|
155
|
+
id,
|
|
156
|
+
sourcePath: factory.sourcePath,
|
|
157
|
+
score,
|
|
158
|
+
confidence,
|
|
159
|
+
reasonCodes: reasonCodes.sort(),
|
|
160
|
+
summaryHash: typeof factory.summary === "string" ? sha256(factory.summary) : undefined,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function selectAutonomousFactory(input: { factories: Record<string, unknown>[]; refinedSpec: string; acceptanceCriteria: string[]; expectedArtifacts: string[] }): Record<string, unknown> {
|
|
165
|
+
return selectFactoryForDemands({
|
|
166
|
+
schema: "zob.autonomous-factory-selection-score.v1",
|
|
167
|
+
factories: input.factories,
|
|
168
|
+
refinedSpec: input.refinedSpec,
|
|
169
|
+
acceptanceCriteria: input.acceptanceCriteria,
|
|
170
|
+
expectedArtifacts: input.expectedArtifacts,
|
|
171
|
+
}) as unknown as Record<string, unknown>;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function factoryManifestAvailability(repoRoot: string, factoryName: string | undefined): Record<string, unknown> {
|
|
175
|
+
if (!factoryName) return { smoke: false, pilot: false, batch: false };
|
|
176
|
+
return {
|
|
177
|
+
smoke: existsSync(join(repoRoot, ".pi", "factories", factoryName, "smoke-manifest.json")),
|
|
178
|
+
pilot: existsSync(join(repoRoot, ".pi", "factories", factoryName, "pilot-manifest.json")),
|
|
179
|
+
batch: existsSync(join(repoRoot, ".pi", "factories", factoryName, "batch-manifest.json")),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function readFactoryRegistryReadiness(repoRoot: string, factoryName: string | undefined): Record<string, unknown> {
|
|
184
|
+
const reportPath = "reports/factory-registry-readiness-audit-smoke.json";
|
|
185
|
+
const absolutePath = join(repoRoot, reportPath);
|
|
186
|
+
const base = {
|
|
187
|
+
schema: "zob.autonomous-factory-readiness-snapshot.v1",
|
|
188
|
+
reportPath,
|
|
189
|
+
reportPresent: false,
|
|
190
|
+
reportHash: undefined,
|
|
191
|
+
selectedFactory: factoryName,
|
|
192
|
+
registeredBatchReady: false,
|
|
193
|
+
arbitraryFactoryNoShip: true,
|
|
194
|
+
currentSourceProofRequired: true,
|
|
195
|
+
proofBeforeExecutionRequired: true,
|
|
196
|
+
readinessFreshness: "missing_registry_snapshot",
|
|
197
|
+
bodyStored: false,
|
|
198
|
+
promptBodiesStored: false,
|
|
199
|
+
outputBodiesStored: false,
|
|
200
|
+
};
|
|
201
|
+
if (!existsSync(absolutePath)) return base;
|
|
202
|
+
try {
|
|
203
|
+
const rawJson = readFileSync(absolutePath, "utf8");
|
|
204
|
+
const parsed = JSON.parse(rawJson) as unknown;
|
|
205
|
+
const registry = isRecord(parsed) ? parsed : {};
|
|
206
|
+
const readyFactories = Array.isArray(registry.registeredAgenticBatchReadyFactories) ? registry.registeredAgenticBatchReadyFactories.filter((item): item is string => typeof item === "string") : [];
|
|
207
|
+
const missingFactories = Array.isArray(registry.factoriesMissingRegisteredBatchProof) ? registry.factoriesMissingRegisteredBatchProof.filter((item): item is string => typeof item === "string") : [];
|
|
208
|
+
const registeredBatchReady = typeof factoryName === "string" && readyFactories.includes(factoryName);
|
|
209
|
+
return {
|
|
210
|
+
...base,
|
|
211
|
+
reportPresent: true,
|
|
212
|
+
reportHash: sha256(rawJson),
|
|
213
|
+
registeredBatchReady,
|
|
214
|
+
arbitraryFactoryNoShip: registry.arbitraryFactoryNoShip !== false,
|
|
215
|
+
currentSourceProofRequired: true,
|
|
216
|
+
proofBeforeExecutionRequired: !registeredBatchReady,
|
|
217
|
+
readinessFreshness: "snapshot_requires_current_source_refresh_before_execution",
|
|
218
|
+
registeredAgenticBatchReadyFactoryCount: readyFactories.length,
|
|
219
|
+
factoriesMissingRegisteredBatchProofCount: missingFactories.length,
|
|
220
|
+
selectedFactoryMissingRegisteredBatchProof: typeof factoryName === "string" ? missingFactories.includes(factoryName) : undefined,
|
|
221
|
+
};
|
|
222
|
+
} catch {
|
|
223
|
+
return { ...base, reportPresent: true, readinessFreshness: "invalid_registry_snapshot", reportHash: undefined };
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function buildAutonomousContextArtifacts(repoRoot: string, scope: Record<string, unknown>, queryHash: string): Record<string, unknown> {
|
|
228
|
+
const scopeErrors = validateContextScope(repoRoot, scope);
|
|
229
|
+
if (scopeErrors.length > 0) return { lookupResults: [], contextPack: undefined, contextPackValid: false, contextPackErrors: scopeErrors };
|
|
230
|
+
const allowedSources = Array.isArray(scope.allowedSources) ? scope.allowedSources.filter((source): source is string => typeof source === "string") : [];
|
|
231
|
+
try {
|
|
232
|
+
const lookupResults: Record<string, unknown>[] = [];
|
|
233
|
+
if (allowedSources.includes("zob-harness-docs")) {
|
|
234
|
+
const citation = "harness-system:zob-harness-docs:docs/AUTONOMOUS_SUPER_FACTORY_GOAL.md#phase-3";
|
|
235
|
+
lookupResults.push(buildBrainLookupResult(repoRoot, {
|
|
236
|
+
scope,
|
|
237
|
+
brainId: "harness-system",
|
|
238
|
+
sourceId: "zob-harness-docs",
|
|
239
|
+
queryHash,
|
|
240
|
+
facts: [{ factHash: sha256("autonomous loop requires spec context factory oracle final report"), citations: [citation], confidence: "HIGH" }],
|
|
241
|
+
gaps: [{ gapHash: sha256("P0 dry-run does not execute live factories"), citations: [citation], noShipIfTreatedAsPass: true }],
|
|
242
|
+
confidence: "HIGH",
|
|
243
|
+
}));
|
|
244
|
+
}
|
|
245
|
+
if (allowedSources.includes("factory-run-reports")) {
|
|
246
|
+
const citation = "factory-evidence:factory-run-reports:reports/factory-registry-readiness-audit-smoke.json";
|
|
247
|
+
lookupResults.push(buildBrainLookupResult(repoRoot, {
|
|
248
|
+
scope,
|
|
249
|
+
brainId: "factory-evidence",
|
|
250
|
+
sourceId: "factory-run-reports",
|
|
251
|
+
queryHash,
|
|
252
|
+
facts: [{ factHash: sha256("registered factory current-source proof is required before execution"), citations: [citation], confidence: "HIGH", sourcePresent: existsSync(join(repoRoot, "reports", "factory-registry-readiness-audit-smoke.json")) }],
|
|
253
|
+
gaps: [{ gapHash: sha256("selected factory may still require current-source proof refresh"), citations: [citation], noShipIfTreatedAsPass: true }],
|
|
254
|
+
confidence: "HIGH",
|
|
255
|
+
}));
|
|
256
|
+
}
|
|
257
|
+
if (lookupResults.length === 0 && allowedSources.includes("zob-harness-src")) {
|
|
258
|
+
const citation = "harness-system:zob-harness-src:.pi/extensions/zob-harness/src/domains/autonomy/autonomous-runtime.ts";
|
|
259
|
+
lookupResults.push(buildBrainLookupResult(repoRoot, {
|
|
260
|
+
scope,
|
|
261
|
+
brainId: "harness-system",
|
|
262
|
+
sourceId: "zob-harness-src",
|
|
263
|
+
queryHash,
|
|
264
|
+
facts: [{ factHash: sha256("autonomous dry-run implementation is repo-local metadata-only"), citations: [citation], confidence: "MEDIUM" }],
|
|
265
|
+
confidence: "MEDIUM",
|
|
266
|
+
}));
|
|
267
|
+
}
|
|
268
|
+
if (lookupResults.length === 0) return { lookupResults: [], contextPack: undefined, contextPackValid: false, contextPackErrors: ["no_allowed_context_source_for_autonomous_lookup"] };
|
|
269
|
+
const contextPack = buildContextPack(repoRoot, scope, lookupResults);
|
|
270
|
+
const contextPackErrors = validateContextPack(repoRoot, contextPack);
|
|
271
|
+
return { lookupResults, contextPack, contextPackValid: contextPackErrors.length === 0, contextPackErrors };
|
|
272
|
+
} catch (error) {
|
|
273
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
274
|
+
return { lookupResults: [], contextPack: undefined, contextPackValid: false, contextPackErrors: [message] };
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export function buildAutonomousRuntimeGates(input: { runId: string; risk: AutonomousRisk; budgetProfile: AutonomousBudgetProfile; applyPolicy: AutonomousApplyPolicy; maxContextTokens?: number }): Record<string, unknown> {
|
|
279
|
+
const budgetGate = evaluateBudgetPreflightDryRun({
|
|
280
|
+
runs: 0,
|
|
281
|
+
durationMs: 0,
|
|
282
|
+
parallelChildren: 0,
|
|
283
|
+
caps: { maxRuns: 0, maxParallelChildren: 0 },
|
|
284
|
+
strictRequested: input.budgetProfile === "strict_requested",
|
|
285
|
+
});
|
|
286
|
+
const modelRoutingGate = evaluateModelRoutingDryRun({
|
|
287
|
+
mode: "factory",
|
|
288
|
+
taskType: "autonomous-runtime-dry-run",
|
|
289
|
+
risk: input.risk,
|
|
290
|
+
contextTokens: input.maxContextTokens,
|
|
291
|
+
estimatedRuns: 0,
|
|
292
|
+
estimatedParallelChildren: 0,
|
|
293
|
+
caps: { maxRuns: 0, maxParallelChildren: 0 },
|
|
294
|
+
strictRequested: input.budgetProfile === "strict_requested",
|
|
295
|
+
});
|
|
296
|
+
const sandboxGate = {
|
|
297
|
+
schema: "zob.autonomous-sandbox-gate.v1",
|
|
298
|
+
applyPolicy: input.applyPolicy,
|
|
299
|
+
sandboxSimulationPlanned: input.applyPolicy === "sandbox_simulation",
|
|
300
|
+
manualApplyOnly: input.applyPolicy === "manual_apply_only",
|
|
301
|
+
launchAuthorizedApplyPlanned: input.applyPolicy === "auto_apply_in_scope",
|
|
302
|
+
launchAuthorizationRequiredForApply: input.applyPolicy === "auto_apply_in_scope",
|
|
303
|
+
productionWritesPerformed: false,
|
|
304
|
+
autoApply: false,
|
|
305
|
+
rollbackRequiredBeforeRealApply: true,
|
|
306
|
+
oracleDiffReviewRequiredBeforeRealApply: true,
|
|
307
|
+
childDispatchAllowed: false,
|
|
308
|
+
noExecution: true,
|
|
309
|
+
bodyStored: false,
|
|
310
|
+
promptBodiesStored: false,
|
|
311
|
+
outputBodiesStored: false,
|
|
312
|
+
};
|
|
313
|
+
const daemonGate = {
|
|
314
|
+
schema: "zob.autonomous-daemon-gate.v1",
|
|
315
|
+
autoStartDaemon: false,
|
|
316
|
+
continuousLoop: false,
|
|
317
|
+
daemonStarted: false,
|
|
318
|
+
manualOneShotOnly: true,
|
|
319
|
+
killSwitchRequiredBeforeLiveAutonomy: true,
|
|
320
|
+
childDispatchAllowed: false,
|
|
321
|
+
noExecution: true,
|
|
322
|
+
bodyStored: false,
|
|
323
|
+
promptBodiesStored: false,
|
|
324
|
+
outputBodiesStored: false,
|
|
325
|
+
};
|
|
326
|
+
const missionControlGate = {
|
|
327
|
+
schema: "zob.autonomous-mission-control-gate.v1",
|
|
328
|
+
proposalOnly: true,
|
|
329
|
+
directWorkerWrites: false,
|
|
330
|
+
transportDispatch: false,
|
|
331
|
+
networkComsEnabled: false,
|
|
332
|
+
topologyGuardRequired: true,
|
|
333
|
+
hashOnlyLedgerRequired: true,
|
|
334
|
+
childDispatchAllowed: false,
|
|
335
|
+
noExecution: true,
|
|
336
|
+
bodyStored: false,
|
|
337
|
+
promptBodiesStored: false,
|
|
338
|
+
outputBodiesStored: false,
|
|
339
|
+
};
|
|
340
|
+
const autonomousStrictBudgetGate = {
|
|
341
|
+
schema: "zob.autonomous-strict-budget-gate.v1",
|
|
342
|
+
strictBudgetRequiredForAutonomy: true,
|
|
343
|
+
budgetProfile: input.budgetProfile,
|
|
344
|
+
strictRequested: input.budgetProfile === "strict_requested",
|
|
345
|
+
strictEnabled: false,
|
|
346
|
+
globalDefaultEnabled: false,
|
|
347
|
+
budgetEnforced: false,
|
|
348
|
+
childDispatchAllowed: false,
|
|
349
|
+
dispatchBlockedUntilLiveStrictGate: true,
|
|
350
|
+
noExecution: true,
|
|
351
|
+
bodyStored: false,
|
|
352
|
+
promptBodiesStored: false,
|
|
353
|
+
outputBodiesStored: false,
|
|
354
|
+
};
|
|
355
|
+
const checks = [
|
|
356
|
+
{ name: "autonomous_strict_budget_requested_no_dispatch", passed: autonomousStrictBudgetGate.strictRequested === true && autonomousStrictBudgetGate.noExecution === true && autonomousStrictBudgetGate.budgetEnforced === false && autonomousStrictBudgetGate.childDispatchAllowed === false },
|
|
357
|
+
{ name: "budget_preflight_advisory_no_dispatch", passed: budgetGate.noExecution === true && budgetGate.childDispatchAllowed === false && budgetGate.budgetEnforced === false && budgetGate.wouldBlockDispatch === false },
|
|
358
|
+
{ name: "model_routing_dry_run_no_dispatch", passed: modelRoutingGate.noExecution === true && modelRoutingGate.modelRouterUsed === false && modelRoutingGate.routingApplied === false && modelRoutingGate.childDispatchAllowed === false },
|
|
359
|
+
{ name: "sandbox_no_production_apply", passed: sandboxGate.productionWritesPerformed === false && sandboxGate.autoApply === false && sandboxGate.noExecution === true },
|
|
360
|
+
{ name: "daemon_not_started", passed: daemonGate.daemonStarted === false && daemonGate.autoStartDaemon === false && daemonGate.continuousLoop === false },
|
|
361
|
+
{ name: "mission_control_proposals_only", passed: missionControlGate.proposalOnly === true && missionControlGate.directWorkerWrites === false && missionControlGate.transportDispatch === false && missionControlGate.networkComsEnabled === false },
|
|
362
|
+
];
|
|
363
|
+
const failedChecks = checks.filter((check) => !check.passed).map((check) => check.name);
|
|
364
|
+
const gates = {
|
|
365
|
+
schema: "zob.autonomous-runtime-gates.v1",
|
|
366
|
+
runId: input.runId,
|
|
367
|
+
passed: failedChecks.length === 0,
|
|
368
|
+
failedChecks,
|
|
369
|
+
checks,
|
|
370
|
+
budgetGate,
|
|
371
|
+
autonomousStrictBudgetGate,
|
|
372
|
+
modelRoutingGate,
|
|
373
|
+
sandboxGate,
|
|
374
|
+
daemonGate,
|
|
375
|
+
missionControlGate,
|
|
376
|
+
dryRun: true,
|
|
377
|
+
noExecution: true,
|
|
378
|
+
childDispatchAllowed: false,
|
|
379
|
+
globalBudgetEnforced: false,
|
|
380
|
+
globalModelRoutingEnabled: false,
|
|
381
|
+
daemonStarted: false,
|
|
382
|
+
productionWritesPerformed: false,
|
|
383
|
+
autoApply: false,
|
|
384
|
+
networkAccessed: false,
|
|
385
|
+
bodyStored: false,
|
|
386
|
+
promptBodiesStored: false,
|
|
387
|
+
outputBodiesStored: false,
|
|
388
|
+
};
|
|
389
|
+
if (hasForbiddenBodyKeys(gates)) throw new Error("autonomous runtime gates would store forbidden plaintext body keys");
|
|
390
|
+
return gates;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
export function buildAutonomousStrictBudgetProofPlan(input: { runId: string; runtimeGates: Record<string, unknown>; validation: Record<string, unknown> }): Record<string, unknown> {
|
|
394
|
+
const scenarioSpecs = [
|
|
395
|
+
{ name: "strict_gate_allows_within_caps", gateInput: { runId: `${input.runId}-strict-budget-allow`, mode: "smoke", execution: "agentic", taskCount: 1, budget: { strictEnabled: true, maxRuns: 2, estimatedRuns: 1, maxParallelChildren: 1, estimatedParallelChildren: 1 } } },
|
|
396
|
+
{ name: "strict_gate_blocks_exceedance_pre_dispatch", gateInput: { runId: `${input.runId}-strict-budget-block`, mode: "smoke", execution: "agentic", taskCount: 3, budget: { strictEnabled: true, maxRuns: 2, estimatedRuns: 3, maxParallelChildren: 1, estimatedParallelChildren: 1 } } },
|
|
397
|
+
{ name: "strict_gate_default_disabled_advisory", gateInput: { runId: `${input.runId}-strict-budget-default`, mode: "smoke", execution: "agentic", taskCount: 3, budget: { strictRequested: true, maxRuns: 2, estimatedRuns: 3, maxParallelChildren: 1, estimatedParallelChildren: 1 } } },
|
|
398
|
+
].map((scenario) => {
|
|
399
|
+
const gate = evaluateStrictBudgetDispatchGate(scenario.gateInput);
|
|
400
|
+
return {
|
|
401
|
+
name: scenario.name,
|
|
402
|
+
inputHash: sha256(JSON.stringify(scenario.gateInput)),
|
|
403
|
+
strictRequested: gate.strictRequested === true,
|
|
404
|
+
strictEnabled: gate.strictEnabled === true,
|
|
405
|
+
budgetEnforced: gate.budgetEnforced === true,
|
|
406
|
+
wouldExceed: gate.wouldExceed === true,
|
|
407
|
+
wouldBlockDispatch: gate.wouldBlockDispatch === true,
|
|
408
|
+
gateChildDispatchAllowed: gate.childDispatchAllowed === true,
|
|
409
|
+
dispatchDecision: gate.dispatchDecision,
|
|
410
|
+
stopCondition: gate.stopCondition,
|
|
411
|
+
noExecution: gate.noExecution === true,
|
|
412
|
+
failures: Array.isArray(gate.failures) ? gate.failures.filter((failure): failure is string => typeof failure === "string") : [],
|
|
413
|
+
bodyStored: false,
|
|
414
|
+
promptBodiesStored: false,
|
|
415
|
+
outputBodiesStored: false,
|
|
416
|
+
};
|
|
417
|
+
});
|
|
418
|
+
const allow = scenarioSpecs.find((scenario) => scenario.name === "strict_gate_allows_within_caps");
|
|
419
|
+
const block = scenarioSpecs.find((scenario) => scenario.name === "strict_gate_blocks_exceedance_pre_dispatch");
|
|
420
|
+
const defaultDisabled = scenarioSpecs.find((scenario) => scenario.name === "strict_gate_default_disabled_advisory");
|
|
421
|
+
const autonomousStrictBudgetGate = isRecord(input.runtimeGates.autonomousStrictBudgetGate) ? input.runtimeGates.autonomousStrictBudgetGate : {};
|
|
422
|
+
const checks = [
|
|
423
|
+
{ name: "strict_gate_allows_within_caps", passed: allow?.strictEnabled === true && allow.budgetEnforced === true && allow.wouldBlockDispatch === false && allow.gateChildDispatchAllowed === true && allow.dispatchDecision === "allow_strict" },
|
|
424
|
+
{ name: "strict_gate_blocks_exceedance_pre_dispatch", passed: block?.strictEnabled === true && block.budgetEnforced === true && block.wouldBlockDispatch === true && block.gateChildDispatchAllowed === false && block.dispatchDecision === "block" && block.stopCondition === "blocked" },
|
|
425
|
+
{ name: "strict_gate_default_disabled_advisory", passed: defaultDisabled?.strictRequested === true && defaultDisabled.strictEnabled === false && defaultDisabled.budgetEnforced === false && defaultDisabled.wouldBlockDispatch === false && defaultDisabled.dispatchDecision === "allow_advisory" },
|
|
426
|
+
{ name: "autonomous_runtime_global_budget_still_disabled", passed: autonomousStrictBudgetGate.strictRequested === true && autonomousStrictBudgetGate.strictEnabled === false && autonomousStrictBudgetGate.budgetEnforced === false && autonomousStrictBudgetGate.childDispatchAllowed === false },
|
|
427
|
+
{ name: "run_scope_no_global_autonomy", passed: input.validation.globalAutonomyReady === false && input.validation.globalAutonomyNoShip === true && input.validation.childDispatchAllowed === false && input.validation.productionWritesPerformed === false && input.validation.autoApply === false },
|
|
428
|
+
];
|
|
429
|
+
const failedChecks = checks.filter((check) => check.passed !== true).map((check) => check.name);
|
|
430
|
+
const proof = {
|
|
431
|
+
schema: "zob.autonomous-strict-budget-proof-plan.v1",
|
|
432
|
+
runId: input.runId,
|
|
433
|
+
phase: "5B",
|
|
434
|
+
status: failedChecks.length === 0 ? "strict_budget_dispatch_gate_proof_ready_global_default_blocked" : "strict_budget_dispatch_gate_proof_incomplete",
|
|
435
|
+
strictBudgetProofReady: failedChecks.length === 0,
|
|
436
|
+
strictBudgetDispatchGateAvailable: true,
|
|
437
|
+
strictBudgetAllowProofPassed: allow?.dispatchDecision === "allow_strict" && allow.budgetEnforced === true,
|
|
438
|
+
strictBudgetBlockProofPassed: block?.dispatchDecision === "block" && block.wouldBlockDispatch === true,
|
|
439
|
+
strictBudgetDefaultDisabledProofPassed: defaultDisabled?.dispatchDecision === "allow_advisory" && defaultDisabled.strictEnabled === false,
|
|
440
|
+
finalE2ERequirementCleared: false,
|
|
441
|
+
no_ship: true,
|
|
442
|
+
checks,
|
|
443
|
+
failedChecks,
|
|
444
|
+
scenarios: scenarioSpecs,
|
|
445
|
+
evidenceRefs: [
|
|
446
|
+
`reports/autonomous-runs/${safeFileStem(input.runId)}/runtime-gates.json`,
|
|
447
|
+
`reports/autonomous-runs/${safeFileStem(input.runId)}/validation.json`,
|
|
448
|
+
],
|
|
449
|
+
blockers: [
|
|
450
|
+
"live_autonomous_strict_budget_not_enforced",
|
|
451
|
+
"global_default_strict_budget_disabled",
|
|
452
|
+
"final_e2e_strict_budget_evidence_required",
|
|
453
|
+
],
|
|
454
|
+
autonomousRuntimeStrictBudgetEnforced: false,
|
|
455
|
+
globalStrictBudgetEnabled: false,
|
|
456
|
+
globalBudgetEnforced: false,
|
|
457
|
+
liveAutonomousBudgetEnforced: false,
|
|
458
|
+
budgetEnforced: false,
|
|
459
|
+
strictEnabled: false,
|
|
460
|
+
childDispatchAllowed: false,
|
|
461
|
+
daemonStarted: false,
|
|
462
|
+
productionWritesPerformed: false,
|
|
463
|
+
autoApply: false,
|
|
464
|
+
noExecution: true,
|
|
465
|
+
globalAutonomyReady: false,
|
|
466
|
+
globalAutonomyNoShip: true,
|
|
467
|
+
bodyStored: false,
|
|
468
|
+
promptBodiesStored: false,
|
|
469
|
+
outputBodiesStored: false,
|
|
470
|
+
};
|
|
471
|
+
if (hasForbiddenBodyKeys(proof)) throw new Error("autonomous strict budget proof plan would store forbidden plaintext body keys");
|
|
472
|
+
return proof;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
export function buildAutonomousModelRoutingPlan(input: { runId: string; risk: AutonomousRisk; budgetProfile: AutonomousBudgetProfile; maxContextTokens?: number; specText: string; selectedFactory?: string }): Record<string, unknown> {
|
|
476
|
+
const strictRequested = input.budgetProfile === "strict_requested";
|
|
477
|
+
const contextTokens = typeof input.maxContextTokens === "number" && Number.isFinite(input.maxContextTokens) ? Math.max(0, Math.floor(input.maxContextTokens)) : 0;
|
|
478
|
+
const highContextRequired = contextTokens >= 120_000;
|
|
479
|
+
const securitySensitive = input.risk === "high" || /\b(security|secure|vulnerability|vulnerabilities|auth|permission|permissions|sandbox|apply|write|privilege|injection)\b/i.test(input.specText);
|
|
480
|
+
const routeSpecs: Array<{ stage: string; mode: "explore" | "plan" | "implement" | "oracle" | "factory"; taskType: string; outputContract?: string; risk: AutonomousRisk; contextTokens?: number; expectedModelClass: string; securityCritical?: boolean; oracleCritical?: boolean }> = [
|
|
481
|
+
{ stage: "context_reuse_scout", mode: "explore", taskType: "read-only-inspection", risk: "low", expectedModelClass: "cheap_scout" },
|
|
482
|
+
{ stage: "context_pack", mode: "explore", taskType: "context-pack-read-only", risk: "low", contextTokens: contextTokens || undefined, expectedModelClass: highContextRequired ? "high_context" : "cheap_scout" },
|
|
483
|
+
{ stage: "factory_selection", mode: "factory", taskType: securitySensitive ? "security-critical-plan" : "factory-selection", risk: securitySensitive ? "high" : input.risk, expectedModelClass: securitySensitive ? "strong_reasoning" : "balanced_worker", securityCritical: securitySensitive },
|
|
484
|
+
{ stage: "factory_smoke_plan", mode: "factory", taskType: `factory-smoke:${input.selectedFactory ?? "unselected"}`, risk: input.risk, expectedModelClass: input.risk === "high" ? "strong_reasoning" : "balanced_worker" },
|
|
485
|
+
{ stage: "smoke_oracle", mode: "oracle", taskType: "oracle-review", outputContract: "oracle.v1", risk: "high", expectedModelClass: "strong_oracle", oracleCritical: true },
|
|
486
|
+
{ stage: "pilot_oracle", mode: "oracle", taskType: "oracle-review", outputContract: "oracle.v1", risk: "high", expectedModelClass: "strong_oracle", oracleCritical: true },
|
|
487
|
+
{ stage: "final_report_synthesis", mode: "implement", taskType: "synthesis-final-report", risk: input.risk, expectedModelClass: input.risk === "high" ? "strong_reasoning" : "balanced_worker" },
|
|
488
|
+
];
|
|
489
|
+
if (securitySensitive) {
|
|
490
|
+
routeSpecs.push({ stage: "security_reasoning_gate", mode: "plan", taskType: "security-critical-plan", risk: "high", expectedModelClass: "strong_reasoning", securityCritical: true });
|
|
491
|
+
}
|
|
492
|
+
const routes = routeSpecs.map((spec) => {
|
|
493
|
+
const route = evaluateModelRoutingDryRun({
|
|
494
|
+
mode: spec.mode,
|
|
495
|
+
taskType: spec.taskType,
|
|
496
|
+
outputContract: spec.outputContract,
|
|
497
|
+
risk: spec.risk,
|
|
498
|
+
contextTokens: spec.contextTokens,
|
|
499
|
+
estimatedRuns: 0,
|
|
500
|
+
estimatedParallelChildren: 0,
|
|
501
|
+
caps: { maxRuns: 0, maxParallelChildren: 0 },
|
|
502
|
+
strictRequested,
|
|
503
|
+
});
|
|
504
|
+
return {
|
|
505
|
+
stage: spec.stage,
|
|
506
|
+
mode: spec.mode,
|
|
507
|
+
taskType: spec.taskType,
|
|
508
|
+
outputContract: spec.outputContract,
|
|
509
|
+
risk: spec.risk,
|
|
510
|
+
contextTokens: spec.contextTokens,
|
|
511
|
+
expectedModelClass: spec.expectedModelClass,
|
|
512
|
+
recommendedModelClass: route.recommendedModelClass,
|
|
513
|
+
matchedExpectedClass: route.recommendedModelClass === spec.expectedModelClass,
|
|
514
|
+
reasonCodes: Array.isArray(route.reasonCodes) ? route.reasonCodes : [],
|
|
515
|
+
budgetWouldExceed: route.budgetWouldExceed === true,
|
|
516
|
+
budgetEnforced: route.budgetEnforced === true,
|
|
517
|
+
strictRequested: route.strictRequested === true,
|
|
518
|
+
strictEnabled: route.strictEnabled === true,
|
|
519
|
+
modelRouterUsed: route.modelRouterUsed === true,
|
|
520
|
+
routingApplied: route.routingApplied === true,
|
|
521
|
+
childDispatchAllowed: route.childDispatchAllowed === true,
|
|
522
|
+
noExecution: route.noExecution === true,
|
|
523
|
+
securityCritical: spec.securityCritical === true,
|
|
524
|
+
oracleCritical: spec.oracleCritical === true,
|
|
525
|
+
bodyStored: false,
|
|
526
|
+
promptBodiesStored: false,
|
|
527
|
+
outputBodiesStored: false,
|
|
528
|
+
};
|
|
529
|
+
});
|
|
530
|
+
const oracleRoutes = routes.filter((route) => route.oracleCritical === true);
|
|
531
|
+
const securityRoutes = routes.filter((route) => route.securityCritical === true);
|
|
532
|
+
const checks = [
|
|
533
|
+
{ name: "model_routing_plan_present", passed: routes.length >= 7 },
|
|
534
|
+
{ name: "low_risk_readonly_uses_cheap_scout", passed: routes.some((route) => route.stage === "context_reuse_scout" && route.recommendedModelClass === "cheap_scout") },
|
|
535
|
+
{ name: "oracle_uses_strong_oracle", passed: oracleRoutes.length > 0 && oracleRoutes.every((route) => route.recommendedModelClass === "strong_oracle") },
|
|
536
|
+
{ name: "high_context_uses_high_context", passed: !highContextRequired || routes.some((route) => route.stage === "context_pack" && route.recommendedModelClass === "high_context") },
|
|
537
|
+
{ name: "security_not_downgraded", passed: !securitySensitive || (securityRoutes.length > 0 && securityRoutes.every((route) => route.recommendedModelClass === "strong_reasoning" || route.recommendedModelClass === "strong_oracle" || route.recommendedModelClass === "high_context")) },
|
|
538
|
+
{ name: "budget_aware_strict_requested", passed: strictRequested && routes.every((route) => route.strictRequested === true && route.budgetEnforced === false && route.strictEnabled === false) },
|
|
539
|
+
{ name: "routing_dry_run_no_dispatch", passed: routes.every((route) => route.noExecution === true && route.modelRouterUsed === false && route.routingApplied === false && route.childDispatchAllowed === false) },
|
|
540
|
+
{ name: "global_live_routing_disabled", passed: true },
|
|
541
|
+
];
|
|
542
|
+
const failedChecks = checks.filter((check) => check.passed !== true).map((check) => check.name);
|
|
543
|
+
const plan = {
|
|
544
|
+
schema: "zob.autonomous-model-routing-plan.v1",
|
|
545
|
+
runId: input.runId,
|
|
546
|
+
selectedFactory: input.selectedFactory,
|
|
547
|
+
routingRequiredForAutonomy: true,
|
|
548
|
+
routingPlanReady: failedChecks.length === 0,
|
|
549
|
+
failedChecks,
|
|
550
|
+
checks,
|
|
551
|
+
routes,
|
|
552
|
+
highContextRequired,
|
|
553
|
+
securitySensitive,
|
|
554
|
+
budgetAware: strictRequested,
|
|
555
|
+
strictRequested,
|
|
556
|
+
strictEnabled: false,
|
|
557
|
+
budgetEnforced: false,
|
|
558
|
+
liveRoutingEnabled: false,
|
|
559
|
+
globalLiveRoutingEnabled: false,
|
|
560
|
+
modelRouterUsed: false,
|
|
561
|
+
routingApplied: false,
|
|
562
|
+
childDispatchAllowed: false,
|
|
563
|
+
noExecution: true,
|
|
564
|
+
bodyStored: false,
|
|
565
|
+
promptBodiesStored: false,
|
|
566
|
+
outputBodiesStored: false,
|
|
567
|
+
};
|
|
568
|
+
if (hasForbiddenBodyKeys(plan)) throw new Error("autonomous model routing plan would store forbidden plaintext body keys");
|
|
569
|
+
return plan;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
export function buildAutonomousModelRoutingProofPlan(input: { runId: string; modelRoutingPlan: Record<string, unknown>; validation: Record<string, unknown> }): Record<string, unknown> {
|
|
573
|
+
const proofModelByClass = { cheap_scout: "scout-model", balanced_worker: "worker-model", strong_reasoning: "reasoning-model", strong_oracle: "oracle-model", high_context: "long-context-model" };
|
|
574
|
+
const scenarioSpecs = [
|
|
575
|
+
{ name: "routing_default_disabled", gateInput: { runId: `${input.runId}-routing-default`, mode: "factory" as const, stage: "map", agent: "explore", outputContract: "explore.v1", modelRouting: { enabled: false, modelByClass: proofModelByClass } } },
|
|
576
|
+
{ name: "routing_oracle_applies_when_enabled", gateInput: { runId: `${input.runId}-routing-oracle`, mode: "factory" as const, stage: "validate", agent: "oracle-merge", outputContract: "oracle-merge.v1", modelRouting: { enabled: true, modelByClass: proofModelByClass } } },
|
|
577
|
+
{ name: "routing_high_context_applies_when_enabled", gateInput: { runId: `${input.runId}-routing-high-context`, mode: "factory" as const, stage: "reduce", agent: "synthesis", outputContract: "synthesis.v1", modelRouting: { enabled: true, contextTokens: 150_000, modelByClass: proofModelByClass } } },
|
|
578
|
+
{ name: "routing_security_not_downgraded_when_enabled", gateInput: { runId: `${input.runId}-routing-security`, mode: "plan" as const, stage: "security_reasoning_gate", agent: "planner", outputContract: "plan.v1", risk: "high" as const, taskType: "security-critical-plan", modelRouting: { enabled: true, modelByClass: proofModelByClass } } },
|
|
579
|
+
].map((scenario) => {
|
|
580
|
+
const gate = evaluateModelRoutingDispatchGate(scenario.gateInput);
|
|
581
|
+
return {
|
|
582
|
+
name: scenario.name,
|
|
583
|
+
inputHash: sha256(JSON.stringify(scenario.gateInput)),
|
|
584
|
+
liveRoutingRequested: gate.liveRoutingRequested === true,
|
|
585
|
+
liveRoutingEnabled: gate.liveRoutingEnabled === true,
|
|
586
|
+
modelRouterUsed: gate.modelRouterUsed === true,
|
|
587
|
+
routingApplied: gate.routingApplied === true,
|
|
588
|
+
selectedModelClass: gate.selectedModelClass,
|
|
589
|
+
recommendedModelClass: gate.recommendedModelClass,
|
|
590
|
+
selectedModelHash: typeof gate.selectedModelHash === "string" ? gate.selectedModelHash : undefined,
|
|
591
|
+
selectedModelStored: gate.selectedModelStored === true,
|
|
592
|
+
modelByClassProvided: gate.modelByClassProvided === true,
|
|
593
|
+
gateChildDispatchAllowed: gate.childDispatchAllowed === true,
|
|
594
|
+
defaultDispatchDecision: gate.defaultDispatchDecision,
|
|
595
|
+
noExecution: gate.noExecution === true,
|
|
596
|
+
budgetEnforced: gate.budgetEnforced === true,
|
|
597
|
+
strictEnabled: gate.strictEnabled === true,
|
|
598
|
+
reasonCodes: Array.isArray(gate.reasonCodes) ? gate.reasonCodes.filter((reason): reason is string => typeof reason === "string") : [],
|
|
599
|
+
bodyStored: false,
|
|
600
|
+
promptBodiesStored: false,
|
|
601
|
+
outputBodiesStored: false,
|
|
602
|
+
};
|
|
603
|
+
});
|
|
604
|
+
const defaultDisabled = scenarioSpecs.find((scenario) => scenario.name === "routing_default_disabled");
|
|
605
|
+
const oracle = scenarioSpecs.find((scenario) => scenario.name === "routing_oracle_applies_when_enabled");
|
|
606
|
+
const highContext = scenarioSpecs.find((scenario) => scenario.name === "routing_high_context_applies_when_enabled");
|
|
607
|
+
const security = scenarioSpecs.find((scenario) => scenario.name === "routing_security_not_downgraded_when_enabled");
|
|
608
|
+
const checks = [
|
|
609
|
+
{ name: "routing_default_disabled", passed: defaultDisabled?.liveRoutingEnabled === false && defaultDisabled.modelRouterUsed === false && defaultDisabled.routingApplied === false && defaultDisabled.gateChildDispatchAllowed === false && defaultDisabled.defaultDispatchDecision === "allow_default_model" },
|
|
610
|
+
{ name: "routing_oracle_uses_strong_oracle_when_enabled", passed: oracle?.liveRoutingEnabled === true && oracle.modelRouterUsed === true && oracle.routingApplied === true && oracle.selectedModelClass === "strong_oracle" && typeof oracle.selectedModelHash === "string" && oracle.selectedModelStored === false },
|
|
611
|
+
{ name: "routing_high_context_uses_high_context_when_enabled", passed: highContext?.liveRoutingEnabled === true && highContext.selectedModelClass === "high_context" && typeof highContext.selectedModelHash === "string" && highContext.selectedModelStored === false },
|
|
612
|
+
{ name: "routing_security_not_downgraded_when_enabled", passed: security?.liveRoutingEnabled === true && security.selectedModelClass === "strong_reasoning" && typeof security.selectedModelHash === "string" && security.selectedModelStored === false },
|
|
613
|
+
{ name: "autonomous_model_routing_plan_still_disabled", passed: input.modelRoutingPlan.liveRoutingEnabled === false && input.modelRoutingPlan.globalLiveRoutingEnabled === false && input.modelRoutingPlan.modelRouterUsed === false && input.modelRoutingPlan.routingApplied === false && input.modelRoutingPlan.childDispatchAllowed === false },
|
|
614
|
+
{ name: "run_scope_no_global_autonomy", passed: input.validation.globalAutonomyReady === false && input.validation.globalAutonomyNoShip === true && input.validation.childDispatchAllowed === false && input.validation.productionWritesPerformed === false && input.validation.autoApply === false },
|
|
615
|
+
];
|
|
616
|
+
const failedChecks = checks.filter((check) => check.passed !== true).map((check) => check.name);
|
|
617
|
+
const proof = {
|
|
618
|
+
schema: "zob.autonomous-model-routing-proof-plan.v1",
|
|
619
|
+
runId: input.runId,
|
|
620
|
+
phase: "6B",
|
|
621
|
+
status: failedChecks.length === 0 ? "model_routing_dispatch_gate_proof_ready_global_default_blocked" : "model_routing_dispatch_gate_proof_incomplete",
|
|
622
|
+
modelRoutingProofReady: failedChecks.length === 0,
|
|
623
|
+
liveRoutingDispatchGateAvailable: true,
|
|
624
|
+
routingDefaultDisabledProofPassed: defaultDisabled?.defaultDispatchDecision === "allow_default_model" && defaultDisabled.liveRoutingEnabled === false,
|
|
625
|
+
routingOracleProofPassed: oracle?.selectedModelClass === "strong_oracle" && oracle.routingApplied === true,
|
|
626
|
+
routingHighContextProofPassed: highContext?.selectedModelClass === "high_context" && highContext.routingApplied === true,
|
|
627
|
+
routingSecurityNoDowngradeProofPassed: security?.selectedModelClass === "strong_reasoning" && security.routingApplied === true,
|
|
628
|
+
selectedModelsStored: false,
|
|
629
|
+
selectedModelHashesOnly: scenarioSpecs.every((scenario) => scenario.selectedModelStored === false && (scenario.liveRoutingEnabled === false || typeof scenario.selectedModelHash === "string")),
|
|
630
|
+
finalE2ERequirementCleared: false,
|
|
631
|
+
no_ship: true,
|
|
632
|
+
checks,
|
|
633
|
+
failedChecks,
|
|
634
|
+
scenarios: scenarioSpecs,
|
|
635
|
+
evidenceRefs: [
|
|
636
|
+
`reports/autonomous-runs/${safeFileStem(input.runId)}/model-routing-plan.json`,
|
|
637
|
+
`reports/autonomous-runs/${safeFileStem(input.runId)}/validation.json`,
|
|
638
|
+
],
|
|
639
|
+
blockers: [
|
|
640
|
+
"live_autonomous_model_routing_not_enabled",
|
|
641
|
+
"global_default_model_routing_disabled",
|
|
642
|
+
"final_e2e_model_routing_evidence_required",
|
|
643
|
+
],
|
|
644
|
+
globalLiveRoutingEnabled: false,
|
|
645
|
+
liveAutonomousRoutingApplied: false,
|
|
646
|
+
modelRouterUsed: false,
|
|
647
|
+
routingApplied: false,
|
|
648
|
+
budgetEnforced: false,
|
|
649
|
+
strictEnabled: false,
|
|
650
|
+
childDispatchAllowed: false,
|
|
651
|
+
daemonStarted: false,
|
|
652
|
+
productionWritesPerformed: false,
|
|
653
|
+
autoApply: false,
|
|
654
|
+
noExecution: true,
|
|
655
|
+
globalAutonomyReady: false,
|
|
656
|
+
globalAutonomyNoShip: true,
|
|
657
|
+
bodyStored: false,
|
|
658
|
+
promptBodiesStored: false,
|
|
659
|
+
outputBodiesStored: false,
|
|
660
|
+
};
|
|
661
|
+
if (hasForbiddenBodyKeys(proof)) throw new Error("autonomous model routing proof plan would store forbidden plaintext body keys");
|
|
662
|
+
return proof;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
export function buildAutonomousRunGraph(input: {
|
|
666
|
+
runId: string;
|
|
667
|
+
specLocked: boolean;
|
|
668
|
+
contextScopeValid: boolean;
|
|
669
|
+
contextPackValid: boolean;
|
|
670
|
+
runtimeGatesValid: boolean;
|
|
671
|
+
modelRoutingPlanValid: boolean;
|
|
672
|
+
factorySelected: boolean;
|
|
673
|
+
registeredBatchReady: boolean;
|
|
674
|
+
proofBeforeExecutionRequired: boolean;
|
|
675
|
+
selectedFactory?: string;
|
|
676
|
+
}): Record<string, unknown> {
|
|
677
|
+
const nodes = [
|
|
678
|
+
{ id: "spec_gate", kind: "gate", artifactRef: "spec-gate.json", passed: input.specLocked, stopOnFail: true },
|
|
679
|
+
{ id: "context_scope", kind: "context", artifactRef: "context-scope.json", passed: input.contextScopeValid, stopOnFail: true },
|
|
680
|
+
{ id: "context_lookup", kind: "context", artifactRef: "context-lookup.json", passed: input.contextPackValid, stopOnFail: true },
|
|
681
|
+
{ id: "context_pack", kind: "context", artifactRef: "context-pack.json", passed: input.contextPackValid, stopOnFail: true },
|
|
682
|
+
{ id: "runtime_gates", kind: "gate", artifactRef: "runtime-gates.json", passed: input.runtimeGatesValid, stopOnFail: true },
|
|
683
|
+
{ id: "model_routing_plan", kind: "gate", artifactRef: "model-routing-plan.json", passed: input.modelRoutingPlanValid, stopOnFail: true },
|
|
684
|
+
{ id: "factory_selection", kind: "selection", artifactRef: "factory-selection.json", passed: input.factorySelected, selectedFactory: input.selectedFactory, stopOnFail: true },
|
|
685
|
+
{ id: "registered_factory_current_source_proof", kind: "proof", artifactRef: "proof-plan.json", passed: input.registeredBatchReady, proofBeforeExecutionRequired: input.proofBeforeExecutionRequired, stopOnFail: false },
|
|
686
|
+
{ id: "smoke", kind: "future_execution", artifactRef: "SMOKE_PASSED.sentinel", passed: false, dispatchAllowed: false },
|
|
687
|
+
{ id: "smoke_oracle", kind: "future_oracle", artifactRef: "oracle-review-pass.json", passed: false, dispatchAllowed: false },
|
|
688
|
+
{ id: "pilot", kind: "future_execution", artifactRef: "PILOT_PASSED.sentinel", passed: false, dispatchAllowed: false },
|
|
689
|
+
{ id: "pilot_oracle", kind: "future_oracle", artifactRef: "oracle-review-pass.json", passed: false, dispatchAllowed: false },
|
|
690
|
+
{ id: "batch", kind: "future_execution", artifactRef: "BATCH_PASSED.sentinel", passed: false, dispatchAllowed: false },
|
|
691
|
+
{ id: "final_report", kind: "report", artifactRef: "final-report.md", passed: false, dispatchAllowed: false },
|
|
692
|
+
];
|
|
693
|
+
const edges = [
|
|
694
|
+
["spec_gate", "context_scope"],
|
|
695
|
+
["context_scope", "context_lookup"],
|
|
696
|
+
["context_lookup", "context_pack"],
|
|
697
|
+
["context_pack", "runtime_gates"],
|
|
698
|
+
["runtime_gates", "model_routing_plan"],
|
|
699
|
+
["model_routing_plan", "factory_selection"],
|
|
700
|
+
["factory_selection", "registered_factory_current_source_proof"],
|
|
701
|
+
["registered_factory_current_source_proof", "smoke"],
|
|
702
|
+
["smoke", "smoke_oracle"],
|
|
703
|
+
["smoke_oracle", "pilot"],
|
|
704
|
+
["pilot", "pilot_oracle"],
|
|
705
|
+
["pilot_oracle", "batch"],
|
|
706
|
+
["batch", "final_report"],
|
|
707
|
+
].map(([from, to]) => ({ from, to, parentOwned: true, dispatchAllowed: false }));
|
|
708
|
+
const runGraph = {
|
|
709
|
+
schema: "zob.autonomous-run-graph.v1",
|
|
710
|
+
runId: input.runId,
|
|
711
|
+
status: input.specLocked && input.contextScopeValid && input.contextPackValid && input.runtimeGatesValid && input.modelRoutingPlanValid && input.factorySelected ? "dry_run_graph_ready" : "dry_run_graph_blocked",
|
|
712
|
+
parentOwned: true,
|
|
713
|
+
nodes,
|
|
714
|
+
edges,
|
|
715
|
+
stopConditions: ["clarification_required", "context_scope_invalid", "context_pack_invalid", "runtime_gates_invalid", "model_routing_plan_invalid", "factory_selection_missing", "current_source_proof_missing", "oracle_fail", "budget_exceeded", "secret_reference", "production_apply_requested"],
|
|
716
|
+
futureExecutionNodesDispatchAllowed: false,
|
|
717
|
+
childDispatchAllowed: false,
|
|
718
|
+
noExecution: true,
|
|
719
|
+
daemonStarted: false,
|
|
720
|
+
productionWritesPerformed: false,
|
|
721
|
+
autoApply: false,
|
|
722
|
+
globalAutonomyReady: false,
|
|
723
|
+
globalAutonomyNoShip: true,
|
|
724
|
+
bodyStored: false,
|
|
725
|
+
promptBodiesStored: false,
|
|
726
|
+
outputBodiesStored: false,
|
|
727
|
+
};
|
|
728
|
+
if (hasForbiddenBodyKeys(runGraph)) throw new Error("autonomous run graph would store forbidden plaintext body keys");
|
|
729
|
+
return runGraph;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
export function detectContextNeedTags(specText: string): string[] {
|
|
733
|
+
const lower = specText.toLowerCase();
|
|
734
|
+
const tags = new Set<string>(["harness-system", "factory-evidence"]);
|
|
735
|
+
if (/factory|batch|pilot|smoke|oracle/.test(lower)) tags.add("factory-evidence");
|
|
736
|
+
if (/context|gbrain|brain|citation|source/.test(lower)) tags.add("context-gbrain");
|
|
737
|
+
if (/budget|cost|cap/.test(lower)) tags.add("budget-policy");
|
|
738
|
+
if (/model|routing|oracle/.test(lower)) tags.add("model-routing");
|
|
739
|
+
if (/sandbox|apply|write|patch|edit/.test(lower)) tags.add("sandbox-policy");
|
|
740
|
+
if (/daemon|queue|worker|mission|coms|heartbeat/.test(lower)) tags.add("mission-control");
|
|
741
|
+
return [...tags].sort();
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
export function buildClarificationQuestions(input: {
|
|
745
|
+
shortSpec: boolean;
|
|
746
|
+
missingAcceptance: boolean;
|
|
747
|
+
missingArtifacts: boolean;
|
|
748
|
+
missingAllowedPaths: boolean;
|
|
749
|
+
unsafeAllowedPaths: boolean;
|
|
750
|
+
missingApplyPolicy: boolean;
|
|
751
|
+
missingBudgetProfile: boolean;
|
|
752
|
+
riskyApply: boolean;
|
|
753
|
+
sensitiveReference: boolean;
|
|
754
|
+
}): string[] {
|
|
755
|
+
const questions: string[] = [];
|
|
756
|
+
if (input.shortSpec) questions.push("What exact deliverable should the autonomous dry-run plan target?");
|
|
757
|
+
if (input.missingAcceptance) questions.push("What acceptance criteria must be true before the run can proceed past spec lock?");
|
|
758
|
+
if (input.missingArtifacts) questions.push("Which final artifacts or reports should be produced?");
|
|
759
|
+
if (input.missingAllowedPaths) questions.push("Which repo-relative allowed_paths should bound future autonomous work?");
|
|
760
|
+
if (input.unsafeAllowedPaths) questions.push("Please remove unsafe or forbidden entries from allowed_paths and keep them in forbidden_paths only.");
|
|
761
|
+
if (input.missingApplyPolicy) questions.push("Which apply_policy should govern this autonomous run: no_apply, sandbox_simulation, manual_apply_only, or auto_apply_in_scope?");
|
|
762
|
+
if (input.missingBudgetProfile) questions.push("Which budget_profile should govern this autonomous run: advisory or strict_requested?");
|
|
763
|
+
if (input.riskyApply) questions.push("Should this remain no-apply/manual-apply, or is a sandbox simulation explicitly required?");
|
|
764
|
+
if (input.sensitiveReference) questions.push("Please remove or replace any secret-like values with safe placeholders before planning.");
|
|
765
|
+
return questions;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
export function buildAutonomousRuntimeDryRun(repoRoot: string, input: AutonomousRuntimeDryRunInput): Record<string, unknown> {
|
|
769
|
+
const userNeed = typeof input.userNeed === "string" ? input.userNeed.trim() : "";
|
|
770
|
+
const refinedSpec = typeof input.refinedSpec === "string" && input.refinedSpec.trim().length > 0 ? input.refinedSpec.trim() : userNeed;
|
|
771
|
+
const constraints = stableStrings(input.constraints);
|
|
772
|
+
const acceptanceCriteria = stableStrings(input.acceptanceCriteria);
|
|
773
|
+
const expectedArtifacts = stableStrings(input.expectedArtifacts);
|
|
774
|
+
const allowedPaths = stableStrings(input.allowedPaths);
|
|
775
|
+
const forbiddenPaths = stableStrings(input.forbiddenPaths ?? DEFAULT_AUTONOMOUS_FORBIDDEN_PATHS);
|
|
776
|
+
const applyPolicyProvided = typeof input.applyPolicy === "string";
|
|
777
|
+
const budgetProfileProvided = typeof input.budgetProfile === "string";
|
|
778
|
+
const applyPolicy = input.applyPolicy ?? "no_apply";
|
|
779
|
+
const budgetProfile = input.budgetProfile ?? "advisory";
|
|
780
|
+
const risk = input.risk ?? "medium";
|
|
781
|
+
const authorizedAutonomyLevel = input.authorizedAutonomyLevel ?? inferAutonomousLevel(applyPolicy);
|
|
782
|
+
const userLaunchConfirmed = input.userLaunchConfirmed === true;
|
|
783
|
+
const allowedActions = stableStrings(input.allowedActions ?? defaultAutonomousAllowedActions(applyPolicy));
|
|
784
|
+
const runId = safeFileStem(input.runId ?? `autonomous-dry-run-${sha256(refinedSpec || "missing-spec").slice(0, 12)}`);
|
|
785
|
+
const specText = `${userNeed}\n${refinedSpec}\n${constraints.join("\n")}\n${acceptanceCriteria.join("\n")}\n${expectedArtifacts.join("\n")}`;
|
|
786
|
+
const shortSpec = refinedSpec.length < 24;
|
|
787
|
+
const ambiguous = AMBIGUOUS_PATTERNS.some((pattern) => pattern.test(refinedSpec));
|
|
788
|
+
const sensitiveReference = SECRET_PATTERNS.some((pattern) => pattern.test(specText));
|
|
789
|
+
const missingAcceptance = acceptanceCriteria.length === 0;
|
|
790
|
+
const missingArtifacts = expectedArtifacts.length === 0;
|
|
791
|
+
const pathGateErrors = validateAutonomousSpecPathGate(allowedPaths, forbiddenPaths);
|
|
792
|
+
const missingAllowedPaths = allowedPaths.length === 0;
|
|
793
|
+
const unsafeAllowedPaths = pathGateErrors.some((error) => error !== "allowed_paths_required_before_execution");
|
|
794
|
+
const missingApplyPolicy = !applyPolicyProvided;
|
|
795
|
+
const missingBudgetProfile = !budgetProfileProvided;
|
|
796
|
+
const riskyApply = applyPolicy !== "no_apply" && allowedPaths.length === 0;
|
|
797
|
+
const clarificationRequired = !userNeed || shortSpec || ambiguous || sensitiveReference || missingAcceptance || missingArtifacts || missingAllowedPaths || unsafeAllowedPaths || missingApplyPolicy || missingBudgetProfile || riskyApply;
|
|
798
|
+
const clarificationQuestions = buildClarificationQuestions({ shortSpec: !userNeed || shortSpec || ambiguous, missingAcceptance, missingArtifacts, missingAllowedPaths, unsafeAllowedPaths, missingApplyPolicy, missingBudgetProfile, riskyApply, sensitiveReference });
|
|
799
|
+
|
|
800
|
+
const contextScope = buildDefaultContextScope(repoRoot, {
|
|
801
|
+
runId,
|
|
802
|
+
allowedSources: input.allowedSources,
|
|
803
|
+
forbiddenSources: forbiddenPaths,
|
|
804
|
+
agentProfile: "autonomous-runtime-dry-run-p0",
|
|
805
|
+
maxContextTokens: input.maxContextTokens,
|
|
806
|
+
});
|
|
807
|
+
const contextScopeErrors = validateContextScope(repoRoot, contextScope);
|
|
808
|
+
const contextArtifacts = buildAutonomousContextArtifacts(repoRoot, contextScope, sha256(refinedSpec));
|
|
809
|
+
const contextPackValid = contextArtifacts.contextPackValid === true;
|
|
810
|
+
const contextPackErrors = Array.isArray(contextArtifacts.contextPackErrors) ? contextArtifacts.contextPackErrors : [];
|
|
811
|
+
const runtimeGates = buildAutonomousRuntimeGates({ runId, risk, budgetProfile, applyPolicy, maxContextTokens: input.maxContextTokens });
|
|
812
|
+
const runtimeGatesValid = runtimeGates.passed === true;
|
|
813
|
+
const capabilityIndex = buildCapabilityIndex(repoRoot);
|
|
814
|
+
const reuseScout = buildReuseScoutReport(repoRoot, { query: refinedSpec, run_id: runId, limit: 8 });
|
|
815
|
+
const candidates = Array.isArray(reuseScout.candidates) ? reuseScout.candidates : [];
|
|
816
|
+
const factories = capabilityFactories(capabilityIndex);
|
|
817
|
+
const factoryForgeAvailable = factories.some((factory) => factory.id === "factory-forge");
|
|
818
|
+
const factoryScore = selectAutonomousFactory({ factories, refinedSpec, acceptanceCriteria, expectedArtifacts });
|
|
819
|
+
const selectedFactory = typeof factoryScore.selectedFactory === "string" ? factoryScore.selectedFactory : (factoryForgeAvailable ? "factory-forge" : undefined);
|
|
820
|
+
const selectionStatus = typeof factoryScore.selectionStatus === "string" && factoryScore.selectionStatus !== "no_factory_available"
|
|
821
|
+
? factoryScore.selectionStatus
|
|
822
|
+
: (factoryForgeAvailable ? "factory_forge_quarantine_recommended" : "no_factory_available");
|
|
823
|
+
const manifestAvailability = factoryManifestAvailability(repoRoot, selectedFactory);
|
|
824
|
+
const factoryReadiness = readFactoryRegistryReadiness(repoRoot, selectedFactory);
|
|
825
|
+
const proofBeforeExecutionRequired = factoryReadiness.proofBeforeExecutionRequired === true;
|
|
826
|
+
const modelRoutingPlan = buildAutonomousModelRoutingPlan({ runId, risk, budgetProfile, maxContextTokens: input.maxContextTokens, specText, selectedFactory });
|
|
827
|
+
const modelRoutingPlanValid = modelRoutingPlan.routingPlanReady === true;
|
|
828
|
+
const selectionBlockers = selectedFactory ? [] : ["no_factory_available_for_spec"];
|
|
829
|
+
|
|
830
|
+
const strictBudgetMissing = budgetProfile !== "strict_requested";
|
|
831
|
+
const blockers = [
|
|
832
|
+
...(!userNeed ? ["user_need_required"] : []),
|
|
833
|
+
...(clarificationRequired ? ["clarification_required_before_execution"] : []),
|
|
834
|
+
...pathGateErrors,
|
|
835
|
+
...(missingApplyPolicy ? ["apply_policy_required_before_execution"] : []),
|
|
836
|
+
...(missingBudgetProfile ? ["budget_profile_required_before_execution"] : []),
|
|
837
|
+
...(!missingBudgetProfile && strictBudgetMissing ? ["autonomous_strict_budget_required_before_execution"] : []),
|
|
838
|
+
...(contextScopeErrors.length > 0 ? ["context_scope_invalid"] : []),
|
|
839
|
+
...(!contextPackValid ? ["context_pack_invalid"] : []),
|
|
840
|
+
...(!runtimeGatesValid ? ["runtime_gates_invalid"] : []),
|
|
841
|
+
...(!modelRoutingPlanValid ? ["model_routing_plan_invalid"] : []),
|
|
842
|
+
...selectionBlockers,
|
|
843
|
+
];
|
|
844
|
+
const specLocked = blockers.length === 0;
|
|
845
|
+
const launchAuthorization = {
|
|
846
|
+
schema: "zob.launch-authorization.v1",
|
|
847
|
+
runId,
|
|
848
|
+
originalUserAskHash: sha256(userNeed),
|
|
849
|
+
refinedSpecHash: sha256(refinedSpec),
|
|
850
|
+
specLocked,
|
|
851
|
+
userLaunchConfirmed,
|
|
852
|
+
launchConfirmedAt: userLaunchConfirmed && typeof input.launchConfirmedAt === "string" && input.launchConfirmedAt.trim().length > 0 ? input.launchConfirmedAt.trim() : undefined,
|
|
853
|
+
authorizedAutonomyLevel,
|
|
854
|
+
allowedActions,
|
|
855
|
+
allowedPaths,
|
|
856
|
+
forbiddenPaths,
|
|
857
|
+
applyPolicy: {
|
|
858
|
+
mode: applyPolicy,
|
|
859
|
+
rollbackRequired: applyPolicy !== "no_apply",
|
|
860
|
+
exactDiffHashRequired: applyPolicy !== "no_apply",
|
|
861
|
+
postApplyValidationRequired: applyPolicy !== "no_apply",
|
|
862
|
+
postApplyOracleRequired: applyPolicy !== "no_apply",
|
|
863
|
+
},
|
|
864
|
+
budgetPolicy: {
|
|
865
|
+
mode: budgetProfile,
|
|
866
|
+
strict: budgetProfile === "strict_requested",
|
|
867
|
+
strictBudgetRequired: true,
|
|
868
|
+
strictBudgetSatisfied: budgetProfile === "strict_requested",
|
|
869
|
+
},
|
|
870
|
+
stopConditions: ["scope_drift", "secret_required", "validation_fail_exhausted", "oracle_no_ship", "budget_exceeded", "stale_worker_unrecoverable"],
|
|
871
|
+
launchAuthorizesInScopeActions: specLocked && userLaunchConfirmed,
|
|
872
|
+
actionExecutionBlockedUntilLaunch: !userLaunchConfirmed,
|
|
873
|
+
exceptionApprovalRequiredOnlyForOutOfScope: true,
|
|
874
|
+
bodyStored: false,
|
|
875
|
+
promptBodiesStored: false,
|
|
876
|
+
outputBodiesStored: false,
|
|
877
|
+
};
|
|
878
|
+
const status = specLocked ? "dry_run_plan_ready" : "clarification_or_gate_required";
|
|
879
|
+
const runGraph = buildAutonomousRunGraph({
|
|
880
|
+
runId,
|
|
881
|
+
specLocked,
|
|
882
|
+
contextScopeValid: contextScopeErrors.length === 0,
|
|
883
|
+
contextPackValid,
|
|
884
|
+
runtimeGatesValid,
|
|
885
|
+
modelRoutingPlanValid,
|
|
886
|
+
factorySelected: Boolean(selectedFactory),
|
|
887
|
+
registeredBatchReady: factoryReadiness.registeredBatchReady === true,
|
|
888
|
+
proofBeforeExecutionRequired,
|
|
889
|
+
selectedFactory,
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
const report = {
|
|
893
|
+
schema: "zob.autonomous-runtime-dry-run.v1",
|
|
894
|
+
runId,
|
|
895
|
+
status,
|
|
896
|
+
no_ship: true,
|
|
897
|
+
noShipReason: "P0 dry-run only; global autonomy remains disabled until current-source proof and policy gates pass.",
|
|
898
|
+
globalAutonomyReady: false,
|
|
899
|
+
globalAutonomyNoShip: true,
|
|
900
|
+
dryRun: true,
|
|
901
|
+
noExecution: true,
|
|
902
|
+
childDispatchAllowed: false,
|
|
903
|
+
daemonStarted: false,
|
|
904
|
+
productionWritesPerformed: false,
|
|
905
|
+
autoApply: false,
|
|
906
|
+
networkAccessed: false,
|
|
907
|
+
bodyStored: false,
|
|
908
|
+
promptBodiesStored: false,
|
|
909
|
+
outputBodiesStored: false,
|
|
910
|
+
specGate: {
|
|
911
|
+
schema: "zob.autonomous-spec-gate.v1",
|
|
912
|
+
userNeedHash: sha256(userNeed),
|
|
913
|
+
refinedSpecHash: sha256(refinedSpec),
|
|
914
|
+
constraintHashes: hashes(constraints),
|
|
915
|
+
acceptanceCriteriaHashes: hashes(acceptanceCriteria),
|
|
916
|
+
expectedArtifactHashes: hashes(expectedArtifacts),
|
|
917
|
+
allowedPaths,
|
|
918
|
+
forbiddenPaths,
|
|
919
|
+
allowedPathsRequired: true,
|
|
920
|
+
pathGatePassed: pathGateErrors.length === 0,
|
|
921
|
+
pathGateErrors,
|
|
922
|
+
applyPolicyRequired: true,
|
|
923
|
+
applyPolicyProvided,
|
|
924
|
+
applyPolicy,
|
|
925
|
+
budgetProfileRequired: true,
|
|
926
|
+
budgetProfileProvided,
|
|
927
|
+
budgetProfile,
|
|
928
|
+
autonomousStrictBudgetRequired: true,
|
|
929
|
+
autonomousStrictBudgetSatisfied: budgetProfile === "strict_requested",
|
|
930
|
+
risk,
|
|
931
|
+
specTextStored: false,
|
|
932
|
+
specLocked,
|
|
933
|
+
launchAuthorizationRequired: true,
|
|
934
|
+
userLaunchConfirmed,
|
|
935
|
+
launchAuthorizesInScopeActions: launchAuthorization.launchAuthorizesInScopeActions,
|
|
936
|
+
actionExecutionBlockedUntilLaunch: launchAuthorization.actionExecutionBlockedUntilLaunch,
|
|
937
|
+
clarificationRequired,
|
|
938
|
+
clarificationQuestions,
|
|
939
|
+
blockers,
|
|
940
|
+
},
|
|
941
|
+
launchAuthorization,
|
|
942
|
+
contextPlan: {
|
|
943
|
+
schema: "zob.autonomous-context-plan.v1",
|
|
944
|
+
contextNeedTags: detectContextNeedTags(specText),
|
|
945
|
+
contextScope,
|
|
946
|
+
contextScopeValid: contextScopeErrors.length === 0,
|
|
947
|
+
contextScopeErrors,
|
|
948
|
+
lookupResults: contextArtifacts.lookupResults,
|
|
949
|
+
contextPack: contextArtifacts.contextPack,
|
|
950
|
+
contextPackValid,
|
|
951
|
+
contextPackErrors,
|
|
952
|
+
lookupPlan: {
|
|
953
|
+
queryHash: sha256(refinedSpec),
|
|
954
|
+
allowedSources: contextScope.allowedSources,
|
|
955
|
+
citationRequired: true,
|
|
956
|
+
boundedContextOnly: true,
|
|
957
|
+
gbrainImportEnabled: false,
|
|
958
|
+
gbrainEmbedEnabled: false,
|
|
959
|
+
gbrainSyncEnabled: false,
|
|
960
|
+
gbrainWriteEnabled: false,
|
|
961
|
+
},
|
|
962
|
+
},
|
|
963
|
+
runtimeGates,
|
|
964
|
+
modelRoutingPlan,
|
|
965
|
+
runGraph,
|
|
966
|
+
factorySelection: {
|
|
967
|
+
schema: "zob.autonomous-factory-selection.v1",
|
|
968
|
+
queryHash: reuseScout.queryHash,
|
|
969
|
+
selectionStatus,
|
|
970
|
+
selectedFactory,
|
|
971
|
+
selectedFactorySourcePath: selectedFactory ? `.pi/factories/${selectedFactory}/factory.json` : undefined,
|
|
972
|
+
manifestAvailability,
|
|
973
|
+
candidateCount: candidates.length,
|
|
974
|
+
reuseScoutCandidates: candidates.filter(isRecord).map((candidate) => ({
|
|
975
|
+
kind: candidate.kind,
|
|
976
|
+
id: candidate.id,
|
|
977
|
+
sourcePath: candidate.sourcePath,
|
|
978
|
+
score: candidate.score,
|
|
979
|
+
reasonCodes: candidate.reasonCodes,
|
|
980
|
+
summaryHash: candidate.summaryHash,
|
|
981
|
+
})),
|
|
982
|
+
deterministicScoring: factoryScore,
|
|
983
|
+
factoryForgeAvailable,
|
|
984
|
+
factoryReadiness,
|
|
985
|
+
currentSourceProofRequired: true,
|
|
986
|
+
proofBeforeExecutionRequired,
|
|
987
|
+
noAutoActivation: true,
|
|
988
|
+
quarantineRequiredForNewFactory: selectionStatus === "factory_forge_quarantine_recommended",
|
|
989
|
+
},
|
|
990
|
+
proofPlan: {
|
|
991
|
+
schema: "zob.autonomous-proof-plan.v1",
|
|
992
|
+
parentOwned: true,
|
|
993
|
+
stages: [
|
|
994
|
+
{ name: "spec_lock", required: true, passed: specLocked },
|
|
995
|
+
{ name: "launch_authorization", required: true, passed: launchAuthorization.launchAuthorizesInScopeActions, executionBlockedUntilLaunch: launchAuthorization.actionExecutionBlockedUntilLaunch, dispatchAllowed: false, noExecution: true },
|
|
996
|
+
{ name: "context_scope", required: true, passed: contextScopeErrors.length === 0, citationRequired: true },
|
|
997
|
+
{ name: "context_lookup_and_pack", required: true, passed: contextPackValid, citationRequired: true, boundedContextOnly: true, dispatchAllowed: false },
|
|
998
|
+
{ name: "runtime_gates_preflight", required: true, passed: runtimeGatesValid, dispatchAllowed: false, noExecution: true },
|
|
999
|
+
{ name: "model_routing_plan", required: true, passed: modelRoutingPlanValid, dispatchAllowed: false, liveRoutingEnabled: false },
|
|
1000
|
+
{ name: "factory_selection", required: true, passed: Boolean(selectedFactory) },
|
|
1001
|
+
{ name: "registered_factory_current_source_proof", required: true, passed: factoryReadiness.registeredBatchReady === true, dispatchAllowed: false, proofBeforeExecutionRequired },
|
|
1002
|
+
{ name: "smoke", required: true, dispatchAllowed: false, sentinelRequired: "SMOKE_PASSED.sentinel" },
|
|
1003
|
+
{ name: "smoke_oracle", required: true, dispatchAllowed: false, verdictRequired: "PASS", noShipRequired: false },
|
|
1004
|
+
{ name: "pilot", required: true, dispatchAllowed: false, requiresSmokeOracle: true, sentinelRequired: "PILOT_PASSED.sentinel" },
|
|
1005
|
+
{ name: "pilot_oracle", required: true, dispatchAllowed: false, verdictRequired: "PASS", noShipRequired: false },
|
|
1006
|
+
{ name: "batch", required: true, dispatchAllowed: false, requiresPilotOracle: true, sentinelRequired: "BATCH_PASSED.sentinel", batchConcurrencyCapRequired: true },
|
|
1007
|
+
{ name: "final_report", required: true, dispatchAllowed: false, validationJsonRequired: true, doneSentinelRequired: true },
|
|
1008
|
+
],
|
|
1009
|
+
gates: ["strict_goal_spec", "context_scope", "context_lookup_and_pack", "runtime_gates_preflight", "model_routing_plan", "run_graph_ready", "registered_factory_current_source_proof", "budget_preflight", "model_routing_policy", "sandbox_apply_policy", "daemon_policy", "oracle_review", "mission_control_proposals_only"],
|
|
1010
|
+
noShipConditions: ["clarification_required", "context_scope_invalid", "context_pack_invalid", "runtime_gates_invalid", "model_routing_plan_invalid", "factory_selection_missing", "oracle_fail", "budget_exceeded", "secret_reference", "production_apply_requested", "current_source_proof_missing"],
|
|
1011
|
+
},
|
|
1012
|
+
finalReportPlan: {
|
|
1013
|
+
schema: "zob.autonomous-final-report-plan.v1",
|
|
1014
|
+
artifactPath: `reports/autonomous-runs/${runId}/dry-run-report.json`,
|
|
1015
|
+
includesEvidenceRefs: true,
|
|
1016
|
+
includesBlockers: true,
|
|
1017
|
+
includesNoShipDecision: true,
|
|
1018
|
+
rawSpecStored: false,
|
|
1019
|
+
},
|
|
1020
|
+
validation: {
|
|
1021
|
+
passed: blockers.length === 0,
|
|
1022
|
+
blockers,
|
|
1023
|
+
warnings: ["dry_run_only", "global_autonomy_no_ship", "no_child_dispatch", ...(proofBeforeExecutionRequired ? ["selected_factory_current_source_proof_required_before_execution"] : [])],
|
|
1024
|
+
},
|
|
1025
|
+
generatedAt: new Date().toISOString(),
|
|
1026
|
+
};
|
|
1027
|
+
if (hasForbiddenBodyKeys(report)) throw new Error("autonomous dry-run report would store forbidden plaintext body keys");
|
|
1028
|
+
return report;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
export function buildAutonomousRuntimeDryRunValidation(report: Record<string, unknown>): Record<string, unknown> {
|
|
1032
|
+
const validation = {
|
|
1033
|
+
schema: "zob.autonomous-runtime-dry-run-validation.v1",
|
|
1034
|
+
runId: report.runId,
|
|
1035
|
+
status: report.status,
|
|
1036
|
+
passed: report.status === "dry_run_plan_ready",
|
|
1037
|
+
no_ship: report.no_ship,
|
|
1038
|
+
dryRun: report.dryRun,
|
|
1039
|
+
noExecution: report.noExecution,
|
|
1040
|
+
childDispatchAllowed: report.childDispatchAllowed,
|
|
1041
|
+
daemonStarted: report.daemonStarted,
|
|
1042
|
+
productionWritesPerformed: report.productionWritesPerformed,
|
|
1043
|
+
autoApply: report.autoApply,
|
|
1044
|
+
networkAccessed: report.networkAccessed,
|
|
1045
|
+
globalAutonomyReady: report.globalAutonomyReady,
|
|
1046
|
+
globalAutonomyNoShip: report.globalAutonomyNoShip,
|
|
1047
|
+
blockers: isRecord(report.validation) && Array.isArray(report.validation.blockers) ? report.validation.blockers : [],
|
|
1048
|
+
requiredArtifacts: ["spec-gate.json", "context-scope.json", "context-lookup.json", "context-pack.json", "runtime-gates.json", "model-routing-plan.json", "run-graph.json", "factory-selection.json", "proof-plan.json", "dry-run-report.json", "validation.json", "final-report.md", "DRY_RUN_READY.sentinel"],
|
|
1049
|
+
sentinel: report.status === "dry_run_plan_ready" ? "DRY_RUN_READY.sentinel" : undefined,
|
|
1050
|
+
bodyStored: false,
|
|
1051
|
+
promptBodiesStored: false,
|
|
1052
|
+
outputBodiesStored: false,
|
|
1053
|
+
generatedAt: new Date().toISOString(),
|
|
1054
|
+
};
|
|
1055
|
+
if (hasForbiddenBodyKeys(validation)) throw new Error("autonomous dry-run validation would store forbidden plaintext body keys");
|
|
1056
|
+
return validation;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
export function buildAutonomousRuntimeDryRunFinalReport(report: Record<string, unknown>): string {
|
|
1060
|
+
const factorySelection = isRecord(report.factorySelection) ? report.factorySelection : {};
|
|
1061
|
+
const validation = isRecord(report.validation) ? report.validation : {};
|
|
1062
|
+
const blockers = Array.isArray(validation.blockers) ? validation.blockers.map((blocker) => `- ${String(blocker)}`).join("\n") : "";
|
|
1063
|
+
return [
|
|
1064
|
+
"# Autonomous Runtime Dry-Run Report",
|
|
1065
|
+
"",
|
|
1066
|
+
`Run ID: ${String(report.runId ?? "unknown")}`,
|
|
1067
|
+
`Status: ${String(report.status ?? "unknown")}`,
|
|
1068
|
+
`No-ship: ${String(report.no_ship ?? true)}`,
|
|
1069
|
+
"",
|
|
1070
|
+
"## Safety posture",
|
|
1071
|
+
"",
|
|
1072
|
+
`- Dry-run only: ${String(report.dryRun === true)}`,
|
|
1073
|
+
`- No execution: ${String(report.noExecution === true)}`,
|
|
1074
|
+
`- Child dispatch allowed: ${String(report.childDispatchAllowed === true)}`,
|
|
1075
|
+
`- Daemon started: ${String(report.daemonStarted === true)}`,
|
|
1076
|
+
`- Production writes performed: ${String(report.productionWritesPerformed === true)}`,
|
|
1077
|
+
`- Auto-apply: ${String(report.autoApply === true)}`,
|
|
1078
|
+
`- Global autonomy no-ship: ${String(report.globalAutonomyNoShip === true)}`,
|
|
1079
|
+
"",
|
|
1080
|
+
"## Factory selection",
|
|
1081
|
+
"",
|
|
1082
|
+
`- Status: ${String(factorySelection.selectionStatus ?? "unknown")}`,
|
|
1083
|
+
`- Selected factory: ${String(factorySelection.selectedFactory ?? "none")}`,
|
|
1084
|
+
"",
|
|
1085
|
+
"## Blockers",
|
|
1086
|
+
"",
|
|
1087
|
+
blockers || "- None for dry-run plan readiness.",
|
|
1088
|
+
"",
|
|
1089
|
+
"## Evidence refs",
|
|
1090
|
+
"",
|
|
1091
|
+
"- spec-gate.json",
|
|
1092
|
+
"- context-scope.json",
|
|
1093
|
+
"- context-lookup.json",
|
|
1094
|
+
"- context-pack.json",
|
|
1095
|
+
"- runtime-gates.json",
|
|
1096
|
+
"- model-routing-plan.json",
|
|
1097
|
+
"- run-graph.json",
|
|
1098
|
+
"- factory-selection.json",
|
|
1099
|
+
"- proof-plan.json",
|
|
1100
|
+
"- dry-run-report.json",
|
|
1101
|
+
"- validation.json",
|
|
1102
|
+
"- DRY_RUN_READY.sentinel when status=dry_run_plan_ready",
|
|
1103
|
+
"",
|
|
1104
|
+
"Compliance: P0 dry-run artifact only; no global autonomy claim.",
|
|
1105
|
+
"",
|
|
1106
|
+
].join("\n");
|
|
1107
|
+
}
|