Skip to content

writ repo remove leaves the clone it made in the writ-owned home #792

Closed

Description

@David-Noble-at-work

Feature: #463 — writ command surface: layers, segments, adoption.

writ repo add <layer> <repository-url> clones into the writ-owned home, XDG_DATA_HOME/devlore/writ/repos/<layer>.
writ repo remove <layer> drops the registration and leaves that clone behind. The next add of the same
layer from a URL then finds the directory occupied, and the user is cleaning up writ’s own state by hand.

Ruled 2026-09-04: a clone writ made in its own home is writ’s to remove. Unregistering a layer removes
the registration and the writ-owned clone, and says so. A working tree the user registered by path — theirs,
anywhere else on disk — is never touched; the registration alone goes. The same distinction governs set
replacing a registration (#791): the displaced writ-owned clone is removed, a displaced user path is left
alone.

The verbs become set and unset in #791; this fix rides on whichever spelling lands first. Both are lanes of
#887 (schedule) — #791 is lane 8, this is lane 9.

The record, ruled 2026-09-18

Ownership is not narration: it reaches stdout as a field, so a script and a --dry-run can both read it. The
shape is #791’s, and unset emits:

{
  "layer": "personal",
  "state": "unregistered",
  "previous": {
    "source": "[email protected]:me/personal.git",
    "root": "/Users/me/.local/share/devlore/writ/repos/personal",
    "owner": "writ"
  }
}

previous.owner is the whole ruling: writ means the tree at previous.root was removed with the
registration, user means only the registration went. There is no separate removed field — writ clones only
into <data home>/devlore/writ/repos/<name>, so a removed clone is always previous.root.

--dry-run emits the same record and does nothing, which is how a caller learns what would go.

Acceptance

  • unsetting a layer registered from a URL removes XDG_DATA_HOME/devlore/writ/repos/<layer> and narrates it
  • unsetting a layer registered by path removes the registration only, asserted
  • the record carries previous.root and previous.owner, and --dry-run emits it without removing anything
  • the guide docs/guides/writ/repositories.md says which clones writ owns and removes

Activity

  1. David-Noble-at-work commented on Sep 14, 2026

    @David-Noble-at-work
    ContributorAuthor

    A second route to the same orphan, observed 2026-09-13 on danoble-ud24-1.local.

    This issue records the clone left behind by repo remove. The same orphan arrives without any remove at all,
    because repo add clones before it validates:

    $ writ repo add base [email protected]:NobleFactor/noblefactor-ops.git
    Cloning into '/home/david-noble/.local/share/devlore/writ/repos/base'...
    Error: layer base is already registered; run 'writ repo remove base' first
    

    The clone is complete and unreferenced; the registration never happened. On that machine it was
    #840's phantom registration that triggered the refusal,
    but any refusal after the clone does the same thing.

    Whichever spelling lands, set or add, the validation belongs before the network operation: a registration
    that will be refused should be refused before anything is written to disk. That is the cheaper half of the same
    ruling this issue already makes about ownership of a writ-owned clone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Area:CLICommand-line interfaceEpic:WritDeploymentwrit deployment: layers, adoption, and driftThread:WritRepoa layer points where you saybugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions