os-sdlc shard-plan: code_files heuristic resolves to tests/test_helper.rb instead of production files #300

Closed
opened 2026-08-06 21:17:14 +00:00 by jared · 4 comments
Owner

In #297 shard-plan assigned code_files=[tests/test_helper.rb] though the fix belonged in lib/aidd_lint/fence_mask.rb. The programmer prompt's ownership rules then technically forbade the real fix; dispatcher had to annotate around it.

In #297 shard-plan assigned code_files=[tests/test_helper.rb] though the fix belonged in lib/aidd_lint/fence_mask.rb. The programmer prompt's ownership rules then technically forbade the real fix; dispatcher had to annotate around it.
Author
Owner

Spec: shard-plan code_files must resolve to production files, not test-support files

Problem Statement

When the os-sdlc implement pipeline shards a ticket, shard-plan derives each shard's code_files from the literal require/require_relative lines in the shard's test file. When a test reaches production code only transitively (e.g. through tests/test_helper.rb), the heuristic assigns the test-support file as the owned code file and never discovers the real production file. The programmer brief then forbids editing the file the fix actually belongs in ("never edit any file outside your owned set"), forcing the dispatcher to annotate around the ownership rules by hand (as happened in #297, where the fix belonged in the fence-mask production file but the shard owned only test_helper).

Solution

Make shard-plan's collaborator discovery follow require chains transitively: when a required file is itself a test-support file (lives under the tests directory), recurse into its requires instead of claiming it, so the closure lands on the production files the test actually exercises. Test-support files are excluded from code_files outright. Reservation of shared collaborators and the single-programmer fallback behave exactly as today, operating on the improved sets.

User Stories

  1. As the os-sdlc dispatcher, I want shard code_files to name the production files a test transitively exercises, so that the programmer is permitted to make the real fix.
  2. As a sharded programmer agent, I want my owned code files to include the file the failing test actually covers, so that I never have to violate or work around my ownership rules.
  3. As the os-sdlc dispatcher, I want test-support files (test_helper and friends) excluded from code_files, so that no shard "owns" infrastructure shared by every test.
  4. As the os-sdlc dispatcher, I want transitive discovery to remain deterministic (static require parsing, no code execution), so that shard-plan stays a reproducible CLI step.
  5. As the os-sdlc dispatcher, I want require cycles between files to terminate cleanly, so that a self-requiring or mutually-requiring pair can't hang or crash planning.
  6. As the os-sdlc dispatcher, I want production files reached by multiple shards' transitive closures to land in the reserved set exactly as directly-required shared files do today, so that disjoint ownership is preserved.
  7. As the os-sdlc dispatcher, I want a shard whose closure yields no production files to be handled by the existing empty-shard/fallback behavior, so that planning degrades to single-programmer rather than emitting an unownable shard.
  8. As the os-sdlc dispatcher, I want requires that don't resolve to files on disk (gems, stdlib) to continue to be silently ignored, so that behavior on normal test files is unchanged.
  9. As a maintainer of os-sdlc, I want existing shard-plan scenarios (direct requires, reservation, project-config reserved paths, collapse fallback) to keep passing unchanged, so that the fix is a pure recall improvement.
  10. As a maintainer of os-sdlc, I want a regression test reproducing the #297/#300 shape (test → test_helper → production file), so that this failure mode stays fixed.

Implementation Decisions

  • The change is confined to the shard-plan collaborator-discovery logic in the os-sdlc Ruby library; the programmer brief, ownership-rule wording, reservation logic, and the shard-plan CLI contract (flags, output shape) are unchanged.
  • Discovery becomes a transitive closure over static require/require_relative parsing: resolve each target relative to the requiring file (existing resolution rules); if the resolved file is a test-support file, recurse into it rather than including it; otherwise include it as a collaborator.
  • A file is a test-support file when it resolves under the project's tests directory (the directory containing the shard's test files). No allowlist of names like test_helper — location, not naming, decides.
  • Cycle safety via a visited set; each file is parsed at most once per shard.
  • Unresolvable require targets are skipped, exactly as today.
  • Downstream behavior (shared-collaborator reservation, reserved_paths merge, trim, single-programmer fallback) is untouched and operates on the closed sets.
  • No new configuration keys.

