Repository navigation
Description
sync-models: unrecognized arguments are silently ignored — a typo'd --dry-rnu rewrites the live OpenCode config in place (and reloads opencode)
Summary
bin/sync-models.mjs — the legacy model sync that, per bin/provider-catalog-sync.mjs's header, "rewrites the deployed config in place (and auto-removes)" and is still the script the sync-models service maintains the deployed user config with — parses its CLI flags by membership only and never rejects an argument it does not recognize:
bin/sync-models.mjs:6-7—const DRY_RUN = process.argv.includes('--dry-run'),const VERBOSE = process.argv.includes('--verbose') || …. There is no allowlist check overprocess.argvanywhere in the file.
So sync-models.mjs --dry-rnu (or any unknown flag, e.g. --bogus-flag) is silently treated as a full APPLY run: it rewrites the target OpenCode config in place (bin/sync-models.mjs:693-696, after writing a .backup), including removals, and then triggers opencode reload (:700) — exiting 0 and printing "Successfully updated". The operator who typo'd the dry-run flag gets no signal the live config was just rewritten.
This is the same defect class already filed for the sibling deploy/install scripts — #3264 (pkarr-worker deploy.mjs), #3278 (opencode-claimant install.mjs), #3281 (id-mail worker deploy.mjs), #3287 (github-backup worker deploy.mjs) — but a different script none of them covers. The repo's shell tools already meet the stricter standard: lib/bws-to-sops.sh dies on unknown argument and scripts/stage-docs.sh exits 1 on an unknown option.
Evidence (verified this run)
Laptop probe ~/git/fleet/probe-2026-10-31-laneB-syncmodels/ (sync-models.mjs + sync-models.policy.json copied verbatim; sha256 f53c214ae40f9358113c19c9458b517a7859932f2e5cbbedee49b3d328d3ca5e / 73807ce822c1d477f02e9a9b9456141a5fcacc8f905954792204bba5b0a70590, matching main b56ccda5). Deterministic change source: temp HOME whose .codex/models_cache.json holds one model (probe-model-1) that the temp target config lacks; agy stubbed off via PATH; target config pointed at a temp file via OPENCODE_CONFIG_PATH:
- Control —
--dry-run:Mode: DRY-RUN (no files will be changed),+ Adding openai-codex/probe-model-1,Dry run complete. No files written., exit 0; config unchanged, no.backup. --dry-rnu:Mode: APPLY, same addition, thenCreated backup at …/config.jsonc.backupandSuccessfully updated …/config.jsonc!, exit 0; the config on disk now containsprobe-model-1.--bogus-flag: exit 0, identical APPLY outcome (backup written, config rewritten).
Why it matters
Unlike its PR-based successor (provider-catalog-sync.mjs, dry-run by default, changes land through a reviewable PR), this script edits the deployed config directly and auto-removes models the sources no longer list. A typo in the one safety flag turns a preview into an unreviewed rewrite of the live config plus an opencode reload, with a success exit code — the class of surprise the successor tool was built to eliminate, still reachable through the legacy path the service actually runs.
Acceptance criteria
- Any argument that is not
--dry-run,--verboseor-vmakes the script exit non-zero with a usage error naming the offending argument, before any fetch, discovery, or file write. --dry-run,--verbose/-v, and bare (APPLY) behavior is unchanged.- A stubbed/temp-HOME test (or equivalent) pins: unknown flag → non-zero exit + config untouched + no
.backup;--dry-run→ no writes even when changes exist.
Activity
dezren39 commentedon Nov 1, 2026
🤖 Agent note · filed
bin/sync-models.mjs(mainb56ccda5, sha256f53c214a…) reads--dry-run/--verbosebyprocess.argv.includesonly (sync-models.mjs:6-7) and never rejects unknown arguments. Laptop probe~/git/fleet/probe-2026-10-31-laneB-syncmodels/(temp HOME with a codex cache holding one model the temp target config lacks; agy stubbed off):--dry-run→ "Dry run complete. No files written.", config untouched;--dry-rnuand--bogus-flag→ exit 0 in APPLY mode after "Created backup" + "Successfully updated" with the model written into the config on disk. Same defect class as pkarr-worker(deploy): unrecognized arguments are silently ignored — a typo'd --dry-rnu or --deploy-version=<id> performs a real deploy of HEAD #3264 / opencode-claimant(install): unrecognized arguments are silently ignored — a typo'd --dry-rnu performs a real install, and a typo'd --stor writes the real OpenChamber store #3278 / id-mail(worker deploy): unrecognized arguments are silently ignored — a typo'd --dry-rnu enters the real deploy sequence and force-deletes the retired 'id-mail' Worker #3281 / github-backup(worker deploy): unrecognized arguments are silently ignored — a typo'd --dry-rnu performs a real deploy (upload + secret reset) #3287, but a different script none of them covers.dezren39 commentedon Nov 1, 2026
Adopted as Phase 1 of design #3352. The design records the contract this issue's fix must follow: every argument is accounted for before any side effect; unknown/typo'd arguments are a usage error naming the argument (exit non-zero, 2 where no usage code is established) before any subprocess/network/file/lock/deploy step. Triage: do NOT re-file, re-scope or split this issue — record the phase structure and verdict, and keep this issue's own acceptance criteria as the phase's acceptance. Design doc: files/designs/code-operator-argument-contract.md (keep-the-four-repos-healthy goal workspace).
dezren39 commentedon Nov 1, 2026
🤖 Agent note · picked up
6 remaining items
dezren39 commentedon Nov 2, 2026
🤖 Agent note · picked up
origin/main:bin/sync-models.mjsstill parses argv only at lines 6-7 with no validation.dezren39 commentedon Nov 2, 2026
🤖 Agent note · PR opened
bin/sync-models.mjs(only--dry-run,--verbose,-vaccepted; anything else exits 2 with a usage line naming the argument, before any fetch/discovery/backup/write). Tests inbin/sync-models.test.mjsadd temp-HOME probes for--bogus-flag,--dry-rnu, and a positional arg (fail non-zero, config byte-identical, no backup) plus--dry-runstill exits 0 writing nothing.node --test bin/sync-models.test.mjs— 10 pass, 0 fail. Manual temp-HOME probe:--bogus-flagexit 2 config unchanged;--dry-runexit 0 config unchanged.queue/5880-3297-sync-models-argv→main, commit4aaeeff62). No other sync behavior changed; service units untouched.Merge pull request #4379 from developing-today/queue/5880-3297-sync-m…
dezren39 commentedon Nov 2, 2026
🤖 Agent note · done — fixed and merged
c92785e); issue sync-models: unrecognized arguments are silently ignored — a typo'd --dry-rnu rewrites the live OpenCode config in place (and reloads opencode) #3297 is now CLOSED.node --test bin/sync-models.test.mjs10 pass / 0 fail; manual temp-HOME probe confirmed--bogus-flagexits 2 with the config byte-identical and--dry-runexits 0 writing nothing. PR checks showed only CodeRabbit neutral with merge state CLEAN at merge time.