feat: publish custodian fleet standards batch
Some checks failed
Build and publish policy-nexus image / build-and-push (push) Failing after 0s
Some checks failed
Build and publish policy-nexus image / build-and-push (push) Failing after 0s
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a058f3-8ba0-7692-a042-9a870fc3d663
This commit is contained in:
parent
885c6bb1cb
commit
5fbd44a703
35 changed files with 3077 additions and 148 deletions
|
|
@ -1,5 +1,5 @@
|
|||
# Uses the estate's tier-2 container-build runner and organization-scoped
|
||||
# REGISTRY_USER / REGISTRY_TOKEN secrets.
|
||||
# Uses the estate's tier-2 container-build runner, a dedicated repository-read
|
||||
# FORGEJO_SOURCE_TOKEN, and package-write REGISTRY_USER / REGISTRY_TOKEN.
|
||||
name: Build and publish policy-nexus image
|
||||
|
||||
on:
|
||||
|
|
@ -25,8 +25,12 @@ concurrency:
|
|||
group: policy-nexus-publication
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
REGISTRY: forgejo.coulomb.social
|
||||
FORGEJO_ORIGIN: https://forgejo.coulomb.social
|
||||
IMAGE_NAME: coulomb/policy-nexus
|
||||
DOCKER_HOST: tcp://127.0.0.1:2375
|
||||
|
||||
|
|
@ -36,12 +40,17 @@ jobs:
|
|||
steps:
|
||||
- name: Build, verify, and publish immutable policy artifact
|
||||
env:
|
||||
FORGEJO_SOURCE_TOKEN: ${{ secrets.FORGEJO_SOURCE_TOKEN }}
|
||||
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
|
||||
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
run: |
|
||||
set -eu
|
||||
REF="${GITHUB_SHA:-}"
|
||||
test "${#REF}" -eq 40
|
||||
if [ -z "${FORGEJO_SOURCE_TOKEN:-}" ]; then
|
||||
echo "FORGEJO_SOURCE_TOKEN is required for private source repositories" >&2
|
||||
exit 2
|
||||
fi
|
||||
SHORT="${REF:0:7}"
|
||||
BUILD_ROOT="$(mktemp -d)"
|
||||
PYTHON_CONTAINER=""
|
||||
|
|
@ -56,7 +65,8 @@ jobs:
|
|||
mkdir -p "${BUILD_CONTEXT}" "${HOME}/bin"
|
||||
|
||||
wget -qO "${BUILD_ROOT}/policy-nexus.tar.gz" \
|
||||
"https://forgejo.coulomb.social/${GITHUB_REPOSITORY}/archive/${SHORT}.tar.gz"
|
||||
--header="Authorization: token ${FORGEJO_SOURCE_TOKEN}" \
|
||||
"${FORGEJO_ORIGIN}/${GITHUB_REPOSITORY}/archive/${REF}.tar.gz"
|
||||
tar xzf "${BUILD_ROOT}/policy-nexus.tar.gz" \
|
||||
-C "${BUILD_CONTEXT}" --strip-components=1
|
||||
|
||||
|
|
@ -69,11 +79,14 @@ jobs:
|
|||
docker create --name "${PYTHON_CONTAINER}" "${PYTHON_IMAGE}" sleep 300
|
||||
docker cp "${BUILD_CONTEXT}/." "${PYTHON_CONTAINER}:/workspace"
|
||||
docker start "${PYTHON_CONTAINER}"
|
||||
docker exec --workdir /workspace "${PYTHON_CONTAINER}" \
|
||||
docker exec --workdir /workspace \
|
||||
--env FORGEJO_SOURCE_TOKEN "${PYTHON_CONTAINER}" \
|
||||
python3 tools/fetch_sources.py \
|
||||
--config source-inventory.config.json \
|
||||
--destination _sources \
|
||||
--policy-revision "${REF}"
|
||||
--policy-revision "${REF}" \
|
||||
--token-env FORGEJO_SOURCE_TOKEN \
|
||||
--token-origin "${FORGEJO_ORIGIN}"
|
||||
NETKINGDOM_REVISION="$(docker exec "${PYTHON_CONTAINER}" python3 -c 'import json; print(json.load(open("/workspace/_sources/source-lock.json"))["repositories"]["net-kingdom"]["revision"])')"
|
||||
SOURCE_SET_DIGEST="$(docker exec "${PYTHON_CONTAINER}" python3 -c 'import json; print(json.load(open("/workspace/_sources/source-lock.json"))["source_set_digest"])')"
|
||||
docker cp "${PYTHON_CONTAINER}:/workspace/_sources" "${BUILD_CONTEXT}/"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="6515ed9ef8499cb3de3397f0ae3993cc71440599">
|
||||
<meta name="policy-source-revision" content="885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373">
|
||||
<meta name="policy-source-digest" content="a28668fb4b8b6c5ec8c94baac000061276d85ef1849ec7ab8d132b913dbfe3be">
|
||||
<title>Policy addressing and permanence</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>policy-nexus-adr-0001</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>Policy addressing and permanence</h1><p class="sub">Source: <code>policy-nexus · docs/adr/ADR-0001-addressing-and-permanence.md · 6515ed9ef8499cb3de3397f0ae3993cc71440599</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#permanence-promise"><span class="n">·</span>Permanence promise</a></li><li><a href="#publication-scope"><span class="n">·</span>Publication scope</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li></ol></nav><main><ul><li>Status: accepted</li><li>Date: 2026-08-18</li><li>Owner: the-custodian</li></ul>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>policy-nexus-adr-0001</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>Policy addressing and permanence</h1><p class="sub">Source: <code>policy-nexus · docs/adr/ADR-0001-addressing-and-permanence.md · 885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#permanence-promise"><span class="n">·</span>Permanence promise</a></li><li><a href="#publication-scope"><span class="n">·</span>Publication scope</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li></ol></nav><main><ul><li>Status: accepted</li><li>Date: 2026-08-18</li><li>Owner: the-custodian</li></ul>
|
||||
<section id="decision"><h2>Decision</h2>
|
||||
<p>A document has one stable current address and immutable revision addresses:</p>
|
||||
<pre>/<kind>/<document>/<version>/
|
||||
|
|
@ -211,4 +211,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="consequences"><h2>Consequences</h2>
|
||||
<ul><li>Builds fail if a source disappears, an id differs, a path collides, or an immutable revision would change; stale output is not silently called fresh.</li><li>Pages show status, revision, owner, last review and exact source revision.</li><li>Availability remains restart recovery on the single-node rail. This contract promises stable addressing, not a high-availability SLA.</li></ul>
|
||||
</section><footer><span>policy-nexus-adr-0001 · accepted-1 · accepted</span><span>policy-nexus · docs/adr/ADR-0001-addressing-and-permanence.md · 6515ed9ef8499cb3de3397f0ae3993cc71440599</span></footer></main></div></div></html>
|
||||
</section><footer><span>policy-nexus-adr-0001 · accepted-1 · accepted</span><span>policy-nexus · docs/adr/ADR-0001-addressing-and-permanence.md · 885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="44500fc85cf29d8e9b2ee5c91994032ed3d04e5b">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="6aef66cd5cf71a48f5b4e14401dc19a755e2b182445b272d5952df0eb0dea8ec">
|
||||
<title>Custodian Agent Runtime — v0.1 Bootstrap Design</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-002</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-03-12</span><span>generated from canonical source — do not edit</span></div><h1>Custodian Agent Runtime — v0.1 Bootstrap Design</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-002-custodian-agent-runtime-design.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</code></p><p class="sub">Review due: 2026-09-12</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="#decisions"><span class="n">·</span>Decisions</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#deferred"><span class="n">·</span>Deferred</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-002</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-03-12</span><span>generated from canonical source — do not edit</span></div><h1>Custodian Agent Runtime — v0.1 Bootstrap Design</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-002-custodian-agent-runtime-design.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2026-09-12</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="#decisions"><span class="n">·</span>Decisions</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#deferred"><span class="n">·</span>Deferred</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -239,4 +239,4 @@ Act — Execute only sanctioned write operations from the plan</pre>
|
|||
</section>
|
||||
<section id="deferred"><h2>Deferred</h2>
|
||||
<ul><li>Async event loop / daemon mode (Phase 2)</li><li>RAG over canon (Phase 1 roadmap item)</li><li>Tool adapters beyond state-hub HTTP (planned in <code>runtime/tool_adapters/</code>)</li><li>Deployment on Railiance k3s as a scheduled CronJob</li></ul>
|
||||
</section><footer><span>CUST-ADR-002 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-002-custodian-agent-runtime-design.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-002 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-002-custodian-agent-runtime-design.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="44500fc85cf29d8e9b2ee5c91994032ed3d04e5b">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="a454df0e1d227f99ebb36c4abd45c76cc12579086d34f0c0ccfccfd7f4790823">
|
||||
<title>Canon Federation and Concept Ownership Across InfoTech and Commerce</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-006</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-17</span><span>generated from canonical source — do not edit</span></div><h1>Canon Federation and Concept Ownership Across InfoTech and Commerce</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-006-canon-federation-concept-ownership.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</code></p><p class="sub">Review due: 2027-02-17</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="#resolutions"><span class="n">·</span>Resolutions</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-006</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-17</span><span>generated from canonical source — do not edit</span></div><h1>Canon Federation and Concept Ownership Across InfoTech and Commerce</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-006-canon-federation-concept-ownership.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-17</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="#resolutions"><span class="n">·</span>Resolutions</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted 2026-08-17. All seven ownership questions are resolved (see Resolutions); content may now move under <code>CFED-WP-0001</code>.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -250,4 +250,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li>ADR-001 — workplans originate as repo files; hub is a read model</li><li>ADR-005 — cross-repo workplans live in dedicated project repos</li><li><code>info-tech-canon/infospace/models/organization/InfoTechCanonOrganizationModel.md:55</code></li><li><code>info-tech-canon/infospace/models/access-control/InfoTechCanonAccessControlModel.md:106</code>, <code>:214</code></li><li><code>info-tech-canon/infospace/models/governance/InfoTechCanonGovernanceModel.md:107</code></li><li><code>info-tech-canon/demand/CapabilityProvisionEconomics.md</code></li><li><code>identity-canon/canon/CanonicalGlossary.md</code>, <code>canon/DesignPrinciples.md</code></li></ul>
|
||||
</section><footer><span>CUST-ADR-006 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-006-canon-federation-concept-ownership.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-006 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-006-canon-federation-concept-ownership.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="44500fc85cf29d8e9b2ee5c91994032ed3d04e5b">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="3b68adfa6ab329e73f857cf691dc405136d2d66a0135e2c37c236aabe4659557">
|
||||
<title>Connectivity-First Network Posture for Custodian Infrastructure</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-004</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-03-26</span><span>generated from canonical source — do not edit</span></div><h1>Connectivity-First Network Posture for Custodian Infrastructure</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-004-connectivity-first-network-posture.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</code></p><p class="sub">Review due: 2026-09-26</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="#rationale"><span class="n">·</span>Rationale</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-rejected"><span class="n">·</span>Alternatives Rejected</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-004</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-03-26</span><span>generated from canonical source — do not edit</span></div><h1>Connectivity-First Network Posture for Custodian Infrastructure</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-004-connectivity-first-network-posture.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2026-09-26</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="#rationale"><span class="n">·</span>Rationale</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#alternatives-rejected"><span class="n">·</span>Alternatives Rejected</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -233,4 +233,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
<p>Considered briefly. VPN would solve the connectivity problem but introduces a persistent network layer that all traffic traverses, reducing the explicitness of individual access paths. ops-bridge tunnels are per-service and per-actor, which gives better observability and blast-radius control. VPN is not ruled out as a future complement but is not the primary approach.</p>
|
||||
<h3>Ad-hoc SSH (no ops-bridge)</h3>
|
||||
<p>The pre-ops-bridge approach. Rejected because it has no health checks, no actor attribution, no audit log, and requires manual intervention to restore. ops-bridge formalises the same SSH tunnel pattern with operational discipline.</p>
|
||||
</section><footer><span>CUST-ADR-004 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-004-connectivity-first-network-posture.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-004 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-004-connectivity-first-network-posture.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="44500fc85cf29d8e9b2ee5c91994032ed3d04e5b">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="13195a721d0e579715f5f39ca6f72b5e49c583611e6ca089e6d4618708ae917f">
|
||||
<title>Cross-Repo Workplans Live in Dedicated Project Repos</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-005</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-06-22</span><span>generated from canonical source — do not edit</span></div><h1>Cross-Repo Workplans Live in Dedicated Project Repos</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-005-cross-repo-workplans-project-repos.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</code></p><p class="sub">Review due: 2026-12-22</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="#lifecycle"><span class="n">·</span>Lifecycle</a></li><li><a href="#naming"><span class="n">·</span>Naming</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</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>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-005</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-06-22</span><span>generated from canonical source — do not edit</span></div><h1>Cross-Repo Workplans Live in Dedicated Project Repos</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-005-cross-repo-workplans-project-repos.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2026-12-22</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="#lifecycle"><span class="n">·</span>Lifecycle</a></li><li><a href="#naming"><span class="n">·</span>Naming</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</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.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -222,4 +222,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li>ADR-001 — Workplans and Work Items Are Repository Artefacts</li><li><code>CUST-WP-0050</code> — Repo Classification & State Hub Registration Redesign (D1)</li><li><code>canon/standards/repo-classification-standard_v1.0.md</code></li></ul>
|
||||
</section><footer><span>CUST-ADR-005 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-005-cross-repo-workplans-project-repos.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-005 · accepted-1 · accepted</span><span>the-custodian · canon/architecture/adr-005-cross-repo-workplans-project-repos.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="44500fc85cf29d8e9b2ee5c91994032ed3d04e5b">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="f94f429c72f6cfd01ee83f1e5689d2d10ae52d7588d7cbd3ca40aca7eef46fb0">
|
||||
<title>Federated Namespaces</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-011</span> <span class="stat">proposed · draft-2</span> <span>the-custodian</span> <span>reviewed 2026-08-17</span><span>generated from canonical source — do not edit</span></div><h1>Federated Namespaces</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-011-federated-namespaces-and-reconciliation-limits.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</code></p><p class="sub">Review due: 2027-02-17</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="#reconciliation-tiers-and-where-automation-stops"><span class="n">·</span>Reconciliation tiers, and where automation stops</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#open-question"><span class="n">·</span>Open question</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-011</span> <span class="stat">proposed · draft-2</span> <span>the-custodian</span> <span>reviewed 2026-08-17</span><span>generated from canonical source — do not edit</span></div><h1>Federated Namespaces</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-011-federated-namespaces-and-reconciliation-limits.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-17</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="#reconciliation-tiers-and-where-automation-stops"><span class="n">·</span>Reconciliation tiers, and where automation stops</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#open-question"><span class="n">·</span>Open question</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Proposed, draft-2. Amends <code>ADR-007</code> decisions 1 and 2; extends <code>ADR-010</code> decision 4; adopts the plane/ladder/posture form and the accuracy-not-altitude conformance rule from <code>ADR-008</code> (Multi-Tenancy Framework).</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -281,4 +281,4 @@ any participant below R2 -> T1 at best; manual thereafter
|
|||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li><code>canon/standards/federated-organization-standard_v1.0.md</code> — bounded autonomy, escalation, sovereignty by default, rebuildability</li><li>ADR-001 — workplans originate as repo files</li><li>ADR-007 — identifier uniqueness and derived identifiers (amended here)</li><li>ADR-008 — Multi-Tenancy Framework; source of the plane/ladder/posture form and the accuracy-not-altitude conformance rule</li><li>ADR-010 — hub authority, local cache, and the two kinds of hub data</li><li><code>CUST-WP-0058</code> — instance-per-client tenancy</li><li><code>SHR-INV-0001</code> — 425-item disposition inventory, T3 cost evidence</li><li><code>RMGR-WP-0004-T02</code> — <code>rmgr conform</code>, the guard machinery</li></ul>
|
||||
</section><footer><span>CUST-ADR-011 · draft-2 · proposed</span><span>the-custodian · canon/architecture/adr-011-federated-namespaces-and-reconciliation-limits.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-011 · draft-2 · proposed</span><span>the-custodian · canon/architecture/adr-011-federated-namespaces-and-reconciliation-limits.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="44500fc85cf29d8e9b2ee5c91994032ed3d04e5b">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="5979da20799118259fc19246f51e8cc8f2c0c1be3d414318bd51d5a27d9ad565">
|
||||
<title>Hub Authority, Local Cache, and the Two Kinds of Hub Data</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-010</span> <span class="stat">proposed · draft-2</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Hub Authority, Local Cache, and the Two Kinds of Hub Data</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-010-hub-authority-and-local-cache-model.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</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="#orphan-disposition"><span class="n">·</span>Orphan disposition</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#implementation"><span class="n">·</span>Implementation</a></li><li><a href="#references"><span class="n">·</span>References</a></li><li><a href="#outcome-2026-08-24"><span class="n">·</span>Outcome (2026-08-24)</a></li><li><a href="#outcome-2026-08-28"><span class="n">·</span>Outcome (2026-08-28)</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-010</span> <span class="stat">proposed · draft-2</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Hub Authority, Local Cache, and the Two Kinds of Hub Data</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-010-hub-authority-and-local-cache-model.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="#orphan-disposition"><span class="n">·</span>Orphan disposition</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#implementation"><span class="n">·</span>Implementation</a></li><li><a href="#references"><span class="n">·</span>References</a></li><li><a href="#outcome-2026-08-24"><span class="n">·</span>Outcome (2026-08-24)</a></li><li><a href="#outcome-2026-08-28"><span class="n">·</span>Outcome (2026-08-28)</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Proposed, and <strong>partially superseded by <code>ADR-012</code></strong> (accepted 2026-08-25). Decisions 1, 5 and 6 are sharpened or given a mechanism there; see the notes on each below. Everything else in this ADR remains in force.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -250,4 +250,4 @@ same filename, different UUID 4 duplicate registration</pre>
|
|||
<section id="outcome-2026-08-28"><h2>Outcome (2026-08-28)</h2>
|
||||
<div class="rule-quote"><p>Added by <code>CUST-WP-0068</code>. The 2026-08-24 outcome closed the <em>repository</em> divergence. The work-record divergence this ADR originally measured — 955 local / 649 primary — remained, because the retired instance's database was still load-bearing. That is now closed.</p></div>
|
||||
<ul><li><strong>Central holds 1167 workplans.</strong> Records that existed only in the cache were re-derived from their files, renamed onto the canonical scheme, or given a written disposition (<code>docs/recovery/cache-only-disposition-2026-08-28.md</code>).</li><li><strong>No open work record exists only in the cache.</strong> Remaining cache-only slugs are aliases of recovered records, clay-borg product files (not workplans), or prefix-migration residue.</li><li><strong>The cache database is discarded.</strong> Final dump <code>~/backups/state-hub-cache-2026-08-28.dump</code>. Container <code>infra-postgres-1</code> and volume <code>infra_pg_data</code> removed. Port 5432 is free.</li><li><strong>The local instance is no longer load-bearing for any record type.</strong> Decision 3 is now true in operation, not only in argument.</li></ul>
|
||||
</section><footer><span>CUST-ADR-010 · draft-2 · proposed</span><span>the-custodian · canon/architecture/adr-010-hub-authority-and-local-cache-model.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-010 · draft-2 · proposed</span><span>the-custodian · canon/architecture/adr-010-hub-authority-and-local-cache-model.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="44500fc85cf29d8e9b2ee5c91994032ed3d04e5b">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="fcb49719e2b85b9120c0bd5bebd5e82748ca713f16b44951c028b60205514e2b">
|
||||
<title>Materialized Derived State with Fingerprint Invalidation for Repo-Sourced Data</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-003</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>Materialized Derived State with Fingerprint Invalidation for Repo-Sourced Data</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-003-materialized-derived-state.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</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="#pattern-name"><span class="n">·</span>Pattern Name</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#implementation-checklist"><span class="n">·</span>Implementation Checklist</a></li><li><a href="#current-implementations"><span class="n">·</span>Current Implementations</a></li><li><a href="#planned-applications"><span class="n">·</span>Planned Applications</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-003</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>Materialized Derived State with Fingerprint Invalidation for Repo-Sourced Data</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-003-materialized-derived-state.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="#pattern-name"><span class="n">·</span>Pattern Name</a></li><li><a href="#decision"><span class="n">·</span>Decision</a></li><li><a href="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#implementation-checklist"><span class="n">·</span>Implementation Checklist</a></li><li><a href="#current-implementations"><span class="n">·</span>Current Implementations</a></li><li><a href="#planned-applications"><span class="n">·</span>Planned Applications</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted, and <strong>partially superseded by <code>ADR-012</code></strong> (accepted 2026-08-25). Decision 2's fingerprint composition is invalidated in part; decision 5's rebuild principle is given a concrete source and a required operation. See the notes on each.</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -245,4 +245,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li>ADR-001: Workplans and Work Items Are Repository Artefacts</li><li>ADR-002: Custodian Agent Runtime Design</li><li><code>state-hub/api/doi_engine.py</code> — reference implementation</li><li><code>state-hub/api/models/doi_cache.py</code> — reference schema</li><li><code>state-hub/migrations/versions/k8f9a0b1c2d3_doi_cache.py</code> — reference migration</li></ul>
|
||||
</section><footer><span>CUST-ADR-003 · accepted-2 · accepted</span><span>the-custodian · canon/architecture/adr-003-materialized-derived-state.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-003 · accepted-2 · accepted</span><span>the-custodian · canon/architecture/adr-003-materialized-derived-state.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="44500fc85cf29d8e9b2ee5c91994032ed3d04e5b">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="b5e8582459f546ae789ad5fd62f458454aa19997b520e32b6b9f792d6af55987">
|
||||
<title>What the Hub Projects</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-012</span> <span class="stat">accepted · 1.0</span> <span>the-custodian</span> <span>reviewed 2026-08-25</span><span>generated from canonical source — do not edit</span></div><h1>What the Hub Projects</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-012-projection-source-and-preliminary-overlay.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</code></p><p class="sub">Review due: 2027-02-25</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="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#relationship-to-prior-decisions"><span class="n">·</span>Relationship to prior decisions</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-012</span> <span class="stat">accepted · 1.0</span> <span>the-custodian</span> <span>reviewed 2026-08-25</span><span>generated from canonical source — do not edit</span></div><h1>What the Hub Projects</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-012-projection-source-and-preliminary-overlay.md · 4b951be3947f9457cc091a7d359d9232646b4c93</code></p><p class="sub">Review due: 2027-02-25</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="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#relationship-to-prior-decisions"><span class="n">·</span>Relationship to prior decisions</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p><strong>Accepted 2026-08-25</strong> by Bernd Worsch. Supersedes <code>ADR-010</code> decision 1's phrase "authoritative as a reading of the repositories" by making the reading concrete, and implements decision 6's unbuilt notion of "preliminary".</p>
|
||||
</section>
|
||||
<section id="context"><h2>Context</h2>
|
||||
|
|
@ -245,4 +245,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li><code>ADR-001</code> — workplans originate as repo files; hub is a read model</li><li><code>ADR-010</code> — hub authority, local cache, and the two kinds of hub data</li><li><code>ADR-007</code> — identifier uniqueness and derived identifiers</li><li><code>CUST-WP-0067</code> — hub target resolution; retired the impersonating local instance</li><li><code>CUST-WP-0068</code> — cache-only work-record recovery; surfaced the stale <code>git_fingerprint</code> and the duplicate registrations</li><li>Verification, 2026-08-25: central pod holds no repository files; <code>sweep</code> disabled; 117 repositories record a laptop path; <code>the-custodian</code> <code>git_fingerprint</code> is the initial commit while <code>last_state_synced_at</code> is current</li></ul>
|
||||
</section><footer><span>CUST-ADR-012 · 1.0 · accepted</span><span>the-custodian · canon/architecture/adr-012-projection-source-and-preliminary-overlay.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-012 · 1.0 · accepted</span><span>the-custodian · canon/architecture/adr-012-projection-source-and-preliminary-overlay.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="44500fc85cf29d8e9b2ee5c91994032ed3d04e5b">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="1169f0c1f485a2bb7241a8f64f3167c060c04f83341b12586fd9be5c2b3693f8">
|
||||
<title>Workplan Identity Uniqueness, Single Registrar, and Repo Worker Topology</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-007</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>Workplan Identity Uniqueness, Single Registrar, and Repo Worker Topology</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</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="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#migration-needs-a-separate-ruling"><span class="n">·</span>Migration — needs a separate ruling</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>CUST-ADR-007</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>Workplan Identity Uniqueness, Single Registrar, and Repo Worker Topology</h1><p class="sub">Source: <code>the-custodian · canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.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="#consequences"><span class="n">·</span>Consequences</a></li><li><a href="#migration-needs-a-separate-ruling"><span class="n">·</span>Migration — needs a separate ruling</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="status"><h2>Status</h2>
|
||||
<p>Accepted 2026-08-17. Identifier uniqueness, the registrar model, lifecycle protection, and worker topology are settled.</p>
|
||||
<p><strong>Remediation of existing collisions (§ Migration) remains an open ruling.</strong> It is disruptive, touches six repositories, and no active work depends on it — all five duplicated identifiers are <code>finished</code>.</p>
|
||||
</section>
|
||||
|
|
@ -276,4 +276,4 @@ CUST-WP- the-custodian 50 plans
|
|||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li>Decision <code>747011c6</code> — repository standards belong to Repo Manager</li><li>ADR-001 — workplans originate as repo files; hub is a read model</li><li><code>RMGR-WP-0004</code> — repository standards conformance and governed scaffolding</li><li><code>STATE-WP-0080</code> — register scaffolding handoff</li><li>Fleet scan 2026-08-16: 955 hub workplans, 525 parseable identifiers, 3 reused prefixes, 5 reused identifiers</li></ul>
|
||||
</section><footer><span>CUST-ADR-007 · accepted-2 · accepted</span><span>the-custodian · canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</span></footer></main></div></div></html>
|
||||
</section><footer><span>CUST-ADR-007 · accepted-2 · accepted</span><span>the-custodian · canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="44500fc85cf29d8e9b2ee5c91994032ed3d04e5b">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="183023ee57bae9c29e726fec5ee0361633fe3a2b182436a57869ae4b2a27af24">
|
||||
<title>Workplans and Work Items Are Repository Artefacts</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@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 · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</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>
|
||||
<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>
|
||||
|
|
@ -254,4 +254,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</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 · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</span></footer></main></div></div></html>
|
||||
</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>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="44500fc85cf29d8e9b2ee5c91994032ed3d04e5b">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="3b4f93acdedc6f6d1a1c737c3327d9d55061506c5a879be09e6b0a2ea7f5f9bc">
|
||||
<title>Coulomb estate architecture</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>coulomb-estate-architecture</span> <span class="stat">proposed · draft-3</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Coulomb estate architecture</h1><p class="sub">Source: <code>the-custodian · canon/architecture/coulomb-estate_v0.1.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</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="#about-this-document"><span class="n">·</span>About this document</a></li><li><a href="#s1"><span class="n">1</span>Introduction and Goals</a></li><li><a href="#s2"><span class="n">2</span>Architecture Constraints</a></li><li><a href="#s3"><span class="n">3</span>System Scope and Context</a></li><li><a href="#s4"><span class="n">4</span>Solution Strategy</a></li><li><a href="#s5"><span class="n">5</span>Building Block View</a></li><li><a href="#s6"><span class="n">6</span>Runtime View</a></li><li><a href="#s7"><span class="n">7</span>Deployment View</a></li><li><a href="#s8"><span class="n">8</span>Cross-Cutting Concepts</a></li><li><a href="#s9"><span class="n">9</span>Architecture Decisions</a></li><li><a href="#s10"><span class="n">10</span>Quality Requirements</a></li><li><a href="#s11"><span class="n">11</span>Risks and Technical Debt</a></li><li><a href="#s12"><span class="n">12</span>Glossary</a></li></ol></nav><main><section id="about-this-document"><h2>About this document</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>coulomb-estate-architecture</span> <span class="stat">proposed · draft-3</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Coulomb estate architecture</h1><p class="sub">Source: <code>the-custodian · canon/architecture/coulomb-estate_v0.1.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="#about-this-document"><span class="n">·</span>About this document</a></li><li><a href="#s1"><span class="n">1</span>Introduction and Goals</a></li><li><a href="#s2"><span class="n">2</span>Architecture Constraints</a></li><li><a href="#s3"><span class="n">3</span>System Scope and Context</a></li><li><a href="#s4"><span class="n">4</span>Solution Strategy</a></li><li><a href="#s5"><span class="n">5</span>Building Block View</a></li><li><a href="#s6"><span class="n">6</span>Runtime View</a></li><li><a href="#s7"><span class="n">7</span>Deployment View</a></li><li><a href="#s8"><span class="n">8</span>Cross-Cutting Concepts</a></li><li><a href="#s9"><span class="n">9</span>Architecture Decisions</a></li><li><a href="#s10"><span class="n">10</span>Quality Requirements</a></li><li><a href="#s11"><span class="n">11</span>Risks and Technical Debt</a></li><li><a href="#s12"><span class="n">12</span>Glossary</a></li></ol></nav><main><section id="about-this-document"><h2>About this document</h2>
|
||||
<p>This is the first-wave <strong>estate map</strong>. It describes how the Coulomb / Custodian estate is put together: canons, hubs, rails, and publication. System-level arc42 documents (Railiance, NetKingdom, State Hub, Policy Nexus) live in their owning repos. Chapter 9 lists estate ADRs; it does not paste them.</p>
|
||||
</section>
|
||||
<section id="s1"><h2><span class="sn">01</span>Introduction and Goals</h2>
|
||||
|
|
@ -271,4 +271,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="s12"><h2><span class="sn">12</span>Glossary</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Term</th><th>Meaning</th></tr></thead><tbody><tr><td>Estate</td><td>The set of Coulomb / Custodian repos, canons, hubs, and rails.</td></tr><tr><td>Canon</td><td>Governing documents owned by one of the three federated canons.</td></tr><tr><td>Read model</td><td>A derived index. Never the origin of work or decisions.</td></tr><tr><td>Publication entry</td><td>One explicit object in policy-nexus <code>publication.json</code>.</td></tr><tr><td>First-wave complete</td><td>Chapters 1, 3, 4, 5.1, 9 and 12 are real; others real or N/A.</td></tr><tr><td>Project repo</td><td>A <code>prj-*</code> repo that coordinates cross-repo work (ADR-005).</td></tr></tbody></table></div>
|
||||
</section><footer><span>coulomb-estate-architecture · draft-3 · proposed</span><span>the-custodian · canon/architecture/coulomb-estate_v0.1.md · 44500fc85cf29d8e9b2ee5c91994032ed3d04e5b</span></footer></main></div></div></html>
|
||||
</section><footer><span>coulomb-estate-architecture · draft-3 · proposed</span><span>the-custodian · canon/architecture/coulomb-estate_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="6515ed9ef8499cb3de3397f0ae3993cc71440599">
|
||||
<meta name="policy-source-revision" content="885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373">
|
||||
<meta name="policy-source-digest" content="179cbb86bca95f71f46f51ca1971ff1c274eed7d900adf0672b537d4bcc5b480">
|
||||
<title>Policy Nexus architecture</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>policy-nexus-architecture</span> <span class="stat">proposed · draft-1</span> <span>the-custodian</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>Policy Nexus architecture</h1><p class="sub">Source: <code>policy-nexus · docs/architecture/policy-nexus_v0.1.md · 6515ed9ef8499cb3de3397f0ae3993cc71440599</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#about-this-document"><span class="n">·</span>About this document</a></li><li><a href="#s1"><span class="n">1</span>Introduction and Goals</a></li><li><a href="#s2"><span class="n">2</span>Architecture Constraints</a></li><li><a href="#s3"><span class="n">3</span>System Scope and Context</a></li><li><a href="#s4"><span class="n">4</span>Solution Strategy</a></li><li><a href="#s5"><span class="n">5</span>Building Block View</a></li><li><a href="#s6"><span class="n">6</span>Runtime View</a></li><li><a href="#s7"><span class="n">7</span>Deployment View</a></li><li><a href="#s8"><span class="n">8</span>Cross-Cutting Concepts</a></li><li><a href="#s9"><span class="n">9</span>Architecture Decisions</a></li><li><a href="#s10"><span class="n">10</span>Quality Requirements</a></li><li><a href="#s11"><span class="n">11</span>Risks and Technical Debt</a></li><li><a href="#s12"><span class="n">12</span>Glossary</a></li></ol></nav><main><section id="about-this-document"><h2>About this document</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>policy-nexus-architecture</span> <span class="stat">proposed · draft-1</span> <span>the-custodian</span> <span>reviewed 2026-08-18</span><span>generated from canonical source — do not edit</span></div><h1>Policy Nexus architecture</h1><p class="sub">Source: <code>policy-nexus · docs/architecture/policy-nexus_v0.1.md · 885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373</code></p><p class="sub">Review due: 2027-02-18</p></header><div class="layout"><nav class="rail" aria-label="Sections"><ol><li><a href="#about-this-document"><span class="n">·</span>About this document</a></li><li><a href="#s1"><span class="n">1</span>Introduction and Goals</a></li><li><a href="#s2"><span class="n">2</span>Architecture Constraints</a></li><li><a href="#s3"><span class="n">3</span>System Scope and Context</a></li><li><a href="#s4"><span class="n">4</span>Solution Strategy</a></li><li><a href="#s5"><span class="n">5</span>Building Block View</a></li><li><a href="#s6"><span class="n">6</span>Runtime View</a></li><li><a href="#s7"><span class="n">7</span>Deployment View</a></li><li><a href="#s8"><span class="n">8</span>Cross-Cutting Concepts</a></li><li><a href="#s9"><span class="n">9</span>Architecture Decisions</a></li><li><a href="#s10"><span class="n">10</span>Quality Requirements</a></li><li><a href="#s11"><span class="n">11</span>Risks and Technical Debt</a></li><li><a href="#s12"><span class="n">12</span>Glossary</a></li></ol></nav><main><section id="about-this-document"><h2>About this document</h2>
|
||||
<p>This document follows the <strong>arc42</strong> template for the publication surface at <code>policy.coulomb.social</code>. It is the first-wave architecture document this repository is allowed to author. Other first-wave systems are written in their owning repos.</p>
|
||||
</section>
|
||||
<section id="s1"><h2><span class="sn">01</span>Introduction and Goals</h2>
|
||||
|
|
@ -245,4 +245,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="s12"><h2><span class="sn">12</span>Glossary</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Term</th><th>Meaning</th></tr></thead><tbody><tr><td>Current address</td><td>The stable URL for the document as it now stands.</td></tr><tr><td>Revision address</td><td>Write-once URL for one source digest.</td></tr><tr><td>Publication entry</td><td>One object in <code>publication.json</code>. Discovery is not publication.</td></tr><tr><td>First-wave complete</td><td>Chapters 1, 3, 4, 5.1, 9 and 12 are real; others real or N/A.</td></tr></tbody></table></div>
|
||||
</section><footer><span>policy-nexus-architecture · draft-1 · proposed</span><span>policy-nexus · docs/architecture/policy-nexus_v0.1.md · 6515ed9ef8499cb3de3397f0ae3993cc71440599</span></footer></main></div></div></html>
|
||||
</section><footer><span>policy-nexus-architecture · draft-1 · proposed</span><span>policy-nexus · docs/architecture/policy-nexus_v0.1.md · 885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373</span></footer></main></div></div></html>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="da30ce6723f9c5e6fdd994c78bb646986e819d3f">
|
||||
<meta name="policy-source-revision" content="0e35f84ad5f2f9397d76ffacb99f9973544f08ac">
|
||||
<meta name="policy-source-digest" content="e7104b2182612efe90c9a12168757506402490229814d454e94917ae62d2bfac">
|
||||
<title>State Hub architecture</title>
|
||||
<style>
|
||||
|
|
@ -191,7 +191,7 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
||||
|
||||
</style>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>state-hub-architecture</span> <span class="stat">proposed · draft-3</span> <span>state-hub</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>State Hub architecture</h1><p class="sub">Source: <code>state-hub · docs/architecture/state-hub_v0.1.md · da30ce6723f9c5e6fdd994c78bb646986e819d3f</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="#about-this-document"><span class="n">·</span>About this document</a></li><li><a href="#s1"><span class="n">1</span>Introduction and Goals</a></li><li><a href="#s2"><span class="n">2</span>Architecture Constraints</a></li><li><a href="#s3"><span class="n">3</span>System Scope and Context</a></li><li><a href="#s4"><span class="n">4</span>Solution Strategy</a></li><li><a href="#s5"><span class="n">5</span>Building Block View</a></li><li><a href="#s6"><span class="n">6</span>Runtime View</a></li><li><a href="#s7"><span class="n">7</span>Deployment View</a></li><li><a href="#s8"><span class="n">8</span>Cross-Cutting Concepts</a></li><li><a href="#s9"><span class="n">9</span>Architecture Decisions</a></li><li><a href="#s10"><span class="n">10</span>Quality Requirements</a></li><li><a href="#s11"><span class="n">11</span>Risks and Technical Debt</a></li><li><a href="#s12"><span class="n">12</span>Glossary</a></li></ol></nav><main><section id="about-this-document"><h2>About this document</h2>
|
||||
<div class="wrap"><header><div class="eyebrow"><span>state-hub-architecture</span> <span class="stat">proposed · draft-3</span> <span>state-hub</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>State Hub architecture</h1><p class="sub">Source: <code>state-hub · docs/architecture/state-hub_v0.1.md · 0e35f84ad5f2f9397d76ffacb99f9973544f08ac</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="#about-this-document"><span class="n">·</span>About this document</a></li><li><a href="#s1"><span class="n">1</span>Introduction and Goals</a></li><li><a href="#s2"><span class="n">2</span>Architecture Constraints</a></li><li><a href="#s3"><span class="n">3</span>System Scope and Context</a></li><li><a href="#s4"><span class="n">4</span>Solution Strategy</a></li><li><a href="#s5"><span class="n">5</span>Building Block View</a></li><li><a href="#s6"><span class="n">6</span>Runtime View</a></li><li><a href="#s7"><span class="n">7</span>Deployment View</a></li><li><a href="#s8"><span class="n">8</span>Cross-Cutting Concepts</a></li><li><a href="#s9"><span class="n">9</span>Architecture Decisions</a></li><li><a href="#s10"><span class="n">10</span>Quality Requirements</a></li><li><a href="#s11"><span class="n">11</span>Risks and Technical Debt</a></li><li><a href="#s12"><span class="n">12</span>Glossary</a></li></ol></nav><main><section id="about-this-document"><h2>About this document</h2>
|
||||
<p>First-wave arc42 for State Hub, the estate's live coordination read-model. This service is in active retirement planning; new permanent ownership should not land here. Chapter 9 points at the estate ADRs that still bind it.</p>
|
||||
</section>
|
||||
<section id="s1"><h2><span class="sn">01</span>Introduction and Goals</h2>
|
||||
|
|
@ -244,4 +244,4 @@ a:focus-visible,.rail a:focus-visible{outline:2px solid var(--brass);outline-off
|
|||
</section>
|
||||
<section id="s12"><h2><span class="sn">12</span>Glossary</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Term</th><th>Meaning</th></tr></thead><tbody><tr><td>Read model</td><td>Derived index; never the origin.</td></tr><tr><td>Registrar</td><td>The single instance allowed to mint workplan UUIDs.</td></tr><tr><td>Retirement</td><td>Coordinated move of capabilities out of this repo.</td></tr></tbody></table></div>
|
||||
</section><footer><span>state-hub-architecture · draft-3 · proposed</span><span>state-hub · docs/architecture/state-hub_v0.1.md · da30ce6723f9c5e6fdd994c78bb646986e819d3f</span></footer></main></div></div></html>
|
||||
</section><footer><span>state-hub-architecture · draft-3 · proposed</span><span>state-hub · docs/architecture/state-hub_v0.1.md · 0e35f84ad5f2f9397d76ffacb99f9973544f08ac</span></footer></main></div></div></html>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -17,6 +17,91 @@
|
|||
"status": "proposed",
|
||||
"title": "NetKingdom Tenancy Posture v0.1"
|
||||
},
|
||||
{
|
||||
"canonical_path": "standards/autonomy-lanes/v0.1/index.html",
|
||||
"currency": "current",
|
||||
"id": "canon-autonomy-lanes",
|
||||
"last_reviewed": "2026-08-31",
|
||||
"lifecycle": "active",
|
||||
"owner": "the-custodian",
|
||||
"review_due": "2027-02-28",
|
||||
"revision": "accepted-1",
|
||||
"revision_path": "standards/autonomy-lanes/v0.1/revisions/accepted-1/index.html",
|
||||
"source_digest": "106cb0c99f73983199c9f1d8491143aa2a2eb41ee450a02ec7968d3763f30399",
|
||||
"source_path": "canon/standards/autonomy-lanes_v0.1.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "accepted",
|
||||
"title": "Autonomy Lanes (Fleet) v0.1"
|
||||
},
|
||||
{
|
||||
"canonical_path": "standards/contribution-convention/v0.1/index.html",
|
||||
"currency": "current",
|
||||
"id": "canon-contrib-convention",
|
||||
"last_reviewed": "2026-08-31",
|
||||
"lifecycle": "active",
|
||||
"owner": "the-custodian",
|
||||
"review_due": "2027-02-28",
|
||||
"revision": "accepted-1",
|
||||
"revision_path": "standards/contribution-convention/v0.1/revisions/accepted-1/index.html",
|
||||
"source_digest": "6dfc1d7b2b82ab18228a84660c1c7dff607aad1d9da37ac12084cdd2ab8ae112",
|
||||
"source_path": "canon/standards/contribution-convention_v0.1.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "accepted",
|
||||
"title": "Contribution Convention v0.1"
|
||||
},
|
||||
{
|
||||
"canonical_path": "standards/project-repository-flavor/v0.1/index.html",
|
||||
"currency": "current",
|
||||
"id": "canon-project-repository-flavor",
|
||||
"last_reviewed": "2026-08-31",
|
||||
"lifecycle": "active",
|
||||
"owner": "the-custodian",
|
||||
"review_due": "2027-02-28",
|
||||
"revision": "accepted-1",
|
||||
"revision_path": "standards/project-repository-flavor/v0.1/revisions/accepted-1/index.html",
|
||||
"source_digest": "61889b2f18a82a08b66ef90d758efe5c028a4f52aced1721a23e69c6f24a8224",
|
||||
"source_path": "canon/standards/project-repository-flavor_v0.1.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "accepted",
|
||||
"title": "Project Repository Flavor (prj-) v0.1"
|
||||
},
|
||||
{
|
||||
"canonical_path": "standards/work-record-types/v0.1/index.html",
|
||||
"currency": "current",
|
||||
"id": "canon-work-record-types",
|
||||
"last_reviewed": "2026-08-31",
|
||||
"lifecycle": "active",
|
||||
"owner": "the-custodian",
|
||||
"review_due": "2027-02-28",
|
||||
"revision": "accepted-1",
|
||||
"revision_path": "standards/work-record-types/v0.1/revisions/accepted-1/index.html",
|
||||
"source_digest": "1a40de294be332ee713cdaab532a32a83718f3952c339fbff835ecee899a8dbc",
|
||||
"source_path": "canon/standards/work-record-types_v0.1.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "accepted",
|
||||
"title": "Work Record Types & Identity (Fleet) v0.1"
|
||||
},
|
||||
{
|
||||
"canonical_path": "standards/workplan-terminology/v0.1/index.html",
|
||||
"currency": "current",
|
||||
"id": "canon-workplan-terminology-fleet",
|
||||
"last_reviewed": "2026-08-31",
|
||||
"lifecycle": "active",
|
||||
"owner": "the-custodian",
|
||||
"review_due": "2027-02-28",
|
||||
"revision": "accepted-1",
|
||||
"revision_path": "standards/workplan-terminology/v0.1/revisions/accepted-1/index.html",
|
||||
"source_digest": "199812632ac342ca3231498e545e3701e10c191ca144035b36a23c1a0b717712",
|
||||
"source_path": "canon/standards/workplan-terminology-fleet_v0.1.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "accepted",
|
||||
"title": "Workplan Terminology (Fleet) v0.1"
|
||||
},
|
||||
{
|
||||
"canonical_path": "architecture/coulomb-estate/v0.1/index.html",
|
||||
"currency": "current",
|
||||
|
|
@ -30,7 +115,7 @@
|
|||
"source_digest": "3b4f93acdedc6f6d1a1c737c3327d9d55061506c5a879be09e6b0a2ea7f5f9bc",
|
||||
"source_path": "canon/architecture/coulomb-estate_v0.1.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "44500fc85cf29d8e9b2ee5c91994032ed3d04e5b",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "proposed",
|
||||
"title": "Coulomb estate architecture"
|
||||
},
|
||||
|
|
@ -81,7 +166,7 @@
|
|||
"source_digest": "e7104b2182612efe90c9a12168757506402490229814d454e94917ae62d2bfac",
|
||||
"source_path": "docs/architecture/state-hub_v0.1.md",
|
||||
"source_repo": "state-hub",
|
||||
"source_revision": "da30ce6723f9c5e6fdd994c78bb646986e819d3f",
|
||||
"source_revision": "0e35f84ad5f2f9397d76ffacb99f9973544f08ac",
|
||||
"status": "proposed",
|
||||
"title": "State Hub architecture"
|
||||
},
|
||||
|
|
@ -98,7 +183,7 @@
|
|||
"source_digest": "179cbb86bca95f71f46f51ca1971ff1c274eed7d900adf0672b537d4bcc5b480",
|
||||
"source_path": "docs/architecture/policy-nexus_v0.1.md",
|
||||
"source_repo": "policy-nexus",
|
||||
"source_revision": "6515ed9ef8499cb3de3397f0ae3993cc71440599",
|
||||
"source_revision": "885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373",
|
||||
"status": "proposed",
|
||||
"title": "Policy Nexus architecture"
|
||||
},
|
||||
|
|
@ -115,7 +200,7 @@
|
|||
"source_digest": "a28668fb4b8b6c5ec8c94baac000061276d85ef1849ec7ab8d132b913dbfe3be",
|
||||
"source_path": "docs/adr/ADR-0001-addressing-and-permanence.md",
|
||||
"source_repo": "policy-nexus",
|
||||
"source_revision": "6515ed9ef8499cb3de3397f0ae3993cc71440599",
|
||||
"source_revision": "885c6bb1cb805b64cbcfa99dd2c5817f6d4a1373",
|
||||
"status": "accepted",
|
||||
"title": "Policy addressing and permanence"
|
||||
},
|
||||
|
|
@ -438,7 +523,7 @@
|
|||
"source_digest": "183023ee57bae9c29e726fec5ee0361633fe3a2b182436a57869ae4b2a27af24",
|
||||
"source_path": "canon/architecture/adr-001-workplans-as-repo-artefacts.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "44500fc85cf29d8e9b2ee5c91994032ed3d04e5b",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "accepted",
|
||||
"title": "Workplans and Work Items Are Repository Artefacts"
|
||||
},
|
||||
|
|
@ -455,7 +540,7 @@
|
|||
"source_digest": "6aef66cd5cf71a48f5b4e14401dc19a755e2b182445b272d5952df0eb0dea8ec",
|
||||
"source_path": "canon/architecture/adr-002-custodian-agent-runtime-design.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "44500fc85cf29d8e9b2ee5c91994032ed3d04e5b",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "accepted",
|
||||
"title": "Custodian Agent Runtime \u2014 v0.1 Bootstrap Design"
|
||||
},
|
||||
|
|
@ -472,7 +557,7 @@
|
|||
"source_digest": "fcb49719e2b85b9120c0bd5bebd5e82748ca713f16b44951c028b60205514e2b",
|
||||
"source_path": "canon/architecture/adr-003-materialized-derived-state.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "44500fc85cf29d8e9b2ee5c91994032ed3d04e5b",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "accepted",
|
||||
"title": "Materialized Derived State with Fingerprint Invalidation for Repo-Sourced Data"
|
||||
},
|
||||
|
|
@ -489,7 +574,7 @@
|
|||
"source_digest": "3b68adfa6ab329e73f857cf691dc405136d2d66a0135e2c37c236aabe4659557",
|
||||
"source_path": "canon/architecture/adr-004-connectivity-first-network-posture.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "44500fc85cf29d8e9b2ee5c91994032ed3d04e5b",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "accepted",
|
||||
"title": "Connectivity-First Network Posture for Custodian Infrastructure"
|
||||
},
|
||||
|
|
@ -506,7 +591,7 @@
|
|||
"source_digest": "13195a721d0e579715f5f39ca6f72b5e49c583611e6ca089e6d4618708ae917f",
|
||||
"source_path": "canon/architecture/adr-005-cross-repo-workplans-project-repos.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "44500fc85cf29d8e9b2ee5c91994032ed3d04e5b",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "accepted",
|
||||
"title": "Cross-Repo Workplans Live in Dedicated Project Repos"
|
||||
},
|
||||
|
|
@ -523,7 +608,7 @@
|
|||
"source_digest": "a454df0e1d227f99ebb36c4abd45c76cc12579086d34f0c0ccfccfd7f4790823",
|
||||
"source_path": "canon/architecture/adr-006-canon-federation-concept-ownership.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "44500fc85cf29d8e9b2ee5c91994032ed3d04e5b",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "accepted",
|
||||
"title": "Canon Federation and Concept Ownership Across InfoTech and Commerce"
|
||||
},
|
||||
|
|
@ -540,7 +625,7 @@
|
|||
"source_digest": "1169f0c1f485a2bb7241a8f64f3167c060c04f83341b12586fd9be5c2b3693f8",
|
||||
"source_path": "canon/architecture/adr-007-workplan-identity-and-repo-worker-topology.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "44500fc85cf29d8e9b2ee5c91994032ed3d04e5b",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "accepted",
|
||||
"title": "Workplan Identity Uniqueness, Single Registrar, and Repo Worker Topology"
|
||||
},
|
||||
|
|
@ -557,7 +642,7 @@
|
|||
"source_digest": "5979da20799118259fc19246f51e8cc8f2c0c1be3d414318bd51d5a27d9ad565",
|
||||
"source_path": "canon/architecture/adr-010-hub-authority-and-local-cache-model.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "44500fc85cf29d8e9b2ee5c91994032ed3d04e5b",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "proposed",
|
||||
"title": "Hub Authority, Local Cache, and the Two Kinds of Hub Data"
|
||||
},
|
||||
|
|
@ -574,7 +659,7 @@
|
|||
"source_digest": "f94f429c72f6cfd01ee83f1e5689d2d10ae52d7588d7cbd3ca40aca7eef46fb0",
|
||||
"source_path": "canon/architecture/adr-011-federated-namespaces-and-reconciliation-limits.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "44500fc85cf29d8e9b2ee5c91994032ed3d04e5b",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "proposed",
|
||||
"title": "Federated Namespaces: Four Planes, Declared Posture, and the Limits of Reconciliation"
|
||||
},
|
||||
|
|
@ -948,7 +1033,7 @@
|
|||
"source_digest": "b5e8582459f546ae789ad5fd62f458454aa19997b520e32b6b9f792d6af55987",
|
||||
"source_path": "canon/architecture/adr-012-projection-source-and-preliminary-overlay.md",
|
||||
"source_repo": "the-custodian",
|
||||
"source_revision": "44500fc85cf29d8e9b2ee5c91994032ed3d04e5b",
|
||||
"source_revision": "4b951be3947f9457cc091a7d359d9232646b4c93",
|
||||
"status": "accepted",
|
||||
"title": "What the Hub Projects: Forge as Projection Source, Working Copies as Preliminary Overlay"
|
||||
},
|
||||
|
|
|
|||
222
build/standards/autonomy-lanes/v0.1/index.html
Normal file
222
build/standards/autonomy-lanes/v0.1/index.html
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="106cb0c99f73983199c9f1d8491143aa2a2eb41ee450a02ec7968d3763f30399">
|
||||
<title>Autonomy Lanes (Fleet) v0.1</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>canon-autonomy-lanes</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Autonomy Lanes (Fleet) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/autonomy-lanes_v0.1.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="#the-rule"><span class="n">·</span>The rule</a></li><li><a href="#lanes"><span class="n">·</span>Lanes</a></li><li><a href="#lane-as-a-spine-field"><span class="n">·</span>Lane as a spine field</a></li><li><a href="#approval-packages-yellow-and-above"><span class="n">·</span>Approval packages (yellow and above)</a></li><li><a href="#human-attention-is-a-wip-limited-workstation"><span class="n">·</span>Human attention is a WIP-limited workstation</a></li><li><a href="#raising-autonomy"><span class="n">·</span>Raising autonomy</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><div class="rule-quote"><p>Ratified by founder 2026-07-20 (CUST-WP-0060-T01, hub decision f4640f9e). Promotes the binky-control AutonomyPolicy lane model to fleet canon, unchanged in substance. binky-control's <code>AutonomyPolicy.md</code> remains the company-level policy instance; this standard makes the lane vocabulary and enforcement rules fleet-wide.</p></div>
|
||||
<section id="the-rule"><h2>The rule</h2>
|
||||
<div class="rule-quote"><p>If the responsible human is unavailable, the system must either continue safely, prepare the next decision, or explicitly defer with evidence. It must not silently idle.</p></div>
|
||||
<p>Valid states: <code>proceeding</code> | <code>prepared for review</code> | <code>deferred by policy</code>. Invalid state: <code>waiting because unsure</code>. Uncertainty triggers research, comparison, preparation, or risk classification — not paralysis. "Ask the human" is never the default.</p>
|
||||
</section>
|
||||
<section id="lanes"><h2>Lanes</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Lane</th><th>Name</th><th>Agent may</th><th>Human involvement</th></tr></thead><tbody><tr><td><strong>green</strong></td><td>Safe autonomous</td><td>research, summarize, classify, draft, organize, test, prepare</td><td>none (human-on-the-loop via logs)</td></tr><tr><td><strong>blue</strong></td><td>Reversible execution</td><td>internal docs, backlog updates, local scripts, reports, local commits</td><td>none, but logged</td></tr><tr><td><strong>yellow</strong></td><td>Deferred approval</td><td>prepare external emails, invoices, offers, releases, payments</td><td>async approval via decision records</td></tr><tr><td><strong>orange</strong></td><td>Time-window approval</td><td>customer/legal/accounting/banking actions needing business hours</td><td>engagement records, batched into command days</td></tr><tr><td><strong>red</strong></td><td>Human-only</td><td>signing, strategic commitments, bank/credential changes, sensitive legal/HR/security</td><td>always; agents prepare packages only</td></tr></tbody></table></div>
|
||||
<p>Optimization target: <strong>maximize green+blue throughput, queue yellow, batch orange, protect red from automation.</strong> Risk-tiered gating (in-the-loop for irreversible actions, on-the-loop for recoverable ones) is the only oversight pattern that scales.</p>
|
||||
</section>
|
||||
<section id="lane-as-a-spine-field"><h2>Lane as a spine field</h2>
|
||||
<p><code>lane</code> is a <strong>mandatory field on every work record</strong> (see <code>work-record-types_v0.1.md</code>) and on every agent instance manifest. The chain is closed end-to-end:</p>
|
||||
<pre>work record.lane → view routing (autopilot / decision / engagement)
|
||||
→ harness tool profile (enforced allow-list)
|
||||
→ ops-warden credential lane (catalog access)</pre>
|
||||
<p>Declaring a lane an item does not hold is a policy violation the harness must catch (tool profile refuses the run).</p>
|
||||
</section>
|
||||
<section id="approval-packages-yellow-and-above"><h2>Approval packages (yellow and above)</h2>
|
||||
<p>An agent hitting a lane boundary prepares a complete decision package, never a bare question: recommended action, reason, evidence links, risk level, reversibility, deadline (<code>needed_by</code>), attention cost, fallback if no response, options.</p>
|
||||
</section>
|
||||
<section id="human-attention-is-a-wip-limited-workstation"><h2>Human attention is a WIP-limited workstation</h2>
|
||||
<p>The responsible human's capacity is modeled like any lane capacity: attention budget (minutes/day, max decisions/day, max deep topics/day) and availability as first-class state (<code>available | evening_window | unavailable | office_hour_day</code>), with an explicit escalation allow-list when unavailable (critical security incident, payment failure, legal deadline). Yellow routes to the decision view, orange to the engagement view, both subject to that capacity.</p>
|
||||
<p><strong>Time-boxing is hub-owned:</strong> <code>needed_by</code> / <code>fallback_if_no_response</code> windows are watched by the hub → NATS → activity-core; a lapsed window raises the escalation or executes the declared fallback — never a human re-reading a file.</p>
|
||||
</section>
|
||||
<section id="raising-autonomy"><h2>Raising autonomy</h2>
|
||||
<p>Autonomy per area is raised only after the system proves reliable there, by explicit human decision recorded as a decision work record. Lane assignments are auditable history; lowering a lane needs no approval.</p>
|
||||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li><code>binky-control/AutonomyPolicy.md</code> (origin instance)</li><li><code>canon/standards/work-record-types_v0.1.md</code></li><li><code>research/2026-07-19-work-orchestration-best-practices.md</code> §2</li></ul>
|
||||
</section><footer><span>canon-autonomy-lanes · accepted-1 · accepted</span><span>the-custodian · canon/standards/autonomy-lanes_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="106cb0c99f73983199c9f1d8491143aa2a2eb41ee450a02ec7968d3763f30399">
|
||||
<title>Autonomy Lanes (Fleet) v0.1</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>canon-autonomy-lanes</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Autonomy Lanes (Fleet) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/autonomy-lanes_v0.1.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="#the-rule"><span class="n">·</span>The rule</a></li><li><a href="#lanes"><span class="n">·</span>Lanes</a></li><li><a href="#lane-as-a-spine-field"><span class="n">·</span>Lane as a spine field</a></li><li><a href="#approval-packages-yellow-and-above"><span class="n">·</span>Approval packages (yellow and above)</a></li><li><a href="#human-attention-is-a-wip-limited-workstation"><span class="n">·</span>Human attention is a WIP-limited workstation</a></li><li><a href="#raising-autonomy"><span class="n">·</span>Raising autonomy</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><div class="rule-quote"><p>Ratified by founder 2026-07-20 (CUST-WP-0060-T01, hub decision f4640f9e). Promotes the binky-control AutonomyPolicy lane model to fleet canon, unchanged in substance. binky-control's <code>AutonomyPolicy.md</code> remains the company-level policy instance; this standard makes the lane vocabulary and enforcement rules fleet-wide.</p></div>
|
||||
<section id="the-rule"><h2>The rule</h2>
|
||||
<div class="rule-quote"><p>If the responsible human is unavailable, the system must either continue safely, prepare the next decision, or explicitly defer with evidence. It must not silently idle.</p></div>
|
||||
<p>Valid states: <code>proceeding</code> | <code>prepared for review</code> | <code>deferred by policy</code>. Invalid state: <code>waiting because unsure</code>. Uncertainty triggers research, comparison, preparation, or risk classification — not paralysis. "Ask the human" is never the default.</p>
|
||||
</section>
|
||||
<section id="lanes"><h2>Lanes</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Lane</th><th>Name</th><th>Agent may</th><th>Human involvement</th></tr></thead><tbody><tr><td><strong>green</strong></td><td>Safe autonomous</td><td>research, summarize, classify, draft, organize, test, prepare</td><td>none (human-on-the-loop via logs)</td></tr><tr><td><strong>blue</strong></td><td>Reversible execution</td><td>internal docs, backlog updates, local scripts, reports, local commits</td><td>none, but logged</td></tr><tr><td><strong>yellow</strong></td><td>Deferred approval</td><td>prepare external emails, invoices, offers, releases, payments</td><td>async approval via decision records</td></tr><tr><td><strong>orange</strong></td><td>Time-window approval</td><td>customer/legal/accounting/banking actions needing business hours</td><td>engagement records, batched into command days</td></tr><tr><td><strong>red</strong></td><td>Human-only</td><td>signing, strategic commitments, bank/credential changes, sensitive legal/HR/security</td><td>always; agents prepare packages only</td></tr></tbody></table></div>
|
||||
<p>Optimization target: <strong>maximize green+blue throughput, queue yellow, batch orange, protect red from automation.</strong> Risk-tiered gating (in-the-loop for irreversible actions, on-the-loop for recoverable ones) is the only oversight pattern that scales.</p>
|
||||
</section>
|
||||
<section id="lane-as-a-spine-field"><h2>Lane as a spine field</h2>
|
||||
<p><code>lane</code> is a <strong>mandatory field on every work record</strong> (see <code>work-record-types_v0.1.md</code>) and on every agent instance manifest. The chain is closed end-to-end:</p>
|
||||
<pre>work record.lane → view routing (autopilot / decision / engagement)
|
||||
→ harness tool profile (enforced allow-list)
|
||||
→ ops-warden credential lane (catalog access)</pre>
|
||||
<p>Declaring a lane an item does not hold is a policy violation the harness must catch (tool profile refuses the run).</p>
|
||||
</section>
|
||||
<section id="approval-packages-yellow-and-above"><h2>Approval packages (yellow and above)</h2>
|
||||
<p>An agent hitting a lane boundary prepares a complete decision package, never a bare question: recommended action, reason, evidence links, risk level, reversibility, deadline (<code>needed_by</code>), attention cost, fallback if no response, options.</p>
|
||||
</section>
|
||||
<section id="human-attention-is-a-wip-limited-workstation"><h2>Human attention is a WIP-limited workstation</h2>
|
||||
<p>The responsible human's capacity is modeled like any lane capacity: attention budget (minutes/day, max decisions/day, max deep topics/day) and availability as first-class state (<code>available | evening_window | unavailable | office_hour_day</code>), with an explicit escalation allow-list when unavailable (critical security incident, payment failure, legal deadline). Yellow routes to the decision view, orange to the engagement view, both subject to that capacity.</p>
|
||||
<p><strong>Time-boxing is hub-owned:</strong> <code>needed_by</code> / <code>fallback_if_no_response</code> windows are watched by the hub → NATS → activity-core; a lapsed window raises the escalation or executes the declared fallback — never a human re-reading a file.</p>
|
||||
</section>
|
||||
<section id="raising-autonomy"><h2>Raising autonomy</h2>
|
||||
<p>Autonomy per area is raised only after the system proves reliable there, by explicit human decision recorded as a decision work record. Lane assignments are auditable history; lowering a lane needs no approval.</p>
|
||||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li><code>binky-control/AutonomyPolicy.md</code> (origin instance)</li><li><code>canon/standards/work-record-types_v0.1.md</code></li><li><code>research/2026-07-19-work-orchestration-best-practices.md</code> §2</li></ul>
|
||||
</section><footer><span>canon-autonomy-lanes · accepted-1 · accepted</span><span>the-custodian · canon/standards/autonomy-lanes_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
273
build/standards/contribution-convention/v0.1/index.html
Normal file
273
build/standards/contribution-convention/v0.1/index.html
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="6dfc1d7b2b82ab18228a84660c1c7dff607aad1d9da37ac12084cdd2ab8ae112">
|
||||
<title>Contribution Convention v0.1</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>canon-contrib-convention</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Contribution Convention v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/contribution-convention_v0.1.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="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#artifact-types"><span class="n">·</span>Artifact Types</a></li><li><a href="#directory-layout"><span class="n">·</span>Directory Layout</a></li><li><a href="#frontmatter-schema"><span class="n">·</span>Frontmatter Schema</a></li><li><a href="#id-schemes"><span class="n">·</span>ID Schemes</a></li><li><a href="#status-lifecycle"><span class="n">·</span>Status Lifecycle</a></li><li><a href="#relationship-to-state-hub"><span class="n">·</span>Relationship to State Hub</a></li></ol></nav><main><section id="purpose"><h2>Purpose</h2>
|
||||
<p>This document defines the canonical convention for tracking upstream contributions across all custodian-ecosystem repositories. A <em>contribution</em> is any intentional engagement with an external upstream project: a bug report, feature request, extension-point proposal, or pull request.</p>
|
||||
<p>Contributions are tracked as Markdown artifacts with typed YAML frontmatter, committed to the repository that authors them, and indexed in the State Hub DB. This enables the Custodian to maintain a full audit trail of all upstream engagement across all six project domains.</p>
|
||||
</section>
|
||||
<section id="artifact-types"><h2>Artifact Types</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Code</th><th>Name</th><th>Description</th></tr></thead><tbody><tr><td><code>br</code></td><td>Bug Report</td><td>A defect reported to an upstream project</td></tr><tr><td><code>fr</code></td><td>Feature Request</td><td>A capability requested from an upstream project</td></tr><tr><td><code>ep</code></td><td>Extension-Point Proposal</td><td>A proposed extension point in an upstream project</td></tr><tr><td><code>upr</code></td><td>Upstream PR</td><td>A pull request submitted or planned for upstream</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section id="directory-layout"><h2>Directory Layout</h2>
|
||||
<pre><repo-root>/
|
||||
contrib/
|
||||
bug-reports/ # BR artifacts
|
||||
feature-requests/ # FR artifacts
|
||||
extension-points/ # EP artifacts
|
||||
upstream-prs/ # UPR artifacts</pre>
|
||||
<p>Each artifact file follows the naming pattern:</p>
|
||||
<pre><YYYY-MM-DD>--<org>--<repo>--<slug>.md</pre>
|
||||
<p>Examples:</p>
|
||||
<ul><li><code>contrib/bug-reports/2026-03-01--observablehq--framework--plot-tooltip-flicker.md</code></li><li><code>contrib/upstream-prs/2026-02-26--observablehq--framework--toc-sidebar-inject.md</code></li><li><code>contrib/extension-points/EP-CUST-002--anthropic--claude-code--hook-on-tool-result.md</code></li></ul>
|
||||
</section>
|
||||
<section id="frontmatter-schema"><h2>Frontmatter Schema</h2>
|
||||
<p>All contribution artifacts share a common base frontmatter:</p>
|
||||
<pre>---
|
||||
id: <type>-<YYYY-MM-DD>--<org>--<repo>--<slug> # unique string ID
|
||||
type: br | fr | ep | upr # required
|
||||
target_org: <github-org-or-owner> # required
|
||||
target_repo: <repository-name> # required
|
||||
title: "Human-readable title" # required
|
||||
status: draft | submitted | acknowledged | accepted | rejected | merged | withdrawn
|
||||
domain: infotech | agents | communication | ... # current sector domain; see Repo Classification Standard §6
|
||||
related_workstream: <workstream-slug> # optional
|
||||
state_hub_contribution_id: <uuid> # set once registered in State Hub
|
||||
created: "YYYY-MM-DD"
|
||||
updated: "YYYY-MM-DD"
|
||||
---</pre>
|
||||
<h3>BR — Bug Report (additional fields)</h3>
|
||||
<pre>upstream_version: "1.2.3" # version where bug was observed
|
||||
reproduction_steps: |
|
||||
1. …
|
||||
2. …
|
||||
expected: "What should happen"
|
||||
actual: "What actually happens"
|
||||
workaround: "Any known workaround" # optional
|
||||
upstream_issue_url: "https://…" # optional — link once filed</pre>
|
||||
<h3>FR — Feature Request (additional fields)</h3>
|
||||
<pre>motivation: "Why this feature is needed"
|
||||
proposed_api: |
|
||||
# Sketch of the proposed interface
|
||||
alternatives: "What we do instead today"
|
||||
upstream_issue_url: "https://…" # optional</pre>
|
||||
<h3>EP — Extension-Point Proposal (additional fields)</h3>
|
||||
<pre>ep_id: EP-<DOMAIN>-NNN # e.g. EP-RAIL-007
|
||||
location: "src/file.ts:42" # file:line in upstream where hook would live
|
||||
proposed_interface: |
|
||||
# Interface or callback signature sketch
|
||||
rationale: "Why this extension point is valuable"
|
||||
upstream_issue_url: "https://…" # optional</pre>
|
||||
<h3>UPR — Upstream PR (additional fields)</h3>
|
||||
<pre>local_component_path: "relative/path/in/this/repo"
|
||||
target_upstream_file: "path/in/upstream/repo"
|
||||
upstream_pr_url: "https://…" # set once submitted
|
||||
draft_pr_body: |
|
||||
## Summary
|
||||
…
|
||||
|
||||
## Motivation
|
||||
…</pre>
|
||||
</section>
|
||||
<section id="id-schemes"><h2>ID Schemes</h2>
|
||||
<ul><li><strong>BR / FR / UPR</strong>: <code><type>-<YYYY-MM-DD>--<org>--<repo>--<slug></code> — date-prefixed slug</li><li><strong>EP</strong>: <code>EP-<DOMAIN>-NNN</code> where <code><DOMAIN></code> is uppercase (CUST, RAIL, MARK, etc.) and <code>NNN</code> is a zero-padded three-digit sequence per domain (EP-CUST-001, EP-CUST-002, …). This scheme is an extension of the Railiance EP convention defined in the staged-promotion-lifecycle workstream; this canon document is the authoritative master spec.</li></ul>
|
||||
</section>
|
||||
<section id="status-lifecycle"><h2>Status Lifecycle</h2>
|
||||
<pre>draft → submitted → acknowledged → accepted → merged
|
||||
↘ ↘
|
||||
rejected withdrawn</pre>
|
||||
<ul><li><code>draft</code>: artifact created locally, not yet sent upstream</li><li><code>submitted</code>: issue filed or PR opened upstream</li><li><code>acknowledged</code>: upstream team has responded</li><li><code>accepted</code>: upstream has agreed to the proposal</li><li><code>rejected</code>: upstream has declined</li><li><code>merged</code>: PR merged / fix released</li><li><code>withdrawn</code>: we decided not to pursue</li></ul>
|
||||
</section>
|
||||
<section id="relationship-to-state-hub"><h2>Relationship to State Hub</h2>
|
||||
<p>Once an artifact is registered via <code>register_contribution()</code> MCP tool or <code>POST /contributions/</code> API, the State Hub assigns a UUID and returns it. That UUID is written back into <code>state_hub_contribution_id</code> in the frontmatter.</p>
|
||||
<p>The State Hub is a <strong>read/cache layer</strong> — the Markdown file is always the authoritative source of truth. If the DB is reset, contributions can be re-ingested from the files.</p>
|
||||
</section><footer><span>canon-contrib-convention · accepted-1 · accepted</span><span>the-custodian · canon/standards/contribution-convention_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="6dfc1d7b2b82ab18228a84660c1c7dff607aad1d9da37ac12084cdd2ab8ae112">
|
||||
<title>Contribution Convention v0.1</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>canon-contrib-convention</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Contribution Convention v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/contribution-convention_v0.1.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="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#artifact-types"><span class="n">·</span>Artifact Types</a></li><li><a href="#directory-layout"><span class="n">·</span>Directory Layout</a></li><li><a href="#frontmatter-schema"><span class="n">·</span>Frontmatter Schema</a></li><li><a href="#id-schemes"><span class="n">·</span>ID Schemes</a></li><li><a href="#status-lifecycle"><span class="n">·</span>Status Lifecycle</a></li><li><a href="#relationship-to-state-hub"><span class="n">·</span>Relationship to State Hub</a></li></ol></nav><main><section id="purpose"><h2>Purpose</h2>
|
||||
<p>This document defines the canonical convention for tracking upstream contributions across all custodian-ecosystem repositories. A <em>contribution</em> is any intentional engagement with an external upstream project: a bug report, feature request, extension-point proposal, or pull request.</p>
|
||||
<p>Contributions are tracked as Markdown artifacts with typed YAML frontmatter, committed to the repository that authors them, and indexed in the State Hub DB. This enables the Custodian to maintain a full audit trail of all upstream engagement across all six project domains.</p>
|
||||
</section>
|
||||
<section id="artifact-types"><h2>Artifact Types</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Code</th><th>Name</th><th>Description</th></tr></thead><tbody><tr><td><code>br</code></td><td>Bug Report</td><td>A defect reported to an upstream project</td></tr><tr><td><code>fr</code></td><td>Feature Request</td><td>A capability requested from an upstream project</td></tr><tr><td><code>ep</code></td><td>Extension-Point Proposal</td><td>A proposed extension point in an upstream project</td></tr><tr><td><code>upr</code></td><td>Upstream PR</td><td>A pull request submitted or planned for upstream</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section id="directory-layout"><h2>Directory Layout</h2>
|
||||
<pre><repo-root>/
|
||||
contrib/
|
||||
bug-reports/ # BR artifacts
|
||||
feature-requests/ # FR artifacts
|
||||
extension-points/ # EP artifacts
|
||||
upstream-prs/ # UPR artifacts</pre>
|
||||
<p>Each artifact file follows the naming pattern:</p>
|
||||
<pre><YYYY-MM-DD>--<org>--<repo>--<slug>.md</pre>
|
||||
<p>Examples:</p>
|
||||
<ul><li><code>contrib/bug-reports/2026-03-01--observablehq--framework--plot-tooltip-flicker.md</code></li><li><code>contrib/upstream-prs/2026-02-26--observablehq--framework--toc-sidebar-inject.md</code></li><li><code>contrib/extension-points/EP-CUST-002--anthropic--claude-code--hook-on-tool-result.md</code></li></ul>
|
||||
</section>
|
||||
<section id="frontmatter-schema"><h2>Frontmatter Schema</h2>
|
||||
<p>All contribution artifacts share a common base frontmatter:</p>
|
||||
<pre>---
|
||||
id: <type>-<YYYY-MM-DD>--<org>--<repo>--<slug> # unique string ID
|
||||
type: br | fr | ep | upr # required
|
||||
target_org: <github-org-or-owner> # required
|
||||
target_repo: <repository-name> # required
|
||||
title: "Human-readable title" # required
|
||||
status: draft | submitted | acknowledged | accepted | rejected | merged | withdrawn
|
||||
domain: infotech | agents | communication | ... # current sector domain; see Repo Classification Standard §6
|
||||
related_workstream: <workstream-slug> # optional
|
||||
state_hub_contribution_id: <uuid> # set once registered in State Hub
|
||||
created: "YYYY-MM-DD"
|
||||
updated: "YYYY-MM-DD"
|
||||
---</pre>
|
||||
<h3>BR — Bug Report (additional fields)</h3>
|
||||
<pre>upstream_version: "1.2.3" # version where bug was observed
|
||||
reproduction_steps: |
|
||||
1. …
|
||||
2. …
|
||||
expected: "What should happen"
|
||||
actual: "What actually happens"
|
||||
workaround: "Any known workaround" # optional
|
||||
upstream_issue_url: "https://…" # optional — link once filed</pre>
|
||||
<h3>FR — Feature Request (additional fields)</h3>
|
||||
<pre>motivation: "Why this feature is needed"
|
||||
proposed_api: |
|
||||
# Sketch of the proposed interface
|
||||
alternatives: "What we do instead today"
|
||||
upstream_issue_url: "https://…" # optional</pre>
|
||||
<h3>EP — Extension-Point Proposal (additional fields)</h3>
|
||||
<pre>ep_id: EP-<DOMAIN>-NNN # e.g. EP-RAIL-007
|
||||
location: "src/file.ts:42" # file:line in upstream where hook would live
|
||||
proposed_interface: |
|
||||
# Interface or callback signature sketch
|
||||
rationale: "Why this extension point is valuable"
|
||||
upstream_issue_url: "https://…" # optional</pre>
|
||||
<h3>UPR — Upstream PR (additional fields)</h3>
|
||||
<pre>local_component_path: "relative/path/in/this/repo"
|
||||
target_upstream_file: "path/in/upstream/repo"
|
||||
upstream_pr_url: "https://…" # set once submitted
|
||||
draft_pr_body: |
|
||||
## Summary
|
||||
…
|
||||
|
||||
## Motivation
|
||||
…</pre>
|
||||
</section>
|
||||
<section id="id-schemes"><h2>ID Schemes</h2>
|
||||
<ul><li><strong>BR / FR / UPR</strong>: <code><type>-<YYYY-MM-DD>--<org>--<repo>--<slug></code> — date-prefixed slug</li><li><strong>EP</strong>: <code>EP-<DOMAIN>-NNN</code> where <code><DOMAIN></code> is uppercase (CUST, RAIL, MARK, etc.) and <code>NNN</code> is a zero-padded three-digit sequence per domain (EP-CUST-001, EP-CUST-002, …). This scheme is an extension of the Railiance EP convention defined in the staged-promotion-lifecycle workstream; this canon document is the authoritative master spec.</li></ul>
|
||||
</section>
|
||||
<section id="status-lifecycle"><h2>Status Lifecycle</h2>
|
||||
<pre>draft → submitted → acknowledged → accepted → merged
|
||||
↘ ↘
|
||||
rejected withdrawn</pre>
|
||||
<ul><li><code>draft</code>: artifact created locally, not yet sent upstream</li><li><code>submitted</code>: issue filed or PR opened upstream</li><li><code>acknowledged</code>: upstream team has responded</li><li><code>accepted</code>: upstream has agreed to the proposal</li><li><code>rejected</code>: upstream has declined</li><li><code>merged</code>: PR merged / fix released</li><li><code>withdrawn</code>: we decided not to pursue</li></ul>
|
||||
</section>
|
||||
<section id="relationship-to-state-hub"><h2>Relationship to State Hub</h2>
|
||||
<p>Once an artifact is registered via <code>register_contribution()</code> MCP tool or <code>POST /contributions/</code> API, the State Hub assigns a UUID and returns it. That UUID is written back into <code>state_hub_contribution_id</code> in the frontmatter.</p>
|
||||
<p>The State Hub is a <strong>read/cache layer</strong> — the Markdown file is always the authoritative source of truth. If the DB is reset, contributions can be re-ingested from the files.</p>
|
||||
</section><footer><span>canon-contrib-convention · accepted-1 · accepted</span><span>the-custodian · canon/standards/contribution-convention_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
279
build/standards/project-repository-flavor/v0.1/index.html
Normal file
279
build/standards/project-repository-flavor/v0.1/index.html
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="61889b2f18a82a08b66ef90d758efe5c028a4f52aced1721a23e69c6f24a8224">
|
||||
<title>Project Repository Flavor (prj-) v0.1</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>canon-project-repository-flavor</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Project Repository Flavor (prj-) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/project-repository-flavor_v0.1.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="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#when-to-use-a-project-repository"><span class="n">·</span>When to use a project repository</a></li><li><a href="#naming"><span class="n">·</span>Naming</a></li><li><a href="#authority-boundary"><span class="n">·</span>Authority boundary</a></li><li><a href="#required-files"><span class="n">·</span>Required files</a></li><li><a href="#lifecycle"><span class="n">·</span>Lifecycle</a></li><li><a href="#residuals-before-completion"><span class="n">·</span>Residuals before completion</a></li><li><a href="#completion-record"><span class="n">·</span>Completion record</a></li><li><a href="#archive-procedure"><span class="n">·</span>Archive procedure</a></li><li><a href="#workplan-and-agent-conventions"><span class="n">·</span>Workplan and agent conventions</a></li><li><a href="#minimal-layout-example"><span class="n">·</span>Minimal layout example</a></li><li><a href="#reference-instance"><span class="n">·</span>Reference instance</a></li><li><a href="#conformance-checklist"><span class="n">·</span>Conformance checklist</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="purpose"><h2>Purpose</h2>
|
||||
<p>Define the durable <strong>project repository</strong> flavor used for complex cross-repository efforts: naming, required files, authority boundary, lifecycle, residual handoff, and archive procedure.</p>
|
||||
<p>This standard implements and completes <strong>ADR-005</strong> (<em>Cross-Repo Workplans Live in Dedicated Project Repos</em>). It does <strong>not</strong> replace the Repo Classification Standard: project repositories still use <code>category: project</code> in <code>.repo-classification.yaml</code>.</p>
|
||||
</section>
|
||||
<section id="when-to-use-a-project-repository"><h2>When to use a project repository</h2>
|
||||
<p>Create a project repository when <strong>all</strong> of the following hold:</p>
|
||||
<ol><li>The work coordinates change across <strong>two or more</strong> functional repositories.</li><li>Binding the coordination workplan to any single product/tooling repo would misrepresent ownership or pollute that repo's history.</li><li>The effort has a <strong>bounded outcome</strong> with explicit success and retirement conditions (not an open-ended product roadmap).</li></ol>
|
||||
<p>Do <strong>not</strong> create a project repository for:</p>
|
||||
<ul><li>single-repo workplans;</li><li>small cross-cutting fixes that fit one lead repo's workplan plus dependency links;</li><li>durable products, libraries, or services (those use <code>INTENT.md</code> and ordinary product/tooling/research categories);</li><li>long-lived domain charters (those remain under <code>the-custodian/canon/projects/</code>).</li></ul>
|
||||
</section>
|
||||
<section id="naming"><h2>Naming</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Element</th><th>Convention</th></tr></thead><tbody><tr><td>Git / local directory</td><td><code>prj-<kebab-slug></code></td></tr><tr><td>Hub <code>repo</code> slug</td><td>same as directory name</td></tr><tr><td>Workplan prefix</td><td>short uppercase prefix derived from the project, ending in <code>-WP-</code> (example: <code>SHR-WP-</code> for State Hub Retirement)</td></tr><tr><td>Classification</td><td><code>category: project</code></td></tr></tbody></table></div>
|
||||
<p><strong>Canonical prefix is <code>prj-</code>.</strong> ADR-005's illustrative <code>proj-</code> form is superseded for new repositories. Do not invent parallel prefixes (<code>project-</code>, <code>xrepo-</code>, …).</p>
|
||||
<p>Slug rules:</p>
|
||||
<ul><li>lowercase kebab-case;</li><li>outcome-oriented (<code>prj-state-hub-retirement</code>), not a random ticket id;</li><li>stable for the life of the project (rename only with an explicit migration note in <code>history/</code>).</li></ul>
|
||||
</section>
|
||||
<section id="authority-boundary"><h2>Authority boundary</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Concern</th><th>Owner</th></tr></thead><tbody><tr><td>Project goal, success gates, retirement conditions</td><td>project repo (<code>GOAL.md</code>)</td></tr><tr><td>Architecture decisions, sequencing, dependency map, migration ledger, risks, consolidated evidence</td><td>project repo</td></tr><tr><td>Cross-repo workplans that coordinate the effort</td><td>project repo (<code>workplans/</code>)</td></tr><tr><td>Production implementation, tests, deployables</td><td><strong>participating functional repositories</strong></td></tr><tr><td>Per-repo implementation workplans and local evidence</td><td>each functional repository</td></tr><tr><td>Durable post-project standards and ADRs</td><td>permanent homes (<code>the-custodian</code> canon, or the owning product/tooling repo)</td></tr></tbody></table></div>
|
||||
<p><strong>Hard rules:</strong></p>
|
||||
<ol><li>Project repositories <strong>MUST NOT</strong> host production implementation code for the systems being changed.</li><li>Project workplans <strong>link</strong> child workplans by stable ID; they <strong>MUST NOT</strong> copy or replace child task lists.</li><li>The hub remains a read/index layer; work records originate as files (ADR-001).</li><li>Results of the project live primarily in the modified functional repositories and promoted canon. The project repo is coordination + provenance.</li></ol>
|
||||
</section>
|
||||
<section id="required-files"><h2>Required files</h2>
|
||||
<p>At registration / first meaningful commit:</p>
|
||||
<div class="scroll"><table><thead><tr><th>Path</th><th>Required</th><th>Role</th></tr></thead><tbody><tr><td><code>GOAL.md</code></td><td><strong>yes</strong></td><td>Outcome, invariants, success gates, project retirement conditions. <strong>Replaces <code>INTENT.md</code> for this flavor.</strong></td></tr><tr><td><code>SCOPE.md</code></td><td><strong>yes</strong></td><td>Project authority, participating repos, in/out of scope, work-record rule.</td></tr><tr><td><code>README.md</code></td><td><strong>yes</strong></td><td>Short entry point linking <code>GOAL.md</code>, <code>SCOPE.md</code>, genesis/history, active workplans.</td></tr><tr><td><code>AGENTS.md</code></td><td><strong>yes</strong></td><td>Agent session protocol for this project (orient → work → close; hub integration).</td></tr><tr><td><code>.repo-classification.yaml</code></td><td><strong>yes</strong></td><td><code>category: project</code> plus domain / capability tags for the <em>effort</em>.</td></tr><tr><td><code>workplans/</code></td><td><strong>yes</strong></td><td>At least one foundation workplan; prefix unique to the project.</td></tr><tr><td><code>history/</code></td><td>recommended</td><td>Genesis and significant milestones (why the project exists).</td></tr><tr><td><code>WORK-RECORDS.md</code></td><td>generated</td><td>Hub index; do not hand-edit.</td></tr><tr><td><code>.custodian-brief.md</code></td><td>generated</td><td>Offline orientation brief.</td></tr></tbody></table></div>
|
||||
<h3><code>GOAL.md</code> (not <code>INTENT.md</code>)</h3>
|
||||
<p>Durable product and tooling repositories explain <strong>why they exist</strong> with <code>INTENT.md</code>. Project repositories are temporary and outcome-bounded; they use <strong><code>GOAL.md</code></strong> instead.</p>
|
||||
<p><code>GOAL.md</code> MUST include:</p>
|
||||
<ol><li><strong>Outcome</strong> — what success looks like in one short section.</li><li><strong>Invariants</strong> — rules that must hold during the project.</li><li><strong>Success gates</strong> — checkable conditions for “goal achieved”.</li><li><strong>Project retirement</strong> — conditions under which <em>this repository</em> may be archived (usually: gates met + residuals handed off + durable decisions promoted).</li></ol>
|
||||
<p>Recommended frontmatter:</p>
|
||||
<pre>---
|
||||
repo: prj-<slug>
|
||||
repo_flavor: project
|
||||
project_status: draft | active | completed | archived
|
||||
started: "YYYY-MM-DD"
|
||||
reviewed: "YYYY-MM-DD"
|
||||
---</pre>
|
||||
<p><strong>Anti-pattern:</strong> shipping both <code>INTENT.md</code> and <code>GOAL.md</code> in a <code>prj-</code> repo. If a durable intent emerges, promote it into a permanent repository's <code>INTENT.md</code> (or canon) and keep the project goal as the temporary outcome document.</p>
|
||||
<h3>Relation to durable <code>INTENT.md</code></h3>
|
||||
<div class="scroll"><table><thead><tr><th>Repository kind</th><th>Purpose document</th></tr></thead><tbody><tr><td>product / tooling / research / business / experimental</td><td><code>INTENT.md</code></td></tr><tr><td><strong>project (<code>prj-</code>)</strong></td><td><strong><code>GOAL.md</code> only</strong></td></tr></tbody></table></div>
|
||||
<p>Tooling that scaffolds repositories (e.g. <code>statehub register</code>) MUST treat <code>GOAL.md</code> + <code>repo_flavor: project</code> as sufficient purpose documentation for <code>prj-</code> repos and MUST NOT require inventing an <code>INTENT.md</code> that pretends the project is a permanent product.</p>
|
||||
</section>
|
||||
<section id="lifecycle"><h2>Lifecycle</h2>
|
||||
<pre>draft → active → completed → archived</pre>
|
||||
<div class="scroll"><table><thead><tr><th>Status</th><th>Meaning</th><th>Repo / hub signals</th></tr></thead><tbody><tr><td><code>draft</code></td><td>Convention and foundation still forming; may not yet be registered</td><td><code>project_status: draft</code>; workplans often <code>proposed</code> / <code>ready</code></td></tr><tr><td><code>active</code></td><td>Coordination and child implementation in progress</td><td><code>project_status: active</code>; at least one workplan <code>active</code> or <code>ready</code></td></tr><tr><td><code>completed</code></td><td>All success gates have accepted evidence; residuals have live owners outside this repo</td><td><code>project_status: completed</code>; project workplans <code>finished</code> or cancelled with rationale</td></tr><tr><td><code>archived</code></td><td>Repository is read-only provenance</td><td>forge archive flag; hub repo/workplan <code>archived</code>; no normal writes</td></tr></tbody></table></div>
|
||||
<p>Promotion rules:</p>
|
||||
<ul><li><code>draft → active</code> when <code>GOAL.md</code> / <code>SCOPE.md</code> are reviewable and the foundation workplan is <code>ready</code> or <code>active</code>.</li><li><code>active → completed</code> only when <strong>every</strong> <code>GOAL.md</code> success gate has accepted evidence <strong>and</strong> residuals are live work records elsewhere (see below).</li><li><code>completed → archived</code> after the completion record is written, durable decisions are promoted, and a final consistency/link check passes.</li></ul>
|
||||
</section>
|
||||
<section id="residuals-before-completion"><h2>Residuals before completion</h2>
|
||||
<p>Actionable leftovers MUST NOT live only in finished workplan prose or <code>SCOPE.md</code>. Before any project workplan is set to <code>finished</code>, and again before <code>project_status: completed</code>, each residual becomes a <strong>live work record</strong> outside the closing narrative:</p>
|
||||
<ul><li>intake with <code>origin: residual</code> + <code>origin_ref: <WP-id></code>, or</li><li>a next workplan / decision / engagement / register-entry in a permanent repo.</li></ul>
|
||||
<p>Canon: <code>work-record-types_v0.1.md</code> § Residuals. Fleet residual listing is a State Hub concern, not a project-local queue file.</p>
|
||||
</section>
|
||||
<section id="completion-record"><h2>Completion record</h2>
|
||||
<p>Before archival, the project repository MUST contain a completion record (recommended path: <code>history/YYYY-MM-DD-completion.md</code>) that lists:</p>
|
||||
<ol><li>deployed or merged revisions that realize the outcome;</li><li>every participating repository touched, with links to merged PRs/commits or child workplan IDs;</li><li>promoted durable artefacts (canon paths, ADRs, standards);</li><li>migration and retirement evidence pointers (counts, cutover windows, backups);</li><li>residual work-record IDs and their owning repos;</li><li>rollback expiry or remaining operational obligations, if any.</li></ol>
|
||||
<p>Without this record, do not archive.</p>
|
||||
</section>
|
||||
<section id="archive-procedure"><h2>Archive procedure</h2>
|
||||
<ol><li>Verify all success gates and retirement conditions in <code>GOAL.md</code>.</li><li>Confirm residuals are live and owned outside this repository.</li><li>Promote remaining durable decisions/standards to permanent homes; leave pointers from the project repo.</li><li>Finish or cancel project workplans; move finished files to <code>workplans/archived/YYMMDD-<id>-<slug>.md</code> per workplan convention.</li><li>Write the completion record.</li><li>Set <code>project_status: archived</code> in <code>GOAL.md</code> frontmatter.</li><li>Run <code>statehub fix-consistency</code> (or equivalent) so the hub reflects finished workplans and the archived status.</li><li>Archive the repository in the forge (read-only); do <strong>not</strong> delete it.</li><li>Optionally mark the hub registration archived / read-only.</li></ol>
|
||||
<p><strong>Archive means read-only provenance, never deletion.</strong> Historical evidence and coordination narrative remain queryable.</p>
|
||||
</section>
|
||||
<section id="workplan-and-agent-conventions"><h2>Workplan and agent conventions</h2>
|
||||
<ul><li>Workplan files: <code>workplans/<PREFIX>-WP-NNNN-<slug>.md</code> with fleet status vocabulary (<code>proposed</code> … <code>archived</code>).</li><li>Session start order for agents: <code>GOAL.md</code> → <code>SCOPE.md</code> → genesis/history → active workplans (see project <code>AGENTS.md</code>).</li><li>Progress and task status follow ordinary State Hub / fix-consistency rules.</li><li>Ad-hoc low-risk fixes may use <code>workplans/ADHOC-YYYY-MM-DD.md</code> with canonical id <code>{PREFIX}-WP-ADHOC-YYYY-MM-DD</code>; anything multi-step belongs in a normal workplan.</li></ul>
|
||||
</section>
|
||||
<section id="minimal-layout-example"><h2>Minimal layout example</h2>
|
||||
<pre>prj-example-cutover/
|
||||
GOAL.md
|
||||
SCOPE.md
|
||||
README.md
|
||||
AGENTS.md
|
||||
.repo-classification.yaml
|
||||
history/
|
||||
2026-08-09-genesis.md
|
||||
workplans/
|
||||
EX-WP-0001-foundation.md</pre>
|
||||
</section>
|
||||
<section id="reference-instance"><h2>Reference instance</h2>
|
||||
<p>The first repository under this standard is <code>prj-state-hub-retirement</code> (State Hub retirement / hub-core consolidation). Use it as the structural reference when scaffolding later <code>prj-</code> repos; do not copy its domain-specific content.</p>
|
||||
</section>
|
||||
<section id="conformance-checklist"><h2>Conformance checklist</h2>
|
||||
<p>A repository conforms to the <code>prj-</code> flavor when:</p>
|
||||
<ul><li>[ ] Named <code>prj-<slug></code> and classified <code>category: project</code>.</li><li>[ ] Has <code>GOAL.md</code> with outcome, invariants, success gates, and retirement.</li><li>[ ] Has no durable-product <code>INTENT.md</code> (or documents an explicit temporary exception during migration of a mis-scaffolded repo).</li><li>[ ] Has <code>SCOPE.md</code>, <code>README.md</code>, <code>AGENTS.md</code>, and <code>.repo-classification.yaml</code>.</li><li>[ ] Hosts coordination workplans only; implementation lives in child repos.</li><li>[ ] Links child workplans by ID rather than duplicating their tasks.</li><li>[ ] Defines archive/completion discipline consistent with this standard.</li><li>[ ] On completion, writes a completion record and archives read-only.</li></ul>
|
||||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li>ADR-001 — Workplans and Work Items Are Repository Artefacts</li><li>ADR-005 — Cross-Repo Workplans Live in Dedicated Project Repos</li><li><code>repo-classification-standard_v1.0.md</code> — <code>category: project</code></li><li><code>work-record-types_v0.1.md</code> — residuals and work-record kinds</li><li><code>workplan-terminology-fleet_v0.1.md</code> — workplan vocabulary</li></ul>
|
||||
</section><footer><span>canon-project-repository-flavor · accepted-1 · accepted</span><span>the-custodian · canon/standards/project-repository-flavor_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
@ -0,0 +1,279 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="61889b2f18a82a08b66ef90d758efe5c028a4f52aced1721a23e69c6f24a8224">
|
||||
<title>Project Repository Flavor (prj-) v0.1</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>canon-project-repository-flavor</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Project Repository Flavor (prj-) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/project-repository-flavor_v0.1.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="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#when-to-use-a-project-repository"><span class="n">·</span>When to use a project repository</a></li><li><a href="#naming"><span class="n">·</span>Naming</a></li><li><a href="#authority-boundary"><span class="n">·</span>Authority boundary</a></li><li><a href="#required-files"><span class="n">·</span>Required files</a></li><li><a href="#lifecycle"><span class="n">·</span>Lifecycle</a></li><li><a href="#residuals-before-completion"><span class="n">·</span>Residuals before completion</a></li><li><a href="#completion-record"><span class="n">·</span>Completion record</a></li><li><a href="#archive-procedure"><span class="n">·</span>Archive procedure</a></li><li><a href="#workplan-and-agent-conventions"><span class="n">·</span>Workplan and agent conventions</a></li><li><a href="#minimal-layout-example"><span class="n">·</span>Minimal layout example</a></li><li><a href="#reference-instance"><span class="n">·</span>Reference instance</a></li><li><a href="#conformance-checklist"><span class="n">·</span>Conformance checklist</a></li><li><a href="#related"><span class="n">·</span>Related</a></li></ol></nav><main><section id="purpose"><h2>Purpose</h2>
|
||||
<p>Define the durable <strong>project repository</strong> flavor used for complex cross-repository efforts: naming, required files, authority boundary, lifecycle, residual handoff, and archive procedure.</p>
|
||||
<p>This standard implements and completes <strong>ADR-005</strong> (<em>Cross-Repo Workplans Live in Dedicated Project Repos</em>). It does <strong>not</strong> replace the Repo Classification Standard: project repositories still use <code>category: project</code> in <code>.repo-classification.yaml</code>.</p>
|
||||
</section>
|
||||
<section id="when-to-use-a-project-repository"><h2>When to use a project repository</h2>
|
||||
<p>Create a project repository when <strong>all</strong> of the following hold:</p>
|
||||
<ol><li>The work coordinates change across <strong>two or more</strong> functional repositories.</li><li>Binding the coordination workplan to any single product/tooling repo would misrepresent ownership or pollute that repo's history.</li><li>The effort has a <strong>bounded outcome</strong> with explicit success and retirement conditions (not an open-ended product roadmap).</li></ol>
|
||||
<p>Do <strong>not</strong> create a project repository for:</p>
|
||||
<ul><li>single-repo workplans;</li><li>small cross-cutting fixes that fit one lead repo's workplan plus dependency links;</li><li>durable products, libraries, or services (those use <code>INTENT.md</code> and ordinary product/tooling/research categories);</li><li>long-lived domain charters (those remain under <code>the-custodian/canon/projects/</code>).</li></ul>
|
||||
</section>
|
||||
<section id="naming"><h2>Naming</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Element</th><th>Convention</th></tr></thead><tbody><tr><td>Git / local directory</td><td><code>prj-<kebab-slug></code></td></tr><tr><td>Hub <code>repo</code> slug</td><td>same as directory name</td></tr><tr><td>Workplan prefix</td><td>short uppercase prefix derived from the project, ending in <code>-WP-</code> (example: <code>SHR-WP-</code> for State Hub Retirement)</td></tr><tr><td>Classification</td><td><code>category: project</code></td></tr></tbody></table></div>
|
||||
<p><strong>Canonical prefix is <code>prj-</code>.</strong> ADR-005's illustrative <code>proj-</code> form is superseded for new repositories. Do not invent parallel prefixes (<code>project-</code>, <code>xrepo-</code>, …).</p>
|
||||
<p>Slug rules:</p>
|
||||
<ul><li>lowercase kebab-case;</li><li>outcome-oriented (<code>prj-state-hub-retirement</code>), not a random ticket id;</li><li>stable for the life of the project (rename only with an explicit migration note in <code>history/</code>).</li></ul>
|
||||
</section>
|
||||
<section id="authority-boundary"><h2>Authority boundary</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Concern</th><th>Owner</th></tr></thead><tbody><tr><td>Project goal, success gates, retirement conditions</td><td>project repo (<code>GOAL.md</code>)</td></tr><tr><td>Architecture decisions, sequencing, dependency map, migration ledger, risks, consolidated evidence</td><td>project repo</td></tr><tr><td>Cross-repo workplans that coordinate the effort</td><td>project repo (<code>workplans/</code>)</td></tr><tr><td>Production implementation, tests, deployables</td><td><strong>participating functional repositories</strong></td></tr><tr><td>Per-repo implementation workplans and local evidence</td><td>each functional repository</td></tr><tr><td>Durable post-project standards and ADRs</td><td>permanent homes (<code>the-custodian</code> canon, or the owning product/tooling repo)</td></tr></tbody></table></div>
|
||||
<p><strong>Hard rules:</strong></p>
|
||||
<ol><li>Project repositories <strong>MUST NOT</strong> host production implementation code for the systems being changed.</li><li>Project workplans <strong>link</strong> child workplans by stable ID; they <strong>MUST NOT</strong> copy or replace child task lists.</li><li>The hub remains a read/index layer; work records originate as files (ADR-001).</li><li>Results of the project live primarily in the modified functional repositories and promoted canon. The project repo is coordination + provenance.</li></ol>
|
||||
</section>
|
||||
<section id="required-files"><h2>Required files</h2>
|
||||
<p>At registration / first meaningful commit:</p>
|
||||
<div class="scroll"><table><thead><tr><th>Path</th><th>Required</th><th>Role</th></tr></thead><tbody><tr><td><code>GOAL.md</code></td><td><strong>yes</strong></td><td>Outcome, invariants, success gates, project retirement conditions. <strong>Replaces <code>INTENT.md</code> for this flavor.</strong></td></tr><tr><td><code>SCOPE.md</code></td><td><strong>yes</strong></td><td>Project authority, participating repos, in/out of scope, work-record rule.</td></tr><tr><td><code>README.md</code></td><td><strong>yes</strong></td><td>Short entry point linking <code>GOAL.md</code>, <code>SCOPE.md</code>, genesis/history, active workplans.</td></tr><tr><td><code>AGENTS.md</code></td><td><strong>yes</strong></td><td>Agent session protocol for this project (orient → work → close; hub integration).</td></tr><tr><td><code>.repo-classification.yaml</code></td><td><strong>yes</strong></td><td><code>category: project</code> plus domain / capability tags for the <em>effort</em>.</td></tr><tr><td><code>workplans/</code></td><td><strong>yes</strong></td><td>At least one foundation workplan; prefix unique to the project.</td></tr><tr><td><code>history/</code></td><td>recommended</td><td>Genesis and significant milestones (why the project exists).</td></tr><tr><td><code>WORK-RECORDS.md</code></td><td>generated</td><td>Hub index; do not hand-edit.</td></tr><tr><td><code>.custodian-brief.md</code></td><td>generated</td><td>Offline orientation brief.</td></tr></tbody></table></div>
|
||||
<h3><code>GOAL.md</code> (not <code>INTENT.md</code>)</h3>
|
||||
<p>Durable product and tooling repositories explain <strong>why they exist</strong> with <code>INTENT.md</code>. Project repositories are temporary and outcome-bounded; they use <strong><code>GOAL.md</code></strong> instead.</p>
|
||||
<p><code>GOAL.md</code> MUST include:</p>
|
||||
<ol><li><strong>Outcome</strong> — what success looks like in one short section.</li><li><strong>Invariants</strong> — rules that must hold during the project.</li><li><strong>Success gates</strong> — checkable conditions for “goal achieved”.</li><li><strong>Project retirement</strong> — conditions under which <em>this repository</em> may be archived (usually: gates met + residuals handed off + durable decisions promoted).</li></ol>
|
||||
<p>Recommended frontmatter:</p>
|
||||
<pre>---
|
||||
repo: prj-<slug>
|
||||
repo_flavor: project
|
||||
project_status: draft | active | completed | archived
|
||||
started: "YYYY-MM-DD"
|
||||
reviewed: "YYYY-MM-DD"
|
||||
---</pre>
|
||||
<p><strong>Anti-pattern:</strong> shipping both <code>INTENT.md</code> and <code>GOAL.md</code> in a <code>prj-</code> repo. If a durable intent emerges, promote it into a permanent repository's <code>INTENT.md</code> (or canon) and keep the project goal as the temporary outcome document.</p>
|
||||
<h3>Relation to durable <code>INTENT.md</code></h3>
|
||||
<div class="scroll"><table><thead><tr><th>Repository kind</th><th>Purpose document</th></tr></thead><tbody><tr><td>product / tooling / research / business / experimental</td><td><code>INTENT.md</code></td></tr><tr><td><strong>project (<code>prj-</code>)</strong></td><td><strong><code>GOAL.md</code> only</strong></td></tr></tbody></table></div>
|
||||
<p>Tooling that scaffolds repositories (e.g. <code>statehub register</code>) MUST treat <code>GOAL.md</code> + <code>repo_flavor: project</code> as sufficient purpose documentation for <code>prj-</code> repos and MUST NOT require inventing an <code>INTENT.md</code> that pretends the project is a permanent product.</p>
|
||||
</section>
|
||||
<section id="lifecycle"><h2>Lifecycle</h2>
|
||||
<pre>draft → active → completed → archived</pre>
|
||||
<div class="scroll"><table><thead><tr><th>Status</th><th>Meaning</th><th>Repo / hub signals</th></tr></thead><tbody><tr><td><code>draft</code></td><td>Convention and foundation still forming; may not yet be registered</td><td><code>project_status: draft</code>; workplans often <code>proposed</code> / <code>ready</code></td></tr><tr><td><code>active</code></td><td>Coordination and child implementation in progress</td><td><code>project_status: active</code>; at least one workplan <code>active</code> or <code>ready</code></td></tr><tr><td><code>completed</code></td><td>All success gates have accepted evidence; residuals have live owners outside this repo</td><td><code>project_status: completed</code>; project workplans <code>finished</code> or cancelled with rationale</td></tr><tr><td><code>archived</code></td><td>Repository is read-only provenance</td><td>forge archive flag; hub repo/workplan <code>archived</code>; no normal writes</td></tr></tbody></table></div>
|
||||
<p>Promotion rules:</p>
|
||||
<ul><li><code>draft → active</code> when <code>GOAL.md</code> / <code>SCOPE.md</code> are reviewable and the foundation workplan is <code>ready</code> or <code>active</code>.</li><li><code>active → completed</code> only when <strong>every</strong> <code>GOAL.md</code> success gate has accepted evidence <strong>and</strong> residuals are live work records elsewhere (see below).</li><li><code>completed → archived</code> after the completion record is written, durable decisions are promoted, and a final consistency/link check passes.</li></ul>
|
||||
</section>
|
||||
<section id="residuals-before-completion"><h2>Residuals before completion</h2>
|
||||
<p>Actionable leftovers MUST NOT live only in finished workplan prose or <code>SCOPE.md</code>. Before any project workplan is set to <code>finished</code>, and again before <code>project_status: completed</code>, each residual becomes a <strong>live work record</strong> outside the closing narrative:</p>
|
||||
<ul><li>intake with <code>origin: residual</code> + <code>origin_ref: <WP-id></code>, or</li><li>a next workplan / decision / engagement / register-entry in a permanent repo.</li></ul>
|
||||
<p>Canon: <code>work-record-types_v0.1.md</code> § Residuals. Fleet residual listing is a State Hub concern, not a project-local queue file.</p>
|
||||
</section>
|
||||
<section id="completion-record"><h2>Completion record</h2>
|
||||
<p>Before archival, the project repository MUST contain a completion record (recommended path: <code>history/YYYY-MM-DD-completion.md</code>) that lists:</p>
|
||||
<ol><li>deployed or merged revisions that realize the outcome;</li><li>every participating repository touched, with links to merged PRs/commits or child workplan IDs;</li><li>promoted durable artefacts (canon paths, ADRs, standards);</li><li>migration and retirement evidence pointers (counts, cutover windows, backups);</li><li>residual work-record IDs and their owning repos;</li><li>rollback expiry or remaining operational obligations, if any.</li></ol>
|
||||
<p>Without this record, do not archive.</p>
|
||||
</section>
|
||||
<section id="archive-procedure"><h2>Archive procedure</h2>
|
||||
<ol><li>Verify all success gates and retirement conditions in <code>GOAL.md</code>.</li><li>Confirm residuals are live and owned outside this repository.</li><li>Promote remaining durable decisions/standards to permanent homes; leave pointers from the project repo.</li><li>Finish or cancel project workplans; move finished files to <code>workplans/archived/YYMMDD-<id>-<slug>.md</code> per workplan convention.</li><li>Write the completion record.</li><li>Set <code>project_status: archived</code> in <code>GOAL.md</code> frontmatter.</li><li>Run <code>statehub fix-consistency</code> (or equivalent) so the hub reflects finished workplans and the archived status.</li><li>Archive the repository in the forge (read-only); do <strong>not</strong> delete it.</li><li>Optionally mark the hub registration archived / read-only.</li></ol>
|
||||
<p><strong>Archive means read-only provenance, never deletion.</strong> Historical evidence and coordination narrative remain queryable.</p>
|
||||
</section>
|
||||
<section id="workplan-and-agent-conventions"><h2>Workplan and agent conventions</h2>
|
||||
<ul><li>Workplan files: <code>workplans/<PREFIX>-WP-NNNN-<slug>.md</code> with fleet status vocabulary (<code>proposed</code> … <code>archived</code>).</li><li>Session start order for agents: <code>GOAL.md</code> → <code>SCOPE.md</code> → genesis/history → active workplans (see project <code>AGENTS.md</code>).</li><li>Progress and task status follow ordinary State Hub / fix-consistency rules.</li><li>Ad-hoc low-risk fixes may use <code>workplans/ADHOC-YYYY-MM-DD.md</code> with canonical id <code>{PREFIX}-WP-ADHOC-YYYY-MM-DD</code>; anything multi-step belongs in a normal workplan.</li></ul>
|
||||
</section>
|
||||
<section id="minimal-layout-example"><h2>Minimal layout example</h2>
|
||||
<pre>prj-example-cutover/
|
||||
GOAL.md
|
||||
SCOPE.md
|
||||
README.md
|
||||
AGENTS.md
|
||||
.repo-classification.yaml
|
||||
history/
|
||||
2026-08-09-genesis.md
|
||||
workplans/
|
||||
EX-WP-0001-foundation.md</pre>
|
||||
</section>
|
||||
<section id="reference-instance"><h2>Reference instance</h2>
|
||||
<p>The first repository under this standard is <code>prj-state-hub-retirement</code> (State Hub retirement / hub-core consolidation). Use it as the structural reference when scaffolding later <code>prj-</code> repos; do not copy its domain-specific content.</p>
|
||||
</section>
|
||||
<section id="conformance-checklist"><h2>Conformance checklist</h2>
|
||||
<p>A repository conforms to the <code>prj-</code> flavor when:</p>
|
||||
<ul><li>[ ] Named <code>prj-<slug></code> and classified <code>category: project</code>.</li><li>[ ] Has <code>GOAL.md</code> with outcome, invariants, success gates, and retirement.</li><li>[ ] Has no durable-product <code>INTENT.md</code> (or documents an explicit temporary exception during migration of a mis-scaffolded repo).</li><li>[ ] Has <code>SCOPE.md</code>, <code>README.md</code>, <code>AGENTS.md</code>, and <code>.repo-classification.yaml</code>.</li><li>[ ] Hosts coordination workplans only; implementation lives in child repos.</li><li>[ ] Links child workplans by ID rather than duplicating their tasks.</li><li>[ ] Defines archive/completion discipline consistent with this standard.</li><li>[ ] On completion, writes a completion record and archives read-only.</li></ul>
|
||||
</section>
|
||||
<section id="related"><h2>Related</h2>
|
||||
<ul><li>ADR-001 — Workplans and Work Items Are Repository Artefacts</li><li>ADR-005 — Cross-Repo Workplans Live in Dedicated Project Repos</li><li><code>repo-classification-standard_v1.0.md</code> — <code>category: project</code></li><li><code>work-record-types_v0.1.md</code> — residuals and work-record kinds</li><li><code>workplan-terminology-fleet_v0.1.md</code> — workplan vocabulary</li></ul>
|
||||
</section><footer><span>canon-project-repository-flavor · accepted-1 · accepted</span><span>the-custodian · canon/standards/project-repository-flavor_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
246
build/standards/work-record-types/v0.1/index.html
Normal file
246
build/standards/work-record-types/v0.1/index.html
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="1a40de294be332ee713cdaab532a32a83718f3952c339fbff835ecee899a8dbc">
|
||||
<title>Work Record Types & Identity (Fleet) v0.1</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>canon-work-record-types</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Work Record Types & Identity (Fleet) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/work-record-types_v0.1.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="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#core-definition"><span class="n">·</span>Core definition</a></li><li><a href="#kind-registry-closed-list"><span class="n">·</span>Kind registry (closed list)</a></li><li><a href="#identity-layering"><span class="n">·</span>Identity layering</a></li><li><a href="#abstract-lifecycles-canon-fixed-minimal"><span class="n">·</span>Abstract lifecycles (canon-fixed, minimal)</a></li><li><a href="#residuals-role-not-kind"><span class="n">·</span>Residuals (role, not kind)</a></li><li><a href="#source-files-index-and-views"><span class="n">·</span>Source files, index, and views</a></li><li><a href="#tags"><span class="n">·</span>Tags</a></li><li><a href="#budgets"><span class="n">·</span>Budgets</a></li><li><a href="#reconciliation-loop-normative"><span class="n">·</span>Reconciliation loop (normative)</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><div class="rule-quote"><p>Ratified by founder 2026-07-20 (CUST-WP-0060-T01, hub decision f4640f9e). Source: <code>research/WorkOrchestrationArchitectureDraft.md</code> v0.2 (founder-reviewed 2026-07-20). Extends — does not replace — <code>workplan-terminology-fleet_v0.1.md</code> and ADR-001/ADR-005.</p></div>
|
||||
<section id="purpose"><h2>Purpose</h2>
|
||||
<p>Define <strong>work record</strong> as the umbrella term for every identified, lifecycle-bearing coordination artefact in the fleet; register the closed list of work-record <strong>kinds</strong>, their id schemes and abstract lifecycles; and fix the two-layer identity rule. This is the backbone convention for all work — planning, development, testing, operations, security & compliance, controlling, billing, marketing, sales — under one conceptual framework (different demands are met by flow profiles and kind-specific fields, never by parallel ontologies).</p>
|
||||
</section>
|
||||
<section id="core-definition"><h2>Core definition</h2>
|
||||
<p>A <strong>work record</strong> is any identified, lifecycle-bearing coordination artefact. A <strong>task</strong> is one <em>kind</em> of work record — the smallest executable unit. Every work record, regardless of kind, carries the <strong>conventional spine</strong>:</p>
|
||||
<div class="scroll"><table><thead><tr><th>Field</th><th>Convention</th></tr></thead><tbody><tr><td><code>id</code></td><td>canonical name per the type registry below</td></tr><tr><td><code>uuid</code></td><td>UUIDv7, hub-assigned at first index, written back to the source file</td></tr><tr><td><code>kind</code></td><td>one of the registered kinds</td></tr><tr><td><code>lane</code></td><td>autonomy lane (<code>autonomy-lanes_v0.1.md</code>)</td></tr><tr><td><code>status</code></td><td>abstract lifecycle of the kind (below)</td></tr><tr><td><code>owner</code></td><td>agent identity (<code>agt-…</code>) or human</td></tr><tr><td><code>repo</code></td><td>owning repo (ADR-001/ADR-005 anchor)</td></tr><tr><td><code>tags</code></td><td>policy + derived tags (§ Tags)</td></tr><tr><td><code>created</code> / <code>updated</code></td><td>dates (UUIDv7 supplies fine-grained internal time)</td></tr></tbody></table></div>
|
||||
<p>Kind-specific fields (budget, evidence, counterparty, deadline_pressure, attention_cost, …) extend the spine; they never replace it.</p>
|
||||
</section>
|
||||
<section id="kind-registry-closed-list"><h2>Kind registry (closed list)</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Kind</th><th>Id scheme</th><th>Meaning</th><th>Absorbs / legacy</th></tr></thead><tbody><tr><td><span class="kind ">`workplan`</span></td><td><code>{PREFIX}-WP-NNNN</code> · <code>{PREFIX}-WP-ADHOC-YYYY-MM-DD</code></td><td>structured, dependency-bearing body of work; repository-qualified daily container for small same-day tasks</td><td>unqualified <code>ADHOC-YYYY-MM-DD</code>; <code>MASON-0001</code> (grandfathered)</td></tr><tr><td><span class="kind ">`task`</span></td><td><code>{WP-ID}-TNN</code></td><td>smallest executable unit</td><td>unqualified <code>ADHOC-YYYY-MM-DD-TNN</code>; <code>MASON-0001-TNN</code> (grandfathered); issue-core issues become external projections only</td></tr><tr><td><span class="kind ">`intake`</span></td><td><code>{PREFIX}-IN-NNNN</code></td><td>spark: idea, finding, directive, request</td><td>hub suggestions (legacy, read-only close-out); <code>AWQ-NNN</code> (grandfathered)</td></tr><tr><td><span class="kind ">`decision`</span></td><td><code>{PREFIX}-DEC-YYYY-NNN</code></td><td>approval package + resolution</td><td><code>DEC-YYYY-NNN</code> (binky, grandfathered as-is)</td></tr><tr><td><span class="kind ">`engagement`</span></td><td><code>{PREFIX}-ENG-YYYY-NNN</code></td><td>scheduled external interaction (counterparty, prepared material, time window)</td><td><code>OH-YYYY-NNN</code> (grandfathered)</td></tr><tr><td><span class="kind ">`register-entry`</span></td><td>existing schemes: <code>RISK-NNN</code>, <code>RISK-F-NNNN</code>, <code>RISK-REG-NNNN</code>, <code>TD-…</code>, <code>CAP-…</code>, <code>CCR-YYYY-NNNN</code>, <code>ADR-NNN</code></td><td>risks/findings, regulatory records, technical debt, capability requests, credential change requests, architecture decisions</td><td>unchanged semantics, brought under the spine</td></tr></tbody></table></div>
|
||||
<p>Rules:</p>
|
||||
<ol><li><strong>Prefix grammar:</strong> <code>{PREFIX}</code> is one or more uppercase alphanumeric segments, each beginning with a letter, joined by hyphens. Both compact prefixes such as <code>CUST</code> and repository-derived prefixes such as <code>RAPP-OPENBAO</code> or <code>RAIL-K8S</code> are canonical. The final <code>-WP-</code> token remains the unambiguous kind separator.</li><li><strong>The registry is closed.</strong> An id pattern not registered in <code>work-record-types.yaml</code> fails CI and <code>fix-consistency</code> (the <em>sidetrack detector</em>). New kinds/prefixes are added by canon PR — deliberately cheap (one YAML entry + one schema) so the legitimate path is easier than any workaround.</li><li><strong>Grandfathering:</strong> existing ids are never renamed. Legacy prefixes map to kinds in the registry; retirement of a <em>scheme</em> (never of records) follows the legacy-meter discipline of <code>workplan-terminology-fleet_v0.1.md</code>.</li></ol>
|
||||
<p>Compatibility correction 2026-08-23: State Hub message <code>24504ce7-4f73-47da-a150-629b07b37073</code> exposed that the machine pattern did not accept the already owner-registered <code>RAPP-OPENBAO-WP</code> prefix. The grammar now matches ADR-007's repository-derived prefix model; prefix ownership and uniqueness remain separate registry checks and are not weakened by this syntax correction.</p>
|
||||
<p>The same compatibility review initially registered unqualified <code>ADHOC-YYYY-MM-DD</code> containers. A same-day collision between Activity Core and Net Kingdom then demonstrated that this form violates ADR-007's fleet-namespace uniqueness rule and cannot be used with deterministic UUID derivation. New daily records therefore use <code>{PREFIX}-WP-ADHOC-YYYY-MM-DD</code>; the filename remains <code>workplans/ADHOC-YYYY-MM-DD.md</code>. Existing unqualified ids are grandfathered and are never silently re-derived or disambiguated. Ad-hoc containers remain only for low-risk work completed directly.</p>
|
||||
<p>Risk Nexus findings (<code>RISK-F-*</code>) and regulatory records (<code>RISK-REG-*</code>) are registered as variants of <code>register-entry</code>, not as parallel work kinds. Their lifecycles remain owned by the register convention. <code>RISK-N-*</code> notes are deliberately not registered: a note has no lifecycle, so it does not meet the core definition of a work record. A note becomes part of the backbone only when an event promotes its substance into a lifecycle-bearing kind.</p>
|
||||
</section>
|
||||
<section id="identity-layering"><h2>Identity layering</h2>
|
||||
<ul><li><strong>UUIDv7 is primary</strong> for bookkeeping, relations, dependencies, and history. It is stable across renames, migrations, and terminology transitions.</li><li><strong>Canonical names are primary for humans and agents</strong> — UI, CLI, API output, prose, commits. UUIDs stay inspectable on demand but are never required reading.</li><li>The hub writes the UUID back into the source file at first index (pattern: today's <code>state_hub_*_id</code> fields).</li><li>A repeated source block with the same canonical id <strong>and the same UUID</strong> is one record with duplicate source occurrences. Index it once, retain every source location as diagnostic provenance, and report the duplication for governed cleanup. The repetition must not mint a second record. The same canonical id with different UUIDs is an identity collision and fails closed.</li></ul>
|
||||
</section>
|
||||
<section id="abstract-lifecycles-canon-fixed-minimal"><h2>Abstract lifecycles (canon-fixed, minimal)</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Kind</th><th>Lifecycle</th></tr></thead><tbody><tr><td><span class="kind ">task</span></td><td>`wait → todo → progress → done \</td><td>cancel` (InfoTechCanon)</td></tr><tr><td><span class="kind ">workplan</span></td><td><code>proposed → ready → active → blocked → backlog → finished → archived</code></td></tr><tr><td><span class="kind ">intake</span></td><td>`open → vetted → routed → closed(promoted \</td><td>declined \</td><td>absorbed)`</td></tr><tr><td><span class="kind ">decision</span></td><td>`prepared → resolved(approved \</td><td>rejected \</td><td>revised \</td><td>deferred)`</td></tr><tr><td><span class="kind ">engagement</span></td><td><code>queued → prepared → done</code></td></tr><tr><td><span class="kind ">register-entry</span></td><td>per existing register conventions (unchanged)</td></tr></tbody></table></div>
|
||||
<p><strong>Promotion is a first-class transition:</strong> <code>intake.routed → workplan | task | decision | engagement</code>, executed by one CLI/MCP call that writes both artefacts, sets <code>promoted_to</code> / <code>origin</code> back-links, and re-syncs. Manual transcription of an intake item into other kinds is a process defect.</p>
|
||||
<p><strong>Kind-specific rigor lives in flow profiles</strong>, not extra states: named task-flow-engine workstation definitions whose entry/exit assertions encode per-work-kind gates (e.g. compliance tasks cannot exit <code>progress</code> without an evidence link). Profiles are YAML in repos, in the same reconciliation loop.</p>
|
||||
</section>
|
||||
<section id="residuals-role-not-kind"><h2>Residuals (role, not kind)</h2>
|
||||
<p>A <strong>residual</strong> is work intentionally left after a workplan (or large task bundle) finishes. It is <strong>not</strong> a registered kind — inventing a parallel “residuals queue” or parking leftovers only in <code>SCOPE.md</code> / finished-file prose is a process defect. Residuals must be <strong>live work records</strong> so the hub can list them across repos and domains.</p>
|
||||
<div class="scroll"><table><thead><tr><th>Residual shape</th><th>Capture as</th><th>Required links</th></tr></thead><tbody><tr><td>Small Green/Blue follow-up, parkable</td><td><strong>intake</strong> (e.g. AWQ / <code>*-IN-*</code>)</td><td><code>origin: residual</code>, <code>origin_ref: <parent-WP-id></code></td></tr><tr><td>Multi-step / dependency-bearing</td><td><strong>workplan</strong> (spawn next WP)</td><td>body or frontmatter names parent WP; optional <code>origin</code>/<code>origin_ref</code> when promoted from intake</td></tr><tr><td>Needs founder choice</td><td><strong>decision</strong></td><td>same origin fields when created from residual intake</td></tr><tr><td>Needs founder time window</td><td><strong>engagement</strong></td><td>same</td></tr><tr><td>Persistent gap / risk</td><td><strong>register-entry</strong> (risk, tech debt, …)</td><td>cross-link parent WP in notes</td></tr></tbody></table></div>
|
||||
<p><strong>Close discipline for finished workplans:</strong></p>
|
||||
<ol><li>Short residual <strong>narrative</strong> may remain under the closing task (human context).</li><li><strong>Before</strong> <code>status: finished</code>, each residual that is still actionable becomes a live record (intake and/or child workplan). Prose alone is not the backlog.</li><li>Progress milestone may name the handoff ids.</li><li><code>statehub fix-consistency</code> so the index (<code>WORK-RECORDS.md</code>, hub) reflects the handoff.</li></ol>
|
||||
<p><strong>Fleet list (future CLI):</strong> filter open/vetted/routed intakes (and ready/ active workplans) with <code>origin ∈ {residual, handoff}</code> and optional <code>topic_id</code> / <code>repo</code> / <code>origin_ref</code>. Implementation home for that query is <strong>state-hub</strong> (<code>statehub residuals</code> / API), not domain repos.</p>
|
||||
</section>
|
||||
<section id="source-files-index-and-views"><h2>Source files, index, and views</h2>
|
||||
<ol><li><strong>Any repo file is a potential source of work records.</strong> Records are authored as schema-valid YAML blocks in context — thematic live documents, meeting notes, design docs, triage logs. The schema is the contract, not the location. Workplans keep dedicated files.</li><li><strong>A generated per-repo work-record index</strong> references every registered record in its source location (transclusion-style; markitect-family tooling). It is the "everything across all files" orientation view and a concurrency cross-check.</li><li><strong>Every working list is a generated view</strong> (<code>[auto]</code>-marked) over indexed records — autopilot views, decision queues, engagement batches, briefs. Hand-maintained completed-logs and queue tails are retired.</li><li>Ordering of views is <strong>lane + priority + age</strong> by default; dependency capture optional; WSJF optional and situational (overload triage only).</li></ol>
|
||||
</section>
|
||||
<section id="tags"><h2>Tags</h2>
|
||||
<p>Two classes, both in <code>tags</code>, never in <code>status</code>:</p>
|
||||
<ul><li><strong>Derived tags</strong> — computed, read-only in files: <code>stalled</code>, <code>stale</code>, <code>overdue-decision</code>, <code>budget-breached</code>, <code>orphaned</code>.</li><li><strong>Policy tags</strong> — assigned under tagging policies: <code>automatable</code>, <code>needs-human</code>, <code>unclear-implementation</code>, <code>red-adjacent</code>, <code>compliance-relevant</code>, <code>residual</code> (optional badge when origin is not used).</li></ul>
|
||||
<p>States migrate badly; tags migrate trivially. Anything situational is a tag.</p>
|
||||
<p><strong>Origin values (intake and promoted children):</strong> use stable strings, not free prose. For residuals prefer <code>origin: residual</code> (or <code>handoff</code>) and <code>origin_ref: <parent canonical id></code> (e.g. <code>BINKY-WP-0006</code>). Other established origins (e.g. <code>legacy-suggestion:<uuid></code>, mail-triage ids) remain valid.</p>
|
||||
</section>
|
||||
<section id="budgets"><h2>Budgets</h2>
|
||||
<p>Guardrail envelopes resolve programmatically at run start: workplan-frontmatter override → per-repo <code>budgets.yaml</code> (lane/default envelopes) → <strong>global best-guess default</strong>. Nothing runs unbounded. Budget resolution and enforcement is automation infrastructure, never agentic effort; metering via token events; breach ⇒ <code>budget-breached</code> + escalation.</p>
|
||||
</section>
|
||||
<section id="reconciliation-loop-normative"><h2>Reconciliation loop (normative)</h2>
|
||||
<pre>author (any repo file) → CI schema validation → commit
|
||||
→ fix-consistency: register/sync, UUID write-back
|
||||
→ hub read model → generated index + views → NATS events → activity-core</pre>
|
||||
<p>The hub remains a read model per ADR-001; runtime operations data (logs, metrics, run histories, token events) is the sanctioned DB-only exception.</p>
|
||||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li><code>research/WorkOrchestrationArchitectureDraft.md</code> (v0.2)</li><li><code>research/2026-07-19-work-orchestration-infrastructure-survey.md</code></li><li><code>research/2026-07-19-work-orchestration-best-practices.md</code></li><li><code>canon/architecture/adr-001-workplans-as-repo-artefacts.md</code>, <code>adr-005-…</code></li><li><code>canon/standards/workplan-terminology-fleet_v0.1.md</code></li><li><code>canon/standards/autonomy-lanes_v0.1.md</code></li><li><code>state-hub/docs/task-flow-engine-spec.md</code></li></ul>
|
||||
</section><footer><span>canon-work-record-types · accepted-1 · accepted</span><span>the-custodian · canon/standards/work-record-types_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="1a40de294be332ee713cdaab532a32a83718f3952c339fbff835ecee899a8dbc">
|
||||
<title>Work Record Types & Identity (Fleet) v0.1</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>canon-work-record-types</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Work Record Types & Identity (Fleet) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/work-record-types_v0.1.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="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#core-definition"><span class="n">·</span>Core definition</a></li><li><a href="#kind-registry-closed-list"><span class="n">·</span>Kind registry (closed list)</a></li><li><a href="#identity-layering"><span class="n">·</span>Identity layering</a></li><li><a href="#abstract-lifecycles-canon-fixed-minimal"><span class="n">·</span>Abstract lifecycles (canon-fixed, minimal)</a></li><li><a href="#residuals-role-not-kind"><span class="n">·</span>Residuals (role, not kind)</a></li><li><a href="#source-files-index-and-views"><span class="n">·</span>Source files, index, and views</a></li><li><a href="#tags"><span class="n">·</span>Tags</a></li><li><a href="#budgets"><span class="n">·</span>Budgets</a></li><li><a href="#reconciliation-loop-normative"><span class="n">·</span>Reconciliation loop (normative)</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><div class="rule-quote"><p>Ratified by founder 2026-07-20 (CUST-WP-0060-T01, hub decision f4640f9e). Source: <code>research/WorkOrchestrationArchitectureDraft.md</code> v0.2 (founder-reviewed 2026-07-20). Extends — does not replace — <code>workplan-terminology-fleet_v0.1.md</code> and ADR-001/ADR-005.</p></div>
|
||||
<section id="purpose"><h2>Purpose</h2>
|
||||
<p>Define <strong>work record</strong> as the umbrella term for every identified, lifecycle-bearing coordination artefact in the fleet; register the closed list of work-record <strong>kinds</strong>, their id schemes and abstract lifecycles; and fix the two-layer identity rule. This is the backbone convention for all work — planning, development, testing, operations, security & compliance, controlling, billing, marketing, sales — under one conceptual framework (different demands are met by flow profiles and kind-specific fields, never by parallel ontologies).</p>
|
||||
</section>
|
||||
<section id="core-definition"><h2>Core definition</h2>
|
||||
<p>A <strong>work record</strong> is any identified, lifecycle-bearing coordination artefact. A <strong>task</strong> is one <em>kind</em> of work record — the smallest executable unit. Every work record, regardless of kind, carries the <strong>conventional spine</strong>:</p>
|
||||
<div class="scroll"><table><thead><tr><th>Field</th><th>Convention</th></tr></thead><tbody><tr><td><code>id</code></td><td>canonical name per the type registry below</td></tr><tr><td><code>uuid</code></td><td>UUIDv7, hub-assigned at first index, written back to the source file</td></tr><tr><td><code>kind</code></td><td>one of the registered kinds</td></tr><tr><td><code>lane</code></td><td>autonomy lane (<code>autonomy-lanes_v0.1.md</code>)</td></tr><tr><td><code>status</code></td><td>abstract lifecycle of the kind (below)</td></tr><tr><td><code>owner</code></td><td>agent identity (<code>agt-…</code>) or human</td></tr><tr><td><code>repo</code></td><td>owning repo (ADR-001/ADR-005 anchor)</td></tr><tr><td><code>tags</code></td><td>policy + derived tags (§ Tags)</td></tr><tr><td><code>created</code> / <code>updated</code></td><td>dates (UUIDv7 supplies fine-grained internal time)</td></tr></tbody></table></div>
|
||||
<p>Kind-specific fields (budget, evidence, counterparty, deadline_pressure, attention_cost, …) extend the spine; they never replace it.</p>
|
||||
</section>
|
||||
<section id="kind-registry-closed-list"><h2>Kind registry (closed list)</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Kind</th><th>Id scheme</th><th>Meaning</th><th>Absorbs / legacy</th></tr></thead><tbody><tr><td><span class="kind ">`workplan`</span></td><td><code>{PREFIX}-WP-NNNN</code> · <code>{PREFIX}-WP-ADHOC-YYYY-MM-DD</code></td><td>structured, dependency-bearing body of work; repository-qualified daily container for small same-day tasks</td><td>unqualified <code>ADHOC-YYYY-MM-DD</code>; <code>MASON-0001</code> (grandfathered)</td></tr><tr><td><span class="kind ">`task`</span></td><td><code>{WP-ID}-TNN</code></td><td>smallest executable unit</td><td>unqualified <code>ADHOC-YYYY-MM-DD-TNN</code>; <code>MASON-0001-TNN</code> (grandfathered); issue-core issues become external projections only</td></tr><tr><td><span class="kind ">`intake`</span></td><td><code>{PREFIX}-IN-NNNN</code></td><td>spark: idea, finding, directive, request</td><td>hub suggestions (legacy, read-only close-out); <code>AWQ-NNN</code> (grandfathered)</td></tr><tr><td><span class="kind ">`decision`</span></td><td><code>{PREFIX}-DEC-YYYY-NNN</code></td><td>approval package + resolution</td><td><code>DEC-YYYY-NNN</code> (binky, grandfathered as-is)</td></tr><tr><td><span class="kind ">`engagement`</span></td><td><code>{PREFIX}-ENG-YYYY-NNN</code></td><td>scheduled external interaction (counterparty, prepared material, time window)</td><td><code>OH-YYYY-NNN</code> (grandfathered)</td></tr><tr><td><span class="kind ">`register-entry`</span></td><td>existing schemes: <code>RISK-NNN</code>, <code>RISK-F-NNNN</code>, <code>RISK-REG-NNNN</code>, <code>TD-…</code>, <code>CAP-…</code>, <code>CCR-YYYY-NNNN</code>, <code>ADR-NNN</code></td><td>risks/findings, regulatory records, technical debt, capability requests, credential change requests, architecture decisions</td><td>unchanged semantics, brought under the spine</td></tr></tbody></table></div>
|
||||
<p>Rules:</p>
|
||||
<ol><li><strong>Prefix grammar:</strong> <code>{PREFIX}</code> is one or more uppercase alphanumeric segments, each beginning with a letter, joined by hyphens. Both compact prefixes such as <code>CUST</code> and repository-derived prefixes such as <code>RAPP-OPENBAO</code> or <code>RAIL-K8S</code> are canonical. The final <code>-WP-</code> token remains the unambiguous kind separator.</li><li><strong>The registry is closed.</strong> An id pattern not registered in <code>work-record-types.yaml</code> fails CI and <code>fix-consistency</code> (the <em>sidetrack detector</em>). New kinds/prefixes are added by canon PR — deliberately cheap (one YAML entry + one schema) so the legitimate path is easier than any workaround.</li><li><strong>Grandfathering:</strong> existing ids are never renamed. Legacy prefixes map to kinds in the registry; retirement of a <em>scheme</em> (never of records) follows the legacy-meter discipline of <code>workplan-terminology-fleet_v0.1.md</code>.</li></ol>
|
||||
<p>Compatibility correction 2026-08-23: State Hub message <code>24504ce7-4f73-47da-a150-629b07b37073</code> exposed that the machine pattern did not accept the already owner-registered <code>RAPP-OPENBAO-WP</code> prefix. The grammar now matches ADR-007's repository-derived prefix model; prefix ownership and uniqueness remain separate registry checks and are not weakened by this syntax correction.</p>
|
||||
<p>The same compatibility review initially registered unqualified <code>ADHOC-YYYY-MM-DD</code> containers. A same-day collision between Activity Core and Net Kingdom then demonstrated that this form violates ADR-007's fleet-namespace uniqueness rule and cannot be used with deterministic UUID derivation. New daily records therefore use <code>{PREFIX}-WP-ADHOC-YYYY-MM-DD</code>; the filename remains <code>workplans/ADHOC-YYYY-MM-DD.md</code>. Existing unqualified ids are grandfathered and are never silently re-derived or disambiguated. Ad-hoc containers remain only for low-risk work completed directly.</p>
|
||||
<p>Risk Nexus findings (<code>RISK-F-*</code>) and regulatory records (<code>RISK-REG-*</code>) are registered as variants of <code>register-entry</code>, not as parallel work kinds. Their lifecycles remain owned by the register convention. <code>RISK-N-*</code> notes are deliberately not registered: a note has no lifecycle, so it does not meet the core definition of a work record. A note becomes part of the backbone only when an event promotes its substance into a lifecycle-bearing kind.</p>
|
||||
</section>
|
||||
<section id="identity-layering"><h2>Identity layering</h2>
|
||||
<ul><li><strong>UUIDv7 is primary</strong> for bookkeeping, relations, dependencies, and history. It is stable across renames, migrations, and terminology transitions.</li><li><strong>Canonical names are primary for humans and agents</strong> — UI, CLI, API output, prose, commits. UUIDs stay inspectable on demand but are never required reading.</li><li>The hub writes the UUID back into the source file at first index (pattern: today's <code>state_hub_*_id</code> fields).</li><li>A repeated source block with the same canonical id <strong>and the same UUID</strong> is one record with duplicate source occurrences. Index it once, retain every source location as diagnostic provenance, and report the duplication for governed cleanup. The repetition must not mint a second record. The same canonical id with different UUIDs is an identity collision and fails closed.</li></ul>
|
||||
</section>
|
||||
<section id="abstract-lifecycles-canon-fixed-minimal"><h2>Abstract lifecycles (canon-fixed, minimal)</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Kind</th><th>Lifecycle</th></tr></thead><tbody><tr><td><span class="kind ">task</span></td><td>`wait → todo → progress → done \</td><td>cancel` (InfoTechCanon)</td></tr><tr><td><span class="kind ">workplan</span></td><td><code>proposed → ready → active → blocked → backlog → finished → archived</code></td></tr><tr><td><span class="kind ">intake</span></td><td>`open → vetted → routed → closed(promoted \</td><td>declined \</td><td>absorbed)`</td></tr><tr><td><span class="kind ">decision</span></td><td>`prepared → resolved(approved \</td><td>rejected \</td><td>revised \</td><td>deferred)`</td></tr><tr><td><span class="kind ">engagement</span></td><td><code>queued → prepared → done</code></td></tr><tr><td><span class="kind ">register-entry</span></td><td>per existing register conventions (unchanged)</td></tr></tbody></table></div>
|
||||
<p><strong>Promotion is a first-class transition:</strong> <code>intake.routed → workplan | task | decision | engagement</code>, executed by one CLI/MCP call that writes both artefacts, sets <code>promoted_to</code> / <code>origin</code> back-links, and re-syncs. Manual transcription of an intake item into other kinds is a process defect.</p>
|
||||
<p><strong>Kind-specific rigor lives in flow profiles</strong>, not extra states: named task-flow-engine workstation definitions whose entry/exit assertions encode per-work-kind gates (e.g. compliance tasks cannot exit <code>progress</code> without an evidence link). Profiles are YAML in repos, in the same reconciliation loop.</p>
|
||||
</section>
|
||||
<section id="residuals-role-not-kind"><h2>Residuals (role, not kind)</h2>
|
||||
<p>A <strong>residual</strong> is work intentionally left after a workplan (or large task bundle) finishes. It is <strong>not</strong> a registered kind — inventing a parallel “residuals queue” or parking leftovers only in <code>SCOPE.md</code> / finished-file prose is a process defect. Residuals must be <strong>live work records</strong> so the hub can list them across repos and domains.</p>
|
||||
<div class="scroll"><table><thead><tr><th>Residual shape</th><th>Capture as</th><th>Required links</th></tr></thead><tbody><tr><td>Small Green/Blue follow-up, parkable</td><td><strong>intake</strong> (e.g. AWQ / <code>*-IN-*</code>)</td><td><code>origin: residual</code>, <code>origin_ref: <parent-WP-id></code></td></tr><tr><td>Multi-step / dependency-bearing</td><td><strong>workplan</strong> (spawn next WP)</td><td>body or frontmatter names parent WP; optional <code>origin</code>/<code>origin_ref</code> when promoted from intake</td></tr><tr><td>Needs founder choice</td><td><strong>decision</strong></td><td>same origin fields when created from residual intake</td></tr><tr><td>Needs founder time window</td><td><strong>engagement</strong></td><td>same</td></tr><tr><td>Persistent gap / risk</td><td><strong>register-entry</strong> (risk, tech debt, …)</td><td>cross-link parent WP in notes</td></tr></tbody></table></div>
|
||||
<p><strong>Close discipline for finished workplans:</strong></p>
|
||||
<ol><li>Short residual <strong>narrative</strong> may remain under the closing task (human context).</li><li><strong>Before</strong> <code>status: finished</code>, each residual that is still actionable becomes a live record (intake and/or child workplan). Prose alone is not the backlog.</li><li>Progress milestone may name the handoff ids.</li><li><code>statehub fix-consistency</code> so the index (<code>WORK-RECORDS.md</code>, hub) reflects the handoff.</li></ol>
|
||||
<p><strong>Fleet list (future CLI):</strong> filter open/vetted/routed intakes (and ready/ active workplans) with <code>origin ∈ {residual, handoff}</code> and optional <code>topic_id</code> / <code>repo</code> / <code>origin_ref</code>. Implementation home for that query is <strong>state-hub</strong> (<code>statehub residuals</code> / API), not domain repos.</p>
|
||||
</section>
|
||||
<section id="source-files-index-and-views"><h2>Source files, index, and views</h2>
|
||||
<ol><li><strong>Any repo file is a potential source of work records.</strong> Records are authored as schema-valid YAML blocks in context — thematic live documents, meeting notes, design docs, triage logs. The schema is the contract, not the location. Workplans keep dedicated files.</li><li><strong>A generated per-repo work-record index</strong> references every registered record in its source location (transclusion-style; markitect-family tooling). It is the "everything across all files" orientation view and a concurrency cross-check.</li><li><strong>Every working list is a generated view</strong> (<code>[auto]</code>-marked) over indexed records — autopilot views, decision queues, engagement batches, briefs. Hand-maintained completed-logs and queue tails are retired.</li><li>Ordering of views is <strong>lane + priority + age</strong> by default; dependency capture optional; WSJF optional and situational (overload triage only).</li></ol>
|
||||
</section>
|
||||
<section id="tags"><h2>Tags</h2>
|
||||
<p>Two classes, both in <code>tags</code>, never in <code>status</code>:</p>
|
||||
<ul><li><strong>Derived tags</strong> — computed, read-only in files: <code>stalled</code>, <code>stale</code>, <code>overdue-decision</code>, <code>budget-breached</code>, <code>orphaned</code>.</li><li><strong>Policy tags</strong> — assigned under tagging policies: <code>automatable</code>, <code>needs-human</code>, <code>unclear-implementation</code>, <code>red-adjacent</code>, <code>compliance-relevant</code>, <code>residual</code> (optional badge when origin is not used).</li></ul>
|
||||
<p>States migrate badly; tags migrate trivially. Anything situational is a tag.</p>
|
||||
<p><strong>Origin values (intake and promoted children):</strong> use stable strings, not free prose. For residuals prefer <code>origin: residual</code> (or <code>handoff</code>) and <code>origin_ref: <parent canonical id></code> (e.g. <code>BINKY-WP-0006</code>). Other established origins (e.g. <code>legacy-suggestion:<uuid></code>, mail-triage ids) remain valid.</p>
|
||||
</section>
|
||||
<section id="budgets"><h2>Budgets</h2>
|
||||
<p>Guardrail envelopes resolve programmatically at run start: workplan-frontmatter override → per-repo <code>budgets.yaml</code> (lane/default envelopes) → <strong>global best-guess default</strong>. Nothing runs unbounded. Budget resolution and enforcement is automation infrastructure, never agentic effort; metering via token events; breach ⇒ <code>budget-breached</code> + escalation.</p>
|
||||
</section>
|
||||
<section id="reconciliation-loop-normative"><h2>Reconciliation loop (normative)</h2>
|
||||
<pre>author (any repo file) → CI schema validation → commit
|
||||
→ fix-consistency: register/sync, UUID write-back
|
||||
→ hub read model → generated index + views → NATS events → activity-core</pre>
|
||||
<p>The hub remains a read model per ADR-001; runtime operations data (logs, metrics, run histories, token events) is the sanctioned DB-only exception.</p>
|
||||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li><code>research/WorkOrchestrationArchitectureDraft.md</code> (v0.2)</li><li><code>research/2026-07-19-work-orchestration-infrastructure-survey.md</code></li><li><code>research/2026-07-19-work-orchestration-best-practices.md</code></li><li><code>canon/architecture/adr-001-workplans-as-repo-artefacts.md</code>, <code>adr-005-…</code></li><li><code>canon/standards/workplan-terminology-fleet_v0.1.md</code></li><li><code>canon/standards/autonomy-lanes_v0.1.md</code></li><li><code>state-hub/docs/task-flow-engine-spec.md</code></li></ul>
|
||||
</section><footer><span>canon-work-record-types · accepted-1 · accepted</span><span>the-custodian · canon/standards/work-record-types_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
236
build/standards/workplan-terminology/v0.1/index.html
Normal file
236
build/standards/workplan-terminology/v0.1/index.html
Normal file
|
|
@ -0,0 +1,236 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="199812632ac342ca3231498e545e3701e10c191ca144035b36a23c1a0b717712">
|
||||
<title>Workplan Terminology (Fleet) v0.1</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>canon-workplan-terminology-fleet</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Workplan Terminology (Fleet) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/workplan-terminology-fleet_v0.1.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="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#canonical-term"><span class="n">·</span>Canonical term</a></li><li><a href="#work-record-umbrella-v0-2-addendum-cust-wp-0060"><span class="n">·</span>Work-record umbrella (v0.2 addendum, CUST-WP-0060)</a></li><li><a href="#legacy-bridges-keep-until-retired"><span class="n">·</span>Legacy bridges (keep until retired)</a></li><li><a href="#event-subjects-normative"><span class="n">·</span>Event subjects (normative)</a></li><li><a href="#agent-and-documentation-rules"><span class="n">·</span>Agent and documentation rules</a></li><li><a href="#retirement-rule-unchanged"><span class="n">·</span>Retirement rule (unchanged)</a></li><li><a href="#verification"><span class="n">·</span>Verification</a></li><li><a href="#out-of-scope-this-standard"><span class="n">·</span>Out of scope (this standard)</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="purpose"><h2>Purpose</h2>
|
||||
<p>Define <strong>workplan</strong> as the canonical fleet term for repo-backed deliverable work indexed by State Hub. Preserve explicit <strong>legacy bridges</strong> where APIs, events, generated fields, or historical documents still say <code>workstream</code>, until metered retirement criteria are met.</p>
|
||||
<p>This standard complements:</p>
|
||||
<ul><li><strong>ADR-001</strong> — workplans originate as repo files; the hub indexes them.</li><li><strong>STATE-WP-0054</strong> — State Hub compatibility layer and <code>legacy-meter</code>.</li><li><strong>STATE-WP-0069</strong> — State Hub legacy interface retirement (child plan).</li><li><strong>CUST-WP-0055</strong> — fleet-wide coordination and prose migration.</li></ul>
|
||||
<p>Authoritative interface matrix for State Hub: <code>state-hub/docs/workplan-terminology-transition.md</code>.</p>
|
||||
</section>
|
||||
<section id="canonical-term"><h2>Canonical term</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Concept</th><th>Fleet term</th><th>Meaning</th></tr></thead><tbody><tr><td>Repo-backed body of work</td><td><strong>workplan</strong></td><td>Markdown file under <code>workplans/</code> per ADR-001</td></tr><tr><td>Workplan file id</td><td><code>{PREFIX}-WP-NNNN</code></td><td>e.g. <code>CUST-WP-0055</code>, <code>STATE-WP-0069</code></td></tr><tr><td>Hub index row</td><td><strong>workplan</strong> (product term)</td><td>DB entity keyed by UUID; may still use legacy column names internally</td></tr><tr><td>Task within a workplan</td><td><strong>task</strong></td><td><code>id: {WP}-TNN</code> in workplan file blocks</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section id="work-record-umbrella-v0-2-addendum-cust-wp-0060"><h2>Work-record umbrella (v0.2 addendum, CUST-WP-0060)</h2>
|
||||
<p>The workplan and task definitions above are unchanged. Since v0.2 they are two <em>kinds</em> of the fleet umbrella term <strong>work record</strong> — any identified, lifecycle-bearing coordination artefact. The full kind registry (workplan, task, <strong>intake item</strong>, <strong>decision</strong>, <strong>engagement</strong>, <strong>register entry</strong>), the conventional spine, identity layering (UUIDv7 internal, canonical names external), and grandfathered legacy id schemes (<code>AWQ-</code>, <code>DEC-</code>, <code>OH-</code>) are normative in <code>work-record-types_v0.1.md</code> (+ machine registry <code>work-record-types.yaml</code>). Autonomy-lane vocabulary is normative in <code>autonomy-lanes_v0.1.md</code>. "Suggestion" is a legacy bridge name for the intake kind (state-hub suggestions table: read-only legacy pending close-out). This file keeps its <code>_v0.1</code> name for reference stability; the frontmatter <code>version</code> field is authoritative.</p>
|
||||
<p>Use <strong>workplan</strong> in human-facing prose: <code>SCOPE.md</code>, <code>AGENTS.md</code>, <code>INTENT.md</code>, README, workplan bodies, operator runbooks, and agent session guidance.</p>
|
||||
</section>
|
||||
<section id="legacy-bridges-keep-until-retired"><h2>Legacy bridges (keep until retired)</h2>
|
||||
<p>Do <strong>not</strong> mass-rename these in the CUST-WP-0055 migration window:</p>
|
||||
<div class="scroll"><table><thead><tr><th>Surface</th><th>Canonical</th><th>Legacy bridge</th><th>Retirement owner</th></tr></thead><tbody><tr><td>Workplan frontmatter link</td><td>(implicit workplan UUID)</td><td><code>state_hub_workstream_id</code></td><td>Separate bridge-field migration</td></tr><tr><td>REST/MCP parameters</td><td><code>workplan_id</code></td><td><code>workstream_id</code></td><td><code>STATE-WP-0069</code> + legacy-meter</td></tr><tr><td>REST routes</td><td><code>/workplans/</code></td><td><code>/workstreams/</code></td><td><code>STATE-WP-0069</code></td></tr><tr><td>MCP procedures</td><td><code>create_workplan</code>, etc.</td><td><code>create_workstream</code>, etc.</td><td><code>STATE-WP-0069</code></td></tr><tr><td>State Hub completion event</td><td><code>org.statehub.workplan.completed</code></td><td><code>org.statehub.workstream.completed</code></td><td><code>STATE-WP-0069</code> T05</td></tr><tr><td>activity-core catalog (custodian-era)</td><td><code>org.statehub.workplan.completed</code></td><td><code>org.workstream.completed</code></td><td><code>CUST-WP-0055</code> T03</td></tr><tr><td>Archived workplan prose</td><td>workplan (when editing)</td><td>historical "workstream" text</td><td>Grandfathered; header note only</td></tr><tr><td>Grandfathered filenames</td><td>—</td><td>paths containing <code>workstream</code></td><td>ADR-001 non-rename policy</td></tr></tbody></table></div>
|
||||
<p><strong>Do not</strong> introduce a bare <code>org.workplan.completed</code> event subject. State Hub uses the <code>org.statehub.*</code> namespace.</p>
|
||||
</section>
|
||||
<section id="event-subjects-normative"><h2>Event subjects (normative)</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Subject</th><th>Status</th><th>Notes</th></tr></thead><tbody><tr><td><code>org.statehub.workplan.completed</code></td><td><strong>preferred</strong></td><td>Emitted on workplan finish; subscribe here</td></tr><tr><td><code>org.statehub.workstream.completed</code></td><td>legacy (metered)</td><td>Dual-published today; retire per legacy-meter</td></tr><tr><td><code>org.workstream.completed</code></td><td>legacy (catalog)</td><td>activity-core custodian-era type; align to State Hub subject</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section id="agent-and-documentation-rules"><h2>Agent and documentation rules</h2>
|
||||
<ol><li><strong>Write workplan</strong> in instructions, orientation steps, and error messages aimed at humans or coding agents.</li><li><strong>Mention workstream only</strong> in an explicit compatibility footnote, e.g.: > Legacy term: State Hub still exposes <code>/workstreams</code> and <code>workstream_id</code> > aliases until legacy-meter retires them (<code>STATE-WP-0069</code>).</li><li><strong>Leave unchanged</strong> in code or docs when the string is a wire key, route, legacy-meter registry entry, or <code>state_hub_workstream_id</code> frontmatter field.</li><li><strong>Prefer</strong> <code>GET /workplans/</code> and <code>workplan_id</code> in new examples and scripts.</li></ol>
|
||||
<p>Regenerated agent files (<code>state-hub/scripts/update_agent_instruction_files.py</code>) should follow rules 1–2. Templates live under <code>state-hub/scripts/project_rules/*.template</code>.</p>
|
||||
</section>
|
||||
<section id="retirement-rule-unchanged"><h2>Retirement rule (unchanged)</h2>
|
||||
<p>A legacy interface may be removed only when <strong>all</strong> are true:</p>
|
||||
<ul><li>registered in State Hub <code>legacy-meter</code>;</li><li>replacement reference verified;</li><li>no manual hold;</li><li>zero measured calls in the review window.</li></ul>
|
||||
<p>State Hub owns usage evidence; activity-core may run weekly review activities. See <code>state-hub/docs/workplan-terminology-transition.md</code>.</p>
|
||||
</section>
|
||||
<section id="verification"><h2>Verification</h2>
|
||||
<p>Fleet terminology drift is measured with:</p>
|
||||
<pre>python tools/scan_workstream_terminology.py
|
||||
python tools/scan_workstream_terminology.py --repo <slug> --json</pre>
|
||||
<p>Baseline artefact (2026-07-08): <code>docs/evidence/workstream-terminology-baseline-20260708.json</code>.</p>
|
||||
<p>Exit criteria and scan exclusions: <code>CUST-WP-0055</code> T08.</p>
|
||||
</section>
|
||||
<section id="out-of-scope-this-standard"><h2>Out of scope (this standard)</h2>
|
||||
<ul><li>Renaming <code>state_hub_workstream_id</code> in workplan frontmatter.</li><li>Database table or ORM model renames (completed in <code>STATE-WP-0065</code>).</li><li>Rewriting archived workplan bodies in bulk (<code>CUST-WP-0055</code> T07).</li></ul>
|
||||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li><code>canon/architecture/adr-001-workplans-as-repo-artefacts.md</code></li><li><code>state-hub/docs/workplan-terminology-transition.md</code></li><li><code>state-hub/workplans/STATE-WP-0054-workplan-terminology-transition-legacy-meter.md</code></li><li><code>state-hub/workplans/STATE-WP-0069-workplan-terminology-legacy-retirement.md</code></li><li><code>workplans/CUST-WP-0055-workplan-terminology-fleet-refactor.md</code></li></ul>
|
||||
</section><footer><span>canon-workplan-terminology-fleet · accepted-1 · accepted</span><span>the-custodian · canon/standards/workplan-terminology-fleet_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
<!doctype html>
|
||||
<html lang="en"><meta charset="utf-8">
|
||||
<meta name="policy-source-revision" content="4b951be3947f9457cc091a7d359d9232646b4c93">
|
||||
<meta name="policy-source-digest" content="199812632ac342ca3231498e545e3701e10c191ca144035b36a23c1a0b717712">
|
||||
<title>Workplan Terminology (Fleet) v0.1</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>canon-workplan-terminology-fleet</span> <span class="stat">accepted · accepted-1</span> <span>the-custodian</span> <span>reviewed 2026-08-31</span><span>generated from canonical source — do not edit</span></div><h1>Workplan Terminology (Fleet) v0.1</h1><p class="sub">Source: <code>the-custodian · canon/standards/workplan-terminology-fleet_v0.1.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="#purpose"><span class="n">·</span>Purpose</a></li><li><a href="#canonical-term"><span class="n">·</span>Canonical term</a></li><li><a href="#work-record-umbrella-v0-2-addendum-cust-wp-0060"><span class="n">·</span>Work-record umbrella (v0.2 addendum, CUST-WP-0060)</a></li><li><a href="#legacy-bridges-keep-until-retired"><span class="n">·</span>Legacy bridges (keep until retired)</a></li><li><a href="#event-subjects-normative"><span class="n">·</span>Event subjects (normative)</a></li><li><a href="#agent-and-documentation-rules"><span class="n">·</span>Agent and documentation rules</a></li><li><a href="#retirement-rule-unchanged"><span class="n">·</span>Retirement rule (unchanged)</a></li><li><a href="#verification"><span class="n">·</span>Verification</a></li><li><a href="#out-of-scope-this-standard"><span class="n">·</span>Out of scope (this standard)</a></li><li><a href="#references"><span class="n">·</span>References</a></li></ol></nav><main><section id="purpose"><h2>Purpose</h2>
|
||||
<p>Define <strong>workplan</strong> as the canonical fleet term for repo-backed deliverable work indexed by State Hub. Preserve explicit <strong>legacy bridges</strong> where APIs, events, generated fields, or historical documents still say <code>workstream</code>, until metered retirement criteria are met.</p>
|
||||
<p>This standard complements:</p>
|
||||
<ul><li><strong>ADR-001</strong> — workplans originate as repo files; the hub indexes them.</li><li><strong>STATE-WP-0054</strong> — State Hub compatibility layer and <code>legacy-meter</code>.</li><li><strong>STATE-WP-0069</strong> — State Hub legacy interface retirement (child plan).</li><li><strong>CUST-WP-0055</strong> — fleet-wide coordination and prose migration.</li></ul>
|
||||
<p>Authoritative interface matrix for State Hub: <code>state-hub/docs/workplan-terminology-transition.md</code>.</p>
|
||||
</section>
|
||||
<section id="canonical-term"><h2>Canonical term</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Concept</th><th>Fleet term</th><th>Meaning</th></tr></thead><tbody><tr><td>Repo-backed body of work</td><td><strong>workplan</strong></td><td>Markdown file under <code>workplans/</code> per ADR-001</td></tr><tr><td>Workplan file id</td><td><code>{PREFIX}-WP-NNNN</code></td><td>e.g. <code>CUST-WP-0055</code>, <code>STATE-WP-0069</code></td></tr><tr><td>Hub index row</td><td><strong>workplan</strong> (product term)</td><td>DB entity keyed by UUID; may still use legacy column names internally</td></tr><tr><td>Task within a workplan</td><td><strong>task</strong></td><td><code>id: {WP}-TNN</code> in workplan file blocks</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section id="work-record-umbrella-v0-2-addendum-cust-wp-0060"><h2>Work-record umbrella (v0.2 addendum, CUST-WP-0060)</h2>
|
||||
<p>The workplan and task definitions above are unchanged. Since v0.2 they are two <em>kinds</em> of the fleet umbrella term <strong>work record</strong> — any identified, lifecycle-bearing coordination artefact. The full kind registry (workplan, task, <strong>intake item</strong>, <strong>decision</strong>, <strong>engagement</strong>, <strong>register entry</strong>), the conventional spine, identity layering (UUIDv7 internal, canonical names external), and grandfathered legacy id schemes (<code>AWQ-</code>, <code>DEC-</code>, <code>OH-</code>) are normative in <code>work-record-types_v0.1.md</code> (+ machine registry <code>work-record-types.yaml</code>). Autonomy-lane vocabulary is normative in <code>autonomy-lanes_v0.1.md</code>. "Suggestion" is a legacy bridge name for the intake kind (state-hub suggestions table: read-only legacy pending close-out). This file keeps its <code>_v0.1</code> name for reference stability; the frontmatter <code>version</code> field is authoritative.</p>
|
||||
<p>Use <strong>workplan</strong> in human-facing prose: <code>SCOPE.md</code>, <code>AGENTS.md</code>, <code>INTENT.md</code>, README, workplan bodies, operator runbooks, and agent session guidance.</p>
|
||||
</section>
|
||||
<section id="legacy-bridges-keep-until-retired"><h2>Legacy bridges (keep until retired)</h2>
|
||||
<p>Do <strong>not</strong> mass-rename these in the CUST-WP-0055 migration window:</p>
|
||||
<div class="scroll"><table><thead><tr><th>Surface</th><th>Canonical</th><th>Legacy bridge</th><th>Retirement owner</th></tr></thead><tbody><tr><td>Workplan frontmatter link</td><td>(implicit workplan UUID)</td><td><code>state_hub_workstream_id</code></td><td>Separate bridge-field migration</td></tr><tr><td>REST/MCP parameters</td><td><code>workplan_id</code></td><td><code>workstream_id</code></td><td><code>STATE-WP-0069</code> + legacy-meter</td></tr><tr><td>REST routes</td><td><code>/workplans/</code></td><td><code>/workstreams/</code></td><td><code>STATE-WP-0069</code></td></tr><tr><td>MCP procedures</td><td><code>create_workplan</code>, etc.</td><td><code>create_workstream</code>, etc.</td><td><code>STATE-WP-0069</code></td></tr><tr><td>State Hub completion event</td><td><code>org.statehub.workplan.completed</code></td><td><code>org.statehub.workstream.completed</code></td><td><code>STATE-WP-0069</code> T05</td></tr><tr><td>activity-core catalog (custodian-era)</td><td><code>org.statehub.workplan.completed</code></td><td><code>org.workstream.completed</code></td><td><code>CUST-WP-0055</code> T03</td></tr><tr><td>Archived workplan prose</td><td>workplan (when editing)</td><td>historical "workstream" text</td><td>Grandfathered; header note only</td></tr><tr><td>Grandfathered filenames</td><td>—</td><td>paths containing <code>workstream</code></td><td>ADR-001 non-rename policy</td></tr></tbody></table></div>
|
||||
<p><strong>Do not</strong> introduce a bare <code>org.workplan.completed</code> event subject. State Hub uses the <code>org.statehub.*</code> namespace.</p>
|
||||
</section>
|
||||
<section id="event-subjects-normative"><h2>Event subjects (normative)</h2>
|
||||
<div class="scroll"><table><thead><tr><th>Subject</th><th>Status</th><th>Notes</th></tr></thead><tbody><tr><td><code>org.statehub.workplan.completed</code></td><td><strong>preferred</strong></td><td>Emitted on workplan finish; subscribe here</td></tr><tr><td><code>org.statehub.workstream.completed</code></td><td>legacy (metered)</td><td>Dual-published today; retire per legacy-meter</td></tr><tr><td><code>org.workstream.completed</code></td><td>legacy (catalog)</td><td>activity-core custodian-era type; align to State Hub subject</td></tr></tbody></table></div>
|
||||
</section>
|
||||
<section id="agent-and-documentation-rules"><h2>Agent and documentation rules</h2>
|
||||
<ol><li><strong>Write workplan</strong> in instructions, orientation steps, and error messages aimed at humans or coding agents.</li><li><strong>Mention workstream only</strong> in an explicit compatibility footnote, e.g.: > Legacy term: State Hub still exposes <code>/workstreams</code> and <code>workstream_id</code> > aliases until legacy-meter retires them (<code>STATE-WP-0069</code>).</li><li><strong>Leave unchanged</strong> in code or docs when the string is a wire key, route, legacy-meter registry entry, or <code>state_hub_workstream_id</code> frontmatter field.</li><li><strong>Prefer</strong> <code>GET /workplans/</code> and <code>workplan_id</code> in new examples and scripts.</li></ol>
|
||||
<p>Regenerated agent files (<code>state-hub/scripts/update_agent_instruction_files.py</code>) should follow rules 1–2. Templates live under <code>state-hub/scripts/project_rules/*.template</code>.</p>
|
||||
</section>
|
||||
<section id="retirement-rule-unchanged"><h2>Retirement rule (unchanged)</h2>
|
||||
<p>A legacy interface may be removed only when <strong>all</strong> are true:</p>
|
||||
<ul><li>registered in State Hub <code>legacy-meter</code>;</li><li>replacement reference verified;</li><li>no manual hold;</li><li>zero measured calls in the review window.</li></ul>
|
||||
<p>State Hub owns usage evidence; activity-core may run weekly review activities. See <code>state-hub/docs/workplan-terminology-transition.md</code>.</p>
|
||||
</section>
|
||||
<section id="verification"><h2>Verification</h2>
|
||||
<p>Fleet terminology drift is measured with:</p>
|
||||
<pre>python tools/scan_workstream_terminology.py
|
||||
python tools/scan_workstream_terminology.py --repo <slug> --json</pre>
|
||||
<p>Baseline artefact (2026-07-08): <code>docs/evidence/workstream-terminology-baseline-20260708.json</code>.</p>
|
||||
<p>Exit criteria and scan exclusions: <code>CUST-WP-0055</code> T08.</p>
|
||||
</section>
|
||||
<section id="out-of-scope-this-standard"><h2>Out of scope (this standard)</h2>
|
||||
<ul><li>Renaming <code>state_hub_workstream_id</code> in workplan frontmatter.</li><li>Database table or ORM model renames (completed in <code>STATE-WP-0065</code>).</li><li>Rewriting archived workplan bodies in bulk (<code>CUST-WP-0055</code> T07).</li></ul>
|
||||
</section>
|
||||
<section id="references"><h2>References</h2>
|
||||
<ul><li><code>canon/architecture/adr-001-workplans-as-repo-artefacts.md</code></li><li><code>state-hub/docs/workplan-terminology-transition.md</code></li><li><code>state-hub/workplans/STATE-WP-0054-workplan-terminology-transition-legacy-meter.md</code></li><li><code>state-hub/workplans/STATE-WP-0069-workplan-terminology-legacy-retirement.md</code></li><li><code>workplans/CUST-WP-0055-workplan-terminology-fleet-refactor.md</code></li></ul>
|
||||
</section><footer><span>canon-workplan-terminology-fleet · accepted-1 · accepted</span><span>the-custodian · canon/standards/workplan-terminology-fleet_v0.1.md · 4b951be3947f9457cc091a7d359d9232646b4c93</span></footer></main></div></div></html>
|
||||
|
|
@ -5,15 +5,15 @@ Rows: 162
|
|||
## Inventory dispositions
|
||||
|
||||
- `excluded`: 10
|
||||
- `metadata-pending`: 84
|
||||
- `published`: 60
|
||||
- `metadata-pending`: 79
|
||||
- `published`: 65
|
||||
- `unsupported-format`: 8
|
||||
|
||||
## Proposed dispositions
|
||||
|
||||
- `conflict`: 5
|
||||
- `local`: 50
|
||||
- `publish`: 95
|
||||
- `local`: 52
|
||||
- `publish`: 93
|
||||
- `superseded`: 12
|
||||
|
||||
## Front-matter `id` collisions
|
||||
|
|
|
|||
|
|
@ -4868,8 +4868,8 @@
|
|||
"review"
|
||||
],
|
||||
"notes": "",
|
||||
"proposed_disposition": "publish",
|
||||
"review_notes": "Bootstrap protocol.",
|
||||
"proposed_disposition": "local",
|
||||
"review_notes": "Explicitly sensitivity: internal and contains internal budget/legal formation detail. Keep inventoried and off the public Policy Nexus surface.",
|
||||
"source_path": "canon/constitution/bootstrap-protocol_v0.1.md",
|
||||
"source_repo": "the-custodian",
|
||||
"successor": ""
|
||||
|
|
@ -4899,8 +4899,8 @@
|
|||
"review"
|
||||
],
|
||||
"notes": "",
|
||||
"proposed_disposition": "publish",
|
||||
"review_notes": "Estate constitution.",
|
||||
"proposed_disposition": "local",
|
||||
"review_notes": "Custodian-owned but explicitly sensitivity: internal. Keep inventoried and off the public Policy Nexus surface.",
|
||||
"source_path": "canon/constitution/custodian_constitution_v0.1.md",
|
||||
"source_repo": "the-custodian",
|
||||
"successor": ""
|
||||
|
|
@ -4912,22 +4912,19 @@
|
|||
"file_present": true,
|
||||
"frontmatter": {
|
||||
"id": "canon-autonomy-lanes",
|
||||
"last_reviewed": "",
|
||||
"owner": "",
|
||||
"review_interval": "",
|
||||
"revision": "",
|
||||
"status": "active",
|
||||
"last_reviewed": "2026-08-31",
|
||||
"owner": "the-custodian",
|
||||
"review_interval": "6m",
|
||||
"revision": "accepted-1",
|
||||
"status": "accepted",
|
||||
"title": "Autonomy Lanes (Fleet) v0.1",
|
||||
"updated": "2026-07-20",
|
||||
"version": "0.1"
|
||||
},
|
||||
"id_collisions": [],
|
||||
"inventory_disposition": "metadata-pending",
|
||||
"inventory_reason": "In scope; awaits explicit publication addressing and owner/revision/review metadata.",
|
||||
"missing_fields": [
|
||||
"owner",
|
||||
"review"
|
||||
],
|
||||
"inventory_disposition": "published",
|
||||
"inventory_reason": "Published through an explicit publication.json document entry.",
|
||||
"missing_fields": [],
|
||||
"notes": "",
|
||||
"proposed_disposition": "publish",
|
||||
"review_notes": "Autonomy lanes.",
|
||||
|
|
@ -5097,22 +5094,19 @@
|
|||
"file_present": true,
|
||||
"frontmatter": {
|
||||
"id": "canon-contrib-convention",
|
||||
"last_reviewed": "",
|
||||
"owner": "",
|
||||
"review_interval": "",
|
||||
"revision": "",
|
||||
"status": "active",
|
||||
"last_reviewed": "2026-08-31",
|
||||
"owner": "the-custodian",
|
||||
"review_interval": "6m",
|
||||
"revision": "accepted-1",
|
||||
"status": "accepted",
|
||||
"title": "Contribution Convention v0.1",
|
||||
"updated": "",
|
||||
"version": "0.1"
|
||||
},
|
||||
"id_collisions": [],
|
||||
"inventory_disposition": "metadata-pending",
|
||||
"inventory_reason": "In scope; awaits explicit publication addressing and owner/revision/review metadata.",
|
||||
"missing_fields": [
|
||||
"owner",
|
||||
"review"
|
||||
],
|
||||
"inventory_disposition": "published",
|
||||
"inventory_reason": "Published through an explicit publication.json document entry.",
|
||||
"missing_fields": [],
|
||||
"notes": "",
|
||||
"proposed_disposition": "publish",
|
||||
"review_notes": "Contribution convention.",
|
||||
|
|
@ -5492,22 +5486,19 @@
|
|||
"file_present": true,
|
||||
"frontmatter": {
|
||||
"id": "canon-project-repository-flavor",
|
||||
"last_reviewed": "",
|
||||
"owner": "",
|
||||
"review_interval": "",
|
||||
"revision": "",
|
||||
"status": "active",
|
||||
"last_reviewed": "2026-08-31",
|
||||
"owner": "the-custodian",
|
||||
"review_interval": "6m",
|
||||
"revision": "accepted-1",
|
||||
"status": "accepted",
|
||||
"title": "Project Repository Flavor (prj-) v0.1",
|
||||
"updated": "2026-08-09",
|
||||
"version": "0.1"
|
||||
},
|
||||
"id_collisions": [],
|
||||
"inventory_disposition": "metadata-pending",
|
||||
"inventory_reason": "In scope; awaits explicit publication addressing and owner/revision/review metadata.",
|
||||
"missing_fields": [
|
||||
"owner",
|
||||
"review"
|
||||
],
|
||||
"inventory_disposition": "published",
|
||||
"inventory_reason": "Published through an explicit publication.json document entry.",
|
||||
"missing_fields": [],
|
||||
"notes": "",
|
||||
"proposed_disposition": "publish",
|
||||
"review_notes": "prj- flavor.",
|
||||
|
|
@ -5820,22 +5811,19 @@
|
|||
"file_present": true,
|
||||
"frontmatter": {
|
||||
"id": "canon-work-record-types",
|
||||
"last_reviewed": "",
|
||||
"owner": "",
|
||||
"review_interval": "",
|
||||
"revision": "",
|
||||
"status": "active",
|
||||
"last_reviewed": "2026-08-31",
|
||||
"owner": "the-custodian",
|
||||
"review_interval": "6m",
|
||||
"revision": "accepted-1",
|
||||
"status": "accepted",
|
||||
"title": "Work Record Types & Identity (Fleet) v0.1",
|
||||
"updated": "2026-08-23",
|
||||
"version": "0.1"
|
||||
},
|
||||
"id_collisions": [],
|
||||
"inventory_disposition": "metadata-pending",
|
||||
"inventory_reason": "In scope; awaits explicit publication addressing and owner/revision/review metadata.",
|
||||
"missing_fields": [
|
||||
"owner",
|
||||
"review"
|
||||
],
|
||||
"inventory_disposition": "published",
|
||||
"inventory_reason": "Published through an explicit publication.json document entry.",
|
||||
"missing_fields": [],
|
||||
"notes": "",
|
||||
"proposed_disposition": "publish",
|
||||
"review_notes": "Work-record type registry.",
|
||||
|
|
@ -5850,22 +5838,19 @@
|
|||
"file_present": true,
|
||||
"frontmatter": {
|
||||
"id": "canon-workplan-terminology-fleet",
|
||||
"last_reviewed": "",
|
||||
"owner": "",
|
||||
"review_interval": "",
|
||||
"revision": "",
|
||||
"status": "active",
|
||||
"last_reviewed": "2026-08-31",
|
||||
"owner": "the-custodian",
|
||||
"review_interval": "6m",
|
||||
"revision": "accepted-1",
|
||||
"status": "accepted",
|
||||
"title": "Workplan Terminology (Fleet) v0.1",
|
||||
"updated": "2026-07-20",
|
||||
"version": "0.2"
|
||||
},
|
||||
"id_collisions": [],
|
||||
"inventory_disposition": "metadata-pending",
|
||||
"inventory_reason": "In scope; awaits explicit publication addressing and owner/revision/review metadata.",
|
||||
"missing_fields": [
|
||||
"owner",
|
||||
"review"
|
||||
],
|
||||
"inventory_disposition": "published",
|
||||
"inventory_reason": "Published through an explicit publication.json document entry.",
|
||||
"missing_fields": [],
|
||||
"notes": "",
|
||||
"proposed_disposition": "publish",
|
||||
"review_notes": "Fleet workplan terminology.",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"schema_version": 1,
|
||||
"ruled_at": "2026-08-18",
|
||||
"ruled_at": "2026-08-31",
|
||||
"workplan": "PNEX-WP-0003",
|
||||
"note": "T03/T04 overlay. Regenerating the ledger merges these fields onto inventory facts. Kind 1 on a shared front-matter id is also applied automatically.",
|
||||
"note": "T03/T04 overlay, amended by PNEX-WP-0004's Custodian disclosure review. Regenerating the ledger merges these fields onto inventory facts. Kind 1 on a shared front-matter id is also applied automatically.",
|
||||
"rulings": [
|
||||
{
|
||||
"source_repo": "the-custodian",
|
||||
|
|
@ -772,18 +772,18 @@
|
|||
{
|
||||
"source_repo": "the-custodian",
|
||||
"source_path": "canon/constitution/custodian_constitution_v0.1.md",
|
||||
"proposed_disposition": "publish",
|
||||
"proposed_disposition": "local",
|
||||
"conflict_kinds": [],
|
||||
"successor": "",
|
||||
"review_notes": "Estate constitution."
|
||||
"review_notes": "Custodian-owned but explicitly sensitivity: internal. Keep inventoried and off the public Policy Nexus surface."
|
||||
},
|
||||
{
|
||||
"source_repo": "the-custodian",
|
||||
"source_path": "canon/constitution/bootstrap-protocol_v0.1.md",
|
||||
"proposed_disposition": "publish",
|
||||
"proposed_disposition": "local",
|
||||
"conflict_kinds": [],
|
||||
"successor": "",
|
||||
"review_notes": "Bootstrap protocol."
|
||||
"review_notes": "Explicitly sensitivity: internal and contains internal budget/legal formation detail. Keep inventoried and off the public Policy Nexus surface."
|
||||
},
|
||||
{
|
||||
"source_repo": "the-custodian",
|
||||
|
|
|
|||
|
|
@ -54,6 +54,46 @@
|
|||
"subtitle": "A framework for describing, holding and improving multi-tenancy \u2014 including where we are not there yet.",
|
||||
"review_interval": "6m"
|
||||
},
|
||||
{
|
||||
"id": "canon-autonomy-lanes",
|
||||
"source_repo": "the-custodian",
|
||||
"source_path": "canon/standards/autonomy-lanes_v0.1.md",
|
||||
"canonical_path": "standards/autonomy-lanes/v0.1/index.html",
|
||||
"revision_path": "standards/autonomy-lanes/v0.1/revisions/{revision}/index.html",
|
||||
"review_interval": "6m"
|
||||
},
|
||||
{
|
||||
"id": "canon-contrib-convention",
|
||||
"source_repo": "the-custodian",
|
||||
"source_path": "canon/standards/contribution-convention_v0.1.md",
|
||||
"canonical_path": "standards/contribution-convention/v0.1/index.html",
|
||||
"revision_path": "standards/contribution-convention/v0.1/revisions/{revision}/index.html",
|
||||
"review_interval": "6m"
|
||||
},
|
||||
{
|
||||
"id": "canon-project-repository-flavor",
|
||||
"source_repo": "the-custodian",
|
||||
"source_path": "canon/standards/project-repository-flavor_v0.1.md",
|
||||
"canonical_path": "standards/project-repository-flavor/v0.1/index.html",
|
||||
"revision_path": "standards/project-repository-flavor/v0.1/revisions/{revision}/index.html",
|
||||
"review_interval": "6m"
|
||||
},
|
||||
{
|
||||
"id": "canon-work-record-types",
|
||||
"source_repo": "the-custodian",
|
||||
"source_path": "canon/standards/work-record-types_v0.1.md",
|
||||
"canonical_path": "standards/work-record-types/v0.1/index.html",
|
||||
"revision_path": "standards/work-record-types/v0.1/revisions/{revision}/index.html",
|
||||
"review_interval": "6m"
|
||||
},
|
||||
{
|
||||
"id": "canon-workplan-terminology-fleet",
|
||||
"source_repo": "the-custodian",
|
||||
"source_path": "canon/standards/workplan-terminology-fleet_v0.1.md",
|
||||
"canonical_path": "standards/workplan-terminology/v0.1/index.html",
|
||||
"revision_path": "standards/workplan-terminology/v0.1/revisions/{revision}/index.html",
|
||||
"review_interval": "6m"
|
||||
},
|
||||
{
|
||||
"id": "coulomb-estate-architecture",
|
||||
"source_repo": "the-custodian",
|
||||
|
|
|
|||
|
|
@ -794,8 +794,8 @@
|
|||
"source_repo": "the-custodian"
|
||||
},
|
||||
{
|
||||
"disposition": "metadata-pending",
|
||||
"reason": "In scope; awaits explicit publication addressing and owner/revision/review metadata.",
|
||||
"disposition": "published",
|
||||
"reason": "Published through an explicit publication.json document entry.",
|
||||
"source_path": "canon/standards/autonomy-lanes_v0.1.md",
|
||||
"source_repo": "the-custodian"
|
||||
},
|
||||
|
|
@ -830,8 +830,8 @@
|
|||
"source_repo": "the-custodian"
|
||||
},
|
||||
{
|
||||
"disposition": "metadata-pending",
|
||||
"reason": "In scope; awaits explicit publication addressing and owner/revision/review metadata.",
|
||||
"disposition": "published",
|
||||
"reason": "Published through an explicit publication.json document entry.",
|
||||
"source_path": "canon/standards/contribution-convention_v0.1.md",
|
||||
"source_repo": "the-custodian"
|
||||
},
|
||||
|
|
@ -902,8 +902,8 @@
|
|||
"source_repo": "the-custodian"
|
||||
},
|
||||
{
|
||||
"disposition": "metadata-pending",
|
||||
"reason": "In scope; awaits explicit publication addressing and owner/revision/review metadata.",
|
||||
"disposition": "published",
|
||||
"reason": "Published through an explicit publication.json document entry.",
|
||||
"source_path": "canon/standards/project-repository-flavor_v0.1.md",
|
||||
"source_repo": "the-custodian"
|
||||
},
|
||||
|
|
@ -962,14 +962,14 @@
|
|||
"source_repo": "the-custodian"
|
||||
},
|
||||
{
|
||||
"disposition": "metadata-pending",
|
||||
"reason": "In scope; awaits explicit publication addressing and owner/revision/review metadata.",
|
||||
"disposition": "published",
|
||||
"reason": "Published through an explicit publication.json document entry.",
|
||||
"source_path": "canon/standards/work-record-types_v0.1.md",
|
||||
"source_repo": "the-custodian"
|
||||
},
|
||||
{
|
||||
"disposition": "metadata-pending",
|
||||
"reason": "In scope; awaits explicit publication addressing and owner/revision/review metadata.",
|
||||
"disposition": "published",
|
||||
"reason": "Published through an explicit publication.json document entry.",
|
||||
"source_path": "canon/standards/workplan-terminology-fleet_v0.1.md",
|
||||
"source_repo": "the-custodian"
|
||||
}
|
||||
|
|
|
|||
57
tests/test_fetch_sources.py
Normal file
57
tests/test_fetch_sources.py
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
|
||||
ROOT = Path(__file__).parents[1]
|
||||
sys.path.insert(0, str(ROOT / "tools"))
|
||||
from fetch_sources import _archive_url, _request
|
||||
|
||||
|
||||
class FetchSourcesAuthenticationTest(unittest.TestCase):
|
||||
def test_same_origin_request_carries_forgejo_token(self) -> None:
|
||||
request = _request(
|
||||
"https://forgejo.coulomb.social/api/v1/repos/coulomb/policy-nexus",
|
||||
token="test-secret",
|
||||
token_origin="https://forgejo.coulomb.social",
|
||||
)
|
||||
|
||||
self.assertEqual("token test-secret", request.get_header("Authorization"))
|
||||
self.assertNotIn("test-secret", request.full_url)
|
||||
|
||||
def test_cross_origin_request_refuses_source_token(self) -> None:
|
||||
with self.assertRaisesRegex(ValueError, "refusing to send source credential"):
|
||||
_request(
|
||||
"https://example.invalid/coulomb/policy-nexus/archive/main.tar.gz",
|
||||
token="test-secret",
|
||||
token_origin="https://forgejo.coulomb.social",
|
||||
)
|
||||
|
||||
def test_token_and_origin_must_be_configured_together(self) -> None:
|
||||
with self.assertRaisesRegex(ValueError, "must be provided together"):
|
||||
_request(
|
||||
"https://forgejo.coulomb.social/coulomb/policy-nexus",
|
||||
token="test-secret",
|
||||
)
|
||||
|
||||
def test_anonymous_request_has_no_authorization_header(self) -> None:
|
||||
request = _request("https://forgejo.coulomb.social/public/repository")
|
||||
|
||||
self.assertIsNone(request.get_header("Authorization"))
|
||||
|
||||
def test_archive_uses_full_resolved_revision(self) -> None:
|
||||
revision = "a" * 40
|
||||
|
||||
self.assertEqual(
|
||||
f"https://forgejo.coulomb.social/coulomb/policy-nexus/archive/{revision}.tar.gz",
|
||||
_archive_url(
|
||||
"https://forgejo.coulomb.social/coulomb/policy-nexus.git",
|
||||
revision,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -6,6 +6,7 @@ from __future__ import annotations
|
|||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path, PurePosixPath
|
||||
import tarfile
|
||||
import tempfile
|
||||
|
|
@ -13,7 +14,43 @@ import urllib.parse
|
|||
import urllib.request
|
||||
|
||||
|
||||
def _revision(remote: str, branch: str) -> str:
|
||||
def _url_origin(url: str) -> str:
|
||||
parsed = urllib.parse.urlparse(url)
|
||||
if parsed.scheme != "https" or not parsed.netloc or parsed.username or parsed.password:
|
||||
raise ValueError(f"authenticated source URL must use an HTTPS origin: {url!r}")
|
||||
return f"{parsed.scheme}://{parsed.netloc.lower()}"
|
||||
|
||||
|
||||
def _credential_origin(value: str) -> str:
|
||||
parsed = urllib.parse.urlparse(value)
|
||||
if parsed.path not in ("", "/") or parsed.params or parsed.query or parsed.fragment:
|
||||
raise ValueError("credential origin must contain only an HTTPS scheme and authority")
|
||||
return _url_origin(value)
|
||||
|
||||
|
||||
def _request(
|
||||
url: str, *, token: str | None = None, token_origin: str | None = None
|
||||
) -> urllib.request.Request:
|
||||
if bool(token) != bool(token_origin):
|
||||
raise ValueError("source token and token origin must be provided together")
|
||||
request = urllib.request.Request(url)
|
||||
if token:
|
||||
expected_origin = _credential_origin(token_origin or "")
|
||||
if _url_origin(url) != expected_origin:
|
||||
raise ValueError(
|
||||
f"refusing to send source credential outside {expected_origin}"
|
||||
)
|
||||
request.add_header("Authorization", f"token {token}")
|
||||
return request
|
||||
|
||||
|
||||
def _revision(
|
||||
remote: str,
|
||||
branch: str,
|
||||
*,
|
||||
token: str | None = None,
|
||||
token_origin: str | None = None,
|
||||
) -> str:
|
||||
parsed = urllib.parse.urlparse(remote)
|
||||
parts = parsed.path.removesuffix(".git").strip("/").split("/")
|
||||
if parsed.scheme != "https" or len(parts) != 2:
|
||||
|
|
@ -21,7 +58,9 @@ def _revision(remote: str, branch: str) -> str:
|
|||
owner, repo = (urllib.parse.quote(part, safe="") for part in parts)
|
||||
branch_name = urllib.parse.quote(branch, safe="")
|
||||
url = f"{parsed.scheme}://{parsed.netloc}/api/v1/repos/{owner}/{repo}/branches/{branch_name}"
|
||||
with urllib.request.urlopen(url, timeout=30) as response:
|
||||
with urllib.request.urlopen(
|
||||
_request(url, token=token, token_origin=token_origin), timeout=30
|
||||
) as response:
|
||||
revision = json.load(response).get("commit", {}).get("id", "")
|
||||
if len(revision) != 40 or any(char not in "0123456789abcdef" for char in revision):
|
||||
raise ValueError(f"{remote}: could not resolve a clean 40-hex {branch} revision")
|
||||
|
|
@ -31,7 +70,7 @@ def _revision(remote: str, branch: str) -> str:
|
|||
def _archive_url(remote: str, revision: str) -> str:
|
||||
if not remote.startswith("https://") or not remote.endswith(".git"):
|
||||
raise ValueError(f"archive source must be an HTTPS .git URL, got {remote!r}")
|
||||
return f"{remote[:-4]}/archive/{revision[:7]}.tar.gz"
|
||||
return f"{remote[:-4]}/archive/{revision}.tar.gz"
|
||||
|
||||
|
||||
def _extract(archive: Path, target: Path) -> None:
|
||||
|
|
@ -73,7 +112,14 @@ def _extract(archive: Path, target: Path) -> None:
|
|||
output.write(chunk)
|
||||
|
||||
|
||||
def fetch(config_path: Path, destination: Path, policy_revision: str) -> dict[str, object]:
|
||||
def fetch(
|
||||
config_path: Path,
|
||||
destination: Path,
|
||||
policy_revision: str,
|
||||
*,
|
||||
token: str | None = None,
|
||||
token_origin: str | None = None,
|
||||
) -> dict[str, object]:
|
||||
if len(policy_revision) != 40 or any(
|
||||
char not in "0123456789abcdef" for char in policy_revision
|
||||
):
|
||||
|
|
@ -95,10 +141,14 @@ def fetch(config_path: Path, destination: Path, policy_revision: str) -> dict[st
|
|||
continue
|
||||
remote = repository["remote"]
|
||||
branch = repository.get("branch", "main")
|
||||
revision = _revision(remote, branch)
|
||||
revision = _revision(
|
||||
remote, branch, token=token, token_origin=token_origin
|
||||
)
|
||||
url = _archive_url(remote, revision)
|
||||
with tempfile.NamedTemporaryFile(suffix=".tar.gz") as archive:
|
||||
with urllib.request.urlopen(url, timeout=60) as response:
|
||||
with urllib.request.urlopen(
|
||||
_request(url, token=token, token_origin=token_origin), timeout=60
|
||||
) as response:
|
||||
while chunk := response.read(1024 * 1024):
|
||||
archive.write(chunk)
|
||||
archive.flush()
|
||||
|
|
@ -127,8 +177,29 @@ def main() -> int:
|
|||
parser.add_argument("--config", type=Path, default=Path("source-inventory.config.json"))
|
||||
parser.add_argument("--destination", type=Path, required=True)
|
||||
parser.add_argument("--policy-revision", required=True)
|
||||
parser.add_argument(
|
||||
"--token-env",
|
||||
help="environment variable containing a Forgejo repository-read token",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--token-origin",
|
||||
help="sole HTTPS origin to which the source token may be sent",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
lock = fetch(args.config.resolve(), args.destination.resolve(), args.policy_revision)
|
||||
token = None
|
||||
if args.token_env:
|
||||
token = os.environ.get(args.token_env, "").strip()
|
||||
if not token:
|
||||
parser.error(f"source token environment variable {args.token_env!r} is empty")
|
||||
if bool(token) != bool(args.token_origin):
|
||||
parser.error("--token-env and --token-origin must be supplied together")
|
||||
lock = fetch(
|
||||
args.config.resolve(),
|
||||
args.destination.resolve(),
|
||||
args.policy_revision,
|
||||
token=token,
|
||||
token_origin=args.token_origin,
|
||||
)
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,166 @@
|
|||
---
|
||||
id: PNEX-WP-0004
|
||||
type: workplan
|
||||
title: "Publish the first deferred fleet-standards batch and authenticate CI source acquisition"
|
||||
domain: infotech
|
||||
repo: policy-nexus
|
||||
status: active
|
||||
owner: the-custodian
|
||||
topic_slug: policy-nexus
|
||||
created: "2026-08-31"
|
||||
updated: "2026-08-31"
|
||||
depends_on_workplans:
|
||||
- PNEX-WP-0003
|
||||
state_hub_workstream_id: "a4f65253-4aab-5a43-8a19-3d07c11da244"
|
||||
---
|
||||
|
||||
# PNEX-WP-0004 — fleet standards publication and CI source authentication
|
||||
|
||||
## Goal
|
||||
|
||||
Publish the first coherent return from `CUST-IN-0016`: five reviewed,
|
||||
Custodian-owned fleet standards. At the same time, make the scheduled Forgejo
|
||||
candidate build capable of reading private source repositories through a
|
||||
dedicated least-privilege credential rather than anonymous HTTP or an admin
|
||||
token.
|
||||
|
||||
Done means the five standards have permanent current and immutable URLs, the
|
||||
source inventory and ADR-review ledger reflect the Custodian rulings, the
|
||||
retained-history/currency/release gates pass, and the CI workflow fails closed
|
||||
with an actionable error when its dedicated source-read credential is absent.
|
||||
|
||||
## Publication batch
|
||||
|
||||
| id | Source | Address series |
|
||||
| --- | --- | --- |
|
||||
| `canon-autonomy-lanes` | `canon/standards/autonomy-lanes_v0.1.md` | `/standards/autonomy-lanes/v0.1/` |
|
||||
| `canon-contrib-convention` | `canon/standards/contribution-convention_v0.1.md` | `/standards/contribution-convention/v0.1/` |
|
||||
| `canon-project-repository-flavor` | `canon/standards/project-repository-flavor_v0.1.md` | `/standards/project-repository-flavor/v0.1/` |
|
||||
| `canon-work-record-types` | `canon/standards/work-record-types_v0.1.md` | `/standards/work-record-types/v0.1/` |
|
||||
| `canon-workplan-terminology-fleet` | `canon/standards/workplan-terminology-fleet_v0.1.md` | `/standards/workplan-terminology/v0.1/` |
|
||||
|
||||
All five are owned by `the-custodian`, reviewed on 2026-08-31, use revision
|
||||
`accepted-1`, and retain a six-month review interval. Source-owner commit:
|
||||
`the-custodian@4b951be`.
|
||||
|
||||
## Explicit exclusions and deferrals
|
||||
|
||||
- `bootstrap-protocol_v0.1.md` and `custodian_constitution_v0.1.md` declare
|
||||
`sensitivity: internal`; they must not be published on the public surface.
|
||||
- `repo-classification-standard_v1.0.md` remains deferred until its `active`
|
||||
front-matter and body-level `Draft v1.0` statement are reconciled.
|
||||
- `sbom-convention_v0.1.md` remains deferred until its authority and operating
|
||||
model are reviewed against current SBOM Nexus architecture.
|
||||
- The other owner repositories and all five conflict rows stay with
|
||||
`CUST-IN-0016`; they are not pulled into this bounded batch.
|
||||
|
||||
## CI credential boundary
|
||||
|
||||
`fetch_sources.py` may accept a Forgejo token only through an environment
|
||||
variable or an explicit caller-provided value. It sends the token solely to the configured
|
||||
Forgejo origin over HTTPS, never prints it, never writes it to `source-lock`,
|
||||
and refuses a credential for a remote on another origin. The workflow uses a
|
||||
dedicated `FORGEJO_SOURCE_TOKEN` secret. Registry credentials remain confined
|
||||
to registry login and are not reused for repository reads.
|
||||
|
||||
Provisioning the secret is an external Custodian/platform handoff: the token
|
||||
must have organization-private repository read access and no package write,
|
||||
admin, cluster, or deployment authority. Code and tests may land before that
|
||||
secret is installed; the scheduled workflow must fail closed until it is.
|
||||
|
||||
## Tasks
|
||||
|
||||
### T01 — Owner review and disclosure gate
|
||||
|
||||
```task
|
||||
id: PNEX-WP-0004-T01
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "2301c729-841b-5c5c-a9dd-aa5d4390c36b"
|
||||
```
|
||||
|
||||
Review the Custodian slice, add truthful publication metadata to the five
|
||||
public fleet standards, and record the internal/deferred sources explicitly in
|
||||
`CUST-IN-0016`.
|
||||
|
||||
Completed 2026-08-31 in `the-custodian@4b951be`. No normative body text was
|
||||
changed.
|
||||
|
||||
### T02 — Register and audit the five standards
|
||||
|
||||
```task
|
||||
id: PNEX-WP-0004-T02
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "a4378f0b-cf58-5dac-9f8e-2a69b07ff6e3"
|
||||
```
|
||||
|
||||
Add five explicit `publication.json` entries, refresh the source inventory and
|
||||
review ledger, and ensure the two internal constitution sources are never
|
||||
classified as publishable output.
|
||||
|
||||
Completed 2026-08-31. The explicit registry contains 65 documents; the source
|
||||
audit reports 65 published and 79 metadata-pending sources. The two internal
|
||||
constitution records are ruled `local` and have no publication address.
|
||||
|
||||
### T03 — Authenticate private source acquisition
|
||||
|
||||
```task
|
||||
id: PNEX-WP-0004-T03
|
||||
status: done
|
||||
priority: high
|
||||
state_hub_task_id: "e0c0fa67-5a90-5990-a4e9-35e517816a7d"
|
||||
```
|
||||
|
||||
Add same-origin Forgejo-token support to `fetch_sources.py`, cover header,
|
||||
redaction, and cross-origin refusal behavior with unit tests, and pass only the
|
||||
dedicated source token from the Forgejo workflow. Authenticate the workflow's
|
||||
own archive download as well as every declared owner-repository fetch.
|
||||
|
||||
Completed 2026-08-31. Five authentication-boundary tests cover same-origin
|
||||
header injection, cross-origin refusal, paired token/origin configuration,
|
||||
anonymous mode, and full-revision archive addressing. The complete 22-test
|
||||
suite passes. Installing the read-only Forgejo Actions secret remains the
|
||||
credential-owner handoff and is not a code-completion gate.
|
||||
|
||||
### T04 — Build and publish the immutable candidate
|
||||
|
||||
```task
|
||||
id: PNEX-WP-0004-T04
|
||||
status: progress
|
||||
priority: high
|
||||
state_hub_task_id: "a6f789ea-5d90-55cf-b67b-5cf401b81e66"
|
||||
```
|
||||
|
||||
Run `make check`, retained-history build, currency, and release verification.
|
||||
Publish the OCI candidate and record its image, publication-manifest,
|
||||
source-inventory, and source-set digests.
|
||||
|
||||
2026-08-31: the local retained-history build, release verifier, and currency
|
||||
gate pass for all 65 documents. Pre-publication identities are publication
|
||||
manifest `c54efb4226f964b8af4e37cebcccda6d3becaa5db1cd9465c166392d2a87c842`,
|
||||
source inventory
|
||||
`b061ebc593f8e6353929eb795663d66278eca094429f139b6060e7b236e3d8d8`, and
|
||||
source set
|
||||
`7e0f0ee3fdf3bcdc8d34e7fc9ba12304ba84864b06c63e9226324e6aa0ea4e7f`.
|
||||
|
||||
### T05 — Promote, smoke, and close
|
||||
|
||||
```task
|
||||
id: PNEX-WP-0004-T05
|
||||
status: todo
|
||||
priority: medium
|
||||
state_hub_task_id: "07c9c18d-95cf-5b09-940a-40b5ff5828a7"
|
||||
```
|
||||
|
||||
Update the paired `rapp-policy-nexus` and `railiance-apps` bindings, pass
|
||||
server-side admission, deploy atomically, and verify all five current and
|
||||
immutable `accepted-1` URLs before closing this workplan.
|
||||
|
||||
## Residuals
|
||||
|
||||
- Secret provisioning and rotation remain with the credential owner surfaced
|
||||
by `warden route`; no token value enters this repository or State Hub.
|
||||
- `CUST-IN-0016` remains open for 26 other-owner metadata returns, two
|
||||
substantive Custodian reviews, and five owner conflict rows. The two internal
|
||||
constitutions are explicit local/excluded outcomes, not publication backlog.
|
||||
Loading…
Add table
Add a link
Reference in a new issue