Repository navigation
fix(config): refuse mutation after an existing configuration read fails - #1007
Conversation
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
PR SummaryMedium Risk Overview Missing files and successful reads behave as before: absent config still falls back to defaults, cached in-memory config, or empty Adds serialized SDK tests ( Reviewed by Cursor Bugbot for commit 0e7c77f. Bugbot is set up for automated code reviews on this repo. Configure here. |
|
Codex review: needs maintainer review before merge. Reviewed October 8, 2026, 3:12 AM ET / 07:12 UTC (Revision 2). ClawSweeper reviewWhat this changesThe branch refuses provider and configuration mutations when an existing configuration file cannot be read, while preserving missing-file fallbacks. Example: Add provider owned-public-new with a truncated config.json
Review scores
ProductKind: Bug fix · Worth it: Yes · Fix scope: Complete Merge readiness✅ Ready for maintainer review This PR remains useful: current main still permits the destructive overwrite, and the added public CLI transcript resolves the previous proof blocker. No actionable patch defect remains. Priority: P2 Before mergeNone. FindingsNone. Agent review detailsHow this fits togetherPeekaboo shares saved configuration between its CLI, macOS app, and automation SDK. Provider changes and settings updates read this configuration, modify it, and write it back to disk. flowchart TD
A[Provider or settings update] --> B[Read saved configuration]
B --> C{Read succeeded?}
C -->|Yes| D[Modify loaded settings]
C -->|No| E{File still exists?}
E -->|Yes| F[Return error and preserve file]
E -->|No| D
D --> G[Save configuration]
Technical reviewBest possible solution: Keep failed-read protection inside the existing serialized mutation boundary, preserving valid settings, missing-file creation, and explicit reset behavior. Do we have a high-confidence way to reproduce the issue? Yes: current source returns nil on decoding or read failures, then mutation paths fall back and save replacement configuration. Contributor baseline evidence records the corresponding destructive results; this review did not execute them. Is this the best way to solve the issue? Yes: a shared guard before mutation is a narrow repair that retains the existing loader, locking, serialization, and missing-file behavior. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against c02c26927d77. Provenance checked
TestingProof path: shipped entry point. Added test files: 1. SecurityNone. EvidenceWhat I checked:
Likely related people:
Review metrics
LabelsLabel changes:
Label justifications:
Rating scale6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior. WorkflowClawSweeper edits this one comment on every review. Comment HistoryReview history (1 earlier review cycle)
|
|
Added the requested real public CLI AFTER proof to the PR body, including copied actual terminal receipts and JSON refusal output so it does not depend on access to hosted job artifacts. The unchanged ordinary macOS workflow built the real CLI from a tests-only validation branch at No upstream production change or additional upstream PR was needed for this proof. @clawsweeper re-review |
|
Landed as 81bce40. Thanks @rudycelekli! Verification: I confirmed |
A Peekaboo CLI binary invoked under any name not ending in "peekaboo" (a copy such as peekaboo-before, or a symlink such as pb -> peekaboo) rejected every command with "Unknown command '<its own path>'", because CommanderRuntimeRouter dropped argv[0] only when it hasSuffix("peekaboo"). The CLI entry points now take full argv and always drop exactly the executable element; the same heuristic is removed from agent default-subcommand normalization and result-envelope classification. A caller audit found only two tail-only callers (both tests), now passing an executable name.
Also adds the changelog credits for #1006 and #1007.
Tests: CommanderRuntimeArgvTests plus expanded resolution/classification tests cover absolute paths, pb, peekaboo-4.9, peekaboo-before and the peekaboo forms (141 assertion failures against the old code); focused swift test 78 tests in 7 suites; manual copied-binary and real pb symlink --version/see --help; Codex autoreview scoped-clean; hosted CI and CodeQL green.
Summary
Provider add/remove and
updateConfigurationcan overwrite an existing configuration after loading it fails. A truncated JSON file, invalid field type or permission-denied read producesnil, which the mutation paths treat as a missing file or replace with cached data.Refuse these mutations when loading failed and the configuration file still exists. The error occurs before the update closure or write. Missing files still use the existing defaults/cached fallback. The lenient loading API and explicit reset operation remain unchanged.
Native evidence
peekaboo config provider addon owned files: three failed reads previously returned success and replaced the files; four valid JSON/JSONC, missing-file and dry-run controls passed. CLI remove has an earlier guard and is not claimed affected.0e7c77f4902493adef925f80d757d809b3a4eec9, all 23 cases pass. The ten failed reads refuse mutation, preserve independently hashed file bytes and never enter the update closure. Permission cases ran as UID 501 with ownedchmod 000fixtures restored afterward.Verification
swiftformat --lint: no files require formatting (2,089 checked).swiftlint: 112 existing warnings, zero serious violations.pnpm run test:safe(2,266 tests / 271 suites) and execution of the new SDK owner.Baseline expected failures were qualification evidence, not acceptance. Final acceptance ran the real complete SDK on hosted macOS; no local Swift rebuild, UI permission or hardware behavior is claimed. The two production files and unchanged regression owner received independent source/evidence review before signing. No workflows, manifests, locks or submodules change.
Public CLI AFTER proof requested in review
The proof is in a tests-only validation branch in our fork at
0b9b72286638b0e4e5e3e5febd2954a9738ac961(owner diff). Both production files, the original SDK owner prefix, manifests, workflows, locks and submodules are byte-identical to this PR's0e7c77f4902493adef925f80d757d809b3a4eec9tree. The ordinary macOS workflow built the real CLI and suppliedPEEKABOO_CLI_BINARY; all seven new process cases actually executed as UID 501.Command used for each owned fixture (with
--dry-runadded for that control):Each process receives only an owned HOME/TMP/config directory, a whitelisted PATH, and migration-disabled setting. This config command makes no provider request. The child is waited for and the owned fixtures/permissions are restored and removed afterward.
Copied actual terminal receipts below (same built binary SHA-256 for all cases):
Actual truncated-file JSON error excerpt (only the owned temporary path is redacted):
{ "error" : { "code" : "ADD_FAILED", "message" : "Failed to add provider: File I\/O error: Unable to read existing configuration at <owned-config>/config.json. Refusing to replace it." }, "data" : null, "debug_logs" : [ "[2026-10-08T06:22:35.418Z] DEBUG: Runtime host: local (in-process)" ], "success" : false }Truncated/wrong-type/unreadable files return failure and preserve exact bytes. Valid JSON/JSONC preserve custom/default/logging/environment-reference values while adding the provider; absence creates config; dry-run succeeds without writing. The existing 23 SDK cases pass again.
At the tests-only proof head, all unchanged mandatory groups pass: ordinary six jobs, CodeQL three jobs, and supplemental four groups including the actual full safe suite. This proof branch does not change the submitted production fix and does not create another upstream PR.