policy-nexus/build/adr/custodian-workplans-as-repo-artefacts/v1/index.html
tegwick 5fbd44a703
Some checks failed
Build and publish policy-nexus image / build-and-push (push) Failing after 0s
feat: publish custodian fleet standards batch
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663
2026-08-31 22:24:25 +02:00

257 lines
27 KiB
HTML

<!doctype html>
<html lang="en"><meta charset="utf-8">
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
<meta name="policy-source-digest" content="183023ee57bae9c29e726fec5ee0361633fe3a2b182436a57869ae4b2a27af24">
<title>Workplans and Work Items Are Repository Artefacts</title>
<style>
:root{
--paper:#EDEEF0; --surface:#F6F7F8; --surface-2:#E4E6E9;
--ink:#171D24; --ink-2:#4A5561; --ink-3:#737E8A;
--rule:#D3D7DC; --rule-strong:#B6BCC3;
--brass:#8A6A2E; --brass-soft:#EFE5CD; --brass-line:#C9AE74;
--clay:#8A3A2C; --clay-soft:#F2DFDA;
--l0:#DCE0E2; --l1:#B9C4C7; --l2:#8CA1A6; --l3:#567D84; --l4:#23555E;
--chip-fg:#F6F7F8;
--font-display:ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",sans-serif;
--font-body:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,serif;
--font-mono:ui-monospace,"SF Mono","Cascadia Code",Menlo,Consolas,monospace;
--measure:66ch;
}
@media (prefers-color-scheme:dark){
:root:not([data-theme="light"]){
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
--rule:#2A3138; --rule-strong:#3B444D;
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
--clay:#D08A76; --clay-soft:#3A211B;
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
--chip-fg:#12161A;
}
}
:root[data-theme="dark"]{
--paper:#12161A; --surface:#191E24; --surface-2:#222831;
--ink:#E6E9EC; --ink-2:#A3ADB7; --ink-3:#78838E;
--rule:#2A3138; --rule-strong:#3B444D;
--brass:#C9A45C; --brass-soft:#33290F; --brass-line:#6B5426;
--clay:#D08A76; --clay-soft:#3A211B;
--l0:#262C32; --l1:#35424A; --l2:#4A626B; --l3:#6A939D; --l4:#97C4CD;
--chip-fg:#12161A;
}
*{box-sizing:border-box}
body{
margin:0; background:var(--paper); color:var(--ink);
font-family:var(--font-body); font-size:17px; line-height:1.62;
-webkit-font-smoothing:antialiased;
}
.wrap{max-width:1180px;margin:0 auto;padding:0 24px 96px}
.layout{display:grid;grid-template-columns:180px minmax(0,1fr);gap:56px;align-items:start}
@media (max-width:960px){.layout{grid-template-columns:1fr;gap:0}.rail{display:none}}
/* ---------- rail ---------- */
.rail{position:sticky;top:28px;padding-top:8px;font-family:var(--font-display);font-size:12px;line-height:1.5}
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
.rail a{color:var(--ink-3);text-decoration:none;display:flex;gap:9px}
.rail a:hover,.rail a:focus-visible{color:var(--brass)}
.rail .n{font-family:var(--font-mono);font-size:10px;color:var(--rule-strong);min-width:16px;padding-top:1px}
.rail .grp{margin-top:14px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--rule-strong)}
/* ---------- header ---------- */
header{padding:64px 0 40px;border-bottom:2px solid var(--ink);margin-bottom:44px}
.eyebrow{font-family:var(--font-mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);display:flex;flex-wrap:wrap;gap:14px;margin-bottom:22px}
.eyebrow .stat{color:var(--clay)}
h1{font-family:var(--font-display);font-weight:800;letter-spacing:-.035em;line-height:.94;font-size:clamp(46px,9vw,92px);margin:0 0 6px;text-wrap:balance}
.sub{font-family:var(--font-display);font-weight:500;font-size:clamp(16px,2.4vw,21px);letter-spacing:-.01em;color:var(--ink-2);margin:0 0 30px;max-width:34ch;line-height:1.3}
.metagrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:20px 28px;border-top:1px solid var(--rule);padding-top:20px}
.metagrid dt{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);margin-bottom:5px}
.metagrid dd{margin:0;font-family:var(--font-display);font-size:13.5px;line-height:1.45;color:var(--ink)}
/* ---------- typography ---------- */
section{margin-bottom:60px;scroll-margin-top:24px}
h2{font-family:var(--font-display);font-weight:750;letter-spacing:-.022em;font-size:clamp(24px,3.4vw,31px);line-height:1.12;margin:0 0 18px;text-wrap:balance;display:flex;gap:14px;align-items:baseline}
h2 .sn{font-family:var(--font-mono);font-size:12px;font-weight:400;color:var(--brass);letter-spacing:.06em;flex:none;padding-top:2px}
h3{font-family:var(--font-display);font-weight:700;font-size:16px;letter-spacing:-.008em;margin:34px 0 10px;color:var(--ink)}
p{margin:0 0 15px;max-width:var(--measure)}
ul,ol{max-width:var(--measure);margin:0 0 15px;padding-left:20px}
li{margin-bottom:7px}
strong{font-weight:600}
em{font-style:italic}
code{font-family:var(--font-mono);font-size:.855em;background:var(--surface-2);padding:1px 5px;border-radius:2px}
a{color:var(--brass)}
.lede{font-size:19px;line-height:1.55;color:var(--ink-2);max-width:60ch}
/* ---------- devices ---------- */
.callout{border-left:3px solid var(--brass);background:var(--brass-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
.callout p:last-child{margin-bottom:0}
.callout .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
.rule-quote{border-top:2px solid var(--ink);border-bottom:2px solid var(--ink);padding:26px 0;margin:28px 0;max-width:var(--measure)}
.rule-quote p{font-family:var(--font-display);font-weight:600;font-size:19px;line-height:1.38;letter-spacing:-.014em;margin:0;text-wrap:balance}
.hard{border-left:3px solid var(--clay);background:var(--clay-soft);padding:18px 22px;margin:0 0 24px;max-width:var(--measure)}
.hard .lbl{font-family:var(--font-mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--clay);display:block;margin-bottom:8px}
.hard p:last-child{margin-bottom:0}
.dec{font-family:var(--font-mono);font-size:10.5px;letter-spacing:.08em;color:var(--brass);text-transform:uppercase}
.vec{font-family:var(--font-mono);font-size:.9em;font-weight:600;background:var(--surface-2);padding:2px 7px;border-radius:2px;white-space:nowrap;letter-spacing:.04em}
/* ---------- tables ---------- */
.scroll{overflow-x:auto;margin:0 0 24px;-webkit-overflow-scrolling:touch}
table{border-collapse:collapse;width:100%;min-width:520px;font-family:var(--font-display);font-size:13.5px;line-height:1.45}
th{text-align:left;font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink-3);font-weight:400;padding:0 16px 8px 0;border-bottom:1px solid var(--rule-strong);vertical-align:bottom}
td{padding:11px 16px 11px 0;border-bottom:1px solid var(--rule);vertical-align:top;color:var(--ink-2)}
td:first-child{color:var(--ink);font-weight:600}
tbody tr:last-child td{border-bottom:none}
.lvl{font-family:var(--font-mono);font-weight:600;font-size:12px;letter-spacing:.04em;color:var(--ink)}
/* ---------- ladders ---------- */
.breakout{margin:34px 0 40px}
.bhead{display:flex;justify-content:space-between;align-items:baseline;gap:20px;border-bottom:1px solid var(--rule-strong);padding-bottom:9px;margin-bottom:22px;flex-wrap:wrap}
.bhead h3{margin:0;font-size:13px;letter-spacing:.1em;text-transform:uppercase;font-family:var(--font-mono);font-weight:400;color:var(--ink-3)}
.bhead .note{font-family:var(--font-display);font-size:12.5px;color:var(--ink-3)}
.ladders{display:grid;gap:26px}
.ladder{display:grid;grid-template-columns:126px minmax(0,1fr);gap:18px;align-items:start}
@media (max-width:700px){.ladder{grid-template-columns:1fr;gap:10px}}
.ladder .pname{font-family:var(--font-display);font-weight:700;font-size:14px;letter-spacing:-.01em;padding-top:2px}
.ladder .pname span{display:block;font-family:var(--font-mono);font-size:10px;font-weight:400;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);margin-top:3px}
.rungs{display:grid;gap:3px;grid-template-columns:repeat(5,minmax(0,1fr))}
@media (max-width:700px){.rungs{grid-template-columns:repeat(2,minmax(0,1fr))}}
.rung{padding:9px 10px 11px;background:var(--surface);border-top:4px solid var(--l0);min-width:0}
.rung.r1{border-top-color:var(--l1)} .rung.r2{border-top-color:var(--l2)}
.rung.r3{border-top-color:var(--l3)} .rung.r4{border-top-color:var(--l4)}
.rung .code{font-family:var(--font-mono);font-size:11px;font-weight:600;letter-spacing:.06em;color:var(--ink);display:block;margin-bottom:4px}
.rung .txt{font-family:var(--font-display);font-size:11.5px;line-height:1.34;color:var(--ink-2);display:block}
.rung.na{opacity:.42}
/* ---------- matrix ---------- */
.matrix-shell{display:grid;grid-template-columns:auto minmax(0,1fr);gap:12px;align-items:stretch;margin-bottom:14px}
.ylab{writing-mode:vertical-rl;transform:rotate(180deg);font-family:var(--font-mono);font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);text-align:center;padding-bottom:22px}
.mgrid{display:grid;grid-template-columns:34px repeat(5,minmax(0,1fr));gap:3px}
.mcell{background:var(--surface);min-height:60px;padding:6px;display:flex;flex-direction:column;justify-content:flex-end;gap:4px;min-width:0}
.mcell.tint1{background:color-mix(in srgb,var(--l1) 26%,var(--surface))}
.mcell.tint2{background:color-mix(in srgb,var(--l2) 26%,var(--surface))}
.mcell.tint3{background:color-mix(in srgb,var(--l3) 24%,var(--surface))}
.mcell.tint4{background:color-mix(in srgb,var(--l4) 22%,var(--surface))}
.mcell.void{background:repeating-linear-gradient(135deg,transparent,transparent 5px,var(--rule) 5px,var(--rule) 6px);opacity:.55}
.rlab,.clab{font-family:var(--font-mono);font-size:10px;font-weight:600;letter-spacing:.05em;color:var(--ink-3);display:flex;align-items:center;justify-content:center}
.rlab{min-height:60px}
.clab{padding-top:7px;min-height:22px}
.pin{font-family:var(--font-mono);font-size:9.5px;font-weight:600;letter-spacing:.02em;background:var(--ink);color:var(--paper);padding:2px 5px;border-radius:2px;line-height:1.3;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pin.ghost{background:transparent;color:var(--ink-2);border:1px dashed var(--rule-strong)}
.mnote{display:flex;gap:22px;flex-wrap:wrap;font-family:var(--font-display);font-size:12px;color:var(--ink-3);padding-top:6px}
.mnote .k{display:flex;align-items:center;gap:7px}
.sw{width:13px;height:13px;flex:none;background:var(--ink)}
.sw.g{background:transparent;border:1px dashed var(--rule-strong)}
.sw.v{background:repeating-linear-gradient(135deg,transparent,transparent 4px,var(--rule) 4px,var(--rule) 5px);border:1px solid var(--rule)}
@media (max-width:640px){
.mgrid{grid-template-columns:28px repeat(5,minmax(0,1fr))}
.mcell{min-height:52px;padding:4px}
.pin{font-size:8px;padding:1px 3px}
.rlab{min-height:52px}
}
/* ---------- methodology ---------- */
.verbs{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule)}
.verb{background:var(--surface);padding:18px 18px 20px}
.verb h4{font-family:var(--font-display);font-weight:750;font-size:15px;margin:0 0 7px;letter-spacing:-.01em}
.verb p{font-family:var(--font-display);font-size:12.5px;line-height:1.46;color:var(--ink-2);margin:0;max-width:none}
.verb .step{font-family:var(--font-mono);font-size:9.5px;letter-spacing:.13em;color:var(--brass);display:block;margin-bottom:9px}
/* ---------- questions ---------- */
.qs{display:flex;flex-direction:column;gap:0;border-top:1px solid var(--rule-strong)}
.q{display:grid;grid-template-columns:34px minmax(0,1fr) 170px;gap:18px;padding:16px 0;border-bottom:1px solid var(--rule);align-items:start}
@media (max-width:760px){.q{grid-template-columns:28px minmax(0,1fr);gap:12px}.q .owner{grid-column:2}}
.q .qn{font-family:var(--font-mono);font-size:11px;color:var(--brass);padding-top:3px}
.q .qt{font-family:var(--font-display);font-size:14px;line-height:1.48;color:var(--ink-2)}
.q .qt b{color:var(--ink);font-weight:700;display:block;margin-bottom:2px;font-size:14.5px}
.owner{font-family:var(--font-mono);font-size:10px;letter-spacing:.05em;color:var(--ink-3);padding-top:4px}
.owner .tag{display:inline-block;border:1px solid var(--rule-strong);padding:2px 7px;border-radius:2px}
.owner .tag.need{border-color:var(--clay);color:var(--clay)}
/* ---------- misc ---------- */
.numbers{font-family:var(--font-mono);font-size:12.5px;line-height:1.85;background:var(--surface);border-left:3px solid var(--l3);padding:16px 20px;margin:0 0 22px;overflow-x:auto;max-width:var(--measure)}
.numbers .v{color:var(--ink);font-weight:600}
.numbers .k{color:var(--ink-3)}
pre{font-family:var(--font-mono);font-size:12.5px;line-height:1.68;background:var(--surface);border-left:3px solid var(--rule-strong);padding:16px 20px;overflow-x:auto;margin:0 0 22px;max-width:var(--measure);color:var(--ink-2)}
.alt{border-bottom:1px solid var(--rule);padding:14px 0;max-width:var(--measure)}
.alt:last-of-type{border-bottom:none}
.alt b{font-family:var(--font-display);font-size:14px;display:block;margin-bottom:3px}
.alt p{font-size:14.5px;margin:0;color:var(--ink-2)}
.alt .verdict{font-family:var(--font-mono);font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--clay)}
footer{border-top:2px solid var(--ink);margin-top:20px;padding-top:22px;font-family:var(--font-mono);font-size:11px;letter-spacing:.06em;color:var(--ink-3);display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap}
.tm td,.tm th{text-align:center}
.tm td:first-child,.tm th:first-child{text-align:left}
.yes{color:var(--l4);font-weight:700}
.no{color:var(--clay);font-weight:700}
.kind{font-family:var(--font-mono);font-size:9px;letter-spacing:.09em;text-transform:uppercase;padding:2px 6px;border-radius:2px;white-space:nowrap;border:1px solid var(--rule-strong);color:var(--ink-3)}
.kind.adv{border-color:var(--clay);color:var(--clay)}
.routes{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:2px;background:var(--rule);border:1px solid var(--rule);margin:0 0 22px}
.route{background:var(--surface);padding:16px 18px}
.route h4{font-family:var(--font-display);font-weight:750;font-size:14px;margin:0 0 6px}
.route p{font-family:var(--font-display);font-size:12.5px;line-height:1.45;color:var(--ink-2);margin:0;max-width:none}
.route .tag{font-family:var(--font-mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);display:block;margin-bottom:8px}
a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-offset:3px}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
</style>
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-001</span> <span class="stat">accepted · accepted-2</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Workplans and Work Items Are Repository Artefacts</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-001-workplans-as-repo-artefacts.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-28</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#status"><span class="n">·</span>Status</a></li><li><a href="#context"><span class="n">·</span>Context</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#workplan-closure"><span class="n">·</span>Workplan closure</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#migration"><span class="n">·</span>Migration</a></li><li><a href="#alternatives-considered"><span class="n">·</span>Alternatives considered</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
<p>Accepted 2026-02-28.</p>
<p>Amended 2026-08-31 to distinguish file-backed work records from hub-native records, identify the Forge default branch as the central projection baseline, and align identity, lifecycle, reconciliation, and closure with ADR-007, ADR-010, ADR-011, ADR-012, and the work-record standards. The central decision is unchanged.</p>
</section>
<section id="context"><h2>Context</h2>
<p>During early State Hub development, workstreams and tasks were created directly in PostgreSQL through bootstrap APIs. This made a database the origin of durable work rather than a projection of repository-owned artefacts. The pattern was convenient, but it made work difficult to audit, review, recover, and carry between generations of tooling.</p>
<p>The original decision correctly moved durable workplans and their work items into repositories. It overstated the consequence, however, by saying that the entire Hub database and every item that matters for coordination must be reconstructible from repository files. Later decisions established two different persistence classes:</p>
<ul><li><strong>file-backed records</strong>, whose durable meaning originates in a repository;</li><li><strong>hub-native records</strong>, such as append-only progress and runtime facts, whose durable meaning originates in the Hub.</li></ul>
<p>Later decisions also established that a central projection reads the pushed default branch in Forgejo. An arbitrary workstation checkout is a workspace, not the shared baseline. Unpushed local work may be represented only as an explicit preliminary overlay.</p>
</section>
<section id="decision"><h2>Decision</h2>
<h3>1. File-backed work originates in the owning repository</h3>
<p>Workplans and their file-backed work items <strong>MUST originate as repository artefacts in the repository that owns the work</strong>. The Hub indexes and projects those artefacts but is not their origin.</p>
<p>This includes the workplan, embedded tasks, declared dependencies, residual handoffs, and durable governed decision artefacts when those are represented as files. No authoritative field of a file-backed record may exist solely in a Hub database.</p>
<p>The owning repository is identified by repository identity, not merely by a domain or topic. Domains and topics classify work; they do not own its source.</p>
<h3>2. Authority is explicit per persistence class</h3>
<p>Every record contract must declare whether the record is file-backed or hub-native. The same record must not be writable as authoritative in both places.</p>
<ul><li>For a <strong>file-backed record</strong>, the repository artefact is authoritative and the Hub row is derived state.</li><li>For a <strong>hub-native record</strong>, the Hub is authoritative. Progress events, messages, token events, run history, and similar runtime facts are not made fictional repository records merely to satisfy a rebuild slogan.</li></ul>
<p>The word <code>decision</code> is used by more than one subsystem. Architecture decisions and other governed decision artefacts remain files. A runtime decision event may be hub-native only where its schema says so explicitly; it does not replace the governed artefact.</p>
<p>This replaces the original blanket rejection of a hybrid architecture. The architecture is hybrid <strong>by declared record class</strong>, never ambiguous within one record.</p>
<h3>3. Forge is the central projection baseline</h3>
<p>For the shared central view, the source is the pushed default-branch state held by Forgejo, as decided by ADR-012. Every projected record must be attributable to its source repository, path, and commit.</p>
<p>A working copy remains the authoring workspace. Unpushed work may appear in the Hub only as an attributed preliminary overlay. It must not silently replace or be presented as the Forge-derived baseline. When its commit reaches Forge, the baseline absorbs it and the overlay retires.</p>
<h3>4. Mutations of file-backed state are file-first</h3>
<p>Creating or changing a file-backed work record means changing its repository artefact first. A convenience tool or API is conformant only when it performs a governed repository mutation and leaves a reviewable file and commit. Writing only the projected database row is not a durable update.</p>
<p>Direct Hub APIs remain valid for hub-native records. They may also provide diagnostics or propose repository patches, but a successful database PATCH is not evidence that a file-backed status changed.</p>
<h3>5. The rebuild guarantee applies to the projection, not the whole database</h3>
<p>Given a repository and a specific Forge commit, the system must be able to reconcile that repository's file-derived projection so that it is equivalent to the records derived from that commit. Reconciliation must be idempotent, verifiable, and scoped per repository; a fleet operation is iteration over the same per-repository operation.</p>
<p>Reconciliation retires file-derived records that no longer derive. It does not delete hub-native history attached to them. It must refuse and report a repository whose records exist only in the projection until those records have an explicit disposition. A Forge rebuild does not reconstruct preliminary overlays and must disclose their retirement before proceeding.</p>
<p>Therefore the <strong>file-derived projection is disposable</strong>. The database as a whole is not disposable when it also contains hub-native facts.</p>
<h3>6. Identity and lifecycle are delegated contracts</h3>
<p>This ADR does not define a second identity or lifecycle schema.</p>
<ul><li>Workplan and task identity follow ADR-007 as amended by ADR-011: global identity is namespace-aware, and derivable Hub identifiers are governed by that contract. Existing historical identifiers are grandfathered according to its migration rules.</li><li>Work-record kinds, locations, lifecycle values, and residual handling follow <code>canon/standards/work-record-types_v0.1.md</code> and <code>canon/standards/workplan-terminology-fleet_v0.1.md</code>.</li></ul>
<p>New normative text uses <code>workplan</code> and <code>work record</code>. <code>workstream</code> remains only as a metered compatibility term for legacy database and API surfaces.</p>
<h3>7. Reconciliation belongs at the repository boundary</h3>
<p>Repo Manager owns discovery, parsing, identity checks, and reconciliation for file-backed records. State Hub owns the projection and hub-native records. The implementation may distribute fetch and parse work, but it must preserve that authority boundary.</p>
<p>Legacy <code>create_workstream</code>, <code>create_task</code>, workstation-driven <code>sync-workplans</code>, and similarly named commands are not normative interfaces. They are conformant only if their current implementation satisfies decisions 3 and 4; otherwise they are transitional or retired.</p>
</section>
<section id="workplan-closure"><h2>Workplan closure</h2>
<p>A workplan cannot be marked <code>finished</code> merely by changing its Hub row. Before closure, the responsible worker must:</p>
<ol><li>review the source file and the projected view for unfinished tasks;</li><li>record completed and cancelled outcomes in the source task blocks using the canonical task lifecycle;</li><li>turn every actionable carry-forward item into a live work record with <code>origin: residual</code> and an <code>origin_ref</code>, or into another explicitly linked workplan;</li><li>set the source workplan to <code>finished</code>, update it, and commit the result;</li><li>publish the commit to Forge for the shared baseline and verify that the projection reconciles to that commit.</li></ol>
<p>A local reconciliation before push may expose preliminary state, but it does not complete step 5.</p>
<p>Automated stale-task cleanup must report file/projection drift. It may not silently cancel a file-backed task only in the database. An automated repair may change such a task only through the same governed repository mutation and commit path as any other file-backed change. Cleanup of hub-native records is governed by their own retention contract.</p>
</section>
<section id="consequences"><h2>Consequences</h2>
<h3>Positive</h3>
<ul><li>Durable work remains inspectable, reviewable, and recoverable through Git.</li><li>The central view has an exact repository and commit provenance instead of reflecting whichever workstation synced most recently.</li><li>Reconciliation can be exercised per repository without destroying progress history or other hub-native evidence.</li><li>Multiple contributors share a published baseline while retaining an honest representation of preliminary work.</li><li>Service ownership is clearer: repositories own file-backed truth; the Hub owns runtime facts and projection services.</li></ul>
<h3>Negative</h3>
<ul><li>File-backed changes require a repository mutation and normally a push before they become shared baseline state.</li><li>Forge availability affects projection freshness, although it does not prevent local authoring.</li><li>Preliminary, stale, and retired projection states must be visible in APIs and user interfaces.</li><li>Git merge conflicts become the explicit conflict mechanism for simultaneous edits to the same authoritative artefact.</li><li>Tools that previously corrected only database state must be changed to emit a diagnostic or perform a governed repository update.</li></ul>
</section>
<section id="migration"><h2>Migration</h2>
<p>No bulk rename, UUID rewrite, or historical file rewrite is required by this amendment. Existing identifiers and legacy terminology retain the grandfathering rules of ADR-007, ADR-011, and the terminology standard.</p>
<p>Implementations must audit and retire DB-first creation, closure, and stale-task cleanup paths. Existing file-backed projection rows without a Forge source commit are migration state: they must be matched to a repository artefact or explicitly dispositioned before reset. Forge-derived reconciliation and preliminary overlays are implemented under ADR-012 rather than duplicated here.</p>
<p>The <code>accepted-1</code> publication remains the immutable historical revision. This document is <code>accepted-2</code>.</p>
</section>
<section id="alternatives-considered"><h2>Alternatives considered</h2>
<p><strong>Database-first with export.</strong> Rejected. Export can be skipped, making the reviewable artefact secondary and stale.</p>
<p><strong>Files only, with no projection database.</strong> Rejected. Cross-repository queries, runtime views, and append-only operational facts need indexed services.</p>
<p><strong>Treat every Hub record as reconstructible from Git.</strong> Rejected. This either loses runtime truth during rebuild or creates artificial files whose only purpose is mirroring a database.</p>
<p><strong>Let working copies push authoritative projection rows.</strong> Rejected by ADR-012. It makes the baseline depend on the last workstation to reconcile and cannot be audited against a shared commit.</p>
</section>
<section id="related"><h2>Related</h2>
<ul><li>ADR-003 — materialized and derived state</li><li>ADR-005 — cross-repository work ownership</li><li>ADR-007 — workplan identity and repository worker topology</li><li>ADR-010 — Hub authority and local cache model</li><li>ADR-011 — namespace-aware federation and reconciliation limits</li><li>ADR-012 — Forge projection source and preliminary overlay</li><li><code>canon/standards/work-record-types_v0.1.md</code> — work-record kinds, lifecycle, residuals, and reconciliation</li><li><code>canon/standards/workplan-terminology-fleet_v0.1.md</code> — canonical terminology</li><li><code>canon/values/foundational_values_v0.1.md</code> — local-first operation, auditability, and reversibility</li></ul>
</section><footer><span>CUST-ADR-001 · accepted-2 · accepted</span><span>the-custodian · canon/architecture/adr-001-workplans-as-repo-artefacts.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>