Insights Skill -- Knowledge Extraction & Skill Evolution
Extract and backfill durable insights from existing transcripts and CLAUDE.md files into _insights.yaml. Compile execution feedback (edge cases, corrections) into patterns and propose SKILL.md improvements.
This skill complements the forward-looking extraction in /transcript Step 3.5 and /ops Step 5.5 by processing the historical corpus and closing the feedback loop.
Design Principles
- No duplication of extraction logic. The authoritative definition of insight types, thresholds, and
_insights.yamlformat lives in/transcriptStep 3.5. This skill references it and includes a quick-reference copy for convenience. - Dedup by
source.file. Processing the same file twice never creates duplicate entries. - Additive only. Never removes or modifies existing insights (except
scan-claude-mdwhich replaces stale CLAUDE.md-sourced entries, and the promotion/demotion passes incompilewhich mutateconfidence,confirmation_count,status, andsuperseded_byfields per CR-013). - Silent accumulation, active loading. Insights are written by
/transcript,/ops, and this skill. Promoted rules (per CR-013 lifecycle below) are read back by/opsand/transcriptas a context preamble before each run. Hypotheses remain silent; only rules surface.
Confidence Lifecycle (CR-013)
Each insight has an optional confidence field:
hypothesis(default when absent) — observation that needs more confirmation. Not loaded into other skills' context.rule— confirmed pattern. Loaded as a preamble by/opsand/transcriptwhen working in the rule's folder chain.
Two lifecycle transitions, both performed by /insights compile:
- Promotion: when ≥
compile_threshold(default 3) semantically similarhypothesisentries exist in one folder, the canonical (earliest) entry is promoted toconfidence: rule. Non-canonical entries are markedstatus: superseded,superseded_by: <canonical-id>. The canonical entry'sconfirmation_countis set to the group size andconfirmations[]is populated with each merged entry'ssource. - Demotion: when a
correctionentry contradicts arule(same primary tag, opposing summary keyword), the rule'sconfidenceflips back tohypothesis, the correction'ssourceis appended tocontradicted_by[], andconfirmation_countis reduced by 1 (floor 1).
confidence and status are orthogonal:
status(active / superseded / archived) is the curation/archival lifecycle.confidence(hypothesis / rule) is the maturity lifecycle.
A rule can be archived. A hypothesis can be superseded by a more specific hypothesis. Both fields coexist.
Schema fields added in v2 (all optional, additive):
confidence: hypothesis | rule # default: hypothesis
confirmation_count: 1 # integer, default 1
confirmations: # list, populated on promotion
- source: <relative-path>
date: YYMMDD
contradicted_by: # list, populated on demotion
- source: <relative-path>
date: YYMMDD
String Resolution
Template strings marked as {strings.section.key} are resolved at runtime.
Resolution order:
- Org config
stringssection (if loaded) - Language-matched defaults from
base.yaml:swedish->strings_svenglish->stringsinput-> match detected transcript language
- Hardcoded strings already in template (fallback)
Configuration
Reads workflows.knowledge_extraction from base.yaml (or org config override):
| Key | Default | Description |
|---|---|---|
enabled |
true |
Master switch for extraction |
min_insights |
1 |
Minimum qualifying insights to write file |
types |
[decision, preference, learning, opportunity, pattern] |
Insight types to extract |
max_per_meeting |
10 |
Cap per source file |
If enabled: false, all subcommands exit immediately with a message.
Subcommands
reprocess [target] -- Extract insights from existing transcripts
Trigger: /insights reprocess <target>
Targets (all three supported):
- Folder path:
/insights reprocess _contacts/bob-smithor/insights reprocess _projects/acme/meetings/management all:/insights reprocess all-- all folders containing a CHANGELOG.mdsince YYMMDD:/insights reprocess since 260201-- only files dated after the given date, across all folders with CHANGELOG.md
Steps:
Resolve target folders:
- If folder path: resolve to that single folder (must contain CHANGELOG.md)
- If
all: scan vault recursively for all folders containing CHANGELOG.md (max depth 6, skip.archive/,.handoff/,clones/) - If
since YYMMDD: same asall, but with date filter applied in step 4
For each target folder, list
YYMMDD-*.mdfiles (transcript files matching the 6-digit date prefix pattern)Build dedup set: If
_insights.yamlexists, load it and collect allsource.filevalues into a setFilter files:
- Skip files already in the dedup set (already processed)
- Skip standup files: filename contains
standupordaily-standup, OR file is <500 words with no qualifying insights - If
since YYMMDDtarget: additionally skip files whose filename date prefix is before the given date
Sort remaining files chronologically (oldest first, for consistent ID ordering)
Process each file:
- Read the file content
- Apply the same extraction logic as
/transcriptStep 3.5:- Scan for decisions with rationale, stated preferences, learnings, opportunities, and patterns
- Apply threshold: only non-obvious, durable, specific insights
- Respect
max_per_meetingcap - Respect configured
typeslist
- For each qualifying insight, create an entry with:
id: next available ID (fromnext_idin existing file, or starting at 1)type: one of the configured typesdate: extracted from the filename prefix (YYMMDD)summary: one sentencerationale: one sentence contextsource.file: the transcript filenamesource.section: the section heading where the insight was foundtags: max 5 keywordsstatus:activesuperseded_by:null
Write/append to
_insights.yamlin the same folder as the CHANGELOG.md:- If file exists: append new entries, update
next_idandlast_updated - If file does not exist: create with
version: 2,contextset from folder name or CHANGELOG context
- If file exists: append new entries, update
Progress output:
Processing =bob-smith (8 files, 6 new)... Extracted 4 insights
Processing acme/meetings/management (52 files, 52 new)... Extracted 28 insights
...
Reprocessing complete.
Processed 186 files across 14 folders.
Extracted 89 insights (89 new, 0 already existed).
Skip conditions:
- Folder has no CHANGELOG.md
- All files already processed (dedup)
- File is a pure standup (<500 words, no qualifying insights)
scan-claude-md -- Extract knowledge from CLAUDE.md files
Trigger: /insights scan-claude-md
Steps:
Scan vault subfolders for CLAUDE.md files (max depth 4, skip
.archive/,.handoff/,clones/)For each CLAUDE.md, find nearest parent folder with CHANGELOG.md as target for
_insights.yaml. If no CHANGELOG.md exists in any parent (up to vault root), skip this CLAUDE.md with a note.Check freshness:
- If
_insights.yamlalready has entries withsource.file: "CLAUDE.md"AND the CLAUDE.md file has not been modified sincelast_updatedin the insights file, skip (already current) - If CLAUDE.md is newer: remove all existing
source.file: "CLAUDE.md"entries from_insights.yaml(preserving transcript-sourced insights), then re-extract
- If
Extract insights using type mapping:
Signal in CLAUDE.md Insight type "Chose X over Y", "Using X because", "Beslut:", "Decision:" decision"NEVER", "MUST", "Always", "Alltid", "Aldrig" preference"Avoid", "Don't", "Undvik", "Learned:", "Lärdom:" learningRules, conventions, naming patterns, routing tables, format specifications patternNote:
opportunitytype is not mapped for CLAUDE.md -- these files contain established decisions and conventions, not future opportunities. Opportunities are only extracted from transcripts viareprocess.Set source metadata:
source.file:"CLAUDE.md"source.section: the##heading under which the insight was found
Skip sections that contain only:
- Bare directory listings (pure file trees without commentary)
- Pure glossaries (term: definition lists without rationale)
- Metadata-only content (version numbers, dates, links without context)
Write to
_insights.yamlfollowing the same format. Assign IDs continuing fromnext_id.
Output:
Scanning CLAUDE.md files...
acme/CLAUDE.md -> acme/ (12 insights, replaced 8 stale)
_contacts/bob-smith/CLAUDE.md -> _contacts/bob-smith/ (3 insights, new)
bravo/CLAUDE.md -> skipped (no CHANGELOG.md in parent)
...
Scan complete.
Processed 14 CLAUDE.md files.
Extracted 42 insights (34 new, 8 replaced).
Skipped 3 files (no CHANGELOG.md parent).
status -- Show current insights state
Trigger: /insights status
Steps:
- Scan vault for all
_insights.yamlfiles - Scan vault for all folders with CHANGELOG.md (potential insight targets)
Output:
Insights Status
===============
_insights.yaml files: 14
Total insights: 186
By type:
decision: 52
preference: 38
learning: 41
opportunity: 28
pattern: 27
By status:
active: 172
superseded: 11
archived: 3
Top folders:
acme/meetings/management 42 insights
_contacts/bob-smith 18 insights
_contacts/david-ekberg 15 insights
...
Reprocessing opportunities:
12 folders have CHANGELOG.md but no _insights.yaml
3 folders have _insights.yaml older than newest transcript
Total: ~340 unprocessed transcript files
Confidence Lifecycle (CR-013)
─────────────────────────────
Hypotheses: 142
Rules: 18 (most recent promotion: 260505)
Recent demotions: 2 (last 30 days)
Top 5 hypotheses near promotion (count, type, summary):
2 preference "Carol prefers async updates over sync standups"
2 pattern "Marketing meetings run 10-15 min over scheduled time"
2 learning "GA4 events take ~24h to surface in dashboards"
2 decision "Use _projects/ for time-boxed initiatives"
2 pattern "Bob wraps board prep with risk callout"
Skill Evolution
───────────────
Execution feedback: 23 entries (18 edge_case, 5 correction)
Compiled patterns: 3 skill_pattern entries
Pending proposals: 2 in <proposals_path>/
Applied proposals: 1 in <proposals_path>/.applied/
Config: auto_apply=false, compile_threshold=3, propose_threshold=5,
demote_on_contradiction=true
Status implementation notes:
- "Hypotheses" count = entries with
confidence: hypothesisOR missingconfidencefield, ANDstatus: active. - "Rules" count = entries with
confidence: ruleANDstatus: active. - "Most recent promotion" = max
dateacross rules where the rule was promoted (track via the most recent entry inconfirmations[], since that is when the threshold was crossed). - "Recent demotions" = count of entries with non-empty
contradicted_by[]whose latest demotion date is within the last 30 days. - "Top 5 hypotheses near promotion" = hypotheses with the highest
confirmation_count, ties broken by recency. Show count, type, and summary.
compile -- Compile execution feedback into patterns and run lifecycle passes
Trigger: /insights compile or /insights compile since YYMMDD
Performs three passes in order: skill-pattern compilation, hypothesis-to-rule promotion, rule-to-hypothesis demotion.
Pass 1: skill_pattern compilation (existing)
Reads execution feedback entries (edge_case, correction) across _insights.yaml files and compiles recurring patterns into skill_pattern entries.
- Scan all
_insights.yamlfiles in the vault for entries wheresource.skillis set (execution feedback) - Filter by date if
since YYMMDDis specified - Group by similarity -- cluster entries by tags, summary keywords, and
source.skill+source.step - Apply compile threshold -- only groups with
compile_threshold(default: 3) or more entries become patterns. Read threshold fromworkflows.knowledge_extraction.evolution.compile_thresholdin config. - For each qualifying group, create a
skill_patternentry in the most relevant_insights.yaml:- id: [next_id] type: skill_pattern date: YYMMDD # today summary: "Pattern description synthesized from N occurrences" detail: "Dates, contexts, and common resolution across occurrences" source: skill: insights/compile entries: [list of source entry IDs and their _insights.yaml locations] tags: [synthesized, from, source, entries] status: active - Dedup -- if a
skill_patternentry already covers the same cluster (by matchingsource.entries), update it instead of creating a duplicate
Pass 2: hypothesis → rule promotion (CR-013)
For each folder's _insights.yaml, find clusters of confirmed hypotheses and promote the canonical entry to a rule.
- Filter to candidates: entries where
confidenceishypothesis(or absent) ANDstatus: activeANDtypeis one ofdecision | preference | learning | pattern(skipopportunity,quote,metric,edge_case,correction,skill_pattern).metricis never promotable (CR-046): the same measurement recurring three times is a time series, not a standing instruction. Trend questions belong in/analytics. - Group by similarity within the folder:
- Same
type - Fuzzy summary match (case-insensitive, ignore stop words; require ≥60% token overlap)
- At least one shared tag
- All three conditions required (conservative; prefer false negatives over false promotions)
- Same
- Apply threshold: groups with size ≥
compile_threshold(default 3, fromworkflows.knowledge_extraction.evolution.compile_threshold) qualify. - For each qualifying group:
- Pick the earliest entry by
dateas canonical. - Set
canonical.confidence: rule. - Set
canonical.confirmation_countto group size. - Append each non-canonical entry's
sourcetocanonical.confirmations[]. - Mark each non-canonical entry
status: superseded,superseded_by: <canonical-id>.
- Pick the earliest entry by
- Dedup: if the canonical entry already has
confidence: rule, only append new (not-already-listed) confirmations and updateconfirmation_count.
Pass 3: rule → hypothesis demotion (CR-013)
Skipped if workflows.knowledge_extraction.evolution.demote_on_contradiction is false. Default: true.
- Find all rules: entries with
confidence: ruleANDstatus: active, across the folder chain (current folder and parents per CR-011 walking resolution). - For each rule, scan for targeting corrections:
correctionentries newer than the rule's most recent confirmation, that:- Share the rule's primary tag (first tag in
tags[]). - Contain an opposing keyword in
summary(heuristic: rule says "always X" and correction says "do not X" or "X was wrong"; rule says "prefers Y" and correction says "does not prefer Y").
- Share the rule's primary tag (first tag in
- For each rule with at least one targeting correction:
- Set
rule.confidence: hypothesis. - Append each correction's
sourcetorule.contradicted_by[]. - Reduce
rule.confirmation_countby the number of contradictions, floor at 1.
- Set
- Do not delete confirmations. History is preserved in
confirmations[]for audit.
Output:
Compiling execution feedback and running lifecycle passes...
Pass 1 (skill_pattern compilation):
Scanned 14 _insights.yaml files, found 23 execution feedback entries.
Compiled 3 patterns.
Skipped 8 entries below compile threshold (3).
Pass 2 (hypothesis → rule promotion):
Scanned 142 active hypotheses across 14 folders.
Promoted 4 rules:
- meetings/management/_insights.yaml#17 [preference] "Bob prefers concise weekly summaries" (3 confirmations)
- _contacts/bob-smith/_insights.yaml#8 [pattern] "Bob raises customer-success topics last in 1-on-1s" (4 confirmations)
- meetings/board/_insights.yaml#5 [decision] "Board updates use English for India team" (3 confirmations)
- meetings/marketing/ppc/_insights.yaml#12 [learning] "PMax campaigns underperform below $500/day budget" (3 confirmations)
Marked 8 superseded entries (canonical's mergees).
Pass 3 (rule → hypothesis demotion):
Scanned 18 active rules.
Demoted 1 rule:
- meetings/management/_insights.yaml#11 [preference] "Always include Risk Assessment section"
contradicted by 260507-summary.md (Bob asked to skip risk section for routine weeks)
Compile freshness stamp (CR-020)
After all three passes, write last_compiled: YYMMDD as a top-level field in every _insights.yaml the run scanned (additive; v1/v2 readers ignore it). This makes compile-staleness detectable: /insights status and /ops sweep flag when the newest entry in a file is >30 days newer than its last_compiled (or when the field is absent entirely -- i.e. compile has never run). Insights are write-heavy by design; the stamp is what keeps the synthesis half of the loop honest.
normalize -- One-shot schema migration for drifted _insights.yaml files (CR-020)
Trigger: /insights normalize [path] [--dry-run] (no path = whole vault; --dry-run is the DEFAULT — writing requires explicit --apply)
Brings legacy and drifted _insights.yaml files up to the current schema. Complements /ops normalize (which fixes Swedish characters); this fixes structure and vocabulary.
What it fixes, per entry:
| Drift | Fix |
|---|---|
ISO date "2026-03-09" |
→ 260309 (YYMMDD) |
String ids (bp-017, board-003) |
→ sequential integers preserving order; record old id as legacy_id |
Missing type |
→ infer from content; if ambiguous, set the most likely type and append type-inferred to tags for review |
Non-canonical types (decision-pattern, principle, outcome, design, ...) |
→ map to nearest canonical (pattern, learning, learning, decision) |
Non-canonical confidence (high, confirmed, supported) |
→ hypothesis + confirmation_count: 2 (the writer evidently meant "confirmed once more") |
Non-canonical confidence (medium, low) |
→ hypothesis (count unchanged) |
Legacy fields (added: → date, string source: → source.file) |
→ rename/restructure |
superseded_by set but status: active |
→ status: superseded |
Missing top-level version/next_id/last_updated |
→ add (version: 2, next_id: max(id)+1, last_updated from newest entry) |
| Tags > 5 | → truncate from the tail |
Process:
- Scan target for
_insights.yamlfiles (skip.archive/,.transcripts/,.handoff/,clones/) - Report every proposed change grouped by file (dry-run output = a unified change list with counts per drift class)
- On
--apply: write files atomically, add a one-line CHANGELOG entry in each affected folder (- **YYMMDD: Normalize** _insights.yaml -- N schema fixes (CR-020)) - Never touch entry content (
summary/rationaletext) -- structure and vocabulary only; content remediation stays with/ops normalize
synthesize -- Render insight clusters into the knowledge wiki (CR-027)
Trigger: /insights synthesize [topic|all] (no argument = all clusters above threshold)
Turns the accumulated _insights.yaml corpus into a curated wiki: readable, crosslinked topic articles plus a master index. This is the synthesis layer the atomic entries feed — compile promotes rules (machine-facing context), synthesize produces articles (human- and session-facing knowledge). Clustering here is semantic and vault-wide (cross-folder, by topic), deliberately unlike compile Pass 2 (mechanical, per-folder): prose summaries rarely repeat verbatim, so token-overlap cannot build this layer.
Config (workflows.knowledge_synthesis in base.yaml or org/vault config):
| Key | Default | Meaning |
|---|---|---|
enabled |
true |
Master switch |
article_threshold |
5 |
Minimum insights in a topic cluster to warrant an article |
wiki_path |
.knowledge/wiki |
Article location, vault-relative |
Process:
- Load the corpus: every
_insights.yaml(skip.archive/,.transcripts/,.handoff/,clones/), entries withstatus: active. Typesquoteandopportunityare supporting material (quotes illustrate; opportunities go in an article's open-questions section) — they never drive cluster selection alone. - Cluster by topic, vault-wide: group semantically related insights across folders (shared tags are the seed; semantic judgment merges synonymous tags and splits overloaded ones). A cluster ≥
article_threshold(or an explicitly requested<topic>) gets an article. - Write/update the article at
<wiki_path>/<topic-slug>.md:- Topic-named, not dated — articles are living documents (like rolling plans), never
YYMMDD-prefixed. - Frontmatter:
sources:(list offile#idfor every insight used),updated: YYMMDD,related: [slugs]. - Body: synthesized prose — what has been learned, how thinking evolved, points of tension between insights, and an open-questions section. Verbatim
quoteentries may be quoted with attribution. Obsidian[[wikilinks]]to related articles. Language per the vault language policy; names allowed (CR-020 reusability note applies — this wiki is private). - Vocabulary is canonicalized at synthesis: known ASR-legacy terms in source insights are written correctly in articles (source entries stay untouched — the wiki is the cleaned layer).
- Verticals boundary: if the topic matches a registered
workflows.verticalsdoc, the article LINKS to the vertical for org-operational state instead of duplicating it.
- Topic-named, not dated — articles are living documents (like rolling plans), never
- Idempotent refresh: re-running updates an article only from insights not yet in its
sources:, appending/reworking sections as needed and bumpingupdated:. An article containing<!-- human-edited -->is NEVER auto-updated — report it and ask (flag once, respect the answer). - Maintain
<vault>/.knowledge/INDEX.md: one line per article —[[slug]] — one-sentence hook (updated YYMMDD)— grouped by theme; plus an Osorterat section listing loose notes at the.knowledge/root (legacy notes are never modified or moved by this skill). - Report: articles created/updated/skipped(human-edited), clusters below threshold (with counts, so growth toward threshold is visible).
How the wiki is USED (the no-RAG contract): a session answering a knowledge question reads INDEX.md first, then opens only the relevant article(s). No vault-wide scanning, no retrieval infrastructure. The INDEX is maintained by this subcommand only — never hand-edited by other skills.
propose -- Generate SKILL.md improvement proposals
Trigger: /insights propose
Reads compiled skill_pattern entries and generates concrete SKILL.md improvement proposals.
Steps:
Scan all
_insights.yamlfiles forskill_patternentriesApply propose threshold -- only patterns with
propose_threshold(default: 5) or more underlying occurrences generate proposals. Read threshold fromworkflows.knowledge_extraction.evolution.propose_thresholdin config.For each qualifying pattern: a. Read the target SKILL.md file (determined by
source.skill) b. Identify the relevant step or section c. Generate a concrete proposed change as a markdown fileSave proposals to the configured private proposals path —
workflows.knowledge_extraction.evolution.proposals_path(default<vault>/.skill-evolution/proposals/, vault-relative). Never inside the skill repo (CR-028): generated proposals derive from vault data and are development-evolution material — local only. Format:# Proposal: [Short title] **Based on:** [N] occurrences of [pattern summary] **Target:** skills/[skill]/SKILL.md **Pattern entry:** [reference to skill_pattern in _insights.yaml] ## Proposed change **In section:** [Step or section name] **Action:** [Add/Modify/Remove] > [Exact text to add or replace, written in the same style as the target SKILL.md] ## Rationale [Why this change addresses the pattern, with references to specific occurrences]Check auto_apply setting from
workflows.knowledge_extraction.evolution.auto_apply:- If
false(default): save proposal file, report to user - If
true: apply the change to SKILL.md directly, log in CHANGELOG with[AUTO-EVOLUTION]tag, save proposal as record
- If
Output (auto_apply: false):
Generated 2 proposals:
1. <proposals_path>/260404-transcript-name-disambiguation.md
Target: skills/transcript/SKILL.md (Step 1)
Based on: 7 edge_case entries across 4 contacts
2. <proposals_path>/260410-ops-short-call-threshold.md
Target: skills/transcript/SKILL.md (Step 4)
Based on: 5 skill_pattern entries
Review proposals and run /insights propose apply to accept.
Output (auto_apply: true):
Auto-applied 2 proposals:
1. skills/transcript/SKILL.md -- added name disambiguation pre-check (Step 1)
[AUTO-EVOLUTION] Based on 7 edge_case entries
2. skills/transcript/SKILL.md -- added short-call skip for task import (Step 4)
[AUTO-EVOLUTION] Based on 5 skill_pattern entries
Changes logged in CHANGELOG.md. Review with: git diff HEAD~1
propose apply -- Apply a proposal
Trigger: /insights propose apply [proposal-file] or /insights propose apply all
Steps:
- If specific file: Read the proposal, apply the change to the target SKILL.md
- If
all: Apply all proposals in the configuredproposals_paththat haven't been applied yet - For each applied proposal:
a. Edit the target SKILL.md with the proposed change
b. Add a CHANGELOG entry with
[EVOLUTION]tag c. Move the proposal file to<proposals_path>/.applied/with a date prefix d. Mark the sourceskill_patternentry asstatus: archivedin_insights.yaml
Output:
Applied: <proposals_path>/260404-transcript-name-disambiguation.md
-> skills/transcript/SKILL.md updated (Step 1: added pre-check)
-> CHANGELOG.md updated
-> Proposal archived to <proposals_path>/.applied/
1 proposal applied. Review changes with: git diff
help -- Usage guide
Trigger: /insights help
Output:
/insights -- Knowledge Extraction & Skill Evolution
=====================================================
Backfill _insights.yaml, compile execution feedback, and evolve skills.
Usage:
/insights reprocess =bob-smith Extract from one folder
/insights reprocess all Extract from all folders with CHANGELOG.md
/insights reprocess since 260201 Extract from files dated after 260201
/insights scan-claude-md Extract from CLAUDE.md files
/insights compile Compile execution feedback into patterns
/insights compile since 260301 Compile only recent feedback
/insights normalize [path] [--apply] Migrate drifted files to current schema (dry-run default)
/insights synthesize [topic|all] Render insight clusters into wiki articles + INDEX (CR-027)
/insights propose Generate SKILL.md improvement proposals
/insights propose apply [file|all] Apply a proposal to SKILL.md
/insights status Show insights + evolution statistics
/insights help This guide
Knowledge extraction (content):
/transcript Step 3.5 Extracts insights from NEW transcripts (forward)
/ops Step 5.5 Extracts insights from NEW meeting docs (forward)
/insights reprocess Extracts insights from EXISTING transcripts (backfill)
/insights scan-claude-md Extracts from CLAUDE.md files
Skill evolution (execution feedback):
/ops Step 9 Captures edge cases and corrections (silent)
/transcript Step 4.5 Captures edge cases and corrections (silent)
/insights compile Finds patterns in execution feedback
/insights propose Generates SKILL.md improvements from patterns
Data flow:
/transcript or /ops ─┐
├── _insights.yaml ──> visualisation app
/insights ───────────┘ │
├── execution feedback (edge_case, correction)
│ │
│ /insights compile -> skill_pattern entries
│ │
│ /insights propose -> SKILL.md improvements
│ │
└── skills get smarter over time
Config: workflows.knowledge_extraction.evolution in base.yaml
auto_apply: false (default) -- proposals require manual review
auto_apply: true -- proposals applied automatically
Extraction Reference (Quick Copy)
This is a convenience copy. The authoritative definition is in /transcript Step 3.5 (~/.claude/skills/transcript/SKILL.md).
| Type | Captures | Written by |
|---|---|---|
decision |
Choice + rationale | /transcript, /ops, /insights reprocess |
preference |
Working style | /transcript, /ops, /insights reprocess |
learning |
What worked/didn't | /transcript, /ops, /insights reprocess |
opportunity |
Ideas not yet actioned | /transcript, /ops, /insights reprocess |
pattern |
Recurring themes | /transcript, /ops, /insights reprocess |
quote |
Memorable verbatim quote (exempt from promotion -- never becomes a rule) | /transcript, /ops, /insights reprocess |
metric |
A measurement where the number is the claim (exempt from promotion -- CR-046) | /transcript, /ops, /insights reprocess |
edge_case |
Skill hit ambiguous input | /transcript Step 4.5, /ops Step 9 |
correction |
User corrected skill output | /transcript Step 4.5, /ops Step 9 |
skill_pattern |
Compiled execution pattern | /insights compile |
metric vs learning (CR-046): remove the number from the summary. Nothing left -> metric. Claim survives -> learning citing evidence.
Threshold: Only non-obvious, durable, specific insights. If fewer than min_insights (default: 1) qualify, skip the file silently.
Format: See /transcript Step 3.5 for the complete _insights.yaml schema.
Reusability and language rules for _insights.yaml
Reusability (CR-020 -- replaces the former privacy rule)
Names are allowed in insight entries. The old rule ("never include personal or company names in summary, rationale, or tags") was retired in the 2026-04-07 audit and formally removed by CR-020 -- the vault is private, and quote entries need attribution by construction. What remains is a reusability preference: when an insight generalizes beyond the person who sparked it, prefer name-free phrasing in summary and tags so the entry reads well in cross-folder views -- context and source.file already carry the who/what. Names in rationale are always fine. See /transcript Step 3.5 for examples.
Contact Classification (CR-009)
Insights are extracted from all contacts regardless of their classification (family, personal, professional, confidential) — knowledge is valuable in all contexts. The core-skills-visualisation app is responsible for respecting classification when rendering.
Vocabulary guard (CR-020)
Before writing any entry, apply the write-time vocabulary guard defined in /transcript Step 3.5: canonical type values only, confidence limited to hypothesis | rule, YYMMDD dates, integer ids with next_id maintained, max 5 tags. This applies to every subcommand in this skill that writes entries.
Swedish Character Enforcement (CR-007: pre-write validator)
When processing Swedish-language content, ALL Swedish words MUST use correct å, ä, ö characters. Never substitute with a or o. This applies equally to _insights.yaml YAML fields as to markdown files -- YAML content is just as prone to missing characters.
Pre-write validator (CR-007, mandatory):
Before writing any entry to _insights.yaml where the summary, rationale, or context field is in Swedish (detected by presence of any å/ä/ö character anywhere in the file, OR by folder language per language_inheritance in base.yaml):
- Load
~/.claude/skills/ops-config/swedish_substitutions.yaml - Scan each Swedish text field token-by-token using word-boundary matching
- For each match against the substitution map (excluding
category: skip):- Non-ambiguous matches: refuse to write, report the violation, ask the user to confirm or fix
- Ambiguous matches: warn but proceed (log to execution feedback as
edge_case)
- If no violations, proceed with the write
This is the structural validation that the MEMORY.md reminder cannot provide -- the model may write a tempting "...byggs fran Meta..." line, but the validator catches it before the file lands on disk.
To remediate existing files written before this validator was added, run /ops normalize <path>.
Common mistakes to avoid (full list in swedish_substitutions.yaml):
- "pagaende" -> "pågående", "foretag" -> "företag", "fran" -> "från"
- "fore" -> "före", "nasta" -> "nästa", "behovs" -> "behövs", "kravs" -> "krävs"
- "anvandning" -> "användning", "mote" -> "möte", "losning" -> "lösning"
- "manader" -> "månader", "forberedelse" -> "förberedelse", "karnteam" -> "kärnteam"
- "prissattning" -> "prissättning", "overgang" -> "övergång", "forandring" -> "förändring"