You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(memory+guard): quarantine scan-rejected atoms and fix socket_path transport (#87)
Two follow-ups to the PIGuard false-positive investigation (#85):
1. Scan-rejected atoms no longer vanish. The guard scan in addAtom ran
before quarantine routing and hard-dropped rejections, so any guard
false positive silently destroyed a legitimate memory with no review
path. Rejections now go to quarantine with a recorded reason
("scan_rejected: ..." alongside "tainted"), visible via
odek memory extended quarantine. PromoteAtom skips the guard rescan:
the human review is the approval, and a rescan would reject the same
false positive again. The extractor no longer pre-scans atoms - the
single scan gate is at persistence, so extraction and manual adds get
identical quarantine-on-reject behavior.
2. guard.socket_path actually works now. The piguard client dialed the
Unix socket but spoke HTTP, while the go-prompt-injection-guard daemon
speaks newline-delimited JSON - every scan errored and fallback_to_local
silently degraded to local-only scanning. Socket mode now forwards the
request as one NDJSON line per call (matching the daemon protocol),
surfaces {"error":...} daemon replies, and is covered by fake-daemon
socket tests plus an E2E run against the real daemon container
(BENIGN facts pass, injections rejected, batch/long work).
|`batch_url`|`""`| Batch detection endpoint; if unset, derived from `url` by substituting the endpoint path |
192
192
|`long_url`|`""`| Long-text detection endpoint; if unset, derived from `url` by substituting the endpoint path |
193
-
|`socket_path`|`""`| Unix socket path for the sidecar (alternative to `url`) |
194
-
|`threshold`|`0.9`|Score above which content is treated as injected |
193
+
|`socket_path`|`""`| Unix socket of the piguard daemon (alternative to `url`); speaks the daemon's native newline-delimited JSON protocol directly, no HTTP gateway needed|
194
+
|`threshold`|`0.9`|Confidence above which an `INJECTION` verdict is treated as injected. The sidecar score is the confidence of the predicted label, so the threshold never applies to `BENIGN` results|
195
195
|`timeout_seconds`|`5`| Per-request timeout |
196
196
|`fallback_to_local`|`true`| If the sidecar fails, fall back to the local rule scan |
197
197
|`max_text_length`|`0`| Truncate text sent to the sidecar; `0` means no limit. The local scan still sees the full text |
Copy file name to clipboardExpand all lines: docs/EXTENDED_MEMORY.md
+4-2Lines changed: 4 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -269,18 +269,20 @@ Loaded and summarized user-model values are scanned for injection patterns; any
269
269
270
270
Atoms with a tainted `source_class` (`tool_output`, `file_read`, `web`, `mcp`, `subagent`, `agent_generated`, `inferred`) are stored in `extended/quarantine.json` instead of the live atom corpus.
271
271
272
+
Atoms that fail the injection guard scan at persistence time are also quarantined rather than dropped, so guard false positives can be reviewed and restored instead of silently lost. Each quarantine entry records a `reason`: `tainted` for untrusted source classes, or `scan_rejected: ...` with the guard's verdict.
273
+
272
274
A quarantined atom has the same schema as a trusted atom but:
273
275
274
276
-`source_class` is one of the tainted classes.
275
277
-`trust_boost` is 0.
276
278
- It is excluded from semantic search.
277
279
- It is subject to `quarantine_ttl_days` and may be auto-deleted.
278
280
279
-
Per-turn extraction only produces `user_said` atoms, so normal user messages do not land in quarantine. Quarantine is used when an atom is explicitly added (via the tool/API or programmatically) with a tainted source class, or when an `inferred` atom is produced by a future flow.
281
+
Per-turn extraction only produces `user_said` atoms, so normal user messages do not land in quarantine. Quarantine is used when an atom is explicitly added (via the tool/API or programmatically) with a tainted source class, when the guard scan rejects an atom, or when an `inferred` atom is produced by a future flow.
280
282
281
283
Promotion from quarantine to the live store is implemented and human-gated:
282
284
283
-
-`odek memory extended promote <atom-id>` moves the atom to the live store with `source_class: user_approved`.
285
+
-`odek memory extended promote <atom-id>` moves the atom to the live store with `source_class: user_approved`. The guard rescan is skipped on promote — the human review is the approval, and a rescan would reject guard false positives again.
284
286
-`odek memory extended pin <atom-id>` pins a live atom so it is never evicted.
0 commit comments