An agent harness for spec-driven development.
charter spec context-subscriptions.md
10 kB · 218 lines
Markdown
at main


id: context-subscriptions kind: architecture title: Context Subscriptions and Freshness status: proposed depends_on:

  • axioms
  • consumer-agents
  • agent-runtime
  • agent-harness
  • data-model
  • work-queue

Context Subscriptions and Freshness #

Charter should let heterogeneous agents operate against a shared, live project model without pretending every runner exposes the same context-window controls.

The product problem is visible in multi-agent projects: several capable agents can read the same repository and still walk over one another because each run starts from a private, aging picture of the project. More agents increase execution capacity while making coordination harder to reconstruct.

Charter's answer should be a shared document graph, explicit subscriptions, versioned context packets, and freshness enforcement at write boundaries.

Product claim #

Charter owns context state and freshness. Runner adapters own context transport.

The core system should know:

  • which documents and event classes a consumer subscribes to;
  • which document versions and events a run received;
  • which prompt and context documents were mandatory for that run;
  • which relevant documents changed while the run was active;
  • whether the run's assumptions or proposed writes are stale;
  • what refresh, rebase, rejection, or conflict occurred before effects were accepted.

Charter should not require every runner to support live prompt mutation. Letta, Codex, Claude Code, Cursor, local scripts, CI workers, and future harnesses expose different context and interruption surfaces. Heterogeneous agents remain first-class.

Three separate relationships #

An agent's relationship to a document has at least three independent dimensions.

Subscription #

The consumer should be informed when a matching document or event changes. Subscription creates a cursor and freshness obligation. It does not imply that the full document is permanently present in the model prompt.

Packet inclusion #

The document's current version, a selected span, or a change summary is included in a bounded context packet for a particular run.

Prompt residency #

A capable adapter may keep the document or a projection of it resident in an agent's persistent prompt or memory surface. This is an adapter capability, not a Charter correctness requirement.

Keeping these dimensions separate avoids turning subscribed into a euphemism for “consume tokens forever.”

Context manifest #

Every agent run should bind to an inspectable context manifest.

The manifest should include:

  • consumer id and runner adapter;
  • source work item and event ids;
  • prompt document ids and exact versions;
  • attached context document ids and exact versions;
  • subscription cursors used to assemble the packet;
  • mandatory documents required by project or consumer policy;
  • omitted, summarized, or truncated context with reasons;
  • packet token or byte budget when known;
  • packet hash and creation timestamp.

This manifest is the receipt for what Charter supplied. It does not claim that an opaque model attended to every token. It makes the selection and transport boundary inspectable.

Transport modes #

Runner adapters can support different delivery modes while preserving the same Charter contract.

Task-boundary packet #

Charter renders a complete packet when the run starts and supplies it through stdin, a temporary file, environment references, an API, or another stable runner interface.

This is the universal baseline and matches the current pluggable runner design.

Pull context #

Charter exposes document versions, events, and manifests through files, CLI, API, MCP, or a Jazz-native client. The agent retrieves additional context during the run.

Between-step updates #

When the harness controls repeated model/tool cycles, the adapter can inject subscribed deltas before the next model step. Letta-like runtimes can use this to approximate live project memory.

Prompt-resident projection #

When the harness supports persistent system memory or pinned instructions, the adapter can materialize selected documents into that surface and update them according to its own context-window semantics.

Live delivery is a better experience when available. It is not the foundation of correctness.

Freshness and write coordination #

Shared awareness alone does not prevent collisions. Agents can watch each other overwrite the same surface with exquisite real-time provenance.

Every mutating run should declare the document versions and work scopes it acted against. Before Charter accepts a proposal, write, report, or completion effect, it should compare those base versions with current state.

Possible outcomes:

  • fresh: relevant base versions still match;
  • stale but non-conflicting: subscribed context changed outside the run's write/read scope;
  • refresh required: a relevant assumption changed and the adapter can resume with a delta;
  • rebase required: the proposal may still be valid but must be reconciled against current state;
  • conflict: another accepted run changed the same protected scope;
  • rejected: authority, lease, or freshness policy forbids applying the effect.

Version checks, work claims, write scopes, and conflict receipts provide correctness even when a runner cannot be interrupted.

Change delivery #

Charter should not prepend an unbounded stream of raw diffs to every turn.

A change packet should prefer:

  • document id and old/new version ids;
  • semantic event type such as spec.document.updated, decision.superseded, or work.claimed;
  • concise change summary when available;
  • affected heading, span, field, or work scope;
  • exact diff or event reference;
  • authority and provenance;
  • current full document when the consumer is too far behind for useful delta replay.

Each consumer maintains a cursor. Delivery advances the cursor only when the packet or update is durably recorded. Lagging consumers receive a checkpoint or fresh snapshot rather than historical confetti.

Centralized harness mode #

Charter may also provide a first-party managed harness that supports prompt-resident documents and between-step updates directly.

That mode is strategically useful: it can demonstrate the strongest experience, reduce adapter variance, and make shared working memory tangible. It should coexist with the heterogeneous runner contract rather than replace it.

The product split is:

  • Charter core: documents, versions, subscriptions, cursors, manifests, packets, claims, freshness, and conflict state;
  • Charter managed runtime: a first-party implementation with live injection and context-budget management;
  • external adapters: progressively capable integrations for existing agent harnesses.

This lets Charter own the coordination layer without requiring the market to replace every agent tool before the first useful run.

Initial data-model additions #

ContextSubscription #

  • id
  • consumerId
  • documentSelector
  • eventTypes
  • deliveryMode: task-boundary, pull, between-step, prompt-resident
  • required: whether project policy prevents omission
  • cursor
  • contextBudgetHint
  • createdAt / updatedAt

The first implementation may keep simple subscriptions on AgentConsumer, but the durable target should permit per-subscription cursors and delivery policy.

ContextManifest #

  • id
  • consumerId
  • requestId / packetId
  • documentVersions
  • promptDocumentVersions
  • subscriptionCursors
  • omissions / summaries
  • budget
  • manifestSha256
  • createdAt

RunFreshness #

  • requestId
  • baseManifestId
  • checkedAt
  • currentDocumentVersions
  • changedRelevantDocuments
  • status: fresh, stale, refresh-required, rebase-required, conflict, rejected
  • resolutionEventId

First implementation slice #

Do not begin with arbitrary mid-process injection.

The first useful slice is:

  1. Add exact document version maps and subscription cursors to durable packets.
  2. Persist a context manifest for every request.
  3. Record each request's declared read/write scope.
  4. Re-check relevant versions when the run reports or proposes an effect.
  5. Mark stale/conflicting runs visibly rather than accepting their completion state as current truth.
  6. Expose the manifest and freshness result through CLI and API inspection.
  7. Add one richer adapter later, likely a managed Letta runner, that can deliver between-step deltas.

This slice improves coordination for every runner before Charter attempts context-window management for any one of them.

Acceptance criteria #

  1. A user can inspect exactly which document versions a run started with.
  2. A consumer can subscribe to project documents without requiring prompt residency.
  3. A runner with only stdin/file input can participate fully at task boundaries.
  4. A runner with live context controls can receive deltas through an adapter without changing the core subscription model.
  5. Charter detects when a relevant document changed during a run.
  6. A stale run cannot silently overwrite a newer accepted change.
  7. Context omissions and budget decisions are visible in the run manifest.
  8. A user can answer “what does this agent currently know, what changed since it started, and is its result still safe to apply?” from Charter state rather than terminal archaeology.

Open questions #

  • Which freshness changes should merely annotate a run, and which should block completion?
  • Are read/write scopes declared by consumers, inferred from work items, or refined during execution?
  • How should a managed runtime allocate finite prompt residency across required, pinned, and recently changed documents?
  • Can Jazz subscriptions provide a durable cursor primitive directly, or should Charter store semantic event cursors per subscription?
  • What is the minimum adapter contract for resuming a run with a delta rather than starting a replacement run?
  • Should project-level documents be mandatory for every consumer even when an external runner has a very small context window?