Make the os-sdlc suite pass without bundler and stop ProcessStartGuard hiding assertion failures #1669
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#1669
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
The os-sdlc cop tests depend on the directory that the suite runs from. The takedown
green-suitestep runsruby plugins/os-sdlc/test/all.rbfrom the cc-os root, and 12 cop tests fail there. From/tmp, 23 cop tests fail. Fromplugins/os-sdlc, all pass. A second fault hides the real failure: Minitest probes forgdiffwhenassert_equalfails, andProcessStartGuardraises on that probe. So each failure reads as a process-start error, not as an assertion failure.Correction (2026-11-10): the first body named RuboCop 1.92.2 and bundler as the cause. That is wrong.
lib/os_sdlc.rbsetsBUNDLE_GEMFILEand requiresbundler/setup, so every run loads RuboCop 1.90.0. The cause is the working directory.CopSource.parse(source, path)asksRuboCop::ConfigStore#for_file(path || Dir.pwd)for the Ruby version. For a path with no.rubocop.ymlabove it, RuboCop takes the version from the working directory: 4.0 fromplugins/os-sdlc/Gemfile.lock, the 3.4 of the cc-os root.rubocop.ymlfor no-path calls from the root, or the 2.7 default elsewhere. Ruby 2.7 cannot parse an endlessdef, so the AST is nil and the cop reports nothing.Observed
With Minitest's diff replaced by
inspect,process_start_outside_adapter_test.rb:162shows the real failure:EXPECTED: ["Move this process start into an adapter: ..."],ACTUAL: [].Probe from the cc-os root:
CopSource.target_version("/x/lib/acme/subject.rb")gives 2.7 (TargetRuby::Default);parse("module T\n def self.f = 1\nend\n")at 2.7 givesvalid=false,ast=nil,unexpected token tEQL. Fromplugins/os-sdlcit gives 4.0 (TargetRuby::BundlerLockFile) and a valid AST.Failing from the cc-os root:
AdapterBuiltOutsideEntryTest(5),ProcessStartOutsideAdapterTest(7). Also failing from/tmp:DomainEffectInEdge,PrecedenceInEdge,RepeatedPathLiteral(8),RequireInsideCode.Reproduce
Approach
A cop test states the Ruby version of its fixture source. It does not take the version from the working directory.
CopSource.parsegets the same optionalversionargument thatCopSource.from_filealready has. The test support passes one fixed version, read once from the plugin's own config. A tmpdir fixture that models a project on disk declares its Ruby version in its own.rubocop.yml, as a real linted project does. Minitest's external diff is turned off, so a failedassert_equalprintsExpected:/Actual:withinspectand starts no process.ProcessStartGuardstays strict (ruling 88).Required work:
CopSource.parsetakes an optional thirdversionargument that defaults totarget_version(path)— check: presentdef self.parse(source, path = nil, version = target_version(path))inplugins/os-sdlc/lib/os_sdlc/cops/structural/cop_source.rbCopHelpersholds the fixed fixture version and passes it fromoffenses_forandautocorrected_source_for— check: presentCopSource.target_version(SOURCE_PATH)inplugins/os-sdlc/test/support/cop_helpers.rbtest/support/rescue_source.rband every directCopSource.parsecall intest/pass the fixed version:reach_through_chain_test.rb:174,rescue_site_test.rb:145,detector/recording_cop_test.rb:18,unlayered_constant_test.rb:83,inward_dependency_test.rb:255,feature_envy_test.rb:162,instance_variable_assumption_test.rb:333,primitive_obsessed_ivar_test.rb:135,require_relative_density_test.rb:74,unused_private_method_test.rb:208,unreachable_branch_after_guard_test.rb:265. Leavecop_source_test.rbcalls as they are; they test the default.CopSource.from_filewrites.rubocop.ymlwithAllCops: TargetRubyVersion: 3.4in its project root:adapter_built_outside_entry_test.rbsetup, andunused_private_method_test.rb:147-151if its fixtures fail from/tmp— check: presentTargetRubyVersioninplugins/os-sdlc/test/cops/adapter_built_outside_entry_test.rbtest/test_helper.rbsetsMinitest::Assertions.diff = nilafterrequire "minitest/autorun". This is a permitted comment site: one line may say that it stops Minitest from startingdiff/gdiff(ruling 88). — check: presentMinitest::Assertions.diff = nilinplugins/os-sdlc/test/test_helper.rbRejected: run the suite under
bundle execorcdinto the plugin in.sdlc/project.yaml— bundler is already active throughlib/os_sdlc.rb, and acdhides the fault; the cops lint other projects from other directories.Rejected: let
ProcessStartGuardallowdiff/gdiff— Minitest then runsdiff -uthrough backticks, a real process start (ruling 88).Rejected: fix
CopSource.from_filein production to use the running cop's config — open ticket #1226 owns that fault.Acceptance criteria
ruby plugins/os-sdlc/test/all.rbruns from/home/jared/dev/cc-os, then it reports 0 failures and 0 errors.ruby /home/jared/dev/cc-os/plugins/os-sdlc/test/all.rbruns from/tmp, then it reports 0 failures and 0 errors.bundle exec ruby -Itest test/all.rbruns inplugins/os-sdlc, then it reports 0 failures and 0 errors.defand a path with no.rubocop.ymlabove it, whenCopSource.parse(source, path, 3.4)runs, then the processed source is valid and has an AST.assert_equalfails, when the suite reports it, then the message showsExpected:andActual:with both values, and noProcessStartGuard::ProcessStartederror appears.system("true"), when it runs, thenProcessStartGuard::ProcessStartedis raised and no process starts.Owner sketch
Non-goals
CopSource.from_fileandtarget_versionin production still use a freshConfigStoreand the working directory. #1226 owns that..sdlc/project.yaml:27does not change.Origin
takedown-run --live 1668, step19-green-suite.rubocop.ymlabove them, so RuboCop picks Ruby 2.7 from the working directory and endlessdefdoes not parse (DESIGN:plugins/os-sdlc/lib/os_sdlc/cops/structural/cop_source.rb:12,test/support/cop_helpers.rb:7); and: real failure hidden ← Minitestdiffprobesgdiff←ProcessStartGuardraises (DESIGN:plugins/os-sdlc/test/test_helper.rb:48)plugins/os-sdlc/lib/os_sdlc/cops/structural/cop_source.rb;plugins/os-sdlc/test/support/cop_helpers.rb;plugins/os-sdlc/test/test_helper.rbVERDICT: CREATE (ticket-skeptic, 2026-11-10): no open ticket has the same mechanism and fault.
Follow-up dropped by ticket-skeptic: the production version risk in CopSource.from_file/target_version is a depth-1 follow-up of this AI-created ticket, and open #1226 already covers it. #1669 fixes only the test fixtures and the Minitest diff probe.
Occurrence: A failed assert_equal shows a process-guard error, because Minitest starts gdiff to print the difference
Seen: plugins/os-sdlc/test/test_helper.rb
Run: Session 720a7477-bb8e-4373-8d74-6bbdb56f0200 (#1665, branch ticket-1665)
Adds: two agents hit it on 2026-11-10. One read the guard error as a production defect (it reported that Boot::Inputs.collaborator_pass starts gdiff, which is false). The other changed its assertions to compare two fields in place of two full payloads.
Work started on branch ticket-1669 (os-sdlc implement pipeline, map poodr-ticket-implementation).
Resolution
Done: CopSource.parse takes an optional version argument (default unchanged). Cop test support and every direct CopSource.parse call in test/ pass a fixed version read from the plugin config; the adapter_built_outside_entry tmpdir fixture declares TargetRubyVersion in its own .rubocop.yml. test_helper sets Minitest::Assertions.diff = nil, so a failed assert_equal prints Expected/Actual and starts no process; ProcessStartGuard stays strict.
Evidence: Implementation 268, commit
879905543on ticket-1669. Suite 3894 runs, 0 failures, 0 errors from the cc-os root, from /tmp, and under bundle exec in plugins/os-sdlc. Gates: required-work, suite, survivors, behavior-verifier, contract-auditor all pass.Follow-ups: CopSource.from_file production version choice: existing #1226 (evidence added 2026-11-10). Rerun /os-sdlc:ticket-takedown 1668, which this unblocks: tracked on #1668.