Commit bf3d8f3
feat(memory): classifyMemoryTopic helper + recordMemoryWithAutoTopic wrapper
Wires the TarotScript memory-topic-classify spread into aegis-oss as an
opt-in auto-topic inference path for recordMemory. Callers that want
automatic topic classification switch from recordMemory() (explicit
topic) to recordMemoryWithAutoTopic() (classifier-inferred topic)
and pass the tarotscript service binding alongside the memory binding.
Existing call sites are unchanged — this is additive, not a replacement.
The migration rollout plan (see artifacts/tarotscript-classifier-migration.md
in aegis-daemon) calls for observation-mode first: flip on for one
caller, watch divergence between classifier output and operator-provided
topics for a week, then expand.
New module: web/src/kernel/classify-memory-topic.ts
Exports:
- CANONICAL_MEMORY_TOPICS — the 15-topic set the classifier can emit.
Kept in sync with decks/memory-topics.deck in the tarotscript repo
via a test assertion. Deck drift fails loudly.
- runMemoryTopicClassification(fetcher, fact) — raw classification
call, returns facts object or null on failure. No fallback logic.
- classifyMemoryTopic(fetcher, fact) — high-level wrapper with
fallback semantics. Falls through to { topic: 'general',
source: 'fallback' } when:
* fetcher call fails (network, auth, binding unavailable)
* classifier returns low confidence
* classifier returns an unknown canonical topic (deck drift guard)
Fallback rationale: classification is best-effort metadata, never
block the memory write. The 'general' card exists in the deck as the
stable fallback bucket precisely for this. Callers distinguish
classifier vs fallback via result.source.
New wrapper in memory-adapter.ts:
- recordMemoryWithAutoTopic(mem, tarotscriptFetcher, fact, confidence, source)
composes classifyMemoryTopic + recordMemory. Returns both the record
result AND the classification metadata so callers can observe
divergence during rollout.
Tests (13 cases in web/tests/classify-memory-topic.test.ts):
- Worker response parsing (facts extraction, receipt hash)
- Non-OK response returns null (never throws)
- Network error returns null
- Correct request shape sent to worker (spreadType, querent, seed, inscribe)
- Happy path: moderate confidence → returns classifier topic
- Low confidence → falls through to 'general', marked fallback
- Unreachable worker → falls through to 'general'
- Unknown topic (deck drift) → falls through to 'general', confidence preserved
- Seed passed through
- CANONICAL_MEMORY_TOPICS drift guard (enumerates all 15 topics)
- recordMemoryWithAutoTopic happy path (infers operator, writes with topic)
- recordMemoryWithAutoTopic on classifier failure (writes with 'general')
- Critical invariant: classifier failure must not block the memory write
Full web suite: 66 files, 1473 pass, 1 skipped. Typecheck clean in
aegis-oss/web and aegis-daemon/web.
Not yet wired into any existing call site — operators flip on auto-topic
at the call site by switching to recordMemoryWithAutoTopic as observation
begins. First target is memory topic routing from dreaming cycle and
inbox-processor (both async, low-latency-tolerance).
Related:
- Stackbilt-dev/tarotscript@7f6854c — memory-topics deck + spread
- Stackbilt-dev/tarotscript@ae0c517 — worker bundle regeneration
- artifacts/tarotscript-classifier-migration.md in aegis-daemon
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent 2cade81 commit bf3d8f3
File tree
3 files changed
+468
-0
lines changed- web
- src/kernel
- tests
3 files changed
+468
-0
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
10 | 11 | | |
11 | 12 | | |
12 | 13 | | |
| |||
115 | 116 | | |
116 | 117 | | |
117 | 118 | | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
118 | 152 | | |
119 | 153 | | |
120 | 154 | | |
| |||
0 commit comments