Skip to content

Refuse a Tree Source Reducing to the Repository Root, and Blame the Source Rather Than the Destination - #1443

Merged
ptr727 merged 2 commits into
developfrom
feature/tree-source-empty
Sep 8, 2026
Merged

ptr727 merged 2 commits into
developfrom
feature/tree-source-empty

Conversation

@ptr727

@ptr727 ptr727 commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Relates #1317, #1442.

Answers the one finding Copilot raised on the develop -> main promotion pull request #1442. A
finding there needs its own feature branch, since the promotion PR's head is develop.

The defect

tree_source() reduced "", ".", "./", "/", "//" and whitespace to an empty result, and
manifest_carried_destination() read that as the repository root declared as a carried tree. Every
declared destination was then refused with a message saying it is carried to other repositories,
which blames the destination when the source is what needs fixing.

No tree may name the repository root: spec/validate.py says so in its own words ("must be below
the repository root") and scripts/carry.py enforces it by comparing PurePosixPath objects. So
the empty reduction is refused by its own name now, and the caller's root-tree branch goes with it,
having been reachable only from a manifest this refuses first.

The correction inside this branch

The first commit's message said such a source is one "which its schema forbids". That is false for
exactly the inputs it fires on. spec/files.schema.json constrains a tree source as
{"type": "string", "minLength": 1, "not": {"const": "."}}, so it forbids "" and "." and
nothing else, while "./" and ".///." are schema-valid, reduce the same way, and are the only two
spellings that reach the guard in a repository spec/validate.py already passes. The message would
have sent a maintainer to re-read a schema permitting what they wrote.

The second commit says the reduction instead, which is what the code decides, and names the
schema's two forbidden spellings as the subset they are. The docstring and the test's own name and
docstring carried the same claim and moved in the same edit.

Verification

All gates green: build_dist.py --check, 1166 unit tests, ruff format and check, mypy,
prose_lint.py, repo_gate.py, spec/validate.py, canonical_review.py check.

Two adversarial passes ran over the branch diff. The first found the false schema claim above. The
second reports no false statement and no bug, and proved the change is not a behavior regression by
differencing the old and new tree_source() over 3,906 generated spellings: they differ on 133
inputs, all of them cases where the old function returned "", and agree exactly on every input
carrying a real segment. The removed root-tree branch was proved unreachable over 9,331 spellings
rather than assumed.

Against the real manifest nothing moves: its one tree source is .github/skills, all four
reference targets still refuse, and README.md, docs/fleet-map.md and repo-config/README.md
still admit.

Known and not fixed here

spec/validate.py compares a tree source to "." as a raw string, so "./" and ".///." pass it
and pass its is_dir test, while carry.py refuses both. A manifest author gets a green validator
and a failing carrier. Pre-existing, and this branch closes it only for build_dist.py's own
consumer.

ptr727 and others added 2 commits September 8, 2026 10:34
Relates #1317, #1442.

`tree_source()` reduced `""`, `"."`, `"./"`, `"/"`, `"//"`, and whitespace to
an empty result, and `manifest_carried_destination()` read that as the
repository root declared as a carried tree. Every declared destination was
then refused with a message saying it is carried to other repositories,
which names the wrong file: the fault is a schema-invalid tree source, and
whoever has to fix the manifest was pointed at the destination instead.

The schema forbids a source that is empty or ".", so no valid source
reduces to nothing, and the empty reduction is refused by its own name now.
The caller's root-tree branch goes with it, since it was reachable only
from a manifest this refuses first.

Raised by Copilot on the develop -> main promotion pull request #1442, which
is why the fix lands here rather than there. The finding is the same shape
this branch's parent has already answered twice: a defect upstream
validation makes unreachable is ranked lower by that, not closed.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Relates #1317, #1442.

The refusal added in the previous commit said a root-naming source is one
"which its schema forbids". `spec/files.schema.json` constrains a tree
source as `{"type": "string", "minLength": 1, "not": {"const": "."}}`, so it
forbids `""` and `"."` and nothing else. `"./"` and `".///."` are
schema-valid, reduce to nothing the same way, and are the only two spellings
that reach this guard in a repository `spec/validate.py` already passes,
since that validator rejects a leading slash and a source that is not a
directory. So the message was wrong for exactly the inputs it fires on, and
would send a maintainer to re-read a schema that permits what they wrote.

It says the reduction now, which is what the code actually decides, and
names the schema's two forbidden spellings as the subset they are. The
docstring and the test's own name and docstring carried the same claim and
are corrected in the same edit, which is the one-rule-many-surfaces failure
this branch's parent hit three times.

Two smaller ones with it: the old wording said the misleading message
"names the wrong file" where it names the wrong fault, since it did cite
`spec/files.json`, and a cross-reference read as pointing at the test
immediately below it rather than the one two down, so it names that test
instead.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 8, 2026 17:47
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing

@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 131362df-ed99-46a2-8d23-f5246449ac9b


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The change is narrowly scoped, removes a misleading behavior path, and adds targeted test coverage for the corrected refusal behavior.

Pull request overview

This PR fixes a validation edge case in build_dist where certain trees[].source spellings could reduce to the repository root, which previously led to misleading refusal errors that blamed destinations rather than the invalid source.

Changes:

  • Refuse tree sources that reduce to the repository root in tree_source() with a targeted error message.
  • Remove the now-unnecessary “root tree carries everything” branch from manifest_carried_destination().
  • Add/adjust unit tests to cover root-reducing spellings and keep segment-spelling matching tests focused on valid tree sources.
File summaries
File Description
scripts/build_dist.py Adds an explicit guard for root-reducing tree sources and simplifies carried-destination detection accordingly.
scripts/tests/test_build_dist.py Updates existing coverage and adds a dedicated test for rejecting sources that reduce to the repository root.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@ptr727
ptr727 merged commit 7ad3644 into develop Sep 8, 2026
9 checks passed
@ptr727
ptr727 deleted the feature/tree-source-empty branch September 8, 2026 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants