Skip to content

Resolve missing config inputs through canonical ancestors - #396

Merged
firejune merged 1 commit into
mainfrom
jinni/336-symlinked-config-inputs
Nov 10, 2026
Merged

firejune merged 1 commit into
mainfrom
jinni/336-symlinked-config-inputs

Conversation

@firejune

Copy link
Copy Markdown
Contributor

Closes #336

Changes

  • Resolve a missing config input through its nearest existing canonical ancestor before comparing it with the canonical project root.
  • Preserve missing-input behavior for contained paths and project-escape refusals for lexical escapes, outside symlink directories and outside symlink files.
  • Add a regression that opens a synthetic project through a symlink, exercises the normal correction writer and verifies missing nested inputs plus escape controls.

Verification

Nova ordinary pool ran typecheck, lint and tests/config-inputs.test.ts with exact changed-file hashes. Result was 41 pass, 0 fail and 152 assertions. The job held a slot for 14.286 seconds and ended quiescent.

A bounded native macOS attempt could not import the Parts source entry in this isolated worktree, so it provides no native behavior verdict. The explicit symlink regression passed on Nova. The native invocation failure is retained in the lane evidence.

Parent independent diff and input-hash review completed. Hosted CI and the single automatic review remain pending.

Keep missing contained inputs distinct from project escapes when the project root is opened through a symlink. Preserve outside-path guards and cover the supported correction entry point.

Co-Authored-By: Jinni <342598851+fj-jinni[bot]@users.noreply.github.com>
Co-Authored-By: Naru <342599188+fj-naru[bot]@users.noreply.github.com>
@firejune firejune added the by:codex Written by a Codex (Naru) worker; Claude side judges the review label Nov 10, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-10T14:00:06.522581Z a989c41 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@firejune

Copy link
Copy Markdown
Contributor Author

Claude review (cross-family)

Reviewer: Claude (HQ). Read: src/config-inputs.ts, tests/config-inputs.test.ts, the configInputBindings callers in src/corrections.ts and src/drafts.ts, and src/check-reads.ts at head a989c41ed58ffb43af6cbe5cc5a65271d9d4a827. Verdict: approve once CI is green

What I checked

  • Missing input under a project opened through a symlink: the nearest existing ancestor is realpath'd and the missing tail is re-appended, so the path compares against the canonical root and binds inside the project (the config-inputs: a missing input under a symlinked project path refuses as 'leaves the project' #336 case).
  • Escapes still refuse: lexical .. out of the project, a missing file under an in-project symlink directory pointing outside, and an existing symlink file pointing outside. path.resolve removes .. before any filesystem call, so the bytes read and the containment check use the same location.
  • Dangling symlink on the path: the walk stops at the symlink and realpathSync throws, so a dangling link pointing outside can no longer bind as "missing". Before this PR, allowMissing accepted it on the lexical path without any containment check.
  • Present inputs: behaviour unchanged (realpathSync, then contained). With allowMissing=false, a missing contained input still throws ENOENT. A missing escaping input now reports "leaves the project" first, which is the more accurate message.
  • Correction writer: a missing input now binds its canonical path, which is the same form drafts.ts records for present inputs, so the f.path === input.path match against draft.config_inputs lines up again.
  • No new finding codes, *_SINCE constants, pins or template bytes. Invariants 2 to 6 are untouched.

Findings

  • P2 src/config-inputs.ts:104: with allowMissing=true, a dangling in-project symlink whose target is also inside the project (for example evidence/req.json -> evidence/out/req.json, not produced yet) used to bind {path, sha256: null} and now throws a raw ENOENT with no named code; refusing is the safe choice, but the error should name the input (${ref.at}) and the remedy.
  • P3 tests/config-inputs.test.ts:291: the regression has no dangling-symlink case (inside or outside), so the isSymbolicLink() break that closes the old dangling-link escape is not pinned by a test.

@firejune
firejune merged commit dc33323 into main Nov 10, 2026
2 checks passed
@firejune
firejune deleted the jinni/336-symlinked-config-inputs branch November 10, 2026 14:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

by:codex Written by a Codex (Naru) worker; Claude side judges the review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

config-inputs: a missing input under a symlinked project path refuses as 'leaves the project'

1 participant