From 4b2d9bed54c97b130fb0903cf3de51bb1d6a1c5a Mon Sep 17 00:00:00 2001 From: qxbyte <126648675+qxbyte@users.noreply.github.com> Date: Sun, 5 Jul 2026 18:20:59 +0800 Subject: [PATCH 1/7] =?UTF-8?q?refactor(specode):=20intake=20SKILL=20instr?= =?UTF-8?q?uction=20prose=20=E2=86=92=20English=20(keep=20Chinese=20output?= =?UTF-8?q?/injected)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Language unification (specode only): the agent-facing instruction prose is now idiomatic English. Protected Chinese kept verbatim — the injected `## 项目级约束` section template, the `参考定位(非事实来源)` label, and the requirements-template section headings (背景/范围/验收标准/开放问题). Co-Authored-By: Claude Fable 5 Co-Authored-By: qxbyte <126648675+qxbyte@users.noreply.github.com> --- plugins/specode/skills/intake/SKILL.md | 100 ++++++++++++------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/plugins/specode/skills/intake/SKILL.md b/plugins/specode/skills/intake/SKILL.md index d132353..d296722 100644 --- a/plugins/specode/skills/intake/SKILL.md +++ b/plugins/specode/skills/intake/SKILL.md @@ -1,53 +1,53 @@ --- name: intake user-invocable: false -description: specode 的需求 intake 引擎——项目分析 + 定位 + 澄清 + 写 requirements.md。在 spec 起始阶段(requirements phase)由 specode 编排 SKILL 通过 Skill 工具按名调用(specode:intake),取代旧的「brainstorming 兼职写需求 / 或薄弱 native 问卷」。产出 //requirements.md(含 project_root frontmatter 契约)+ 交给 design 阶段的定位指针。不是用户直接触发的命令。 +description: specode's requirements-intake engine — project analysis + code location + clarification + writing requirements.md. Invoked by name (specode:intake) via the Skill tool by the specode orchestration SKILL at the start of a spec (requirements phase); it replaces the old "brainstorming moonlighting as a requirements writer / thin native questionnaire". Produces //requirements.md (with the project_root frontmatter contract) plus the location pointers handed to the design phase. Not a user-triggered command. --- -# intake — specode 需求 intake 引擎 +# intake — specode's requirements-intake engine -## §0 你是谁 / 何时被调用 +## §0 Who you are / when you're invoked -- specode 编排壳在 **requirements phase** 通过 `Skill` 工具按名调用你(`specode:intake`);此时 `` 已解析、`//` 目录已建、slug 已定。 -- 你是 requirements 的**唯一生产者**——specode 不再分「superpowers 在/不在」两条 requirements 路径。superpowers 的 `brainstorming` 从此**只做 design**(产 design.md),不再兼职写需求。 -- 你相对旧「native 2-4 问问卷」的价值全在 **§3 项目分析** + **§4 基于分析的澄清**:先读真实项目建立事实基线,再问有依据的问题——这才是 specode 版的"驱动生成能力",不是空泛问卷。 -- 你的产物: - 1. `//requirements.md`(散文需求 + 硬 frontmatter 契约,见 §1); - 2. 一段交给 design 阶段的「**参考定位(非事实来源)**」定位指针(§5,临时上下文,不持久化为事实)。 +- The specode orchestration shell invokes you by name (`specode:intake`) via the `Skill` tool during the **requirements phase**. By then `` is resolved, `//` exists, and the slug is fixed. +- You are the **sole producer of `requirements.md`** — specode no longer forks the requirements phase on "superpowers present or not". superpowers' `brainstorming` is used only for **design** from here on; it never moonlights as a requirements writer. +- What sets you apart from the old "native 2-4 question wizard" is entirely **§Step 2 project analysis** + **§Step 3 analysis-driven clarification**: read the real project first to establish a factual baseline, then ask grounded questions — that is specode's own "driving capability", not a blank questionnaire. +- Your outputs: + 1. `//requirements.md` — prose requirements plus the hard frontmatter contract (§1); + 2. a block of **`参考定位(非事实来源)`** location pointers handed to the design phase (§5, ephemeral context, never persisted as fact). -## §1 硬约束 🔒(绝不可动) +## §1 Hard constraints 🔒 (never violate) -1. **frontmatter 契约(最高优先级,用户明确要求保留)**:`requirements.md` 顶部 YAML **必须**含三个字段——`spec_id` / `created_at` / `project_root`。其中 **`project_root` 是下游 distill / task-swarm / retrieval 的单一事实源**,**只能**经 `resolve_root.py write-project-root` 单一验证写入口落盘(它校验绝对路径 / 目录存在 / `/Volumes` 挂载),**绝不手写该字段**。你换的是"谁生成 requirements 的正文内容",**绝不破坏这套契约元素**。 -2. **散文需求**:`requirements.md` 是自然语言 spec(背景 / 范围 in-out / `- [ ] AC-N` / 开放问题),**无形式化子句、无 checkbox**——计划在 tasks.md、设计在 design.md,别越界。Bug 修复用 Current / Expected 散文写在这里,不单独建 `bugfix.md`。 -3. **用户可见输出中文**;技术名 / 路径 / 代码标识符 / frontmatter 键名保持英文原样。 -4. **不回贴全文**(见 §6 报告纪律)。 +1. **Frontmatter contract (highest priority — explicitly required by the user)**: the YAML at the top of `requirements.md` **must** carry three fields — `spec_id` / `created_at` / `project_root`. `project_root` is the **single source of truth** for downstream distill / task-swarm / retrieval, and it may **only** be written through the single validated writer `resolve_root.py write-project-root` (it validates absolute path / dir exists / `/Volumes` mount); **never hand-write that field**. You change *who generates the body of requirements*, and must **never** break these contract elements. +2. **Prose requirements**: `requirements.md` is a natural-language spec (background / scope in-out / `- [ ] AC-N` / open questions), **no formalized clauses, no checkboxes** — the plan lives in tasks.md and the design in design.md; don't cross that boundary. Bug fixes go here as Current / Expected prose; there is no separate `bugfix.md`. +3. **User-facing output is Chinese** — technical names / paths / code identifiers / frontmatter key names stay verbatim. +4. **Never reprint the full document** (see §5 reporting discipline). -## §2 run.sh resolver 前缀(每次 CLI 调用) +## §2 run.sh resolver prefix (every CLI call) -所有 `resolve_root.py` 调用**必须**走 `run.sh` 包装器 + 绝对 plugin-root。skill 驱动的 Bash 里 `$CLAUDE_PLUGIN_ROOT` 不一定有值,必须 `find` 兜底。shell 状态不跨 Bash 调用保留,所以**每次**都带这段自包含 resolver 前缀: +Every `resolve_root.py` call **must** go through the `run.sh` wrapper with an absolute plugin-root. `$CLAUDE_PLUGIN_ROOT` is not reliably set in skill-driven Bash, so a `find` fallback is mandatory. Shell state does not persist across Bash calls, so prefix **every** call with this self-contained resolver: ```bash R="${CLAUDE_PLUGIN_ROOT:-$CODEBUDDY_PLUGIN_ROOT}"; [ -f "$R/scripts/run.sh" ] || R="$(find "$HOME/.claude/plugins/cache" "$HOME/.codebuddy/plugins/cache" -path '*/specode/*/scripts/run.sh' 2>/dev/null | sort -V | tail -1)"; R="${R%/scripts/run.sh}" sh "$R/scripts/run.sh" "$R/scripts/resolve_root.py" ``` -## §3 autonomous-mode 感知(每个 AskUserQuestion 站点适用) +## §3 Autonomous-mode awareness (applies at every AskUserQuestion site) -本 skill 有两处会 `AskUserQuestion`(§Step1 project_root 确认、§Step3 澄清)。每处**先**按 autonomous-mode 规则判定是否跳过——完整规则(gate→key→env mapping + 决策伪代码)见 `skills/specode/references/autonomous-mode.md`。要点:`interactive == false` 且该 gate 的 key `source ∈ {env, file}` 时跳过提问用 default,否则原样 `AskUserQuestion`。本 skill 的两处 gate:project_root 确认 → key `project_root_default`;澄清 → 无独立 key,仅受 `interactive` 主开关约束(非交互则基于已有信息尽力起草、把不确定项写进「开放问题」而非阻塞)。 +This skill has two `AskUserQuestion` sites (§Step 1 project_root confirmation, §Step 3 clarification). At each, first apply the autonomous-mode rule to decide whether to skip — the full rule (gate→key→env mapping + decision pseudo-code) is in `skills/specode/references/autonomous-mode.md`. In short: when `interactive == false` and the gate's key has `source ∈ {env, file}`, skip the prompt and use the default; otherwise ask via `AskUserQuestion`. This skill's two gates: project_root confirmation → key `project_root_default`; clarification → no dedicated key, governed only by the `interactive` master switch (when non-interactive, draft from the information at hand and record uncertainties under "开放问题" instead of blocking). -## §4 流程(5 步,质量在 Step 2–3) +## §4 Flow (5 steps; quality is in Step 2–3) -### Step 1 — project_root 确认(必做,autonomous-aware) +### Step 1 — Confirm project_root (required, autonomous-aware) -1. 取默认:`resolve_root.py resolve-project-root`(返回 cwd 的 `git rev-parse --show-toplevel`,无 git 则 cwd)。 -2. 按 §3 决定:`AskUserQuestion` 一次(默认值预选,让用户确认或覆盖)/ 或 autonomous 直接用 default。 -3. **持有确认的绝对路径**——Step 2(约束扫描 + 检索)用它、Step 4 经 `write-project-root` 落盘。此刻 requirements.md frontmatter 尚未写,直接用持有的绝对路径,**不要** `read-project-root`。 +1. Get the default: `resolve_root.py resolve-project-root` (returns `git rev-parse --show-toplevel` of cwd, else cwd). +2. Decide per §3: `AskUserQuestion` once (default pre-selected, user confirms or overrides), or use the default directly in autonomous mode. +3. **Hold the confirmed absolute path** — Step 2 (constraint scan + retrieval) uses it, and Step 4 persists it via `write-project-root`. At this point requirements.md frontmatter is not yet written, so use the held absolute path directly; do **not** call `read-project-root`. -### Step 2 — 项目分析(intake 高于问卷的关键,先读真实项目再问) +### Step 2 — Project analysis (what lifts intake above a questionnaire — read the real project before asking) -不是"问用户要什么"就完事——**先读真实项目建立事实基线**: +Don't stop at "ask the user what they want" — **read the real project first to build a factual baseline**: -- **a. 项目级约束扫描**(filesystem-only):扫下列存在的文件并以 **path-only**(不拷内容)注入 requirements 草稿的 `## 项目级约束(CLAUDE.md / AGENT.md)` 段。扫描序(去重、仅存在的):(1) `/CLAUDE.md|AGENTS.md|AGENT.md|CODEBUDDY.md`;(2) `` 直接父目录下同 4 文件(覆盖 monorepo workspace 根);(3) 用户描述中点名的子目录。段模板: +- **a. Project-level constraint scan** (filesystem-only): scan the following existing files and inject them **path-only** (do not copy content) into the requirements draft as a `## 项目级约束(CLAUDE.md / AGENT.md)` section. Scan order (deduped, existing only): (1) `/CLAUDE.md|AGENTS.md|AGENT.md|CODEBUDDY.md`; (2) the same four files in ``'s immediate parent (covers a monorepo workspace root); (3) any subdirectory named in the user's request. Section template: ```markdown ## 项目级约束(CLAUDE.md / AGENT.md) @@ -58,47 +58,47 @@ sh "$R/scripts/run.sh" "$R/scripts/resolve_root.py" - `` ``` - 为何 path-only:主 agent 上下文已有完整内容,复制一遍只是冗余 + 陈旧风险;task-swarm 渲染 task.md 时按同样规则把路径塞进 subagent prompt。一个文件都没扫到(典型 fresh 项目)→ **整段省略**(不写「无」之类占位)。 + Why path-only: the main agent already has the full content in context, so copying it in is redundant + staleness risk; task-swarm renders task.md by injecting these paths into subagent prompts by the same rule. If nothing is found (a typical fresh project) → **omit the whole section** (don't write a "none" placeholder). -- **b. 经验检索定位**(`/knowledge-base/MEMORY.md` 存在时)——**这是 ragkit / 经验检索的主节点**。按 `skills/specode/references/retrieval.md` 跑:先试 Tier-0 Gate(`ragkit:query` 可用且 `knowledge-base/.ragkit/chunks.json` 存在时多路召回),否则两级 gated(Tier-1 读 MEMORY 小索引比对当前需求页面/字段/域,命中才 Tier-2 读 ≤5 点全文)。产出「**参考定位(非事实来源)**」指针(文件路径 + 调用链)。`MEMORY.md` 不存在 → **静默跳过**(不报错、不写空段)。**顶层不变量**:指针只定位真实代码,**真实代码是唯一事实**;不把 KB 内容当当前代码的真相。 +- **b. Experience-retrieval location** (when `/knowledge-base/MEMORY.md` exists) — **this is the primary node for ragkit / experience retrieval**. Run it per `skills/specode/references/retrieval.md`: try the Tier-0 gate first (`ragkit:query` multi-recall when ragkit is available and `knowledge-base/.ragkit/chunks.json` exists), otherwise the two-tier gated flow (Tier-1 reads the small MEMORY index and matches the current need's page/field/domain; on a hit, Tier-2 reads ≤5 full docs). Produce `参考定位(非事实来源)` pointers (file paths + call chains). MEMORY.md absent → **silently skip** (no error, no empty section). **Top-level invariant**: pointers only locate real code; **real code is the only source of truth** — never treat KB content as the truth about current code. -- **c. 读真实代码**:对 b 定位到的关键文件**实际打开读**(不只拿路径)——理解现有结构 / 命名 / 模式,作为需求分析与范围界定的事实基线。 +- **c. Read the real code**: for the key files located in (b), **actually open and read them** (not just collect paths) — understand the existing structure / naming / patterns as the factual baseline for requirements analysis and scoping. -- **d. fresh 项目**(无 knowledge-base、无 agent docs)→ b/c 静默跳过,靠 Step 3 澄清 + 用户描述建立理解。 +- **d. Fresh project** (no knowledge-base, no agent docs) → (b)/(c) silently skipped; build understanding from Step 3 clarification + the user's description. -### Step 3 — 澄清(brainstorming 级,非固定问卷) +### Step 3 — Clarification (brainstorming-caliber, not a fixed questionnaire) -在 Step 2 的项目分析之上做**逐条澄清**(一次一个问题、优先多选),围绕 **purpose / scope(in / out)/ constraints / success criteria**。关键:**由 Step 2 的分析驱动**——问的是「基于现有的 `X` 代码/模式,这个需求该怎样接入 / 边界在哪」这类**有依据的问题**,不是空泛问卷。 +On top of Step 2's project analysis, **clarify one question at a time** (prefer multiple-choice), covering **purpose / scope (in / out) / constraints / success criteria**. The key: **let Step 2's analysis drive the questions** — ask grounded questions like "given the existing `X` code/pattern, how should this requirement plug in / where's the boundary" rather than a blank questionnaire. -- autonomous-aware(§3):非交互则基于已有信息尽力起草,把不确定项写进「开放问题」,不阻塞。 -- **何时停**:intent / scope / AC 足够清晰、开放问题已列出即可——不要过度追问(YAGNI)。 +- Autonomous-aware (§3): when non-interactive, draft from what you have and record uncertainties under "开放问题" instead of blocking. +- **When to stop**: once intent / scope / AC are clear enough and open questions are listed — don't over-ask (YAGNI). -### Step 4 — 写 requirements.md +### Step 4 — Write requirements.md -按 `assets/templates/requirements.md` 结构写正文:`## 背景 / 为什么` · `## 范围`(包含 / 不包含)· `## 验收标准`(`- [ ] AC-N`,可观察可验证)· `## 开放问题`(+ Step 2a 的 `## 项目级约束` 段,若有)。落 `//requirements.md`。 +Write the body per `assets/templates/requirements.md`: `## 背景 / 为什么` · `## 范围` (in / out) · `## 验收标准` (`- [ ] AC-N`, observable and verifiable) · `## 开放问题` (plus the `## 项目级约束` section from Step 2a, if any). Land it at `//requirements.md`. -然后落 **frontmatter(§1 硬约束)**: +Then persist the **frontmatter (§1 hard constraint)**: -1. 写 `spec_id: ` / `created_at: YYYY-MM-DD`(可随正文一起写进顶部 YAML)。 -2. **`project_root` 只经单一写入口落盘**: +1. Write `spec_id: ` / `created_at: YYYY-MM-DD` (fine to write into the top YAML alongside the body). +2. **`project_root` is written only through the single writer**: ```bash - sh "$R/scripts/run.sh" "$R/scripts/resolve_root.py" write-project-root --spec / --root + sh "$R/scripts/run.sh" "$R/scripts/resolve_root.py" write-project-root --spec / --root ``` - 它校验并把 `project_root` 写进 requirements.md frontmatter。**绝不手写该字段。** + It validates and writes `project_root` into requirements.md frontmatter. **Never hand-write that field.** -### Step 5 — 交接给 design +### Step 5 — Hand off to design -把 Step 2b 的「参考定位(非事实来源)」指针作为**临时上下文**交回 specode 编排(供 design 阶段用:specode 调 `brainstorming` 时把这段作为 context 传入,或 native design 直接沿用)。**不持久化为 requirements.md 的事实结论**(retrieval.md 顶层不变量)。design 默认继承这些指针、仅在开辟 intake 未覆盖的新领域时才补查(design 的检索是**条件性 top-up**,非强制)。 +Hand Step 2b's `参考定位(非事实来源)` pointers back to the specode orchestration as **ephemeral context** for the design phase (specode passes them as context when it calls `brainstorming`, or native design reuses them directly). **Do not persist them as factual conclusions in requirements.md** (the retrieval.md top-level invariant). Design inherits these pointers by default and only re-queries when it opens new territory intake didn't cover (design's retrieval is a **conditional top-up**, not mandatory). -交接后**结束本 skill**,把控制权还给 specode 编排(它接着进入 design phase)。 +After the handoff, **end this skill** and return control to the specode orchestration (which proceeds into the design phase). -## §5 报告纪律 +## §5 Reporting discipline -不回贴 requirements.md 全文。报告只含:文件路径(一行)+ 3-8 条要点/关键澄清 + 开放问题(若有)+ 下一步(进入 design)。唯一例外是用户明确要求看全文。 +Don't reprint the full requirements.md. Report only: the file path (one line) + 3-8 key points / clarifications + open questions (if any) + the next action (entering design). The only exception is when the user explicitly asks for the full text. ## §6 References -- `skills/specode/references/retrieval.md` — 经验检索规格(Step 2b 的引擎;intake 是其**主节点**)。 -- `skills/specode/references/knowledge-flow.md` — 一页纸知识流心智模型(KB 谁产·谁读·何时的全局图)。 -- `assets/templates/requirements.md` — 需求模板(Step 4 结构 + frontmatter 契约)。 -- `skills/specode/references/autonomous-mode.md` — §3 判定的完整规则来源(gate→key→env + 伪代码)。 +- `skills/specode/references/retrieval.md` — experience-retrieval spec (the engine behind Step 2b; intake is its **primary node**). +- `assets/templates/requirements.md` — requirements template (Step 4 structure + frontmatter contract). +- `skills/specode/references/autonomous-mode.md` — the full rule behind §3 (gate→key→env + pseudo-code). +- `skills/specode/references/knowledge-flow.md` — one-page knowledge-loop mental model (the global picture of who writes/reads the KB and when). From d063959bbf49d612ecbd0d010acf48b7b631ca3c Mon Sep 17 00:00:00 2001 From: qxbyte <126648675+qxbyte@users.noreply.github.com> Date: Sun, 5 Jul 2026 18:22:07 +0800 Subject: [PATCH 2/7] =?UTF-8?q?refactor(specode):=20retrieval.md=20instruc?= =?UTF-8?q?tion=20prose=20=E2=86=92=20English=20(keep=20contract=20row=20+?= =?UTF-8?q?=20injection=20block)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kept verbatim: the `| 标题 | 类型 | 描述 | 来源 | 路径 | tags |` contract row (the lockstep test extracts it), the `## 参考定位(非事实来源)` injection format block, and all Chinese field-name identifiers used as keys. Co-Authored-By: Claude Fable 5 Co-Authored-By: qxbyte <126648675+qxbyte@users.noreply.github.com> --- .../skills/specode/references/retrieval.md | 110 +++++++++--------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/plugins/specode/skills/specode/references/retrieval.md b/plugins/specode/skills/specode/references/retrieval.md index f1f6486..3f5dbd7 100644 --- a/plugins/specode/skills/specode/references/retrieval.md +++ b/plugins/specode/skills/specode/references/retrieval.md @@ -1,62 +1,62 @@ -# specode 经验检索注入(Tier-0 Gate + 两级 gated,模型驱动 prose) +# specode experience-retrieval injection (Tier-0 gate + two-tier gated, model-driven prose) -> 本文件是检索规格。**主调用方 = `specode:intake` skill 的项目分析步(§Step 2b)——检索的主节点**;design phase 只做**条件性 top-up**(默认继承 intake 已定位的指针,仅在开辟新领域时补查)。检索智能全在这里的 prose, -> **运行时无新增脚本**:读 `MEMORY.md` 用 `Read` 工具即可(它是 `/knowledge-base/` 下的本地文件)。 +> This file is the retrieval spec. **Primary caller = the project-analysis step (§Step 2b) of the `specode:intake` skill — the primary retrieval node**; the design phase does only a **conditional top-up** (inherits intake's located pointers by default, re-queries only when it opens new territory). All retrieval intelligence is prose here; +> **no extra script at runtime**: read `MEMORY.md` with the `Read` tool (it's a local file under `/knowledge-base/`). -## 顶层不变量 🔒(与本能力存在的理由) +## Top-level invariant 🔒 (the reason this capability exists) -KB 是「**定位用,非事实用**」: -- 新需求下,模型实现逻辑**不依赖** KB;KB 只提供**指针**(文件路径 + 调用链 + 导航经验)。 -- 拿到指针后**仍以真实代码为唯一事实**去读、分析、改。 -- 检索注入的全部价值 = **缩短「定位到要分析的代码」的延迟**,不增加事实来源。 -- 禁止:仅凭 KB 内容推进新需求 / 把历史结论当成当前代码的真相。 +The KB is **for locating, not for facts**: +- For a new requirement, the model's implementation logic does **not** depend on the KB; the KB only supplies **pointers** (file paths + call chains + navigation experience). +- Once you have a pointer, **real code remains the only source of truth** — read, analyze, and change against it. +- The entire value of retrieval injection = **shortening the latency of locating the code to analyze**, not adding a source of truth. +- Forbidden: advancing a new requirement on KB content alone / treating a historical conclusion as the truth about current code. -## 触发面 +## Trigger surface -- **主节点 = intake(requirements phase 的项目分析步)**:由 `specode:intake` skill §Step 2b 调用,产「参考定位(非事实来源)」指针。 -- **design phase = 条件性 top-up**:**默认继承 intake 的指针、不重复全量检索**;仅当 design 开辟了 intake 未覆盖的新领域时才按本规格补查一次。 -- **tasks 阶段不检索**:直接继承 design.md 已定位的文件路径。 -- **执行 / task-swarm 阶段零注入**:不向 task-swarm 传任何 KB / 检索产物,task-swarm 保持任意 spec 的纯执行器。 +- **Primary node = intake (the project-analysis step of the requirements phase)**: called by `specode:intake` §Step 2b, producing `参考定位(非事实来源)` pointers. +- **Design phase = conditional top-up**: **inherit intake's pointers by default, do not re-run a full retrieval**; re-query per this spec only when design opens territory intake didn't cover. +- **Tasks phase: no retrieval** — inherit the file paths already located in design.md. +- **Execution / task-swarm: zero injection** — pass no KB / retrieval artifact to task-swarm; it stays a pure executor of any spec. -## 前置(决定要不要检索) +## Precondition (whether to retrieve at all) -1. 经 `resolve_root.py read-project-root --spec /` 取 `project_root`。 -2. 看 `/knowledge-base/MEMORY.md` 是否存在。 - - **不存在**(fresh 项目 / 还没 distill 过)→ **静默跳过整个检索**,不报错、不写空段,正常进入需求/设计。 - - 存在 → 进入下方检索流程(先尝试 Tier-0 Gate,不适用时再走两级 gated)。 +1. Get `project_root` via `resolve_root.py read-project-root --spec /`. +2. Check whether `/knowledge-base/MEMORY.md` exists. + - **Absent** (fresh project / never distilled) → **silently skip the whole retrieval**; no error, no empty section, proceed normally into requirements/design. + - Present → enter the retrieval flow below (try the Tier-0 gate first, fall through to two-tier gated). -## Tier-0 Gate:RagKit(可选加速路,先于 Tier-1) +## Tier-0 gate: RagKit (optional fast path, ahead of Tier-1) -本节仅在「前置」通过(MEMORY.md 存在)后才被求值,且与「触发面」约束相同:**仅 intake(requirements 项目分析,主节点)与 design(条件性 top-up)生效,执行 / task-swarm 阶段不触发**。满足以下**全部**条件才走本节;任一不满足 → 跳过本节按下方两级 gated 流程执行,且**不要读取 RagKit 的任何文档/skill**(零额外 token): +This section is evaluated only after the precondition passes (MEMORY.md exists), and under the same trigger-surface constraint: **only intake (requirements project-analysis, primary) and design (conditional top-up); not triggered in execution / task-swarm**. Take this section only when **all** of the following hold; if any fails → skip it and run the two-tier gated flow below, and **do not read any RagKit doc/skill** (zero extra tokens): -1. 会话可用 skills 列表中存在 `ragkit:query`; -2. `test -f /knowledge-base/.ragkit/chunks.json` 成立(索引已构建)。 +1. `ragkit:query` is present in the session's available-skills list; +2. `test -f /knowledge-base/.ragkit/chunks.json` holds (the index is built). -走法: -- 检索词**由模型根据当前需求自行提炼**(页面名 / 字段 / 功能域 / 调用链等角度),调用 `ragkit:query` skill 执行检索;**允许多轮、多角度**调用,直到定位充分或确认无相关知识。 -- 返回的是定位卡片(指针)。对每条做语义取舍——tags/词面命中 ≠ 相关(同 Tier-1 纪律);采纳的条目按 Tier-2 方式 `Read` 原文并跳到真实代码;采纳条目按 Tier-2 同等纪律封顶(默认 ≤5 点/phase,复杂需求可标注理由突破)。 -- 注入仍用下方「注入格式」的「参考定位(非事实来源)」段;命中并注入后**跳过 Tier-1/2**。 -- RagKit 输出的降级/提示信息(╭─ RagKit ─╮ 块)原样转述给用户。 -- 若多轮检索后确认无相关知识 → 退出本节,继续下方 Tier-1/2 流程。 +How to run it: +- The model **derives the query terms itself** from the current need (page name / field / functional domain / call chain, etc.) and calls the `ragkit:query` skill; **multiple rounds and multiple angles are allowed** until location is sufficient or you confirm there's nothing relevant. +- It returns location cards (pointers). Judge each semantically — a tags/lexical match ≠ relevance (same discipline as Tier-1); for adopted entries `Read` the source and jump to real code as in Tier-2; cap adopted entries under the same Tier-2 discipline (default ≤5 per phase, may exceed with a stated reason for complex needs). +- Injection still uses the `参考定位(非事实来源)` section from the "Injection format" below; once you hit and inject, **skip Tier-1/2**. +- Relay RagKit's degradation/hint output (the ╭─ RagKit ─╮ block) to the user verbatim. +- If multiple rounds confirm nothing relevant → exit this section and continue with the Tier-1/2 flow below. -本 gate 与 RagKit **零依赖**:specode 不读其内部实现;RagKit 缺席时本节整体不生效(与 task-swarm 的 zero-import 模式同构)。 +This gate is **zero-dependency** on RagKit: specode does not read its internals; when RagKit is absent this section is simply inert (isomorphic to task-swarm's zero-import model). -## 两级 gated 检索 +## Two-tier gated retrieval -### Tier-1(默认便宜) -1. `Read` `/knowledge-base/MEMORY.md`(开销极小)。它每行一个知识点,列: - `| 标题 | 类型 | 描述 | 来源 | 路径 | tags |`。 -2. 取当前需求的**页面名 / 字段名 / 功能域**关键词,比对每条的 `tags` + `描述`。**`tags`/`描述` 命中只是「候选」,不等于相关**——必须进一步判断该知识点的「**改动类型 / 语义**」是否真适用于当前需求,不适用就不取。例:当前是「列表**加一列**」需求,命中了某「列表字段**脱敏**」case 的 `列表页` tag,但脱敏改法与加列不同类 → 只取其中的「定位类」点(如列表页定位套路),**不注入**脱敏 case。盲目「tag 命中即注入」会退化成 v3 的噪声注入、污染上下文。 -3. 若无(语义上真正)相关项 → 结束检索,默认成本仅一次小索引读。 +### Tier-1 (cheap by default) +1. `Read` `/knowledge-base/MEMORY.md` (tiny cost). One knowledge point per row, columns: + `| 标题 | 类型 | 描述 | 来源 | 路径 | tags |`. +2. Take the current need's **page name / field name / functional domain** keywords and compare against each row's `tags` + `描述`. **A `tags`/`描述` match is only a *candidate*, not relevance** — you must further judge whether the point's **change type / semantics** truly applies to the current need, and drop it if not. Example: the current need is "add a column to a list", and a "list field *masking*" case matched on its `列表页` tag, but masking is a different change type than adding a column → take only its "location-type" point (e.g. the list-page location routine), and **do not inject** the masking case. Blindly "inject on tag match" degrades into v3's noise injection and pollutes the context. +3. If nothing is (semantically) relevant → end retrieval; default cost is a single small index read. -### Tier-2(命中才贵) -4. 对命中项 `Read` 全文,**封顶 ≤5 个点 / phase**;可酌情少读。**软上限**:复杂需求命中更多点时,可在「参考定位」段**标注理由后突破 5**(N 本就是 prose 软约束)。 -5. 用文档里的 `前端文件 / 后端文件 / 调用链` 字段**跳到真实代码**,读真实代码做分析(真实代码是唯一事实)。 -6. **跨需求组合借鉴**:命中多个点时,按各自 `来源` 追溯各自的改法 / 定位路径,拼起来参考(例:新需求3 可同时命中「需求1 的脱敏 case」+「需求2 的列表定位 navigation」,组合参考)。 +### Tier-2 (expensive only on a hit) +4. `Read` the full text of matched points, **capped at ≤5 per phase**; read fewer when appropriate. **Soft cap**: for a complex need matching more points, you may **exceed 5 with a stated reason** in the `参考定位` section (N is a prose soft constraint anyway). +5. Use the doc's `前端文件 / 后端文件 / 调用链` fields to **jump to real code**, and analyze against the real code (real code is the only truth). +6. **Cross-requirement composition**: when several points hit, trace each one's `来源` back to its own change/location path and compose the references (e.g. new requirement 3 may hit both "requirement 1's masking case" + "requirement 2's list-location navigation", used together). -## 注入格式 +## Injection format -把检索结果贴成醒目的独立段,确保下游绝不误当事实: +Paste the results as a conspicuous standalone section so downstream never mistakes it for fact: ```markdown ## 参考定位(非事实来源,仅用于快速定位真实代码) @@ -65,22 +65,22 @@ KB 是「**定位用,非事实用**」: > 以上仅为定位指针,**可能指向计划中 / 已重构 / 已移动的代码**。实际改动以当前真实代码为准,需逐一打开核对。 ``` -- 在 **intake(requirements phase 项目分析)**:该段帮助分析「这个需求要动哪些真实代码」,作为澄清 / 范围界定的输入;**不写进 `requirements.md` 的事实结论**(作临时上下文交给 design)。 -- 在 **design phase(条件性 top-up)**:默认直接用 intake 交来的指针把模块边界 / 接口设计 ground 到真实代码;只有开辟新领域才补查。design 的判断仍基于真实代码(tasks 阶段不再单独检索,直接继承 design.md 已定位的文件路径)。 +- In **intake (requirements project-analysis)**: this section helps analyze "which real code this requirement touches", as input for clarification / scoping; **not written as a factual conclusion in `requirements.md`** (handed to design as ephemeral context). +- In **design (conditional top-up)**: by default use intake's handed pointers to ground module boundaries / interface design to real code; re-query only when opening new territory. Design's judgment is still based on real code (the tasks phase no longer retrieves — it inherits the file paths already located in design.md). -## schema ↔ 推理 对照表(变更纪律 🔒) +## Schema ↔ reasoning table (change discipline 🔒) -> KB schema 与本检索 prose 是同一份契约的两面,**锁步演进**:MEMORY/frontmatter 改一个字段,下表与对应步骤同步改;禁止各自漂移。三处(distill 写出的 frontmatter、`knowledge.py` 的 MEMORY 列、本检索 prose)必须一致。 +> The KB schema and this retrieval prose are two faces of one contract and **evolve in lockstep**: change a MEMORY/frontmatter field → change this table and the matching steps together; no independent drift. The three sites (the frontmatter distill writes, `knowledge.py`'s MEMORY columns, this retrieval prose) must agree. The `tests/test_contract_lockstep.py` gate enforces this. -| MEMORY / KB 字段 | 检索时怎么用 | +| MEMORY / KB field | how retrieval uses it | |---|---| -| `tags` / 关键词 | **Tier-1 主匹配键**:当前需求的页面/字段/域去比对 | -| `描述` | Tier-1 相关性二次信号 | -| `类型`(case/navigation) | 决定读取意图:case→借鉴同类需求改法;navigation→定位文件/入口 | -| `来源`(slug) | **跨需求组合借鉴**:命中多点时按来源追溯各自改法/路径拼接参考 | -| `路径` | Tier-2 命中后 `Read` 的目标(相对 `knowledge-base/`) | -| 文档内 `前后端文件 + 调用链` | 定位真实代码的跳板(读完去读真实代码) | +| `tags` / keywords | **Tier-1 primary match key**: compare the current need's page/field/domain against it | +| `描述` | Tier-1 secondary relevance signal | +| `类型` (case/navigation) | decides read intent: case → borrow a same-type requirement's change; navigation → locate files/entry points | +| `来源` (slug) | **cross-requirement composition**: on multiple hits, trace each `来源` to compose its change/path | +| `路径` | the `Read` target after a Tier-2 hit (relative to `knowledge-base/`) | +| the doc's `前后端文件 + 调用链` | the springboard to real code (after reading, go read the real code) | -## 为什么不重蹈 v3 +## Why this doesn't repeat v3 -v3 的确定性 Python recall 自动注入历史**内容**、不省 token,被 4.0.0 拔掉。本路线:① 引擎是模型判断、非脚本打分;② 默认只读小索引;③ 注入指针非事实、体量小且标注「非事实来源」;④ 命中才读、封顶 N=5。成功标准 = **定位更快/更准**(token 持平亦可接受)。 +v3's deterministic Python recall auto-injected historical **content** and didn't save tokens; it was removed in 4.0.0. This route: (1) the engine is model judgment, not a script score; (2) reads only the small index by default; (3) injects pointers not facts, small and labeled `非事实来源`; (4) reads only on a hit, capped at N=5. Success criterion = **faster/more accurate location** (token-neutral is acceptable). From 91b9a7281cf3fc814129b2d8e9f0f447bbad77b8 Mon Sep 17 00:00:00 2001 From: qxbyte <126648675+qxbyte@users.noreply.github.com> Date: Sun, 5 Jul 2026 18:23:30 +0800 Subject: [PATCH 3/7] =?UTF-8?q?refactor(specode):=20distill=20SKILL=20inst?= =?UTF-8?q?ruction=20prose=20=E2=86=92=20English=20(keep=20prompts/output?= =?UTF-8?q?=20Chinese)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit doc-template.md is left untouched (it's the produced KB-doc template = fixed output, stays Chinese). Kept verbatim in the SKILL: the AskUserQuestion user prompts (是否进入 distill…/继续沉淀 / 中止/复制一份到 Obsidian 库?) and the Chinese frontmatter field identifiers (标题/类型/来源/tags/描述). Co-Authored-By: Claude Fable 5 Co-Authored-By: qxbyte <126648675+qxbyte@users.noreply.github.com> --- plugins/specode/skills/distill/SKILL.md | 175 +++++++++--------------- 1 file changed, 64 insertions(+), 111 deletions(-) diff --git a/plugins/specode/skills/distill/SKILL.md b/plugins/specode/skills/distill/SKILL.md index b47a116..731da9e 100644 --- a/plugins/specode/skills/distill/SKILL.md +++ b/plugins/specode/skills/distill/SKILL.md @@ -7,35 +7,25 @@ description: > own `/knowledge-base/` (cases/ + navigation/ + MEMORY.md); optionally copied to an Obsidian vault. Trigger ONLY via `/specode:distill ` — never auto-run by the main specode flow. - Md-only, no auto-injection. Pure "atomic locate-pointer 沉淀器 for the + Md-only, no auto-injection. Pure "atomic locate-pointer sedimenter for the current project". --- -# distill — project knowledge-base 沉淀器(原子双轨) +# distill — project knowledge-base sedimenter (atomic dual-track) -## 顶层不变量 🔒 +## Top-level invariant 🔒 -**KB 是「定位用,非事实用」。** distill 写出的每个知识点是**定位指针**—— -文件路径 + 调用链 + 可复用导航经验,**不是事实结论**。检索端只用它快速 -**定位**到真实代码;真实代码始终是唯一事实来源。绝不允许仅凭 KB 内容推进 -新需求,或把历史结论当成当前代码的真相。这条不变量是整套设计存在的理由, -所有下游行为与本条冲突时以本条为准(见设计文档 §0)。 +**The KB is "for locating, not for facts".** Every knowledge point distill writes is a **location pointer** — file path + call chain + reusable navigation experience, **not a factual conclusion**. The retrieval side uses it only to quickly **locate** real code; real code is always the only source of truth. Never advance a new requirement on KB content alone, or treat a historical conclusion as the truth about current code. This invariant is the reason the whole design exists; where any downstream behavior conflicts with it, this rule wins (see design doc §0). -主产物是**项目目录** `/knowledge-base/`(检索端读的就是这里), -**不是** Obsidian。Obsidian 只是可选的人读副本。 +The primary product is the **project directory** `/knowledge-base/` (what the retrieval side reads), **not** Obsidian. Obsidian is only an optional human-readable copy. --- -## 定位与历史 +## Positioning & history -distill 是一个**手动、按需**触发的沉淀器:把一个完成(或进行中)的 spec + -**当前 agent 上下文**,提炼成若干**原子知识点**(一需求扇出 N 份独立文档), -落到该 spec 所属项目的 `knowledge-base/`,并维护一份轻量索引 `MEMORY.md`。 +distill is a **manual, on-demand** sedimenter: it turns a finished (or in-progress) spec + the **current agent context** into a set of **atomic knowledge points** (one requirement fans out into N standalone docs), files them into the spec's owning project `knowledge-base/`, and maintains a lightweight index `MEMORY.md`. -**md-only**(只产 markdown,无任何静默注入)。当前形态 = 项目 -`knowledge-base/` primary 的原子双轨(case + navigation)定位沉淀器 + 可选 -Obsidian 副本。(v1-v3 的自动注入 / yml 形态已在 4.0.0 / 5.0.1 完全移除;要旧 -行为 checkout `backup/specode-v3.4.0-task-swarm-v0.9.2`。历史细节见 CHANGELOG。) +**md-only** (produces only markdown, no silent injection). Current shape = a project-`knowledge-base/`-primary atomic dual-track (case + navigation) location sedimenter + optional Obsidian copy. (The v1-v3 auto-injection / yml shape was fully removed in 4.0.0 / 5.0.1; for the old behavior checkout `backup/specode-v3.4.0-task-swarm-v0.9.2`. History detail is in the CHANGELOG.) --- @@ -48,19 +38,13 @@ Obsidian 副本。(v1-v3 的自动注入 / yml 形态已在 4.0.0 / 5.0.1 完 | Arg | Default | Meaning | |---|---|---| | `` | (required) | spec slug under `/` | -| `--target-dir` | (none) | **可选** Obsidian 副本目录(绝对路径;直写不拼接)。不给则 Step 5 用 `AskUserQuestion` 询问 | +| `--target-dir` | (none) | **optional** Obsidian copy directory (absolute path; written directly, no concatenation). If omitted, Step 5 asks via `AskUserQuestion` | -主产物**固定**落 `/knowledge-base/`,不可由参数改写。`project_root` -由 `resolve_root.py read-project-root --spec /` 读取(来自该 -spec `requirements.md` frontmatter 的 `project_root`),**不从 cwd 反推**。 +The primary product **always** lands in `/knowledge-base/` and cannot be overridden by an argument. `project_root` is read via `resolve_root.py read-project-root --spec /` (from that spec's `requirements.md` frontmatter `project_root`), **never re-derived from cwd**. -**Manual only**:没有 auto-trigger。specode 主流程验收收尾后只**提示**入口 -(「是否进入 distill 沉淀本次经验?」),不强制、不自动跑。用户想更新本项目的 -定位库时才运行本命令。 +**Manual only**: there is no auto-trigger. After acceptance the main specode flow only **offers** the entry point (「是否进入 distill 沉淀本次经验?」), never forcing or auto-running it. Run this command when you want to update the project's location library. -> **建议在执行 + 验收完成后运行 distill。** 沉淀「已落地 + 已验证」的知识点价值 -> 最高;在尚未执行完的 spec 上沉淀,知识点可能指向**计划中但未落地的代码**(如 -> tasks 计划提到、但执行从未创建的工具文件)。Step 1 有一道执行完成度检查会就此告警。 +> **Recommended: run distill after execution + acceptance are complete.** Distilling "landed + verified" knowledge points has the highest value; distilling an unfinished spec risks pointers into **planned-but-unbuilt code** (e.g. a util file the tasks plan mentions but execution never created). Step 1 has a completion check that warns about this. --- @@ -68,130 +52,99 @@ spec `requirements.md` frontmatter 的 `project_root`),**不从 cwd 反推** | Source | What it provides | |---|---| -| `//` | spec dir(**只读**):`requirements.md` / `design.md` / `tasks.md` / `implementation-log.md` 等结构化事实 | -| `//requirements.md` YAML frontmatter | `project_root`(经 `read-project-root` 读出,用于定位主产物落盘目录) | -| **当前 agent 上下文** | 超出 spec 本身的**人类导航经验**:前后端调用链、页面按钮→哪个文件、什么配置映射到后端入口等,由模型从本轮上下文提炼并落地(navigation 型知识点的主来源) | +| `//` | spec dir (**read-only**): `requirements.md` / `design.md` / `tasks.md` / `implementation-log.md` and other structured facts | +| `//requirements.md` YAML frontmatter | `project_root` (read via `read-project-root`, used to locate the primary product directory) | +| **current agent context** | **human navigation experience** beyond the spec itself: front/back-end call chains, "this page button → which file", "which config maps to which backend entry", etc. — the model distills these from the current context (the primary source of navigation-type points) | --- ## Output structure ``` -/knowledge-base/ # 主产物(不提交项目仓库) -├── MEMORY.md # knowledge.py memory-rebuild 由各文档 frontmatter 生成 -├── cases/.md # 一个 case 型原子点一文件 -└── navigation/.md # 一个 navigation 型原子点一文件 +/knowledge-base/ # primary product (not committed to the repo) +├── MEMORY.md # generated by knowledge.py memory-rebuild from each doc's frontmatter +├── cases/.md # one case-type atomic point per file +└── navigation/.md # one navigation-type atomic point per file -/ # 可选副本:cp 文档过去 + 在该目录再跑一次 memory-rebuild +/ # optional copy: cp the docs over + rerun memory-rebuild there ├── MEMORY.md ├── cases/... └── navigation/... ``` -- 文件按**主题** kebab 命名,**不按 slug**;`slug` 降级为文档 frontmatter 的 - `来源` 溯源字段。每个文档的 frontmatter / 正文结构以 `references/doc-template.md` - 为准(两类模板:`case` / `navigation`,frontmatter 键名固定)。 -- `MEMORY.md` **不手改** —— 永远由 `knowledge.py memory-rebuild` 从各文档 - frontmatter 全量重建(frontmatter 是单一事实源)。 +- Files are named by **topic** (kebab), **not by slug**; `slug` degrades to the docs' frontmatter `来源` provenance field. Each doc's frontmatter / body structure follows `references/doc-template.md` (two templates: `case` / `navigation`, frontmatter keys are fixed). +- `MEMORY.md` is **never hand-edited** — always rebuilt in full by `knowledge.py memory-rebuild` from each doc's frontmatter (frontmatter is the single source of truth). --- -## Flow(5 步) +## Flow (5 steps) -> 所有 `resolve_root.py` / `knowledge.py` 调用**必须**走 `run.sh` 包装器,并用 -> 下面这段自包含 resolver 前缀解析 `$R`(skill 驱动的 Bash 调用里 -> `$CLAUDE_PLUGIN_ROOT` 不一定有值,必须 `find` 兜底): +> Every `resolve_root.py` / `knowledge.py` call **must** go through the `run.sh` wrapper, resolving `$R` with this self-contained prefix (`$CLAUDE_PLUGIN_ROOT` is not reliably set in skill-driven Bash, so a `find` fallback is mandatory): > > ```bash > R="${CLAUDE_PLUGIN_ROOT:-$CODEBUDDY_PLUGIN_ROOT}"; [ -f "$R/scripts/run.sh" ] || R="$(find "$HOME/.claude/plugins/cache" "$HOME/.codebuddy/plugins/cache" -path '*/specode/*/scripts/run.sh' 2>/dev/null | sort -V | tail -1)"; R="${R%/scripts/run.sh}" > ``` -### Step 1 — 解析 slug + project_root,建目录,落 .gitignore +### Step 1 — Resolve slug + project_root, make dirs, ensure .gitignore -1. 先用 `resolve_root.py get-root` 取 ``,确认 - `//requirements.md` 存在(否则报错退出)。 -2. 读 `project_root`: +1. Get `` via `resolve_root.py get-root` and confirm `//requirements.md` exists (else error out). +2. Read `project_root`: ```bash sh "$R/scripts/run.sh" "$R/scripts/resolve_root.py" read-project-root --spec / ``` - 退出 0 → stdout 即 `project_root`;非 0(缺 frontmatter / 路径非法)→ 报错并 - 提示该 spec 需先补 `project_root` 字段。 + exit 0 → stdout is `project_root`; non-zero (missing frontmatter / invalid path) → error and tell the user the spec needs its `project_root` field first. 3. `mkdir -p /knowledge-base/cases /knowledge-base/navigation` -4. 确保 `knowledge-base/` 进项目 `.gitignore`(不提交仓库): +4. Ensure `knowledge-base/` is in the project `.gitignore` (not committed): ```bash sh "$R/scripts/run.sh" "$R/scripts/knowledge.py" ensure-gitignore --project-root ``` -5. **执行完成度检查(F1,防悬空指针)**: +5. **Completion check (F1, dangling-pointer guard)**: ```bash sh "$R/scripts/run.sh" "$R/scripts/resolve_root.py" plan-unchecked --spec / ``` - - exit 0 → 该 spec 的计划 Task 已全部勾选(已执行),正常继续。 - - exit 2(仍有未勾选 `- [ ]` Task)或 exit 3(无 tasks.md 且 design.md 不含 - checkbox——尚未出计划)→ 该 spec **尚未执行完**, - 沉淀的知识点可能引用**未落地代码**。先 `AskUserQuestion` 警告并让用户选 - 「继续沉淀 / 中止」;用户选中止则结束,不写任何文档。 - (5.x legacy spec 的计划在 design.md 里,`plan-unchecked` 自动兜底识别,无需分支处理。) + - exit 0 → the spec's plan Tasks are all checked (executed), proceed normally. + - exit 2 (unchecked `- [ ]` Tasks remain) or exit 3 (no tasks.md and design.md has no checkboxes — no plan yet) → the spec is **not fully executed**, and distilled points may reference **unbuilt code**. First `AskUserQuestion` to warn and let the user pick 「继续沉淀 / 中止」; if they abort, end without writing any doc. + (5.x legacy specs keep the plan in design.md; `plan-unchecked` detects that automatically, no branching needed.) -### Step 2 — 读全 spec + 回顾 agent 上下文(不消费旧 KB) +### Step 2 — Read the whole spec + review agent context (don't consume old KB) -`Read` `//` 下每个 `.md`(requirements / design / tasks / -implementation-log 等),并回顾本轮 agent 上下文里反复用到的「找文件 / 调用链 / -配置映射」导航经验,留作 Step 3。 +`Read` every `.md` under `//` (requirements / design / tasks / implementation-log, etc.), and review the "find a file / call chain / config mapping" navigation experience you repeatedly used in this session's agent context, saved for Step 3. -> **不消费旧 KB 当事实**:**不**读任何旧 KB(`knowledge-base/` / `MEMORY.md`) -> 当事实输入。distill 只**产出**指针,从不把历史 KB 当真相消费。 -> (例外:Step 4 写 navigation 点前可 `Read` `MEMORY.md` **仅用于去重比对**—— -> 这是索引维护,不是把历史 KB 当事实喂给新内容,与本不变量不冲突。) +> **Don't consume old KB as fact**: do **not** read any old KB (`knowledge-base/` / `MEMORY.md`) as factual input. distill only **produces** pointers, never consumes historical KB as truth. (Exception: before writing a navigation point in Step 4 you may `Read` `MEMORY.md` **only for dedup comparison** — that's index maintenance, not feeding historical KB as fact into new content, and doesn't conflict with the invariant.) -### Step 3 — `AskUserQuestion` 提案原子拆分(不可跳过) +### Step 3 — `AskUserQuestion` to propose the atomic breakdown (not skippable) -按 `references/breakdown-heuristics.md` 把 spec + 上下文拆成若干**原子知识点**, -每点一文档,归入两类之一: +Per `references/breakdown-heuristics.md`, break the spec + context into a set of **atomic knowledge points**, one doc per point, in one of two categories: -- `case` —— 本需求「改了什么 + 在哪些前后端文件 + 调用链 + 踩坑」(每个独立改动 - 一个点,不要整需求塞一个文档)。 -- `navigation` —— 超出本需求的**项目级导航经验**(页面按钮→文件、配置→后端入口、 - 某类页面的定位套路),换个需求也能复用。 +- `case` — what this requirement "changed + in which front/back-end files + call chain + gotchas" (one point per independent change; don't cram a whole requirement into one doc). +- `navigation` — **project-level navigation experience** beyond this requirement (page button → file, config → backend entry, the location routine for a class of pages), reusable across requirements. -每个候选给 `标题 / 类型 / 来源(slug) / tags / 描述`;`tags` 取自**页面名 / -字段名 / 功能域**三类具体名词(不引入受控词表)。`AskUserQuestion` 让用户 -confirm / add / drop / rename / recategorize,锁定后进 Step 4。 +Give each candidate `标题 / 类型 / 来源(slug) / tags / 描述`; `tags` are taken from three kinds of concrete nouns — **page name / field name / functional domain** (no controlled vocabulary). `AskUserQuestion` lets the user confirm / add / drop / rename / recategorize; once locked, go to Step 4. -### Step 4 — 写 case/navigation 文档 + 重建 MEMORY +### Step 4 — Write case/navigation docs + rebuild MEMORY -逐个把确认后的知识点按 `references/doc-template.md` 写入 -`/knowledge-base/{cases,navigation}/.md`(host agent -直接 author markdown,无外部 writer CLI)。 +Write each confirmed knowledge point per `references/doc-template.md` into `/knowledge-base/{cases,navigation}/.md` (the host agent authors the markdown directly, no external writer CLI). -- 已存在同名文件 → `Read` 后问用户 `overwrite / skip / merge`。 -- **navigation 跨 spec 去重合并(写前必查,F7)**:写每个 navigation 点**前先 - `Read` `/knowledge-base/MEMORY.md`**,按 `tags` + `标题` 比对是否 - 已有同主题 navigation 点——是则 **merge/更新已有文档**(不新建重复文件),否则 - 新建。不查就新建会产生重复点,而 `memory-rebuild` 在索引层**不去重**(会把两条 - 都索引)。(仅 case 一需求一改一文档,通常不涉及去重。) +- Same-name file already exists → `Read` it, then ask the user `overwrite / skip / merge`. +- **navigation cross-spec dedup merge (must check before writing, F7)**: **before writing each navigation point, first `Read` `/knowledge-base/MEMORY.md`** and compare by `tags` + `标题` for an existing same-topic navigation point — if found, **merge/update the existing doc** (don't create a duplicate file), else create new. Skipping the check and creating new produces duplicate points, and `memory-rebuild` **does not dedup** at the index layer (it would index both). (case is one-change-one-doc per requirement and usually doesn't involve dedup.) -全部写完后,重建索引(由 frontmatter 全量重建,请勿手改 MEMORY.md): +Once all are written, rebuild the index (rebuilt in full from frontmatter, never hand-edit MEMORY.md): ```bash sh "$R/scripts/run.sh" "$R/scripts/knowledge.py" memory-rebuild --kb /knowledge-base ``` -### Step 5 — 双轨落盘(可选 Obsidian 副本) +### Step 5 — Dual-track landing (optional Obsidian copy) -`AskUserQuestion`「复制一份到 Obsidian 库?」: +`AskUserQuestion`「复制一份到 Obsidian 库?」: -- **不需要** → 结束。 -- **需要** → 让用户**输入绝对路径**(明确提示:这是直接写入的目录,distill - **不做任何拼接**)。若路径在 `/Volumes/` 下,先校验挂载 - (`ls "/Volumes/"` 成功,否则拒绝并提示)。然后: +- **No** → end. +- **Yes** → have the user **enter an absolute path** (state clearly: this is the exact write directory, distill does **no** concatenation). If the path is under `/Volumes/`, first verify the mount (`ls "/Volumes/"` succeeds, else refuse and warn). Then: ```bash sh "$R/scripts/run.sh" "$R/scripts/knowledge.py" copy-to --kb /knowledge-base --dest ``` - `copy-to` **一步完成**:把 `cases/` + `navigation/` 复制到副本目录并重建该目录 - 自己的 `MEMORY.md`(dest 绝对路径直写不拼接)。Obsidian 侧不重新生成内容、只复制 - + 重建索引。(旧的「手动 `cp` 两次 + 记得再 `memory-rebuild`」多步法已由本 verb 取代,杜绝漏跑重建。) + `copy-to` does it **in one step**: copies `cases/` + `navigation/` to the copy directory and rebuilds that directory's own `MEMORY.md` (dest absolute path written directly, no concatenation). The Obsidian side doesn't regenerate content, only copies + rebuilds the index. (The old "manual `cp` twice + remember to `memory-rebuild`" multi-step is replaced by this verb, eliminating the missed rebuild.) -> 双轨逻辑只属于 distill 自身:不影响主流程,也不影响检索端——检索端永远只读 -> 项目目录的 `knowledge-base/`,绝不读 Obsidian 副本。 +> The dual-track logic belongs to distill alone: it doesn't affect the main flow, nor the retrieval side — retrieval always reads only the project directory's `knowledge-base/`, never the Obsidian copy. --- @@ -199,20 +152,20 @@ sh "$R/scripts/run.sh" "$R/scripts/knowledge.py" memory-rebuild --kb /knowledge-base/` | distill 的主产物固定落项目目录的 `cases/` + `navigation/` + `MEMORY.md` | -| Spec 目录只读 | 绝不修改 `//` 下任何文件 | -| `project_root` 单一来源 | 经 `resolve_root.py read-project-root --spec ...` 读取,**不从 cwd 反推** | -| Obsidian 是可选副本,直写不拼接 | `--target-dir` / 用户输入的绝对路径直接作为写入目录,distill 不做任何路径拼接 | -| `/Volumes/` 挂载校验 | 副本目录在 `/Volumes/` 下时先验挂载,未挂载则拒绝 | -| `knowledge-base/` 不提交仓库 | 本地私有定位资产;落盘时 `ensure-gitignore` 保证 `.gitignore` 含 `knowledge-base/` | -| Md-only | 只产 markdown(无 yml、无静默注入) | -| 不消费旧 KB / 无注入 | distill 不读旧 KB 当事实;产物不喂任何后续 spec 的 `requirements.md`、不喂 task-swarm | -| MEMORY 不手改 | 永远由 `knowledge.py memory-rebuild` 从各文档 frontmatter 全量重建 | -| Read-before-overwrite | 目标 md 已存在 → `Read` 后问用户 overwrite / skip / merge | +| Primary write domain = `/knowledge-base/` | distill's primary product always lands in the project dir's `cases/` + `navigation/` + `MEMORY.md` | +| Spec dir read-only | never modify any file under `//` | +| `project_root` single source | read via `resolve_root.py read-project-root --spec ...`, **not re-derived from cwd** | +| Obsidian is an optional copy, written directly | `--target-dir` / the user-entered absolute path is used as the write directory as-is; distill does no path concatenation | +| `/Volumes/` mount check | when the copy dir is under `/Volumes/`, verify the mount first, refuse if not mounted | +| `knowledge-base/` not committed | local-private location asset; on landing, `ensure-gitignore` guarantees `.gitignore` contains `knowledge-base/` | +| Md-only | produces only markdown (no yml, no silent injection) | +| Don't consume old KB / no injection | distill doesn't read old KB as fact; its output feeds no later spec's `requirements.md`, and not task-swarm | +| MEMORY not hand-edited | always rebuilt in full by `knowledge.py memory-rebuild` from each doc's frontmatter | +| Read-before-overwrite | target md already exists → `Read` it, then ask the user overwrite / skip / merge | --- ## References -- `references/breakdown-heuristics.md` —— 原子知识点提炼 → case / navigation 两类映射。 -- `references/doc-template.md` —— case / navigation 两类文档的 frontmatter + 正文模板。 +- `references/breakdown-heuristics.md` — distilling atomic knowledge points → the case / navigation two-category mapping. +- `references/doc-template.md` — the frontmatter + body templates for the case / navigation doc types. From 752572693c8f76727b5706d2b48c830d07276bcc Mon Sep 17 00:00:00 2001 From: qxbyte <126648675+qxbyte@users.noreply.github.com> Date: Sun, 5 Jul 2026 18:26:47 +0800 Subject: [PATCH 4/7] =?UTF-8?q?refactor(specode):=20main=20SKILL=20+=20obs?= =?UTF-8?q?idian/knowledge-flow=20instruction=20prose=20=E2=86=92=20Englis?= =?UTF-8?q?h?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Converted the residual Chinese instruction prose to English. Kept verbatim Chinese: the 执行方式 selector option labels (user-facing selections), the "请验收"/"继续"/distill-prompt user phrases, the injected-section labels (## 项目级约束, 参考定位(非事实来源)), the design-template section names (背景与目标/…/测试策略), and MEMORY column identifiers. Also dropped two pure-history v4.0.0 blockquotes. selectors.md untouched (stays Chinese). Co-Authored-By: Claude Fable 5 Co-Authored-By: qxbyte <126648675+qxbyte@users.noreply.github.com> --- plugins/specode/skills/specode/SKILL.md | 34 +++++----- .../specode/references/knowledge-flow.md | 67 ++++++++++--------- .../skills/specode/references/obsidian.md | 6 +- 3 files changed, 53 insertions(+), 54 deletions(-) diff --git a/plugins/specode/skills/specode/SKILL.md b/plugins/specode/skills/specode/SKILL.md index 30f03bb..e90d8e9 100644 --- a/plugins/specode/skills/specode/SKILL.md +++ b/plugins/specode/skills/specode/SKILL.md @@ -24,7 +24,7 @@ Regardless of the execution engine (superpowers, task-swarm, or specode-native), | Document | Fixed filename | Content | |---|---|---| | Requirements | `requirements.md` | Prose spec: background / why · scope (in/out) · acceptance `- [ ] AC-N` · open questions. Pure natural language, no formalized clause syntax. | -| Design | `design.md` | **传统设计文档** (per the `assets/templates/design.md` sections): 背景与目标 / 架构概览(方案取舍)/ 模块划分与职责 / 接口设计 / 数据流 / 错误处理 / 测试策略. Prose + diagrams only — no checkboxes, no TDD steps. | +| Design | `design.md` | **Traditional design doc** (per the `assets/templates/design.md` sections): 背景与目标 / 架构概览(方案取舍)/ 模块划分与职责 / 接口设计 / 数据流 / 错误处理 / 测试策略. Prose + diagrams only — no checkboxes, no TDD steps. | | Plan | `tasks.md` | superpowers writing-plans executable-plan format: `Goal` / `Architecture` / `Tech Stack` + `## Task N` (each Task carries `**Files:**` file scope, `**Interfaces:**` Consumes/Produces contracts, `验证: AC-N` back-reference to requirements, `(needs: Task N)` dependencies, and `- [ ]` TDD steps). Engine-neutral — all four execution engines consume this one file. | | Execution log | `implementation-log.md` | Appended during execution: design deviations / key decisions / final acceptance summary. | @@ -56,20 +56,20 @@ Each phase is annotated "if superpowers is installed, call it / otherwise go nat 1. **specsRoot**: `get-root` (first-time setup if missing) → obtain `` → `mkdir -p //` (the host agent derives the kebab-case slug from the request). 2. **requirements (clarify + requirements)** — **invoke the `specode:intake` skill via the `Skill` tool** and let it own this whole phase. intake is a **standalone specode skill** (`skills/intake/`, peer to `distill`, `user-invocable: false`) — it is the **sole producer of `requirements.md`**; there is **no** "superpowers vs native" fork here anymore (`brainstorming` is used only for design, see step 3). intake internally runs, in order: (1) `project_root` confirmation (`resolve-project-root` default → `AskUserQuestion` once, autonomous-aware) — it holds the confirmed absolute path; (2) **project analysis**: agent-docs scan (`## 项目级约束` path-only section) + **experience retrieval — this is the primary retrieval node** (per `references/retrieval.md`: Tier-0 RagKit / two-tier gated) + actually reading the located real code; (3) analysis-driven clarification (brainstorming-caliber, one question at a time, not a fixed wizard); (4) write `requirements.md` per the template **and persist the frontmatter contract** — `spec_id` / `created_at` + `project_root` **via `resolve_root.py write-project-root`** (single validated writer; never hand-write it); (5) hand the located 「参考定位(非事实来源)」 pointers back as ephemeral context for design. Full behavior lives in `skills/intake/SKILL.md` — do not re-derive it here. - > **frontmatter 契约 🔒**: `requirements.md` 的 `spec_id` / `created_at` / `project_root` 是下游 distill / task-swarm / retrieval 的单一事实源;`project_root` 只经 `write-project-root` 单一写入口落盘。intake 负责保证这套契约,specode 编排不重复写、不手改。 -3. **design (传统设计文档)**: - - superpowers installed → call `superpowers:brainstorming` for **design only** (single artifact → `design.md`). Pre-instruct it: **requirements are already settled in `requirements.md` (read it as input) — go straight to design presentation, produce only `design.md`** per the `assets/templates/design.md` sections (背景与目标 / 架构概览 / 模块划分与职责 / 接口设计 / 数据流 / 错误处理 / 测试策略——散文,无 checkbox); also pass intake's 「参考定位(非事实来源)」 pointers as ephemeral grounding context. Relocate the artifact to `//design.md` (post-relocation check = **one** file). + > **frontmatter contract 🔒**: `requirements.md`'s `spec_id` / `created_at` / `project_root` are the single source of truth for downstream distill / task-swarm / retrieval; `project_root` is written only through the single writer `write-project-root`. intake guarantees this contract; the specode orchestration does not re-write or hand-edit it. +3. **design (traditional design doc)**: + - superpowers installed → call `superpowers:brainstorming` for **design only** (single artifact → `design.md`). Pre-instruct it: **requirements are already settled in `requirements.md` (read it as input) — go straight to design presentation, produce only `design.md`** per the `assets/templates/design.md` sections (背景与目标 / 架构概览 / 模块划分与职责 / 接口设计 / 数据流 / 错误处理 / 测试策略 — prose, no checkboxes); also pass intake's 「参考定位(非事实来源)」 pointers as ephemeral grounding context. Relocate the artifact to `//design.md` (post-relocation check = **one** file). - > brainstorming 的终态硬编码为「invoke writing-plans」——这正好对齐 specode 的 design → tasks 顺序,**顺其自然即可**:让它(或你)产完 design.md 后进入 tasks phase(step 4),不要在 design 里另起炉灶。 - - not installed → **specode-native**: the host agent authors `design.md` per the `assets/templates/design.md` template(同上七节,散文无 checkbox). - - **经验检索(条件性 top-up,非强制)**: design 默认**继承 intake(step 2)已定位的指针**,不重复全量检索。仅当 design 开辟了 intake 未覆盖的新领域时,才按 `references/retrieval.md` 补查一次(此 phase frontmatter 已写,用 `resolve_root.py read-project-root --spec /` 取 `project_root`);命中点的前后端文件 + 调用链用于把**模块边界 / 接口设计 ground 到真实代码**(design 的判断仍基于真实代码)。`/knowledge-base/MEMORY.md` 不存在 → 静默跳过。 + > brainstorming's terminal state is hardcoded to "invoke writing-plans" — that happens to align with specode's design → tasks order, so **let it flow naturally**: once design.md is produced (by it or by you), proceed into the tasks phase (step 4); don't start over inside design. + - not installed → **specode-native**: the host agent authors `design.md` per the `assets/templates/design.md` template (same seven sections, prose, no checkboxes). + - **experience retrieval (conditional top-up, not mandatory)**: design **inherits intake's (step 2) already-located pointers** by default and does not re-run a full retrieval. Only when design opens territory intake didn't cover, re-query once per `references/retrieval.md` (frontmatter is written by this phase, so get `project_root` via `resolve_root.py read-project-root --spec /`); the hits' front/back-end files + call chains ground **module boundaries / interface design to real code** (design's judgment is still based on real code). `/knowledge-base/MEMORY.md` absent → silently skip. - > design 检索是**定位用**(把设计 ground 到真实代码),只产出指针、**不引入任何「规则确认 / 偏离 gate」**(4.0.0 起不做任何 `.ai-memory/knowledge/rules/` 关联的 rule 检查;勿重新引入)。 + > design retrieval is **for locating** (grounding the design to real code), producing pointers only and **introducing no "rule acknowledgement / deviation gate"** (since 4.0.0, no `.ai-memory/knowledge/rules/`-related rule check; don't reintroduce it). 4. **tasks (executable plan)**: - - superpowers installed → call `superpowers:writing-plans`. Pre-instruct the target path `//tasks.md`. **writing-plans 结尾会硬编码问一句「Subagent-Driven vs Inline Execution」——它无参数可关;忽略那个提问、不据此进入执行**,继续走 specode 自己的 §执行方式 selector(step 5)。specode 只能"消化"这个提问,不是真的能抑制它。 + - superpowers installed → call `superpowers:writing-plans`. Pre-instruct the target path `//tasks.md`. **writing-plans ends by hardcoding a "Subagent-Driven vs Inline Execution" question — it has no flag to disable it; ignore that question and don't act on it**, and continue to specode's own §执行方式 selector (step 5). specode can only "digest" that question, not truly suppress it. - not installed → **specode-native**: break down into `## Task N` + `**Files:**` + `**Interfaces:**` + `验证: AC-N` + `- [ ]` TDD steps per the `assets/templates/tasks.md` template. - Relocate the artifact to `//tasks.md`. - - tasks 阶段**不做单独检索**——直接继承 design.md 已定位好的文件路径(`**Files:**` 从 design 的模块/接口落点导出)。 + - the tasks phase does **no separate retrieval** — it inherits the file paths already located in design.md (each `**Files:**` derives from design's module/interface landing points). 5. **「执行方式」selector**: after tasks.md is confirmed, call `AskUserQuestion` to present it (adaptive 4 options, see §执行方式 selector), verbatim per the `references/selectors.md` example. 6. **Execution** (branches by selector choice, all TDD): - Delegate to task-swarm (installed) → see §task-swarm handoff. @@ -79,11 +79,9 @@ Each phase is annotated "if superpowers is installed, call it / otherwise go nat - Append to `implementation-log.md` during execution. 7. **Acceptance (coding complete)**: - superpowers installed → call `superpowers:verification-before-completion` (optionally also `superpowers:requesting-code-review`). - - not installed → **specode-native**: the host agent verifies item by item against the `AC-N` in `requirements.md` / `design.md` 测试策略 / `tasks.md` checkbox 全勾. + - not installed → **specode-native**: the host agent verifies item by item against the `AC-N` in `requirements.md` / `design.md`'s test strategy (测试策略) / all `tasks.md` checkboxes checked. - Say "请验收" in prose and write an acceptance summary in `implementation-log.md`. **There is no formal acceptance-gate selector.** - - **沉淀提示(distill, gated by `auto_distill`)**: acceptance 写完后,按 §Autonomous-mode defaults rule 决定是否提示沉淀 —— 用 §specsRoot resolver `resolve_root.py read-defaults --key auto_distill --json` 取 effective value + source;当 `interactive == false` 且有 effective default(`source ∈ {env, file}`)时按 default **静默处理**(不打断),否则 `AskUserQuestion`「是否运行 `/specode:distill ` 把本次经验沉淀进项目 knowledge-base?」。distill 仍是**用户触发的独立命令**(本体行为见 `skills/distill/SKILL.md`,Plan A 已改为项目 `knowledge-base/` primary);这里只把入口提示重新挂回 acceptance 末尾,**不在主流程里自动跑 distill**。 - - > **v4.0.0 → 重新挂回**: 4.0.0 曾把 acceptance 后的自动 distill sub-step 整体移除;现按 `auto_distill` default **把入口提示重新挂回**(见上一条 bullet,遵循既有 autonomous-mode 规则——interactive 时询问、非 interactive 有 effective default 时静默,**非无条件自动执行**)。沉淀目标是项目 `knowledge-base/`(供下次 requirements/design 检索定位),md-only 行为见 `skills/distill/SKILL.md`。 + - **distill prompt (gated by `auto_distill`)**: after acceptance is written, decide whether to prompt for distillation per the §Autonomous-mode defaults rule — get the effective value + source via `resolve_root.py read-defaults --key auto_distill --json`; when `interactive == false` with an effective default (`source ∈ {env, file}`), handle it **silently** per the default (no interruption), otherwise `AskUserQuestion`「是否运行 `/specode:distill ` 把本次经验沉淀进项目 knowledge-base?」. distill is still a **user-triggered standalone command** (its behavior is in `skills/distill/SKILL.md`, now project-`knowledge-base/`-primary); this only re-hooks the entry-point prompt at the end of acceptance, and does **not** auto-run distill in the main flow. phase ↔ skill quick map: `requirements` → **`specode:intake`** (specode's own standalone skill, always — no superpowers fork); `design` → brainstorming (design only, single artifact) or native; `tasks` → writing-plans; execution → subagent-driven-development / executing-plans (the task-swarm path does not use superpowers); acceptance → verification-before-completion / requesting-code-review. @@ -104,7 +102,7 @@ specode treats both superpowers and task-swarm as **soft dependencies** (purely ## 执行方式 selector (the single fixed per-spec selector, after tasks.md completes) -After tasks.md is confirmed, call `AskUserQuestion` to present **adaptive 4 options** — **show an option only if its engine is installed**: +After tasks.md is confirmed, call `AskUserQuestion` to present **adaptive 4 options** — **show an option only if its engine is installed**. Pass the option label/description text below verbatim (they are user-facing selections and stay in Chinese): 1. **委托 task-swarm(多 agent 并发)** — requires task-swarm. 2. **superpowers subagent-driven(每 Task 派全新 subagent + 两阶段评审,推荐)** — requires superpowers. @@ -119,7 +117,7 @@ When presenting, pass question / header / options **verbatim** per the `referenc `/specode:continue ` (slug required; missing or nonexistent → error + suggest `/specode:list` first): locate `//`, read the directory contents, and infer the phase per this table. -**加载即停(load-and-stop)🔒**: `/specode:continue ` never auto-resumes. It does exactly three things: (1) locate `//` and read every fixed doc present; (2) report a **progress brief** — slug, inferred phase, per-doc existence, tasks.md checkbox progress (x/N; legacy specs: design.md checkboxes), and what the next action *would* be; (3) **stop and wait for the user's instruction**. Only when the user says 继续 (or equivalent) does execution resume from the inferred phase; if the user instead supplies requirement changes, digest them into the affected docs first, then ask whether to resume. The "Resume action" column below describes what happens *after* the user gives the go-ahead — it is not automatic behavior. +**Load-and-stop 🔒**: `/specode:continue ` never auto-resumes. It does exactly three things: (1) locate `//` and read every fixed doc present; (2) report a **progress brief** — slug, inferred phase, per-doc existence, tasks.md checkbox progress (x/N; legacy specs: design.md checkboxes), and what the next action *would* be; (3) **stop and wait for the user's instruction**. Only when the user says 继续 (or equivalent) does execution resume from the inferred phase; if the user instead supplies requirement changes, digest them into the affected docs first, then ask whether to resume. The "Resume action" column below describes what happens *after* the user gives the go-ahead — it is not automatic behavior. | Directory state | Inferred phase | Resume action (after user go-ahead) | |---|---|---| @@ -168,5 +166,5 @@ When writing / updating spec documents, **never** reprint the full text in chat. - `references/obsidian.md` — specsRoot path resolution, the full `resolve_root.py` verb table, and directory conventions. - `references/autonomous-mode.md` — the autonomous / CI defaults rule: gate→key→env mapping + the skip-the-prompt decision pseudo-code. - `references/superpowers-wiring.md` — the per-phase ↔ superpowers skill mapping, pre-instructions, and post-relocation instructions. -- `references/retrieval.md` — 经验检索注入规格(intake 项目分析为主节点 / design 条件性 top-up)。 -- `references/knowledge-flow.md` — 一页纸知识流心智模型:distill / knowledge-base / MEMORY / ragkit / intake-检索 的谁产·谁索引·谁读·何时。 +- `references/retrieval.md` — experience-retrieval injection spec (intake project-analysis is the primary node / design is a conditional top-up). +- `references/knowledge-flow.md` — one-page knowledge-loop mental model: who produces / indexes / reads distill / knowledge-base / MEMORY / ragkit / intake-retrieval, and when. diff --git a/plugins/specode/skills/specode/references/knowledge-flow.md b/plugins/specode/skills/specode/references/knowledge-flow.md index 32daa8f..6672bb6 100644 --- a/plugins/specode/skills/specode/references/knowledge-flow.md +++ b/plugins/specode/skills/specode/references/knowledge-flow.md @@ -2,47 +2,48 @@ description: One-page mental model of specode's experience/knowledge loop — who produces, who indexes, who reads, and when. Read this to understand how distill / knowledge-base / MEMORY / ragkit / intake-retrieval fit together. --- -# 知识流心智模型(谁产 · 谁索引 · 谁读 · 何时) +# Knowledge-flow mental model (who produces · indexes · reads · when) -一句话:**KB 是「定位用,非事实用」。** 它只提供指针(文件路径 + 调用链 + 导航经验)帮你更快跳到真实代码;**真实代码始终是唯一事实来源**。绝不允许仅凭 KB 内容推进新需求。 +In one line: **the KB is "for locating, not for facts".** It only supplies pointers (file paths + call chains + navigation experience) to help you jump to real code faster; **real code is always the only source of truth**. Never advance a new requirement on KB content alone. ``` - 产出(写) 索引 消费(读) + produce (write) index consume (read) ───────────────────────── ─────────────── ───────────────────────────── - /specode:distill MEMORY.md intake(requirements 项目分析) - (手动,验收末尾按 (小 md 索引,列 = 主检索节点 - auto_distill 提示; 标题/类型/描述/ · Tier-1 读 MEMORY 比对页面/字段/域 - 绝不自动跑) 来源/路径/tags) · 命中 → Tier-2 读 ≤5 点 → 跳真实代码 - │ ▲ · 若装 ragkit 且 chunks.json 存在 - ▼ │ memory-rebuild → Tier-0 ragkit:query 多路召回 - /knowledge-base/ (由各文档 frontmatter │ - ├── cases/.md ────────► 全量重建,不手改) ▼ - ├── navigation/.md .ragkit/(可选) design(条件性 top-up) - └── MEMORY.md chunks.json + vectors = 默认继承 intake 指针, - │ 由 /ragkit:embed 建 仅新领域才补查 - │(可选副本) (仅装 ragkit 时) │ - ▼ ▼ - Obsidian vault 把设计/需求 ground 到真实代码 - (knowledge.py copy-to, (tasks / 执行 / task-swarm = 零注入) - 人读镜像) + /specode:distill MEMORY.md intake (requirements analysis) + (manual; prompted at the (small md index, = primary retrieval node + end of acceptance per columns 标题/类型/ · Tier-1: read MEMORY, match page/field/domain + auto_distill; never 描述/来源/路径/tags) · hit → Tier-2: read ≤5 points → jump to real code + auto-run) ▲ · if ragkit present and chunks.json exists + │ │ memory-rebuild → Tier-0 ragkit:query multi-recall + ▼ │ (rebuilt in full │ + /knowledge-base/ from each doc's ▼ + ├── cases/.md ────────► frontmatter, design (conditional top-up) + ├── navigation/.md never hand-edited) = inherits intake's pointers by default, + └── MEMORY.md .ragkit/ (optional) re-queries only for new territory + │ chunks.json + vectors │ + │ (optional copy) built by /ragkit:embed ▼ + ▼ (only when ragkit ground design/requirements to real code + Obsidian vault installed) (tasks / execution / task-swarm = zero injection) + (knowledge.py copy-to, + human-readable mirror) ``` -## 铁律 +## Iron rules -- **产出是手动的**:只有 `/specode:distill ` 写 KB;主流程绝不自动沉淀(验收末尾只*提示*入口,按 `auto_distill` 决定)。 -- **frontmatter 是单一事实源**:`MEMORY.md` 永远由 `knowledge.py memory-rebuild` 从各文档 frontmatter 全量重建,**不手改**(`memory-validate` 查漂移)。 -- **消费只在两处**:intake 的项目分析步(主节点)+ design(条件性 top-up)。**tasks / 执行 / task-swarm 零注入**——到那时文件路径已在 design.md / tasks.md 里。 -- **注入是指针非事实**:贴成「参考定位(非事实来源)」段,只用于定位、不写进 requirements.md 的事实结论。 -- **全程 opt-in**:无 `knowledge-base/MEMORY.md` → 检索静默跳过(默认成本 ≈ 一次小索引读)。无 ragkit → Tier-0 不生效,退到 Tier-1/2。 -- **`knowledge-base/` 不入仓**:本地私有定位资产(`ensure-gitignore` 保证);Obsidian 副本是可选的人读镜像。 +- **Production is manual**: only `/specode:distill ` writes the KB; the main flow never auto-sediments (acceptance only *offers* the entry point, gated by `auto_distill`). +- **Frontmatter is the single source of truth**: `MEMORY.md` is always rebuilt in full by `knowledge.py memory-rebuild` from each doc's frontmatter, **never hand-edited** (`memory-validate` checks for drift). +- **Consumption happens in only two places**: intake's project-analysis step (primary node) + design (conditional top-up). **tasks / execution / task-swarm inject nothing** — by then the file paths are already in design.md / tasks.md. +- **Injection is pointers, not facts**: pasted as a `参考定位(非事实来源)` section, used only for locating, never written as a factual conclusion in requirements.md. +- **Fully opt-in**: no `knowledge-base/MEMORY.md` → retrieval is silently skipped (default cost ≈ one small index read). No ragkit → Tier-0 is inert, falls through to Tier-1/2. +- **`knowledge-base/` is not committed**: a local-private location asset (`ensure-gitignore` guarantees it); the Obsidian copy is an optional human-readable mirror. -## 契约锁步 🔒 +## Contract lockstep 🔒 -MEMORY 列 + frontmatter 键在三处必须一致:`skills/distill/references/doc-template.md`(写)、`scripts/knowledge.py` `_COLS`(索引)、`skills/specode/references/retrieval.md`(读)。改一处 → 改三处。`tests/test_contract_lockstep.py` 是这条纪律的 CI 门禁。 +The MEMORY columns + frontmatter keys must agree across three sites: `skills/distill/references/doc-template.md` (writes), `scripts/knowledge.py` `_COLS` (indexes), `skills/specode/references/retrieval.md` (reads). Change one → change all three. `tests/test_contract_lockstep.py` is the CI gate for this discipline. -## 各部件的权威文档 +## Authoritative doc for each part -- 产出:`skills/distill/SKILL.md` + `skills/distill/references/doc-template.md` -- 索引 CLI:`scripts/knowledge.py`(`memory-rebuild` / `memory-validate` / `copy-to` / `ensure-gitignore`) -- 消费:`skills/specode/references/retrieval.md`(Tier-0 gate + 两级 gated) -- 主消费方:`skills/intake/SKILL.md` §Step 2b +- Produce: `skills/distill/SKILL.md` + `skills/distill/references/doc-template.md` +- Index CLI: `scripts/knowledge.py` (`memory-rebuild` / `memory-validate` / `copy-to` / `ensure-gitignore`) +- Consume: `skills/specode/references/retrieval.md` (Tier-0 gate + two-tier gated) +- Primary consumer: `skills/intake/SKILL.md` §Step 2b diff --git a/plugins/specode/skills/specode/references/obsidian.md b/plugins/specode/skills/specode/references/obsidian.md index 54785d0..243b467 100644 --- a/plugins/specode/skills/specode/references/obsidian.md +++ b/plugins/specode/skills/specode/references/obsidian.md @@ -43,9 +43,9 @@ Autonomous-mode behavior (when to skip each `AskUserQuestion`) is specified in ` |---|---| | No requirements.md | intake | | requirements.md present, no design.md | design | -| design.md present (contains `## Task` + `- [ ]`), no tasks.md | legacy 5.x spec — design.md is the plan, 执行中/完成 by its checkboxes | +| design.md present (contains `## Task` + `- [ ]`), no tasks.md | legacy 5.x spec — design.md is the plan; executing/complete by its checkboxes | | design.md present (new-style prose), no tasks.md | tasks | -| tasks.md present, unchecked `- [ ]` remain | 执行中 | -| All tasks.md checkboxes checked | 完成 | +| tasks.md present, unchecked `- [ ]` remain | executing | +| All tasks.md checkboxes checked | complete | (The full continuation table, including load-and-stop semantics, lives in SKILL.md §Continuation.) From d61c7d9c139401d513a5cf2db492cbea72f729ac Mon Sep 17 00:00:00 2001 From: qxbyte <126648675+qxbyte@users.noreply.github.com> Date: Sun, 5 Jul 2026 18:28:10 +0800 Subject: [PATCH 5/7] =?UTF-8?q?refactor(specode):=20command=20files=20?= =?UTF-8?q?=E2=86=92=20English=20(keep=20the=20"=E7=BB=A7=E7=BB=AD"=20resu?= =?UTF-8?q?me=20keyword=20Chinese)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit distill.md fully translated to match the other commands' English descriptions; spec.md 传统设计文档 → traditional design doc. continue.md keeps "继续" (the Chinese word the user says to resume). selectors.md untouched. Co-Authored-By: Claude Fable 5 Co-Authored-By: qxbyte <126648675+qxbyte@users.noreply.github.com> --- plugins/specode/commands/distill.md | 32 ++++++++++++++--------------- plugins/specode/commands/spec.md | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/plugins/specode/commands/distill.md b/plugins/specode/commands/distill.md index 1042a71..126da67 100644 --- a/plugins/specode/commands/distill.md +++ b/plugins/specode/commands/distill.md @@ -1,26 +1,26 @@ --- -description: 手动把一个已完成(或进行中)的 spec 沉淀为项目 knowledge-base/ 的原子定位知识点(cases/ + navigation/ + MEMORY.md)。可选复制一份到 Obsidian 库。仅手动触发,绝不自动运行。 +description: Manually distill a finished (or in-progress) spec into the project's `knowledge-base/` as atomic location knowledge points (cases/ + navigation/ + MEMORY.md). Optionally copy to an Obsidian vault. Manual trigger only — never auto-run. --- -`/specode:distill ` — 把单个 spec 提炼成**原子定位知识点**,落盘到该 spec 所属项目的 `knowledge-base/`,并可选复制一份到 Obsidian 库。 +`/specode:distill ` — distill a single spec into **atomic location knowledge points**, landed in the spec's owning project `knowledge-base/`, optionally copied to an Obsidian vault. -用法: +Usage: -- `/specode:distill ` — slug 必须能在 `/` 下找到对应目录;`` 为必填 -- 可选 flag:`--target-dir ` — 直接指定 Obsidian 副本目录(绝对路径;直写不拼接);不给时 distill 结尾会用 `AskUserQuestion` 询问是否复制以及目标路径 +- `/specode:distill ` — the slug must resolve to a directory under `/`; `` is required. +- optional flag: `--target-dir ` — specify the Obsidian copy directory directly (absolute path; written directly, no concatenation); if omitted, distill ends by asking via `AskUserQuestion` whether to copy and where. -行为:调用 `distill` skill,纯粹从 spec 文档 + 当前 agent 上下文提炼原子知识点(case / navigation 两类)→ 落盘到项目 `knowledge-base/` → 重建 MEMORY.md 索引 → 可选 Obsidian 副本。完整流程以 `skills/distill/SKILL.md`(当前权威)为准。 +Behavior: invoke the `distill` skill, which distills atomic knowledge points (two types: case / navigation) purely from the spec docs + current agent context → lands them in the project `knowledge-base/` → rebuilds the MEMORY.md index → optional Obsidian copy. The full flow is authoritative in `skills/distill/SKILL.md`. -> 建议在**执行 + 验收完成后**运行:沉淀「已落地 + 已验证」的知识点价值最高;在未执行完的 spec 上沉淀,知识点可能指向未落地代码(distill Step 1 的执行完成度检查会告警)。 +> Recommended to run **after execution + acceptance are complete**: distilling "landed + verified" knowledge points has the highest value; distilling an unfinished spec risks pointers into unbuilt code (distill Step 1's completion check warns about this). -红线(v5.1+): +Red lines (v5.1+): -- **主写域 = `/knowledge-base/`**(`cases/` + `navigation/` + `MEMORY.md`);Obsidian 是**可选副本**,不是默认主产物 -- spec 目录**只读**:绝不修改 `//` 下任何文件 -- **md-only**:只产 markdown,无 yml、无任何静默注入 -- `--target-dir` / 用户输入路径**直写不拼接**;`/Volumes/` 下需先校验挂载 -- `knowledge-base/` 不提交项目仓库(落盘时 `ensure-gitignore` 保证) -- `project_root` 经 `resolve_root.py read-project-root --spec ...` 读取,**不从 cwd 反推** -- **仅手动触发** —— specode 主流程绝不自动调用;验收收尾后仅提示入口 +- **Primary write domain = `/knowledge-base/`** (`cases/` + `navigation/` + `MEMORY.md`); Obsidian is an **optional copy**, not the default primary product. +- Spec dir **read-only**: never modify any file under `//`. +- **md-only**: produces only markdown, no yml, no silent injection. +- `--target-dir` / the user-entered path is **written directly, no concatenation**; under `/Volumes/`, verify the mount first. +- `knowledge-base/` is not committed to the repo (`ensure-gitignore` guarantees it on landing). +- `project_root` is read via `resolve_root.py read-project-root --spec ...`, **not re-derived from cwd**. +- **Manual trigger only** — the main specode flow never auto-invokes it; acceptance only offers the entry point. -> 需要 v3 的旧行为(自动触发 + 写 `.ai-memory/knowledge/` 的 yml)?checkout `backup/specode-v3.4.0-task-swarm-v0.9.2`。 +> Need the v3 behavior (auto-trigger + writing yml to `.ai-memory/knowledge/`)? checkout `backup/specode-v3.4.0-task-swarm-v0.9.2`. diff --git a/plugins/specode/commands/spec.md b/plugins/specode/commands/spec.md index 940b092..025d7e4 100644 --- a/plugins/specode/commands/spec.md +++ b/plugins/specode/commands/spec.md @@ -20,4 +20,4 @@ After activation, follow the orchestration logic in specode SKILL.md (each phase - default: `resolve_root.py resolve-project-root` (returns `git rev-parse --show-toplevel` of cwd, falling back to cwd) → present it via `AskUserQuestion` **once** for the user to confirm/override. - persist: after requirements.md exists, `resolve_root.py write-project-root --spec / --root ` writes it into the requirements.md YAML frontmatter (validates absolute path / dir exists / `/Volumes` mounted). This frontmatter field is the **only** place project_root lives. - read (any later phase / skill): `resolve_root.py read-project-root --spec /` — the single read entry. Never read cwd/workdir instead. -4. Follow SKILL.md §pipeline: requirements (**`specode:intake` skill** — project analysis + clarification + writes requirements.md with the frontmatter contract) → design (brainstorming design-only/native, 传统设计文档) → tasks (writing-plans/native) → "execution mode" selector → execution → acceptance. Four fixed artifacts land under `//`. +4. Follow SKILL.md §pipeline: requirements (**`specode:intake` skill** — project analysis + clarification + writes requirements.md with the frontmatter contract) → design (brainstorming design-only/native, traditional design doc) → tasks (writing-plans/native) → "execution mode" selector → execution → acceptance. Four fixed artifacts land under `//`. From 28cec442e0344261e8d0e8b6e4c1561f9c923873 Mon Sep 17 00:00:00 2001 From: qxbyte <126648675+qxbyte@users.noreply.github.com> Date: Sun, 5 Jul 2026 18:32:15 +0800 Subject: [PATCH 6/7] =?UTF-8?q?refactor(specode):=20script=20docstrings=20?= =?UTF-8?q?+=20comments=20=E2=86=92=20English=20(keep=20user=20strings=20C?= =?UTF-8?q?hinese)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit resolve_root.py / knowledge.py / spec_hooks.py module + function docstrings and inline comments are now English. Kept Chinese (user-facing / contract): all stderr/stdout user messages, the MEMORY.md output note, the SessionStart DISCIPLINE reminder + cache-drift hint, and the _COLS / frontmatter key identifiers (标题/类型/描述/来源/路径/tags). Co-Authored-By: Claude Fable 5 Co-Authored-By: qxbyte <126648675+qxbyte@users.noreply.github.com> --- plugins/specode/scripts/knowledge.py | 31 ++++++------ plugins/specode/scripts/resolve_root.py | 66 +++++++++++++------------ plugins/specode/scripts/spec_hooks.py | 16 +++--- 3 files changed, 59 insertions(+), 54 deletions(-) diff --git a/plugins/specode/scripts/knowledge.py b/plugins/specode/scripts/knowledge.py index 4bc3900..ee1ab2a 100644 --- a/plugins/specode/scripts/knowledge.py +++ b/plugins/specode/scripts/knowledge.py @@ -1,18 +1,19 @@ #!/usr/bin/env python3 -"""knowledge.py — specode 项目级知识库 (knowledge-base/) 索引维护 (stdlib-only)。 +"""knowledge.py — index maintenance for specode's project knowledge-base/ (stdlib-only). verbs: - ensure-gitignore --project-root 确保 /.gitignore 含 `knowledge-base/` - (无 .git 且无 .gitignore 时跳过,不建 stray) - memory-rebuild --kb /**/*.md frontmatter 重建 /MEMORY.md - memory-validate --kb 校验 MEMORY 与磁盘文档是否一致(漂移检测) - copy-to --kb --dest 把 cases/+navigation/ 复制到 dest 并重建其 - MEMORY(一步 dual-landing;dest 绝对路径直写不拼接) - -knowledge-base/ 是「定位用,非事实用」的指针库;MEMORY.md 是其轻量索引, -单一事实源是各文档的 frontmatter——memory-rebuild 永远由 frontmatter 全量重建。 - -exit codes: 0 ok / 1 用法或参数错 / 2 校验发现漂移(memory-validate) + ensure-gitignore --project-root ensure /.gitignore contains `knowledge-base/` + (skipped when no .git and no .gitignore — no stray file) + memory-rebuild --kb rebuild /MEMORY.md from /**/*.md frontmatter + memory-validate --kb check MEMORY vs the on-disk docs for consistency (drift detection) + copy-to --kb --dest copy cases/+navigation/ to dest and rebuild its + MEMORY (one-step dual-landing; dest absolute path written directly) + +knowledge-base/ is a "for locating, not for facts" pointer library; MEMORY.md is its lightweight +index, and the single source of truth is each doc's frontmatter — memory-rebuild always rebuilds +it in full from frontmatter. + +exit codes: 0 ok / 1 usage or argument error / 2 drift found (memory-validate) """ from __future__ import annotations @@ -151,7 +152,7 @@ def cmd_memory_rebuild(args) -> int: def cmd_copy_to(args) -> int: """F4: one-step dual-landing — copy cases/ + navigation/ to an absolute - dest dir, then rebuild that dir's MEMORY. 直写不拼接:dest 即写入目录。""" + dest dir, then rebuild that dir's MEMORY. Written directly, no concatenation: dest IS the write dir.""" src = Path(args.kb) if not src.is_dir(): sys.stderr.write(f"knowledge: 源 knowledge-base 不存在:{src}\n") @@ -181,8 +182,8 @@ def cmd_ensure_gitignore(args) -> int: return 1 gi = root / ".gitignore" if not gi.exists() and not (root / ".git").exists(): - # F3: 非 git 项目且无既有 .gitignore → 不创建 stray 文件(无 git 时 - # .gitignore 也不生效;knowledge-base 本就本地私有,无需 ignore)。 + # F3: non-git project with no existing .gitignore → don't create a stray file + # (.gitignore has no effect without git; knowledge-base is local-private anyway). sys.stdout.write( f"knowledge: {root} 无 .git 且无 .gitignore,跳过" f"(knowledge-base 本地私有,无需 ignore)\n") diff --git a/plugins/specode/scripts/resolve_root.py b/plugins/specode/scripts/resolve_root.py index 068dcc0..be3cedd 100644 --- a/plugins/specode/scripts/resolve_root.py +++ b/plugins/specode/scripts/resolve_root.py @@ -1,26 +1,26 @@ #!/usr/bin/env python3 -"""resolve_root.py — specode lite 的 specsRoot 解析与持久化(stdlib-only)。 +"""resolve_root.py — specsRoot resolution + persistence for specode lite (stdlib-only). verbs: - get-root [--root P] 解析 specsRoot:--root > env SPECODE_ROOT > config.specsRoot - set-root --root P 绝对路径,持久化到 ~/.config/specode/config.json.specsRoot - list-specs [--root P] 列出 root 下的 spec 目录名(每行一个 slug):含任一固定产物 - (requirements/design/tasks/implementation-log.md)的子目录,或 - 空子目录(intake:目录已建、requirements 未写);隐藏目录除外 - - resolve-project-root [--cwd P] 计算 project_root 默认值(git toplevel || cwd),供 - host agent AskUserQuestion 确认用 - write-project-root --spec P --root A 把 project_root 写进 spec 的 requirements.md - frontmatter(单一写入口;校验绝对路径/目录存在/挂载) - read-project-root --spec P 从 spec 的 requirements.md frontmatter 读 project_root - (所有下游唯一读入口;缺字段 exit 3 / 值非法 exit 4) - -project_root 是 spec(在 specsRoot 下)与其知识落地项目之间的唯一 join key,**只存一处** -——该 spec 的 requirements.md YAML frontmatter。write/read 是其唯一写入口与读入口,杜绝各 -环节各自用 cwd/workdir 推导导致的分裂。 - -exit codes: 0 ok / 1 用法或参数错 / 3 未配置(specsRoot 未配置 / project_root 字段缺失) - / 4 project_root 值非法(非绝对 / 目录不存在 / 外置盘未挂载) + get-root [--root P] resolve specsRoot: --root > env SPECODE_ROOT > config.specsRoot + set-root --root P absolute path, persisted to ~/.config/specode/config.json.specsRoot + list-specs [--root P] list spec dir names under root (one slug per line): subdirs + containing any fixed doc (requirements/design/tasks/implementation-log.md), + or empty subdirs (intake: dir created, requirements not yet written); + hidden dirs excluded + resolve-project-root [--cwd P] compute the project_root default (git toplevel || cwd), + for the host agent to confirm via AskUserQuestion + write-project-root --spec P --root A write project_root into a spec's requirements.md + frontmatter (single writer; validates absolute / dir exists / mount) + read-project-root --spec P read project_root from a spec's requirements.md frontmatter + (the single reader for all downstream; missing field exit 3 / invalid exit 4) + +project_root is the sole join key between a spec (under specsRoot) and its target project, stored +in exactly ONE place — that spec's requirements.md YAML frontmatter. write/read are its only +write/read entry points, preventing the split-brain of each step deriving it from cwd/workdir. + +exit codes: 0 ok / 1 usage or argument error / 3 unconfigured (specsRoot unset / project_root field missing) + / 4 project_root value invalid (non-absolute / dir missing / external drive not mounted) """ from __future__ import annotations @@ -59,7 +59,7 @@ def _atomic_write_json(path: Path, data: dict) -> None: fd, tmp = tempfile.mkstemp(dir=str(path.parent), suffix=".tmp") try: with os.fdopen(fd, "w", encoding="utf-8") as f: - fd = -1 # fdopen 接管 fd + fd = -1 # fdopen takes over the fd json.dump(data, f, ensure_ascii=False, indent=2) f.flush() os.fsync(f.fileno()) @@ -81,7 +81,8 @@ def _resolve(root_flag): if env: return env cfg = _read_config() - # specsRoot 是当前键;obsidianRoot 是 1.0.0 前的旧键,读端兜底让老用户升级即用、不必重设。 + # specsRoot is the current key; obsidianRoot is the pre-1.0.0 legacy key — the read side + # falls back to it so upgrading users keep working without re-setting. val = cfg.get("specsRoot") or cfg.get("obsidianRoot") return val or None @@ -103,7 +104,7 @@ def cmd_set_root(args) -> int: return 1 cfg = _read_config() cfg["specsRoot"] = p - # v0.9 痛点 #8: drop the legacy `obsidianRoot` key so downstream plugins + # v0.9 pain point #8: drop the legacy `obsidianRoot` key so downstream plugins # that still read it (obsidian-wiki etc.) don't see a stale path after # the user moves their vault. The read-side already falls back from # specsRoot to obsidianRoot, so leaving both in the JSON silently created @@ -118,14 +119,14 @@ def cmd_set_root(args) -> int: def _is_spec_dir(child: Path) -> bool: - """含任一固定产物 → spec;空目录 → intake spec(目录已建、requirements 未写)。 - 只装无关内容的目录(如 attachments/)不算 spec。""" + """Has any fixed doc → spec; empty dir → intake spec (dir created, requirements not yet written). + A dir holding only unrelated content (e.g. attachments/) is not a spec.""" if any((child / doc).exists() for doc in _FIXED_DOCS): return True try: next(child.iterdir()) except StopIteration: - return True # 空目录 = intake + return True # empty dir = intake except OSError: return False return False @@ -138,10 +139,10 @@ def cmd_list_specs(args) -> int: return 3 base = Path(root) if not base.is_dir(): - return 0 # 配置了但目录还不存在 → 空列表 + return 0 # configured but the dir doesn't exist yet → empty list for child in sorted(base.iterdir()): if child.name.startswith("."): - continue # .obsidian / .git 等隐藏目录不是 spec + continue # hidden dirs like .obsidian / .git are not specs if child.is_dir() and _is_spec_dir(child): sys.stdout.write(child.name + "\n") return 0 @@ -155,7 +156,7 @@ def _atomic_write_text(path: Path, text: str) -> None: fd, tmp = tempfile.mkstemp(dir=str(path.parent), suffix=".tmp") try: with os.fdopen(fd, "w", encoding="utf-8") as f: - fd = -1 # fdopen 接管 fd + fd = -1 # fdopen takes over the fd f.write(text) f.flush() os.fsync(f.fileno()) @@ -286,7 +287,8 @@ def cmd_write_project_root(args) -> int: return 1 req = _requirements_path(args.spec) if not req.is_file(): - # 允许在尚无 requirements.md 时由上层先创建;这里要求文件已存在以免写错位置 + # allow an upper layer to create requirements.md first; require the file to exist + # here so we don't write to the wrong place sys.stderr.write(f"specode: 找不到 requirements.md:{req}\n") return 1 text = req.read_text(encoding="utf-8") @@ -344,7 +346,7 @@ def cmd_plan_unchecked(args) -> int: line.lstrip().startswith(("- [ ]", "- [x]")) for line in d.read_text(encoding="utf-8").splitlines() ): - target = d # 5.x legacy spec:design.md 即计划 + target = d # 5.x legacy spec: design.md is the plan else: sys.stderr.write( f"specode: 找不到可执行计划(无 tasks.md," @@ -539,7 +541,7 @@ def cmd_reset_default(args) -> int: def cmd_doctor(args) -> int: - """v0.9 痛点 #9: surface config drift early. + """v0.9 pain point #9: surface config drift early. Exit codes mirror the read-project-root convention so scripts can branch deterministically: diff --git a/plugins/specode/scripts/spec_hooks.py b/plugins/specode/scripts/spec_hooks.py index 04a515f..83a8f9e 100644 --- a/plugins/specode/scripts/spec_hooks.py +++ b/plugins/specode/scripts/spec_hooks.py @@ -1,13 +1,15 @@ #!/usr/bin/env python3 -"""spec_hooks.py — specode lite 的唯一 hook:SessionStart 注入纪律。 +"""spec_hooks.py — specode lite's only hook: SessionStart discipline injection. -读 stdin(容忍非 TTY / 空),emit additionalContext JSON 到 stdout,exit 0。 -任何异常都吞掉并 exit 0(advisory,绝不阻断)。 +Reads stdin (tolerates non-TTY / empty), emits additionalContext JSON to stdout, exit 0. +Swallows any exception and exits 0 (advisory, never blocks). -v0.9 试跑 M8:增加 _check_plugin_cache_drift() 静默 check —— 解析 __file__ -推当前 cache 装载的版本号,对照本地 pluginhub git 仓库(如果存在)的 -marketplace.json 最新版本,diff 时在 additionalContext 末尾加一段提示 -告诉用户 reload。无网络访问;marketplace.json 不可达时 skip silently。 +v0.9 trial M8: adds a silent _check_plugin_cache_drift() — parses __file__ to infer the +currently cache-loaded version, compares against the local pluginhub git repo's (if present) +marketplace.json latest version, and on a diff appends a hint to additionalContext telling the +user to reload. No network access; if marketplace.json is unreachable, skip silently. + +Note: the emitted DISCIPLINE reminder and the drift-hint message stay Chinese (user-facing output). """ from __future__ import annotations From 62337250ffc48c4e48a15b8829a38da7bcac0212 Mon Sep 17 00:00:00 2001 From: qxbyte <126648675+qxbyte@users.noreply.github.com> Date: Sun, 5 Jul 2026 18:33:16 +0800 Subject: [PATCH 7/7] =?UTF-8?q?release(specode):=206.1.2=20=E2=80=94=20plu?= =?UTF-8?q?gin=20language=20unification=20(specode=20only)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bump manifests to 6.1.2, date both CHANGELOGs (kept Chinese per standing rule), refresh README version rows + badge. Co-Authored-By: Claude Fable 5 Co-Authored-By: qxbyte <126648675+qxbyte@users.noreply.github.com> --- .claude-plugin/marketplace.json | 4 ++-- CHANGELOG.md | 4 ++++ README.md | 4 ++-- README.zh-CN.md | 4 ++-- plugins/specode/.claude-plugin/plugin.json | 4 ++-- plugins/specode/CHANGELOG.md | 6 +++++- 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index a6d6c0a..f86e912 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,8 +9,8 @@ { "name": "specode", "source": "./plugins/specode", - "version": "6.1.1", - "description": "Lightweight spec-driven workflow: orchestrates superpowers skills per phase, lands 4 fixed docs (requirements/design/tasks/implementation-log). **v6.1.1**: 新增契约锁步 CI 门禁 tests/test_contract_lockstep.py(MEMORY 列 + frontmatter 键在 knowledge.py/retrieval.md/doc-template.md 三处一致,负控验证可抓 reorder/drop);新增 references/knowledge-flow.md 一页纸知识流心智模型(distill/knowledge-base/MEMORY/ragkit/intake-检索 的谁产·谁读·何时)。 **v6.1.0**: 新增独立 intake skill(skills/intake/,同 distill,user-invocable:false)接管 requirements phase — 项目分析(agent-docs 扫描+经验检索+读真实代码)+基于分析的澄清+写 requirements.md(保留 spec_id/created_at/project_root frontmatter 契约);修正 6.0.0 的brainstorming 双产物错位 — brainstorming 从此只产 design.md(单产物),requirements 由 intake 产;检索主节点移到 intake 项目分析步、design 降为条件性 top-up;弊端修复 — writing-plans 结尾的执行方式提问改为「忽略而非抑制」;SKILL 轻量化 215→171 行(verb 表/autonomous-mode 细节下沉到 refs,零行为变化)。 **v6.0.0 BREAKING**: 固定产物 3→4 — design.md 重定义为**传统设计文档**(背景与目标/架构概览/模块划分/接口设计/数据流/错误处理/测试策略,散文无 checkbox);新增 tasks.md 承载可执行计划(writing-plans 格式 + Interfaces 契约块,引擎中立,task-swarm/superpowers/自执行统一消费,pipeline.yml 改从 tasks.md 推导);流水线变为 requirements→design→tasks→执行方式 selector→执行→验收,brainstorming 一次跨 requirements+design 双产物落盘(后置 relocate 检查两份);continue 改「加载即停」— 只读文档+汇报进度简报后停下等指令,绝不自动续跑;design-unchecked 更名 plan-unchecked(tasks.md 优先,design.md 含 checkbox 按 5.x legacy 兜底,旧名保留 alias)。5.x 存量 spec 由 continue 推断表 legacy 行兜底识别,不中断。 **v5.2.0**: 新增 Tier-0 RagKit gate — 检测到 ragkit 插件 + 已建索引(chunks.json)时,requirements/design 的经验检索走 `ragkit:query` 多路召回(模型自主提炼检索词、可多轮多角度、≤5 点封顶),未安装零成本跳过,zero-import。 **v5.1.3**: `list-specs` 让 intake 阶段(目录已建、requirements 未写)的 spec 可见 — 列出含任一固定产物的子目录 + 空子目录(intake),隐藏目录与无关内容目录仍排除;全库文档陈旧内容清理(README/CONTRIBUTING/SKILL 残留措辞)。 **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`。", + "version": "6.1.2", + "description": "Lightweight spec-driven workflow: orchestrates superpowers skills per phase, lands 4 fixed docs (requirements/design/tasks/implementation-log). **v6.1.2**: 插件语言统一(仅 specode,零行为变化)——面向 agent 的指令/说明 prose 全部转地道英文(SKILL/references/commands/脚本 docstring+注释);用户可见的固定输出与选择保持中文(执行方式 selector、模板、注入段 ## 项目级约束 / ## 参考定位、脚本 stderr 用户消息、CHANGELOG)。 **v6.1.1**: 新增契约锁步 CI 门禁 tests/test_contract_lockstep.py(MEMORY 列 + frontmatter 键在 knowledge.py/retrieval.md/doc-template.md 三处一致,负控验证可抓 reorder/drop);新增 references/knowledge-flow.md 一页纸知识流心智模型(distill/knowledge-base/MEMORY/ragkit/intake-检索 的谁产·谁读·何时)。 **v6.1.0**: 新增独立 intake skill(skills/intake/,同 distill,user-invocable:false)接管 requirements phase — 项目分析(agent-docs 扫描+经验检索+读真实代码)+基于分析的澄清+写 requirements.md(保留 spec_id/created_at/project_root frontmatter 契约);修正 6.0.0 的brainstorming 双产物错位 — brainstorming 从此只产 design.md(单产物),requirements 由 intake 产;检索主节点移到 intake 项目分析步、design 降为条件性 top-up;弊端修复 — writing-plans 结尾的执行方式提问改为「忽略而非抑制」;SKILL 轻量化 215→171 行(verb 表/autonomous-mode 细节下沉到 refs,零行为变化)。 **v6.0.0 BREAKING**: 固定产物 3→4 — design.md 重定义为**传统设计文档**(背景与目标/架构概览/模块划分/接口设计/数据流/错误处理/测试策略,散文无 checkbox);新增 tasks.md 承载可执行计划(writing-plans 格式 + Interfaces 契约块,引擎中立,task-swarm/superpowers/自执行统一消费,pipeline.yml 改从 tasks.md 推导);流水线变为 requirements→design→tasks→执行方式 selector→执行→验收,brainstorming 一次跨 requirements+design 双产物落盘(后置 relocate 检查两份);continue 改「加载即停」— 只读文档+汇报进度简报后停下等指令,绝不自动续跑;design-unchecked 更名 plan-unchecked(tasks.md 优先,design.md 含 checkbox 按 5.x legacy 兜底,旧名保留 alias)。5.x 存量 spec 由 continue 推断表 legacy 行兜底识别,不中断。 **v5.2.0**: 新增 Tier-0 RagKit gate — 检测到 ragkit 插件 + 已建索引(chunks.json)时,requirements/design 的经验检索走 `ragkit:query` 多路召回(模型自主提炼检索词、可多轮多角度、≤5 点封顶),未安装零成本跳过,zero-import。 **v5.1.3**: `list-specs` 让 intake 阶段(目录已建、requirements 未写)的 spec 可见 — 列出含任一固定产物的子目录 + 空子目录(intake),隐藏目录与无关内容目录仍排除;全库文档陈旧内容清理(README/CONTRIBUTING/SKILL 残留措辞)。 **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/CHANGELOG.md b/CHANGELOG.md index 6c5b5a6..060f148 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +## 6.1.2 (2026-07-05) — specode + +- **插件语言统一(仅 specode,零行为变化)**:面向 agent 的指令/说明 prose(SKILL / references / commands / 脚本 docstring+注释)全部转地道英文;用户可见的固定输出与选择保持中文(执行方式 selector、模板、注入段 `## 项目级约束` / `## 参考定位`、脚本 stderr 用户消息、CHANGELOG、契约字段标识符)。测试零回归(90 passed)。 + ## 6.1.1 (2026-07-05) — specode - **契约锁步 CI 门禁**(`tests/test_contract_lockstep.py`):MEMORY 列 + frontmatter 键在 `knowledge.py` / `retrieval.md` / `doc-template.md` 三处一致,负控验证可抓 reorder/drop(+5 测,共 90)。 diff --git a/README.md b/README.md index 9d8effa..d934c4e 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-6.1.1-blue.svg)](./plugins/specode/.claude-plugin/plugin.json) +[![specode](https://img.shields.io/badge/specode-6.1.2-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.1-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** | 6.1.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 4 fixed docs per spec. **v6.1.1**: contract-lockstep CI gate (`test_contract_lockstep.py`) keeps the MEMORY column + frontmatter contract byte-identical across knowledge.py / retrieval.md / doc-template.md (negative-controlled to catch reorder/drop); new `references/knowledge-flow.md` one-page knowledge-loop mental model. **v6.1.0**: new standalone `specode:intake` skill (peer to `distill`) owns the requirements phase — project analysis (agent-docs scan + experience retrieval + reading located real code) + analysis-driven clarification + writes `requirements.md` preserving the `spec_id`/`created_at`/`project_root` frontmatter contract; fixes the 6.0.0 brainstorming dual-artifact mismatch (brainstorming now produces `design.md` only); retrieval's primary node moves to intake with design as a conditional top-up; writing-plans' execution-mode question is now ignored (not "suppressed"); SKILL.md lightened 215→171 lines (verb table + autonomous-mode detail sunk to references) and dead v3/codemap-term noise dropped from distill. **v6.0.0 BREAKING**: fixed docs 3 → 4 — `design.md` redefined as a **traditional design doc** (背景与目标/架构概览/模块划分/接口设计/数据流/错误处理/测试策略, prose only, no checkboxes); new `tasks.md` carries the executable plan (writing-plans format + `**Interfaces:**` contract blocks), engine-neutral — task-swarm (pipeline.yml now derived from it) / superpowers / specode self-execute all consume the same file; pipeline becomes requirements → design → tasks → 执行方式 selector → execute → acceptance, with brainstorming spanning requirements+design in one dual-artifact call; `/specode:continue` becomes **load-and-stop** — reads docs, reports a progress brief, then waits for the user's instruction (never auto-resumes); `design-unchecked` renamed `plan-unchecked` (tasks.md first, 5.x legacy design.md fallback, old name kept as alias); 5.x specs keep working via the legacy inference row. **v5.2.0**: Tier-0 RagKit gate tightened — probe changed from `test -d .ragkit` to `test -f .ragkit/chunks.json` (eliminates false-positive when only config.json exists after `backend set`); Tier-0 採纳条目 capped at Tier-2 discipline (≤5/phase, reasoned override allowed). **v5.1.3**: `list-specs` now surfaces intake-phase specs (dir created, requirements not yet written) — lists subdirs containing any fixed doc plus empty subdirs, hidden dirs still excluded; repo-wide stale-docs cleanup. **v5.1.2**: distill polish — `ensure-gitignore` skips in a non-git project with no existing `.gitignore` (no stray file); new `knowledge.py copy-to` verb (one-step dual-landing: copy cases/navigation + rebuild the dest's MEMORY) now used by distill Step 5; navigation `来源` keeps the origin slug (reusing specs listed in body). **v5.1.1**: validation-driven fixes — distill runs `design-unchecked` before sedimenting (warns if the spec isn't fully executed, so knowledge points don't reference unbuilt code); dedup navigation points against MEMORY before writing; retrieval emphasizes semantic relevance over tag-overlap. **v5.1.0**: reintroduces experience retrieval/injection on a new "pointers-not-facts" footing — new stdlib `knowledge.py` (ensure-gitignore/memory-rebuild/memory-validate); distill now emits **atomic case/navigation knowledge-points** to the project's `/knowledge-base/` (cases/ + navigation/ + a MEMORY index, gitignored), optionally copied to Obsidian; new `references/retrieval.md` two-tier gated retrieval wired into the requirements/design phases (inject pointers not facts, default reads only the small index, ≤5 docs on hit); acceptance re-hooks the distill prompt via the existing `auto_distill` default. **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`. | +| **specode** | 6.1.2 | 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 4 fixed docs per spec. **v6.1.2**: plugin language unified (specode only, zero behavior change) — agent-facing instruction/explanation prose (SKILL/references/commands/script docstrings) is now idiomatic English, while user-facing fixed output and selections stay Chinese (the 执行方式 selector, templates, injected `## 项目级约束` / `## 参考定位` sections, script stderr user messages, CHANGELOG, and the contract field identifiers). **v6.1.1**: contract-lockstep CI gate (`test_contract_lockstep.py`) keeps the MEMORY column + frontmatter contract byte-identical across knowledge.py / retrieval.md / doc-template.md (negative-controlled to catch reorder/drop); new `references/knowledge-flow.md` one-page knowledge-loop mental model. **v6.1.0**: new standalone `specode:intake` skill (peer to `distill`) owns the requirements phase — project analysis (agent-docs scan + experience retrieval + reading located real code) + analysis-driven clarification + writes `requirements.md` preserving the `spec_id`/`created_at`/`project_root` frontmatter contract; fixes the 6.0.0 brainstorming dual-artifact mismatch (brainstorming now produces `design.md` only); retrieval's primary node moves to intake with design as a conditional top-up; writing-plans' execution-mode question is now ignored (not "suppressed"); SKILL.md lightened 215→171 lines (verb table + autonomous-mode detail sunk to references) and dead v3/codemap-term noise dropped from distill. **v6.0.0 BREAKING**: fixed docs 3 → 4 — `design.md` redefined as a **traditional design doc** (背景与目标/架构概览/模块划分/接口设计/数据流/错误处理/测试策略, prose only, no checkboxes); new `tasks.md` carries the executable plan (writing-plans format + `**Interfaces:**` contract blocks), engine-neutral — task-swarm (pipeline.yml now derived from it) / superpowers / specode self-execute all consume the same file; pipeline becomes requirements → design → tasks → 执行方式 selector → execute → acceptance, with brainstorming spanning requirements+design in one dual-artifact call; `/specode:continue` becomes **load-and-stop** — reads docs, reports a progress brief, then waits for the user's instruction (never auto-resumes); `design-unchecked` renamed `plan-unchecked` (tasks.md first, 5.x legacy design.md fallback, old name kept as alias); 5.x specs keep working via the legacy inference row. **v5.2.0**: Tier-0 RagKit gate tightened — probe changed from `test -d .ragkit` to `test -f .ragkit/chunks.json` (eliminates false-positive when only config.json exists after `backend set`); Tier-0 採纳条目 capped at Tier-2 discipline (≤5/phase, reasoned override allowed). **v5.1.3**: `list-specs` now surfaces intake-phase specs (dir created, requirements not yet written) — lists subdirs containing any fixed doc plus empty subdirs, hidden dirs still excluded; repo-wide stale-docs cleanup. **v5.1.2**: distill polish — `ensure-gitignore` skips in a non-git project with no existing `.gitignore` (no stray file); new `knowledge.py copy-to` verb (one-step dual-landing: copy cases/navigation + rebuild the dest's MEMORY) now used by distill Step 5; navigation `来源` keeps the origin slug (reusing specs listed in body). **v5.1.1**: validation-driven fixes — distill runs `design-unchecked` before sedimenting (warns if the spec isn't fully executed, so knowledge points don't reference unbuilt code); dedup navigation points against MEMORY before writing; retrieval emphasizes semantic relevance over tag-overlap. **v5.1.0**: reintroduces experience retrieval/injection on a new "pointers-not-facts" footing — new stdlib `knowledge.py` (ensure-gitignore/memory-rebuild/memory-validate); distill now emits **atomic case/navigation knowledge-points** to the project's `/knowledge-base/` (cases/ + navigation/ + a MEMORY index, gitignored), optionally copied to Obsidian; new `references/retrieval.md` two-tier gated retrieval wired into the requirements/design phases (inject pointers not facts, default reads only the small index, ≤5 docs on hit); acceptance re-hooks the distill prompt via the existing `auto_distill` default. **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.1 | Maintain an Obsidian LLM-Wiki with three skills: deterministic structure layer (`wiki-struct`: Home tree / READMEs / partition pages), content curation (`wiki-curate`: ingest / curate / lint), unified orchestrator (`wiki-orchestrate`). Generic code + per-vault config in the home-dir registry `~/.config/obsidian-wiki/` (falls back to `/.wiki/config.json`). **v2.0.0 BREAKING**: the spec-distill skill was extracted into specode's `/specode:distill`. See [`plugins/obsidian-wiki/`](./plugins/obsidian-wiki). | | **ragkit** | 0.1.0 | Standalone knowledge-base **RAG** — vector + lexical + metadata three-channel recall, RRF-fused, returns pointer cards. Optional downstream consumer of specode `distill` output; zero heavy deps (stdlib + numpy for lexical mode). See [`plugins/ragkit/`](./plugins/ragkit). | diff --git a/README.zh-CN.md b/README.zh-CN.md index 3b7abed..74d024e 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-6.1.1-blue.svg)](./plugins/specode/.claude-plugin/plugin.json) +[![specode](https://img.shields.io/badge/specode-6.1.2-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.1-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** | 6.1.1 | 轻量**规格驱动工作流**——编排外壳,每个阶段委托给 [superpowers](https://github.com/obra/superpowers) 技能(一等公民原生降级),每条规格固定产出 4 份文档。**v6.1.1**:契约锁步 CI 门禁(`test_contract_lockstep.py`)保证 MEMORY 列 + frontmatter 键在 knowledge.py / retrieval.md / doc-template.md 三处一致(负控可抓 reorder/drop);新增 `references/knowledge-flow.md` 一页纸知识流心智模型。**v6.1.0**:新增独立 `specode:intake` skill(与 `distill` 平级)接管 requirements phase——项目分析(agent-docs 扫描 + 经验检索 + 读定位到的真实代码)+ 基于分析的澄清 + 写 `requirements.md`(保留 `spec_id`/`created_at`/`project_root` frontmatter 契约);修正 6.0.0 brainstorming 双产物错位(brainstorming 从此只产 `design.md`);检索主节点移到 intake、design 降为条件性 top-up;writing-plans 执行方式提问改为「忽略而非抑制」;SKILL.md 轻量化 215→171 行(verb 表 + autonomous-mode 细节下沉到 references),并清理 distill 里的 v3/codemap 死术语噪声。**v6.0.0 BREAKING**:固定产物 3→4——`design.md` 重定义为**传统设计文档**(背景与目标/架构概览/模块划分/接口设计/数据流/错误处理/测试策略,散文无 checkbox);新增 `tasks.md` 承载可执行计划(writing-plans 格式 + `**Interfaces:**` 契约块),引擎中立——task-swarm(pipeline.yml 改从它推导)/ superpowers / specode 自执行统一消费同一份文件;流水线变为 requirements → design → tasks → 执行方式 selector → 执行 → 验收,brainstorming 一次跨 requirements+design 双产物落盘;`/specode:continue` 改**加载即停**——只读文档 + 汇报进度简报后停下等指令,绝不自动续跑;`design-unchecked` 更名 `plan-unchecked`(tasks.md 优先,5.x legacy design.md 兜底,旧名保留 alias);5.x 存量 spec 经 legacy 推断行兜底不中断。**v5.2.0**:Tier-0 RagKit gate 收紧——探针从 `test -d .ragkit` 改为 `test -f .ragkit/chunks.json`(消除 `backend set` 只写 config.json 时的假阳性);Tier-0 采纳条目封顶 Tier-2 同等纪律(≤5 点/phase,复杂需求可标注理由突破)。 **v5.1.3**:`list-specs` 让 intake 阶段(目录已建、requirements 未写)的 spec 可见——列出含任一固定产物的子目录 + 空子目录,隐藏目录仍排除;全库文档陈旧内容清理。 **v5.1.2**:distill 打磨——非 git 且无 .gitignore 时 `ensure-gitignore` 跳过(不建 stray);新增 `copy-to` 一步 dual-landing(复制 + 重建 dest MEMORY),distill Step5 改用;navigation `来源` 单值保留 origin。 **v5.1.1**:试跑验证修复——distill 沉淀前 `design-unchecked` 检查是否执行完(未完告警,防指向未落地代码);写 navigation 前比对 MEMORY 去重;retrieval 强调语义相关而非 tag 命中。 **v5.1.0**:以全新「定位用·非事实用」路线重新引入经验检索注入——新增 stdlib `knowledge.py`(ensure-gitignore/memory-rebuild/memory-validate);distill 改产**原子 case/navigation 知识点**到项目 `/knowledge-base/`(cases/+navigation/+MEMORY 索引,不入仓),可选复制到 Obsidian;新增 `references/retrieval.md` 两级 gated 检索接入 requirements/design 阶段(注入指针非事实、默认只读小索引、命中才读≤5点);acceptance 末尾按 `auto_distill` 重新挂回 distill 提示。 **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`。 | +| **specode** | 6.1.2 | 轻量**规格驱动工作流**——编排外壳,每个阶段委托给 [superpowers](https://github.com/obra/superpowers) 技能(一等公民原生降级),每条规格固定产出 4 份文档。**v6.1.2**:插件语言统一(仅 specode,零行为变化)——面向 agent 的指令/说明 prose 转地道英文,用户可见的固定输出与选择保持中文(执行方式 selector、模板、注入段、脚本 stderr、CHANGELOG、契约字段标识符)。**v6.1.1**:契约锁步 CI 门禁(`test_contract_lockstep.py`)保证 MEMORY 列 + frontmatter 键在 knowledge.py / retrieval.md / doc-template.md 三处一致(负控可抓 reorder/drop);新增 `references/knowledge-flow.md` 一页纸知识流心智模型。**v6.1.0**:新增独立 `specode:intake` skill(与 `distill` 平级)接管 requirements phase——项目分析(agent-docs 扫描 + 经验检索 + 读定位到的真实代码)+ 基于分析的澄清 + 写 `requirements.md`(保留 `spec_id`/`created_at`/`project_root` frontmatter 契约);修正 6.0.0 brainstorming 双产物错位(brainstorming 从此只产 `design.md`);检索主节点移到 intake、design 降为条件性 top-up;writing-plans 执行方式提问改为「忽略而非抑制」;SKILL.md 轻量化 215→171 行(verb 表 + autonomous-mode 细节下沉到 references),并清理 distill 里的 v3/codemap 死术语噪声。**v6.0.0 BREAKING**:固定产物 3→4——`design.md` 重定义为**传统设计文档**(背景与目标/架构概览/模块划分/接口设计/数据流/错误处理/测试策略,散文无 checkbox);新增 `tasks.md` 承载可执行计划(writing-plans 格式 + `**Interfaces:**` 契约块),引擎中立——task-swarm(pipeline.yml 改从它推导)/ superpowers / specode 自执行统一消费同一份文件;流水线变为 requirements → design → tasks → 执行方式 selector → 执行 → 验收,brainstorming 一次跨 requirements+design 双产物落盘;`/specode:continue` 改**加载即停**——只读文档 + 汇报进度简报后停下等指令,绝不自动续跑;`design-unchecked` 更名 `plan-unchecked`(tasks.md 优先,5.x legacy design.md 兜底,旧名保留 alias);5.x 存量 spec 经 legacy 推断行兜底不中断。**v5.2.0**:Tier-0 RagKit gate 收紧——探针从 `test -d .ragkit` 改为 `test -f .ragkit/chunks.json`(消除 `backend set` 只写 config.json 时的假阳性);Tier-0 采纳条目封顶 Tier-2 同等纪律(≤5 点/phase,复杂需求可标注理由突破)。 **v5.1.3**:`list-specs` 让 intake 阶段(目录已建、requirements 未写)的 spec 可见——列出含任一固定产物的子目录 + 空子目录,隐藏目录仍排除;全库文档陈旧内容清理。 **v5.1.2**:distill 打磨——非 git 且无 .gitignore 时 `ensure-gitignore` 跳过(不建 stray);新增 `copy-to` 一步 dual-landing(复制 + 重建 dest MEMORY),distill Step5 改用;navigation `来源` 单值保留 origin。 **v5.1.1**:试跑验证修复——distill 沉淀前 `design-unchecked` 检查是否执行完(未完告警,防指向未落地代码);写 navigation 前比对 MEMORY 去重;retrieval 强调语义相关而非 tag 命中。 **v5.1.0**:以全新「定位用·非事实用」路线重新引入经验检索注入——新增 stdlib `knowledge.py`(ensure-gitignore/memory-rebuild/memory-validate);distill 改产**原子 case/navigation 知识点**到项目 `/knowledge-base/`(cases/+navigation/+MEMORY 索引,不入仓),可选复制到 Obsidian;新增 `references/retrieval.md` 两级 gated 检索接入 requirements/design 阶段(注入指针非事实、默认只读小索引、命中才读≤5点);acceptance 末尾按 `auto_distill` 重新挂回 distill 提示。 **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.1 | 维护 Obsidian LLM-Wiki 的三个 skill:确定性结构层(`wiki-struct`:Home 树 / README / 分区页)、内容策展(`wiki-curate`:ingest / curate / lint)、统一编排器(`wiki-orchestrate`)。通用代码 + 家目录注册表 `~/.config/obsidian-wiki/` 按库配置(回退库内 `.wiki/config.json`)。**v2.0.0 BREAKING**:spec-distill 已剥离并迁入 specode 的 `/specode:distill`。详见 [`plugins/obsidian-wiki/`](./plugins/obsidian-wiki)。 | | **ragkit** | 0.1.0 | 独立知识库 **RAG**——向量 + 词汇 + 元数据三路召回,RRF 融合,返回定位卡片。specode `distill` 产出的 `knowledge-base/` 可直接消费;零重型依赖(词汇路仅需 stdlib + numpy)。详见 [`plugins/ragkit/`](./plugins/ragkit)。 | diff --git a/plugins/specode/.claude-plugin/plugin.json b/plugins/specode/.claude-plugin/plugin.json index 1273490..e2ef0a6 100644 --- a/plugins/specode/.claude-plugin/plugin.json +++ b/plugins/specode/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "specode", - "version": "6.1.1", - "description": "Lightweight spec-driven workflow: orchestrates superpowers skills per phase, lands 4 fixed docs (requirements/design/tasks/implementation-log). **v6.1.1**: 新增契约锁步 CI 门禁 tests/test_contract_lockstep.py(MEMORY 列 + frontmatter 键在 knowledge.py/retrieval.md/doc-template.md 三处一致,负控验证可抓 reorder/drop);新增 references/knowledge-flow.md 一页纸知识流心智模型(distill/knowledge-base/MEMORY/ragkit/intake-检索 的谁产·谁读·何时)。 **v6.1.0**: 新增独立 intake skill(skills/intake/,同 distill,user-invocable:false)接管 requirements phase — 项目分析(agent-docs 扫描+经验检索+读真实代码)+基于分析的澄清+写 requirements.md(保留 spec_id/created_at/project_root frontmatter 契约);修正 6.0.0 的brainstorming 双产物错位 — brainstorming 从此只产 design.md(单产物),requirements 由 intake 产;检索主节点移到 intake 项目分析步、design 降为条件性 top-up;弊端修复 — writing-plans 结尾的执行方式提问改为「忽略而非抑制」;SKILL 轻量化 215→171 行(verb 表/autonomous-mode 细节下沉到 refs,零行为变化)。 **v6.0.0 BREAKING**: 固定产物 3→4 — design.md 重定义为**传统设计文档**(背景与目标/架构概览/模块划分/接口设计/数据流/错误处理/测试策略,散文无 checkbox);新增 tasks.md 承载可执行计划(writing-plans 格式 + Interfaces 契约块,引擎中立,task-swarm/superpowers/自执行统一消费,pipeline.yml 改从 tasks.md 推导);流水线变为 requirements→design→tasks→执行方式 selector→执行→验收,brainstorming 一次跨 requirements+design 双产物落盘(后置 relocate 检查两份);continue 改「加载即停」— 只读文档+汇报进度简报后停下等指令,绝不自动续跑;design-unchecked 更名 plan-unchecked(tasks.md 优先,design.md 含 checkbox 按 5.x legacy 兜底,旧名保留 alias)。5.x 存量 spec 由 continue 推断表 legacy 行兜底识别,不中断。 **v5.2.0**: Tier-0 RagKit gate tightened — probe changed from `test -d .ragkit` to `test -f .ragkit/chunks.json` (eliminates false-positive when only config.json exists after `backend set`); Tier-0 采纳条目 capped at Tier-2 discipline (≤5/phase, reasoned override allowed). **v5.1.3**: `list-specs` 让 intake 阶段(目录已建、requirements 未写)的 spec 可见 — 列出含任一固定产物的子目录 + 空子目录(intake),隐藏目录与无关内容目录仍排除;全库文档陈旧内容清理(README/CONTRIBUTING/SKILL 残留措辞)。 **v5.1.2**: distill 打磨 — ensure-gitignore 在非 git 且无既有 .gitignore 时跳过(不建 stray);新增 knowledge.py copy-to(一步 dual-landing:复制 cases/navigation + 重建 dest MEMORY),distill Step5 改用它;navigation 来源 单值保留 origin、复用 spec 写正文。 **v5.1.1**: 试跑验证修复 — distill 沉淀前用 design-unchecked 检查 spec 是否执行完(未完则告警,防知识点指向未落地代码);写 navigation 点前先比对 MEMORY 去重;retrieval 强调语义相关而非 tag 命中;F2(非 git project_root)评估为 by design 不修。 **v5.1.0**: 重新引入「经验检索注入」走全新「定位用·非事实用」路线 — 新增 stdlib knowledge.py(ensure-gitignore/memory-rebuild/memory-validate);distill 改产**原子 case/navigation 知识点**到项目 /knowledge-base/(cases/+navigation/+MEMORY 索引,不入仓),可选复制到 Obsidian;新增 references/retrieval.md 两级 gated 检索接入 requirements/design phase(注入指针非事实、默认只读小索引、命中才读≤5点);acceptance 末尾按 auto_distill 重挂 distill 提示。 **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`。", + "version": "6.1.2", + "description": "Lightweight spec-driven workflow: orchestrates superpowers skills per phase, lands 4 fixed docs (requirements/design/tasks/implementation-log). **v6.1.2**: 插件语言统一(仅 specode,零行为变化)——面向 agent 的指令/说明 prose 全部转地道英文(SKILL/references/commands/脚本 docstring+注释);用户可见的固定输出与选择保持中文(执行方式 selector、模板、注入段 ## 项目级约束 / ## 参考定位、脚本 stderr 用户消息、CHANGELOG)。 **v6.1.1**: 新增契约锁步 CI 门禁 tests/test_contract_lockstep.py(MEMORY 列 + frontmatter 键在 knowledge.py/retrieval.md/doc-template.md 三处一致,负控验证可抓 reorder/drop);新增 references/knowledge-flow.md 一页纸知识流心智模型(distill/knowledge-base/MEMORY/ragkit/intake-检索 的谁产·谁读·何时)。 **v6.1.0**: 新增独立 intake skill(skills/intake/,同 distill,user-invocable:false)接管 requirements phase — 项目分析(agent-docs 扫描+经验检索+读真实代码)+基于分析的澄清+写 requirements.md(保留 spec_id/created_at/project_root frontmatter 契约);修正 6.0.0 的brainstorming 双产物错位 — brainstorming 从此只产 design.md(单产物),requirements 由 intake 产;检索主节点移到 intake 项目分析步、design 降为条件性 top-up;弊端修复 — writing-plans 结尾的执行方式提问改为「忽略而非抑制」;SKILL 轻量化 215→171 行(verb 表/autonomous-mode 细节下沉到 refs,零行为变化)。 **v6.0.0 BREAKING**: 固定产物 3→4 — design.md 重定义为**传统设计文档**(背景与目标/架构概览/模块划分/接口设计/数据流/错误处理/测试策略,散文无 checkbox);新增 tasks.md 承载可执行计划(writing-plans 格式 + Interfaces 契约块,引擎中立,task-swarm/superpowers/自执行统一消费,pipeline.yml 改从 tasks.md 推导);流水线变为 requirements→design→tasks→执行方式 selector→执行→验收,brainstorming 一次跨 requirements+design 双产物落盘(后置 relocate 检查两份);continue 改「加载即停」— 只读文档+汇报进度简报后停下等指令,绝不自动续跑;design-unchecked 更名 plan-unchecked(tasks.md 优先,design.md 含 checkbox 按 5.x legacy 兜底,旧名保留 alias)。5.x 存量 spec 由 continue 推断表 legacy 行兜底识别,不中断。 **v5.2.0**: Tier-0 RagKit gate tightened — probe changed from `test -d .ragkit` to `test -f .ragkit/chunks.json` (eliminates false-positive when only config.json exists after `backend set`); Tier-0 采纳条目 capped at Tier-2 discipline (≤5/phase, reasoned override allowed). **v5.1.3**: `list-specs` 让 intake 阶段(目录已建、requirements 未写)的 spec 可见 — 列出含任一固定产物的子目录 + 空子目录(intake),隐藏目录与无关内容目录仍排除;全库文档陈旧内容清理(README/CONTRIBUTING/SKILL 残留措辞)。 **v5.1.2**: distill 打磨 — ensure-gitignore 在非 git 且无既有 .gitignore 时跳过(不建 stray);新增 knowledge.py copy-to(一步 dual-landing:复制 cases/navigation + 重建 dest MEMORY),distill Step5 改用它;navigation 来源 单值保留 origin、复用 spec 写正文。 **v5.1.1**: 试跑验证修复 — distill 沉淀前用 design-unchecked 检查 spec 是否执行完(未完则告警,防知识点指向未落地代码);写 navigation 点前先比对 MEMORY 去重;retrieval 强调语义相关而非 tag 命中;F2(非 git project_root)评估为 by design 不修。 **v5.1.0**: 重新引入「经验检索注入」走全新「定位用·非事实用」路线 — 新增 stdlib knowledge.py(ensure-gitignore/memory-rebuild/memory-validate);distill 改产**原子 case/navigation 知识点**到项目 /knowledge-base/(cases/+navigation/+MEMORY 索引,不入仓),可选复制到 Obsidian;新增 references/retrieval.md 两级 gated 检索接入 requirements/design phase(注入指针非事实、默认只读小索引、命中才读≤5点);acceptance 末尾按 auto_distill 重挂 distill 提示。 **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 600f1ac..9eab4a1 100644 --- a/plugins/specode/CHANGELOG.md +++ b/plugins/specode/CHANGELOG.md @@ -4,7 +4,11 @@ specode 是 spec-driven 轻量工作流插件:requirements → design → task ## Unreleased -## 6.1.1 (2026-07-05) +## 6.1.2 (2026-07-05) + +- **插件语言统一(仅 specode,零行为变化)**:把面向 agent 的**指令 / 说明性 prose 全部转成地道英文**(按中文语义转写,非直译)——`skills/*/SKILL.md`(specode / intake / distill)、`skills/specode/references/*.md`(retrieval / obsidian / superpowers-wiring / knowledge-flow)、`commands/*.md`、以及三个脚本的 docstring + 行内注释。 +- **用户可见的固定输出与选择保持中文**(明确不动):执行方式 selector 的选项文案(`references/selectors.md` 未动)、`assets/templates/*.md`(生成的 spec 文档模板)、注入用户文档的段(`## 项目级约束` / `## 参考定位(非事实来源)`)、脚本 stderr/stdout 用户消息、SessionStart DISCIPLINE 提示、MEMORY.md 输出说明、以及 `_COLS` / frontmatter 键标识符(`标题/类型/描述/来源/路径/tags`)。 +- **CHANGELOG 永远保持中文**(本次及以后)。测试零回归(90 passed),契约锁步门禁验证 MEMORY 列未受影响。 - **契约锁步 CI 门禁**(`tests/test_contract_lockstep.py`):把 CLAUDE.md 的「变更纪律」变成可执行测试——读 `knowledge.py` **真实**产出的 MEMORY 表头(跑 memory-rebuild,非源码内省),断言它与 `references/retrieval.md`、`skills/distill/references/doc-template.md` 文档化的列一致,并断言 doc-template 的 frontmatter 键 == knowledge.py 读的键。提取器经**负控验证**能抓 reorder/drop,门禁可真失败而非白过。三处任一漂移 → 测试红。(+5 测,共 90。) - **一页纸知识流心智模型**(`references/knowledge-flow.md`):ASCII 产出→索引→消费全图(distill 写 / `knowledge.py` 索引 / intake+design 读、tasks+执行零注入)+ 「定位用非事实用」不变量 + 各部件权威文档指针。挂进 SKILL/intake References + 两 README 架构树(顺带把 `autonomous-mode.md` 补进树)。