specs/PhaseProvenanceSpecAddendum.md synthesizes T02-T04's accepted decisions into one reviewable document: the phase_manifest schema diff (repo_hub/repo_hub_uri/repo_id/repo_name, base_phase_id), the specs/policies/ + specs/profiles/ extraction with concrete file lists and frontmatter shapes, the ledger UI change, a forgejo_hubs migration sketch for the hosted hub registry, the three-example-manifest backfill plan, and a suggested implementation task breakdown. This is a proposal only, not yet accepted for implementation -- per the maintainer's own established sequencing, this is the document to discuss before any of it is filed as its own workplan. All five WP-0012 tasks are done; workplan marked finished. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
328 lines
17 KiB
Markdown
328 lines
17 KiB
Markdown
---
|
||
id: TREV-WP-0012
|
||
type: workplan
|
||
title: "Phase provenance, ledger reference, and degeneration-policy modeling"
|
||
domain: infotech
|
||
repo: target-revenue
|
||
status: finished
|
||
owner: claude
|
||
topic_slug: infotech
|
||
created: "2026-07-30"
|
||
updated: "2026-08-03"
|
||
state_hub_workstream_id: "763a31ee-85fe-43d0-9040-1e6fd432601c"
|
||
---
|
||
|
||
# Phase provenance, ledger reference, and degeneration-policy modeling
|
||
|
||
Triggered by using the Control Plane UI for the first time (WP-0009-T04):
|
||
the Phase registration form asked for a bare `source_revision` with no
|
||
repo attribution, a hand-typed `ledger` URI, and an opaque
|
||
`degeneration_policy` id with no way to see what it actually specifies.
|
||
These aren't UI bugs — the Phase Manifest schema
|
||
(`schemas/phase_manifest.schema.json`) itself doesn't yet carry the
|
||
structure the UI would need to show any of this properly, and FR-11
|
||
(Successive Phases, `specs/ProductRequirementsDocument.md`) already commits
|
||
the framework to base-release/prior-Phase provenance that the schema has
|
||
never modeled either.
|
||
|
||
This is a **modeling-only** workplan: it produces documents (a use-cases
|
||
spec and a discussable spec addendum) and decisions, not schema or UI
|
||
changes. Implementation follows in later workplans once the addendum is
|
||
reviewed (T05).
|
||
|
||
```task
|
||
id: TREV-WP-0012-T01
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "2871b8ff-b845-4ed4-aaa1-8fdfd1f601b7"
|
||
```
|
||
|
||
**Write the use-cases document**, as its own spec file (not folded into
|
||
`specs/PhaseManifestSpecification.md`) — working title
|
||
`specs/PhaseLifecycleUseCases.md`. Cover, systematically, at minimum:
|
||
|
||
1. First Phase ever declared for a repo (the three real pilot candidates:
|
||
`net-kingdom`, `railiance-vergabe-teilnahme`, `info-tech-canon`).
|
||
2. A successive Phase on a repo that already had an earlier, converted
|
||
Phase (FR-11) — including what "base release" means when the prior
|
||
Phase's Milestone Release is itself the base.
|
||
3. Operator registers a Phase; Contributor proposes a Development Credit;
|
||
Operator/Admin reviews (already built, WP-0009 — include for
|
||
completeness/cross-reference, not to redesign it).
|
||
4. Remission Credit accrual over time under the active degeneration
|
||
policy — note as an open gap for WP-0013, not solved here.
|
||
5. Conversion Event fires, Attestation published — note as a UI gap for
|
||
WP-0014.
|
||
6. Monetization Extension registration and canonical-status review — note
|
||
as a UI gap for WP-0014.
|
||
7. Breach/Compliance Record publication — note as a UI gap for WP-0014.
|
||
8. A second Licensor tenant besides `binky` onboards.
|
||
9. An external auditor verifies a Phase's evidence package offline,
|
||
without needing to trust or even reach the Control Plane UI (FR-8/FR-9
|
||
— call out explicitly that this use case has *no* UI surface by
|
||
design, so it doesn't get silently forgotten as "not yet built").
|
||
|
||
**Result:** `specs/PhaseLifecycleUseCases.md` written, covering all nine
|
||
use cases. Two findings worth flagging beyond the original scope: (a) use
|
||
case 2 (successive Phases) and use case 1 (first Phase) turned out to
|
||
share one underlying provenance model rather than being separate
|
||
concerns, so T02 below covers both together; (b) cross-checking
|
||
`specs/TargetRevenueControlPlaneConcept.md` §2's rights table while
|
||
writing use cases 6–7 found that breach-record publication already has a
|
||
decided rights tier (Operator+) but extension registration/canonicalization
|
||
does not — that's now recorded as an explicit open question for
|
||
WP-0014-T01 rather than something to assume while building that UI.
|
||
|
||
```task
|
||
id: TREV-WP-0012-T02
|
||
status: done
|
||
priority: high
|
||
human_accept_required: true
|
||
human_accepted_by: Bernd
|
||
human_accepted_at: "2026-07-30"
|
||
state_hub_task_id: "1d888dc7-360d-4ee5-8f4c-d1173670b0f7"
|
||
```
|
||
|
||
**Decide repo identification and Phase-provenance fields (human gate).**
|
||
Per direction already given: identity rests on the Forgejo instance
|
||
("home hub") plus the repo's own stable id within that instance, *and*
|
||
the Forgejo service URI and repo name are also retained (not derived) —
|
||
so a rename or instance move stays repairable rather than silently
|
||
breaking a Phase's provenance link. Concretely decide and record:
|
||
|
||
- Field names/shape for `milestone_release`: a hub identifier, a
|
||
Forgejo-internal repo id, the Forgejo service URI, and the repo name
|
||
(owner/repo slug) — four values, not one string.
|
||
- Whether this is required or recommended for Stage 0 (precedent:
|
||
`longstop_at` moved from recommended to required under a working
|
||
default, `specs/OpenQuestions-WorkingDefaults.md` Q8).
|
||
- How a successive Phase (use case 2 above) references its base — a
|
||
`trsl:phase:...` id, and what a first-ever Phase puts there instead
|
||
(null, or an explicit "no prior Phase" marker — decide which is
|
||
cleaner for fold/validation logic downstream).
|
||
- Whether any of this is retroactively backfillable for the three
|
||
existing pilot-candidate example manifests, or only required going
|
||
forward.
|
||
|
||
**Result (accepted 2026-07-30):** Grounded against the real Forgejo
|
||
instance before deciding, not assumed — confirmed live that
|
||
`forgejo.coulomb.social` assigns every repo a stable numeric id
|
||
(`target-revenue` is `103`, via `GET /api/v1/repos/coulomb/target-revenue`)
|
||
that survives renames, and confirmed it has **no** instance-level identity
|
||
endpoint (`/api/v1/nodeinfo` → 404, `/api/v1/version` returns only a
|
||
version string) — so unlike the repo id, a hub identifier is necessarily
|
||
something this project mints, not something Forgejo already provides.
|
||
|
||
Decided:
|
||
|
||
- `phase.milestone_release` gains four **required** fields: `repo_hub`
|
||
(a stable slug, e.g. `"forgejo-coulomb"`), `repo_hub_uri` (the Forgejo
|
||
service URL, e.g. `"https://forgejo.coulomb.social"`), `repo_id`
|
||
(Forgejo's own numeric repo id), `repo_name` (`"owner/repo"` slug).
|
||
Required immediately, not merely recommended — no grace period, unlike
|
||
`target_basis`'s current recommended-only status.
|
||
- `phase.base_phase_id` (optional, `trsl:phase:...` pattern) references
|
||
a prior Phase for a successive Phase; simply **absent** for a
|
||
first-ever Phase — no sentinel value, matching how
|
||
`ledger_entry.schema.json`'s `reverses` is already optional-only-when-
|
||
applicable.
|
||
- **Important refinement from the maintainer's own steer**: the
|
||
`repo_hub` → `repo_hub_uri` mapping is *not* static data checked into
|
||
this repo. `target-revenue` is the generic framework, not a specific
|
||
deployment's list of repos it happens to monetize — that mapping is
|
||
operational data owned by the **hosted Trust Service** (a new table,
|
||
analogous to `licensor_identities`, auto-populated the first time a hub
|
||
is seen), never a file in this git repo. A Phase Manifest stays fully
|
||
self-describing and offline-verifiable regardless (it carries
|
||
`repo_hub_uri`/`repo_name` directly at registration time, per use case
|
||
9) — the hosted table exists purely as an admin/repair convenience if
|
||
a hub's URI ever needs correcting after the fact, not a validation
|
||
dependency.
|
||
- The three existing example manifests will be backfilled — deferred
|
||
until after T03/T04 and the T05 spec addendum, since the schema change
|
||
is shared across all three decision tasks and the maintainer's own
|
||
process (item f, chat 2026-07-30) calls for the addendum to be
|
||
discussed before any implementation, including this backfill.
|
||
|
||
```task
|
||
id: TREV-WP-0012-T03
|
||
status: done
|
||
priority: high
|
||
human_accept_required: true
|
||
human_accepted_by: Bernd
|
||
human_accepted_at: "2026-07-30"
|
||
state_hub_task_id: "dbbabc02-8694-4e7d-8a15-c626ff72875b"
|
||
```
|
||
|
||
**Decide the degeneration-policy / calculation-model spec-file
|
||
convention (human gate).** Per direction already given: every policy or
|
||
calculation model (this includes the Development Effort Calculator's own
|
||
Candidate A formula, `specs/DevelopmentEffortCalculatorConcept.md`, not
|
||
just degeneration policies) corresponds to a markdown specification file
|
||
with a simple, distinct name, an id, and a revision — built on git's own
|
||
mechanisms (commit hash and/or file path, no new versioning
|
||
infrastructure). Concretely decide:
|
||
|
||
- Where these spec files live (likely already `specs/*.md` — decide
|
||
whether a dedicated subdirectory or naming convention is needed so a
|
||
policy id like `trsl:policy:linear-longstop-v0` maps unambiguously to
|
||
one file).
|
||
- What "id and revision, built on git internals" means precisely — e.g.
|
||
the policy id embeds the file path and a pinned commit hash, or the
|
||
file's own frontmatter carries an id/revision pair that a human commits
|
||
to alongside code changes (check how `the-custodian`/state-hub already
|
||
present read-only reference-documentation views linked by id, per the
|
||
user's explicit steer to reuse that pattern rather than invent a new
|
||
one, and follow whichever mechanism is actually in use there).
|
||
- How the Control Plane UI links a policy id shown next to a Phase to a
|
||
**read-only** rendered view of that spec file — no in-UI editing,
|
||
consistent with every other governance-action pattern in this project.
|
||
- Whether this same convention should also cover the six canonical
|
||
monetization profiles (`specs/CanonicalMonetizationProfiles.md`) for
|
||
consistency, or is scoped to degeneration policies and calculators only
|
||
for now.
|
||
|
||
**Result (accepted 2026-07-30):** Checked the maintainer's specific
|
||
`state-hub` reference before deciding — it's `dashboard/src/docs/*.md`,
|
||
built via Observable Framework into static HTML, opened as a standalone
|
||
page or in a "?" context-help overlay iframe
|
||
(`dashboard/src/docs/reference.md`). That's a real static-site build
|
||
pipeline, materially heavier than anything else in this repo. Decided to
|
||
carry the *spirit* (markdown spec → rendered read-only view, linked
|
||
contextually from wherever the id appears) without adopting that
|
||
toolchain, since `target-revenue`'s Control Plane is a lightweight
|
||
FastAPI+Jinja2 app with no existing build step to hang a static-site
|
||
generator off of.
|
||
|
||
Decided:
|
||
|
||
- New `specs/policies/` subdirectory, one file per degeneration policy —
|
||
e.g. `specs/policies/linear-longstop-v0.md` — extracted out of Q7's
|
||
prose in `specs/OpenQuestions-WorkingDefaults.md` (which stays as the
|
||
index of *decisions about* policies, not the policies' own content).
|
||
Each file's frontmatter carries the full versioned policy id (e.g.
|
||
`policy_id: trsl:policy:linear-longstop-v0@1.0`), so the id→file mapping
|
||
is explicit and machine-checkable, not merely inferred from the
|
||
filename.
|
||
- `specs/DevelopmentEffortCalculatorConcept.md` already conforms as-is —
|
||
one file, one model, distinct name — no move. Add/confirm an
|
||
`id`+`revision`-shaped frontmatter field for consistency with the new
|
||
policy files (there's no `trsl:...` schema id for calculators today,
|
||
since they aren't referenced by id from inside a Phase Manifest the way
|
||
`degeneration_policy` is — this is a documentation-traceability
|
||
convention only, not a new schema value).
|
||
- Extend the same convention to the six canonical monetization profiles
|
||
now, in this same pass — a new `specs/profiles/` subdirectory, one file
|
||
per profile (development, operations, ideation, service, consulting,
|
||
sponsorship), splitting them out of the shared
|
||
`specs/CanonicalMonetizationProfiles.md`, even though nothing currently
|
||
links to a profile by bare id from the UI the way `degeneration_policy`
|
||
is linked. `id`+`revision` frontmatter, matching the policy files.
|
||
- "Id and revision, built on git internals" means: the id is the stable
|
||
policy/profile identifier already used in Phase Manifests today
|
||
(including its existing `@version` suffix, e.g. `...@1.0`), mapped to
|
||
exactly one file by naming convention; the revision/audit trail is
|
||
simply that file's own git history (`git log -- specs/policies/
|
||
linear-longstop-v0.md`) — no new versioning table, no pinned-commit
|
||
scheme, nothing beyond what git already provides for free.
|
||
- Control Plane UI rendering: a small Python markdown library, one new
|
||
read-only route (e.g. `GET /reference/policies/{slug}`, and
|
||
equivalently for profiles/calculators), rendering the spec file's
|
||
current content server-side at request time. A plain link next to
|
||
wherever a policy id already appears (`phase_detail.html`,
|
||
`phase_new.html`) — never in-UI editable, matching every other
|
||
governance-action pattern already established in this project.
|
||
|
||
As with T02, no files are moved or created yet — `specs/policies/`,
|
||
`specs/profiles/`, and the new render route are implementation, deferred
|
||
to after T04 and the T05 spec addendum per the maintainer's own established
|
||
sequencing (item f, chat 2026-07-30).
|
||
|
||
```task
|
||
id: TREV-WP-0012-T04
|
||
status: done
|
||
priority: medium
|
||
human_accept_required: true
|
||
human_accepted_by: Bernd
|
||
human_accepted_at: "2026-08-03"
|
||
state_hub_task_id: "a1cf0180-2dc7-44bb-a34f-99b5e92f5144"
|
||
```
|
||
|
||
**Decide the ledger's UI treatment (human gate).** Per direction already
|
||
given: keep the `ledger` field in the schema — not as something the
|
||
standard Phase view surfaces, but as an internal reference reachable only
|
||
via an explicit drill-down/details action. This is intentional groundwork
|
||
for eventually supporting more than one ledger per Phase (federation,
|
||
`specs/ProductRequirementsDocument.md` NFR-3), not just a display
|
||
preference. Decide:
|
||
|
||
- What the drill-down actually shows (the raw ledger URI/reference plus a
|
||
link to `GET /phases/{id}/ledger`'s live data, or something more), and
|
||
where it lives in the Control Plane's navigation (a "details" link on
|
||
`phase_detail.html` rather than a top-level field).
|
||
- Whether the Phase registration form still needs a `ledger` input at
|
||
all going forward, or whether the Trust Service should compute/assign
|
||
it automatically now that it is always the ledger's host in Stage 0 —
|
||
distinct from the schema question of whether the field stays.
|
||
|
||
**Result (accepted 2026-08-03):**
|
||
|
||
- The Phase registration form (`phase_new.html`) drops the `ledger`
|
||
input entirely. The Trust Service auto-computes and assigns the
|
||
canonical `/phases/{id}/ledger` reference at registration time — no
|
||
human ever types it in v0. The schema field itself is untouched by
|
||
this decision (still present, still federation-ready for a future
|
||
Phase whose ledger genuinely lives elsewhere) — this is a Control
|
||
Plane UI simplification, not a schema change, and needs no
|
||
addendum-level review of its own.
|
||
- The drill-down view shows only the raw `ledger` reference/URI as
|
||
stored in the manifest, plus — only when it resolves to this same
|
||
Trust Service instance — a link to `GET /phases/{id}/ledger`'s live
|
||
JSON. No new rendering of ledger *data*: `phase_detail.html`'s existing
|
||
Ledger entries table already covers that and stays exactly as
|
||
prominent as it is today; this decision only concerns the otherwise-
|
||
invisible raw reference string, reachable via a small "ledger
|
||
reference" link/disclosure on `phase_detail.html` rather than a
|
||
top-level field.
|
||
|
||
All four T02–T04 decisions now feed T05's spec addendum draft.
|
||
|
||
```task
|
||
id: TREV-WP-0012-T05
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "152b54a6-08a9-4ced-a5f6-d5638d102900"
|
||
```
|
||
|
||
**Draft the spec addendum** reflecting T01–T04's accepted decisions, for
|
||
review before any implementation — schema changes (`schemas/
|
||
phase_manifest.schema.json`), the policy-spec-file convention, and the
|
||
Control Plane UI changes it implies. Do not implement anything from this
|
||
task; it produces a reviewable document only. Once accepted, file the
|
||
implementation work as its own workplan(s), consistent with how WP-0009
|
||
and WP-0010 were split from a single combined plan.
|
||
|
||
**Result:** `specs/PhaseProvenanceSpecAddendum.md` written — six
|
||
sections covering the schema diff (§1), the `specs/policies/`/
|
||
`specs/profiles/` extraction with concrete file lists and frontmatter
|
||
shapes (§2), the ledger UI change (§3), a new `forgejo_hubs` migration
|
||
sketch for the hub-registry decision from T02 (§4), the backfill plan
|
||
for the three example manifests (§5), and a suggested implementation
|
||
task breakdown (§6) for whatever workplan follows once this addendum is
|
||
reviewed. **Not yet accepted** — this is the document to discuss before
|
||
any implementation work is filed or started. All five WP-0012 tasks are
|
||
now done; this workplan is finished pending that discussion, which
|
||
happens outside this workplan's own task list.
|
||
|
||
Use cases 4, 6, and 7 above are bigger than a modeling exercise — they
|
||
are missing implementation, not missing documentation — and are tracked
|
||
separately rather than folded in here:
|
||
|
||
- `workplans/TREV-WP-0013-remission-credit-automation.md` — use case 4.
|
||
- `workplans/TREV-WP-0014-control-plane-extensions-breach-attestation-ui.md`
|
||
— use cases 5, 6, 7.
|
||
|
||
Use case 8 (second Licensor tenant onboarding) is judged small enough to
|
||
stay under `workplans/TREV-WP-0008-governance-and-pilot-rollout.md`
|
||
rather than warrant its own workplan — revisit that call if it turns out
|
||
to need real design work once a second tenant is actually on the table.
|