From 50f4564561212c2a2f1550b4a4d2258f72278b82 Mon Sep 17 00:00:00 2001 From: tegwick Date: Mon, 22 Jun 2026 01:36:31 +0200 Subject: [PATCH] Resolve CUST-WP-0050 D1: repo-anchored model + ADR-005 Adopt the repo as the primary workplan anchor: repo_id becomes required, market-domain is derived from each repo's classification, and the domain/topic spine is demoted/retired (RepoGoal becomes the goal primitive). Add task T10 for the re-anchor plus the workstream -> workplan rename across schema/API/MCP. Add ADR-005 (Cross-Repo Workplans Live in Dedicated Project Repos): complex cross-repo efforts get their own project repo (category: project) as the anchor, retired to archive on completion with results living on in the modified product repos. Rewrite D1 as resolved and add D1a for the project-repo naming/archival convention. Co-Authored-By: Claude Opus 4.8 --- ...-005-cross-repo-workplans-project-repos.md | 113 ++++++++++++++++++ ...po-classification-registration-redesign.md | 102 +++++++++++++--- 2 files changed, 198 insertions(+), 17 deletions(-) create mode 100644 canon/architecture/adr-005-cross-repo-workplans-project-repos.md diff --git a/canon/architecture/adr-005-cross-repo-workplans-project-repos.md b/canon/architecture/adr-005-cross-repo-workplans-project-repos.md new file mode 100644 index 0000000..e5a3829 --- /dev/null +++ b/canon/architecture/adr-005-cross-repo-workplans-project-repos.md @@ -0,0 +1,113 @@ +--- +id: ADR-005 +type: architecture-decision-record +title: "Cross-Repo Workplans Live in Dedicated Project Repos" +status: accepted +decided_by: Bernd Worsch +date: "2026-06-22" +tags: ["architecture", "state-hub", "workplans", "cross-repo", "project-repo", "source-of-truth", "lifecycle"] +--- + +# ADR-005: Cross-Repo Workplans Live in Dedicated Project Repos + +## Status + +Accepted. + +## Context + +ADR-001 established that workplans and work items originate as files in the +repository that owns them, so the State Hub can rebuild its coordination state +from repo-owned files alone. The repo-classification redesign (`CUST-WP-0050`) +takes the next step: it makes the **repo the primary anchor** for a workplan +(`workstreams.repo_id` becomes required) and **derives** the market-domain from +the repo's `.repo-classification.yaml` rather than maintaining a separate +`topic`/`domain` spine. Repos are the most stable, git-managed entities in the +ecosystem; binding to them is the most durable anchor available. + +This raises an unavoidable question: **what anchors a genuinely cross-repo +workplan?** Some efforts coordinate change across many repositories — ecosystem +migrations, the FOS hub bootstrap (`CUST-WP-0025`), or `CUST-WP-0050` itself, +which touches ~70 repos. If every workplan must bind to exactly one repo: + +- binding it to one arbitrary product repo misrepresents the work and pollutes + that repo's history with coordination it does not own; +- leaving it unbound reintroduces the hub-only orphan that ADR-001 forbids; +- modelling it as an array of `repo_id`s breaks the "one stable anchor, clear + ownership, clean lifecycle" property and complicates the rebuild principle. + +## Decision + +**A complex cross-repo workplan gets its own dedicated *project repo*.** + +- The project repo is a real, git-managed repository. It owns the coordination + workplan, its tasks, its decisions, and any cross-cutting artefacts. It is the + required `repo` anchor for that workplan, satisfying the repo-primary-anchor + rule without distorting any single product repo. +- The project repo is classified under the Repo Classification Standard, normally + `category: project`. Its `domain`/tags describe the effort, not any one product. +- **Implementation still happens in the product repos.** Changes land via + per-repo workplans and PRs in the repos being modified. The project repo + *coordinates and references* that work (via dependency edges / links); it does + not own product code. +- **On completion, the project repo is retired to archive — not deleted.** Its + durable results live on in the product repos it modified (the merged changes + are the outcome). The archived project repo remains as an immutable provenance + record of the coordination, consistent with the append-only-memory value. + +The project repo's completion record MUST list the product repos it modified and +link to the merged PRs/commits, so the trail survives archival. + +## Lifecycle + +``` +draft → active → completed → archived +``` + +- **active** — work in progress; workplan `status: active`; repo live in Gitea + and registered in the Hub. +- **completed** — all tasks done; completion record written (modified repos + + links). +- **archived** — repo archived in Gitea and `status: archived` in the Hub. The + workplan moves to `workplans/archived/` per the workplan convention. Results + persist in the product repos; the project repo is read-only history. + +## Naming + +Project repos SHOULD be identifiable as such (e.g. a `proj-` prefix or a +dedicated grouping). Exact convention is deferred to `CUST-WP-0050` rollout +(tracked as an open question there), but the lifecycle and ownership rules above +are fixed by this ADR. + +## Consequences + +- **Pro:** every workplan — including cross-repo ones — has a stable, + git-managed anchor; no hub-only orphans; the rebuild principle (ADR-001) holds. +- **Pro:** the classification standard applies uniformly; project repos are just + repos with `category: project`. +- **Pro:** clean, explicit lifecycle; results are never lost on retirement + because they live in the modified product repos. +- **Con:** proliferation of short-lived repos; requires discipline around the + naming and archival convention. +- **Con:** cross-references between the project repo and the product repos it + modified must be recorded deliberately, or the provenance trail degrades after + archival. +- **Con:** judgement is required on *when* an effort is "complex enough" to merit + a project repo versus a single-repo workplan; small cross-cutting changes + should not spawn a repo. + +## Alternatives Considered + +- **Bind to a "lead" product repo.** Rejected: distorts that repo's history and + creates ambiguous ownership. +- **Keep an optional hub-only topic for cross-repo coordination.** Rejected: + reintroduces the soft, non-git-managed spine that `CUST-WP-0050` removes and + ADR-001 discourages. +- **Multi-anchor workplan (array of repo_ids, no primary).** Rejected: breaks + single-anchor simplicity, ownership clarity, and lifecycle modelling. + +## Related + +- ADR-001 — Workplans and Work Items Are Repository Artefacts +- `CUST-WP-0050` — Repo Classification & State Hub Registration Redesign (D1) +- `canon/standards/repo-classification-standard_v1.0.md` diff --git a/workplans/CUST-WP-0050-repo-classification-registration-redesign.md b/workplans/CUST-WP-0050-repo-classification-registration-redesign.md index 98d0ea2..31bd018 100644 --- a/workplans/CUST-WP-0050-repo-classification-registration-redesign.md +++ b/workplans/CUST-WP-0050-repo-classification-registration-redesign.md @@ -11,6 +11,7 @@ planning_priority: high planning_order: 50 created: "2026-06-22" updated: "2026-06-22" +state_hub_workstream_id: "9f031f48-8de8-48b6-8e69-d2d83ad70a7a" --- # CUST-WP-0050 - Repo Classification & State Hub Registration Redesign @@ -63,7 +64,7 @@ The new standard fixes the root cause: it separates *category* (work mode), *domain* (intended market/user), *capability tags* (what it does), and *business stake* (who cares) — concerns the current 14 "domains" conflate. -### Architecture decision: replace the domain model +### Architecture decision: repo-anchored model, domain derived from classification The standard's `domain` is a **fixed 14-value market vocabulary** (infotech, financials, communication, consumer, health, industrials, energy, utilities, @@ -72,12 +73,31 @@ the Hub's current 14 coordination domains. Per the steering decision on 2026-06-22, the new market-domain vocabulary **replaces** the Hub's domain model (rather than augmenting it or running a parallel two-axis model). -This is a **breaking migration**: the current `domains` table is 1:1 with -`topics`, and topics own workstreams, goals, decisions, and progress events. The -new market domains are coarse (most repos are `infotech`), so the old 1:1 -domain↔topic assumption cannot survive unchanged. **Decoupling coordination -topics from the market-domain attribute is the central design problem of T04/T05** -(see Open Questions D1). +The current spine is `Domain → Topic → Workstream`, where `topics.domain_id` and +`workstreams.topic_id` are both **NOT NULL** and the 14 domains are seeded **1:1 +with 14 topics** (a data convention — the schema actually allows many topics per +domain, but that has never been used). `workstreams.repo_id` and +`repo_goals.repo_id` already exist, but the *required* anchor is the soft, +hub-only `topic`, while the stable git-managed `repo` link is optional. + +Per the 2026-06-22 steering decision, this redesign **flips the polarity**: the +**repo becomes the primary anchor** for workplans, and market-domain is +**derived** from the repo's `.repo-classification.yaml`, not stored as a separate +`topic`/`domain` parent. Concretely: + +- `workstreams.repo_id` becomes the **required** anchor; `topic_id` is demoted to + optional (or `topic` is retired) — see T10. +- Market-domain is computed from `repo → classification.domain`; the standalone + `topics.domain_id` / `managed_repos.domain_id` spine is removed. +- `RepoGoal` (already repo-anchored) becomes the goal primitive; `DomainGoal` + becomes a thin strategic rollup keyed by the 14 market domains. +- **Cross-repo workplans** anchor to a dedicated **project repo** that retires to + archive on completion, with results living on in the modified product repos — + see **ADR-005** and Open Question D1. + +This is consistent with ADR-001: the spine becomes the git-managed repo plus its +committed classification file, so the Hub stays fully rebuildable from repo-owned +files. It is a **breaking migration** of the coordination spine (T04/T05). ## Scope @@ -98,12 +118,19 @@ In scope: - Updates to dashboard, consistency checker, MCP/REST surface, and orientation docs to the new taxonomy. +In scope (added 2026-06-22): + +- Re-anchor workplans to repos (`repo_id` required, `topic` optional/retired) and + derive market-domain from classification (T04/T10). +- Rename `workstream → workplan` across schema, API, and MCP so the Hub + vocabulary matches the repo files and current usage (T10). + Out of scope: -- Re-architecting workstream/task semantics beyond what the domain replacement - forces. +- Re-architecting task-level semantics beyond what the re-anchor and rename force. - Changing the Gitea hosting model or repo contents beyond adding the - classification file. + classification file (and, for cross-repo efforts, creating project repos per + ADR-005). - Classifying throwaway/forked/non-ecosystem repos (explicit exclusion list). ## Repo boundary @@ -125,6 +152,7 @@ hub remains a read/index model fed by repo-owned files (ADR-001). id: CUST-WP-0050-T01 status: todo priority: high +state_hub_task_id: "d978b1f3-4eca-4a17-835b-2c25d13cae22" ``` Extract the standard's controlled vocabularies (5 categories, 14 domains, the @@ -144,6 +172,7 @@ a small validator can check a `.repo-classification.yaml` against it. id: CUST-WP-0050-T02 status: todo priority: high +state_hub_task_id: "b7edfbb5-483f-4600-9356-8f885c78ce58" ``` Author and human-review `.repo-classification.yaml` for the custodian-domain @@ -160,6 +189,7 @@ has been reviewed by a human. id: CUST-WP-0050-T03 status: todo priority: high +state_hub_task_id: "81489716-61ef-4207-ab8a-5877843281de" ``` Produce proposed `.repo-classification.yaml` for every active repo in the Gitea @@ -179,6 +209,7 @@ file (or is on the recorded exclusion list). id: CUST-WP-0050-T04 status: todo priority: high +state_hub_task_id: "b61f6267-c2b2-4325-95fa-30ee899ce7d1" ``` Replace the `domains` table contents with the 14 fixed market domains and add @@ -186,8 +217,10 @@ classification storage to `managed_repos`: `category`, primary `domain_id`, `secondary_domains[]`, `capability_tags[]`, `business_stake[]`, `business_mechanics[]`, plus provenance (`classified_at`, `classified_by`, `standard_version`). Enforce the allowed-values from T01 at the API boundary. -Decouple `topic` from market-domain (see D1). Provide an Alembic migration and -updated SQLAlchemy models + Pydantic schemas. +Make `repo_id` the **required** workplan anchor, derive market-domain from the +repo's classification, and demote/retire the `topic`/`domain` spine (see D1 and +T10). Provide an Alembic migration and updated SQLAlchemy models + Pydantic +schemas. Done when the schema/model/API accept and validate the full classification and reject invalid values, with a forward migration and a tested downgrade path. @@ -198,6 +231,7 @@ reject invalid values, with a forward migration and a tested downgrade path. id: CUST-WP-0050-T05 status: todo priority: high +state_hub_task_id: "171fa385-4d78-41ea-b749-ac3f9082fe47" ``` Define and apply the mapping from the old 14 domains/topics to the new model @@ -219,6 +253,7 @@ deferred with reasons. id: CUST-WP-0050-T06 status: todo priority: high +state_hub_task_id: "6ae14007-d6d2-4395-814e-ace91486a953" ``` Build an idempotent `register-from-classification` capability (Make target + @@ -238,6 +273,7 @@ emits a report of registered / updated / skipped / invalid. id: CUST-WP-0050-T07 status: todo priority: medium +state_hub_task_id: "6411bf3f-9de2-4bcd-9ffe-6209cda6ba93" ``` Run T06 against the classification files for the 57 previously-registered repos, @@ -254,6 +290,7 @@ the managed-repo set matches the (non-excluded) Gitea inventory. id: CUST-WP-0050-T08 status: todo priority: medium +state_hub_task_id: "09951aec-2960-4c50-b73d-4e2e7bd285c9" ``` Update the dashboard to navigate by category/domain/capability/business-stake; @@ -271,6 +308,7 @@ classification rule, and docs no longer assume the old domain model. id: CUST-WP-0050-T09 status: todo priority: medium +state_hub_task_id: "babbb80a-c52d-4ec2-b217-2f6196a2e5f3" ``` Switch orientation/registration tooling to the new model end-to-end, archive the @@ -279,13 +317,43 @@ old domain semantics, and run `make fix-consistency REPO=the-custodian`. Done when an end-to-end pass (classify → auto-register → dashboard view) is verified and the old ad-hoc domain model is retired. +### T10 - Re-anchor to repos + rename workstream → workplan + +```task +id: CUST-WP-0050-T10 +status: todo +priority: high +state_hub_task_id: "bee16416-a67f-4155-93d7-09f278daa04f" +``` + +Two coupled changes to the coordination spine, executed in `/home/worsch/state-hub`: + +1. **Re-anchor:** make `repo_id` the required anchor for a workplan, derive + market-domain from the repo's classification, and remove the + `topic`/`domain` parent spine (or demote `topic` to an optional cross-repo + tag). Promote `RepoGoal` to the goal primitive; reduce `DomainGoal` to a thin + rollup. Cross-repo workplans anchor to a **project repo** per ADR-005. +2. **Rename:** rename `workstream → workplan` across the DB table, SQLAlchemy + models, Pydantic schemas, REST routes, and MCP tools/resources, so the Hub + vocabulary matches the repo `workplans/` files and current usage. Provide + migration + compatibility/redirect notes for existing tool callers. + +Sequence with T04/T05 (same migration window where practical). Done when a +workplan is anchored to a repo with no required topic, market-domain resolves +from classification, and the API/MCP surface uses "workplan" with green tests. + ## Open Questions / Decisions -- **D1 (blocking T04/T05): topic ↔ market-domain after replacement.** Market - domains are coarse; coordination still needs finer grouping. Proposed: keep - `topic` as the coordination unit, made independent of market domain (market - domain becomes a `managed_repo` attribute; a topic may span repos of different - market domains). Needs confirmation before schema work starts. +- **D1 (RESOLVED 2026-06-22): the repo is the primary anchor.** Workplans bind to + repos (`repo_id` required); market-domain is *derived* from the repo's + classification; `topic`/`domain` stop being the spine (`topic` retires or + becomes an optional cross-repo tag). This supersedes the earlier "keep topic as + an independent coordination unit" proposal. Implemented by T04/T10. +- **D1a (open, follows from D1): anchor for cross-repo workplans.** Per **ADR-005**, + a complex cross-repo effort gets its own **project repo** (`category: project`) + as the anchor, retired to archive on completion with results living in the + modified product repos. Open sub-point: the project-repo **naming convention** + (e.g. `proj-` vs a dedicated grouping) and the archival trigger details. - **D2: classification ownership/approval.** Who approves each repo's `.repo-classification.yaml` — per-repo owner, or central custodian review? - **D3: exclusion list.** Confirm exclusions (fork `tegwick/the-custodian`,