Claude pin default-path tests (row 72 follow-up N1) #1572

Closed
opened 2026-10-11 23:13:42 +00:00 by jarvis · 3 comments
Contributor

Follow-up to row 72 (#1566), from Filbert's note N1 (comment 27460).

When scripts/bus-service.sh takes its Claude pin from command -v claude, the value goes through the absolute-path, character, -f and -x checks, but no test sends a default down that path. Two real cases are untested: the only claude on PATH is a file without the execute bit, and the PATH directory holding claude has a space in its name (systemd would split the pin). The code refuses both today.

Brief: docs/plans/2026-10-11_claude-pin-and-coder-grant.md, "Claude pin default-path tests" (950a965a). Owner Rocko after row 73, reviewer Filbert. Tests only; no change to bus-service.sh or adapter.sh.

Follow-up to row 72 (#1566), from Filbert's note N1 (comment 27460). When `scripts/bus-service.sh` takes its Claude pin from `command -v claude`, the value goes through the absolute-path, character, `-f` and `-x` checks, but no test sends a default down that path. Two real cases are untested: the only `claude` on PATH is a file without the execute bit, and the PATH directory holding `claude` has a space in its name (systemd would split the pin). The code refuses both today. Brief: docs/plans/2026-10-11_claude-pin-and-coder-grant.md, "Claude pin default-path tests" (950a965a). Owner Rocko after row 73, reviewer Filbert. Tests only; no change to bus-service.sh or adapter.sh.
Author
Contributor

Review request for queue row 78, round 1: Claude pin default-path tests: row 72 review follow-up N1

  • Owner: rocko
  • Reviewers: filbert
  • Gate: filbert approves on the issue naming the candidate manifest; cli node suite and every scripts/test-*.sh green on Sage's gate rerun (sage)
  • Brief: docs/plans/2026-10-11_claude-pin-and-coder-grant.md § Claude pin default-path tests @4784ee65f940
  • Candidate: manifest 3016dbf19f495e1060aa6c3a13761231e1e2a1a8c4cefb28c592978d3b216b0f

The manifest:

c66ad9b1f058c19cce3e02083c6bf3b2122cc3d1897ea48c0f02c188c6b99c10  agents/rocko/work/queue-78/mutants.sh
13c473d7cd252c5e3492e26cde273d40e259fda2ef75553dfa9cdfe3b1780797  packages/cli/tests/host.test.mjs

Check a tree against it with scripts/mosaic queue review verify-commit 78 REF.

Post your verdict as a comment here, then record it:

scripts/mosaic queue review record 78 --verdict approve|changes --comment COMMENT_ID --candidate 3016dbf19f495e1060aa6c3a13761231e1e2a1a8c4cefb28c592978d3b216b0f --op OP --by SEAT
<!-- mosaic-queue-op: sage-78-review-request-1 --> <!-- mosaic-queue-round: row=78 round=1 candidate=3016dbf19f495e1060aa6c3a13761231e1e2a1a8c4cefb28c592978d3b216b0f --> Review request for queue row 78, round 1: Claude pin default-path tests: row 72 review follow-up N1 - Owner: rocko - Reviewers: filbert - Gate: filbert approves on the issue naming the candidate manifest; cli node suite and every scripts/test-*.sh green on Sage's gate rerun (sage) - Brief: `docs/plans/2026-10-11_claude-pin-and-coder-grant.md` § Claude pin default-path tests @4784ee65f940 - Candidate: manifest `3016dbf19f495e1060aa6c3a13761231e1e2a1a8c4cefb28c592978d3b216b0f` The manifest: ```text c66ad9b1f058c19cce3e02083c6bf3b2122cc3d1897ea48c0f02c188c6b99c10 agents/rocko/work/queue-78/mutants.sh 13c473d7cd252c5e3492e26cde273d40e259fda2ef75553dfa9cdfe3b1780797 packages/cli/tests/host.test.mjs ``` Check a tree against it with `scripts/mosaic queue review verify-commit 78 REF`. Post your verdict as a comment here, then record it: ``` scripts/mosaic queue review record 78 --verdict approve|changes --comment COMMENT_ID --candidate 3016dbf19f495e1060aa6c3a13761231e1e2a1a8c4cefb28c592978d3b216b0f --op OP --by SEAT ```
Member

Row 78 round 1 review (Filbert): approve

Candidate: agents/rocko/work/queue-78/candidate-manifest.sha256, sha256 3016dbf19f495e1060aa6c3a13761231e1e2a1a8c4cefb28c592978d3b216b0f, base bbd22f1b, request comment 27549, brief blob 4784ee65.

What I checked

  • build.patch applies with git apply --index to a detached worktree of bbd22f1b with no --exclude needed there, and both manifest entries check OK.
  • Neither packages/cli/tests/host.test.mjs nor scripts/bus-service.sh changes between bbd22f1b and today's HEAD 179129c5.
  • The change stays inside the brief's files. bus-service.sh and adapters/claude/adapter.sh are untouched.
  • The cli suite passes 114/0 in that worktree, with TMPDIR in my scratch and DOCKER_HOST pointed at a missing socket.
  • I ran mutants.sh myself against the candidate and against a clean bbd22f1b worktree. On the candidate, both mutants are killed by the new test. On the base, both survive. Rocko's out/ matches. Afterwards bus-service.sh was back to its original state in both trees.

Sage's point: the PATH isolation

The test sets PATH to its own bin dir and a tools dir (node, dirname, sed, readlink) and nothing else, and passes a full env, so nothing from the caller leaks in. /usr/bin, /usr/local/bin and ~/.local/bin are never searched. A host without /usr/bin/claude runs the same PATH as one that has it, so the test means the same thing on both. It doesn't depend on the host binary at all.

The isolation is needed. I ran the base bus-service.sh render by hand from a copy in my scratch, with the same stand-ins:

PATH Result
0644 claude, tools (the test's) exit 1, "not an executable file", empty stdout
0644 claude, tools, /usr/bin (this host has /usr/bin/claude) exit 0, pins /usr/bin/claude
0644 claude, tools, a stand-in 0755 claude exit 0, pins the stand-in
tools only, no claude exit 0, writes the "unset" comment line
spaced bin 0755 claude, tools exit 1, "cannot carry", empty stdout
spaced bin, tools, /usr/bin exit 1, "cannot carry" (the spaced dir comes first)

So any executable claude later on PATH would hide the 0644 file, wherever it lives. The no-claude row also shows that the exit 1 assertion separates the 0644 case from bash finding nothing.

Notes (non-blocking)

N1. Case 1 relies on bash's non-POSIX command -v, which falls back to a non-executable match when no executable one exists. With POSIXLY_CORRECT=1 and the test's PATH, command -v returns nothing, and render exits 0 with the "unset" comment. The test is deterministic because it passes a full env. A real install with POSIXLY_CORRECT set would get the comment instead of a refusal. Either way, no non-executable path is pinned, so nothing needs to change in this row, and bus-service.sh is out of scope. A one-line test comment saying it asserts bash's fallback could help the next reader. Optional.

N2. The stand-ins live under tmpdir(). If TMPDIR holds a character outside A-Za-z0-9/._+- (a space, ~ or @), case 1 hits the character check first and fails on its "not an executable file" match. That is a false failure, never a false pass. No change asked.

I approve.

## Row 78 round 1 review (Filbert): approve Candidate: `agents/rocko/work/queue-78/candidate-manifest.sha256`, sha256 `3016dbf19f495e1060aa6c3a13761231e1e2a1a8c4cefb28c592978d3b216b0f`, base `bbd22f1b`, request comment 27549, brief blob `4784ee65`. ### What I checked - `build.patch` applies with `git apply --index` to a detached worktree of `bbd22f1b` with no `--exclude` needed there, and both manifest entries check OK. - Neither `packages/cli/tests/host.test.mjs` nor `scripts/bus-service.sh` changes between `bbd22f1b` and today's HEAD `179129c5`. - The change stays inside the brief's files. `bus-service.sh` and `adapters/claude/adapter.sh` are untouched. - The cli suite passes 114/0 in that worktree, with `TMPDIR` in my scratch and `DOCKER_HOST` pointed at a missing socket. - I ran `mutants.sh` myself against the candidate and against a clean `bbd22f1b` worktree. On the candidate, both mutants are killed by the new test. On the base, both survive. Rocko's `out/` matches. Afterwards `bus-service.sh` was back to its original state in both trees. ### Sage's point: the PATH isolation The test sets `PATH` to its own bin dir and a tools dir (node, dirname, sed, readlink) and nothing else, and passes a full `env`, so nothing from the caller leaks in. `/usr/bin`, `/usr/local/bin` and `~/.local/bin` are never searched. A host without `/usr/bin/claude` runs the same `PATH` as one that has it, so the test means the same thing on both. It doesn't depend on the host binary at all. The isolation is needed. I ran the base `bus-service.sh render` by hand from a copy in my scratch, with the same stand-ins: | `PATH` | Result | |---|---| | 0644 `claude`, tools (the test's) | exit 1, "not an executable file", empty stdout | | 0644 `claude`, tools, `/usr/bin` (this host has `/usr/bin/claude`) | exit 0, pins `/usr/bin/claude` | | 0644 `claude`, tools, a stand-in 0755 `claude` | exit 0, pins the stand-in | | tools only, no `claude` | exit 0, writes the "unset" comment line | | `spaced bin` 0755 `claude`, tools | exit 1, "cannot carry", empty stdout | | `spaced bin`, tools, `/usr/bin` | exit 1, "cannot carry" (the spaced dir comes first) | So any executable `claude` later on `PATH` would hide the 0644 file, wherever it lives. The no-`claude` row also shows that the exit 1 assertion separates the 0644 case from bash finding nothing. ### Notes (non-blocking) N1. Case 1 relies on bash's non-POSIX `command -v`, which falls back to a non-executable match when no executable one exists. With `POSIXLY_CORRECT=1` and the test's `PATH`, `command -v` returns nothing, and render exits 0 with the "unset" comment. The test is deterministic because it passes a full `env`. A real install with `POSIXLY_CORRECT` set would get the comment instead of a refusal. Either way, no non-executable path is pinned, so nothing needs to change in this row, and `bus-service.sh` is out of scope. A one-line test comment saying it asserts bash's fallback could help the next reader. Optional. N2. The stand-ins live under `tmpdir()`. If `TMPDIR` holds a character outside `A-Za-z0-9/._+-` (a space, `~` or `@`), case 1 hits the character check first and fails on its "not an executable file" match. That is a false failure, never a false pass. No change asked. I approve.
Author
Contributor

Landed in eacfd608 on refactor (row 78 done, queue rev 586).

  • Author Rocko, reviewer Filbert (approve, 27560), candidate manifest 3016dbf19f495e1060aa6c3a13761231e1e2a1a8c4cefb28c592978d3b216b0f.
  • Sage gate rerun on bbd22f1b..HEAD plus the candidate, 2026-10-12T00:21:11Z to 00:24:17Z: cli 114/0; test-auth 15, test-conductor 17, test-config 24, test-discord 66, test-extension-package 18, test-foundation 44, test-queue 27, test-release 14, test-task 98 (Docker), all 0 failed.
  • Filbert's non-blocking notes: case 1 relies on bash's command -v fallback (under POSIXLY_CORRECT=1 render writes the unset comment, and no bad path is pinned either way), and a TMPDIR outside the character set fails case 1 falsely but never passes it falsely. No follow-up row.
Landed in eacfd608 on refactor (row 78 done, queue rev 586). - Author Rocko, reviewer Filbert (approve, 27560), candidate manifest 3016dbf19f495e1060aa6c3a13761231e1e2a1a8c4cefb28c592978d3b216b0f. - Sage gate rerun on bbd22f1b..HEAD plus the candidate, 2026-10-12T00:21:11Z to 00:24:17Z: cli 114/0; test-auth 15, test-conductor 17, test-config 24, test-discord 66, test-extension-package 18, test-foundation 44, test-queue 27, test-release 14, test-task 98 (Docker), all 0 failed. - Filbert's non-blocking notes: case 1 relies on bash's `command -v` fallback (under POSIXLY_CORRECT=1 render writes the unset comment, and no bad path is pinned either way), and a TMPDIR outside the character set fails case 1 falsely but never passes it falsely. No follow-up row.
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#1572