# Coordination Infrastructure — Repo Spec v0.1 — 2026-09-23

Author: this session (Sigwell Command Center project).
Status: **CANDIDATE spec, for Ellari's review.** Nothing in this document has been built, deployed, or hosted. It describes a repo layout and protocols only. Deployment to ellari.dev requires a platform decision (§8) this document does not make.

Working title: **Sigwell Command / Accountistry / FranchiseDash — Coordination Infrastructure**, hosted at `ellari.dev` (path TBD — §8).

## 0. What this replaces, and why now

Today's Handoff Ledger (artifact + `HANDOFF_LEDGER_DATA` JSON in this project) proved the pattern this repo generalizes: one canonical machine-readable file per concern, and a disposable HTML renderer that reads it rather than embedding it. That correction — made by a different conversation in this project, independently verified and adopted by this one — is the direct ancestor of this spec. The failure it fixes has now happened twice in this project alone: the same SAF package independently verified by two conversations unaware of each other, and the reviewer-tracking register independently rebuilt by at least three conversations in parallel. A repo with one place to write, and per-thread sections that read from it, is how "every thread generates a handoff ledger" stops meaning "every thread hand-authors its own copy of the same facts."

## 1. Principles

1. **One canonical data file per concern.** Lanes, handoffs, open items, and now thread metadata each have exactly one machine-readable source of truth in `data/`. Every rendered page reads from it; nothing renders from a hand-typed copy.
2. **Renderers are disposable.** HTML/CSS/JS under `site/` can be deleted and rebuilt from `data/` at any time with no information loss. If a renderer and the data disagree, the data wins.
3. **Prose stays human, tags stay machine.** Long-form reasoning, adjudications, and narrative context keep living in the Claude Project's `.md` docs (or this repo's own `docs/`, once threads write directly here — see §7). The JSON files carry only what a script needs to filter, join, or render.
4. **Append and correct, never silently overwrite.** This project's existing discipline (evidence grading, `[S]`/`[U]`/`[I]`/`[E]`, corrections logged rather than erased) carries over. A wrong entry gets a `corrects`/`supersedes` pointer, not a quiet edit.
5. **No authority beyond the record.** This repo tracks what happened and what's open. It grants no thread financial, filing, access, or outreach authority — unchanged from every protocol adopted in this project so far.

## 2. Repo layout

```
coordination-infrastructure/
├── README.md
├── SPEC.md                          # this document, canonical copy
├── data/
│   ├── schema/
│   │   ├── lane.schema.json
│   │   ├── handoff.schema.json
│   │   ├── open_item.schema.json
│   │   └── continuity_capsule.schema.json
│   ├── lanes.json                   # registry of all lanes, active + archived
│   ├── handoff_log.json             # global handoff log (today's ledger_data.json, generalized)
│   ├── open_items.json              # global open items
│   └── threads/
│       ├── THR-CV-SIGWELL-BOOKS/
│       │   ├── thread.json          # this lane's own metadata (see §4)
│       │   └── continuity/
│       │       └── <date>_capsule.json   # successor handoffs, if any (see §6)
│       ├── THR-CV-SIGWELL-MODEL/
│       │   └── ...
│       └── ...                      # one directory per registered lane
├── archive/
│   ├── README.md                    # retention policy, immutability rule (see §5)
│   └── <thread-id>/<archived-date>/ # frozen snapshots, read-only once written
├── site/
│   ├── index.html                   # landing dashboard — lane cards + global log (evolves today's Handoff Ledger)
│   ├── thread.html                  # per-thread view, reads data/threads/<id>/thread.json + filtered log
│   └── assets/
└── scripts/
    └── validate.*                   # schema validation, run before any merge
```

Each registered lane gets exactly one directory under `data/threads/`. A thread's own section on the site (`site/thread.html?id=THR-...` or `/threads/THR-.../`) is generated from that directory plus the global log filtered by `from_lane`/`to` — never a separate hand-authored page.

## 3. Data schemas (extending today's JSON)

`lane.schema.json` — one object per registered lane, in `data/lanes.json`:

| Field | Type | Notes |
|---|---|---|
| `id` | string | Stable ID, `THR-` prefix (today's convention, kept). |
| `label` | string | Human label, as Ellari uses it. |
| `platform` | enum | `claude` \| `chatgpt` \| `other` \| `unconfirmed`. New — today's ChatGPT-sidebar screenshot showed lanes may not even share a platform. |
| `task_id` | string\|null | |
| `task_id_confirmed` | bool | |
| `identity_claim` | string | Free-text tag, as today. |
| `status` | enum | `active` \| `archived` \| `superseded`. New. |
| `opened` | date | |
| `closed` | date\|null | |
| `predecessor_id` | string\|null | Set when this lane is a successor (§6). |
| `successor_id` | string\|null | Set once a successor exists. |
| `note` | string | |

`handoff.schema.json` — unchanged from today's `HANDOFF_LEDGER_DATA` `handoff_log` entries (`date`, `artifact`, `from_lane`, `to`, `verified_by`, `verification_method`, `status`, `receipt`, `pair_group`), plus one new optional field: `corrects` / `supersedes` (entry ID or null), reusing the correction vocabulary already present (unadopted, but reusable by name) in the OG-V control-plane package's proposed Correction/Supersession Protocol — `CORRECTS` / `RETRACTS` / `SUPERSEDES` / `DUPLICATE_OF` / `DERIVED_FROM` / `DISPUTED_BY`.

`open_item.schema.json` — unchanged from today's `open_items` entries (`id`, `text`, `resolved`, `resolution`).

`continuity_capsule.schema.json` — new, see §6.

## 4. Per-thread section

Each lane's page shows, generated entirely from data:

- Identity block: label, platform, task ID (confirmed or not), status.
- Its own handoff rows (global log filtered to `from_lane == id` or `to == id`).
- Open items that name this lane.
- If `status == archived` or `superseded`: a banner linking to its archive snapshot (§5) and/or successor (§6).

No thread writes its own HTML page. A thread that wants a visible section adds or edits its `thread.json` and appends rows to the global log — the renderer does the rest. This is the direct fix for "every thread generate a handoff ledger": the generation is the data write, not a new HTML file.

## 5. Archiving protocol

**Trigger conditions** (any one is sufficient): a thread reaches a successor (§6); a thread's work is fully adjudicated/closed with no further action expected; Ellari retires a lane explicitly.

**What happens:** the thread's current `data/threads/<id>/` contents, plus every `data/handoff_log.json` row naming it, are copied verbatim into `archive/<id>/<archived-date>/` as a frozen snapshot. `lanes.json`'s `status` flips to `archived` (or `superseded`, if §6 applies). The live `data/threads/<id>/` directory is **not deleted** — it keeps existing as the queryable current-state view, but its `thread.json.status` marks it closed.

**Immutability rule:** nothing under `archive/` is ever edited after it's written. A later correction to an archived fact is a new entry in the *active* data files with a `corrects` pointer back to the archived record — never an edit to the archive itself. This is the same rule this project has applied to every prior handoff package: preserve predecessor bytes, issue corrections additively.

**Retention:** kept indefinitely by default (this is a small-volume coordination record, not a data-retention liability) unless Ellari sets a different policy in `archive/README.md`.

## 6. Successor thread protocol (max thread length)

**Trigger:** a thread approaches its platform's context/length limit and can't safely continue — whether that's judged by the thread itself, by Ellari, or by elapsed volume is Ellari's call; this spec doesn't prescribe a detection mechanism, only what happens once the call is made.

**What a closing thread must produce — a continuity capsule** (`data/threads/<id>/continuity/<date>_capsule.json`):

| Field | Purpose |
|---|---|
| `capsule_id` | Stable ID for this handoff event. |
| `from_thread` | The closing lane's `id`. |
| `to_thread` | The new lane's `id`, once registered (null until then — a capsule can be written before the successor exists). |
| `created` | Date. |
| `trigger` | `context_limit` \| `manual_split` \| `other`. |
| `carried_forward.open_items` | IDs of open items the successor must inherit — not all of them; only ones still live. |
| `carried_forward.in_flight_receipts` | Receipt IDs for anything mid-review/HOLD. |
| `carried_forward.unresolved_questions` | Free text — anything not yet formalized as an open item. |
| `carried_forward.authority_state` | Always `none`, restated explicitly per §1.5 — a successor inherits no authority the predecessor didn't have. |
| `left_behind` | Explicit note of what does *not* carry forward (full prior transcript, resolved items, superseded drafts) — so a successor doesn't over-claim continuity it doesn't have. |
| `handoff_receipt` | This project's `SCC-...` receipt ID for the handoff, once logged. |

**What happens on the registry side:** the new thread gets its own `THR-` ID and `thread.json`, with `predecessor_id` set to the closing thread's ID. The closing thread's `thread.json` gets `successor_id` set and `status: superseded`. Both directions are recorded — a reader can walk the chain either way. The closing thread is then archived per §5.

**What a successor must NOT do:** claim the predecessor's task ID as its own without independent confirmation (the same discipline this project applied to the Compiler V task-ID question); treat everything in the capsule as settled fact rather than the predecessor's account of it; or skip writing its own `thread.json` because "it's really the same thread" — it isn't, by this project's own repeated finding that different conversation instances under the same label are not reliably the same continuity.

This directly extends the review state machine already adopted in this project (`ASSIGNED → RECEIVED → INTEGRITY_CHECKED → SUBSTANTIVE_REVIEW → RETURNED → ADJUDICATED → CLOSED`, with side-state `SUPERSEDED`) — a thread-level supersession using the same vocabulary as an artifact-level one, not a new concept.

## 7. Build / publish workflow

1. A thread that does coordination-relevant work edits `data/*.json` directly (appends a handoff row, updates a lane's status, writes a continuity capsule) — via whatever this repo's edit mechanism turns out to be (§8 decides: direct git commits by threads with repo access, a PR flow, or Ellari relaying edits manually as she does today).
2. `scripts/validate.*` checks every touched file against its schema before it's accepted — catches malformed dates, unknown lane IDs, orphaned `pair_group`/`corrects` references.
3. `site/*.html` needs no rebuild step if it fetches `data/*.json` at load time (as today's Handoff Ledger now does) — publishing the data *is* publishing the update. A pre-rendered static-export step is optional, only needed if ellari.dev's hosting can't serve the JSON files directly alongside the HTML.

## 8. Open decisions (Ellari's call, not drafted here)

- **Hosting platform for ellari.dev.** GitHub Pages, Vercel, Netlify, or something already in place — this spec is platform-agnostic by design (static files + client-side fetch), but the repo's CI/deploy config depends on the answer. This session has GitHub and Vercel tooling available if either is the answer.
- **Who/what can write to the repo.** Whether AI threads get direct commit access, go through a PR a thread proposes and Ellari merges, or whether Ellari keeps relaying edits by hand (as now) with threads only ever proposing JSON diffs for her to apply. The spec works under any of these; it doesn't pick one.
- **Public vs. private.** This repo would contain lane labels, receipt IDs, and coordination metadata — not the underlying tax/financial source documents, which should stay out of it entirely regardless of visibility. Still, public-vs-private on ellari.dev is Ellari's call.

## 9. Migration from the current state

Seed `data/lanes.json`, `data/handoff_log.json`, and `data/open_items.json` directly from this project's `HANDOFF_LEDGER_DATA_v0.2_2026-09-23.json` — already in the target shape with one addition (`platform`, `status`, `predecessor_id`, `successor_id` per lane, all currently unset/`active`/`null`). `Thread_and_Handoff_Tracker_v0.2_2026-09-23.md` becomes the seed for `README.md`'s prose framing. Nothing else in the Claude Project needs to move — this repo starts from the one file already built to be canonical, not from a fresh survey of all 100+ docs.

---
Receipt: `SCC-REPOSPEC-001`
