feat: blockchain-inspired World Ledger for agent activity tracking#92
feat: blockchain-inspired World Ledger for agent activity tracking#92Jing-yilin wants to merge 2 commits intofeat/domain-separated-signingfrom
Conversation
Append-only event ledger with hash chain and world signatures: - WorldLedger class: genesis block, hash chain (SHA-256), Ed25519-signed entries - Events: world.genesis, world.join, world.leave, world.evict, world.action - State derived from event replay (getAgentSummaries) - Persisted as JSON Lines (.jsonl), survives server restarts - Chain integrity verification (verify()) - HTTP endpoints: /world/ledger (with filtering), /world/agents - Auto-integrated into world-server.ts onMessage handlers - 13 new tests covering chain integrity, persistence, tampering, filtering Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Jing-yilin
left a comment
There was a problem hiding this comment.
Codex Review
[High] Corrupted/truncated ledger tails are silently discarded and verify() still reports success
WorldLedger.load() swallows JSON parse failures and just keeps the valid prefix in memory. That means a partial append or truncated tail line is treated as if it never existed, and verify() only checks the surviving prefix. I reproduced this by appending an invalid JSON fragment to a valid ledger file: the reloaded ledger dropped the broken line, length shrank to 2, and verify() still returned { ok: true }. For an append-only integrity feature, silently accepting data loss like this defeats the tamper/crash detection story.
Refs: packages/agent-world-sdk/src/world-ledger.ts:41, packages/agent-world-sdk/src/world-ledger.ts:166
[Medium] /world/agents reports stale agents as online after a server restart
getAgentSummaries() derives online purely from the durable event log, and /world/agents returns that value directly. After a restart, agentLastSeen is empty, but any agent whose last persisted event was world.join is still exposed as online: true until another leave/evict entry is appended. I reproduced this by starting createWorldServer, appending a join, stopping it, starting a new server against the same dataDir, and hitting /world/agents; the second process reported the old agent as online even though no session had rejoined.
Refs: packages/agent-world-sdk/src/world-ledger.ts:121, packages/agent-world-sdk/src/world-server.ts:204
[Low] The new HTTP API never applies the advertised until filter
LedgerQueryOpts supports an upper time bound, but /world/ledger only parses agent_id, event, since, and limit. The SDK method can filter by until; the HTTP endpoint cannot, so the public API doesn’t match the documented/queryable surface promised by this PR.
Refs: packages/agent-world-sdk/src/types.ts:181, packages/agent-world-sdk/src/world-server.ts:188
Verification run:
npm --prefix packages/agent-world-sdk run buildnpm run buildnode --test test/*.test.mjs
- [High] verify() now detects corrupted/dropped lines via corruptedLines counter and seq gap detection — truncated ledger no longer silently passes verification - [Medium] getAgentSummaries(liveAgentIds?) accepts optional live session set; /world/agents passes agentLastSeen keys so online status reflects reality after restart - [Low] /world/ledger endpoint now parses the 'until' query parameter - 2 new tests: corrupted line detection, liveAgentIds online status Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Summary
Append-only event ledger with hash chain and world signatures, inspired by blockchain design.
Core Design
world.genesisentry on world startupprevHash(SHA-256 of previous entry)Changes
New:
WorldLedgerclass (packages/agent-world-sdk/src/world-ledger.ts).jsonlgetAgentSummaries()— derive current state from event replayverify()— validate entire chain integrityIntegration into
world-server.tsGET /world/ledger— query ledger entries with filtersGET /world/agents— agent summaries derived from ledgerWorldServerreturn valueTypes (
types.ts)LedgerEntry,LedgerEvent,AgentSummary,LedgerQueryOptsTests (
test/world-ledger.test.mjs)Test Results
144/144 tests pass (131 existing + 13 new)