I3409 — An episode answers, for each prompt it captured, the intent it matched, the task that recorded it, that task's outcome and the evidence of the criterion it serves, with the same identities on every surface and after any replay
Extend intents.matched with an episode mode that derives the vertical slice on read. For each prompt the episode captured, it answers six things. First, the prompt identity and the match verdict. Second, the task whose task.started names that prompt (I3411), labelled recorded; for a line without the key it answers the next task the episode started, labelled inferred. Third, that task's bound issue and intent from task.started and intents.binding. Fourth, its task.finished outcome and verify command, from the recorded contract. Fifth, the evidence state of the criterion the issue serves, from intent_realization. Sixth, an agreement verdict: agrees, differs or no task. The live intent inspector lists the open episodes' prompts that matched the intent, by identity only. It re-reads on the frame I3431 emits, and to a viewer beyond loopback it says the list is answered on this machine only.
BLOCKED wave 5 · p2 · implementation profile · parallel safe
Blocked. This issue cannot start until I3408, I3411, I3433, I3431, milestone:a-prompt-reaches-the-work-it-serves are done. The status is derived from that, not declared.
Objective
Extend intents.matched with an episode mode that derives the vertical slice on read. For each prompt the episode captured, it answers six things. First, the prompt identity and the match verdict. Second, the task whose task.started names that prompt (I3411), labelled recorded; for a line without the key it answers the next task the episode started, labelled inferred. Third, that task's bound issue and intent from task.started and intents.binding. Fourth, its task.finished outcome and verify command, from the recorded contract. Fifth, the evidence state of the criterion the issue serves, from intent_realization. Sixth, an agreement verdict: agrees, differs or no task. The live intent inspector lists the open episodes' prompts that matched the intent, by identity only. It re-reads on the frame I3431 emits, and to a viewer beyond loopback it says the list is answered on this machine only.
Why
The owner's 2026-10-19 Cognitive Fabric pack names this vertical slice and asks that replaying the stream leave the same identities and state (campaigns/prismatic-way-cognitive-fabric-prompt-pack/prompts/00_MASTER.md, prompts/02_EVENTS_INTENTS.md, the verification examples of contracts/EVENT_CONTRACT.md, and the verification/ACCEPTANCE.md row on CLI, API, MCP and UI).
Current state
A capture record names its episode (lib/capture.sh:583-586), but no task or intent. task.started carries issue and intent once the binding is asked (lib/start.sh:158-160). intents.binding resolves a task to its intent at start (lib/intent_binding.sh:30-60). No read model joins them, and /ui refreshes on a 60 s poll (share/ui/ui.js:228,404).
Desired state
One declaration answers the slice with identical identities on the command line, loopback HTTP, MCP and the live /ui. Replaying the episode's events, or shuffling the arrival of independent ones, gives a byte-identical answer. Every join names how it is known, and no snapshot carries it (I3433).
Scope
- apps/majordomus-cli/src/devcontext
- apps/majordomus-cli/src/capability/builtin/intents.rs
- apps/majordomus-cli/src/ui/intent.rs
- apps/majordomus-cli/tests/intent.rs
- docs/generated/registry.json
- docs/generated/registry.yaml
- docs/generated/openapi.json
- docs/generated/openapi.yaml
- docs/generated/modules/intents.md
- site/data/generated/openapi.json
- site/data/registry/registry.json
Out of scope
- Writing a link record (the slice is derived, not stored)
- Monitor or mesh publication of matches
- Changing the session domain (I3142)
Dependencies
- I3408BLOCKED A captured prompt is answered, on this machine only, with the existing intents and issues it matches or with no match, and the answer carries identities and never the prompt's text
- I3411BLOCKED A task records the captured prompt it followed, so the join from prompt to task is a recorded fact rather than a time adjacency
- I3433BLOCKED A UI snapshot page renders only the readings its subject declares publishable, and a page that reads any other reading, or a capability that refuses remote callers, is withheld with a link to the live page
- I3431BLOCKED A record a process outside the server writes (a knowledge record reaching the index, a ledger line or a captured prompt) reaches an open view within one heartbeat, without a reload
Acceptance criteria
- A fixture episode with one prompt, a task.started naming it, its binding and a task.finished answers matched, the task (recorded), the issue, the outcome, the verify command, the criterion's evidence state and agrees
- The same fixture without the prompt key answers the task labelled inferred
- The fixture with the capture hook replayed 100 times and its independent ledger lines read in shuffled order answers byte-identically
- The command line, loopback HTTP and MCP answers for the fixture are equal, and the live intent inspector lists the prompt identity
- A request from beyond loopback is refused, and the snapshot written for publication contains no prompt identity or match
Validation
- cargo test --manifest-path apps/majordomus-cli/Cargo.toml --test intent
- bin/majordomus-cli generate --check
- majordomus capabilities describe intents.matched
Evidence required
- test_a_prompt_reaches_its_task
Evidence
None recorded. Every token above needs a command or an artifact behind it before this issue can be completed; narrative is refused.
Timeline
- started
- —
- verified
- —
- completed
- —
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I3409.yaml. Read it back with majordomus plan show I3409.