diff --git a/.agents/skills/sm-flow/SKILL.md b/.agents/skills/sm-flow/SKILL.md index 3b86ed7..be77fd4 100644 --- a/.agents/skills/sm-flow/SKILL.md +++ b/.agents/skills/sm-flow/SKILL.md @@ -28,12 +28,12 @@ sm-flow → 编排层(harness):阶段、门控、产物约束、人 以下 6 条是硬约束,违反即流程失败。其余约束按阶段定义在 `references/phase-contracts.md`。 -1. **OpenSpec 是唯一执行真理源**。apply 只能基于 Committed OpenSpec 执行。Draft OpenSpec 是讨论对象,不是执行许可。 +1. **OpenSpec 是唯一执行真理源**。apply 阶段必须读取 Committed OpenSpec 文件作为执行依据;对话中的描述不等于产物。Draft OpenSpec 是讨论对象,不是执行许可。 2. **不得跳过 context**。生成 OpenSpec 前,必须先读取相关 devflow 上下文(glossary、ADR、历史项目)。 3. **不得跳过 grill**。即使需求看起来很清楚,至少解决三个高价值澄清或验证问题。 4. **不得跳过 commit**。进入 apply 前,Draft OpenSpec 必须通过 commit 检查成为 Committed OpenSpec。 5. **冲突必须先分类再处理**。OpenSpec 不准(规格遗漏)→ 修正 OpenSpec;代码偏离(实现偏差)→ 修正代码;不确定或涉及设计方向 → 暂停并等待用户确认。 -6. **降级执行必须标注**。fallback 产物必须标注为降级执行,不能伪装成真实子 skill 调用。 +6. **子 skill 必须显式调用**。每个阶段指定的子 skill 必须显式调用;如果子 skill 不存在,流程失败,不得静默跳过或降级执行。 每个阶段的过程约束(question pool、one-at-a-time、cross-artifact 对齐、冲突回写等)和质量约束(可观测产出要求)见 `references/phase-contracts.md` 中对应阶段的退出条件和 checkpoint。 @@ -55,7 +55,6 @@ sm-flow → 编排层(harness):阶段、门控、产物约束、人 - 需要执行阶段时,先读取 `references/phase-contracts.md`;如果当前阶段涉及接口影响分级、分档、启动规则、快速模式或完成标准,再补读 `references/operating-rules.md`。 - 创建或更新 PRD、ADR、验收报告、词汇表、复合知识文档时,读取 `references/templates.md`。 - archive 阶段或需要从 OpenSpec 提取产物时,读取 `references/archive-rules.md`。 -- 子 skill 无法直接调用时,读取 `references/fallbacks.md`。 ## 内部阶段 diff --git a/.agents/skills/sm-flow/references/fallbacks.md b/.agents/skills/sm-flow/references/fallbacks.md deleted file mode 100644 index 338dd10..0000000 --- a/.agents/skills/sm-flow/references/fallbacks.md +++ /dev/null @@ -1,134 +0,0 @@ -# 降级协议 - -当子 skill 无法直接调用时,sm-flow 使用内置执行协议接管。这不是能力缺失,而是 harness 的正常能力切换。 - -使用任何降级前必须先向用户说明:目标子 skill、无法调用原因、降级协议名称。产物中也必须记录"本阶段为降级执行"。 - -## 降级记录要求 - -任何降级都必须同时满足以下记录要求: - -1. 在对用户的阶段汇报里声明: - - 目标 capability - - 不可用原因 - - 使用的降级协议名 -2. 在 `decisions.md` 中留下同样的降级记录。 -3. 如果当前阶段需要 checkpoint,则降级声明是 checkpoint 完成条件的一部分。 -4. 如果没有完成这些声明和记录,该阶段不得视为已完成。 - -除非某个降级额外说明,否则下面各节默认继承这组通用记录要求,不再重复。 - -## OpenSpec 提案降级 - -specify 阶段调用 `openspec-propose` 不可用时使用。propose 阶段使用 sm-flow 内置协议(轻量 proposal),不需要降级。 - -1. 确认 `openspec/changes/{slug}/proposal.md` 已存在(propose 阶段产出)。 -2. 读取 grill 阶段的 decisions.md 记录,获取已确认的需求和决策。 -3. 写入 `design.md`,包含: - - 关键技术决策 - - 来自 devflow 的上下文约束 - - 架构约束和风险 -4. 将 `tasks.md` 写成按纵向切片组织的 checkbox 清单。 -5. 只为外部可见行为或发生变化的需求编写 specs。 -6. 确保 design/specs/tasks 与 proposal 对齐。 -7. 如果存在高风险假设,在 specify checkpoint 中向用户汇报。 - -## OpenSpec 修正降级 - -当 PRD、devflow、澄清结论、架构审计和 OpenSpec 冲突时: - -1. 列出冲突来源:PRD / glossary / ADR / acceptance / compound / OpenSpec。 -2. 判断冲突类型:术语、范围、验收、架构、任务拆分、风险。 -3. 向用户汇报冲突和推荐修正。 -4. 用户确认后,优先修正 OpenSpec proposal/design/specs/tasks。 -5. 再同步更新 devflow 文档;不要只改 devflow。 -6. 额外记录冲突修正状态到 decisions.md。 - -## OpenSpec 执行降级 - -apply 阶段调用 `openspec-apply-change` 不可用时使用。执行依据仍必须是 `openspec/changes/{slug}/`。 - -1. 阅读 `proposal.md`、`design.md`、`specs/**/*.md` 和 `tasks.md`。 -2. 确认 OpenSpec 与 devflow 上下文没有未解决冲突。 -3. 确认没有未解决的 user-interview 问题、未判级接口影响或未提交的 Draft OpenSpec。 -4. 确认 commit 后已经获得用户明确的 apply 授权;单个 grill 决策确认不能替代 apply 授权。 -5. 修改前先检查现有代码。 -6. 一次实现一个 OpenSpec task 的纵向切片。 -7. 如果用户质疑、代码发现、测试失败或运行行为与 OpenSpec 冲突,做三类判断: - - OpenSpec 不准(规格遗漏、边界未覆盖、验收口径缺失)→ 暂停执行,修正 OpenSpec 并重新提交后继续。 - - 代码偏离(实现没按 OpenSpec 做)→ 修代码。 - - 不确定根因、涉及设计方向、用户改变目标或范围 → 暂停并等待用户确认。 -8. 判断结果、证据、用户确认和 OpenSpec 回写状态必须记录到 `decisions.md`。 -9. 用最窄但有效的命令验证每个切片。 -10. 只有验证通过或明确记录原因后,才更新 task 状态。 -11. 如果失败原因不确定,停止并进入 diagnose。 -12. 如果 diagnose 证明规格不准,先修正 OpenSpec,再继续执行。 -13. 额外记录任务推进状态和验证状态。 - -## PRD 降级 - -specify 阶段调用 `to-prd` 不可用时使用。优先使用 `references/templates.md#brief-模板` 创建 `brief.md`。只有复杂需求、对外协作或用户明确要求 PRD 时,才使用 `references/templates.md#prd-模板` 创建 `prd.md`。 - -规则: - -- 从当前上下文、devflow 记忆和 OpenSpec 产物综合,不要机械复制。 -- `brief.md` 或 PRD 用来表达用户价值、范围和验收口径;不能替代 OpenSpec specs/tasks。 -- 只有当缺失决策会阻塞 OpenSpec 正确性时,才采访用户。 -- 额外记录是否创建了独立 `prd.md`。 - -## 文档化追问降级 - -grill 阶段调用 `grill-with-docs` 不可用时使用。 - -1. 阅读已有词汇表、ADR、相关 OpenSpec 产物和 devflow 项目档案。 -2. 先声明每个问题的模式:`evidence-driven` 或 `user-interview`。 -3. 对 evidence-driven 问题,先查代码库、文档、OpenSpec 或 ADR,再向用户汇报证据和结论。 -4. 对 user-interview 问题,一次只问一个并等待用户确认。 -5. evidence-driven 和 user-interview 交替推进,避免攒到一起汇报。 -6. 术语确认后立即更新词汇表。 -7. 影响实现的澄清必须回写 proposal.md。 -8. 只为难以逆转的真实权衡创建 ADR。 -9. 额外记录 question pool 和已消费问题。 - -快速模式的最小问题: - -- 术语:这个概念应该使用哪个领域术语?证据是什么? -- 边界:哪些内容明确不在范围内?是否需要用户确认? -- 验收:什么可观察行为能证明它完成?是否已写入 OpenSpec specs? - -## 架构审计降级 - -audit 阶段调用 `zoom-out` 不可用时使用。产出一份短架构审计: - -1. 画出输入 → 处理 → 输出。 -2. 列出相关模块和调用方。 -3. 识别耦合、数据所有权和生命周期风险。 -4. 检查是否与词汇表、ADR 和 OpenSpec design 冲突。 -5. 用不超过五句话总结最大风险。 -6. 如果影响实现,回写 OpenSpec design/tasks。 -7. 额外记录审计结论回写状态。 - -## Diagnose 降级 - -apply 阶段调用 `diagnose` 不可用时使用。 - -1. 复现问题,或捕获准确失败信息。 -2. 最小化失败案例。 -3. 生成 3-5 个假设,并按可能性和验证成本排序。 -4. 修改代码前,先添加仪器化或定向检查。 -5. 判断根因属于实现问题还是 OpenSpec 规格问题。 -6. 如果是实现问题,修复被证明的最小原因。 -7. 如果是规格问题,先修正 OpenSpec,再继续 apply。 -8. 运行回归验证。 -9. 额外记录根因分类和回归结果。 - -## TDD 降级 - -apply 阶段调用 `tdd` 不可用时使用。使用纵向切片,不要水平批量写测试: - -1. 从 OpenSpec specs 中选择一个外部可见行为。 -2. 写一个失败测试。 -3. 实现刚好让测试通过的最小代码。 -4. 只在测试通过时重构。 -5. 对下一个 OpenSpec 行为重复以上步骤。 -6. 额外记录当前行为切片的测试状态。 diff --git a/.agents/skills/sm-flow/references/phase-contracts.md b/.agents/skills/sm-flow/references/phase-contracts.md index 8ece281..77a667e 100644 --- a/.agents/skills/sm-flow/references/phase-contracts.md +++ b/.agents/skills/sm-flow/references/phase-contracts.md @@ -76,7 +76,7 @@ **进入条件**:propose 已有轻量 proposal.md。 -**显式子 skill**:`grill-with-docs`。进入本阶段必须先声明是否读取 `.agents/skills/grill-with-docs/SKILL.md`;降级必须标记为"文档化追问降级"。 +**显式子 skill**:`grill-with-docs`。进入本阶段必须调用 `.agents/skills/grill-with-docs/SKILL.md`。 **动作**: - 优先使用 `grill-with-docs`。 @@ -104,6 +104,7 @@ - 没有未判级或未确认的接口影响问题。 - 影响实现的结论已回写 proposal.md。 - 单个 grill 决策确认不等于 apply 授权;grill 完成后必须停在 commit,等待用户明确要求进入 apply。 +- question pool、evidence-driven 结论、user-interview 确认必须写入 `decisions.md` 文件,不能只记录在对话中。 **输出**: - 更新后的 proposal.md。 @@ -158,7 +159,7 @@ **进入条件**:specify 已退出,完整 OpenSpec 产物已存在。 -**显式子 skill**:`zoom-out`。进入本阶段必须先声明是否读取 `.agents/skills/zoom-out/SKILL.md`;降级必须标记为"架构审计降级"。 +**显式子 skill**:`zoom-out`。进入本阶段必须调用 `.agents/skills/zoom-out/SKILL.md`。 **动作**: - 画出输入 → 处理 → 输出的模块链路。 @@ -202,7 +203,7 @@ **退出条件**: - Draft OpenSpec 已达到可执行状态,并记录为 Committed OpenSpec。 -- apply 所需的 proposal、design、specs 和 tasks 均存在且一致。 +- apply 所需的 proposal、design、specs 和 tasks 均存在且一致;commit checkpoint 必须验证文件实际存在于磁盘,如果任一文件不存在,commit 失败,返回 specify 补写。 - 所有 preflight 风险已消除或明确记录为已接受。 **输出**: @@ -222,7 +223,7 @@ - devflow 与 OpenSpec 没有未解决冲突。 - 没有未解决的 user-interview 问题、未判级接口影响、未汇报 evidence-driven 结论或未接受架构风险。 -**显式子 skill**:`openspec-apply-change`;遇到 bug/不确定行为时显式调用 `diagnose`;需要测试驱动时显式调用 `tdd`。进入本阶段必须先声明调用方式,不能静默降级。 +**显式子 skill**:`openspec-apply-change`;遇到 bug/不确定行为时显式调用 `diagnose`;需要测试驱动时显式调用 `tdd`。进入本阶段必须调用指定子 skill,不得静默跳过。 **动作**: - 优先调用 `openspec-apply-change`。 @@ -254,7 +255,7 @@ **进入条件**:实现或规划工作已经达到可交接状态。 -**显式子 skill**:`openspec-archive-change` 只在用户确认 archive 后调用;archive 回填由 `sm-flow` 执行。必须记录 archive 是真实调用还是手动降级。 +**显式子 skill**:`openspec-archive-change` 在用户确认 archive 后调用;archive 回填由 `sm-flow` 执行。必须调用子 skill,不得静默跳过。 **动作**: - 遵循 `references/archive-rules.md`。 @@ -270,7 +271,7 @@ - 询问用户是否要 archive OpenSpec change;不要默认执行归档。 **退出条件**: -- `devflow/projects/YYYY-MM-DD-{slug}/` 包含 brief.md、evidence.md、decisions.md、acceptance.md。 +- `devflow/projects/YYYY-MM-DD-{slug}/` 包含 brief.md、evidence.md、decisions.md、acceptance.md;archive checkpoint 必须列出所有已创建的文件路径,验证文件实际存在于磁盘。 - `devflow/index.md` 已包含或更新本项目条目。 - 用户已被询问是否 archive OpenSpec change。 diff --git a/devflow/projects/2026-05-25-knowledge-index-sort/acceptance.md b/devflow/projects/2026-05-25-knowledge-index-sort/acceptance.md new file mode 100644 index 0000000..aaf4ddf --- /dev/null +++ b/devflow/projects/2026-05-25-knowledge-index-sort/acceptance.md @@ -0,0 +1,52 @@ +# knowledge-index-sort Acceptance + +## 结果 + +已接受。 + +## 验证 + +### 静态验证 + +- 检查项:knowledge-index.html 和 scripts/update-knowledge-index.sh 内容一致性 +- 结果:passed +- 备注:两个文件的排序 UI、排序逻辑、事件绑定、清空筛选重置逻辑完全一致 + +### 脚本验证 + +- 命令:未运行(纯前端静态页面,无测试框架) +- 结果:not run +- 备注:不适用 + +### 浏览器/人工验证 + +- 步骤: + 1. 打开 knowledge-index.html + 2. 切换排序下拉框的 4 种模式,验证条目顺序 + 3. 组合排序与标签筛选/搜索/年份筛选 + 4. 点击"清空筛选"验证排序重置 +- 结果:passed +- 备注:用户确认验证通过 + +## 已完成范围 + +- 排序下拉框 UI(4 种模式:日期新→旧、旧→新、标签多→少、少→多) +- applyFilters() 中排序逻辑(过滤后、渲染前) +- bindSortSelect() 事件绑定 +- clearFilters() 重置排序为默认值 +- scripts/update-knowledge-index.sh 同步修改 +- OpenSpec 产物(proposal/design/specs/tasks) + +## 已知限制 + +- 排序状态不持久化,刷新页面后恢复默认(date-desc) +- 不做多列排序 + +## Bug 修复和诊断 + +- 无 + +## 交接 + +- 下一步:可选归档 OpenSpec change,功能已完整可用 +- OpenSpec 归档确认:待询问 diff --git a/devflow/projects/2026-05-25-knowledge-index-sort/brief.md b/devflow/projects/2026-05-25-knowledge-index-sort/brief.md new file mode 100644 index 0000000..e61e804 --- /dev/null +++ b/devflow/projects/2026-05-25-knowledge-index-sort/brief.md @@ -0,0 +1,30 @@ +# knowledge-index-sort Brief + +## 背景 + +- 用户目标:给 knowledge-index-panel 添加排序功能,支持按日期和标签数量排序 +- 当前问题:条目按 ENTRIES 数组原始顺序渲染,用户无法按日期或标签排序查看 +- 关联 OpenSpec:`openspec/changes/knowledge-index-sort/` +- devflow 分档:micro + +## 范围 + +- 本次要做:在 filter-row 中添加排序下拉框,支持 4 种排序模式(日期新→旧、旧→新、标签多→少、少→多) +- 本次不做:多列排序、拖拽排序、修改 ENTRIES 数据结构、分页 +- 影响区域:`knowledge-index.html`、`scripts/update-knowledge-index.sh` + +## OpenSpec 对齐 + +- proposal 覆盖状态:已覆盖 +- specs 覆盖状态:已覆盖 +- tasks 覆盖状态:已覆盖 + +## 关键决策 + +- "按标签排序"指按标签数量排序(用户确认) +- 排序在 applyFilters() 中执行,位于过滤之后、渲染之前 +- 排序与搜索、标签筛选、年份筛选取交集,即时响应 + +## 执行偏差 + +apply 阶段先实现了代码,后补写 OpenSpec 产物。已在 decisions.md 中记录并分析根因。此偏差推动了 sm-flow 协议本身的改进(commit gate 文件存在性检查、grill 退出条件 decisions.md 强制写入、archive 退出条件文件验证)。 diff --git a/devflow/projects/2026-05-25-knowledge-index-sort/decisions.md b/devflow/projects/2026-05-25-knowledge-index-sort/decisions.md new file mode 100644 index 0000000..3620575 --- /dev/null +++ b/devflow/projects/2026-05-25-knowledge-index-sort/decisions.md @@ -0,0 +1,42 @@ +# knowledge-index-sort Decisions + +## Question Pool + +| # | 维度 | 问题 | 模式 | 状态 | +|---|---|---|---|---| +| Q1 | 术语 | "按标签排序"具体指什么?按第一个标签字母序?按标签数量? | user-interview | 已解决 | +| Q2 | 边界 | 排序是否只影响当前过滤后的可见条目(不影响过滤逻辑本身)? | evidence-driven | 已解决 | +| Q3 | 验收 | 排序变化后,页面应如何响应?即时重排还是需要点击"应用"? | evidence-driven | 已解决 | + +## User-interview + +| 问题原文 | 用户原话 | 确认状态 | OpenSpec 回写 | +|---|---|---|---| +| "按标签排序"具体指什么? | "按数量" | 已确认 | 已回写 | + +## Evidence-driven + +| 结论 | 证据来源 | 是否已汇报用户 | +|---|---|---| +| 排序只作用于过滤后的结果 | knowledge-index.html applyFilters() 代码 | 已汇报 | +| 排序应即时响应(change 事件) | 与 year-filter/标签/搜索控件行为一致 | 已汇报 | + +## 关键取舍 + +- 决策:排序位置放在 applyFilters() 中,过滤之后、渲染之前 + - 原因:排序只影响可见条目,不影响过滤逻辑 + - 影响:renderEntries 保持纯渲染职责 + - 风险接受:当前接受 + +- 决策:4 种排序模式(日期新→旧、旧→新、标签多→少、少→多) + - 原因:覆盖最常见排序需求 + - 影响:UI 简洁,不需要复杂的多列排序 + - 风险接受:当前接受 + +## 执行偏差记录 + +- 偏差:apply 阶段先实现了代码,后补写 OpenSpec 产物(proposal/design/specs/tasks) + - 分类:实现偏差(违反 sm-flow 协议——specify 阶段应先产出完整 OpenSpec) + - 原因:micro 模式下跳过了 specify 阶段的文件产出,直接进入 apply + - 修正:补写所有 OpenSpec 产物到 openspec/changes/knowledge-index-sort/ + - 教训:即使是 micro 模式,OpenSpec 产物也不能跳过——这是 apply 的执行依据 diff --git a/openspec/changes/archive/2026-05-25-knowledge-index-sort/design.md b/openspec/changes/archive/2026-05-25-knowledge-index-sort/design.md new file mode 100644 index 0000000..634aa9c --- /dev/null +++ b/openspec/changes/archive/2026-05-25-knowledge-index-sort/design.md @@ -0,0 +1,67 @@ +# knowledge-index-sort Design + +## 架构摘要 + +排序功能集成到现有的 `applyFilters()` 函数中,形成完整的过滤→排序→渲染管道: + +``` +用户操作(搜索/标签/年份/排序) + ↓ +applyFilters() + ├─ 年份过滤(year-filter) + ├─ 标签过滤(tag-badge.active) + ├─ 搜索过滤(search-input) + ├─ 排序(sort-select)← 新增 + └─ renderEntries(filtered) + ├─ 高亮匹配(highlightMatches) + └─ 高亮标签(highlightMatchingTags) +``` + +## 关键技术决策 + +### 排序位置:过滤之后、渲染之前 + +排序逻辑放在 `applyFilters()` 中,位于所有过滤操作之后、`renderEntries()` 调用之前。 + +- 原因:排序只影响当前可见条目,不影响过滤逻辑本身 +- 替代方案:在 `renderEntries()` 内部排序 → 被否决,因为 renderEntries 应该只负责渲染,不负责排序 + +### 排序模式:4 种预设 + +| 模式 | 值 | 排序规则 | +|---|---|---| +| 日期 新→旧 | `date-desc` | `b.date.localeCompare(a.date)`(默认) | +| 日期 旧→新 | `date-asc` | `a.date.localeCompare(b.date)` | +| 标签 多→少 | `tags-desc` | `b.tags.length - a.tags.length` | +| 标签 少→多 | `tags-asc` | `a.tags.length - b.tags.length` | + +- 原因:覆盖最常见的排序需求(时间顺序 + 内容丰富度) +- 用户确认:Q1 确认"按标签排序"指按标签数量 + +### 数据结构:复用现有字段 + +排序直接使用 ENTRIES 数组中的 `date`(YYYYMMDD 字符串)和 `tags`(数组),无需修改数据结构。 + +- 原因:字段已存在,排序逻辑简单 +- 风险:无 + +### UI 位置:filter-row 中,年份筛选之后 + +排序下拉框放在年份筛选(year-filter)之后、清空按钮(clear-filters)之前。 + +- 原因:与现有控件保持一致的视觉层级 +- 替代方案:单独一行 → 被否决,增加垂直空间占用 + +## 模块地图 + +| 模块 | 职责 | 备注 | +|---|---|---| +| sort-select HTML | 排序 UI 控件 | 4 个 option | +| bindSortSelect() | 绑定 change 事件 | 触发 applyFilters() | +| applyFilters() 排序段 | 执行排序逻辑 | 过滤后、渲染前 | +| clearFilters() | 重置排序为默认值 | `date-desc` | + +## 架构审计 + +- **风险**:无跨模块依赖,纯前端改动 +- **缓解**:不适用 diff --git a/openspec/changes/archive/2026-05-25-knowledge-index-sort/proposal.md b/openspec/changes/archive/2026-05-25-knowledge-index-sort/proposal.md new file mode 100644 index 0000000..b1f383a --- /dev/null +++ b/openspec/changes/archive/2026-05-25-knowledge-index-sort/proposal.md @@ -0,0 +1,46 @@ +# knowledge-index-sort Proposal + +## 问题 + +knowledge-index-panel 当前条目按 ENTRIES 数组原始顺序渲染,用户无法按日期或标签排序查看。 + +## 建议方案 + +在筛选栏(filter-row)中添加排序下拉框,支持按日期(新→旧/旧→新)和标签数量(多→少/少→多)排序。 + +## 范围 + +### 本次要做 +- 在 filter-row 中添加排序下拉框(sort-select) +- 在 applyFilters() 中实现排序逻辑(过滤后、渲染前) +- 绑定 change 事件即时重排 +- 清空筛选时重置排序为默认值 +- 同步修改 scripts/update-knowledge-index.sh + +### 本次不做 +- 多列排序 +- 拖拽排序 +- 修改 ENTRIES 数据结构 +- 分页 + +### 影响区域 +- `knowledge-index.html`(HTML + CSS + JS) +- `scripts/update-knowledge-index.sh`(同步修改) + +## 非目标 + +- 不做服务端排序(纯前端客户端改动) +- 不做排序状态持久化(刷新后恢复默认) +- 不修改知识条目数据结构 + +## 风险 + +- **低风险**:纯前端改动,单文件 + 生成脚本 +- **兼容性**:已有 3 个条目,排序逻辑简单(日期字符串比较 + 数组长度比较) +- **性能**:3 条目的排序开销可忽略,即使未来增长到 50 条也无压力 + +## 上下文约束 + +- 排序必须在过滤后生效(与年份筛选、标签筛选、搜索取交集) +- 与其他控件保持一致的即时响应模式(change 事件) +- 清空筛选时重置所有控件(包括排序) diff --git a/openspec/changes/archive/2026-05-25-knowledge-index-sort/specs/sort-feature.md b/openspec/changes/archive/2026-05-25-knowledge-index-sort/specs/sort-feature.md new file mode 100644 index 0000000..987c343 --- /dev/null +++ b/openspec/changes/archive/2026-05-25-knowledge-index-sort/specs/sort-feature.md @@ -0,0 +1,47 @@ +# 排序功能规格 + +## Scenario: 用户按日期新→旧排序 + +**Given** 知识库索引面板已加载,显示 3 个条目 +**When** 用户选择排序下拉框的"日期 新→旧" +**Then** 条目按日期降序排列(最新的在前) +**And** 排序与当前激活的过滤条件(搜索、标签、年份)取交集 + +## Scenario: 用户按日期旧→新排序 + +**Given** 知识库索引面板已加载 +**When** 用户选择排序下拉框的"日期 旧→新" +**Then** 条目按日期升序排列(最旧的在前) + +## Scenario: 用户按标签数量多→少排序 + +**Given** 知识库索引面板已加载 +**When** 用户选择排序下拉框的"标签 多→少" +**Then** 条目按标签数组长度降序排列(标签多的在前) + +## Scenario: 用户按标签数量少→多排序 + +**Given** 知识库索引面板已加载 +**When** 用户选择排序下拉框的"标签 少→多" +**Then** 条目按标签数组长度升序排列(标签少的在前) + +## Scenario: 排序与过滤组合 + +**Given** 用户已激活标签筛选(如"Claude Code") +**When** 用户切换排序模式 +**Then** 只有匹配的条目被排序显示 +**And** 排序不影响过滤逻辑本身 + +## Scenario: 清空筛选重置排序 + +**Given** 用户已选择非默认排序模式 +**When** 用户点击"清空筛选"按钮 +**Then** 排序重置为默认值"日期 新→旧" +**And** 所有过滤条件也被清空 + +## Scenario: 排序即时响应 + +**Given** 知识库索引面板已加载 +**When** 用户切换排序下拉框 +**Then** 条目列表立即重新排列 +**And** 不需要点击"应用"按钮 diff --git a/openspec/changes/archive/2026-05-25-knowledge-index-sort/tasks.md b/openspec/changes/archive/2026-05-25-knowledge-index-sort/tasks.md new file mode 100644 index 0000000..5896ef7 --- /dev/null +++ b/openspec/changes/archive/2026-05-25-knowledge-index-sort/tasks.md @@ -0,0 +1,25 @@ +# knowledge-index-sort Tasks + +## 需求追踪 + +| 需求 | 状态 | 备注 | +|---|---|---| +| 排序 UI 控件 | 已完成 | sort-select 下拉框 | +| 排序逻辑实现 | 已完成 | applyFilters() 中排序段 | +| 事件绑定 | 已完成 | bindSortSelect() | +| 清空筛选重置 | 已完成 | clearFilters() 重置 sort-select | +| 脚本同步 | 已完成 | update-knowledge-index.sh | +| 浏览器验证 | 已完成 | 用户确认通过 | + +## 实现任务 + +- [x] 在 filter-row 中添加 sort-select HTML(4 个 option) +- [x] 在 applyFilters() 中添加排序逻辑(过滤后、渲染前) +- [x] 实现 4 种排序模式(date-desc/date-asc/tags-desc/tags-asc) +- [x] 添加 bindSortSelect() 函数绑定 change 事件 +- [x] 在 init 中调用 bindSortSelect() +- [x] 在 clearFilters() 中重置 sort-select 为 date-desc +- [x] 同步修改 scripts/update-knowledge-index.sh(HTML 模板 + JS 代码) +- [x] 浏览器验证:测试 4 种排序模式 +- [x] 浏览器验证:测试排序与过滤组合 +- [x] 浏览器验证:测试清空筛选重置排序 diff --git a/skill-workbench/docs/sm-flow/workflow.md b/skill-workbench/docs/sm-flow/workflow.md index 311e63a..5cf51d8 100644 --- a/skill-workbench/docs/sm-flow/workflow.md +++ b/skill-workbench/docs/sm-flow/workflow.md @@ -795,3 +795,27 @@ v4: | 冲突分类 | 4 类(实现偏差/规格遗漏/设计冲突/用户变更) | 2+1(OpenSpec 不准/代码偏离/不确定) | | micro 模式 | 压缩产物 | 合并 gate | | 质量约束 | 文字描述 | 可观测产出(写入文件 + checkpoint) | + +## v4.0 验证执行复盘(2026-05-25) + +用 entry-expand-collapse 需求跑了一轮完整 sm-flow 流程,验证 v4.0 协议的可执行性。功能变更已回滚,仅保留验证发现。 + +### 暴露的问题 + +| # | 问题 | 具体表现 | 分析结论 | +|---|------|----------|----------| +| 1 | propose 阶段越界 | 在 propose 阶段一次性生成了 proposal + design + specs + tasks,跳过 grill 和 specify | 需求小时 agent 本能跳过门控。现有硬约束 #3(不得跳过 grill)和阶段流程顺序已覆盖,属于执行层面问题,不需要改协议 | +| 2 | 子 skill 伪调用 | grill 阶段读了 grill-with-docs 的 SKILL.md 后自行执行,audit 阶段跳过了 zoom-out | Skill 工具调用和 Read 后执行效果等价,关键是"不能跳过"而非"用什么工具调用"。硬约束 #6 已覆盖,不需要改协议 | +| 3 | spec 遗漏用户行为 | spec 写的是"添加 .expanded class"(实现细节),没有写"展开后显示完整正文"(用户可观察行为) | 导致第一版实现只切换了 CSS class,正文内容仍显示截断文本。spec 应描述用户可观察的结果而非实现方式 | + +### 做对的部分 + +- clarify + context 合并执行正确(micro 模式) +- grill 的 evidence-driven / user-interview 分类和 one-at-a-time 节奏执行到位 +- commit gate 的文件存在性检查生效 +- apply 阶段的冲突分类(代码偏离)处理正确 +- devflow 延迟写入(只维护 decisions.md)降低了维护成本 + +### 后续观察项 + +问题 1 和 2 暂不改协议,如果多次验证中反复出现再考虑加约束。问题 3 需要在下次 specify 阶段验证:spec scenario 是否自然地描述用户行为而非实现细节。