maestro-flow 0.5.48 → 0.5.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/.agents/skills/manage-harvest/SKILL.md +4 -2
  2. package/.agents/skills/manage-knowledge-audit/SKILL.md +7 -2
  3. package/.agents/skills/quality-review/SKILL.md +2 -2
  4. package/.agents/skills/spec-add/SKILL.md +4 -0
  5. package/.agy/skills/manage-harvest/SKILL.md +4 -2
  6. package/.agy/skills/manage-knowledge-audit/SKILL.md +7 -2
  7. package/.agy/skills/quality-review/SKILL.md +2 -2
  8. package/.agy/skills/spec-add/SKILL.md +4 -0
  9. package/.claude/commands/manage-harvest.md +4 -2
  10. package/.claude/commands/manage-knowledge-audit.md +7 -2
  11. package/.claude/commands/quality-review.md +2 -2
  12. package/.claude/commands/spec-add.md +4 -0
  13. package/dashboard/dist-server/dashboard/src/server/wiki/embedding.d.ts +2 -2
  14. package/dashboard/dist-server/dashboard/src/server/wiki/embedding.js +28 -37
  15. package/dashboard/dist-server/dashboard/src/server/wiki/embedding.js.map +1 -1
  16. package/dashboard/dist-server/dashboard/src/server/wiki/graph-analysis.d.ts +0 -34
  17. package/dashboard/dist-server/dashboard/src/server/wiki/graph-analysis.js +0 -126
  18. package/dashboard/dist-server/dashboard/src/server/wiki/graph-analysis.js.map +1 -1
  19. package/dashboard/dist-server/dashboard/src/server/wiki/spec-entry-parser.d.ts +6 -0
  20. package/dashboard/dist-server/dashboard/src/server/wiki/spec-entry-parser.js +17 -1
  21. package/dashboard/dist-server/dashboard/src/server/wiki/spec-entry-parser.js.map +1 -1
  22. package/dashboard/dist-server/dashboard/src/server/wiki/time-decay.d.ts +28 -0
  23. package/dashboard/dist-server/dashboard/src/server/wiki/time-decay.js +70 -0
  24. package/dashboard/dist-server/dashboard/src/server/wiki/time-decay.js.map +1 -0
  25. package/dashboard/dist-server/dashboard/src/server/wiki/time-decay.test.d.ts +1 -0
  26. package/dashboard/dist-server/dashboard/src/server/wiki/time-decay.test.js +78 -0
  27. package/dashboard/dist-server/dashboard/src/server/wiki/time-decay.test.js.map +1 -0
  28. package/dashboard/dist-server/dashboard/src/server/wiki/virtual-wiki-adapters.js +6 -1
  29. package/dashboard/dist-server/dashboard/src/server/wiki/virtual-wiki-adapters.js.map +1 -1
  30. package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.d.ts +1 -0
  31. package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.js +104 -29
  32. package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.js.map +1 -1
  33. package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.test.js +2 -2
  34. package/dashboard/dist-server/dashboard/src/server/wiki/wiki-indexer.test.js.map +1 -1
  35. package/dashboard/dist-server/dashboard/src/server/wiki/writer.js +8 -5
  36. package/dashboard/dist-server/dashboard/src/server/wiki/writer.js.map +1 -1
  37. package/dashboard/dist-server/src/search/daemon-client.js +5 -3
  38. package/dashboard/dist-server/src/search/daemon-client.js.map +1 -1
  39. package/dashboard/dist-server/src/tools/spec-entry-parser.d.ts +42 -1
  40. package/dashboard/dist-server/src/tools/spec-entry-parser.js +22 -2
  41. package/dashboard/dist-server/src/tools/spec-entry-parser.js.map +1 -1
  42. package/dashboard/dist-server/src/tools/spec-loader.js +10 -3
  43. package/dashboard/dist-server/src/tools/spec-loader.js.map +1 -1
  44. package/dist/src/agents/api-explore/agent-loop.d.ts +2 -0
  45. package/dist/src/agents/api-explore/agent-loop.d.ts.map +1 -1
  46. package/dist/src/agents/api-explore/agent-loop.js +1 -1
  47. package/dist/src/agents/api-explore/agent-loop.js.map +1 -1
  48. package/dist/src/agents/api-explore/circuit-breaker.d.ts +11 -0
  49. package/dist/src/agents/api-explore/circuit-breaker.d.ts.map +1 -1
  50. package/dist/src/agents/api-explore/circuit-breaker.js +70 -1
  51. package/dist/src/agents/api-explore/circuit-breaker.js.map +1 -1
  52. package/dist/src/agents/api-explore/llm.d.ts +5 -0
  53. package/dist/src/agents/api-explore/llm.d.ts.map +1 -1
  54. package/dist/src/agents/api-explore/llm.js +31 -0
  55. package/dist/src/agents/api-explore/llm.js.map +1 -1
  56. package/dist/src/agents/api-explore/runner.d.ts.map +1 -1
  57. package/dist/src/agents/api-explore/runner.js +54 -6
  58. package/dist/src/agents/api-explore/runner.js.map +1 -1
  59. package/dist/src/commands/search.d.ts +4 -0
  60. package/dist/src/commands/search.d.ts.map +1 -1
  61. package/dist/src/commands/search.js +18 -3
  62. package/dist/src/commands/search.js.map +1 -1
  63. package/dist/src/commands/spec.d.ts.map +1 -1
  64. package/dist/src/commands/spec.js +113 -0
  65. package/dist/src/commands/spec.js.map +1 -1
  66. package/dist/src/commands/wiki.js +2 -2
  67. package/dist/src/commands/wiki.js.map +1 -1
  68. package/dist/src/search/daemon-client.d.ts.map +1 -1
  69. package/dist/src/search/daemon-client.js +5 -3
  70. package/dist/src/search/daemon-client.js.map +1 -1
  71. package/dist/src/search/daemon.d.ts.map +1 -1
  72. package/dist/src/search/daemon.js +17 -0
  73. package/dist/src/search/daemon.js.map +1 -1
  74. package/dist/src/tools/spec-conflict-marker.d.ts +62 -0
  75. package/dist/src/tools/spec-conflict-marker.d.ts.map +1 -1
  76. package/dist/src/tools/spec-conflict-marker.js +280 -1
  77. package/dist/src/tools/spec-conflict-marker.js.map +1 -1
  78. package/dist/src/tools/spec-entry-parser.d.ts +42 -1
  79. package/dist/src/tools/spec-entry-parser.d.ts.map +1 -1
  80. package/dist/src/tools/spec-entry-parser.js +22 -2
  81. package/dist/src/tools/spec-entry-parser.js.map +1 -1
  82. package/dist/src/tools/spec-loader.d.ts.map +1 -1
  83. package/dist/src/tools/spec-loader.js +10 -3
  84. package/dist/src/tools/spec-loader.js.map +1 -1
  85. package/dist/src/tools/spec-writer.d.ts +2 -0
  86. package/dist/src/tools/spec-writer.d.ts.map +1 -1
  87. package/dist/src/tools/spec-writer.js +8 -6
  88. package/dist/src/tools/spec-writer.js.map +1 -1
  89. package/dist/src/utils/update-notices.js +12 -0
  90. package/dist/src/utils/update-notices.js.map +1 -1
  91. package/package.json +1 -1
  92. package/workflows/agy-instructions.md +14 -5
  93. package/workflows/claude-instructions.md +25 -3
  94. package/workflows/codex-instructions.md +14 -5
  95. package/workflows/finish-work.md +65 -86
  96. package/workflows/knowledge-audit.md +2 -1
  97. package/workflows/specs-add.md +7 -3
