SPEC-099 v0.2 — Dewey (Recallgate Advisory)
Status: draft v0.2 — Texi architecture review approved_with_required_revisions on v0.1; all eight required revisions and three nits applied as v0.2.
Author: Donna
Reviewer (architecture): Texi
Reviewer (governance): Candi
Final operator approver: Frank
Origin: Plan 003 Phase 3 Step 3.1; Texi review signal a2c61a0f.
Renamed: v0.1 was “Dewey (Recallgate)”; v0.2 is Recallgate Advisory per Texi nit 1, since enforce is deferred.
Supersedes: v0.1 (docs/specs/spec-099-v0-1-dewey-recallgate.md).
v0.1 was approved-with-required-revisions; the largest concern was that assignment acceptance is not a clean runtime boundary today. v0.2 retreats to advisory-only and defines the missing boundary as a precondition for any future enforce mode.
Summary
Recall enforcement gate at task-start, advisory-only. Element 5 of method.wall-break.persistence (“recall-on-task-start”) operationalized as a runtime warning surface. v0.2 ships only the advisory mode and the data plumbing; enforce mode is deferred to a v0.3 that depends on the explicit assignment_acceptance state landing first.
This conservative scoping is direct from Texi’s v0.1 review: prism_signal_ack is diagnostic and must stay cheap and reliable. Enforce mode must apply to a defined accept/start-work transition, not to ACK.
What v0.2 ships
recallgate_event audit family — every Tier-1 / Tier-2 task-class detected at TaskAssigned ACK or prism_todo add emits a recallgate_event referencing the upstream memory_recall_events rows (per Texi revision 6 + watson_shape answer).
- Advisory warning surface — TaskAssigned ACK and
prism_todo add return a warnings: [...] block when the gate would have fired, so agents see the protocol’s expectation without being blocked.
- Task-class matcher — pure function over assignment payload text/tags/paths (per Texi revision 4). No inference about future touched files.
assignment_id definition — formalized so the audit events have a stable key (per Texi revision 1).
- Recent-window semantics clarified (per Texi revision 3).
What v0.2 does NOT ship (deferred to v0.3+)
- Enforce mode — refusal at any boundary. Deferred until explicit
assignment_acceptance state/verb exists in Prism’s surface.
- Force-override — also deferred. Without an enforce boundary, force is meaningless and would create misleading audit data (per Texi revision 7).
- Memorule-specific recall —
source_type='memorule' requirement waits for SPEC-094 v0.5 (Memorules) ratification (per Texi nit 2).
assignment_id definition (per Texi revision 1)
The audit/warning surface needs a stable correlation key. v0.2 derives assignment_id from one of these sources, in priority order:
- Signal-driven:
assignment_id = TaskAssigned.signal_id. The signal is the authoritative envelope.
- TODO-driven:
assignment_id = "todo:{project_id}:{todo_number}" — namespaced compound key.
- Operator-chat-driven: out of enforcement scope for v0.2. The agent may self-mint an
assignment_id as a UUID for its own audit tracking, but this v0.2 does not gate on it.
When assignment_id cannot be derived, the gate emits assignment_id_unknown warning and skips. No false-positive warnings on ambient signal traffic.
ACK is not acceptance (per Texi revision 2)
prism_signal_ack semantics are unchanged by this SPEC. ACK records observed / model_acted as today.
The Recallgate advisory surface piggybacks on ACK responses for TaskAssigned signals: the ACK return shape gains an optional warnings field. ACK never refuses, blocks, or alters ack-side state.
For future v0.3 enforce: there must first be an explicit acceptance state — proposals out of scope here. Candidate shapes (NOT prescribed):
prism_assignment_accept(signal_id, ...) verb
prism_signal_ack(..., accept_assignment=True) ACK extension
- “First material Prism write after TaskAssigned” inferred boundary (
prism_remember, prism_journal, prism_postmortem, prism_decide, etc.)
v0.2 explicitly does not pick one. v0.3 will, after operational data shows which is least surprising.
Recent-window semantics (per Texi revision 3)
A recall satisfies the gate if EITHER:
- (a)
semantic_recall was invoked within 60 seconds before the assignment-acceptance event (signal arrival, TODO add), OR
- (b)
semantic_recall was invoked after assignment arrival AND before the next material output.
“Material output” v0.2 enumeration (the verbs that count as material work, anchoring window (b)):
prism_remember (any kind)
prism_journal
prism_postmortem
prism_decide
prism_spec (create or update)
prism_plan (create or update)
prism_retro
prism_signal with payload (ACK doesn’t count)
- Any backend write to
memory_embeddings outside Prism verbs
Window (b) closes when the agent invokes ANY of the above without first running semantic_recall. The gate fires at that moment as an advisory warning.
Task-class matcher (per Texi revision 4 + 5)
Pure function over assignment payload, no future-state inference:
def classify_assignment(*, payload_text: str, tags: list[str], paths: list[str]) -> TaskClass:
"""Classify by explicit signals only. False-positives bias toward unmatched."""
Inputs:
payload_text — summary, subject, body, ask, next_actions flattened
tags — explicit task tags from the payload
paths — paths explicitly mentioned in the payload (NOT inferred from “this looks like spec implementation”)
Tier 1 (advisory v0.2; enforce-eligible v0.3) — narrowed per Texi:
- Spec implementation, ratification, or governance change explicitly mentioned (path under
docs/specs/, tag governance|ratification|spec-implementation|spec-ratify)
- BIOS edits explicitly mentioned (
CLAUDE.md, AGENTS.md, templates/CLAUDE.md, templates/AGENTS.md)
- Authority / method-fragment changes explicitly mentioned (
docs/method-fragments/, docs/adrs/, tag authority|method-fragment|adr)
- Cross-lane / session / identity routing changes (tag
cross-lane|session-binding|identity-routing)
- Dashboard / telemetry when altering enforcement or observability contracts (tag
enforcement|observability-contract); routine dashboard tweaks are NOT Tier 1.
Tier 2 (advisory only):
- Routine docs edits under
docs/ paths without governance language
- Routine dashboard / UI work
- Telemetry surface tweaks not altering contracts
Unmatched → no warning. Bias narrow at v0.2.
Watson event shape (per Texi revision 6 + watson_shape answer)
recallgate_event is a lightweight node that references existing memory_recall_events rather than duplicating recall payloads:
(:RecallgateEvent {
id: <uuid>,
assignment_id: <string>,
task_class: <"tier1"|"tier2">,
gate_mode: <"off"|"advisory">, -- enforce reserved for v0.3
outcome: <"satisfied"|"warned">,
actor_session_id: <uuid>,
actor_persona: <string>,
actor_surface: <string>,
occurred_at: <iso8601>
})
-[:REFERENCES_RECALL]->(:MemoryRecallEvent {...}) -- existing SPEC-065 entity
recall_event_id references the upstream memory_recall_events row; the gate event stores only counts and references, never recall query strings or result bodies.
Future Watson SPEC reads :RecallgateEvent joined to :MemoryRecallEvent for proof-of-recall surfaces.
Behavior — v0.2 modes
Env flag: PRISM_RECALLGATE_MODE = off | advisory. Default: advisory.
enforce is explicitly NOT a valid value in v0.2; setting PRISM_RECALLGATE_MODE=enforce is treated as advisory with a one-time startup log warning. The constant remains off | advisory | enforce in code so v0.3 can flip without env-name churn.
off
Check does not run. No warnings, no audit events.
advisory (default)
For Tier-1 or Tier-2 watched assignments where the recent-window has not been satisfied, the relevant ACK / TODO-add response gains:
{
"ok": true,
"warnings": [
{
"kind": "missing_recall_on_task_start",
"task_class": "tier1",
"assignment_id": "...",
"remediation": "Issue semantic_recall against TriGraph for prior work on this task-class before producing material output."
}
]
}
A :RecallgateEvent {outcome: 'warned'} is written. When recall later satisfies the window, a corresponding :RecallgateEvent {outcome: 'satisfied'} may be written for the same assignment_id.
Backend (v0.2 scope)
New helper in backend/app/services/recallgate.py:
def classify_assignment(...) -> TaskClass: ...
def detect_recall_window_unsatisfied(
*,
session_id: UUID,
assignment_id: str,
task_class: TaskClass,
recent_recall_events: list[MemoryRecallEvent],
arrival_time: datetime,
) -> RecallgateOutcome: ...
def emit_recallgate_event(...) -> None: ...
Pure functions over inputs (no I/O); the caller orchestrates DB writes for recallgate_event and ACK piggyback warnings.
Caller integration v0.2:
prism_signal_ack for TaskAssigned signals: piggybacks advisory warning into ACK return shape
prism_todo create handler: piggybacks advisory warning into create return
No other surface in v0.2.
Tests (per Texi revision 8)
Backend unit tests in backend/tests/test_recallgate.py:
- Task-class classification:
- Tier 1:
docs/specs/ path with ratify token → tier1
- Tier 1: BIOS path mention → tier1
- Tier 1: cross-lane tag → tier1
- Tier 2: routine
docs/ edit without governance language → tier2
- Unmatched: housekeeping
prism_todo add (“clean up old branches”) → unmatched, no warning (per Texi revision 8)
- Unmatched: routine TaskAssigned that doesn’t carry implementation/ratify language → unmatched (per Texi revision 8)
- Unmatched: ACK-only diagnostic signal — no warning (per Texi revision 8)
- Recent-window:
- Recall 30s before arrival → satisfied
- Recall 90s before arrival → unsatisfied (outside 60s pre-window)
- Recall after arrival, before any material output → satisfied
- No recall, then
prism_journal invoked → unsatisfied at journal-time
- No recall, only ACK invoked → no warning emitted and material-window remains open (ACK is not material output; ACK alone does not satisfy the recall requirement either)
assignment_id derivation:
- TaskAssigned-driven uses
signal_id
- TODO-driven uses
todo:<project>:<number>
- Unknown source emits
assignment_id_unknown warning, no recallgate_event
- Mode behavior:
- mode=off: no events, no warnings
- mode=advisory: warnings + events
- mode=enforce env value: treated as advisory + startup-log warning
:RecallgateEvent shape:
- References
memory_recall_events row by id, not body duplication
- Includes assignment_id, task_class, gate_mode, outcome, actor fields
Integration tests:
- TaskAssigned ACK with task-class=tier1 + no recall in window → ACK return includes
warnings, ACK semantics otherwise unchanged (no refusal, no state mutation)
- Same with task-class=unmatched → ACK return has no warnings
- Phase 0 advisory shipped for at least 7 days of active multi-agent sessions.
- Telemetry:
recallgate_event rows non-zero AND :RecallgateEvent ↔ :MemoryRecallEvent reference graph populated.
- Warning precision measured (per Texi nit 3): of warnings fired, what fraction caught real “agent skipped recall” cases vs. classified false-positive on assignment payload language. Precision target ≥0.7 on a 50+ sample window.
- Explicit
assignment_acceptance boundary defined in a separate SPEC or ADR (this is the gating prerequisite for any v0.3 enforce mode).
- Texi architecture review of v0.2 → v0.3 deltas (enforce semantics, force-override semantics, lifecycle invariant assertions).
- Candi governance ratification of v0.3.
Revisions applied (v0.1 → v0.2)
| # | Texi required revision | Where applied |
|---|
| 1 | Define assignment_id | §assignment_id definition |
| 2 | Separate ACK from acceptance | §ACK is not acceptance + §Behavior — v0.2 modes |
| 3 | Fix recent-window semantics | §Recent-window semantics |
| 4 | Task-class matcher inputs | §Task-class matcher |
| 5 | Tier 1 narrowing | §Task-class matcher |
| 6 | Watson event references existing recall_events | §Watson event shape |
| 7 | Force-override deferred until acceptance boundary | §What v0.2 does NOT ship |
| 8 | Tests for no-op TaskAssigned, housekeeping TODO, ACK-only | §Tests, classification block |
| # | Texi nit | Where applied |
|---|
| 1 | Rename v0.1 → “Recallgate Advisory” | Title + headline |
| 2 | Memorule-specific recall waits for SPEC-094 v0.5 | §What v0.2 does NOT ship |
| 3 | Warning precision in acceptance criteria | §Acceptance criteria item 3 |
Cross-references
method.wall-break.persistence v0.2 — Element 5 (recall-on-task-start)
- SPEC-096 v0.2 — phasing pattern (mode trinary, force-audit) selectively mirrored — v0.2 only ships the advisory tier of that pattern
- SPEC-094 v0.5 — Memorules; v0.3 will integrate Memorule-aware recall once v0.5 ratifies (per Texi nit 2)
- SPEC-065 —
memory_recall_events (referenced by :RecallgateEvent)
- (future) Watson SPEC — consumes
:RecallgateEvent joined to :MemoryRecallEvent
- (future)
assignment_acceptance SPEC/ADR — gating dependency for v0.3 enforce
- Plan 003 Phase 3 — this spec’s home phase
- Texi v0.1 review signal
a2c61a0f
Risk
- R2 — adds new audit-event family + ACK / TODO-add response surface change. Backward-compat preserved: ACK / TODO-add semantics unchanged for callers who don’t inspect
warnings.
- Highest-risk surface in v0.2: the task-class classifier. False positives produce noisy warnings that train agents to ignore them; false negatives leave the gap. v0.2 errs narrow.
- Deferred force-override is intentional — without an explicit acceptance boundary, force creates misleading audit data.
Last modified on June 7, 2026