From 2a40a45833ca347715819cfb46ba5c9df26547eb Mon Sep 17 00:00:00 2001 From: Dieter Baier Date: Mon, 31 Aug 2026 14:21:33 +0200 Subject: [PATCH 1/2] issue_81: Define the canonical Convergence Check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every artifact of a change is reviewed on its own — the issue at refinement, the scenario at specification, the ADR at decision, the diff at review — and nothing looks across them at the end. Drift between two individually correct artifacts is what this gate finds. A dedicated skill rather than a reference under skills/references/: that directory holds writing guides, and this is a workflow with a result that an agent has to be able to select by name. Three rules carry most of its weight: - Every question must be able to fail for this change. One that cannot is reported as not applicable, never as passed — the same defect as a scenario written green against unfixed code. - The three tiers stay separate, and an assisted finding is never reported as deterministic proof. - A waiver is a decision about proportionality; a blocker is an impossibility. Recording one as the other buries the problem in an accepted deviation. It composes rules it does not own and reads the skill that owns each one, because a second copy of a rule inside a gate is the drift the gate exists to detect. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01USXp58FoRppFK6FUht8K7u --- README.md | 4 + adapters/codex/AGENTS.md | 1 + .../rules/architecture-knowledge-toolkit.mdc | 1 + .../github-copilot/copilot-instructions.md | 1 + adapters/opencode/AGENTS.md | 1 + adapters/pi/AGENTS.md | 1 + adapters/vibe/AGENTS.md | 1 + skills/convergence-check/SKILL.md | 181 ++++++++++++++++++ 8 files changed, 191 insertions(+) create mode 100644 skills/convergence-check/SKILL.md diff --git a/README.md b/README.md index 8d1af11..0e1bac1 100644 --- a/README.md +++ b/README.md @@ -252,6 +252,10 @@ Use the skill contracts under `skills/` for focused architecture workflows: - [`skills/quality-scenario`](/skills/quality-scenario/SKILL.md) for measurable quality scenarios. - [`skills/risk`](/skills/risk/SKILL.md) for architecture risks and mitigations. - [`skills/traceability-review`](/skills/traceability-review/SKILL.md) for metadata relation reviews. +- [`skills/convergence-check`](/skills/convergence-check/SKILL.md) for the final + consistency gate: whether request, behaviour specification, architecture + knowledge, implementation, tests and delivery metadata tell one story, reported + as converged, converged with recorded waivers, not converged, or blocked. - [`skills/pr-review`](/skills/pr-review/SKILL.md) for pull request reviews, including GitHub PR comments or `.pr_comments/.pr_comments.md` fallback files. - [`skills/post-merge-sync`](/skills/post-merge-sync/SKILL.md) for returning a local checkout to the latest base branch after a pull request has been merged. diff --git a/adapters/codex/AGENTS.md b/adapters/codex/AGENTS.md index 68671fb..2e803e8 100644 --- a/adapters/codex/AGENTS.md +++ b/adapters/codex/AGENTS.md @@ -25,6 +25,7 @@ Paths are relative to the architecture-knowledge-toolkit repository root. - `clock-in`: `skills/clock-in/SKILL.md` - `clock-out`: `skills/clock-out/SKILL.md` - `commit-message`: `skills/commit-message/SKILL.md` +- `convergence-check`: `skills/convergence-check/SKILL.md` - `domain-modeling`: `skills/domain-modeling/SKILL.md` - `implement-issue-workflow`: `skills/implement-issue-workflow/SKILL.md` - `post-merge-sync`: `skills/post-merge-sync/SKILL.md` diff --git a/adapters/cursor/rules/architecture-knowledge-toolkit.mdc b/adapters/cursor/rules/architecture-knowledge-toolkit.mdc index 834a496..d2912ca 100644 --- a/adapters/cursor/rules/architecture-knowledge-toolkit.mdc +++ b/adapters/cursor/rules/architecture-knowledge-toolkit.mdc @@ -29,6 +29,7 @@ Paths are relative to the architecture-knowledge-toolkit repository root. - `clock-in`: `skills/clock-in/SKILL.md` - `clock-out`: `skills/clock-out/SKILL.md` - `commit-message`: `skills/commit-message/SKILL.md` +- `convergence-check`: `skills/convergence-check/SKILL.md` - `domain-modeling`: `skills/domain-modeling/SKILL.md` - `implement-issue-workflow`: `skills/implement-issue-workflow/SKILL.md` - `post-merge-sync`: `skills/post-merge-sync/SKILL.md` diff --git a/adapters/github-copilot/copilot-instructions.md b/adapters/github-copilot/copilot-instructions.md index b1989bc..7c9fe74 100644 --- a/adapters/github-copilot/copilot-instructions.md +++ b/adapters/github-copilot/copilot-instructions.md @@ -25,6 +25,7 @@ Paths are relative to the architecture-knowledge-toolkit repository root. - `clock-in`: `skills/clock-in/SKILL.md` - `clock-out`: `skills/clock-out/SKILL.md` - `commit-message`: `skills/commit-message/SKILL.md` +- `convergence-check`: `skills/convergence-check/SKILL.md` - `domain-modeling`: `skills/domain-modeling/SKILL.md` - `implement-issue-workflow`: `skills/implement-issue-workflow/SKILL.md` - `post-merge-sync`: `skills/post-merge-sync/SKILL.md` diff --git a/adapters/opencode/AGENTS.md b/adapters/opencode/AGENTS.md index 282e561..2d89bcd 100644 --- a/adapters/opencode/AGENTS.md +++ b/adapters/opencode/AGENTS.md @@ -25,6 +25,7 @@ Paths are relative to the architecture-knowledge-toolkit repository root. - `clock-in`: `skills/clock-in/SKILL.md` - `clock-out`: `skills/clock-out/SKILL.md` - `commit-message`: `skills/commit-message/SKILL.md` +- `convergence-check`: `skills/convergence-check/SKILL.md` - `domain-modeling`: `skills/domain-modeling/SKILL.md` - `implement-issue-workflow`: `skills/implement-issue-workflow/SKILL.md` - `post-merge-sync`: `skills/post-merge-sync/SKILL.md` diff --git a/adapters/pi/AGENTS.md b/adapters/pi/AGENTS.md index b37653a..056433b 100644 --- a/adapters/pi/AGENTS.md +++ b/adapters/pi/AGENTS.md @@ -25,6 +25,7 @@ Paths are relative to the architecture-knowledge-toolkit repository root. - `clock-in`: `skills/clock-in/SKILL.md` - `clock-out`: `skills/clock-out/SKILL.md` - `commit-message`: `skills/commit-message/SKILL.md` +- `convergence-check`: `skills/convergence-check/SKILL.md` - `domain-modeling`: `skills/domain-modeling/SKILL.md` - `implement-issue-workflow`: `skills/implement-issue-workflow/SKILL.md` - `post-merge-sync`: `skills/post-merge-sync/SKILL.md` diff --git a/adapters/vibe/AGENTS.md b/adapters/vibe/AGENTS.md index cd799cc..7dc89d2 100644 --- a/adapters/vibe/AGENTS.md +++ b/adapters/vibe/AGENTS.md @@ -25,6 +25,7 @@ Paths are relative to the architecture-knowledge-toolkit repository root. - `clock-in`: `skills/clock-in/SKILL.md` - `clock-out`: `skills/clock-out/SKILL.md` - `commit-message`: `skills/commit-message/SKILL.md` +- `convergence-check`: `skills/convergence-check/SKILL.md` - `domain-modeling`: `skills/domain-modeling/SKILL.md` - `implement-issue-workflow`: `skills/implement-issue-workflow/SKILL.md` - `post-merge-sync`: `skills/post-merge-sync/SKILL.md` diff --git a/skills/convergence-check/SKILL.md b/skills/convergence-check/SKILL.md new file mode 100644 index 0000000..5475dc6 --- /dev/null +++ b/skills/convergence-check/SKILL.md @@ -0,0 +1,181 @@ +--- +name: convergence-check +description: Check that a completed change tells one consistent story across request, behaviour specification, architecture knowledge, implementation, tests, and delivery metadata, and report converged, converged with recorded waivers, not converged, or blocked. Use before declaring a pull request mergeable, before treating an implementation issue as complete, when asked whether a change is done, or when issues, specs, architecture documentation and code may have drifted apart. +--- + +# Convergence Check + +## Purpose + +A change is finished when its artifacts agree. Each one is reviewed on its own — +the issue at refinement, the scenario at specification, the ADR at decision, the +diff at review — and nothing looks across them at the end. Drift between two +individually correct artifacts is what this check exists to find. + +It is a **gate**, not a phase. It adds no work of its own: it inspects what the +other skills already produced and reports whether it holds together. + +## What it is not + +- **Not a demand that artifacts say the same thing.** They sit at different + abstraction levels and are supposed to. An issue states intent, a scenario + states behaviour, an ADR states a decision and its cost. Convergence means no + contradiction and no missing mandatory evidence, not repetition. +- **Not a repair tool.** A failed check produces findings and follow-up actions. + It must never rewrite an accepted requirement, soften a recorded decision, or + retarget a relation in order to make the artifacts agree. Making the evidence + fit the conclusion is the failure this check is supposed to catch. +- **Not proof.** Only the deterministic tier proves anything. See + "Automation boundary". + +## When to run it + +At least once, at the end: + +- before a pull request is declared mergeable, and +- before an implementation issue is treated as complete. + +Running it earlier is fine and cheap, but an early pass is not a result: the +artifacts it inspects are not all final yet. + +## Every question must be able to fail + +Before answering a question, know what evidence would make it fail for **this** +change. A question that cannot fail here is **not applicable**, and it is +reported as such. + +Do not report a question as passed when it never had a way to fail. That is the +same defect as a scenario written to be green against unfixed code: a guard with +no failure path is worse than an absent guard, because it reads like coverage. + +## The seven questions + +### 1. Intent and scope + +- Does the implemented change still match the Epic or UserStory it came from? +- Is every scope change reflected in the issue and the specification, rather + than only in the diff? + +### 2. Behaviour + +- Is every added or changed observable behaviour described by a Gherkin + scenario, or covered by an explicit recorded waiver? +- Is each scenario mapped to at least one automated verification under the + bridge convention? +- Does any implemented edge case contradict the specification? + +`../bdd-specification/SKILL.md` owns these rules. This check asks whether they +were met; it does not restate what a scenario or a bridge must look like. + +### 3. Architecture impact + +- Were the affected boundaries, components, interfaces, dependencies, runtime + interactions, deployment elements, quality attributes, risks and constraints + assessed? +- Were only genuinely affected architecture artifacts changed? Collateral + updates to unaffected documents are a finding, not tidiness. + +`../architecture-impact/SKILL.md` owns the assessment. + +### 4. Decisions + +- Are conflicts with existing ADRs resolved rather than left implicit? +- Is every architecture-significant decision recorded as an ADR, instead of + living only in code or pull request discussion? +- Are the decisions that still need a human explicit? + +Apply the proportionality rule from `../adr/SKILL.md`: a decision that does not +warrant an ADR is not a finding, and a missing ADR for a decision that does is. + +### 5. Traceability + +- Can the path from Epic or UserStory through specification and architecture + impact to implementation, tests and pull request be followed? +- Are the authoritative outgoing relations valid, and were the derived views + regenerated? + +`../traceability-review/SKILL.md` owns relation review. + +### 6. Implementation and verification + +- Do code and configuration implement the specified behaviour and the recorded + decisions? +- Do the relevant tests, validators, generators, render checks and builds pass? +- Are unavailable checks and residual risks reported rather than omitted? + +### 7. Documentation and delivery state + +- Do the issue, the pull request, the source documentation and the code describe + the same resulting state? +- Are superseded assumptions and stale references removed, or explicitly kept + with a valid lifecycle status? +- Do deliberately deferred pieces have follow-up issues? + +## Automation boundary + +Three tiers, and they must not be presented as one. + +| Tier | What it is | Examples | +|---|---|---| +| **Deterministic** | Established from repository data; a machine decides | metamodel validation, adapter drift check, test and build results, dangling relation targets, regenerated fragments matching their source | +| **Assisted** | An assistant proposes findings a human confirms | contradiction between a scenario and an implemented edge case, an unrecorded decision, a stale reference, scope drift | +| **Human** | Only a person can decide | whether a decision is architecture-significant, whether a waiver is warranted, whether residual risk is acceptable | + +**Never report an assisted finding as deterministic proof.** State the tier with +the finding. An assistant reporting "traceability is complete" without a +deterministic check behind it is asserting something it cannot know. + +Prefer the deterministic tier wherever the rule can actually be established from +repository data — and add a deterministic check only where it can. A check that +merely looks deterministic is the same failure as a scenario that cannot fail. + +## Result + +One of four, stated explicitly: + +| Result | Meaning | +|---|---| +| **Converged** | No unresolved contradiction, no missing mandatory evidence | +| **Converged with recorded waivers** | Deviations a human explicitly accepted, each with a traceable rationale | +| **Not converged** | Contradictions, missing links, missing verification, or undocumented decisions remain | +| **Blocked** | The check needs evidence that is unavailable, or a human decision that has not been made | + +**A waiver and a blocker are different things**, and confusing them hides work. +A waiver is a human decision about **proportionality** — "this is too small to +specify". A blocker is an **impossibility** — the evidence cannot be produced, or +the question cannot be answered at this layer. No amount of human authority turns +an impossibility into a waiver; recording one as the other buries the problem in +an accepted deviation. + +Not converged and blocked are both normal outcomes. Neither is a reason to +adjust the artifacts until the result improves. + +## Findings and follow-up + +Every result that is not "converged" names concrete findings: what contradicts +what, which evidence is missing, and which tier established it. + +Each finding gets one of three dispositions, and no finding is left without one: + +- fixed in this change; +- deferred to a follow-up issue, referenced by number; +- accepted as a recorded waiver, with the rationale and who accepted it. + +"Noted" is not a disposition. + +## Reuse, don't restate + +This check composes rules it does not own. When a question needs a rule, read +the skill that owns it rather than reproducing the rule here — a second copy of +a rule in a gate is exactly the drift the gate is meant to detect. + +## Required reading + +Read the ones the change touches, not all of them: + +- `../bdd-specification/SKILL.md` — behaviour specification and the test bridge +- `../architecture-impact/SKILL.md` — what counts as architecture impact +- `../adr/SKILL.md` — decision proportionality and lifecycle +- `../traceability-review/SKILL.md` — relation validity and derived views +- `../pr-review/SKILL.md` — how findings are reported on a pull request +- `../../general-semantic-contracts.md` — the engine-agnostic baseline From 37df96d76a9ba76278c1bc86439ec3ec7134b591 Mon Sep 17 00:00:00 2001 From: Dieter Baier Date: Mon, 31 Aug 2026 14:46:22 +0200 Subject: [PATCH 2/2] issue_81: Split blocked into pending and unavailable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review on #84: the result table said blocked covers a human decision that has not been made, while the paragraph below defined a blocker as an impossibility that human authority cannot convert into a waiver. A pending decision is not an impossibility — it resolves the moment someone decides — so the two halves contradicted each other. Blocked now means the gate cannot reach a result yet, and every blocker names its kind. Pending resolves by naming who must decide or which check must run; unavailable does not resolve by waiting, and reporting it as pending sends someone to wait for something that will not arrive. That also fixes the waiver rule rather than restating it. A waiver is a legitimate outcome of a pending blocker: the person judges the deviation disproportionate and records why. It is never an outcome of an unavailable one, because what is missing there is not disproportionate — it cannot be produced. Findings gain a fourth disposition, since a blocked finding previously had none. And "not applicable" is now separated from "unavailable": the first has no bearing on the change, the second bears on it and cannot be answered here. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01USXp58FoRppFK6FUht8K7u --- skills/convergence-check/SKILL.md | 60 ++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/skills/convergence-check/SKILL.md b/skills/convergence-check/SKILL.md index 5475dc6..1515272 100644 --- a/skills/convergence-check/SKILL.md +++ b/skills/convergence-check/SKILL.md @@ -48,6 +48,12 @@ Do not report a question as passed when it never had a way to fail. That is the same defect as a scenario written to be green against unfixed code: a guard with no failure path is worse than an absent guard, because it reads like coverage. +**Not applicable is not the same as blocked.** A question is *not applicable* +when it has no bearing on this change — nothing touched the deployment view, so +there is nothing there to contradict. It is an *unavailable blocker* when it does +bear on the change but cannot be answered at this layer. The first needs no +follow-up; the second does. See "Every blocker names its kind". + ## The seven questions ### 1. Intent and scope @@ -138,30 +144,58 @@ One of four, stated explicitly: | **Converged** | No unresolved contradiction, no missing mandatory evidence | | **Converged with recorded waivers** | Deviations a human explicitly accepted, each with a traceable rationale | | **Not converged** | Contradictions, missing links, missing verification, or undocumented decisions remain | -| **Blocked** | The check needs evidence that is unavailable, or a human decision that has not been made | - -**A waiver and a blocker are different things**, and confusing them hides work. -A waiver is a human decision about **proportionality** — "this is too small to -specify". A blocker is an **impossibility** — the evidence cannot be produced, or -the question cannot be answered at this layer. No amount of human authority turns -an impossibility into a waiver; recording one as the other buries the problem in -an accepted deviation. +| **Blocked** | The gate cannot reach a result yet: required evidence or a required human decision is missing | Not converged and blocked are both normal outcomes. Neither is a reason to adjust the artifacts until the result improves. +### Every blocker names its kind + +"Blocked" alone does not say what to do next, and the two kinds need opposite +actions: + +| Kind | Meaning | What resolves it | +|---|---|---| +| **Pending** | The evidence or decision is obtainable; it does not exist yet | Name who must decide, or which check must run. Then run the gate again. | +| **Unavailable** | The evidence cannot be produced, or the question cannot be answered at this layer | A change of approach, or an explicit record of the limitation. Waiting does not help. | + +A pending blocker is temporary and resolves by itself once the person decides or +the check runs — the gate then returns converged, converged with recorded +waivers, or not converged. An unavailable blocker does not resolve by waiting, +and reporting it as pending sends someone to wait for something that will not +arrive. + +### A waiver is not a way out of a blocker + +A waiver is a human decision about **proportionality** — "this is too small to +specify". It is a legitimate outcome of a **pending** blocker: the person decides +the deviation is acceptable, records the rationale, and the gate returns +*converged with recorded waivers*. + +It is never an outcome of an **unavailable** blocker. There, the missing thing is +not disproportionate — it cannot be produced at all, and no amount of human +authority changes that. Recording an impossibility as an accepted deviation +buries the problem in a result that reads as agreement. + +If a question turned out to be unanswerable at this layer, the honest report is +the unavailable blocker plus what would answer it elsewhere — not a waiver, and +not a passed question. + ## Findings and follow-up Every result that is not "converged" names concrete findings: what contradicts what, which evidence is missing, and which tier established it. -Each finding gets one of three dispositions, and no finding is left without one: +Each finding gets one of four dispositions, and no finding is left without one: -- fixed in this change; -- deferred to a follow-up issue, referenced by number; -- accepted as a recorded waiver, with the rationale and who accepted it. +- **fixed** in this change; +- **deferred** to a follow-up issue, referenced by number; +- **accepted** as a recorded waiver, with the rationale and who accepted it; +- **blocked**, naming the kind — pending, with who must decide or which check + must run, or unavailable, with why and what would answer it elsewhere. -"Noted" is not a disposition. +"Noted" is not a disposition. Neither is "blocked" on its own: a blocker without +its kind and its named next step is an open question wearing a status. ## Reuse, don't restate