@@ -48,7 +48,7 @@ Additional flags, source registry (scan paths), and storage locations defined in
48
48
  2. **Never modify source artifacts** — harvest is purely extractive; source files remain untouched
49
49
  3. **Dedup before write** — MUST check harvest-log.jsonl and existing stores before each write to prevent duplicates
50
50
  4. **Source tagging** — MUST set `source: "harvest"` on every issues.jsonl row so concurrent writers can be distinguished
51
- 5. **Conflict pre-check on spec routing** — when routing to spec, MUST compare against existing specs with same keywords/category; set `confidence="low"` and log conflict note if semantic conflict detected
51
+ 5. **Relationship pre-check on spec routing** — when routing to spec, MUST compare against existing specs with same keywords/category. Classify the relationship: **supersede** (new replaces old) → attach `supersedes = <old-sid>`, after add run `maestro spec supersede`; **conflict** (genuine dispute) → set `confidence="low"` and log conflict note; **independent** no metadata
52
52
  6. **Provenance tracking** — every routed item MUST be logged in harvest-log.jsonl with fragment ID, target store, and timestamp
53
53
  7. **Dry-run safety** — `--dry-run` MUST NOT write any files; preview only
54
54
  </invariants>
@@ -88,8 +88,10 @@ Extraction patterns, classification rules, routing infrastructure, and fragment
88
88
  | Wiki graph needs linking | `/manage-wiki connect --fix` |
89
89
  | Issues created | `/manage-issue list --source harvest` |
90
90
  | Specs extracted | `/spec-load --role implement` |
91
- | Specs extracted (冲突审查) | `/manage-knowledge-audit --scope spec` — 新写入的 spec 可能与现有条目矛盾 |
91
+ | Specs extracted (审查) | `/manage-knowledge-audit --scope spec` — 新写入的 spec 可能与现有条目矛盾或替代 |
92
+ | 查看演化链 | `maestro spec history <sid>` — 确认 supersede 链完整 |
92
93
  | Spec 冲突标记已存在 | `maestro spec conflict list` — 查看当前冲突状态 |
94
+ | 知识健康检查 | `maestro spec health` — 悬空/循环 supersedes 校验 |
93
95
  | Full phase retrospective | `/quality-retrospective` |
94
96
  </completion>
95
97
 
@@ -83,15 +83,17 @@ Follow `~/.maestro/workflows/knowledge-audit.md` Stages 1-8 in order.
83
83
 
84
84
  ### Conflict Resolution Integration
85
85
 
86
- 四态决策(扩展自三态 keep/deprecate/delete):
86
+ 五态决策(扩展自三态 keep/deprecate/delete):
87
87
 