Testing Decisions

  • Tests assert external behavior only: the plan structure returned by the planner for synthetic on-disk fixtures (test files, helper files, lib files with literal require lines) — never the internals of the traversal.
  • Prior art: the existing shard-plan test file, which already builds synthetic require graphs on disk and asserts on the resulting plan; new scenarios follow its idioms.
  • New scenarios: (a) test → test_helper → lib file yields the lib file as the owned code file and never the helper; (b) two tests whose closures share a lib file via a common helper put it in reserved; (c) require cycle terminates with correct ownership; (d) closure yielding only test-support files produces an empty code set handled by existing fallback rules; (e) all existing scenarios unchanged.

Out of Scope

  • Runtime/coverage-based discovery of what a test exercises (executing tests to trace loads).
  • Name-convention mapping (foo_test.rb → foo.rb).
  • Changes to programmer/wiring prompts or the ownership-rule wording.
  • Any change to reservation semantics or .sdlc/project.yaml schema.
  • Retroactive re-planning of past tickets.

Further Notes

  • ADR-0089 establishes sharded parallel programmers over disjoint file sets; this spec refines the discovery heuristic within that design and does not reverse it. If the implementer judges the heuristic change itself decision-worthy, record it as an amending ADR rather than superseding 0089.
  • The implement SKILL.md is file_locked; this change should not need to touch it.
