Skip to main content

skill-learn

Memory creation - add memories from text, files, directories, or task artifacts, with content mapping and deduplication. Invoke for /learn command memory operations.

跳到安装

来源信息

仓库
benbrastmckie/nvim
最近来源活动
2026年7月28日 01:49
检测到的 SKILL.md 语言
英语
星标
444
分支
459

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
2 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
skill-learn
description
Memory creation - add memories from text, files, directories, or task artifacts, with content mapping and deduplication. Invoke for /learn command memory operations.
allowed-tools
Bash, Grep, Read, Write, Edit, AskUserQuestion
# Learn Skill (Direct Execution) Direct execution skill for memory creation. Handles memory creation, similarity search, classification, and index maintenance through content mapping, MCP-based deduplication, and three memory operations (UPDATE, EXTEND, CREATE). This skill owns memory *creation* only; vault analysis and maintenance (scoring, health reporting, purge/merge/compress/refine/gc, and the telemetry-sourced sub-modes) live in the sibling `skill-distill` skill. **MANDATORY INTERACTIVE REQUIREMENT -- DO NOT SKIP**: - STOP at Step 4 and call AskUserQuestion to show files. Write NOTHING to disk until user responds. - STOP at Memory Search and call AskUserQuestion for each segment. Write NOTHING to disk until user responds. - These are not optional. Running autonomously without user input is a critical failure. ## Context References Reference (do not load eagerly): - Path: `@.memory/30-Templates/memory-template.md` - Memory template - Path: `@.memory/20-Indices/index.md` - Memory index - Path: `@.memory/memory-index.json` - Machine-queryable memory index - Path: `@.claude/context/project/memory/learn-usage.md` - Usage guide --- ## Execution Modes | Mode | Input | Description | |------|-------|-------------| | `text` | Text content | Add quoted text as memory | | `file` | File path | Add single file content as memory | | `directory` | Directory path | Scan directory for learnable content | | `task` | Task number | Review task artifacts and create memories | All non-task modes flow through: **Content Mapping** -> **Memory Search** -> **Memory Operations** --- ## Content Mapping Content mapping is the intermediate representation between input acquisition and memory operations. It segments input into topic-aligned chunks that can be matched against existing memories. ### Content Map Data Structure ```json { "source": { "type": "text|file|directory", "path": "/path/to/input", "total_tokens": 2500 }, "segments": [ { "id": "seg-001", "topic": "python/libs/requests", "source_file": "/path/to/file.md", "source_lines": "15-42", "summary": "HTTP request retry pattern with backoff", "estimated_tokens": 350, "key_terms": ["requests", "retry", "backoff", "session", "timeout"] } ] } ``` ### Field Descriptions | Field | Type | Description | |-------|------|-------------| | `id` | string | Unique segment identifier (seg-NNN) | | `topic` | string | Inferred topic path (slash-separated hierarchy) | | `source_file` | string | Original file path (for file/directory modes) | | `source_lines` | string | Line range in source file (e.g., "15-42") | | `summary` | string | 1-2 sentence summary of segment content | | `estimated_tokens` | number | Approximate token count for this segment | | `key_terms` | array | 3-5 significant terms for matching | ### Segmentation Algorithms #### Structured Files (Markdown) Split at heading boundaries: ``` 1. Identify all headings (# ## ### ####) 2. Each heading starts a new segment 3. Segment includes all content until next same-or-higher level heading 4. Top-level content before first heading becomes its own segment ``` #### Structured Files (Code) Split at blank-line-separated blocks: ``` 1. Identify function/class definitions 2. Group related comments with their definitions 3. Separate standalone comment blocks as documentation segments 4. Keep import/require blocks together ``` #### Unstructured Text Split at paragraph boundaries with topic grouping: ``` 1. Split at double-newline (paragraph boundaries) 2. Group adjacent paragraphs with keyword overlap >40% 3. Single-sentence paragraphs merge with adjacent ``` #### Directory Input Each file becomes an initial segment, then large files are split: ``` 1. Each file is an initial segment 2. Files >800 tokens are split at section boundaries 3. Files <100 tokens are candidates for merging with related files ``` ### Small-Input Bypass Inputs under 500 tokens skip segmentation and become a single segment: ``` if total_tokens < 500: segments = [{ "id": "seg-001", "topic": inferred_topic, "summary": first_line_or_60_chars, "estimated_tokens": total_tokens, "key_terms": extract_keywords(content, 5) }] ``` ### Segment Size Guidelines | Condition | Action | |-----------|--------| | Segment <100 tokens | Merge with adjacent same-topic segment | | Segment 200-500 tokens | Ideal size, no action | | Segment >800 tokens | Split at next heading/paragraph boundary | ### Key Term Extraction Extract 3-5 significant terms per segment: ``` 1. Remove stop words (the, a, is, are, etc.) 2. Extract nouns and technical terms (>4 characters) 3. Prioritize: proper nouns > technical terms > common nouns 4. Deduplicate (case-insensitive) 5. Return top 5 by frequency within segment ``` --- ## Memory Search After content mapping, each segment is matched against existing memories to determine the appropriate operation (UPDATE, EXTEND, or CREATE). ### MCP Search Path When MCP server is available, use the execute pattern: ``` For each segment in content_map.segments: query = segment.key_terms.join(" ") results = execute("search", { "query": query, "vault": ".memory", "limit": 5 }) ``` ### Grep Fallback Path When MCP is unavailable, use keyword-based file search: ```bash # For each segment for keyword in $key_terms; do grep -l -i "$keyword" .memory/10-Memories/*.md 2>/dev/null done | sort | uniq -c | sort -rn | head -5 ``` ### Overlap Scoring Score keyword overlap between segment and each matching memory: ``` overlap_score = |segment_terms intersect memory_terms| / |segment_terms| Where: - segment_terms = segment.key_terms - memory_terms = keywords extracted from memory content (same algorithm) ``` ### Exact-Key Dedup for Reserved Namespaces The reserved topic namespace `email/preferences/*` (see `.claude/extensions/email/context/project/email/design/email-to-memory-preferences.md`) is a **sanctioned, explicitly documented deviation** from the fuzzy Classification Thresholds below. For a segment/candidate whose `topic` matches `email/preferences/*`, an **exact `topic ==` match** against `.memory/memory-index.json` short-circuits classification straight to UPDATE/EXTEND (disambiguated by the namespace-scoped tally-arithmetic variant two sections below) WITHOUT ever computing keyword overlap: ```bash jq --arg k "email/preferences/${ACCOUNT}/${KEY}" \ '.entries[] | select(.topic == $k)' .memory/memory-index.json ``` Rationale: for this namespace the identity key (sender/domain normalization, computed deterministically by `.claude/scripts/email-preference-harvest.sh`) is already a verified, deterministic identity — re-deriving it via fuzzy keyword overlap would be strictly *fuzzier* than the key itself. A miss (no exact match) falls through to CREATE by default; the ordinary fuzzy path below still runs afterward as a **near-miss suggestion only** (e.g. flagging `email/preferences/gmail/mail.foo.com` as a near-miss of an existing `email/preferences/gmail/foo.com` entry) — presented to the human at gate time, never auto-applied. This exact-key short-circuit applies ONLY to the reserved `email/preferences/*` namespace; all other topics continue to use the Classification Thresholds below unchanged. ### Classification Thresholds | Overlap Score | Classification | Action | |---------------|----------------|--------| | >60% | HIGH | UPDATE - Replace memory content | | 30-60% | MEDIUM | EXTEND - Append new section | | <30% | LOW | CREATE - New memory | ### Namespace-Scoped Tally-Arithmetic UPDATE/EXTEND (`email/preferences/*` only) Distinct from the generic wholesale UPDATE/EXTEND templates elsewhere in this skill (which replace/append full memory *content*), the reserved `email/preferences/*` namespace's UPDATE/EXTEND operations mutate a small structured **tally block** in the memory body instead: - **EXTEND** (this round's dominant confirmed action matches the memory's stored dominant action): append a dated `## History` line (`- {date}: +{action} (n={n_this_round}, scope={inbox|archive})`) and bump the matching action's counter and `last_seen`. Existing content is never rewritten. - **UPDATE** (this round's dominant action contradicts the stored dominant action): increment the *opposite* counter (never overwrite/reset the matching one — the contradicting action's own count and `last_seen` are what change), which can flip the *derived* dominant action per the tie-break rule below; move the prior summary line to `## History` marked `(superseded)`. Both operations reuse the exact same tally arithmetic (`.claude/scripts/email-preference-harvest.sh tally-op`) — the EXTEND/UPDATE distinction is purely about which body sections get touched (History append vs. superseded-summary move), not about a different counter-update rule. **Dominant action** is always *derived*, never a stored scalar: `dominant = argmax(delete_count, archive_count, keep_count)`, ties broken by whichever action has the more recent per-action `last_seen` (`.claude/scripts/email-preference-harvest.sh dominant`). **Memory body template** (§3.5 of the design; schema fields map 1:1 to what these operations read/write): ```markdown --- title: "Email preference: {domain-or-hash-key}" created: {today} tags: [email, preference, {domain}] topic: "email/preferences/{account}/{key}" source: "skill-email-cleanup harvest" modified: {today} keywords: [{domain}, email, preference] summary: "Confirmed-decision tally for {domain-or-hash-key}: {dominant_action} ({dominant_count}/{total})" retrieval_count: 0 last_retrieved: category: preference --- # Email preference: {domain-or-hash-key} **Tally**: delete={delete_count} (last: {delete_last_seen}), archive={archive_count} (last: {archive_last_seen}), keep={keep_count} (last: {keep_last_seen}) **Dominant action** (derived): {dominant_action} **Evidence**: junked {delete_count + archive_count}, kept {keep_count} ## History - {date}: +{action} (n={n_this_round}, scope={inbox|archive}) ## Connections <!-- Add links to related memories using [[MEM-filename]] syntax --> ``` **Archive-scope tally isolation**: archive-scope-sourced confirms (from `skill-email-cleanup --archive`) are recorded in a distinct `### Archive-scope tally` sub-section within the SAME memory (never a separate memory) — this preserves the "one evolving memory per sender/domain" invariant while preventing a burst of old archive-triage confirms from silently dominating a sender's current-inbox dominant action. The archive-scope sub-section carries its own `{delete_count, archive_count, keep_count, last_seen}` tally, computed and derived identically to the inbox-scope tally above, but never merged into it. **Revocation/edit UX**: a user-invoked "forget this preference" action reuses the existing tombstone pattern documented in the sibling `skill-distill/SKILL.md`'s Purge Sub-Mode "Tombstone Application" subsection (`status: tombstoned`, `tombstoned_at`, `tombstone_reason`) — set `tombstone_reason: "user_revoked"` for this case. This is distinct from `/distill --purge` (automatic, staleness-driven) and is never automatic; `skill-email-cleanup`'s Stage 7 wires the user-invoked trigger for it. ### Search Result Presentation -- MANDATORY STOP **YOU MUST call AskUserQuestion for EACH segment before writing anything. Do NOT infer what the user wants. Do NOT skip segments. Do NOT write memory files without explicit user confirmation per segment.** Present each segment with related memories via AskUserQuestion: ``` Segment: {segment.summary} Topic: {segment.topic} Key terms: {segment.key_terms.join(", ")} Related Memories: 1. MEM-requests-retry-patterns (72% overlap) -> Recommended: UPDATE 2. MEM-python-http-patterns (45% overlap) -> Recommended: EXTEND 3. MEM-api-error-handling (18% overlap) -> Recommended: CREATE (no strong match) What would you like to do with this segment? [ ] UPDATE MEM-requests-retry-patterns (replace content) [ ] EXTEND MEM-python-http-patterns (append section) [ ] CREATE new memory [ ] SKIP - don't save this segment ``` ### Interactive Override Users can override any recommendation: - Change UPDATE to CREATE (preserve existing, create duplicate) - Change EXTEND to UPDATE (replace instead of append) - Skip any segment - Merge segments before processing (combine into single memory) --- ## Memory Operations Three distinct operations for memory management: ### UPDATE Operation Replace memory content while preserving structure: ``` 1. Read existing memory file 2. Preserve frontmatter: created (original), tags, topic 3. Update frontmatter: modified = today 4. Move current content to ## History section with date marker 5. Replace main content with new segment content 6. Preserve ## Connections section 7. Write updated memory ``` Template for UPDATE: ```markdown --- title: "{new_title_from_segment}" created: {original_created} tags: {merged_tags} topic: "{existing_or_updated_topic}" source: "{new_source}" modified: {today} --- # {new_title} {new_content_from_segment} ## History
在 GitHub 查看
这个 SKILL.md 很大,SkillsMP 这里只预览前一段内容。 在 GitHub 查看