Skip to content

Family workstation layout: a plain <Family>/ folder holding the holder and the members' working clones — family.py init lands there, the scaffold learns --family, the holder gains a siblings utility that warns and never moves #76

Closed

Description

@brettheap

Lane: xfactory-2 (xFactory-2)

Governing record for a workflow change: the family's WORKSTATION LAYOUT — a plain parent folder named after the family, holding the holder clone and the members' working clones as siblings — becomes something the tooling places and checks, never something it moves. Design only at this stage; nothing here is claimed for authoring yet.

Where this comes from

The ruling that created families (Brett Heap, 2026-09-04): "InkRouter is only something that can download all the others easily? like a holder FOLDER and some utilities for the family of services." The implementation made the holder a REPOSITORY that pins member assembly roots as submodules under members/. The plain folder in the ruling's words was never written down — and it exists anyway, arranged by hand:

~/projects/InkRouter/                 a plain folder, not a git repository
  InkRouter/                          the holder (InkRouter/InkRouter): family.yaml, members/IRRS, members/IRSS pinned + detached
  IRRS/                               working clone of InkRouter/IRRS, on main — where the lanes work
  IRSS/                               working clone of InkRouter/IRSS, on main
  IRRS-worktrees/…                    a linked worktree of IRRS
  session-handoff-2026-09-08-lane-*.md   lane handoffs (lane-collision-protocol Rule 4's estate folder)

Two copies of each member on disk is correct and intended: the holder's members/<Project> is a pinned, detached checkout for make bootstrap and make validate; development happens in the sibling clone on its tracking branch, and the family is bumped to follow. Nothing documents this, and the first question a reader asks — "is InkRouter/InkRouter the family, and what is the parent folder?" — was asked today (2026-09-09).

What the tooling does today

  • scripts/family.py init materializes the holder in a TEMP directory unless --work-dir is passed (work_root / family), so the person arranges the folder afterwards by hand.
  • setup.sh / setup-project.py land a new project beside where the person stands (--into = invocation directory, setup.sh self-bootstrap clones the new project into /tmp/<Project>: PARENT defaults to .. of the TEMPORARY checkout #39). No family awareness: grep -i family setup-project.py finds nothing.
  • The holder template (templates/family-root/) has bootstrap.py and validate-family.py. There is no utility that produces the working clones beside the holder — the "download all the others easily" of the ruling is answered only by submodules inside the holder.

The proposal

Place at clone time; check afterwards; never move.

  1. family.py init gets a real landing spot. Default: create <into>/<Family>/ where the person stands and clone the holder INSIDE it, at <Family>/<Family> — the same "lands where you were standing" rule setup.sh self-bootstrap clones the new project into /tmp/<Project>: PARENT defaults to .. of the TEMPORARY checkout #39 gave projects. --work-dir stays as the override. Refuse (no --force) if <Family>/<Family> exists and is non-empty, as today.
  2. The scaffold learns --family <Name>. openRepoShape IRTS --org InkRouter --family InkRouter lands the new project at <Family>/IRTS, creating <Family>/ if absent, and the "next commands" block ends with the family.py add line. Detection, advisory only: when the invocation directory is <X>/ and <X>/<X>/family.yaml exists with name: <X>, the plan says "you are standing in the family folder; the project lands beside the holder" — no flag needed, nothing else changes.
  3. The holder gains the missing family utility. A Makefile target in templates/family-root/ (name to decide — make siblings? make workstation?) that, for each row in family.yaml, clones the member as a standalone working copy at ../<Project> on its tracking branch, idempotently (an existing clone is fetched, never reset), and prints the layout. Creates nothing on GitHub; needs the same read credential make bootstrap needs. When the holder's parent folder is NOT named <Family>, it WARNS and prints the mv for the human to run — the doctor pattern, not a mover. It never moves anything itself.
  4. The layout is documented in the family-root README (and the openRepoShape README's Families section): the plain folder, the two copies and which one you work in, the doubled <Family>/<Family> name and why it is kept, and where handoff files live.

Deliberately NOT proposed

A setup.sh in the holder that checks whether it is under a same-named folder and, if not, creates that folder and MOVES the checkout there. It relocates the directory out from under the shell, editors and every agent lane standing in it; it breaks linked worktrees, whose .git files carry absolute paths (~/.agents/AGENTS.md calls stale worktree pointers the canonical symptom); and it is the one thing this standard refuses everywhere else — an act done by surprise, where every refusal today names what to run instead. The warning-plus-mv in (3) gives the same outcome with the human's hand on it.

Open decisions

  • The target's name in (3), and whether it also belongs in scripts/family.py (run from a checkout of the standard) so it works before the holder is cloned.
  • Whether --family in (2) should also be honoured by native-Windows setup-project.py (it should; same flag, same landing rule).
  • Keep the doubled <Family>/<Family> clone name (recommended: the repository keeps its name and family.yaml disambiguates) or clone the holder under another local name.

Reach

Changes land in openRepoShape: scripts/family.py, setup-project.py (+ setup.sh/openRepoShape pass-through), templates/family-root/{Makefile,README.md,scripts/}, README, AGENTS.md, tests. Existing holders — InkRouter/InkRouter today — take the template additions through update-shape.py check / apply --add <path>, per file, on the human's word. Nothing changes for a project in no family.

🤖 Generated with Claude Code

Activity

  1. brettheap commented on Sep 9, 2026

    @brettheap
    ContributorAuthor

    Companion: #77 — continuing in-flight feature work on another workstation (park/resume over pushed branches, a per-user workspace manifest in a repository the person owns, handoffs that travel). Its point 5 makes the siblings utility proposed here the front half of rebuilding a whole estate on a fresh machine, so the two should be ruled on together.

  2. brettheap commented on Sep 9, 2026

    @brettheap
    ContributorAuthor

    RULING for the family workstation layout (this issue), ANY lane — Brett Heap, 2026-09-09, walked through by lane xfactory-2 (xFactory-2) as multiple choice; each answer below is Brett's.

    1a. The holder's target is make siblings. It clones each family.yaml member as a working copy beside the holder, on its tracking branch, idempotently; warns and prints the mv when the parent folder is not <Family>; never moves anything.
    1b. One implementation, two entry points. The utility lives in scripts/family.py in openRepoShape so it works before a holder is on disk; the holder's Makefile target calls the copied script. No second code path.
    2. --family <Name> is honoured by setup-project.py, so native Windows gets it by the same flag and the same landing rule as setup.sh and the openRepoShape command.
    3. The doubled <Family>/<Family> layout stands. The holder clone keeps its repository name inside the family folder; family.yaml disambiguates; the README documents it.

    Unchanged from the body: family.py init lands at <into>/<Family>/<Family>; the scaffold detects a family folder and says so in the plan; nothing ever moves a checkout.

    Rule 1 still decides who executes: claim here before authoring. Companion rulings on #77.

  3. brettheap commented on Sep 9, 2026

    @brettheap
    ContributorAuthor

    CLAIMED — lane xfactory-2 (xFactory-2), session harness 47c80b53-25d0-407b-8e19-432e9316bf61, 2026-09-09T15:40Z, for the whole of this issue as ruled above (RULING of 2026-09-09T15:16Z), in two pull requests: (A) the family side — family.py init landing at <into>/<Family>/<Family>, make siblings implemented once in templates/family-root/scripts/ and reached from family.py siblings, the holder template and docs — branch feat/family-siblings-and-init-landing; (B) the scaffold side — --family <Name> in setup-project.py (so Windows too), pass-through in setup.sh/openRepoShape, family-folder detection in the plan, docs — branch feat/scaffold-family-flag. Brett Heap's word, 2026-09-09: "claim 76 and start on it".

    Reads before claiming:

    1. Comments on this record: the Continuing in-flight feature work on another workstation: park/resume over pushed branches, a per-user workspace manifest in a repository the person owns, and handoffs that travel (companion to #76) #77 cross-reference and the RULING, both this lane's. No other claim.
    2. gh pr list --repo opensoft/openRepoShape --state open: none. --state all --search 'siblings OR "--family" OR "family folder"': only merged history (v0.4: spec-only adoption seeds the empty leg; the FAMILY shape (a holder that pins member assembly roots) #16 introduced the family shape; adopt execute and family init set the xf-project-<id> topic, as the scaffold does #24, update-shape.py: the apply commit names the root's manifest, not project.yaml #47, update-shape.py: the no-shape refusal names the kind's manifest validator #52 touched family.py), nothing on this object.
    3. git ls-remote --heads origin | grep -i -E 'sibling|family-folder|scaffold-family|init-landing|076': none.
  4. brettheap commented on Sep 9, 2026

    @brettheap
    ContributorAuthor

    (lane xfactory-2 (xFactory-2), 2026-09-09T16:20Z) PULL REQUESTS OPEN for the claim above: slice (B) the scaffold side — #78 (feat/scaffold-family-flag, head c59c000); slice (A) the family side — #79 (feat/family-siblings-and-init-landing, head 1c094bd). The two grow README.md, AGENTS.md and the hygiene size caps at the same lines; whichever lands second is rebased by this lane before merge. docs/handbook.html lags the README after #79 and is a follow-up, not part of this claim.

  5. brettheap commented on Sep 9, 2026

    @brettheap
    ContributorAuthor

    (lane xfactory-2 (xFactory-2), 2026-09-09T16:51Z) MERGED — both slices of the claim above, squash: #78 (the scaffold side, --family) → 0170edd; #79 (the family side, family.py init landing + make siblings) → b6df51b. Object complete. Follow-ups NOT part of this claim: docs/handbook.html lags the README's Families section; the existing holder InkRouter/InkRouter takes scripts/siblings.py through update-shape.py check → apply --add scripts/siblings.py on Brett's word.

  6. brettheap commented on Sep 9, 2026

    @brettheap
    ContributorAuthor

    Closed on Brett Heap's word, 2026-09-09: "close 76". Rulings recorded above; both PRs merged (see the MERGED comment).

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions