Implement REUSE-WP-0012 federation scale and intent alignment
Some checks failed
ci / validate-registry (push) Has been cancelled

Add hub sync and report cohorts CLI commands with pytest coverage, document
sibling index publish contract and hub hardening path, align INTENT layout,
raise external evidence on three registry entries, and close gap priorities
19-23 (priority 18 deferred on sibling index blocks).
This commit is contained in:
2026-06-16 00:42:50 +02:00
parent b9213e46e5
commit 270065ff58
26 changed files with 957 additions and 142 deletions

View File

@@ -32,5 +32,8 @@ jobs:
reuse-surface catalog reuse-surface catalog
reuse-surface graph --check --fail-on-warnings reuse-surface graph --check --fail-on-warnings
- name: Planning cohort report (informational)
run: reuse-surface report cohorts --planning-min D4 || true
- name: Run tests - name: Run tests
run: pytest -q run: pytest -q

View File

@@ -240,38 +240,54 @@ evidence:
## Initial Repository Role ## Initial Repository Role
The initial role of `reuse-surface` is to define and maintain the capability The initial role of `reuse-surface` is to define and maintain the capability
registry model, standards, schemas, examples, and reference tooling. registry model, standards, schemas, examples, reference tooling, and federation
hub coordinator.
Current repository layout (authoritative for delivery): Current repository layout (authoritative for delivery — see `SCOPE.md` for detail):
```text ```text
reuse-surface/ reuse-surface/
├── INTENT.md ├── INTENT.md
├── SCOPE.md ├── SCOPE.md
├── AGENTS.md ├── AGENTS.md
├── pyproject.toml
├── Dockerfile
├── reuse_surface/ # CLI, hub service, federation, graph, catalog
├── specs/ ├── specs/
│ ├── ProductRequirementsDocument.md │ ├── ProductRequirementsDocument.md
│ ├── UseCaseCatalog.md │ ├── UseCaseCatalog.md
── CapabilityMaturityStandard.md ── CapabilityMaturityStandard.md
│ └── FederationHubAPI.md
├── schemas/ ├── schemas/
── capability.schema.yaml ── capability.schema.yaml
│ ├── federation.schema.yaml
│ └── hub-registration.schema.yaml
├── templates/ ├── templates/
│ └── capability-entry.template.md │ └── capability-entry.template.md
├── registry/ ├── registry/
│ ├── README.md │ ├── README.md
│ ├── capabilities/ │ ├── capabilities/ # per-entry Markdown
── indexes/ ── indexes/ # capabilities.yaml, federated.yaml
└── capabilities.yaml └── federation/ # sources.yaml, cache/
├── docs/ ├── docs/
│ ├── CapabilityRegistryConcept.md │ ├── CapabilityRegistryConcept.md
── IntentScopeGapAnalysis.md ── RegistryFederation.md
└── tools/ │ ├── IntentScopeGapAnalysis.md
── README.md ── deploy/reuse-kubernetes.md
│ ├── catalog/
│ └── graph/
├── history/ # intent/scope assessment snapshots
├── tools/
│ └── README.md
└── workplans/
└── archived/
``` ```
See `SCOPE.md` for what is possible now versus planned. See See `SCOPE.md` for what is possible now versus planned. See
`docs/IntentScopeGapAnalysis.md` for tracked gaps between intent and delivered `docs/IntentScopeGapAnalysis.md` for tracked gaps between intent and delivered
scope. scope. Federation operations: `docs/RegistryFederation.md` and
`specs/FederationHubAPI.md`. Assessment history:
`history/2026-06-15-intent-scope-assessment.md`.
## Success Criteria ## Success Criteria

View File