88
88
  | 动作 | 适用场景 | 执行 |
89
89
  |------|---------|------|
90
90
  | `keep` | 内容正确,无需变更 | 写 audit-log ignore 记录 |
91
91
  | `contest` | 矛盾真实存在,需进一步审查 | `maestro spec conflict mark <file> <line> --note "<evidence>"` |
92
- | `deprecate` | 内容过时或被取代 | 注入 `status="deprecated"` + `maestro spec conflict clear <file> <line>` |
92
+ | `supersede` | 内容过时,已有更新版本替代 | `maestro spec supersede <old-sid> --by <new-sid>`(保留演化链) |
93
+ | `deprecate` | 内容过时,无替代版本 | 注入 `status="deprecated"` + `maestro spec conflict clear <file> <line>` |
93
94
  | `delete` | 内容明确错误 | 移除 entry + `maestro spec conflict clear <file> <line>` |
94
95
 
96
+ **supersede vs deprecate**: supersede 用于有明确替代条目的场景(建立演化链),deprecate 用于无替代条目的场景。
95
97
  **关键**: deprecate/delete 执行时,如果目标条目有 conflict-marker,必须同步调用 `maestro spec conflict clear` 清除标记,避免悬空冲突。
96
98
 
97
99
  ### Code-as-Truth 校验(审查核心原则)
@@ -117,6 +119,9 @@ Follow `~/.maestro/workflows/knowledge-audit.md` Stages 1-8 in order.
117
119
  | 验证 spec 现状 | `/spec-load --role implement` |
118
120
  | 查看冲突标记 | `maestro spec conflict list` |
119
121
  | 清除已解决冲突 | `maestro spec conflict clear-all <file>` |
122
+ | 查看演化链 | `maestro spec history <sid>` |
123
+ | 知识健康检查 | `maestro spec health` |
124
+ | 回填存量 sid | `maestro spec backfill-sid` |
120
125
  | 周期巡检 | `--scope all --report` |
121
126
  </completion>
122
127
 
@@ -66,7 +66,7 @@ Each artifact's type determines its outputs at `.workflow/{a.path}/`:
66
66
  3. **Verdict is data-driven** — NEVER change verdict severity to accommodate user preference without new evidence. Verdicts flow from findings, not negotiation.
67
67
  4. **Dimension independence** — each review dimension produces findings independently. One dimension's results MUST NOT suppress or override another's.
68
68
  5. **Prior review delta** — when a prior review.json exists for the same phase, findings MUST be compared. Do NOT re-report already-resolved findings as new.
69
- 6. **Spec conflict integrity** — if code contradicts a spec entry, flag via `maestro spec conflict mark`. NEVER silently accept the contradiction or edit the spec inline.
69
+ 6. **Spec conflict integrity** — if code contradicts a spec entry: if the code is the evolved practice (spec outdated), suggest `maestro spec supersede`; if genuinely disputed, flag via `maestro spec conflict mark`. NEVER silently accept the contradiction or edit the spec inline.
70
70
  </invariants>
71
71
 
72
72
  <execution>
@@ -87,7 +87,7 @@ Follow '~/.maestro/workflows/review.md' completely.
87
87
  - REQUIRED: review.json written with findings, severity distribution, and verdict.
88
88
  - REQUIRED: Issues auto-created based on level thresholds.
89
89
  - REQUIRED: index.json updated with review status.
90
- - REQUIRED: Spec conflict check — if any finding directly contradicts a loaded spec entry (code behavior ≠ spec rule), suggest `maestro spec conflict mark` on the spec entry. Code is the single source of truth.
90
+ - REQUIRED: Spec conflict check — if any finding directly contradicts a loaded spec entry (code behavior ≠ spec rule): if spec is outdated (code evolved), suggest `maestro spec supersede`; if genuinely disputed, suggest `maestro spec conflict mark`. Code is the single source of truth.
91
91
 
92
92
  **Output writes to REVIEW_DIR** (not EXEC_DIR):
93
93
  - `REVIEW_DIR/review.json` — findings, severity distribution, verdict
@@ -25,6 +25,7 @@ $ARGUMENTS -- expects `[--scope <scope>] [--uid <uid>] <category> <content>`
25
25
 
26
26
  **Options:**
27
27
  - `--description <desc>` — One-line description for search results (falls back to content[:240])
28
+ - `--json` — Output JSON with generated `sid` (needed for supersession: `maestro spec supersede <old-sid> --by <new-sid>`)
28
29
  - `--ref <path>` — Create as index entry referencing a knowhow document. If the path exists, only creates the spec index entry. If path doesn't exist, also creates the knowhow file.
29
30
  - `--knowhow-type <type>` — Knowhow document type when creating with --ref (asset, blueprint, document, template, recipe, reference, decision)
30
31
 
@@ -104,6 +105,9 @@ Follow '~/.maestro/workflows/specs-add.md' completely.
104
105
  | Condition | Suggestion |
105
106
  |-----------|-----------|
106
107
  | Verify entry added | `maestro load --type spec --scope <scope> --keyword {keyword}` |
108
+ | New entry replaces old one | `maestro spec supersede <old-sid> --by <new-sid>` |
109
+ | View evolution chain | `maestro spec history <sid>` |
107
110
  | Add more entries | `/spec-add <category>` |
108
111
  | View all specs | `/spec-load --category <category>` |
112
+ | Check knowledge health | `maestro spec health` |
109
113
  </completion>
@@ -48,7 +48,7 @@ Additional flags, source registry (scan paths), and storage locations defined in
48
48
  2. **Never modify source artifacts** — harvest is purely extractive; source files remain untouched
49
49
  3. **Dedup before write** — MUST check harvest-log.jsonl and existing stores before each write to prevent duplicates
50
50
  4. **Source tagging** — MUST set `source: "harvest"` on every issues.jsonl row so concurrent writers can be distinguished
51
- 5. **Conflict pre-check on spec routing** — when routing to spec, MUST compare against existing specs with same keywords/category; set `confidence="low"` and log conflict note if semantic conflict detected
51
+ 5. **Relationship pre-check on spec routing** — when routing to spec, MUST compare against existing specs with same keywords/category. Classify the relationship: **supersede** (new replaces old) → attach `supersedes = <old-sid>`, after add run `maestro spec supersede`; **conflict** (genuine dispute) → set `confidence="low"` and log conflict note; **independent** no metadata
52
52
  6. **Provenance tracking** — every routed item MUST be logged in harvest-log.jsonl with fragment ID, target store, and timestamp
53
53
  7. **Dry-run safety** — `--dry-run` MUST NOT write any files; preview only
54
54
  </invariants>
@@ -88,8 +88,10 @@ Extraction patterns, classification rules, routing infrastructure, and fragment
88
88
  | Wiki graph needs linking | `/manage-wiki connect --fix` |
89
89
  | Issues created | `/manage-issue list --source harvest` |
90
90
  | Specs extracted | `/spec-load --role implement` |
91
- | Specs extracted (冲突审查) | `/manage-knowledge-audit --scope spec` — 新写入的 spec 可能与现有条目矛盾 |
91
+ | Specs extracted (审查) | `/manage-knowledge-audit --scope spec` — 新写入的 spec 可能与现有条目矛盾或替代 |
92
+ | 查看演化链 | `maestro spec history <sid>` — 确认 supersede 链完整 |
92
93
  | Spec 冲突标记已存在 | `maestro spec conflict list` — 查看当前冲突状态 |
94
+ | 知识健康检查 | `maestro spec health` — 悬空/循环 supersedes 校验 |
93
95
  | Full phase retrospective | `/quality-retrospective` |
94
96
  </completion>
95
97
 
@@ -83,15 +83,17 @@ Follow `~/.maestro/workflows/knowledge-audit.md` Stages 1-8 in order.
83
83
 
84
84
  ### Conflict Resolution Integration
85
85
 
86
- 四态决策(扩展自三态 keep/deprecate/delete):
86
+ 五态决策(扩展自三态 keep/deprecate/delete):
87
87
 
88
88
  | 动作 | 适用场景 | 执行 |
89
89
  |------|---------|------|
90
90
  | `keep` | 内容正确,无需变更 | 写 audit-log ignore 记录 |
91
91
  | `contest` | 矛盾真实存在,需进一步审查 | `maestro spec conflict mark <file> <line> --note "<evidence>"` |
92
- | `deprecate` | 内容过时或被取代 | 注入 `status="deprecated"` + `maestro spec conflict clear <file> <line>` |
92
+ | `supersede` | 内容过时,已有更新版本替代 | `maestro spec supersede <old-sid> --by <new-sid>`(保留演化链) |
93
+ | `deprecate` | 内容过时,无替代版本 | 注入 `status="deprecated"` + `maestro spec conflict clear <file> <line>` |
93
94
  | `delete` | 内容明确错误 | 移除 entry + `maestro spec conflict clear <file> <line>` |
94
95
 
96
+ **supersede vs deprecate**: supersede 用于有明确替代条目的场景(建立演化链),deprecate 用于无替代条目的场景。
95
97
  **关键**: deprecate/delete 执行时,如果目标条目有 conflict-marker,必须同步调用 `maestro spec conflict clear` 清除标记,避免悬空冲突。
96
98
 
97
99
  ### Code-as-Truth 校验(审查核心原则)
@@ -117,6 +119,9 @@ Follow `~/.maestro/workflows/knowledge-audit.md` Stages 1-8 in order.
117
119
  | 验证 spec 现状 | `/spec-load --role implement` |
118
120
  | 查看冲突标记 | `maestro spec conflict list` |
119
121
  | 清除已解决冲突 | `maestro spec conflict clear-all <file>` |
122
+ | 查看演化链 | `maestro spec history <sid>` |
123
+ | 知识健康检查 | `maestro spec health` |
124
+ | 回填存量 sid | `maestro spec backfill-sid` |
120
125
  | 周期巡检 | `--scope all --report` |
121
126
  </completion>
122
127
 
@@ -66,7 +66,7 @@ Each artifact's type determines its outputs at `.workflow/{a.path}/`:
66
66
  3. **Verdict is data-driven** — NEVER change verdict severity to accommodate user preference without new evidence. Verdicts flow from findings, not negotiation.
67
67
  4. **Dimension independence** — each review dimension produces findings independently. One dimension's results MUST NOT suppress or override another's.
68
68
  5. **Prior review delta** — when a prior review.json exists for the same phase, findings MUST be compared. Do NOT re-report already-resolved findings as new.
69
- 6. **Spec conflict integrity** — if code contradicts a spec entry, flag via `maestro spec conflict mark`. NEVER silently accept the contradiction or edit the spec inline.
69
+ 6. **Spec conflict integrity** — if code contradicts a spec entry: if the code is the evolved practice (spec outdated), suggest `maestro spec supersede`; if genuinely disputed, flag via `maestro spec conflict mark`. NEVER silently accept the contradiction or edit the spec inline.
70
70
  </invariants>
71
71
 
72
72
  <execution>
@@ -87,7 +87,7 @@ Follow '~/.maestro/workflows/review.md' completely.
87
87
  - REQUIRED: review.json written with findings, severity distribution, and verdict.
88
88
  - REQUIRED: Issues auto-created based on level thresholds.
89
89
  - REQUIRED: index.json updated with review status.
90
- - REQUIRED: Spec conflict check — if any finding directly contradicts a loaded spec entry (code behavior ≠ spec rule), suggest `maestro spec conflict mark` on the spec entry. Code is the single source of truth.
90
+ - REQUIRED: Spec conflict check — if any finding directly contradicts a loaded spec entry (code behavior ≠ spec rule): if spec is outdated (code evolved), suggest `maestro spec supersede`; if genuinely disputed, suggest `maestro spec conflict mark`. Code is the single source of truth.
91
91
 
92
92
  **Output writes to REVIEW_DIR** (not EXEC_DIR):
93
93
  - `REVIEW_DIR/review.json` — findings, severity distribution, verdict
@@ -22,6 +22,7 @@ $ARGUMENTS -- expects `[--scope <scope>] [--uid <uid>] <category> <content>`
22
22
 
23
23
  **Options:**
24
24
  - `--description <desc>` — One-line description for search results (falls back to content[:240])
25
+ - `--json` — Output JSON with generated `sid` (needed for supersession: `maestro spec supersede <old-sid> --by <new-sid>`)
25
26
  - `--ref <path>` — Create as index entry referencing a knowhow document. If the path exists, only creates the spec index entry. If path doesn't exist, also creates the knowhow file.
26
27
  - `--knowhow-type <type>` — Knowhow document type when creating with --ref (asset, blueprint, document, template, recipe, reference, decision)
27
28
 
@@ -101,6 +102,9 @@ Follow '~/.maestro/workflows/specs-add.md' completely.
101
102
  | Condition | Suggestion |
102
103
  |-----------|-----------|
103
104
  | Verify entry added | `maestro load --type spec --scope <scope> --keyword {keyword}` |
105
+ | New entry replaces old one | `maestro spec supersede <old-sid> --by <new-sid>` |
106
+ | View evolution chain | `maestro spec history <sid>` |
104
107
  | Add more entries | `/spec-add <category>` |
105
108
  | View all specs | `/spec-load --category <category>` |
109
+ | Check knowledge health | `maestro spec health` |
106
110
  </completion>
@@ -46,7 +46,7 @@ Additional flags, source registry (scan paths), and storage locations defined in
46
46
  2. **Never modify source artifacts** — harvest is purely extractive; source files remain untouched
47
47
  3. **Dedup before write** — MUST check harvest-log.jsonl and existing stores before each write to prevent duplicates
48
48
  4. **Source tagging** — MUST set `source: "harvest"` on every issues.jsonl row so concurrent writers can be distinguished
49
- 5. **Conflict pre-check on spec routing** — when routing to spec, MUST compare against existing specs with same keywords/category; set `confidence="low"` and log conflict note if semantic conflict detected
49
+ 5. **Relationship pre-check on spec routing** — when routing to spec, MUST compare against existing specs with same keywords/category. Classify the relationship: **supersede** (new replaces old) → attach `supersedes = <old-sid>`, after add run `maestro spec supersede`; **conflict** (genuine dispute) → set `confidence="low"` and log conflict note; **independent** no metadata
50
50
  6. **Provenance tracking** — every routed item MUST be logged in harvest-log.jsonl with fragment ID, target store, and timestamp
51
51
  7. **Dry-run safety** — `--dry-run` MUST NOT write any files; preview only
52
52
  </invariants>
@@ -86,8 +86,10 @@ Extraction patterns, classification rules, routing infrastructure, and fragment
86
86
  | Wiki graph needs linking | `/manage-wiki connect --fix` |
87
87
  | Issues created | `/manage-issue list --source harvest` |
88
88
  | Specs extracted | `/spec-load --role implement` |
89
- | Specs extracted (冲突审查) | `/manage-knowledge-audit --scope spec` — 新写入的 spec 可能与现有条目矛盾 |
89
+ | Specs extracted (审查) | `/manage-knowledge-audit --scope spec` — 新写入的 spec 可能与现有条目矛盾或替代 |
90
+ | 查看演化链 | `maestro spec history <sid>` — 确认 supersede 链完整 |
90
91
  | Spec 冲突标记已存在 | `maestro spec conflict list` — 查看当前冲突状态 |
92
+ | 知识健康检查 | `maestro spec health` — 悬空/循环 supersedes 校验 |
91
93
  | Full phase retrospective | `/quality-retrospective` |
92
94
  </completion>
93
95
 
@@ -81,15 +81,17 @@ Follow `~/.maestro/workflows/knowledge-audit.md` Stages 1-8 in order.
81
81
 
82
82
  ### Conflict Resolution Integration
83
83
 
84
- 四态决策(扩展自三态 keep/deprecate/delete):
84
+ 五态决策(扩展自三态 keep/deprecate/delete):
85
85
 
86
86
  | 动作 | 适用场景 | 执行 |
87
87
  |------|---------|------|
88
88
  | `keep` | 内容正确,无需变更 | 写 audit-log ignore 记录 |
89
89
  | `contest` | 矛盾真实存在,需进一步审查 | `maestro spec conflict mark <file> <line> --note "<evidence>"` |
90
- | `deprecate` | 内容过时或被取代 | 注入 `status="deprecated"` + `maestro spec conflict clear <file> <line>` |
90
+ | `supersede` | 内容过时,已有更新版本替代 | `maestro spec supersede <old-sid> --by <new-sid>`(保留演化链) |
91
+ | `deprecate` | 内容过时,无替代版本 | 注入 `status="deprecated"` + `maestro spec conflict clear <file> <line>` |
91
92
  | `delete` | 内容明确错误 | 移除 entry + `maestro spec conflict clear <file> <line>` |
92
93
 
94
+ **supersede vs deprecate**: supersede 用于有明确替代条目的场景(建立演化链),deprecate 用于无替代条目的场景。
93
95
  **关键**: deprecate/delete 执行时,如果目标条目有 conflict-marker,必须同步调用 `maestro spec conflict clear` 清除标记,避免悬空冲突。
94
96
 
95
97
  ### Code-as-Truth 校验(审查核心原则)
@@ -115,6 +117,9 @@ Follow `~/.maestro/workflows/knowledge-audit.md` Stages 1-8 in order.
115
117
  | 验证 spec 现状 | `/spec-load --role implement` |
116
118
  | 查看冲突标记 | `maestro spec conflict list` |
117
119
  | 清除已解决冲突 | `maestro spec conflict clear-all <file>` |
120
+ | 查看演化链 | `maestro spec history <sid>` |
121
+ | 知识健康检查 | `maestro spec health` |
122
+ | 回填存量 sid | `maestro spec backfill-sid` |
118
123
  | 周期巡检 | `--scope all --report` |
119
124
  </completion>
120
125
 
@@ -64,7 +64,7 @@ Each artifact's type determines its outputs at `.workflow/{a.path}/`:
64
64
  3. **Verdict is data-driven** — NEVER change verdict severity to accommodate user preference without new evidence. Verdicts flow from findings, not negotiation.
65
65
  4. **Dimension independence** — each review dimension produces findings independently. One dimension's results MUST NOT suppress or override another's.
66
66
  5. **Prior review delta** — when a prior review.json exists for the same phase, findings MUST be compared. Do NOT re-report already-resolved findings as new.
67
- 6. **Spec conflict integrity** — if code contradicts a spec entry, flag via `maestro spec conflict mark`. NEVER silently accept the contradiction or edit the spec inline.
67
+ 6. **Spec conflict integrity** — if code contradicts a spec entry: if the code is the evolved practice (spec outdated), suggest `maestro spec supersede`; if genuinely disputed, flag via `maestro spec conflict mark`. NEVER silently accept the contradiction or edit the spec inline.
68
68
  </invariants>
69
69
 
70
70
  <execution>
@@ -85,7 +85,7 @@ Follow '~/.maestro/workflows/review.md' completely.
85
85
  - REQUIRED: review.json written with findings, severity distribution, and verdict.
86
86
  - REQUIRED: Issues auto-created based on level thresholds.
87
87
  - REQUIRED: index.json updated with review status.
88
- - REQUIRED: Spec conflict check — if any finding directly contradicts a loaded spec entry (code behavior ≠ spec rule), suggest `maestro spec conflict mark` on the spec entry. Code is the single source of truth.
88
+ - REQUIRED: Spec conflict check — if any finding directly contradicts a loaded spec entry (code behavior ≠ spec rule): if spec is outdated (code evolved), suggest `maestro spec supersede`; if genuinely disputed, suggest `maestro spec conflict mark`. Code is the single source of truth.
89
89
 
90
90
  **Output writes to REVIEW_DIR** (not EXEC_DIR):
91
91
  - `REVIEW_DIR/review.json` — findings, severity distribution, verdict
@@ -23,6 +23,7 @@ $ARGUMENTS -- expects `[--scope <scope>] [--uid <uid>] <category> <content>`
23
23
 
24
24
  **Options:**
25
25
  - `--description <desc>` — One-line description for search results (falls back to content[:240])
26
+ - `--json` — Output JSON with generated `sid` (needed for supersession: `maestro spec supersede <old-sid> --by <new-sid>`)
26
27
  - `--ref <path>` — Create as index entry referencing a knowhow document. If the path exists, only creates the spec index entry. If path doesn't exist, also creates the knowhow file.
27
28
  - `--knowhow-type <type>` — Knowhow document type when creating with --ref (asset, blueprint, document, template, recipe, reference, decision)
28
29
 
@@ -102,6 +103,9 @@ Follow '~/.maestro/workflows/specs-add.md' completely.
102
103
  | Condition | Suggestion |
103
104
  |-----------|-----------|
104
105
  | Verify entry added | `maestro load --type spec --scope <scope> --keyword {keyword}` |
106
+ | New entry replaces old one | `maestro spec supersede <old-sid> --by <new-sid>` |
107
+ | View evolution chain | `maestro spec history <sid>` |
105
108
  | Add more entries | `/spec-add <category>` |
106
109
  | View all specs | `/spec-load --category <category>` |
110
+ | Check knowledge health | `maestro spec health` |
107
111
  </completion>
@@ -100,7 +100,7 @@ export declare function vectorSearch(queryVector: Float32Array, index: Embedding
100
100
  * Falls back to flat cosine scan when zvec is unavailable or feature flag is set.
101
101
  */
102
102
  export declare function vectorSearchZvec(queryVector: Float32Array, dir: string, limit: number): Promise<VectorSearchResult[]>;
103
- export declare function saveEmbeddingIndex(index: EmbeddingIndex, dir: string): void;
103
+ export declare function saveEmbeddingIndex(index: EmbeddingIndex, dir: string): Promise<void>;
104
104
  export declare function loadEmbeddingIndex(dir: string): EmbeddingIndex | null;
105
105
  export interface DocForEmbedding {
106
106
  id: string;
@@ -109,7 +109,7 @@ export interface DocForEmbedding {
109
109
  tags: string[];
110
110
  body?: string;
111
111
  }
112
- export declare function hashDocContent(d: DocForEmbedding): string;
112
+ export declare function hashDocContent(d: DocForEmbedding, enrichedText?: string): string;
113
113
  /**
114
114
  * Split a document into multiple chunks for embedding.
115
115
  * Short docs (<500 chars body) produce a single chunk.
@@ -198,8 +198,6 @@ async function callEmbeddingApi(texts, config) {
198
198
  }
199
199
  if (firstErr) {
200
200
  const filled = results.filter(Boolean).length;
201
- if (filled === 0)
202
- throw firstErr;
203
201
  if (filled < texts.length)
204
202
  throw firstErr;
205
203
  }
@@ -472,12 +470,6 @@ const ZVEC_DIR = 'embedding.zvec';
472
470
  export function vectorSearch(queryVector, index, limit) {
473
471
  if (index.dimension && queryVector.length !== index.dimension)
474
472
  return [];
475
- // Feature flag: force flat cosine scan (bypass zvec)
476
- if (process.env.MAESTRO_EMBEDDING_FLAT_SCAN) {
477
- return flatCosineSearch(queryVector, index, limit);
478
- }
479
- // Sync path — zvec requires async setup, so use flat scan here.
480
- // For zvec-accelerated search, callers should use vectorSearchZvec.
481
473
  return flatCosineSearch(queryVector, index, limit);
482
474
  }
483
475
  /**
@@ -533,7 +525,7 @@ const SQLITE_FILE = 'embedding-index.db';
533
525
  import { createRequire } from 'node:module';
534
526
  const _require = createRequire(import.meta.url);
535
527
  const BINARY_FILE = 'embedding-index.bin';
536
- export function saveEmbeddingIndex(index, dir) {
528
+ export async function saveEmbeddingIndex(index, dir) {
537
529
  mkdirSync(dir, { recursive: true });
538
530
  // --- Binary format (kept for backward compat and feature flag fallback) ---
539
531
  const dim = index.dimension;
@@ -573,10 +565,8 @@ export function saveEmbeddingIndex(index, dir) {
573
565
  const tmpPath = join(dir, BINARY_FILE + '.tmp');
574
566
  writeFileSync(tmpPath, buf);
575
567
  renameSync(tmpPath, join(dir, BINARY_FILE));
576
- // --- zvec collection save (async, best-effort) ---
577
- saveZvecIndex(index, dir).catch(() => {
578
- // zvec save failed — binary format still available as fallback
579
- });
568
+ // --- zvec collection save ---
569
+ await saveZvecIndex(index, dir);
580
570
  // Remove legacy files
581
571
  for (const f of [CACHE_FILE, SQLITE_FILE, SQLITE_FILE + '-shm', SQLITE_FILE + '-wal', SQLITE_FILE + '-journal']) {
582
572
  try {
@@ -586,14 +576,26 @@ export function saveEmbeddingIndex(index, dir) {
586
576
  catch { /* ignore */ }
587
577
  }
588
578
  }
579
+ let _zvecSaving = false;
589
580
  /**
590
581
  * Save embedding index to zvec collection format.
591
582
  * Creates/replaces a zvec collection at `dir/embedding.zvec`.
592
583
  */
