Name the SCOPE-block mistake in compose warnings (REUSE-WP-0020-T03)
An index row with no id now says whether it looks like a SCOPE.md capability block, instead of leaving the author to work out why their repo contributes nothing to the federated index. That confusion is invisible without a diagnostic: the row is valid YAML, the file parses, and the member just silently disappears. Swept all 61 federation sources with --refresh: evidence-binder is the only affected member. The other ten zero-count repos are genuine empty scaffolds. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
9d015d4604
commit
0300c5b142
3 changed files with 67 additions and 4 deletions
|
|
@ -183,6 +183,26 @@ def resolve_source_index_path(
|
|||
return _write_remote_cache(source["repo"], url, content, cache_dir), warnings
|
||||
|
||||
|
||||
SCOPE_BLOCK_KEYS = {"type", "title", "description", "keywords"}
|
||||
|
||||
|
||||
def _shape_hint(item: dict[str, Any]) -> str:
|
||||
"""Name the likely mistake when an index row has no id.
|
||||
|
||||
The fenced `capability` blocks in a repo's SCOPE.md use
|
||||
type/title/description/keywords, which is close enough to an index row to
|
||||
be copied into one by mistake — and then the member silently contributes
|
||||
nothing. Say so instead of leaving the author to guess.
|
||||
"""
|
||||
if SCOPE_BLOCK_KEYS & set(item):
|
||||
return (
|
||||
" — looks like a SCOPE.md capability block"
|
||||
" (type/title/description/keywords); an index row needs"
|
||||
" id/name/summary/vector/domain/status/owner/path"
|
||||
)
|
||||
return ""
|
||||
|
||||
|
||||
def _read_index_entries(
|
||||
index_path: Path, repo: str
|
||||
) -> tuple[list[Any], list[str]]:
|
||||
|
|
@ -234,7 +254,10 @@ def compose_federated_index(
|
|||
continue
|
||||
cap_id = item.get("id")
|
||||
if not cap_id:
|
||||
warnings.append(f"{source['repo']}: capability #{position} has no id, skipped")
|
||||
warnings.append(
|
||||
f"{source['repo']}: capability #{position} has no id, skipped"
|
||||
f"{_shape_hint(item)}"
|
||||
)
|
||||
continue
|
||||
if cap_id in seen_ids:
|
||||
warnings.append(
|
||||
|
|
|
|||
|
|
@ -283,3 +283,33 @@ def test_malformed_source_still_listed_with_zero_count(tmp_path, monkeypatch):
|
|||
)
|
||||
remote = next(s for s in federated["sources"] if s["repo"] == "remote-repo")
|
||||
assert remote["count"] == 0
|
||||
|
||||
|
||||
def test_scope_shaped_row_names_the_mistake(tmp_path, monkeypatch):
|
||||
"""A SCOPE.md capability block copied into an index should say so."""
|
||||
body = """
|
||||
version: 1
|
||||
domain: helix_forge
|
||||
capabilities:
|
||||
- type: library
|
||||
title: Evidence-to-target binding
|
||||
description: Links evidence items to structured targets.
|
||||
keywords: [evidence, binding]
|
||||
"""
|
||||
_, warnings = _compose_with_remote_body(body, tmp_path, monkeypatch)
|
||||
hint = next(w for w in warnings if "remote-repo" in w)
|
||||
assert "SCOPE.md capability block" in hint
|
||||
assert "id/name/summary" in hint
|
||||
|
||||
|
||||
def test_plain_missing_id_gets_no_scope_hint(tmp_path, monkeypatch):
|
||||
body = """
|
||||
version: 1
|
||||
capabilities:
|
||||
- name: Has a name but no id
|
||||
summary: Something
|
||||
"""
|
||||
_, warnings = _compose_with_remote_body(body, tmp_path, monkeypatch)
|
||||
hint = next(w for w in warnings if "remote-repo" in w)
|
||||
assert "has no id" in hint
|
||||
assert "SCOPE.md" not in hint
|
||||
|
|
|
|||
|
|
@ -312,9 +312,19 @@ blocks that belong in `SCOPE.md` use `type` / `title` / `description` /
|
|||
one from the wrong place.
|
||||
|
||||
That makes it a systemic trap rather than a one-off mistake, so the Terminology
|
||||
section now documents the distinction explicitly. Worth a follow-up: `validate`
|
||||
could detect SCOPE-shaped rows in an index and say so by name, and `report gaps`
|
||||
could sweep the federation for other members with the same confusion.
|
||||
section now documents the distinction explicitly, and the compose warning now
|
||||
names it:
|
||||
|
||||
```
|
||||
evidence-binder: capability #0 has no id, skipped — looks like a SCOPE.md
|
||||
capability block (type/title/description/keywords); an index row needs
|
||||
id/name/summary/vector/domain/status/owner/path
|
||||
```
|
||||
|
||||
**Federation swept 2026-08-21.** Composed all 61 sources with `--refresh`:
|
||||
`evidence-binder` is the **only** affected member. The other ten zero-count
|
||||
repos are genuine empty scaffolds and produced no warnings, so the confusion has
|
||||
not spread.
|
||||
|
||||
## Fix Wall-Clock Rot In The Plan-Check Test Suite
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue