Skip to content

fix(decisions): measure staleness from the commit that landed a decision - #4357

Merged
swati510 merged 3 commits into
mainfrom
fix/decision-staleness-evidence-commit
Oct 22, 2026
Merged

swati510 merged 3 commits into
mainfrom
fix/decision-staleness-evidence-commit

Conversation

@RaghavChamadiya

Copy link
Copy Markdown
Member

What

A decision recorded on a branch names that branch's commits, and the squash that lands them arrives after the record is created. Staleness counted every commit after created_at, so the landing commit itself made the record stale by construction. On this repository 162 of 172 accepted decisions read as stale and filled 162 of 217 quarter rows in repowise next.

How

  • New analysis/decisions/landing.py places each record's evidence commits on HEAD's first-parent line. A commit there landed as itself. A branch commit landed in the one first-parent commit after it that names it (subject less (#N), or a * <subject> bullet in the squash body) and changes a file it changed. Anything else is unresolved and the record keeps created_at as its anchor, so an unresolved commit never makes a record fresher.
  • compute_staleness measures from the later of the record's birth and that landing. Both rescore paths (index and update) pass the repo path. decision show and the get_why "still true" sentence count <landing>..HEAD with the same anchor. Every other reader (decision health, needs_review, Do next, stale_governance) reads the stored score.
  • The Do next row claims only what the score measures: "the files it governs changed since it was recorded", and asks for a review.
  • Docs: docs/layers/DECISIONS.md staleness bullet.

Verification

Bar, written before measuring: on a copy of this repository's index, every decision that flips stale to fresh is listed. A blind judge with opaque ids reads the diffs of every commit after recording and must find 0 flipped rows with a later change to the decided behaviour. Rows flipping fresh to stale: expected 0. A held-out index with decisions is measured if one exists.

Results:

  • Stale (score >= 0.5) across active and proposed: 610 to 581. Accepted and stale: 162 to 142.
  • 29 rows flip stale to fresh (20 accepted). 4 more drop from 1.0 to 0.5. 0 rows move up and 0 flip fresh to stale.
  • Blind judging covered all 29 flips, the 4 partial moves and 10 still-stale controls, 43 rows in total. Flips with a real later change: 0 of 29. Partial moves: 0 of 4. Controls: 4 of 10 have one, which shows the judge does find real drift. There are only 29 flips, so the 30-row sample size could not be reached and every flip was judged.
  • Quarter rows in repowise next: 217 to 197.
  • Held-out: the only other local index with decisions is a Flask index. Its 24 scoped records were all mined after their commits landed, so 0 anchors move. No held-out index has records written before landing.
  • Most of the remaining stale records govern files with real later commits.
  • Tests: the new tests/unit/analysis/test_decision_landing.py runs real git. A recompute wiring test was added, and the existing decision, currency, actions, why and persist suites pass.

A decision recorded on a branch names the branch's commits, and the squash
that lands them comes after the record is created, so every such record
counted its own landing commit as a change to the files it governs and went
stale by construction. Staleness, the decision show / get_why sentence and
every reader of the stored score now count from the later of the record's
birth and the first-parent commit that landed its evidence: the commit itself,
or the one squash that names it (title or squash-body bullet) and changes its
files. Unresolved evidence keeps the birth as the anchor.

The Do next row for a drifting decision claims only what the score measures:
its files changed since it was recorded.
@RaghavChamadiya

Copy link
Copy Markdown
Member Author

The two complex-method findings (compute_staleness, describe_decision_currency) are addressed in the latest push: the staleness anchor and the currency landing lookup each moved into a small helper.

@repowise-bot

repowise-bot Bot commented Oct 21, 2026

Copy link
Copy Markdown
Check Result
Coverage 96.2% of 27 changed lines covered · 1 uncovered in 1 file
Tests 11 of 12 changed code files reached by a test · 1 with no test signal · which tests
Security No new findings on changed lines
Doc drift No drift in docs this PR edits
Coverage: 1 uncovered changed line

Patch coverage 96.2% (26 of 27 changed executable lines covered)

ed9bd08 · cobertura · 5 of 16 changed files measured, 4 out of scope

File Uncovered changed lines Covered
packages/core/src/repowise/core/analysis/decisions/staleness.py 79 5 of 6
1 changed file is not in the coverage report, so not counted
  • packages/core/src/repowise/core/analysis/decisions/landing.py

Report from this run for ed9bd08.


📊 See the full report for this PR

@swati510
swati510 merged commit da35e82 into main Oct 22, 2026
10 checks passed
@swati510
swati510 deleted the fix/decision-staleness-evidence-commit branch October 22, 2026 04:19
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.

2 participants