Skip to content

Commit 39d030e

Browse files
fix(decisions): rank a person above a document, and retire two sources that never landed (#1290)
* fix(decisions): a mined document was overwriting the user's own words SOURCE_RANK put adr (8) above session (7), and the headline-promotion branch in crud.decisions compares with >=, so 7 >= 8 was false and a transcript could never take the headline from an ADR. The audit attributes 9 of the 14 genuinely valuable records in the store to this. Swap the two. Only those two values trade places, so the ladder's value set is unchanged, MAX_SOURCE_RANK stays 9, and no other source's confidence moves; had session been lifted to a new top rank instead, compute_confidence's divisor would have shifted and every stored confidence in every existing store would have been on a different scale from every new one. adr and pr now tie at 7: both are write-ups rather than the decision being made. decision_evidence.source_rank is stamped at insert time and read straight from the column by two ORDER BY clauses, so it cannot be derived on read: the ladder is copied into every row. Without a backfill a store holds rows on both ladders and bulk_upsert_decisions derives headline confidence from max(source_rank) across the mixture, which looks like a working store and is not one. reconcile_source_ranks re-stamps them and re-derives confidence for only the decisions that moved, reusing the upsert path's own expression. It runs on the persist path rather than only in Alembic because local stores are created by init_db and never see a migration, next to the existing one-shot drain from #751. Idempotent, and a no-op scan once reconciled. Migration 0045 does the same for hosted Postgres. * feat(decisions): retire two sources that never produced a usable record readme_mining and changelog mined prose that describes a repo rather than evidence of a choice made in it. Between them they produced 153 records in this project's own store and zero that ever became active, while accounting for most of a 214-deep review queue that nobody drains because almost nothing in it is worth confirming. Both miners are deleted outright (217 lines), along with their helpers, the constants only they used, and CHANGELOG_MINING_PROMPT. README_MINING_PROMPT stays: discover_adrs borrows it for the fallback it runs on an ADR file with no recognizable structure, which is the prompt, not the source. Their names stay in SOURCE_RANK so rows written before this still rank instead of dropping to the unknown-source floor, and RETIRED_SOURCES is now the one list of what is gone. The persist path already drained code_comment (#751) from a hardcoded string; it loops over the tuple instead, so a fourth removal is wired by adding one name. The extractor docs, the rank annotations and three tests all read the same tuple. Two things found while removing the hardcoding: decision list --source had drifted into offering readme_mining while omitting session, so you could not list the records the source ladder cares most about. The choices are derived from the ladder now, minus retired names and minus the placeholder rungs no store carries. reconcile_source_ranks returned with re-derived confidence still pending in the session, so whether the repair survived depended on what the caller did next. It flushes. Also drops migration 0045 rather than fixing it. Hosted runs the same persist pipeline as a local store, so it was redundant, and worse: it corrected the ranks without re-deriving confidence, which made the runtime repair's own no-op check pass on the next run and would have left hosted confidences on the old ladder permanently. One repair path cannot disagree with itself. The confidence expression was briefly copy-pasted between the upsert path and the reconcile path. Both call _rederive_headline now, with a test that pins them to the same number.
1 parent 886bc3c commit 39d030e

17 files changed

Lines changed: 497 additions & 340 deletions

File tree

docs/layers/DECISIONS.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@ it is the only one that needs a provider.
5656
| Inline markers | `inline_marker` | `# WHY:` / `# DECISION:` / `# TRADEOFF:` / `# ADR:` / `# RATIONALE:` / `# REJECTED:` | Any comment syntax (`#`, `//`, `--`, `/*`, `*`). Up to 5 continuation lines, plus 20 lines of surrounding context. Fenced code blocks in Markdown are skipped. |
5757
| Git archaeology | `git_archaeology` | Commit messages | Gated on 19 decision verbs (migrate, switch to, replace, adopt, deprecate, drop, rewrite, split, revert, and the rest). |
5858
| PR bodies | `pr` | Squash-merge and PR commit bodies | A body only qualifies when it looks like a PR description (`## Why`, `## Motivation`, `## Context`, `Closes #`, `Before:` / `After:`). Up to 25 bodies. |
59-
| CHANGELOG | `changelog` | `CHANGELOG` / `HISTORY` / `NEWS` / `CHANGES` / release notes | keep-a-changelog `Changed` / `Removed` / `Deprecated` / `Security` sections only. `Added` is deliberately excluded: a new feature is rarely a structural decision. Up to 15 versions. |
60-
| README and docs | `readme_mining` | README and docs prose | Implicit decisions stated in prose. |
6159
| Code comments | `comment` | Block comments and docstrings on high-centrality files | Bounded to 30 nodes, and to prose carrying a rationale cue ("because", "instead of", "rather than", "trade-off", "we chose", "deliberately"). Centrality-bounded on purpose: comment archaeology across a whole repo is noise. |
6260
| Doc generation | `llm_inferred` | The wiki generation pass | The page generator proposes decisions it inferred while writing a page. Every field must survive the grounding gate below. |
6361

@@ -74,9 +72,7 @@ decisions:
7472
comment: false # skip comment archaeology
7573
# inline_marker: false
7674
# git_archaeology: false
77-
# readme_mining: false
7875
# adr: false
79-
# changelog: false
8076
# pr: false
8177
```
8278

@@ -112,9 +108,13 @@ confidence = 0.4 + 0.5 * (best_source_rank / 9)
112108
x verification penalty
113109
```
114110

115-
The rank ladder is `cli` 9, `adr` 8, `session` and `pr` 7, `commit` and
116-
`git_archaeology` 6, `changelog` 5, `inline_marker` 4, `comment` and
117-
`readme_mining` 3, and the heuristic tiers below that. The result is clamped to
111+
The rank ladder is `cli` 9, `session` 8, `adr` and `pr` 7, `commit` and
112+
`git_archaeology` 6, `inline_marker` 4, `comment` 3, and the heuristic tiers
113+
below that. `session` sits above `adr` because a transcript carries what a person
114+
actually said while deciding, and a document is someone's later write-up of it;
115+
with the order reversed the write-up overwrote the words. Retired sources keep
116+
their rungs (`changelog` 5, `readme_mining` 3) so rows written before their
117+
removal still rank instead of dropping to the unknown-source floor. The result is clamped to
118118
`[0, 0.99]`: nothing is ever certain.
119119

120120
**Sources corroborate, they do not overwrite.** The same decision found in an ADR
@@ -244,7 +244,7 @@ the primary repo. Decision ids accept an 8-character prefix.
244244
| Flag | Values |
245245
|------|--------|
246246
| `--status` | `proposed`, `active`, `deprecated`, `superseded`, `dismissed`, `all` (default) |
247-
| `--source` | `git_archaeology`, `inline_marker`, `readme_mining`, `cli`, `all` (default) |
247+
| `--source` | any source in the rank ladder except the retired ones, plus `all` (default) |
248248
| `--proposed` | Shortcut for `--status proposed` |
249249
| `--stale-only` | Only records with staleness at or above 0.5 |
250250

docs/reference/CLI_REFERENCE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ repowise decision health [PATH] # health dashboard
641641
| Flag | Description |
642642
|------|-------------|
643643
| `--status` | `active`, `proposed`, `deprecated`, `superseded`, `all` |
644-
| `--source` | `git_archaeology`, `inline_marker`, `readme_mining`, `cli`, `all` |
644+
| `--source` | `adr`, `cli`, `comment`, `commit`, `git_archaeology`, `inline_marker`, `llm_inferred`, `pr`, `session`, `all` |
645645
| `--proposed` | Shortcut for `--status proposed` |
646646
| `--stale-only` | Only stale decisions |
647647

docs/reference/CONFIG.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,7 @@ decisions:
317317
comment: false # LLM comment archaeology (top central files)
318318
# inline_marker: false # WHY:/DECISION: markers
319319
# git_archaeology: false
320-
# readme_mining: false
321-
# adr: false
320+
# adr: false
322321
# changelog: false
323322
# pr: false
324323
```

packages/cli/src/repowise/cli/commands/decision_cmd.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@
1515
resolve_command_target,
1616
run_async,
1717
)
18+
from repowise.core.analysis.decisions.provenance import LISTABLE_SOURCES
19+
20+
#: The ladder's real sources plus the no-filter sentinel. Derived, because the
21+
#: hand-written copy had drifted: it offered ``readme_mining`` (since retired)
22+
#: while omitting ``session``, the source carrying a user's own words and the
23+
#: one you would most want to filter for.
24+
_SOURCE_CHOICES: tuple[str, ...] = (*LISTABLE_SOURCES, "all")
1825

1926

2027
def _resolve_decision_repo(path: str | None):
@@ -157,7 +164,7 @@ async def _persist() -> str:
157164
)
158165
@click.option(
159166
"--source",
160-
type=click.Choice(["git_archaeology", "inline_marker", "readme_mining", "cli", "all"]),
167+
type=click.Choice(_SOURCE_CHOICES),
161168
default="all",
162169
)
163170
@click.option("--proposed", is_flag=True, default=False, help="Show only proposed decisions.")

0 commit comments

Comments
 (0)