Skip to content

Fix CLI resource loading through symlinks - #2890

Merged
steipete merged 2 commits into
mainfrom
fix/issue-2889-cli-symlink-resources
Aug 12, 2026
Merged

Fix CLI resource loading through symlinks#2890
steipete merged 2 commits into
mainfrom
fix/issue-2889-cli-symlink-resources

Conversation

@steipete

Copy link
Copy Markdown
Owner

Summary

  • resolve the physical CLI executable before probing adjacent CodexBarCore resources
  • preserve app-bundle precedence, direct helper/tarball behavior, both resource suffixes, and the guarded SwiftPM fallback
  • cover documented symlink installs in portable tests, packaged-app smoke, and every release CLI artifact matrix entry

Fixes #2889

Root cause

The documented app/Homebrew CLI install invokes CodexBarCLI through /usr/local/bin/codexbar or /opt/homebrew/bin/codexbar. Outside an app bundle, the resource resolver treated the uncanonicalized bundle/invocation location as the executable-adjacent directory. A symlink living outside Contents/Helpers therefore could not see the physical helper's adjacent CodexBar_CodexBarCore.bundle, so bundled JavaScript providers failed cleanly instead of loading.

Implementation

CodexBarCoreResources now derives the running executable URL from Bundle.executableURL, Darwin _NSGetExecutablePath, or Linux /proc/self/exe, resolves symlinks, and probes the physical parent directory. App resource lookup still runs first; missing resources still return nil; .bundle, .resources, and the guarded development fallback remain supported.

The packaged-app smoke now invokes the helper both directly and through a symlink located outside Contents/Helpers while all checkout reads are denied. The release CLI workflow also exercises both CodexBarCLI and the packaged codexbar symlink for every macOS, glibc Linux, and static musl artifact.

Validation

  • existing macOS resource resolver tests updated for the executable-URL seam
  • new portable test proves direct and symlink executable URLs resolve the same physical .bundle and .resources directories
  • bash -n Scripts/verify_packaged_app_launch.sh
  • make check: passed
  • full make test: 841 selections across 71 groups passed with no retries or timeouts
  • structured Codex autoreview: clean, no accepted or actionable finding
  • TruffleHog patch scan: clean
  • Developer ID-signed release package built successfully
  • with the source checkout sandbox-denied:
    • direct packaged helper resource smoke passed
    • external symlink to the packaged helper resource smoke passed
    • packaged app resource smoke passed
    • packaged app survived the checkout-independent launch smoke
  • codesign --verify --deep --strict --verbose=2 CodexBar.app
  • spctl --assess --type execute --verbose=4 CodexBar.app

The package is signed by Developer ID Application: Peter Steinberger (Y5PE65HELJ) and accepted by Gatekeeper. No provider credentials or network access are required for the proof.

@clawsweeper

clawsweeper Bot commented Aug 12, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

@steipete

Copy link
Copy Markdown
Owner Author

@clawsweeper review

@steipete

Copy link
Copy Markdown
Owner Author

@codex review

@clawsweeper

clawsweeper Bot commented Aug 12, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

Re-review progress:

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: 1857e5bdb1

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Aug 12, 2026
@clawsweeper

clawsweeper Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed August 12, 2026, 12:16 PM ET / 16:16 UTC.

ClawSweeper review

What this changes

The PR resolves the physical CLI executable before finding adjacent provider-plugin resources and adds symlink coverage to portable tests, packaged-app smoke checks, and release artifacts.

Regression provenance

Possible regression — probable (reproduction; reviewed change). No predecessor PR is attributed.

Merge readiness

⚠️ Ready for maintainer review - 2 items remain

Keep open for normal owner review: the focused resolver change correctly addresses the linked Homebrew-style symlink failure, with no blocking defect found. Active release-artifact jobs should complete on the current head before merge.

Priority: P1
Reviewed head: 90d576aa2f5417f1c7a97527a98d702338d03e6a

Review scores

