Repository navigation
repo set and unset replace add and remove, a clone takes git's name, and a group refuses a verb it does not have - #898
Merged
Conversation
… it does not have A layer has exactly one registration, so registering one that is registered re-points it rather than failing: the verb is set, the vocabulary config set and config unset already use for a keyed value. unset is idempotent. set to the root a layer already has narrates unchanged. Every refusal precedes the clone, where add cloned first and refused after. add, remove, rm and ls are gone, not aliased. The record says what changed. source is the URL writ would fetch from -- the upstream's remote, else origin, else empty -- and root is where writ reads; owner says whose tree it is, and previous carries what was displaced or removed, so a script reads on stdout what narration says on stderr. repo list carries source and owner on every row. A clone writ made goes with its registration. unset removes it and says so; a set that re-points elsewhere removes the one it displaces; a tree registered by path is never touched. --dry-run emits the record and does nothing. Removal passes a guard that decides from the path, not from the record. A group refuses a verb it does not have. Cobra checks unknown commands at the root alone and abandons a runless group before validating its arguments, so writ repo add exited 0 and printed help with add retired -- as did every unknown verb under every group in writ, lore and star. Each program now validates the command line before executing it, using cobra's exported Find and its own NoArgs, so the message is cobra's by construction and exits 64 through the mapping §9 already had. No group gains a RunE; invariant 7 stands. §3 states the rule. Closes #791 Closes #792 Closes #897
This was referenced Sep 20, 2026
… one repo set <layer> <url> cloned into repos/<layer>: three directories named base, team and personal, whatever repositories they held. The clone now takes the name git clone would give it -- the last path component with a trailing slash and a .git suffix stripped -- so noblefactor-ops.git lands at repos/noblefactor-ops and the directory says which repository it holds. Two layers whose repositories share a name are refused, naming both, before anything is cloned. A URL that yields no name is refused as git refuses it. owner is unaffected: the clone is still under the writ home. The layer-journey scenario, skipped on develop for want of repo set, ran on this pull request's first CI and asserted #793 in the same step as #791. The scenario is the ruled interface; the code now follows it, and make test-scenario is in the pre-flight, where the first run left it out. Closes #793
This was referenced Sep 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lanes 8 to 11 of #887.
repo setandunset(#791) — a layer has oneregistration;
setre-points it,unsetis idempotent, an unchangedsetsays so, every refusal precedesthe clone, and the retired spellings are gone rather than aliased. The record carries
source,root,owner,branchandprevious.—
unsetand a displacingsetremove it and say so; a tree registered by path is never touched;--dry-runemits the record and does nothing. Removal passes a guard that decides from the path.forward from #894 by ruling of 2026-09-19) — a URL
without a destination clones to
repos/<repository>, neverrepos/<layer>; two layers resolving to one nameare refused naming both, before the clone; a URL that yields no name is refused.
— every program validates the command line before executing it, so
writ repo addand every unknown verbunder every group exit 64 with cobra's own message instead of printing help at exit 0. No group gains a
RunE; §14 invariant 7 stands; §3 states the rule.Test plan
make checkgreen;make test-scenariogreen — the layer-journey scenario is writ names a cloned repository by its layer; it should name it the way git clone does #793's end-to-end test,and its absence from the first commit's pre-flight is why the first CI run was red
repo addrefused withunknown command "add" for "writ repo";listshows sourceand owner on the real registrations;
setto the same root saysunchangeddanoble-ud24-1.local(linux/arm64), snapshotted first:unsettwice per layer — the first removeswrit's clone, #792 live;
setby URL re-clonesbase and team where "already exists" had blocked them the day before, and says
unchangedthe secondtime;
setby path,unchanged; personal by path to~/Workspace/Personal, owneruser, source fromits
origin. Baredeployexits 64 (#843); areal deploy stops at
file.mkdir(#822), as on2026-09-18 — not this PR's;
upgradeexits 0danoble-wd11-3.local: carried to the next PR's sequence by ruling of 2026-09-19 — the host disk isfull (22 GB free of 3.7 TB) and a snapshot of the running 32 GB machine does not fit.
C:\Users\david-noble\writ-e2e.ps1carries the sequence in the new verbsTime
Computed by the algorithm of noblefactor-ops#188 at merge.