Skip to main content

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

  1. 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).
  2. 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.
  3. Task-class matcher — pure function over assignment payload text/tags/paths (per Texi revision 4). No inference about future touched files.
  4. assignment_id definition — formalized so the audit events have a stable key (per Texi revision 1).
  5. 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 recallsource_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:
  1. Signal-driven: assignment_id = TaskAssigned.signal_id. The signal is the authoritative envelope.
  2. TODO-driven: assignment_id = "todo:{project_id}:{todo_number}" — namespaced compound key.
  3. 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_textsummary, 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

Acceptance criteria for v0.2 → v0.3 promotion

  1. Phase 0 advisory shipped for at least 7 days of active multi-agent sessions.
  2. Telemetry: recallgate_event rows non-zero AND :RecallgateEvent ↔ :MemoryRecallEvent reference graph populated.
  3. 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.
  4. Explicit assignment_acceptance boundary defined in a separate SPEC or ADR (this is the gating prerequisite for any v0.3 enforce mode).
  5. Texi architecture review of v0.2 → v0.3 deltas (enforce semantics, force-override semantics, lifecycle invariant assertions).
  6. Candi governance ratification of v0.3.

Revisions applied (v0.1 → v0.2)

#Texi required revisionWhere applied
1Define assignment_id§assignment_id definition
2Separate ACK from acceptance§ACK is not acceptance + §Behavior — v0.2 modes
3Fix recent-window semantics§Recent-window semantics
4Task-class matcher inputs§Task-class matcher
5Tier 1 narrowing§Task-class matcher
6Watson event references existing recall_events§Watson event shape
7Force-override deferred until acceptance boundary§What v0.2 does NOT ship
8Tests for no-op TaskAssigned, housekeeping TODO, ACK-only§Tests, classification block
#Texi nitWhere applied
1Rename v0.1 → “Recallgate Advisory”Title + headline
2Memorule-specific recall waits for SPEC-094 v0.5§What v0.2 does NOT ship
3Warning 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