Skip to content
This repository was archived by the owner on Jul 27, 2026. It is now read-only.

fix(fleet-state): create .bak before write + validate TMP before promote (replay of e0e326f) - #32

Open
antfleet-ops wants to merge 1 commit into
mainfrom
replay/fleet-state-bak-e0e326f
Open

fix(fleet-state): create .bak before write + validate TMP before promote (replay of e0e326f)#32
antfleet-ops wants to merge 1 commit into
mainfrom
replay/fleet-state-bak-e0e326f

Conversation

@antfleet-ops

Copy link
Copy Markdown

Bench replay of upstream aaronjmars/aeon#203 (commit e0e326f).

This PR triggers AntFleet's review pipeline against aeon's .bak + TMP-validate change. Patch Agent v1.5 is enabled for this install as the v1.5 canary — expect a suggestion block in the review comment when both reviewers (Opus 4.7 + GPT-5) agree on a localized fix.

Source: https://github.com/aaronjmars/aeon/pull/203

…ote (aeonfun#203)

The persist-state step in `skills/fleet-state/SKILL.md` declared
"keep one `.bak` rolling. If `jq empty` fails after write → restore from
`.bak`" — but nothing in the step ever created the `.bak`. The
sequence was `mv $TMP ...json` first, then `jq empty` validation on
the live file, with rollback attempting `cp ...json.bak ...json`.

Two issues this caused:

1. On any failed validate, the rollback `cp` would silently fail
   (no source) and the operator would be left with a corrupt
   `fleet-state.json` and no recovery path. Subsequent fleet-state runs
   read this file as the baseline — so once corrupt, the historical
   bucket totals and spotlight rotation pointer would stay wrong for
   every following week.

2. Even when the new content was bad, the live file was already
   overwritten (the `mv` runs before validation), so the previous
   week's state was unrecoverable.

This change:

- Adds a `cp …json …json.bak` step BEFORE the write attempt, so the
  rollback path always has a non-empty backup. Runs every persist
  iteration as a rolling backup.
- Moves the `jq empty` check from "after `mv`" to "before `mv`" — the
  candidate JSON is validated in the temp file, and only promoted if
  valid. If it's invalid, the temp file is discarded and the live
  file is restored from `.bak` defensively.

Net effect: a malformed jq output now leaves the live file at the
prior good state instead of replacing it with a corrupt blob.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: antfleet-ops <285575208+antfleet-ops@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@antfleet

antfleet Bot commented May 22, 2026

Copy link
Copy Markdown

AntFleet · 2 findings

Both reviewers flagged the items below on the changed files. AntFleet posts only what two independent frontier models agree on.


Bug · High — jq pipeline for SPOTLIGHT_PICK fails when history is empty
skills/fleet-state/SKILL.md:113-117

If contributor-spotlight history is empty, SPOTLIGHT_PICK becomes an empty string. Piping empty input to jq (without -n) causes a parse error and a non-zero exit, aborting the run. This violates the "degrade gracefully" intent.

Fix: Avoid echo | jq on possibly empty input. Either extract both fields directly from the file with a single jq call (e.g., jq -r '(.history | sort_by(.featured_at) | .[-1]) // {} | [.fork, .featured_at] | @TSV' ...) or guard: if [ -n "$SPOTLIGHT_PICK" ]; then ... fi. Alternatively, use jq -n with inpu…


Docs-gap · Low — Step 2 'Resolve parent repo' contradicts the Sandbox note's no-gh-api claim
skills/fleet-state/SKILL.md:79-86

The Sandbox note asserts the skill performs 'No gh api calls,' but Step 2 explicitly runs gh api repos/... (and gh repo view) to resolve the parent repo when PARENT_OVERRIDE is empty. This is a deceptive doc — an operator reading the security/sandbox section would believe the skill is hermetic local I/O when in fact it shells out to GitHub on every non-override run.

Fix: Either remove the gh api invocation in Step 2 (e.g., cache PARENT_REPO from an existing state file, or require the override), or update the Sandbox note to declare the single gh api repos/<self> call used purely to discover the parent repo's full_name.

Review 1939cc1e · claude-opus-4-7 + gpt-5 (unanimous) · 265s · ~$0.40

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant