feat(shapes): a component file is a candidate shape in its own right (milestone 439 step 5)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 52s
CI & Build / integration (push) Successful in 54s
CI & Build / Build & push image (push) Canceled after 0s
CI & Build / Python tests (push) Canceled after 1m42s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 52s
CI & Build / integration (push) Successful in 54s
CI & Build / Build & push image (push) Canceled after 0s
CI & Build / Python tests (push) Canceled after 1m42s
A single-file component defines `.card`, `.title` and a `Props`, never anything named after itself — so the ledger could not hold "StatusChip is canon" and could not say a new card was built where one already existed. - coverage.is_file_unit: a file that RENDERS (its markup names classes, or it opens a <script>/<template>/<style> block) and defines nothing named after its stem gets one `file` row. Structural, not a framework list: Svelte and Vue components qualify, a TSX component already has its function's row, a module is accounted for by its definitions. Emitting every file would have put every module of every project in the todo at once. - No body fingerprint on file rows, so an edit never re-asks a judgment. - `file` is its own form and family; derive grouping skips it (`index`, `+page` repeat by convention). Divergence buckets it on its own, so a new component where a component canon dominates is a fair question. - mark_canonicals: a snippet recorded at a path with no symbol makes that file row canonical; it still covers no definition inside. - The write hooks apply the same test before noting a new file for the end-of-turn question. Plugin version minted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -408,6 +408,11 @@ async def mark_canonicals(
|
||||
fall back to unclassified. Agent judgments are never overwritten.
|
||||
"""
|
||||
usable = [(nid, p, s) for nid, p, s in recorded if (s or "").strip()]
|
||||
# A location naming a FILE and no symbol is a whole-file record: it makes
|
||||
# no claim about a definition inside (`location_covers`), but it is
|
||||
# exactly the claim a `file` row asks about (milestone 439).
|
||||
whole_files = {(p or "").strip(): nid for nid, p, s in recorded
|
||||
if (p or "").strip() and not (s or "").strip()}
|
||||
now = datetime.now(timezone.utc)
|
||||
async with async_session() as session:
|
||||
rows = (
|
||||
@@ -426,6 +431,8 @@ async def mark_canonicals(
|
||||
),
|
||||
None,
|
||||
)
|
||||
if covering is None and row.kind == "file":
|
||||
covering = whole_files.get(row.path)
|
||||
if covering is not None and row.status in _MECHANICAL_TODO:
|
||||
await _judge(session, row, status="canonical", snippet_id=covering,
|
||||
by="mechanical", reason=None, at=now)
|
||||
@@ -991,6 +998,10 @@ def shape_form(signature: str, kind: str = "sym") -> str:
|
||||
"""
|
||||
if kind == "css":
|
||||
return "css"
|
||||
if kind == "file":
|
||||
# A whole file (milestone 439): its own family, comparable only with
|
||||
# other files — a component is never told to build from a helper.
|
||||
return "file"
|
||||
sig = (signature or "").strip()
|
||||
if not sig:
|
||||
return FORM_UNKNOWN
|
||||
@@ -1085,6 +1096,8 @@ def shape_family(form: str) -> str:
|
||||
return "value"
|
||||
if form == "css":
|
||||
return "css"
|
||||
if form == "file":
|
||||
return "file"
|
||||
return ""
|
||||
|
||||
|
||||
@@ -2040,6 +2053,10 @@ async def apply_derive_groups(project_id: int) -> int:
|
||||
CodeShape.status.in_(_MECHANICAL_TODO),
|
||||
CodeShape.vanished_at.is_(None),
|
||||
CodeShape.proposed_snippet_id.is_(None),
|
||||
# A file row is named by its stem, and `index`, `+page`
|
||||
# and `__init__` repeat by convention, not by copying —
|
||||
# a derive family of them would be pure noise.
|
||||
CodeShape.kind != "file",
|
||||
)
|
||||
)
|
||||
).scalars().all()
|
||||
|
||||
Reference in New Issue
Block a user