# Spec: shard-plan code_files must resolve to production files, not test-support files ## Problem Statement When the os-sdlc implement pipeline shards a ticket, shard-plan derives each shard's `code_files` from the literal `require`/`require_relative` lines in the shard's test file. When a test reaches production code only transitively (e.g. through `tests/test_helper.rb`), the heuristic assigns the test-support file as the owned code file and never discovers the real production file. The programmer brief then forbids editing the file the fix actually belongs in ("never edit any file outside your owned set"), forcing the dispatcher to annotate around the ownership rules by hand (as happened in #297, where the fix belonged in the fence-mask production file but the shard owned only test_helper). ## Solution Make shard-plan's collaborator discovery follow require chains transitively: when a required file is itself a test-support file (lives under the tests directory), recurse into its requires instead of claiming it, so the closure lands on the production files the test actually exercises. Test-support files are excluded from `code_files` outright. Reservation of shared collaborators and the single-programmer fallback behave exactly as today, operating on the improved sets. ## User Stories 1. As the os-sdlc dispatcher, I want shard code_files to name the production files a test transitively exercises, so that the programmer is permitted to make the real fix. 2. As a sharded programmer agent, I want my owned code files to include the file the failing test actually covers, so that I never have to violate or work around my ownership rules. 3. As the os-sdlc dispatcher, I want test-support files (test_helper and friends) excluded from code_files, so that no shard "owns" infrastructure shared by every test. 4. As the os-sdlc dispatcher, I want transitive discovery to remain deterministic (static require parsing, no code execution), so that shard-plan stays a reproducible CLI step. 5. As the os-sdlc dispatcher, I want require cycles between files to terminate cleanly, so that a self-requiring or mutually-requiring pair can't hang or crash planning. 6. As the os-sdlc dispatcher, I want production files reached by multiple shards' transitive closures to land in the reserved set exactly as directly-required shared files do today, so that disjoint ownership is preserved. 7. As the os-sdlc dispatcher, I want a shard whose closure yields no production files to be handled by the existing empty-shard/fallback behavior, so that planning degrades to single-programmer rather than emitting an unownable shard. 8. As the os-sdlc dispatcher, I want requires that don't resolve to files on disk (gems, stdlib) to continue to be silently ignored, so that behavior on normal test files is unchanged. 9. As a maintainer of os-sdlc, I want existing shard-plan scenarios (direct requires, reservation, project-config reserved paths, collapse fallback) to keep passing unchanged, so that the fix is a pure recall improvement. 10. As a maintainer of os-sdlc, I want a regression test reproducing the #297/#300 shape (test → test_helper → production file), so that this failure mode stays fixed. ## Implementation Decisions - The change is confined to the shard-plan collaborator-discovery logic in the os-sdlc Ruby library; the programmer brief, ownership-rule wording, reservation logic, and the shard-plan CLI contract (flags, output shape) are unchanged. - Discovery becomes a transitive closure over static `require`/`require_relative` parsing: resolve each target relative to the requiring file (existing resolution rules); if the resolved file is a test-support file, recurse into it rather than including it; otherwise include it as a collaborator. - A file is a test-support file when it resolves under the project's tests directory (the directory containing the shard's test files). No allowlist of names like `test_helper` — location, not naming, decides. - Cycle safety via a visited set; each file is parsed at most once per shard. - Unresolvable require targets are skipped, exactly as today. - Downstream behavior (shared-collaborator reservation, `reserved_paths` merge, trim, single-programmer fallback) is untouched and operates on the closed sets. - No new configuration keys. ## Testing Decisions - Tests assert external behavior only: the plan structure returned by the planner for synthetic on-disk fixtures (test files, helper files, lib files with literal require lines) — never the internals of the traversal. - Prior art: the existing shard-plan test file, which already builds synthetic require graphs on disk and asserts on the resulting plan; new scenarios follow its idioms. - New scenarios: (a) test → test_helper → lib file yields the lib file as the owned code file and never the helper; (b) two tests whose closures share a lib file via a common helper put it in reserved; (c) require cycle terminates with correct ownership; (d) closure yielding only test-support files produces an empty code set handled by existing fallback rules; (e) all existing scenarios unchanged. ## Out of Scope - Runtime/coverage-based discovery of what a test exercises (executing tests to trace loads). - Name-convention mapping (foo_test.rb → foo.rb). - Changes to programmer/wiring prompts or the ownership-rule wording. - Any change to reservation semantics or `.sdlc/project.yaml` schema. - Retroactive re-planning of past tickets. ## Further Notes - ADR-0089 establishes sharded parallel programmers over disjoint file sets; this spec refines the discovery heuristic within that design and does not reverse it. If the implementer judges the heuristic change itself decision-worthy, record it as an amending ADR rather than superseding 0089. - The implement SKILL.md is file_locked; this change should not need to touch it.
Author
Owner

Spec: shard-plan code_files must resolve to production files, not test-support files

Problem Statement

When the os-sdlc implement pipeline shards a ticket, shard-plan derives each shard's code_files from the literal require/require_relative lines in the shard's test file. When a test reaches production code only transitively (e.g. through tests/test_helper.rb), the heuristic assigns the test-support file as the owned code file and never discovers the real production file. The programmer brief then forbids editing the file the fix actually belongs in ("never edit any file outside your owned set"), forcing the dispatcher to annotate around the ownership rules by hand (as happened in #297, where the fix belonged in the fence-mask production file but the shard owned only test_helper).

Solution

Make shard-plan's collaborator discovery follow require chains transitively: when a required file is itself a test-support file (lives under the tests directory), recurse into its requires instead of claiming it, so the closure lands on the production files the test actually exercises. Test-support files are excluded from code_files outright. Reservation of shared collaborators and the single-programmer fallback behave exactly as today, operating on the improved sets.

User Stories

  1. As the os-sdlc dispatcher, I want shard code_files to name the production files a test transitively exercises, so that the programmer is permitted to make the real fix.
  2. As a sharded programmer agent, I want my owned code files to include the file the failing test actually covers, so that I never have to violate or work around my ownership rules.
  3. As the os-sdlc dispatcher, I want test-support files (test_helper and friends) excluded from code_files, so that no shard "owns" infrastructure shared by every test.
  4. As the os-sdlc dispatcher, I want transitive discovery to remain deterministic (static require parsing, no code execution), so that shard-plan stays a reproducible CLI step.
  5. As the os-sdlc dispatcher, I want require cycles between files to terminate cleanly, so that a self-requiring or mutually-requiring pair can't hang or crash planning.
  6. As the os-sdlc dispatcher, I want production files reached by multiple shards' transitive closures to land in the reserved set exactly as directly-required shared files do today, so that disjoint ownership is preserved.
  7. As the os-sdlc dispatcher, I want a shard whose closure yields no production files to be handled by the existing empty-shard/fallback behavior, so that planning degrades to single-programmer rather than emitting an unownable shard.
  8. As the os-sdlc dispatcher, I want requires that don't resolve to files on disk (gems, stdlib) to continue to be silently ignored, so that behavior on normal test files is unchanged.
  9. As a maintainer of os-sdlc, I want existing shard-plan scenarios (direct requires, reservation, project-config reserved paths, collapse fallback) to keep passing unchanged, so that the fix is a pure recall improvement.
  10. As a maintainer of os-sdlc, I want a regression test reproducing the #297/#300 shape (test → test_helper → production file), so that this failure mode stays fixed.

Implementation Decisions

  • The change is confined to the shard-plan collaborator-discovery logic in the os-sdlc Ruby library; the programmer brief, ownership-rule wording, reservation logic, and the shard-plan CLI contract (flags, output shape) are unchanged.
  • Discovery becomes a transitive closure over static require/require_relative parsing: resolve each target relative to the requiring file (existing resolution rules); if the resolved file is a test-support file, recurse into it rather than including it; otherwise include it as a collaborator.
  • A file is a test-support file when it resolves under the project's tests directory (the directory containing the shard's test files). No allowlist of names like test_helper — location, not naming, decides.
  • Cycle safety via a visited set; each file is parsed at most once per shard.
  • Unresolvable require targets are skipped, exactly as today.
  • Downstream behavior (shared-collaborator reservation, reserved_paths merge, trim, single-programmer fallback) is untouched and operates on the closed sets.
  • No new configuration keys.

Testing Decisions

  • Tests assert external behavior only: the plan structure returned by the planner for synthetic on-disk fixtures (test files, helper files, lib files with literal require lines) — never the internals of the traversal.
  • Prior art: the existing shard-plan test file, which already builds synthetic require graphs on disk and asserts on the resulting plan; new scenarios follow its idioms.
  • New scenarios: (a) test → test_helper → lib file yields the lib file as the owned code file and never the helper; (b) two tests whose closures share a lib file via a common helper put it in reserved; (c) require cycle terminates with correct ownership; (d) closure yielding only test-support files produces an empty code set handled by existing fallback rules; (e) all existing scenarios unchanged.

Out of Scope

  • Runtime/coverage-based discovery of what a test exercises (executing tests to trace loads).
  • Name-convention mapping (foo_test.rb → foo.rb).
  • Changes to programmer/wiring prompts or the ownership-rule wording.
  • Any change to reservation semantics or .sdlc/project.yaml schema.
  • Retroactive re-planning of past tickets.

Further Notes

  • ADR-0089 establishes sharded parallel programmers over disjoint file sets; this spec refines the discovery heuristic within that design and does not reverse it. If the implementer judges the heuristic change itself decision-worthy, record it as an amending ADR rather than superseding 0089.
  • The implement SKILL.md is file_locked; this change should not need to touch it.
# Spec: shard-plan code_files must resolve to production files, not test-support files ## Problem Statement When the os-sdlc implement pipeline shards a ticket, shard-plan derives each shard's `code_files` from the literal `require`/`require_relative` lines in the shard's test file. When a test reaches production code only transitively (e.g. through `tests/test_helper.rb`), the heuristic assigns the test-support file as the owned code file and never discovers the real production file. The programmer brief then forbids editing the file the fix actually belongs in ("never edit any file outside your owned set"), forcing the dispatcher to annotate around the ownership rules by hand (as happened in #297, where the fix belonged in the fence-mask production file but the shard owned only test_helper). ## Solution Make shard-plan's collaborator discovery follow require chains transitively: when a required file is itself a test-support file (lives under the tests directory), recurse into its requires instead of claiming it, so the closure lands on the production files the test actually exercises. Test-support files are excluded from `code_files` outright. Reservation of shared collaborators and the single-programmer fallback behave exactly as today, operating on the improved sets. ## User Stories 1. As the os-sdlc dispatcher, I want shard code_files to name the production files a test transitively exercises, so that the programmer is permitted to make the real fix. 2. As a sharded programmer agent, I want my owned code files to include the file the failing test actually covers, so that I never have to violate or work around my ownership rules. 3. As the os-sdlc dispatcher, I want test-support files (test_helper and friends) excluded from code_files, so that no shard "owns" infrastructure shared by every test. 4. As the os-sdlc dispatcher, I want transitive discovery to remain deterministic (static require parsing, no code execution), so that shard-plan stays a reproducible CLI step. 5. As the os-sdlc dispatcher, I want require cycles between files to terminate cleanly, so that a self-requiring or mutually-requiring pair can't hang or crash planning. 6. As the os-sdlc dispatcher, I want production files reached by multiple shards' transitive closures to land in the reserved set exactly as directly-required shared files do today, so that disjoint ownership is preserved. 7. As the os-sdlc dispatcher, I want a shard whose closure yields no production files to be handled by the existing empty-shard/fallback behavior, so that planning degrades to single-programmer rather than emitting an unownable shard. 8. As the os-sdlc dispatcher, I want requires that don't resolve to files on disk (gems, stdlib) to continue to be silently ignored, so that behavior on normal test files is unchanged. 9. As a maintainer of os-sdlc, I want existing shard-plan scenarios (direct requires, reservation, project-config reserved paths, collapse fallback) to keep passing unchanged, so that the fix is a pure recall improvement. 10. As a maintainer of os-sdlc, I want a regression test reproducing the #297/#300 shape (test → test_helper → production file), so that this failure mode stays fixed. ## Implementation Decisions - The change is confined to the shard-plan collaborator-discovery logic in the os-sdlc Ruby library; the programmer brief, ownership-rule wording, reservation logic, and the shard-plan CLI contract (flags, output shape) are unchanged. - Discovery becomes a transitive closure over static `require`/`require_relative` parsing: resolve each target relative to the requiring file (existing resolution rules); if the resolved file is a test-support file, recurse into it rather than including it; otherwise include it as a collaborator. - A file is a test-support file when it resolves under the project's tests directory (the directory containing the shard's test files). No allowlist of names like `test_helper` — location, not naming, decides. - Cycle safety via a visited set; each file is parsed at most once per shard. - Unresolvable require targets are skipped, exactly as today. - Downstream behavior (shared-collaborator reservation, `reserved_paths` merge, trim, single-programmer fallback) is untouched and operates on the closed sets. - No new configuration keys. ## Testing Decisions - Tests assert external behavior only: the plan structure returned by the planner for synthetic on-disk fixtures (test files, helper files, lib files with literal require lines) — never the internals of the traversal. - Prior art: the existing shard-plan test file, which already builds synthetic require graphs on disk and asserts on the resulting plan; new scenarios follow its idioms. - New scenarios: (a) test → test_helper → lib file yields the lib file as the owned code file and never the helper; (b) two tests whose closures share a lib file via a common helper put it in reserved; (c) require cycle terminates with correct ownership; (d) closure yielding only test-support files produces an empty code set handled by existing fallback rules; (e) all existing scenarios unchanged. ## Out of Scope - Runtime/coverage-based discovery of what a test exercises (executing tests to trace loads). - Name-convention mapping (foo_test.rb → foo.rb). - Changes to programmer/wiring prompts or the ownership-rule wording. - Any change to reservation semantics or `.sdlc/project.yaml` schema. - Retroactive re-planning of past tickets. ## Further Notes - ADR-0089 establishes sharded parallel programmers over disjoint file sets; this spec refines the discovery heuristic within that design and does not reverse it. If the implementer judges the heuristic change itself decision-worthy, record it as an amending ADR rather than superseding 0089. - The implement SKILL.md is file_locked; this change should not need to touch it.
Author
Owner

Spec: shard-plan code_files must resolve to production files, not test-support files

Problem Statement

When the os-sdlc implement pipeline shards a ticket, shard-plan derives each shard's code_files from the literal require/require_relative lines in the shard's test file. When a test reaches production code only transitively (e.g. through tests/test_helper.rb), the heuristic assigns the test-support file as the owned code file and never discovers the real production file. The programmer brief then forbids editing the file the fix actually belongs in ("never edit any file outside your owned set"), forcing the dispatcher to annotate around the ownership rules by hand (as happened in #297, where the fix belonged in the fence-mask production file but the shard owned only test_helper).

Solution

Make shard-plan's collaborator discovery follow require chains transitively: when a required file is itself a test-support file (lives under the tests directory), recurse into its requires instead of claiming it, so the closure lands on the production files the test actually exercises. Test-support files are excluded from code_files outright. Reservation of shared collaborators and the single-programmer fallback behave exactly as today, operating on the improved sets.

User Stories

  1. As the os-sdlc dispatcher, I want shard code_files to name the production files a test transitively exercises, so that the programmer is permitted to make the real fix.
  2. As a sharded programmer agent, I want my owned code files to include the file the failing test actually covers, so that I never have to violate or work around my ownership rules.
  3. As the os-sdlc dispatcher, I want test-support files (test_helper and friends) excluded from code_files, so that no shard "owns" infrastructure shared by every test.
  4. As the os-sdlc dispatcher, I want transitive discovery to remain deterministic (static require parsing, no code execution), so that shard-plan stays a reproducible CLI step.
  5. As the os-sdlc dispatcher, I want require cycles between files to terminate cleanly, so that a self-requiring or mutually-requiring pair can't hang or crash planning.
  6. As the os-sdlc dispatcher, I want production files reached by multiple shards' transitive closures to land in the reserved set exactly as directly-required shared files do today, so that disjoint ownership is preserved.
  7. As the os-sdlc dispatcher, I want a shard whose closure yields no production files to be handled by the existing empty-shard/fallback behavior, so that planning degrades to single-programmer rather than emitting an unownable shard.
  8. As the os-sdlc dispatcher, I want requires that don't resolve to files on disk (gems, stdlib) to continue to be silently ignored, so that behavior on normal test files is unchanged.
  9. As a maintainer of os-sdlc, I want existing shard-plan scenarios (direct requires, reservation, project-config reserved paths, collapse fallback) to keep passing unchanged, so that the fix is a pure recall improvement.
  10. As a maintainer of os-sdlc, I want a regression test reproducing the #297/#300 shape (test → test_helper → production file), so that this failure mode stays fixed.

Implementation Decisions

  • The change is confined to the shard-plan collaborator-discovery logic in the os-sdlc Ruby library; the programmer brief, ownership-rule wording, reservation logic, and the shard-plan CLI contract (flags, output shape) are unchanged.
  • Discovery becomes a transitive closure over static require/require_relative parsing: resolve each target relative to the requiring file (existing resolution rules); if the resolved file is a test-support file, recurse into it rather than including it; otherwise include it as a collaborator.
  • A file is a test-support file when it resolves under the project's tests directory (the directory containing the shard's test files). No allowlist of names like test_helper — location, not naming, decides.
  • Cycle safety via a visited set; each file is parsed at most once per shard.
  • Unresolvable require targets are skipped, exactly as today.
  • Downstream behavior (shared-collaborator reservation, reserved_paths merge, trim, single-programmer fallback) is untouched and operates on the closed sets.
  • No new configuration keys.

Testing Decisions

  • Tests assert external behavior only: the plan structure returned by the planner for synthetic on-disk fixtures (test files, helper files, lib files with literal require lines) — never the internals of the traversal.
  • Prior art: the existing shard-plan test file, which already builds synthetic require graphs on disk and asserts on the resulting plan; new scenarios follow its idioms.
  • New scenarios: (a) test → test_helper → lib file yields the lib file as the owned code file and never the helper; (b) two tests whose closures share a lib file via a common helper put it in reserved; (c) require cycle terminates with correct ownership; (d) closure yielding only test-support files produces an empty code set handled by existing fallback rules; (e) all existing scenarios unchanged.

Out of Scope

  • Runtime/coverage-based discovery of what a test exercises (executing tests to trace loads).
  • Name-convention mapping (foo_test.rb → foo.rb).
  • Changes to programmer/wiring prompts or the ownership-rule wording.
  • Any change to reservation semantics or .sdlc/project.yaml schema.
  • Retroactive re-planning of past tickets.

Further Notes

  • ADR-0089 establishes sharded parallel programmers over disjoint file sets; this spec refines the discovery heuristic within that design and does not reverse it. If the implementer judges the heuristic change itself decision-worthy, record it as an amending ADR rather than superseding 0089.
  • The implement SKILL.md is file_locked; this change should not need to touch it.
# Spec: shard-plan code_files must resolve to production files, not test-support files ## Problem Statement When the os-sdlc implement pipeline shards a ticket, shard-plan derives each shard's `code_files` from the literal `require`/`require_relative` lines in the shard's test file. When a test reaches production code only transitively (e.g. through `tests/test_helper.rb`), the heuristic assigns the test-support file as the owned code file and never discovers the real production file. The programmer brief then forbids editing the file the fix actually belongs in ("never edit any file outside your owned set"), forcing the dispatcher to annotate around the ownership rules by hand (as happened in #297, where the fix belonged in the fence-mask production file but the shard owned only test_helper). ## Solution Make shard-plan's collaborator discovery follow require chains transitively: when a required file is itself a test-support file (lives under the tests directory), recurse into its requires instead of claiming it, so the closure lands on the production files the test actually exercises. Test-support files are excluded from `code_files` outright. Reservation of shared collaborators and the single-programmer fallback behave exactly as today, operating on the improved sets. ## User Stories 1. As the os-sdlc dispatcher, I want shard code_files to name the production files a test transitively exercises, so that the programmer is permitted to make the real fix. 2. As a sharded programmer agent, I want my owned code files to include the file the failing test actually covers, so that I never have to violate or work around my ownership rules. 3. As the os-sdlc dispatcher, I want test-support files (test_helper and friends) excluded from code_files, so that no shard "owns" infrastructure shared by every test. 4. As the os-sdlc dispatcher, I want transitive discovery to remain deterministic (static require parsing, no code execution), so that shard-plan stays a reproducible CLI step. 5. As the os-sdlc dispatcher, I want require cycles between files to terminate cleanly, so that a self-requiring or mutually-requiring pair can't hang or crash planning. 6. As the os-sdlc dispatcher, I want production files reached by multiple shards' transitive closures to land in the reserved set exactly as directly-required shared files do today, so that disjoint ownership is preserved. 7. As the os-sdlc dispatcher, I want a shard whose closure yields no production files to be handled by the existing empty-shard/fallback behavior, so that planning degrades to single-programmer rather than emitting an unownable shard. 8. As the os-sdlc dispatcher, I want requires that don't resolve to files on disk (gems, stdlib) to continue to be silently ignored, so that behavior on normal test files is unchanged. 9. As a maintainer of os-sdlc, I want existing shard-plan scenarios (direct requires, reservation, project-config reserved paths, collapse fallback) to keep passing unchanged, so that the fix is a pure recall improvement. 10. As a maintainer of os-sdlc, I want a regression test reproducing the #297/#300 shape (test → test_helper → production file), so that this failure mode stays fixed. ## Implementation Decisions - The change is confined to the shard-plan collaborator-discovery logic in the os-sdlc Ruby library; the programmer brief, ownership-rule wording, reservation logic, and the shard-plan CLI contract (flags, output shape) are unchanged. - Discovery becomes a transitive closure over static `require`/`require_relative` parsing: resolve each target relative to the requiring file (existing resolution rules); if the resolved file is a test-support file, recurse into it rather than including it; otherwise include it as a collaborator. - A file is a test-support file when it resolves under the project's tests directory (the directory containing the shard's test files). No allowlist of names like `test_helper` — location, not naming, decides. - Cycle safety via a visited set; each file is parsed at most once per shard. - Unresolvable require targets are skipped, exactly as today. - Downstream behavior (shared-collaborator reservation, `reserved_paths` merge, trim, single-programmer fallback) is untouched and operates on the closed sets. - No new configuration keys. ## Testing Decisions - Tests assert external behavior only: the plan structure returned by the planner for synthetic on-disk fixtures (test files, helper files, lib files with literal require lines) — never the internals of the traversal. - Prior art: the existing shard-plan test file, which already builds synthetic require graphs on disk and asserts on the resulting plan; new scenarios follow its idioms. - New scenarios: (a) test → test_helper → lib file yields the lib file as the owned code file and never the helper; (b) two tests whose closures share a lib file via a common helper put it in reserved; (c) require cycle terminates with correct ownership; (d) closure yielding only test-support files produces an empty code set handled by existing fallback rules; (e) all existing scenarios unchanged. ## Out of Scope - Runtime/coverage-based discovery of what a test exercises (executing tests to trace loads). - Name-convention mapping (foo_test.rb → foo.rb). - Changes to programmer/wiring prompts or the ownership-rule wording. - Any change to reservation semantics or `.sdlc/project.yaml` schema. - Retroactive re-planning of past tickets. ## Further Notes - ADR-0089 establishes sharded parallel programmers over disjoint file sets; this spec refines the discovery heuristic within that design and does not reverse it. If the implementer judges the heuristic change itself decision-worthy, record it as an amending ADR rather than superseding 0089. - The implement SKILL.md is file_locked; this change should not need to touch it.
Author
Owner

Resolution

Done: shard-plan collaborator discovery is now a transitive closure over static require parsing: recurses through test-support files (location-based under the test file's dir), lands on the production files a test actually exercises, cycle-safe via visited set; test-support files excluded from code_files; reservation/fallback untouched.

Evidence: Merged to main via sdlc/300 (worktree commit 4e5b91b, merge 32b7e3f); suite on main after merge: 759 runs / 0 failures; reviewer verdict APPROVE (spec fidelity, test relevance, design). Run also flushed out and fixed pipeline bugs #305 and #306 on main (a639666, 5d858fc, 9446f79).

Follow-ups: Captured: duplicate transitive test coverage consolidation (new issue above). Dropped: tests_dir uses File.dirname(test_file) not test_path — spec-sanctioned; only matters if nested test subdirectories ever appear.

## Resolution **Done:** shard-plan collaborator discovery is now a transitive closure over static require parsing: recurses through test-support files (location-based under the test file's dir), lands on the production files a test actually exercises, cycle-safe via visited set; test-support files excluded from code_files; reservation/fallback untouched. **Evidence:** Merged to main via sdlc/300 (worktree commit 4e5b91b, merge 32b7e3f); suite on main after merge: 759 runs / 0 failures; reviewer verdict APPROVE (spec fidelity, test relevance, design). Run also flushed out and fixed pipeline bugs #305 and #306 on main (a639666, 5d858fc, 9446f79). **Follow-ups:** Captured: duplicate transitive test coverage consolidation (new issue above). Dropped: tests_dir uses File.dirname(test_file) not test_path — spec-sanctioned; only matters if nested test subdirectories ever appear.
jared closed this issue 2026-08-07 12:15:57 +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#300
No description provided.