feat(memory): injection receipts + blame path (T1+T2+T3, decision 4255039) - #83
Merged
Conversation
…5039) Every recall response now emits an append-only injection receipt mirroring exactly the bound payload (emitted AFTER bound_payload: transcript-DB parity invariant). Presence-in-context evidence only, never causality. - injection_receipts + injection_receipt_items DDL, both backends (session_id NULLable; memory_id deliberately unconstrained so a hard-forget never rewrites the audit trail) - PgReceiptsMixin: single data-modifying-CTE INSERT — _execute borrows a pool connection per call, two statements would lose atomicity - emit_injection_receipt: I/O failure is the only degradation mode; a missing memory_id is an upstream contract violation and raises - receipt_id surfaced in the recall response + outputSchema Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013NkxreafqWnvPCwrL6KJEs
…s (decision 4255039)
Every hook channel injecting memory content now emits an append-only
receipt at injection time, with the ⟦rcpt:id⟧ marker carried inside the
injected text so the model can hand receipt ids back to cortex:why
(receipt-based primary path — server-side session-temporal resolution
does not exist in MCP).
- session_start banner, auto_recall (UserPromptSubmit) and agent_briefing
(SubagentStart — the forgotten 4th channel, correction 3) each emit one
receipt mirroring exactly what is printed: auto_recall's char-budget
drops are excluded from the receipt items (parity invariant,
correction 11; mutation-tested), truncated entries keep their id.
- channel enum hardened to {recall, session_start, auto_recall,
agent_briefing}: loud app-level validation, DDL CHECK on both backends,
PG migration for T1-created free-TEXT tables (exercised live in test),
code↔DDL parity asserted by test. SQLite pre-T2 tables keep free TEXT
(CHECK needs a table rebuild — same stance as the non-enforced FK
migrations); the emitter validation is the enforcement point there.
- session_id = transcript_path basename (correction 7 — the event's
session_id field diverges 148/200 lines on fixture 7374abf5); absent
or non-string transcript_path degrades to NULL at the hook boundary.
- superseded_by_id IS NULL lock on every hook injection query
(correction 8): banner anchors/team/hot, briefing both passes,
auto_recall FTS.
- receipt-write I/O failure degrades to a marker-less injection; the
hook's primary output never breaks.
Adversarially reviewed (3-lens multi-agent pass, findings verified by
refutation): 9 confirmed findings fixed, incl. budget-drop parity test,
live PG CHECK + migration tests, banner-order assertion anchored to the
rendered text, receipts tables added to test cleanup, stub script row
contract. 1139 tests green (hooks/handlers/infrastructure/integration).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013NkxreafqWnvPCwrL6KJEs
…cision 4255039) Adversarial review applied: receipt_ids bounded at 999 (SQLITE_MAX_VARIABLE_NUMBER, sqlite.org/limits.html §9) with uniform rejection above int4, O(n) set-based dedup with precomputed resolved_ids, documented tiebreak "receipt id DESC" in commands/why.md. Full suite green: 4122 passed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013NkxreafqWnvPCwrL6KJEs
…s landing Pre-existing drift from commit 9917e17f (tranche 1): canonical-writer lines shifted 581→583, 641→643, 301→303, 345→347. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013NkxreafqWnvPCwrL6KJEs
CI lint pins nothing and pulled ruff 0.15.20, whose formatter diverges from the local 0.15.6 on 8 receipts files; reformatted with 0.15.20. Renamed the ambiguous comprehension variable `l` to `text` in test_hook_receipts.py (E741). No behavior change — 61 affected tests pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013NkxreafqWnvPCwrL6KJEs
pull Bot
pushed a commit
to asleekgeek/Cortex
that referenced
this pull request
Jul 7, 2026
The Lint job installed ruff unpinned, so CI silently tracked the latest release while local environments lagged. Formatter output changes across ruff minor versions: PR cdeust#83 hit a 0.15.6-local vs 0.15.20-CI divergence where CI reported 8 files "would reformat" that were clean locally. Pin the CI install to 0.15.20 — the version the repo is currently formatted with (verified: `ruff@0.15.20 format --check .` passes on 769 files). Future upgrades bump the pin and reformat in the same commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013NkxreafqWnvPCwrL6KJEs
pull Bot
pushed a commit
to asleekgeek/Cortex
that referenced
this pull request
Jul 7, 2026
Re-ink the README banner and the 9 docs diagrams to the AI Architect Proof Dossier system: paper surface (paper-0/sheet), warm ink (pfg-0/2), terracotta accent (accent-deep), ruled hairlines, and the data-only stage palette. Every colour literal traces to a DS token; oklch->sRGB conversions are scripted (CSS Color 4 math), not eyeballed — the legend in each file documents the mapping. banner.svg also carries the corrected benchmark headline numbers (same values as PR cdeust#83's 9f90291); whichever merges second resolves the overlap by taking this file. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013NkxreafqWnvPCwrL6KJEs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the blame path (decision 4255039) in three slices, rebased on
mainpost-PR82 (bf7872e8, supersede-write-path) — receipts and supersession cohabit cleanly.2e13baf9): every memory injected into context carries a⟦rcpt:N⟧receipt recording what was injected, where, and why.6079b513): receipts wired through the injection hook channels.63380af6): thewhytool resolves⟦rcpt:N⟧markers back to their originating memories, closing the blame loop.152865f3): heat-writers allow-list line numbers recomputed deterministically against the rebased tree via the test's own_scan_heat_writers()(pg_store.py694/754,sqlite_store.py384/428).Verification
Notes
9d204a04) resolved by deterministic recomputation — neitheroursnortheirswas correct.🤖 Generated with Claude Code
https://claude.ai/code/session_013NkxreafqWnvPCwrL6KJEs