From 394a93a7e04ad95aa75ea252c5e38613e667b3fe Mon Sep 17 00:00:00 2001 From: Lex Date: Mon, 17 Aug 2026 08:50:49 +0800 Subject: [PATCH 1/3] feat(routes): add ultra-flow and release cross-domain routes (issue #11) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six-block ultra-flow (exploration → design → development → acceptance → release → summary) with five graded checkpoints: three light direction verdicts (continue/replan) and two independent-evidence trios at the design→development and acceptance→release boundaries. Release route assembles mechanism probe, version derivation, default-hold human gate, publish, and verification. Domains stay at 7×(full+lite); README documents the new route class. --- README.md | 12 +- release-route.yaml | 96 +++++++++++++++ ultra-flow-route.yaml | 270 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 release-route.yaml create mode 100644 ultra-flow-route.yaml diff --git a/README.md b/README.md index b8931c3..aa7d2ee 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ opencode DAG 编排的参考模板配置仓库(唯一权威源)。 仓库只保留 7 个领域,每个领域恰好一份 `full` 和一份 `lite`: | 领域 | 完整参考 | 轻量参考 | -| ---------------- | ------------------------------- | ------------------------------- | +| --------------- | ------------------------------- | ------------------------------- | | 产品文档与规划 | `product-planning-full.yaml` | `product-planning-lite.yaml` | | 技术与架构设计 | `technical-design-full.yaml` | `technical-design-lite.yaml` | | 项目开发交付 | `project-development-full.yaml` | `project-development-lite.yaml` | @@ -19,6 +19,16 @@ opencode DAG 编排的参考模板配置仓库(唯一权威源)。 | 漏洞与供应链安全 | `security-audit-full.yaml` | `security-audit-lite.yaml` | | 性能与资源审计 | `performance-audit-full.yaml` | `performance-audit-lite.yaml` | +## 跨域路线 + +跨域路线不占领域槽位(7 域 one full + one lite 的定策不变),是跨多个领域的 +预拼装拓扑: + +| 路线 | 用途 | +| --------------------- | ---------------------------------------------------------------------------- | +| `ultra-flow-route.yaml` | 六积木(探索 → 设计 → 开发 → 验收 → 发布 → 汇总)+ 五道分级检查点(轻量方向判定 ×3、独立取证三件套 ×2)。检查点 verdict 为 `continue`/`replan`:continue 不扰流程,replan 唤醒父会话做 additive 重规划(findings 注入、回环 ≤3)。发布积木可由父对话在重定向时删除 | +| `release-route.yaml` | 发布装配:机制探测 → 版本推导(latest tag + commit 类型)→ 人工门(默认 hold,父会话注入确认后才 publish)→ 发布执行 → 验证 | + ## 积木式路线 新路线用 `config.objective + config.blocks` 组合以下原语: diff --git a/release-route.yaml b/release-route.yaml new file mode 100644 index 0000000..452bea9 --- /dev/null +++ b/release-route.yaml @@ -0,0 +1,96 @@ +# Cross-domain route (not one of the 7 domain pairs): release assembly after +# the final ordered merge. Default is a human gate — release-execute only runs +# after the parent confirms the release brief. The parent retargets the +# objective to the real plan and repository before start. +title: "Release assembly: mechanism probe → version derivation → human gate → publish → verify" +config: + name: release-route + max_concurrency: 2 + max_node_replan_attempts: 3 + max_total_nodes: 10 + node_defaults: + worker_config: + timeout_ms: 900000 + nodes: + - id: release-map + name: "probe release mechanics" + worker_type: explore + depends_on: [] + prompt_template: + inline: >- + Probe the release mechanics of this repository: the workflow objective. + Identify the release pathway (release workflow dispatch vs platform + release creation vs package publish), the latest tag, branch + protection or ruleset constraints on releasing, and what the merge + history since the last tag contains. Report facts only. + + - id: release-plan + name: "derive version and draft changelog" + worker_type: plan + depends_on: [release-map] + prompt_template: + inline: >- + From the release-map evidence, derive the candidate version (latest + tag plus landed commit types: feat → minor, fix → patch, breaking → + major) and draft the changelog grouped by type. Produce the complete + release brief: mechanism, version, changelog, publish steps, and + rollback path. Flag every assumption. + + - id: release-gate + name: "release human gate brief" + worker_type: general + depends_on: [release-plan] + report_to_parent: true + required: true + worker_config: + timeout_ms: 600000 + output_schema: + type: object + properties: + verdict: + type: string + enum: [proceed, hold] + brief: + type: string + required: [verdict, brief] + prompt_template: + inline: >- + Release gate. Consolidate the release-plan brief for human + confirmation: mechanism, candidate version, changelog draft, and the + exact publish command sequence. Default verdict hold — publishing is + irreversible and the parent must obtain the human decision; submit + proceed ONLY when the parent has injected an explicit confirmation. + + - id: release-execute + name: "publish the release" + worker_type: general + depends_on: [release-gate] + prompt_template: + inline: >- + Execute the confirmed release exactly as briefed: create the tag, + write the changelog entry or release notes, and trigger the detected + release pathway. Record every command and its output; do not + improvise steps beyond the brief. + + - id: release-verify + name: "verify the release landed" + worker_type: verify + depends_on: [release-execute] + prompt_template: + inline: >- + Verify the release exists and matches the brief: the tag or release + asset is visible on the platform, the version string is exact, and + any release workflow run completed successfully. Cite the observed + evidence; PASS only on exact match. + + - id: release-report + name: "release report" + worker_type: general + depends_on: [release-verify] + prompt_template: + inline: >- + Report the release outcome: mechanism used, published version, + verification evidence, and rollback path. Write the complete report + to a non-empty markdown file under the project + .opencode/workflow-reports/ directory, then submit ONLY that + absolute file path as your output. diff --git a/ultra-flow-route.yaml b/ultra-flow-route.yaml new file mode 100644 index 0000000..a61c116 --- /dev/null +++ b/ultra-flow-route.yaml @@ -0,0 +1,270 @@ +# Cross-domain route (not one of the 7 domain pairs). The parent retargets +# every stage to the real task, removes stage-release when the project has no +# release mechanics, and starts the graph. Checkpoints are direction gates: +# verdict continue lets the flow run on untouched; verdict replan wakes the +# parent, which adds correction nodes (findings as input, max 3 back-edges, +# one decision point after the third). +title: "Ultra flow: exploration → design → development → acceptance → release → summary with checkpoints" +config: + name: ultra-flow-route + max_concurrency: 4 + max_node_replan_attempts: 3 + max_total_nodes: 26 + node_defaults: + worker_config: + timeout_ms: 1800000 + nodes: + - id: stage-exploration + name: "stage 1: product exploration" + worker_type: explore + depends_on: [] + prompt_template: + inline: >- + Explore the product side of this objective: the workflow objective. Establish + the user, the job, current workarounds, pain, frequency, stakes, and + the desired outcome. Separate observed facts from assumptions. Grill + every materially ambiguous point into a sharp answer with an + auto-formed recommendation, and end with one sharpened brief plus the + decisions that remain user-owned. + + - id: cp-after-exploration + name: "checkpoint: exploration → design direction" + worker_type: general + depends_on: [stage-exploration] + report_to_parent: true + required: true + worker_config: + timeout_ms: 600000 + output_schema: + type: object + properties: + verdict: + type: string + enum: [continue, replan] + findings: + type: string + target: + type: string + required: [verdict, findings] + prompt_template: + inline: >- + Direction checkpoint. The objective is stated in your workflow context. Read the exploration + output above. Judge ONLY whether the direction is correct and whether + a replan is needed before design begins. Verdict continue when the + brief supports proceeding; replan with findings and the stage to + re-enter as target otherwise. Submit exactly the schema. + + - id: stage-design + name: "stage 2: project design (spec + how)" + worker_type: plan + depends_on: [cp-after-exploration] + prompt_template: + inline: >- + Design stage for the workflow objective. WHAT: define the behavior contract — + observable behavior, acceptance scenarios, capability scope, suitable + as the body of exactly one platform issue (the issue IS the atom; no + X.Y task fragmentation). HOW: record a design decision only when the + change is cross-cutting, risky, or ambiguous, with alternatives + considered. Return the spec text, the design decision (or why none is + needed), and any user-owned decision that surfaced. + + - id: cp-design-standards + name: "checkpoint: design quality evidence" + worker_type: explore + depends_on: [stage-design] + prompt_template: + inline: >- + Independently assess the design stage output for the workflow objective: + completeness, testability, ambiguity, and repository convention fit. + Cite each finding precisely and separate hard defects from judgement + calls. + + - id: cp-design-intent + name: "checkpoint: design alignment evidence" + worker_type: explore + depends_on: [stage-design] + prompt_template: + inline: >- + Independently compare the design stage output with the original + objective: the workflow objective. Identify missing intent, scope creep, and + requirements that look covered but are misread. + + - id: cp-design-decision + name: "checkpoint: design → development decision" + worker_type: general + depends_on: [cp-design-standards, cp-design-intent] + report_to_parent: true + required: true + worker_config: + timeout_ms: 600000 + output_schema: + type: object + properties: + verdict: + type: string + enum: [continue, replan] + findings: + type: string + target: + type: string + required: [verdict, findings] + prompt_template: + inline: >- + Weighted design gate. Read both evidence nodes above and the design + output. Decide whether development may start for the workflow objective. + Verdict continue only when the design is faithful to intent and free + of hard defects; otherwise replan with findings and target stage. + Submit exactly the schema. + + - id: stage-development + name: "stage 3: project development" + worker_type: build + depends_on: [cp-design-decision] + prompt_template: + inline: >- + Development stage for the workflow objective. Follow the project-development + discipline retargeted by the parent: disjoint write sets, a failing + behavior check at the public seam before the smallest change that + passes it, vertical slices, and repository gates bound to the exact + HEAD fingerprint. Stop on ownership or interface drift and report it. + + - id: cp-after-development + name: "checkpoint: development → acceptance direction" + worker_type: general + depends_on: [stage-development] + report_to_parent: true + required: true + worker_config: + timeout_ms: 600000 + output_schema: + type: object + properties: + verdict: + type: string + enum: [continue, replan] + findings: + type: string + target: + type: string + required: [verdict, findings] + prompt_template: + inline: >- + Direction checkpoint. The objective is stated in your workflow context. Read the development + output above. Judge whether the implemented direction still matches + the design and objective, and whether acceptance testing may start. + Verdict continue or replan with findings and target. Submit exactly + the schema. + + - id: stage-acceptance + name: "stage 4: test and acceptance evidence" + worker_type: general + depends_on: [cp-after-development] + prompt_template: + inline: >- + Test and acceptance stage for the workflow objective. Run the documented gates + for every affected package and gather acceptance evidence: behavior + checks at public seams, CI check status from the platform, and the + difference between claimed and observed behavior. Bind every result + to the exact HEAD fingerprint and report gaps verbatim. + + - id: cp-acceptance-standards + name: "checkpoint: acceptance standards evidence" + worker_type: explore + depends_on: [stage-acceptance] + prompt_template: + inline: >- + Independently assess the acceptance evidence for the workflow objective + against repository standards and required gates: completeness of the + gate set, validity of the fingerprint binding, and any stale or + missing evidence. + + - id: cp-acceptance-intent + name: "checkpoint: acceptance alignment evidence" + worker_type: explore + depends_on: [stage-acceptance] + prompt_template: + inline: >- + Independently compare the acceptance evidence with the original + objective and the design-stage acceptance scenarios: the workflow objective. + Identify untested scenarios, weakened assertions, and behavior that + was never asked for. + + - id: cp-acceptance-decision + name: "checkpoint: acceptance → release decision" + worker_type: general + depends_on: [cp-acceptance-standards, cp-acceptance-intent] + report_to_parent: true + required: true + worker_config: + timeout_ms: 600000 + output_schema: + type: object + properties: + verdict: + type: string + enum: [continue, replan] + findings: + type: string + target: + type: string + required: [verdict, findings] + prompt_template: + inline: >- + Weighted acceptance gate for the workflow objective. Read both evidence nodes + above. Verdict continue only when CI is green, the review evidence + supports delivery, and acceptance scenarios are genuinely covered; + otherwise replan with findings and the stage to re-enter. Submit + exactly the schema. + + - id: stage-release + name: "stage 5: build and release (optional)" + worker_type: general + depends_on: [cp-acceptance-decision] + prompt_template: + inline: >- + Release stage for the workflow objective. Probe the repository's release + mechanics (release workflow vs platform release creation), the latest + tag, and the commits landed by this plan. Derive the candidate + version from tag plus commit types (feat → minor, fix → patch, + breaking → major) and draft the changelog. Do NOT publish: submit the + release brief (mechanism, version, changelog, rollback) for the + human gate. + + - id: cp-after-release + name: "checkpoint: release → summary direction" + worker_type: general + depends_on: [stage-release] + report_to_parent: true + required: true + worker_config: + timeout_ms: 600000 + output_schema: + type: object + properties: + verdict: + type: string + enum: [continue, replan] + findings: + type: string + target: + type: string + required: [verdict, findings] + prompt_template: + inline: >- + Direction checkpoint for the workflow objective. Read the release stage + output. Verdict continue when the release outcome (or its documented + skip) is consistent with the plan; replan with findings and target + otherwise. Submit exactly the schema. + + - id: stage-summary + name: "stage 6: summary" + worker_type: general + depends_on: [cp-after-release] + prompt_template: + inline: >- + Consolidated report for the workflow objective: stages executed including + skips with reasons, issue numbers, PR URLs, CI status, replan passes + used, merge position in the plan, release outcome, and any gate + waiting on the human. Write the complete report to a non-empty + markdown file under the project .opencode/workflow-reports/ + directory, then submit ONLY that absolute file path as your output. From 74e232acc58cd8114ddd4cbdbdff24702d4a41f2 Mon Sep 17 00:00:00 2001 From: Lex Date: Mon, 17 Aug 2026 09:17:34 +0800 Subject: [PATCH 2/3] fix(ci): admit declared cross-domain routes in catalog validation The validator hardcoded the 7-domain full/lite pair catalog, so the new ultra-flow-route and release-route templates failed the gate. Declare the cross-domain routes as an explicit allowlist: they keep config/name validation and join the route-name reference check, but bypass the lite topology rules, which apply to domain pairs only. --- script/validate-route-catalog.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/script/validate-route-catalog.ts b/script/validate-route-catalog.ts index d9b5cf4..7938d84 100644 --- a/script/validate-route-catalog.ts +++ b/script/validate-route-catalog.ts @@ -14,18 +14,23 @@ const domains = [ const expected = domains .flatMap((domain) => [`${domain}-full.yaml`, `${domain}-lite.yaml`]) .sort() -const routeNames = expected.map((file) => path.basename(file, ".yaml")) +// Cross-domain routes compose several domains into one topology; they are not +// domain pairs, so they bypass the lite/topology checks but still carry +// config with config.name == filename stem. +const crossDomainRoutes = ["release-route.yaml", "ultra-flow-route.yaml"] +const catalog = [...expected, ...crossDomainRoutes].sort() +const routeNames = catalog.map((file) => path.basename(file, ".yaml")) const files = (await fs.readdir(root)) .filter((file) => /\.ya?ml$/i.test(file)) .sort() -if (JSON.stringify(files) !== JSON.stringify(expected)) { - console.error(`Route catalog must contain exactly:\n${expected.join("\n")}`) +if (JSON.stringify(files) !== JSON.stringify(catalog)) { + console.error(`Route catalog must contain exactly:\n${catalog.join("\n")}`) console.error(`Found:\n${files.join("\n")}`) process.exit(1) } -for (const filename of expected) { +for (const filename of catalog) { const parsed: unknown = Bun.YAML.parse( await Bun.file(path.join(root, filename)).text(), ) @@ -38,7 +43,7 @@ for (const filename of expected) { } console.log( - `Validated ${expected.length} routes across ${domains.length} full/lite domains.`, + `Validated ${catalog.length} routes: ${domains.length} full/lite domains plus ${crossDomainRoutes.length} cross-domain routes.`, ) function isRecord(value: unknown): value is Record { From c581a1239a686a5be51f7bfc39c253af93473c52 Mon Sep 17 00:00:00 2001 From: Lex Date: Mon, 17 Aug 2026 09:19:18 +0800 Subject: [PATCH 3/3] fix(ci): include cross-domain routes in the catalog test fixture The guardrail tests copy the catalog into a temp dir before running the validator; with the cross-domain allowlist added they must seed release-route.yaml and ultra-flow-route.yaml too, or every case fails at the exact-catalog gate before reaching the behavior under test. --- script/validate-route-catalog.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/script/validate-route-catalog.test.ts b/script/validate-route-catalog.test.ts index a309e3a..2b9c1cb 100644 --- a/script/validate-route-catalog.test.ts +++ b/script/validate-route-catalog.test.ts @@ -13,6 +13,7 @@ const routes = [ "security-audit", "technical-design", ].flatMap((domain) => [`${domain}-full.yaml`, `${domain}-lite.yaml`]) +routes.push("release-route.yaml", "ultra-flow-route.yaml") let fixture: string