Measure Result What it means
Overall readiness 🐚 platinum hermit (4/6) The repair is focused and has strong packaged-runtime evidence; the active cross-platform release jobs remain the last routine merge check.
Proof confidence 🦞 diamond lobster (5/6) Not applicable: This owner-authored PR is exempt from the external-contributor proof gate; its body nevertheless records direct and external-symlink packaged-helper smoke results with checkout reads denied.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Not applicable Not applicable: This owner-authored PR is exempt from the external-contributor proof gate; its body nevertheless records direct and external-symlink packaged-helper smoke results with checkout reads denied.
Evidence reviewed 5 items Resolver fix: The branch resolves the supplied or running executable URL through symlinks before using its parent directory to probe both supported resource bundle suffixes.
Portable regression coverage: The new portable test creates a physical helper and an external symlink, then requires both paths to resolve the same adjacent .bundle and .resources directory.
Packaged runtime proof path: The packaged-app smoke creates a symlink outside Contents/Helpers, denies checkout reads, and requires the resource smoke marker from that symlinked helper.
Findings None None.
Security None None.

How this fits together

CodexBar’s CLI loads bundled provider-plugin resources from alongside its packaged helper executable. A Homebrew-style symlink must resolve to that physical helper before the CLI can load those resources and serve provider commands.

flowchart LR
  A[CLI invocation] --> B[Direct path or symlink]
  B --> C[Resolve physical executable]
  C --> D[Find adjacent resource bundle]
  D --> E[Load provider plugins]
  E --> F[CLI provider command]
Loading

Before merge

  • Resolve merge risk (P1) - The changed release CLI smoke path is still running on macOS, glibc Linux, and static-musl Linux for the current head; merge after those artifact checks complete successfully.
  • Complete next step (P2) - The owner-authored PR has a bounded, reviewed repair and only requires normal current-head release-matrix completion.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Review surface 6 files changed; production +30, tests +49 The implementation is small while adding focused portable coverage plus packaged-app and release-artifact validation.

Merge-risk options

Maintainer options:

  1. Finish release artifact validation (recommended)
    Wait for the current macOS, glibc Linux, and static-musl CLI jobs to pass on this exact head before merging the workflow-backed regression coverage.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Wait for the current release CLI matrix to complete successfully on the exact head before merge.

Technical review

Best possible solution:

Land the physical-executable lookup with its portable and packaged-artifact regression coverage once the current release matrix validates the exact head.

Do we have a high-confidence way to reproduce the issue?

Yes—current-main source establishes the old lookup boundary, and the branch’s portable plus packaged-helper smoke paths exercise the direct-versus-symlink case without provider credentials.

Is this the best way to solve the issue?

Yes—the physical executable path is the narrow, package-layout-stable anchor for adjacent resources, while preserving app-bundle precedence and existing fallback behavior.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against c4ed34d0e44a.

Labels

Label changes:

  • add rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • remove rating: 🦞 diamond lobster: Current PR rating is rating: 🐚 platinum hermit, so this older rating label is no longer current.

Label justifications:

  • P1: Homebrew-style CLI invocation can fail to load bundled provider plugins, blocking affected provider commands.
  • merge-risk: 🚨 automation: The PR changes packaged-app and release CLI workflow smoke assertions across shipped artifact platforms.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: This owner-authored PR is exempt from the external-contributor proof gate; its body nevertheless records direct and external-symlink packaged-helper smoke results with checkout reads denied.

Evidence

What I checked:

Likely related people:

  • steipete: Current-main blame attributes the existing resource resolver to Peter Steinberger, and the two branch commits implement and refine this focused repair. (role: feature owner and recent area contributor; confidence: high; commits: 330ae4384b18, 1857e5bdb1f1, 90d576aa2f54; files: Sources/CodexBarCore/CodexBarCoreResources.swift, Scripts/verify_packaged_app_launch.sh, .github/workflows/release-cli.yml)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Confirm the active macOS, glibc Linux, and static-musl release CLI jobs succeed on the current head.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (2 earlier review cycles)
  • reviewed 2026-08-12T15:44:47.775Z sha 1857e5b :: needs maintainer review before merge. :: none
  • reviewed 2026-08-12T15:48:41.426Z sha 1857e5b :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added merge-risk: 🚨 automation 🚨 Merging this PR could break CI, automerge, proof capture, label sync, or automation. P1 Urgent regression or broken agent/channel workflow affecting real users now. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. and removed P2 Normal priority bug or improvement with limited blast radius. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Aug 12, 2026
@steipete

Copy link
Copy Markdown
Owner Author

