Skip to content

refactor(test-writing)!: drop upstream-covered checks and repair consensus - #168

Merged
Martin Bens (SpiGAndromeda) merged 15 commits into
mainfrom
refactor/test-writing-scope-and-review-pipeline
Aug 31, 2026
Merged

Martin Bens (SpiGAndromeda) merged 15 commits into
mainfrom
refactor/test-writing-scope-and-review-pipeline

Conversation

@SpiGAndromeda

@SpiGAndromeda Martin Bens (SpiGAndromeda) commented Aug 31, 2026 •

Copy link
Copy Markdown
Collaborator

Two changes to test-writing, plus a fix to the MCP argument validator every bundled server shares.

Rules and a tool that Shopware already reports

A rule that restates a check Shopware's own toolchain performs makes the reviewer a second, weaker copy of it. Whether the upstream check fails the build or only surfaces the condition makes no difference — surfacing is enough.

Removed:

Removed Reported upstream by
CONV-015 — #[Package] on a test class Danger MissingPackageAttributeInTests (missing), PHPStan TestPackageMatchRule (wrong value)
UNIT-002 — exactly one #[CoversClass] Danger SingleCoversClassInTests, PHPStan CoversAttributeRule (covers-free case)
UNIT-003's stub-typing and shopware.createMockWithoutExpectations sections PHPStan, and UNIT-004 for the uncalled-callback mechanism
assert_surviving_tests and its scanner PHPUnit's No tests found in class warning, printed under Shopware's displayDetailsOnTestsThatTriggerWarnings

The unit-review catalog goes from 46 rules to 44. UNIT-003 keeps the mocking judgement no analyser makes: prefer a real implementation, then a Shopware stub, then a mock.

The guard was a line-based PHP scanner — 1,157 lines plus 2,094 lines of tests — answering a question PHPUnit answers, and answering it wrongly on inputs a real parser handles (attribute identity by unqualified name, imports scoped per bracketed namespace, anonymous classes, one-line class declarations). Findings keep deleted_methods and removed_assertions: naming what a remediation removes is useful to a reader whether or not a tool verifies it.

Generation is a separate job from checking. The templates still emit #[Package], and now carry the /** @internal */ docblock shopware.internalClass requires on any class under a \Tests\ namespace, with import blocks ordered so ordered_imports leaves them alone. The generators derive a missing package value from the covered class, then the nearest mirrored src/ directory, and report none rather than guessing.

PROVIDER-002 now constrains the suffix and nothing else. It required a present-tense verb start and named noun and adjective starts as violations, which flags provider names trunk uses throughout (referencePriceCalculationProvider, compareDataProvider) and contradicted its own fix examples.

Team review consensus

Four defects, each of which made a review under-report or report a clean pass it had not earned.

