fix(scope): allow the co-located test sibling of an in-scope source#59
Conversation
Found by a discovery eval sweep: 2 of 4 multi-file seeds (query, checkout) dead-stalled to the cycle cap on test-sibling-required. Root cause is a harness contradiction — the gate DEMANDS the model add a co-located test (e.g. lexer.test.ts) for a logic file it changed, but the editable scope lists only the sources (lexer.ts, parser.ts, ...), so writable() REJECTED the very file the rule required. Unsatisfiable → guaranteed thrash. (Single-file seeds escaped it: their one acceptance test is provided, satisfying the sibling.) Fix: writable() now also allows a *.test/*.spec sibling whose underlying source is in scope (co-located). isInScope stays literal; only writable widens. Can't write a test for an out-of-scope source. Tests added.
There was a problem hiding this comment.
Code Review
This pull request updates the writable function to implicitly allow writing to co-located test files (e.g., *.test.* or *.spec.*) of in-scope source files, preventing potential deadlocks. The review feedback highlights a gap where a .tsx or .jsx source file is in scope but its test file uses a .ts or .js extension, and suggests handling this case along with adding a corresponding test.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
…ni review) A .tsx/.jsx source is commonly tested by a plain .test.ts. Match the test's STEM against source extensions (ts/tsx/mts/cts/js/jsx/mjs/cjs) rather than keeping the test file's own extension, so Component.test.ts is allowed when Component.tsx is in scope. Test added.
There was a problem hiding this comment.
Pull request overview
This PR resolves a harness contradiction where test-sibling-required can demand creation of a co-located test file that the editable scope previously forbade, causing unsatisfiable tasks and model stalls. It updates the scope write-check to implicitly allow *.test.* / *.spec.* siblings when (and only when) the underlying source stem is in scope, and adds regression tests for the behavior.
Changes:
- Extend
writable()to allow co-located*.test.*/*.spec.*siblings when a corresponding in-scope source file exists. - Add a regression test covering co-located test sibling allowance and ensuring
isInScopestays literal.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| packages/core/src/lib/scope/scope.ts | Implements the “test sibling of in-scope source is writable” allowance in writable() via a testStem() + source-extension check. |
| packages/core/tests/scope.test.ts | Adds regression coverage proving co-located test siblings become writable while isInScope remains unchanged. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…eview) The loose [cm]?[jt]sx? also matched non-existent extensions (.mjsx/.mtsx), widening the writable set (lexer.test.mjsx accepted when lexer.ts in scope). Pin to the real test-file extensions: ts/tsx/js/jsx + [cm]ts/[cm]js. Tests for both the rejected bogus extensions and the valid module variants.
Found by a discovery eval sweep (running evals to surface real friction, per the established loop). A 4-seed edit-heavy sweep against the local cluster blocked 2 of 4 (
query,checkout) — both dead-stalled to the cycle cap ontest-sibling-required.Root cause: an unsatisfiable harness contradiction
test-sibling-requireddemands the model add a co-located test (e.g.lexer.test.ts) for any logic file it changed.files: lexer.ts, parser.ts, executor.ts, query.ts), andwritable()does literal/glob matching — sowritable("lexer.test.ts", scope)returnedfalse.Confirmed directly:
checkouthit the identical wall onpricing.test.ts. Single-file seeds (slugify) escaped it because their one acceptance test is provided, satisfying the sibling.Fix
writable()now also allows a*.test.*/*.spec.*sibling whose underlying source is in scope (co-located):lexer.test.tsis writable ifflexer.tsis.isInScopestays literal (unchanged) — the allowance lives only inwritable().pricing.test.ts,evil.test.tsstill rejected).Tests
scope: co-located siblings of in-scope sources are writable; out-of-scope-source tests are not; the source itself stays writable;isInScopestays literal.bun run validategreen (1832 tests).Note
The model also thrashed sub-optimally (kept editing
lexer.tsinstead of creating the test), but the scope contradiction is the root enabling condition — with it fixed, the gate's instruction ("Addlexer.test.ts") is now actually followable. Mirroredtests/paths (the rule's secondary option) are a possible follow-up; co-located is what the rule suggests first and what unblocks the observed stalls.