QA Report — Adaptive Context Injection (ACI) — FINAL PASS¶
Reviewer: Quinn
Date: 2026-03-21
Spec version: Final v2 (Forge, 2026-03-21)
Reference: QA_REPORT.md (original findings, 11 total: 5 blockers, 3 major, 3 minor)
Status: APPROVED WITH NOTES
Verdict¶
APPROVED WITH NOTES
All 11 original findings are properly resolved — not just patched, but consistently applied throughout the spec. Hook integration points verified against live OpenClaw docs. One new AC-level math conflict identified (notes below) that must be resolved during validation, not during build. Three minor clarity issues flagged for Melody's attention before implementation begins.
Original Findings Resolution¶
Blockers (F-01 through F-05) — ALL RESOLVED ✅¶
F-01 — Hook API shape → RESOLVED ✅
Section 10 BootstrapHookEvent interface now correctly places sessionKey at event top-level and bootstrapFiles nested under context. Section 4 and Section 6 Integration Point 1 consistently use event.sessionKey and event.context.bootstrapFiles. Cross-checked against live docs (hooks.md line 217, 228): confirmed. Also correctly flagged that WorkspaceBootstrapFile exact type shape is undocumented and requires Task 1 empirical verification.
F-02 — MEMORY.md injection status → RESOLVED ✅
Phase 0 pre-flight explicitly requires capturing /context list and confirming MEMORY.md status before any changes. Phase 1 is now conditional (if MEMORY.md IS injected → remove it; if NOT injected → no-op for removal, but still add on-demand instruction). Docs confirm MEMORY.md is NOT in the default bootstrap list (context.md lines 105-113: AGENTS.md, SOUL.md, TOOLS.md, IDENTITY.md, USER.md, HEARTBEAT.md, BOOTSTRAP.md only). Phase 1 correctly handles both outcomes.
F-03 — before_prompt_build is plugin-only → RESOLVED ✅
Section 3 (Layer 3), Section 6 (Integration Point 2), and Task complexity table all correctly characterize before_prompt_build as a plugin lifecycle hook requiring full plugin development (⭐⭐⭐). Docs confirm (plugin.md lines 730-772): api.on('before_prompt_build', ...) inside a plugin's register(api) function, requires openclaw.plugin.json. V2 deferred correctly. V1 uses behavioral SOUL.md instructions only.
F-04 — AC-1 token contradiction → RESOLVED ✅
Original contradiction eliminated by integrating wisdom into SOUL.md (no separate WISDOM.md). All topics now get SOUL.md + TOOLS_COMPACT.md (same 2-file set). AC-1 split into AC-1a (minimal topics ≤400 tok) and AC-1b (enriched topics ≤400 tok) — both now use identical file sets. See new issue N-01 below regarding residual arithmetic tension.
F-05 — WISDOM.md Layer placement → RESOLVED ✅
The bootstrap paradox rationale is explicitly documented in Section 3 ("Wisdom is judgment. You need judgment to decide what else to load."). Wisdom is Layer 0, inside SOUL.md. Decision documented in spec header as final (Jeff, 2026-03-21). No separate WISDOM.md file exists or will be created. Enforced consistently throughout (see WISDOM.md reference audit below).
Major Findings (F-06 through F-08) — ALL RESOLVED ✅¶
F-06 — Basename allowlist risk → RESOLVED ✅
Section 6 Integration Point 1 has explicit ⚠️ callout. Section 10 has explicit ⚠️ callout. Risk 9 covers probability/impact/mitigation. Task 1 is explicitly tasked with testing non-standard filename injection and must report before Melody writes handler.ts. The risk cannot be eliminated at spec time (requires empirical test), but the gates are correct.
F-07 — Non-deterministic behavioral tests → RESOLVED ✅
AC-3 and AC-9 now both have:
- 3 specific named test prompts
- Required pass rate: 3/3
- Evidence criterion: read or memory_search tool call visible in session logs
- Pass/fail definitions explicit
Both ACs are now deterministic and auditable.
F-08 — Phase 0 no rollback for SOUL.md → RESOLVED ✅
Phase 0 pre-flight now creates SOUL.md.bak (and AGENTS.md.bak, TOOLS.md.bak) as a hard gate before any file modifications. Phase 0 rollback explicitly documented. Full rollback table in Appendix B covers all phases. SOUL.md.bak verified in AC-8.
Minor Findings (F-09 through F-11) — ALL RESOLVED ✅¶
F-09 — LESSONS_LEARNED.md existence → RESOLVED ✅
Task 3 explicitly requires verifying LESSONS_LEARNED.md exists. compress-wisdom.sh pre-check logs warnings for missing files and continues with available sources. Risk 7 covers probability/impact/mitigation.
F-10 — No pre-migration baseline → RESOLVED ✅
Phase 0 pre-flight step 1 captures /context list to baseline-context.txt before any files change. Appendix A explicitly states doc numbers are estimates and must be replaced with actual capture.
F-11 — Implicit Phase 2 dependencies → RESOLVED ✅
Phase 2 dependency section now explicitly states: Phase 0 complete, Phase 1 complete, Task 1 complete. Task 7 dependency includes Task 1 + Task 6. Phase ordering is unambiguous.
Wisdom-in-SOUL.md Consistency Audit — CLEAN ✅¶
All WISDOM.md references in the spec correctly reflect the final decision:
- Lines with "WISDOM.md" either say "no separate WISDOM.md" or describe why one is not created
- SOUL_WISDOM_DRAFT.md is correctly described as "a section draft" for integration, not a standalone file
- SESSION_FILE_SETS contains no WISDOM.md entry
- TOPIC_FILE_MAP is empty {} (correct — no topic overrides reference WISDOM.md)
- AC-7 includes: "no separate WISDOM.md file exists in the workspace root"
- Spec footer repeats the decision
- Zero stale WISDOM.md references found
Rollback Coverage Audit — COMPLETE ✅¶
| Phase | Rollback | Format |
|---|---|---|
| 0 | ✅ | cp backups/SOUL.md.bak SOUL.md && cp backups/AGENTS.md.bak AGENTS.md |
| 1 | ✅ | Two options: disable hook in openclaw.json OR restore SOUL.md |
| 2 | ✅ | hooks.internal.entries.aci-bootstrap.enabled: false |
| 3 | ✅ | Remove shedding instructions from SOUL.md (behavioral only) |
| 4 | ✅ | Re-enable TOOLS.md injection, disable TOOLS_COMPACT.md selection |
| Full | ✅ | Restore all three backups + disable hook |
All phases have rollback. Phase 0 is the hardest to roll back but has the most safety gates (backup required before any modification).
Hook Integration Verification — VERIFIED ✅¶
Docs source: /opt/homebrew/lib/node_modules/openclaw/docs/automation/hooks.md and /opt/homebrew/lib/node_modules/openclaw/docs/concepts/context.md
agent:bootstrap:
- Exists ✅ (hooks.md line 261: "agent:bootstrap: Before workspace bootstrap files are injected")
- event.sessionKey is top-level ✅ (hooks.md line 217)
- event.context.bootstrapFiles is mutable ✅ (hooks.md line 228: bootstrapFiles?: WorkspaceBootstrapFile[])
- Workspace hook location <workspace>/hooks/ has highest precedence ✅
before_prompt_build:
- Plugin API only ✅ (plugin.md lines 730-772: api.on('before_prompt_build', ...))
- Correctly deferred to v2 ✅
- Complexity ⭐⭐⭐ correctly noted ✅
Default bootstrap files (context.md lines 105-113):
AGENTS.md, SOUL.md, TOOLS.md, IDENTITY.md, USER.md, HEARTBEAT.md, BOOTSTRAP.md
MEMORY.md is NOT in the default list → F-02 was valid; conditional Phase 1 handles this correctly.
openclaw.json config format:
Spec's config block matches documented format (hooks.md "New Config Format" section). ✅
Behavioral Test Criteria Audit¶
| AC | Test Protocol | Deterministic? | Status |
|---|---|---|---|
| AC-1a | /context list → count files + tokens |
Yes | ✅ Pass |
| AC-1b | /context list → count files + tokens |
Yes | ✅ Pass (see N-01) |
| AC-2 | /context list → verify file set + token count |
Yes | ✅ Pass |
| AC-3 | 3 prompts, 3/3 pass, read tool call in logs | Yes (F-07 resolved) | ✅ Pass |
| AC-4 | /context list in subagent session |
Yes | ✅ Pass |
| AC-5 | 5 session types × file set verification | Yes | ✅ Pass |
| AC-6 | Token count + content audit of TOOLS_COMPACT.md | Yes (manual) | ✅ Pass |
| AC-7 | Wisdom section audit: entry count, token count, no specifics | Yes (manual) | ✅ Pass |
| AC-8 | Disable hook, verify bulk injection resumes | Yes | ✅ Pass |
| AC-9 | 3 prompts × 3 session types, 3/3 pass, read tool call in logs | Yes (F-07 resolved) | ✅ Pass |
New Issues Introduced by Changes¶
N-01 — AC-1 / AC-6 Arithmetic Tension (MAJOR — must resolve before validation)¶
The conflict: AC-1 (both 1a and 1b) requires total bootstrap tokens ≤ 400. AC-6 allows TOOLS_COMPACT.md up to 300 tokens. SOUL.md target is ~150-200 tokens. At stated upper bounds: 200 + 300 = 500 tokens → fails AC-1.
Math: | SOUL.md | TOOLS_COMPACT.md | Total | AC-1 result | |---|---|---|---| | 150 tok | 200 tok | 350 tok | PASS | | 150 tok | 250 tok | 400 tok | PASS (borderline) | | 150 tok | 300 tok | 450 tok | FAIL | | 200 tok | 200 tok | 400 tok | PASS (borderline) | | 200 tok | 250 tok | 450 tok | FAIL |
The spec's stated targets don't guarantee AC-1 passes. AC-6 permits a TOOLS_COMPACT.md that would cause AC-1 to fail.
Recommendation (must resolve before Quinn validates):
Either:
1. Raise AC-1 threshold to ≤ 500 tokens (from 400), keeping AC-6 at ≤ 300 tokens; or
2. Tighten TOOLS_COMPACT.md target in AC-6 to ≤ 200 tokens to guarantee room for SOUL.md
Option 1 is recommended — 500 tokens is still an 80%+ reduction from current baseline (~6,000+ tokens). A 400-token ceiling is arbitrary and too tight given that SOUL.md alone targets 150-200 tokens.
This is a validation criterion conflict, not an architectural problem. Implementation can proceed; this must be aligned before Quinn runs AC-1.
N-02 — bootstrapFiles optional in docs but required in spec interface (MINOR)¶
Docs mark bootstrapFiles as optional (bootstrapFiles?) in context. Spec's BootstrapHookEvent marks it as required. Melody's handler.ts should defensively handle undefined bootstrapFiles (e.g., early return with warning if not present). Not a blocker — Task 1 will confirm actual behavior — but worth noting in handler defensive coding.
N-03 — "MAIN_DM" label inconsistency in Section 4 classification rules (MINOR)¶
Classification rule 3a says: "→ MAIN_DM (load USER.md)" — but "MAIN_DM" is NOT in the SessionType union. The actual type is "PRIVATE_DM". If Melody implements this literally by creating a MAIN_DM case, it won't match any key in SESSION_FILE_SETS and will fall to FALLBACK.
Recommendation: Fix Section 4 rule 3a to say "→ PRIVATE_DM" instead of "→ MAIN_DM." The SESSION_FILE_SETS already correctly maps PRIVATE_DM to ["SOUL.md", "USER.md", "TOOLS_COMPACT.md"]. The distinction between Jeff DMs and external DMs is handled by PRIVATE_DM vs EXTERNAL_DM types.
N-04 — Phase 4 purpose is ambiguous relative to Phase 2 (MINOR)¶
Phase 4 header says "TOOLS_COMPACT.md → TOOLS.md consolidation" and notes: "Replace full TOOLS.md injection with TOOLS_COMPACT.md in all non-main sessions (via hook — should already be in place from Phase 2)."
If it's already in place from Phase 2, what does Phase 4 do? Reading carefully, Phase 4's actual new work is: (1) confirm full TOOLS.md stays available for on-demand reads, and (2) ensure SOUL.md includes the on-demand TOOLS.md instruction. These are small additions, not a standalone phase. This is confusing for anyone trying to understand the execution sequence.
Recommendation: Either rename Phase 4 to "TOOLS.md On-Demand Instruction Verification" to reflect what it actually does, or collapse it into Phase 3 (behavioral shedding already in SOUL.md). Low severity — won't affect correctness.
Internal Consistency Checks¶
Token math across spec:
- SOUL.md target ~150-200 tok ✅ (used consistently in Layer 0, AC-7, Appendix A)
- TOOLS_COMPACT.md ≤300 tok ✅ (AC-6, Layer 1, Appendix A)
- AC-2 (main DM) allows ≤500 tok → SOUL.md (200) + USER.md (97) + TOOLS_COMPACT.md (300) = 597 → potentially tight but USER.md is small (97 tok), so at realistic SOUL.md (150) + USER.md (97) + TOOLS_COMPACT.md (250) = 497 → borderline. At 300 + 200 + 97 = 597 → fails. Recommend aligning with N-01 fix (raise threshold to 600 for AC-2 or tighten file sizes).
File sets in SESSION_FILE_SETS vs topic table:
Topic table shows all topics → no extra files (correct with wisdom in SOUL.md). SESSION_FILE_SETS[FORUM_TOPIC] = ["SOUL.md", "TOOLS_COMPACT.md"] ✅. Consistent.
Phase ordering:
0 → 1 → 2 → 3 → 4 (with noted Phase 4 ambiguity). Phase 2 depends on Phase 0 + Phase 1 + Task 1. Task ordering in Section 12 matches. ✅
Session types in type union vs SESSION_FILE_SETS:
Every SessionType has a corresponding entry in SESSION_FILE_SETS. ✅
Exception: see N-03 (MAIN_DM label in rules, no MAIN_DM type).
Subagent bootstrap:
SESSION_FILE_SETS[SUBAGENT] = ["SOUL.md"] only ✅. AC-4 validates this. Consistent with docs note that subagent allowlist restricts injection.
Summary¶
| Category | Original | Resolved | New |
|---|---|---|---|
| Blockers | 5 | 5 ✅ | 0 |
| Major | 3 | 3 ✅ | 1 (N-01) |
| Minor | 3 | 3 ✅ | 3 (N-02, N-03, N-04) |
All original blockers and findings resolved. One new major issue (N-01) is an AC number alignment problem — not an architecture defect, does not require a spec rewrite, but must be resolved before Quinn validates AC-1. Three new minor issues are clarity/defensive coding notes for Melody.
The spec is architecturally sound, hook integration is verified against live docs, rollback coverage is complete, wisdom-in-SOUL.md is consistently applied, and test protocols are deterministic.
Pre-Implementation Checklist¶
Before Melody writes a line of code:
- [ ] N-01: Align AC-1 threshold (raise to ≤500 tok) OR tighten TOOLS_COMPACT.md target (≤200 tok) — Jules/Forge decision
- [ ] N-03: Fix "MAIN_DM" label in Section 4 rule 3a → should be "PRIVATE_DM"
- [ ] N-02: Handler defensive note for undefined bootstrapFiles (can be in handler.ts implementation notes)
- [ ] Task 1 (Atlas): Must complete before Task 7 begins — no exceptions
Quinn — Final pass complete. 2026-03-21.