A local-first event pipeline for independent agents, built on Jazz.
thought-stream spec focuses.md
7.7 kB

Focus declarations and the policy DAG #

Purpose #

A focus is a governed policy cell over the shared evidence stream. It gives one recurring obligation a stable identity, bounded source scope, objective, budgets, requested permissions, and retirement condition. A focus may overlap other focuses: one ATProto post can be evidence for broad news, AI news, a person-specific watch, and a Tinker research focus without being copied into one parent's private state.

The durable structure is therefore a DAG. parentFocusIds records product lineage and specialization, not exclusive ownership of source events.

First implemented primitive #

Version 1 implements an inert focus-declaration proposal:

strictly shaped YAML declaration
→ canonical fingerprint
→ stream.thought.focus.declaration.proposed@1
→ separate future review/activation boundary

The proposal contains:

  • stable id, version, name, and description;
  • zero or more parent focus ids;
  • scope summary and bounded include/exclude tags;
  • one objective statement;
  • exact event-type, source-pattern, privacy, and replay subscriptions;
  • daily inference and human-attention ceilings;
  • requested read tools and requested external actions;
  • an explicit retirement rule.

The proposal event is always sensitive and explicitly records that it activates nothing, expands no data access, grants no external action, starts no training, and promotes no adapter. The operator CLI treats one id@version as an idempotency boundary, so changed CLI content requires a version bump. Agent-authored Telegram proposals are run-scoped receipts and may repeat a semantic identity; approval/materialization must resolve duplicate or conflicting ids/versions. Event-type registration, source availability, requested-capability allowlisting, and parent existence/acyclicity are deliberately marked unchecked in proposal evidence. Approval or materialization must resolve those dependencies and fail closed before any executable declaration exists.

Repository declarations under focuses/ are reviewable source. thought stream focus-propose --file <yaml> appends one proposal to Jazz. focus-list exposes body-dark identities and fingerprints; semantic focus ids and parent ids are still sensitive metadata.

The private Telegram interface is /focus <description> or /focus@<current-bot> <description>. A bare /focus is answered deterministically with usage and no provider call. The trusted context compiler enables propose_focus only for an exact description-bearing focus command, and runtime settlement independently revalidates the command and per-turn capability. The model must submit one complete schema-valid declaration; the trusted parent recomputes its fingerprint and atomically settles the sensitive run-scoped proposal beside the conversational output, completion receipt, and consumer progress. Native later history is reconstructed only from that exact completion/proposal chain. The webhook normalizes command authority but does not interpret focus semantics.

Relationship to consumers and Tinker #

A focus declaration is product intent, not an executable agent declaration. The current agents/*.yaml contract remains the runtime authority for subscriptions, model/provider binding, accounting, prompt, outputs, tools, and enabled state. agents/news-focus.example.yaml is the first permanently disabled Tinker-backed runtime sketch for focuses/news.yaml; it deliberately has no environment activation switch. Proposing the focus does not activate that consumer.

Later compilation must bind one approved focus version and fingerprint to one exact consumer declaration, evaluator declaration, dataset projection, candidate adapter, and deployment receipt. No layer may infer approval from file presence or proposal existence. Compilation must also resolve every parent, reject cycles across the complete proposed/approved graph, verify event and source contracts, and allowlist every requested capability.

Actor-model boundary #

The shared Stream is a durable event log plus query/subscription fabric, not an all-to-all actor mailbox. Broadcasting every event to every model would erase the main product boundary.

Focuses are actor-like at the edge:

  • each has a stable identity and versioned behavior;
  • its compiled subscription is its mailbox policy;
  • per-source progress and adapter state are private to that focus;
  • it reacts to admitted messages and emits new typed events;
  • it never reads another focus's private state directly.

Delivery remains a separate policy. A delivery consumer can observe many focus outputs and decide what reaches Cameron and when; its decision is another receipt-backed stream action. This preserves actor-style local state without abandoning the Stream's replayable evidence and overlapping subscriptions.

Ten producer channels #

These are ten useful admission surfaces, not ten grants of authority. Every producer stays read-only against its source and owns one source id, cursor, idempotency contract, privacy floor, and durable append.

Producer Useful evidence Current state
RSS/Atom Publications, blogs, release feeds, newsletters with public feeds Implemented polling connector.
ATProto Jetstream Bluesky posts/likes and protocol-native saves or annotations Implemented bounded live connector.
Telegram Bot API Direct text, images, replies, corrections, reactions Implemented authenticated webhook ingress.
X Activity API Personal account activity and explicit public-account watchlists Webhook contract specified in x-webhook.md; implementation and activation pending.
Filesystem / Coil Notes, specs, project documents, diffs, local artifacts Implemented bounded scan/watch connector.
Email / JMAP Envelope changes, threads, sender/recipient metadata, previews, attachment metadata Implemented read-only Fastmail polling with first-start replay: now; bodies and mail mutation are absent.
Git and forges Commits, refs, diffs, pull requests, CI and review receipts Contract identified; connector not implemented.
Calendar / CalDAV Event changes, free/busy windows, travel and meeting context Contract identified; connector not implemented.
Web reading and saves Semble cards, Margin annotations, bookmarks, browser share/save events Partly observable through ATProto; dedicated admission is not implemented.
Mobile capture Share intents, voice notes, photos, location chosen for capture, app-authored observations A future private cross-platform app can own this producer; no mobile client exists.
Timers, signed webhooks, and runtime receipts Scheduled ticks, external automation, service/agent lifecycle, sensor-style local events Some typed runtime evidence exists; generic timer/webhook producers are not implemented.

Choose the next producer by evidence value and custody cost, not connector count. Fastmail's live source addresses its broad private surface with metadata-only requests, a sensitive privacy floor, a dedicated credential compartment, and no historical replay.

Missing primitives #

Still unimplemented:

  • focus proposal decisions and materialization;
  • evaluator declarations and exact label sources;
  • child-focus proposal review;
  • per-focus dataset custody and export;
  • Tinker candidate training orchestration;
  • incumbent/candidate shadow comparison;
  • adapter promotion and rollback receipts;
  • focus-DAG inspection;
  • mobile focus-declaration interface.

These are explicit gaps. The proposal CLI is not a policy foundry by itself.