Repository navigation
Description
Summary
Scribe (packages/squad-cli/templates/scribe-charter.md + spawn template at squad.agent.md:600-618) runs the entire mutable-state lifecycle — inbox merging, decisions archival, history summarization, cross-agent propagation — using squad_state_* tools exclusively. It never calls any memory.* tool. This means the governance pipeline (classifier → FORBIDDEN scan → audit) only ever runs at first-write, not at any downstream lifecycle event.
The classifier is single-touch: it engages when an agent calls memory.write directly, and never again. Every promotion, archival, propagation, or merge bypasses it.
Evidence
Scribe's task list, verbatim from squad.agent.md:600-618:
| Step | What | Tool used |
|---|---|---|
| 0 | Health check | squad_state_health ✓ |
| 0b | Pre-check decisions/inbox state | squad_state_list + squad_state_read |
| 1 | Decisions archive (>=20KB → 30d, >=50KB → 7d) | implicit rewrite (no audit row) |
| 2 | Merge inbox into decisions.md | squad_state_list + squad_state_read + squad_state_write + squad_state_delete |
| 3 | Write orchestration log | squad_state_write |
| 4 | Write session log | squad_state_write |
| 5 | Cross-agent updates to others' history.md | squad_state_append |
| 6 | Summarize history.md (≥15KB) | implicit rewrite |
| 8 | Health report | squad_state_write / squad_state_append |
Verified against packages/squad-sdk/src/memory/index.ts:69-79 — the MemoryAuditRecord type supports 'classify' | 'write' | 'reject' | 'promote' | 'delete' | 'search' | 'configure' | 'provider-error'. None of these get written during Scribe's lifecycle steps.
Compare to the general "Memory Governance Tools" section at squad.agent.md:275-278 which IS pitched as general advice for all agents — Scribe's own template bypasses it.
Concrete failure modes
1. Forensics gap — archived items have no provenance
When Scribe archives a 35-day-old decision during the 20KB trigger, the audit log has no entry. If three months later you ask "when did we lose the X decision?" — there's nothing in audit.jsonl to answer. The decision is preserved (in decisions-archive.md) but the disposition event is invisible.
A memory.delete call writes a tombstone with id, actor, timestamp, reason. Scribe's rewrite produces nothing equivalent.
2. Late-discovered FORBIDDEN content can propagate
If an agent wrote a decision via squad_state_write directly (bypassing the classifier — which is allowed today), the content lands in decisions/inbox/. Scribe step 2 reads it via squad_state_read and writes it to decisions.md via squad_state_write. The FORBIDDEN scan never runs on the inbox-to-ledger transition. A credential or PII would propagate from inbox to canonical ledger silently.
If Scribe step 2 called memory.classify on each inbox entry before merging, late-discovered FORBIDDEN content would be caught.
3. Cross-agent propagation bypasses classification
Step 5 appends 📌 Team update (...): {summary} — decided by {Name} to N affected agents' history.md files. The summary text is whatever Scribe extracts from the decision. If the original decision body had something that needed redaction, the summary inherits it. No classifier touch.
4. memory.promote is dead code
The SDK has the full promote(id, targetClass) API (packages/squad-sdk/src/memory/index.ts:1328-1338-area, exposed via PR #1251's bridge as memory.promote). Nothing in the spec or any agent's charter ever calls it. There's no automated path that says "this LOCAL entry has been cited 5 times — promote it to DECISION."
5. lastReadAt / usage stats don't exist
memory/index.json tracks createdAt / updatedAt but not lastReadAt. Since reads happen via filesystem grep (the read-side gap I previously surfaced), there's nothing to update even if the field existed. Without read tracking, Scribe can't make importance-aware archival decisions (see related issue: importance-aware archival).
Proposed direction
Scribe should be the showcase consumer of the governed memory pipeline, not its biggest blind spot.
Phase 1 — additive, non-breaking:
- Step 2 (inbox merge): call
memory.classifyon each entry. If FORBIDDEN, log and skip; otherwise proceed. - Step 1 (archive): replace bare file rewrite with
memory.delete(id, actor='scribe', reason='archive-30d-trigger')per archived block. This writes the tombstone. - Step 0b: optionally call
memory.auditto get the existing audit trail for the current decisions.md state — useful for the health report.
Phase 2 — once usage data exists:
4. Step 1: archival decisions consult memory/index.json for class and loadGuidance — never archive POLICY or loadGuidance: ALWAYS (see related issue).
5. Step 6 (history summarization): use memory.search(author) to find related governed entries before discarding history detail.
Phase 3 — long term:
6. memory.promote automation: items cited N times via search get auto-promoted to DECISION; items unread for N days get auto-demoted to ARCHIVE.
Related
- #1243 — history.md vs governed memory direction (touches the cross-agent propagation point)
- #600 and #595 — tiered history retrieval (overlaps with summarization step)
- PR #1251 — the bridge that makes
memory.*MCP-callable in the first place (prerequisite for any fix here) - #1037 (closed) — context budget proposal that anticipated this kind of integration
Severity
🔴 Critical for governance integrity, not for day-1 functionality. Squads work today; the audit log just doesn't capture what's actually happening during lifecycle events. As governed memory adoption grows (post-PR #1251), this gap becomes the chokepoint for any compliance, security, or forensics story.
Activity
bradygaster commentedon Sep 24, 2026
Consolidation direction: #1270 is the canonical architecture issue for the governed-memory versus raw-state API boundary. This issue remains open as the concrete Scribe lifecycle gap (reclassification, audit/provenance, promotion, and cross-agent propagation) to implement after that direction is chosen. #1243 separately owns bounded
history.mdcontext and authority.bradygaster commentedon Nov 5, 2026
Consolidated into #2392 during 2.0 board triage (owner decision). The decision and its validation tests are tracked there; original text remains here for reference.