Skip to content

Sync runtime history portably on macOS - #798

Merged
luisleo526 merged 3 commits into
mainfrom
fix/macos-runtime-history-sync
Nov 10, 2026
Merged

luisleo526 merged 3 commits into
mainfrom
fix/macos-runtime-history-sync

Conversation

@luisleo526

Copy link
Copy Markdown
Collaborator

Engine v1.11.0's source does not compile on macOS: src/runtime_context.cpp calls ::fdatasync in the runtime history flush, and macOS does not declare it (error: no member named 'fdatasync' in the global namespace). The engine's own CI has no macOS leg, so it showed up only in a downstream macOS build. Engine release archives are Linux-only and are not affected.

Change

  • src/runtime_context.cpp: on Apple platforms the flush uses fcntl(F_FULLFSYNC) with an fsync fallback, the pattern the other fdatasync users in the engine already carry. The EINTR retry and the storage error on failure are kept. The non-Apple fdatasync loop is unchanged.
  • scripts/test_native_source_guard.py: a source guard that fails when an engine source calls fdatasync without an Apple branch.

Red first

  • The guard alone (first commit) fails on engine main 51919507 at src/runtime_context.cpp; with the fix (second commit) it passes.
  • The macOS compile itself is checked by a downstream macOS build with the engine at this head before merge.

🤖 Generated with Claude Code

luisleo526 and others added 2 commits November 10, 2026 07:36
Adds a source guard to the native source guard tests: any engine source
that calls fdatasync must also provide a branch for Apple platforms,
where fdatasync is not declared. On engine main 5191950 the guard fails
on src/runtime_context.cpp; the runtime source is unchanged here.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The runtime history flush called ::fdatasync unconditionally, which does
not compile on macOS ("no member named 'fdatasync' in the global
namespace"). On Apple platforms it now uses fcntl(F_FULLFSYNC) with an
fsync fallback, the same pattern the other fdatasync users in the engine
already carry, keeping the EINTR retry and the storage error on failure.
The non-Apple fdatasync loop is unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 2 advisory finding(s) below merit a look before merge.

Not checked: tests were not run; no formal proof of the changed code.


Graphify review — findings

Fixes runtime history flushing on Apple by switching flush_pages to F_FULLFSYNC with an fsync fallback and an EINTR retry loop, while other platforms keep the fdatasync loop. The fallback means a failed or interrupted full sync can drop to the weaker fsync guarantee, which is the durability risk in this path. Adds a portability scan to scripts/test_native_source_guard.py that parses #if/#elif/#else conditions to reject any ::fdatasync call still reachable on Apple. It fails closed on unreadable input, symlinks, empty source trees, or zero calls found, and runs an 18-case self-test before the real scan. Teaches _mask_cpp to skip C++17 digit separators like 1'024 so they are no longer mistaken for character-literal quotes.

Worth a look

  • Interrupted F_FULLFSYNC can silently fall back to weaker fsync — src/runtime_context.cpp:270 · Escalate · medium
    • unverified hypothesis — survived the adversarial refute pass; needs human review
  • Full-sync errors are silently downgraded — src/runtime_context.cpp:272 · Escalate · medium
    • unverified hypothesis — survived the adversarial refute pass; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 91 functions depend on the 89 functions this change touches.

Health — this change adds coupling hotspots:

  • worse: main() — 1 callers, 6 callees

Verification — 91 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 91 function(s) in the blast radius were not formally verified this run

Test selection

Test selection

3 of 1400 test file(s) selected (0%) via static blast radius.

  • scripts/test_native_source_guard.py — impact, changed-test
  • tests/test_request_feed_inventory_admission.py — impact
  • tests/test_runtime_context.cpp — impact

Selection is safe under the controlled-regression assumption; always-run tests + a periodic full run are the backstops. Advisory — it never changes the check verdict.

Docs that may be stale (advisory)

· 1 grounded finding(s) anchored inline below.

@@ -363,6 +573,8 @@ def self_test() -> int:
def main() -> int:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression — main()

fans out to 6 callees (efferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Update the two symbol citations after an import shifted their definitions.
The documentation's scope, checker, assertions and runtime are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@luisleo526
luisleo526 merged commit f5e929d into main Nov 10, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant