Skip to content

Report an empty or half-written team file as incomplete - #2720

Merged
Birfy merged 1 commit into
mainfrom
dev/2716-core-an-empty-or-half-written-team-file
Nov 9, 2026
Merged

Birfy merged 1 commit into
mainfrom
dev/2716-core-an-empty-or-half-written-team-file

Conversation

@Birfy

@Birfy Birfy commented Nov 9, 2026 •

Copy link
Copy Markdown
Collaborator

Written-by: Dev

Fixes #2716

Owner: Dev
Reviewer: Reviewer

What changed

A state.json that parses but carries no version ({}, null, [], an empty string) was answered with saved by a newer FlyBot; update FlyBot: the person was told to update a program that is already current, and the repair that works — move the empty or half-written file aside — was never said. readFileState() now branches on the missing version before the fall-through and answers the team file has no version — it is incomplete (an empty or half-written file). The newer-version sentence stays for a version above STATE_VERSION ({"version":999} still reads saved by a newer FlyBot), and in both cases the file is not changed and no .broken- copy is left.

Verification at the tip

Tip SHA: bfee86c
Ran (TZ=UTC; DSH_HARNESS points at an existing core/dev/harness install because this checkout has no node_modules of its own):

  • cd core && node --import ./test/harness-resolve.mjs --test test/store.test.js → 39 pass, 0 fail. Before the source change the same file was 38 pass, 1 fail (a team file with no version is reported as incomplete, not as a newer FlyBot, actual: (saved by a newer FlyBot; update FlyBot)).
  • cd core && node --import ./test/harness-resolve.mjs --test test/install.test.js → 4 pass, 0 fail.
  • cd core && node --import ./test/harness-resolve.mjs --test test/diagnostics.test.js → 65 pass, 0 fail (its two newer FlyBot rows build a {"version":99} file, untouched by this change).
  • node scripts/ds-bot-patches.mjs check → ok 10 patches apply cleanly in order, ok core/ equals ds-bot/ + patches/ds-bot/.
  • node core/scripts/build-client.mjs --check → exit 0 (npm run build rewrote no byte; no client source touched).
  • cd core && npm run lint (oxlint half) → 0 errors; node scripts/lint-plugins.mjs → ok.
  • node .github/scripts/changelog.mjs check → 7 fragment(s) in changelog.d/ are well formed.
    Not run (and why): full npm run verify, node scripts/ds-bot-patches.mjs generate and canonical need git, and arch-docs needs git log origin/main..HEAD — this host has no git (and no ~/.dsh access is used). patches/ds-bot/0002-flybot-api-host.patch and patches/ds-bot/0014-flybot-branding.patch were updated by hand to the stored form and check reproduces core/ byte for byte, so canonical is the gate left to CI; docs/subsystems/core-host.md is updated in this diff, so arch-docs is covered. Smoke test not run: nothing under core/index.js or host startup changed.

Checkpoint

{
  "pr": 2720,
  "claim": "Dev",
  "issue": 2716,
  "summary": "A team file that parses but carries no version ({}, null, [], an empty string) now answers that it is incomplete, not that a newer FlyBot wrote it. The person is pointed at the file to move aside instead of at an update that cannot help. A version above STATE_VERSION keeps the newer-version sentence, and neither case changes the file or leaves a .broken- copy. A zero-byte or truncated file still takes its backup-and-load-fresh path, and tests in core/test/store.test.js cover all of it.",
  "files": [
    "core/src/host/store.js",
    "core/test/store.test.js",
    "patches/ds-bot/0002-flybot-api-host.patch",
    "patches/ds-bot/0014-flybot-branding.patch",
    "docs/subsystems/core-host.md",
    "changelog.d/2716-team-file-incomplete.fixed.md"
  ],
  "checks": { "ran": "store.test.js 39 pass, install.test.js 4 pass, diagnostics.test.js 65 pass, ds-bot-patches check, build-client --check, oxlint, lint-plugins, changelog check", "result": "green", "at": "bfee86c2b7c036d19325ba51177c667941b1e076" },
  "next": "none — ready for review"
}

A state.json that parses but carries no version ({}, null, [], an empty
string) fell through to the sentence a genuinely newer file gets, telling
the person to update a FlyBot that is already current. Branch on the
missing version before that fall-through and name the real repair: the
file is incomplete, so it has to be moved aside. The newer-version
sentence stays for a version above STATE_VERSION, and the file is still
never changed.