593
584
  async function saveZvecIndex(index, dir) {
585
+ if (_zvecSaving)
586
+ return;
594
587
  const zvec = await getZvec();
595
588
  if (!zvec)
596
589
  return;
590
+ _zvecSaving = true;
591
+ try {
592
+ await _saveZvecIndexInner(zvec, index, dir);
593
+ }
594
+ finally {
595
+ _zvecSaving = false;
596
+ }
597
+ }
598
+ async function _saveZvecIndexInner(zvec, index, dir) {
597
599
  const collectionPath = join(dir, ZVEC_DIR);
598
600
  const dim = index.dimension;
599
601
  // Remove existing collection directory if present
@@ -692,7 +694,7 @@ export function loadEmbeddingIndex(dir) {
692
694
  if (existsSync(dbPath)) {
693
695
  try {
694
696
  const idx = loadFromSqlite(dir);
695
- saveEmbeddingIndex(idx, dir);
697
+ void saveEmbeddingIndex(idx, dir);
696
698
  return idx;
697
699
  }
698
700
  catch { /* fall through */ }
@@ -702,7 +704,7 @@ export function loadEmbeddingIndex(dir) {
702
704
  if (existsSync(jsonPath)) {
703
705
  try {
704
706
  const idx = loadFromLegacyJson(jsonPath);
705
- saveEmbeddingIndex(idx, dir);
707
+ void saveEmbeddingIndex(idx, dir);
706
708
  return idx;
707
709
  }
708
710
  catch {
@@ -848,9 +850,11 @@ function loadFromLegacyJson(filePath) {
848
850
  buildTimeMs: raw.buildTimeMs,
849
851
  };
850
852
  }
851
- export function hashDocContent(d) {
852
- const text = [d.title, d.summary, d.tags.join(','), d.body ?? ''].join('|');
853
- return createHash('md5').update(text).digest('hex');
853
+ export function hashDocContent(d, enrichedText) {
854
+ const parts = [d.title, d.summary, d.tags.join(','), d.body ?? ''];
855
+ if (enrichedText)
856
+ parts.push(enrichedText);
857
+ return createHash('md5').update(parts.join('|')).digest('hex');
854
858
  }
855
859
  /**
856
860
  * Extract meaningful content from a markdown body: first paragraph + heading lines,
@@ -938,7 +942,7 @@ export async function buildEmbeddingIndex(docs, existingIndex, precomputedHashes
938
942
  const apiMode = isApiMode();
939
943
  const config = apiMode ? null : await detectDevice();
940
944
  const t0 = Date.now();
941
- const currentHashes = precomputedHashes ?? docs.map(hashDocContent);
945
+ const currentHashes = precomputedHashes ?? docs.map(d => hashDocContent(d));
942
946
  // Split all docs into chunks (1:N doc-to-chunk mapping)
943
947
  const allChunkIds = [];
944
948
  const allChunkDocIds = [];
@@ -957,34 +961,21 @@ export async function buildEmbeddingIndex(docs, existingIndex, precomputedHashes
957
961
  }
958
962
  let vectors;
959
963
  const activeModel = getModelId();
960
- // Model changed discard all cached vectors, force full rebuild
961
- const modelMatch = existingIndex && existingIndex.modelId === activeModel;
964
+ const activeDim = apiMode ? (loadEmbeddingApiConfig()?.dimensions ?? 0) : 384;
965
+ // Model, dimensions, or mode changed discard all cached vectors, force full rebuild
966
+ const modelMatch = existingIndex
967
+ && existingIndex.modelId === activeModel
968
+ && (activeDim === 0 || existingIndex.dimension === activeDim);
962
969
  if (modelMatch && existingIndex.docIds.length > 0) {
963
- // Build existing chunk cache: chunkId → { vector, parentDocId }
964
970
  const existingChunkMap = new Map();
965
- const existingDocHashes = new Map();
966
- // Reconstruct per-doc hashes from existing index
967
971
  if (existingIndex.chunkDocIds && existingIndex.contentHashes) {
968
972
  for (let i = 0; i < existingIndex.docIds.length; i++) {
969
973
  existingChunkMap.set(existingIndex.docIds[i], existingIndex.vectors[i]);
970
974
  }
971
- // contentHashes are per-doc; find unique doc→hash mapping
972
- const seen = new Set();
973
- for (let i = 0; i < existingIndex.chunkDocIds.length; i++) {
974
- const parentId = existingIndex.chunkDocIds[i];
975
- if (!seen.has(parentId) && existingIndex.contentHashes[i] !== undefined) {
976
- // contentHashes in chunk-based index: stored per-doc in the order of docChunkRanges
977
- seen.add(parentId);
978
- }
979
- }
980
975
  }
981
976
  else {
982
- // Legacy index without chunkDocIds — docIds are direct doc IDs
983
977
  for (let i = 0; i < existingIndex.docIds.length; i++) {
984
978
  existingChunkMap.set(existingIndex.docIds[i], existingIndex.vectors[i]);
985
- if (existingIndex.contentHashes?.[i]) {
986
- existingDocHashes.set(existingIndex.docIds[i], existingIndex.contentHashes[i]);
987
- }
988
979
  }
989
980
  }
990
981
  // Determine which docs changed (hash comparison at doc level)