ADR-0086: Procedural Skill Crystallization and Consumption¶
| Field | Value |
|---|---|
| Status | Accepted (Implemented) |
| Date | 2026-09-22 |
| Authors | Spector Maintainers & Architecture Working Group |
| Deciders | Spector Technical Steering Committee (TSC) |
| Supersedes | Operational interpretation of ADR-0008 MSCE skill formation (free-text distill in ProceduralCrystallizationRelay) |
| Superseded By | None |
| Related | ADR-0008 (TANGLE / GPM / MSCE), ADR-0028 (pure encoding header), ADR-0029 (provenance region), ADR-0030 (unified engram header), ADR-0032 (persona enactment / ConfidenceLevel), ADR-0033 (kernel decoupling to spector-core), ADR-0035 (pathway catalog / recipes), ADR-0054 (lifespan-adaptive forgetting), ADR-0068 (Phileas PII), ADR-0069 (Synapse tool access policy), ADR-0071 (Remember pathway), ADR-0072 (fused scoring), ADR-0074 (Reflect sleep consolidation), ADR-0080 / ADR-0083 (pathway telemetry), ADR-0084 (dual-plane chat), ADR-0085 (dynamic configuration). Agentic recall and remember is a separate forthcoming ADR. |
| Last Verified | 2026-09-22 (Verified against main @ 62eace7) |
1. Context¶
Spector already treats procedural memory as the procedural heuristics tier: a small, durable, append-only RecordMemory of crystallized habits, looked up in microseconds and injected into LLM context as skills.
ADR-0008 introduced GPM (Goal & Procedural Memory) and MSCE (Multi-Scale Crystallization). The production writer is ProceduralCrystallizationRelay on ReflectPathway (ADR-0074). Dream's EfeTriageRelay already classifies PRAGMATIC simulations as procedural-rule candidates. Synapse already consumes procedural hits: ContextPackFormatter budgets 25% of a context pack for ## 2. PROCEDURAL HEURISTICS & DECISION CADENCE and labels each hit [Skill #id]. MCP memory_remember already accepts tier=PROCEDURAL as “skills, patterns, how-to.”
Cognitive work in Spector is pathways + relays, not god-methods (ADR-0035). ReflectRecipe is a 14-relay sleep pipeline. When it needs to persist an abstraction it nests RememberPathway behind a shared breaker/bulkhead (ADR-0074 §5.2). ProceduralCrystallizationRelay violates that grain: it clusters, prompts, writes, and hangs a hyperedge in one class.
What the relay actually writes today is not a skill. It:
- Reads unconsolidated episodic turns only.
- Groups by
sessionId. - Requires ≥2 non-blank turns.
- Calls the LLM with a hardcoded prompt, or falls back to the first 100 characters of the first turn.
- Remembers a free-text string as
MemoryType.PROCEDURALwith tagsprocedural,crystallized,skill,FLAG_CRYSTALLIZED,MemorySource.REFLECTED. - Adds a hyperedge whose only node is the newly interned
skill:<id>withROLE_DERIVED_FROM— a self-edge, not lineage.
Semantic facts, working scratch, existing procedural near-duplicates, TANGLE chains, and ADR-0029 provenance rows are unused. templateEngine is probed and ignored. Dream's PRAGMATIC path can mint a second, uncoordinated procedural write.
The 64-byte procedural header (ADR-0030 / ProceduralHeaderLayout → SemanticProceduralHeaderLayout) is an index card shared with semantic. Variable skill structure cannot live there. The body already lives in TextBlobMemory. Mutable support already has a home in StrengthMemory (Region 4). Lineage already has a home in ProvenanceMemory (Region 26), whose target_kind enumerates PROCEDURAL but whose source_kind was originally only EPISODIC = 1 (formerly EPISODIC_LOG).
ACT-R is useful as a separation of concerns, not as a single crystallization formula. In ACT-R, knowledge compilation creates a production; utility learning ranks it later; conflict resolution selects among matching productions. Those three jobs must not collapse into one Reflect relay or one SkillCompiler method.
Agentic recall / remember — an online tool loop that reframes a cue until the right trace surfaces — is a different problem and is explicitly out of scope.
flowchart TB
subgraph Today["Current MSCE write — one Reflect relay does everything"]
Epi["Episodic unconsolidated turns"] --> Group["Group by sessionId"]
Group --> Distill["One LLM string or first 100 chars"]
Distill --> Rem["RememberPathway PROCEDURAL"]
Rem --> Slot["64B header + vector"]
Rem --> Blob["TextBlob free-text"]
Rem --> Self["Hyperedge skill → self"]
end
Sem["Semantic facts"] -.->|ignored| Distill
WM["Working memory"] -.->|ignored| Distill
Existing["Existing procedural"] -.->|no dedup| Rem
Dream["Dream PRAGMATIC"] -.->|second writer| Rem 2. Problem Statement¶
Procedural memory is advertised as compiled “when X happens, do Y” policy. The implementation stores un-gated session summaries inside a single Reflect relay. That creates seven architectural failures:
- No admission control. Any two-turn session becomes a pinned, high-persistence engram in a small store (
ProceduralMemorydefault capacity 1,000; throws when full). Failures crystallize the same as successes. - Importance is hardcoded, not computed. Every skill is written at
importance = 1.0through a relay-built synthetic header. The importance calculator that governs every other tier is bypassed, so procedural rows are uniformly pinned at maximum salience regardless of content. - Unstructured payload. Context pack injects
r.text(). There is no trigger, no steps, no success criterion, no kind, no evidence list. - Broken lineage. Hypergraph self-edges and Bloom tags (
session-<hex>) are not ADR-0029 provenance. Semantic parents have nosource_kind. - Latent duplicate writer. Dream has a
PROCEDURALinsight type and aPRAGMATICtriage outcome with no rule saying they may not become a second procedural writer. Nothing enforces one write gate. - Wrong instinct to add an agent. A live agent looping MCP
memory_recallto “author a skill” would overfit the current turn and fight the sleep pipeline. - Wrong instinct to add a mega-compiler. Packing admit + extract + persist + lineage + utility + verify/retry into one
SkillCompilermethod repeats the relay bloat ADR-0035 removed. Spector already has pathways for small tasks.
The header must not grow. Formation must be a pathway that Reflect and MCP can both trigger. Utility learning, when it exists, is not a compile gate.
3. Decision Drivers¶
- Pathways over god-methods. Compilation is
SkillPathway+SkillReciperelays. Reflect does not grow a 15th mega-stage. - Two legal triggers. Reflect (batch sleep) and MCP/CLI (one-shot). Dream proposes; it does not write.
- Nested Remember only. SkillPathway never writes slabs itself. Persist nests
RememberPathwaybehind the existing ADR-0074 breaker/bulkhead. - ACT-R split, not ACT-R formulas. Compile ≠ utility ≠ conflict resolution. Do not implement \(P(a|s)\cdot V\) as the admit gate.
- Formation is offline. Not during the chat token loop. Not via
AgentMemoryBridgesequence tracking (ADR-0084). - No agent for minting. An optional LLM inside
SkillExtractRelayis an extractor, not a think-loop. Agentic recall / remember is a later ADR. - No procedural header / stride change. ADR-0028 / ADR-0030 stay intact.
- Multi-tier parents. Episodic, semantic, and mixed evidence.
- Markdown is the skill. YAML frontmatter for machine fields. JSON is extract IR only. SnakeYAML, not CommonMark.
- Lineage is not a tag. ADR-0029 rows + hypergraph
ROLE_DERIVED_FROM. - Dedup over mint. Near-duplicates reinforce Strength; they do not append a slot.
- Utility is post-outcome. New skills start weak (ACT-R compiled-production prior). \(U\) lives in Strength, updated only when a success/fail bit exists.
4. Considered Options¶
Option 1: Status quo — free-text distill in the Reflect relay¶
- Description: Keep
distillSkills()as one LLM string per session. - Advantages: Zero new types.
- Disadvantages: Unusable skills; store fill; Reflect remains a god-stage.
Option 2: Skill-generation agent on Synapse graphs¶
- Description: LangGraph4j node that loops recall/remember until a skill “looks right.”
- Advantages: Interactive authoring.
- Disadvantages: Online, duplicate writer, fights ADR-0084.
Option 3: Widen ProceduralLayout / spend _reserved¶
- Description: Pack kind / support / confidence into the 64B header.
- Advantages: Hot-path fields.
- Disadvantages: Shared header with semantic; cannot hold steps; violates ADR-0028.
Option 4: One SkillCompiler god-class called from the existing relay¶
- Description: Extract logic out of the relay into a single compiler method that admits, extracts, writes, lines, and scores.
- Advantages: Faster to type than a pathway.
- Disadvantages: Reintroduces facade bloat. Cannot be triggered cleanly from MCP without Reflect. Utility and compile share a stack frame. Hard to circuit-break extract separately from persist.
Option 5: SkillPathway + thin relays; Reflect and MCP are callers (selected)¶
- Description: First-class pathway in the ADR-0035 catalog. Relays: admit, extract, dedup, persist (nested Remember), lineage. Optional
REINFORCEmode for utility.ProceduralCrystallizationRelayshrinks to cluster-and-dispatch. MCPmemory_compile_skillcalls the same pathway. - Advantages: Matches how Remember is nested from Reflect today; one write gate; MCP does not need Reflect; utility cannot pollute compile.
- Disadvantages: New catalog entry, signal type, recipe tests.
5. Decision Outcome¶
Chosen Option: Option 5 — SkillPathway as the only compilation unit. Reflect and MCP trigger it. Dream does not. Utility is a later REINFORCE mode on the same pathway, not a compile relay.
Agentic recall / remember, when specified, may discover parents and then must call SkillPathway. It does not own schema, layout, or persist.
5.1 ACT-R mapping onto Spector verbs¶
ACT-R 5 utility is \(U = PG - C\) with Bayesian \(P = S/(S+F)\). ACT-R 6 replaced that with \(U \leftarrow U + \alpha(R - U)\) and time-discounted reward. Conflict resolution is softmax over matching productions. Compiled productions start with low utility and earn the right to fire.
None of those equations are implemented as a single crystallization threshold. They split like this:
| ACT-R job | Spector | When |
|---|---|---|
| Knowledge compilation | SkillPathway COMPILE | Reflect sweep or MCP commit |
| Persist production | nested RememberPathway | SkillPersistRelay |
| Utility learning | SkillPathway REINFORCE → StrengthMemory | Only with an outcome bit |
| Conflict resolution | RecallPathway fused score + context pack | Every cue |
Admit on support × valence (existing header fields). Do not use \(P(a|s)\cdot V(a,s)\) as \(U_{\text{compile}}\). Do not put \(U\) in the 64B encoding header.
5.2 SkillPathway in the catalog¶
DefaultSpectorMemory.skillPathway() sits next to rememberPathway() / reflectPathway(). No new kernel store.
flowchart TB
subgraph Callers
RF["ReflectPathway<br/>ProceduralCrystallizationRelay — thin dispatcher"]
MCP["MCP memory_compile_skill<br/>CLI spector skill compile"]
DR["Dream EfeTriage PRAGMATIC"]
end
subgraph Skill["SkillPathway + SkillRecipe"]
R1["ClusterAdmitRelay"]
R2["SkillExtractRelay"]
R3["SkillDedupRelay"]
R4["SkillPersistRelay"]
R5["SkillLineageRelay"]
R6["SkillUtilityRelay — REINFORCE only"]
end
RF -->|"SkillSignal COMPILE"| Skill
MCP -->|"COMPILE or DRY_RUN"| Skill
DR -->|"candidate ids only"| RF
R4 -->|"nested, breaker + bulkhead"| Rem[RememberPathway]
R5 --> Prov[ProvenanceMemory]
R5 --> G[HyperEntityGraph]
R6 --> Str[StrengthMemory] SkillSignal:
| Field | Role |
|---|---|
mode | COMPILE | DRY_RUN | REINFORCE |
parents | list of {tsid, MemoryType} |
cue | optional text used as embed / name seed |
commit | false → DRY_RUN (preview body + duplicate-of, no Remember) |
skillId + reward / {success, cost} | REINFORCE only |
Relays — one job each:
| Relay | Does | Does not |
|---|---|---|
ClusterAdmitRelay | \(k\) sessions, valence / resolved, reject working-only and ADR-0084 denylist payloads | LLM |
SkillExtractRelay | LLM JSON IR → markdown + YAML frontmatter; algorithmic n-gram / tool-sequence fallback; templateEngine | Remember |
SkillDedupRelay | cosine + tag near-duplicate; rewrite signal to REINFORCE if hit | mint a second slot |
SkillPersistRelay | nested Remember PROCEDURAL + FLAG_CRYSTALLIZED + SOURCE_DISTILLED | parse parents |
SkillLineageRelay | one provenance row per parent + hypergraph ROLE_DERIVED_FROM | encode header |
SkillUtilityRelay | Strength \(N_{\text{ok}}/N_{\text{fail}}\); optional \(U \leftarrow U+\alpha((R-c)-U)\) | rewrite blob or header identity |
DRY_RUN stops after extract+dedup and returns the would-be SkillBody plus duplicateOf.
Circuit-break extract separately from persist. Persist shares Remember’s breaker/bulkhead with Dream and Reflect (ADR-0074).
5.3 Object model — where each field lives¶
The skill is not the 64-byte slot. The slot is the retrieval card. The skill is the blob body.
flowchart LR
subgraph Slot["ProceduralMemory record — unchanged"]
H["64B EncodingHeader<br/>type=PROCEDURAL<br/>FLAG_CRYSTALLIZED<br/>source=DISTILLED<br/>importance = prior U at mint<br/>Bloom tags"]
V["quantized vector<br/>embed name + trigger + steps"]
end
subgraph Blob["TextBlobMemory"]
MD["YAML frontmatter + markdown body<br/>THE skill"]
end
subgraph Prov["ProvenanceMemory Region 26"]
Rows["1..N rows, same target_tsid<br/>source_kind EPISODIC / SEMANTIC / PROCEDURAL"]
end
subgraph Str["StrengthMemory Region 4"]
Sup["support, last fired, running U<br/>mutable"]
end
subgraph Graph["HyperEntityGraph"]
Edge["ROLE_DERIVED_FROM<br/>parents → skill"]
end
ID["skill-<tsid>"] --> H
ID --> MD
ID --> Rows
ID --> Sup
Edge --> ID | Field | Plane | Notes |
|---|---|---|
id | Index key | Prefix skill-. Register in ADR-0029 D5 prefix_kind. |
name, kind, trigger, steps, tools, success, schema | Text blob frontmatter | Authoritative machine fields. |
Markdown below --- | Text blob body | What the LLM follows. Legacy rows: entire blob is body. |
| Embed text | Vector in slot | name + trigger + joined steps. |
| Confidence / prior \(U\) at mint | Header importance and frontmatter | Header used by SIMD scoring. New skills start weak (compiled-production prior). |
| Support / last-fired / running \(U\) | Strength region | Mutable. Never freeze n= in the encoding header. |
| Parents / evidence | Provenance + hypergraph | Never parent TSIDs in the 64B header. |
| Crystallized | FLAG_CRYSTALLIZED | Means “compiled procedure,” any allowed parent tier. |
| Distilled vs dreamed | Header source + flags | Committed skills are SOURCE_DISTILLED. Uncommitted dream residue may be FLAG_DREAMED / SOURCE_SIMULATED and is not a skill. |
kind values: heuristic (default, semantic-only or legacy), playbook (ordered steps; prefer mixed parents), graph_template (deferred Phase 6).
5.4 On-disk skill body¶
New writes always emit spector.skill.v1:
---
schema: spector.skill.v1
name: null-check-auth-validator
kind: playbook
confidence: 0.35
tools: []
parents:
episodic: ["<episode-tsid>"]
semantic: ["rem-log-<tsid>"]
---
# Null-check auth validator
When a login endpoint throws NPE on missing principal:
1. Reproduce with a request that has no auth context
2. Guard the principal in the validator
3. Add a regression test
Done when the NPE is gone and the test is green.
confidence at mint is a prior, not a claim of reliability. Strength / REINFORCE moves the live score.
Parser (SkillBody.parse(String) owned by the skill module, shared with Synapse formatter):
flowchart TB
In[Text blob] --> Strip[Strip BOM / leading WS]
Strip --> Fence{Starts with --- ?}
Fence -->|no| Legacy["meta = empty<br/>kind = heuristic<br/>body = entire string"]
Fence -->|yes| Split[Split to next ---]
Split --> Yaml["SnakeYAML SafeConstructor"]
Yaml -->|ok + schema v1| Meta[SkillMeta]
Yaml -->|fail or unknown schema| Safe["meta = empty<br/>body = entire original string"]
Split --> Body[Remainder = skill markdown] Rules:
- Add BOM-managed
org.yaml:snakeyamlto the module that owns the parser. Do not addorg.commonmark/commonmark-ext-yaml-front-matter. That extension’s defaultYamlSubsetParsercannot represent nestedparents. - Do not reuse
MarkdownDocumentReader. It strips list markers and fences. - Cortex HTML preview may keep using
marked. Storage and recall paths never HTML-render. - JSON may be used inside
SkillExtractRelay. The Remember boundary always serializes markdown + frontmatter.
5.5 Provenance extension — semantic and procedural parents¶
Lock ordinals to ProvenanceLayout.java / docs/kernel/regions/provenance.md and typed via ProvenanceSourceKind (EPISODIC = 1, SEMANTIC = 2, PROCEDURAL = 3):
| Field | Canonical value |
|---|---|
source_kind | EPISODIC = 1 (formerly EPISODIC_LOG), SEMANTIC = 2 (new), PROCEDURAL = 3 (new), WORKING = 4 reserved, unused in v1 |
target_kind | SEMANTIC = 2, PROCEDURAL = 3 |
Use the existing 12-byte _reserved block at offset 56 of the 72-byte provenance row. Do not change stride.
| When | Offset 56–63 | Offset 64–67 |
|---|---|---|
source_kind = EPISODIC | remain zero | remain zero |
source_kind ∈ {SEMANTIC, PROCEDURAL} | source_tsid int64 | source_partition int32, or zero |
Mixed skills = multiple rows, same target_tsid. Write order: persist success → lineage rows → hyperedges → then mark source episodic turns consolidated if they were members of this compile. On provenance exhaustion: keep the skill, metric skill.provenance.dropped (ADR-0029 D6 fail-open).
5.6 Trigger flows¶
All writers funnel through SkillPathway. Relays outside SkillPathway do not call RememberPathway with procedural free text.
flowchart TB
subgraph Inputs
E[Episodic clusters]
S[Semantic how-tos]
M[Mixed]
D[Dream PRAGMATIC residue]
O[MCP / CLI]
end
subgraph Dispatch
PCR["ProceduralCrystallizationRelay<br/>cluster only"]
MCP[memory_compile_skill]
end
subgraph SP["SkillPathway"]
Adm[ClusterAdmitRelay]
Dedup{SkillDedupRelay}
Ext[SkillExtractRelay]
Persist[SkillPersistRelay]
end
E --> PCR
S --> PCR
M --> PCR
D --> PCR
PCR -->|COMPILE| Adm
O --> MCP --> Adm
Adm --> Dedup
Dedup -->|hit| Reinf[REINFORCE existing]
Dedup -->|miss + commit| Ext --> Persist
Dedup -->|miss + DRY_RUN| Preview[return SkillBody] 5.6.1 Reflect — dispatcher, not compiler¶
sequenceDiagram
participant RP as ReflectPathway
participant PCR as ProceduralCrystallizationRelay
participant SP as SkillPathway
participant Rem as RememberPathway
RP->>PCR: transmit(ReflectSignal)
PCR->>PCR: cluster episodic + semantic + TANGLE
PCR->>SP: SkillSignal COMPILE parents
SP->>SP: admit / extract / dedup
alt duplicate
SP->>SP: REINFORCE Strength + missing lineage
else new and commit
SP->>Rem: RememberSignal PROCEDURAL
Rem-->>SP: ingested
SP->>SP: provenance + hypergraph
end
SP-->>PCR: SkillReport Admission defaults for automated sleep clustering (config, not header fields): k_sessions = 3, or k = 2 plus valence / FLAG_RESOLVED. Reject working-only clusters and tool-JSON / CoT dumps. Explicit tool/compiler invocations (MCP memory_compile_skill, CLI spector skill compile) providing a pre-extracted body and parent reference or valid cue bypass multi-item clustering shapes via Rule 5, while denylist patterns and working-only rejection remain strictly enforced. Do not document or treat admission as "k ≥ 2 always" across all entry points; explicit tool compilation permits single-parent or cue-directed crystallization when sanitized.
In v1, the automated sleep consolidation trigger in ProceduralCrystallizationRelay scans and clusters unconsolidated episodic turns. Semantic how-tos and mixed episodic-semantic skills are fully supported across the core pathway, data representations, and lineage persistence, but in v1 they are compiled via MCP/CLI tools rather than autonomous background Reflect consolidation. Full automated multi-tier scanning during sleep consolidation is deferred; do not claim all 7 phases cover autonomous semantic graduation from Reflect.
Semantic-only clusters default to heuristic. Mixed axiom + episodic proof default to playbook. Working memory may cue clustering; it is not a v1 source_kind.
5.6.2 Dream — propose only¶
flowchart TB
Efe[EfeTriageRelay PRAGMATIC] --> Cand[Candidate parent ids]
Cand --> PCR[Next Reflect dispatcher]
PCR --> SP[SkillPathway admit]
SP -->|fail| Hold[Dreamed residue only<br/>not a skill]
SP -->|pass| Same[COMPILE write gate] Dream must not call Remember for procedural skills. spector.memory.skill.dream-auto-commit defaults false: PRAGMATIC hits wait for Reflect unless an operator flips the flag.
5.6.3 MCP / CLI — same pathway¶
sequenceDiagram
participant Agent as External agent / Cortex
participant MCP as spector-mcp
participant SP as SkillPathway
Agent->>MCP: memory_compile_skill ids-or-cue commit=false
MCP->>SP: DRY_RUN
SP-->>MCP: SkillBody + parents + duplicateOf
Agent->>MCP: memory_compile_skill commit=true
MCP->>SP: COMPILE
SP-->>Agent: skill id or reinforced id Single-shot tool, not a think-loop. Searching for better parents is the forthcoming agentic-recall ADR.
5.7 Use flows — consumption, not formation¶
Using a skill is ordinary recall plus formatting. Conflict resolution stays here.
flowchart TB
Cue[User / agent cue] --> Rec[RecallPathway fused scan]
Rec --> Hit[Procedural hits]
Hit --> Parse[SkillBody.parse]
Parse --> Pack[ContextPackFormatter]
Pack --> LLM[Chat / MCP consumer]
Str[Strength U] -.->|later mix into procedural arm| Rec ContextPackFormatter already allocates 25% of the token budget to procedural. Item renderer:
- [Skill #skill-…] null-check-auth-validator (playbook, conf 0.35)
When: login NPE / missing auth context
Do:
1. Reproduce …
2. Guard principal …
Done: NPE gone and test green
v1 meta → short When/Do/Done; clip full markdown while budget remains; never dump raw YAML fences when meta parsed. Legacy blobs emit r.text() as today.
THE_EXECUTOR recall profile remains the scorer bias for “apply the habit.” Optional later: softmax over Strength \(U\) among matching skills (P(i)=e^{U_i/\tau}/\sum e^{U_j/\tau}). Not required to close this ADR.
explain(skillId) reads provenance + hypergraph, not tags.
Chat priming (ADR-0084) calls Recall + pack only. The graph may follow a playbook. It does not write one.
5.8 Utility / REINFORCE — separate mode¶
flowchart LR
subgraph Compile["SkillPathway COMPILE"]
A[admit] --> E[extract] --> D[dedup] --> P[Remember] --> L[lineage]
end
subgraph Learn["SkillPathway REINFORCE"]
U[SkillUtilityRelay] --> Str[StrengthMemory]
end
Compile --> Slot[Procedural slot]
Outcome[later success / fail / reward] --> Learn
Str -.-> Slot Without an outcome signal, REINFORCE is a no-op. There is no Voyager env by default. Do not add verify/retry on COMPILE.
If a later episode that lists this skill as parent is FLAG_RESOLVED, Reflect may emit REINFORCE with success=true. That is a dispatcher line, not a new Reflect stage that recomputes the skill.
Mint prior: low importance (compiled-child analog of ACT-R \(U_0 \approx 0\) or \(U_0 = -G\)). Live \(U\) never writes back into the encoding header.
5.9 What does not change¶
ProceduralLayout.SCHEMA_VERSIONremains 1. Encoding-header_reservedstays unused.ProceduralMemorycapacity, SWMR append, throw-on-full.- Fused SIMD scorer: still scores header + vector. YAML parse is off the scan path.
- Remember / Recall contracts (ADR-0071 / ADR-0072), with one additive change:
RememberSignalgains aconsolidationFlagsOverlaybyte thatCorticalWriteTransactionRelayORs into a Remember-built header. Verified againstmain: the existingforCognitiveWithHeaderpath is all-or-nothing —DopaminergicSurpriseRelaycopiesheader.importance()and skips the calculator, and the fresh-header branch hardcodesconsolidationFlags = 0. The overlay is the only new surface;MemorySource.DISTILLED → EngramSource.DISTILLEDalready works throughsource.toEngramSource(). The overlay is not exposed onRememberContext.Builderin v1. - Dual-plane chat (ADR-0084): skills are cognitive, not
CHAT_EVENT. - Reflect’s other 13 relays.
5.10 Relationship to prior ADRs¶
| ADR | Relationship |
|---|---|
| ADR-0008 | GPM/MSCE intent kept. Implementation of skill formation moves off the Reflect god-relay onto SkillPathway. |
| ADR-0028 / 0030 | Encoding header stays a pure 64B identity. |
| ADR-0029 | source_kind gains SEMANTIC / PROCEDURAL; reserved bytes hold source_tsid. |
| ADR-0035 | New catalog citizen. Recipes, not facades. |
| ADR-0074 | ProceduralCrystallizationRelay remains a Reflect stage but becomes a dispatcher. Nested SkillPathway uses the same breaker family as nested Remember. |
| ADR-0071 | Only legal write path for a compiled skill. |
| ADR-0072 | Later may consume Strength \(U\) on the procedural arm. Not a close-out requirement. |
| ADR-0084 | Conversation reflector may produce parents; it does not write procedural skills. |
| Forthcoming agentic recall/remember ADR | May loop recall tools. Persist only via SkillPathway. |
Positive Consequences¶
- Compilation is testable and circuit-broken without standing up a full Reflect sweep.
- MCP and Reflect cannot drift onto two writers.
- Reflect stays a sleep pipeline instead of absorbing skill schema work.
- Utility cannot sneak into admit/extract.
- Skills become triggerable, inspectable, and lineage-backed without a kernel layout break.
Negative Consequences & Trade-offs¶
- One more pathway to register, observe, and document.
- SnakeYAML becomes a memory-module compile dependency.
- Context-pack and inspect paths must parse frontmatter (per hit, not per scanned slot).
- Provenance ordinal docs must be corrected; existing
source_kind=1rows stay valid. REINFORCEis inert until an outcome bit exists. That is accepted.graph_templateenactment is deferred.
6. Pros and Cons of the Options¶
| Option | Pros | Cons |
|---|---|---|
| 1. Status quo text distill | No work | Unusable skills; Reflect god-stage |
| 2. Formation agent | Interactive | Online, duplicate writer |
| 3. Header / stride change | Hot-path fields | Breaks ADR-0028 |
| 4. SkillCompiler god-class | Fast to sketch | Facade bloat; MCP must go through Reflect or a second entry |
| 5. SkillPathway + relays (selected) | Catalog grain, two triggers, nested Remember, utility isolated | New recipe + tests |
7. Implementation Plan¶
- Phase 1 — Pathway shell.
SkillPathway/SkillSignal/SkillReport/SkillRecipewith persist + lineage relays only.ProceduralCrystallizationRelaydispatches current free-text through the pathway. Nested catalog + breaker proven. No schema change yet. - Phase 2 — Admit / extract / dedup relays +
SkillBody. SnakeYAML parser; extract IR → v1 markdown; algorithmic fallback; cosine reinforce. Reflect relay only builds parent lists. - Phase 3 — Semantic and mixed parents.
source_kind=SEMANTIC+ reservedsource_tsid; mixed two-row provenance; tagsfrom:semantic/from:episodicas gates only. Note: in v1, semantic and mixed compilation is exercised via MCP/CLI tools; autonomous background Reflect consolidation remains focused on episodic turn clusters. - Phase 4 — Consumption.
ContextPackFormattershort form;explain()mixed parents. - Phase 5 — MCP / CLI + Dream redirect.
memory_compile_skill(DRY_RUN/COMPILE); CLI sibling command (spector skill compile); PRAGMATIC persist removed;skill-prefix_kind registered. - Phase 6 —
REINFORCE/SkillUtilityRelay. Only after an outcome signal exists. Optional softmax mix into Recall. Not required to mark this ADR Accepted. - Phase 7 — Deferred.
graph_template+ approval-backedFlowSpec.
Configuration (names illustrative): spector.memory.skill.min-sessions, spector.memory.skill.duplicate-cosine, spector.memory.skill.allow-semantic-only, spector.memory.skill.dream-auto-commit (default false), spector.memory.skill.utility-alpha.
8. Code Reference & Verification¶
- Primary Module(s):
memory/spector-memory,memory/spector-kernel(provenance enum / reserved bytes only),synapse/spector-mcp,synapse/spector-synapse(formatter + MCP tool) - Key Packages:
com.spectrayan.spector.memory.pathway.skill(new)com.spectrayan.spector.memory.pathway.reflect.relaycom.spectrayan.spector.memory.pathway.remembercom.spectrayan.spector.commons.pathway(PathwayCatalog,PathwayComposer)com.spectrayan.spector.kernel.store/kernel.layoutcom.spectrayan.spector.mcp.util(ContextPackFormatter)
- Current classes this ADR changes:
ProceduralCrystallizationRelay.java— dispatcher onlyReflectRecipe.java/ReflectPathway.java— still lists the relay; nested SkillPathway via catalogSpectorRuntime.java/DefaultSpectorMemory.java— registerSkillPathwayEfeTriageRelayDream persist path — candidates onlyContextPackFormatter.java— compiled skill renderingProvenanceLayout—source_kind+ reservedsource_tsid
- New classes (names illustrative):
SkillPathway,SkillSignal,SkillReport,SkillRecipeClusterAdmitRelay,SkillExtractRelay,SkillDedupRelay,SkillPersistRelay,SkillLineageRelay,SkillUtilityRelaySkillBody,SkillMeta,SkillKind- MCP spec
memory_compile_skill.json+ handler
- Verification Tests:
SkillBodyParseTest— legacy prose, v1 fence, nestedparents, corrupt YAML fails openClusterAdmitRelayTest— k-session, valence, working-only reject, denylistSkillDedupRelayTest— second cluster bumps Strength, no second slotSkillPathwayNestedRememberTest— breaker/bulkhead; Reflect dispatcher does not Remember itselfSemanticSkillCrystallizationTest— semantic-only heuristic +source_kind=SEMANTICMixedSkillProvenanceTest— two rows, onetarget_tsidDreamPragmaticDoesNotPinTestMemoryCompileSkillToolTest—DRY_RUNvsCOMPILESkillUtilityRelayTest— no-op without outcome; delta update with reward- Layout:
ProceduralLayout.SCHEMA_VERSION == 1; header stride 64; provenance stride 72 SkillImportanceViaCalculatorTestshould assert signal.header() is null at entry to DopaminergicSurpriseRelay and FLAG_CRYSTALLIZED is set on the written header — that pins both halves of the invariant.
Invariants (must remain true)¶
- No change to
ProceduralLayoutstride, layout id0x434F4700, or encoding-header_reservedusage. - Every committed skill is
MemoryType.PROCEDURAL+FLAG_CRYSTALLIZED+ nestedRememberPathway. ProceduralCrystallizationRelaydoes not callRememberPathwayfor skills.- Dream and Synapse chat do not call
RememberPathwayfor skills. SkillBody.parseon a blob that does not start with---returns the entire string as body.- Parent identity is provenance + hypergraph, never
session-<hex>tags. - SIMD recall does not parse YAML.
- Semantic-only skills are allowed; working-only skills are not.
- Near-duplicate
COMPILEbecomesREINFORCErather than appending a slot. SkillUtilityRelaydoes not run onCOMPILE.- Agentic recall / remember, when specified later, may discover parents; it may persist a skill only through
SkillPathway.