diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 1f97482..4b8996c 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,7 +9,7 @@ "name": "second-brain", "source": "./", "description": "Self-evolving AI second brain. Auto-learns from sessions, discovers tools, maintains a local knowledge base, and self-critiques code quality.", - "version": "0.23.1" + "version": "0.24.0" } ] } diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 3e168ec..dc2f949 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "second-brain", "description": "Self-evolving AI second brain. Automatically learns from sessions, discovers tools, maintains a local knowledge base, and self-critiques code quality — getting smarter with every interaction.", - "version": "0.23.1", + "version": "0.24.0", "author": { "name": "second-brain" }, diff --git a/docs/plans/2026-06-02-ai-native-representation-phase1.md b/docs/plans/2026-06-02-ai-native-representation-phase1.md new file mode 100644 index 0000000..d04bf5a --- /dev/null +++ b/docs/plans/2026-06-02-ai-native-representation-phase1.md @@ -0,0 +1,528 @@ +# AI-Native Representation — Phase 1 Implementation Plan + +> **For agentic workers:** Implement task-by-task following TDD. Steps use checkbox (`- [ ]`) syntax. See `second-brain:test-driven-development` and `second-brain:verification-before-completion`. + +**Goal:** Make the per-page `` structured block a *recognized, parsed, schema-validated, and safe* construct across the KB pipeline — the deterministic foundation for the AI-native representation (spec `docs/specs/2026-06-02-ai-native-knowledge-representation-design.md`). + +**Architecture:** A new pure `ai-block.ts` module owns the marker, the flat-YAML parse, the per-type schemas, and `stripAiBlock`. `parseDoc` exposes `aiBlock`; `knowledge_validate` schema-checks it (gentle warnings); and every length/first-sentence consumer (`firstSentence`, FORGET `wc -c`, the search stub-penalty) strips the block first so it can't skew signals. No authoring, no consumption changes yet — those are Phase 1b/2/3. + +**Tech Stack:** TypeScript (mcp/src/tools, vitest), bash (scripts + tests/test-*.sh), esbuild bundles. + +**Out of scope (later phases):** extractor authoring of blocks at capture (Phase 1b: `extract-prompt.txt` + `merge-project-update.sh`); search-weight/return + session-load injection + `knowledge_fetch` tier (Phase 2); dream/maintainer refresh + lint staleness + one-shot backfill (Phase 3). + +**Hard constraints (from spec §5b state-check):** block values are plain slugs (never `[[links]]`); the block is excluded from FORGET `wc -c` and the `<100`-char stub penalty; `firstSentence` strips it; graph-project must not clobber it. + +--- + +### Task 1: Pure `ai-block` module — marker, parse, schemas, validate, strip + +**Files:** +- Create: `mcp/src/tools/ai-block.ts` +- Test: `mcp/src/tools/ai-block.test.ts` + +- [ ] **Step 1: Write the failing test** + +```typescript +import { describe, it, expect } from 'vitest'; +import { parseAiBlock, stripAiBlock, validateAiBlock, AI_BLOCK_SCHEMAS } from './ai-block.js'; + +const page = [ + '---', 'title: awk', 'type: learnings', '---', + '', + 'claim: never interpolate shell vars into awk', + 'trigger: writing awk in a .sh', + 'action: pass via -v + numeric coercion', + 'scope: mawk (Pi default)', + '', '', '## Notes', 'mawk errors on empty interpolation. Period.', +].join('\n'); + +describe('ai-block', () => { + it('parses the flat key:value block into an object', () => { + const b = parseAiBlock(page)!; + expect(b.claim).toBe('never interpolate shell vars into awk'); + expect(b.action).toBe('pass via -v + numeric coercion'); + }); + it('returns null when there is no block', () => { + expect(parseAiBlock('---\ntitle: x\n---\n# x\nno block here')).toBeNull(); + }); + it('strips the block (for length/first-sentence counts)', () => { + const s = stripAiBlock(page); + expect(s).not.toContain('ai:begin'); + expect(s).not.toContain('claim:'); + expect(s).toContain('## Notes'); + }); + it('validateAiBlock reports missing REQUIRED fields for the type', () => { + expect(validateAiBlock('learnings', { claim: 'x' })).toEqual(['action']); // action required, missing + expect(validateAiBlock('learnings', { claim: 'x', action: 'y' })).toEqual([]); + expect(validateAiBlock('unknown-type', { foo: 'bar' })).toEqual([]); // unknown type → no schema → no warnings + }); + it('has schemas for the six structured types', () => { + for (const t of ['learnings', 'decisions', 'entities', 'issues', 'concepts', 'security']) + expect(AI_BLOCK_SCHEMAS[t].required.length).toBeGreaterThan(0); + }); + it('folds a continuation line into the previous field value', () => { + const md = ['', 'claim: line one', ' continued', 'action: do it', ''].join('\n'); + expect(parseAiBlock(md)!.claim).toBe('line one continued'); + }); +}); +``` + +- [ ] **Step 2: Run test to verify it fails** + +Run: `cd mcp && npx vitest run src/tools/ai-block.test.ts` +Expected: FAIL — cannot find module `./ai-block.js`. + +- [ ] **Step 3: Write minimal implementation** + +```typescript +// mcp/src/tools/ai-block.ts +export const AI_BLOCK_RE = /\n?([\s\S]*?)/; + +export interface AiBlockSchema { fields: string[]; required: string[]; } + +// Per-type schemas (spec §4). `required` = the load-bearing fields a good page of that +// type should carry; missing ones are WARNINGS (gentle), never errors. +export const AI_BLOCK_SCHEMAS: Record = { + learnings: { fields: ['claim', 'trigger', 'action', 'scope', 'evidence', 'supersedes'], required: ['claim', 'action'] }, + decisions: { fields: ['context', 'choice', 'alternatives', 'rationale', 'status', 'supersedes'], required: ['choice'] }, + entities: { fields: ['identity', 'current_state', 'depends_on', 'owns', 'status'], required: ['identity'] }, + issues: { fields: ['symptom', 'cause', 'fix', 'severity', 'status'], required: ['symptom', 'status'] }, + concepts: { fields: ['problem', 'solution', 'where_applied', 'tradeoffs'], required: ['problem', 'solution'] }, + security: { fields: ['threat', 'mitigation', 'scope', 'status'], required: ['threat', 'mitigation'] }, +}; + +/** Parse the flat-YAML `key: value` body of the ai:begin…ai:end region into an object. + * A line not matching `key:` is folded (appended) into the previous field's value. + * Returns null when the page has no block. */ +export function parseAiBlock(content: string): Record | null { + const m = content.match(AI_BLOCK_RE); + if (!m) return null; + const out: Record = {}; + let last = ''; + for (const raw of m[1].split('\n')) { + const line = raw.trimEnd(); + if (!line.trim()) continue; + const kv = line.match(/^([a-z_][a-z0-9_]*):\s*(.*)$/i); + if (kv) { last = kv[1]; out[last] = kv[2].trim(); } + else if (last) { out[last] = (out[last] + ' ' + line.trim()).trim(); } + } + return out; +} + +/** Remove the ai:begin…ai:end region so length/first-sentence consumers ignore it. */ +export function stripAiBlock(text: string): string { + return text.replace(AI_BLOCK_RE, ''); +} + +/** Missing REQUIRED fields for the page type (empty when type unknown or all present). */ +export function validateAiBlock(type: string, block: Record): string[] { + const schema = AI_BLOCK_SCHEMAS[type]; + if (!schema) return []; + return schema.required.filter(f => !block[f] || !block[f].trim()); +} +``` + +- [ ] **Step 4: Run test to verify it passes** + +Run: `cd mcp && npx vitest run src/tools/ai-block.test.ts` +Expected: PASS (6 cases). + +- [ ] **Step 5: Commit** + +```bash +git add mcp/src/tools/ai-block.ts mcp/src/tools/ai-block.test.ts +git commit -m "feat(ai-block): pure parse + per-type schemas + validate + strip" +``` + +--- + +### Task 2: `parseDoc` exposes `aiBlock`; body-link fallback ignores the block + +**Files:** +- Modify: `mcp/src/tools/knowledge-search.ts` (`ParsedDoc` interface ~line 11-23; `parseDoc` ~line 305-347) +- Test: `mcp/src/tools/knowledge-search.test.ts` + +- [ ] **Step 1: Write the failing test** + +```typescript +// add to knowledge-search.test.ts (parseDoc already imported) +describe('parseDoc ai-block', () => { + it('exposes the parsed ai-block as doc.aiBlock', () => { + const md = ['---', 'title: A', 'type: learnings', '---', + '', 'claim: c', 'action: a', '', '', '# A', 'body'].join('\n'); + const doc = parseDoc(md, '/w/learnings/a.md'); + expect(doc.aiBlock?.claim).toBe('c'); + }); + it('does NOT scrape a [[link]] that sits inside the ai-block into related:', () => { + // (block values should be plain slugs, but guard anyway: stripped before the body-link fallback) + const md = ['---', 'title: B', 'type: learnings', '---', + '', 'supersedes: [[ghost]]', 'claim: c', 'action: a', '', '', '# B', 'see [[real-page]]'].join('\n'); + const doc = parseDoc(md, '/w/learnings/b.md'); + expect(doc.related).toContain('real-page'); + expect(doc.related).not.toContain('ghost'); + }); +}); +``` + +- [ ] **Step 2: Run test to verify it fails** + +Run: `cd mcp && npx vitest run src/tools/knowledge-search.test.ts -t ai-block` +Expected: FAIL — `doc.aiBlock` undefined; `ghost` present in related. + +- [ ] **Step 3: Write minimal implementation** + +In `knowledge-search.ts`: import at top — `import { parseAiBlock, stripAiBlock } from './ai-block.js';` +Add to `ParsedDoc` interface: `aiBlock?: Record;` +In `parseDoc`, after the frontmatter block is parsed and `doc.body` is set, add: +```typescript + doc.aiBlock = parseAiBlock(content) ?? undefined; +``` +And the body `[[link]]` fallback (the `if (!doc.related.length)` / wiki-link scrape, ~line 340-344) must run on a block-stripped body. Change the scrape source to `stripAiBlock(doc.body)`: +```typescript + // existing fallback, but ignore links that live inside the ai-block: + const bodyForLinks = stripAiBlock(doc.body); + // ...use bodyForLinks in the [[...]] matchAll instead of doc.body... +``` + +- [ ] **Step 4: Run test to verify it passes** + +Run: `cd mcp && npx vitest run src/tools/knowledge-search.test.ts` +Expected: PASS (all, incl. the two new). + +- [ ] **Step 5: Commit** + +```bash +git add mcp/src/tools/knowledge-search.ts mcp/src/tools/knowledge-search.test.ts +git commit -m "feat(ai-block): parseDoc exposes aiBlock; body-link fallback strips the block" +``` + +--- + +### Task 3: Search stub-penalty measures prose only (block excluded) + +**Files:** +- Modify: `mcp/src/tools/knowledge-search.ts` (stub penalty ~line 213-215: `body.length < 100`) +- Test: `mcp/src/tools/knowledge-search.test.ts` + +- [ ] **Step 1: Write the failing test** + +```typescript +import { knowledgeSearch } from './knowledge-search.js'; // already imported +it('a short page with a big ai-block is still penalized as a stub (prose-only length)', async () => { + const dir = await fsp.mkdtemp(join(tmpdir(), 'ks-stub-')); + await fsp.mkdir(join(dir, 'wiki', 'learnings'), { recursive: true }); + const bigBlock = ['', 'claim: wireguard tunnel handshake', 'action: x', 'scope: y', 'evidence: z z z z z', ''].join('\n'); + // prose body is ~5 chars; only the block is long + await fsp.writeFile(join(dir, 'wiki', 'learnings', 'stub.md'), `---\ntitle: stub\ntype: learnings\n---\n${bigBlock}\n\nhi.`); + await fsp.writeFile(join(dir, 'wiki', 'learnings', 'full.md'), `---\ntitle: full\ntype: learnings\n---\n# full\n` + 'wireguard tunnel handshake details. '.repeat(20)); + const r = await knowledgeSearch({ query: 'wireguard tunnel handshake', knowledgeDir: dir }); + const stub = r.results.find((x: any) => x.slug === 'stub'); + const full = r.results.find((x: any) => x.slug === 'full'); + expect(stub && full && full.score > stub.score).toBe(true); // stub penalized despite the long block +}); +``` + +(Adjust the result-shape accessor — `r.results`/`.slug`/`.score` — to match `knowledgeSearch`'s actual return; confirm by reading the function before writing.) + +- [ ] **Step 2: Run test to verify it fails** + +Run: `cd mcp && npx vitest run src/tools/knowledge-search.test.ts -t stub` +Expected: FAIL — the block's length lifts `stub` over the `<100` penalty, so it is not penalized. + +- [ ] **Step 3: Write minimal implementation** + +In the stub-penalty check (~line 213-215), measure block-stripped prose length: +```typescript + const proseLen = stripAiBlock(doc.body).trim().length; + const isStub = /', 'problem: BLOCKWORD should not surface', 'solution: x', '', '', 'Real prose sentence here.'].join('\n'); + await fsp.writeFile(join(kd, 'wiki', 'concepts', 'p.md'), `---\ntitle: P\ntype: concepts\n---\n${body}`); + await knowledgeReindex(kd); + const idx = await fsp.readFile(join(kd, 'wiki', 'index.md'), 'utf-8'); + expect(idx).not.toContain('BLOCKWORD'); +}); +``` + +- [ ] **Step 2: Run test to verify it fails** + +Run: `cd mcp && npx vitest run src/tools/knowledge-reindex.test.ts -t ai-block` +Expected: FAIL — `firstSentence` grabs the block text (`problem: BLOCKWORD…`) as the description. + +- [ ] **Step 3: Write minimal implementation** + +In `knowledge-reindex.ts`, import `stripAiBlock` and add it to the `firstSentence` strip chain (it already strips `graph:begin`): +```typescript +import { stripAiBlock } from './ai-block.js'; +// in firstSentence(body): + const text = stripAiBlock(body) + .replace(//g, '') + .replace(/^#.*\n/m, '') + .trim(); +``` + +- [ ] **Step 4: Run test to verify it passes** + +Run: `cd mcp && npx vitest run src/tools/knowledge-reindex.test.ts` +Expected: PASS (all reindex cases). + +- [ ] **Step 5: Commit** + +```bash +git add mcp/src/tools/knowledge-reindex.ts mcp/src/tools/knowledge-reindex.test.ts +git commit -m "fix(ai-block): firstSentence strips the ai-block before extracting description" +``` + +--- + +### Task 5: `knowledge_validate` schema-checks the block (gentle warning) + +**Files:** +- Modify: `mcp/src/tools/knowledge-validate.ts` (issue type union ~line 6; the per-page loop ~line 31-95) +- Test: `mcp/src/tools/knowledge-validate.test.ts` + +- [ ] **Step 1: Write the failing test** + +```typescript +// knowledge-validate.test.ts (knowledgeValidate imported) +it('warns (not errors) when an ai-block is missing a required field for its type', async () => { + const dir = await fs.mkdtemp(join(tmpdir(), 'kv-ai-')); + const wiki = join(dir, 'wiki'); + await fs.mkdir(join(wiki, 'learnings'), { recursive: true }); + // learnings requires claim + action; this block omits action + await fs.writeFile(join(wiki, 'learnings', 'l.md'), + '---\ntitle: L\ntype: learnings\n---\n\nclaim: c\n\n# L\n'); + const res = await knowledgeValidate(dir, { autofix: false }); + const w = res.issues.find(i => i.type === 'ai_block_incomplete' && /action/.test(i.message)); + expect(w).toBeDefined(); + expect(w!.severity).toBe('warning'); +}); +it('does not warn when the page has no ai-block (additive/optional during migration)', async () => { + const dir = await fs.mkdtemp(join(tmpdir(), 'kv-noai-')); + const wiki = join(dir, 'wiki'); + await fs.mkdir(join(wiki, 'learnings'), { recursive: true }); + await fs.writeFile(join(wiki, 'learnings', 'l.md'), '---\ntitle: L\ntype: learnings\n---\n# L\nprose\n'); + const res = await knowledgeValidate(dir, { autofix: false }); + expect(res.issues.find(i => i.type === 'ai_block_incomplete')).toBeUndefined(); +}); +``` + +- [ ] **Step 2: Run test to verify it fails** + +Run: `cd mcp && npx vitest run src/tools/knowledge-validate.test.ts -t ai-block` +Expected: FAIL — no `ai_block_incomplete` issue type exists. + +- [ ] **Step 3: Write minimal implementation** + +In `knowledge-validate.ts`: add `'ai_block_incomplete'` to the `type:` union (~line 6). Import `parseAiBlock, validateAiBlock` from `./ai-block.js`. In the per-page loop (where `parseDoc(content)` already runs), after computing the page's type (`doc.type` or the folder), add: +```typescript + const block = parseAiBlock(content); + if (block) { + const missing = validateAiBlock(doc.type || basename(dirname(filePath)), block); + if (missing.length) issues.push({ + type: 'ai_block_incomplete', severity: 'warning', path: filePath, + message: `ai-block missing required field(s) for type ${doc.type}: ${missing.join(', ')}`, + }); + } +``` +(Only when a block exists — absent block is fine, additive.) + +- [ ] **Step 4: Run test to verify it passes** + +Run: `cd mcp && npx vitest run src/tools/knowledge-validate.test.ts` +Expected: PASS (all). + +- [ ] **Step 5: Commit** + +```bash +git add mcp/src/tools/knowledge-validate.ts mcp/src/tools/knowledge-validate.test.ts +git commit -m "feat(ai-block): knowledge_validate warns on incomplete ai-block (gentle)" +``` + +--- + +### Task 6: FORGET byte-count excludes the ai-block + +**Files:** +- Modify: `scripts/wiki-forget-score.sh` (body byte count ~line 25) +- Test: `tests/test-wiki-forget-ai-block.sh` (new) + +- [ ] **Step 1: Write the failing test** + +```bash +#!/bin/bash +# A page whose only "length" is a big ai-block must still count as a near-stub for the +# category-floor gate — the block must be excluded from the wc -c body measure (spec §5b). +set -u +ROOT="$(cd "$(dirname "$0")"/.. && pwd)"; SCORER="$ROOT/scripts/wiki-forget-score.sh" +TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT +fail(){ echo "FAIL: $1"; exit 1; }; pass(){ echo "PASS: $1"; } +command -v jq >/dev/null 2>&1 || fail "jq required" +export KNOWLEDGE_DIR="$TMP/knowledge"; export BRAIN_DIR="$TMP/.second-brain" +mkdir -p "$KNOWLEDGE_DIR/wiki/entities" "$BRAIN_DIR" +# entities is a 0.5-category; a tiny-prose page padded ONLY by a long ai-block: +{ echo '---'; echo 'title: E'; echo 'type: entities'; echo '---' + echo ''; echo 'identity: some long identity line padding padding padding padding' + echo 'current_state: more padding padding padding padding padding padding padding'; echo '' + echo '# E'; echo 'hi'; } > "$KNOWLEDGE_DIR/wiki/entities/e.md" +OUT=$(bash "$SCORER" 2>/dev/null) || fail "scorer failed" +# row: scoreslugpathreasonsprotflag ; reasons must show the stub-floor body<200 hit +echo "$OUT" | awk -F'\t' '$2=="e"{print $4}' | grep -qi 'stub\|body<200\|cat=0.2\|s_cat' || true +# The robust assertion: prose is <200 bytes, so the category floor (0.2) must apply → +# the page must NOT score as a full 0.5 entity. Compare against a real long-prose entity. +{ echo '---'; echo 'title: F'; echo 'type: entities'; echo '---'; echo '# F' + for i in $(seq 1 30); do echo "real prose line $i with enough content to exceed two hundred bytes easily"; done; } > "$KNOWLEDGE_DIR/wiki/entities/f.md" +OUT=$(bash "$SCORER" 2>/dev/null) +se=$(echo "$OUT" | awk -F'\t' '$2=="e"{print $1}'); sf=$(echo "$OUT" | awk -F'\t' '$2=="f"{print $1}') +awk -v a="$se" -v b="$sf" 'BEGIN{exit !(a+0 < b+0)}' || fail "block-padded stub (e=$se) scored >= real-prose entity (f=$sf) — block not excluded from body count" +pass "ai-block excluded from FORGET body byte-count (block-padded page still hits the stub floor)" +echo; echo "ALL PASS" +``` + +- [ ] **Step 2: Run test to verify it fails** + +Run: `bash tests/test-wiki-forget-ai-block.sh` +Expected: FAIL — `wc -c` includes the block, so `e` exceeds 200 bytes, skips the stub floor, and scores ≥ `f`. + +- [ ] **Step 3: Write minimal implementation** + +In `wiki-forget-score.sh`, where it computes `body=$(wc -c < "$f")` (~line 25), strip the ai-block (and other generated marked regions) first so the count is prose-only. Use awk to drop `ai:begin…ai:end` (mawk-safe — fence-style state toggle, no shell interpolation): +```bash + body=$(awk ' + //) skip=0; next } + { print } + ' "$f" | wc -c) +``` + +- [ ] **Step 4: Run test to verify it passes** + +Run: `bash tests/test-wiki-forget-ai-block.sh` then `bash tests/test-wiki-forget-score.sh` (existing, must stay green) +Expected: both PASS. + +- [ ] **Step 5: Commit** + +```bash +git add scripts/wiki-forget-score.sh tests/test-wiki-forget-ai-block.sh +git commit -m "fix(ai-block): FORGET body byte-count excludes the ai-block (prose-only)" +``` + +--- + +### Task 7: graph-project never clobbers the ai-block (safety regression) + +**Files:** +- Test: `mcp/src/tools/knowledge-reindex.test.ts` (graph-project runs inside reindex) + +- [ ] **Step 1: Write the failing-or-passing test (regression guard)** + +```typescript +it('reindex/graph-projection preserves the ai-block byte-for-byte', async () => { + const kd = await fsp.mkdtemp(join(tmpdir(), 'ri-keep-')); + await fsp.mkdir(join(kd, 'wiki', 'decisions'), { recursive: true }); + const block = ['', 'choice: use X', 'status: active', ''].join('\n'); + await fsp.writeFile(join(kd, 'wiki', 'decisions', 'd.md'), `---\ntitle: D\ntype: decisions\nrelated: []\n---\n${block}\n\n# D\nbody [[other]]`); + await fsp.mkdir(join(kd, 'wiki', 'decisions'), { recursive: true }); + await fsp.writeFile(join(kd, 'wiki', 'decisions', 'other.md'), `---\ntitle: O\ntype: decisions\n---\n# O\n`); + await appendEdge(join(kd, 'graph', 'edges.jsonl'), + { op: 'assert', from: 'd', to: 'other', type: 'requires', valid_from: '2026-05-01', recorded_at: '2026-05-01T00:00:00Z' }); + await knowledgeReindex(kd); // projects related: + ## Dependencies onto d.md + const after = await fsp.readFile(join(kd, 'wiki', 'decisions', 'd.md'), 'utf-8'); + expect(after).toContain(block); // the ai-block region survives projection intact +}); +``` + +- [ ] **Step 2: Run test to verify it (likely passes — graph-project only touches its own region + frontmatter)** + +Run: `cd mcp && npx vitest run src/tools/knowledge-reindex.test.ts -t preserves` +Expected: PASS (graph-project rewrites only `related:` frontmatter + the `graph:begin` region, both distinct from `ai:begin`). If it FAILS, graph-project is corrupting the block → fix `graph-project.ts` to skip/preserve the `ai:begin` region; do not weaken the test. + +- [ ] **Step 3: (only if Step 2 failed) preserve the block in graph-project.ts** + +If failing: in `graph-project.ts`, capture the `ai:begin…ai:end` region before rewriting and restore it after, or scope the rewrite regexes to avoid it. (No code if Step 2 passed.) + +- [ ] **Step 4: Re-run to confirm green** + +Run: `cd mcp && npx vitest run src/tools/knowledge-reindex.test.ts` +Expected: PASS. + +- [ ] **Step 5: Commit** + +```bash +git add mcp/src/tools/knowledge-reindex.test.ts mcp/src/tools/graph-project.ts +git commit -m "test(ai-block): guard that reindex/projection preserves the ai-block" +``` + +--- + +### Task 8: Build, full gate, version + migration row + +**Files:** +- Modify: `mcp/src/server.ts` (knowledge-base version), `.claude-plugin/plugin.json` + `marketplace.json`, `skills/upgrade/SKILL.md` + +- [ ] **Step 1: Rebuild bundles** (new `ai-block.ts` must be inlined into the dependent bundles) + +Run: `cd mcp && npm run build` +Expected: tsc clean; bundles rebuilt. + +- [ ] **Step 2: Full suite** + +Run: `bash tests/run-all.sh` +Expected: ALL GREEN (new vitest + `test-wiki-forget-ai-block.sh` auto-discovered; existing `test-wiki-forget-score.sh` + knowledge-eval not regressed). + +- [ ] **Step 3: Version + migration row** + +Bump `plugin.json` + `marketplace.json` to `0.24.0`; bump `mcp/src/server.ts` knowledge-base to `2.5.0`; add a `0.24.0` row to `skills/upgrade/SKILL.md` describing: AI-native representation **Phase 1** (the `ai:begin` block is parsed/schema-validated/strip-safe across parseDoc, validate, reindex firstSentence, FORGET byte-count, search stub-penalty); additive/back-compat (no block ⇒ unchanged); authoring (extractor) + consumption (search/session-load) are Phases 1b/2. + +- [ ] **Step 4: Validate + migration-row gate** + +Run: `bash scripts/validate-plugin.sh && bash tests/test-upgrade-migration-row.sh` +Expected: both PASS. + +- [ ] **Step 5: Commit** + +```bash +git add -A +git commit -m "chore(release): AI-native representation Phase 1 — 0.24.0 + MCP 2.5.0" +``` + +--- + +## Release gate (after all tasks) + +Run `/second-brain:code-review-deep` on the branch (the deep-review release gate), address findings, then PR. Do not merge until green + reviewed. + +## Self-review checklist (run before implementing) + +- **Spec coverage (Phase 1):** ai-block parse/schema/validate/strip (T1) ✓ · parseDoc.aiBlock + plain-slug guard (T2) ✓ · stub-penalty prose-only (T3) ✓ · firstSentence strip (T4) ✓ · validate gentle warning (T5) ✓ · FORGET byte-count exclude (T6) ✓ · graph-project safety (T7) ✓ · version/row (T8). Authoring (extractor) + consumption (search/session-load/knowledge_fetch) are **explicitly Phase 1b/2** (not gaps). +- **Type consistency:** `parseAiBlock(content)→Record|null`, `stripAiBlock(text)→string`, `validateAiBlock(type, block)→string[]`, `AI_BLOCK_SCHEMAS[type].{fields,required}` — used identically across T1–T7; `ParsedDoc.aiBlock?: Record` (T2) feeds T5. +- **No placeholders:** every code step shows real code. T3's result-shape accessor (`r.results/.slug/.score`) is flagged to confirm against `knowledgeSearch`'s actual return before writing the test. diff --git a/docs/specs/2026-06-02-ai-native-knowledge-representation-design.md b/docs/specs/2026-06-02-ai-native-knowledge-representation-design.md new file mode 100644 index 0000000..f6fcb61 --- /dev/null +++ b/docs/specs/2026-06-02-ai-native-knowledge-representation-design.md @@ -0,0 +1,135 @@ +# AI-Native Knowledge Representation — Design + +- **Status:** Draft (brainstormed 2026-06-02; web-researched; direction approved — "structured block + prose"; pending spec review). A **future track**, orthogonal to the just-shipped hierarchy (0.23.x) — the hierarchy is *where* a page lives; this is *how a page is written for an AI reader*. +- **Target release:** plugin 0.24.0 candidate (additive, flag-gated, back-compat). +- **Lineage:** extends `kb-main-groups-heterogeneous` (groups may differ — now: their *block schemas* differ) and the KB-org spec `2026-06-02-knowledge-base-hierarchical-organization-design`. + +--- + +## 1. Problem / reframe + +The KB (wiki pages, learnings, decisions, …) is **AI-to-AI**: written by AI (extractor, dream, maintainer) and read by AI (session-load injection, `knowledge_search` results fed to Claude). The human almost never reads it directly. Yet it is shaped as **human-PKM prose markdown**. + +The cost: **prose forces every AI reader to re-derive structure** — extract the claim, the trigger, the action, the evidence, the relations — on *every* read, with "no shared intermediate" ([Knows: Agent-Native Structured Representations](https://arxiv.org/html/2604.17309v1)). That is repeated tokens + reasoning each retrieval, and it's lossy (different readers extract differently). + +## 2. Research basis (don't overcorrect) + +- **Keep markdown.** It is the validated AI substrate — Karpathy's LLM-wiki pattern (raw → LLM-generated wiki → schema), which second-brain already mirrors, and the [llms.txt](https://buildwithfern.com/post/how-to-write-llm-friendly-documentation) movement (heading hierarchy > HTML; far fewer tokens). Don't go full-JSON. +- **Multi-granularity, not atomic-only.** SOTA agent memory ([TriMem](https://www.emergentmind.com/topics/memory-mechanisms-in-llm-based-agents)) keeps three coexisting layers — raw segments (fidelity) + atomic facts (retrieval) + synthesized profiles (reasoning). ["Beyond Atomic Facts"](https://arxiv.org/abs/2605.19952) warns atomic-only loses context. +- **Provenance + confidence + typed records are first-class** for AI weighting and against memory-poisoning ([mem0 2026](https://mem0.ai/blog/state-of-ai-agent-memory-2026), [typed-memory provenance](https://arxiv.org/html/2605.25869)). + +**What we already have:** the *synthesized profile* (prose pages) + the *relations* (bi-temporal edge graph) + *raw* (episodic transcripts). **What's missing:** the **atomic, schema'd shared-intermediate** layer + first-class provenance/confidence/applicability on pages. + +## 3. Goals / Non-goals + +**Goals** +- Add a per-page **machine-first structured block** (the shared intermediate) an AI reads *directly* without re-parsing prose. +- Make **provenance, confidence, scope/applicability** first-class so retrieval can *weight* what it surfaces. +- Keep the markdown substrate, the prose (nuance), and everything that works on it (BM25, embeddings, Obsidian, the projection/validation machinery). +- Multi-granularity: raw (episodic) + **atomic (new block)** + synthesized (prose) + relations (edges) coexist. + +**Non-goals** +- No full-JSON rewrite / dropping prose (overshoots; "Beyond Atomic Facts"). +- No new store for the block (it lives IN the page — not a sidecar to sync). +- No change to the hierarchy/MOC layer (orthogonal). + +## 4. The AI block + +A **marked body region** per page — consistent with the codebase's existing generated/marked regions (`graph:begin`, `theme:begin`, `moc:begin`), so the same author-only-the-region + validate machinery applies: + +``` + +claim: +trigger: +action: +scope: +evidence: +supersedes: + +``` + +- **Authored, not projected.** Unlike `related:`/`## Dependencies` (projected from edges), the block is *authored* by whatever writes the page (the prose is its source). It is written ONCE by the producing AI and read MANY times by consuming AIs without re-derivation. +- **Per-type schema** (the missing formalization of the maintainer's existing ENRICH category guidance): + +| type | block fields | +|---|---| +| `learnings` | claim, trigger, action, scope, evidence, supersedes | +| `decisions` | context, choice, alternatives, rationale, status, supersedes | +| `entities` | identity, current_state, depends_on, owns, status | +| `issues` | symptom, cause, fix, severity, status | +| `concepts` | problem, solution, where_applied, tradeoffs | +| `security` | threat, mitigation, scope, status | + +- **Frontmatter gains** `confidence:` and `provenance:` — the weighting signals. **Confidence is HYBRID (RESOLVED — SOTA):** the producing AI's **verbalized** confidence (high/med/low) is the *primary* signal — a March 2026 study found verbalized confidence is the best-*calibrated* (ECE 0.166 vs 0.229 for self-consistency, at 1/5th the cost) — **corroborated** by an evidence/recurrence count (how many sessions/sources assert the claim, tracked in `evidence:`) and recency (`created`/`updated`). Not pure-corroboration (2026 research shows it's worse-calibrated alone). Refs: [LLM grader calibration](https://arxiv.org/abs/2603.29559), [verbal+consistency hybrid](https://openreview.net/forum?id=66D3rZrNjV). +- **Field values are PLAIN SLUGS, never `[[wikilinks]]`** (e.g. `supersedes: other-slug`, not `supersedes: [[other-slug]]`). Constraint from the state-check: the FORGET connectivity signal and `parseDoc`'s body-`[[link]]` → `related:` fallback both scrape `[[..]]`; a bracketed value in the block would silently pollute connectivity + the projected `related:`. Relations belong in the edge graph, not the block. +- **Format (RESOLVED — SOTA):** **flat YAML `key: value`** (multi-line via folded `>`), inside the marked region. YAML is the model-preferred structured format (GPT-5/Gemini benchmarks) and ~16% more token-efficient than JSON with better nested-data comprehension; it stays plain-text so BM25/embeddings/Obsidian keep working, and **flat** YAML is parseable by a tiny line parser with **no new dependency** (offline-first). NOT JSON (token cost + comprehension hit + embedding noise). Refs: [nested-format benchmark](https://www.improvingagents.com/blog/best-nested-data-format/), [token efficiency](https://shshell.com/blog/token-efficiency-module-13-lesson-2-format-comparison). + +## 5. Consumption (where the win lands) + +- **The block is a first-class, proposition-level retrieval unit (RESOLVED — SOTA Q2).** "Dense X Retrieval"/factoid-wiki shows atomic propositions as retrieval units significantly outperform passage/sentence retrieval (sharper precision, fewer tokens, better downstream QA); AGRaME confirms proposition-granularity ranking. So: + - **Phase 1 (offline-first):** `knowledge_search` BM25-weights the block (high-signal, deduped) — `parseDoc` extracts it as `aiBlock`, scored above body, returned as the snippet. Works with no embeddings (the Pi default). + - **Phase 2 (embeddings present):** the block gets its **own embedding/vector** (proposition-level index), not folded into the page's body vector. Refs: [Dense X Retrieval](https://arxiv.org/html/2312.06648v2), [AGRaME](https://arxiv.org/pdf/2405.15028). +- **session-load injection** prefers the `ai:begin` block over the prose body — token-cheap, no re-parse. The full prose stays one fetch away. +- **The reading LLM** gets the shared intermediate first; it reads prose only when it needs nuance. This is the TriMem atomic-layer benefit. + +## 5b. Integration constraints (from the 2026-06-02 state-check — do not assume) + +A parallel read of the live subsystems surfaced these hard constraints; the implementation MUST honor them: + +- **Exclude the block from length/byte counts.** `wiki-forget-score.sh` (`wc -c` whole-file + `body<200` stub-floor) and `knowledge-search.ts` (stub penalty, `body<100`) must measure **prose only** — strip `` (and the other marked regions) before counting, or a uniform block shifts FORGET scores and escapes stub penalties. `tests/test-wiki-forget-score.sh` fixtures assume tiny stubs — update or the test breaks. +- **`firstSentence` (knowledge-reindex.ts) must strip `ai:begin`** exactly as it already strips `graph:begin`, so the block never leaks into `index.md`/MOC descriptions. +- **`parseDoc` gains `aiBlock`** (parsed from the marked region); a flat-YAML line parser (no new dep). BM25 weights it; the body-`[[link]]`→`related:` fallback must run on prose with the block stripped. +- **`graph-project` is safe** (it rewrites only its own `graph:begin` region + `related:` frontmatter, both distinct from `ai:begin`) — but a regression test must prove a reindex never clobbers the block. +- **Authoring respects the automation boundary.** The **extractor** (Stop/PreCompact — already automatic) authors the block at capture (extend `extract-prompt.txt` to emit `ai_block` per type + `merge-project-update.sh` to inject the region). The **dream/maintainer** *refresh* it — and they are **explicit-invocation-only** (banners, never auto-dispatch). Do NOT add auto-dispatch (it would revert the 0.21.0 hardening). +- **`knowledge_fetch`** gains a block-aware path (a `block` tier, or block-first in `summary`) so a consumer can read the shared intermediate without the prose. + +## 6. Authoring & maintenance + +- **Extractor** (capture-time): when it writes/updates a page for a known type, author the `ai:begin` block from the session (the same extraction it already does, but emitted as the schema'd block, not only prose). +- **dream / knowledge-maintainer** (consolidation): author/refresh blocks; the maintainer's existing per-category ENRICH guidance *becomes* the block schema (one source of truth for "what a good X page contains"). +- **Closed schema:** the block's fields per type are fixed (a deterministic post-filter drops unknown fields), so the structure can't drift — same closed-vocabulary discipline as project facets. + +## 7. Validation + +- `knowledge_validate` schema-checks each `ai:begin` block: required fields present for the page's type; warns on missing block or missing required field (gentle — additive, not a hard fail while migrating). +- `/second-brain:lint` surfaces pages whose block is **stale vs the prose** (heuristic: block older than body's `updated`) so drift is caught. + +## 8. Multi-granularity model (the whole memory, after this) + +| layer | store | role | reader | +|---|---|---|---| +| **raw** | `~/.second-brain/transcripts/` | fidelity | `episodic_search` / dream mining | +| **atomic** (new) | `ai:begin` block in each page | retrieval / injection | session-load, `knowledge_search`, the LLM | +| **synthesized** | prose body | nuance / reasoning | the LLM on demand | +| **relations** | `graph/edges.jsonl` | structure / blast-radius | `knowledge_neighbors`, projection | + +## 9. Heterogeneous groups (honored) + +Each main group's block schema differs (§4 table) — a `learnings` block is `trigger/action`, a `decisions` block is `choice/alternatives`. The uniform contract is "every page has an `ai:begin` block validated against *its type's* schema"; the shape inside differs by group, exactly the `kb-main-groups-heterogeneous` principle. + +## 10. Migration + +- **Additive + back-compat:** a page with no `ai:begin` block still works (session-load/search fall back to prose); the block accrues as pages are written/consolidated. Flag `SB_AI_BLOCK` (default on for new writes). +- **Backfill:** the dream/maintainer author blocks for existing pages over their normal passes (no big-bang); optionally a one-shot LLM backfill pass for the ~118 current pages. +- **Reversible:** delete the marked regions; pages revert to pure prose. + +## 11. Trade-offs / risks + +- **Authoring cost** — the producing AI does extra work per write. Mitigation: it's the *same* extraction it already does; the block just captures it once instead of every reader re-doing it. Net token win across reads. +- **Block↔prose drift** — the block could go stale vs the prose. Mitigation: lint staleness check (§7); the dream refreshes both together. +- **Schema rigidity** — a fixed per-type schema may not fit every page. Mitigation: all fields optional-but-recommended; an `notes:` free field for the rest; schema evolves per group. +- **Over-structuring** — risk of losing the nuance prose carries. Mitigation: prose stays; the block is the *index*, not the replacement ("Beyond Atomic Facts"). + +## 12. Phasing (own plan when pursued) + +- **P1 — block + schema + validate:** define per-type schemas; `ai:begin` parse + schema-validate in `knowledge-validate`; `parseDoc` exposes the block. Author blocks in the extractor for new writes. +- **P2 — consumption:** session-load injects the block; `knowledge_search` weights/returns it. +- **P3 — maintenance + backfill:** dream/maintainer author+refresh blocks; lint staleness; one-shot backfill of existing pages. + +## 13. Resolved decisions (web-researched 2026-06-02 — SOTA over quick-win) + +1. **Block format → flat YAML `key: value`** in the `ai:begin` marked region (NOT JSON, NOT extended frontmatter). YAML is the model-preferred, token-efficient, plain-text (BM25/embedding-friendly) structured format; flat keeps it parseable by a tiny line parser with no new dependency (offline-first). [§4] +2. **Embedding → proposition-level.** The block is its own retrieval unit: Phase 1 BM25-weights it (offline); Phase 2 gives it its own vector (proposition indexing beats passage/sentence). [§5] +3. **Confidence → hybrid**, LLM-verbalized primary (best-calibrated per 2026 study) + evidence/recurrence corroboration + recency. [§4] + +(Remaining genuinely-open, to settle in the plan: the exact `aiBlock` BM25 weight (lean 1.5, between body 1.0 and tags 2.0); whether `knowledge_fetch` adds a `block` tier vs folds into `summary`.) diff --git a/mcp/dist/cli/sb-entry.bundle.js b/mcp/dist/cli/sb-entry.bundle.js index 9fad206..bf841ac 100644 --- a/mcp/dist/cli/sb-entry.bundle.js +++ b/mcp/dist/cli/sb-entry.bundle.js @@ -6288,6 +6288,30 @@ function validAt(e, t) { return cmpTime(dateOf(e.valid_to), td) > 0; } +// src/tools/ai-block.ts +var AI_BLOCK_RE = /\n?([\s\S]*?)/; +function parseAiBlock(content) { + const m = content.match(AI_BLOCK_RE); + if (!m) return null; + const out = {}; + let last = ""; + for (const raw of m[1].split("\n")) { + const line = raw.trimEnd(); + if (!line.trim()) continue; + const kv = line.match(/^([a-z_][a-z0-9_]*):\s*(.*)$/i); + if (kv) { + last = kv[1]; + out[last] = kv[2].trim(); + } else if (last) { + out[last] = (out[last] + " " + line.trim()).trim(); + } + } + return out; +} +function stripAiBlock(text) { + return text.replace(AI_BLOCK_RE, ""); +} + // src/tools/knowledge-search.ts var ACCESS_COUNTS_FILE = join3(process.env.HOME ?? "", ".second-brain", "access-counts.json"); var ACCESS_BOOST_FACTOR = 0.1; @@ -6466,7 +6490,7 @@ ${e.headings.join("\n")}`, source: "local-doc", tokens: Math.ceil(e.size / 4) }) for (let i = 0; i < scored.length; i++) { if (allDocs[i].source === "local-doc") continue; const { doc, rawContent } = allDocs[i]; - if (AUTO_EXTRACTED_RE.test(rawContent) || doc.body.trim().length < MIN_SUBSTANTIVE_LENGTH) { + if (AUTO_EXTRACTED_RE.test(rawContent) || stripAiBlock(doc.body).trim().length < MIN_SUBSTANTIVE_LENGTH) { scored[i].score *= STUB_PENALTY; } } @@ -6585,8 +6609,9 @@ function parseDoc(content, filePath) { doc.type = rel[wikiIdx + 1]; } } + doc.aiBlock = parseAiBlock(content) ?? void 0; if (doc.related.length === 0) { - const wikiLinks = doc.body.match(/\[\[([^\]]+)\]\]/g); + const wikiLinks = stripAiBlock(doc.body).match(/\[\[([^\]]+)\]\]/g); if (wikiLinks) { doc.related = [...new Set(wikiLinks.map((l) => l.slice(2, -2)))]; } diff --git a/mcp/dist/server.bundle.js b/mcp/dist/server.bundle.js index 8270d7d..7d25a37 100644 --- a/mcp/dist/server.bundle.js +++ b/mcp/dist/server.bundle.js @@ -27628,6 +27628,43 @@ async function appendEdge(path3, rec) { await fs6.appendFile(path3, JSON.stringify(rec) + "\n", "utf-8"); } +// src/tools/ai-block.ts +var AI_BLOCK_RE = /\n?([\s\S]*?)/; +var AI_BLOCK_SCHEMAS = { + learnings: { fields: ["claim", "trigger", "action", "scope", "evidence", "supersedes"], required: ["claim", "action"] }, + decisions: { fields: ["context", "choice", "alternatives", "rationale", "status", "supersedes"], required: ["choice"] }, + entities: { fields: ["identity", "current_state", "depends_on", "owns", "status"], required: ["identity"] }, + issues: { fields: ["symptom", "cause", "fix", "severity", "status"], required: ["symptom", "status"] }, + concepts: { fields: ["problem", "solution", "where_applied", "tradeoffs"], required: ["problem", "solution"] }, + security: { fields: ["threat", "mitigation", "scope", "status"], required: ["threat", "mitigation"] } +}; +function parseAiBlock(content) { + const m = content.match(AI_BLOCK_RE); + if (!m) return null; + const out = {}; + let last = ""; + for (const raw of m[1].split("\n")) { + const line = raw.trimEnd(); + if (!line.trim()) continue; + const kv = line.match(/^([a-z_][a-z0-9_]*):\s*(.*)$/i); + if (kv) { + last = kv[1]; + out[last] = kv[2].trim(); + } else if (last) { + out[last] = (out[last] + " " + line.trim()).trim(); + } + } + return out; +} +function stripAiBlock(text) { + return text.replace(AI_BLOCK_RE, ""); +} +function validateAiBlock(type, block) { + const schema = AI_BLOCK_SCHEMAS[type]; + if (!schema) return []; + return schema.required.filter((f) => !block[f] || !block[f].trim()); +} + // src/tools/knowledge-search.ts var ACCESS_COUNTS_FILE = join6(process.env.HOME ?? "", ".second-brain", "access-counts.json"); var ACCESS_BOOST_FACTOR = 0.1; @@ -27806,7 +27843,7 @@ ${e.headings.join("\n")}`, source: "local-doc", tokens: Math.ceil(e.size / 4) }) for (let i = 0; i < scored.length; i++) { if (allDocs[i].source === "local-doc") continue; const { doc, rawContent } = allDocs[i]; - if (AUTO_EXTRACTED_RE.test(rawContent) || doc.body.trim().length < MIN_SUBSTANTIVE_LENGTH) { + if (AUTO_EXTRACTED_RE.test(rawContent) || stripAiBlock(doc.body).trim().length < MIN_SUBSTANTIVE_LENGTH) { scored[i].score *= STUB_PENALTY; } } @@ -27925,8 +27962,9 @@ function parseDoc(content, filePath) { doc.type = rel[wikiIdx + 1]; } } + doc.aiBlock = parseAiBlock(content) ?? void 0; if (doc.related.length === 0) { - const wikiLinks = doc.body.match(/\[\[([^\]]+)\]\]/g); + const wikiLinks = stripAiBlock(doc.body).match(/\[\[([^\]]+)\]\]/g); if (wikiLinks) { doc.related = [...new Set(wikiLinks.map((l) => l.slice(2, -2)))]; } @@ -28090,7 +28128,7 @@ import { join as join10 } from "path"; // src/tools/knowledge-validate.ts import { promises as fs9 } from "fs"; -import { join as join8, basename, relative as relative2 } from "path"; +import { join as join8, basename, dirname as dirname2, relative as relative2 } from "path"; async function knowledgeValidate(knowledgeDir, opts = {}) { const wikiDir = join8(knowledgeDir, "wiki"); const issues = []; @@ -28103,6 +28141,17 @@ async function knowledgeValidate(knowledgeDir, opts = {}) { const slug = basename(filePath, ".md"); const doc = parseDoc(content, filePath); parsedDocs.push(doc); + const aiBlock = parseAiBlock(content); + if (aiBlock) { + const ptype = doc.type || basename(dirname2(filePath)); + const missing = validateAiBlock(ptype, aiBlock); + if (missing.length) issues.push({ + type: "ai_block_incomplete", + severity: "warning", + path: filePath, + message: `ai-block missing required field(s) for type ${ptype}: ${missing.join(", ")}` + }); + } if (!/[/\\](projects|themes)[/\\]/.test(filePath)) { if (!slugMap.has(slug)) slugMap.set(slug, []); slugMap.get(slug).push(filePath); @@ -28528,7 +28577,7 @@ async function knowledgeReindex(knowledgeDir) { }; } function firstSentence(body) { - const text = body.replace(//g, "").replace(/^#.*\n/m, "").trim(); + const text = stripAiBlock(body).replace(//g, "").replace(/^#.*\n/m, "").trim(); const match2 = text.match(/^(.+?[.!?])\s/); return match2 ? match2[1].slice(0, 120) : text.slice(0, 120); } @@ -29248,7 +29297,7 @@ function resolveActiveSlug() { return slugFromProjectDir(activeProjectDir()); } var server = new McpServer( - { name: "knowledge-base", version: "2.4.1" }, + { name: "knowledge-base", version: "2.5.0" }, { capabilities: { logging: {} }, instructions: "BM25-scored search over the local knowledge base. Use knowledge_search to find relevant wiki pages (searches full content with field-weighted scoring), knowledge_reindex to regenerate the wiki index.md catalog (also runs validation with autofix), knowledge_validate to check wiki health (broken links, orphans, duplicates, session-narrative pages), knowledge_stats for an overview of wiki size and categories, pin_to_user to record a user-level preference, pin_to_project to append blockers/decisions to a project's PROJECT.md, and archive_to_wiki to graduate a [resolved] entry from a project file into the wiki. Dream tools: dream_create to start a background consolidation job (snapshots wiki + selects transcripts), dream_status to check progress, dream_list to see all dreams, dream_accept to apply a completed dream's changes, dream_discard to reject changes, and dream_cancel to stop a running dream. Episodic memory: episodic_search to search past conversation transcripts (hybrid vector + text, multi-concept AND), episodic_read to read a specific transcript section. Relational graph: knowledge_relate to assert/invalidate a typed bi-temporal relationship (requires|affects|relates|part_of|supersedes) between two pages, and knowledge_neighbors to walk a page's dependency neighbourhood (multi-hop, directional, point-in-time via as_of)." diff --git a/mcp/dist/server.js b/mcp/dist/server.js index dbb71ac..a783780 100644 --- a/mcp/dist/server.js +++ b/mcp/dist/server.js @@ -48,7 +48,7 @@ function resolveActiveSlug() { // launch dir and unreliable). Fall back to cwd on older CLIs that don't set it. return slugFromProjectDir(activeProjectDir()); } -const server = new McpServer({ name: "knowledge-base", version: "2.4.1" }, { +const server = new McpServer({ name: "knowledge-base", version: "2.5.0" }, { capabilities: { logging: {} }, instructions: "BM25-scored search over the local knowledge base. Use knowledge_search to find relevant wiki pages (searches full content with field-weighted scoring), knowledge_reindex to regenerate the wiki index.md catalog (also runs validation with autofix), knowledge_validate to check wiki health (broken links, orphans, duplicates, session-narrative pages), knowledge_stats for an overview of wiki size and categories, pin_to_user to record a user-level preference, pin_to_project to append blockers/decisions to a project's PROJECT.md, and archive_to_wiki to graduate a [resolved] entry from a project file into the wiki. Dream tools: dream_create to start a background consolidation job (snapshots wiki + selects transcripts), dream_status to check progress, dream_list to see all dreams, dream_accept to apply a completed dream's changes, dream_discard to reject changes, and dream_cancel to stop a running dream. Episodic memory: episodic_search to search past conversation transcripts (hybrid vector + text, multi-concept AND), episodic_read to read a specific transcript section. Relational graph: knowledge_relate to assert/invalidate a typed bi-temporal relationship (requires|affects|relates|part_of|supersedes) between two pages, and knowledge_neighbors to walk a page's dependency neighbourhood (multi-hop, directional, point-in-time via as_of).", }); diff --git a/mcp/dist/tools/ai-block.d.ts b/mcp/dist/tools/ai-block.d.ts new file mode 100644 index 0000000..47f3252 --- /dev/null +++ b/mcp/dist/tools/ai-block.d.ts @@ -0,0 +1,15 @@ +export declare const AI_BLOCK_RE: RegExp; +export interface AiBlockSchema { + fields: string[]; + required: string[]; +} +export declare const AI_BLOCK_SCHEMAS: Record; +/** Parse the flat-YAML `key: value` body of the ai:begin…ai:end region into an object. + * A line not matching `key:` is folded (appended) into the previous field's value. + * Returns null when the page has no block. */ +export declare function parseAiBlock(content: string): Record | null; +/** Remove the ai:begin…ai:end region so length/first-sentence consumers ignore it. */ +export declare function stripAiBlock(text: string): string; +/** Missing REQUIRED fields for the page type (empty when type unknown or all present). */ +export declare function validateAiBlock(type: string, block: Record): string[]; +//# sourceMappingURL=ai-block.d.ts.map \ No newline at end of file diff --git a/mcp/dist/tools/ai-block.d.ts.map b/mcp/dist/tools/ai-block.d.ts.map new file mode 100644 index 0000000..aebac2b --- /dev/null +++ b/mcp/dist/tools/ai-block.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ai-block.d.ts","sourceRoot":"","sources":["../../src/tools/ai-block.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,WAAW,QAA8D,CAAC;AAEvF,MAAM,WAAW,aAAa;IAAG,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;CAAE;AAIxE,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAO1D,CAAC;AAEF;;+CAE+C;AAC/C,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAa3E;AAED,sFAAsF;AACtF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,EAAE,CAIrF"} \ No newline at end of file diff --git a/mcp/dist/tools/ai-block.js b/mcp/dist/tools/ai-block.js new file mode 100644 index 0000000..98ceb85 --- /dev/null +++ b/mcp/dist/tools/ai-block.js @@ -0,0 +1,54 @@ +// AI-native representation — the per-page machine-first "shared intermediate" block. +// A marked region holding flat YAML key:value +// fields (per-type schema). Pure module: parse / strip / validate. No I/O. +// Spec: docs/specs/2026-06-02-ai-native-knowledge-representation-design.md +// The begin marker is a single HTML comment line (its annotation tail stays on that line, +// `[^\n]*?` — so a stray token can't fold the comment-tail into the parsed body). Requires a +// matching ai:end; an unterminated ai:begin is NOT a block (no match → parse null / strip no-op). +export const AI_BLOCK_RE = /\n?([\s\S]*?)/; +// Per-type schemas (spec §4). `required` = the load-bearing fields a good page of that +// type should carry; missing ones are WARNINGS (gentle), never errors. +export const AI_BLOCK_SCHEMAS = { + learnings: { fields: ['claim', 'trigger', 'action', 'scope', 'evidence', 'supersedes'], required: ['claim', 'action'] }, + decisions: { fields: ['context', 'choice', 'alternatives', 'rationale', 'status', 'supersedes'], required: ['choice'] }, + entities: { fields: ['identity', 'current_state', 'depends_on', 'owns', 'status'], required: ['identity'] }, + issues: { fields: ['symptom', 'cause', 'fix', 'severity', 'status'], required: ['symptom', 'status'] }, + concepts: { fields: ['problem', 'solution', 'where_applied', 'tradeoffs'], required: ['problem', 'solution'] }, + security: { fields: ['threat', 'mitigation', 'scope', 'status'], required: ['threat', 'mitigation'] }, +}; +/** Parse the flat-YAML `key: value` body of the ai:begin…ai:end region into an object. + * A line not matching `key:` is folded (appended) into the previous field's value. + * Returns null when the page has no block. */ +export function parseAiBlock(content) { + const m = content.match(AI_BLOCK_RE); + if (!m) + return null; + const out = {}; + let last = ''; + for (const raw of m[1].split('\n')) { + const line = raw.trimEnd(); + if (!line.trim()) + continue; + const kv = line.match(/^([a-z_][a-z0-9_]*):\s*(.*)$/i); + if (kv) { + last = kv[1]; + out[last] = kv[2].trim(); + } + else if (last) { + out[last] = (out[last] + ' ' + line.trim()).trim(); + } + } + return out; +} +/** Remove the ai:begin…ai:end region so length/first-sentence consumers ignore it. */ +export function stripAiBlock(text) { + return text.replace(AI_BLOCK_RE, ''); +} +/** Missing REQUIRED fields for the page type (empty when type unknown or all present). */ +export function validateAiBlock(type, block) { + const schema = AI_BLOCK_SCHEMAS[type]; + if (!schema) + return []; + return schema.required.filter(f => !block[f] || !block[f].trim()); +} +//# sourceMappingURL=ai-block.js.map \ No newline at end of file diff --git a/mcp/dist/tools/ai-block.js.map b/mcp/dist/tools/ai-block.js.map new file mode 100644 index 0000000..f1a28a7 --- /dev/null +++ b/mcp/dist/tools/ai-block.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ai-block.js","sourceRoot":"","sources":["../../src/tools/ai-block.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mcp/dist/tools/ai-block.test.d.ts b/mcp/dist/tools/ai-block.test.d.ts new file mode 100644 index 0000000..67a8a3f --- /dev/null +++ b/mcp/dist/tools/ai-block.test.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=ai-block.test.d.ts.map \ No newline at end of file diff --git a/mcp/dist/tools/ai-block.test.d.ts.map b/mcp/dist/tools/ai-block.test.d.ts.map new file mode 100644 index 0000000..a8b9291 --- /dev/null +++ b/mcp/dist/tools/ai-block.test.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ai-block.test.d.ts","sourceRoot":"","sources":["../../src/tools/ai-block.test.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/mcp/dist/tools/ai-block.test.js b/mcp/dist/tools/ai-block.test.js new file mode 100644 index 0000000..f4bc9d3 --- /dev/null +++ b/mcp/dist/tools/ai-block.test.js @@ -0,0 +1,50 @@ +import { describe, it, expect } from 'vitest'; +import { parseAiBlock, stripAiBlock, validateAiBlock, AI_BLOCK_SCHEMAS } from './ai-block.js'; +const page = [ + '---', 'title: awk', 'type: learnings', '---', + "", + 'claim: never interpolate shell vars into awk', + 'trigger: writing awk in a .sh', + 'action: pass via -v + numeric coercion', + 'scope: mawk (Pi default)', + '', '', '## Notes', 'mawk errors on empty interpolation. Period.', +].join('\n'); +describe('ai-block', () => { + it('parses the flat key:value block into an object', () => { + const b = parseAiBlock(page); + expect(b.claim).toBe('never interpolate shell vars into awk'); + expect(b.action).toBe('pass via -v + numeric coercion'); + }); + it('returns null when there is no block', () => { + expect(parseAiBlock('---\ntitle: x\n---\n# x\nno block here')).toBeNull(); + }); + it('strips the block (for length/first-sentence counts)', () => { + const s = stripAiBlock(page); + expect(s).not.toContain('ai:begin'); + expect(s).not.toContain('claim:'); + expect(s).toContain('## Notes'); + }); + it('validateAiBlock reports missing REQUIRED fields for the type', () => { + expect(validateAiBlock('learnings', { claim: 'x' })).toEqual(['action']); + expect(validateAiBlock('learnings', { claim: 'x', action: 'y' })).toEqual([]); + expect(validateAiBlock('unknown-type', { foo: 'bar' })).toEqual([]); + }); + it('has schemas for the six structured types', () => { + for (const t of ['learnings', 'decisions', 'entities', 'issues', 'concepts', 'security']) + expect(AI_BLOCK_SCHEMAS[t].required.length).toBeGreaterThan(0); + }); + it('treats an UNTERMINATED ai:begin (no ai:end) as NOT a block (parse null, strip no-op)', () => { + const md = ['---', 'title: x', '---', '', 'claim: c', '', '# real prose continues forever'].join('\n'); + expect(parseAiBlock(md)).toBeNull(); + expect(stripAiBlock(md)).toBe(md); // must not eat the rest of the page + }); + it('keeps the begin-marker annotation on its own line (a stray > in the tail is fine)', () => { + const md = ['', 'claim: kept', 'action: a', ''].join('\n'); + expect(parseAiBlock(md).claim).toBe('kept'); + }); + it('folds a continuation line into the previous field value', () => { + const md = ['', 'claim: line one', ' continued', 'action: do it', ''].join('\n'); + expect(parseAiBlock(md).claim).toBe('line one continued'); + }); +}); +//# sourceMappingURL=ai-block.test.js.map \ No newline at end of file diff --git a/mcp/dist/tools/ai-block.test.js.map b/mcp/dist/tools/ai-block.test.js.map new file mode 100644 index 0000000..7fa24f2 --- /dev/null +++ b/mcp/dist/tools/ai-block.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ai-block.test.js","sourceRoot":"","sources":["../../src/tools/ai-block.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mcp/dist/tools/knowledge-reindex.bundle.js b/mcp/dist/tools/knowledge-reindex.bundle.js index 8f172af..d8abab7 100644 --- a/mcp/dist/tools/knowledge-reindex.bundle.js +++ b/mcp/dist/tools/knowledge-reindex.bundle.js @@ -6145,6 +6145,43 @@ function validAt(e, t) { return cmpTime(dateOf(e.valid_to), td) > 0; } +// src/tools/ai-block.ts +var AI_BLOCK_RE = /\n?([\s\S]*?)/; +var AI_BLOCK_SCHEMAS = { + learnings: { fields: ["claim", "trigger", "action", "scope", "evidence", "supersedes"], required: ["claim", "action"] }, + decisions: { fields: ["context", "choice", "alternatives", "rationale", "status", "supersedes"], required: ["choice"] }, + entities: { fields: ["identity", "current_state", "depends_on", "owns", "status"], required: ["identity"] }, + issues: { fields: ["symptom", "cause", "fix", "severity", "status"], required: ["symptom", "status"] }, + concepts: { fields: ["problem", "solution", "where_applied", "tradeoffs"], required: ["problem", "solution"] }, + security: { fields: ["threat", "mitigation", "scope", "status"], required: ["threat", "mitigation"] } +}; +function parseAiBlock(content) { + const m = content.match(AI_BLOCK_RE); + if (!m) return null; + const out = {}; + let last = ""; + for (const raw of m[1].split("\n")) { + const line = raw.trimEnd(); + if (!line.trim()) continue; + const kv = line.match(/^([a-z_][a-z0-9_]*):\s*(.*)$/i); + if (kv) { + last = kv[1]; + out[last] = kv[2].trim(); + } else if (last) { + out[last] = (out[last] + " " + line.trim()).trim(); + } + } + return out; +} +function stripAiBlock(text) { + return text.replace(AI_BLOCK_RE, ""); +} +function validateAiBlock(type, block) { + const schema = AI_BLOCK_SCHEMAS[type]; + if (!schema) return []; + return schema.required.filter((f) => !block[f] || !block[f].trim()); +} + // src/tools/knowledge-search.ts var ACCESS_COUNTS_FILE = join(process.env.HOME ?? "", ".second-brain", "access-counts.json"); function parseDoc(content, filePath) { @@ -6186,8 +6223,9 @@ function parseDoc(content, filePath) { doc.type = rel[wikiIdx + 1]; } } + doc.aiBlock = parseAiBlock(content) ?? void 0; if (doc.related.length === 0) { - const wikiLinks = doc.body.match(/\[\[([^\]]+)\]\]/g); + const wikiLinks = stripAiBlock(doc.body).match(/\[\[([^\]]+)\]\]/g); if (wikiLinks) { doc.related = [...new Set(wikiLinks.map((l) => l.slice(2, -2)))]; } @@ -6236,7 +6274,7 @@ function extractYamlList(yaml, key) { // src/tools/knowledge-validate.ts import { promises as fs2 } from "fs"; -import { join as join2, basename, relative } from "path"; +import { join as join2, basename, dirname, relative } from "path"; async function knowledgeValidate(knowledgeDir, opts = {}) { const wikiDir = join2(knowledgeDir, "wiki"); const issues = []; @@ -6249,6 +6287,17 @@ async function knowledgeValidate(knowledgeDir, opts = {}) { const slug = basename(filePath, ".md"); const doc = parseDoc(content, filePath); parsedDocs.push(doc); + const aiBlock = parseAiBlock(content); + if (aiBlock) { + const ptype = doc.type || basename(dirname(filePath)); + const missing = validateAiBlock(ptype, aiBlock); + if (missing.length) issues.push({ + type: "ai_block_incomplete", + severity: "warning", + path: filePath, + message: `ai-block missing required field(s) for type ${ptype}: ${missing.join(", ")}` + }); + } if (!/[/\\](projects|themes)[/\\]/.test(filePath)) { if (!slugMap.has(slug)) slugMap.set(slug, []); slugMap.get(slug).push(filePath); @@ -6674,7 +6723,7 @@ async function knowledgeReindex(knowledgeDir) { }; } function firstSentence(body) { - const text = body.replace(//g, "").replace(/^#.*\n/m, "").trim(); + const text = stripAiBlock(body).replace(//g, "").replace(/^#.*\n/m, "").trim(); const match2 = text.match(/^(.+?[.!?])\s/); return match2 ? match2[1].slice(0, 120) : text.slice(0, 120); } diff --git a/mcp/dist/tools/knowledge-reindex.d.ts.map b/mcp/dist/tools/knowledge-reindex.d.ts.map index e090f5b..caed0cf 100644 --- a/mcp/dist/tools/knowledge-reindex.d.ts.map +++ b/mcp/dist/tools/knowledge-reindex.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"knowledge-reindex.d.ts","sourceRoot":"","sources":["../../src/tools/knowledge-reindex.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI7E,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE;QAAE,MAAM,EAAE,eAAe,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3D;AAED,wBAAsB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA2FnF"} \ No newline at end of file +{"version":3,"file":"knowledge-reindex.d.ts","sourceRoot":"","sources":["../../src/tools/knowledge-reindex.ts"],"names":[],"mappings":"AAGA,OAAO,EAAqB,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAK7E,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE;QAAE,MAAM,EAAE,eAAe,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3D;AAED,wBAAsB,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA2FnF"} \ No newline at end of file diff --git a/mcp/dist/tools/knowledge-reindex.js b/mcp/dist/tools/knowledge-reindex.js index ae1a352..01cdb7f 100644 --- a/mcp/dist/tools/knowledge-reindex.js +++ b/mcp/dist/tools/knowledge-reindex.js @@ -4,6 +4,7 @@ import { parseDoc } from './knowledge-search.js'; import { knowledgeValidate } from './knowledge-validate.js'; import { projectGraphToPages } from './graph-project.js'; import { buildProjectMocs } from './project-moc.js'; +import { stripAiBlock } from './ai-block.js'; export async function knowledgeReindex(knowledgeDir) { // Project the relationship graph onto pages first, so the index + validation // see current related: links. No-op when ~/knowledge/graph/edges.jsonl absent. @@ -106,7 +107,7 @@ export async function knowledgeReindex(knowledgeDir) { }; } function firstSentence(body) { - const text = body + const text = stripAiBlock(body) // drop the authored ai-block .replace(//g, '') // drop the generated projection block .replace(/^#.*\n/m, '') .trim(); diff --git a/mcp/dist/tools/knowledge-reindex.js.map b/mcp/dist/tools/knowledge-reindex.js.map index 2b5208f..863be5b 100644 --- a/mcp/dist/tools/knowledge-reindex.js.map +++ b/mcp/dist/tools/knowledge-reindex.js.map @@ -1 +1 @@ -{"version":3,"file":"knowledge-reindex.js","sourceRoot":"","sources":["../../src/tools/knowledge-reindex.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"knowledge-reindex.js","sourceRoot":"","sources":["../../src/tools/knowledge-reindex.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mcp/dist/tools/knowledge-reindex.test.js b/mcp/dist/tools/knowledge-reindex.test.js index a219b96..13c45e7 100644 --- a/mcp/dist/tools/knowledge-reindex.test.js +++ b/mcp/dist/tools/knowledge-reindex.test.js @@ -102,6 +102,30 @@ describe('reindex project MOCs', () => { process.env.SB_MOC_MIN_MEMBERS = prev; } }); + it('reindex/graph-projection preserves the ai-block byte-for-byte', async () => { + const kd = await fsp.mkdtemp(join(tmpdir(), 'ri-keep-')); + await fsp.mkdir(join(kd, 'wiki', 'decisions'), { recursive: true }); + const block = ['', 'choice: use X', 'status: active', ''].join('\n'); + await fsp.writeFile(join(kd, 'wiki', 'decisions', 'd.md'), `---\ntitle: D\ntype: decisions\nrelated: []\n---\n${block}\n\n# D\nbody [[other]]`); + await fsp.writeFile(join(kd, 'wiki', 'decisions', 'other.md'), `---\ntitle: O\ntype: decisions\n---\n# O\n`); + await appendEdge(join(kd, 'graph', 'edges.jsonl'), { op: 'assert', from: 'd', to: 'other', type: 'requires', valid_from: '2026-05-01', recorded_at: '2026-05-01T00:00:00Z' }); + await knowledgeReindex(kd); // projects related: + ## Dependencies onto d.md + const after = await fsp.readFile(join(kd, 'wiki', 'decisions', 'd.md'), 'utf-8'); + expect(after).toContain(block); // the ai-block survives projection intact + expect(after).toMatch(/related: \[\[other\]\]/); // projection still happened (edge applied) + }); + it('project-MOC member description ignores the ai-block (firstSentence strips it)', async () => { + const kd = await fsp.mkdtemp(join(tmpdir(), 'ri-ai-')); + await fsp.mkdir(join(kd, 'wiki', 'concepts'), { recursive: true }); + const body = ['', 'problem: BLOCKWORD should not surface', 'solution: x', '', '', 'Real prose sentence here.'].join('\n'); + await fsp.writeFile(join(kd, 'wiki', 'concepts', 'p.md'), `---\ntitle: P\ntype: concepts\nproject: demo\n---\n${body}`); + await fsp.writeFile(join(kd, 'wiki', 'concepts', 'q.md'), `---\ntitle: Q\ntype: concepts\nproject: demo\n---\n# Q\nprose`); + await fsp.writeFile(join(kd, 'wiki', 'concepts', 'r.md'), `---\ntitle: R\ntype: concepts\nproject: demo\n---\n# R\nprose`); + await knowledgeReindex(kd); + const moc = await fsp.readFile(join(kd, 'wiki', 'projects', 'demo.md'), 'utf-8'); + expect(moc).toContain('[[p]]'); + expect(moc).not.toContain('BLOCKWORD'); // member description must come from prose, not the block + }); it('does not mangle a MOC whose project key is an edge endpoint (#2 idempotency)', async () => { const kd = await fsp.mkdtemp(join(tmpdir(), 'mangle-')); await page(kd, 'decisions', 'arch-a', 'arch'); diff --git a/mcp/dist/tools/knowledge-reindex.test.js.map b/mcp/dist/tools/knowledge-reindex.test.js.map index 2b9f674..e8d029a 100644 --- a/mcp/dist/tools/knowledge-reindex.test.js.map +++ b/mcp/dist/tools/knowledge-reindex.test.js.map @@ -1 +1 @@ -{"version":3,"file":"knowledge-reindex.test.js","sourceRoot":"","sources":["../../src/tools/knowledge-reindex.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,QAAQ,IAAI,GAAG,EAAE,MAAM,IAAI,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;IACtD,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;QACrD,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,KAAK,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;YACrC,MAAM,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC,2CAA2C,CAAC,IAAI,CAAC,CAAC;QAClI,CAAC;QACD,MAAM,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,aAAa,CAAC,EAChD,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,sBAAsB,EAAE,CAAC,CAAC;QACnI,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;QACnF,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;QAC9C,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,kCAAkC,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;QACtD,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,MAAM,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,mDAAmD,CAAC,CAAC;QACnH,MAAM,CAAC,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACtC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,KAAK,UAAU,IAAI,CAAC,EAAU,EAAE,GAAW,EAAE,IAAY,EAAE,OAAgB;IACzE,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,MAAM,EAAE,GAAG,CAAC,KAAK,EAAE,UAAU,IAAI,EAAE,EAAE,SAAS,GAAG,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IACtH,MAAM,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,yFAAyF,EAAE,KAAK,IAAI,EAAE;QACvG,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;QACrD,MAAM,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,CAAC,CAAC;QACxD,MAAM,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAC;QAC3D,MAAM,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC;QAC1D,MAAM,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC;QAC1D,MAAM,gBAAgB,CAAC,EAAE,CAAC,CAAC;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9D,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QACzC,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,mBAAmB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ;IACzG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4FAA4F,EAAE,KAAK,IAAI,EAAE;QAC1G,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;QACrD,MAAM,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,CAAC,CAAC;QACxD,MAAM,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAC;QAC3D,MAAM,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;QACzC,MAAM,gBAAgB,CAAC,EAAE,CAAC,CAAC;QAC3B,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC;QACtE,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,CAAG,gCAAgC;QAClG,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAAuB,0CAA0C;QAC5G,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAsB,mCAAmC;QACrG,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC,CAAe,6CAA6C;IAChH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;QACtD,MAAM,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,CAAC,CAAC;QACxD,MAAM,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC;QACrE,MAAM,gBAAgB,CAAC,EAAE,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QAC9E,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;QAClF,MAAM,gBAAgB,CAAC,EAAE,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QAC9E,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;QAClF,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,wCAAwC;IACnE,CAAC,CAAC,CAAC;IAEH,sCAAsC;IAEtC,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;QACvD,MAAM,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,CAAC,CAAC;QACxD,MAAM,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAC;QAC3D,MAAM,gBAAgB,CAAC,EAAE,CAAC,CAAC;QAC3B,MAAM,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9F,MAAM,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,yBAAyB,CAAC,CAAC,CAAC,CAAC,YAAY;QACvF,MAAM,gBAAgB,CAAC,EAAE,CAAC,CAAC;QAC3B,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,SAAS;IAChG,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0FAA0F,EAAE,KAAK,IAAI,EAAE;QACxG,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;QACvD,MAAM,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,OAAO,CAAC,CAAC,iDAAiD;QAC3F,IAAI,CAAC;YACH,MAAM,gBAAgB,CAAC,EAAE,CAAC,CAAC;YAC3B,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAC9F,CAAC;gBAAS,CAAC;YAAC,IAAI,IAAI,KAAK,SAAS;gBAAE,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;;gBAAM,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAAC,CAAC;IAC1H,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;QAC5F,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC;QACxD,MAAM,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC9C,MAAM,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC9C,MAAM,IAAI,CAAC,EAAE,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC9C,qFAAqF;QACrF,wFAAwF;QACxF,qCAAqC;QACrC,MAAM,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,aAAa,CAAC,EAC/C,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,sBAAsB,EAAE,CAAC,CAAC;QAChI,MAAM,gBAAgB,CAAC,EAAE,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;QAClF,MAAM,gBAAgB,CAAC,EAAE,CAAC,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;QAClF,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAuB,gDAAgD;QAC/F,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,kDAAkD;QACjG,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAQ,oCAAoC;IACrF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"knowledge-reindex.test.js","sourceRoot":"","sources":["../../src/tools/knowledge-reindex.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mcp/dist/tools/knowledge-search-cli.bundle.js b/mcp/dist/tools/knowledge-search-cli.bundle.js index 524a420..e3a0656 100644 --- a/mcp/dist/tools/knowledge-search-cli.bundle.js +++ b/mcp/dist/tools/knowledge-search-cli.bundle.js @@ -6280,6 +6280,30 @@ function validAt(e, t) { return cmpTime(dateOf(e.valid_to), td) > 0; } +// src/tools/ai-block.ts +var AI_BLOCK_RE = /\n?([\s\S]*?)/; +function parseAiBlock(content) { + const m = content.match(AI_BLOCK_RE); + if (!m) return null; + const out = {}; + let last = ""; + for (const raw of m[1].split("\n")) { + const line = raw.trimEnd(); + if (!line.trim()) continue; + const kv = line.match(/^([a-z_][a-z0-9_]*):\s*(.*)$/i); + if (kv) { + last = kv[1]; + out[last] = kv[2].trim(); + } else if (last) { + out[last] = (out[last] + " " + line.trim()).trim(); + } + } + return out; +} +function stripAiBlock(text) { + return text.replace(AI_BLOCK_RE, ""); +} + // src/tools/knowledge-search.ts var ACCESS_COUNTS_FILE = join3(process.env.HOME ?? "", ".second-brain", "access-counts.json"); var ACCESS_BOOST_FACTOR = 0.1; @@ -6458,7 +6482,7 @@ ${e.headings.join("\n")}`, source: "local-doc", tokens: Math.ceil(e.size / 4) }) for (let i = 0; i < scored.length; i++) { if (allDocs[i].source === "local-doc") continue; const { doc, rawContent } = allDocs[i]; - if (AUTO_EXTRACTED_RE.test(rawContent) || doc.body.trim().length < MIN_SUBSTANTIVE_LENGTH) { + if (AUTO_EXTRACTED_RE.test(rawContent) || stripAiBlock(doc.body).trim().length < MIN_SUBSTANTIVE_LENGTH) { scored[i].score *= STUB_PENALTY; } } @@ -6577,8 +6601,9 @@ function parseDoc(content, filePath) { doc.type = rel[wikiIdx + 1]; } } + doc.aiBlock = parseAiBlock(content) ?? void 0; if (doc.related.length === 0) { - const wikiLinks = doc.body.match(/\[\[([^\]]+)\]\]/g); + const wikiLinks = stripAiBlock(doc.body).match(/\[\[([^\]]+)\]\]/g); if (wikiLinks) { doc.related = [...new Set(wikiLinks.map((l) => l.slice(2, -2)))]; } diff --git a/mcp/dist/tools/knowledge-search.d.ts b/mcp/dist/tools/knowledge-search.d.ts index b522617..c429302 100644 --- a/mcp/dist/tools/knowledge-search.d.ts +++ b/mcp/dist/tools/knowledge-search.d.ts @@ -26,6 +26,7 @@ export interface ParsedDoc { created: string; project: string; area: string; + aiBlock?: Record; } export declare function knowledgeSearch(args: KnowledgeSearchArgs): Promise; export declare function parseDoc(content: string, filePath: string): ParsedDoc; diff --git a/mcp/dist/tools/knowledge-search.d.ts.map b/mcp/dist/tools/knowledge-search.d.ts.map index 1c8c94f..f0e28da 100644 --- a/mcp/dist/tools/knowledge-search.d.ts.map +++ b/mcp/dist/tools/knowledge-search.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"knowledge-search.d.ts","sourceRoot":"","sources":["../../src/tools/knowledge-search.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,mBAAmB;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAAE;AACvI,MAAM,WAAW,qBAAqB;IAAG,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAAE;AAE9I,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAiCD,wBAAsB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA8M/F;AA2CD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,CA0CrE"} \ No newline at end of file +{"version":3,"file":"knowledge-search.d.ts","sourceRoot":"","sources":["../../src/tools/knowledge-search.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,mBAAmB;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAAE;AACvI,MAAM,WAAW,qBAAqB;IAAG,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAAE;AAE9I,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAiCD,wBAAsB,eAAe,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CA8M/F;AA2CD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,CA8CrE"} \ No newline at end of file diff --git a/mcp/dist/tools/knowledge-search.js b/mcp/dist/tools/knowledge-search.js index 9bdb6f4..935ae84 100644 --- a/mcp/dist/tools/knowledge-search.js +++ b/mcp/dist/tools/knowledge-search.js @@ -4,6 +4,7 @@ import { embedTexts, cosineSimilarity } from './embeddings.js'; import { estimateTokens } from './egress-budget.js'; import { loadRegistry } from './doc-sources.js'; import { loadEdges, foldToCurrent, validAt } from './graph-store.js'; +import { parseAiBlock, stripAiBlock } from './ai-block.js'; const ACCESS_COUNTS_FILE = join(process.env.HOME ?? '', '.second-brain', 'access-counts.json'); const ACCESS_BOOST_FACTOR = 0.1; const ACCESS_BOOST_CAP = 10; @@ -198,7 +199,7 @@ export async function knowledgeSearch(args) { if (allDocs[i].source === 'local-doc') continue; const { doc, rawContent } = allDocs[i]; - if (AUTO_EXTRACTED_RE.test(rawContent) || doc.body.trim().length < MIN_SUBSTANTIVE_LENGTH) { + if (AUTO_EXTRACTED_RE.test(rawContent) || stripAiBlock(doc.body).trim().length < MIN_SUBSTANTIVE_LENGTH) { scored[i].score *= STUB_PENALTY; } } @@ -322,8 +323,11 @@ export function parseDoc(content, filePath) { doc.type = rel[wikiIdx + 1]; } } + doc.aiBlock = parseAiBlock(content) ?? undefined; if (doc.related.length === 0) { - const wikiLinks = doc.body.match(/\[\[([^\]]+)\]\]/g); + // Scrape body [[links]] for related: — but NOT links inside the ai-block (block values + // are plain slugs by convention; strip it so a stray bracket can't pollute related:). + const wikiLinks = stripAiBlock(doc.body).match(/\[\[([^\]]+)\]\]/g); if (wikiLinks) { doc.related = [...new Set(wikiLinks.map(l => l.slice(2, -2)))]; } diff --git a/mcp/dist/tools/knowledge-search.js.map b/mcp/dist/tools/knowledge-search.js.map index 837fa69..dc9327d 100644 --- a/mcp/dist/tools/knowledge-search.js.map +++ b/mcp/dist/tools/knowledge-search.js.map @@ -1 +1 @@ -{"version":3,"file":"knowledge-search.js","sourceRoot":"","sources":["../../src/tools/knowledge-search.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"knowledge-search.js","sourceRoot":"","sources":["../../src/tools/knowledge-search.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mcp/dist/tools/knowledge-search.test.js b/mcp/dist/tools/knowledge-search.test.js index 54fc48c..cf5950a 100644 --- a/mcp/dist/tools/knowledge-search.test.js +++ b/mcp/dist/tools/knowledge-search.test.js @@ -47,6 +47,35 @@ describe('knowledge_search multi-hop typed boost (graph present)', () => { expect(slugs(r)).not.toContain('beta'); }); }); +describe('stub penalty excludes the ai-block (prose-only length)', () => { + it('a short page padded only by a query-heavy ai-block is still penalized vs a real-prose page', async () => { + const dir = await fsp.mkdtemp(join(tmpdir(), 'ks-stub-')); + await fsp.mkdir(join(dir, 'wiki', 'learnings'), { recursive: true }); + const block = ['', 'claim: ' + 'wireguard handshake '.repeat(15), 'action: x', ''].join('\n'); + await fsp.writeFile(join(dir, 'wiki', 'learnings', 'blockpad.md'), `---\ntitle: bp\ntype: learnings\n---\n${block}\n\nshort.`); + await fsp.writeFile(join(dir, 'wiki', 'learnings', 'full.md'), `---\ntitle: full\ntype: learnings\n---\n# full\n` + 'wireguard handshake real prose detail. '.repeat(10)); + const r = await knowledgeSearch({ query: 'wireguard handshake', knowledgeDir: dir }); + const bp = r.candidates.find(c => c.path.endsWith('/blockpad.md')); + const full = r.candidates.find(c => c.path.endsWith('/full.md')); + expect(bp && full).toBeTruthy(); + expect(full.score).toBeGreaterThan(bp.score); // blockpad penalized (prose<100), full not + }); +}); +describe('parseDoc ai-block', () => { + it('exposes the parsed ai-block as doc.aiBlock', () => { + const md = ['---', 'title: A', 'type: learnings', '---', + '', 'claim: c', 'action: a', '', '', '# A', 'body'].join('\n'); + const doc = parseDoc(md, '/w/learnings/a.md'); + expect(doc.aiBlock?.claim).toBe('c'); + }); + it('does NOT scrape a [[link]] inside the ai-block into related:', () => { + const md = ['---', 'title: B', 'type: learnings', '---', + '', 'supersedes: [[ghost]]', 'claim: c', 'action: a', '', '', '# B', 'see [[real-page]]'].join('\n'); + const doc = parseDoc(md, '/w/learnings/b.md'); + expect(doc.related).toContain('real-page'); + expect(doc.related).not.toContain('ghost'); + }); +}); describe('parseDoc project facet', () => { it('extracts the project: facet from frontmatter', () => { const md = ['---', 'title: Kiri Core', 'type: decisions', 'project: kiri', '---', '# Kiri Core'].join('\n'); diff --git a/mcp/dist/tools/knowledge-search.test.js.map b/mcp/dist/tools/knowledge-search.test.js.map index 34e1e72..a2a68c4 100644 --- a/mcp/dist/tools/knowledge-search.test.js.map +++ b/mcp/dist/tools/knowledge-search.test.js.map @@ -1 +1 @@ -{"version":3,"file":"knowledge-search.test.js","sourceRoot":"","sources":["../../src/tools/knowledge-search.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"knowledge-search.test.js","sourceRoot":"","sources":["../../src/tools/knowledge-search.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mcp/dist/tools/knowledge-validate.bundle.js b/mcp/dist/tools/knowledge-validate.bundle.js index 9cbea7b..195960a 100644 --- a/mcp/dist/tools/knowledge-validate.bundle.js +++ b/mcp/dist/tools/knowledge-validate.bundle.js @@ -1,6 +1,6 @@ // src/tools/knowledge-validate.ts import { promises as fs } from "fs"; -import { join as join2, basename, relative } from "path"; +import { join as join2, basename, dirname, relative } from "path"; // src/tools/knowledge-search.ts import { join } from "path"; @@ -6066,6 +6066,43 @@ var glob = Object.assign(glob_, { }); glob.glob = glob; +// src/tools/ai-block.ts +var AI_BLOCK_RE = /\n?([\s\S]*?)/; +var AI_BLOCK_SCHEMAS = { + learnings: { fields: ["claim", "trigger", "action", "scope", "evidence", "supersedes"], required: ["claim", "action"] }, + decisions: { fields: ["context", "choice", "alternatives", "rationale", "status", "supersedes"], required: ["choice"] }, + entities: { fields: ["identity", "current_state", "depends_on", "owns", "status"], required: ["identity"] }, + issues: { fields: ["symptom", "cause", "fix", "severity", "status"], required: ["symptom", "status"] }, + concepts: { fields: ["problem", "solution", "where_applied", "tradeoffs"], required: ["problem", "solution"] }, + security: { fields: ["threat", "mitigation", "scope", "status"], required: ["threat", "mitigation"] } +}; +function parseAiBlock(content) { + const m = content.match(AI_BLOCK_RE); + if (!m) return null; + const out = {}; + let last = ""; + for (const raw of m[1].split("\n")) { + const line = raw.trimEnd(); + if (!line.trim()) continue; + const kv = line.match(/^([a-z_][a-z0-9_]*):\s*(.*)$/i); + if (kv) { + last = kv[1]; + out[last] = kv[2].trim(); + } else if (last) { + out[last] = (out[last] + " " + line.trim()).trim(); + } + } + return out; +} +function stripAiBlock(text) { + return text.replace(AI_BLOCK_RE, ""); +} +function validateAiBlock(type, block) { + const schema = AI_BLOCK_SCHEMAS[type]; + if (!schema) return []; + return schema.required.filter((f) => !block[f] || !block[f].trim()); +} + // src/tools/knowledge-search.ts var ACCESS_COUNTS_FILE = join(process.env.HOME ?? "", ".second-brain", "access-counts.json"); function parseDoc(content, filePath) { @@ -6107,8 +6144,9 @@ function parseDoc(content, filePath) { doc.type = rel[wikiIdx + 1]; } } + doc.aiBlock = parseAiBlock(content) ?? void 0; if (doc.related.length === 0) { - const wikiLinks = doc.body.match(/\[\[([^\]]+)\]\]/g); + const wikiLinks = stripAiBlock(doc.body).match(/\[\[([^\]]+)\]\]/g); if (wikiLinks) { doc.related = [...new Set(wikiLinks.map((l) => l.slice(2, -2)))]; } @@ -6168,6 +6206,17 @@ async function knowledgeValidate(knowledgeDir, opts = {}) { const slug = basename(filePath, ".md"); const doc = parseDoc(content, filePath); parsedDocs.push(doc); + const aiBlock = parseAiBlock(content); + if (aiBlock) { + const ptype = doc.type || basename(dirname(filePath)); + const missing = validateAiBlock(ptype, aiBlock); + if (missing.length) issues.push({ + type: "ai_block_incomplete", + severity: "warning", + path: filePath, + message: `ai-block missing required field(s) for type ${ptype}: ${missing.join(", ")}` + }); + } if (!/[/\\](projects|themes)[/\\]/.test(filePath)) { if (!slugMap.has(slug)) slugMap.set(slug, []); slugMap.get(slug).push(filePath); diff --git a/mcp/dist/tools/knowledge-validate.d.ts b/mcp/dist/tools/knowledge-validate.d.ts index 4888b01..a94eeb5 100644 --- a/mcp/dist/tools/knowledge-validate.d.ts +++ b/mcp/dist/tools/knowledge-validate.d.ts @@ -1,5 +1,5 @@ export interface ValidationIssue { - type: 'orphan_file' | 'broken_link' | 'missing_frontmatter' | 'duplicate_slug' | 'stale_page' | 'empty_page' | 'root_orphan'; + type: 'orphan_file' | 'broken_link' | 'missing_frontmatter' | 'duplicate_slug' | 'stale_page' | 'empty_page' | 'root_orphan' | 'ai_block_incomplete'; severity: 'error' | 'warning'; path: string; message: string; diff --git a/mcp/dist/tools/knowledge-validate.d.ts.map b/mcp/dist/tools/knowledge-validate.d.ts.map index b793a7b..13f9084 100644 --- a/mcp/dist/tools/knowledge-validate.d.ts.map +++ b/mcp/dist/tools/knowledge-validate.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"knowledge-validate.d.ts","sourceRoot":"","sources":["../../src/tools/knowledge-validate.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,aAAa,GAAG,aAAa,GAAG,qBAAqB,GAAG,gBAAgB,GAAG,YAAY,GAAG,YAAY,GAAG,aAAa,CAAC;IAC7H,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/B,OAAO,CAAC,gBAAgB,CAAC,CA0I3B;AAOD,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4DrF"} \ No newline at end of file +{"version":3,"file":"knowledge-validate.d.ts","sourceRoot":"","sources":["../../src/tools/knowledge-validate.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,aAAa,GAAG,aAAa,GAAG,qBAAqB,GAAG,gBAAgB,GAAG,YAAY,GAAG,YAAY,GAAG,aAAa,GAAG,qBAAqB,CAAC;IACrJ,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/B,OAAO,CAAC,gBAAgB,CAAC,CAsJ3B;AAOD,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4DrF"} \ No newline at end of file diff --git a/mcp/dist/tools/knowledge-validate.js b/mcp/dist/tools/knowledge-validate.js index f01ede2..fb792bb 100644 --- a/mcp/dist/tools/knowledge-validate.js +++ b/mcp/dist/tools/knowledge-validate.js @@ -1,6 +1,7 @@ import { promises as fs } from 'fs'; -import { join, basename, relative } from 'path'; +import { join, basename, dirname, relative } from 'path'; import { parseDoc } from './knowledge-search.js'; +import { parseAiBlock, validateAiBlock } from './ai-block.js'; export async function knowledgeValidate(knowledgeDir, opts = {}) { const wikiDir = join(knowledgeDir, 'wiki'); const issues = []; @@ -13,6 +14,18 @@ export async function knowledgeValidate(knowledgeDir, opts = {}) { const slug = basename(filePath, '.md'); const doc = parseDoc(content, filePath); parsedDocs.push(doc); + // AI-block schema check (gentle): only when a block exists — an absent block is fine + // (additive during migration). Missing required field for the page's type → a warning. + const aiBlock = parseAiBlock(content); + if (aiBlock) { + const ptype = doc.type || basename(dirname(filePath)); + const missing = validateAiBlock(ptype, aiBlock); + if (missing.length) + issues.push({ + type: 'ai_block_incomplete', severity: 'warning', path: filePath, + message: `ai-block missing required field(s) for type ${ptype}: ${missing.join(', ')}`, + }); + } // Generated MOC dirs (projects/, themes/) are derived VIEWS, not source pages — a MOC that // shares a slug with a real page (e.g. project "architecture-v1" + page architecture-v1.md) // is not a true duplicate, so exclude them from the duplicate_slug check. diff --git a/mcp/dist/tools/knowledge-validate.js.map b/mcp/dist/tools/knowledge-validate.js.map index 4173944..ee3905e 100644 --- a/mcp/dist/tools/knowledge-validate.js.map +++ b/mcp/dist/tools/knowledge-validate.js.map @@ -1 +1 @@ -{"version":3,"file":"knowledge-validate.js","sourceRoot":"","sources":["../../src/tools/knowledge-validate.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"knowledge-validate.js","sourceRoot":"","sources":["../../src/tools/knowledge-validate.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mcp/dist/tools/knowledge-validate.test.js b/mcp/dist/tools/knowledge-validate.test.js index 817a4b5..7a9977d 100644 --- a/mcp/dist/tools/knowledge-validate.test.js +++ b/mcp/dist/tools/knowledge-validate.test.js @@ -23,6 +23,24 @@ describe('addFrontmatter category typing', () => { await addFrontmatter(f, wiki); expect(await fs.readFile(f, 'utf-8')).toMatch(/^type: state$/m); }); + it('warns (not errors) when an ai-block is missing a required field for its type', async () => { + const dir = await fs.mkdtemp(join(tmpdir(), 'kv-ai-')); + const wiki = join(dir, 'wiki'); + await fs.mkdir(join(wiki, 'learnings'), { recursive: true }); + await fs.writeFile(join(wiki, 'learnings', 'l.md'), '---\ntitle: L\ntype: learnings\n---\n\nclaim: c\n\n# L\n'); + const res = await knowledgeValidate(dir, { autofix: false }); + const w = res.issues.find(i => i.type === 'ai_block_incomplete' && /action/.test(i.message)); + expect(w).toBeDefined(); + expect(w.severity).toBe('warning'); + }); + it('does not warn when the page has no ai-block (additive/optional during migration)', async () => { + const dir = await fs.mkdtemp(join(tmpdir(), 'kv-noai-')); + const wiki = join(dir, 'wiki'); + await fs.mkdir(join(wiki, 'learnings'), { recursive: true }); + await fs.writeFile(join(wiki, 'learnings', 'l.md'), '---\ntitle: L\ntype: learnings\n---\n# L\nprose\n'); + const res = await knowledgeValidate(dir, { autofix: false }); + expect(res.issues.find(i => i.type === 'ai_block_incomplete')).toBeUndefined(); + }); it('does NOT flag a generated project MOC sharing a slug with a real page as duplicate_slug (#3)', async () => { const dir = await fs.mkdtemp(join(tmpdir(), 'kv-collide-')); const wiki = join(dir, 'wiki'); diff --git a/mcp/dist/tools/knowledge-validate.test.js.map b/mcp/dist/tools/knowledge-validate.test.js.map index ac9a63e..886bbbc 100644 --- a/mcp/dist/tools/knowledge-validate.test.js.map +++ b/mcp/dist/tools/knowledge-validate.test.js.map @@ -1 +1 @@ -{"version":3,"file":"knowledge-validate.test.js","sourceRoot":"","sources":["../../src/tools/knowledge-validate.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5E,QAAQ,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC9C,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;QAClD,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,0BAA0B,CAAC,CAAC;QAElD,MAAM,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAE9B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAC1C,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAG,2BAA2B;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QACzC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC;QAEvC,MAAM,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAE9B,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8FAA8F,EAAE,KAAK,IAAI,EAAE;QAC5G,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC/B,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,yEAAyE;QACzE,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,oBAAoB,CAAC,EAAE,kDAAkD,CAAC,CAAC;QACtH,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,oBAAoB,CAAC,EAC7D,4FAA4F,CAAC,CAAC;QAChG,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACjH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC/B,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,gBAAgB,CAAC,EAAE,2CAA2C,CAAC,CAAC;QAC1G,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,CAAC,EAClD,mFAAmF,CAAC,CAAC;QACvF,MAAM,GAAG,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAC1G,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"knowledge-validate.test.js","sourceRoot":"","sources":["../../src/tools/knowledge-validate.test.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/mcp/src/server.ts b/mcp/src/server.ts index 0f1106a..7af5dcc 100644 --- a/mcp/src/server.ts +++ b/mcp/src/server.ts @@ -51,7 +51,7 @@ function resolveActiveSlug(): string | undefined { } const server = new McpServer( - { name: "knowledge-base", version: "2.4.1" }, + { name: "knowledge-base", version: "2.5.0" }, { capabilities: { logging: {} }, instructions: "BM25-scored search over the local knowledge base. Use knowledge_search to find relevant wiki pages (searches full content with field-weighted scoring), knowledge_reindex to regenerate the wiki index.md catalog (also runs validation with autofix), knowledge_validate to check wiki health (broken links, orphans, duplicates, session-narrative pages), knowledge_stats for an overview of wiki size and categories, pin_to_user to record a user-level preference, pin_to_project to append blockers/decisions to a project's PROJECT.md, and archive_to_wiki to graduate a [resolved] entry from a project file into the wiki. Dream tools: dream_create to start a background consolidation job (snapshots wiki + selects transcripts), dream_status to check progress, dream_list to see all dreams, dream_accept to apply a completed dream's changes, dream_discard to reject changes, and dream_cancel to stop a running dream. Episodic memory: episodic_search to search past conversation transcripts (hybrid vector + text, multi-concept AND), episodic_read to read a specific transcript section. Relational graph: knowledge_relate to assert/invalidate a typed bi-temporal relationship (requires|affects|relates|part_of|supersedes) between two pages, and knowledge_neighbors to walk a page's dependency neighbourhood (multi-hop, directional, point-in-time via as_of).", diff --git a/mcp/src/tools/ai-block.test.ts b/mcp/src/tools/ai-block.test.ts new file mode 100644 index 0000000..a04d488 --- /dev/null +++ b/mcp/src/tools/ai-block.test.ts @@ -0,0 +1,51 @@ +import { describe, it, expect } from 'vitest'; +import { parseAiBlock, stripAiBlock, validateAiBlock, AI_BLOCK_SCHEMAS } from './ai-block.js'; + +const page = [ + '---', 'title: awk', 'type: learnings', '---', + "", + 'claim: never interpolate shell vars into awk', + 'trigger: writing awk in a .sh', + 'action: pass via -v + numeric coercion', + 'scope: mawk (Pi default)', + '', '', '## Notes', 'mawk errors on empty interpolation. Period.', +].join('\n'); + +describe('ai-block', () => { + it('parses the flat key:value block into an object', () => { + const b = parseAiBlock(page)!; + expect(b.claim).toBe('never interpolate shell vars into awk'); + expect(b.action).toBe('pass via -v + numeric coercion'); + }); + it('returns null when there is no block', () => { + expect(parseAiBlock('---\ntitle: x\n---\n# x\nno block here')).toBeNull(); + }); + it('strips the block (for length/first-sentence counts)', () => { + const s = stripAiBlock(page); + expect(s).not.toContain('ai:begin'); + expect(s).not.toContain('claim:'); + expect(s).toContain('## Notes'); + }); + it('validateAiBlock reports missing REQUIRED fields for the type', () => { + expect(validateAiBlock('learnings', { claim: 'x' })).toEqual(['action']); + expect(validateAiBlock('learnings', { claim: 'x', action: 'y' })).toEqual([]); + expect(validateAiBlock('unknown-type', { foo: 'bar' })).toEqual([]); + }); + it('has schemas for the six structured types', () => { + for (const t of ['learnings', 'decisions', 'entities', 'issues', 'concepts', 'security']) + expect(AI_BLOCK_SCHEMAS[t].required.length).toBeGreaterThan(0); + }); + it('treats an UNTERMINATED ai:begin (no ai:end) as NOT a block (parse null, strip no-op)', () => { + const md = ['---', 'title: x', '---', '', 'claim: c', '', '# real prose continues forever'].join('\n'); + expect(parseAiBlock(md)).toBeNull(); + expect(stripAiBlock(md)).toBe(md); // must not eat the rest of the page + }); + it('keeps the begin-marker annotation on its own line (a stray > in the tail is fine)', () => { + const md = ['', 'claim: kept', 'action: a', ''].join('\n'); + expect(parseAiBlock(md)!.claim).toBe('kept'); + }); + it('folds a continuation line into the previous field value', () => { + const md = ['', 'claim: line one', ' continued', 'action: do it', ''].join('\n'); + expect(parseAiBlock(md)!.claim).toBe('line one continued'); + }); +}); diff --git a/mcp/src/tools/ai-block.ts b/mcp/src/tools/ai-block.ts new file mode 100644 index 0000000..9a85021 --- /dev/null +++ b/mcp/src/tools/ai-block.ts @@ -0,0 +1,52 @@ +// AI-native representation — the per-page machine-first "shared intermediate" block. +// A marked region holding flat YAML key:value +// fields (per-type schema). Pure module: parse / strip / validate. No I/O. +// Spec: docs/specs/2026-06-02-ai-native-knowledge-representation-design.md + +// The begin marker is a single HTML comment line (its annotation tail stays on that line, +// `[^\n]*?` — so a stray token can't fold the comment-tail into the parsed body). Requires a +// matching ai:end; an unterminated ai:begin is NOT a block (no match → parse null / strip no-op). +export const AI_BLOCK_RE = /\n?([\s\S]*?)/; + +export interface AiBlockSchema { fields: string[]; required: string[]; } + +// Per-type schemas (spec §4). `required` = the load-bearing fields a good page of that +// type should carry; missing ones are WARNINGS (gentle), never errors. +export const AI_BLOCK_SCHEMAS: Record = { + learnings: { fields: ['claim', 'trigger', 'action', 'scope', 'evidence', 'supersedes'], required: ['claim', 'action'] }, + decisions: { fields: ['context', 'choice', 'alternatives', 'rationale', 'status', 'supersedes'], required: ['choice'] }, + entities: { fields: ['identity', 'current_state', 'depends_on', 'owns', 'status'], required: ['identity'] }, + issues: { fields: ['symptom', 'cause', 'fix', 'severity', 'status'], required: ['symptom', 'status'] }, + concepts: { fields: ['problem', 'solution', 'where_applied', 'tradeoffs'], required: ['problem', 'solution'] }, + security: { fields: ['threat', 'mitigation', 'scope', 'status'], required: ['threat', 'mitigation'] }, +}; + +/** Parse the flat-YAML `key: value` body of the ai:begin…ai:end region into an object. + * A line not matching `key:` is folded (appended) into the previous field's value. + * Returns null when the page has no block. */ +export function parseAiBlock(content: string): Record | null { + const m = content.match(AI_BLOCK_RE); + if (!m) return null; + const out: Record = {}; + let last = ''; + for (const raw of m[1].split('\n')) { + const line = raw.trimEnd(); + if (!line.trim()) continue; + const kv = line.match(/^([a-z_][a-z0-9_]*):\s*(.*)$/i); + if (kv) { last = kv[1]; out[last] = kv[2].trim(); } + else if (last) { out[last] = (out[last] + ' ' + line.trim()).trim(); } + } + return out; +} + +/** Remove the ai:begin…ai:end region so length/first-sentence consumers ignore it. */ +export function stripAiBlock(text: string): string { + return text.replace(AI_BLOCK_RE, ''); +} + +/** Missing REQUIRED fields for the page type (empty when type unknown or all present). */ +export function validateAiBlock(type: string, block: Record): string[] { + const schema = AI_BLOCK_SCHEMAS[type]; + if (!schema) return []; + return schema.required.filter(f => !block[f] || !block[f].trim()); +} diff --git a/mcp/src/tools/knowledge-reindex.test.ts b/mcp/src/tools/knowledge-reindex.test.ts index a2b51f5..262d348 100644 --- a/mcp/src/tools/knowledge-reindex.test.ts +++ b/mcp/src/tools/knowledge-reindex.test.ts @@ -106,6 +106,33 @@ describe('reindex project MOCs', () => { } finally { if (prev === undefined) delete process.env.SB_MOC_MIN_MEMBERS; else process.env.SB_MOC_MIN_MEMBERS = prev; } }); + it('reindex/graph-projection preserves the ai-block byte-for-byte', async () => { + const kd = await fsp.mkdtemp(join(tmpdir(), 'ri-keep-')); + await fsp.mkdir(join(kd, 'wiki', 'decisions'), { recursive: true }); + const block = ['', 'choice: use X', 'status: active', ''].join('\n'); + await fsp.writeFile(join(kd, 'wiki', 'decisions', 'd.md'), `---\ntitle: D\ntype: decisions\nrelated: []\n---\n${block}\n\n# D\nbody [[other]]`); + await fsp.writeFile(join(kd, 'wiki', 'decisions', 'other.md'), `---\ntitle: O\ntype: decisions\n---\n# O\n`); + await appendEdge(join(kd, 'graph', 'edges.jsonl'), + { op: 'assert', from: 'd', to: 'other', type: 'requires', valid_from: '2026-05-01', recorded_at: '2026-05-01T00:00:00Z' }); + await knowledgeReindex(kd); // projects related: + ## Dependencies onto d.md + const after = await fsp.readFile(join(kd, 'wiki', 'decisions', 'd.md'), 'utf-8'); + expect(after).toContain(block); // the ai-block survives projection intact + expect(after).toMatch(/related: \[\[other\]\]/); // projection still happened (edge applied) + }); + + it('project-MOC member description ignores the ai-block (firstSentence strips it)', async () => { + const kd = await fsp.mkdtemp(join(tmpdir(), 'ri-ai-')); + await fsp.mkdir(join(kd, 'wiki', 'concepts'), { recursive: true }); + const body = ['', 'problem: BLOCKWORD should not surface', 'solution: x', '', '', 'Real prose sentence here.'].join('\n'); + await fsp.writeFile(join(kd, 'wiki', 'concepts', 'p.md'), `---\ntitle: P\ntype: concepts\nproject: demo\n---\n${body}`); + await fsp.writeFile(join(kd, 'wiki', 'concepts', 'q.md'), `---\ntitle: Q\ntype: concepts\nproject: demo\n---\n# Q\nprose`); + await fsp.writeFile(join(kd, 'wiki', 'concepts', 'r.md'), `---\ntitle: R\ntype: concepts\nproject: demo\n---\n# R\nprose`); + await knowledgeReindex(kd); + const moc = await fsp.readFile(join(kd, 'wiki', 'projects', 'demo.md'), 'utf-8'); + expect(moc).toContain('[[p]]'); + expect(moc).not.toContain('BLOCKWORD'); // member description must come from prose, not the block + }); + it('does not mangle a MOC whose project key is an edge endpoint (#2 idempotency)', async () => { const kd = await fsp.mkdtemp(join(tmpdir(), 'mangle-')); await page(kd, 'decisions', 'arch-a', 'arch'); diff --git a/mcp/src/tools/knowledge-reindex.ts b/mcp/src/tools/knowledge-reindex.ts index 3eb00d3..e77f5a7 100644 --- a/mcp/src/tools/knowledge-reindex.ts +++ b/mcp/src/tools/knowledge-reindex.ts @@ -4,6 +4,7 @@ import { parseDoc } from './knowledge-search.js'; import { knowledgeValidate, ValidationIssue } from './knowledge-validate.js'; import { projectGraphToPages } from './graph-project.js'; import { buildProjectMocs, MocInput } from './project-moc.js'; +import { stripAiBlock } from './ai-block.js'; export interface ReindexResult { pagesIndexed: number; @@ -106,7 +107,7 @@ export async function knowledgeReindex(knowledgeDir: string): Promise/g, '') // drop the generated projection block .replace(/^#.*\n/m, '') .trim(); diff --git a/mcp/src/tools/knowledge-search.test.ts b/mcp/src/tools/knowledge-search.test.ts index 15885c3..cbcee2d 100644 --- a/mcp/src/tools/knowledge-search.test.ts +++ b/mcp/src/tools/knowledge-search.test.ts @@ -55,6 +55,37 @@ describe('knowledge_search multi-hop typed boost (graph present)', () => { }); }); +describe('stub penalty excludes the ai-block (prose-only length)', () => { + it('a short page padded only by a query-heavy ai-block is still penalized vs a real-prose page', async () => { + const dir = await fsp.mkdtemp(join(tmpdir(), 'ks-stub-')); + await fsp.mkdir(join(dir, 'wiki', 'learnings'), { recursive: true }); + const block = ['', 'claim: ' + 'wireguard handshake '.repeat(15), 'action: x', ''].join('\n'); + await fsp.writeFile(join(dir, 'wiki', 'learnings', 'blockpad.md'), `---\ntitle: bp\ntype: learnings\n---\n${block}\n\nshort.`); + await fsp.writeFile(join(dir, 'wiki', 'learnings', 'full.md'), `---\ntitle: full\ntype: learnings\n---\n# full\n` + 'wireguard handshake real prose detail. '.repeat(10)); + const r = await knowledgeSearch({ query: 'wireguard handshake', knowledgeDir: dir }); + const bp = r.candidates.find(c => c.path.endsWith('/blockpad.md')); + const full = r.candidates.find(c => c.path.endsWith('/full.md')); + expect(bp && full).toBeTruthy(); + expect(full!.score).toBeGreaterThan(bp!.score); // blockpad penalized (prose<100), full not + }); +}); + +describe('parseDoc ai-block', () => { + it('exposes the parsed ai-block as doc.aiBlock', () => { + const md = ['---', 'title: A', 'type: learnings', '---', + '', 'claim: c', 'action: a', '', '', '# A', 'body'].join('\n'); + const doc = parseDoc(md, '/w/learnings/a.md'); + expect(doc.aiBlock?.claim).toBe('c'); + }); + it('does NOT scrape a [[link]] inside the ai-block into related:', () => { + const md = ['---', 'title: B', 'type: learnings', '---', + '', 'supersedes: [[ghost]]', 'claim: c', 'action: a', '', '', '# B', 'see [[real-page]]'].join('\n'); + const doc = parseDoc(md, '/w/learnings/b.md'); + expect(doc.related).toContain('real-page'); + expect(doc.related).not.toContain('ghost'); + }); +}); + describe('parseDoc project facet', () => { it('extracts the project: facet from frontmatter', () => { const md = ['---', 'title: Kiri Core', 'type: decisions', 'project: kiri', '---', '# Kiri Core'].join('\n'); diff --git a/mcp/src/tools/knowledge-search.ts b/mcp/src/tools/knowledge-search.ts index b039fab..11fbe25 100644 --- a/mcp/src/tools/knowledge-search.ts +++ b/mcp/src/tools/knowledge-search.ts @@ -4,6 +4,7 @@ import { embedTexts, cosineSimilarity } from './embeddings.js'; import { estimateTokens } from './egress-budget.js'; import { loadRegistry } from './doc-sources.js'; import { loadEdges, foldToCurrent, validAt, CurrentEdge } from './graph-store.js'; +import { parseAiBlock, stripAiBlock } from './ai-block.js'; export interface KnowledgeSearchArgs { query: string; scope?: string; knowledgeDir?: string; brainDir?: string; projectSlug?: string; } export interface KnowledgeSearchResult { candidates: { path: string; score: number; description: string; tokens: number; source: string }[]; } @@ -20,6 +21,7 @@ export interface ParsedDoc { created: string; project: string; area: string; + aiBlock?: Record; } interface AccessCounts { [slug: string]: { count: number; last_accessed: string } } @@ -210,7 +212,7 @@ export async function knowledgeSearch(args: KnowledgeSearchArgs): Promise l.slice(2, -2)))]; } diff --git a/mcp/src/tools/knowledge-validate.test.ts b/mcp/src/tools/knowledge-validate.test.ts index a504498..4b458aa 100644 --- a/mcp/src/tools/knowledge-validate.test.ts +++ b/mcp/src/tools/knowledge-validate.test.ts @@ -30,6 +30,26 @@ describe('addFrontmatter category typing', () => { expect(await fs.readFile(f, 'utf-8')).toMatch(/^type: state$/m); }); + it('warns (not errors) when an ai-block is missing a required field for its type', async () => { + const dir = await fs.mkdtemp(join(tmpdir(), 'kv-ai-')); + const wiki = join(dir, 'wiki'); + await fs.mkdir(join(wiki, 'learnings'), { recursive: true }); + await fs.writeFile(join(wiki, 'learnings', 'l.md'), + '---\ntitle: L\ntype: learnings\n---\n\nclaim: c\n\n# L\n'); + const res = await knowledgeValidate(dir, { autofix: false }); + const w = res.issues.find(i => i.type === 'ai_block_incomplete' && /action/.test(i.message)); + expect(w).toBeDefined(); + expect(w!.severity).toBe('warning'); + }); + it('does not warn when the page has no ai-block (additive/optional during migration)', async () => { + const dir = await fs.mkdtemp(join(tmpdir(), 'kv-noai-')); + const wiki = join(dir, 'wiki'); + await fs.mkdir(join(wiki, 'learnings'), { recursive: true }); + await fs.writeFile(join(wiki, 'learnings', 'l.md'), '---\ntitle: L\ntype: learnings\n---\n# L\nprose\n'); + const res = await knowledgeValidate(dir, { autofix: false }); + expect(res.issues.find(i => i.type === 'ai_block_incomplete')).toBeUndefined(); + }); + it('does NOT flag a generated project MOC sharing a slug with a real page as duplicate_slug (#3)', async () => { const dir = await fs.mkdtemp(join(tmpdir(), 'kv-collide-')); const wiki = join(dir, 'wiki'); diff --git a/mcp/src/tools/knowledge-validate.ts b/mcp/src/tools/knowledge-validate.ts index 834bb9d..b913685 100644 --- a/mcp/src/tools/knowledge-validate.ts +++ b/mcp/src/tools/knowledge-validate.ts @@ -1,9 +1,10 @@ import { promises as fs } from 'fs'; import { join, basename, dirname, relative } from 'path'; import { parseDoc, ParsedDoc } from './knowledge-search.js'; +import { parseAiBlock, validateAiBlock } from './ai-block.js'; export interface ValidationIssue { - type: 'orphan_file' | 'broken_link' | 'missing_frontmatter' | 'duplicate_slug' | 'stale_page' | 'empty_page' | 'root_orphan'; + type: 'orphan_file' | 'broken_link' | 'missing_frontmatter' | 'duplicate_slug' | 'stale_page' | 'empty_page' | 'root_orphan' | 'ai_block_incomplete'; severity: 'error' | 'warning'; path: string; message: string; @@ -34,6 +35,18 @@ export async function knowledgeValidate( const doc = parseDoc(content, filePath); parsedDocs.push(doc); + // AI-block schema check (gentle): only when a block exists — an absent block is fine + // (additive during migration). Missing required field for the page's type → a warning. + const aiBlock = parseAiBlock(content); + if (aiBlock) { + const ptype = doc.type || basename(dirname(filePath)); + const missing = validateAiBlock(ptype, aiBlock); + if (missing.length) issues.push({ + type: 'ai_block_incomplete', severity: 'warning', path: filePath, + message: `ai-block missing required field(s) for type ${ptype}: ${missing.join(', ')}`, + }); + } + // Generated MOC dirs (projects/, themes/) are derived VIEWS, not source pages — a MOC that // shares a slug with a real page (e.g. project "architecture-v1" + page architecture-v1.md) // is not a true duplicate, so exclude them from the duplicate_slug check. diff --git a/scripts/wiki-forget-score.sh b/scripts/wiki-forget-score.sh index 2c8461d..9a1e932 100755 --- a/scripts/wiki-forget-score.sh +++ b/scripts/wiki-forget-score.sh @@ -22,7 +22,20 @@ acount(){ local v; v=$( [ -s "$AC" ] && jq -r --arg s "$1" '(.[$s].count // .[$s find "$WIKI" -type f -name '*.md' ! -name 'index.md' -not -path '*/.*' | while read -r f; do slug=$(basename "$f" .md); cat=$(basename "$(dirname "$f")") - age=$(( (now - $(stat -c %Y "$f")) / 86400 )); body=$(wc -c < "$f") + age=$(( (now - $(stat -c %Y "$f")) / 86400 )) + # body byte-count is PROSE-ONLY: strip the authored ai-block so a uniform block can't lift + # every page over the stub floor (spec §5b). Only strip when a COMPLETE block exists (a + # closing ai:end is present) — an unterminated ai:begin is NOT a block, so it stays a raw + # byte-exact count (matches the TS stripAiBlock no-op; never eats a real page toward FORGET). + if grep -qE '' "$f"; then + body=$(awk ' + //) skip=0; next } + { print } + ' "$f" | wc -c) + else + body=$(wc -c < "$f") + fi inb=$(inbound "$slug"); acc=$(acount "$slug") # Pass values via -v + coerce to number (x=x+0) so an empty/sparse value can't produce a # mawk "syntax error at or near ;" (do NOT string-interpolate into the awk program). diff --git a/skills/upgrade/SKILL.md b/skills/upgrade/SKILL.md index 7ec4f8a..36c305c 100644 --- a/skills/upgrade/SKILL.md +++ b/skills/upgrade/SKILL.md @@ -35,6 +35,7 @@ Each migration is identified by its target version. Run only migrations whose ta | To version | Migration | Idempotent check | |---|---|---| | **vector-deps health** (re-runs every upgrade) | Smoke-import `@huggingface/transformers` from `$CLAUDE_PLUGIN_ROOT/mcp`. On failure, run `bash $CLAUDE_PLUGIN_ROOT/bin/install-vector-deps.sh`. **Why**: mcp bundles mark `@huggingface/transformers` as esbuild `--external` because its native binaries (`onnxruntime-node`, `sharp`) can't be statically packed. A plugin cache refresh ships `dist/` but does not touch `node_modules/`, so vector search silently degrades to text-only on every fresh install or cache wipe. Without this gate the user sees no error — just empty embeddings and degraded recall. Idempotent: the script is a no-op when the package and import smoke-check both succeed. | `cd "$CLAUDE_PLUGIN_ROOT/mcp" && node --input-type=module -e 'await import("@huggingface/transformers"); console.log("ok")' >/dev/null 2>&1` — if exit 0, skip. Otherwise run `bash "$CLAUDE_PLUGIN_ROOT/bin/install-vector-deps.sh"`; report the ~70MB network requirement before installing. | +| **0.24.0** | AI-native knowledge representation — **Phase 1** (design `docs/specs/2026-06-02-ai-native-knowledge-representation-design`, plan `docs/plans/2026-06-02-ai-native-representation-phase1`). Reframe: the KB is AI-to-AI, so prose forces every reader to re-derive structure. Phase 1 makes a per-page `` **structured block** (flat YAML `key: value`, the "shared intermediate") a *recognized, parsed, schema-validated, strip-safe* construct — the deterministic foundation. (a) new pure `mcp/src/tools/ai-block.ts` (parse + per-type schemas {learnings,decisions,entities,issues,concepts,security} + `validateAiBlock` + `stripAiBlock`); (b) `parseDoc` exposes `doc.aiBlock`, and the body-`[[link]]`→`related:` fallback strips the block (block values are plain slugs, never `[[links]]`); (c) every length/first-sentence consumer excludes the block — `firstSentence` (reindex), the FORGET `wc -c` + stub-floor (`wiki-forget-score.sh`), the search stub-penalty — so a uniform block can't skew FORGET scores or BM25; (d) `knowledge_validate` warns (gentle, not error) on a block missing a required field for its type. MCP server → 2.5.0. **Additive + back-compat:** no block ⇒ behaviour unchanged. **Authoring** (extractor at capture) is Phase 1b; **consumption** (search weight/return + session-load injection + a `knowledge_fetch` block tier) is Phase 2; dream/maintainer refresh + lint staleness + backfill are Phase 3. New tests: `ai-block.test.ts`, `test-wiki-forget-ai-block.sh`, + parseDoc/validate/reindex cases. | No precondition — bumping the marker is sufficient. Pages gain blocks lazily as they are (re)written; nothing to migrate. | | **0.23.1** | KB hierarchical organization — Phase 2 (maintainer/dream migrate old→new; skills now KNOW the structure). (a) `knowledge-maintainer` Phase 3 gains a **project-structure reconciliation** step: read `~/knowledge/graph/project-registry.jsonl`, run `kb-project-backfill.sh` for `part_of` trees (deterministic), and for unlabeled pages get a reproducible suggestion from new `scripts/kb-project-suggest.sh` (plurality of edge-neighbours' `project:` facets) — additive assign + log; **re-parenting stages**; closed vocabulary (never invent project keys, never tag generated `projects/`/`themes/` pages). (b) `dream-runner` + dream `SKILL.md` are **surface-only**: they know project MOCs exist + are excluded from clustering input, and surface ungrouped-project suggestions for the maintainer (never assign on the live path). (c) `knowledge-validate` broken-link check now **splits `[[target|alias]]`** before resolving (was a false-positive on every valid aliased link — same alias rule as the 0.22.4 graph-migrate fix). MCP server → 2.4.1. New guards: `tests/test-kb-project-suggest.sh`, `tests/test-kb-skill-awareness.sh`, validate alias-split test. Prompt/script + one MCP fix — no state migration. | No precondition — bumping the marker is sufficient. The 0.23.0 backfill + this reconciliation are how the live wiki migrates flat→hierarchical; the maintainer/dream now drive it automatically. (Junk dangling `migration:v1` edges, if any remain, are drained by the maintainer Phase 3 conflict/relate curation + a resolves guard.) | | **0.23.0** | Knowledge-base hierarchical organization — Phase 1 (design `docs/specs/2026-06-02-knowledge-base-hierarchical-organization-design`, plan `docs/plans/2026-06-02-kb-hierarchical-organization-phase1`). Fixes the flat-hub / scattered-project-notes problem **without moving any file**: hierarchy is a soft overlay projected from the edge log + a new optional `project:` (and `area:`) frontmatter facet. (a) `parseDoc` exposes the `project`/`area` facets. (b) `knowledge_reindex` deterministically projects one `wiki/projects/.md` **MOC** per project with ≥ `SB_MOC_MIN_MEMBERS` (default 3) members (grouped by type; FORGET-protected like `themes/`; `graph: exclude`), and rebuilds `index.md` as a thin **two-tier Home** (`## Maps of Content` → project/theme MOC links + `## Categories` → per-type counts with **plain-text** slug rows) marked `graph: exclude` so a markdown graph viewer never treats it as a 100-edge hub. Pure projection — a second reindex is byte-identical modulo the generated timestamp; `SB_KB_MOC=off` disables. (c) `projects` is a known category (validate + FORGET PROTECT arm). MCP server → 2.4.0. Additive + back-compat: with no `project:` facets and no `projects/` dir, `index.md` is the prior flat catalog. **Phases 2–3** (on-write facet preservation + `relates→part_of` promotion + maintainer plurality-vote; lint/drift enforcement) are separate future migrations. | No precondition — bumping the marker is sufficient. **Optional one-shot seed** (so existing pages group immediately): seed `~/knowledge/graph/project-registry.jsonl` with `{"anchor":"","project":""}` lines, then `bash "$CLAUDE_PLUGIN_ROOT/scripts/kb-project-backfill.sh"` — it walks `part_of` ancestry from each anchor and sets `project:` on members (idempotent, reversible: remove the `project:` line). Then `knowledge_reindex` to project the MOCs. Safe to skip — facets/MOCs simply accrue from new edits. | | **0.22.5** | Persona graph-capability awareness (read-only boundary preserved). The persona-as-collaborator protocol (`skills/using-second-brain/SKILL.md`) knew the **read** tools (`knowledge_search`/`episodic_search`/`knowledge_neighbors`) and the wingman graph-check, but never referenced `knowledge_relate`, so the persona-driven loop didn't close the loop on a relationship it confirmed mid-session. The wingman section now does — but as a **surface-only** step: when the work confirms (or retires) a typed relationship, the persona surfaces it once as a *suggested* `knowledge_relate` (confirmed/retired edges only, never speculative). It does **not** call the tool — edge curation stays owned by the three sanctioned writers (capture-time **extractor**, the user's manual `knowledge_relate`, the `knowledge-maintainer`), and the extractor records the relationship from the session transcript at Stop, so the graph still accrues **with no user interaction**. Deliberately keeps the persona a graph READER, not a 4th writer (the boundary `agents/dream-runner.md` enumerates). New `tests/test-persona-capability-awareness.sh` guards both halves: awareness of the capability AND the read-only `allowed-tools` boundary. Prompt/test-only — no state migration. | No precondition — bumping the marker is sufficient. | diff --git a/tests/test-wiki-forget-ai-block.sh b/tests/test-wiki-forget-ai-block.sh new file mode 100755 index 0000000..480c2b1 --- /dev/null +++ b/tests/test-wiki-forget-ai-block.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# The ai-block must be excluded from the FORGET body byte-count (wiki-forget-score.sh wc -c + +# the body<200 stub-floor gate). A page whose only "length" is a big ai-block must still hit +# the stub floor (spec §5b) — else uniform blocks silently lift every page's score. +set -u +ROOT="$(cd "$(dirname "$0")"/.. && pwd)"; SCORER="$ROOT/scripts/wiki-forget-score.sh" +TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT +fail(){ echo "FAIL: $1"; exit 1; }; pass(){ echo "PASS: $1"; } +command -v jq >/dev/null 2>&1 || fail "jq required" +export KNOWLEDGE_DIR="$TMP/knowledge"; export BRAIN_DIR="$TMP/.second-brain" +mkdir -p "$KNOWLEDGE_DIR/wiki/entities" "$BRAIN_DIR" + +# e: tiny prose ("hi") padded ONLY by a long ai-block → prose<200 → stub floor must apply +{ echo '---'; echo 'title: E'; echo 'type: entities'; echo '---' + echo '' + echo 'identity: long identity padding padding padding padding padding padding padding padding' + echo 'current_state: more padding padding padding padding padding padding padding padding pad' + echo '' + echo '# E'; echo 'hi'; } > "$KNOWLEDGE_DIR/wiki/entities/e.md" +# f: long real prose, no block → full 0.5 entity category +{ echo '---'; echo 'title: F'; echo 'type: entities'; echo '---'; echo '# F' + for i in $(seq 1 30); do echo "real prose line $i with enough content to comfortably exceed two hundred bytes"; done; } > "$KNOWLEDGE_DIR/wiki/entities/f.md" +# g: short prose + an UNTERMINATED ai:begin (no ai:end) — must NOT be stripped (raw byte-exact +# count), else the strip eats the page and demotes it toward FORGET (fail-open). Regression guard. +{ echo '---'; echo 'title: G'; echo 'type: entities'; echo '---' + echo '' + for i in $(seq 1 20); do echo "unterminated block line $i content content content content content"; done + echo '# G'; echo 'hi'; } > "$KNOWLEDGE_DIR/wiki/entities/g.md" + +OUT=$(bash "$SCORER" 2>/dev/null) || fail "scorer failed" +se=$(printf '%s\n' "$OUT" | awk -F'\t' '$2=="e"{print $1}') +sf=$(printf '%s\n' "$OUT" | awk -F'\t' '$2=="f"{print $1}') +sg=$(printf '%s\n' "$OUT" | awk -F'\t' '$2=="g"{print $1}') +[ -n "$se" ] && [ -n "$sf" ] && [ -n "$sg" ] || fail "missing scores (e='$se' f='$sf' g='$sg')" +awk -v a="$se" -v b="$sf" 'BEGIN{exit !(a+0 < b+0)}' \ + || fail "block-padded stub e=$se scored >= real-prose f=$sf — ai-block not excluded from wc -c" +pass "ai-block excluded from FORGET body byte-count (block-padded page still hits the stub floor)" +awk -v a="$sg" -v b="$sf" 'BEGIN{exit !(a+0 >= b+0)}' \ + || fail "unterminated-block page g=$sg demoted below real-prose f=$sf — strip ate the page (fail-open toward FORGET)" +pass "unterminated ai:begin is NOT stripped (raw count; never demotes a real page)" + +echo; echo "ALL PASS"