Sdlc/Minitest/TautologicalAssertion: resolve last lvar assignment and carve out determinism pins #1357
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#1357
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
Rewritten 2026-10-27 from docs/lint-lessons/analyses/sdlc-minitest-tautological-assertion.md.
Sdlc/Minitest/TautologicalAssertionresolves a variable to its first assignment, sofirst = C.new.next; first = 5; assert_equal first, C.new.nextis flagged andfirst = 5; first = C.new.next; ...is missed. The message tells the author of a determinism test to pin one output, which deletes the property the test states. The earlier carve-out (skip identicalX.new(args)calls) would stop the cop from firing on its own must-fire fixtureSubject.new(same_args), because a determinism pin and that fixture are the same shape.Approach
Required work:
plugins/os-sdlc/lib/os_sdlc/cops/minitest/tautological_assertion/same_subject_calls.rb, resolve the variable to the last assignment that ends before the assertion — check: absenteach_descendant(:lvasgn)&.findinplugins/os-sdlc/lib/os_sdlc/cops/minitest/tautological_assertion/same_subject_calls.rbrefute_equalof the same method on constructions with different receiver source — check: presentrefute_equalinplugins/os-sdlc/lib/os_sdlc/cops/minitest/tautological_assertion/*.rbrefute_equalwith a different input — check: presentrefute_equalinplugins/os-sdlc/lib/os_sdlc/cops/minitest/tautological_assertion.rbplugins/os-sdlc/tests/cops/tautological_assertion_test.rb: must-fire for a late assignment to the call and for a pin alone; must-pass for a reassigned variable and for a pin plus a sensitivity assertion.Acceptance criteria
first = C.new.next; first = 5; assert_equal first, C.new.next, when the cop runs, then it reports no offense.first = 5; first = C.new.next; assert_equal first, C.new.next, when the cop runs, then it reports one offense.assert_equal S.new(seed: 1).call, S.new(seed: 1).callalone, when the cop runs, then it reports one offense whose message namesrefute_equal.refute_equal S.new(seed: 1).call, S.new(seed: 2).callin the same method, when the cop runs, then it reports no offense.Subject.new(same_args)fixture, when the cop runs, then it still reports one offense.Owner sketch
Origin
same_subject_calls.rb:55)Skeptic DROP (depth-1): proposal to enable stock Lint/UselessAssignment (disabled by DisabledByDefault; 4 unclassified hits in plugins/os-sdlc/tests). Revisit if a hit proves a real defect. Draft: docs/lint-lessons/analyses/sdlc-minitest-tautological-assertion.md question (b).
Body rewritten 2026-10-27 from the false-positive process; analysis and lint lesson merged to main (docs/lint-lessons/analyses/, plugins/os-sdlc/lint-lessons/).
Work started on branch ticket-1357 (os-sdlc implement pipeline).
Resolution
Done: TautologicalAssertion resolves a local variable to the last assignment before the assertion; a determinism pin is not reported when the same method has refute_equal of that method on constructions with different source; the message names refute_equal; nil guard for assertions outside a def; lesson signal names the carve-out. Merged
49e185f1, pushed.Evidence: plugins/os-sdlc/tests/cops/tautological_assertion_test.rb 13 runs green (AC1-5 plus same-input refute_equal still fires and block-form fires); ruby plugins/os-sdlc/tests/all.rb 2817 runs 0 failures 69.0s; rubocop clean on changed files; cop sweep over plugins/ 0 hits before and after.
Follow-ups: Pipeline session collision (implementation 200 abandoned by concurrent 201) captured via os-backlog:capture.
Follow-up: the pipeline session collision is recorded as an occurrence on #1447.