Compare commits

...

3 commits

Author SHA1 Message Date
0300c5b142 Name the SCOPE-block mistake in compose warnings (REUSE-WP-0020-T03)
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
ci / validate-registry (push) Successful in 1m20s
Build and Publish Container Image / build-and-push (push) Successful in 34s
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>
2026-08-21 03:23:29 +02:00
9d015d4604 Record T07 done and the SCOPE-block root cause of T03
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 03:22:01 +02:00
823ce9e120 Add standard SCOPE.md sections and capability blocks (REUSE-WP-0020-T07)
Clears the hub scope check's C5b/C5c warnings: Relevant When, Not Relevant
When, How It Fits, Terminology, Related / Overlapping, and Provided
Capabilities were all missing, along with any fenced capability block.

The Terminology section calls out something this workplan ran into for real:
the fenced `capability` blocks in SCOPE.md (type/title/description/keywords)
look like index rows in registry/indexes/capabilities.yaml but are a different
shape and are not validated. evidence-binder copied the SCOPE block shape into
its index, which is why it had no `id` and broke federation composition.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 03:21:45 +02:00
5 changed files with 197 additions and 5 deletions

113
SCOPE.md
View file

@ -34,6 +34,119 @@ for reuse within this product boundary.
- Own unrelated adjacent systems or make irreversible operational decisions
without human approval.
## Relevant When
- Deciding whether a capability already exists before planning or building one
(`reuse-surface plan-check`).
- Registering a new capability so it becomes visible for reuse.
- Promoting a capability along the D/A/C/R maturity axes with evidence.
- Comparing candidate capabilities by maturity, scope, relations, and consumer
guidance.
- Detecting overlap or duplication between capabilities across repos.
- Adding a sibling repo to the federation, or debugging why its index does not
appear in the federated view.
- Recording or interpreting reuse telemetry as R-axis evidence.
---
## Not Relevant When
- Hosting, running, or operating the capabilities themselves — the registry
describes capabilities, it does not execute them.
- Looking for a package registry, service catalog, issue tracker, or project
management system. Those are different tools with different guarantees.
- Judging internal code quality. Maturity here is about discovery and delivery,
not about how the implementation is written.
- Deploying the hub. The Kubernetes release lives in `railiance-apps`
(`charts/reuse-surface/`); this repo owns the image and the deploy guide only.
- Routing credentials. See `.claude/rules/credential-routing.md` — ops-warden
issues SSH certificates, OpenBao holds secrets.
---
## How It Fits
`reuse-surface` sits between planning and implementation. A workplan or intent
is checked against the federated index before work starts; the verdict is
reuse, extend, or new. Capabilities registered by sibling repos flow in through
federation, and observed reuse flows back as maturity evidence.
- **Upstream:** each sibling repo publishes `registry/indexes/capabilities.yaml`
from its own checkout. The repo owns its entries; this registry never edits
them.
- **Here:** the federation composer merges member indexes into
`registry/indexes/federated.yaml`, and the hosted hub serves the same view at
`GET /v1/federated`.
- **Downstream:** humans and agents query the index, the CLI, or the hub before
building. `plan-check --record-outcome` returns telemetry that feeds the
R axis.
State Hub is the coordination layer, not the registry: workplans and decisions
live there, capability descriptions live here.
---
## Terminology
| Term | Meaning |
|---|---|
| **Capability** | A reusable unit of function, described by a registry entry. Not a package, not a service — either can implement one. |
| **Maturity vector** | `D / A / C / R` — Discovery, Availability, Consumability, Reliability. See `specs/CapabilityMaturityStandard.md`. |
| **Registry entry** | Markdown with YAML front matter under `registry/capabilities/`, validated against `schemas/capability.schema.yaml`. |
| **Index** | `registry/indexes/capabilities.yaml` — one row per entry, the discovery surface for this repo. |
| **Federated index** | The composed view across all member repos. |
| **Member / source** | A repo registered in `registry/federation/sources.yaml` or on the hub. |
| **Hub** | The hosted service at `https://reuse.coulomb.social` that composes and serves the federated index. |
| **Promotion** | Raising a maturity axis, backed by evidence and recorded in `promotion_history`. |
**Note on two similar formats.** The fenced `capability` blocks in a repo's
`SCOPE.md` (`type` / `title` / `description` / `keywords`) are *not* the same
shape as index rows in `registry/indexes/capabilities.yaml`
(`id` / `name` / `summary` / `vector` / `domain` / `status` / `owner` / `path` /
`tags` / `consumption_modes`). SCOPE blocks are a prose-level advertisement;
index rows are validated registry data and require an `id`. Copying one shape
into the other is a real and observed failure mode — it silently breaks
federation for that member.
---
## Related / Overlapping
| Repo / system | Relationship |
|---|---|
| **State Hub** (`~/state-hub`) | Coordination read model: workplans, tasks, decisions, progress. Complementary — it tracks *work*, this tracks *capabilities*. |
| **railiance-apps** | Owns the Kubernetes release for the hub (`charts/reuse-surface/`, RAILIANCE-WP-0007). Deploys what this repo builds. |
| **ops-warden** | Credential and access routing. Explicitly out of scope here. |
| **Sibling domain repos** | Federation members. Each owns its own entries and index; this repo owns only composition and the standard. |
| **Package registries** (PyPI, npm, OCI) | Distribute artifacts. This registry describes capabilities and may reference artifacts, but does not host them. |
---
## Provided Capabilities
```capability
type: registry
title: Capability registration and maturity assessment
description: Register capabilities as validated Markdown entries with D/A/C/R maturity vectors, promotion history, and evidence, so they become discoverable and comparable for planning and implementation reuse.
keywords: [registry, capability, maturity, discovery, promotion, reuse, governance]
```
```capability
type: service
title: Capability index federation
description: Compose capability indexes published by many repos into one federated view, served locally by CLI and in production by a hosted hub with webhook-driven refresh and staleness visibility.
keywords: [federation, index, compose, hub, webhook, capabilities, cross-repo]
```
```capability
type: tooling
title: Pre-build reuse check
description: Match a draft workplan or free-text intent against the federated capability index and return a reuse, extend, or new verdict, bridging a new verdict to a State Hub capability request and recording the outcome as reuse telemetry.
keywords: [plan-check, reuse, verdict, planning, telemetry, capability-request]
```
---
## What Is Possible Now
The MVP registry foundation, CLI tooling (REUSE-WP-0003), federation stack

