mirror of
https://github.com/vercel-labs/fx.git
synced 2026-10-28 10:15:17 +08:00
`--resume last` stopped at a stale schema-v3 session whose committed log cannot be replayed: listing ranks it by its manifest, and opening it fails. It now skips a candidate that listing cannot read either and resumes the next newest session. A session behind an interrupted upgrade still reports its boundary error, and a busy session is still returned. When nothing readable remains, the message says this workspace has no readable saved sessions and that some saved sessions are unreadable. `fx doctor` now replays a stale schema-v3 session and reports it when the log cannot be replayed, so the doctor hint points at the session latest resume skipped. The session index's internal constants and helpers are no longer public, the benchmark fixture stops computing the removed stat fingerprint, and one e2e test title now matches what it checks.
122 lines
4.2 KiB
Python
122 lines
4.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Generate projected schema-v3 sessions around large sparse event logs."""
|
|
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
|
|
|
|
def write_private_json(path: Path, value: object) -> None:
|
|
path.write_text(json.dumps(value, separators=(",", ":")) + "\n", encoding="utf-8")
|
|
path.chmod(0o600)
|
|
|
|
|
|
def generate(home: Path, workspace: Path, count: int, log_size: int, deny_event_read: bool) -> None:
|
|
sessions_root = home / ".fx" / "sessions"
|
|
sessions_root.mkdir(parents=True, mode=0o700, exist_ok=True)
|
|
(home / ".fx").chmod(0o700)
|
|
sessions_root.chmod(0o700)
|
|
|
|
for index in range(count):
|
|
session_id = f"benchmark-session-{index:02d}"
|
|
authority_id = f"{index + 1:032x}"
|
|
generation = f"{index + 101:032x}"
|
|
session_dir = sessions_root / session_id
|
|
session_dir.mkdir(mode=0o700)
|
|
|
|
for lock_name in ("session.lock", "commit.lock"):
|
|
lock = session_dir / lock_name
|
|
lock.touch(mode=0o600)
|
|
lock.chmod(0o600)
|
|
|
|
event_log = session_dir / "events.jsonl"
|
|
with event_log.open("wb") as file:
|
|
file.truncate(log_size)
|
|
event_log.chmod(0o000 if deny_event_read else 0o600)
|
|
|
|
write_private_json(
|
|
session_dir / "authority.json",
|
|
{
|
|
"schema_version": 1,
|
|
"session_id": session_id,
|
|
"authority_id": authority_id,
|
|
"storage_format": "event_log_v1",
|
|
"source": "native_create",
|
|
},
|
|
)
|
|
watermark = session_dir / f"commit.{generation}.json"
|
|
write_private_json(
|
|
watermark,
|
|
{
|
|
"schema_version": 1,
|
|
"session_id": session_id,
|
|
"log_generation": generation,
|
|
"through_seq": 1,
|
|
"through_event_id": f"{index + 201:032x}",
|
|
"through_event_log_bytes": log_size,
|
|
},
|
|
)
|
|
if deny_event_read:
|
|
watermark.chmod(0o000)
|
|
write_private_json(
|
|
session_dir / "session.json",
|
|
{
|
|
"schema_version": 3,
|
|
"storage_format": "event_log_v1",
|
|
"id": session_id,
|
|
"authority_id": authority_id,
|
|
"log_generation": generation,
|
|
"created_at_ms": 1000 + index,
|
|
"updated_at_ms": 2000 + index,
|
|
"origin_workspace_root": str(workspace),
|
|
"workspace_root": str(workspace),
|
|
"conversation_language": "en",
|
|
"history_len": index,
|
|
"total_input_tokens": 0,
|
|
"total_output_tokens": 0,
|
|
"last_event_seq": 1,
|
|
"event_log_bytes": log_size,
|
|
# fx decides staleness by log size and reads no stat identity.
|
|
"event_log_stat_fingerprint": "00" * 32,
|
|
"generation_base_seq": 1,
|
|
"generation_base_bytes": log_size,
|
|
"checkpoint_seq": None,
|
|
"checkpoint_sha256": None,
|
|
"preferences": {
|
|
"model": "anthropic/claude-opus-4.7",
|
|
"effort": "auto",
|
|
"fast_mode": False,
|
|
},
|
|
},
|
|
)
|
|
write_private_json(
|
|
session_dir / "display.json",
|
|
{
|
|
"schema_version": 1,
|
|
"title": f"Benchmark session {index:02d}",
|
|
"preview": f"Benchmark session {index:02d} preview",
|
|
"origin_workspace_root": str(workspace),
|
|
},
|
|
)
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--home", required=True, type=Path)
|
|
parser.add_argument("--workspace", required=True, type=Path)
|
|
parser.add_argument("--sessions", type=int, default=8)
|
|
parser.add_argument("--log-size", type=int, default=256 * 1024 * 1024)
|
|
parser.add_argument("--deny-event-read", action="store_true")
|
|
args = parser.parse_args()
|
|
generate(
|
|
args.home.resolve(),
|
|
args.workspace.resolve(),
|
|
args.sessions,
|
|
args.log_size,
|
|
args.deny_event_read,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|