Repository navigation
AGENTS.md, README and scaffold-project.py --help say nothing of the scaffold's two path-collision refusals (scaffold-leg-path-collides, scaffold-pin-collides) or that spec, code and shape cannot be pinned, so a human or agent can learn of them only by hitting them #288
Description
Lane: openreposhape-4 (openRepoShape-4)
Found by this lane's adversarial review of the #241 fix branch (fix/scaffold-pin-product-collisions, PR #256, head a25c2e1; its nit N4), verified on main 39ac59c (the leg-path half by running the refusal, the docs half by grep), and re-checked by grep on main c3a9645 after #256 landed: neither refusal code appears in AGENTS.md, README.md or docs/cli.md, --pin's help still ends "Repeatable." (scaffold-project.py:315), and --spec-path / --code-path still have no help= (:296-297). The other line numbers below are on 39ac59c. It is a docs gap and changes no behaviour. Not claimed.
What is wrong. Two refusals protect the scaffold from dying after both legs are pushed, and neither is in a document:
scaffold-leg-path-collides(scaffold-project.py accepts a leg path that collides with a path the shape writes (--spec-path contracts,--code-path project.yaml), creates all three repositories and pushes both legs, then dies: #172's shape half on the scaffold side #197, on main as b538015):--spec-path/--code-paththat is, holds or lies inside a path the shape writes into the assembly root.git diff b538015^ b538015 --stattouches no.mdfile.scaffold-pin-collides(scaffold-project.py--pin spec@<sha>(orcode@,shape@, or two--pins whose products differ only by case) passes--dry-run, then creates all three repositories, pushes both legs and dies withREFUSED materialize-collision, because the pin'scontracts/<product>-pin.yamlis a file the shape already writes #241, PR scaffold-project.py: a--pinwhose file the shape writes itself (spec,code,shape, any case, owner or not) or another--pinwrites (openGlassandOpenGlass, or one product twice) is refused before anything is created, under--dry-runalike, so--pin spec@<sha>no longer plans and then makes three repositories to die in the materializer, and a repeated pin is no longer dropped without a word (#241) #256, landed as c3a9645): a--pinwhose product lowercases tospec,codeorshape(the shape writescontracts/<product>-pin.yamlfor those three itself), or two--pins of one product (one file holds one pin).
What a reader has today, on 39ac59c:
- AGENTS.md "Scaffolding a project that DECLARES descent" (AGENTS.md:166-183) says only that the pin "writes
contracts/openglass-pin.yamlbeside the manifest". README's neutral-pin text (README.md:656 and :695) says nothing that is false, and nothing about either refusal. --spec-pathand--code-pathhave nohelp=at all (scaffold-project.py:277-278;docs/cli.md:276-277are bare lines), and neither flag appears in AGENTS.md or README (grep -n "spec-path\|code-path" AGENTS.md README.mdfinds nothing).--pin's help ends "Repeatable." (scaffold-project.py:296,docs/cli.md:293). That is the sentence an operator reads before passing--pin openGlass@$A --pin openGlass@$B, which scaffold-project.py: a--pinwhose file the shape writes itself (spec,code,shape, any case, owner or not) or another--pinwrites (openGlassandOpenGlass, or one product twice) is refused before anything is created, under--dry-runalike, so--pin spec@<sha>no longer plans and then makes three repositories to die in the materializer, and a repeated pin is no longer dropped without a word (#241) #256 refuses.- The one place the three reserved names appear is the leg-path remediation, which lists all of
assembly_root_paths():
# $U: a clean checkout at 39ac59c; $C a local clone of a stand-in neutral product; gh is a shim that logs and exits 97 (never called).
python3 $U/scaffold-project.py --org testorg --project Northwind --elected-by 'Test Human' --elected-on 2026-09-02 \
--local-remote-dir $R/remotes --pin-source $C --work-dir $R/work --spec-path contracts --dry-run
# exit 2 REFUSED scaffold-leg-path-collides: --spec-path 'contracts' contains `contracts/spec-pin.yaml` and 3 more. The shape writes them into the assembly root before the legs are mounted, ...
# Remediation: nothing was created, ... a path the shape writes into the assembly root (`README.md`, `project.yaml`, `contracts/spec-pin.yaml`, ... `contracts/shape-pin.yaml`). The defaults `spec` and `code` pass.
# the same flags with `--pin spec@$SHA --dry-run` on 39ac59c: exit 0, "pin opensoft/spec @ ab07fa7e6048 ... -> contracts/spec-pin.yaml"; #256 turns that into scaffold-pin-collides.Both refusals fire at the plan, before the typed yes and before anything is created, so no work is lost. What is missing is the explanation: AGENTS.md section 2 tells an agent "If it refuses, read the refusal: each one names what to run instead" (AGENTS.md:87), and these two name nothing to run, because the remedy is to pass a different value. An agent briefed from AGENTS.md alone cannot say beforehand that --pin code@... or a repeated --pin will be refused, and the scaffold-pin-collides sentence #256 writes ("name the product for the repository it pins") assumes a typo: for a repository genuinely named code, spec or shape nothing can pin it, and the refusal never says outright that those three names are reserved.
Why. Neither change touched a .md file: git diff b538015^ b538015 --stat lists adopt-project.py, scaffold-project.py, scripts/shape_materialize.py and one test file, and a25c2e1 changes scaffold-project.py and adds one test file. docs/cli.md is generated from --help (scripts/render-cli-reference.py), so a flag with no help= has no reference line either. The two refusals themselves are at scaffold-project.py:434-473 (leg paths, on 39ac59c) and :476-498 (pins, on a25c2e1; on main since c3a9645).
What it should do. One docs change for both, with the decisions left to the author:
- Where the text goes. One sentence or short list in AGENTS.md's "Scaffolding a project that DECLARES descent" (a product whose name lowercases to
spec,codeorshape, or the same product twice, is refused before anything is created; the shape writes those pin files itself and one file holds one pin) and one for the leg paths (a leg path may not be, hold or lie inside a path the shape writes; the defaults pass). Whether README's neutral-pin paragraph needs the same line. --help. "Repeatable." could read "Repeatable, once per product", and--spec-path/--code-pathcould say what they are and name the refusal.docs/cli.mdmust then be regenerated (tests/test_cli_reference.pyfails otherwise).- Whether the
scaffold-pin-collidesremediation should namespec,codeandshapeoutright as reserved, as the leg-path one lists the paths. scaffold-project.py: a--pinwhose file the shape writes itself (spec,code,shape, any case, owner or not) or another--pinwrites (openGlassandOpenGlass, or one product twice) is refused before anything is created, under--dry-runalike, so--pin spec@<sha>no longer plans and then makes three repositories to die in the materializer, and a repeated pin is no longer dropped without a word (#241) #256 has landed, so it is taken here. - Both refusals are on main now (b538015 and c3a9645), so one change documents both and the AGENTS.md section is edited once.
How to test. There is no behaviour to test. tests/test_cli_reference.py covers docs/cli.md against --help. If AGENTS.md is edited, grep -n "scaffold-pin-collides\|scaffold-leg-path-collides" AGENTS.md README.md docs/cli.md should find each code once, and the codes must be spelled as the tool prints them (run both refusals and compare).
Related: #197 (PR #234, the leg-path refusal, landed as b538015), #241 (PR #256, the pin refusal, landed as c3a9645).
Activity
brettheap commentedon Oct 12, 2026
CLAIMED — lane openRepoShape-4, session 3431c370-df80-4c11-a041-41bce42d8b38@Eagle, 2026-10-12T00:41:09Z, for #288
Logged in
lanes/log/openRepoShape-4.mdat9288d5ac5127aa06eb6c372fa213e53bf19c7e7f.The three reads (lane-collision-protocol Rule 1):
docs/handbook.html: the "For AI assistants" section says that two ref…
AGENTS.md, README, docs/handbook.html and scaffold-project.py --help:…
tests/test_repo_hygiene.py: the AGENTS.md cap entry for #288 says nin…
Merge origin/main (a1b3a4b) into fix/adopt-plan-quote-yaml-keywords
Merge origin/main (a1b3a4b: #299 via #315, #216 via #228, #260 via #316…
Merge origin/main 8cdca5e into fix/adopt-root-kept-symlinks: thirteen…
Merge origin/main (53bee5b) into fix/setup-help-offline, so the handb…
setup.sh: `--help` from anywhere but a checkout is the shim's own few…