Repository navigation
writ adopt carries the platform (--platform <token>) and leaves a deployment record: its graph carries the files annotation and its trace appends to the current lifetime #931
Description
Epic: #451 · Feature: #762 The writ lifecycle surface · Schedule: #916, lane 14, PR A · Waits on: #922 (lane 1)
The ruling, 2026-09-23
An adopted file is deployed: after writ adopt, the record says so, reconcile says linked, and the next
deploy recognizes the link as writ's own. Adopt copies content into a project location within a scope, in one of
the three layers, and it must carry platform information: the caller names the platform label, and the file
lands in the suffixed project directory the deploy walk reads.
Today
writ adopt [--layer personal|team|base] --project <name> <item>... moves each item to
<layer>/<scope>/<project>/<rel> and links it back, inferring the scope (Home or System) from the item's location,
and runs each scope's adoptions as one execution graph whose trace persists. Two gaps:
- No platform. Every adoption lands in the platform-neutral project directory.
common.Darwin,
noblefactor-ops.Linux.Debian,personal.Windowscannot be targeted. - The trace is not a deployment record. Adopt's graph origin carries no
filesannotation (target, source,
action, layer, project, scope), which is whatreadback.Foldreads to know what a run left. So an adopted link is
invisible toreconcile, and the nextdeployunderstoprefuses it as foreign.
The change
--platform <token>, optional. The vocabulary isplatform.Token's --Darwin,Windows,Linux.Debian,
Linux.Fedora, ... -- plusUnix; anything else is a usage error (64), so a typo cannot mint a suffix the walk
never reads. The destination becomes<layer>/<scope>/<project>.<token>/<rel>; absent, the neutral directory as
today.- The graph carries the
filesannotation deploy's carries, one entry per adopted file: target (the original
location, now the link), source (the project location), actionfile.link, layer, project, scope, and
target_root. The graph is built and run as today; the trace it leaves is then a deployment record the fold
reads exactly as it reads a deployed link. - The trace appends to the current lifetime (deploy replaces the record: readback.Fold is bounded to the current lifetime, one writ deploy invocation across scopes #922): adopt is a write into the current deployment. With no
current lifetime, adopt refuses with not-found (66): there is no deployment to adopt into. - Scope inference uses the scope set of the platform (--scope, multi-valued and writ-only, replaces the inert --target: absent means every scope defined on this platform; Home and System are well known, Windows adds ProgramFiles and ProgramData, and writ.scopes adds the rest #926 once it lands): a Windows item under
%ProgramData%
infersProgramData.
Acceptance
-
--platform <suffix>lands the file under<layer>/Home/<project>.<suffix>/, the suffix in the segment vocabulary (ruled 2026-09-23);--platform Ubuntuis a usage error (64) naming the vocabulary:TestAdopt_Platform, both VMs - after an adopt,
reconcilereports the linklinkedand a deploy understopaccepts it:TestAdopt_LeavesADeploymentRecord, both VMs (2026-09-23) - the adopt's trace is in the current lifetime's runs (both VMs: the lifetime's last run is
adopt); with no current lifetime, adopt exits 66 (RequireCurrentLifetime, deploy replaces the record: readback.Fold is bounded to the current lifetime, one writ deploy invocation across scopes #922) - the
writ adoptLong and example document--platformand the vocabulary - both VMs: adopt one file with the platform's own suffix,
reconcilelinked,deployaccepted, undone (2026-09-23)
Plan and design documents
| Kind | Document |
|---|---|
| Plan | a lane plan arrives with the branch (PR A, beside #922) |
| Design | 10-command-line-interface.md, 5.1-reconciliation.md, docs/plans/extract-starlark-from-op/phase-8/writ-adopt-command.md |
Landed 2026-09-23 (lane 14, PR A)
One chain per item and the segment vocabulary, ruled 2026-09-23. Two findings on the way: a graph holding a
flow.choose does not load back (#939), so the existing-destination guard runs before the graph; and adopt had never
worked on a real install, because a registered layer is a symlink and the confined run root refused to write through
it -- the layer path now resolves through its symlink.
Activity
writ adopt carries the platform and leaves a deployment record
Deploy replaces the record: the lifetime in the store, reconcile's si…
David-Noble-at-work commentedon Sep 24, 2026
Landed in PR #940 (merged 2026-09-24T06:13:59Z). The pull request body carried no closing keyword, so this is closed by hand.
docs(lifecycle): lifetimes are generations: writ follows git and Nix
feat(writ): the operations honor --scope, and a scoped deploy keeps t…