From a23d9932a2c9489746a603d56ab14747c615f000 Mon Sep 17 00:00:00 2001 From: Qiang Xue <126648675+qxbyte@users.noreply.github.com> Date: Tue, 30 Jun 2026 01:15:20 +0800 Subject: [PATCH] =?UTF-8?q?release:=20specode=205.0.1=20=E2=80=94=20distil?= =?UTF-8?q?l=20=E6=94=B6=E6=95=9B=20md-only=20+=20=E9=9A=90=E8=97=8F=20+?= =?UTF-8?q?=20=E6=B8=85=E7=90=86=20.ai-memory/codemap=20=E6=AE=8B=E7=95=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 把 distill 彻底收敛为「纯 md-only Obsidian 整理器」,并清掉全仓最后的记忆注入文档残留。 Changed: - skills/distill/SKILL.md: 加 user-invocable:false → 斜杠菜单不再有裸 /distill, 且消除「命令 + 同名可见 skill」造成的 /specode:distill 重复(只留命令一条) - distill 收敛纯 md-only: 移除 --format md|yml|both + codemap knowledge write 写入器路径 (yml 唯一消费者 codemap recall 早在 v4.0.0 删除,yml 无人读取) Removed/cleaned 文档死引用: - assets/templates/requirements.md: 删已废弃的「## 已知约束/历史坑」recall 注入段 (v4.0.0 已移除该注入,SKILL 早声明不再含此段,模板未同步 → 会盖进每个新 spec) - skills/distill/references/doc-template.md: 重写为 v5 md-only 模板(删 yml schema / .ai-memory 路径表 / codemap 写入器,frontmatter 对齐 SKILL Obsidian 风格,留 5 类模板正文) - skills/distill/references/breakdown-heuristics.md: 剥 .ai-memory/codemap/yml/supersede,留 5 维方法论 - commands/spec.md / skills/specode/references/obsidian.md / tests/test_project_root.py: project_root 去掉过时的 .ai-memory/knowledge feeds + codemap recall 措辞 - commands/distill.md: 移除 --format flag 全量复核: 除 CHANGELOG 历史 + 「已移除 X」迁移说明外,仓库不再把 .ai-memory / codemap knowledge write / yml-pipeline 描述成现行行为。 verify: version-sync gate ✓ (specode@5.0.1) · pytest ✓ 233 passed Co-Authored-By: Claude Opus 4.8 (1M context) Co-Authored-By: Qiang Xue <126648675+qxbyte@users.noreply.github.com> --- .claude-plugin/marketplace.json | 4 +- CLAUDE.md | 6 +- README.md | 4 +- README.zh-CN.md | 4 +- plugins/specode/.claude-plugin/plugin.json | 4 +- plugins/specode/CHANGELOG.md | 19 + .../specode/assets/templates/requirements.md | 7 - plugins/specode/commands/distill.md | 2 +- plugins/specode/skills/distill/SKILL.md | 36 +- .../references/breakdown-heuristics.md | 38 +- .../skills/distill/references/doc-template.md | 338 ++++-------------- .../skills/specode/references/obsidian.md | 2 +- plugins/specode/tests/test_project_root.py | 2 +- 13 files changed, 143 insertions(+), 323 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index a60e750..c23eb97 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,8 +9,8 @@ { "name": "specode", "source": "./plugins/specode", - "version": "5.0.0", - "description": "Lightweight spec-driven workflow: orchestrates superpowers skills per phase, lands 3 fixed docs (requirements/design/implementation-log). **v5.0.0 BREAKING**: 命令去 `specode-` 前缀 — `/specode:spec` / `/specode:continue` / `/specode:list` / `/specode:distill`(原 `/specode:specode-*`);内核 skill 加 `user-invocable:false` 隐藏裸 `/specode`。**v4.0.0 BREAKING**: 彻底拔出记忆注入工程 — 砍 P3-1 codemap recall / P3-2 rule-check / acceptance auto-distill prompt。保留 project-level CLAUDE.md scan。distill v4 完全重写为手动 md-only Obsidian wiki organizer, 默认写 `/Volumes/External HD/Obsidian/Notes/11-KnowledgeBase//`。如需 v3 行为 checkout `backup/specode-v3.4.0-task-swarm-v0.9.2`。", + "version": "5.0.1", + "description": "Lightweight spec-driven workflow: orchestrates superpowers skills per phase, lands 3 fixed docs (requirements/design/implementation-log). **v5.0.1**: distill skill 加 `user-invocable:false`(隐藏裸 `/distill` + 消除 `/specode:distill` 重复);distill 收敛为纯 md-only(移除 `--format yml|both` + codemap 死路径);清理全部 `.ai-memory`/codemap 文档残留 + requirements 模板删 recall 段。**v5.0.0 BREAKING**: 命令去 `specode-` 前缀 — `/specode:spec` / `/specode:continue` / `/specode:list` / `/specode:distill`(原 `/specode:specode-*`);内核 skill 加 `user-invocable:false` 隐藏裸 `/specode`。**v4.0.0 BREAKING**: 彻底拔出记忆注入工程 — 砍 P3-1 codemap recall / P3-2 rule-check / acceptance auto-distill prompt。保留 project-level CLAUDE.md scan。distill v4 完全重写为手动 md-only Obsidian wiki organizer, 默认写 `/Volumes/External HD/Obsidian/Notes/11-KnowledgeBase//`。如需 v3 行为 checkout `backup/specode-v3.4.0-task-swarm-v0.9.2`。", "homepage": "https://github.com/qxbyte/pluginhub", "repository": "https://github.com/qxbyte/pluginhub", "license": "MIT", diff --git a/CLAUDE.md b/CLAUDE.md index 3d2f4af..8bb3fab 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co A **three-plugin** marketplace for Claude Code and CodeBuddy CLIs. The root is only the marketplace shell; each plugin under `plugins//` is self-contained with its own `plugin.json`, skills, scripts, tests, and CHANGELOG. -- **specode** (`plugins/specode/`, v5.0.0) — a **lightweight spec-driven workflow plugin**. It is not a state machine: it is a thin **orchestration shell** (壳) that walks a host agent through a phase pipeline (requirements → design → 执行方式 → 执行 → 验收) and, at each phase, **delegates the heavy lifting to superpowers skills** (`brainstorming` / `writing-plans` / `subagent-driven-development` / `executing-plans` / `verification-before-completion`). When superpowers is absent, specode falls back to a **specode-native** path (first-class, not an afterthought). It produces **3 fixed documents** (`requirements.md` / `design.md` / `implementation-log.md`) under the user's specs directory. **This is the plugin this `CLAUDE.md` documents** unless stated otherwise. +- **specode** (`plugins/specode/`, v5.0.1) — a **lightweight spec-driven workflow plugin**. It is not a state machine: it is a thin **orchestration shell** (壳) that walks a host agent through a phase pipeline (requirements → design → 执行方式 → 执行 → 验收) and, at each phase, **delegates the heavy lifting to superpowers skills** (`brainstorming` / `writing-plans` / `subagent-driven-development` / `executing-plans` / `verification-before-completion`). When superpowers is absent, specode falls back to a **specode-native** path (first-class, not an afterthought). It produces **3 fixed documents** (`requirements.md` / `design.md` / `implementation-log.md`) under the user's specs directory. **This is the plugin this `CLAUDE.md` documents** unless stated otherwise. - **task-swarm** (`plugins/task-swarm/`, v0.10.1) — a standalone implementation-phase orchestrator (multi-coder fork + reviewer/validator state machine), extracted out of specode in milestone M1. It has its own CLI (`scripts/task_swarm/`), state machine, agents, skill, and CHANGELOG. specode hands off to it only via the user-chosen "委托 task-swarm" option in the 执行方式 selector, with **zero import** (calls task-swarm's own `/task-swarm:swarm` command). - **obsidian-wiki** (`plugins/obsidian-wiki/`, v2.0.0) — a **skills-only** plugin (no commands, no hooks) for maintaining an Obsidian LLM-Wiki: a deterministic structure layer (Home tree / per-dir READMEs / partition pages via `wiki-struct`), content curation (`wiki-curate`), and a unified orchestrator (`wiki-orchestrate`). Generic code + per-vault `.wiki/config.json`, zero hardcoded structure. Largely independent of the other two — its only historical tie is that the old spec→knowledge distill capability was **extracted out of it into specode's `distill`** in its own v2.0.0. @@ -91,7 +91,7 @@ specode has almost no runtime logic. The behavior lives in **`skills/specode/SKI Both superpowers and task-swarm are **soft dependencies** (run-time only, called via SKILL prose, zero import). specode installed alone must run the whole 启动→coding 完成 loop via the native fallbacks — the fallback path is a first-class peer of the superpowers path, not a footnote. ### `distill` — the off-pipeline 4th command -`/specode:distill []` is **not** part of the requirements→验收 pipeline and does **not** produce or touch the 3 fixed docs. It is a manual, user-triggered organizer (own command `commands/distill.md` + own skill `skills/distill/SKILL.md`) that converts a finished spec into **md-only** Obsidian knowledge notes (default `/Volumes/External HD/Obsidian/Notes/11-KnowledgeBase//`). As of v4.0.0 it has **no** machine-readable yml output (md-only default; `--format yml|both` opt-in), **no** codemap recall, and is **never auto-triggered** — treat it as a standalone wiki utility, not a workflow phase. The `distill` SKILL.md is authoritative for current behavior; the two `skills/distill/references/*.md` (breakdown-heuristics / doc-template) still carry v3-era `.ai-memory/` path framing and want a dedicated alignment pass. +`/specode:distill []` is **not** part of the requirements→验收 pipeline and does **not** produce or touch the 3 fixed docs. It is a manual, user-triggered organizer (own command `commands/distill.md` + own skill `skills/distill/SKILL.md`) that converts a finished spec into **md-only** Obsidian knowledge notes (default `/Volumes/External HD/Obsidian/Notes/11-KnowledgeBase//`). It is **md-only** (the yml / `codemap knowledge write` path was removed in 5.0.1 — its only consumer, codemap recall, was already gone since v4.0.0), takes **no** `.ai-memory`, and is **never auto-triggered** — treat it as a standalone wiki utility, not a workflow phase. The `distill` SKILL.md and both `skills/distill/references/*.md` (breakdown-heuristics / doc-template) are aligned to this md-only reality. ### The 3 fixed documents (硬约束) Whatever the execution engine, a spec **always** produces exactly these 3, with **fixed filenames**, **fixed location** `//`: @@ -138,7 +138,7 @@ Detailed steps are in CONTRIBUTING.md §Release. Each plugin releases **independ - `plugins//.claude-plugin/plugin.json` → `"version"` - `.claude-plugin/marketplace.json` → **that plugin's** entry's `version` (leave the other two entries alone) -Workflow (per plugin): bump both manifests → rename `## Unreleased` in the plugin's CHANGELOG to `## X.Y.Z (YYYY-MM-DD)` + add a fresh `## Unreleased` above → `python3 scripts/check_marketplace_versions.py` (must pass) → run that plugin's tests → commit + push → `claude plugin tag --dry-run plugins/` → `claude plugin tag plugins/ --push`. Tag format is `--v{version}` (annotated, e.g. `specode--v5.0.0`, `task-swarm--v0.10.1`). **Pushing the tag IS the release** — host CLIs fetch the marketplace manifest from GitHub by git tag. +Workflow (per plugin): bump both manifests → rename `## Unreleased` in the plugin's CHANGELOG to `## X.Y.Z (YYYY-MM-DD)` + add a fresh `## Unreleased` above → `python3 scripts/check_marketplace_versions.py` (must pass) → run that plugin's tests → commit + push → `claude plugin tag --dry-run plugins/` → `claude plugin tag plugins/ --push`. Tag format is `--v{version}` (annotated, e.g. `specode--v5.0.1`, `task-swarm--v0.10.1`). **Pushing the tag IS the release** — host CLIs fetch the marketplace manifest from GitHub by git tag. Semver "API surface" for **specode** = the four command names (`/specode:spec <需求>` / `/specode:continue ` / `/specode:list` / `/specode:distill []`), the `SessionStart` hook event, the persisted `config.json.specsRoot` field, and the 3 fixed document filenames. Removing/renaming any of these is **major**; adding a backwards-compatible capability is **minor**. diff --git a/README.md b/README.md index 84a96d6..c6fd250 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # pluginhub [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./README.md#license) -[![specode](https://img.shields.io/badge/specode-5.0.0-blue.svg)](./plugins/specode/.claude-plugin/plugin.json) +[![specode](https://img.shields.io/badge/specode-5.0.1-blue.svg)](./plugins/specode/.claude-plugin/plugin.json) [![task-swarm](https://img.shields.io/badge/task--swarm-0.10.1-blue.svg)](./plugins/task-swarm/.claude-plugin/plugin.json) [![obsidian-wiki](https://img.shields.io/badge/obsidian--wiki-2.0.0-blue.svg)](./plugins/obsidian-wiki/.claude-plugin/plugin.json) [![Claude Code](https://img.shields.io/badge/Claude%20Code-compatible-8A2BE2)](https://github.com/qxbyte/pluginhub#installation) @@ -20,7 +20,7 @@ any plugin it hosts. More plugins will land here over time. | Plugin | Version | What it does | | --- | --- | --- | -| **specode** | 5.0.0 | A lightweight spec-driven **workflow** — orchestration shell that delegates each phase to [superpowers](https://github.com/obra/superpowers) skills (first-class native fallback) and lands 3 fixed docs per spec. **v5.0.0 BREAKING**: commands dropped the redundant `specode-` prefix — `/specode:spec` / `/specode:continue` / `/specode:list` / `/specode:distill` (were `/specode:specode-*`); the `distill` skill dir + name were renamed to `distill`; the `specode` orchestration skill is now `user-invocable: false` so the bare `/specode` no longer shows in the slash menu (still auto-activates via its commands). Preserved AI-EDS-era features: project-level `CLAUDE.md` / `AGENT.md` filesystem scan injected as `## 项目级约束` section (痛点 #14 方案 D), SessionStart cache-vs-marketplace drift hint (M8), autonomous-mode defaults — 5 schema keys + 5 `SPECODE_*` env vars + `read-defaults` / `write-default` / `reset-default` verbs (M1+M9). **v4.0.0 BREAKING**: removed memory-injection pipeline — P3-1 `codemap recall` injection / P3-2 rule-acknowledgement post-check / acceptance auto-distill prompt all dropped; round 1/2 baseline showed the recall round-trip did not net save token. `distill` skill v4 rewritten as a **manual-only Obsidian organizer** — `/specode:distill ` writes md (default) to `/Volumes/External HD/Obsidian/Notes/11-KnowledgeBase//`, no `.ai-memory/` writes. To restore v3 behaviour: `git checkout backup/specode-v3.4.0-task-swarm-v0.9.2`. | +| **specode** | 5.0.1 | A lightweight spec-driven **workflow** — orchestration shell that delegates each phase to [superpowers](https://github.com/obra/superpowers) skills (first-class native fallback) and lands 3 fixed docs per spec. **v5.0.1**: the `distill` skill is now `user-invocable: false` (hides the bare `/distill` + the duplicate `/specode:distill`, leaving one clean command entry); distill is now **md-only** (dropped the dead `--format yml|both` + `codemap knowledge write` path); purged all remaining `.ai-memory`/codemap doc references and removed the obsolete recall section from the requirements template. **v5.0.0 BREAKING**: commands dropped the redundant `specode-` prefix — `/specode:spec` / `/specode:continue` / `/specode:list` / `/specode:distill` (were `/specode:specode-*`); the `distill` skill dir + name were renamed to `distill`; the `specode` orchestration skill is now `user-invocable: false` so the bare `/specode` no longer shows in the slash menu (still auto-activates via its commands). Preserved AI-EDS-era features: project-level `CLAUDE.md` / `AGENT.md` filesystem scan injected as `## 项目级约束` section (痛点 #14 方案 D), SessionStart cache-vs-marketplace drift hint (M8), autonomous-mode defaults — 5 schema keys + 5 `SPECODE_*` env vars + `read-defaults` / `write-default` / `reset-default` verbs (M1+M9). **v4.0.0 BREAKING**: removed memory-injection pipeline — P3-1 `codemap recall` injection / P3-2 rule-acknowledgement post-check / acceptance auto-distill prompt all dropped; round 1/2 baseline showed the recall round-trip did not net save token. `distill` skill v4 rewritten as a **manual-only Obsidian organizer** — `/specode:distill ` writes md (default) to `/Volumes/External HD/Obsidian/Notes/11-KnowledgeBase//`, no `.ai-memory/` writes. To restore v3 behaviour: `git checkout backup/specode-v3.4.0-task-swarm-v0.9.2`. | | **task-swarm** | 0.10.1 | Multi-agent **orchestration** driven by a `pipeline.yml`: semantic task groups with cross-group concurrency, fork coders, per-group reviewer + validator loops. **v0.10.1**: the `task-swarm` orchestration skill is now `user-invocable: false` so the bare `/task-swarm` no longer shows in the slash menu (the `/task-swarm:swarm` command is unchanged). Preserved AI-EDS-era features: frontmatter-first `project_root` + registry-based run lookup (0.7.x), `## 项目级约束(必读)` section + `_PROJECT_AGENT_DOCS.md` inbox sentinel (0.7.3 + 0.7.4), lifecycle group with `init` dedupe (`--on-existing {error/resume/abort-old/force-new}` flag) + `run.pipeline_end_validator` (0.8.0 + 0.8.1), M2 `run-loop` auto-driver (0.8.1), task.md `## 开发纪律 (范式参考)` section listing superpowers skill names as paradigm identifiers (0.9.0–0.9.2). **v0.10.0 BREAKING**: removed `_ingest_lessons.py` + `cmd_resolve` auto-ingest + `--no-ingest` flag — `cmd_resolve` no longer writes `/.ai-memory/knowledge/cases\|pitfalls/*.yml`. To restore v0.9.x behaviour: `git checkout backup/specode-v3.4.0-task-swarm-v0.9.2`. See [`plugins/task-swarm/`](./plugins/task-swarm). | | **obsidian-wiki** | 2.0.0 | Maintain an Obsidian LLM-Wiki: deterministic structure layer (Home tree / READMEs / partition pages), SpecIn → knowledge-base distillation + MEMORY, content curation (lint / ingest / curate), unified orchestrator. Generic + per-vault `.wiki/config.json`. See [`plugins/obsidian-wiki/`](./plugins/obsidian-wiki). | diff --git a/README.zh-CN.md b/README.zh-CN.md index 54c46cd..6f94d65 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -3,7 +3,7 @@ # pluginhub [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./README.zh-CN.md#许可证) -[![specode](https://img.shields.io/badge/specode-5.0.0-blue.svg)](./plugins/specode/.claude-plugin/plugin.json) +[![specode](https://img.shields.io/badge/specode-5.0.1-blue.svg)](./plugins/specode/.claude-plugin/plugin.json) [![task-swarm](https://img.shields.io/badge/task--swarm-0.10.1-blue.svg)](./plugins/task-swarm/.claude-plugin/plugin.json) [![obsidian-wiki](https://img.shields.io/badge/obsidian--wiki-2.0.0-blue.svg)](./plugins/obsidian-wiki/.claude-plugin/plugin.json) [![Claude Code](https://img.shields.io/badge/Claude%20Code-compatible-8A2BE2)](https://github.com/qxbyte/pluginhub#installation) @@ -18,7 +18,7 @@ | 插件 | 版本 | 做什么 | | --- | --- | --- | -| **specode** | 5.0.0 | 轻量**规格驱动工作流**——编排外壳,每个阶段委托给 [superpowers](https://github.com/obra/superpowers) 技能(一等公民原生降级),每条规格固定产出 3 份文档。**v5.0.0 BREAKING**:命令去掉冗余 `specode-` 前缀——`/specode:spec` / `/specode:continue` / `/specode:list` / `/specode:distill`(原 `/specode:specode-*`);`distill` skill 目录与 `name` 同改为 `distill`;编排内核 skill `specode` 改为 `user-invocable: false`,斜杠菜单不再显示裸 `/specode`(仍经命令自动激活)。AI-EDS 时代保留至 v4.0.0 的能力:项目级 `CLAUDE.md` / `AGENT.md` filesystem 扫描注入「## 项目级约束」段(痛点 #14 方案 D)、SessionStart cache 与 marketplace drift 提示(M8)、autonomous-mode defaults(5 schema key + 5 个 `SPECODE_*` env var + `read-defaults` / `write-default` / `reset-default` verb,M1+M9)。**v4.0.0 BREAKING**:拔除记忆注入工程——P3-1 `codemap recall` 注入 / P3-2 rule-acknowledgement post-check / acceptance 后自动 distill 全部砍掉;round 1/2 baseline 实验证明 recall 注入未 net 节省 token。`distill` skill v4 完全重写为**仅手动**Obsidian 整理器——`/specode:distill ` 默认 md-only 写到 `/Volumes/External HD/Obsidian/Notes/11-KnowledgeBase//`,不再写 `.ai-memory/`。如需 v3 行为:`git checkout backup/specode-v3.4.0-task-swarm-v0.9.2`。 | +| **specode** | 5.0.1 | 轻量**规格驱动工作流**——编排外壳,每个阶段委托给 [superpowers](https://github.com/obra/superpowers) 技能(一等公民原生降级),每条规格固定产出 3 份文档。**v5.0.1**:`distill` skill 改为 `user-invocable: false`(隐藏裸 `/distill` 与重复的 `/specode:distill`,只留命令一条);distill 收敛为纯 **md-only**(移除已死的 `--format yml|both` 与 `codemap knowledge write` 路径);清理全部 `.ai-memory`/codemap 文档残留,并从 requirements 模板删除已废弃的 recall 段。**v5.0.0 BREAKING**:命令去掉冗余 `specode-` 前缀——`/specode:spec` / `/specode:continue` / `/specode:list` / `/specode:distill`(原 `/specode:specode-*`);`distill` skill 目录与 `name` 同改为 `distill`;编排内核 skill `specode` 改为 `user-invocable: false`,斜杠菜单不再显示裸 `/specode`(仍经命令自动激活)。AI-EDS 时代保留至 v4.0.0 的能力:项目级 `CLAUDE.md` / `AGENT.md` filesystem 扫描注入「## 项目级约束」段(痛点 #14 方案 D)、SessionStart cache 与 marketplace drift 提示(M8)、autonomous-mode defaults(5 schema key + 5 个 `SPECODE_*` env var + `read-defaults` / `write-default` / `reset-default` verb,M1+M9)。**v4.0.0 BREAKING**:拔除记忆注入工程——P3-1 `codemap recall` 注入 / P3-2 rule-acknowledgement post-check / acceptance 后自动 distill 全部砍掉;round 1/2 baseline 实验证明 recall 注入未 net 节省 token。`distill` skill v4 完全重写为**仅手动**Obsidian 整理器——`/specode:distill ` 默认 md-only 写到 `/Volumes/External HD/Obsidian/Notes/11-KnowledgeBase//`,不再写 `.ai-memory/`。如需 v3 行为:`git checkout backup/specode-v3.4.0-task-swarm-v0.9.2`。 | | **task-swarm** | 0.10.1 | 由 `pipeline.yml` 驱动的**多 agent 编排**:语义任务组 + 跨组并发、fork coder、按组 reviewer + validator 循环。**v0.10.1**:编排内核 skill `task-swarm` 改为 `user-invocable: false`,斜杠菜单不再显示裸 `/task-swarm`(命令 `/task-swarm:swarm` 不变)。AI-EDS 时代保留至 v0.10.0 的能力:frontmatter-first `project_root` + registry-based run 查找(0.7.x)、coder/reviewer/validator `task.md` 中「## 项目级约束(必读)」段 + `_PROJECT_AGENT_DOCS.md` inbox sentinel(0.7.3+0.7.4)、lifecycle group + `init` dedupe(`--on-existing` flag)+ `run.pipeline_end_validator`(0.8.0+0.8.1)、M2 `run-loop` 自动驱动器(0.8.1)、task.md 「## 开发纪律 (范式参考)」段列出 superpowers skill 名作为范式标识(0.9.0–0.9.2)。**v0.10.0 BREAKING**:拔除记忆注入工程——删 `_ingest_lessons.py` + `cmd_resolve` 自动 ingest + `--no-ingest` flag,`cmd_resolve` 不再写 `/.ai-memory/knowledge/cases\|pitfalls/*.yml`。如需 v0.9.x 行为:`git checkout backup/specode-v3.4.0-task-swarm-v0.9.2`。详见 [`plugins/task-swarm/`](./plugins/task-swarm)。 | | **obsidian-wiki** | 2.0.0 | 维护 Obsidian LLM-Wiki:确定性结构层(Home 树 / README / 分区页)、SpecIn → knowledge-base 蒸馏 + MEMORY、内容养护(lint / ingest / curate)、统一编排器。通用代码 + 按 vault 配 `.wiki/config.json`。详见 [`plugins/obsidian-wiki/`](./plugins/obsidian-wiki)。 | diff --git a/plugins/specode/.claude-plugin/plugin.json b/plugins/specode/.claude-plugin/plugin.json index 31450f8..f790f57 100644 --- a/plugins/specode/.claude-plugin/plugin.json +++ b/plugins/specode/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "specode", - "version": "5.0.0", - "description": "Lightweight spec-driven workflow: orchestrates superpowers skills per phase, lands 3 fixed docs (requirements/design/implementation-log). **v5.0.0 BREAKING**: 命令去 `specode-` 前缀 — `/specode:spec` / `/specode:continue` / `/specode:list` / `/specode:distill`(原 `/specode:specode-*`);distill skill 目录与名同改为 `distill`;编排内核 skill `specode` 加 `user-invocable:false`,斜杠菜单不再显示裸 `/specode`(仍经命令/自然语言自动激活)。**v4.0.0 BREAKING**: 彻底拔出记忆注入工程 — 砍掉 specode 主流程的 (1) P3-1 codemap recall 注入 `## 已知约束 / 历史坑` 段, (2) P3-2 rule-acknowledgement post-check, (3) acceptance 后自动 AskUser 触发 distill。round 1/2 baseline 实验证明 recall 注入未 net 节省 token。保留 project-level CLAUDE.md / AGENT.md filesystem scan (不涉及 .ai-memory)。distill skill v4 完全重写: 仅手动触发 `/specode:distill `, 默认 md-only, 默认写 `/Volumes/External HD/Obsidian/Notes/11-KnowledgeBase//` (--target-dir 可覆盖), 不再调 codemap recall, 不再默认写 .ai-memory yml。如需 v3 记忆注入行为, checkout `backup/specode-v3.4.0-task-swarm-v0.9.2`。", + "version": "5.0.1", + "description": "Lightweight spec-driven workflow: orchestrates superpowers skills per phase, lands 3 fixed docs (requirements/design/implementation-log). **v5.0.1**: distill skill 加 `user-invocable:false`(隐藏裸 `/distill` + 消除 `/specode:distill` 重复项,只留命令一条);distill 收敛为纯 **md-only**(移除 `--format yml|both` + `codemap knowledge write` 死路径);清理全部 `.ai-memory`/codemap 文档残留,并从 requirements 模板删除已废弃的「已知约束/历史坑」recall 段。**v5.0.0 BREAKING**: 命令去 `specode-` 前缀 — `/specode:spec` / `/specode:continue` / `/specode:list` / `/specode:distill`(原 `/specode:specode-*`);distill skill 目录与名同改为 `distill`;编排内核 skill `specode` 加 `user-invocable:false`,斜杠菜单不再显示裸 `/specode`(仍经命令/自然语言自动激活)。**v4.0.0 BREAKING**: 彻底拔出记忆注入工程 — 砍掉 specode 主流程的 (1) P3-1 codemap recall 注入 `## 已知约束 / 历史坑` 段, (2) P3-2 rule-acknowledgement post-check, (3) acceptance 后自动 AskUser 触发 distill。round 1/2 baseline 实验证明 recall 注入未 net 节省 token。保留 project-level CLAUDE.md / AGENT.md filesystem scan (不涉及 .ai-memory)。distill skill v4 完全重写: 仅手动触发 `/specode:distill `, 默认 md-only, 默认写 `/Volumes/External HD/Obsidian/Notes/11-KnowledgeBase//` (--target-dir 可覆盖), 不再调 codemap recall, 不再默认写 .ai-memory yml。如需 v3 记忆注入行为, checkout `backup/specode-v3.4.0-task-swarm-v0.9.2`。", "author": { "name": "xueqiang", "email": "xueqiang361@gmail.com" diff --git a/plugins/specode/CHANGELOG.md b/plugins/specode/CHANGELOG.md index f837ec8..7b9de7e 100644 --- a/plugins/specode/CHANGELOG.md +++ b/plugins/specode/CHANGELOG.md @@ -4,6 +4,25 @@ specode 是 spec-driven 轻量工作流插件:requirements → design → exec ## Unreleased +## 5.0.1 (2026-06-30) — distill 收敛 md-only + 隐藏 + 全量清理 .ai-memory/codemap 残留 + +承接 5.0.0,把 distill 彻底收敛为「纯 md-only Obsidian 整理器」,并清掉全仓最后的记忆注入文档残留。 + +### Changed + +- **`skills/distill/SKILL.md`**:加 `user-invocable: false` —— 斜杠菜单不再出现裸 `/distill`,也消除了「命令 + 同名可见 skill」造成的 `/specode:distill` 重复项(现只剩命令一条干净入口;Claude 仍可自动调用该 skill)。 +- **distill 收敛为纯 md-only**:移除 `--format md|yml|both` flag 与 `codemap knowledge write` 写入器路径。yml 输出的唯一消费者(`codemap recall`)早在 v4.0.0 删除,yml 已无人读取,故彻底移除。 + +### Removed / cleaned(文档与模板里的死引用) + +- **`assets/templates/requirements.md`**:删除已废弃的「## 已知约束 / 历史坑」段 —— 该段是 v4.0.0 已移除的 P3-1 codemap-recall 注入占位,SKILL 早已声明 requirements.md 不再含此段,模板未同步(会盖进每个新 spec)。 +- **`skills/distill/references/doc-template.md`**:重写为 v5 md-only 模板参考 —— 删除 yml schema / `.ai-memory/knowledge/` 路径表 / codemap 写入器框架,frontmatter 对齐 SKILL 的 Obsidian 风格,保留 5 类 md 模板正文与深度标准。 +- **`skills/distill/references/breakdown-heuristics.md`**:剥掉 `.ai-memory`/`codemap knowledge write`/yml 双产/supersede 框架,保留 5 维拆分方法论。 +- **`commands/spec.md` / `skills/specode/references/obsidian.md` / `tests/test_project_root.py`**:`project_root` 描述去掉过时的 ".ai-memory/knowledge feeds" + "codemap recall" 消费者措辞。 +- **`commands/distill.md`**:移除 `--format` flag。 + +全量复核:除 CHANGELOG 历史条目与「已移除 X」迁移说明外,仓库不再有把 `.ai-memory`/`codemap knowledge write`/yml-pipeline 描述成现行行为的文档。测试 233 passed。 + ## 5.0.0 (2026-06-30) — BREAKING: 命令去 `specode-` 前缀 + 内核 skill 隐藏 命令名 = specode 的 semver API surface。本版把命令去掉冗余的 `specode-` 前缀(插件命名空间已提供 `specode:`),并把不该被直接点的编排内核 skill 从斜杠菜单隐藏 —— 对齐 superpowers 的命名形态(无裸 `/superpowers`)。 diff --git a/plugins/specode/assets/templates/requirements.md b/plugins/specode/assets/templates/requirements.md index 51c3af8..72c4554 100644 --- a/plugins/specode/assets/templates/requirements.md +++ b/plugins/specode/assets/templates/requirements.md @@ -8,13 +8,6 @@ created_at: YYYY-MM-DD > specode requirements — 散文描述 + 验收标准追溯标签。 -## 已知约束 / 历史坑 - -<由 host agent 在 phase-0 context-recall 步骤自动注入; -当 `/.ai-memory/knowledge/` 为空或 `codemap recall` 不可用时本段省略。 -格式:每行 `- [[]] (, score=) — · <summary>`。 -草稿作者写需求时务必先看这段,再决定是否覆盖/绕过历史结论。> - ## 背景 / 为什么 <这个需求解决什么问题、为谁、动机。> diff --git a/plugins/specode/commands/distill.md b/plugins/specode/commands/distill.md index 11a70b6..cc5dd66 100644 --- a/plugins/specode/commands/distill.md +++ b/plugins/specode/commands/distill.md @@ -8,7 +8,7 @@ description: 手动把一个已完成(或进行中)的 spec 整理成 Obsidi - `/specode:distill <slug>` — 显式给 slug;`<slug>` 必须能在 `<specsRoot>/` 下找到对应目录 - `/specode:distill` — 不带参数时,host agent 默认沉淀**当前会话刚处理的 spec**(specode 主流程刚走完 acceptance 的那个);如果当前会话不在 spec 上下文里,host agent 应先建议 `/specode:list` -- 可选 flag:`--target-dir <abs-path>`(覆盖默认输出目录)、`--format md|yml|both`(默认 `md`) +- 可选 flag:`--target-dir <abs-path>`(覆盖默认输出目录) 行为:调用 `distill` skill,**纯粹从 spec 文档**提炼,按 5 维启发式拆分 → 生成分类别 markdown 笔记 → 落盘。完整流程与字段模板以 `skills/distill/SKILL.md`(v4+ 权威)为准。 diff --git a/plugins/specode/skills/distill/SKILL.md b/plugins/specode/skills/distill/SKILL.md index bb8d71d..090f674 100644 --- a/plugins/specode/skills/distill/SKILL.md +++ b/plugins/specode/skills/distill/SKILL.md @@ -1,5 +1,6 @@ --- name: distill +user-invocable: false description: > Manually distill a single specode-managed spec into Obsidian-friendly markdown knowledge files. Default output: md-only, written to @@ -21,24 +22,27 @@ showed the memory-injection round-trip did not net save token (recall 段 in task.md was extra context cost ≥ saving in most cases). v4.0.0 deletes that pipeline. -**v4 positioning**: a **manual, on-demand** organizer that converts a -finished spec into clean Obsidian markdown for the user's wiki. No -machine-readable yml (unless explicitly asked). No silent injection -elsewhere. +**positioning**: a **manual, on-demand** organizer that converts a +finished spec into clean Obsidian markdown for the user's wiki. +**md-only** — no yml, no `codemap knowledge write`, no `.ai-memory`, no +silent injection elsewhere. (The yml/codemap path was removed in 5.0.1: +its only consumer, `codemap recall`, was already deleted in v4.0.0, so +yml output had nothing left to feed.) --- ## Trigger ``` -/specode:distill <slug> [--target-dir <abs-path>] [--format md|yml|both] +/specode:distill <slug> [--target-dir <abs-path>] ``` | Arg | Default | Meaning | |---|---|---| | `<slug>` | (required) | spec slug under `<specsRoot>/` | | `--target-dir` | `/Volumes/External HD/Obsidian/Notes/11-KnowledgeBase/<slug>/` | output root (must be absolute; will be `mkdir -p` 'd) | -| `--format` | `md` | `md` = obsidian markdown only; `yml` = machine yml only (writes to `<target-dir>/yml/<category>/<id>.yml`); `both` = pair | + +Output is **always Obsidian markdown** — there is no `--format` flag. **Manual only**: there is no auto-trigger. specode v4.0.0 main flow's acceptance phase **does not prompt** the user to distill. The user runs this command whenever they want to update their Obsidian wiki from a finished spec. @@ -97,8 +101,6 @@ related: [[biz-checkout-flow]], [[pit-coupon-stack]] ... ``` -For `--format yml` or `--format both`: also writes `<target-dir>/<slug>/yml/<category>/<id>.yml` via `codemap knowledge write` (requires `codemap-aimemory` independent install). If `codemap` CLI not found and user picked `yml` / `both`, **abort with error** (do not silently degrade — user explicitly asked for yml). - --- ## Flow (4 steps; user controls cadence) @@ -163,9 +165,7 @@ Category-specific section sets (see `references/doc-template.md` for full templa - **cases**: `实施摘要` / `关键决策` / `踩过的坑 / fix` / `验收结果` / `变更文件` - **pitfalls**: `现象` / `根因` / `修复方法` / `预防措施` / `影响范围` -Write each `.md` to `<target-dir>/<slug>/<category>/<knowledge_id>.md`. Existing file → `Read` then ask user `overwrite / skip / merge`. - -For `--format yml` or `both`: also pipe to `codemap knowledge write` (independent install required). Writer's `--project` flag points to `<target-dir>/<slug>/yml-store` (a tmp dir; distill v4 does NOT use the spec's `project_root` here). +Write each `.md` to `<target-dir>/<slug>/<category>/<knowledge_id>.md`. Existing file → `Read` then ask user `overwrite / skip / merge`. The host agent authors the markdown directly — there is no external writer CLI. --- @@ -176,8 +176,8 @@ For `--format yml` or `both`: also pipe to `codemap knowledge write` (independen | Spec dir is read-only | Never modify anything under `<specsRoot>/<slug>/` | | `--target-dir` is the SOLE write scope | Distill writes only under `<target-dir>/<slug>/`. Never writes to spec dir or to `<project_root>/.ai-memory/` | | External-drive precheck | If `--target-dir` is under `/Volumes/`, verify mounted; refuse if not | -| No codemap recall | v4 explicitly does NOT call `codemap recall`. Distill is purely spec-content driven | -| No silent yml | yml only written if user `--format yml` or `--format both`; default is md-only | +| No codemap recall | Distill explicitly does NOT call `codemap recall`. It is purely spec-content driven | +| Md-only output | Distill produces Obsidian markdown only — no yml, no `codemap knowledge write`, no `.ai-memory` (yml/codemap path removed in 5.0.1) | | No injection elsewhere | Distill output is for the user's Obsidian wiki — it does NOT feed any future spec's `requirements.md`, does NOT feed any `task.md` to subagents | | Read-before-overwrite | If target md exists, `Read` then ask user before overwriting | @@ -188,11 +188,11 @@ For `--format yml` or `both`: also pipe to `codemap knowledge write` (independen | Removed | Why | |---|---| | Auto-trigger from acceptance phase | v4 specode main flow has no distill prompt; user runs manually only | -| Pre-step P2-2 codemap recall reverse-check | v4 doesn't read `.ai-memory/` at all | -| Default dual yml + md write | Default is md-only; yml requires explicit `--format yml` / `both` | -| Default write to `<project_root>/.ai-memory/knowledge/` | v4 default writes to `/Volumes/External HD/Obsidian/Notes/11-KnowledgeBase/<slug>/` | +| Pre-step P2-2 codemap recall reverse-check | Distill doesn't read `.ai-memory/` at all | +| yml output (`--format yml` / `both` via `codemap knowledge write`) | Removed in 5.0.1 — md-only. yml's only consumer (`codemap recall`) was deleted in v4.0.0, so it fed nothing | +| Default write to `<project_root>/.ai-memory/knowledge/` | Default writes to `/Volumes/External HD/Obsidian/Notes/11-KnowledgeBase/<slug>/` | | Coordination with task-swarm's ingest_lessons | task-swarm v0.10.0+ removes ingest entirely; no coordination needed | -| Same-id merge across distill + auto-ingest | No auto-ingest exists in v4; manual `--format both` writes are user's responsibility | +| Same-id merge across distill + auto-ingest | No auto-ingest exists; existing target md → `Read` then ask overwrite / skip / merge | If user wants the v3 behavior (auto-trigger + write to `.ai-memory/`), checkout `backup/specode-v3.4.0-task-swarm-v0.9.2` branch. @@ -209,4 +209,4 @@ If user wants the v3 behavior (auto-trigger + write to `.ai-memory/`), checkout ## References - `references/breakdown-heuristics.md` — 5-dimension breakdown → 5-category mapping -- `references/doc-template.md` — md template per category (5 templates total; yml templates retained for `--format yml` mode) +- `references/doc-template.md` — Obsidian md template per category (5 templates total) diff --git a/plugins/specode/skills/distill/references/breakdown-heuristics.md b/plugins/specode/skills/distill/references/breakdown-heuristics.md index 428dae3..47dcb2c 100644 --- a/plugins/specode/skills/distill/references/breakdown-heuristics.md +++ b/plugins/specode/skills/distill/references/breakdown-heuristics.md @@ -1,26 +1,26 @@ -# 知识点拆分启发式(spec-distill v2) +# 知识点拆分启发式(distill) -> 供 `spec-distill sync` 流程第 4 步 LLM 提议知识点拆分时参考。 +> 供 `/specode:distill` 流程第 3 步 LLM 提议知识点拆分时参考。 > 拆分方案由 LLM 提议、用户在 `AskUserQuestion` 中最终拍板。 > -> **v2 重要变化**:5 维启发式映射到 `.ai-memory/knowledge/` 下的 **5 类目录**; -> 每个候选知识点必须明确 `category`(`knowledge_id` 由写入器派生,可选)。 -> 落盘经 `codemap knowledge write`(content payload),写入器同时产 yml + md 双产; -> 字段集见 `references/doc-template.md`。 +> distill 是 **md-only** 整理器:5 维启发式映射到 **5 类目录**,每个候选必须明确 +> `category`;host agent 据 category + 标题派生 `knowledge_id = <prefix>-<kebab(title)>`, +> 直接撰写 Obsidian markdown(无 yml、无 `codemap knowledge write` 写入器、不碰 +> `.ai-memory/`)。每类 md 的 frontmatter + 正文结构见 `references/doc-template.md`。 ## 五维 → 五类目录映射表 -| 启发式维度 | 目录 | ID 前缀 | type 字段 | -|---|---|---|---| -| 1. 按业务流程 | `business/` | `biz-` | `business_process` | -| 2. 按表 / 字段 | `modules/` | `mod-` | `module_map` | -| 3. 按功能页 / 特性 | `business/` | `biz-` | `business_process` | -| 4. 按调用链 | `modules/` | `mod-` | `module_map` | -| 5. 按机制 / 规则 | `rules/` | `rule-` | `business_rule` | -| **额外**:本 spec 实现案例 | `cases/` | `case-` | `case` | -| **额外**:可复用坑点 | `pitfalls/` | `pit-` | `pitfall` | +| 启发式维度 | 目录 | ID 前缀 | +|---|---|---| +| 1. 按业务流程 | `business/` | `biz-` | +| 2. 按表 / 字段 | `modules/` | `mod-` | +| 3. 按功能页 / 特性 | `business/` | `biz-` | +| 4. 按调用链 | `modules/` | `mod-` | +| 5. 按机制 / 规则 | `rules/` | `rule-` | +| **额外**:本 spec 实现案例 | `cases/` | `case-` | +| **额外**:可复用坑点 | `pitfalls/` | `pit-` | -> 每个 spec 至少产 1 篇 `case-*.yml`(必有 — 来自 `implementation-log.md`),其他类按需。`implementation-log` / `bugfix` 中"有复用价值的坑"单独拎出 `pit-*.yml`,不要塞到 case 内。 +> 每个 spec 至少产 1 篇 `case-<slug>.md`(必有 — 来自 `implementation-log.md`),其他类按需。`implementation-log` / `bugfix` 中"有复用价值的坑"单独拎出 `pit-*.md`,不要塞到 case 内。 --- @@ -126,11 +126,11 @@ ## 拆分流程 -1. LLM 读完全 spec 文档后,按上述五种维度各提一批候选;**每个候选标注** `category` + 拟标题 + 一句摘要 + 拟 tags(`knowledge_id` 可选——写入器据 category + spec_id/title/signature 自动派生)。 -2. 至少强制一篇 `cases` 候选(记录本次实现,来源 `implementation-log.md` / `bugfix.md` / `acceptance-checklist.md`);写入器据 `spec_id` 派生为 `case-<spec_id>`,与 task-swarm 自动 case 同 id 以触发 supersede。 +1. LLM 读完全 spec 文档后,按上述五种维度各提一批候选;**每个候选标注** `category` + 拟标题 + 一句摘要 + 拟 tags(`knowledge_id = <prefix>-<kebab(title)>`)。 +2. 至少强制一篇 `cases` 候选(记录本次实现,来源 `implementation-log.md` / `bugfix.md` / `acceptance-checklist.md`);id 固定为 `case-<slug>`,重跑 distill 默认整篇 overwrite。 3. 用 `AskUserQuestion` 呈现给用户,让用户**增删/合并/改名/改归属**。 4. 用户确认后才开始落盘,**不自动跳过此步**。 -5. 对每个候选构造 content payload(`category` + `fields` + `md_body`)→ 调 `codemap knowledge write`(见 `SKILL.md` Step 5);字段集见 `references/doc-template.md`。**不手写 yml**(写入器不可用时才回退手写)。 +5. 对每个确认候选,host agent **直接撰写 Obsidian markdown**(frontmatter + 正文,见 `references/doc-template.md` 与 `SKILL.md` Step 4),写到 `<target-dir>/<slug>/<category>/<knowledge_id>.md`。无外部写入器、无 yml。 --- diff --git a/plugins/specode/skills/distill/references/doc-template.md b/plugins/specode/skills/distill/references/doc-template.md index 618d462..ea5113d 100644 --- a/plugins/specode/skills/distill/references/doc-template.md +++ b/plugins/specode/skills/distill/references/doc-template.md @@ -1,121 +1,61 @@ -# distill — 字段参考(payload `fields` + md 正文) +# distill — Obsidian markdown 模板参考(5 类) -> **重要(FIX-2)**:distill **不再手写 yml**。它构造 *content payload* -> 交给单一写入器 `codemap knowledge write`(见 `SKILL.md` Step 5)。本文件因此 -> 是**字段参考**:每类 payload 的 `fields` 应包含哪些语义字段、md 正文长什么样。 +> distill 是 **md-only** 的 Obsidian 知识整理器(5.0.1+):host agent **直接撰写 +> markdown**,没有 yml、没有 `codemap knowledge write` 写入器、不碰 `.ai-memory/`。 +> 本文件给出 5 个类别各自的 **md frontmatter + 正文结构**模板。流程见 `SKILL.md`。 > -> 由**写入器**自动盖章、**不要**放进 `fields` 的字段: -> `schema_version` / `knowledge_id` / `type` / `version` / `created_at` / -> `updated_at`(写入器据 category + spec_id/title/signature 推导 id、盖日期、 -> 按同 id 合并规则升 version)。 -> -> 由 **LLM 提供**: -> - `fields`:下面各类列出的语义字段(`statement` / `why` / `steps` / -> `implementation_summary` / `symptom` / ... )。 -> - `md_body`:人读叙事正文(散文 / ascii 调用链 / `[[wikilink]]`),写入器逐字 -> 写进孪生 md 的机器渲染 frontmatter 之下(方案A)。 -> -> 下面每类的 "yml schema" 段落即该类 `fields` 的字段集;"md 模板" 段即 `md_body` -> 的推荐结构。**fallback**(写入器不可用)时才需按完整 yml schema 手写双产。 - +> 旧的 yml schema / `.ai-memory/knowledge/` 双产物路径 / codemap 写入器已在 5.0.1 +> 移除(其唯一消费者 `codemap recall` 早在 v4.0.0 删除,yml 输出无人读取)。 --- ## 类别 → 目录 → 前缀 总览 -| category | yml 目录 | md 目录 | id 前缀 | type | -|---|---|---|---|---| -| `rules` | `.ai-memory/knowledge/rules/` | `knowledge-base/rules/` | `rule-` | `business_rule` | -| `business` | `.ai-memory/knowledge/business/` | `knowledge-base/business/` | `biz-` | `business_process` | -| `modules` | `.ai-memory/knowledge/modules/` | `knowledge-base/modules/` | `mod-` | `module_map` | -| `cases` | `.ai-memory/knowledge/cases/` | `knowledge-base/cases/` | `case-` | `case` | -| `pitfalls` | `.ai-memory/knowledge/pitfalls/` | `knowledge-base/pitfalls/` | `pit-` | `pitfall` | +所有产物都落在 `--target-dir`(默认 `/Volumes/External HD/Obsidian/Notes/11-KnowledgeBase/`)下的 `<slug>/<category>/`: + +| category | 目录 | id 前缀 | 含义 | +|---|---|---|---| +| `rules` | `<target-dir>/<slug>/rules/` | `rule-` | 业务规则 / 全局机制 | +| `business` | `<target-dir>/<slug>/business/` | `biz-` | 业务流程 / 功能页 | +| `modules` | `<target-dir>/<slug>/modules/` | `mod-` | 表 / 字段 / 调用链 / 模块地图 | +| `cases` | `<target-dir>/<slug>/cases/` | `case-` | 历史案例(每 spec 必产 1 篇,id = `<slug>`) | +| `pitfalls` | `<target-dir>/<slug>/pitfalls/` | `pit-` | 可复用的失败 / 修复经验 | + +文件名 = `<knowledge_id>.md`,`knowledge_id = <prefix>-<kebab(title)>`(cases 为 `case-<slug>`)。 --- -## 公共字段(5 类 yml 通用) - -```yaml -schema_version: "1.0" -knowledge_id: <prefix>-<kebab-slug> # 与文件名 stem 一致 -type: <见上表> # 与目录一一对应 -version: 1 # 同 id 升级 +1 -created_at: YYYY-MM-DD -updated_at: YYYY-MM-DD -status: active # active / deprecated / draft -confidence: high # high / medium / low -source_spec: <specsRoot>/<slug> # 相对或绝对都行,按 host agent 习惯 -source_files: - - requirements.md - - design.md - - implementation-log.md -related_requirements: # spec_id / 需求号 列表 - - REQ-2024-0078 -related_knowledge: # 同 .ai-memory/knowledge/ 内其它 .yml 的 knowledge_id - - mod-order-pricing - - rule-coupon-points-mutex -related_code: # codemap entity_id 或 file/entity 对 - - file: src/modules/order/pricing.js - entity: calculateOrderPrice - line_range: [120, 180] -tags: - - coupon - - pricing -``` +## 公共 Obsidian frontmatter -公共 md frontmatter(最小,避免和正文叙事冗余): +每篇 md 顶部用统一的 Obsidian 友好 frontmatter(与 `SKILL.md` Step 4 一致): ```markdown --- -knowledge_id: <prefix>-<kebab-slug> -type: <同 yml> -version: 1 -updated_at: YYYY-MM-DD -tags: [coupon, pricing] -related_requirements: [REQ-2024-0078] -related_knowledge: [mod-order-pricing] -related_code: - - file: src/modules/order/pricing.js - entity: calculateOrderPrice +title: <中文标题> +category: <rules|business|modules|cases|pitfalls> +spec_id: <slug> +created_at: <YYYY-MM-DD> +tags: [tag1, tag2] +related: [[id1]], [[id2]] # 可选:同 wiki 内其它知识点的 [[wikilink]] --- ``` -> md 不重复 yml 中可派生的字段(source_files / status / confidence / created_at);如需查阅打开同名 yml 即可。 +> 可按需追加任何 Obsidian 兼容字段(如 `related_requirements: [121659]`、`related_code:` 路径列表),但保持上面 6 个为基础集。正文用散文 / 表格 / ascii / `[[wikilink]]`,面向人读。 --- ## 1. `rules/` — 业务规则 / 全局机制 -### 1.1 yml schema - -公共字段之外加: - -```yaml -statement: "优惠券和积分抵扣不能同时使用" -why: "避免用户双重优惠导致亏损" -trigger_conditions: - - "下单时同时勾选优惠券和使用积分" -exceptions: - - "VIP 等级 ≥ 8 的用户例外,见 rule-vip-privilege" -enforcement: - - "service 层 validateCouponAndPoints() 抛异常" - - "前端 OrderPricing.vue 互斥禁用" -``` - -### 1.2 md 模板 +正文段:`一句话规则` / `为什么有这条规则` / `触发条件` / `例外` / `在代码哪些层强制` / `关联`。 ```markdown --- -knowledge_id: rule-coupon-points-mutex -type: business_rule -version: 1 -updated_at: 2026-06-26 +title: 优惠券与积分抵扣互斥规则 +category: rules +spec_id: REQ-2024-0078 +created_at: 2026-06-26 tags: [coupon, points, mutex] -related_requirements: [REQ-2024-0078] -related_knowledge: [biz-order-checkout] -related_code: - - file: src/modules/order/validators.js - entity: validateCouponAndPoints +related: [[biz-order-checkout]], [[pit-coupon-null-amount]] --- # 优惠券与积分抵扣互斥规则 @@ -158,47 +98,16 @@ related_code: ## 2. `business/` — 业务流程 / 功能页 -### 2.1 yml schema - -```yaml -title: "Q01 承保送收付入库流程" -trigger: "承保系统下单完成" -end_state: "SfCreditMain + SfBusinessCredit 双表落库 + 推 ATP" -steps: - - n: 1 - actor: "承保系统" - action: "调用 Q01 接口" - inputs: [policyNo, paymentComCode, codInd] - - n: 2 - actor: "收付系统" - action: "判断 paymentComCode 是否需要覆盖赋值" - branches: - - condition: "paymentComCode != centerCode" - next: "覆盖为 centerCode" - - condition: "paymentComCode == centerCode" - next: "保留原值" -data_flow: - - "Q01 → SfCreditMain.PAYSTATUS = 0" - - "Q17 / Q01 入库顺序约束:Q17 先于 Q01" -ui_constraints: # 功能页特有;非功能页可空 - - element: "保存按钮" - rule: "未选优惠券时灰禁用" -``` - -### 2.2 md 模板 +正文段:`概述` / `触发与终止` / `步骤`(ascii 流程图)/ `数据流约束` / `关键 UI 约束(如这是功能页)` / `关联`。 ```markdown --- -knowledge_id: biz-q01-underwrite-to-payment -type: business_process -version: 1 -updated_at: 2026-06-26 +title: Q01 承保送收付入库流程 +category: business +spec_id: 121659 +created_at: 2026-06-26 tags: [Q01, underwrite, payment, SfCreditMain] -related_requirements: [121659, 123000] -related_knowledge: [mod-sf-credit-main, rule-paymentcomcode-fallback] -related_code: - - file: src/main/java/com/pointwise/.../payment/biz/SfCreditMainBizImpl.java - entity: handleQ01Input +related: [[mod-sf-credit-main]], [[rule-paymentcomcode-fallback]] --- # Q01 承保送收付入库流程 @@ -243,58 +152,23 @@ related_code: - 数据模型:[[mod-sf-credit-main]] - 关联规则:[[rule-paymentcomcode-fallback]] -- 历史案例:[[case-121659-implementation]] +- 历史案例:[[case-121659]] ``` --- ## 3. `modules/` — 表 / 字段 / 调用链 / 模块地图 -### 3.1 yml schema - -```yaml -title: "SfCreditMain 字段说明" -scope: table # table / call_chain / module / api -entity_kind: table -primary_entity: tbl-sf_credit_main -columns: # 仅 scope=table 时 - - name: PAYSTATUS - type: TINYINT - enum: - - value: 0 - meaning: 未处理 - - value: 1 - meaning: 已确认 - - value: 3 - meaning: 部分确认(已作废,保留兼容) - - name: CNY_PAY_AMOUNT - type: DECIMAL(18,2) - note: "实际归属 SfBusinessCredit,非 SfCreditMain 字段" -shard: # 分库分表 - key: underwriteEndDate - routing: SfRouter - database: 主库 -call_chain: # 仅 scope=call_chain 时 - - step: "前端 SfPlanAuthority.vue:142" - next: "POST /api/payment/authorityQuery" - - step: "Controller PaymentController.authorityQuery" - next: "Service authorityQueryByPaymentNo" -``` - -### 3.2 md 模板 +正文段:`概述` / `表结构(关键字段)`(枚举全列,含已作废值并标注)/ `分库分表 / 路由` / `关联表 ascii` / `调用链`(如 scope=call_chain)/ `关联`。 ```markdown --- -knowledge_id: mod-sf-credit-main -type: module_map -version: 1 -updated_at: 2026-06-26 +title: SfCreditMain 字段说明 +category: modules +spec_id: 121659 +created_at: 2026-06-26 tags: [SfCreditMain, table, fields, sharding] -related_requirements: [121659, 123000] -related_knowledge: [biz-q01-underwrite-to-payment] -related_code: - - file: src/main/resources/mapper/SfCreditMainMapper.xml - - entity: tbl-sf_credit_main +related: [[biz-q01-underwrite-to-payment]], [[pit-cny-pay-amount-misplace]] --- # SfCreditMain 字段说明 @@ -349,48 +223,16 @@ SfCreditMain.creditingNo (1) ─────► (N) SfBusinessCredit.creditingNo ## 4. `cases/` — 历史案例(每个 spec 必产 1 篇) -### 4.1 yml schema - -```yaml -case_id: case-REQ-2024-0078 -spec_id: REQ-2024-0078 # 与 spec 目录名对齐 -title: "订单列表增加按金额区间筛选" -implementation_summary: | - 在 OrderQueryService 增加 amountMin / amountMax 参数; - 前端 admin/order-list.vue 加范围输入框;使用 BigDecimal。 -changed_files: - - src/modules/order/query.js - - src/modules/admin/order-list.vue -key_decisions: - - decision: "使用 BigDecimal 避免浮点精度问题" - reason: "金额查询历史踩过浮点 0.1+0.2=0.30000000000004 的坑" - - decision: "复用已有权限校验中间件" - reason: "保持鉴权一致;不另起 middleware" -bugs_encountered: - - "初始实现未处理金额为 null 的情况,validation 直接 NPE" -lessons: - - "涉及金额查询时,必须考虑 null 和 0 的边界" -review_findings: - - finding: "重复的金额校验逻辑" - severity: minor - action: "已抽到 amountValidator 工具方法" -acceptance_status: passed # passed / failed / partial -``` - -### 4.2 md 模板 +正文段:`实现摘要` / `改动文件` / `关键决策`(配理由)/ `实施中遇到的 bug` / `教训(lessons learned)` / `Review 反馈` / `验收`。id 固定为 `case-<slug>`,重跑 distill 默认整篇 overwrite(case 描述的就是"这次实现")。 ```markdown --- -knowledge_id: case-REQ-2024-0078 -type: case -version: 1 -updated_at: 2026-06-26 +title: 订单列表增加按金额区间筛选 +category: cases +spec_id: REQ-2024-0078 +created_at: 2026-06-26 tags: [order, query, amount-range] -related_requirements: [REQ-2024-0078] -related_knowledge: [pit-amount-null-validation] -related_code: - - file: src/modules/order/query.js - - file: src/modules/admin/order-list.vue +related: [[pit-amount-null-validation]] --- # case REQ-2024-0078 — 订单列表增加按金额区间筛选 @@ -436,46 +278,16 @@ related_code: ## 5. `pitfalls/` — 坑点(可复用的失败 / 修复经验) -### 5.1 yml schema - -```yaml -pit_id: pit-amount-null-validation -title: "金额参数为 null 时未做兜底校验导致 NPE" -context: "电商订单计算价格、查询订单列表等所有涉及金额的接口" -symptom: | - 调用方未传 amount 字段时,BigDecimal.add 抛 NullPointerException; - 前端表现为接口 500,无明确错误码。 -root_cause: | - validator 假设 amount 必非 null,未走前置 Objects.requireNonNullElse; - schema 未把 amount 标记为 required 也未给 default。 -fix: - - "validator 内 amountMin = Optional.ofNullable(amountMin).orElse(BigDecimal.ZERO)" - - "OpenAPI schema 把 amountMin / amountMax 显式标 nullable=true + default=0" -prevention: - - "新接口涉及金额查询时,必须 review null/0 兜底逻辑" - - "PR 模板加一条 checklist: '金额参数是否处理 null'" -affects: # 文件路径或 entity_id - - src/modules/order/query.js - - src/modules/order/calculator.js -first_seen_in: REQ-2024-0078 -seen_again_in: # 后续重复踩到时追加 - - REQ-2024-0092 -``` - -### 5.2 md 模板 +正文段四件套必填:`适用范围` / `症状` / `根因` / `修复` / `怎么避免再犯` / `影响范围` / `历史`。写不全不算合格。 ```markdown --- -knowledge_id: pit-amount-null-validation -type: pitfall -version: 2 -updated_at: 2026-06-26 +title: 金额参数 null 未兜底导致 NPE +category: pitfalls +spec_id: REQ-2024-0078 +created_at: 2026-06-26 tags: [amount, null-safety, npe, validation] -related_requirements: [REQ-2024-0078, REQ-2024-0092] -related_knowledge: [case-REQ-2024-0078] -related_code: - - file: src/modules/order/query.js - - file: src/modules/order/calculator.js +related: [[case-REQ-2024-0078]] --- # pit — 金额参数 null 未兜底导致 NPE @@ -527,39 +339,35 @@ BigDecimal max = Optional.ofNullable(amountMax).orElse(BigDecimal.valueOf(Long.M --- -## 各 yml 段 / md 段的内容来源对照 +## 各 md 段的内容来源对照 | 段 | 主要 source | 备注 | |---|---|---| -| 公共:`source_spec` / `source_files` / `related_requirements` | spec 目录 + frontmatter | 机器可写无需 LLM 判断 | -| 公共:`related_code` | `design.md` + `implementation-log.md` | 抽 Java 类全名 / Vue 文件路径 / Mapper id | +| frontmatter:`spec_id` / `tags` / `related` | spec 目录 + frontmatter | spec_id = slug;related 由 host agent 据本批候选互链 | | `rules.*` | `requirements.md` 业务约束 / `design.md` 校验设计 | 抽"X 时不能 Y"型句子 | -| `business.*` | `design.md` 时序图 / 流程图 / `requirements.md` 场景 | 步骤化为 `steps[]` | +| `business.*` | `design.md` 时序图 / 流程图 / `requirements.md` 场景 | 步骤化为 ascii 流程 | | `modules.*` | `design.md` 数据模型 / 接口设计 | 字段枚举 / 调用链 / 分库分表键 | -| `cases.*` | `implementation-log.md` + `bugfix.md` + `tests` + `acceptance-checklist` | **每 spec 必产 1 篇** | -| `pitfalls.*` | `implementation-log.md` + `bugfix.md` | 仅"有复用价值的坑"独立成篇;临时调试不纳入 | +| `cases.*` | `implementation-log.md` + `bugfix` + `tests` + `acceptance` | **每 spec 必产 1 篇** | +| `pitfalls.*` | `implementation-log.md` + `bugfix` | 仅"有复用价值的坑"独立成篇;临时调试不纳入 | --- -## 同 id 升级规则(yml + md 同时升级) +## 同名升级规则(md) -如目标目录已有同 `knowledge_id`: +如目标目录已有同 `knowledge_id` 的 md: -1. `Read` 两份原文件(yml + md)。 -2. **不重写**:`title` / `statement` / `key_decisions` 等结构性字段保留。 -3. **追加**:`related_requirements` 追加本次 spec;`source_files` 追加;`seen_again_in`(pit 专有)追加新条目。 -4. **更新**:`updated_at: today`;`version +1`(yml + md frontmatter 同步)。 -5. **冲突时**:若本次新信息与原文相悖,`AskUserQuestion` 让用户选"覆盖 / 新建 `-v2` 后缀文件 / 跳过"。 -6. **cases/case-* 特例**:同一 spec 重新跑 distill 默认 supersede(直接 overwrite),不走 append 流程——因为 case 描述的就是"这次实现",重跑意味着重写实现。 +1. `Read` 原文件。 +2. **不重写**结构性内容(`title` / 一句话规则 / 关键决策 等)。 +3. **追加**:本次 spec 的相关需求号、新增的关联 `[[wikilink]]`、坑点的"再次踩到"行。 +4. **冲突时**:若本次新信息与原文相悖,`AskUserQuestion` 让用户选"覆盖 / 新建 `-v2` 后缀文件 / 跳过"。 +5. **cases/case-* 特例**:同一 spec 重新跑 distill 默认整篇 overwrite(不走 append)——case 描述的就是"这次实现",重跑意味着重写。 --- ## 深度标准(写得多深算合格) -参考现有 `新收付(fin)` 系统语料的人脑可读基线: - -- **modules 类**:字段枚举全列(含已作废值并标注);分库分表键明确(如 `分表键 underwriteEndDate`);调用链含完整 Java 类路径 + 方法名。 +- **modules 类**:字段枚举全列(含已作废值并标注);分库分表键明确(如 `分表键 underwriteEndDate`);调用链含完整类路径 + 方法名。 - **rules 类**:触发条件精确到字段比较;列出反例 / 边界条件;标注在代码哪一层强制。 -- **business 类**:每步标注 actor + action + branches;功能页含 UI 约束表。 -- **cases 类**:`key_decisions` 配 `reason`;`bugs_encountered` 含表面症状;`lessons` 是一句结论。 -- **pitfalls 类**:`symptom` + `root_cause` + `fix` + `prevention` 四件套必填,写不完不算合格。 +- **business 类**:每步标注 actor + action + 分支;功能页含 UI 约束表。 +- **cases 类**:关键决策配理由;遇到的 bug 含表面症状;教训是一句结论。 +- **pitfalls 类**:`症状` + `根因` + `修复` + `预防` 四件套必填,写不完不算合格。 diff --git a/plugins/specode/skills/specode/references/obsidian.md b/plugins/specode/skills/specode/references/obsidian.md index 413f08e..05299fd 100644 --- a/plugins/specode/skills/specode/references/obsidian.md +++ b/plugins/specode/skills/specode/references/obsidian.md @@ -19,7 +19,7 @@ CLI via run.sh: `resolve_root.py get-root` / `set-root --root P` / `list-specs` - The directory the user provides is used **verbatim** as the specs root; specode appends no internal sub-structure (the user may supply a fully qualified path such as `.../spec-in/<os>-<user>/specs`). - Each spec = `<specsRoot>/<slug>/`, containing the fixed files `requirements.md` / `design.md` / `implementation-log.md`. - `pipeline.yml` is generated only when delegating to task-swarm; it is not a fixed artifact. -- project_root = the project whose `.ai-memory/knowledge` a spec feeds. It is the **single join key** between a spec and its project, stored in **exactly one place** — the spec's `requirements.md` YAML frontmatter — and accessed only through `resolve_root.py {resolve,write,read}-project-root`. Default is `git rev-parse --show-toplevel` of cwd (fallback cwd), **confirmed once via `AskUserQuestion`**, then persisted to frontmatter by `write-project-root`. Every later phase/skill (distill, task-swarm, recall) reads it via `read-project-root` — never re-derive from cwd/workdir, never guess. +- project_root = the project a spec targets. It is the **single join key** between a spec and its project, stored in **exactly one place** — the spec's `requirements.md` YAML frontmatter — and accessed only through `resolve_root.py {resolve,write,read}-project-root`. Default is `git rev-parse --show-toplevel` of cwd (fallback cwd), **confirmed once via `AskUserQuestion`**, then persisted to frontmatter by `write-project-root`. Later phases/skills (task-swarm; distill for relative-path resolution) read it via `read-project-root` — never re-derive from cwd/workdir, never guess. ## Documents as state (phase inference) | Directory state | Phase | diff --git a/plugins/specode/tests/test_project_root.py b/plugins/specode/tests/test_project_root.py index 82de39c..8e159f8 100644 --- a/plugins/specode/tests/test_project_root.py +++ b/plugins/specode/tests/test_project_root.py @@ -1,7 +1,7 @@ """Tests for project_root verbs in resolve_root.py (FIX-1: single source of truth). project_root is the join key between a spec (under specsRoot) and the project -whose .ai-memory/knowledge it feeds. It lives in exactly one place — the spec's +it targets. It lives in exactly one place — the spec's requirements.md YAML frontmatter — and every consumer reads it through the same ``read-project-root`` entry. ``write-project-root`` is the single validated writer. ``resolve-project-root`` computes the default for the host agent to