Repository navigation
Description
Summary
Two bin/ entry points still use the pre-#2083 entry-point check that compares the raw invoked path against the module's resolved URL. When either script is invoked through a symlink — a symlinked file, or a symlinked directory such as the ~/code -> ~/git/code checkout alias that caused #2083 — the check fails, main() never runs, and the process exits 0 with no output and no error: a silent no-op.
bin/proxy-supervise.mjs was fixed for exactly this in #2083 (its comment at :644-656 spells the mechanism out, and it now compares fs.realpathSync on both sides). The same pattern survives verbatim in:
bin/provider-catalog-sync.mjs:750—path.resolve(process.argv[1]) === new URL(import.meta.url).pathname(path.resolvemakes the path absolute; it does not resolve symlinks, andimport.meta.urlis the resolved module URL).bin/record.mjs:206-209—import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href(same flaw in URL form).
Evidence (main 24901e7b, sandbox probes this run)
provider-catalog-sync:
- Direct:
node bin/provider-catalog-sync.mjs --json→ exit 0, 14,177 bytes of report on stdout. - Via a symlink to the file:
node /tmp/isMain-probe/catalog-link.mjs --json→ exit 0, 0 bytes. - Via a symlinked directory (the proxy-supervise: main() never runs when invoked via a symlinked path (~/code -> ~/git/code) — supervisor timer silently no-ops since 2026-10-27 #2083 scenario):
node ~/code-link/bin/provider-catalog-sync.mjs --json→ exit 0, 0 bytes.
record (with AI_RECORDINGS_FILE pointed at a scratch target, loose-text input):
- Direct: the target's
.quarantinesibling is created with the verbatim line (its never-reject contract for unkeyed text) — main ran. - Via a symlink to the file: neither the target nor the quarantine file is created — main never ran, and the recording is silently lost.
Probe outputs saved in the goal's hidden_files probe-2026-10-29-ismain/ (direct.out / link.out / dirlink.out / README.md).
Why it matters
Both tools are built to be quiet: catalog-sync's no-additions path is a "silent run" by design, and record's contract is exit-0-always. That makes this failure mode invisible — a timer, wrapper, or Nix-store/symlink invocation path that reaches either script through a symlink gets a green exit and nothing happens: catalog additions never materialise, session recordings vanish. This is precisely how the supervisor timer no-oped unnoticed from 2026-10-27 until #2083; the fix landed for one file and the sibling instances of the identical check were left behind.
Acceptance criteria
- Both
bin/provider-catalog-sync.mjsandbin/record.mjsrun theirmain()when invoked via a symlinked file path and via a symlinked directory path (use thefs.realpathSync-on-both-sides comparison already proven inbin/proxy-supervise.mjs:648-656, or an equivalent). - Importing either module as a library (their test suites do this) still does not run
main(). - A regression test covers the symlinked invocation for at least one of the two (catalog-sync's subprocess-style test or a scripted probe), so the check cannot silently regress again.
- A repo-wide grep for entry-point comparisons (
process.argv[1]vsimport.meta.url) shows no remaining raw-path instances inbin/.
Related: #2083 (closed — the proxy-supervise instance of this bug, and the source of the proven fix pattern).
Found by new-issue-creator-code-b (lane B) this run.
Activity
developing-today commentedon Oct 29, 2026
CODE-1106
dezren39 commentedon Oct 29, 2026
🤖 Agent note · filed
probe-2026-10-29-ismain/in the goal's hidden_files (direct 14,177B report vs 0B via file/dir symlinks; record direct creates quarantine, via symlink creates nothing); related closed proxy-supervise: main() never runs when invoked via a symlinked path (~/code -> ~/git/code) — supervisor timer silently no-ops since 2026-10-27 #208399 remaining items
dezren39 commentedon Nov 2, 2026
agent-note:v1 — parked
Agent: repo-worker-code (OpenChamber scheduled lane)
Task: repo-health-code-pilot task 5233
At: 2026-11-02T09:23:36Z
State: parked
Fresh evidence: metadata-only revalidation confirms #2235 is OPEN and assigned to dezren39 (Drew); canonical PR #4123 is OPEN, non-draft, and authored by dezren39 on queue/5233-2235-symlink-entry-points.
Disposition: parked 30 minutes at the Drew-owned hard stop. No PR contents, diff, checks, reviews, branch, worktree, or source inspected/touched. Labels reflect parked state; work/assigned remains set.
Resume condition: PR #4123 closes/merges or Drew explicitly hands off ownership; revalidate fresh before proceeding.
Links: #2235 · #4123 · task 5233
dezren39 commentedon Nov 2, 2026
Parked again (task 5233, lane B): metadata-only revalidation — #2235 still OPEN and assigned to dezren39; canonical PR #4123 still OPEN, authored by dezren39, head f791447. Drew-owned PR hard stop applies; no PR contents, diff, branch, worktree, CI, review, or source inspected or touched. Resume only after PR #4123 closes/merges or Drew hands off.
dezren39 commentedon Nov 2, 2026
Task 5233 resumed by lane A. Ownership correction: PR #4123 is fleet-owned (task 5233 branch; PR body names task 5233) — the earlier Drew-owned park was the author-metadata over-fire. Fresh verification at head f791447: Codex clean; laptop node --test bin/provider-catalog-sync.test.mjs bin/record.test.mjs 39/39 pass. Merging under standing merge authority.
fix(bin): run main when provider-catalog-sync and record are invoked …
dezren39 commentedon Nov 2, 2026
Task 5233 done: PR #4123 squash-merged (c08b27f), #2235 closed. Laptop node --test for both bin suites 39/39 pass at f791447; Codex clean.