Skip to content

Relative selectors resolve and unknown ones error instead of running cwd - #293

Open
calvin-archastro wants to merge 1 commit into
mainfrom
factory/tsk_0UyNNBodV8CtLwmDNWVYiK-e1d2d9d5-3768-428b-b126-
Open

calvin-archastro wants to merge 1 commit into
mainfrom
factory/tsk_0UyNNBodV8CtLwmDNWVYiK-e1d2d9d5-3768-428b-b126-

Conversation

@calvin-archastro

@calvin-archastro calvin-archastro commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Review on ArchCode

Epic: Aster bug bash fixes
Task: Relative selectors resolve and unknown ones error instead of running cwd

Problem and author intent

aster <target> project selection only reliably handled // addresses (via ProjectSelector) and a narrow ./... prefix. Other documented forms were dropped or mis-resolved, and an empty selector list fell back to “the project containing cwd.”

Reported failure modes (issue 267):

  • From the workspace root, services/api and services/* were not kept as selectors, so selection failed with No projects specified.... ./... was retained but prefix matching reported No projects found matching: ./.... //services/api/ was compared literally and reported Project not found.
  • From inside a project directory, totally-bogus, ../web, and ../... were also dropped. With projects empty, cwd detection selected the containing project and exited 0, so a typo or a sibling path silently ran the cwd project (for example //services/api:test).

Intent: keep non-flag selectors, resolve cwd-relative directories and the agreed glob forms to workspace-relative project paths, treat . as the project containing cwd, accept a trailing slash on // addresses, and fail closed on anything unmatched or outside the workspace. // address grammar and run-target addresses stay unchanged. README was left unchanged because the documented forms are implemented rather than dropped.

What changed

Selection now classifies each selector before matching.

  • Parse. Plain positionals (services/api, services/*, ../web) are stored. ./ and ../ are both relative forms. A trailing / is stripped from // addresses and exclusions (// itself is left alone), so //services/api/ is the same address as //services/api. . still means cwd detection, not a path.
  • Resolve. Relative selectors are joined to cwd and . / .. are collapsed logically (logical_normalize, no filesystem canonicalize). The result must stay under the workspace root. Escape fails with selector <s> resolves outside the workspace <root>.
  • Match. Exact relative path; /... recursive prefix (./..., ../..., path/..., empty prefix = all projects); * = one path segment; ** = any depth. Other glob metacharacters (?, [, a * that is not its own segment, .. inside a glob) are rejected. // forms still go through ProjectSelector. //... still means all.
  • Fail closed. A relative or glob selector that matches nothing returns unrecognised project selector '<s>'; use //path, //path/..., ./..., or .. Cwd fallback runs only when no selector was given, or when . / use_cwd is explicit. That fallback is the longest discovered directory that is a prefix of cwd (a root project only when cwd is the workspace root), not every project under cwd.
  • Exclusions use the same address and relative matching. A relative exclusion that fails to prepare is treated as a non-match (it does not exclude and does not fail the command).

Scope

  • src/cli/run.rs — parse, resolve, glob match, select_projects, exclusions, and unit tests.
  • tests/integration.rs — binary-level selector coverage.
  • Frozen diff: 31 hunks, +648 / −112. No omitted hunks or paths in the patch. README is not in the revision.

Risk assessment

High. This path runs for every target command; a wrong match runs or skips the wrong projects, including in CI. Normalization is logical, not canonicalize, so the workspace root string in outside-workspace errors depends on the root the CLI already resolved (the integration test compares against a canonicalized temp root; unit tests use a literal /workspace). Relative exclusions swallow resolution errors via .ok(), so a bad exclusion can silently exclude nothing. An exact // address that is present in the graph or address map but does not match a discovered project still does not get a new error (same shape as the old “in graph but unmatched” branch).

User impact

  • services/api, ./path, ../web, ./..., ../..., path/..., services/*, and services/** select projects against cwd instead of being ignored or falling through to the cwd project.
  • * does not match nested projects (services/* is services/api and services/web, not services/api/v2). ** does. services/api* is unrecognised.
  • Unknown selectors and paths that leave the workspace exit non-zero with the messages above. Scripts that depended on the old silent cwd run for a bad token will now fail.
  • aster test //services/api/ behaves like //services/api.
  • . still runs only the project containing cwd.

Testing

Patch evidence adds these tests. Presence in the diff is not proof they passed.

  • Unit (src/cli/run.rs): test_parse_run_args_keeps_relative_selectors, test_parse_run_args_strips_trailing_address_slash, test_select_projects_relative_directory_and_globs, test_select_projects_parent_selectors_resolve_against_cwd, test_select_projects_unknown_selector_does_not_fall_back_to_cwd, test_select_projects_outside_workspace_names_selector_and_root, test_select_projects_trailing_slash_address_matches_exact_project, test_select_projects_unsupported_glob_is_unrecognised.
  • Integration: tests/integration.rs::relative_and_glob_selectors_select_expected_projects. It builds a temp workspace (services/api, services/web, services/api/v2, libs/core), runs the aster binary, and asserts PASS lines, non-matches, exit status, the unrecognised-selector text, and the outside-workspace text for services/api, services/*, services/**, ./..., //services/api/, bogus, ../web, ../api, ../..., and ...

Advisory pipeline outcomes (all reported succeeded, exit 0): format, lint, test, fix, reformat, verify-lint, verify-test, commit. The fix note cites cargo clippy --locked --workspace --all-targets --all-features -- -D warnings and cargo test --locked --workspace --all-targets --all-features, both exit 0, and commit reported no remediation files. Verification gap: upstream check logs are truncated. The supplied test excerpts name unrelated cases (migrations, server, startup, ui, upgrade) and do not name relative_and_glob_selectors_select_expected_projects or the new cli::run tests. This review does not treat CI as having shown those cases pass. Bare . and ../* are not in the integration excerpt (../* is covered by the parent-selector unit test).

Follow-ups and known issues

  • Relative exclusions that fail to resolve are ignored rather than returned as errors.
  • User-facing README was not part of this diff; confirm docs elsewhere still match * / ** only and the new error strings.
  • No supplied log shows the canonical integration test by name; a reviewer should re-run cargo test --lib cli::run and cargo test --test integration relative_and_glob_selectors_select_expected_projects if those names must be confirmed in CI output.

@calvin-archastro
calvin-archastro requested a review from a team October 31, 2026 21:28
@calvin-archastro

calvin-archastro commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor Author

ArchDev is watching this pull request. State: watching (cycle 12 of 12 for head 0c2bcf2).

when trigger decision result
2026-10-31T22:16:32.471Z merge conflict enqueue job_bad129866db5039e43525312 published 3264c20
2026-10-31T22:33:21.933Z verify head enqueue job_109fca0d6c4b2c626c060558 no change
2026-10-31T23:10:36.590Z merge conflict enqueue job_8a40b2a2f757610d6a8346da published 7a2dff3
2026-10-31T23:30:29.953Z verify head enqueue job_00b9f3e699d2301a972fbb0d no change
2026-11-01T00:17:29.084Z merge conflict enqueue job_68efa449a3e55abc4ec3299a published 52c28fc
2026-11-01T06:35:35.179Z verify head enqueue job_ceb73d7c4fa681db623e7d64 no change
2026-11-01T12:35:21.378Z merge conflict enqueue job_498949bf8ecb880a2e9cfd71 published 51b1c02
2026-11-01T12:58:12.526Z verify head enqueue job_fe52ae6258e76552d83fa589 no change
2026-11-01T16:42:41.124Z merge conflict enqueue job_890013a5855f28d04c803407 failed Pipeline step finalize-conflict failed: command exited with code 1
2026-11-01T17:01:20.906Z verify head enqueue job_41bbd2191b5b0f67b7708acc no change
… 2 earlier cycles omitted

Paused by the no-autofix label or a draft; never resolves reviewer threads. Jobs: job_bad129866db5039e43525312, job_109fca0d6c4b2c626c060558, job_8a40b2a2f757610d6a8346da, job_00b9f3e699d2301a972fbb0d, job_68efa449a3e55abc4ec3299a, job_ceb73d7c4fa681db623e7d64, job_498949bf8ecb880a2e9cfd71, job_fe52ae6258e76552d83fa589, job_890013a5855f28d04c803407, job_41bbd2191b5b0f67b7708acc.

@calvin-archastro
calvin-archastro force-pushed the factory/tsk_0UyNNBodV8CtLwmDNWVYiK-e1d2d9d5-3768-428b-b126- branch 4 times, most recently from 52c28fc to 51b1c02 Compare November 1, 2026 12:46
@calvin-archastro
calvin-archastro force-pushed the factory/tsk_0UyNNBodV8CtLwmDNWVYiK-e1d2d9d5-3768-428b-b126- branch from 51b1c02 to 0c2bcf2 Compare November 1, 2026 16:51

This branch has not been deployed

No deployments
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.

1 participant