Fixes #2716
@Birfy Birfy added the agent-pr Pull request opened by an agent label Nov 9, 2026
@Birfy Birfy self-assigned this Nov 9, 2026
@Birfy

Birfy commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict: PASS at bfee86c
Written-by: Reviewer
Attestation: bfee86c role=Reviewer

Ran at this tip:

$ cd core && DSH_HARNESS=/data/dsh/bot/workspace/w2719/tip/core/dev/harness TZ=UTC node --import ./test/harness-resolve.mjs --test test/store.test.js
# tests 39  # pass 39  # fail 0
$ cd core && DSH_HARNESS=/data/dsh/bot/workspace/w2719/tip/core/dev/harness TZ=UTC node --import ./test/harness-resolve.mjs --test test/install.test.js
# tests 4  # pass 4  # fail 0
$ cp /data/dsh/bot/workspace/i2720/base-store.js core/src/host/store.js
$ cd core && DSH_HARNESS=/data/dsh/bot/workspace/w2719/tip/core/dev/harness TZ=UTC node --import ./test/harness-resolve.mjs --test test/store.test.js
# tests 39  # pass 38  # fail 1
$ node scripts/ds-bot-patches.mjs check
ok 10 patches apply cleanly in order; ok core/ equals ds-bot/ + patches/ds-bot/

Review points, at bfee86c2b7c036d19325ba51177c667941b1e076:

  • core/src/host/store.js:250-254: the new parsed?.version === undefined branch sits after the version === 1 branch (:224) and the version === STATE_VERSION branch (:240), and the diff is +6 lines with no other change, so the v1 migration and the current-version accept path are untouched. parsed?.version === undefined catches {}, null, [] and ""; {"version":999} still reaches store.js:256, and core/test/store.test.js:208 still asserts saved by a newer FlyBot; update FlyBot and passes.
  • Red first: with core/src/host/store.js swapped back to the base blob from 214b2273 and the new tests kept, store.test.js goes 38 pass / 1 fail. Failure line: not ok 38 - a team file with no version is reported as incomplete, not as a newer FlyBot; actual: 'The Bot team file /tmp/ds-bot-store-taq2uB/state.json could not be read (saved by a newer FlyBot; update FlyBot). FlyBot does not change it; fix or move the file and reload.' The source was restored byte for byte afterwards.
  • Coverage: core/test/store.test.js:677 loops {}, null, [], "", asserting the incomplete sentence, no newer FlyBot, a byte-identical file after the attempted save, and no .broken- copy. :696 covers zero-byte and truncated input.
  • Zero-byte note: the issue's last line asks for a 0-byte file to get the incomplete sentence, and this PR deliberately does not do that. A 0-byte file never parses, so it fails JSON.parse before the version branches and keeps the Host files take the ambient umask: team state, Bot memory, chat index and OCR cache are world-readable, and a rewrite widens a 0600 #2697/core: one room record without members makes load() reject for the life of the process #2714 path — copied to state.json.broken-<stamp>, then loaded fresh and writable (audit48/out/1-store-shapes.txt "### 4 zero bytes": readOnly: null, backup listed). It never showed the wrong sentence, and routing it to the new read-only branch would remove that recovery. docs/subsystems/core-host.md:237 and the changelog both state this. Reviewer judges that correct; the literal 0-byte acceptance line is not met and should not be.
  • Scope: 214b2273...bfee86c2 is one commit, 6 files, exactly the PR's list; ds-bot-patches check reproduces core/ from patches/ds-bot/. Tip checks are all green except enqueue-guard, whose only refusal is no Verifier report names the tip bfee86c2b7c0 — this PASS is that report. agent-pr is set and the checkpoint block is valid (6 files, checks.at a 40-character sha, 1181 characters).

Not run: full npm run verify / generate / canonical (this host has no git); the affected store.test.js and install.test.js, the source-only red run, and the patch check above cover the change.

@github-actions github-actions Bot added the pass label Nov 9, 2026
@Birfy
Birfy added this pull request to the merge queue Nov 9, 2026
Merged via the queue into main with commit 2a08170 Nov 9, 2026
19 of 21 checks passed
@Birfy
Birfy deleted the dev/2716-core-an-empty-or-half-written-team-file branch November 9, 2026 01:43
@github-actions github-actions Bot removed the agent-pr Pull request opened by an agent label Nov 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

core: an empty or half-written team file is diagnosed as "saved by a newer FlyBot; update FlyBot"

1 participant