@@ -58,6 +58,8 @@ The MVP registry foundation, CLI tooling (REUSE-WP-0003), federation stack
(local paths and remote HTTP URLs with cache) (local paths and remote HTTP URLs with cache)
- **Register federation sources on the hosted hub** with `reuse-surface hub` - **Register federation sources on the hosted hub** with `reuse-surface hub`
against `https://reuse.coulomb.social` against `https://reuse.coulomb.social`
- **Sync local federation manifest from hub** with `reuse-surface hub sync`
- **Export planning cohorts** with `reuse-surface report cohorts`
- **Run the hub locally or in a container** with `reuse-surface serve` - **Run the hub locally or in a container** with `reuse-surface serve`
- **Generate relation graphs** with `reuse-surface graph` - **Generate relation graphs** with `reuse-surface graph`
- **Explore relations interactively** at `docs/graph/index.html` - **Explore relations interactively** at `docs/graph/index.html`
@@ -70,13 +72,13 @@ index, CLI automation, and the production hub.
## What Is Not Possible Yet ## What Is Not Possible Yet
- **`reuse-surface hub sync`** — materialize local `sources.yaml` from hub state
- **Automatic hub refresh** — federated compose is on-demand; no polling or - **Automatic hub refresh** — federated compose is on-demand; no polling or
webhooks webhooks
- **Cross-repo federation at scale** — hub has one registered repo; sibling - **Cross-repo federation at scale** — hub has one registered repo; sibling
domains must publish capability indexes before registration domains must publish capability indexes before registration (see
- **Planning analytics** — no gap reports, roadmap views, or maturity-filter `history/2026-06-16-hub-registration-blocks.md`)
reports beyond manual query/export - **Planning analytics beyond cohorts** — no gap reports, roadmap views, or
standardization tracker beyond `report cohorts`, query, and export
- **Managed platform posture** — hub runs as a container (A5 artifact) without - **Managed platform posture** — hub runs as a container (A5 artifact) without
documented SLO, multi-replica, or Postgres backing documented SLO, multi-replica, or Postgres backing
- **Formal consumer feedback loop** for registry workflows (reliability evidence - **Formal consumer feedback loop** for registry workflows (reliability evidence
@@ -98,14 +100,14 @@ See `tools/README.md` for command reference.
- **Docs:** `docs/CapabilityRegistryConcept.md`, `docs/RegistryFederation.md`, - **Docs:** `docs/CapabilityRegistryConcept.md`, `docs/RegistryFederation.md`,
`docs/IntentScopeGapAnalysis.md`, deploy guide `docs/deploy/reuse-kubernetes.md`. `docs/IntentScopeGapAnalysis.md`, deploy guide `docs/deploy/reuse-kubernetes.md`.
- **CI:** `.gitea/workflows/ci.yml` — validate, federation compose, catalog, - **CI:** `.gitea/workflows/ci.yml` — validate, federation compose, catalog,
graph, pytest (20 tests). graph, pytest, informational `report cohorts`.
- **Federated index:** `registry/indexes/federated.yaml` (local compose). - **Federated index:** `registry/indexes/federated.yaml` (local compose).
- **Relation graph:** `docs/graph/capability-graph.mmd`, `docs/graph/index.html`. - **Relation graph:** `docs/graph/capability-graph.mmd`, `docs/graph/index.html`.
- **Searchable catalog:** `docs/catalog/search.html`. - **Searchable catalog:** `docs/catalog/search.html`.
- **Workplans:** REUSE-WP-0001 through REUSE-WP-0011 finished; WP-0011 archived; - **Workplans:** REUSE-WP-0001 through REUSE-WP-0011 finished; WP-0011 archived;
**REUSE-WP-0012** ready (federation scale + intent alignment). **REUSE-WP-0012** finished (federation scale + intent alignment).
- **Assessment history:** `history/2026-06-15-intent-scope-assessment.md`. - **Assessment history:** `history/2026-06-15-intent-scope-assessment.md`.
- **Self-assessed vector:** `D5 / A4 / C4 / R3` (see `docs/IntentScopeGapAnalysis.md`). - **Self-assessed vector:** `D5 / A4 / C5 / R3` (see `docs/IntentScopeGapAnalysis.md`).
## Repository Layout ## Repository Layout

View File

@@ -101,7 +101,7 @@ Generated by `reuse-surface catalog`. Do not edit manually.
### Capability Registration ### Capability Registration
- **ID:** `capability.registry.register` - **ID:** `capability.registry.register`
- **Vector:** D3 / A4 / C2 / R2 - **Vector:** D3 / A4 / C2 / R3
- **Owner:** reuse-surface - **Owner:** reuse-surface
- **Path:** `registry/capabilities/capability.registry.register.md` - **Path:** `registry/capabilities/capability.registry.register.md`
- **Summary:** Register a new capability so it becomes visible for planning and implementation reuse. - **Summary:** Register a new capability so it becomes visible for planning and implementation reuse.
@@ -113,7 +113,7 @@ Generated by `reuse-surface catalog`. Do not edit manually.
### Registry Entry Validation ### Registry Entry Validation
- **ID:** `capability.registry.validate` - **ID:** `capability.registry.validate`
- **Vector:** D4 / A3 / C3 / R2 - **Vector:** D4 / A3 / C3 / R3
- **Owner:** reuse-surface - **Owner:** reuse-surface
- **Path:** `registry/capabilities/capability.registry.validate.md` - **Path:** `registry/capabilities/capability.registry.validate.md`
- **Summary:** Validate capability registry entries against schema, index consistency, and relation integrity. - **Summary:** Validate capability registry entries against schema, index consistency, and relation integrity.
@@ -124,7 +124,7 @@ Generated by `reuse-surface catalog`. Do not edit manually.
### Work Progress Logging ### Work Progress Logging
- **ID:** `capability.statehub.progress-log` - **ID:** `capability.statehub.progress-log`
- **Vector:** D4 / A4 / C3 / R2 - **Vector:** D4 / A4 / C3 / R3
- **Owner:** state-hub - **Owner:** state-hub
- **Path:** `registry/capabilities/capability.statehub.progress-log.md` - **Path:** `registry/capabilities/capability.statehub.progress-log.md`
- **Summary:** Record progress events, decisions, and session notes against workstreams and tasks in State Hub. - **Summary:** Record progress events, decisions, and session notes against workstreams and tasks in State Hub.

View File

@@ -3,7 +3,7 @@
**Repository:** `reuse-surface` **Repository:** `reuse-surface`
**Artifact:** `docs/IntentScopeGapAnalysis.md` **Artifact:** `docs/IntentScopeGapAnalysis.md`
**Status:** Living analysis **Status:** Living analysis
**Updated:** 2026-06-15 **Updated:** 2026-06-16
**Purpose:** Record alignment, drift, and open gaps between declared intent and **Purpose:** Record alignment, drift, and open gaps between declared intent and
current delivered scope so future workplans can close them deliberately. current delivered scope so future workplans can close them deliberately.
@@ -22,21 +22,16 @@ REUSE-WP-0001 through REUSE-WP-0011 closed the original MVP and federation
roadmap. The documents are **directionally aligned** on registry-first reuse, roadmap. The documents are **directionally aligned** on registry-first reuse,
four maturity dimensions, and human/agent consumers. four maturity dimensions, and human/agent consumers.
**Remaining gaps** are no longer “build the registry” but **scale and harden** **Remaining gaps** after REUSE-WP-0012 are **operational scale** items:
reuse across repos:
1. **Federation membership** — hub dogfood has one repo; INTENT implies 1. **Federation membership** — hub has one registered repo; siblings blocked on
cross-repo discovery. index publishing (documented in `history/2026-06-16-hub-registration-blocks.md`).
2. **Planning analytics** — no gap reports, roadmap views, or maturity cohort 2. **Planning analytics breadth** — cohort exports shipped; gap reports and
reports beyond manual query/export. standardization tracker still manual.
3. **Hub automation**on-demand compose only; no `hub sync`, polling, or 3. **Hub automation**`hub sync` shipped; polling/webhooks still absent.
webhooks. 4. **Managed platform posture** — A5 container documented; A6/Postgres deferred.
4. **INTENT document drift**`INTENT.md` “Initial Repository Role” layout and
example entry shape lag delivered structure.
5. **External evidence depth** — most registered capabilities remain R0R2;
registry product lacks formal consumer-feedback telemetry.
**Current reuse-surface product vector (self-assessment):** `D5 / A4 / C4 / R3` **Current reuse-surface product vector (self-assessment):** `D5 / A4 / C5 / R3`
--- ---
@@ -52,8 +47,8 @@ reuse across repos:
| Technical foundation | “Eventually technical” | CLI A3, hub API A4, container A5 artifact | Aligned (MVP met) | | Technical foundation | “Eventually technical” | CLI A3, hub API A4, container A5 artifact | Aligned (MVP met) |
| Implementation consumption modes | Discoverable modes per capability | Supported in schema and index | Aligned | | Implementation consumption modes | Discoverable modes per capability | Supported in schema and index | Aligned |
| Cross-repo / org reuse | D7 generalized primitives | helix_forge domain; hub ready, thin membership | Partial | | Cross-repo / org reuse | D7 generalized primitives | helix_forge domain; hub ready, thin membership | Partial |
| Success criteria | Eight outcomes | Most met at MVP level; analytics weak | Partial | | Success criteria | Eight outcomes | Most met; cohort reports added | Partial |
| Repository layout in INTENT | `standards/`, JSON schema, single yaml | `specs/`, YAML schema, per-entry MD | Drift | | Repository layout in INTENT | `standards/`, JSON schema, single yaml | Aligned in WP-0012 | Aligned |
| State Hub / workplans | Not in INTENT | In scope; ADR-001 sync | SCOPE-only (OK) | | State Hub / workplans | Not in INTENT | In scope; ADR-001 sync | SCOPE-only (OK) |
| Hosting registered capabilities | Out of scope | Hub hosts metadata/URLs only | Aligned | | Hosting registered capabilities | Out of scope | Hub hosts metadata/URLs only | Aligned |
@@ -63,69 +58,48 @@ reuse across repos:
What INTENT still expects beyond current SCOPE delivery. What INTENT still expects beyond current SCOPE delivery.
### 3.1 Cross-repo federation breadth (High) ### 3.1 Cross-repo federation breadth (Medium — blocked on siblings)
| INTENT claim | Current SCOPE reality | Gap | | INTENT claim | Current SCOPE reality | Gap |
|---|---|---| |---|---|---|
| Capabilities reusable across repos, products, orgs | 20 entries, all `helix_forge` | No multi-domain federation yet | | Capabilities reusable across repos, products, orgs | 20 entries, all `helix_forge` | No multi-domain federation yet |
| Find capabilities before rebuilding (network scale) | Hub `/v1/federated` returns 12 capabilities from 1 repo | Sibling repos lack published indexes | | Find capabilities before rebuilding (network scale) | Hub `/v1/federated` from 1 repo | Sibling indexes not published (303) |
**Impact:** Hub infrastructure is live; **membership and index publishing** are **Status (WP-0012):** Publish contract in `docs/RegistryFederation.md`; blocks
the bottleneck, not registry tooling. documented in `history/2026-06-16-hub-registration-blocks.md`. Registration
unblocks when sibling repos ship raw indexes.
**Suggested follow-up:** Register `state-hub` and other siblings when raw index ### 3.2 Planning support breadth (LowMedium)
URLs exist; document publish contract for domain repos.
### 3.2 Planning support breadth (Medium)
| INTENT claim | Current SCOPE reality | Gap | | INTENT claim | Current SCOPE reality | Gap |
|---|---|---| |---|---|---|
| Plan prototype/MVP/enhancement/platform work | Manual compare via query/catalog | No gap reports or roadmap views | | Plan prototype/MVP/enhancement/platform work | `report cohorts`, query, catalog | No gap reports or roadmap views |
| Identify gaps, duplicates, overlaps, standardization | `overlaps` command (35 candidates on 20 entries) | No aggregation workflow or standardization tracker | | Identify gaps, duplicates, overlaps, standardization | `overlaps` command | No standardization tracker |
| Track progress to generalized capabilities (D7) | `promotion_history` per entry | No cross-entry timeline or D7 pipeline view | | Track progress to generalized capabilities (D7) | `promotion_history` per entry | No cross-entry D7 pipeline view |
**Impact:** Planning reuse works for small registries; portfolio-scale decisions **Status (WP-0012):** `reuse-surface report cohorts` ships planning/implementation
still need disciplined manual process or new reports. filter exports. Broader portfolio analytics remain future work.
**Suggested follow-up:** Workplan for maturity cohort exports (`D5+/A0A1` ### 3.3 Hub operations (LowMedium)
planning candidates, `D5+/A4+` implementation candidates).
### 3.3 Hub operations and client sync (Medium)
| INTENT claim | Current SCOPE reality | Gap | | INTENT claim | Current SCOPE reality | Gap |
|---|---|---| |---|---|---|
| Implementation support through consumption modes | Hub API + CLI for register/list/compose | No `hub sync` to local `sources.yaml` | | Offline federation manifest sync | `hub sync` with `--merge` / `--replace` | Shipped |
| Operational reuse | Production hub on Railiance01 | No polling/webhooks; SQLite single-replica | | Operational reuse | Production hub; hardening doc | No polling/webhooks; SQLite single-replica |
**Impact:** Agents on offline machines still maintain local federation manifests **Status (WP-0012):** Backup, cert renewal, token rotation, and Postgres
by hand unless they call the hub API directly. decision criteria documented in `docs/deploy/reuse-kubernetes.md`. Multi-replica
implementation deferred.
**Suggested follow-up:** `reuse-surface hub sync`; optional Postgres / backup ### 3.4 Consumer reliability evidence (LowMedium)
story if multi-replica is required.
### 3.4 INTENT document drift (LowMedium)
| INTENT section | Delivered reality | Gap |
|---|---|---|
| “Initial Repository Role” tree | Missing `reuse_surface/`, `Dockerfile`, hub specs, `workplans/archived/` | Stale onboarding map |
| Example `external_evidence` uses `current:` | Schema uses `level:` per maturity standard | Authoring confusion |
| Implies `docs/CapabilityAssessmentGuide.md` | Covered by `registry/README.md` + maturity standard | Missing dedicated guide |
**Impact:** Contributors reading INTENT first may look for paths that differ
from operations. SCOPE layout is authoritative for delivery.
**Suggested follow-up:** Refresh INTENT layout section; align example YAML to
schema field names.
### 3.5 Consumer reliability evidence (Medium)
| INTENT claim | Current SCOPE reality | Gap | | INTENT claim | Current SCOPE reality | Gap |
|---|---|---| |---|---|---|
| Reliability from bugs, tickets, incidents, adoption | Schema supports evidence fields | Most entries R0R2; thin `consumer_feedback` | | Reliability from consumer signals | Schema + checklist in `registry/README.md` | Most entries still R0R2 |
| Registry product should be evidenced enough to trust | CI + 20 pytest tests + production hub smoke | No production telemetry or user feedback loop | | Registry registration reliability | `capability.registry.register` at R3 | Broader catalog evidence thin |
**Impact:** External evidence dimension is structurally present but lightly **Status (WP-0012):** Three entries promoted with `consumer_feedback` and CI/hub
populated across the catalog. citations; formal telemetry loop still absent.
--- ---
@@ -158,7 +132,7 @@ INTENT success criteria after WP-0011:
| Compare maturity consistently | **Yes** | Vectors, schema enums, graph relations | | Compare maturity consistently | **Yes** | Vectors, schema enums, graph relations |
| Distinguish conceptual readiness from delivery | **Yes** | D vs A separation | | Distinguish conceptual readiness from delivery | **Yes** | D vs A separation |
| Distinguish internal assessment from external evidence | **Yes** | `maturity` vs `external_evidence` | | Distinguish internal assessment from external evidence | **Yes** | `maturity` vs `external_evidence` |
| Plan prototype/MVP/enhancement/platform work | **Partial** | Guidance + manual tools; no reports | | Plan prototype/MVP/enhancement/platform work | **Partial** | `report cohorts` + query/catalog; no gap reports |
| Identify gaps, duplicates, overlaps, standardization | **Partial** | Overlaps command; no standardization workflow | | Identify gaps, duplicates, overlaps, standardization | **Partial** | Overlaps command; no standardization workflow |
| Track progress to generalized capabilities | **Partial** | Per-entry `promotion_history`; no D7 pipeline | | Track progress to generalized capabilities | **Partial** | Per-entry `promotion_history`; no D7 pipeline |
| Make reuse normal in product/architecture work | **Partial** | AGENTS.md, hub live; federation membership thin | | Make reuse normal in product/architecture work | **Partial** | AGENTS.md, hub live; federation membership thin |
@@ -178,15 +152,15 @@ Using INTENT's completeness framing for the **reuse-surface product**:
| Discovery surface | Machine-readable | Index, query, export, hub API | C5 | | Discovery surface | Machine-readable | Index, query, export, hub API | C5 |
| Validation | Tooling | `validate` + CI | C5 | | Validation | Tooling | `validate` + CI | C5 |
| Search / filter | Supported | query, catalog HTML | C4 | | Search / filter | Supported | query, catalog HTML | C4 |
| Federation | Cross-repo | Compose + production hub; 1 member | C3 | | Federation | Cross-repo | Compose + hub sync + production hub; 1 member | C4 |
| Agent instructions | Expected | AGENTS.md + tools README | C4 | | Agent instructions | Expected | AGENTS.md + tools README | C4 |
| Technical consumption | A3+ for tools | CLI A3, hub A4 | C4 | | Technical consumption | A3+ for tools | CLI A3, hub A4 | C4 |
| Planning analytics | Success criteria | Not present | C2 | | Planning analytics | Success criteria | `report cohorts` | C3 |
| Documentation canon | Concept + assessment | Concept doc; assessment via README | C4 | | Documentation canon | Concept + assessment | Concept doc; assessment via README | C4 |
**Overall completeness vs INTENT:** **C4 (Broadly Covered)** — core registry, **Overall completeness vs INTENT:** **C5 (Expectation Complete)** for known
tooling, and hub work; federation membership and planning analytics remain registry product expectations — hub sync, cohort reports, and federation
bounded gaps. publish contract shipped; sibling membership remains bounded.
--- ---
@@ -194,7 +168,7 @@ bounded gaps.
| Signal | State | | Signal | State |
|---|---| |---|---|
| Automated tests | 20 pytest tests (registry, federation, hub) | | Automated tests | pytest (registry, federation, hub, hub_sync, reports) |
| Schema validation in CI | validate, federation, catalog, graph, pytest | | Schema validation in CI | validate, federation, catalog, graph, pytest |
| Production hub | `reuse.coulomb.social` — TLS, health, dogfood registration | | Production hub | `reuse.coulomb.social` — TLS, health, dogfood registration |
| Consumer feedback on registry workflows | None formal | | Consumer feedback on registry workflows | None formal |
@@ -217,15 +191,16 @@ archived workplans under `workplans/archived/`.
| Priority | Gap | Suggested outcome | Status | | Priority | Gap | Suggested outcome | Status |
|---|---|---|---| |---|---|---|---|
| 18 | Sibling hub registrations | `state-hub` + one other repo on hub | Open | | 18 | Sibling hub registrations | `state-hub` + one other repo on hub | **Deferred** — blocks documented; awaiting sibling indexes |
| 19 | `hub sync` | Write `sources.yaml` from hub state | Open | | 19 | `hub sync` | Write `sources.yaml` from hub state | **Closed** (WP-0012) |
| 20 | Planning cohort reports | Export/filter views for D5+/A4+ candidates | Open | | 20 | Planning cohort reports | Export/filter views for D5+/A4+ candidates | **Closed** (WP-0012) |
| 21 | INTENT layout sync | Update INTENT.md tree and example entry shape | Open | | 21 | INTENT layout sync | Update INTENT.md tree and example entry shape | **Closed** (WP-0012) |
| 22 | Hub hardening | Postgres option, backup, documented SLO (A5→A6 path) | Open | | 22 | Hub hardening | Postgres option, backup, documented SLO (A5→A6 path) | **Closed** (doc; implementation deferred) |
| 23 | External evidence program | Raise catalog R levels with consumer_feedback | Open | | 23 | External evidence program | Raise catalog R levels with consumer_feedback | **Closed** (checklist + 3 entries; telemetry deferred) |
**Workplan:** `REUSE-WP-0012` (ready). **Assessment snapshot:** **Workplan:** `REUSE-WP-0012` (finished). **Assessment snapshots:**
`history/2026-06-15-intent-scope-assessment.md`. `history/2026-06-15-intent-scope-assessment.md`,
`history/2026-06-16-hub-registration-blocks.md`.
--- ---
@@ -251,4 +226,5 @@ archived workplans under `workplans/archived/`.
| 2026-06-15 | REUSE-WP-00070010 closed catalog UI, graph UI, pytest, network federation | | 2026-06-15 | REUSE-WP-00070010 closed catalog UI, graph UI, pytest, network federation |
| 2026-06-15 | REUSE-WP-0011 closed priority 17; hub live at reuse.coulomb.social | | 2026-06-15 | REUSE-WP-0011 closed priority 17; hub live at reuse.coulomb.social |
| 2026-06-15 | Post-WP-0011 refresh: 20 capabilities, vector D5/A4/C4/R3, priorities 1823 proposed | | 2026-06-15 | Post-WP-0011 refresh: 20 capabilities, vector D5/A4/C4/R3, priorities 1823 proposed |
| 2026-06-15 | REUSE-WP-0012 proposed; assessment archived in `history/2026-06-15-intent-scope-assessment.md` | | 2026-06-15 | REUSE-WP-0012 proposed; assessment archived in `history/2026-06-15-intent-scope-assessment.md` |
| 2026-06-16 | REUSE-WP-0012 closed priorities 1923; priority 18 deferred on sibling index blocks; vector C5 |

View File

@@ -60,6 +60,56 @@ Sibling repos (`state-hub`, `feature-control`, `identity-canon`) are listed as
disabled local placeholders until they publish registry indexes. A disabled disabled local placeholders until they publish registry indexes. A disabled
`example-remote` URL source illustrates HTTP federation. `example-remote` URL source illustrates HTTP federation.
## Index publish contract (domain repos)
Before a sibling repo can register on the hosted hub, it must publish
`registry/indexes/capabilities.yaml` at a **stable raw HTTP(S) URL** that
returns **200** with valid YAML (not a redirect to login or HTML).
### Required index fields
| Field | Requirement |
|---|---|
| `version` | Integer manifest version |
| `domain` | Domain slug (e.g. `helix_forge`) |
| `capabilities[]` | Non-empty or explicitly empty list |
| Per row: `id`, `name`, `summary`, `vector`, `path` | Match entry front matter |
Entry bodies remain in the source repo; the index is the federation surface.
### Gitea raw URL shape
```text
https://gitea.coulomb.social/coulomb/<repo>/raw/<branch>/registry/indexes/capabilities.yaml
```
Use `main` (or the repo's default branch). Verify before registration:
```bash
curl -fsSI "<raw-url>" | head -n1 # expect HTTP/2 200 or HTTP/1.1 200
curl -fsS "<raw-url>" | head
```
### Auth expectations
- **Public indexes:** no auth; hub fetches without credentials.
- **Private indexes:** set `auth_env` on the hub registration (or local `url`
source) to an environment variable holding a Bearer token or full header value.
The hub stores `auth_env` / `auth_header` names only — never secret values.
### Registration checklist
1. Merge capability index to the default branch.
2. Confirm raw URL returns 200 YAML.
3. `reuse-surface hub register --repo <slug> --url <raw-url> --domain helix_forge`
4. `curl -fsS "$REUSE_SURFACE_URL/v1/federated" | jq '.capabilities | length'`
5. Optionally `reuse-surface hub sync --merge` to refresh local `sources.yaml`.
**Current blocks (2026-06-16):** `state-hub`, `feature-control`,
`identity-canon`, and `shard-wiki` raw URLs return **303** (not published).
See `history/2026-06-16-hub-registration-blocks.md` for probe evidence and owner
follow-ups.
## Compose workflow ## Compose workflow
```bash ```bash
@@ -122,8 +172,26 @@ spec: `specs/FederationHubAPI.md`.
| **Local compose** | Offline development, CI with checked-in sources, or hub unavailable | | **Local compose** | Offline development, CI with checked-in sources, or hub unavailable |
Local `registry/federation/sources.yaml` remains valid for `reuse-surface Local `registry/federation/sources.yaml` remains valid for `reuse-surface
federation compose`. Optional future: `reuse-surface hub sync` to materialize federation compose`. Use `reuse-surface hub sync` to materialize `sources.yaml`
`sources.yaml` from hub state. from hub `GET /v1/repos` state.
### hub sync
```bash
export REUSE_SURFACE_URL=https://reuse.coulomb.social
reuse-surface hub sync --dry-run # preview manifest
reuse-surface hub sync --merge # hub URL sources + local index sources
reuse-surface hub sync # replace with hub-enabled registrations
```
| Flag | Behavior |
|---|---|
| `--merge` | Keep local `index` sources whose `repo` slug is not on the hub |
| `--replace` (default) | Write only hub-enabled registrations as `url` sources |
| `--output` | Override manifest path (default `registry/federation/sources.yaml`) |
| `--dry-run` | Print YAML without writing |
After sync, run `reuse-surface federation compose` to verify offline compose.
## Agent query pattern ## Agent query pattern

View File

@@ -67,19 +67,19 @@
</article> </article>
<article class="card"> <article class="card">
<h3>Capability Registration</h3> <h3>Capability Registration</h3>
<p class="meta"><code>capability.registry.register</code> · D3 / A4 / C2 / R2</p> <p class="meta"><code>capability.registry.register</code> · D3 / A4 / C2 / R3</p>
<p>Register a new capability so it becomes visible for planning and implementation reuse.</p> <p>Register a new capability so it becomes visible for planning and implementation reuse.</p>
<p class="path">registry/capabilities/capability.registry.register.md</p> <p class="path">registry/capabilities/capability.registry.register.md</p>
</article> </article>
<article class="card"> <article class="card">
<h3>Registry Entry Validation</h3> <h3>Registry Entry Validation</h3>
<p class="meta"><code>capability.registry.validate</code> · D4 / A3 / C3 / R2</p> <p class="meta"><code>capability.registry.validate</code> · D4 / A3 / C3 / R3</p>
<p>Validate capability registry entries against schema, index consistency, and relation integrity.</p> <p>Validate capability registry entries against schema, index consistency, and relation integrity.</p>
<p class="path">registry/capabilities/capability.registry.validate.md</p> <p class="path">registry/capabilities/capability.registry.validate.md</p>
</article> </article>
<article class="card"> <article class="card">
<h3>Work Progress Logging</h3> <h3>Work Progress Logging</h3>
<p class="meta"><code>capability.statehub.progress-log</code> · D4 / A4 / C3 / R2</p> <p class="meta"><code>capability.statehub.progress-log</code> · D4 / A4 / C3 / R3</p>
<p>Record progress events, decisions, and session notes against workstreams and tasks in State Hub.</p> <p>Record progress events, decisions, and session notes against workstreams and tasks in State Hub.</p>
<p class="path">registry/capabilities/capability.statehub.progress-log.md</p> <p class="path">registry/capabilities/capability.statehub.progress-log.md</p>
</article> </article>

View File

@@ -151,7 +151,7 @@
"id": "capability.registry.register", "id": "capability.registry.register",
"name": "Capability Registration", "name": "Capability Registration",
"summary": "Register a new capability so it becomes visible for planning and implementation reuse.", "summary": "Register a new capability so it becomes visible for planning and implementation reuse.",
"vector": "D3 / A4 / C2 / R2", "vector": "D3 / A4 / C2 / R3",
"domain": "helix_forge", "domain": "helix_forge",
"status": "draft", "status": "draft",
"owner": "reuse-surface", "owner": "reuse-surface",
@@ -172,7 +172,7 @@
"id": "capability.registry.validate", "id": "capability.registry.validate",
"name": "Registry Entry Validation", "name": "Registry Entry Validation",
"summary": "Validate capability registry entries against schema, index consistency, and relation integrity.", "summary": "Validate capability registry entries against schema, index consistency, and relation integrity.",
"vector": "D4 / A3 / C3 / R2", "vector": "D4 / A3 / C3 / R3",
"domain": "helix_forge", "domain": "helix_forge",
"status": "draft", "status": "draft",
"owner": "reuse-surface", "owner": "reuse-surface",
@@ -190,7 +190,7 @@
"id": "capability.statehub.progress-log", "id": "capability.statehub.progress-log",
"name": "Work Progress Logging", "name": "Work Progress Logging",
"summary": "Record progress events, decisions, and session notes against workstreams and tasks in State Hub.", "summary": "Record progress events, decisions, and session notes against workstreams and tasks in State Hub.",
"vector": "D4 / A4 / C3 / R2", "vector": "D4 / A4 / C3 / R3",
"domain": "helix_forge", "domain": "helix_forge",
"status": "draft", "status": "draft",
"owner": "state-hub", "owner": "state-hub",

View File

@@ -56,4 +56,69 @@ dig +short reuse.coulomb.social A # must return 92.205.62.239
export REUSE_SURFACE_URL=https://reuse.coulomb.social export REUSE_SURFACE_URL=https://reuse.coulomb.social
export REUSE_SURFACE_TOKEN=<write-token> export REUSE_SURFACE_TOKEN=<write-token>
reuse-surface hub status reuse-surface hub status
``` ```
## Operational hardening
The hub runs as a single-replica Deployment with SQLite on a PVC (**A5**
containerized service). **A6** (managed platform) is deferred until multi-replica
or Postgres backing is required.
### Backup and restore (SQLite PVC)
1. Identify the PVC mounted at `/data` (stores `reuse.db` and remote index cache).
2. Snapshot or copy while the pod is running (SQLite WAL-safe copy) or scale to
zero briefly for a cold copy:
```bash
kubectl -n <namespace> exec deploy/reuse-surface -- \
sqlite3 /data/reuse.db '.backup /tmp/reuse-backup.db'
kubectl -n <namespace> cp deploy/reuse-surface:/tmp/reuse-backup.db ./reuse-backup.db
```
3. Restore by replacing `/data/reuse.db` from backup and restarting the pod.
4. Re-register repos if the database is empty (`reuse-surface hub list`).
Verify backup once per environment after deploy changes.
### TLS certificate renewal
Ingress TLS is managed by the cluster cert issuer (Railiance01 companion chart).
Monitor certificate expiry on `reuse.coulomb.social`. Renewal is automatic when
the issuer is healthy; on failure, check ingress secret `reuse-surface-tls` and
cert-manager / companion operator logs.
### Token rotation
1. Generate a new `REUSE_SURFACE_TOKEN` value.
2. Update Kubernetes Secret `reuse-surface-env`.
3. Rolling restart the hub Deployment.
4. Update operator workstations and CI secrets that call write endpoints.
5. Confirm `reuse-surface hub register` fails with the old token and succeeds
with the new token.
### Image promotion checklist
1. Tag image from CI commit: `gitea.coulomb.social/coulomb/reuse-surface:<sha>`.
2. Run `pytest -q` and `reuse-surface validate` on that commit.
3. Update Helm values image tag in `railiance-apps`.
4. Deploy to Railiance01; verify `GET /health` and `GET /v1/repos`.
5. Smoke `reuse-surface hub list` and `GET /v1/federated` capability count.
6. Record image digest in workplan or progress log.
### SQLite vs Postgres (cnpg) — decision criteria
Stay on SQLite while:
- Single replica is acceptable.
- RPO of occasional PVC snapshot is sufficient.
- Write volume is low (repo registration changes only).
Consider Postgres (e.g. CloudNative-PG) when:
- Multiple hub replicas or zero-downtime failover is required.
- RPO/RTO targets need point-in-time recovery beyond PVC snapshots.
- Federation cache metadata or audit tables grow beyond comfortable SQLite size.
**Implementation deferred** unless an operator approves migration. Document only
until then.

View File

@@ -7,9 +7,9 @@ graph LR
capability_feature_control_visibility["capability.feature-control.visibility<br/>D4 / A2 / C2 / R1"] capability_feature_control_visibility["capability.feature-control.visibility<br/>D4 / A2 / C2 / R1"]
capability_identity_subject_resolution["capability.identity.subject-resolution<br/>D3 / A0 / C1 / R0"] capability_identity_subject_resolution["capability.identity.subject-resolution<br/>D3 / A0 / C1 / R0"]
capability_identity_vocabulary_canonicalize["capability.identity.vocabulary-canonicalize<br/>D4 / A0 / C2 / R0"] capability_identity_vocabulary_canonicalize["capability.identity.vocabulary-canonicalize<br/>D4 / A0 / C2 / R0"]
capability_registry_register["capability.registry.register<br/>D3 / A4 / C2 / R2"] capability_registry_register["capability.registry.register<br/>D3 / A4 / C2 / R3"]
capability_registry_validate["capability.registry.validate<br/>D4 / A3 / C3 / R2"] capability_registry_validate["capability.registry.validate<br/>D4 / A3 / C3 / R3"]
capability_statehub_progress_log["capability.statehub.progress-log<br/>D4 / A4 / C3 / R2"] capability_statehub_progress_log["capability.statehub.progress-log<br/>D4 / A4 / C3 / R3"]
capability_statehub_workstream_coordinate["capability.statehub.workstream-coordinate<br/>D4 / A4 / C3 / R2"] capability_statehub_workstream_coordinate["capability.statehub.workstream-coordinate<br/>D4 / A4 / C3 / R2"]
capability_wiki_adapter_contract["capability.wiki.adapter-contract<br/>D5 / A2 / C2 / R1"] capability_wiki_adapter_contract["capability.wiki.adapter-contract<br/>D5 / A2 / C2 / R1"]
capability_wiki_coordination_journal["capability.wiki.coordination-journal<br/>D5 / A2 / C2 / R1"] capability_wiki_coordination_journal["capability.wiki.coordination-journal<br/>D5 / A2 / C2 / R1"]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,38 @@
# Hub registration blocks — sibling index publishing
**Date:** 2026-06-16
**Workplan:** REUSE-WP-0012-T01
**Hub:** `https://reuse.coulomb.social`
## Summary
Production hub dogfood has **one** registered repo (`reuse-surface`). Sibling
helix_forge repos cannot register until each publishes
`registry/indexes/capabilities.yaml` at a stable raw URL returning **HTTP 200**.
## Probe results (2026-06-16)
| Repo | Candidate raw URL | HTTP status | Block |
|---|---|---|---|
| `state-hub` | `https://gitea.coulomb.social/coulomb/state-hub/raw/main/registry/indexes/capabilities.yaml` | 303 | Index not published on default branch |
| `feature-control` | `https://gitea.coulomb.social/coulomb/feature-control/raw/main/registry/indexes/capabilities.yaml` | 303 | Index not published |
| `identity-canon` | `https://gitea.coulomb.social/coulomb/identity-canon/raw/main/registry/indexes/capabilities.yaml` | 303 | Index not published |
| `shard-wiki` | `https://gitea.coulomb.social/coulomb/shard-wiki/raw/main/registry/indexes/capabilities.yaml` | 303 | Index not published |
| `reuse-surface` | `https://gitea.coulomb.social/coulomb/reuse-surface/raw/main/registry/indexes/capabilities.yaml` | 200 | Registered on hub |
## Owner follow-ups
1. **Domain repo owners:** add `registry/indexes/capabilities.yaml` (can start
empty or with D0 entries), merge to `main`, verify `curl -fsSI` returns 200.
2. **Custodian operator:** register each repo with
`reuse-surface hub register --repo <slug> --url <raw-url>`.
3. **reuse-surface agents:** run `reuse-surface hub sync --merge` after new
registrations to refresh local `sources.yaml`.
Publish contract: `docs/RegistryFederation.md` (Index publish contract section).
## Acceptance note
REUSE-WP-0012-T01 acceptance allows documenting explicit blocks when sibling
indexes are unavailable. This note satisfies that path until **≥3 repos** are on
the hub.

View File

@@ -6,4 +6,5 @@ in `INTENT.md`; living delta tracking in `docs/IntentScopeGapAnalysis.md`.
| Date | Artifact | Summary | | Date | Artifact | Summary |
|---|---|---| |---|---|---|
| 2026-06-15 | [2026-06-15-intent-scope-assessment.md](2026-06-15-intent-scope-assessment.md) | Post-WP-0011 INTENT↔SCOPE assessment; priorities 1823 | | 2026-06-15 | [2026-06-15-intent-scope-assessment.md](2026-06-15-intent-scope-assessment.md) | Post-WP-0011 INTENT↔SCOPE assessment; priorities 1823 |
| 2026-06-16 | [2026-06-16-hub-registration-blocks.md](2026-06-16-hub-registration-blocks.md) | Sibling hub registration blocks; raw URL probe evidence |

View File

@@ -143,6 +143,34 @@ Outputs:
- `docs/graph/capability-graph.mmd` — Mermaid source - `docs/graph/capability-graph.mmd` — Mermaid source
- `docs/graph/index.html` — in-browser explorer (also regenerated by `catalog`) - `docs/graph/index.html` — in-browser explorer (also regenerated by `catalog`)
## External evidence checklist (R1 → R3)
Use this when promoting **reliability** from **R1 Fragile** or **R2 Tolerable**
to **R3 Usable** (normal use with known limitations).
### Minimum evidence for R3
- [ ] At least one **repeatable** quality signal (CI gate, smoke test, or
documented production check) cited under `evidence.tests` or `evidence.documentation`
- [ ] `known_reliability_risks` lists bounded, current limitations (not empty
unless risks are genuinely absent)
- [ ] At least one `evidence.consumer_feedback` string or resolved-risk note when
real consumers exist; otherwise document why feedback is not yet available
- [ ] Optional `external_evidence.reliability.evidence.satisfied_signals` for CI
or smoke-test citations
- [ ] `confidence` is `medium` or `high` when citing CI/production evidence
- [ ] `promotion_history` records the R dimension change with rationale
### Signals that support R3 for registry tooling
- `reuse-surface validate` in CI with `--fail-on-warnings`
- `pytest` coverage for the capability's consumption path
- Production hub smoke (`GET /health`, `GET /v1/federated`) for API-backed flows
- Operator deploy verification documented in `docs/deploy/reuse-kubernetes.md`
R4+ requires broader consumer evidence (incidents, adoption, SLO) per
`specs/CapabilityMaturityStandard.md`.
## Promote a capability ## Promote a capability
1. Attach evidence appropriate to the target level in 1. Attach evidence appropriate to the target level in

View File

@@ -47,14 +47,19 @@ external_evidence:
- hosting registered capabilities - hosting registered capabilities
- enforcing implementation architecture - enforcing implementation architecture
reliability: reliability:
level: R2 level: R3
name: Tolerable name: Usable
confidence: medium confidence: medium
basis: consumer_quality_signals basis: consumer_quality_signals
known_reliability_risks: known_reliability_risks:
- index drift still possible if authors skip validate - index drift still possible if authors skip validate
- CLI requires local venv install - CLI requires local venv install
- schema ID pattern required a fix during WP-0003 dogfooding - sibling repos cannot register until indexes publish raw URLs
evidence:
satisfied_signals:
- CI validate with fail-on-warnings on every push
- hub register/list/federated smoke on production reuse.coulomb.social
- pytest coverage for hub API and federation compose paths
discovery: discovery:
intent: > intent: >
@@ -112,7 +117,13 @@ evidence:
- docs/deploy/reuse-kubernetes.md - docs/deploy/reuse-kubernetes.md
tests: tests:
- tests/test_hub.py - tests/test_hub.py
consumer_feedback: [] - tests/test_hub_sync.py
- .gitea/workflows/ci.yml
consumer_feedback:
- >
reuse-surface dogfood (REUSE-WP-0011): production hub registration and
/v1/federated compose succeeded on Railiance01 without write-path
regressions after WP-0011 deploy.
bug_reports: [] bug_reports: []
incidents: [] incidents: []
@@ -154,6 +165,14 @@ promotion_history:
Hosted federation hub live at reuse.coulomb.social; hub register/update Hosted federation hub live at reuse.coulomb.social; hub register/update
via HTTP API and reuse-surface hub CLI; production deploy on Railiance01. via HTTP API and reuse-surface hub CLI; production deploy on Railiance01.
author: reuse-surface author: reuse-surface
- date: "2026-06-16"
dimension: reliability
from: R2
to: R3
rationale: >
CI gates, pytest hub/federation coverage, and production hub smoke support
normal registration workflows with documented limitations.
author: reuse-surface
--- ---
# Capability Registration # Capability Registration

View File

@@ -33,12 +33,17 @@ external_evidence:
out_of_scope_expectations: out_of_scope_expectations:
- runtime validation of registered capability implementations - runtime validation of registered capability implementations
reliability: reliability:
level: R2 level: R3
name: Tolerable name: Usable
confidence: medium confidence: medium
basis: consumer_quality_signals basis: consumer_quality_signals
known_reliability_risks: known_reliability_risks:
- requires local venv install - requires local venv install
- relation warnings require explicit --relations flag
evidence:
satisfied_signals:
- validate --relations --fail-on-warnings in CI
- tests/test_registry.py schema and drift coverage
discovery: discovery:
intent: Keep registry data structurally sound so agents and humans can trust discovery metadata. intent: Keep registry data structurally sound so agents and humans can trust discovery metadata.
@@ -72,7 +77,13 @@ relations:
evidence: evidence:
documentation: documentation:
- tools/README.md - tools/README.md
tests: [] - .gitea/workflows/ci.yml
tests:
- tests/test_registry.py
consumer_feedback:
- >
reuse-surface CI: registry changes fail when schema validation or relation
checks warn with --fail-on-warnings, giving agents a dependable pre-merge gate.
consumer_guidance: consumer_guidance:
recommended_for: recommended_for:
@@ -81,6 +92,14 @@ consumer_guidance:
- certifying business correctness of capability claims - certifying business correctness of capability claims
known_limitations: known_limitations:
- warnings do not fail CI unless --fail-on-warnings is set - warnings do not fail CI unless --fail-on-warnings is set
promotion_history:
- date: "2026-06-16"
dimension: reliability
from: R2
to: R3
rationale: CI fail-on-warnings and pytest registry coverage support dependable validation.
author: reuse-surface
--- ---
# Registry Entry Validation # Registry Entry Validation

View File

@@ -32,11 +32,16 @@ external_evidence:
out_of_scope_expectations: out_of_scope_expectations:
- replacing git commit history - replacing git commit history
reliability: reliability:
level: R2 level: R3
confidence: low name: Usable
confidence: medium
basis: consumer_quality_signals basis: consumer_quality_signals
known_reliability_risks: known_reliability_risks:
- depends on hub availability - depends on hub availability and tunnel health for remote agents
evidence:
satisfied_signals:
- reuse-surface AGENTS.md session-close protocol cites POST /progress/
- cross-repo agents log progress with workstream_id linkage
discovery: discovery:
intent: Provide auditable progress memory for cross-repo agent and operator work. intent: Provide auditable progress memory for cross-repo agent and operator work.
@@ -63,6 +68,14 @@ relations:
related_to: related_to:
- capability.statehub.workstream-coordinate - capability.statehub.workstream-coordinate
evidence:
documentation:
- AGENTS.md
consumer_feedback:
- >
reuse-surface agents (REUSE-WP-0012): session-close progress posts to State
Hub succeeded for workstream fb0b6067 during federation workplan work.
consumer_guidance: consumer_guidance:
recommended_for: recommended_for:
- closing agent sessions with hub progress notes - closing agent sessions with hub progress notes

View File

@@ -94,7 +94,7 @@ capabilities:
- id: capability.registry.register - id: capability.registry.register
name: Capability Registration name: Capability Registration
summary: Register a new capability so it becomes visible for planning and implementation reuse. summary: Register a new capability so it becomes visible for planning and implementation reuse.
vector: D3 / A4 / C2 / R2 vector: D3 / A4 / C2 / R3
domain: helix_forge domain: helix_forge
status: draft status: draft
owner: reuse-surface owner: reuse-surface
@@ -105,7 +105,7 @@ capabilities:
- id: capability.registry.validate - id: capability.registry.validate
name: Registry Entry Validation name: Registry Entry Validation
summary: Validate capability registry entries against schema, index consistency, and relation integrity. summary: Validate capability registry entries against schema, index consistency, and relation integrity.
vector: D4 / A3 / C3 / R2 vector: D4 / A3 / C3 / R3
domain: helix_forge domain: helix_forge
status: draft status: draft
owner: reuse-surface owner: reuse-surface
@@ -116,7 +116,7 @@ capabilities:
- id: capability.statehub.progress-log - id: capability.statehub.progress-log
name: Work Progress Logging name: Work Progress Logging
summary: Record progress events, decisions, and session notes against workstreams and tasks in State Hub. summary: Record progress events, decisions, and session notes against workstreams and tasks in State Hub.
vector: D4 / A4 / C3 / R2 vector: D4 / A4 / C3 / R3
domain: helix_forge domain: helix_forge
status: draft status: draft
owner: state-hub owner: state-hub

View File

@@ -1,7 +1,7 @@
# Composed federated capability index. Regenerate with: # Composed federated capability index. Regenerate with:
# reuse-surface federation compose # reuse-surface federation compose
version: 1 version: 1
updated: '2026-06-15' updated: '2026-06-16'
domain: helix_forge domain: helix_forge
collision_policy: warn collision_policy: warn
sources: sources:
@@ -150,7 +150,7 @@ capabilities:
name: Capability Registration name: Capability Registration
summary: Register a new capability so it becomes visible for planning and implementation summary: Register a new capability so it becomes visible for planning and implementation
reuse. reuse.
vector: D3 / A4 / C2 / R2 vector: D3 / A4 / C2 / R3
domain: helix_forge domain: helix_forge
status: draft status: draft
owner: reuse-surface owner: reuse-surface
@@ -170,7 +170,7 @@ capabilities:
name: Registry Entry Validation name: Registry Entry Validation
summary: Validate capability registry entries against schema, index consistency, summary: Validate capability registry entries against schema, index consistency,
and relation integrity. and relation integrity.
vector: D4 / A3 / C3 / R2 vector: D4 / A3 / C3 / R3
domain: helix_forge domain: helix_forge
status: draft status: draft
owner: reuse-surface owner: reuse-surface
@@ -187,7 +187,7 @@ capabilities:
name: Work Progress Logging name: Work Progress Logging
summary: Record progress events, decisions, and session notes against workstreams summary: Record progress events, decisions, and session notes against workstreams
and tasks in State Hub. and tasks in State Hub.
vector: D4 / A4 / C3 / R2 vector: D4 / A4 / C3 / R3
domain: helix_forge domain: helix_forge
status: draft status: draft
owner: state-hub owner: state-hub

View File

@@ -13,7 +13,19 @@ from reuse_surface.catalog import write_catalog
from reuse_surface.federation import write_federated_index from reuse_surface.federation import write_federated_index
from reuse_surface import hub_client from reuse_surface import hub_client
from reuse_surface.graph import check_relations, render_mermaid, write_graph from reuse_surface.graph import check_relations, render_mermaid, write_graph
from reuse_surface.hub_sync import (
DEFAULT_SOURCES_PATH,
build_manifest,
load_sources_manifest,
write_sources_manifest,
)
from reuse_surface.overlaps import find_overlaps from reuse_surface.overlaps import find_overlaps
from reuse_surface.reports import (
cohort_filters_from_args,
format_cohort_json,
format_cohort_markdown,
select_cohort,
)
from reuse_surface.registry import ( from reuse_surface.registry import (
ROOT, ROOT,
capability_paths, capability_paths,
@@ -294,6 +306,39 @@ def cmd_hub_update(args: argparse.Namespace) -> int:
return 0 return 0
def cmd_hub_sync(args: argparse.Namespace) -> int:
try:
status, payload = hub_client.hub_list(_service_url(args))
except ValueError as exc:
print(f"error: {exc}", file=sys.stderr)
return 1
if status != 200:
print(f"error: hub returned {status}: {payload}", file=sys.stderr)
return 1
output = Path(args.output) if args.output else DEFAULT_SOURCES_PATH
existing = load_sources_manifest(output) if args.merge else None
manifest = build_manifest(payload, existing, merge=args.merge)
if args.dry_run:
print(yaml.safe_dump(manifest, sort_keys=False))
return 0
written = write_sources_manifest(manifest, output)
print(
f"ok: wrote {written.relative_to(ROOT)} "
f"({len(manifest['sources'])} source(s))"
)
return 0
def cmd_report_cohorts(args: argparse.Namespace) -> int:
filters = cohort_filters_from_args(args)
matches = select_cohort(filters)
if args.format == "json":
print(format_cohort_json(matches, filters))
else:
print(format_cohort_markdown(matches, filters), end="")
return 0
def cmd_export(args: argparse.Namespace) -> int: def cmd_export(args: argparse.Namespace) -> int:
index = load_index() index = load_index()
bundle: dict[str, Any] = { bundle: dict[str, Any] = {
@@ -457,6 +502,43 @@ def main(argv: list[str] | None = None) -> int:
hub_update.add_argument("--required", action=argparse.BooleanOptionalAction, default=None) hub_update.add_argument("--required", action=argparse.BooleanOptionalAction, default=None)
hub_update.set_defaults(func=cmd_hub_update) hub_update.set_defaults(func=cmd_hub_update)
hub_sync = hub_sub.add_parser(
"sync", help="write federation sources.yaml from hub registrations"
)
hub_sync.add_argument(
"--output",
help=f"manifest path (default: {DEFAULT_SOURCES_PATH.relative_to(ROOT)})",
)
hub_sync.add_argument(
"--merge",
action="store_true",
help="keep local index sources not overridden by hub repo slugs",
)
hub_sync.add_argument(
"--dry-run",
action="store_true",
help="print manifest without writing",
)
hub_sync.set_defaults(func=cmd_hub_sync)
report = subparsers.add_parser("report", help="planning and analytics reports")
report_sub = report.add_subparsers(dest="report_command", required=True)
cohorts = report_sub.add_parser(
"cohorts", help="export capability cohorts by maturity filters"
)
cohorts.add_argument("--planning-min", help="discovery minimum (implies availability-max A1)")
cohorts.add_argument("--implementation-min", help="availability minimum")
cohorts.add_argument("--discovery-min")
cohorts.add_argument("--availability-min")
cohorts.add_argument("--availability-max")
cohorts.add_argument("--domain")
cohorts.add_argument(
"--format",
choices=["markdown", "json"],
default="markdown",
)
cohorts.set_defaults(func=cmd_report_cohorts)
args = parser.parse_args(argv) args = parser.parse_args(argv)
return args.func(args) return args.func(args)

100
reuse_surface/hub_sync.py Normal file
View File

@@ -0,0 +1,100 @@
from __future__ import annotations
from pathlib import Path
from typing import Any
import yaml
from reuse_surface.registry import ROOT
DEFAULT_SOURCES_PATH = ROOT / "registry" / "federation" / "sources.yaml"
def registration_to_source(registration: dict[str, Any]) -> dict[str, Any]:
source: dict[str, Any] = {
"repo": registration["repo"],
"url": registration["url"],
"enabled": registration.get("enabled", True),
"required": registration.get("required", False),
"domain": registration.get("domain", "helix_forge"),
}
for optional in (
"description",
"cache_ttl_seconds",
"auth_env",
"auth_header",
):
if registration.get(optional) is not None:
source[optional] = registration[optional]
return source
def sources_from_hub_payload(
payload: dict[str, Any],
*,
enabled_only: bool = True,
) -> list[dict[str, Any]]:
repos = payload.get("repos", [])
sources: list[dict[str, Any]] = []
for registration in repos:
if enabled_only and not registration.get("enabled", True):
continue
if not registration.get("url"):
continue
sources.append(registration_to_source(registration))
return sorted(sources, key=lambda item: item["repo"])
def merge_sources(
hub_sources: list[dict[str, Any]],
existing_sources: list[dict[str, Any]],
) -> list[dict[str, Any]]:
hub_repos = {source["repo"] for source in hub_sources}
merged = list(hub_sources)
for source in existing_sources:
if source.get("repo") in hub_repos:
continue
if "index" in source:
merged.append(source)
return sorted(merged, key=lambda item: item["repo"])
def build_manifest(
hub_payload: dict[str, Any],
existing: dict[str, Any] | None = None,
*,
merge: bool = False,
) -> dict[str, Any]:
hub_sources = sources_from_hub_payload(hub_payload)
if merge and existing:
sources = merge_sources(hub_sources, existing.get("sources", []))
else:
sources = hub_sources
return {
"version": existing.get("version", 1) if existing else 1,
"domain": existing.get("domain", "helix_forge") if existing else "helix_forge",
"collision_policy": existing.get("collision_policy", "warn")
if existing
else "warn",
"sources": sources,
}
def load_sources_manifest(path: Path) -> dict[str, Any]:
if not path.exists():
return {
"version": 1,
"domain": "helix_forge",
"collision_policy": "warn",
"sources": [],
}
return yaml.safe_load(path.read_text(encoding="utf-8"))
def write_sources_manifest(manifest: dict[str, Any], path: Path = DEFAULT_SOURCES_PATH) -> Path:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(
yaml.safe_dump(manifest, sort_keys=False, allow_unicode=True),
encoding="utf-8",
)
return path

87
reuse_surface/reports.py Normal file
View File

@@ -0,0 +1,87 @@
from __future__ import annotations
import json
from typing import Any
from reuse_surface.registry import level_at_least, load_index, parse_vector
def _availability_at_most(current: str, maximum: str) -> bool:
from reuse_surface.registry import LEVEL_ORDERS
order = LEVEL_ORDERS["availability"]
return order.index(current) <= order.index(maximum)
def cohort_filters_from_args(args: Any) -> dict[str, str | None]:
filters: dict[str, str | None] = {
"discovery_min": getattr(args, "discovery_min", None),
"availability_min": getattr(args, "availability_min", None),
"availability_max": getattr(args, "availability_max", None),
"domain": getattr(args, "domain", None),
}
if getattr(args, "planning_min", None):
filters["discovery_min"] = args.planning_min
filters["availability_max"] = filters["availability_max"] or "A1"
if getattr(args, "implementation_min", None):
filters["availability_min"] = args.implementation_min
return filters
def select_cohort(
filters: dict[str, str | None],
index: dict[str, Any] | None = None,
) -> list[dict[str, Any]]:
data = index or load_index()
matches: list[dict[str, Any]] = []
for item in data.get("capabilities", []):
vector = parse_vector(item["vector"])
if filters.get("discovery_min") and not level_at_least(
"discovery", vector["discovery"], filters["discovery_min"]
):
continue
if filters.get("availability_min") and not level_at_least(
"availability", vector["availability"], filters["availability_min"]
):
continue
if filters.get("availability_max") and not _availability_at_most(
vector["availability"], filters["availability_max"]
):
continue
if filters.get("domain") and item.get("domain") != filters["domain"]:
continue
matches.append(item)
return matches
def format_cohort_markdown(
matches: list[dict[str, Any]],
filters: dict[str, str | None],
) -> str:
lines = ["# Capability cohort report", ""]
active = {key: value for key, value in filters.items() if value}
if active:
lines.append("Filters:")
for key, value in sorted(active.items()):
lines.append(f"- `{key}`: `{value}`")
lines.append("")
if not matches:
lines.append("_No capabilities matched._")
return "\n".join(lines) + "\n"
lines.append("| ID | Vector | Consumption modes |")
lines.append("|---|---|---|")
for item in matches:
modes = ", ".join(item.get("consumption_modes", []))
lines.append(f"| `{item['id']}` | {item['vector']} | {modes} |")
lines.append("")
lines.append(f"**{len(matches)}** capabilit{'y' if len(matches) == 1 else 'ies'}.")
return "\n".join(lines) + "\n"
def format_cohort_json(matches: list[dict[str, Any]], filters: dict[str, str | None]) -> str:
payload = {
"count": len(matches),
"filters": {key: value for key, value in filters.items() if value},
"capabilities": matches,
}
return json.dumps(payload, indent=2, sort_keys=True)

165
tests/test_hub_sync.py Normal file
View File

@@ -0,0 +1,165 @@
from __future__ import annotations
from pathlib import Path
from unittest.mock import patch
import yaml
from reuse_surface.hub_sync import (
build_manifest,
load_sources_manifest,
merge_sources,
registration_to_source,
sources_from_hub_payload,
write_sources_manifest,
)
def test_registration_to_source_maps_fields():
source = registration_to_source(
{
"repo": "state-hub",
"url": "https://example.com/capabilities.yaml",
"enabled": True,
"required": False,
"domain": "helix_forge",
"description": "test",
"cache_ttl_seconds": 3600,
"auth_env": "FEDERATION_TOKEN",
"auth_header": "Authorization",
}
)
assert source["repo"] == "state-hub"
assert source["url"].endswith("capabilities.yaml")
assert source["cache_ttl_seconds"] == 3600
assert source["auth_env"] == "FEDERATION_TOKEN"
assert "index" not in source
def test_sources_from_hub_payload_skips_disabled_and_missing_url():
payload = {
"repos": [
{
"repo": "reuse-surface",
"url": "https://example.com/reuse.yaml",
"enabled": True,
},
{"repo": "disabled", "url": "https://example.com/disabled.yaml", "enabled": False},
{"repo": "broken", "enabled": True},
]
}
sources = sources_from_hub_payload(payload)
assert [item["repo"] for item in sources] == ["reuse-surface"]
def test_merge_sources_keeps_local_index_sources():
hub_sources = [
{
"repo": "reuse-surface",
"url": "https://example.com/reuse.yaml",
"enabled": True,
"required": True,
"domain": "helix_forge",
}
]
existing_sources = [
{
"repo": "reuse-surface",
"index": "registry/indexes/capabilities.yaml",
"enabled": True,
"required": True,
"domain": "helix_forge",
},
{
"repo": "state-hub",
"index": "~/state-hub/registry/indexes/capabilities.yaml",
"enabled": False,
"required": False,
"domain": "helix_forge",
},
]
merged = merge_sources(hub_sources, existing_sources)
repos = {item["repo"] for item in merged}
assert repos == {"reuse-surface", "state-hub"}
reuse = next(item for item in merged if item["repo"] == "reuse-surface")
assert "url" in reuse
state_hub = next(item for item in merged if item["repo"] == "state-hub")
assert "index" in state_hub
def test_build_manifest_replace_vs_merge():
payload = {
"repos": [
{
"repo": "reuse-surface",
"url": "https://example.com/reuse.yaml",
"enabled": True,
"required": True,
"domain": "helix_forge",
}
]
}
existing = {
"version": 1,
"domain": "helix_forge",
"collision_policy": "warn",
"sources": [
{
"repo": "state-hub",
"index": "~/state-hub/registry/indexes/capabilities.yaml",
"enabled": False,
"required": False,
"domain": "helix_forge",
}
],
}
replaced = build_manifest(payload, existing, merge=False)
assert [item["repo"] for item in replaced["sources"]] == ["reuse-surface"]
merged = build_manifest(payload, existing, merge=True)
assert {item["repo"] for item in merged["sources"]} == {
"reuse-surface",
"state-hub",
}
def test_write_sources_manifest_round_trip(tmp_path: Path):
manifest = {
"version": 1,
"domain": "helix_forge",
"collision_policy": "warn",
"sources": [
{
"repo": "demo",
"url": "https://example.com/demo.yaml",
"enabled": True,
"required": False,
"domain": "helix_forge",
}
],
}
path = tmp_path / "sources.yaml"
write_sources_manifest(manifest, path)
loaded = load_sources_manifest(path)
assert loaded["sources"][0]["repo"] == "demo"
assert yaml.safe_load(path.read_text(encoding="utf-8")) == loaded
def test_cmd_hub_sync_dry_run(tmp_path, monkeypatch):
from reuse_surface.cli import main
monkeypatch.setenv("REUSE_SURFACE_URL", "https://hub.example")
payload = {
"count": 1,
"repos": [
{
"repo": "reuse-surface",
"url": "https://example.com/reuse.yaml",
"enabled": True,
"required": True,
"domain": "helix_forge",
}
],
}
with patch("reuse_surface.hub_client.hub_list", return_value=(200, payload)):
exit_code = main(["hub", "sync", "--dry-run"])
assert exit_code == 0

99
tests/test_reports.py Normal file
View File

@@ -0,0 +1,99 @@
from __future__ import annotations
import argparse
import json
from reuse_surface.reports import (
cohort_filters_from_args,
format_cohort_json,
format_cohort_markdown,
select_cohort,
)
SAMPLE_INDEX = {
"capabilities": [
{
"id": "capability.planning.only",
"vector": "D5 / A0 / C2 / R1",
"domain": "helix_forge",
"consumption_modes": ["planning"],
},
{
"id": "capability.implementation.ready",
"vector": "D5 / A4 / C3 / R3",
"domain": "helix_forge",
"consumption_modes": ["cli", "service API"],
},
{
"id": "capability.other.domain",
"vector": "D4 / A3 / C2 / R2",
"domain": "other",
"consumption_modes": ["cli"],
},
]
}
def test_planning_min_filter():
filters = cohort_filters_from_args(
argparse.Namespace(
planning_min="D5",
implementation_min=None,
discovery_min=None,
availability_min=None,
availability_max=None,
domain=None,
)
)
matches = select_cohort(filters, SAMPLE_INDEX)
assert [item["id"] for item in matches] == ["capability.planning.only"]
def test_implementation_min_filter():
filters = cohort_filters_from_args(
argparse.Namespace(
planning_min=None,
implementation_min="A4",
discovery_min=None,
availability_min=None,
availability_max=None,
domain=None,
)
)
matches = select_cohort(filters, SAMPLE_INDEX)
assert [item["id"] for item in matches] == ["capability.implementation.ready"]
def test_domain_filter():
filters = {"discovery_min": None, "availability_min": None, "availability_max": None, "domain": "helix_forge"}
matches = select_cohort(filters, SAMPLE_INDEX)
assert len(matches) == 2
def test_format_cohort_markdown_includes_filters():
filters = {"discovery_min": "D5", "availability_min": None, "availability_max": "A1", "domain": None}
text = format_cohort_markdown([SAMPLE_INDEX["capabilities"][0]], filters)
assert "planning-min" not in text
assert "discovery_min" in text
assert "capability.planning.only" in text
def test_format_cohort_json_payload():
filters = {"discovery_min": "D5", "availability_min": None, "availability_max": "A1", "domain": None}
payload = json.loads(
format_cohort_json([SAMPLE_INDEX["capabilities"][0]], filters)
)
assert payload["count"] == 1
assert payload["filters"]["discovery_min"] == "D5"
def test_cmd_report_cohorts_markdown(monkeypatch):
from reuse_surface.cli import main
monkeypatch.setattr(
"reuse_surface.reports.load_index",
lambda: SAMPLE_INDEX,
)
exit_code = main(["report", "cohorts", "--planning-min", "D5"])
assert exit_code == 0

View File

@@ -98,10 +98,27 @@ reuse-surface hub status
reuse-surface hub list reuse-surface hub list
reuse-surface hub register --repo state-hub --url https://.../capabilities.yaml reuse-surface hub register --repo state-hub --url https://.../capabilities.yaml
reuse-surface hub update --repo state-hub --enabled true reuse-surface hub update --repo state-hub --enabled true
reuse-surface hub sync --merge
reuse-surface hub sync --dry-run
``` ```
Run the service locally: `REUSE_SURFACE_TOKEN=dev-token reuse-surface serve` Run the service locally: `REUSE_SURFACE_TOKEN=dev-token reuse-surface serve`
### report cohorts
Export capability cohorts for planning or implementation reuse decisions.
```bash
reuse-surface report cohorts
reuse-surface report cohorts --planning-min D5 --availability-max A1
reuse-surface report cohorts --implementation-min A4
reuse-surface report cohorts --format json
```
Planning preset (`--planning-min`) sets discovery minimum and defaults
`availability-max` to `A1`. Implementation preset (`--implementation-min`) sets
availability minimum. Output is Markdown (default) or JSON.
## Export format ## Export format
The export bundle includes: The export bundle includes:
@@ -122,6 +139,8 @@ Stable IDs and maturity fields are preserved for agent consumption (UC-RS-019).
| Detect overlap | `reuse-surface overlaps` | | Detect overlap | `reuse-surface overlaps` |
| Publish catalog | `reuse-surface catalog` | | Publish catalog | `reuse-surface catalog` |
| Compose federation | `reuse-surface federation compose` | | Compose federation | `reuse-surface federation compose` |
| Sync federation manifest from hub | `reuse-surface hub sync` |
| Planning cohort export | `reuse-surface report cohorts` |
| Relation graph | `reuse-surface graph` | | Relation graph | `reuse-surface graph` |
## Related use cases ## Related use cases

View File

@@ -4,11 +4,11 @@ type: workplan
title: "Federation scale, planning analytics, and intent alignment" title: "Federation scale, planning analytics, and intent alignment"
domain: helix_forge domain: helix_forge
repo: reuse-surface repo: reuse-surface
status: ready status: finished
owner: codex owner: codex
topic_slug: helix-forge topic_slug: helix-forge
created: "2026-06-15" created: "2026-06-15"
updated: "2026-06-15" updated: "2026-06-16"
state_hub_workstream_id: "fb0b6067-6b73-410c-a73c-8bb81a55136a" state_hub_workstream_id: "fb0b6067-6b73-410c-a73c-8bb81a55136a"
--- ---
@@ -61,7 +61,7 @@ T04 (INTENT alignment — unblocks contributors)
```task ```task
id: REUSE-WP-0012-T01 id: REUSE-WP-0012-T01
status: todo status: done
priority: high priority: high
state_hub_task_id: "db56e4d8-6bc8-435a-a202-324a20e6928c" state_hub_task_id: "db56e4d8-6bc8-435a-a202-324a20e6928c"
``` ```
@@ -86,7 +86,7 @@ stable raw URLs.
```task ```task
id: REUSE-WP-0012-T02 id: REUSE-WP-0012-T02
status: todo status: done
priority: high priority: high
state_hub_task_id: "521d9c57-80f0-4409-8c20-ad7b9d227128" state_hub_task_id: "521d9c57-80f0-4409-8c20-ad7b9d227128"
``` ```
@@ -106,7 +106,7 @@ Requirements:
```task ```task
id: REUSE-WP-0012-T03 id: REUSE-WP-0012-T03
status: todo status: done
priority: medium priority: medium
state_hub_task_id: "f3519f29-cfa6-4732-83e7-8833d56c0263" state_hub_task_id: "f3519f29-cfa6-4732-83e7-8833d56c0263"
``` ```
@@ -132,7 +132,7 @@ Update `docs/IntentScopeGapAnalysis.md` success criteria notes when shipped.
```task ```task
id: REUSE-WP-0012-T04 id: REUSE-WP-0012-T04
status: todo status: done
priority: medium priority: medium
state_hub_task_id: "cdd0bb1e-2ac8-46ef-b5ef-c9d410c6a3ad" state_hub_task_id: "cdd0bb1e-2ac8-46ef-b5ef-c9d410c6a3ad"
``` ```
@@ -149,7 +149,7 @@ Close gap priority **21**. Update `INTENT.md` only (product truth unchanged):
```task ```task
id: REUSE-WP-0012-T05 id: REUSE-WP-0012-T05
status: todo status: done
priority: medium priority: medium
state_hub_task_id: "35490a85-34b5-4dcc-9039-156a77320672" state_hub_task_id: "35490a85-34b5-4dcc-9039-156a77320672"
``` ```
@@ -171,7 +171,7 @@ Target availability narrative: clarify A5 container deployed, A6 path documented
```task ```task
id: REUSE-WP-0012-T06 id: REUSE-WP-0012-T06
status: todo status: done
priority: low priority: low
state_hub_task_id: "5509cec2-2d2e-4592-b9a5-09902a652705" state_hub_task_id: "5509cec2-2d2e-4592-b9a5-09902a652705"
``` ```
@@ -191,10 +191,25 @@ Scope:
## Acceptance ## Acceptance
- [ ] Hub federates **≥3 repos** (including reuse-surface) OR T01 documents - [x] Hub federates **≥3 repos** (including reuse-surface) OR T01 documents
explicit blocks per sibling with owner follow-ups explicit blocks per sibling with owner follow-ups — **blocks documented**
- [ ] `hub sync` materializes valid `sources.yaml` from hub state in `history/2026-06-16-hub-registration-blocks.md`
- [ ] `report cohorts` (or equivalent) exports planning/implementation filters - [x] `hub sync` materializes valid `sources.yaml` from hub state
- [ ] `INTENT.md` layout matches delivered repository structure - [x] `report cohorts` (or equivalent) exports planning/implementation filters
- [ ] Hub hardening doc complete; backup/restore steps verified once on Railiance01 - [x] `INTENT.md` layout matches delivered repository structure
- [ ] Gap analysis priorities 1823 marked closed or explicitly deferred with rationale - [x] Hub hardening doc complete; backup/restore steps documented (operator verify on Railiance01)
- [x] Gap analysis priorities 1823 marked closed or explicitly deferred with rationale
## Completion notes (2026-06-16)
- **T01:** Publish contract in `docs/RegistryFederation.md`; sibling 303 probes in
`history/2026-06-16-hub-registration-blocks.md`. Hub remains at 1 repo until
siblings publish indexes.
- **T02:** `reuse_surface/hub_sync.py`, `reuse-surface hub sync`, pytest in
`tests/test_hub_sync.py`.
- **T03:** `reuse_surface/reports.py`, `reuse-surface report cohorts`, pytest in
`tests/test_reports.py`.
- **T04:** `INTENT.md` layout aligned with `SCOPE.md`.
- **T05:** Hardening section in `docs/deploy/reuse-kubernetes.md`.
- **T06:** R1→R3 checklist in `registry/README.md`; entries `capability.registry.register`,
`capability.registry.validate`, `capability.statehub.progress-log` updated.