View file

@ -74,7 +74,7 @@
| task | REUSE-WP-0020-T02 | done | — | workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md |
| task | REUSE-WP-0020-T03 | wait | — | workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md |
| task | REUSE-WP-0020-T04 | wait | — | workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md |
| task | REUSE-WP-0020-T05 | progress | — | workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md |
| task | REUSE-WP-0020-T05 | done | — | workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md |
| task | REUSE-WP-0020-T06 | todo | — | workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md |
| task | REUSE-WP-0020-T07 | todo | — | workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md |
| task | REUSE-WP-0020-T08 | done | — | workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md |

View file

@ -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(

View file

@ -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

View file

@ -290,16 +290,42 @@ Two smaller production inconsistencies found while verifying T01:
```task
id: REUSE-WP-0020-T07
status: todo
status: done
priority: low
```
Unrelated to the retirement, recorded so it is not lost. The hub's repo scope
check reports `C5b`/`C5c` warnings: `SCOPE.md` is missing the standard H2
check reported `C5b`/`C5c` warnings: `SCOPE.md` was missing the standard H2
sections *Relevant When*, *Not Relevant When*, *How It Fits*, *Terminology*,
*Related / Overlapping*, *Provided Capabilities*, and carries no fenced
*Related / Overlapping*, *Provided Capabilities*, and carried no fenced
capability block.
**Done 2026-08-21** (`823ce9e`). All six sections added plus three `capability`
blocks.
Writing this section surfaced the **root cause of T03**. The fenced `capability`
blocks that belong in `SCOPE.md` use `type` / `title` / `description` /
`keywords` — which is *exactly* the shape `evidence-binder` put in its
`registry/indexes/capabilities.yaml`, where the required shape is `id` / `name`
/ `summary` / `vector` / `domain` / `status` / `owner` / `path` / `tags` /
`consumption_modes`. They did not invent a broken format; they copied a valid
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, 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
```task