Skip to content

shape-doctor.py: the members row calls a beside-the-holder repository the working clone on its project id alone, where the family's own verifier also requires the origin #146

Closed

Description

@brettheap

Lane: openreposhape-2 (openRepoShape-2)

What is wrong. shape-doctor.py's is_this_member (shape-doctor.py:1969)
decides that the directory beside a family holder IS this member on the
strength of project.yaml alone: it is a git repository, its manifest is a
project-manifest, and its id (or, with no id in the row, its name)
matches the family's row. It never looks at the clone's origin.

The family's OWN verifier asks two questions, not one.
templates/family-root/scripts/siblings.py:405-437
(verify_sibling) refuses a clone whose origin is not the row's
repository:/url with WRONG ORIGIN before it compares the project id,
and refuses a matching origin with a different id as WRONG PROJECT — "ONE
definition of 'is this the right clone', used by the placement half and by the
--make dispatch", as its docstring puts it.

So a fork, a stale clone of a renamed repository, or any copy of the same
project from a different origin sitting at ../<Project> is reported by the
doctor as working_clone, and the members row then says a working checkout
is beside the holder when make siblings would call that same directory
WRONG ORIGIN and refuse to touch it. The report and the tool disagree about
the same directory, which is the one thing the doctor is written not to do —
"Every row is somebody else's check."

is_this_member's own docstring already claims the two are the same question:
"scripts/siblings.py::verify_sibling asks the same question before it will
touch a directory, and for the same reason". Today that claim is half true.

Found by Copilot on PR #142 (a pure python:S3776 refactor of five other
functions, where is_this_member is byte-identical); left alone there under
that PR's "behaviour byte-identical" law rather than fixed in a refactor.

What would fix it. Ask the origin question too, in the doctor's own
read-only way:

  • compare the sibling's git remote get-url origin against the member row's
    repository: (and .gitmodules' url for the mount, which is what
    siblings.py resolves first), with the same normalization same_repository
    uses — .git, a trailing /, and the scp-vs-url spellings must compare
    equal, or a family whose rows are spelled one way and whose clones the other
    would go from a false positive to a false negative;
  • keep it a REPORT and never a refusal: the row would say the sibling is a
    clone of something else rather than counting it, and the verdict stays
    whatever it is today for a member with no working clone (an ok row — the
    workstation layout is not a compliance fact);
  • the normalization lives in the family template today and shape-doctor.py
    imports nothing from templates/, so the fix has a shape decision in it:
    either a small local normalizer with the rule written down beside it, or
    moving same_repository somewhere both may import (it is also wanted by
    scripts/family.py);
  • a regression test in tests/test_shape_doctor.py beside
    test_an_unrelated_repository_beside_the_holder_is_not_the_member: a
    sibling carrying the SAME project.yaml id with a DIFFERENT origin, which
    passes today and must not.

Activity

  1. brettheap commented on Sep 12, 2026

    @brettheap
    ContributorAuthor

    (lane openreposhape-2 (openRepoShape-2), 2026-09-12T15:52Z) CLAIMED — session 9c6378ea, on Brett Heap's word 'fix 146'. Branch fix/doctor-member-origin-like-siblings, worktree ~/projects/openRepoShape--i146-member-origin on Eagle, from origin/main 57ddeac. Scope: is_this_member asks the origin question too — the sibling's git remote get-url origin against the .gitmodules url for the mount and the row's repository:, through a normaliser that mirrors siblings.py::same_repository (with a parity test over both), so the members row stops calling a fork or a stale clone the working clone; it stays a report, never a refusal.

  2. brettheap commented on Sep 12, 2026

    @brettheap
    ContributorAuthor

    (lane openreposhape-2 (openRepoShape-2), 2026-09-12T16:2xZ) PULL REQUEST OPEN: #147 (head ef0e206).

  3. brettheap commented on Sep 12, 2026

    @brettheap
    ContributorAuthor

    (lane openreposhape-2 (openRepoShape-2), 2026-09-12T18:33:34Z) MERGED — #147 → 5c63116 (squash), on Brett Heap's word 'go, fan out on all of it, hold the doctor refactor'. shape-doctor.py: the members row asks the origin question the family's own verifier asks — the sibling's git remote get-url origin against the url the holder mounts the member from (.gitmodules first, family.yaml repository: second, a relative ../Repo.git resolved against the holder's remote), so a fork or a stale clone beside the holder is reported as a clone of something else instead of counted as the working clone; a report, never a refusal; credentials redacted from everything stored or printed; the shared rule lives in the non-pinned shape_materialize.py mirroring siblings.py, bound by a parity test over 24 url pairs; four Copilot/Codex rounds, six real findings taken, one (case-folding of filesystem paths) declined and filed as #149; 1147 passed / 1 skipped; no pinned file. Object complete.

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