Findings fragmented instead of pooling votes. Identity was the rule id plus the cited line rounded into a five-line bucket, so two reviewers reporting one defect a few lines apart became separate single-vote groups — and a single-vote group is contested and excluded from the report body. A finding is now rule_id|method; line position takes no part. Two costs come with it, both accepted: two distinct defects under one rule in one method merge into one record (the losing stance's summary, current and title drop, its remediation survives in suggested_variants), and the two reviewers read as two votes for the merged record.

A unit that lost its reviewers passed clean. With one live stance every finding was a 1-of-1 minority routed out of the body; with zero, the file rendered PASS. Fewer than two live stances now throws and fails the shard. Wave 1 also stopped rebuilding a reconciler for a slot whose stance was excluded — seeded with no findings of its own and invited to adopt its peers', it returned under the same reviewer label and restored the count the floor exists to catch.

Agent output overwrote the reviewer label, which is the consensus vote key, so three agents emitting one string collapsed to a single vote and turned every unanimous finding contested. REVIEWER_SCHEMA also gained status and reason, so a reviewer whose sub-skill could not finish reports that rather than an empty finding set indistinguishable from a clean file.

Informational findings raised a file's status. INTEGRATION-008's placement hint is status-neutral by contract, so one clean integration test read PASS to the reviewing skill and NEEDS_ATTENTION to the team review. Alongside: red_team.change_rate was the literal 0 and is now computed from deduped proposal and landing sets (null on an empty denominator), and the universal agent guardrail no longer orders every agent to read the test file, which contradicted digest mode on exactly the oversized classes digest mode exists for.

Shared MCP argument validation

validate_tool_arguments enforced required, additionalProperties: false and enum, and nothing else. A declared type was never read, so get_rules({"ids": 12345}) was accepted against a schema declaring "type": "string". Scalar type, pattern on string values, and array items.type/items.enum per element are now enforced, with diagnostics ordered missing → unknown → type → pattern → items → enum. The template and all three plugin copies stay byte-identical.

Breaking

  • The assert_surviving_tests MCP tool is gone from the test-rules server. A caller invoking it gets an unknown-tool error.
  • CONV-015 and UNIT-002 no longer exist. get_rules(ids=...) returns not-found for either, and reviews report no findings under those ids.

Verification

234 BATS tests passing across plugin-tests/mcp-shared/ and plugin-tests/test-writing/, claude plugin validate . passing, shellcheck -x -s bash clean across the server and its libraries, and the rule frontmatter validator clean.

CONV-015 stated the inverse of what Shopware enforces: the Danger rule MissingPackageAttributeInTests fails any pull request adding a tests/**/*Test.php file without the attribute. The rule now requires #[Package] on every test class (must-fix, review-unit class-structure, excluded from scoped reviews) and states the three-rule derivation algorithm that the generators will reference: covers-target value, else the dominant value in the mirrored src/ directory, else report rather than guess.

CONV-005 drops to should-fix and gains a category-identification precedence (error, edge, config, variation, happy path, in priority order), an exception for documented adjacency, and a known gap stating that intra-category order is undefined. CONV-017's fix example relocated construction into setUp(), which its own detection criteria exclude. The replacement relocates into the single consuming test method. CONV-017 and DESIGN-006 move to review-unit class-bodies because reference counting and coverage ratios need every test body, not a method slice.

UNIT-003's PHPUnit claims are corrected against the real types: Stub's method() returns InvocationStubber, which declares no with(), so ->with() on a createStub() double is a type error, and ->method() without expects() registers an any-invocation matcher that zero calls satisfy. The PHPStan rule shopware.createMockWithoutExpectations interaction is stated, and UNIT-004 aligns with the same hazard wording. UNIT-001, UNIT-002, and DESIGN-004 gain deletion-safety criteria (per-assertion survivor naming, no class emptied to zero tests, input-reading vs return-reading assertions kept distinct) so redundancy findings cannot silently drop non-mutation coverage. DESIGN-001, DESIGN-003, DESIGN-006, and DESIGN-010 state their scope, static-provider constraint, discriminator requirement, and composition order with DESIGN-004.

review_unit.bats pins the scoped-review exclude set to exactly seven rules and asserts the reclassified class-structure and class-bodies groupings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The generation skills produced test classes without #[Package], which Shopware's Danger rule MissingPackageAttributeInTests rejects and the repaired CONV-015 now flags as must-fix. Every class-emission block across the seven templates (five unit categories, migration, integration) and the deprecation-guards full-class example carries the Shopware\Core\Framework\Log\Package import and the attribute, and each generation SKILL.md extracts the value from the covered class or derives it per CONV-015's Package Derivation rule. Where derivation yields no value, the generator emits no attribute and records the condition in a new Package report field instead of guessing a default. The former hardcoded 'framework' fallbacks are gone.

The integration template also stops emitting #[CoversClass]. Integration tests carry none by convention, and its presence would route package derivation through the covers-target rule instead of the directory-mirroring rule the template documents.

The integration-to-unit migrating skill requires #[Package] on every migrated class, and each refactoring-pattern After example carries the value of its real source class.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Integration and migration reviews loaded only their own rule group, so the 37 cross-cutting convention, design, isolation, and provider rules declaring test-types: all never reached them. The MCP server now composes, for a given test type, that type's own group with every cross-cutting rule whose test-types includes it. get_rules and build_rule_package present the same selection under the same filters. build_rule_package gains the scope and enforce filters get_rules already had, encodes them into distinct package filenames, and a composed selection matching zero rules fails hard in both tools instead of returning a valid-looking empty catalog.

The integration, migration, and team reviewing skills load the composed catalog for their type instead of their own group alone. The migration review's output contract gains warnings and informational tiers with a NEEDS_ATTENTION status, because the composed catalog carries should-fix and consider rules that its former all-must-fix vocabulary could not express.

The audit behind composition narrowed ISOLATION-005 (mock slow operations) to test-types: unit, since INTEGRATION-001/002 and MIGRATION-001/002 mandate real collaborators for the other types. The remaining 36 cross-cutting rules keep all.

build_rule_package.bats asserts the composed per-type catalogs instead of single-group byte-identity, names the convention rules the composed migration catalog contains, and pins get_rules/build_rule_package parity under scope and enforce filters. selection_equivalence.bats covers a composed multi-group selection. config.json's instructions string names every tool the server exposes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Input resolution excluded any test file missing #[CoversClass] and failed hard when its source could not be resolved, which classified every integration test as ambiguous or dropped it, because integration tests carry no #[CoversClass] by convention. input-resolution.md now states that a missing attribute excludes no file. Unit and migration tests keep attribute-based resolution and report ambiguous when it is missing or unresolvable. An integration test mirrors its directory onto src/ (tests/integration/X/Y/ maps to src/X/Y/, walking up until the directory exists) and takes every .php file directly inside that directory as source_paths, with source_lines summed across them, reporting ambiguous only when the walk-up exhausts src/.

The integration reviewing skill identifies the SUT by the same mirroring and states the convention. INTEGRATION-002's collaborator test reads the resolved source set instead of #[CoversClass] targets and cites the phase step that defines it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ation

The team-review workflow matched findings by rule_id and a five-line location window, so two distinct defects under one rule on one method merged into one finding and borrowed each other's votes, while a withdrawal removed every finding sharing a rule_id. Every finding now receives a finding_id at ingest, composed of rule_id, the normalized method (or class-level), and an FNV-1a fingerprint of the whitespace-normalized current text (summary where current is empty). Line numbers take no part in identity, and findKey is removed. Reviewing agents never emit the id; the workflow stamps it, and every schema that refers back to an existing finding (reconciliation, red-team challenges and resurrections, defense withdrawals, re-adoptions, and maintained findings) requires it, with unresolvable references thrown rather than re-derived. Unit consensus, the file-level union, wave-0 and binding key sets, withdrawal, adoption counting, and arbitration all key on it.

A merged finding keeps every distinct remediation its stances proposed: suggested_variants deduplicates under whitespace normalization ordered longest first, suggested is the first entry, and location, summary, current, and method come from the record supplying it, with per-field fallback to the paired original only where the owning record lacks a field. Locations union in true first-seen order across units, buckets, and defenders. Promotions resolve their quoted id against kept, contested, per-file adversary maps, and an identity-complete withdrawn-originals store fed by both peer passes, merging instead of duplicating and restoring instead of refabricating. A defender's duplicate entries and maintained findings contribute their remediation payloads without extra votes, and implies_src_change ORs across every contributing stance.

The consensus reference states the identity and drops the location window, both reviewer output references carry finding_id and the variant fields, and the AGENTS.md fidelity contract states the preservation policy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A finding that deleted test methods stated nothing about what its deletion removed, and nothing checked what a file's findings left behind, so applying a review could silently empty a test class (PHPUnit reports "No tests found in class" and exits non-OK) or drop an assertion no surviving test covers. Every finding schema and record builder in the team-review workflow now carries deleted_methods (empty by default, names normalized through methodId) and removed_assertions (a list of {assertion, covered_by_test}, where covered_by_test names the surviving test or the literal "none — coverage lost"; the name avoids covered_by, which the result shape already uses for the SUT-coverage map). Both fields ride every merge the way suggested_variants does: deleted_methods unions, removed_assertions concatenates and dedupes.

The team review calls assert_surviving_tests once per file after the adversarial stage produces the final finding set (or against the consensus result when that stage is skipped), passing the union of deleted_methods across the file's kept findings. EMPTY raises a must-fix finding that applying the file's findings leaves the class with no tests, a refusal naming unmatched methods raises a must-fix finding against each finding that cited one, and UNRESOLVED is informational and accuses nothing. Guard findings merge after the adversarial stage and are not subject to its replacement.

Each of the three reviewing skills runs the same guard over its own findings before its report: EMPTY yields an error entry under UNIT-001 (the emptied class is the aggregate of that rule's deletions) and sets ISSUES_FOUND, an unmatched-method refusal yields an error entry against the citing finding, UNRESOLVED stays informational. The team-reviewing and three reviewing skills' allowed-tools and the test-reviewer agent's tools declare the new MCP tool, and every output-format reference states the two fields.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A review said nothing about whether the file's tests passed before the review, so a finding-driven fix session could inherit a failing suite and attribute the failure to the applied findings. Each of the three reviewing skills now declares baseline (pass, fail, or unavailable) among its inputs, records the supplied value, and reports it. A fail yields a top-line entry stating the file's tests were already failing independent of the rule catalog and sets ISSUES_FOUND. Unavailable is recorded and changes nothing else.

baseline is an input, not an action. No skill in the plugin executes tests, and no tool is named for obtaining the value. It defaults to unavailable when the caller does not know it. The team review carries baseline on each manifest entry in input-resolution.md, threads each file's value into its shard arguments in Phase 3, and renders it per file section in Phase 7.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The team review's report conventions carried consensus, provenance, branch scope, arbitration, and source-change status as heading suffixes, and the result shape did not carry everything the template needed. Phase 7 now renders the report from the fields the workflow emits, following the report-format template. The workflow script emits fields and renders nothing. Finding headings are exactly "#### [RULE-ID] Title" with Method, Consensus, Provenance (the finding's adversary_impact value, upper-cased with the ADVERSARY_ prefix where applicable), Branch scope (touched/untouched/n/a from branch_touched), Arbitration, Source change, and Removed assertions as fields. Multiple remediations render as numbered Suggested Fix entries, one per suggested_variants entry, and each file section states its caller-supplied baseline.

The result shape now carries per-file baseline (validated fail-hard when present and invalid, defaulting to unavailable when absent, emitted in both review and adversarial modes) plus finding_id, locations, summary, and suggested_variants. contestedView emits consensus, adversary_impact, implies_src_change, and current, so contested findings render under the same conventions, and srcChangeOf traverses contested findings so the source-change escalation list counts every rendered claim.

The three reviewing skills and their output formats pin the finding schema. current is copied verbatim from the file at review time, and suggested is the complete method body after the change, empty only where deleted_methods names the deleted method. A line present in current and absent from suggested is a removal the finding names. The skills render the field as Issue, but the team-review schema names it summary. Every example block now complies with those rules.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Nothing could state what a test class contains once a set of deletions is applied, so deletion-safety reasoning had no ground truth. The test-rules server now exposes assert_surviving_tests. Given a test_path and the deleted_methods findings remove entirely (empty array allowed), it reports total, deleted, surviving, and a status of OK, EMPTY (discovery succeeded and nothing survives), or UNRESOLVED (abstract class, a base the tool cannot establish as PHPUnit or Shopware, or trait-drawn methods, so the runnable set is not derivable from this file alone). UNRESOLVED blocks the safety calculation and accuses no finding.

A method counts as a test when it is public, non-static, non-abstract, and named test* or attributed #[Test], including as a member of a grouped attribute list. #[DataProvider] does not exclude, and provider methods are excluded for carrying no test marker. The scanner is quote-aware (// inside a string is not a comment), skips heredoc and nowdoc bodies under PHP 7.3+ closer rules, attributes methods to the class named after the file so fixture classes do not miscount, and refuses what it cannot parse, including a scan failure, a file declaring no class named after its basename, an entry naming no method in the file, or a deleted_methods entry that is not a clean PHP identifier (validated JSON-side with \A/\z anchors, since oniguruma's $ matches before a trailing newline). Output is built with jq -n -c, every failable call checks its status explicitly, and the bash floor stays 4.4.

surviving_tests.bats pins 36 cases, each first run against the state before the behavior it covers existed and observed to fail there. Three of the parser defects the review found were live in shopware/shopware test files, one of which would have raised a false EMPTY must-fix under the deletion guard.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The README moves CONV-015 to the Must-Fix table (routes a failing CI job to the owning domain team) and CONV-005 to Should-Fix, and documents the assert_surviving_tests MCP tool with its input, output, and status vocabulary. AGENTS.md lists the tool, adds lib/survival.sh to its directory tree, states the finding-identity formula in the fix-application fidelity contract, repairs the rule-discovery flow that predated composed per-type catalogs, and gains modification-guide rows for the tool, the finding identity, and the report format. plugin-tests/README.md lists surviving_tests.bats.

The CHANGELOG's 5.0.0 entry names each breaking surface: finding headings lose their status suffixes in favour of fields; the finding schema gains finding_id, deleted_methods, removed_assertions, suggested_variants, and locations; CONV-015 reverses its verdict and becomes must-fix while CONV-005 becomes should-fix; CONV-017 and DESIGN-006 move to class-bodies and leave scoped reviews; integration and migration reviews load a composed catalog; every generator emits #[Package].

plugin.json and all eleven SKILL.md frontmatters declare 5.0.0, bumped by the plugin-updating skill. Release gates ran green: claude plugin validate, validate-review-unit.sh (71 rules), and the full BATS suite (876 tests).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…flow

The surviving-test scanner gains quote-aware brace-depth tracking, so anonymous-class methods and namespace-level functions after the class no longer count as target-class tests (deleting every real test now reports EMPTY, not OK), and a quoted "class X" inside a string literal no longer truncates the scan, which had silently dropped 12 of 29 methods in a real Shopware test file. Parent recognition resolves through FQCNs and use-imports instead of short names, so a foreign Acme\TestCase yields UNRESOLVED while every one of 2755 real PHPUnit imports keeps resolving. The deleted_methods entry pattern requires a valid PHP identifier start, shape validation runs before the status branch, and UNRESOLVED payloads carry the reason the reviewing skills must render. tools.json and config.json describe all three tools and the new field.

In the team-review workflow, unionRecords ORs implies_src_change across both records, closing three union sites that silently dropped a true escalation, and the Wave-2 adversarial package carries the manifest's resolved source_path and source_paths so adversarial lenses reach integration SUT sources that have no #[CoversClass]. The report template renders a Deleted methods bullet wherever a finding deletes methods, so a deletion stance stays visible even when a competing keep-and-fix remediation wins the variant ordering.

The adversarial skill's embedded output contract and its output-format reference now match REDTEAM_SCHEMA field for field, the README's migration contract includes NEEDS_ATTENTION, and workflow-design.md, README, and AGENTS.md state the composed test_type selection instead of the pre-composition group calls.

Brace tracking applies per-line net deltas, a known accepted limitation, so a syntactically invalid line like "}} {" can slip past the unbalanced-brace refusal. The input class the guard serves is real, parseable test files, all 2771 of which scan correctly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`validate_tool_arguments` checked `required`, `additionalProperties: false` and `enum`, and nothing else. A declared `type` was never read, so `get_rules({"ids": 12345})` was accepted against a schema declaring `"type": "string"`, and any tool relying on the schema to reject a wrong-typed argument had no such guarantee. Scalar `type`, `pattern` against string values, and array `items.type`/`items.enum` per element are now enforced alongside the existing checks, with diagnostics ordered missing, unknown, type, pattern, items, enum so a value failing several constraints reports the most fundamental defect first.

The `items` constraints are read by plain field access rather than `// empty`: an `items` object declaring only one of `type`/`enum` yielded zero outputs for the absent key, and a jq `as` binding over zero outputs skips its entire body, so the constraint that was declared went unchecked.

All four copies stay byte-identical to the template, which the repository's sync check compares rather than propagates.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A rule that restates a check Shopware's toolchain already performs makes the reviewer a second, weaker copy of it. CONV-015 and UNIT-002 are removed on that basis, whether or not the upstream check fails the build. Surfacing is enough.

CONV-015 required `#[Package]` on a test class. Shopware's Danger rule `MissingPackageAttributeInTests` reports a missing attribute and its PHPStan rule `TestPackageMatchRule` reports a wrong value. UNIT-002 required exactly one `#[CoversClass]` and flagged a class carrying none. `SingleCoversClassInTests` counts the attributes above the class declaration and fails above one. `CoversAttributeRule` reports the covers-free case. UNIT-003 keeps its mocking judgement and loses the two sections PHPStan reports: the `Stub::method(): InvocationStubber` typing behind a `->with()` call on a stub, and the workaround for `shopware.createMockWithoutExpectations`. UNIT-004 already owns the uncalled-callback mechanism that section duplicated.

Generation is a separate job from checking. The templates still emit `#[Package]`, and now also carry the `/** @internal */` docblock that `shopware.internalClass` requires on any class under a `\Tests\` namespace, with the import blocks reordered so `ordered_imports` leaves them alone. Deriving the value no longer needs the rule catalog: the generators read it from the covered class, then from the nearest mirrored `src/` directory, and report `none` rather than guessing.

PROVIDER-002 now constrains the suffix and nothing else. It demanded a present-tense verb start and named noun and adjective starts as violations, which flags provider names trunk uses throughout (`referencePriceCalculationProvider`, `compareDataProvider`) and contradicted its own fix examples. Its unsourced "78% of existing Shopware data providers" rationale is deleted rather than re-sourced.

The unit-review catalog drops from 46 rules to 44. Two BATS cases used the removed rules as `review-unit` and `scoped-review` fixtures and now use CONV-007, which carries the same frontmatter.

BREAKING CHANGE: CONV-015 and UNIT-002 no longer exist. A caller passing either to `get_rules(ids=...)` gets a not-found result, and reviews no longer report findings under those ids.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`assert_surviving_tests` answered one question: after applying a review's deletions, does the class still run a test? PHPUnit answers it already, emitting `No tests found in class` as a warning that Shopware's `displayDetailsOnTestsThatTriggerWarnings` prints. Answering it a second time cost a 1,157-line line-based PHP scanner and 2,094 lines of tests for it, and the scanner was wrong on inputs a real parser handles: attribute identity by unqualified name, imports scoped per bracketed namespace, anonymous classes, one-line class declarations. The tool, its scanner, its tests, and the guard step in the four review skills are removed. Findings keep `deleted_methods` and `removed_assertions`, which say what a remediation takes out of a class and are worth reading whether or not anything verifies them.

A finding is now identified as `rule_id|method`. Identity was the rule id plus the cited line rounded into a five-line bucket, so two reviewers reporting one defect a few lines apart landed in different buckets, each became a single-vote group, and a single-vote group is contested and excluded from the report body. Line position no longer takes part. Two costs come with it: two distinct defects under one rule in one method merge into one record, with the losing stance's `summary`, `current` and `title` dropped while its remediation survives in `suggested_variants`, and the two reviewers read as two votes for the merged record.

A review unit that comes back with fewer than two live stances now throws and fails its shard. With one stance every finding is a 1-of-1 minority routed out of the body, and with zero the file rendered `PASS`. A clean verdict for a review that never happened. Wave 1 also stopped rebuilding a reconciler for a slot whose stance was excluded: seeded with no findings of its own and invited to adopt its peers', it returned under the same reviewer label and restored the count the floor exists to catch.

`REVIEWER_SCHEMA` gained `status` and `reason` so a reviewer whose sub-skill could not finish reports that instead of an empty finding set, which reads as a clean file. Agent output no longer overwrites the workflow's reviewer label, the consensus vote key: three agents emitting one string collapsed to a single vote and turned every unanimous finding contested.

Informational findings no longer raise a file's status. `INTEGRATION-008`'s placement hint is status-neutral by contract, so one clean integration test read `PASS` to the reviewing skill and `NEEDS_ATTENTION` to the team review. `red_team.change_rate` was the literal `0` and is now computed from deduped proposal and landing sets, `null` on an empty denominator. The universal agent guardrail no longer orders every agent to read the test file, which contradicted digest mode on exactly the oversized classes digest mode exists for, and the digest prompt names the route that actually put the unit on that track.

BREAKING CHANGE: the `assert_surviving_tests` MCP tool is removed from the `test-rules` server. A caller invoking it gets an unknown-tool error.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The plugin README, AGENTS.md and CHANGELOG described three MCP tools, 46 unit-review rules, and a deletion after-state guard that reviews no longer run. They now describe two tools and 44 rules, and the guard tables, tool reference, directory tree, modification guide and architecture flow lose the guard along with it. The repository README's rule count moves with them, and the test-suite listing drops the removed BATS file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

@SpiGAndromeda Martin Bens (SpiGAndromeda) changed the title Refactor/test writing scope and review pipeline refactor(test-writing)!: drop upstream-covered checks and repair consensus Aug 31, 2026
@SpiGAndromeda
Martin Bens (SpiGAndromeda) merged commit 7dc35a9 into main Aug 31, 2026
13 checks passed
@SpiGAndromeda
Martin Bens (SpiGAndromeda) deleted the refactor/test-writing-scope-and-review-pipeline branch September 3, 2026 19:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant