Skip to content

coupling: route-lane findings from /coupling:reduce dry-run over scripts/ #2914

Description

@kyle-sexton

First dogfood run of /coupling:reduce (dry-run, scope scripts/, PR #2913) produced 8 verified findings. One is apply-lane (shipped separately as a chore/decouple-scripts-test-git-helpers PR); these 7 are route-lane — cross-file or architectural, surfaced for human decision per the detector-findings doctrine, never auto-applied. Each was reproduced against the tree before filing (evidence commands in the ledger; grep-reproducible).

Ranked by strength × degree × distance × volatility:

  • Seven checkers re-implement base-ref validation + changed-file resolution (connascence of algorithm, 7 scripts). Divergence already live: check-changed-skills.sh:53 and check-docs-only.sh:63 lack the NUL-safety/--diff-filter=d invariant that check-shell-portability.sh:259 / check-skill-portability.sh:135 carry. Remediation: extract scripts/lib/changed-files.sh (resolve_base/changed_paths), mirroring the scripts/lib/sync-cluster.sh precedent.
  • Portability-gate bugfix did not propagate between twin scanners: the ci: harden shell-portability-lint detection precision (sed -i spellings, portability-scope precision, awk operand edge case) #1513 awk-operand fail-open guard exists in check-shell-portability.sh:141-144 and is absent from check-skill-portability.sh (verified 1 vs 0). Remediation: extract scripts/lib/token-scan.sh (token loading, operand guard, mode dispatch); both gates become parameterizations. The missing guard itself may deserve an immediate one-line fix ahead of the extraction.
  • affected-tests.sh scrapes sync-*.sh source text for src=/copies=( (content coupling, 5 producers, comment-guarded). Remediation: each sync script publishes a --print-manifest surface; the consumer invokes instead of scraping.
  • fetch-depth: 0 + origin/$BASE_REF incantation replicated across 20 CI jobs (connascence of value + execution order; only the stale-base lane fetches the base explicitly). Remediation: composite action .github/actions/checkout-with-base owning depth, base fetch, and BASE_REF export.
  • docs_only string contract fans out to 46 references in ci.yml (connascence of meaning; the inverse-polarity invariant is maintained by a prose comment). Remediation: hoist scope resolution into one job; consumers read needs.scope.outputs.docs_only.
  • Test-harness scaffolding re-declared in 23 suites in two dialects (20 PASS/FAIL counter files vs 3 TAP-ish). Remediation: scripts/lib/test-harness.sh in one dialect, sourced.
  • One # comment/blank-stripped line format, five bespoke parsers over ~10 scripts/*.txt data files — check-shell-portability.sh itself parses it two different ways (lines 183 vs 194). Remediation: scripts/lib/read-list.sh read_active_lines defining comment/escape semantics once.

Full typed ledger (edges, strength, degree, locality, volatility, evidence) lives in the memory-tier artifact .work/coupling/coupling-ledger.md of the machine that ran the pass; re-running /coupling:reduce dry-run scripts regenerates it from current state.

Also deferred from the apply-lane batch: check-stale-base-overlap.test.sh:21 hand-rolls git init -q -b main; git_init_test_repo has no init-args seam, so adopting it there needs a tiny helper extension first (route: extend test-git-helpers.sh with an optional initial-branch argument).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions