Skip to content

feat(contract): machine-readable ACP block contract — schemaVersion + ./contract export (#368) - #369

Open
ranxianglei wants to merge 1 commit into
masterfrom
2026-09-11_acp-block-contract
Open

feat(contract): machine-readable ACP block contract — schemaVersion + ./contract export (#368)#369
ranxianglei wants to merge 1 commit into
masterfrom
2026-09-11_acp-block-contract

Conversation

@ranxianglei

Copy link
Copy Markdown
Owner

Machine-readable, versioned contract for ACP compression blocks — closes #368. Purely additive; zero behavior change (no sidecar relocation, no pi-integration change, no version bump).

Downstream tools (e.g. pi-billion-memory) today glob ~/.pi/agent/sessions/**/*.jsonl.acp.json and parse private fields. This gives them a stable boundary so a field rename or path move degrades loudly (version mismatch) instead of silently scanning 0 files and surfacing back as a “did bcp change the format?” issue.

R1 — versioned sidecar envelope

Every <session>.acp.json now carries a top-level { schemaVersion, producer:{name,version} }, written at the single choke point SessionStateStore.save() (src/state.ts). Semantics:

  • missing schemaVersion == v1 — legacy files keep loading unchanged;
  • unknown/higher version → bcp stays tolerant (loads known fields) but logs unknown-schema-version once per file, so a downgrade is observable rather than silent;
  • bump only on breakage (rename/remove/re-semantic); otherwise additive-only, never bumps.

R2 — public exports + JSON Schema

New subpath billion-context-pi/contract:

import { SCHEMA_VERSION, PRODUCER_NAME, BcpBlockV1, createSidecarEnvelope } from "billion-context-pi/contract";

Plus schema/bcp-block-v1.json (JSON Schema, shipped in the npm package via files). BcpBlockV1 required stable core: blockId, summary, tier, compressedTokens, createdAt (epoch milliseconds, not ISO 8601); optional topic / startRef / endRef / effectiveMessageIds. Internal pruning/index fields are intentionally outside the contract (additionalProperties: true).

Field names follow our real persisted CompressionBlock shape (the issue delegated naming to us). Notably createdAt is a number (epoch ms), matching acp-kernel — called out explicitly in both the TS type and the schema.

R3 — atomic-write promise

Documented in README: the sidecar is written as temp file + rename(), so a reader never observes a half-written file — safe to watermark on mtime/size and always replace the whole file. The file remains the source of truth across process restarts.

Deferred (issue marked these optional / later)

R4 (pi.events.emit("bcp:blocks")), R5 (bounded compress.details), P3 (pi.appendEntry) are not included — they're behavior/event additions the issue listed as optional. Happy to follow up if wanted.

Verification

Rebased onto current master (v0.1.66, acp-kernel@0.0.63):

  • npm run typecheck
  • npm test700 pass / 0 fail / 3 skipped
  • npm run build ✓ — emits dist/contract.js + dist/contract.d.ts; runtime smoke-test of the built module passes.

Tests added: tests/contract.test.ts (schema↔type drift guard + envelope builder) and two cases in tests/state.test.ts (envelope written to sidecar; tolerant higher-version load).

… ./contract export (#368)

Additive-only, zero behavior change. Gives downstream tools a stable,
versioned boundary for reading compressed blocks instead of globbing
private sidecar fields.

- R1: sidecar top-level envelope { schemaVersion, producer:{name,version} }
  written by SessionStateStore.save(); load() treats missing==v1 and, on an
  unknown-higher version, stays tolerant (loads known fields) while logging
  once per file so a downgrade is observable rather than silent.
- R2: new billion-context-pi/contract subpath exporting BcpBlockV1,
  SCHEMA_VERSION, PRODUCER_NAME, createSidecarEnvelope; plus
  schema/bcp-block-v1.json (JSON Schema, shipped in the package).
- R3: document the tmp+rename atomic-write promise in README.

Tests: tests/contract.test.ts (schema<->type drift guard, envelope builder)
and tests/state.test.ts (envelope written; tolerant higher-version load).
@github-actions

Copy link
Copy Markdown

📦 Built Extension Artifact

Branch: 2026-09-11_acp-block-contract (2aa6047)

Option A — Install from npm PR tag (recommended)

pi install npm:billion-context-pi@pr-369

Each push to this PR publishes a new version under the pr-369 npm tag.

Option B — Download artifact

  1. Download the artifact from the Actions run
  2. Extract the tarball and install:
tar xzf billion-context-pi-pr369.tgz
pi install ./package

This comment is automatically updated on each push.

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.

为 ACP block 数据提供机器可读的对外契约(schemaVersion + ./contract 导出)

1 participant