Repository navigation
adopt-project.py plan: --spec-path and --code-path have no help=, so plan --help and docs/cli.md print two bare lines for the flags that choose where each leg is mounted, and say nothing of the two refusals plan makes on them before anything is created (adopt-leg-path-collides, adopt-bad-leg-path), which #288 is documenting for the scaffold's twins #340
Description
Lane: openreposhape-4 (openRepoShape-4)
Found by this lane's adversarial review of #288 (PR #309, head 72d1cc2; "Out of scope, named not fixed": "adopt-project.py plan's own --spec-path/--code-path have no help= (the PR body already says so)"). Re-verified on main c7c02fa by reading docs/cli.md (generated from every tool's --help) and by running plan against a one-commit local source repository. It is a docs gap and changes no behaviour. #309 is scoped to scaffold-project.py and does not touch adopt-project.py. Lane 5's open #314 (fix/scaffold-manifest-values, head ab66bc0) adds a help= to plan's --elected-by only. So this survives both landings. Not claimed: the check and execute sides of a hand-edited plan's spec_path: / code_path: (#169 and #172 closed those), and Windows.
What is wrong. plan.add_argument("--spec-path", default="spec") and plan.add_argument("--code-path", default="code") (adopt-project.py:4288-4289 at c7c02fa) carry no help=. These two values are where the legs are mounted in the assembly root and what the plan records as spec_path: / code_path:. plan refuses two kinds of value for them before it writes a plan, and its --help says nothing of either:
# $U: a clean checkout at c7c02fa. docs/cli.md is generated from every tool's --help.
sed -n '/^#### `adopt-project.py plan`/,/^#### `adopt-project.py check`/p' "$U/docs/cli.md" | grep -e '--spec-path\|--code-path'
# [--spec-path SPEC_PATH] [--code-path CODE_PATH]
# --spec-path SPEC_PATH
# --code-path CODE_PATH
R=$(mktemp -d)
git init -q -b main "$R/Atlas" && mkdir "$R/Atlas/docs" && echo spec > "$R/Atlas/docs/spec.md"
git -C "$R/Atlas" add -A && git -C "$R/Atlas" -c user.name=t -c user.email=t@t commit -qm init
cd "$R"
plan() {
python3 "$U/adopt-project.py" plan --source "$R/Atlas" --project Atlas --org testorg \
--elected-by 'Test Human' --out "$R/plan.yaml" "$@" 2>&1 | cut -c1-150
echo "exit ${PIPESTATUS[0]}"
}
plan --spec-path contracts
# REFUSED adopt-leg-path-collides: --spec-path 'contracts' contains `contracts/spec-pin.yaml` and 3 more. The shape writes them into the assembly root,
# Remediation: nothing here picks a path for you, so pass another one yourself. A leg path neither is, holds nor lies inside, whatever the case, a path
# exit 2
plan --spec-path spec/
# REFUSED adopt-bad-leg-path: --spec-path is 'spec/', which is not a canonical leg path: Git records a mount without its `.` segments (a leading `./`),
# Remediation: nothing here rewrites a path for you, so correct the value yourself. A leg path is relative and POSIX: one or more plain segments such as
# exit 2
plan --code-path project.yaml
# REFUSED adopt-leg-path-collides: --code-path 'project.yaml' is `project.yaml`. The shape writes it into the assembly root, and `execute` would write i
# exit 2The refusals are right, and both say "nothing here picks a path for you". The gap is that a reader of plan --help or docs/cli.md, the flag-level reference AGENTS.md points every assistant at, learns neither what the flags are for nor the default, nor that contracts, project.yaml or a trailing / will be refused. #288 found exactly this for scaffold-project.py's --spec-path / --code-path. #309 answers it there with a help= naming the default and the collision rule ("A path that is, holds or lies inside a FILE the shape writes into the root is refused before anything is created: project.yaml is one, and contracts holds several."). That leaves the two front doors that take the same two flags documented differently.
plan's other options without a help=, for the author's scoping (decision 3): --org, --id, --visibility (choices only), --tracking-branch, --path-policy, --out and --work-dir. check has --work-dir, and execute has --source and --work-dir.
Why. The flags predate docs/cli.md (#97), which renders a flag with no help= as a bare line. The two leg-path refusals were added later, by #169 (adopt-bad-leg-path) and #172 (adopt-leg-path-collides), and neither change touched the flags' help, as #197 and #241 did not on the scaffold side (#288's "Why").
What it should do. plan --help says what --spec-path and --code-path are and what plan refuses on them. The decisions are the author's:
- The words. AGENTS.md, README and scaffold-project.py --help: say that a --spec-path or --code-path that is, holds or lies inside a file the shape writes, and a --pin of spec, code or shape or of one product twice, are refused before anything is created, and name those three in the pin refusal's remediation, so an agent briefed from AGENTS.md can say so before it runs the scaffold (#288) #309's scaffold text is the model: "where the spec leg is mounted, as a path in the assembly root (default: spec)", then the refusal rule. Decide whether to name the canonical-path rule too (a trailing
/,./or//isadopt-bad-leg-path), which AGENTS.md, README and scaffold-project.py --help: say that a --spec-path or --code-path that is, holds or lies inside a file the shape writes, and a --pin of spec, code or shape or of one product twice, are refused before anything is created, and name those three in the pin refusal's remediation, so an agent briefed from AGENTS.md can say so before it runs the scaffold (#288) #309 leaves out on the scaffold side, and whether to name the codes in--helpor only describe them. - AGENTS.md. Its "Adopting an existing repository" section never names
--spec-path/--code-path. Decide whether it needs the sentence AGENTS.md, README and scaffold-project.py --help: say that a --spec-path or --code-path that is, holds or lies inside a file the shape writes, and a --pin of spec, code or shape or of one product twice, are refused before anything is created, and name those three in the pin refusal's remediation, so an agent briefed from AGENTS.md can say so before it runs the scaffold (#288) #309 adds to section 2 for the scaffold ("Relay the refusal and ask the human for the value; never choose another yourself").tests/test_repo_hygiene.pycaps AGENTS.md: 477 lines after AGENTS.md, README and scaffold-project.py --help: say that a --spec-path or --code-path that is, holds or lies inside a file the shape writes, and a --pin of spec, code or shape or of one product twice, are refused before anything is created, and name those three in the pin refusal's remediation, so an agent briefed from AGENTS.md can say so before it runs the scaffold (#288) #309, 485 once lane 3'sfix/adopt-record-submodule-placementalso lands. Any added line raises the cap with a dated entry. - Scope. These two flags only, or every option of
plan,checkandexecutelisted above that prints a bare line. docs/cli.mdmust be regenerated withscripts/render-cli-reference.py, inside a real checkout (tests/test_cli_reference.pyfails otherwise). scaffold-project.py and adopt-project.py ask the project's YAML reader and validate-manifest.py about the manifest's values before anything exists, so--id null,--tracking-branch trueand a blank--elected-byare refused (#258, #261) #314 edits the sameplan.add_argumentblock, so whichever of the two lands second resolves the argparse lines and regenerates the file rather than hand-merging it.
How to test. There is no behaviour to test. tests/test_cli_reference.py holds docs/cli.md to --help. Hold each new sentence against the tool, as #288's review did for the scaffold: run plan with contracts, contracts/x (accepted), project.yaml, project.yaml/x, spec/ and the defaults, and check that the help claims neither more nor less than what is refused.
Verified at main c7c02fa (adopt-project.py sha256 406bb745…, docs/cli.md 61c6995f…); neither #309 (2ea1717) nor #314 (ab66bc0) adds these two help= strings.
Related:
- AGENTS.md, README and
scaffold-project.py --helpsay nothing of the scaffold's two path-collision refusals (scaffold-leg-path-collides,scaffold-pin-collides) or thatspec,codeandshapecannot be pinned, so a human or agent can learn of them only by hitting them #288 (the scaffold's twin; PR AGENTS.md, README and scaffold-project.py --help: say that a --spec-path or --code-path that is, holds or lies inside a file the shape writes, and a --pin of spec, code or shape or of one product twice, are refused before anything is created, and name those three in the pin refusal's remediation, so an agent briefed from AGENTS.md can say so before it runs the scaffold (#288) #309, whose review named this). - adopt-project.py accepts a non-canonical leg path such as
--spec-path spec/, so the mount and its.gitmodulesregistration disagree andmainstill saysadoption verified#169 and adopt-project.py accepts a leg mount path that collides with a directory the shape writes, such as--spec-path contracts, so the adoption fails after both legs are pushed (main: at the first bootstrap) #172 (the twoplanrefusals). - docs/cli.md: a flag-level CLI reference for an agent, GENERATED from every shipped tool's --help, with a hygiene test that fails when the committed file drifts from what the generator produces #97 (
docs/cli.md). - scaffold-project.py and adopt-project.py ask the project's YAML reader and validate-manifest.py about the manifest's values before anything exists, so
--id null,--tracking-branch trueand a blank--elected-byare refused (#258, #261) #314 (lane 5; the neighbouring--elected-byhelp, and the same argparse block).
Activity
brettheap commentedon Oct 12, 2026
CLAIMED — lane openRepoShape-2, session 0279452a-ea8e-486f-bf99-698cb0a9bb2f@Eagle, 2026-10-12T15:36:05Z, for #340
Logged in
lanes/log/openRepoShape-2.mdatf2ad770cda2eb9af85603118c3a1223956eeb6e0.The three reads (lane-collision-protocol Rule 1):
adopt-project.py: `plan --help` names the refusals `plan` makes on `-…
adopt-project.py: `plan --help` says of the two refusals it names, an…
docs/release-notes/v1.0.0.md: brought up to main 437a360, so the note…
Merge origin/main 437a360 into fix/adopt-root-kept-symlinks: #329's `…
Merge main 437a360 into fix/adopt-plan-quote-yaml-keywords (#181)