Files
the-custodian/workplans/CUST-WP-0002-contribution-tracking-sbom.md
tegwick d96ed44c57 feat(maintenance): add stale-task cleanup scheme
- scripts/cleanup_stale_tasks.py: daily script that cancels open tasks
  in completed/archived workstreams; handles 307 redirects; emits a
  cleanup progress event summarising results
- Makefile: add cleanup-stale target (also suitable for cron)
- ADR-001: append Workstream Closure Protocol section — mandatory closure
  review before marking workstream completed, with task classification
  table (done/cancelled/carry-forward) and Closure Review file format
- WP-0002 + WP-0005: append Closure Review sections documenting the
  2026-03-02 cleanup run (26 stale DB rows cancelled — all were legacy
  pre-ADR-001 DB-first records; file status was already done)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 00:32:35 +01:00

12 KiB
Raw Blame History

id, type, title, domain, status, owner, topic_slug, state_hub_workstream_id, created, updated
id type title domain status owner topic_slug state_hub_workstream_id created updated
CUST-WP-0002 workplan State Hub v0.3 — Contribution Tracking & SBOM custodian completed custodian custodian 2446400d-6d01-4679-a314-92af0601c608 2026-02-26 2026-02-28

State Hub v0.3 — Contribution Tracking & SBOM

Summary

Establish the custodian as the central authority for cross-repo upstream contribution management (bug reports, feature requests, extension points, upstream PRs) and software supply-chain transparency (SBOM aggregation, licence governance).

Context

Three interconnected layers:

  • Layer 1 — Convention & Canon: define contrib/ directory structure and artifact types (BR, FR, EP, UPR) in markdown with typed YAML frontmatter.
  • Layer 2 — Schema & API: DB tables for contributions, repos (deferred to v0.5), and SBOM entries; FastAPI routers.
  • Layer 3 — MCP Tools & Dashboard: tracking tools and Observable pages.

Dependencies

  • Depends on: dynamic-domains-multi-repo (v0.5, CUST-WP-0005). Four tasks in this workplan (P2.2, P2.4, P3.2, P4.1) are reduced in scope because v0.5 supersedes their original designs:
    • managed_repos table → done by v0.5 P2.1
    • /repos/ API router → done by v0.5 P2.2
    • register_repo MCP tool → done by v0.5 P3.1
    • Base registration workflow → done by v0.5 P2.3
  • state_hub_dep_id: 2033172d-2462-4253-acb7-cb64c7432480

Phase 1 — Convention & Canon

P1.1 — Write canon/standards/contribution-convention_v0.1.md

id: CUST-WP-0002-T01
state_hub_task_id: c2d7df02-5f37-4c02-a418-fe7ab0050edc
status: done
priority: high

Define the master contrib/ convention: directory layout, artifact types (BR/FR/EP/UPR), frontmatter schema per type, ID schemes (EP--NNN for EPs; date-prefixed slug for others), status lifecycle, and relationship to state-hub. Authoritative reference for other repos.

P1.2 — Create contrib/ templates for BR, FR, EP, UPR

id: CUST-WP-0002-T02
state_hub_task_id: 5ef89639-950c-4d57-9578-6d0211edc2df
status: done
priority: high

Four Markdown template files under canon/standards/contrib-templates/: br-template.md, fr-template.md, ep-template.md, upr-template.md. Each has typed YAML frontmatter matching the schema in P1.1 plus a guided prose skeleton.

P1.3 — Store Observable Framework TOC sidebar UPR as first artifact

id: CUST-WP-0002-T03
state_hub_task_id: e8251873-647c-4a4b-b283-298260b19c22
status: done
priority: medium

Create contrib/upstream-prs/2026-02-26--observablehq--framework--toc-sidebar-inject.md using the UPR template. Captures: summary of the injectTocTop utility, motivation, link to local component, target upstream file, draft PR body. Status: draft.

P1.4 — Align Railiance EP convention docs with canon master spec

id: CUST-WP-0002-T04
state_hub_task_id: 1c982457-de52-4fc1-a439-3bf3120bb5b6
status: done
priority: low

The staged-promotion-lifecycle workstream defines EP-RAIL-NNN IDs and inline doc markers. Review and update so the Railiance convention is a proper instance of the custodian master spec, not a parallel one.

Phase 2 — Schema & API

P2.1 — Design and implement contributions DB table + migration

id: CUST-WP-0002-T05
state_hub_task_id: c41d71bd-dc88-4201-bd9a-3f8a4eae4910
status: done
priority: high

