programmer diff-test gate silently runs the full suite when any changed file is unmapped #625
Labels
No labels
P0
P1
P2
P3
bug
category/code-change
category/cross-repo
category/eval-run
category/investigation
category/no-test-target
category/owner-ruling
category/prose-artifact
category/recurring-chore
category/structure
category/umbrella
crc-refactor
create
delete
enhancement
filed-by/agent
filed-by/user
frozen
lint-rule
needs-info
needs-triage
next
plugin/cc-architect
plugin/os
plugin/os-adr
plugin/os-aidd-lint
plugin/os-backlog
plugin/os-context
plugin/os-doc-hygiene
plugin/os-sdlc
plugin/os-vault
project/cc-os
ready-for-agent
ready-for-human
recurring
review
rule-proposal
update
waiting
wayfinder:grilling
wayfinder:map
wayfinder:map
wayfinder:research
wayfinder:task
wayfinder:task
wontfix
worklist/deviations
worklist/lint-rule
worklist/new-implement-build
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
jared/cc-os#625
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
GateCommands#diff_test_commandreturns the suite command wheneverChanges#unmapped_code_pathsis non-empty, before it looks at the tests that are already in the diff. A new production file whose test-writer test has a different basename is "unmapped" by construction, so every programmer gate run on such a ticket costs a full suite run, and the gate output does not say so. Verified still present on main at599afa67(2026-09-24).Observed
Implementation 10 on #557 (session e8c75cf9): all five programmer gate runs (dispatch 125) took 118-139 s and reported 1365 runs / 3093 assertions under the step named
diff-test. That is the full suite. suite-check (dispatch 127) took 123 s for the same suite.#557 added
lib/os_sdlc/model/timestamp_stamping.rbandtests/model/implementation_complete_stamp_test.rb(commit52072ad5).Codebase#tests_forglobs only<basename>_test.rb/<basename>_*_test.rb, so the production file is unmapped even though its test was in the diff.Changes#test_paths(changes.rb:16-18) already unions changed test files with mapped tests. The unmapped guard at gate_commands.rb:27 fires first and discards that set.Reproduce
Approach
Widen to the suite only when there is nothing else to run. Otherwise run the diff's own tests and name the unmapped paths in the gate reply.
One
DiffTestPlaninstance per gate run, shared byGateCommandsandBriefFacts#append_unmapped_note(brief_facts.rb:83-90), so the brief note and the gate reply cannot disagree aboutwidened.Required work:
Pipeline::DiffTestPlan(paths, unmapped, widened?, command).GateCommands#diff_test_commanddelegates to it; the suite fallback applies only when the existing test set is empty.GateCommands#to_htoday returns only command strings, andGateHandoff#gate_commands(gate_handoff.rb:52-54) consumes that. TheDiffTestPlanmust survive toGateHandoff#record(gate_handoff.rb:70-74), whereGateReplyis built.GateReplyis a Struct with no field for it; add a keyword (e.g.diff_test_plan:) with a nil default so existingGateReply.newcall sites, including the helper intests/pipeline/gate_handoff_test.rb(~line 104), keep working.GateReply#to_hmergesdiff_test: plan.to_honly when the plan is present. This makes the diff-test step's reply carryunmappedandwidened— check:os-sdlc-runner programmer-gateoutput on a branch with an unmapped file.BriefFacts#append_unmapped_notereads the plan and states what actually ran ("unmapped code files (no mapped test; diff-test ran changed tests only)" or "... widened to the suite")./os-adr:create— widening is now conditional and always named.docs/implementation-status/os-sdlc.md.Rejected: derive a convention-named test path for the new file and run it if present —
tests_foralready does that; it did not help #557 because the test had another basename.Rejected: never widen — a
bin/orhooks/only change would then run zero tests in the programmer gate.Acceptance criteria
lib/x.rbandtests/y_test.rb(no basename match), when the programmer diff-test gate runs, then only the changed and mapped test files run, and the reply carriesdiff_test.unmapped == ["lib/x.rb"]anddiff_test.widened == false.diff_test.widened == truewith the unmapped paths.diff_test.unmapped == []anddiff_test.widened == false.test_changesfact, then the unmapped note says the diff-test ran changed tests only, not that it widened to the suite.diff_test.widened == falseanddiff_test.unmapped == [the unmapped file].Owner sketch
Non-goals
Changing
Codebase#tests_formapping rules (ADR-0210 clause 5). Making the test-writer name test files after the production basename.Blast radius
coding.yaml,poodr-implementation.yaml,poodr-ticket-implementation.yamlgate the programmer on[diff-test, lint]and need no edit.tests/support/dispatch_240_fixture.rbNAMES list is a captured fixture — do not rename existing tests in this ticket.tests/pipeline/gate_commands_project_dispatch_test.rb#test_diff_test_command_requires_the_mapped_test_filestays green.Retired tests
Origin
599afa67Work started on branch ticket-625 via /os-sdlc:implement (session 91151d77). #626 shipped first on main
481425cf.Resolution
Done: Pipeline::DiffTestPlan owns the diff-test rule: run changes.test_paths when non-empty; widen to the suite only when that set is empty and an unmapped code file exists; nil when both are empty. plan.to_h ({unmapped, widened}) is merged into the gate reply as diff_test for diff-test nodes via a nil-default GateReply field. One plan per gate run shared by GateCommands and GateHandoff. BriefFacts unmapped note words by widened?. ADR-0215 amends ADR-0202, ADR-0208, ADR-0210; status leaf row added.
Evidence: Branch ticket-625 commits
7ea704e7,8fafa566. Pipeline implementation 30 reached programmer green then escalated (bound_exhausted:programmer-repair/fail) on an unrelated red test inherited from main (#633 fork-guard allowlist, filed as #701). Hand-finished per escalation-procedure step 4: allowlist fix, AbcSize extraction, single shared plan instance, nil command for empty/empty. Full suite 1425 runs, 3271 assertions, 0 failures; rubocop clean on touched files.Follow-ups: #701 filed (fork guard ignores untracked test files, skeptic CREATE). The suite-red-from-a-test-file routing gap is already #665. Live verification of the narrowed widening happens on the next implement run.