CI follow-up on run https://github.com/steipete/CodexBar/actions/runs/31613541949:

  • Linux x64/arm64 failed only because Foundation represented the same physical resource directory with different directory-hint/trailing-slash URL identity. Commit 90d576aa2f5417f1c7a97527a98d702338d03e6a keeps the direct/symlink physical-path assertion but compares canonical standardized path components portably.
  • The macOS repeated hung CLI RPC requests stay bounded failure was unrelated existing timing flakiness. The exact CodexUsageFetcherFallbackTests suite passes locally on the current head: 13/13 tests.
  • Current-head focused proof: portable resource suite passes both .bundle and .resources cases; core resource suite passes 6/6; make check and fresh branch autoreview are clean.

@clawsweeper re-review
@codex review

@clawsweeper

clawsweeper Bot commented Aug 12, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. labels Aug 12, 2026
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: 90d576aa2f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@steipete

Copy link
Copy Markdown
Owner Author

The non-publishing release CLI artifact matrix is green on exact head 90d576aa2f5417f1c7a97527a98d702338d03e6a:

https://github.com/steipete/CodexBar/actions/runs/31618914017

Passed artifact jobs:

  • macOS arm64
  • macOS x86_64
  • glibc Linux arm64
  • glibc Linux x86_64
  • static musl Linux arm64
  • static musl Linux x86_64

Each package job exercised both the physical CodexBarCLI and packaged codexbar symlink resource smoke. The Homebrew update job was skipped because this was a manual artifact build, not a GitHub Release event. No tag, Release, tap update, or publication occurred.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Aug 12, 2026

Copy link
Copy Markdown

ClawSweeper status: review started.

I am starting a fresh review of this pull request: Fix CLI resource loading through symlinks This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

@steipete
steipete merged commit 07837ae into main Aug 12, 2026
16 checks passed
@steipete

Copy link
Copy Markdown
Owner Author

Landed, released, and verified.

Behavior:

  • CodexBarCoreResources now resolves the physical CLI executable before probing adjacent provider-plugin resources, so the documented app/Homebrew codexbar symlink works on macOS and Linux.
  • App-bundle precedence, direct helper/tarball lookup, both resource suffixes, missing-bundle handling, and SwiftPM development fallback remain intact.

Proof:

  • Core resource suite: 6/6 tests passed.
  • Portable direct/symlink suite passed both .bundle and .resources cases.
  • Full local matrix: 841 selections across 71 groups passed with no retries or timeouts.
  • make check, structured Codex autoreview, and TruffleHog passed.
  • Developer ID-signed packaged app smoke passed with checkout reads denied for the direct helper, an external symlink to the helper, and the app itself; codesign, Gatekeeper, and stapler validation passed.
  • Exact-head CI passed after the Linux URL directory-hint assertion was normalized portably: https://github.com/steipete/CodexBar/actions/runs/31616528890
  • Non-publishing six-platform artifact matrix passed direct and symlink smoke on macOS arm64/x86_64, glibc Linux arm64/x86_64, and musl Linux arm64/x86_64: https://github.com/steipete/CodexBar/actions/runs/31618914017
  • Exact-head Codex and ClawSweeper reviews reported no actionable correctness or security finding.

Merged as 07837aedcbc68557d00c84fc3fe0aeeb388c0910, closing #2889. The fix shipped in CodexBar 0.49.3: https://github.com/steipete/CodexBar/releases/tag/v0.49.3

Release verification:

  • all 14 app/dSYM/CLI assets are published;
  • release CLI and Homebrew handoff succeeded: https://github.com/steipete/CodexBar/actions/runs/31626495686
  • the live appcast reports 0.49.3 / build 117 with a verified EdDSA signature and a 200 enclosure;
  • the Homebrew cask and formula serve 0.49.3;
  • this Mac upgraded through Homebrew from 0.49.2 to 0.49.3;
  • /opt/homebrew/bin/codexbar resolves to the packaged helper, passes CODEXBAR_RESOURCE_SMOKE=1, and reports CodexBar 0.49.3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 automation 🚨 Merging this PR could break CI, automerge, proof capture, label sync, or automation. P1 Urgent regression or broken agent/channel workflow affecting real users now. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provider plugin load fails from CLI when installed via symlink (Homebrew)

1 participant