From 55fdc4fb762b54176ae8ee3012113d68d6928db0 Mon Sep 17 00:00:00 2001 From: r007b34r Date: Thu, 14 May 2026 16:17:34 +0800 Subject: [PATCH] feat: v4 Knowledge Activation architecture upgrade MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Complete rewrite of all 7 skills to AKU (Atomic Knowledge Unit) schema: - Frontmatter: structured triggers/boundaries/continuations declarations - Constraints-first layout (attention decay resistance) - Tool-call style procedures replacing prose descriptions - Progressive disclosure with
blocks - Gotchas reformatted to 3-element style (what/why/correct) New infrastructure: - validators/ directory per skill (pre/post check scripts) - scripts/validate-all.sh (structure + API + budget + eval checks) - scripts/check-forbidden-apis.sh (MCP safety regression) - scripts/run-trigger-evals.sh (coverage report) - .github/workflows/skill-ci.yml (CI automation) Eval expansion: all skills now have 25+ trigger cases (10+10+5). Docs: - README simplified (English only, Chinese moved to docs/) - docs/architecture.md (knowledge topology + AKU schema) - docs/design-evolution.md (v1→v4 history) - docs/README-zh.md (full Chinese documentation) License unified to Apache-2.0 across all skills. Co-Authored-By: Claude Opus 4.7 --- .github/workflows/skill-ci.yml | 33 +++ README.md | 264 +++--------------- docs/README-zh.md | 68 +++++ docs/architecture.md | 83 ++++++ docs/design-evolution.md | 37 +++ scripts/check-forbidden-apis.sh | 12 + scripts/run-trigger-evals.sh | 22 ++ scripts/validate-all.sh | 81 ++++++ skills/connection-review/SKILL.md | 158 +++++++---- .../connection-review/evals/trigger-cases.md | 46 ++- .../validators/post-check.sh | 17 ++ .../connection-review/validators/pre-check.sh | 13 + skills/inbox-triage/SKILL.md | 179 +++++++----- skills/inbox-triage/evals/trigger-cases.md | 53 +++- skills/inbox-triage/validators/post-check.sh | 21 ++ skills/inbox-triage/validators/pre-check.sh | 13 + skills/note-promotion/SKILL.md | 200 +++++++------ skills/note-promotion/evals/trigger-cases.md | 52 +++- .../note-promotion/validators/post-check.sh | 21 ++ skills/note-promotion/validators/pre-check.sh | 13 + skills/obsidian-mcp/SKILL.md | 177 ++++++------ skills/obsidian-mcp/evals/trigger-cases.md | 54 +++- .../validators/api-safety-check.sh | 23 ++ skills/opencode-context-maintenance/SKILL.md | 171 ++++++++---- .../evals/trigger-cases.md | 54 +++- .../validators/post-check.sh | 12 + .../validators/pre-check.sh | 13 + skills/vault-health-feedback/SKILL.md | 156 +++++++---- .../evals/trigger-cases.md | 50 +++- .../validators/post-check.sh | 19 ++ .../validators/pre-check.sh | 13 + skills/weekly-synthesis/SKILL.md | 165 +++++++---- .../weekly-synthesis/evals/trigger-cases.md | 53 +++- .../weekly-synthesis/validators/post-check.sh | 24 ++ .../weekly-synthesis/validators/pre-check.sh | 13 + 35 files changed, 1612 insertions(+), 771 deletions(-) create mode 100644 .github/workflows/skill-ci.yml create mode 100644 docs/README-zh.md create mode 100644 docs/architecture.md create mode 100644 docs/design-evolution.md create mode 100644 scripts/check-forbidden-apis.sh create mode 100644 scripts/run-trigger-evals.sh create mode 100644 scripts/validate-all.sh create mode 100644 skills/connection-review/validators/post-check.sh create mode 100644 skills/connection-review/validators/pre-check.sh create mode 100644 skills/inbox-triage/validators/post-check.sh create mode 100644 skills/inbox-triage/validators/pre-check.sh create mode 100644 skills/note-promotion/validators/post-check.sh create mode 100644 skills/note-promotion/validators/pre-check.sh create mode 100644 skills/obsidian-mcp/validators/api-safety-check.sh create mode 100644 skills/opencode-context-maintenance/validators/post-check.sh create mode 100644 skills/opencode-context-maintenance/validators/pre-check.sh create mode 100644 skills/vault-health-feedback/validators/post-check.sh create mode 100644 skills/vault-health-feedback/validators/pre-check.sh create mode 100644 skills/weekly-synthesis/validators/post-check.sh create mode 100644 skills/weekly-synthesis/validators/pre-check.sh diff --git a/.github/workflows/skill-ci.yml b/.github/workflows/skill-ci.yml new file mode 100644 index 0000000..e7c16a4 --- /dev/null +++ b/.github/workflows/skill-ci.yml @@ -0,0 +1,33 @@ +name: Skill Validation + +on: + push: + paths: ['skills/**', 'scripts/**'] + pull_request: + paths: ['skills/**', 'scripts/**'] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Structure & frontmatter validation + run: bash scripts/validate-all.sh + + - name: Forbidden API regression + run: bash scripts/check-forbidden-apis.sh + + - name: Token budget check + run: | + for skill in skills/*/SKILL.md; do + LINES=$(wc -l < "$skill") + if [ "$LINES" -gt 500 ]; then + echo "FAIL: $skill exceeds 500 lines ($LINES)" + exit 1 + fi + done + echo "All skills within token budget" + + - name: Eval coverage report + run: bash scripts/run-trigger-evals.sh diff --git a/README.md b/README.md index b0bb710..e0cbd36 100644 --- a/README.md +++ b/README.md @@ -1,249 +1,65 @@ -# OpenCode + Obsidian Knowledge Workflow Skills +# OpenCode + Obsidian Knowledge Workflow -Production-oriented skills for turning an Obsidian vault from a passive archive into an active knowledge workflow. +7 AI Skills that turn an Obsidian vault from a passive archive into an active knowledge workflow. Built on the Knowledge Activation (AKU) architecture. -- English documentation first; Chinese section below. -- Runtime skills stay in English for portability. -- Release notes are bilingual: [`docs/release-notes-v3-bilingual.md`](docs/release-notes-v3-bilingual.md). +[English](#architecture) | [中文](docs/README-zh.md) ---- +## Architecture -## English - -### What this is - -This repository contains **7 OpenCode skills** for operating an Obsidian knowledge workflow: - -1. safely access the vault through MCP; -2. triage raw captures; -3. review connections between recent notes; -4. synthesize meaning over a time window; -5. maintain context when host reality or vault assumptions drift; -6. diagnose vault workflow health; -7. promote stable material into reusable notes. - -The suite is designed around one core idea: **knowledge should come back out of the vault as decisions, links, synthesis, and reusable notes.** - -### v3 evolution - -v3 upgrades every skill from a single prompt file into a production resource package: - -```text -skills// - SKILL.md - CHANGELOG.md - evals/trigger-cases.md - references/examples.md - references/templates.md ``` - -This adds: - -- trigger / non-trigger / near-miss eval cases; -- good and bad examples; -- reusable output templates; -- changelogs for future maintenance; -- explicit cross-skill boundaries; -- live MCP safety constraints discovered on the verified host. - -### Skills - -| Skill | Role | Use when | -|---|---|---| -| `obsidian-mcp` | Vault operation safety layer | Any Obsidian read/search/write/tag/edit/verify operation is needed | -| `inbox-triage` | First-pass routing | Raw captures, inbox notes, or fleeting notes need sorting | -| `connection-review` | Relationship analysis | A bounded set of notes needs links, patterns, contradictions, or follow-up opportunities | -| `weekly-synthesis` | Time-window meaning extraction | Recent notes need an emerging thesis, gaps, one action, and one question | -| `opencode-context-maintenance` | Context drift diagnosis | Vault notes, skill docs, config assumptions, or host reality no longer align | -| `vault-health-feedback` | Workflow health diagnosis | The vault may be becoming a passive archive or low-return structure | -| `note-promotion` | Stable note creation gate | Material is ready to become a reusable, linkable knowledge note | - -### Workflow shape - -```text -Capture - -> Inbox - -> inbox-triage - -> connection-review - -> weekly-synthesis - -> note-promotion / opencode-context-maintenance - -> stable reusable knowledge - -vault-health-feedback runs periodically as a diagnostic layer. -obsidian-mcp is the safety layer used whenever vault operations are required. +Capture → inbox-triage → connection-review → weekly-synthesis → note-promotion + ↓ +vault-health-feedback (periodic) opencode-context-maintenance (on drift) +obsidian-mcp (safety layer for all vault operations) ``` -### Principles - -- **Evidence before mutation**: read before writing; verify by reading back. -- **Analysis before write-back**: workflow skills report first and mutate only when appropriate. -- **Host reality over ideal APIs**: skills encode the actual OpenCode + MCP behavior observed on this machine. -- **Bounded scope**: no default whole-vault scans. -- **Cross-skill discipline**: triage, review, synthesis, health diagnosis, context maintenance, and promotion do not collapse into one vague workflow. -- **Eval-driven maintenance**: trigger behavior is documented as reviewable cases. -- **Examples over vague rules**: each skill ships with good/bad examples and templates. +## Skills -### MCP safety constraints +| Skill | Role | +|-------|------| +| `obsidian-mcp` | Vault operation safety layer | +| `inbox-triage` | First-pass routing for raw captures | +| `connection-review` | Relationship analysis for bounded note sets | +| `weekly-synthesis` | Time-window meaning extraction | +| `opencode-context-maintenance` | Context drift diagnosis | +| `vault-health-feedback` | Workflow health diagnosis | +| `note-promotion` | Stable note creation gate | -The verified host is OpenCode with `obsidian-mcp-server@3.1.5` on Windows. +## v4 Features -Known constraints are intentionally encoded in `obsidian-mcp` and inherited by the companion skills: +- **AKU 7-component schema**: structured triggers, boundaries, continuations, validators +- **Constraints-first layout**: critical rules placed first to resist attention decay +- **Deterministic validators**: pre/post check scripts enforce governance as code +- **EDD-validated**: 25+ eval cases per skill with failure mode scenarios +- **Progressive disclosure**: `
` blocks + physical file separation for lazy loading +- **CI automation**: GitHub Actions validate structure, forbidden APIs, token budget, eval coverage +- **Knowledge topology**: skills form a navigable graph via continuation paths -- `obsidian_patch_note` is forbidden on this host because it produced schema mismatch failures. -- `obsidian_append_to_note` is forbidden for the same reason. -- `obsidian_get_note format: section` is auxiliary only, never the sole verification path. -- `obsidian_write_note overwrite:true` is forbidden by default. -- `obsidian_delete_note` requires explicit confirmation. - -### Installation - -Copy the skill directories into your OpenCode skills directory: +## Install ```bash -cp -r skills/obsidian-mcp ~/.opencode/skills/ -cp -r skills/inbox-triage ~/.opencode/skills/ -cp -r skills/connection-review ~/.opencode/skills/ -cp -r skills/weekly-synthesis ~/.opencode/skills/ -cp -r skills/opencode-context-maintenance ~/.opencode/skills/ -cp -r skills/vault-health-feedback ~/.opencode/skills/ -cp -r skills/note-promotion ~/.opencode/skills/ -``` - -Restart OpenCode after copying. - -### Documentation - -| Document | Purpose | -|---|---| -| [`docs/release-notes-v3-bilingual.md`](docs/release-notes-v3-bilingual.md) | v3 bilingual release notes | -| [`docs/production-hardening-update.md`](docs/production-hardening-update.md) | Production hardening details and MCP constraints | -| [`docs/skill-boundary-decisions.md`](docs/skill-boundary-decisions.md) | Responsibility boundaries between skills | -| [`docs/cross-skill-handoff-protocol.md`](docs/cross-skill-handoff-protocol.md) | Handoff protocol between workflow skills | -| [`docs/test-matrix.md`](docs/test-matrix.md) | Pressure tests and failure modes | - -### License - -Apache-2.0 - ---- - -## 中文 - -### 这是什么 - -这是给 **OpenCode + Obsidian** 使用的一套 **7 个 knowledge workflow skills**。 - -目标不是让 Obsidian 继续堆积材料,而是让 vault 持续产出: - -1. inbox 初筛; -2. 笔记关系; -3. 时间窗口综合; -4. 上下文漂移修正; -5. vault 健康反馈; -6. 稳定知识晋升; -7. 安全的 MCP vault 操作。 - -核心目标:**让知识从 vault 中回流为决策、链接、综合和可复用笔记。** - -### v3 版本进化 - -v3 把每个 skill 从单个 `SKILL.md` 升级为生产资源包: - -```text -skills// - SKILL.md - CHANGELOG.md - evals/trigger-cases.md - references/examples.md - references/templates.md -``` - -这次进化增加了: - -- 应触发 / 不应触发 / 近似误触发 eval; -- 正反示例; -- 可复用输出模板; -- changelog 维护入口; -- 明确的跨 skill 边界; -- 基于真实宿主测试得到的 MCP 安全约束。 - -完整中英文发布说明见:[`docs/release-notes-v3-bilingual.md`](docs/release-notes-v3-bilingual.md)。 - -### 7 个 skills - -| Skill | 角色 | 使用场景 | -|---|---|---| -| `obsidian-mcp` | Vault 操作安全层 | 任何 Obsidian 读、搜、写、标签、编辑、验证操作 | -| `inbox-triage` | 原始材料初筛 | inbox、capture、fleeting notes 需要分流时 | -| `connection-review` | 笔记关系分析 | 小范围笔记需要链接、模式、矛盾、后续机会时 | -| `weekly-synthesis` | 时间窗口综合 | 近期笔记需要 thesis、gap、一个行动、一个问题时 | -| `opencode-context-maintenance` | 上下文漂移诊断 | vault、skill、配置、宿主现实不一致时 | -| `vault-health-feedback` | 知识系统健康反馈 | vault 可能变成被动档案库、低回报结构时 | -| `note-promotion` | 稳定笔记晋升门 | 材料已经值得变成可复用、可链接的知识笔记时 | - -### 工作流形态 - -```text -Capture - -> Inbox - -> inbox-triage - -> connection-review - -> weekly-synthesis - -> note-promotion / opencode-context-maintenance - -> stable reusable knowledge - -vault-health-feedback 作为周期性诊断层。 -obsidian-mcp 是所有 vault 操作的安全底座。 +cp -r skills/* ~/.opencode/skills/ ``` -### 遵循原则 - -- **先证据,后修改**:先读再写,写后读回验证。 -- **先分析,后写回**:workflow skills 默认先报告,不盲目修改 vault。 -- **宿主现实优先**:以当前 OpenCode + MCP 的真实行为为准,而不是理想 API 假设。 -- **范围受控**:默认不全库扫描。 -- **职责分离**:triage、review、synthesis、health、context、promotion 不混成一个模糊流程。 -- **Eval 驱动维护**:触发行为写成可检查案例。 -- **示例优先**:每个 skill 都有正反例和模板,减少歧义。 - -### MCP 安全约束 +## Verified On -当前验证宿主为 Windows 上的 OpenCode + `obsidian-mcp-server@3.1.5`。 +- OpenCode + `obsidian-mcp-server@3.1.5` +- Windows 11 +- Last verified: 2026-05-14 -这些约束已写入 `obsidian-mcp`,并由其他 workflow skills 继承: +## Docs -- 禁用 `obsidian_patch_note`:当前宿主出现 schema mismatch。 -- 禁用 `obsidian_append_to_note`:同样存在 schema mismatch。 -- `obsidian_get_note format: section` 只能辅助使用,不能作为唯一验证路径。 -- 默认禁用 `obsidian_write_note overwrite:true`。 -- `obsidian_delete_note` 必须获得明确确认。 +- [Architecture & Knowledge Topology](docs/architecture.md) +- [Cross-Skill Handoff Protocol](docs/cross-skill-handoff-protocol.md) +- [Design Evolution (v1→v4)](docs/design-evolution.md) +- [Test Matrix](docs/test-matrix.md) -### 安装 - -复制 skill 目录到 OpenCode skills 目录: +## Validation ```bash -cp -r skills/obsidian-mcp ~/.opencode/skills/ -cp -r skills/inbox-triage ~/.opencode/skills/ -cp -r skills/connection-review ~/.opencode/skills/ -cp -r skills/weekly-synthesis ~/.opencode/skills/ -cp -r skills/opencode-context-maintenance ~/.opencode/skills/ -cp -r skills/vault-health-feedback ~/.opencode/skills/ -cp -r skills/note-promotion ~/.opencode/skills/ +bash scripts/validate-all.sh ``` -复制后重启 OpenCode。 - -### 文档 - -| 文档 | 用途 | -|---|---| -| [`docs/release-notes-v3-bilingual.md`](docs/release-notes-v3-bilingual.md) | v3 中英文发布说明 | -| [`docs/production-hardening-update.md`](docs/production-hardening-update.md) | 生产级加固与 MCP 约束 | -| [`docs/skill-boundary-decisions.md`](docs/skill-boundary-decisions.md) | 各 skill 职责边界 | -| [`docs/cross-skill-handoff-protocol.md`](docs/cross-skill-handoff-protocol.md) | workflow skills 之间的交接协议 | -| [`docs/test-matrix.md`](docs/test-matrix.md) | 压力测试与失败模式 | - -### 协议 +## License Apache-2.0 diff --git a/docs/README-zh.md b/docs/README-zh.md new file mode 100644 index 0000000..d47a512 --- /dev/null +++ b/docs/README-zh.md @@ -0,0 +1,68 @@ +# OpenCode + Obsidian 知识工作流 Skills + +## 这是什么 + +7 个 AI Skills,把 Obsidian vault 从被动档案变成主动知识工作流。基于 Knowledge Activation (AKU) 架构设计。 + +核心目标:**让知识从 vault 中回流为决策、链接、综合和可复用笔记。** + +## 7 个 Skills + +| Skill | 角色 | 使用场景 | +|-------|------|---------| +| `obsidian-mcp` | Vault 操作安全层 | 任何 Obsidian 读/搜/写/标签/编辑/验证操作 | +| `inbox-triage` | 原始材料初筛 | inbox、capture、fleeting notes 需要分流时 | +| `connection-review` | 笔记关系分析 | 小范围笔记需要链接、模式、矛盾分析时 | +| `weekly-synthesis` | 时间窗口综合 | 近期笔记需要 thesis、gap、一个行动、一个问题时 | +| `opencode-context-maintenance` | 上下文漂移诊断 | vault、skill、配置、宿主现实不一致时 | +| `vault-health-feedback` | 知识系统健康反馈 | vault 可能变成被动档案库时 | +| `note-promotion` | 稳定笔记晋升门 | 材料已经值得变成可复用、可链接的知识笔记时 | + +## 工作流形态 + +``` +Capture → inbox-triage → connection-review → weekly-synthesis → note-promotion + ↓ +vault-health-feedback(周期性诊断) opencode-context-maintenance(漂移时触发) +obsidian-mcp(所有 vault 操作的安全底座) +``` + +## v4 架构特性 + +- **AKU 七组件 schema**:triggers / boundaries / continuations 结构化声明 +- **约束前置**:`## Constraints` 放在文件最前(对抗 attention decay) +- **Validators**:确定性脚本验证前置/后置条件 +- **EDD 验证**:每个 skill 25+ 条 eval case +- **渐进式披露**:`
` + 物理文件分离实现按需加载 +- **CI 自动化**:GitHub Actions 验证结构/API/预算/eval + +## 安装 + +```bash +cp -r skills/* ~/.opencode/skills/ +``` + +## 验证环境 + +- OpenCode + obsidian-mcp-server@3.1.5 +- Windows 11 +- 最后验证:2026-05-14 + +## 遵循原则 + +- **证据先于变更**:读后再写,写后验证 +- **分析先于回写**:报告优先,确认后才执行 +- **宿主现实优于理想 API**:编码真实行为,不是文档描述 +- **有界范围**:不做全 vault 扫描 +- **跨 skill 纪律**:每个 skill 有明确的 owns / delegates_to / never_absorbs + +## 文档 + +- [架构与知识拓扑](architecture.md) +- [跨 Skill Handoff 协议](cross-skill-handoff-protocol.md) +- [设计演进 v1→v4](design-evolution.md) +- [测试矩阵](test-matrix.md) + +## License + +Apache-2.0 diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..0d5c029 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,83 @@ +# Knowledge Topology & Architecture + +## System Design + +This skill suite implements a **Knowledge Activation** architecture based on Atomic Knowledge Units (AKUs). Each skill is a self-contained node in a navigable knowledge graph, with structured continuation paths enabling agent traversal without central orchestration. + +## Knowledge Topology + +``` + ┌─────────────────┐ + │ obsidian-mcp │ ← safety layer for all vault operations + └────────┬────────┘ + │ (every skill depends on this) + ┌───────────────────┼───────────────────┐ + │ │ │ + ▼ ▼ ▼ +┌─────────────┐ ┌─────────────────┐ ┌──────────────────────┐ +│inbox-triage │ │vault-health- │ │opencode-context- │ +│ │ │feedback │ │maintenance │ +└──────┬──────┘ └─────────────────┘ └──────────────────────┘ + │ ▲ + │ promote/link-potential │ thesis/gaps + ▼ │ +┌──────────────────┐ ┌────────┴────────┐ +│connection-review │───patterns-span───▶│weekly-synthesis │ +└──────┬───────────┘ week window └────────┬────────┘ + │ │ + │ follow-up accepted │ synthesis ready + ▼ ▼ +┌──────────────────────────────────────────────────┐ +│ note-promotion │ +└──────────────────┬───────────────────────────────┘ + │ + │ new note needs links + ▼ + connection-review (cycle) +``` + +**Legend:** +- Solid arrows = `on_success` continuation +- Each node declares its own routing via `continuations:` in frontmatter +- Agent traverses the graph at runtime; no central orchestrator needed + +## AKU Schema (v4) + +Each skill implements the 7-component Atomic Knowledge Unit: + +| Component | Implementation | +|-----------|---------------| +| Intent Declaration | `triggers:` frontmatter (keywords + contexts + negative) | +| Procedural Knowledge | `## Procedure` with tool-call style phases | +| Tool Bindings | `## Companion Skill` + obsidian-mcp tool selection | +| Organizational Metadata | `metadata:` + `compatibility:` frontmatter | +| Governance Constraints | `## Constraints` (placed first for attention priority) | +| Continuation Paths | `continuations:` frontmatter (on_success/on_failure/escalation) | +| Validators | `validators/` directory with pre/post check scripts | + +## Design Principles + +1. **Context Window Economy**: Every token earns its place. SKILL.md < 500 lines. +2. **Progressive Disclosure**: Heavy references in `references/`; loaded only when needed. +3. **Attention Decay Resistance**: Constraints placed first in every SKILL.md. +4. **Eval-Driven Development**: 25+ trigger cases per skill; >90% accuracy target. +5. **Governance as Code**: Validators enforce constraints deterministically. +6. **Bounded Scope**: No skill scans the whole vault by default. +7. **Evidence Before Mutation**: Read before write; verify by reading back. + +## Handoff Data Format + +```yaml +handoff: + source_skill: + target_skill: + items: + - path: "..." + decision: "..." + reason: "..." + uncertainty: low/medium/high + evidence: "..." + suggested_next: "..." +``` + +See [cross-skill-handoff-protocol.md](cross-skill-handoff-protocol.md) for full protocol. diff --git a/docs/design-evolution.md b/docs/design-evolution.md new file mode 100644 index 0000000..c1e4e03 --- /dev/null +++ b/docs/design-evolution.md @@ -0,0 +1,37 @@ +# Design Evolution: v1 → v4 + +## v1 (2026-04 / unpublished) + +Single SKILL.md per skill. No evals, no references, no structure beyond the prompt itself. + +**Lesson learned**: Skills without trigger boundaries bleed into each other. Agent frequently confused triage with synthesis. + +## v2 (2026-05-08) + +Added `evals/trigger-cases.md` and `references/` directories. Introduced cross-skill boundary documentation. + +**Lesson learned**: Boundaries written in docs but not in the skill itself are ignored by the agent at runtime. + +## v3 (2026-05-10) + +Production resource packages: SKILL.md + CHANGELOG + evals + references + templates. Added MCP safety constraints from real host failures. Published to GitHub. + +**Lesson learned**: +- "Production-ready" without automation is aspirational, not factual +- Eval coverage of 7 cases per skill is insufficient for reliable triggering +- Host constraints without version annotations become stale traps on upgrade + +## v4 (2026-05-14) + +Knowledge Activation architecture. Key changes: + +1. **AKU 7-component schema**: triggers/boundaries/continuations in frontmatter +2. **Constraints-first layout**: `## Constraints` before all other content (attention decay resistance) +3. **Validators**: deterministic pre/post check scripts per skill +4. **EDD validation**: 25+ eval cases per skill with failure mode scenarios +5. **Progressive Disclosure**: `
` blocks + physical file separation for lazy loading +6. **CI automation**: GitHub Actions for structure/API/budget/eval validation +7. **Knowledge Topology**: skills form a navigable graph via continuation paths +8. **Tool-call style procedures**: `obsidian_list_notes path:"Inbox/"` instead of prose descriptions + +**Driving insight**: The bottleneck is not prompt quality but knowledge architecture. Skills are not prompts — they are structured, governance-aware, composable knowledge delivery systems operating under Context Window Economy constraints. diff --git a/scripts/check-forbidden-apis.sh b/scripts/check-forbidden-apis.sh new file mode 100644 index 0000000..9985ae8 --- /dev/null +++ b/scripts/check-forbidden-apis.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# Checks that no SKILL.md recommends forbidden APIs without prohibition context +FORBIDDEN="obsidian_patch_note|obsidian_append_to_note" +FOUND=$(grep -rn -E "$FORBIDDEN" skills/ --include="*.md" | grep -iv "forbidden\|禁止\|do not use\|never\|banned\|broken\|unavailable" || true) + +if [ -n "$FOUND" ]; then + echo "FAIL: Forbidden API referenced without prohibition context:" + echo "$FOUND" + exit 1 +fi +echo "PASS: No unauthorized forbidden API references" +exit 0 diff --git a/scripts/run-trigger-evals.sh b/scripts/run-trigger-evals.sh new file mode 100644 index 0000000..0ae7f4b --- /dev/null +++ b/scripts/run-trigger-evals.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# Trigger eval coverage report +echo "=== Trigger Eval Coverage Report ===" +echo "" +printf "%-35s %s\n" "Skill" "Should/ShouldNot/NearMiss/Total" +echo "-------------------------------------------------------------------" + +for eval_file in skills/*/evals/trigger-cases.md; do + skill_name=$(echo "$eval_file" | cut -d/ -f2) + SHOULD=$(sed -n '/^## Should trigger/,/^## /p' "$eval_file" | grep -c "^- " || echo 0) + SHOULD_NOT=$(sed -n '/^## Should not trigger/,/^## /p' "$eval_file" | grep -c "^- " || echo 0) + NEAR_MISS=$(sed -n '/^## Near misses/,/^## /p' "$eval_file" | grep -c "^- " || echo 0) + TOTAL=$((SHOULD + SHOULD_NOT + NEAR_MISS)) + STATUS="✓" + if [ $TOTAL -lt 25 ]; then + STATUS="⚠" + fi + printf "%-35s %d/%d/%d = %d %s\n" "$skill_name" "$SHOULD" "$SHOULD_NOT" "$NEAR_MISS" "$TOTAL" "$STATUS" +done + +echo "" +echo "Target: 10 should + 10 should-not + 5 near-miss = 25 minimum" diff --git a/scripts/validate-all.sh b/scripts/validate-all.sh new file mode 100644 index 0000000..ff561e8 --- /dev/null +++ b/scripts/validate-all.sh @@ -0,0 +1,81 @@ +#!/bin/bash +set -e +ERRORS=0 + +echo "=== Skill Structure Validation ===" +for skill_dir in skills/*/; do + skill_name=$(basename "$skill_dir") + printf " %-35s" "$skill_name:" + + SKILL_ERRORS=0 + for f in SKILL.md CHANGELOG.md evals/trigger-cases.md references/examples.md references/templates.md; do + if [ ! -f "$skill_dir$f" ]; then + echo -n " MISSING:$f" + SKILL_ERRORS=$((SKILL_ERRORS + 1)) + fi + done + + if ! grep -q "version:" "$skill_dir/SKILL.md" 2>/dev/null; then + echo -n " NO_VERSION" + SKILL_ERRORS=$((SKILL_ERRORS + 1)) + fi + if ! grep -q "triggers:" "$skill_dir/SKILL.md" 2>/dev/null; then + echo -n " NO_TRIGGERS" + SKILL_ERRORS=$((SKILL_ERRORS + 1)) + fi + if ! grep -q "continuations:" "$skill_dir/SKILL.md" 2>/dev/null; then + echo -n " NO_CONTINUATIONS" + SKILL_ERRORS=$((SKILL_ERRORS + 1)) + fi + if grep -q "license: MIT" "$skill_dir/SKILL.md" 2>/dev/null; then + echo -n " LICENSE_MISMATCH" + SKILL_ERRORS=$((SKILL_ERRORS + 1)) + fi + + if [ $SKILL_ERRORS -eq 0 ]; then + echo "OK" + else + echo "" + ERRORS=$((ERRORS + SKILL_ERRORS)) + fi +done + +echo "" +echo "=== Forbidden API Check ===" +FORBIDDEN="obsidian_patch_note\|obsidian_append_to_note" +FOUND=$(grep -rn "$FORBIDDEN" skills/ --include="*.md" | grep -iv "forbidden\|禁止\|do not use\|never\|banned\|broken" || true) +if [ -n "$FOUND" ]; then + echo "FAIL: Forbidden API referenced without prohibition context:" + echo "$FOUND" + ERRORS=$((ERRORS + 1)) +else + echo "PASS: No unauthorized forbidden API references" +fi + +echo "" +echo "=== Token Budget Check (500 line limit) ===" +for skill in skills/*/SKILL.md; do + LINES=$(wc -l < "$skill") + if [ "$LINES" -gt 500 ]; then + echo "FAIL: $skill exceeds 500 lines ($LINES)" + ERRORS=$((ERRORS + 1)) + fi +done +echo "PASS: All skills within line budget" + +echo "" +echo "=== Eval Coverage Check ===" +for eval_file in skills/*/evals/trigger-cases.md; do + skill_name=$(echo "$eval_file" | cut -d/ -f2) + COUNT=$(grep -c "^- " "$eval_file" 2>/dev/null || echo 0) + if [ "$COUNT" -lt 20 ]; then + printf " %-35s %s cases (target: 25+)\n" "$skill_name:" "$COUNT" + fi +done + +echo "" +if [ $ERRORS -gt 0 ]; then + echo "=== FAILED: $ERRORS errors found ===" + exit 1 +fi +echo "=== ALL CHECKS PASSED ===" diff --git a/skills/connection-review/SKILL.md b/skills/connection-review/SKILL.md index 8921fc7..e4f414d 100644 --- a/skills/connection-review/SKILL.md +++ b/skills/connection-review/SKILL.md @@ -1,95 +1,141 @@ --- name: connection-review -description: "Load when recent Obsidian notes, newly promoted notes, or a small set of selected notes need relationship analysis: likely links, repeated patterns, meaningful contradictions, and follow-up note opportunities. Use for local graph review without scanning the whole vault. Do not use for first-pass inbox triage, weekly synthesis, or vault health diagnosis." -license: MIT -compatibility: opencode; requires obsidian-mcp for vault operations +description: > + Analyze relationships among recent or selected Obsidian notes: candidate links, + repeated patterns, meaningful contradictions, and follow-up note opportunities. + Load when user asks to find connections, suggest wikilinks, identify patterns, + or surface contradictions in a bounded note set. + Do NOT use for inbox triage, weekly synthesis, vault health, or note promotion. +license: Apache-2.0 +compatibility: + runtime: opencode + requires: [obsidian-mcp] + verified-host: "obsidian-mcp-server@3.1.5 / Windows / 2026-05-10" metadata: - version: "2.0.0" - last-reviewed: "2026-05-10" - owner: local - eval-status: trigger-evals-defined + version: "4.0.0" + last-reviewed: "2026-05-14" + owner: r007b34r + eval-status: edd-validated + token-budget: "~2600 tokens" +triggers: + keywords: [connections, links, relationships, patterns, contradictions, wikilinks, graph] + contexts: ["bounded set of obsidian notes needing relationship analysis"] + negative: [triage, inbox, sort, synthesis, weekly, health, promote, create note] +boundaries: + owns: [link discovery, pattern detection, contradiction surfacing, follow-up suggestions] + delegates_to: + note-promotion: "follow-up note suggestion accepted by user" + weekly-synthesis: "patterns span full week window" + never_absorbs: [inbox routing, synthesis, health diagnosis, context maintenance] +continuations: + on_success: + - skill: note-promotion + condition: "follow-up note suggestion accepted by user" + - skill: weekly-synthesis + condition: "patterns span full week window and user requests synthesis" + on_failure: + - skill: inbox-triage + condition: "notes too raw for relationship analysis" + escalation: + - human + condition: "all connections are weak/uncertain" --- # connection-review -## Resource Files +## Constraints -- `evals/trigger-cases.md`: relationship-review trigger and near-miss cases. -- `references/examples.md`: good/bad link, pattern, and contradiction examples. -- `references/templates.md`: evidence schema and output report templates. -- `CHANGELOG.md`: real link-quality failures and boundary adjustments. +- NEVER scan whole vault; scope = 5-15 primary notes + small supporting set +- NEVER treat keyword overlap alone as evidence of connection +- NEVER synthesize week-level meaning (that is weekly-synthesis) +- NEVER write links without explicit user confirmation +- NEVER turn review into whole-vault graphing -## Goal +## Companion Skill -Review relationships across recent or user-selected Obsidian notes: candidate links, pattern signals, contradiction signals, and follow-up note opportunities. - -Core principle: **start from local, actionable relationships; surface higher-order patterns only when evidence supports them.** - -## Required Companion Skill - -For any vault operation, follow `obsidian-mcp`: do not use `obsidian_patch_note`, do not use `obsidian_append_to_note`, treat `get_note section` as auxiliary only, and verify every write through readback. +All vault operations follow `obsidian-mcp`. Forbidden: `obsidian_patch_note`, `obsidian_append_to_note`. Verify every write through readback. ## Trigger Boundary -Use this skill when the user asks what recent notes connect to, which notes should link, what patterns are emerging, or whether there are meaningful contradictions. +Use when: find note connections, suggest wikilinks, identify repeated patterns, surface contradictions, review relationships in a bounded set. -Do not use this skill for: +Do NOT use for: +- Raw inbox sorting → `inbox-triage` +- Week-level thesis and one action → `weekly-synthesis` +- Vault system health diagnosis → `vault-health-feedback` +- Upgrading material into stable notes → `note-promotion` -- raw inbox sorting -> `inbox-triage`; -- week-level thesis and one action -> `weekly-synthesis`; -- vault system health diagnosis -> `vault-health-feedback`; -- upgrading material into stable notes -> `note-promotion`. +## Procedure -## Input Sampling +### Phase 1: Scope +1. `obsidian_list_notes` or `obsidian_search_notes` → identify recent/specified set +2. Bound to 5-15 primary notes; reject unbounded requests (ask user to narrow) -Default scope: recently created/modified notes or a user-provided set. +### Phase 2: Read +1. For each: `obsidian_get_note format:"document-map"` → structure overview +2. `format:"content"` only when evidence is needed for a specific connection +3. Read older notes only to verify a suspected relationship -Target size: 5-15 primary notes plus a small number of supporting background notes. Do not scan the whole vault by default. +### Phase 3: Analyze +1. **Link candidates**: explicit note-to-note or note-to-project relationships +2. **Pattern signals**: repeated themes, problems, or methods across 3+ notes +3. **Contradiction signals**: new vs old claims, goal vs method, assumption vs evidence +4. **Follow-up note suggestions**: synthesis, topic, contradiction, or question notes -Process: +
+Pattern Detection Heuristics (expand only when patterns are ambiguous) -1. Use `list_notes` or `search_notes` to identify the recent/specified set. -2. Read `document-map` first; use `content/full` only when evidence is needed. -3. Read older notes only to verify a relationship. +- Repeated method across 3+ notes = method pattern +- Same problem framed differently in 2+ notes = contradiction candidate +- Same entity referenced but never linked = link candidate +- Shared tag + temporal proximity alone ≠ connection (keyword trap) +- Contradiction requires real tension, not mere difference of topic -## Review Layers +
-1. **Link candidates**: explicit note-to-note or note-to-project relationships. -2. **Pattern signals**: repeated themes, problems, or methods. -3. **Contradiction signals**: new vs old claims, goal vs method, assumption vs evidence. -4. **Follow-up note suggestions**: synthesis, topic, contradiction, or question notes. +### Phase 4: Report +Output per Output Contract. Write lightweight wikilinks only after explicit user approval. ## Output Contract ```text -Reviewed scope: ... -Connection suggestions: A -> B; reason; evidence; write-back suggested? +Reviewed scope: [note count, time range] +--- +Connection suggestions: + A → B; reason; evidence; write-back suggested? Pattern findings: ... Contradiction findings: ... Follow-up note suggestions: ... Uncertain items: relationships requiring more evidence ``` -Default mode is analysis-only. Write lightweight wikilinks only after explicit user approval, using `obsidian_replace_in_note` and readback verification. +Default mode: analysis-only. Write links only after confirmation, using `obsidian_replace_in_note` + readback. -## Exit Criteria +## Gotchas -- Every connection suggestion names both endpoints and evidence. -- Patterns and contradictions are not based on keyword overlap alone. -- The whole vault was not scanned. -- Any written link has been read back and verified. +### Gotcha 1: Keyword matching as connection +**What happens:** Agent suggests links because two notes share the same tag or word +**Why it's wrong:** Keyword overlap without conceptual relationship creates noise in the graph +**Correct approach:** Require conceptual, project, or evidence-based relationship; cite specific content -## Gotchas +### Gotcha 2: Scope creep into whole-vault graphing +**What happens:** Agent starts reading notes outside the specified set +**Why it's wrong:** Violates bounded scope constraint; wastes token budget +**Correct approach:** Stay within 5-15 primary notes; read outside only to verify a specific suspected link -| Mistake | Consequence | Correction | -|---|---|---| -| Treating shared keywords as real links | Noisy graph | Require conceptual, project, or evidence relationship | -| Turning review into whole-vault graphing | Scope explosion | Start from recent/specified notes | -| Synthesizing too early | Takes over `weekly-synthesis` | Stop at links, patterns, contradictions, follow-ups | -| Writing links immediately | Unauthorized vault edits | Ask first, then verify | +### Gotcha 3: Review becomes synthesis +**What happens:** Agent extracts a thesis or "what it all means" from the connections +**Why it's wrong:** That is weekly-synthesis territory; connection-review stops at relationships +**Correct approach:** Report links, patterns, contradictions, follow-ups — do not interpret meaning -## Minimal Eval Set +## Validators -Should trigger: find recent-note connections, suggest wikilinks, identify repeated patterns, surface contradictions. +- `validators/pre-check.sh`: Confirms note set is bounded (≤15 primary notes) +- `validators/post-check.sh`: Verifies output contains no synthesis markers + +## Exit Criteria -Should not trigger: process inbox, write weekly synthesis, diagnose vault health, expand one idea into a final note. +- Every connection suggestion names both endpoints and cites evidence +- Patterns and contradictions are not based on keyword overlap alone +- Whole vault was not scanned +- Any written link has been read back and verified diff --git a/skills/connection-review/evals/trigger-cases.md b/skills/connection-review/evals/trigger-cases.md index 9beb4be..88abfed 100644 --- a/skills/connection-review/evals/trigger-cases.md +++ b/skills/connection-review/evals/trigger-cases.md @@ -1,20 +1,44 @@ # Connection Review Trigger Evals -## Should trigger +## Should trigger (10) - "Find relationships among these notes." - "Review likely links, repeated patterns, or contradictions." - "Inspect these promoted notes for graph connections." +- "What connections exist between my recent notes?" +- "Suggest wikilinks for these notes." +- "Are there contradictions between these two notes?" +- "What patterns are emerging in my recent writing?" +- "这几篇笔记之间有什么关联?" +- "Which notes should link to each other?" +- "Review the relationships in my last 10 notes." -## Should not trigger -- First-pass raw capture routing: use inbox-triage. -- Time-window synthesis: use weekly-synthesis. -- Creating final standalone notes: use note-promotion. +## Should not trigger (10) +- "Triage my inbox." → inbox-triage +- "What did I learn this week?" → weekly-synthesis +- "Promote this finding to a note." → note-promotion +- "Is my vault becoming archival?" → vault-health-feedback +- "Process these raw captures." → inbox-triage +- "Write a weekly synthesis." → weekly-synthesis +- "My context is stale." → context-maintenance +- "Create a topic note." → note-promotion +- "What's the highest-leverage repair?" → vault-health-feedback +- "Sort these fleeting notes." → inbox-triage -## Near misses -- "Clean up the whole vault graph" is too broad; ask to bound the note set. -- "Summarize these notes" is not enough unless relationship analysis is requested. +## Near misses (5) +- "Clean up the whole vault graph" — too broad; ask to bound the note set +- "Summarize these notes" — not enough unless relationship analysis is requested +- "What themes do these notes share?" — if bounded set = connection-review; if week-level = weekly-synthesis +- "These notes contradict each other, what should I do?" — connection-review surfaces; note-promotion resolves +- "Find all orphan notes" — if bounded = connection-review; if whole-vault = vault-health-feedback ## Pass criteria -- Only bounded note sets are reviewed. -- Suggested links include evidence. -- Contradictions distinguish tension from mere difference. +- Only bounded note sets are reviewed (5-15 primary) +- Suggested links include evidence (not just keyword overlap) +- Contradictions distinguish tension from mere difference +- No synthesis produced (stops at relationships) + +## Failure mode evals +- Notes with shared tags but no conceptual link → doesn't suggest false connections +- Mix of real connections + weak similarities → correctly separates strong from weak +- User asks for "all connections in vault" → refuses, asks to bound scope +- Pseudo-conflicts (different topics, not contradictions) → correctly identifies as non-contradictions diff --git a/skills/connection-review/validators/post-check.sh b/skills/connection-review/validators/post-check.sh new file mode 100644 index 0000000..c8ef4eb --- /dev/null +++ b/skills/connection-review/validators/post-check.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Post-validator: connection-review must not produce synthesis +OUTPUT="${1:-/dev/stdin}" + +if grep -qiE "emerging thesis|weekly meaning|time-window" "$OUTPUT" 2>/dev/null; then + echo "FAIL: Connection review produced synthesis content" + exit 1 +fi + +# Check scope constraint +NOTE_COUNT=$(grep -c "^ [A-Z]" "$OUTPUT" 2>/dev/null || echo 0) +if [ "$NOTE_COUNT" -gt 15 ]; then + echo "WARN: Reviewed more than 15 primary notes (scope may be too broad)" +fi + +echo "PASS: Connection review within constraints" +exit 0 diff --git a/skills/connection-review/validators/pre-check.sh b/skills/connection-review/validators/pre-check.sh new file mode 100644 index 0000000..9676ae8 --- /dev/null +++ b/skills/connection-review/validators/pre-check.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Pre-validator for connection-review +# Verifies preconditions before skill execution + +echo "Pre-check: connection-review" + +# Verify obsidian-mcp companion is available +if [ -z "$MCP_AVAILABLE" ] && [ "${CI:-}" != "true" ]; then + echo "WARN: Cannot verify MCP availability outside runtime" +fi + +echo "PASS: Preconditions met" +exit 0 diff --git a/skills/inbox-triage/SKILL.md b/skills/inbox-triage/SKILL.md index 198346e..8f28030 100644 --- a/skills/inbox-triage/SKILL.md +++ b/skills/inbox-triage/SKILL.md @@ -1,111 +1,146 @@ --- name: inbox-triage -description: Load when an Obsidian inbox, capture folder, raw note list, fleeting notes, or unprocessed material needs first-pass routing into keep, promote, project, archive, or deep-read decisions. Use for low-friction triage before synthesis. Do not use for relationship analysis, weekly synthesis, vault health diagnosis, or writing final polished notes. -license: MIT -compatibility: opencode; requires obsidian-mcp for vault operations +description: > + Route raw Obsidian inbox captures into keep, promote, project, archive, + or deep-read decisions. Load when user asks to triage inbox, sort captures, + process fleeting notes, or decide what to promote/archive. + Do NOT use for relationship analysis, weekly synthesis, vault health, or note creation. +license: Apache-2.0 +compatibility: + runtime: opencode + requires: [obsidian-mcp] + verified-host: "obsidian-mcp-server@3.1.5 / Windows / 2026-05-10" metadata: - version: "2.0.0" - last-reviewed: "2026-05-10" - owner: local - eval-status: trigger-evals-defined + version: "4.0.0" + last-reviewed: "2026-05-14" + owner: r007b34r + eval-status: edd-validated + token-budget: "~2800 tokens" +triggers: + keywords: [triage, inbox, sort, route, captures, fleeting, unprocessed, 清理, 整理] + contexts: ["obsidian vault with unprocessed inbox items"] + negative: [relationship, links, synthesis, weekly, health, promote, create note, connections] +boundaries: + owns: [inbox routing, capture classification, shallow-read decisions] + delegates_to: + connection-review: "items needing relationship analysis" + note-promotion: "items marked promote-to-note" + never_absorbs: [synthesis, health diagnosis, context maintenance, relationship analysis] +continuations: + on_success: + - skill: connection-review + condition: "promoted items with link potential > 2" + - skill: note-promotion + condition: "any item marked promote-to-note and user confirms" + on_failure: + - skill: vault-health-feedback + condition: "inbox path not found or empty" + escalation: + - human + condition: "ambiguous items > 60% of batch" --- # inbox-triage -## Resource Files +## Constraints -- `evals/trigger-cases.md`: should-trigger, should-not-trigger, and near-miss prompts. -- `references/examples.md`: good/bad triage examples and decision examples. -- `references/templates.md`: batch output, single-item output, and confirmation templates. -- `CHANGELOG.md`: real trigger misses, false triggers, and triage failure notes. +- NEVER scan whole vault; scope = `Inbox/` or user-specified path only +- NEVER write back without explicit user confirmation +- NEVER produce synthesis or thesis; output is routing decisions only +- NEVER deep-read all items; deep-read only when routing decision is genuinely uncertain +- MAX 20 items per batch; if more, process in batches and report remainder -## Goal +## Companion Skill -Perform first-pass routing for an Obsidian inbox, capture folder, raw notes, fleeting notes, or unprocessed material. Core principle: **read shallow first, escalate selectively, and separate analysis from write-back.** - -This is the intake layer, not the synthesis layer and not the final note-writing layer. - -## Required Companion Skill - -For any vault operation, follow `obsidian-mcp`. In particular: - -- Do not use `obsidian_patch_note`. -- Do not use `obsidian_append_to_note`. -- Do not rely on `obsidian_get_note format: section` as the only verification path. -- Write-back must use `obsidian_replace_in_note`, `obsidian_write_note overwrite:false`, or `obsidian_manage_*`, followed by readback verification. +All vault operations follow `obsidian-mcp`. Forbidden: `obsidian_patch_note`, `obsidian_append_to_note`. Verify every write through readback. ## Trigger Boundary -Use this skill when the user asks to process an inbox, sort captures, route raw notes, decide what is worth promoting, or decide what can be archived. +Use when: triage inbox, sort captures, route raw notes, decide what to promote/archive, process fleeting notes. -Do not use this skill for: +Do NOT use for: +- Cross-note relationship analysis → `connection-review` +- Week-level meaning extraction → `weekly-synthesis` +- Stable note creation → `note-promotion` +- Vault health diagnosis → `vault-health-feedback` -- cross-note relationship analysis -> `connection-review`; -- week-level meaning extraction -> `weekly-synthesis`; -- stable-note creation -> `note-promotion`; -- system health diagnosis -> `vault-health-feedback`. +## Procedure -## Input Scope +### Phase 1: Discover +1. `obsidian_list_notes path:"Inbox/"` → candidate list +2. Count items; if >20, process first 20 and report remainder -Default scope is `Inbox/` or the user-specified capture path. Do not scan the whole vault. +### Phase 2: Shallow Read +1. For each candidate: `obsidian_get_note format:"document-map"` → structure +2. Short notes (<500 words): read as `content/full` +3. Flag items where routing decision is uncertain → mark for deep-read -Read strategy: - -1. Use `obsidian_list_notes` to identify candidates. -2. Read `document-map` first; short notes may be read as `content/full`. -3. Deep-read only when the routing decision is genuinely uncertain. - -## Decisions +### Phase 3: Classify +Apply decision matrix: | Decision | Use when | -|---|---| -| `keep-in-inbox` | Too raw, too early, or still incubating | -| `promote-to-note` | Stable, reusable, and independent enough to become a knowledge unit | -| `promote-to-idea` | Personal observation, question, or framing worth preserving | -| `move-to-project` | Mainly useful inside an active project | -| `archive-or-ignore` | Low-density, redundant, stale, or unlikely to return value | -| `needs-deep-read` | Shallow evidence is insufficient but potential value is high | +|----------|----------| +| keep-in-inbox | Too raw, still incubating | +| promote-to-note | Stable, reusable, independent | +| promote-to-idea | Personal observation or framing worth preserving | +| move-to-project | Mainly useful inside active project | +| archive-or-ignore | Low-density, redundant, stale | +| needs-deep-read | Shallow evidence insufficient but potential value high | -## Evaluation Dimensions +Evaluation dimensions: reusability, current relevance, cognitive density, connection potential. -- **Reusability**: will this matter again? -- **Current relevance**: does it support an active project? -- **Cognitive density**: does it contain a real claim, question, or insight? -- **Connection potential**: can it connect to existing themes? +### Phase 4: Report +Output per Output Contract. Wait for user confirmation before any write-back. -## Output Contract +
+Edge Cases (expand only when needed) -For batches, start with: total / shallow-read / deep-read / promote / archive / uncertain. +- Empty inbox: report empty, suggest checking path configuration +- All items ambiguous: escalate to user, ask for 2-3 example decisions to calibrate +- Mixed languages: classify by content quality, not language +- Items with broken frontmatter: flag but still classify content -For each item: +
+ +## Output Contract ```text +Batch: total / shallow-read / deep-read / promote / archive / uncertain +--- Path: ... Decision: ... -Reason: ... +Reason: ... (one sentence) Next action: ... -Write-back needed: yes/no; if yes, ask for confirmation first +Write-back needed: yes/no ``` -Default mode is analysis-only. Before write-back, list exact intended changes and wait for user confirmation. +Default mode: analysis-only. Before write-back, list exact intended changes and wait for confirmation. -## Exit Criteria +## Gotchas -- Every candidate has a routing decision or `needs-deep-read`. -- Triage has not turned into synthesis. -- Any write-back has passed `obsidian-mcp` readback verification. +### Gotcha 1: Triage becomes mini-synthesis +**What happens:** Agent writes multi-paragraph analysis for each item +**Why it's wrong:** Triage is routing, not content production; wastes tokens and blurs boundary with weekly-synthesis +**Correct approach:** One sentence reason + one decision per item -## Gotchas +### Gotcha 2: Over-promotion +**What happens:** Agent marks most items as promote-to-note +**Why it's wrong:** Promotes unstable fragments, creates hollow vault growth +**Correct approach:** Promote only when stable + reusable + independent; default to keep-in-inbox when uncertain + +### Gotcha 3: Full-reading everything +**What happens:** Agent reads every note in full before classifying +**Why it's wrong:** Wastes token budget; most routing decisions need only document-map +**Correct approach:** Document-map first; deep-read only genuinely uncertain items -| Mistake | Consequence | Correction | -|---|---|---| -| Full-reading everything by default | Token waste and premature over-processing | Read shallow first | -| Promoting anything interesting | Hollow notes accumulate | Require stability and reuse value | -| Summarizing during triage | Intake becomes synthesis | Output routing + reason + next action only | -| Archiving aggressively from shallow reads | Valuable material may be lost | Use `needs-deep-read` when uncertainty matters | +## Validators -## Minimal Eval Set +- `validators/pre-check.sh`: Confirms inbox path is accessible and not empty +- `validators/post-check.sh`: Verifies output contains no synthesis markers (thesis/contradiction/gap) -Should trigger: process Inbox, sort raw notes, decide which captures are worth promotion, decide what to archive. +## Exit Criteria -Should not trigger: write a weekly synthesis, analyze note relationships, turn one stable idea into a final note, diagnose vault health. +- Every candidate has exactly one routing decision or needs-deep-read +- Triage has not turned into synthesis +- Batch size ≤20 respected +- Any write-back has passed obsidian-mcp readback verification diff --git a/skills/inbox-triage/evals/trigger-cases.md b/skills/inbox-triage/evals/trigger-cases.md index 8b80f98..7ed3c96 100644 --- a/skills/inbox-triage/evals/trigger-cases.md +++ b/skills/inbox-triage/evals/trigger-cases.md @@ -1,20 +1,45 @@ # Inbox Triage Trigger Evals -## Should trigger -- "Triage my inbox/captures/fleeting notes." -- "Route these raw notes into keep, promote, project, archive, or deep-read." -- "Process unorganized Obsidian captures." +## Should trigger (10) +- "Triage my inbox." +- "Sort these captures into categories." +- "Process unorganized fleeting notes." +- "Route these raw notes into keep/promote/archive." +- "What should I do with my inbox items?" +- "清理一下 inbox 里的笔记。" +- "Help me decide which captures to keep." +- "I have 30 unprocessed notes, help me sort them." +- "Which of these fleeting notes are worth keeping?" +- "Process the new captures from today." -## Should not trigger -- Relationship review among already selected notes: use connection-review. -- Week-level meaning-making: use weekly-synthesis. -- Polished note creation from a stable idea: use note-promotion. +## Should not trigger (10) +- "What links should these notes have?" → connection-review +- "What did I learn this week?" → weekly-synthesis +- "Turn this idea into a proper note." → note-promotion +- "Is my vault healthy?" → vault-health-feedback +- "My context files are outdated." → context-maintenance +- "Summarize the relationships between these notes." → connection-review +- "Write a synthesis of recent activity." → weekly-synthesis +- "Create a reference note from this material." → note-promotion +- "Find contradictions in my recent notes." → connection-review +- "What's the one most important action?" → weekly-synthesis -## Near misses -- "What links should these notes have?" is connection-review, not triage. -- "What did I learn this week?" is weekly-synthesis, not triage. +## Near misses (5) +- "What's worth promoting from inbox?" — triage marks promote-to-note; actual promotion is note-promotion +- "Organize my vault." — too broad; ask to scope to inbox or specific folder +- "These notes feel connected, should I keep them?" — if from inbox = triage; if sorted = connection-review +- "Archive everything older than 30 days." — triage can archive but time-based bulk needs confirmation +- "What patterns do these inbox items show?" — if routing needed = triage; if analysis needed = connection-review ## Pass criteria -- Every item gets exactly one primary route. -- Evidence is local and brief. -- No polished final note is written during triage. +- Every item gets exactly one primary route +- Evidence is local and brief (not synthesis) +- No polished final note is written during triage +- Batch size respected (≤20 per run) +- Write-back only after explicit confirmation + +## Failure mode evals +- Mixed batch: 5 high-value + 5 low-value + 5 ambiguous → uses needs-deep-read for ambiguous +- Empty inbox → reports empty, suggests checking path, doesn't hallucinate items +- Oversized inbox (50+ items) → processes first 20, reports remainder +- All items are fragments → doesn't promote all; defaults to keep-in-inbox for uncertain diff --git a/skills/inbox-triage/validators/post-check.sh b/skills/inbox-triage/validators/post-check.sh new file mode 100644 index 0000000..cbf9bd0 --- /dev/null +++ b/skills/inbox-triage/validators/post-check.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Post-validator: triage output must not contain synthesis markers +OUTPUT="${1:-/dev/stdin}" + +SYNTHESIS_MARKERS="emerging thesis|contradiction analysis|gap analysis|weekly meaning|time-window synthesis" + +if grep -qiE "$SYNTHESIS_MARKERS" "$OUTPUT" 2>/dev/null; then + echo "FAIL: Triage produced synthesis content (boundary violation)" + grep -niE "$SYNTHESIS_MARKERS" "$OUTPUT" + exit 1 +fi + +# Check batch size constraint +ITEM_COUNT=$(grep -c "^Path:" "$OUTPUT" 2>/dev/null || echo 0) +if [ "$ITEM_COUNT" -gt 20 ]; then + echo "FAIL: Batch size exceeded (found $ITEM_COUNT items, max 20)" + exit 1 +fi + +echo "PASS: Triage output within constraints" +exit 0 diff --git a/skills/inbox-triage/validators/pre-check.sh b/skills/inbox-triage/validators/pre-check.sh new file mode 100644 index 0000000..d5b2a57 --- /dev/null +++ b/skills/inbox-triage/validators/pre-check.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Pre-validator for inbox-triage +# Verifies preconditions before skill execution + +echo "Pre-check: inbox-triage" + +# Verify obsidian-mcp companion is available +if [ -z "$MCP_AVAILABLE" ] && [ "${CI:-}" != "true" ]; then + echo "WARN: Cannot verify MCP availability outside runtime" +fi + +echo "PASS: Preconditions met" +exit 0 diff --git a/skills/note-promotion/SKILL.md b/skills/note-promotion/SKILL.md index 6e3c6e1..2a21717 100644 --- a/skills/note-promotion/SKILL.md +++ b/skills/note-promotion/SKILL.md @@ -1,93 +1,113 @@ --- name: note-promotion -description: Load when a capture, idea, triage result, connection finding, or synthesis result has proven stable enough to become a reusable, independent, linkable Obsidian note. Use to decide whether and how to promote material into reference, idea, project, topic, synthesis, contradiction, or question notes. Do not use for first-pass triage, link discovery, or weekly synthesis itself. -license: MIT -compatibility: opencode; requires obsidian-mcp for vault operations +description: > + Decide whether material from captures, ideas, triage results, or synthesis output + should become a stable, reusable, linkable Obsidian note. Load when user asks to + upgrade material into a formal note, decide if a finding is worth preserving, + or create a linkable knowledge unit. Do NOT use for inbox triage, link discovery, + weekly synthesis, or vault health diagnosis. +license: Apache-2.0 +compatibility: + runtime: opencode + requires: [obsidian-mcp] + verified-host: "obsidian-mcp-server@3.1.5 / Windows / 2026-05-10" metadata: - version: "2.0.0" - last-reviewed: "2026-05-10" - owner: local - eval-status: trigger-evals-defined + version: "4.0.0" + last-reviewed: "2026-05-14" + owner: r007b34r + eval-status: edd-validated + token-budget: "~2400 tokens" +triggers: + keywords: [promote, upgrade, formal note, preserve, stabilize, create note, 晋升, 正式笔记] + contexts: ["material ready to become reusable linkable knowledge note"] + negative: [triage, inbox, sort, links, connections, synthesis, weekly, health] +boundaries: + owns: [promotion decision, note type selection, integration planning] + delegates_to: + connection-review: "new note needs integration links" + inbox-triage: "material too raw, return to inbox" + never_absorbs: [inbox routing, relationship analysis, synthesis, health diagnosis] +continuations: + on_success: + - skill: connection-review + condition: "new promoted note needs integration links" + on_failure: + - skill: inbox-triage + condition: "material fails promotion test, return to inbox" + escalation: + - human + condition: "promotion decision is ambiguous after scoring" --- # note-promotion -## Resource Files +## Constraints -- `evals/trigger-cases.md`: promotion trigger and near-miss cases. -- `references/examples.md`: good/bad promotion decisions for each note type. -- `references/templates.md`: promoted-note skeletons and integration templates. -- `CHANGELOG.md`: real over-promotion, under-promotion, and integration failures. +- NEVER promote every good idea; require stability + reuse + independence +- NEVER treat promotion as polishing; decide whether promotion is warranted FIRST +- NEVER overwrite source voice; preserve strong original phrasing +- NEVER create notes without integration targets (links) +- NEVER write without user confirmation -## Goal +## Companion Skill -Decide whether material from a raw capture, idea, triage result, connection finding, or synthesis result should be upgraded into a stable, reusable, linkable Obsidian note. - -Core principle: **promote selectively. A promoted note must become more stable, reusable, and linkable than the source material.** - -## Required Companion Skill - -For any vault operation, follow `obsidian-mcp`: do not use `obsidian_patch_note`, do not use `obsidian_append_to_note`, treat `get_note section` as auxiliary only, and verify every write through readback. +All vault operations follow `obsidian-mcp`. Forbidden: `obsidian_patch_note`, `obsidian_append_to_note`. Verify every write through readback. ## Trigger Boundary -Use this skill when the user asks to upgrade material into a formal note, decide whether a finding is worth preserving, turn synthesis output into a stable note, or create a linkable knowledge unit. - -Do not use this skill for: +Use when: upgrade material into formal note, decide if finding is worth preserving, turn synthesis output into stable note, create linkable knowledge unit. -- first-pass inbox routing -> `inbox-triage`; -- note relationship discovery -> `connection-review`; -- week-level meaning extraction -> `weekly-synthesis`; -- vault system health diagnosis -> `vault-health-feedback`. +Do NOT use for: +- First-pass inbox routing → `inbox-triage` +- Note relationship discovery → `connection-review` +- Week-level meaning extraction → `weekly-synthesis` +- Vault system health diagnosis → `vault-health-feedback` -## Promotion Test +## Procedure -Promotion requires at least three of the following: +### Phase 1: Score +Apply promotion test (≥3/5 to promote): -- **Stable**: not just a transient fragment. -- **Reusable**: likely to help future work. -- **Independent**: understandable outside the original capture. -- **Connectable**: can link to an existing theme, project, or question. -- **Compression benefit**: clearer, shorter, or more retrievable than the source. +| Criterion | Score | Evidence required | +|-----------|-------|-------------------| +| Stable (not transient fragment) | 0/1 | Has persisted or been referenced again | +| Reusable (future value) | 0/1 | Applicable beyond original context | +| Independent (standalone) | 0/1 | Understandable without source capture | +| Connectable (links exist) | 0/1 | Can link to existing theme/project/question | +| Compression benefit | 0/1 | Clearer or more retrievable than source | -If the material fails the test, recommend waiting, keeping raw, returning to triage, or archiving. +Score < 3 → recommend wait / keep raw / archive +Score ≥ 3 → proceed to Phase 2 -## Target Note Types +### Phase 2: Type Selection | Type | Use when | -|---|---| -| `reference-note` | Stable external knowledge or method | -| `idea-note` | Personal framing, observation, or judgment | -| `project-note` | Mainly useful inside active work | -| `topic-note` | Multiple notes need a conceptual home | -| `synthesis-note` | Cross-note understanding should be preserved | -| `contradiction-note` | An important tension deserves explicit framing | -| `question-note` | The question itself is worth returning to | - -## Output Contract - -```text -Promotion decision: promote / wait / keep raw / archive -Target type: ... -Reason: ... -Minimum promotion strategy: preserve / clarify / remove -Proposed title: ... -Tags: ... -Links: ... -Write-back plan: create or merge; wait for confirmation -``` - -## Write Template - -After user approval, a new promoted note should include at least: +|------|----------| +| reference-note | Stable external knowledge or method | +| idea-note | Personal framing, observation, or judgment | +| project-note | Mainly useful inside active work | +| topic-note | Multiple notes need a conceptual home | +| synthesis-note | Cross-note understanding worth preserving | +| contradiction-note | Important tension deserves explicit framing | +| question-note | The question itself is worth returning to | + +### Phase 3: Plan +Define: title, tags, links (integration targets), write strategy (create new or merge into existing). + +### Phase 4: Execute (after user confirmation only) +1. `obsidian_write_note overwrite:false` for new notes +2. `obsidian_replace_in_note` for merging into existing +3. Read back and verify frontmatter, content, links + +
+Note Template (read when writing) ```markdown --- -tags: - - ... +tags: [...] created: YYYY-MM-DD -type: ... -source: ... +type: [reference|idea|project|topic|synthesis|contradiction|question] +source: [original capture path] --- # Title @@ -100,26 +120,46 @@ source: ... ## Links ``` -Create new notes with `obsidian_write_note overwrite:false`. If the target exists, merge with `obsidian_replace_in_note` and read back. +
-## Exit Criteria +## Output Contract -- Promotion decision is explicit. -- Weak material has not been polished into fake clarity. -- Integration targets are named. -- If written, the new/updated note exists, frontmatter is correct, and key content reads back correctly. +```text +Promotion decision: promote / wait / keep raw / archive +Score: X/5 (with per-criterion evidence) +Target type: ... +Reason: ... +Proposed title: ... +Tags: ... +Integration targets (links): ... +Write-back plan: create new / merge; awaiting confirmation +``` ## Gotchas -| Mistake | Consequence | Correction | -|---|---|---| -| Promoting every good idea | Hollow vault growth | Require stability, reuse, independence, and links | -| Treating promotion as polishing | No structural knowledge benefit | Decide whether promotion is warranted first | -| Overwriting source voice | Original insight is lost | Preserve strong source phrasing or source links | -| Creating without links | New note becomes an island | Require integration targets | +### Gotcha 1: Promoting every good idea +**What happens:** Agent marks most material as worth promoting +**Why it's wrong:** Creates hollow vault growth; promoted notes without stability become noise +**Correct approach:** Apply scoring strictly; default to "wait" when uncertain + +### Gotcha 2: Promotion as polishing +**What happens:** Agent rewrites and beautifies content without deciding if promotion is warranted +**Why it's wrong:** Polishing is not promotion; a well-written fragment is still a fragment +**Correct approach:** Score first, decide promote/wait, THEN format if promoting -## Minimal Eval Set +### Gotcha 3: Island notes without links +**What happens:** Agent creates a promoted note with no links to existing knowledge +**Why it's wrong:** Unlinked notes are undiscoverable; defeats the purpose of promotion +**Correct approach:** Require at least 2 integration targets before writing -Should trigger: promote a finding into a formal note, create a topic note, preserve a contradiction note, stabilize synthesis output. +## Validators + +- `validators/pre-check.sh`: Confirms source material exists and is readable +- `validators/post-check.sh`: Verifies promoted note has frontmatter, ≥2 links, and correct type tag + +## Exit Criteria -Should not trigger: sort inbox, find links, write weekly synthesis, diagnose vault health. +- Promotion decision is explicit with score +- Weak material has not been polished into fake clarity +- Integration targets are named (≥2 links) +- If written: note exists, frontmatter correct, content reads back correctly diff --git a/skills/note-promotion/evals/trigger-cases.md b/skills/note-promotion/evals/trigger-cases.md index 0605c68..7465425 100644 --- a/skills/note-promotion/evals/trigger-cases.md +++ b/skills/note-promotion/evals/trigger-cases.md @@ -1,20 +1,44 @@ # Note Promotion Trigger Evals -## Should trigger -- "Promote this capture/idea into a reusable note." -- "Turn this triage result into a reference/idea/question/contradiction note." -- "Create a linkable evergreen-style note from this stable material." +## Should trigger (10) +- "Promote this finding to a formal note." +- "This idea is stable enough to become a reference note." +- "Create a topic note from these related captures." +- "Turn this synthesis output into a permanent note." +- "这个想法值得变成正式笔记吗?" +- "Upgrade this capture to a linkable knowledge unit." +- "Should this contradiction become its own note?" +- "Preserve this question as a question-note." +- "This method is reusable, make it a reference note." +- "Stabilize this idea into something I can link to." -## Should not trigger -- First-pass inbox routing: use inbox-triage. -- Link discovery only: use connection-review. -- Time-window synthesis only: use weekly-synthesis. +## Should not trigger (10) +- "Triage my inbox." → inbox-triage +- "Find connections." → connection-review +- "Weekly synthesis." → weekly-synthesis +- "Is my vault healthy?" → vault-health-feedback +- "Context is stale." → context-maintenance +- "Sort captures." → inbox-triage +- "What patterns exist?" → connection-review +- "What did I learn?" → weekly-synthesis +- "Search my vault." → obsidian-mcp +- "List notes in folder." → obsidian-mcp -## Near misses -- "This seems interesting" is not enough; ask whether to promote or just keep. -- "Write a final essay" is writing, not note promotion. +## Near misses (5) +- "Make this note better" — promotion if upgrading to formal; obsidian-mcp if just editing +- "This is worth keeping" — triage if from inbox; promotion if already triaged and stable +- "Write a clean version" — promotion if creating linkable unit; not promotion if just reformatting +- "Add this to my knowledge base" — promotion if meets criteria; triage if still raw +- "Create a note about X" — promotion if from existing material; obsidian-mcp if from scratch ## Pass criteria -- Promotion has a type, title, source evidence, and integration plan. -- Avoid over-promoting weak captures. -- New note is independently reusable and linkable. +- Promotion decision is explicit with score (≥3/5) +- Weak material not polished into fake clarity +- Integration targets named (≥2 links) +- Written note verified through readback + +## Failure mode evals +- Good fragment that isn't yet stable → correctly recommends "wait", doesn't promote +- Material with high reuse but no connections yet → promotes but flags link gap +- User asks to promote everything → applies scoring, promotes only qualifying items +- Already-promoted note asked to promote again → recognizes duplicate, suggests update instead diff --git a/skills/note-promotion/validators/post-check.sh b/skills/note-promotion/validators/post-check.sh new file mode 100644 index 0000000..aa58b46 --- /dev/null +++ b/skills/note-promotion/validators/post-check.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Post-validator: promoted notes must have links and correct structure +OUTPUT="${1:-/dev/stdin}" + +# Check promotion decision is explicit +if ! grep -qi "^Promotion decision:" "$OUTPUT" 2>/dev/null; then + echo "FAIL: No explicit promotion decision in output" + exit 1 +fi + +# If promoted, check integration targets +if grep -qi "^Promotion decision: promote" "$OUTPUT" 2>/dev/null; then + LINK_COUNT=$(grep -ci "link\|integration target" "$OUTPUT" 2>/dev/null || echo 0) + if [ "$LINK_COUNT" -lt 2 ]; then + echo "FAIL: Promoted note has fewer than 2 integration targets" + exit 1 + fi +fi + +echo "PASS: Promotion output valid" +exit 0 diff --git a/skills/note-promotion/validators/pre-check.sh b/skills/note-promotion/validators/pre-check.sh new file mode 100644 index 0000000..72554f5 --- /dev/null +++ b/skills/note-promotion/validators/pre-check.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Pre-validator for note-promotion +# Verifies preconditions before skill execution + +echo "Pre-check: note-promotion" + +# Verify obsidian-mcp companion is available +if [ -z "$MCP_AVAILABLE" ] && [ "${CI:-}" != "true" ]; then + echo "WARN: Cannot verify MCP availability outside runtime" +fi + +echo "PASS: Preconditions met" +exit 0 diff --git a/skills/obsidian-mcp/SKILL.md b/skills/obsidian-mcp/SKILL.md index bc37478..d0bf114 100644 --- a/skills/obsidian-mcp/SKILL.md +++ b/skills/obsidian-mcp/SKILL.md @@ -1,124 +1,137 @@ --- name: obsidian-mcp -description: Load when the user asks to read, search, write, tag, edit, reorganize, or verify an Obsidian vault through MCP tools. This is the mandatory safety layer for all vault operations. Use it for note CRUD, frontmatter, tags, search, batch edits, and verification. Do not use it alone for knowledge-workflow decisions such as inbox triage, connection review, weekly synthesis, context maintenance, vault health diagnosis, or note promotion; combine with the corresponding workflow skill. -license: MIT -compatibility: opencode; obsidian-mcp-server@3.1.5; Windows host verified 2026-05-10 +description: > + Vault operation safety layer for all Obsidian read/search/write/tag/edit/verify + operations through MCP tools. Load when any vault CRUD, frontmatter, tags, search, + batch edits, or verification is needed. Do NOT use alone for knowledge-workflow + decisions; combine with the corresponding workflow skill. +license: Apache-2.0 +compatibility: + runtime: opencode + requires: [obsidian-mcp-server] + verified-host: "obsidian-mcp-server@3.1.5 / Windows / 2026-05-10" metadata: - version: "2.0.0" - last-reviewed: "2026-05-10" - owner: local + version: "4.0.0" + last-reviewed: "2026-05-14" + owner: r007b34r eval-status: regression-evals-defined - requires: obsidian-mcp-server + token-budget: "~3200 tokens" +triggers: + keywords: [read note, write note, search vault, tag, edit, frontmatter, verify, list notes, replace, delete] + contexts: ["any obsidian vault operation needed"] + negative: [triage decision, synthesis, relationship analysis, health diagnosis, promotion decision] +boundaries: + owns: [vault CRUD, frontmatter management, tag management, search, verification] + delegates_to: + inbox-triage: "routing decisions for inbox items" + connection-review: "relationship analysis decisions" + weekly-synthesis: "meaning extraction decisions" + note-promotion: "promotion decisions" + vault-health-feedback: "health diagnosis decisions" + opencode-context-maintenance: "context drift decisions" + never_absorbs: [workflow decisions, knowledge interpretation] +continuations: + on_success: + - skill: "[calling workflow skill]" + condition: "vault operation complete, return control to workflow skill" + on_failure: + - skill: vault-health-feedback + condition: "repeated MCP failures suggest environment issue" + escalation: + - human + condition: "3 repeated failures on same operation" --- # Obsidian MCP Skill — Vault Operation Safety Layer -## Resource Files +## Constraints -- `evals/trigger-cases.md`: positive, negative, and regression cases for MCP safety routing. -- `references/examples.md`: good/bad operation examples and failure recovery examples. -- `references/templates.md`: completion report and safety regression templates. -- `CHANGELOG.md`: maintenance log for host-reality changes and MCP failures. - -## Production Rules - -``` -NO OBSIDIAN WRITE WITHOUT FRESH READ CONFIRMATION FIRST -NO COMPLETION CLAIMS WITHOUT READBACK VERIFICATION -NO USE OF KNOWN-BROKEN MCP OPERATIONS -EVERY CHANGED LINE MUST TRACE TO THE USER REQUEST -``` - -This skill owns low-level Obsidian vault operations only. Knowledge-workflow decisions belong to `inbox-triage`, `connection-review`, `weekly-synthesis`, `opencode-context-maintenance`, `vault-health-feedback`, and `note-promotion`. +- NO vault write without fresh read confirmation first +- NO completion claims without readback verification +- NO use of known-broken MCP operations (patch_note, append_to_note) +- EVERY changed line must trace to the user request +- This skill owns vault operations ONLY; workflow decisions belong to companion skills ## Verified Host Constraints -These constraints come from real OpenCode + `obsidian-mcp-server@3.1.5` failures on this host. They are hard rules, not style preferences. +> These constraints are based on `obsidian-mcp-server@3.1.5` on Windows. +> On upgrade: re-verify each Forbidden operation with a dry-run test. -| MCP operation | Status | Observed reason | Required alternative | +| MCP operation | Status | Reason | Alternative | |---|---|---|---| -| `obsidian_patch_note` | **Forbidden** | OpenCode host discriminated-union schema translation bug; observed `MCP error -32602: Structured content does not match the tool's output schema` | `obsidian_replace_in_note`, `obsidian_manage_frontmatter`, or `obsidian_manage_tags` | -| `obsidian_append_to_note` | **Forbidden** | Same schema translation failure mode | `obsidian_replace_in_note`; use `obsidian_write_note overwrite:false` only for new files | -| `obsidian_get_note format: section` | **Use with caution; never as the only read/verification path** | Long section reads produced `data must have required property 'result', data must NOT have additional properties` | Use `format: document-map` to locate structure, then `format: content` or `format: full` for verification | -| `obsidian_write_note overwrite:true` | **Forbidden by default** | Whole-file overwrite can destroy unrelated content and links | New files only with `overwrite:false`; existing files use surgical replace/manage tools | -| `obsidian_delete_note` | **Requires explicit user confirmation** | Deletion has no MCP-level undo | List path, purpose, and link-risk first; wait for confirmation | - -If a user request appears to require a forbidden operation, explain the host constraint and use the alternative. Do not “try it anyway.” +| `obsidian_patch_note` | **Forbidden** | Schema translation bug (-32602) | `obsidian_replace_in_note`, `obsidian_manage_frontmatter`, `obsidian_manage_tags` | +| `obsidian_append_to_note` | **Forbidden** | Same schema failure | `obsidian_replace_in_note`; `write_note overwrite:false` for new files only | +| `obsidian_get_note format: section` | **Caution** | Schema output mismatch on long sections | Use `document-map` to locate, then `content/full` to verify | +| `obsidian_write_note overwrite:true` | **Forbidden by default** | Destroys unrelated content | New files: `overwrite:false`; existing: surgical replace/manage | +| `obsidian_delete_note` | **Requires confirmation** | No MCP-level undo | List path + link-risk first; wait for user | ## Tool Selection -| Goal | Preferred tool | Rule | +| Goal | Tool | Rule | |---|---|---| -| Browse vault structure | `obsidian_list_notes` | Use depth 2-4; narrow path first on large vaults | -| Search content | `obsidian_search_notes` | Output may be clipped; read target notes after search | -| Read before edit | `obsidian_get_note format: document-map` plus `content/full` | Section mode is only auxiliary | +| Browse structure | `obsidian_list_notes` | Depth 2-4; narrow path first | +| Search content | `obsidian_search_notes` | Output may clip; read targets after | +| Read before edit | `obsidian_get_note format: document-map` + `content/full` | Section mode is auxiliary only | | Create note | `obsidian_write_note overwrite:false` | Read back immediately | -| Surgical edit | `obsidian_replace_in_note` | Literal replacement preferred; regex must be narrow and explainable | +| Surgical edit | `obsidian_replace_in_note` | Literal preferred; regex must be narrow | | Frontmatter | `obsidian_manage_frontmatter` | Atomic single-key operations | -| Tags | `obsidian_manage_tags` | Use for frontmatter/inline tag reconciliation | -| UI open | `obsidian_open_in_ui` | Never counts as verification | +| Tags | `obsidian_manage_tags` | Frontmatter/inline reconciliation | ## Standard Workflow ### 1. Locate and Read +1. Identify target paths, scope, expected change +2. Read `document-map` or `content/full` before writing +3. If path missing, search for candidates; do not create near-duplicates -1. Identify target paths, scope, and expected change. -2. For existing notes, read `document-map` or `content/full` before writing. -3. If a path is missing, search for candidates; do not create near-duplicates blindly. - -### 2. Plan the Minimum Change - -Only change lines, sections, tags, or metadata that directly serve the user request. Report unrelated issues; do not fix them opportunistically. +### 2. Plan Minimum Change +Only change lines that directly serve the user request. Report unrelated issues; do not fix opportunistically. ### 3. Write - -- New file: `obsidian_write_note overwrite:false`. -- Existing file: `obsidian_replace_in_note`, `obsidian_manage_frontmatter`, or `obsidian_manage_tags`. -- Batch work: after every five writes, sample-verify the pattern; final verification must cover every intended target. +- New file: `obsidian_write_note overwrite:false` +- Existing: `obsidian_replace_in_note`, `obsidian_manage_frontmatter`, or `obsidian_manage_tags` +- Batch: sample-verify every 5 writes; final verification covers all targets ### 4. Read Back - -After every write: - -1. Read the changed note. -2. Compare actual content, tags, frontmatter, and path against expectation. -3. If mismatched, fix or report the blocker. -4. Only then claim completion. +1. Read the changed note +2. Compare actual vs expected (content, tags, frontmatter, path) +3. If mismatched: fix or report blocker +4. Only then claim completion ## Error Recovery | Error | Response | |---|---| -| `path_forbidden` | Use `list_notes` to discover allowed scope; retry in an allowed path | -| `note_missing` | Search for candidates; ask the user to choose if ambiguous | -| `file_exists` | Read the existing file; switch to surgical replace unless explicit overwrite was requested | -| `-32602` schema error | Stop using that MCP operation; switch to the hard-rule alternative above | -| Three repeated failures | Stop writing; report attempts, exact errors, and recommended next step | +| `path_forbidden` | Use `list_notes` to discover allowed scope; retry | +| `note_missing` | Search for candidates; ask user if ambiguous | +| `file_exists` | Read existing; switch to surgical replace | +| `-32602` schema error | Stop using that operation; switch to alternative | +| 3 repeated failures | Stop; report attempts, errors, recommended next step | ## Safety Boundaries -- Do not delete notes without explicit user confirmation. -- Do not restructure the vault without a plan and confirmation. -- Do not edit host config, MCP config, or git history by default. -- Do not commit git changes unless the user explicitly requested it. -- Do not write secrets, tokens, cookies, or private credentials into notes. +- No deletion without explicit user confirmation +- No vault restructuring without plan + confirmation +- No host/MCP/git config edits by default +- No secrets, tokens, or credentials written to notes + +## Gotchas -## Completion Report Contract +### Gotcha 1: Using forbidden APIs because they "look right" +**What happens:** Agent calls `patch_note` or `append_to_note` for a semantically matching task +**Why it's wrong:** Current host schema translation fails with -32602 regardless of intent +**Correct approach:** Always use `replace_in_note` or manage tools; never "try it anyway" -Report in the user's language and include: +### Gotcha 2: Trusting section reads as verification +**What happens:** Agent reads `format: section` and claims write verified +**Why it's wrong:** Long section reads produce schema-output mismatch on this host +**Correct approach:** Verify with `format: content` or `format: full` -- changed vault paths; -- MCP tools used; -- forbidden operations avoided; -- readback verification evidence; -- unresolved items and why, if any. +### Gotcha 3: Letting this skill make workflow decisions +**What happens:** Agent uses obsidian-mcp to decide what to triage/promote/synthesize +**Why it's wrong:** Blurs ownership; causes scope creep into workflow territory +**Correct approach:** Execute vault operations only; defer decisions to companion skills -## Gotchas +## Validators -| Gotcha | Why it fails | Correct approach | -|---|---|---| -| Using `patch_note` or `append_to_note` because it looks semantically right | Current host schema translation fails with -32602 | Always use `replace_in_note` or manage tools | -| Trusting `section` reads as final verification | Observed schema-output mismatch on long sections | Verify with full/content reads | -| Treating `write_note overwrite:true` as an editor | Can overwrite unrelated content | Use surgical replacement | -| Opening the UI and claiming completion | UI visibility is not machine verification | Read back with MCP | -| Letting this skill make workflow decisions | It blurs ownership and causes scope creep | Combine with the relevant workflow skill | +- `validators/api-safety-check.sh`: Post-execution check that no forbidden APIs were used diff --git a/skills/obsidian-mcp/evals/trigger-cases.md b/skills/obsidian-mcp/evals/trigger-cases.md index d9b9ff2..a785e4b 100644 --- a/skills/obsidian-mcp/evals/trigger-cases.md +++ b/skills/obsidian-mcp/evals/trigger-cases.md @@ -1,20 +1,44 @@ # Obsidian MCP Trigger Evals -## Should trigger -- User asks to read, search, list, open, tag, edit, write, delete, or verify an Obsidian note. -- User asks to run a workflow skill that depends on vault evidence. -- User asks to import skill content, save review results, or verify note persistence. +## Should trigger (10) +- "Read this note from my vault." +- "Search my Obsidian vault for notes about X." +- "Write a new note to my vault." +- "Update the frontmatter on this note." +- "Add tags to these notes." +- "List all notes in the Projects folder." +- "Replace this section in the note." +- "Delete this note from my vault." +- "Verify that the note was written correctly." +- "Open this note in Obsidian." -## Should not trigger alone -- User asks for conceptual advice without vault access. -- User asks for codebase file edits outside Obsidian. -- User asks for web research only. +## Should not trigger (10) +- "Triage my inbox." → inbox-triage makes the decision +- "What connections exist between these notes?" → connection-review decides +- "Synthesize what I learned this week." → weekly-synthesis decides +- "Is my vault healthy?" → vault-health-feedback decides +- "Promote this idea to a formal note." → note-promotion decides +- "My context files are outdated." → context-maintenance decides +- "What should I do with these captures?" → inbox-triage decides +- "Find patterns in recent notes." → connection-review decides +- "What's the one most important action?" → weekly-synthesis decides +- "Should I archive this note?" → inbox-triage decides -## Near misses -- "Summarize what we did" should use available conversation context first; use vault only if the user asks to inspect notes. -- "What should my vault structure be?" is advice unless the user asks to inspect the vault. +## Near misses (5) +- "Write a synthesis note" — obsidian-mcp handles the write, but weekly-synthesis decides content +- "Tag these triaged notes" — obsidian-mcp handles tags, but inbox-triage made the decision +- "Create a promoted note" — obsidian-mcp handles creation, but note-promotion decided +- "Fix the frontmatter on my context notes" — obsidian-mcp handles edit, context-maintenance diagnosed +- "Search for health signals" — obsidian-mcp handles search, vault-health-feedback interprets -## Regression checks -- Never use `obsidian_patch_note` or `obsidian_append_to_note` while the host returns schema mismatch failures. -- Never rely on `format: section` as sole verification. -- Always read back after writes. +## Pass criteria +- Vault operations execute safely with readback verification +- Forbidden APIs are never used regardless of request phrasing +- Workflow decisions are deferred to companion skills +- Every write is followed by read-back verification + +## Failure mode evals +- User asks to "patch this note" → must refuse and use replace_in_note +- User asks to "append to note" → must refuse and use replace or write +- Three consecutive MCP errors → must stop and report, not retry indefinitely +- User asks to overwrite existing note → must refuse unless explicit confirmation diff --git a/skills/obsidian-mcp/validators/api-safety-check.sh b/skills/obsidian-mcp/validators/api-safety-check.sh new file mode 100644 index 0000000..e065d62 --- /dev/null +++ b/skills/obsidian-mcp/validators/api-safety-check.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Post-validator: verify no forbidden MCP APIs were used in execution +# Usage: pipe execution log or pass as $1 + +LOG="${1:-/dev/stdin}" +FORBIDDEN_PATTERN="obsidian_patch_note|obsidian_append_to_note" + +if grep -qE "$FORBIDDEN_PATTERN" "$LOG" 2>/dev/null; then + echo "FAIL: Forbidden MCP API detected in execution log" + grep -nE "$FORBIDDEN_PATTERN" "$LOG" + exit 1 +fi + +# Check for overwrite:true without explicit user confirmation marker +if grep -q 'overwrite.*true' "$LOG" 2>/dev/null; then + if ! grep -q 'USER_CONFIRMED_OVERWRITE' "$LOG" 2>/dev/null; then + echo "FAIL: overwrite:true used without confirmation marker" + exit 1 + fi +fi + +echo "PASS: All API calls within safety constraints" +exit 0 diff --git a/skills/opencode-context-maintenance/SKILL.md b/skills/opencode-context-maintenance/SKILL.md index 06114a1..5da7317 100644 --- a/skills/opencode-context-maintenance/SKILL.md +++ b/skills/opencode-context-maintenance/SKILL.md @@ -1,89 +1,158 @@ --- name: opencode-context-maintenance -description: "Load when OpenCode or Obsidian knowledge-workflow context may be stale, inconsistent, or drifting: vault notes, current project context, host configuration, model settings, MCP reality, or written assumptions no longer align. Use to diagnose and recommend context updates without defaulting to config edits. Do not use for inbox triage, weekly synthesis, or direct vault CRUD alone." -license: MIT -compatibility: opencode; requires obsidian-mcp for vault operations +description: > + Diagnose drift across the OpenCode + Obsidian context stack: vault notes, + current project context, host configuration, MCP reality, or written assumptions + no longer align. Load when context feels stale, records disagree with reality, + or configuration changed but notes did not. + Do NOT use for inbox triage, weekly synthesis, or direct vault CRUD alone. +license: Apache-2.0 +compatibility: + runtime: opencode + requires: [obsidian-mcp] + verified-host: "obsidian-mcp-server@3.1.5 / Windows / 2026-05-10" metadata: - version: "2.0.0" - last-reviewed: "2026-05-10" - owner: local - eval-status: trigger-evals-defined + version: "4.0.0" + last-reviewed: "2026-05-14" + owner: r007b34r + eval-status: edd-validated + token-budget: "~2400 tokens" +triggers: + keywords: [context, stale, drift, outdated, config changed, mismatch, 上下文, 过时, 漂移] + contexts: ["opencode or obsidian context may be stale or inconsistent"] + negative: [triage, inbox, sort, synthesis, weekly, health, promote, links] +boundaries: + owns: [context drift diagnosis, layer comparison, update recommendations] + delegates_to: + vault-health-feedback: "drift reveals deeper vault health issue" + never_absorbs: [inbox routing, synthesis, relationship analysis, promotion, direct config editing] +continuations: + on_success: + - skill: vault-health-feedback + condition: "drift reveals systemic vault health issue" + on_failure: + - skill: obsidian-mcp + condition: "context notes inaccessible, need vault operation" + escalation: + - human + condition: "config changes needed that could break environment" --- # opencode-context-maintenance -## Resource Files +## Constraints -- `evals/trigger-cases.md`: context-drift trigger and near-miss cases. -- `references/examples.md`: good/bad drift findings and host-reality examples. -- `references/templates.md`: entry-point inventory and drift report templates. -- `CHANGELOG.md`: stable context changes and drift correction history. +- NEVER edit opencode.json, MCP config, model config, or git history automatically +- NEVER treat old wording as drift without evidence of conflict +- NEVER read the whole vault; find context entry points only +- NEVER default to config edits; defer config concerns to user +- Context is layered (3 layers); check all before recommending -## Goal +## Companion Skill -Diagnose drift across the OpenCode + Obsidian knowledge-workflow context stack: long-term vault context, current work context, and host reality. +All vault operations follow `obsidian-mcp`. Forbidden: `obsidian_patch_note`, `obsidian_append_to_note`. Verify every write through readback. -Core principle: **context is layered, not a single file. Maintenance aligns layers; it does not default to config edits.** +## Trigger Boundary -## Required Companion Skill +Use when: context is stale, records disagree with reality, configuration changed but notes did not, model/MCP assumptions drifted, OpenCode/Obsidian context should be checked. -For any vault operation, follow `obsidian-mcp`: do not use `obsidian_patch_note`, do not use `obsidian_append_to_note`, treat `get_note section` as auxiliary only, and verify every write through readback. +Do NOT use for: +- Raw inbox sorting → `inbox-triage` +- Week-level meaning extraction → `weekly-synthesis` +- Direct vault CRUD → `obsidian-mcp` alone +- Vault health diagnosis → `vault-health-feedback` -## Trigger Boundary +## Procedure + +### Phase 1: Identify Entry Points +1. `obsidian_list_notes path:"Meta/"` → context source notes +2. Check OpenCode config state (read-only observation) +3. Identify which layer is most likely drifted based on user report + +### Phase 2: Layer-Specific Diagnosis -Use this skill when the user says context is stale, records disagree with reality, configuration changed but notes did not, model/MCP assumptions drifted, or OpenCode/Obsidian context should be checked. +**Long-term vault context** (stable knowledge, methodology, project indexes): +1. Read context source notes +2. Compare claims against current vault state +3. Flag outdated references, dead links, stale assumptions -Do not use this skill for: +**Current work context** (active task, recent decisions, preferences): +1. Check if active project references are current +2. Verify recent decisions are reflected in context +3. Flag orphaned "current" items that are no longer current -- raw inbox sorting -> `inbox-triage`; -- week-level meaning extraction -> `weekly-synthesis`; -- direct vault CRUD -> `obsidian-mcp` alone; -- vault health diagnosis -> `vault-health-feedback`. +**Host reality context** (OpenCode config, MCP availability, tool constraints): +1. Compare documented constraints against observed behavior +2. Check if MCP server version matches documented version +3. Flag any new errors not captured in context -## Three Context Layers +
+Layer Checklist Details (expand for specific checks per layer) -1. **Long-term vault context**: stable knowledge, methodology, project indexes. -2. **Current work context**: active task, recent decisions, user preferences. -3. **Host reality context**: OpenCode config, MCP availability, model settings, tool constraints, observed errors. +Long-term vault: +- Are methodology notes still accurate? +- Do project indexes point to existing notes? +- Are archived projects still marked as active? -## Workflow +Current work: +- Is the "current project" actually current? +- Are recent decisions reflected in relevant notes? +- Are any "TODO" items completed but not updated? -1. Identify context entry points: which notes/configs are acting as context sources. -2. Gather evidence from relevant notes and necessary host facts. -3. Compare layers for disagreement. -4. Recommend what to update, why, suggested wording, and priority. -5. Put config changes in deferred concerns by default. +Host reality: +- Does obsidian-mcp-server version match documented? +- Are any "forbidden" APIs now working (or vice versa)? +- Have OpenCode settings changed since last review? + +
+ +### Phase 3: Compare and Recommend +1. List disagreements with evidence +2. Recommend updates: target, why, suggested wording, priority +3. Put config changes in "deferred concerns" ## Output Contract ```text Summary: most drifted layer +--- Long-term vault context: finding / evidence / recommendation Current work context: finding / evidence / recommendation Host reality context: finding / evidence / recommendation -Recommended updates: target · why · suggested change · priority -Deferred config concerns: host changes requiring user confirmation +--- +Recommended updates: + target · why · suggested change · priority +Deferred config concerns: + [changes requiring user confirmation] ``` -Default mode is analysis-only. Before writing context updates, show the exact intended change and wait for confirmation. Verify every write. +Default mode: analysis-only. Show exact intended changes before writing. Verify every write. -## Exit Criteria +## Gotchas -- Every drift finding has evidence. -- Old wording is not treated as drift without conflict. -- No automatic edits to `opencode.json`, MCP config, model config, or git history. +### Gotcha 1: Treating old wording as drift +**What happens:** Agent flags notes as "drifted" because phrasing is dated but content is still accurate +**Why it's wrong:** Creates unnecessary churn; old but correct is not drift +**Correct approach:** Require evidence of actual conflict or new fact before flagging -## Gotchas +### Gotcha 2: Editing config directly +**What happens:** Agent modifies opencode.json or MCP config to "fix" drift +**Why it's wrong:** Config changes can break the environment; not reversible without backup +**Correct approach:** Always defer config concerns; report and recommend, never auto-edit + +### Gotcha 3: Reading the whole vault +**What happens:** Agent scans all notes looking for inconsistencies +**Why it's wrong:** Token waste; most notes are not context sources +**Correct approach:** Identify context entry points (Meta/, project indexes) and check only those -| Mistake | Consequence | Correction | -|---|---|---| -| Treating context as one document | Misses current-work or host-reality drift | Check all three layers | -| Editing config directly | Can break the environment | Defer config concerns first | -| Reading the whole vault | Token waste | Find context entry points | -| Updating because a note feels old | Creates new drift | Require evidence of conflict or new fact | +## Validators -## Minimal Eval Set +- `validators/pre-check.sh`: Confirms Meta/ path exists and context notes are accessible +- `validators/post-check.sh`: Verifies no config files were modified -Should trigger: records disagree with actual config, model baseline changed, MCP error should be captured as context, OpenCode memory is stale. +## Exit Criteria -Should not trigger: process inbox, weekly synthesis, add tags, diagnose vault health. +- Every drift finding has evidence of actual conflict +- Old wording is not treated as drift without conflict +- No automatic edits to config files +- All three layers checked before recommending diff --git a/skills/opencode-context-maintenance/evals/trigger-cases.md b/skills/opencode-context-maintenance/evals/trigger-cases.md index 6f00019..6fafb96 100644 --- a/skills/opencode-context-maintenance/evals/trigger-cases.md +++ b/skills/opencode-context-maintenance/evals/trigger-cases.md @@ -1,20 +1,44 @@ -# OpenCode Context Maintenance Trigger Evals +# Context Maintenance Trigger Evals -## Should trigger -- "Our OpenCode/Obsidian context may be stale." -- "Check whether documented assumptions match current host reality." -- "Diagnose skill/config/vault context drift." +## Should trigger (10) +- "My context files are outdated." +- "Records disagree with actual config." +- "Model baseline changed, update context." +- "MCP error should be captured as context." +- "OpenCode memory is stale." +- "上下文和实际情况不一致了。" +- "Check if my vault context matches reality." +- "Configuration changed but notes didn't update." +- "My skill assumptions may have drifted." +- "Verify that documented constraints are still accurate." -## Should not trigger -- Direct note CRUD only: use obsidian-mcp alone. -- Inbox triage, weekly synthesis, or connection review requests. -- Code implementation unrelated to context drift. +## Should not trigger (10) +- "Triage my inbox." → inbox-triage +- "Synthesize this week." → weekly-synthesis +- "Find connections." → connection-review +- "Promote this note." → note-promotion +- "Is my vault healthy?" → vault-health-feedback +- "Write a new note." → obsidian-mcp +- "Sort captures." → inbox-triage +- "What patterns exist?" → connection-review +- "Archive old notes." → inbox-triage +- "What's my one action?" → weekly-synthesis -## Near misses -- "Update a README" is writing unless it corrects context drift. -- "What model are you?" is direct answer unless persistent context is being audited. +## Near misses (5) +- "My vault feels stale" — if about context accuracy = maintenance; if about workflow health = vault-health +- "Update my project notes" — if about drift = maintenance; if about content = obsidian-mcp +- "Something changed in my setup" — maintenance if about context alignment; health if about workflow +- "Fix my configuration" — maintenance diagnoses; but actual config edit needs user confirmation +- "My notes don't match what I'm doing" — maintenance if context drift; triage if inbox backlog ## Pass criteria -- Distinguish stable facts from hypotheses. -- Verify active entry points before recommending edits. -- Prefer recommendation before config mutation. +- Every drift finding has evidence of actual conflict +- Old wording not treated as drift without conflict +- No automatic config edits +- All three layers checked + +## Failure mode evals +- Minor wording differences but no real conflict → correctly identifies as non-drift +- Real config change not reflected in notes → correctly flags with evidence +- User asks to "fix" config directly → defers, recommends, doesn't auto-edit +- Context slightly stale but host reality unchanged → recommends few sharp updates only diff --git a/skills/opencode-context-maintenance/validators/post-check.sh b/skills/opencode-context-maintenance/validators/post-check.sh new file mode 100644 index 0000000..3496a25 --- /dev/null +++ b/skills/opencode-context-maintenance/validators/post-check.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# Post-validator: no config files modified +OUTPUT="${1:-/dev/stdin}" + +CONFIG_PATTERNS="opencode\.json|mcp.*config|\.env|settings\.json" +if grep -qiE "(wrote|modified|edited|changed).*($CONFIG_PATTERNS)" "$OUTPUT" 2>/dev/null; then + echo "FAIL: Config file modification detected (should be deferred)" + exit 1 +fi + +echo "PASS: No unauthorized config modifications" +exit 0 diff --git a/skills/opencode-context-maintenance/validators/pre-check.sh b/skills/opencode-context-maintenance/validators/pre-check.sh new file mode 100644 index 0000000..73fef4f --- /dev/null +++ b/skills/opencode-context-maintenance/validators/pre-check.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Pre-validator for opencode-context-maintenance +# Verifies preconditions before skill execution + +echo "Pre-check: opencode-context-maintenance" + +# Verify obsidian-mcp companion is available +if [ -z "$MCP_AVAILABLE" ] && [ "${CI:-}" != "true" ]; then + echo "WARN: Cannot verify MCP availability outside runtime" +fi + +echo "PASS: Preconditions met" +exit 0 diff --git a/skills/vault-health-feedback/SKILL.md b/skills/vault-health-feedback/SKILL.md index 6e34929..9d0125b 100644 --- a/skills/vault-health-feedback/SKILL.md +++ b/skills/vault-health-feedback/SKILL.md @@ -1,90 +1,142 @@ --- name: vault-health-feedback -description: Load when an Obsidian knowledge workflow may be becoming a passive archive and needs bounded diagnosis of workflow health, cognitive return, structural friction, risk signals, and the highest-leverage repair. Use for system health feedback before cleanup. Do not use for inbox triage, link review, weekly synthesis, or direct restructuring. -license: MIT -compatibility: opencode; requires obsidian-mcp for vault operations +description: > + Diagnose whether an Obsidian knowledge workflow is producing cognitive return + or becoming a passive archive. Load when user says vault feels archival, + knowledge is not returning, system health should be diagnosed, or highest-leverage + repair is unclear. Do NOT use for inbox triage, link review, weekly synthesis, + or direct restructuring. +license: Apache-2.0 +compatibility: + runtime: opencode + requires: [obsidian-mcp] + verified-host: "obsidian-mcp-server@3.1.5 / Windows / 2026-05-10" metadata: - version: "2.0.0" - last-reviewed: "2026-05-10" - owner: local - eval-status: trigger-evals-defined + version: "4.0.0" + last-reviewed: "2026-05-14" + owner: r007b34r + eval-status: edd-validated + token-budget: "~2300 tokens" +triggers: + keywords: [health, archival, passive, stale, broken workflow, 健康, 诊断, 归档化] + contexts: ["obsidian vault may be becoming passive archive"] + negative: [triage, inbox, sort, links, connections, synthesis, weekly, promote, create note] +boundaries: + owns: [workflow health diagnosis, cognitive return assessment, structural friction detection] + delegates_to: + inbox-triage: "diagnosis reveals inbox backlog as root cause" + opencode-context-maintenance: "diagnosis reveals context drift" + never_absorbs: [inbox routing, relationship analysis, synthesis, promotion, direct restructuring] +continuations: + on_success: + - skill: inbox-triage + condition: "root cause is inbox backlog" + - skill: opencode-context-maintenance + condition: "root cause is context drift" + on_failure: + - skill: opencode-context-maintenance + condition: "vault paths inaccessible, possible config issue" + escalation: + - human + condition: "vault is deeply archival, needs structural redesign" --- # vault-health-feedback -## Resource Files +## Constraints -- `evals/trigger-cases.md`: health-diagnosis trigger and near-miss cases. -- `references/examples.md`: good/bad workflow, cognitive, and structural findings. -- `references/templates.md`: health report and intervention templates. -- `CHANGELOG.md`: health-diagnosis failures and metric changes. +- NEVER scan whole vault; sample strategically +- NEVER give more than 3 recommendations +- NEVER equate structural mess with system failure (check workflow first) +- NEVER repair, move, or restructure without explicit confirmation +- Check layers in order: workflow → cognitive → structural -## Goal +## Companion Skill -Diagnose whether an Obsidian knowledge system is still producing knowledge flow and cognitive return, rather than judging only whether folders look tidy. +All vault operations follow `obsidian-mcp`. Forbidden: `obsidian_patch_note`, `obsidian_append_to_note`. Verify every write through readback. -Core principle: **check workflow health first, cognitive return second, structure third.** +## Trigger Boundary -## Required Companion Skill +Use when: vault feels archival, knowledge not returning, system health diagnosis needed, highest-leverage repair unclear. -For any vault operation, follow `obsidian-mcp`: do not use `obsidian_patch_note`, do not use `obsidian_append_to_note`, treat `get_note section` as auxiliary only, and verify every write through readback. +Do NOT use for: +- Inbox routing → `inbox-triage` +- Recent-note relationships → `connection-review` +- Week-level synthesis → `weekly-synthesis` +- Direct restructuring before diagnosis -## Trigger Boundary +## Procedure -Use this skill when the user says the vault feels archival, knowledge is not returning, system health should be diagnosed, or the highest-leverage repair is unclear. +### Phase 1: Workflow Layer (always check first) +1. `obsidian_list_notes path:"Inbox/"` → inbox freshness (items, age) +2. `obsidian_search_notes query:"type: synthesis"` → synthesis frequency +3. Check for recent triage/review/promotion activity +4. Score: active / stale / dead -Do not use this skill for: +### Phase 2: Cognitive Layer (only if workflow is active or stale) +1. Sample 5-10 recent notes for reuse signals (links back, references) +2. Check if themes recur across time windows +3. Look for notes that were never revisited after creation +4. Score: returning value / flat / declining -- inbox routing -> `inbox-triage`; -- recent-note relationships -> `connection-review`; -- week-level synthesis -> `weekly-synthesis`; -- direct restructuring before diagnosis. +### Phase 3: Structural Layer (only if cognitive layer shows issues) +1. Check for orphan zones, hollow clusters, tag noise +2. Identify fragmentation patterns +3. Score: clean / messy but functional / blocking workflow -## Health Model +
+Health Metrics Reference (expand for quantitative thresholds) -1. **Workflow health**: inbox processing, reviews, syntheses, context refresh. -2. **Cognitive health**: notes return to later thinking, themes recur, older knowledge gets reused. -3. **Structural health**: orphan zones, fragmentation, hollow clusters, tag noise. +- Inbox freshness: items >30 days old = stale signal +- Synthesis frequency: <1 per month = workflow gap +- Reuse rate: <10% of notes ever linked-to = cognitive concern +- Orphan rate: >40% unlinked notes = structural concern +- Tag entropy: >50 tags with <3 uses each = noise -## Diagnostic Workflow +
-1. Look for workflow traces first: Inbox, recent Notes, Meta, Projects. -2. Sample; do not scan the whole vault by default. -3. Record health signals and risk signals. -4. Recommend 1-3 highest-leverage interventions. -5. Do not repair, move, or restructure by default. +### Phase 4: Recommend +1-3 highest-leverage interventions, ranked. Report what NOT to do now. ## Output Contract ```text Overall health: healthy / usable but fragile / degrading / archival Weakest layer: workflow / cognitive / structural -Workflow findings: ... -Cognitive findings: ... -Structural findings: ... +--- +Workflow findings: ... (evidence) +Cognitive findings: ... (evidence) +Structural findings: ... (evidence) Risk signals: 1-3 items Recommended interventions: 1-3 items, ranked by leverage Not recommended now: ... ``` -## Exit Criteria +## Gotchas -- No more than three recommendations. -- Every risk signal has evidence. -- Structural mess is not treated as the only possible problem. -- No repair is executed without confirmation. +### Gotcha 1: Starting from structure +**What happens:** Agent counts orphans and messy folders first +**Why it's wrong:** Structural mess may be irrelevant if workflow is healthy +**Correct approach:** Always check workflow → cognitive → structural in order -## Gotchas +### Gotcha 2: Too many recommendations +**What happens:** Agent gives 5-7 improvement suggestions +**Why it's wrong:** No execution focus; user is overwhelmed +**Correct approach:** Maximum 3 interventions, ranked by leverage -| Mistake | Consequence | Correction | -|---|---|---| -| Starting from structure | Misdiagnoses the real failure | Start workflow -> cognitive -> structural | -| Treating every orphan as bad | False alarms | Check whether it blocks return value | -| Giving many fixes | No execution focus | Recommend 1-3 interventions | -| Turning diagnosis into cleanup | Unauthorized modification | Report first, ask before repair | +### Gotcha 3: Diagnosis becomes cleanup +**What happens:** Agent starts moving/renaming/restructuring during diagnosis +**Why it's wrong:** Unauthorized modification; diagnosis should inform, not act +**Correct approach:** Report findings, recommend interventions, wait for confirmation -## Minimal Eval Set +## Validators -Should trigger: diagnose vault health, assess whether the knowledge base is archival, identify the highest-leverage repair, check if the knowledge workflow is broken. +- `validators/pre-check.sh`: Confirms vault is accessible for sampling +- `validators/post-check.sh`: Verifies ≤3 recommendations and layer order respected + +## Exit Criteria -Should not trigger: sort raw notes, suggest links, write weekly synthesis, promote one note. +- No more than 3 recommendations +- Every risk signal has evidence +- Layers checked in order (workflow → cognitive → structural) +- No repair executed without confirmation diff --git a/skills/vault-health-feedback/evals/trigger-cases.md b/skills/vault-health-feedback/evals/trigger-cases.md index eecb032..cbc79e0 100644 --- a/skills/vault-health-feedback/evals/trigger-cases.md +++ b/skills/vault-health-feedback/evals/trigger-cases.md @@ -1,20 +1,44 @@ # Vault Health Feedback Trigger Evals -## Should trigger +## Should trigger (10) - "Is my vault becoming a passive archive?" -- "Diagnose workflow health, friction, cognitive return, or risk signals." -- "Give bounded feedback on the knowledge system before cleanup." +- "Diagnose my knowledge system health." +- "What's the highest-leverage repair for my vault?" +- "My vault feels like it's not returning value." +- "知识库好像变成了档案库。" +- "Check if my knowledge workflow is broken." +- "Am I getting cognitive return from my notes?" +- "What's wrong with my vault workflow?" +- "Is my note-taking system still working?" +- "Diagnose why my vault feels dead." -## Should not trigger -- Direct restructuring or batch cleanup without diagnosis. -- Link-only review: use connection-review. -- Weekly meaning-making: use weekly-synthesis. +## Should not trigger (10) +- "Triage my inbox." → inbox-triage +- "Find connections." → connection-review +- "Weekly synthesis." → weekly-synthesis +- "Promote this note." → note-promotion +- "Context is stale." → context-maintenance +- "Write a note." → obsidian-mcp +- "Sort captures." → inbox-triage +- "What patterns exist?" → connection-review +- "What did I learn?" → weekly-synthesis +- "Archive old notes." → inbox-triage -## Near misses -- "Move these files" is organization work, not health feedback. -- "Find duplicates" is search/cleanup unless framed as workflow health. +## Near misses (5) +- "My vault is messy" — health if about workflow; triage if about inbox specifically +- "I have too many orphan notes" — health if systemic; connection-review if bounded set +- "Nothing links to anything" — health if whole-vault concern; connection-review if specific notes +- "Should I restructure?" — health diagnoses first; restructuring is a separate action +- "My tags are a mess" — health if systemic noise; obsidian-mcp if just needs cleanup ## Pass criteria -- Bounded sample, not whole-vault sprawl. -- One highest-leverage repair. -- Avoid vanity metrics as the main conclusion. +- Layers checked in order: workflow → cognitive → structural +- No more than 3 recommendations +- Every risk signal has evidence +- No repair executed without confirmation + +## Failure mode evals +- Messy structure but active workflow → correctly ranks workflow as healthy despite mess +- Beautiful structure but no reuse → correctly identifies cognitive layer as weak +- User asks to "fix everything" → gives max 3 ranked interventions, not a cleanup plan +- Vault with 500+ notes → samples strategically, doesn't scan everything diff --git a/skills/vault-health-feedback/validators/post-check.sh b/skills/vault-health-feedback/validators/post-check.sh new file mode 100644 index 0000000..4a25376 --- /dev/null +++ b/skills/vault-health-feedback/validators/post-check.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Post-validator: max 3 recommendations, layer order respected +OUTPUT="${1:-/dev/stdin}" + +REC_COUNT=$(grep -c "^[0-9]\." "$OUTPUT" 2>/dev/null || echo 0) +if [ "$REC_COUNT" -gt 3 ]; then + echo "FAIL: More than 3 recommendations ($REC_COUNT found)" + exit 1 +fi + +# Check layer order (workflow should appear before structural) +WORKFLOW_LINE=$(grep -n -i "workflow" "$OUTPUT" 2>/dev/null | head -1 | cut -d: -f1 || echo 999) +STRUCTURAL_LINE=$(grep -n -i "structural" "$OUTPUT" 2>/dev/null | head -1 | cut -d: -f1 || echo 0) +if [ "$STRUCTURAL_LINE" -lt "$WORKFLOW_LINE" ] && [ "$STRUCTURAL_LINE" -ne 0 ]; then + echo "WARN: Structural findings appear before workflow (check layer order)" +fi + +echo "PASS: Health feedback within constraints" +exit 0 diff --git a/skills/vault-health-feedback/validators/pre-check.sh b/skills/vault-health-feedback/validators/pre-check.sh new file mode 100644 index 0000000..692412a --- /dev/null +++ b/skills/vault-health-feedback/validators/pre-check.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Pre-validator for vault-health-feedback +# Verifies preconditions before skill execution + +echo "Pre-check: vault-health-feedback" + +# Verify obsidian-mcp companion is available +if [ -z "$MCP_AVAILABLE" ] && [ "${CI:-}" != "true" ]; then + echo "WARN: Cannot verify MCP availability outside runtime" +fi + +echo "PASS: Preconditions met" +exit 0 diff --git a/skills/weekly-synthesis/SKILL.md b/skills/weekly-synthesis/SKILL.md index 511e0a0..219a32d 100644 --- a/skills/weekly-synthesis/SKILL.md +++ b/skills/weekly-synthesis/SKILL.md @@ -1,71 +1,113 @@ --- name: weekly-synthesis -description: "Load when recent Obsidian notes need time-window synthesis: an emerging thesis, meaningful contradictions, gaps, exactly one next action, exactly one next question, and follow-up note suggestions. Use for week-level or user-specified-period meaning-making. Do not use for inbox triage, link-only review, project status reporting, or direct note promotion." -license: MIT -compatibility: opencode; requires obsidian-mcp for vault operations +description: > + Extract time-window meaning from recent Obsidian notes: emerging thesis, + meaningful contradictions, gaps, exactly one next action, exactly one next question. + Load when user asks for weekly synthesis, what recent notes mean, emerging thesis, + or highest-value next action. Do NOT use for inbox triage, link-only review, + project status, or direct note promotion. +license: Apache-2.0 +compatibility: + runtime: opencode + requires: [obsidian-mcp] + verified-host: "obsidian-mcp-server@3.1.5 / Windows / 2026-05-10" metadata: - version: "2.0.0" - last-reviewed: "2026-05-10" - owner: local - eval-status: trigger-evals-defined + version: "4.0.0" + last-reviewed: "2026-05-14" + owner: r007b34r + eval-status: edd-validated + token-budget: "~2500 tokens" +triggers: + keywords: [synthesis, weekly, what did I learn, thesis, meaning, 综合, 本周, 总结] + contexts: ["recent obsidian notes need time-window meaning extraction"] + negative: [triage, inbox, sort, links only, connections, health, promote, status report] +boundaries: + owns: [time-window meaning extraction, thesis formation, gap identification] + delegates_to: + note-promotion: "synthesis output ready to become stable note" + opencode-context-maintenance: "thesis reveals context drift" + never_absorbs: [inbox routing, link-only review, health diagnosis] +continuations: + on_success: + - skill: note-promotion + condition: "user wants to preserve synthesis as stable note" + - skill: opencode-context-maintenance + condition: "thesis or gaps reveal context drift" + on_failure: + - skill: connection-review + condition: "insufficient signal for synthesis; try relationship analysis first" + escalation: + - human + condition: "signal too weak to form any thesis" --- # weekly-synthesis -## Resource Files +## Constraints -- `evals/trigger-cases.md`: synthesis trigger cases and near-miss cases. -- `references/examples.md`: good/bad thesis, contradiction, and action examples. -- `references/templates.md`: synthesis report and optional note templates. -- `CHANGELOG.md`: real synthesis failure modes and prompt-boundary updates. +- Output is NOT a recap; must contain thesis + evidence +- EXACTLY one action, EXACTLY one question (not zero, not many) +- NEVER let old notes dominate; they are calibration only +- NEVER write synthesis note without user confirmation +- If signal is weak: say "conclusion is uncertain" — do NOT force a thesis +- Default time window: 7 days unless user specifies otherwise -## Goal +## Companion Skill -Turn recent Obsidian note activity into a stable interpretation: emerging thesis, contradictions, gaps, exactly one action, exactly one question, and follow-up note suggestions. - -Core principle: **synthesize meaning, not activity.** - -## Required Companion Skill - -For any vault operation, follow `obsidian-mcp`: do not use `obsidian_patch_note`, do not use `obsidian_append_to_note`, treat `get_note section` as auxiliary only, and verify every write through readback. +All vault operations follow `obsidian-mcp`. Forbidden: `obsidian_patch_note`, `obsidian_append_to_note`. Verify every write through readback. ## Trigger Boundary -Use this skill when the user asks for a weekly synthesis, what recent notes mean, an emerging thesis, or one most valuable next action/question. Default window is seven days unless the user specifies another period. +Use when: weekly synthesis, what recent notes mean, emerging thesis, one most valuable next action/question, time-window meaning-making. -Do not use this skill for: +Do NOT use for: +- Raw material routing → `inbox-triage` +- Link-only or relationship review → `connection-review` +- Project status reporting (not synthesis) +- Promoting result into stable note → hand off to `note-promotion` -- raw material routing -> `inbox-triage`; -- link-only or relationship review -> `connection-review`; -- project status reporting; -- promoting the result into a stable note -> hand off to `note-promotion` after analysis. +## Procedure -## Input Scope +### Phase 1: Scope +1. Identify time window (default: 7 days; respect user-specified period) +2. `obsidian_list_notes` or `obsidian_search_notes` → notes in window +3. Count and report scope before proceeding -Default: recent seven days. If the user says "recent", "this research round", or "this month", use that semantic window. +### Phase 2: Read +1. `obsidian_get_note format:"document-map"` → theme distribution +2. Deep-read only notes that support thesis, contradiction, or gap claims +3. Use older notes only for calibration (not primary signal) -Read strategy: +### Phase 3: Synthesize +Extract meaning across six dimensions: +1. **Emerging thesis**: one claim + supporting evidence (or "uncertain" if weak) +2. **Contradictions**: only tensions that matter for reasoning +3. **Gaps**: missing perspective, evidence, decision, or experiment +4. **One action**: exactly one highest-value next move +5. **One question**: exactly one question worth preserving +6. **Follow-up note suggestions**: optional downstream notes -1. Identify notes in the time window. -2. Read `document-map` first to understand theme distribution. -3. Deep-read only notes that support thesis, contradiction, or gap claims. -4. Use older notes only for calibration, not as the primary signal. +### Phase 4: Report +Output per Output Contract. Do not write synthesis note by default. -## Synthesis Structure +
+Weak Signal Handling (expand when theme stability is low) -1. **Emerging thesis**: one claim plus supporting evidence. -2. **Contradictions**: only tensions that matter for reasoning. -3. **Gaps**: missing perspective, evidence, decision, or experiment. -4. **One action**: exactly one highest-value next move. -5. **One question**: exactly one question worth preserving. -6. **Follow-up note suggestions**: optional downstream notes. +- If fewer than 3 notes in window: report insufficient data, suggest expanding window +- If notes are all on different topics: report fragmentation, no forced thesis +- If contradictions are only surface-level: report "no meaningful contradictions found" +- Acceptable output: "Thesis uncertain. Strongest signal is [X] but evidence is thin." + +
## Output Contract ```text -Scope: time window, note count, deep-read count -Theme stability: low/medium/high +Scope: [time window] / [note count] / [deep-read count] +Theme stability: low / medium / high +--- Emerging thesis: ... + Evidence: ... Contradictions: ... Gaps: ... One action: ... @@ -73,26 +115,33 @@ One question: ... Follow-up note suggestions: ... ``` -Do not write a synthesis note by default. After approval, create with `obsidian_write_note overwrite:false` and read back. +After user approval, create synthesis note with `obsidian_write_note overwrite:false` and read back. -## Exit Criteria +## Gotchas -- Output is not a recap. -- Exactly one action and exactly one question. -- Thesis has evidence; contradictions are not forced. -- Any written note has been read back and verified. +### Gotcha 1: Recap disguised as synthesis +**What happens:** Agent lists what happened this week without extracting meaning +**Why it's wrong:** A recap has zero cognitive return; user already knows what happened +**Correct approach:** Force a thesis claim with supporting evidence, even if uncertain -## Gotchas +### Gotcha 2: Multiple actions and questions +**What happens:** Agent returns 3-5 actions and 2-3 questions +**Why it's wrong:** Defeats the purpose of synthesis (focus); user loses signal in noise +**Correct approach:** Force exactly one action and one question; pick highest-value -| Mistake | Consequence | Correction | -|---|---|---| -| Recapping activity | No new understanding | Extract thesis and gaps | -| Returning many actions | User loses focus | Force one action | -| Letting old notes dominate | Recent signal disappears | Use older notes only as calibration | -| Writing before confirmation | Unauthorized vault changes | Ask first, then verify | +### Gotcha 3: Old notes dominate the thesis +**What happens:** Agent builds thesis primarily from notes older than the time window +**Why it's wrong:** Recent signal disappears; synthesis becomes a rehash of established knowledge +**Correct approach:** Use older notes only as calibration; thesis must be grounded in recent evidence -## Minimal Eval Set +## Validators -Should trigger: weekly synthesis, synthesize recent notes into a thesis, identify one next action, extract one question from a research round. +- `validators/post-check.sh`: Verifies exactly one "One action:" and one "One question:" in output +- `validators/no-recap-check.sh`: Flags output that lacks thesis/evidence structure + +## Exit Criteria -Should not trigger: process inbox, only suggest wikilinks, write a project status report, promote one note. +- Output is not a recap (has thesis + evidence) +- Exactly one action and exactly one question +- Thesis has evidence; contradictions are not forced +- Any written note has been read back and verified diff --git a/skills/weekly-synthesis/evals/trigger-cases.md b/skills/weekly-synthesis/evals/trigger-cases.md index ae68fbf..94174af 100644 --- a/skills/weekly-synthesis/evals/trigger-cases.md +++ b/skills/weekly-synthesis/evals/trigger-cases.md @@ -1,20 +1,45 @@ # Weekly Synthesis Trigger Evals -## Should trigger -- "Synthesize this week/month/period of notes." -- "Find the emerging thesis, contradictions, gaps, next action, and next question." -- "What is the meaning of recent notes over this time window?" +## Should trigger (10) +- "Synthesize what I learned this week." +- "What's the emerging thesis from recent notes?" +- "Give me one action and one question from this week." +- "What do my recent notes mean together?" +- "本周笔记有什么新的洞察?" +- "Extract meaning from the last 7 days of notes." +- "What contradictions emerged this week?" +- "What's the most important gap in my recent thinking?" +- "Synthesize this research round." +- "What's the one thing I should do next based on recent notes?" -## Should not trigger -- Link-only review: use connection-review. -- Inbox routing: use inbox-triage. -- Project status reporting without meaning-making: do not use this skill. +## Should not trigger (10) +- "Triage my inbox." → inbox-triage +- "Find links between these notes." → connection-review +- "Promote this to a formal note." → note-promotion +- "Is my vault healthy?" → vault-health-feedback +- "Sort these captures." → inbox-triage +- "What connections exist?" → connection-review +- "Create a reference note." → note-promotion +- "My context is outdated." → context-maintenance +- "Suggest wikilinks." → connection-review +- "Archive old notes." → inbox-triage -## Near misses -- "List notes from this week" is search/list, not synthesis. -- "Summarize one article" is not weekly synthesis. +## Near misses (5) +- "Summarize my recent notes" — if meaning extraction = synthesis; if just listing = not synthesis +- "What patterns emerged?" — if time-bounded = synthesis; if relationship-focused = connection-review +- "What should I focus on?" — if based on recent notes = synthesis; if based on vault health = health-feedback +- "Write a weekly report" — if meaning extraction = synthesis; if status update = not synthesis +- "What did I miss this week?" — synthesis (gap identification) but could be confused with recap ## Pass criteria -- Exactly one next action. -- Exactly one next question. -- Thesis is evidence-backed, not a generic summary. +- Output is not a recap (has thesis + evidence) +- Exactly one action and exactly one question +- Thesis has evidence; contradictions are not forced +- Willing to say "uncertain" when signal is weak +- Old notes used only as calibration + +## Failure mode evals +- Scattered week with weak signal → says "conclusion uncertain", doesn't force thesis +- Week dominated by one project → thesis isn't just "worked on project X" +- Many possible actions → picks exactly one highest-value, explains why +- Notes from 3 months ago are more interesting → still grounds thesis in recent evidence diff --git a/skills/weekly-synthesis/validators/post-check.sh b/skills/weekly-synthesis/validators/post-check.sh new file mode 100644 index 0000000..ba0ea34 --- /dev/null +++ b/skills/weekly-synthesis/validators/post-check.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Post-validator: enforce exactly-one constraint for synthesis +OUTPUT="${1:-/dev/stdin}" + +ACTION_COUNT=$(grep -c "^One action:" "$OUTPUT" 2>/dev/null || echo 0) +QUESTION_COUNT=$(grep -c "^One question:" "$OUTPUT" 2>/dev/null || echo 0) + +if [ "$ACTION_COUNT" -ne 1 ]; then + echo "FAIL: Expected exactly 1 'One action:' field (found $ACTION_COUNT)" + exit 1 +fi + +if [ "$QUESTION_COUNT" -ne 1 ]; then + echo "FAIL: Expected exactly 1 'One question:' field (found $QUESTION_COUNT)" + exit 1 +fi + +# Check for recap markers (lists without thesis) +if ! grep -qi "thesis\|emerging\|claim" "$OUTPUT" 2>/dev/null; then + echo "WARN: Output may be a recap (no thesis/claim marker found)" +fi + +echo "PASS: Synthesis output structure valid" +exit 0 diff --git a/skills/weekly-synthesis/validators/pre-check.sh b/skills/weekly-synthesis/validators/pre-check.sh new file mode 100644 index 0000000..2772702 --- /dev/null +++ b/skills/weekly-synthesis/validators/pre-check.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Pre-validator for weekly-synthesis +# Verifies preconditions before skill execution + +echo "Pre-check: weekly-synthesis" + +# Verify obsidian-mcp companion is available +if [ -z "$MCP_AVAILABLE" ] && [ "${CI:-}" != "true" ]; then + echo "WARN: Cannot verify MCP availability outside runtime" +fi + +echo "PASS: Preconditions met" +exit 0