From 5598b307fa9fb6700b725d444fe4e34ca8740d61 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Wed, 21 Oct 2026 20:12:53 -0400 Subject: [PATCH] docs(6205): coverage comments state the reason, not the instance that taught it Issue, note and milestone citations are removed along with first-deploy counts and the measured phantom-definition story; "button B" jargon becomes the divergence it names. Each block keeps its present-tense reason. Co-Authored-By: Claude Opus 5.5 --- src/scribe/services/coverage.py | 166 ++++++++++++++++---------------- 1 file changed, 82 insertions(+), 84 deletions(-) diff --git a/src/scribe/services/coverage.py b/src/scribe/services/coverage.py index 36bd0656..bfc517f0 100644 --- a/src/scribe/services/coverage.py +++ b/src/scribe/services/coverage.py @@ -1,5 +1,5 @@ """Pattern-library coverage — what fraction of a bound repo's shapes have a -recorded snippet (#2692, forge job 3 of decision #2686). +recorded snippet. The all-shapes doctrine says every shape gets recorded at first build. This module is the hoping→knowing move: it enumerates the definitions that exist in @@ -43,9 +43,9 @@ logger = logging.getLogger(__name__) # Cache key in the settings KV, on the project OWNER's user_id — the same # channel the scheduler's last-run summary uses for machine-written state. -# v2 suffix with #2788: the payload shape inverted (accounted/unclassified); -# pre-ledger blobs under the old key simply stop being found, so the card -# honestly reads "not measured yet" until the first ledger-era refresh. +# The v2 suffix marks the accounted/unclassified payload shape; a blob under +# an older key is simply not found, so the card honestly reads "not measured +# yet" until the first refresh writes the current shape. _CACHE_KEY_PREFIX = "pattern_coverage_v2_" # Files whose content can't hold definitions — the hook's skip list, verbatim, @@ -93,18 +93,15 @@ _ARROW_RE = re.compile( ) -# --- comment and string spans (#4222) ---------------------------------------- +# --- comment and string spans ----------------------------------------------- # # The matchers above are line-oriented and know nothing about what a line is # INSIDE. A wrapped docstring whose line happens to begin "class AND the …" # reads as a definition of a shape called `AND`, and that phantom reaches the -# agent mid-edit as a divergence prompt about a symbol that does not exist. -# This repo's own source minted twenty-two of them, measured by running the -# extractor over every scannable file with and without this scan. Two — -# `with` and `nobody`, out of one module docstring in -# scripts/check_dangling_styles.py — are persisted, JUDGED `code_shapes` -# rows, so the cost was never only noise in the moment. Those clear -# themselves: sync_shapes marks a row it no longer extracts as vanished. +# agent mid-edit as a divergence prompt about a symbol that does not exist — +# and, once judged, persists as a `code_shapes` row. Masking comment and +# string spans stops the phantoms; any already stored clear themselves, since +# sync_shapes marks a row it no longer extracts as vanished. # # The honest tool for .py would be `ast`, which cannot be fooled by prose at # all. It is not what this uses, because this extractor is mirrored rule for @@ -221,7 +218,7 @@ def _masked_lines(text: str, count: int) -> list[str]: class Definition(NamedTuple): - """One extracted definition with its content fingerprint (#2792). + """One extracted definition with its content fingerprint. `signature` is the definition line itself; `body_sha` hashes the block whitespace- and comment-insensitively; `body` is the block's text, held @@ -234,7 +231,7 @@ class Definition(NamedTuple): signature: str body_sha: str body: str - line: int = -1 # 0-based line the definition starts on (#2869) + line: int = -1 # 0-based line the definition starts on def _definition_on(raw: str) -> tuple[str, str] | None: @@ -253,7 +250,7 @@ def _definition_on(raw: str) -> tuple[str, str] | None: # `type` announces a definition only when something is declared after # the name (`type Foo = …`, `type Foo struct {`); an import specifier # (`import { type Foo, bar }`) is the same two words and defines - # nothing — it showed up as a two-file "identical body" family (#2904). + # nothing, and would read as a two-file "identical body" family. if line.startswith("type") and not re.search(r"[={]", line[m.end():]): return None return ("sym", name) @@ -325,10 +322,10 @@ def extract_definitions(text: str) -> list[Definition]: end = j break block = lines[i:end] - # A CSS rule's fingerprint is its DECLARATIONS, not its selector - # (#2872): the row's identity already carries the selector. Since - # note 2917 the derive grouping no longer reads CSS bodies at all (a - # class is grouped by name only), so for CSS the fingerprint is the + # A CSS rule's fingerprint is its DECLARATIONS, not its selector: + # the row's identity already carries the selector. The derive + # grouping does not read CSS bodies at all (a class is grouped by + # name only), so for CSS the fingerprint is the # recheck identity — "did this rule's body change since it was # judged?" — and nothing more. The shape of the hash is kept as-is on # purpose: changing it would flip every judged CSS row to recheck on @@ -336,20 +333,20 @@ def extract_definitions(text: str) -> list[Definition]: if kind == "css": # One-line rules (`.x { color: red; }`) carry their declarations on # the selector line itself; a block that is only the selector plus - # trailing blanks must not hash to the empty string (which grouped - # 68 unrelated one-liners as one "copy" on first deploy, #2872). + # trailing blanks must not hash to the empty string, which would + # group every unrelated one-liner as one "copy". first = lines[i] brace = first.find("{") head = [first[brace + 1:]] if brace >= 0 and first[brace + 1:].strip() else [] hashed = head + block[1:] if not any(x.strip() for x in hashed): hashed = block - # A SINGLE declaration is not a shape (#2903): `color: var(--fs- + # A SINGLE declaration is not a shape: `color: var(--fs- # text-tertiary)` under .text-muted, .task-mark and .pin-badge-auto # is three meanings sharing one line, not three copies of one # rule. Keep the selector in the hash for one-liners; two - # declarations and up stay selector-agnostic. (Moot for grouping - # since note 2917, kept for fingerprint stability — see above.) + # declarations and up stay selector-agnostic. (Moot for grouping, + # kept for fingerprint stability — see above.) elif _declaration_count(hashed) < 2: hashed = block else: @@ -361,19 +358,20 @@ def extract_definitions(text: str) -> list[Definition]: return out -# --- by-construction scope (#2869) ------------------------------------------- +# --- by-construction scope --------------------------------------------------- # # A Vue single-file component's `