os-sdlc tests start 792 non-git processes: add adapters with fixtures, a runtime guard, two cops, and the lint lesson #1647

Closed
opened 2026-11-09 16:08:39 +00:00 by jared · 5 comments
Owner

Problem

After the tracker change (commit 737d2e13) the os-sdlc suite still starts 792 processes that are not git. Ruling 88 and .claude/rules/ruby-external-calls.md forbid each one. No check enforces the rule, so a new test can start a process and nobody sees it until mutation testing times out.

Observed

A list run on 2026-11-09 recorded these starts: ast-grep 267 (12 test files; lib/os_sdlc/evidence/probe.rb 228, evidence/resolution/token_query.rb 100), ruby 144 (1 test file; system_model/pattern_site/example_run.rb), grep 82, ruby -e 57, ruby -rrubocop 52, true and false 68, os-backlog 39, sh -c 18. test/boot_unchanged_check_test.rb takes about 10 s because Lint::Run::Invocation runs the real lint command. That file causes 14 of the 22 mutation timeouts that remain in lib/os_sdlc/map. The other 8 mutants ran zero tests; they are a different fault.

Reproduce

n/a: structure ticket.

Approach

In this order:

  1. Put each of these calls in an adapter that the entry passes in, with a recorded fixture for tests. Do the lint command first.
  2. Add a runtime guard to test/test_helper.rb. It fails a test that starts a process by any route (Process.spawn, system, backticks, IO.popen). It has no exception list and no baseline (ruling 92, predicted).
  3. Add two cops with must-fire and must-pass fixtures: a process start in lib/ outside an adapter file; an adapter built outside the entry. Three default arguments build one today: tracker/backlog.rb:25, tracker/backlog/project_show.rb:6, crc/filing/backlog_client.rb:10.
  4. Write one lint lesson through /os-sdlc:smell-analysis on these sites. The mutation timeout guidance points to it.
  5. Delete text that conflicts with ruling 88: lens-testing T5 and T6, the CONTRACT row of lens-taxonomy-tests, and the smoke-test allowance in Sdlc/Structural/OwnEntryPointSpawnedInTest and its lesson.
  6. Remove test/support/fake_project_show_bin.rb when nothing uses it.

Acceptance criteria

  1. Given a test that starts a process, when the suite runs, then that test fails and the message names the program.
  2. Given the os-sdlc suite with the guard on, when it runs, then it is green.

