Repository navigation
fix(automation): empty and id-less automation.toml are unreadable; keep file mode; write through links - #10
Conversation
…le mode and links T-20261107-490692877 (finding of the review of #9). A definition that is empty, only a comment, only whitespace, has no id, an empty or non-string id, only a table, or an id that differs from its folder name is not a readable record: it must be unparseable with its own message ('empty' / 'missing id' / 'id mismatch'), and pause-active, activate-all and restore-ccc must never write into it (bytes unchanged, no temp file). _set_status revalidates right before writing. find_automation_anomalies reports empty and id-less files but keeps the duplicate-id detection (id and folder name may differ there). _write_toml copies the mode of the original to the temp file before os.replace (mkstemp makes 0600) and writes to the resolved target of a link. Against c381595 the 45 new tests: 40 fail and 5 are skipped on this Windows host (four POSIX mode tests, one real symlink test); on Linux (WSL, no skips) 44 of the 45 fail. Refs: T-20261107-490692877 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01THB2EysTVQFXz5moenpBvW
…ep file mode; write through links T-20261107-490692877. A truncated automation.toml parses as valid TOML and counted as a record with status UNKNOWN, so activate-all would have written 'status = "ACTIVE"' into it and "repaired" a broken definition with a status. - _read_automation() requires keys, a non-empty string id and (for everything that writes) an id that matches the folder name; otherwise AutomationDefinitionError with the messages 'empty', 'missing id' or 'id mismatch', handled like every other unreadable definition (listed in errors/unparseable_ids, status never ok, nothing written). - _set_status() reads through it, so a file truncated between scan and write is not overwritten. - find_automation_anomalies() reports empty and id-less files as unreadable but still lets the id differ from the folder name (needed for the duplicate-id detection). - _write_toml() copies the mode of the original to the temp file before os.replace (mkstemp creates 0600) and replaces the resolved target of a link, so the link stays. The red tests of e67d735 pass: 65 passed on Linux (WSL, including the four POSIX-mode tests and the symlink test), 60 passed and 5 skipped on Windows; related files (health, orchestrator, tray, metadata, docs contracts, exchange contract) 162 passed. ruff clean. Refs: T-20261107-490692877 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01THB2EysTVQFXz5moenpBvW
|
Welcome! 👋 Thanks for your first pull request in this repository. A maintainer will review it soon. Please make sure:
Thanks for contributing! |
…link adds a prefix The Python jobs of the CI (Windows runners, which may create links) ran the real symlink test and failed on one assertion only: os.readlink() returns the target with the extended-length prefix '\\?\' there, so the Path comparison differed although the link was kept and the target updated. Compare with resolve() and os.path.samefile() instead. Windows 60 passed / 5 skipped locally, Linux (WSL) 65 passed. Refs: T-20261107-490692877 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01THB2EysTVQFXz5moenpBvW
|
Independent review at Base reproduced: Own probe: 9 cases, temp
On the Independent review by Claude Opus 5.5 (claude-opus-5-5). Posted with the owner's account (the bot account is suspended), so this is a comment, not a formal review. |
… (r1 finding PR #10) Unter Windows vererbt _write_toml das Nur-Lesen-Attribut des Originals vor dem os.replace auf die tmp-Datei. os.replace scheitert dann mit WinError 5, das Aufraeumen (unlink) scheitert an der schreibgeschuetzten tmp-Datei ebenfalls: es bleibt automation.toml.<x>.tmp liegen, und die Fehlermeldung nennt nur diese tmp-Datei statt des Ersetzens in das Ziel. Das Original bleibt unveraendert, der Status ist failed. Der Test ist rot: der Ordner enthaelt nach dem Lauf noch die tmp-Datei. Er prueft ausserdem, dass der Fehlertext mit dem Zielpfad endet (Text von os.replace), nicht mit der tmp-Datei. Nur unter Windows (unter POSIX ersetzt os.replace auch eine schreibgeschuetzte Datei). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01THB2EysTVQFXz5moenpBvW
…-only attribute (r1 finding PR #10) Beim Aufraeumen nach einem fehlgeschlagenen Austausch wird die tmp-Datei zuerst beschreibbar gemacht, dann geloescht. Fehler beim Aufraeumen ersetzen den urspruenglichen Fehler nicht mehr (der Text von os.replace nennt das Ziel). Das Original bleibt unveraendert; es bleibt kein automation.toml.<x>.tmp liegen. Macht den roten Test aus 3ce9616 gruen. Gewaehlt ist der Aufraeumweg (chmod im except) statt den Modus erst nach dem os.replace zu setzen: so traegt das Ziel nie, auch nicht kurz, die 0600 von mkstemp, und ein fehlschlagendes chmod nach dem Austausch kann keine ersetzte Datei mit falschem Modus hinterlassen. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01THB2EysTVQFXz5moenpBvW
Holt #11 (CodeQL-Workflow entfernt) in den Branch, damit der rote analyze-Check (Advanced-Workflow gegen Default Setup) auf diesem PR verschwindet. Einziger Konflikt: CHANGELOG.md, beide Eintraege unter Unreleased bleiben erhalten. Ohne Force-Push. Geprueft im Merge-Stand: pytest 579 passed, 6 skipped; ruff check sauber. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01THB2EysTVQFXz5moenpBvW
|
Nacharbeit zum Befund von r1 (schreibgeschützte Reproduziert (Scratch-Verzeichnis, keine echten Commits
Warum der Aufräumweg statt „Modus erst nach dem Replace setzen“: So trägt das Ziel nie, auch nicht kurz, die 0600 von Prüfung (Windows, Merge-Stand): Kein Merge durch mich; r1 prüft erneut. 🤖 Generated with Claude Code |
|
Re-review at |
What
T-20261107-490692877, a finding of the review of #9. A truncated
automation.tomlparses as valid (empty) TOML. It counted as a readable record with statusUNKNOWN, andactivate-allwould have writtenstatus = "ACTIVE"into it: a broken definition "repaired" with a status._read_automation()(used byscan_automations(),find_automation_anomalies()and_set_status()) rejects: an empty file, a file with only a comment or whitespace, a missing, empty, blank or non-stringid, a file with only a table, and anidthat differs from the folder name (casefolded). They end up inUnparseableAutomationwith their own message (empty,missing id,id mismatch), inerrorsandunparseable_idsof every action result (sostatusis neverok), and nothing is written into them._set_status()checks the file again right before writing, so a file that was truncated between the scan and the write is not overwritten.find_automation_anomalies()reports empty and id-less files as unreadable too, but lets theiddiffer from the folder name: the duplicate-id detection needs exactly that (existing testfolder-a/folder-bwithid = "dupe")._write_toml()copies the mode of the original to the temp file beforeos.replace(mkstempcreates 0600)._write_toml()replaces the resolved target of a link and leaves the link alone. Since fix(automation): report unreadable automation.toml instead of skipping it; write it atomically #9os.replaceonto a symlink path would silently turn the link into a regular file and leave the target unchanged.No real Codex files are touched; every test uses temp data.
Tests
Red first (
a159200), then the fix (91cea15). 45 new tests intests/test_automation_control.py:pause-active,activate-all,restore-ccc(27): bytes unchanged, own message,unparseable_ids, status notok, no temp file left;chmodon the temp file thenos.replace(all platforms), write through a link (real symlink where allowed, plus a platform-independent test that resolves a path the way a link would).Against
c381595: 40 of the 45 fail and 5 are skipped on Windows without the right to create links; on Linux (WSL, no skips) 44 of the 45 fail. After the fix: Linux 65 passed intests/test_automation_control.py(the four POSIX-mode tests and the symlink test run), Windows 60 passed and 5 skipped. Related files (health, orchestrator, tray, metadata, docs contracts, exchange contract, the bugsweep resilience test): 162 passed, 5 skipped.ruff check src testsclean. The full suite was not run (targeted groups only).For the reviewer
Worth attacking: an
idthat differs only by case or by surrounding whitespace; a definition that is valid but has nostatus(still a record,activate-alladds the key as before); the revalidation window between scan and write; the link behaviour on Windows junctions;restore-cccwith a remembered id whose file became empty (the id stays remembered, as for other unreadable files).Residual risk: a folder name that differs from the id in real Codex data now blocks the automation from being paused or restored (reported as
id mismatch); the old code accepted it and could address the wrong file when two folders share an id.The CodeQL follow-up (T-20261107-558181168) is a separate PR.
🤖 Generated with Claude Code
https://claude.ai/code/session_01THB2EysTVQFXz5moenpBvW