Skip to content

Capture, ingestion, and questions

Most durable knowledge is discovered mid-task, at exactly the moment nobody wants to stop and file a ticket. Capture is Spor’s answer: one call with two or three sentences, and the server does the structuring.

{
"text": "While wiring the carrier webhooks I noticed the signature check
is duplicated across three handlers. Out of scope now — the
rollout is Friday — but it should be extracted.",
"during": "task-carrier-rollout"
}

The caller keeps working. The server drafts a typed node (here, probably an open task with derived-from → task-carrier-rollout as provenance), validates it against the live schema registry, stamps attribution, and commits. If the deferral rationale is itself load-bearing (“because the rollout is Friday”), the ingester can emit a decision node alongside, edged to the task.

In an agent session the door is the capture MCP tool or /spor:defer; from the shell it is spor add "<text>"; over REST it is POST /v1/capture.

The LLM proposes; deterministic code disposes

Section titled “The LLM proposes; deterministic code disposes”

Ingestion runs a small server-side model with the live schema registry and the node index in its prompt: pick the schema this text instantiates, draft the node, prefer edges to existing nodes over creating duplicates. Then the deterministic half takes over — schema validate() hooks, edge normalization, attribution stamping, the serialized commit. A draft that fails validation bounces back to the model once for self-correction before surfacing to the caller. Non-determinism is confined to drafting; everything that gates or transitions a node is reviewable deterministic code.

The capture ingestion model only ever sees the short distilled prose a client chose to send — never a transcript. Session transcripts stay on the client; what crosses the wire is the two-to-four sentences the client already decided were worth keeping. This is a design line, not an optimization: the server-side model’s entire view of your session is the capture text itself.

If the text fits no schema well, the ingester does not force it: the raw text is preserved as a capture-pending node (cap- prefix) and surfaces in the decision queue for human triage. The same fallback catches drafts that remain invalid after the self-correction bounce. A pending capture is closed only as merged (its content now lives in proper nodes) or rejected (no durable fact) — the type’s transition gate refuses anything else, so captured text cannot be quietly discarded.

Only a transport-level failure (the ingestion model unreachable) is an error, and clients spool captures to an outbox and retry, carrying an idempotency key so a timeout that actually landed server-side is not double-written on replay.

Questions: asks that route to the person who knows

Section titled “Questions: asks that route to the person who knows”

When the graph cannot answer something a teammate would know, file it instead of letting it evaporate:

/spor:ask Which carrier SLAs did we commit to for scan latency?

This creates a question- node that joins the decision queue until answered. Routing is deterministic, not broadcast: the server walks stewards edges from the question’s relevance neighborhood (its explicit mentions first) to the closest steward and writes a routed-to edge to that person. Their queue shows the question; everyone else’s does not. A question no steward matches surfaces to everyone — answerable, just not directed.

The answer loop is lineage, not messaging. Whoever knows writes a node — a decision, an artifact, sometimes just a short answer artifact — with an answers edge back to the question. The asker’s next briefing pulls the answer through the question’s neighborhood; nobody has to remember to reply in the right channel.

Steward routing is only as good as the stewards edges in the graph: a person node with stewards → spec-tracking-events is what makes questions about tracking events land on their queue. See Identity and attribution.