Origin

  • Trigger: list run of process starts in the os-sdlc suite on 2026-11-09
  • Improvised this session: none
  • Chain: mutation timeouts ← slow covering tests ← tests start real processes ← DESIGN (no check enforces .claude/rules/ruby-external-calls.md)
  • Root candidate: none found; searched process start, no-real-process, spawn, adapter, cop, test_helper, ProcessBoundary (#637 is related but not the same fault)
  • Where: plugins/os-sdlc/test/test_helper.rb, plugins/os-sdlc/lib/os_sdlc/lint/run/invocation.rb
  • Session: 19f78576-9fa5-4fd3-9984-a9e58ef897ad
  • Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os-plugins-os-sdlc/19f78576-9fa5-4fd3-9984-a9e58ef897ad.jsonl

VERDICT: CREATE (ticket-skeptic, 2026-11-09): ruling 88 is a stated requirement. #637 asks for a lib-side cop on process starts; the first cop here must absorb #637 or reference it.

## Problem After the tracker change (commit 737d2e13) the os-sdlc suite still starts 792 processes that are not `git`. Ruling 88 and `.claude/rules/ruby-external-calls.md` forbid each one. No check enforces the rule, so a new test can start a process and nobody sees it until mutation testing times out. ## Observed A list run on 2026-11-09 recorded these starts: `ast-grep` 267 (12 test files; `lib/os_sdlc/evidence/probe.rb` 228, `evidence/resolution/token_query.rb` 100), `ruby` 144 (1 test file; `system_model/pattern_site/example_run.rb`), `grep` 82, `ruby -e` 57, `ruby -rrubocop` 52, `true` and `false` 68, `os-backlog` 39, `sh -c` 18. `test/boot_unchanged_check_test.rb` takes about 10 s because `Lint::Run::Invocation` runs the real lint command. That file causes 14 of the 22 mutation timeouts that remain in `lib/os_sdlc/map`. The other 8 mutants ran zero tests; they are a different fault. ## Reproduce n/a: structure ticket. ## Approach In this order: 1. Put each of these calls in an adapter that the entry passes in, with a recorded fixture for tests. Do the lint command first. 2. Add a runtime guard to `test/test_helper.rb`. It fails a test that starts a process by any route (`Process.spawn`, `system`, backticks, `IO.popen`). It has no exception list and no baseline (ruling 92, predicted). 3. Add two cops with must-fire and must-pass fixtures: a process start in `lib/` outside an adapter file; an adapter built outside the entry. Three default arguments build one today: `tracker/backlog.rb:25`, `tracker/backlog/project_show.rb:6`, `crc/filing/backlog_client.rb:10`. 4. Write one lint lesson through `/os-sdlc:smell-analysis` on these sites. The mutation timeout guidance points to it. 5. Delete text that conflicts with ruling 88: lens-testing T5 and T6, the CONTRACT row of lens-taxonomy-tests, and the smoke-test allowance in `Sdlc/Structural/OwnEntryPointSpawnedInTest` and its lesson. 6. Remove `test/support/fake_project_show_bin.rb` when nothing uses it. ## Acceptance criteria 1. Given a test that starts a process, when the suite runs, then that test fails and the message names the program. 2. Given the os-sdlc suite with the guard on, when it runs, then it is green. ## Origin - Trigger: list run of process starts in the os-sdlc suite on 2026-11-09 - Improvised this session: none - Chain: mutation timeouts ← slow covering tests ← tests start real processes ← DESIGN (no check enforces `.claude/rules/ruby-external-calls.md`) - Root candidate: none found; searched process start, no-real-process, spawn, adapter, cop, test_helper, ProcessBoundary (#637 is related but not the same fault) - Where: `plugins/os-sdlc/test/test_helper.rb`, `plugins/os-sdlc/lib/os_sdlc/lint/run/invocation.rb` - Session: 19f78576-9fa5-4fd3-9984-a9e58ef897ad - Transcript: /home/jared/.claude/projects/-home-jared-dev-cc-os-plugins-os-sdlc/19f78576-9fa5-4fd3-9984-a9e58ef897ad.jsonl VERDICT: CREATE (ticket-skeptic, 2026-11-09): ruling 88 is a stated requirement. #637 asks for a lib-side cop on process starts; the first cop here must absorb #637 or reference it.
Author
Owner

Added scope (Jared, 2026-11-09: paths are data, no absolute paths in code or fixtures): the lint recordings must hold no machine path. At record time, test/fixtures/lint_recordings/refresh.rb writes the root as a placeholder and strips machine paths from backtraces; sweep/missing_gem.yml holds 19 /home/jared lines now. test/agent/transcript_path_test.rb has one more. Add a check that fails when a fixture holds an absolute home path. Testing RuboCop itself is out of scope by design: tests assert the request os-sdlc sends and replay recorded answers; refresh.rb is run by hand on a rubocop gem upgrade.

Added scope (Jared, 2026-11-09: paths are data, no absolute paths in code or fixtures): the lint recordings must hold no machine path. At record time, `test/fixtures/lint_recordings/refresh.rb` writes the root as a placeholder and strips machine paths from backtraces; `sweep/missing_gem.yml` holds 19 /home/jared lines now. `test/agent/transcript_path_test.rb` has one more. Add a check that fails when a fixture holds an absolute home path. Testing RuboCop itself is out of scope by design: tests assert the request os-sdlc sends and replay recorded answers; refresh.rb is run by hand on a rubocop gem upgrade.
Author
Owner

Part A started (2026-11-09): worktree ticket-1647-adapters. Scope: adapters with recorded fixtures for every non-git process start in os-sdlc tests; fixture machine-path cleanup; fixture home-path check. Git calls stay for #1645.

Part A started (2026-11-09): worktree ticket-1647-adapters. Scope: adapters with recorded fixtures for every non-git process start in os-sdlc tests; fixture machine-path cleanup; fixture home-path check. Git calls stay for #1645.
Author
Owner

Part B done on branch ticket-1647-lesson (commit 7f055cd1d, not merged). Two gate cops in plugins/os-sdlc/.rubocop.yml: ProcessStartOutsideAdapter (4 true positives: cc-architect/scripts/lib/validate_marketplaces.rb:36, os-sdlc db/mirror_tickle.rb:21, evidence/probe.rb:65, evidence/resolution/token_query.rb:41) and AdapterBuiltOutsideEntry (23 true positives, including the three default-argument sites and every ProjectShell constant call). 0 false positives over plugins/. OwnEntryPointSpawnedInTest lost SmokeTestPatterns, so 14 *_bin_smoke_test.rb files now fire; part A must delete or convert them. The gate lints only changed files, so these hits block only the commit that touches them.

Part B done on branch ticket-1647-lesson (commit 7f055cd1d, not merged). Two gate cops in plugins/os-sdlc/.rubocop.yml: ProcessStartOutsideAdapter (4 true positives: cc-architect/scripts/lib/validate_marketplaces.rb:36, os-sdlc db/mirror_tickle.rb:21, evidence/probe.rb:65, evidence/resolution/token_query.rb:41) and AdapterBuiltOutsideEntry (23 true positives, including the three default-argument sites and every ProjectShell constant call). 0 false positives over plugins/. OwnEntryPointSpawnedInTest lost SmokeTestPatterns, so 14 *_bin_smoke_test.rb files now fire; part A must delete or convert them. The gate lints only changed files, so these hits block only the commit that touches them.
Author
Owner

Status 2026-11-09: part B (cops, lessons, ruling-88 text) merged 7f055cd1; part A (non-git adapters, recordings with no machine path) merged 7b6ee115. Suite starts 3,370 processes, all git; non-git starts 0. Remaining: the runtime guard and mirror_tickle.rb:21 move with #1645 (the guard can only be on when git starts are 0). Suite green: 3,684 runs, 20.3 s at load 1.5.

Status 2026-11-09: part B (cops, lessons, ruling-88 text) merged 7f055cd1; part A (non-git adapters, recordings with no machine path) merged 7b6ee115. Suite starts 3,370 processes, all git; non-git starts 0. Remaining: the runtime guard and mirror_tickle.rb:21 move with #1645 (the guard can only be on when git starts are 0). Suite green: 3,684 runs, 20.3 s at load 1.5.
Author
Owner

Resolution

Done: Non-git adapters with recorded fixtures (project shell, code search, tracer, likec4, example run, backlog); fixtures hold no machine path; two cops and lessons; ruling-88 text deleted; runtime guard on in test_helper (landed with #1645); mirror_tickle adapter

Evidence: main 7f055cd1 (part B), 7b6ee115 (part A), 38b3284d (guard, #1645); suite 3,676 runs green with the guard on, 26.6 s at load 1.4; process starts 4,117 -> 0

Follow-ups: Stale cop cache: existing #1173 (evidence added). Bundler env-scrub check lost with the deleted child-process tests: none, ruling 88

## Resolution **Done:** Non-git adapters with recorded fixtures (project shell, code search, tracer, likec4, example run, backlog); fixtures hold no machine path; two cops and lessons; ruling-88 text deleted; runtime guard on in test_helper (landed with #1645); mirror_tickle adapter **Evidence:** main 7f055cd1 (part B), 7b6ee115 (part A), 38b3284d (guard, #1645); suite 3,676 runs green with the guard on, 26.6 s at load 1.4; process starts 4,117 -> 0 **Follow-ups:** Stale cop cache: existing #1173 (evidence added). Bundler env-scrub check lost with the deleted child-process tests: none, ruling 88 <!-- os-backlog kind: resolution -->
jared closed this issue 2026-11-09 20:46:01 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jared/cc-os#1647
No description provided.