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:
@@ -1231,3 +1231,31 @@ async def test_unjudged_is_what_nobody_read(seeded):
|
||||
assert got[1]["evidence"]["stamped"] == {"snippet_id": sid, "score": 0.7}
|
||||
assert got[2]["evidence"] == {}
|
||||
assert await unjudged_shapes(pid, []) == []
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
async def test_a_whole_file_snippet_makes_its_file_row_canonical(seeded):
|
||||
"""Milestone 439: a snippet recorded at a component's path, with no
|
||||
symbol, is the canon for that file row — the claim a whole-file record
|
||||
makes and a definition row never could. It still covers no definition
|
||||
inside the file."""
|
||||
from scribe.services import snippets as snippets_svc
|
||||
from scribe.services.coverage import _recorded_locations
|
||||
from scribe.services.shape_ledger import mark_canonicals
|
||||
|
||||
owner, pid = seeded["owner"], seeded["pid"]
|
||||
await sync_repo_shapes(pid, REPO, SHAPES + [
|
||||
("web/lib/StatusChip.svelte", "file", "StatusChip"),
|
||||
("web/lib/StatusChip.svelte", "css", "chip"),
|
||||
], seen_marker="c1")
|
||||
chip = await snippets_svc.create_snippet(
|
||||
owner, name="StatusChip — the one status pill",
|
||||
code="<span class=\"chip\">{label}</span>", language="svelte",
|
||||
repo="Widget", path="web/lib/StatusChip.svelte", project_id=pid,
|
||||
)
|
||||
await mark_canonicals(pid, await _recorded_locations(owner, pid))
|
||||
rows, _ = await list_project_shapes(owner, pid, path="web/lib/StatusChip.svelte")
|
||||
by = {(r.kind, r.symbol): r for r in rows}
|
||||
assert by[("file", "StatusChip")].status == "canonical"
|
||||
assert by[("file", "StatusChip")].snippet_id == int(chip.id)
|
||||
assert by[("css", "chip")].status == "unclassified"
|
||||
|
||||
Reference in New Issue
Block a user