feat(workplan): open STATE-WP-0083 for the forge-derived projection reset
Implements ADR-012 decision 7. Placed in state-hub because central must do its own reading: the pod can clone Forgejo anonymously, and driving this from Repo Manager would push a workstation-computed projection into central, which ADR-010 decision 5 forbids. Also the only sanctioned removal path — the hub has no hard-delete for work records by design. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
This commit is contained in:
parent
b02f3c22ad
commit
6390b7bead
1 changed files with 146 additions and 0 deletions
146
workplans/STATE-WP-0083-forge-derived-projection-reset.md
Normal file
146
workplans/STATE-WP-0083-forge-derived-projection-reset.md
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
---
|
||||
id: STATE-WP-0083
|
||||
type: workplan
|
||||
title: "Forge-derived projection reset, per repository"
|
||||
domain: infotech
|
||||
repo: state-hub
|
||||
status: active
|
||||
owner: codex
|
||||
topic_slug: infotech
|
||||
created: "2026-08-25"
|
||||
updated: "2026-08-25"
|
||||
related:
|
||||
- CUST-ADR-012
|
||||
- CUST-WP-0068
|
||||
---
|
||||
|
||||
# Forge-derived projection reset, per repository
|
||||
|
||||
## Goal
|
||||
|
||||
Implement `ADR-012` decision 7: discard a repository's projection and rebuild it
|
||||
from what Forgejo holds. Per repository, routine, idempotent, and verifiable.
|
||||
|
||||
This is the only sanctioned way to remove a hub record. The hub has no
|
||||
hard-delete for work records — `DELETE /tasks/{id}` is `cancel_task`,
|
||||
`DELETE /workstreams/{id}` is `410 Gone`, and no `session.delete` exists for
|
||||
either. Re-derivation is not one option among several; it is the mechanism.
|
||||
|
||||
## Why here and not in Repo Manager
|
||||
|
||||
`ADR-012` decision 1 says central derives from the forge, and the pod can reach
|
||||
it: `git ls-remote https://forgejo.coulomb.social/...` succeeds anonymously from
|
||||
inside the cluster, and `git` is already in the image.
|
||||
|
||||
Driving the reset from Repo Manager would mean computing a projection on a
|
||||
workstation and pushing it into central — precisely the injection of derived
|
||||
state `ADR-010` decision 5 forbids. Central must do its own reading. The cost is
|
||||
that workplan parsing exists in two places; `scripts/consistency_check.py`
|
||||
already parses frontmatter and task blocks here, so the capability is present
|
||||
and should be extracted rather than rewritten.
|
||||
|
||||
## What it must not do
|
||||
|
||||
- **Not restore preliminary overlay records.** They exist because the forge does
|
||||
not hold them; a rebuild from the forge cannot reproduce them and must not
|
||||
pretend to.
|
||||
- **Not destroy hub-native records.** Progress events, decisions and inbox
|
||||
messages originate in the hub (`ADR-010` decision 4). They are not
|
||||
forge-derived and must survive a rebuild of forge-derived state.
|
||||
- **Not proceed silently when records would be lost.** Stop, name them, and
|
||||
require an explicit acknowledgement.
|
||||
|
||||
## Derive a repository's projection from the forge
|
||||
|
||||
```task
|
||||
id: STATE-WP-0083-T01
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
Given a repository slug, clone or fetch its default branch from Forgejo into a
|
||||
temporary location, parse the workplan files, and compute the projection that
|
||||
state would produce: workplans, tasks, their identifiers, statuses and backing
|
||||
paths.
|
||||
|
||||
Read-only and side-effect free. Record the commit the derivation came from —
|
||||
`ADR-012` decision 2 requires provenance, and the existing `git_fingerprint` is
|
||||
worthless precisely because nothing ever wrote it correctly.
|
||||
|
||||
Acceptance: deriving `the-custodian` twice from the same commit yields identical
|
||||
output, and the commit is reported.
|
||||
|
||||
## Report the difference before changing anything
|
||||
|
||||
```task
|
||||
id: STATE-WP-0083-T02
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
Compare the derived projection against what the hub currently holds for that
|
||||
repository, and report: records the forge has that the hub lacks, records the
|
||||
hub has that the forge does not, and records whose fields differ.
|
||||
|
||||
This is the half that is immediately useful without any destructive capability,
|
||||
and it is what makes decision 7's "verifiable" real. It also answers the
|
||||
question `CUST-WP-0068-T09` is waiting on — which stale rows would actually
|
||||
clear — before anyone commits to clearing them.
|
||||
|
||||
Acceptance: a dry-run diff for a repository with known drift matches what
|
||||
manual inspection shows.
|
||||
|
||||
## Apply the reset transactionally
|
||||
|
||||
```task
|
||||
id: STATE-WP-0083-T03
|
||||
status: todo
|
||||
priority: high
|
||||
```
|
||||
|
||||
Replace the repository's forge-derived records with the derived projection in
|
||||
one transaction: create what is missing, update what differs, remove what no
|
||||
longer derives. Hub-native records are untouched.
|
||||
|
||||
Refuse by default when removal would destroy a record with no counterpart in the
|
||||
forge; report what would be lost and require an explicit acknowledgement to
|
||||
proceed. That refusal is evaluated per repository, so one unresolved repository
|
||||
never blocks the rest.
|
||||
|
||||
Acceptance: reset twice produces the same projection; a repository holding
|
||||
records the forge lacks is refused with those records named; hub-native record
|
||||
counts are unchanged across a reset.
|
||||
|
||||
## Fleet form as a loop over the repository form
|
||||
|
||||
```task
|
||||
id: STATE-WP-0083-T04
|
||||
status: todo
|
||||
priority: medium
|
||||
```
|
||||
|
||||
The fleet-wide reset iterates the per-repository reset and shares its
|
||||
implementation, so the rarely-used dangerous path is exercised by the frequently
|
||||
used safe one. Repositories that refuse are skipped and reported, never aborting
|
||||
the pass.
|
||||
|
||||
Acceptance: a fleet dry-run reports per-repository outcomes including refusals,
|
||||
and completes despite them.
|
||||
|
||||
## Retire what the reset replaces
|
||||
|
||||
```task
|
||||
id: STATE-WP-0083-T05
|
||||
status: wait
|
||||
priority: medium
|
||||
```
|
||||
|
||||
Once reset is trusted, `CUST-WP-0068-T09` can clear its stale rows — 4 workplan
|
||||
rows from the prefix migration and 305 task rows across 44 workplans.
|
||||
|
||||
`ADR-003` decision 2's `mtime`-based fingerprints should also be replaced by the
|
||||
source commit at this point; `ADR-012` invalidated that composition and the
|
||||
replacement belongs with the provenance work in `T01`.
|
||||
|
||||
Acceptance: `CUST-WP-0068-T09` closes; no fingerprint input depends on a local
|
||||
filesystem.
|
||||
Loading…
Add table
Add a link
Reference in a new issue