Skip to content

fix(dashboard): proportionate stale-copy remedy; bare --dry-run no longer writes (#67) - #73

Merged
KJ5HST merged 3 commits into
mainfrom
fix/issue-67-stale-version-remedy
Aug 12, 2026
Merged

KJ5HST merged 3 commits into
mainfrom
fix/issue-67-stale-version-remedy

Conversation

@KJ5HST

@KJ5HST KJ5HST commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Closes #67 — both defects, each reproduced before and after against a real scratch portfolio rather than argued from the diff.

Defect 1 — a remedy disproportionate to the finding

check_stale_version() answered "this one copy is old" with Re-sync: python3 <canonical> --sync. But --sync is scoped from the canonical's own location, not the working directory, so it rewrites every discovered sibling — the issue measured 26 files across 25 repos, including 7 creates in repos that do not gitignore the path and 1 where the file is git-tracked. An adopter following a one-line instruction verbatim dirties eight unrelated repositories.

The warning now leads with the safe per-project action and states the portfolio path's blast radius inline:

  ⚠ methodology_dashboard.py is stale: this copy is v2.6.1, canonical is v2.10.6.
    Re-sync THIS project:  cp <canonical> <this copy>
    Re-sync the PORTFOLIO: python3 <canonical> --sync --dry-run
                           (rewrites EVERY discovered sibling repo — preview with
                            --dry-run first, then re-run without it to apply)

--sync itself is unchanged — this is a message fix, not a behavior change. Worth being explicit that the issue's headline number is therefore still true after its own fix: the tool no longer recommends the portfolio-wide write, but running it still does exactly what it did.

Why this is more than tidiness. A remedy nobody can safely run is one mechanism behind an ignored warning. The issue records this staleness line riding ~28 consecutive handoffs in one adopter without being acted on. The measurement was never the missing part — the tool re-derived it correctly every session; the actionable remedy was.

Defect 2 — a flag named --dry-run that writes

--dry-run was consulted only inside the --sync branch, so on its own it fell through to a full scan and wrote dashboard.html and appended to dashboard_history.jsonl. Measured, old vs new, in a throwaway repo:

  OLD  exit=0  files written: dashboard_history.jsonl dashboard.html
  NEW  exit=2  files written: (none)

It is now an error. Refusing rather than silently no-opping is deliberate: a no-op leaves the caller unable to tell "nothing to do" from "flag ignored" — the same unreadable-signal class as defect 1. --sync --dry-run still previews exactly as before; the refusal sits after the --sync branch.

Tests

New TestCliRemedyProportionality (3 cases; unit suite 208 → 211). Subprocess-driven by necessity — importing the module cannot reach main()'s argument handling, so an import-based test would assert nothing about either defect while looking like coverage.

Both defect tests were driven RED against the pre-fix scanner (swapped in from origin/main) and the failing run read, not assumed:

test_a_normal_run_still_writes ... ok        <- presence control
test_bare_dry_run_refuses_instead_of_writing ... FAIL
test_stale_warning_leads_with_the_project_scoped_remedy ... FAIL

The control passing in the same RED run is what proves the two failures were specific rather than a broken harness. It is load-bearing in the other direction too: without it, a scanner that refused every invocation would satisfy the dry-run test and look fixed.

The stale-warning test deliberately asserts a property rather than a string — if --sync appears on any line of the warning, --dry-run must appear on that same line — so it keeps holding if the wording is reworded.

Scope deliberately not taken

The issue also suggests --sync-self and a --yes/scope gate on --sync. Both change the CLI contract rather than fix a defect, and the cp line already supplies the per-project remedy with no new surface area, so they are left for a separate deliverable. Recorded as deliberate in the ledger entry and the handoff receipt so it does not read later as an oversight — but the 26-file blast radius is a real follow-up, not noise.

Verification

  • python3 -m unittest tools.test_methodology_dashboard — 211/211
  • bash bin/tests.sh — 114/114, 0 failed
  • python3 bin/check-links — OK (83 links / 21 files)
  • python3 bin/check-handoff --all — OK (9 receipts, fences balanced)
  • tools/ and starter-kit/ twins byte-identical; DASHBOARD_VERSION 2.10.5 → 2.10.6
  • Learning feat: extend research-documentation workstream with anti-patterns 14-19 #10 corpus sweep run rather than assumed: no live operative doc advertises the old --sync remedy; the only hits are frozen docs/planning records, left verbatim per the v2.7.1 precedent.

The scanner is bin/_manifest.py-TRACKED, so adopters receive both fixes via bin/sync.

KJ5HST added 3 commits August 11, 2026 23:30
…nger writes (#67)

check_stale_version() advertised `--sync` as the fix for a stale copy, but --sync
is scoped from the canonical's own location rather than the working directory, so
it rewrites every discovered sibling (measured: 26 files / 25 repos, 7 creates in
repos that do not gitignore the path, 1 git-tracked target). The warning now leads
with `cp <canonical> <this copy>` and offers the portfolio path only as
--sync --dry-run with its scope stated.

Separately, --dry-run was consulted only inside the --sync branch, so on its own it
fell through to a full scan and wrote dashboard.html + dashboard_history.jsonl. It
is now an error (exit 2) that writes nothing — refusing rather than no-opping, so
the caller can tell 'nothing to do' from 'flag ignored'.

New TestCliRemedyProportionality (3 cases, 208 -> 211). Both defect tests driven RED
against the pre-fix scanner; the third is a presence control. Twins byte-identical.
DASHBOARD_VERSION 2.10.5 -> 2.10.6.

Closes #67
@KJ5HST
KJ5HST merged commit 936f4c6 into main Aug 12, 2026
@KJ5HST
KJ5HST deleted the fix/issue-67-stale-version-remedy branch September 15, 2026 01:35
rmsharp added a commit to rmsharp/methodology that referenced this pull request Sep 17, 2026
…cide the sync commit cap, then P7

S180's receipt (self 7, S179 scored 8) and fork Learning KJ5HST#73: a read-only
phase is read-only only if git status says so. Gates in a clone of
04fccc5: 10/10, results c86e8ef9b42b, tests-sh-passed 311 at 3 receipts.
Next: the operator decides plan item (18), then P7 in wsfct's own
repository.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

check_stale_version() advertises --sync, which writes 26 files across 25 sibling repos

1 participant