diff --git a/release-gate/release-script.test.mjs b/release-gate/release-script.test.mjs index 3fa105b..148a3ff 100644 --- a/release-gate/release-script.test.mjs +++ b/release-gate/release-script.test.mjs @@ -55,6 +55,7 @@ test('production stable release verifies canary promotion evidence before gate c assert.ok(impactIndex > 0, 'missing risk-based impact gate fallback'); assert.doesNotMatch(source, /在同一候选完成 103 灰度验收且晋升证据校验落地前,禁止非 dry-run/); assert.match(source, /read_agent_run_status_json/); + assert.match(source, /starts\.length - 1/); assert.match(source, /obj\.queue/); assert.match(source, /for _ in \$\(seq 1 120\)/); }); diff --git a/scripts/release-portal-runtime-prod.sh b/scripts/release-portal-runtime-prod.sh index 38ea829..d887ad6 100755 --- a/scripts/release-portal-runtime-prod.sh +++ b/scripts/release-portal-runtime-prod.sh @@ -637,14 +637,28 @@ read_agent_run_status_json() { let s = ""; process.stdin.on("data", (chunk) => { s += chunk; }); process.stdin.on("end", () => { - let best = null; - for (const match of s.matchAll(/\{[\s\S]*?\}/g)) { - try { - const obj = JSON.parse(match[0]); - if (obj && typeof obj === "object" && obj.queue) best = JSON.stringify(obj); - } catch {} + const starts = []; + for (let i = 0; i < s.length; i += 1) { + if (s[i] === "{") starts.push(i); + } + for (let i = starts.length - 1; i >= 0; i -= 1) { + const start = starts[i]; + let depth = 0; + for (let j = start; j < s.length; j += 1) { + if (s[j] === "{") depth += 1; + else if (s[j] === "}") depth -= 1; + if (depth !== 0) continue; + const chunk = s.slice(start, j + 1); + try { + const obj = JSON.parse(chunk); + if (obj && typeof obj === "object" && obj.queue) { + process.stdout.write(JSON.stringify(obj)); + return; + } + } catch {} + break; + } } - if (best) process.stdout.write(best); });' || true }