From 823ce9e1206125c80a75f718c36101fdba350ea1 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 21 Aug 2026 03:21:45 +0200 Subject: [PATCH 1/3] 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 --- SCOPE.md | 113 ++++++++++++++++++++++++++++++++++++++++++++++++ WORK-RECORDS.md | 2 +- 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/SCOPE.md b/SCOPE.md index 9f8f3bb..d5835b9 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -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 diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index 58ba7aa..9af5d30 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -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 | From 9d015d4604a00d1960083f4b0ffe0e6e749af724 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 21 Aug 2026 03:22:01 +0200 Subject: [PATCH 2/3] Record T07 done and the SCOPE-block root cause of T03 Co-Authored-By: Claude Opus 5 --- ...-WP-0020-coulombcore-retirement-cutover.md | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md b/workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md index 0d7298b..f7f24be 100644 --- a/workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md +++ b/workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md @@ -290,16 +290,32 @@ 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. 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. + ## Fix Wall-Clock Rot In The Plan-Check Test Suite ```task From 0300c5b14212a1ebe2bebd4afcc3483df836f39f Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 21 Aug 2026 03:23:29 +0200 Subject: [PATCH 3/3] 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 --- reuse_surface/federation.py | 25 +++++++++++++++- tests/test_federation.py | 30 +++++++++++++++++++ ...-WP-0020-coulombcore-retirement-cutover.md | 16 ++++++++-- 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/reuse_surface/federation.py b/reuse_surface/federation.py index 3c8c03e..f736667 100644 --- a/reuse_surface/federation.py +++ b/reuse_surface/federation.py @@ -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( diff --git a/tests/test_federation.py b/tests/test_federation.py index 1119100..1978c7a 100644 --- a/tests/test_federation.py +++ b/tests/test_federation.py @@ -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 diff --git a/workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md b/workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md index f7f24be..5f7549c 100644 --- a/workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md +++ b/workplans/REUSE-WP-0020-coulombcore-retirement-cutover.md @@ -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