feat(skill-memory): per-skill cross-session recall + historian auto-extraction#181
feat(skill-memory): per-skill cross-session recall + historian auto-extraction#181iceteaSA wants to merge 10 commits into
Conversation
dc83db6 to
4034019
Compare
There was a problem hiding this comment.
11 issues found across 78 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/plugin/src/features/magic-context/dreamer/task-executor.ts">
<violation number="1" location="packages/plugin/src/features/magic-context/dreamer/task-executor.ts:419">
P2: Re-embed pre-step errors are suppressed, allowing successful task completion reporting despite a failed prerequisite data maintenance step.</violation>
</file>
Note: This PR contains a large number of files. cubic only reviews up to 40 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.
On a pro plan you can use ultrareview for larger PRs.
Re-trigger cubic
| // Skill-memory P2: re-embed stale/NULL skill-note vectors BEFORE the | ||
| // distill agentic pass so the prompt sees a fully-embedded corpus and | ||
| // P1-era notes promote from the FTS rung to the cosine rung. | ||
| if (config.task === "distill-skill-memory") { |
There was a problem hiding this comment.
P2: Re-embed pre-step errors are suppressed, allowing successful task completion reporting despite a failed prerequisite data maintenance step.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/plugin/src/features/magic-context/dreamer/task-executor.ts, line 419:
<comment>Re-embed pre-step errors are suppressed, allowing successful task completion reporting despite a failed prerequisite data maintenance step.</comment>
<file context>
@@ -412,7 +413,18 @@ export function createDreamTaskExecutor(deps: DreamTaskExecutorDeps): TaskExecut
+ // Skill-memory P2: re-embed stale/NULL skill-note vectors BEFORE the
+ // distill agentic pass so the prompt sees a fully-embedded corpus and
+ // P1-era notes promote from the FTS rung to the cosine rung.
+ if (config.task === "distill-skill-memory") {
+ try {
+ await reembedStaleSkillNotes(db, projectIdentity);
</file context>
There was a problem hiding this comment.
Holding this one as working-as-intended. The catch is not silent — it logs [dreamer] distill-skill-memory reembed pre-step failed: ${e} (task-executor.ts, the line directly inside the catch). The suppression is deliberate: re-embedding is a best-effort optimization pre-step, not a prerequisite — if it fails, the affected notes simply stay on the FTS recall rung instead of the cosine rung, and the distill report still runs correctly. Letting a reembed failure fail the whole task would block a report that doesn't depend on it. The failure is observable via the log; happy to escalate to a metric/warning if you'd prefer louder signal.
There was a problem hiding this comment.
4 issues found across 15 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/plugin/src/features/magic-context/dreamer/task-executor.ts">
<violation number="1" location="packages/plugin/src/features/magic-context/dreamer/task-executor.ts:419">
P2: Re-embed pre-step errors are suppressed, allowing successful task completion reporting despite a failed prerequisite data maintenance step.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
…routing/parser gaps) Council review (deepseek/sonnet/gpt-5.5) of PR cortexkit#181: - Must (consensus rev-2+rev-3): the ctx_skill_note fail-loud guard threw during plugin init when the plugin is disabled (enabled:false OR conflict-disabled) — createSessionHooks returns {magicContext:null} by design, so the unconditional guard crashed the entry module on the disabled path. Gate it on pluginConfig.enabled; pass a throwaway Map to createToolRegistry (which early-returns {} when disabled and never reads it). - Must (rev-3): singular ~/.config/opencode/skill/ global path was misclassified as project tier (opencode's pattern is {skill,skills}/**/SKILL.md) — fixed in deriveSkillTier/deriveSkillSource + the ctx_skill_recall cold-start search list. - Must (rev-3): the frontmatter parser rejected the inline flow-mapping form 'skill-memory: { enabled: true }' — the EXACT form the ctx_skill_recall remediation message and ARCHITECTURE/CONFIGURATION/README advertise. Added inline-mapping parsing so guidance and parser agree. - Should (consensus rev-1+rev-3): recallSkillMemoryBlock swallowed all errors silently — added a log() so FTS/blob corruption is diagnosable (still no-throw). Regression tests: inline frontmatter form (3 cases), singular skill/ global path (2 cases).
…routing/parser gaps) Council review (deepseek/sonnet/gpt-5.5) of PR cortexkit#181: - Must (consensus rev-2+rev-3): the ctx_skill_note fail-loud guard threw during plugin init when the plugin is disabled (enabled:false OR conflict-disabled) — createSessionHooks returns {magicContext:null} by design, so the unconditional guard crashed the entry module on the disabled path. Gate it on pluginConfig.enabled; pass a throwaway Map to createToolRegistry (which early-returns {} when disabled and never reads it). - Must (rev-3): singular ~/.config/opencode/skill/ global path was misclassified as project tier (opencode's pattern is {skill,skills}/**/SKILL.md) — fixed in deriveSkillTier/deriveSkillSource + the ctx_skill_recall cold-start search list. - Must (rev-3): the frontmatter parser rejected the inline flow-mapping form 'skill-memory: { enabled: true }' — the EXACT form the ctx_skill_recall remediation message and ARCHITECTURE/CONFIGURATION/README advertise. Added inline-mapping parsing so guidance and parser agree. - Should (consensus rev-1+rev-3): recallSkillMemoryBlock swallowed all errors silently — added a log() so FTS/blob corruption is diagnosable (still no-throw). Regression tests: inline frontmatter form (3 cases), singular skill/ global path (2 cases).
8f87530 to
00f22d2
Compare
…routing/parser gaps) Council review (deepseek/sonnet/gpt-5.5) of PR cortexkit#181: - Must (consensus rev-2+rev-3): the ctx_skill_note fail-loud guard threw during plugin init when the plugin is disabled (enabled:false OR conflict-disabled) — createSessionHooks returns {magicContext:null} by design, so the unconditional guard crashed the entry module on the disabled path. Gate it on pluginConfig.enabled; pass a throwaway Map to createToolRegistry (which early-returns {} when disabled and never reads it). - Must (rev-3): singular ~/.config/opencode/skill/ global path was misclassified as project tier (opencode's pattern is {skill,skills}/**/SKILL.md) — fixed in deriveSkillTier/deriveSkillSource + the ctx_skill_recall cold-start search list. - Must (rev-3): the frontmatter parser rejected the inline flow-mapping form 'skill-memory: { enabled: true }' — the EXACT form the ctx_skill_recall remediation message and ARCHITECTURE/CONFIGURATION/README advertise. Added inline-mapping parsing so guidance and parser agree. - Should (consensus rev-1+rev-3): recallSkillMemoryBlock swallowed all errors silently — added a log() so FTS/blob corruption is diagnosable (still no-throw). Regression tests: inline frontmatter form (3 cases), singular skill/ global path (2 cases).
00f22d2 to
8db1b8d
Compare
There was a problem hiding this comment.
4 issues found across 78 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/plugin/src/features/magic-context/dreamer/task-executor.ts">
<violation number="1" location="packages/plugin/src/features/magic-context/dreamer/task-executor.ts:419">
P2: Re-embed pre-step errors are suppressed, allowing successful task completion reporting despite a failed prerequisite data maintenance step.</violation>
</file>
Note: This PR contains a large number of files. cubic only reviews up to 40 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.
On a pro plan you can use ultrareview for larger PRs.
Re-trigger cubic
…routing/parser gaps) Council review (deepseek/sonnet/gpt-5.5) of PR cortexkit#181: - Must (consensus rev-2+rev-3): the ctx_skill_note fail-loud guard threw during plugin init when the plugin is disabled (enabled:false OR conflict-disabled) — createSessionHooks returns {magicContext:null} by design, so the unconditional guard crashed the entry module on the disabled path. Gate it on pluginConfig.enabled; pass a throwaway Map to createToolRegistry (which early-returns {} when disabled and never reads it). - Must (rev-3): singular ~/.config/opencode/skill/ global path was misclassified as project tier (opencode's pattern is {skill,skills}/**/SKILL.md) — fixed in deriveSkillTier/deriveSkillSource + the ctx_skill_recall cold-start search list. - Must (rev-3): the frontmatter parser rejected the inline flow-mapping form 'skill-memory: { enabled: true }' — the EXACT form the ctx_skill_recall remediation message and ARCHITECTURE/CONFIGURATION/README advertise. Added inline-mapping parsing so guidance and parser agree. - Should (consensus rev-1+rev-3): recallSkillMemoryBlock swallowed all errors silently — added a log() so FTS/blob corruption is diagnosable (still no-throw). Regression tests: inline frontmatter form (3 cases), singular skill/ global path (2 cases).
041126d to
ef5cba1
Compare
Per-skill "motor memory": when a skill's SKILL.md declares
`skill-memory: { enabled: true }`, accumulated gotchas/discoveries/fixes/
workflow-steps surface in a <skill-memory> block appended to the skill
tool's RESULT on every load (cache-safe — rides the tool-result tail).
Agents write back via ctx_skill_note; ctx_skill_recall is the explicit
companion to the transparent after-hook.
- migration: skill_memory table (per-skill; tier project/global; UNIQUE on
skill_id/tier/project_identity/normalized_hash) + lookup indexes.
- three-hook augmentation: tool.definition advertises an `intent` param;
tool.execute.before stashes intent (bounded TTL); after-hook parses the
skill's Base directory, reads SKILL.md frontmatter, formats the block.
- flat recency×hit recall + storage layer; ctx_skill_note / ctx_skill_recall.
- opt-in distill-skill-memory dreamer task; agent-prompt guidance; TUI/ctx-status stats.
- docs: ARCHITECTURE / STRUCTURE / CONFIGURATION / README.
Upgrade recall from flat recency×hit to a multi-rung cascade: intent + model-matched embeddings → cosine blend across intent_embedding + delta_embedding (relevance/recency/hit weights tunable per skill via ranking_* frontmatter); intent + no model match → FTS5 fallback over the content-linked skill_memory_fts vtable; empty → flat fallback. - migration: delta_embedding + recall_count columns + skill_memory_fts FTS5 vtable. - embed-on-write in insertSkillMemoryNote; delta-only semantic dedup. - programmatic, no-LLM reembed pre-step for the distill-skill-memory dreamer task. - read-side recall_count (distinct from write-side hit_count). - canonical vector serde + dedup/ranking/FTS query helpers.
…ication (P3a) Foundation for the historian to auto-capture skill notes cross-project. - surface the skill name in the historian chunk as a `TC: skill(<name>)` marker (the keystone — the tool input name was previously dropped). - migration: origin_project + source_type columns; unify global-tier notes under project_identity='*' (collision-merge) so a global note is one row recallable from any repo. - partitionKey helper routes global write/recall/reembed/stats through '*'; recall reads global-tier from '*' (cross-project); reembed sweeps '*'.
Close the loop so the historian writes skill notes during compaction without an agent volunteering ctx_skill_note. - historian prompt emits a <skill_observations> block; parser extracts it; threaded through the validated historian result. - both runners (OpenCode + Pi) promote skill observations post-commit via the shared promoteSkillObservations helper, gated by promotionActive && !discardedLast, writing global '*' notes with source_type='historian'. - self-heal net: initializeDatabase re-creates skill_memory + ensureColumn so an upgraded DB recovers even if a migration row is lost.
- Remove committed <<<<<<< HEAD conflict marker in CONFIGURATION.md (P1)
- Move injectSkillIntentParam before the lastChatContext guard so the intent
param is advertised even on tool.definition flights before first chat.message
- Key intentByCallId by sessionID:callID + prefix-prune on session delete so a
concurrent session's delete can't evict another session's in-flight intents
- Log silent catch in promoteSkillObservations (observability for dropped writes)
- Anchor frontmatter regex to start-of-file (drop m flag) so a later --- rule
can't be misparsed; strip inline # comments from unquoted YAML scalars + block header
- Scope distill report SQL to ('<identity>','*') instead of non-deterministic LIMIT 1
- Don't truncate skill name in TC: skill(<name>) marker (identity key); sanitize
newlines/control chars
- Normalize backslash->slash after fileURLToPath for Windows provenance checks
- FTS self-heal rebuild in initializeDatabase when skill_memory_fts is empty but
skill_memory has rows
- Move ctx_skill_recall _test* DI fields to a separate test-only deps type
- Hoist the shared registryKey dynamic import (one import, both blocks)
Pushback: reembed pre-step errors are already logged (task-executor.ts) — the
non-blocking try/catch is by design (failure leaves notes on the FTS rung).
…2/P3) - P1: recall now unions the skill's own partition with the global '*' partition (recallPartitionPredicate helper) so a PROJECT-LOCAL skill surfaces historian-written global notes — previously orphaned (tier='project' query never matched tier='global'/'*'). Write/dedup paths stay exact-partition. - Escape apostrophes in projectPath before SQL string interpolation in the distill prompt template. - Frontmatter regex tolerates a leading UTF-8 BOM / whitespace (still start-anchored). - TC: skill(<name>) marker emits the name VERBATIM when marker-safe, else drops it — never mutates the identity key (recall keys on raw input.name). - Fix misleading frontmatter test: now actually exercises a '#' inside a quoted scalar (preserved) vs unquoted (comment-stripped). Regression tests: project-local skill recalls a global historian note; agent project note + historian global note both surface for the same skill.
…routing/parser gaps) Council review (deepseek/sonnet/gpt-5.5) of PR cortexkit#181: - Must (consensus rev-2+rev-3): the ctx_skill_note fail-loud guard threw during plugin init when the plugin is disabled (enabled:false OR conflict-disabled) — createSessionHooks returns {magicContext:null} by design, so the unconditional guard crashed the entry module on the disabled path. Gate it on pluginConfig.enabled; pass a throwaway Map to createToolRegistry (which early-returns {} when disabled and never reads it). - Must (rev-3): singular ~/.config/opencode/skill/ global path was misclassified as project tier (opencode's pattern is {skill,skills}/**/SKILL.md) — fixed in deriveSkillTier/deriveSkillSource + the ctx_skill_recall cold-start search list. - Must (rev-3): the frontmatter parser rejected the inline flow-mapping form 'skill-memory: { enabled: true }' — the EXACT form the ctx_skill_recall remediation message and ARCHITECTURE/CONFIGURATION/README advertise. Added inline-mapping parsing so guidance and parser agree. - Should (consensus rev-1+rev-3): recallSkillMemoryBlock swallowed all errors silently — added a log() so FTS/blob corruption is diagnosable (still no-throw). Regression tests: inline frontmatter form (3 cases), singular skill/ global path (2 cases).
- budgetFill now counts per-note XML framing (~20 tokens) so the rendered
<skill-memory> block stays within max_tokens instead of ~13% overshoot (rev-1).
- clamp effective pinned budget to min(max_pinned_tokens, max_tokens) so the
default 4000>1500 can't imply pinned gets more room than the whole block (rev-2).
- ctx_skill_recall: derive tier via dirname(resolvedPath) instead of a fragile
.replace('/SKILL.md','') (rev-2).
Updated the budget-truncation test for the framing-inclusive math.
- provenance.ts: anchor the Base-directory regex to line-start (^…/gm) and take the LAST match — opencode appends the provenance line at the END of tool output, so a skill whose CONTENT echoes 'Base directory for this skill:' (e.g. a skill documenting skill-memory) would otherwise shadow the real line and misdirect recall to a bogus identity. - read-session-formatting.ts: narrow the marker-safe exclusion to CR/LF/tab only — a ')' does not break the single-line TC: skill(<name>) marker and the historian reads it as natural language, so a ')'-containing name is preserved verbatim (identity key) instead of dropped. - ARCHITECTURE.md: update the 'Skill-memory (motor memory)' Key Abstraction to the shipped reality (v50/51/52, multi-rung embedding+FTS recall, global-'*' union) — was stale (v37, 'P2 TODO'). Remove the PR-added duplicate 'Tag Identity (v3.3.1+)' section (upstream owns the lean '## Tag identity'; Tag Identity is unrelated to skill-memory — rebase scope-creep). Regression tests: provenance last-match + mid-line rejection; ')' name preserved + CR/LF/tab still dropped.
…emory off Rebase-onto-v0.29.0 resolution completion. Upstream ab4f01c added a memory.enabled gate that drops ALL ctx_memory mentions from the system prompt when memory is off (ctx_memory is then unregistered). The skill-memory guidance carried a 'those belong in ctx_memory' cross-reference that violated the new contract (buildMagicContextSection memory-gating tests). Parameterized ctxSkillMemoryGuidance(memoryEnabled) so the cross-ref drops when memory is off; skill-memory itself stays ungated (independent store).
ef5cba1 to
9c62039
Compare
Summary
Adds skill-memory — per-skill "motor memory" that gives a skill cross-session recall of its own hard-won lessons (gotchas, discoveries, fixes, workflow steps). When a skill's
SKILL.mddeclaresskill-memory: { enabled: true }, accumulated notes for that skill surface automatically in a<skill-memory>block appended to the skill tool's result on every load — and, with the historian extension, the historian writes those notes automatically during compaction (no agent action required).It's fully opt-in per skill and cache-safe by construction: the block rides the tool-result tail (conversation), never the cached system/m[0] prefix, so it can't bust the prompt cache.
How it works
tool.definitionadvertises anintentparam;tool.execute.beforestashes the intent (bounded TTL); the after-hook parses the skill'sBase directory, reads itsSKILL.mdfrontmatter, and formats the recall block. Lands in the tool RESULT (cache-safe).ctx_skill_note(agent-authored) and the historian (auto-extracted). Both dedup on a normalized hash.intent_embedding+delta_embedding(relevance/recency/hit weights tunable per skill viaranking_*frontmatter); FTS5 fallback over a content-linkedskill_memory_ftsvtable; flat recency×hit fallback.TC: skill(<name>)markers in its chunk and emits a<skill_observations>block; both the OpenCode and Pi runners promote those post-commit as global notes (project_identity='*',source_type='historian'), recallable from any project.Review units (4 commits)
The branch is organized into four coherent, reviewable phases:
skill_memorytable migration, the three-hook augmentation, flat recall + storage,ctx_skill_note/ctx_skill_recalltools, opt-indistill-skill-memorydreamer task, TUI/ctx-statusstats, docs.delta_embedding+recall_countcolumns +skill_memory_ftsFTS5 vtable; embed-on-write; the cosine/FTS recall cascade; a programmatic (no-LLM) reembed pre-step.TC: skill(<name>)marker keystone;origin_project+source_typecolumns; global-tier notes unified underproject_identity='*'(collision-merge);partitionKeyrouting.<skill_observations>, parser, validated-result threading, both runners promote via the sharedpromoteSkillObservationshelper, plus aninitializeDatabaseself-heal net (re-createsskill_memory+ensureColumnso an upgraded DB recovers even if a migration row is lost).Schema / migrations
Three migrations (numbered after the current
masterceiling):skill_memorytable, thendelta_embedding/recall_count/FTS, thenorigin_project/source_type/*unification.LATEST_SUPPORTED_VERSIONbumped in lockstep (theschema-version-fencetest enforces it). Migration bodies areensureColumn/IF NOT EXISTSidempotent.Testing
Full plugin + Pi suites pass (one unrelated pre-existing full-suite ordering flake in
tui-config.test.tsthat passes in isolation),tscclean both packages, lint clean, build produces all bundles. Dedicated coverage for the migrations (coexistence + fence), recall rungs, the tools, FTS triggers/backfill, the'*'collision-merge, and the historian promotion path on both runners. Verified working live: the historian auto-extraction writes genuinesource_type='historian'notes, embeddings populate, and the read-siderecall_countincrements on surfacing.Notes for reviewers
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Summary by cubic
Adds per-skill cross-session memory: a cache-safe
<skill-memory>block is appended to eachskilltool RESULT with intent-scoped recall (embeddings + FTS) and historian auto-extraction into global notes. Ships the opt-indistill-skill-memorydreamer task,ctx_skill_note/ctx_skill_recalltools, TUI/CLI stats, and DB migrations to v52 with a self-heal path.New Features
skilltool optionally acceptsintent; before-hook stashes it and after-hook injects recall;ctx_skill_notewrites andctx_skill_recallreads; Status/TUI show per-project totals and pinned counts.intent_embedding+delta_embeddingwith FTS5 fallback; programmatic re-embed backfills NULL/stale vectors beforedistill-skill-memory.TC: skill(<name>)markers →<skill_observations>; both runners promote viapromoteSkillObservationsas global'*'notes (source_type='historian').skill_memorytable + FTS vtable/columns;LATEST_SUPPORTED_VERSION=52;initializeDatabasere-creates missing objects and rebuildsskill_memory_ftswhen needed; dashboard/CLI/config include thedistill-skill-memorytask (off by default).Bug Fixes
'*'so project-local skills surface historian-written notes; writes/dedup remain exact-partition.ctx_skill_notewhen the plugin is disabled; correctly classify singular~/.config/opencode/skill/**asglobal; normalize Windows paths.skill-memory: { enabled: true }; anchor to start-of-file; tolerate leading BOM/whitespace; strip inline#from unquoted scalars.TC: skill(<name>)verbatim (CR/LF/tab only are unsafe); key stashed intents bysessionID:callIDand prune on session delete.ctx_memorycross-reference in skill guidance when memory is off; log recall errors; escape apostrophes in SQL.dirname(resolvedPath)for robustness.Written for commit 9c62039. Summary will update on new commits.
Greptile Summary
This PR introduces skill-memory — per-skill cross-session recall that attaches a
<skill-memory>block to each skill tool result, driven by a 4-rung retrieval cascade (cosine embeddings → FTS5 → flat recency) and historian auto-extraction. The feature is fully opt-in per skill viaSKILL.mdfrontmatter and cache-safe by design (appended to tool results, never to the cached system prefix).skill_memorytable + three DB migrations (v50–v52);ctx_skill_note/ctx_skill_recalltools; before/after hook augmentation with session-scoped intent stash;promoteSkillObservationswrites historian-extracted notes as global'*'-tier entries recallable from any project.recallPartitionPredicateunions the skill's own partition with the global'*'partition so project-local skills also surface historian-written notes — the previous P1 (orphaned historian notes) is fixed.intentByCallIdis now keyedsessionID:callIDand pruned by prefix inonSessionDeleted— the previous P1 (cross-session eviction) is fixed. TheinitializeDatabaseself-heal backfillsskill_memory_ftswhen rows exist but the FTS index is empty — the previous P1 (missing rebuild) is also fixed.Confidence Score: 5/5
Safe to merge; all three correctness issues surfaced in earlier rounds are verifiably fixed in this revision.
The intent stash is now keyed sessionID:callID with per-session prefix pruning, initializeDatabase fires the guarded FTS rebuild, and recallPartitionPredicate unions the own partition with the global '*' partition so historian-written notes reach project-local skills. The remaining findings are maintenance-quality observations — searchSkillMemoryFts calling recallPartitionPredicate twice, the pre-computed part value being passed where raw projectIdentity is expected (idempotent, never wrong), and a cosmetic inaccuracy in the ctx_skill_note success message for global-tier skills.
No files require special attention. The recall.ts and storage.ts recallPartitionPredicate call-site patterns are worth tidying but carry no correctness risk.
Important Files Changed
Sequence Diagram
%%{init: {'theme': 'neutral'}}%% sequenceDiagram participant Agent participant SkillTool as skill tool participant BeforeHook as tool.execute.before participant AfterHook as tool.execute.after participant Registry as SkillLoadRegistry participant RecallCore as recallSkillMemoryBlock participant DB as SQLite (skill_memory) participant Historian Agent->>SkillTool: skill(name, intent) SkillTool->>BeforeHook: stash intent (sessionID:callID) SkillTool-->>Agent: tool output (Base directory: file:///...) AfterHook->>AfterHook: parseSkillProvenance(output) AfterHook->>AfterHook: parseFrontmatterConfig(SKILL.md) AfterHook->>Registry: set(sessionID:skillId, provenance+config) AfterHook->>AfterHook: getAndDeleteIntent(sessionID:callID) AfterHook->>RecallCore: recallSkillMemoryBlock(skill, intent, scope, projectIdentity) RecallCore->>DB: "embedTextForProject(intent) -> vector" alt embeddings available RecallCore->>DB: "getRankingCandidates -> cosine rank" else FTS fallback RecallCore->>DB: searchSkillMemoryFts(sanitized intent) else flat fallback RecallCore->>DB: getSkillMemoryNotes (recency x hit) end RecallCore->>DB: bumpRecallCountByIds RecallCore-->>AfterHook: skill-memory block AfterHook->>AfterHook: append block to output.output Agent->>DB: "ctx_skill_note -> insertSkillMemoryNote / bumpHitCount" Historian->>Historian: detect TC: skill(name) markers Historian->>DB: "promoteSkillObservations (tier=global, project_identity='*')"%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%% sequenceDiagram participant Agent participant SkillTool as skill tool participant BeforeHook as tool.execute.before participant AfterHook as tool.execute.after participant Registry as SkillLoadRegistry participant RecallCore as recallSkillMemoryBlock participant DB as SQLite (skill_memory) participant Historian Agent->>SkillTool: skill(name, intent) SkillTool->>BeforeHook: stash intent (sessionID:callID) SkillTool-->>Agent: tool output (Base directory: file:///...) AfterHook->>AfterHook: parseSkillProvenance(output) AfterHook->>AfterHook: parseFrontmatterConfig(SKILL.md) AfterHook->>Registry: set(sessionID:skillId, provenance+config) AfterHook->>AfterHook: getAndDeleteIntent(sessionID:callID) AfterHook->>RecallCore: recallSkillMemoryBlock(skill, intent, scope, projectIdentity) RecallCore->>DB: "embedTextForProject(intent) -> vector" alt embeddings available RecallCore->>DB: "getRankingCandidates -> cosine rank" else FTS fallback RecallCore->>DB: searchSkillMemoryFts(sanitized intent) else flat fallback RecallCore->>DB: getSkillMemoryNotes (recency x hit) end RecallCore->>DB: bumpRecallCountByIds RecallCore-->>AfterHook: skill-memory block AfterHook->>AfterHook: append block to output.output Agent->>DB: "ctx_skill_note -> insertSkillMemoryNote / bumpHitCount" Historian->>Historian: detect TC: skill(name) markers Historian->>DB: "promoteSkillObservations (tier=global, project_identity='*')"Comments Outside Diff (1)
packages/plugin/src/features/magic-context/skill-memory/recall.ts, line 481-484 (link)catch {}makes recall errors invisibleAny exception thrown inside
recallSkillMemoryBlock— a SQLite error, embedding provider crash, or a coding mistake — is silently swallowed and returns an empty string. From the caller's perspective this is indistinguishable from "no notes exist" or "skill-memory disabled". At minimum asessionLogorconsole.warncall here would let a developer diagnose why the recall block is absent without attaching a debugger.Reviews (6): Last reviewed commit: "fix(skill-memory): gate ctx_memory cross..." | Re-trigger Greptile