> ## Documentation Index
> Fetch the complete documentation index at: https://prism.ntecdev.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Spec 099 v0 2 dewey recallgate advisory

# 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 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:

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:

```python theme={null}
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:

```cypher theme={null}
(: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:

```json theme={null}
{
  "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`:

```python theme={null}
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 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.
