@tea-agent/loop-agent 0.26.5-beta.1 → 0.26.5-beta.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.
|
@@ -398,9 +398,23 @@ export function extractFrontendImplementationJson(text) {
|
|
|
398
398
|
if (trimmed.startsWith("{") && trimmed.endsWith("}"))
|
|
399
399
|
return parse(trimmed);
|
|
400
400
|
const blocks = [...trimmed.matchAll(/```json\s*\n([\s\S]*?)\n```/gi)];
|
|
401
|
-
if (blocks.length
|
|
401
|
+
if (blocks.length === 0)
|
|
402
402
|
throw new Error("output must contain exactly one fenced json object");
|
|
403
|
-
|
|
403
|
+
const candidates = [];
|
|
404
|
+
for (const block of blocks) {
|
|
405
|
+
try {
|
|
406
|
+
const candidate = parse(block[1]);
|
|
407
|
+
if (candidate && typeof candidate === "object" && !Array.isArray(candidate))
|
|
408
|
+
candidates.push(candidate);
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
// Ignore incomplete model scratch blocks. A later complete contract
|
|
412
|
+
// block may still be deterministically recoverable.
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (candidates.length !== 1)
|
|
416
|
+
throw new Error(`output must contain exactly one valid fenced json object (found ${candidates.length})`);
|
|
417
|
+
return candidates[0];
|
|
404
418
|
}
|
|
405
419
|
/**
|
|
406
420
|
* Build the authoritative frontend-implementation-contract sourceBinding from
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { readFile, stat } from "node:fs/promises";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { isOpenspecSpecFilePath } from "../../shared/openspec-spec.js";
|
|
4
|
-
import { frontendImplementationContractSchema, materializeFrontendImplementationContract, assertFrontendSourceBindingFresh, } from "./frontend-implementation-contract.js";
|
|
5
|
+
import { frontendImplementationContractSchema, FRONTEND_IMPLEMENTATION_CONTRACT_SCHEMA_ID, materializeFrontendImplementationContract, assertFrontendSourceBindingFresh, } from "./frontend-implementation-contract.js";
|
|
5
6
|
import { captureFrontendWorktreeBaseline } from "./frontend-worktree-diff.js";
|
|
6
7
|
import { pathMatchesPattern } from "../../shared/git-progress.js";
|
|
7
8
|
async function selectNode(runDir, primary, fallbacks) {
|
|
@@ -160,13 +161,20 @@ export async function runFrontendPrewriteGate(input) {
|
|
|
160
161
|
if (missingIds.length > 0) {
|
|
161
162
|
throw new Error(`frontend prewrite gate missing requirement ids: ${missingIds.join(", ")}`);
|
|
162
163
|
}
|
|
163
|
-
const
|
|
164
|
+
const artifactPath = path.join(input.runDir, input.config.outputDir, input.config.artifactName);
|
|
165
|
+
const artifact = await stat(artifactPath)
|
|
166
|
+
.then(async () => ({
|
|
167
|
+
path: artifactPath,
|
|
168
|
+
schemaId: FRONTEND_IMPLEMENTATION_CONTRACT_SCHEMA_ID,
|
|
169
|
+
sha256: createHash("sha256").update(await readFile(artifactPath)).digest("hex"),
|
|
170
|
+
}))
|
|
171
|
+
.catch(() => materializeFrontendImplementationContract({
|
|
164
172
|
runDir: input.runDir,
|
|
165
173
|
fromNodeId: planNodeId,
|
|
166
174
|
artifactName: input.config.artifactName,
|
|
167
175
|
outputDir: input.config.outputDir,
|
|
168
176
|
sourceBinding: input.sourceBinding,
|
|
169
|
-
});
|
|
177
|
+
}));
|
|
170
178
|
const raw = JSON.parse(await readFile(artifact.path, "utf8"));
|
|
171
179
|
const contract = frontendImplementationContractSchema.parse(raw);
|
|
172
180
|
if (!input.config.allowedMockStrategies.includes(contract.mockApi.strategy)) {
|
|
@@ -2483,10 +2483,34 @@ async function buildFrontendHybridDagFromTask(sources) {
|
|
|
2483
2483
|
sourceContext,
|
|
2484
2484
|
].join("\n\n"),
|
|
2485
2485
|
},
|
|
2486
|
+
{
|
|
2487
|
+
id: "frontend-contract-json-validate-shell",
|
|
2488
|
+
depends_on: ["frontend-contract-json-pi"],
|
|
2489
|
+
role: "verifier",
|
|
2490
|
+
executor: "shell",
|
|
2491
|
+
complexity: "LOW",
|
|
2492
|
+
writePolicy: "read-only",
|
|
2493
|
+
allowedPaths: readOnlyPaths,
|
|
2494
|
+
forbiddenPaths,
|
|
2495
|
+
outputContract: "Validated frontend implementation contract artifact with schema ID and SHA-256.",
|
|
2496
|
+
subtask_prompt: "Materialize and validate the structured frontend contract before prewrite authorization.",
|
|
2497
|
+
shell: {
|
|
2498
|
+
commands: [],
|
|
2499
|
+
jsonArtifactGate: {
|
|
2500
|
+
fromNodeId: "frontend-contract-json-pi",
|
|
2501
|
+
schemaId: "frontend-implementation-contract-v1",
|
|
2502
|
+
artifactName: "frontend-implementation-contract.json",
|
|
2503
|
+
outputDir: "contracts",
|
|
2504
|
+
},
|
|
2505
|
+
cwd: ".",
|
|
2506
|
+
timeoutMs: 60000,
|
|
2507
|
+
},
|
|
2508
|
+
},
|
|
2486
2509
|
{
|
|
2487
2510
|
id: "frontend-prewrite-gate-shell",
|
|
2488
2511
|
depends_on: [
|
|
2489
2512
|
"frontend-contract-json-pi",
|
|
2513
|
+
"frontend-contract-json-validate-shell",
|
|
2490
2514
|
"frontend-final-design-review-pi",
|
|
2491
2515
|
"frontend-design-review-pi",
|
|
2492
2516
|
"frontend-plan-revision-pi",
|