From 48606645c8b51b6a910aced727fa951284b95b9a Mon Sep 17 00:00:00 2001 From: Lex Date: Tue, 1 Sep 2026 23:50:41 +0800 Subject: [PATCH 1/3] chore: record delivery binding for release-route-worker --- .specgit.yaml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.specgit.yaml b/.specgit.yaml index 9c8ce01..0a43f70 100644 --- a/.specgit.yaml +++ b/.specgit.yaml @@ -1,8 +1,10 @@ version: 1 -delivery: specgit-harness +delivery: release-route-worker context: kind: branch - branch: chore/17-specgit-harness + branch: fix/22-release-route-worker issues: - - 17 -pr: 21 + - 22 +issueKinds: + - issue: 22 + kind: kind::fix From 8ce23b2c1604c53c7fcf6a24720379c7f3741531 Mon Sep 17 00:00:00 2001 From: Lex Date: Tue, 1 Sep 2026 23:50:55 +0800 Subject: [PATCH 2/3] chore: record delivery binding for release-route-worker --- .specgit.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.specgit.yaml b/.specgit.yaml index 0a43f70..33ca5e5 100644 --- a/.specgit.yaml +++ b/.specgit.yaml @@ -8,3 +8,4 @@ issues: issueKinds: - issue: 22 kind: kind::fix +pr: 23 From 29295367f6aa7214d71eb3db2ec802b6bc008621 Mon Sep 17 00:00:00 2001 From: Lex Date: Wed, 2 Sep 2026 00:08:34 +0800 Subject: [PATCH 3/3] fix: use supported worker type for release-verify release-verify pinned worker_type: verify, but the compatible runtime catalog (b48dce46) only has explore, build, plan, general; the environment gate rejected start with worker.unknown. Replace with general (what the blocks fallback compiles verify to), and close the portable-profile detection gap with a route-catalog guardrail plus a regression test. --- release-route.yaml | 2 +- script/validate-route-catalog.test.ts | 14 ++++++++++++++ script/validate-route-catalog.ts | 24 ++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/release-route.yaml b/release-route.yaml index aaea6bc..73c8a2a 100644 --- a/release-route.yaml +++ b/release-route.yaml @@ -75,7 +75,7 @@ config: - id: release-verify name: "verify the release landed" - worker_type: verify + worker_type: general depends_on: [release-execute] prompt_template: inline: >- diff --git a/script/validate-route-catalog.test.ts b/script/validate-route-catalog.test.ts index 24d1dbd..f366660 100644 --- a/script/validate-route-catalog.test.ts +++ b/script/validate-route-catalog.test.ts @@ -98,6 +98,20 @@ describe("route catalog guardrails", () => { expect(result.exitCode).toBe(1) expect(result.stderr).toContain("Route catalog must contain exactly") }) + + test("rejects a worker_type outside the compatible runtime agent catalog", async () => { + await rewrite( + "release-route.yaml", + 'name: "verify the release landed"\n worker_type: general', + 'name: "verify the release landed"\n worker_type: verify', + ) + + const result = await validate() + expect(result.exitCode).toBe(1) + expect(result.stderr).toContain( + "not in the compatible runtime agent catalog", + ) + }) }) async function rewrite(file: string, before: string, after: string) { diff --git a/script/validate-route-catalog.ts b/script/validate-route-catalog.ts index 4ad5f44..70ccbd0 100644 --- a/script/validate-route-catalog.ts +++ b/script/validate-route-catalog.ts @@ -20,6 +20,11 @@ const expected = domains const crossDomainRoutes = ["release-route.yaml", "ultra-flow-route.yaml"] const catalog = [...expected, ...crossDomainRoutes].sort() const routeNames = catalog.map((file) => path.basename(file, ".yaml")) +// The compatible runtime gate (runtime-compat.json, commit b48dce46) rejects +// any node whose worker_type is outside its builtin agent catalog +// (build, plan, general, explore); the portable profile skips the catalog when +// absent, so this check closes the gap config-side. +const compatibleWorkerTypes = ["explore", "build", "plan", "general"] const files = (await fs.readdir(root)) // Hidden dotfiles are delivery tooling (e.g. the SpecGit `.specgit.yaml` // binding), never route templates; the catalog inventory is over visible files. @@ -43,6 +48,25 @@ for (const filename of catalog) { if (parsed.config.name !== name) fail(`${filename} config.name must equal ${name}`) if (name.endsWith("-lite")) validateLiteRoute(filename, parsed.config) + validateWorkerTypes(filename, parsed.config) +} + +function validateWorkerTypes( + filename: string, + config: Record, +) { + const workers = [ + ...(Array.isArray(config.nodes) ? config.nodes : []), + ...(Array.isArray(config.blocks) ? config.blocks : []), + ].filter(isRecord) + for (const worker of workers) { + if (worker.worker_type === undefined) continue + const workerType = String(worker.worker_type) + if (compatibleWorkerTypes.includes(workerType)) continue + fail( + `${filename} node ${worker.id} worker type "${workerType}" is not in the compatible runtime agent catalog (${compatibleWorkerTypes.join(", ")})`, + ) + } } console.log(