Add contributions table: id (UUID PK), type (enum: br|fr|ep|upr), target_org, target_repo, slug, title, status (enum: draft|submitted|acknowledged|accepted|rejected|merged|withdrawn), body_path (relative path to .md file), related_topic_id (nullable FK), related_workstream_id (nullable FK), submitted_at, resolved_at, notes, created_at, updated_at. Alembic migration.

P2.2 — sbom_entries table + migration (managed_repos deferred to v0.5)

id: CUST-WP-0002-T06
state_hub_task_id: 28c9bd38-05d8-4466-bff3-3ba4e3957635
status: done
priority: high

SCOPE REDUCED — managed_repos superseded by v0.5 P2.1.

Do not create managed_repos here. After v0.5 P2.1 lands, add sbom_source (text) and last_sbom_at (timestamp) columns to the existing managed_repos table via an additive migration.

Then create sbom_entries table: id (UUID PK), repo_id (FK managed_repos), package_name, package_version, ecosystem, license_spdx (nullable), is_direct (bool), is_dev (bool), snapshot_at (timestamp — new ingest replaces old entries for that repo), created_at.

Prerequisite: v0.5 P2.1 (managed_repos table) must be complete.

P2.3 — Implement /contributions/ router (CRUD + status patch)

id: CUST-WP-0002-T07
state_hub_task_id: ee1cd17c-6dbd-4321-bb72-4499147c4837
status: done
priority: high

FastAPI router: GET list (filter by type, status, target_repo), POST create, GET by id, PATCH status (validates lifecycle transitions), soft delete (sets status=withdrawn). Schemas: ContributionCreate, ContributionRead, ContributionStatusPatch. Add contribution_counts to /state/summary.

P2.4 — Implement /sbom/ router (basic /repos/ endpoints implemented by v0.5)

id: CUST-WP-0002-T08
state_hub_task_id: 25f7ab5c-69d8-41d7-a108-38380eb1f3a9
status: done
priority: high

SCOPE REDUCED — /repos/ superseded by v0.5 P2.2.

This task covers the /sbom/ router only:

  • POST /sbom/ingest — accept repo_slug + list of package entries; replace existing snapshot for that repo.
  • GET /sbom/ — aggregated view across all repos, grouped by license_spdx.
  • GET /sbom/{repo_slug}/ — single-repo SBOM.
  • GET /sbom/report/licences/ — counts and repo lists per SPDX identifier, flagging copyleft (GPL/AGPL/LGPL).
  • Add licence_risk_count to /state/summary.

Prerequisite: v0.5 P2.1 (managed_repos) and P2.2 (sbom_entries) must be complete.

P2.5 — Write make ingest-sbom tooling (pyproject + package.json parsers)

id: CUST-WP-0002-T09
state_hub_task_id: edcf9b02-8177-4abc-b133-d303cc7ea19d
status: done
priority: medium

scripts/ingest_sbom.py: parses uv.lock (Python deps with licence metadata), package-lock.json / yarn.lock (Node deps); outputs normalised list; POSTs to /sbom/ingest/. Makefile target: make ingest-sbom REPO=<slug>. Composable into make seed.

Phase 3 — MCP Tools & Dashboard

P3.1 — New MCP tools: register_contribution, update_contribution_status, get_contributions

id: CUST-WP-0002-T10
state_hub_task_id: 51b2999b-a9c7-4871-8ef8-f5c927ac2454
status: done
priority: high
  • register_contribution(type, target_org, target_repo, title, body_path, related_workstream_id?, notes?) → ContributionRead
  • update_contribution_status(contribution_id, status, notes?) → ContributionRead
  • get_contributions(type?, status?, target_repo?) → list
  • Add state://contributions resource.

P3.2 — New MCP tools: ingest_sbom, get_licence_report (register_repo implemented by v0.5)

id: CUST-WP-0002-T11
state_hub_task_id: 20c5c2ae-7758-42cc-885c-a886957e44c2
status: done
priority: high

SCOPE REDUCED — register_repo superseded by v0.5 P3.1.

  • ingest_sbom(repo_slug: str, lockfile_path: str) — calls scripts/ingest_sbom.py, POSTs result to /sbom/ingest/.
  • get_licence_report() — returns licence groups with copyleft flag from /sbom/report/licences/.
  • Add resources: state://sbom/aggregated, state://sbom/{repo_slug}.

Prerequisite: v0.5 P3.1 (register_repo tool) and P2.4 (/sbom/ router) must be complete.

P3.3 — Dashboard: contributions.md page

id: CUST-WP-0002-T12
state_hub_task_id: 1eb13411-b2da-4d0d-8fe2-e926d029c50f
status: done
priority: medium

New Observable Framework page. Layout: filter bar (type, status, target_repo), status Kanban columns (draft → submitted → acknowledged → accepted/rejected/merged), count KPIs per type. Chart: contribution velocity over time (cumulative, same period selector as decisions page). Apply injectTocTop for page-level KPI.

P3.4 — Dashboard: sbom.md page

id: CUST-WP-0002-T13
state_hub_task_id: 1267f313-1bf3-4059-8276-bfefcd9f6aed
status: done
priority: medium

New Observable Framework page. Aggregated dependency table: package, version, licence, repos using it, direct/dev flags. Licence summary donut chart (MIT vs Apache-2.0 vs GPL family vs other). Copyleft risk section (red highlight for GPL/AGPL/LGPL in direct prod deps). Per-repo drill-down accordion. Register in observablehq.config.js.

P3.5 — Update index.md overview to surface contribution and SBOM health

id: CUST-WP-0002-T14
state_hub_task_id: abab0022-d3a4-45ef-a7e1-e0e7c05d295f
status: done
priority: low

Add contribution counts KPI card (total, by type, any needing follow-up). Add licence risk indicator (green if no copyleft in direct prod deps, red otherwise). Uses /state/summary fields added in P2.3 and P2.4.

Phase 4 — Repo Integration Tooling

P4.1 — Add sbom_source prompt + ingest-sbom step to registration workflow (base workflow by v0.5)

id: CUST-WP-0002-T15
state_hub_task_id: 47987720-23db-4465-861b-1f93bb1bb391
status: done
priority: low

SCOPE REDUCED — base registration workflow superseded by v0.5 P2.3.

SBOM-specific additions to the workflow:

  1. Extend the add-repo command to prompt for ecosystem and sbom_source (path or URL to lockfile).
  2. Optionally run make ingest-sbom REPO=<slug> automatically at end of registration.
  3. Update project_claude_md.template to document the contrib/ convention, SBOM MCP tools, and make ingest-sbom target.

Prerequisite: v0.5 P2.3 (updated registration workflow) must be complete.


Closure Review — 2026-03-02

Outcome: All 15 tasks completed. No carry-forwards. No dropped tasks.

Context: This workplan was created DB-first on 2026-02-28, before ADR-001 was formalised. The workplan file correctly recorded all tasks as status: done, but the DB rows were never synced from the file — they remained in their initial todo state in the database. The daily stale-task cleanup script (scripts/cleanup_stale_tasks.py) detected these 15 stale DB rows and cancelled them on 2026-03-02. No actual work was lost: all deliverables in Phase 14 were shipped as part of State Hub v0.3.

Completed (DB updated at delivery time; file status = done)

  • CUST-WP-0002-T01 — Write canon/standards/contribution-convention_v0.1.md
  • CUST-WP-0002-T02 — Create contrib/ templates for BR, FR, EP, UPR
  • CUST-WP-0002-T03 — Store Observable Framework TOC sidebar UPR as first artifact
  • CUST-WP-0002-T04 — Align Railiance EP convention docs with canon master spec
  • CUST-WP-0002-T05 — Design and implement contributions DB table + migration
  • CUST-WP-0002-T06 — sbom_entries table + migration
  • CUST-WP-0002-T07 — Implement /contributions/ router (CRUD + status patch)
  • CUST-WP-0002-T08 — Implement /sbom/ router
  • CUST-WP-0002-T09 — Write make ingest-sbom tooling
  • CUST-WP-0002-T10 — New MCP tools: register_contribution, update_contribution_status, get_contributions
  • CUST-WP-0002-T11 — New MCP tools: ingest_sbom, get_licence_report
  • CUST-WP-0002-T12 — Dashboard: contributions.md page
  • CUST-WP-0002-T13 — Dashboard: sbom.md page
  • CUST-WP-0002-T14 — Update index.md overview to surface contribution and SBOM health
  • CUST-WP-0002-T15 — Add sbom_source prompt + ingest-sbom step to registration workflow

Cancelled (DB records only — legacy stale rows, not real cancellations)

All 15 DB task rows were cancelled by the cleanup script. The workplan file was authoritative; the DB rows were artefacts of the pre-ADR-001 DB-first creation pattern. This does not reflect a change in work outcome.