@fenglimg/fabric-cli 2.2.0 → 2.3.0-rc.1
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.
- package/README.md +2 -2
- package/dist/audit-PURSJJFH.js +734 -0
- package/dist/{chunk-QPAW6IYT.js → chunk-7V4XMLQ2.js} +3 -3
- package/dist/{chunk-7ZDXBOOU.js → chunk-ACSMNX3V.js} +44 -128
- package/dist/{chunk-PTGQAZEW.js → chunk-GGDVZCD6.js} +2 -4
- package/dist/{chunk-EOT63RDH.js → chunk-I5F5BHWI.js} +9 -0
- package/dist/chunk-PP7QVRXH.js +565 -0
- package/dist/chunk-SL77FXX7.js +54 -0
- package/dist/{chunk-3D7B2UAZ.js → chunk-VQKXTMWH.js} +44 -4
- package/dist/doctor-S6KPGS35.js +27 -0
- package/dist/index.js +90 -80
- package/dist/{info-7FKBTMVO.js → info-NJEY26H6.js} +91 -46
- package/dist/{context-UJCGYOT6.js → inspect-5YZMJPFM.js} +10 -10
- package/dist/{install-v2-3KJX3YRO.js → install-v2-KGIDII4H.js} +163 -364
- package/dist/{store-HOCORVL3.js → store-GF4SFBMJ.js} +155 -57
- package/dist/{sync-DT5UJMMR.js → sync-3XCIRDPK.js} +3 -4
- package/dist/{uninstall-IFN2KYBK.js → uninstall-BG4ML4FC.js} +39 -10
- package/package.json +3 -7
- package/templates/hooks/cite-policy-evict.cjs +1 -1
- package/templates/hooks/configs/claude-code.json +1 -5
- package/templates/hooks/configs/codex-hooks.json +1 -5
- package/templates/hooks/fabric-hint.cjs +67 -41
- package/templates/hooks/knowledge-hint-broad.cjs +82 -24
- package/templates/hooks/knowledge-hint-narrow.cjs +3 -3
- package/templates/hooks/knowledge-pretooluse.cjs +111 -0
- package/templates/hooks/lib/banner-i18n.cjs +12 -11
- package/templates/hooks/lib/bindings-snapshot-reader.cjs +1 -1
- package/templates/hooks/lib/event-writer.cjs +79 -0
- package/templates/hooks/lib/nudge-policy.cjs +11 -0
- package/templates/hooks/lib/theme.cjs +62 -0
- package/templates/hooks/post-tooluse-mutation.cjs +28 -39
- package/templates/skills/fabric-archive/SKILL.md +29 -12
- package/templates/skills/fabric-archive/ref/dry-run-scope.md +1 -1
- package/templates/skills/fabric-archive/ref/i18n-policy.md +1 -1
- package/templates/skills/fabric-archive/ref/phase-1-5-onboard.md +5 -5
- package/templates/skills/fabric-archive/ref/phase-1-cross-session.md +2 -2
- package/templates/skills/fabric-archive/ref/phase-2-5-viability.md +1 -1
- package/templates/skills/fabric-archive/ref/phase-3-5-scope.md +1 -1
- package/templates/skills/fabric-archive/ref/phase-3-6-related-edges.md +1 -1
- package/templates/skills/fabric-archive/ref/phase-3-classify.md +1 -1
- package/templates/skills/fabric-archive/ref/phase-4-5-emit.md +1 -1
- package/templates/skills/fabric-archive/ref/phase-4-mcp-persist.md +6 -5
- package/templates/skills/{fabric-import/ref/checkpoint-state.md → fabric-archive/ref/source-checkpoint.md} +3 -3
- package/templates/skills/{fabric-import/ref/phase-3-dedup.md → fabric-archive/ref/source-dedup.md} +4 -4
- package/templates/skills/{fabric-import/ref/phase-2-mining.md → fabric-archive/ref/source-mining.md} +20 -20
- package/templates/skills/{fabric-import/ref/output-contract.md → fabric-archive/ref/source-output-contract.md} +3 -3
- package/templates/skills/{fabric-import/ref/state-recovery.md → fabric-archive/ref/source-state-recovery.md} +2 -2
- package/templates/skills/{fabric-import/ref/worked-examples.md → fabric-archive/ref/source-worked-examples.md} +10 -10
- package/templates/skills/fabric-archive/ref/worked-examples.md +3 -3
- package/templates/skills/fabric-review/SKILL.md +19 -15
- package/templates/skills/fabric-review/ref/cite-contract.md +2 -2
- package/templates/skills/fabric-review/ref/modify-flow.md +13 -1
- package/templates/skills/fabric-review/ref/per-mode-flows.md +5 -5
- package/templates/skills/fabric-review/ref/relate-mode.md +33 -0
- package/templates/skills/fabric-review/ref/retire-mode.md +47 -0
- package/templates/skills/fabric-review/ref/semantic-check.md +1 -1
- package/templates/skills/fabric-review/ref/worked-examples.md +5 -5
- package/templates/skills/fabric-store/SKILL.md +12 -27
- package/templates/skills/fabric-sync/SKILL.md +16 -35
- package/templates/skills/lib/shared-policy.md +6 -4
- package/dist/chunk-27HK6H5Y.js +0 -69
- package/dist/chunk-E7HJUU34.js +0 -1096
- package/dist/chunk-NLNH64A3.js +0 -43
- package/dist/chunk-QFIVFZRH.js +0 -13
- package/dist/doctor-MDTZWKBK.js +0 -24
- package/dist/metrics-HMFH4YHK.js +0 -135
- package/dist/scope-explain-HLJZ2M33.js +0 -48
- package/dist/status-4R3TM4FJ.js +0 -37
- package/dist/whoami-ITGEFWH4.js +0 -49
- package/templates/skills/fabric/SKILL.md +0 -100
- package/templates/skills/fabric-audit/SKILL.md +0 -63
- package/templates/skills/fabric-connect/SKILL.md +0 -48
- package/templates/skills/fabric-import/SKILL.md +0 -151
- package/templates/skills/fabric-import/ref/i18n-policy.md +0 -78
package/templates/skills/{fabric-import/ref/phase-2-mining.md → fabric-archive/ref/source-mining.md}
RENAMED
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
## Mandatory Scope Rule — Always Broad + Empty Paths (Q-1 Resolution)
|
|
6
6
|
|
|
7
|
-
**EVERY `
|
|
7
|
+
**EVERY `fab_propose` call issued from this skill MUST set:**
|
|
8
8
|
|
|
9
9
|
- `relevance_scope = "broad"`
|
|
10
10
|
- `relevance_paths = []`
|
|
11
11
|
|
|
12
12
|
This is non-negotiable and applies to BOTH Step 2.1 (git mining) AND Step 2.2 (docs mining). No exceptions, no per-candidate override, no Agent judgment.
|
|
13
13
|
|
|
14
|
-
**Rationale — why
|
|
14
|
+
**Rationale — why archive source mode cannot bind paths from git history:**
|
|
15
15
|
|
|
16
|
-
1. `
|
|
16
|
+
1. `archive source mode` is LLM-driven (mines git log + docs), not session-driven (no live `edit_paths` signal).
|
|
17
17
|
2. `git diff --stat` lists files touched by a commit, but those files are the commit's **effect surface**, not the **applicability surface** of the underlying observation. A pitfall surfaced by a fix in `packages/server/src/retry.ts` may apply to every retry call-site in the repo, not just that one file.
|
|
18
18
|
3. LLM-inferred `relevance_paths` from historical commit metadata produces false-narrow bindings — `relevance_paths` becomes a lie about applicability. Post-rc.37 A1 the server no longer filters by `relevance_scope`, so false-narrow does NOT hide knowledge from AI recall (every selectable entry is surfaced regardless of scope). The damage is now downstream: doctor lint accounting, future-AI judgment, and any consumer that reads `relevance_paths` literally treats the wrong globs as ground truth. Broad+[] keeps the metadata honest until the user has the real applicability surface in hand to declare narrow.
|
|
19
19
|
4. Doc-mined observations are usually architectural / cross-cutting (a `docs/architecture.md` "Why a monolith?" decision applies to the whole codebase, not just to `docs/`).
|
|
@@ -24,16 +24,16 @@ This is non-negotiable and applies to BOTH Step 2.1 (git mining) AND Step 2.2 (d
|
|
|
24
24
|
- DO NOT derive `relevance_paths` from the path of a mined Markdown file (e.g. do NOT bind a `docs/architecture.md` observation to `["docs/**"]`).
|
|
25
25
|
- DO NOT extract path-shaped tokens from commit subjects / bodies / doc text and lift them into `relevance_paths`.
|
|
26
26
|
- DO NOT classify a candidate as `relevance_scope = "narrow"` under ANY heuristic.
|
|
27
|
-
- DO NOT copy the public-prefix-generalization logic from fabric-archive Phase 3.5 — that logic is valid only when bound to a real-time `edit_paths` signal from an active session, which
|
|
27
|
+
- DO NOT copy the public-prefix-generalization logic from fabric-archive Phase 3.5 — that logic is valid only when bound to a real-time `edit_paths` signal from an active session, which archive source mode lacks.
|
|
28
28
|
|
|
29
|
-
**Cross-reference —
|
|
29
|
+
**Cross-reference — archive source mode vs fabric-archive scope handling:**
|
|
30
30
|
|
|
31
31
|
| Skill | Scope decision | Why |
|
|
32
32
|
|------------------|--------------------|-----------------------------------------------------------------------|
|
|
33
33
|
| `fabric-archive` | narrow OR broad, case-by-case per Phase 3.5 rules | Has live `edit_paths` from the active session — the actual applicability surface. |
|
|
34
|
-
| `
|
|
34
|
+
| `archive source mode` | ALWAYS broad + `[]` (this skill) | LLM-only, no live session signal; git-history paths are effect-surface, not applicability-surface. |
|
|
35
35
|
|
|
36
|
-
`fabric-archive`'s Phase 3.5 scope decision (narrow-vs-broad rules + public-prefix generalization + glob blacklist) is INTENTIONALLY MORE PERMISSIVE than
|
|
36
|
+
`fabric-archive`'s Phase 3.5 scope decision (narrow-vs-broad rules + public-prefix generalization + glob blacklist) is INTENTIONALLY MORE PERMISSIVE than archive source mode because archive has the data to bind safely. archive source mode is the STRICTER case.
|
|
37
37
|
|
|
38
38
|
**Post-import narrowing path — deferred to user, via `fab_review.modify`:**
|
|
39
39
|
|
|
@@ -77,16 +77,16 @@ For each commit:
|
|
|
77
77
|
- `chore(...)`, `test(...)`, `ci(...)` → almost always skip (mechanical; no reusable insight)
|
|
78
78
|
2. Read the commit body. Extract the LLM-judged "core observation" — what would a future engineer want to know about this commit beyond the diff? Aim for 1–2 sentences in zh-CN (project fabric_language; mirror fabric-archive M3 style).
|
|
79
79
|
3. Apply the **Skip Decision Tree** below. If the commit is skip-worthy, record it in `p2_processed_commits[]` with `skipped: true` and move on.
|
|
80
|
-
4. For non-skipped commits, classify type / propose slug / draft summary. Then call `
|
|
80
|
+
4. For non-skipped commits, classify type / propose slug / draft summary. Then call `fab_propose` with the **mandatory broad + [] scope** (see "Mandatory Scope Rule" above):
|
|
81
81
|
|
|
82
82
|
```ts
|
|
83
|
-
|
|
84
|
-
source_sessions: ["fabric-
|
|
83
|
+
mcp__fabric__fab_propose({
|
|
84
|
+
source_sessions: ["fabric-archive-source-<ISO8601-date>"], // T5: array form; stable per import run
|
|
85
85
|
recent_paths: ["<files touched by this commit, capped at 20>"], // provenance only, NOT a path-binding signal
|
|
86
86
|
user_messages_summary: "<zh-CN 1-2 sentence summary of the commit's core observation; cite the commit sha as 'src=<sha7>'>",
|
|
87
87
|
type: "decisions" | "pitfalls" | "guidelines" | "models" | "processes",
|
|
88
88
|
slug: "<kebab-case 2-5 words derived from commit subject + body>",
|
|
89
|
-
relevance_scope: "broad", // MANDATORY — never "narrow" from
|
|
89
|
+
relevance_scope: "broad", // MANDATORY — never "narrow" from archive source mode
|
|
90
90
|
relevance_paths: [], // MANDATORY — never derived from git history
|
|
91
91
|
proposed_reason: "<inferred per Step 2.1.5 — varies>",
|
|
92
92
|
session_context: "Imported from git log analysis. Origin: commit <sha7> (<subject 30 chars>). No live session — see commit body for full context.",
|
|
@@ -108,7 +108,7 @@ Note: `recent_paths` carries the touched-file list for **provenance display** on
|
|
|
108
108
|
|
|
109
109
|
## Step 2.1.5 — Proposed Reason Inference (rc.7 T6)
|
|
110
110
|
|
|
111
|
-
For each non-skipped commit OR doc section, infer `proposed_reason` from prefix + body signal jointly. The 6 reasons below are the full enum accepted by `
|
|
111
|
+
For each non-skipped commit OR doc section, infer `proposed_reason` from prefix + body signal jointly. The 6 reasons below are the full enum accepted by `fab_propose` (schema-locked):
|
|
112
112
|
|
|
113
113
|
| Source signal | Body cue | Inferred reason |
|
|
114
114
|
|---|---|---|
|
|
@@ -148,7 +148,7 @@ For each Markdown file:
|
|
|
148
148
|
- `LICENSE.md`, `CODE_OF_CONDUCT.md`, `CONTRIBUTING.md` → skip (boilerplate)
|
|
149
149
|
- Files <300 bytes → skip (too thin to extract meaningful observations)
|
|
150
150
|
2. Read the file. Identify candidate observations: section headings that read like decisions ("we chose X over Y"), guidelines ("always do X"), pitfalls ("don't do Y because..."), or process steps ("the deploy procedure is..."). Architecture diagrams in fenced code blocks are strong **model** signals.
|
|
151
|
-
3. For each observation, classify type / propose slug / draft summary. Call `
|
|
151
|
+
3. For each observation, classify type / propose slug / draft summary. Call `fab_propose` with the same shape as Step 2.1 (including the **mandatory `relevance_scope: "broad"` + `relevance_paths: []`**), replacing `recent_paths` with `[<this doc path>]` and citing `src=<doc-relative-path>` in the summary.
|
|
152
152
|
4. Append to `.fabric/.import-state.json`:
|
|
153
153
|
- `p2_processed_docs[].push({path: <doc path>, observations_proposed: <count>, pending_paths: [...]})`
|
|
154
154
|
5. **Hard cap shared with Step 2.1**: total new pending entries across git + docs is capped at `import_max_pending_per_run` (config-resolved, default 10) per Phase 2 run.
|
|
@@ -167,14 +167,14 @@ A candidate signal surfaces (commit body or doc section).
|
|
|
167
167
|
│ └─ NO → skip (not classifiable = not yet ripe)
|
|
168
168
|
├─ Is the slug derivable as 2-5 kebab-case words?
|
|
169
169
|
│ └─ NO → skip (signal too vague for stable identifier)
|
|
170
|
-
└─ Else → propose via
|
|
170
|
+
└─ Else → propose via fab_propose
|
|
171
171
|
```
|
|
172
172
|
|
|
173
173
|
After Step 2.2 completes (or hits the cap), update `.fabric/.import-state.json`: `phase = "P2-done"`, `last_checkpoint_at = <ISO8601 now>`.
|
|
174
174
|
|
|
175
175
|
## Dry-Run Mode
|
|
176
176
|
|
|
177
|
-
When the user invocation carries the verbatim token `--dry-run`, Phase 2 runs WITHOUT calling `
|
|
177
|
+
When the user invocation carries the verbatim token `--dry-run`, Phase 2 runs WITHOUT calling `fab_propose`. Instead it prints a table. v2.0.0-rc.37 NEW-10 dropped the legacy substring fallback on bare `dry-run` / `预览` because those caused false positives on incidental mentions ("preview the table" / "do a dry run later"). UX i18n Policy class 4 — header + column titles bilingualized; row content (slug / commit sha / doc path) NOT translated. Protected tokens `broad`, `relevance_scope`, `relevance_paths` appear verbatim:
|
|
178
178
|
|
|
179
179
|
### zh-CN variant (`fabric_language === "zh-CN"`)
|
|
180
180
|
|
|
@@ -200,14 +200,14 @@ When the user invocation carries the verbatim token `--dry-run`, Phase 2 runs WI
|
|
|
200
200
|
| 3 | git 50367b5 | pitfalls | thundering-herd-no-backoff | broad+[] | Retries without exponential backoff caused a thundering herd outage. |
|
|
201
201
|
```
|
|
202
202
|
|
|
203
|
-
Every dry-run row MUST show `broad+[]` in the Scope column (constant for
|
|
203
|
+
Every dry-run row MUST show `broad+[]` in the Scope column (constant for archive source mode). A row showing anything else is a skill bug — refuse to proceed and surface the violation. Dry-run output is informational only. The state file is NOT written to in dry-run mode (so a real run later starts clean). Phase 3 is also skipped in dry-run.
|
|
204
204
|
|
|
205
205
|
## Idempotency Note — T5 array form
|
|
206
206
|
|
|
207
|
-
The server derives `idempotency_key = sha256({source_session, type, slug})` for every `
|
|
207
|
+
The server derives `idempotency_key = sha256({source_session, type, slug})` for every `fab_propose` call. Re-invoking with the same `(source_session, type, slug)` triple is SAFE: the server appends new evidence to the existing pending file rather than overwriting or producing duplicates — this is why `archive source mode` resume after Ctrl-C / crash never produces duplicate pending entries for already-processed commits.
|
|
208
208
|
|
|
209
|
-
**T5 array-form note (rc.7+)**: when `source_sessions` is passed as an array (rc.7 T5 contract), only `source_sessions[0]` participates in the server-side idempotency hash. Server formula at `packages/server/src/services/extract-knowledge.ts:78` is `sha256(JSON.stringify({source_session: sourceSessions[0], type, slug}))`. Implications for
|
|
209
|
+
**T5 array-form note (rc.7+)**: when `source_sessions` is passed as an array (rc.7 T5 contract), only `source_sessions[0]` participates in the server-side idempotency hash. Server formula at `packages/server/src/services/extract-knowledge.ts:78` is `sha256(JSON.stringify({source_session: sourceSessions[0], type, slug}))`. Implications for archive source mode:
|
|
210
210
|
|
|
211
|
-
- Every Phase 2 call uses `source_sessions: ["fabric-
|
|
212
|
-
- If a future enhancement adds a trailing element (e.g. `["fabric-
|
|
211
|
+
- Every Phase 2 call uses `source_sessions: ["fabric-archive-source-<ISO8601-date>"]` (single-element array, stable per import run). First-element-only rule means re-runs on the same date produce the same idempotency key per `(type, slug)` → resume-safe by construction.
|
|
212
|
+
- If a future enhancement adds a trailing element (e.g. `["fabric-archive-source-<date>", "<commit-sha>"]`), only the first element participates in the hash — the commit-sha tail would NOT change the idempotency key for the same `(type, slug)`. Plan accordingly.
|
|
213
213
|
- The formula is intentionally stable across the rc.5 → rc.7 migration; adding or removing tail entries does NOT change the idempotency key, preserving rc.5 single-session compat.
|
|
@@ -13,7 +13,7 @@ UX i18n Policy class 1 — render either the en variant or the zh-CN variant per
|
|
|
13
13
|
- Commits scanned: <N> (skipped: <S> — cosmetic/metadata/baseline-overlap)
|
|
14
14
|
- Docs scanned: <D> (skipped: <DS> — README/CHANGELOG/boilerplate)
|
|
15
15
|
- Pending proposed: <P> (cap_reached: <true|false>)
|
|
16
|
-
- Scope: all <P> proposed entries use relevance_scope=broad, relevance_paths=[] (
|
|
16
|
+
- Scope: all <P> proposed entries use relevance_scope=broad, relevance_paths=[] (archive source mode contract).
|
|
17
17
|
|
|
18
18
|
## Phase 3 — Dedup
|
|
19
19
|
- Kept (genuinely new): <K>
|
|
@@ -41,7 +41,7 @@ UX i18n Policy class 1 — render either the en variant or the zh-CN variant per
|
|
|
41
41
|
- 扫描 commit 数: <N> (跳过: <S> — cosmetic/metadata/与 baseline 重叠)
|
|
42
42
|
- 扫描文档数: <D> (跳过: <DS> — README/CHANGELOG/样板文件)
|
|
43
43
|
- 提议 pending: <P> (cap_reached: <true|false>)
|
|
44
|
-
- 作用域: 全部 <P> 条提议使用 relevance_scope=broad, relevance_paths=[] (
|
|
44
|
+
- 作用域: 全部 <P> 条提议使用 relevance_scope=broad, relevance_paths=[] (archive source mode 契约)。
|
|
45
45
|
|
|
46
46
|
## Phase 3 — 去重
|
|
47
47
|
- 保留 (新知识): <K>
|
|
@@ -52,7 +52,7 @@ UX i18n Policy class 1 — render either the en variant or the zh-CN variant per
|
|
|
52
52
|
## 状态
|
|
53
53
|
- .fabric/.import-state.json phase: <phase>
|
|
54
54
|
- last_checkpoint_at: <ISO8601>
|
|
55
|
-
- 如 phase != complete, 请重新调用
|
|
55
|
+
- 如 phase != complete, 请重新调用 archive source mode 续作。
|
|
56
56
|
|
|
57
57
|
## 下一步
|
|
58
58
|
- 运行 `fabric-review` 审批 <K> 条新 pending。
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Phase 0 + 0.1 — State Recovery (
|
|
1
|
+
# Phase 0 + 0.1 — State Recovery (archive source mode ref-only)
|
|
2
2
|
|
|
3
3
|
> **Loaded on demand.** Only relevant when a prior import crashed mid-phase, leaving `.tmp-*` residue or a torn `.fabric/.import-state.json`. SKILL.md's hot path inline says "scan for .tmp residue + load state" — this file is the full recovery procedure (atomic-write pattern, sweep rules, corruption detection, fallback to fresh import).
|
|
4
4
|
|
|
@@ -46,7 +46,7 @@ On corruption (any condition above):
|
|
|
46
46
|
1. `Bash: mv .fabric/.import-state.json .fabric/.import-state.json.corrupt-<ISO8601>`
|
|
47
47
|
(preserve the corrupt file for postmortem; do NOT silently overwrite).
|
|
48
48
|
2. Phase 1 restarts from scratch (Phase 1 produces no MCP calls, so re-run
|
|
49
|
-
is safe — re-querying mounted store canonical titles via `
|
|
49
|
+
is safe — re-querying mounted store canonical titles via `fab_pending search`
|
|
50
50
|
idempotent; the `p1_baseline_titles` array is regenerated).
|
|
51
51
|
3. DO NOT attempt automatic partial recovery; corrupt state is a signal
|
|
52
52
|
that something serious happened (disk-full, kill -9 mid-write, fs
|
|
@@ -8,11 +8,11 @@ Source signal: `git log` surfaces commit `50367b5` with subject `feat(server): a
|
|
|
8
8
|
|
|
9
9
|
LLM analysis: this is a **pitfall** (a non-obvious trap that wasted time and is repeatable across services). The body itself documents the trap. Slug candidates: `retry-without-backoff-thundering-herd` (5 words, 38 chars — passes 5 rules).
|
|
10
10
|
|
|
11
|
-
Skill output (note `relevance_scope: "broad"` + `relevance_paths: []` — mandatory for
|
|
11
|
+
Skill output (note `relevance_scope: "broad"` + `relevance_paths: []` — mandatory for archive source mode):
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
|
|
15
|
-
source_sessions: ["fabric-
|
|
14
|
+
mcp__fabric__fab_propose({
|
|
15
|
+
source_sessions: ["fabric-archive-source-2026-05-10"],
|
|
16
16
|
recent_paths: ["packages/server/src/lib/retry.ts"], // provenance only
|
|
17
17
|
user_messages_summary: "重试无指数退避会在短暂上游故障下放大成雪崩。修正:jittered exponential backoff,30 秒上限。src=50367b5",
|
|
18
18
|
type: "pitfalls",
|
|
@@ -29,7 +29,7 @@ Counter-example — DO NOT do this:
|
|
|
29
29
|
```ts
|
|
30
30
|
// WRONG — this skill must never produce narrow + paths from git metadata.
|
|
31
31
|
// The retry pitfall applies to every retry site, not just the file touched by 50367b5.
|
|
32
|
-
|
|
32
|
+
mcp__fabric__fab_propose({
|
|
33
33
|
// ...
|
|
34
34
|
relevance_scope: "narrow", // VIOLATION
|
|
35
35
|
relevance_paths: ["packages/server/src/lib/retry.ts"] // VIOLATION
|
|
@@ -57,8 +57,8 @@ LLM analysis: this is a **decision** (≥2 alternatives weighed — monolith vs
|
|
|
57
57
|
Skill output (broad+[] mandatory; the doc's own path stays in `recent_paths` for provenance, NOT in `relevance_paths`):
|
|
58
58
|
|
|
59
59
|
```ts
|
|
60
|
-
|
|
61
|
-
source_sessions: ["fabric-
|
|
60
|
+
mcp__fabric__fab_propose({
|
|
61
|
+
source_sessions: ["fabric-archive-source-2026-05-10"],
|
|
62
62
|
recent_paths: ["docs/architecture.md"], // provenance only
|
|
63
63
|
user_messages_summary: "选择单体架构而非微服务:3 人团队无法承担多服务运维成本,且主要性能瓶颈在 DB 吞吐而非应用层水平扩展。src=docs/architecture.md",
|
|
64
64
|
type: "decisions",
|
|
@@ -73,7 +73,7 @@ mcp__fabric__fab_extract_knowledge({
|
|
|
73
73
|
After Example A's pending entry (`retry-without-backoff-thundering-herd`) is proposed, Phase 3 runs:
|
|
74
74
|
|
|
75
75
|
```ts
|
|
76
|
-
|
|
76
|
+
mcp__fabric__fab_pending({
|
|
77
77
|
action: "search",
|
|
78
78
|
query: "retry backoff thundering herd",
|
|
79
79
|
filters: { type: "pitfalls" }
|
|
@@ -105,7 +105,7 @@ Final roll-up to user reflects: 1 proposed, 0 kept, 1 rejected_dup, 0 merged, 0
|
|
|
105
105
|
|
|
106
106
|
## Example D — Post-import narrowing (out-of-band, NOT this skill)
|
|
107
107
|
|
|
108
|
-
This example documents the legal narrowing path; it is NOT performed by `
|
|
108
|
+
This example documents the legal narrowing path; it is NOT performed by `archive source mode` itself. After Example B's `monolith-over-microservices-small-team` decision is imported (with `relevance_scope=broad`, `relevance_paths=[]`) and later approved into canonical via `fabric-review`, the user decides the decision is actually narrow to the server package's deploy tooling.
|
|
109
109
|
|
|
110
110
|
The user issues (via `fabric-review`, NOT via this skill):
|
|
111
111
|
|
|
@@ -122,6 +122,6 @@ mcp__fabric__fab_review({
|
|
|
122
122
|
|
|
123
123
|
Key invariants of this flow:
|
|
124
124
|
|
|
125
|
-
- The narrowing decision originates from the **user**, informed by the actual paths they propose — not from `
|
|
126
|
-
- The modify call goes through `fab_review`, not `
|
|
125
|
+
- The narrowing decision originates from the **user**, informed by the actual paths they propose — not from `archive source mode` inferring paths from git metadata.
|
|
126
|
+
- The modify call goes through `fab_review`, not `fab_propose`, because the entry already exists (post-import or post-approval).
|
|
127
127
|
- If the user later flips the entry's layer from `team` to `personal`, server-side auto-degrades scope back to `broad` and clears `relevance_paths` (see rc.5 C3 acceptance criterion; personal knowledge crosses projects so paths don't generalize). This is the only legal way for `relevance_paths` to be re-cleared.
|
|
@@ -11,7 +11,7 @@ Session: User and agent debated whether the Stop-hook should be one .cjs script
|
|
|
11
11
|
Skill output:
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
|
|
14
|
+
mcp__fabric__fab_propose({
|
|
15
15
|
source_sessions: ["WFS-2026-05-10-rc2"],
|
|
16
16
|
recent_paths: ["templates/claude-hooks/", "packages/cli/src/commands/hooks.ts"],
|
|
17
17
|
user_messages_summary: "User pushed back on three-script proposal; agreed single .cjs because stdout JSON shape is universal across Claude Code and Codex CLI.",
|
|
@@ -37,7 +37,7 @@ Session: deepMerge silently replaced the existing `hooks.Stop[]` array in `.clau
|
|
|
37
37
|
Skill output:
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
|
-
|
|
40
|
+
mcp__fabric__fab_propose({
|
|
41
41
|
source_sessions: ["WFS-2026-05-10-rc2"],
|
|
42
42
|
recent_paths: ["packages/cli/src/config/json.ts"],
|
|
43
43
|
user_messages_summary: "deepMerge default behavior REPLACES arrays. hooks.Stop[] needs an array-append-with-dedupe special case keyed on .command string match.",
|
|
@@ -60,7 +60,7 @@ Session: User mentioned across three projects that they prefer 2-space indent in
|
|
|
60
60
|
Skill output:
|
|
61
61
|
|
|
62
62
|
```ts
|
|
63
|
-
|
|
63
|
+
mcp__fabric__fab_propose({
|
|
64
64
|
source_sessions: ["WFS-2026-05-10-rc2"],
|
|
65
65
|
recent_paths: [".editorconfig"],
|
|
66
66
|
user_messages_summary: "Personal indent preference: 2-space TS / 4-space Py. Stable across multiple projects, not project-specific.",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: fabric-review
|
|
3
|
-
description: 审 store-backed pending+canonical knowledge (NOT PR review):
|
|
4
|
-
allowed-tools: Read, Glob, Grep, Bash, Edit, mcp__fabric__fab_review
|
|
3
|
+
description: 审 store-backed pending+canonical knowledge (NOT PR review):pending triage + maintain(含 retire 语义淘汰 + relate 关联建边)。Triggers 审批/review pending;淘汰陈旧/deprecate;连接知识/补 related 边.
|
|
4
|
+
allowed-tools: Read, Glob, Grep, Bash, Edit, mcp__fabric__fab_recall, mcp__fabric__fab_pending, mcp__fabric__fab_review
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
> **Surface**: Skill (AI-driven, per-entry human-judgment routing). See [`docs/surfaces.md`](https://github.com/fenglimg/fabric/blob/main/docs/surfaces.md).
|
|
@@ -25,7 +25,7 @@ This skill is `Infer-not-Ask` for mode and `Ask-when-genuine` for per-item actio
|
|
|
25
25
|
- Per-item action (approve / reject / modify / defer) IS surfaced via AskUserQuestion — the user must judge
|
|
26
26
|
- Layer-flip target (team vs personal) IS surfaced via AskUserQuestion when modify includes layer change
|
|
27
27
|
|
|
28
|
-
Required preconditions before any `fab_review` call: `.fabric/` exists; `mcp__fabric__fab_review` MCP
|
|
28
|
+
Required preconditions before any `fab_review` / `fab_pending` call: `.fabric/` exists; `mcp__fabric__fab_review` (write) + `mcp__fabric__fab_pending` (read) MCP tools registered; a write store is resolved for mutations; `.fabric/events.jsonl` exists (tolerate ENOENT — empty ledger normal first-run).
|
|
29
29
|
|
|
30
30
|
### Config Load
|
|
31
31
|
|
|
@@ -42,13 +42,13 @@ Missing or unreadable → defaults silently.
|
|
|
42
42
|
|
|
43
43
|
### Store routing (v2.1 multi-store)
|
|
44
44
|
|
|
45
|
-
Review iterates **per-store** — the read-set may span multiple stores (`fabric scope
|
|
45
|
+
Review iterates **per-store** — the read-set may span multiple stores (`fabric info scope team` → resolved `readSet.stores`). Pending/backlog is reported per-store (NOT aggregated into one undifferentiated pile); each candidate's provenance store is surfaced in cites as `KB: <store-alias>:<id>`. Promotion (draft → verified/proven) is a normal edit + git commit **inside that store's own repo** — no cross-store move. A `dismissed`/`modify` that flips layer between team and personal still goes through `AskUserQuestion`. Never read `~/.fabric` store trees directly; go through the MCP recall path / `fabric info scope`.
|
|
46
46
|
|
|
47
47
|
`Read ref/cite-contract.md` (v2.2 SK5) for the authoritative cite-contract reference — operator syntax, skip/dismissed reason dictionaries, type routing, audit semantics, backward-compat, and the adjudication ladder (AI-self → multi-LLM cold-eval → non-blocking queue) — sunk out of the bootstrap so cite/governance depth lives here, not in `.fabric/AGENTS.md`.
|
|
48
48
|
|
|
49
49
|
### UX i18n Policy
|
|
50
50
|
|
|
51
|
-
Read `fabric_language` (`zh-CN` / `en` / `zh-CN-hybrid` / `match-existing`); emit user-facing prose in resolved variant. Protected tokens (`fab_review`, `
|
|
51
|
+
Read `fabric_language` (`zh-CN` / `en` / `zh-CN-hybrid` / `match-existing`); emit user-facing prose in resolved variant. Protected tokens (`fab_review`, `fab_pending`, `fab_propose`, `relevance_scope`, layer/scope enums, `stable_id`, the verbatim `强 team` / `强 personal` / `默认 team` block) NEVER translated. `AskUserQuestion` policy: `header` + `question` translate; `options[]` stay English (routing keys).
|
|
52
52
|
|
|
53
53
|
`Read ref/i18n-policy.md` for the full 5-class taxonomy + edge cases.
|
|
54
54
|
|
|
@@ -59,7 +59,7 @@ Read `fabric_language` (`zh-CN` / `en` / `zh-CN-hybrid` / `match-existing`); emi
|
|
|
59
59
|
|
|
60
60
|
The skill MUST infer one of **2 modes** BEFORE any user-facing output (v2.0.0-rc.37 NEW-12 simplified 4 → 2):
|
|
61
61
|
|
|
62
|
-
- **`pending`** — triage the write-side backlog returned by `
|
|
62
|
+
- **`pending`** — triage the write-side backlog returned by `fab_pending action="list"` (`pending_path` identifies each store-backed entry): approve / reject / modify / defer per item via `fab_review`. The dominant entry point.
|
|
63
63
|
- **`maintain`** — sustain the EXISTING canonical KB: browse by topic (search), survey staleness/health, or revisit a specific entry. Merges the legacy `topic` + `health` + `revisit` modes — they are all "operate on already-canonical knowledge", distinct from triaging new drafts.
|
|
64
64
|
|
|
65
65
|
### 2-Step Inference Algorithm
|
|
@@ -69,11 +69,13 @@ The skill MUST infer one of **2 modes** BEFORE any user-facing output (v2.0.0-rc
|
|
|
69
69
|
| Keywords (zh-CN + en) | Inferred mode |
|
|
70
70
|
|---|---|
|
|
71
71
|
| "approve", "review pending", "promote", "what's queued", "审核 pending", "通过" | `pending` |
|
|
72
|
-
| "search/find about <topic>", "what's stale", "demote old", "health check", "look at <id>", "revisit KT-…", "关于…的知识", "过期的", "陈旧的", "整理一下", "再看下 <id>", "回顾" | `maintain` |
|
|
72
|
+
| "search/find about <topic>", "what's stale", "demote old", "health check", "look at <id>", "revisit KT-…", "关于…的知识", "过期的", "陈旧的", "整理一下", "再看下 <id>", "回顾" | `maintain` (browse/health/revisit) |
|
|
73
|
+
| "审计知识库", "清理陈旧知识", "知识库瘦身", "淘汰旧决策", "deprecate", "prune stale", "这些旧决策还要吗" | `maintain` → **retire** sub-flow |
|
|
74
|
+
| "连接知识", "找相关条目", "补 related 边", "知识库连通性", "link related", "建知识图谱" | `maintain` → **relate** sub-flow |
|
|
73
75
|
|
|
74
76
|
A `maintain`-row match → lock `maintain`. A `pending`-row match (or 0/ambiguous) → fall to Step 2.
|
|
75
77
|
|
|
76
|
-
**Step 2 — Backlog default.** Call `
|
|
78
|
+
**Step 2 — Backlog default.** Call `fab_pending action="list"` and inspect returned `items[].pending_path`:
|
|
77
79
|
|
|
78
80
|
- Count ≥ `review_hint_pending_count` (default 10) OR oldest mtime > `review_hint_pending_age_days` (default 7) → `pending` (overflow, same threshold as Stop-hook).
|
|
79
81
|
- Otherwise → default `pending` (most common review entry point).
|
|
@@ -91,9 +93,11 @@ Each mode produces user-facing output, then routes per-item or per-batch decisio
|
|
|
91
93
|
- `fab_review action="modify-layer"` — the dedicated layer-flip path (`changes.layer` required); may reallocate the stable_id + emit an id-redirect.
|
|
92
94
|
- (Legacy `action="modify"` still works — it routes by whether `changes.layer` is present.) See `ref/modify-flow.md`.
|
|
93
95
|
- **`maintain`** — sub-flow inferred from the same keywords:
|
|
94
|
-
- *browse-by-topic*: extract keywords → `
|
|
95
|
-
- *health/staleness*: `
|
|
96
|
-
- *revisit*: user referenced a specific id/slug → `Read` canonical file directly OR `
|
|
96
|
+
- *browse-by-topic*: extract keywords → `fab_pending action="search"` → render top-N (cap `review_topic_result_cap`) → AskUserQuestion only on an action verb.
|
|
97
|
+
- *health/staleness*: `fab_pending action="list"` + tail events → compute stale → render dashboard → per-stale AskUserQuestion `{defer, demote, skip}`.
|
|
98
|
+
- *revisit*: user referenced a specific id/slug → `Read` canonical file directly OR `fab_pending action="list"` with narrow filters → display body + history → AskUserQuestion only if actionable.
|
|
99
|
+
- *retire* (W3-C, 吸收原 fabric-audit): 语义淘汰陈旧/孤儿/被取代的 **canonical** 条目。引擎 `fabric doctor`(给 orphan/stale/health 信号);守两条红线 **deprecate-over-delete**(陈旧≠该删,降 maturity / 标 `superseded-by` 保留 rationale)+ **rescue-before-delete**(删前必做独特-rationale 抢救检查)。逐条判三态 still-valid / superseded(deprecate)/ never-valid(rescue 后删空壳),处置经 `fab_review` 写路径落盘。**完整两条红线定义 / 意图→动作映射 / 三态流程 / scope 纠偏 → `Read ref/retire-mode.md`。**
|
|
100
|
+
- *relate* (W3-C, 吸收原 fabric-connect): **默认不主动建边**,仅用户显式「连一下 / 补 related」时进入。`fab_recall` 拿候选 + 现有 `related` → 按互补/规避/取代/同域/引用链判**高置信**隐藏关联(稀疏优于稠密)→ 落盘**复用 `fab_review` modify 写路径**(零新写面,追加源条目 `related` 数组)。§4 隐私铁律 `KT→KP` FORBIDDEN。**关联类型判据表 / 流程 / 约束 → `Read ref/relate-mode.md`。**
|
|
97
101
|
|
|
98
102
|
`Read ref/per-mode-flows.md` for full step-by-step procedures, bilingual rendering blocks (en + zh-CN per-item display, AskUserQuestion templates, health dashboard format), and the rc.7 T6 `proposed_reason` + `## Why proposed` + `## Session context` rendering contract.
|
|
99
103
|
|
|
@@ -101,7 +105,7 @@ Each mode produces user-facing output, then routes per-item or per-batch decisio
|
|
|
101
105
|
|
|
102
106
|
> Boundary B (locked): "extraction / classification / layer / slug / mode / **semantic dedup** → Skill (LLM); file write / frontmatter / idempotency / counter / layer-flip / atomic promote → MCP (deterministic)"
|
|
103
107
|
|
|
104
|
-
Semantic check is the LLM's job — the MCP tool does NOT compare meaning. Run during `pending` mode (and on demand during `topic`): for each pending entry, `
|
|
108
|
+
Semantic check is the LLM's job — the MCP tool does NOT compare meaning. Run during `pending` mode (and on demand during `topic`): for each pending entry, `fab_pending action="search"` scoped by `filters.type` → LLM judges semantically against returned canonical entries → surface one of three flags as informational:
|
|
105
109
|
|
|
106
110
|
- `⚠ Possible duplicate of <stable_id> (overlap: high)` — same essential claim
|
|
107
111
|
- `⚠ Contradicts <stable_id> (overlap: high)` — opposing claims, same scope
|
|
@@ -135,7 +139,7 @@ Guideline/model entries surface in the SessionStart **ALWAYS-ACTIVE** sink as a
|
|
|
135
139
|
- **Title/summary/tags/maturity** → in-place rewrite; stable_id PRESERVED.
|
|
136
140
|
- **Layer change** → ONLY legal stable_id mutation. BEFORE call, AskUserQuestion `{team, personal}` to confirm target (this IS genuine choice). AFTER server returns, surface BOTH `prior_stable_id` and `new_stable_id` in roll-up — downstream agents may cache the prior id.
|
|
137
141
|
|
|
138
|
-
**
|
|
142
|
+
**Source-mode entries** (`source_sessions[0]` starts with `fabric-archive-source-`) ship with `relevance_scope=broad + relevance_paths=[]` by design; narrowing is fabric-review's responsibility. Render `⚠ Imported (relevance_scope=broad, relevance_paths=[]) — pick 'modify' + say 'narrow to <paths>'` as informational hint. On `modify` of import-origin: extended option list `{narrow scope, edit summary, change layer, change maturity, skip}`; "narrow scope" → free-text follow-up → `changes: { relevance_scope: "narrow", relevance_paths: [<parsed>] }`. Personal layer auto-degrades narrow → broad+[] (server-side), emitting `knowledge_scope_degraded`.
|
|
139
143
|
|
|
140
144
|
`Read ref/modify-flow.md` for layer-flip server transaction (4-step), modify call shape examples (maturity bump / layer flip), and full narrowing flow with bilingual AskUserQuestion templates.
|
|
141
145
|
|
|
@@ -180,11 +184,11 @@ Pending entry presented for review
|
|
|
180
184
|
|
|
181
185
|
- NEVER write a knowledge file directly via Edit/Write/Bash; the only legal mutation path is `mcp__fabric__fab_review`.
|
|
182
186
|
- NEVER call `git mv` from this skill — layer flip and slug rename are server-side transactions.
|
|
183
|
-
- NEVER invent an `action` value — `action` MUST be one of {`
|
|
187
|
+
- NEVER invent an `action` value — `fab_review action` MUST be one of {`approve`, `reject`, `modify`, `modify-content`, `modify-layer`, `defer`} (write-only); read actions {`list`, `search`} go through the read-only `fab_pending` tool.
|
|
184
188
|
- NEVER batch heterogeneous decisions into a single MCP call. Approve and reject MAY be batched within their own action; modify MUST be one call per entry.
|
|
185
189
|
- NEVER invoke `fab_review action="approve"` without at least one `pending_paths` entry.
|
|
186
190
|
- NEVER infer a layer-flip target — the user MUST choose via AskUserQuestion.
|
|
187
|
-
- MUST preserve protected tokens exactly: `stable_id`, `pending_path`, `layer`, `team`, `personal`, `knowledge_promoted`, `knowledge_layer_changed`, `knowledge_proposed`, `knowledge_scope_degraded`, `fab_review`, `MUST`, `NEVER`, `relevance_scope`, `relevance_paths`, `narrow`, `broad`, `proposed_reason`, `session_context`.
|
|
191
|
+
- MUST preserve protected tokens exactly: `stable_id`, `pending_path`, `layer`, `team`, `personal`, `knowledge_promoted`, `knowledge_layer_changed`, `knowledge_proposed`, `knowledge_scope_degraded`, `fab_review`, `fab_pending`, `MUST`, `NEVER`, `relevance_scope`, `relevance_paths`, `narrow`, `broad`, `proposed_reason`, `session_context`.
|
|
188
192
|
|
|
189
193
|
## Output Contract & events.jsonl Constraint (ref-only)
|
|
190
194
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Cite-contract + 裁决阶梯参考 (v2.2 SK5)
|
|
2
2
|
|
|
3
|
-
> 本文是 cite policy 与裁决(adjudication)的**权威详参**,从 bootstrap (`.fabric/AGENTS.md`) 下沉至此,避免 bootstrap 随治理细节膨胀。bootstrap 只留**可执行 core**(cite 行格式 + 验证义务 + operator 例),完整 enum 词典 / 类型路由 / 稽核 / backward-compat / 裁决阶梯看这里。`fabric
|
|
3
|
+
> 本文是 cite policy 与裁决(adjudication)的**权威详参**,从 bootstrap (`.fabric/AGENTS.md`) 下沉至此,避免 bootstrap 随治理细节膨胀。bootstrap 只留**可执行 core**(cite 行格式 + 验证义务 + operator 例),完整 enum 词典 / 类型路由 / 稽核 / backward-compat / 裁决阶梯看这里。`fabric audit cite` 的稽核口径以本文为准。
|
|
4
4
|
|
|
5
5
|
## 1. Cite 行格式 (回顾)
|
|
6
6
|
|
|
@@ -42,7 +42,7 @@ cite 尾段加 contract:`→ <operator> [<operator> ...]`
|
|
|
42
42
|
|
|
43
43
|
## 5. 稽核 + Backward compat
|
|
44
44
|
|
|
45
|
-
- 稽核:`fabric
|
|
45
|
+
- 稽核:`fabric audit cite [--since=7d] [--client=cc|codex|all]` 输出覆盖率,含 `KB: none` sentinel 拆分。不阻断工作,只记录。
|
|
46
46
|
- Backward compat:解析器同时接受老 4-state tags(`planned` / `recalled` / `chained-from <id>`),都映射到 `[applied]` 语义;旧 session cite 仍计入 cite-coverage。
|
|
47
47
|
|
|
48
48
|
## 6. 裁决阶梯 (adjudication ladder)
|
|
@@ -49,13 +49,25 @@ mcp__fabric__fab_review({
|
|
|
49
49
|
|
|
50
50
|
---
|
|
51
51
|
|
|
52
|
+
## Promotion Gate — verified → proven (v2.2 C1)
|
|
53
|
+
|
|
54
|
+
`maturity` promotion to `proven` is the foundational tier and runs a 3-part gate from `processes/maturity-promotion-rubric-v1`. The doctor `knowledge_broad_review_recheck`-adjacent `promotion_candidate` lint only SURFACES candidates (verified entries with `related` in-degree ≥3); the SUFFICIENT judgment lives here in review.
|
|
55
|
+
|
|
56
|
+
Before issuing `fab_review modify ... { maturity: "proven" }`, satisfy all three:
|
|
57
|
+
|
|
58
|
+
1. **0 dismiss (NECESSARY — server-enforced).** The server REFUSES the verified→proven modify when the entry carries an unresolved dismissed cite (latest `assistant_turn_observed` verdict for its id is `dismissed`, last-write-wins). You do NOT need to pre-check this — the modify throws with an actionable message. To clear it, the entry must be re-affirmed (a later `applied` cite) or the objection addressed. Do not work around the block; resolving it IS the gate.
|
|
59
|
+
2. **guideline/model summary cold-eval (NECESSARY for those two types).** For `guidelines`/`models`, run the zero-context self-sufficiency judge before promoting: build the batch with `summary-cold-eval.buildColdEvalBatch([{stable_id, summary}])` + `COLD_EVAL_RUBRIC`, hand it to a `maestro delegate` cold judge (body WITHHELD), and only proceed if `self_sufficient=true`. A FAIL means the summary only points at the body — fix the summary (modify) first, then re-judge. (decisions/pitfalls/processes skip this — they are reference, not always-active rules.)
|
|
60
|
+
3. **Foundational affirmation (SUFFICIENT — human).** Surface AskUserQuestion confirming the reviewer judges the entry "foundational / load-bearing", not merely correct. Promotion to proven is a standing-rule claim; the human makes it.
|
|
61
|
+
|
|
62
|
+
Only after 1–3 hold, call `fab_review action="modify-content" changes={ maturity: "proven" }`. The modify itself stamps `last_review_confirmed_at` (every approve/modify is a review re-confirmation — this also resets the broad review-recheck clock).
|
|
63
|
+
|
|
52
64
|
## Narrowing Imported Entries
|
|
53
65
|
|
|
54
66
|
The fabric-import skill creates pending entries with `relevance_scope=broad` + `relevance_paths=[]` as a deliberate contract — it cannot derive paths from git history. **Narrowing imported entries is fabric-review's responsibility.**
|
|
55
67
|
|
|
56
68
|
### Detection
|
|
57
69
|
|
|
58
|
-
An entry is "import-origin" when `source_sessions[0]` starts with `fabric-
|
|
70
|
+
An entry is "import-origin" when `source_sessions[0]` starts with `fabric-archive-source-` (e.g. `fabric-archive-source-2026-05-10`).
|
|
59
71
|
|
|
60
72
|
### Pending mode rendering
|
|
61
73
|
|
|
@@ -6,9 +6,9 @@ Full bilingual rendering blocks + step-by-step procedures for the four modes ref
|
|
|
6
6
|
|
|
7
7
|
## Mode: pending — Approve / Reject / Modify Backlog
|
|
8
8
|
|
|
9
|
-
1. Call `
|
|
9
|
+
1. Call `fab_pending` with `action: "list"`, no filters (or `filters.layer="both"` if user explicitly mentioned both layers).
|
|
10
10
|
2. Server returns `items[]` (each = `{pending_path, type, layer, maturity, tags?, title?, summary?}`).
|
|
11
|
-
3. Before presenting, perform **Semantic Check** (see `ref/semantic-check.md`) by issuing one or more `action
|
|
11
|
+
3. Before presenting, perform **Semantic Check** (see `ref/semantic-check.md`) by issuing one or more `fab_pending action="search"` calls scoped by `filters.type` to surface possible duplicates / contradictions among already-canonical entries.
|
|
12
12
|
4. For each pending item, render a per-item block. v2.0.0-rc.7 T6: render `proposed_reason` (frontmatter) + `## Why proposed` line (body, 1-line enum explanation) + first line of `## Session context` so future-self has full context without re-reading the transcript. UX i18n Policy class 1 — roll-up templates; protected tokens (`pending_path`, `layer`, `team`, `decisions`, `proposed_reason`, `Tags`, etc.) appear verbatim in BOTH variants:
|
|
13
13
|
|
|
14
14
|
**en variant** (`fabric_language === "en"`):
|
|
@@ -74,7 +74,7 @@ Full bilingual rendering blocks + step-by-step procedures for the four modes ref
|
|
|
74
74
|
## Mode: topic — Search & Surface Findings
|
|
75
75
|
|
|
76
76
|
1. Extract the topic keyword(s) from the user's message (e.g. "find about deepMerge" → query="deepMerge").
|
|
77
|
-
2. Call `
|
|
77
|
+
2. Call `fab_pending action="search"` with `query` and any obvious filters (if user said "team-only" → `filters.layer="team"`).
|
|
78
78
|
3. Server returns `items[]` ranked by relevance — these are entries already in mounted store `knowledge/<type>/` (NOT pending), unless `filters` says otherwise.
|
|
79
79
|
4. Render top-N (cap at `review_topic_result_cap`, config-resolved, default 8) results with title / summary / pending_path.
|
|
80
80
|
5. If the user follow-up indicates intent to act ("approve all", "modify the second one"), pivot into the corresponding pending mode action — the search result already gives the `pending_path` needed for the action.
|
|
@@ -84,7 +84,7 @@ Full bilingual rendering blocks + step-by-step procedures for the four modes ref
|
|
|
84
84
|
|
|
85
85
|
## Mode: health — Corpus Health & Stale Detection
|
|
86
86
|
|
|
87
|
-
1. Call `
|
|
87
|
+
1. Call `fab_pending action="list"` with `filters.maturity="draft"` (or no filter for full corpus inspection).
|
|
88
88
|
2. Tail `.fabric/events.jsonl` for layer_changed / demoted / rejected counts in the trailing 30 days.
|
|
89
89
|
3. Compute stale candidates: pending entries with mtime older than `review_stale_pending_days` (config-resolved, default 14) OR maturity=draft entries with no recent evidence-append events.
|
|
90
90
|
4. Render a corpus dashboard. UX i18n Policy class 1 — roll-up templates; render per `fabric_language`:
|
|
@@ -134,7 +134,7 @@ Full bilingual rendering blocks + step-by-step procedures for the four modes ref
|
|
|
134
134
|
## Mode: revisit — Specific Entry Deep Dive
|
|
135
135
|
|
|
136
136
|
1. The user referenced a specific entry (by id `KT-D-7` or by slug `single-cjs-hook`).
|
|
137
|
-
2. Call `
|
|
137
|
+
2. Call `fab_pending action="list"` with `filters` narrowed by best-guess fields; if the entry is canonical (has stable_id), use the path returned by `fab_pending` instead of inventing a store path.
|
|
138
138
|
3. Display the full body (frontmatter + content). Tail the events.jsonl for any history events tagged with this stable_id.
|
|
139
139
|
4. Surface AskUserQuestion `{options: ["approve", "modify", "reject", "skip"]}` only if the entry is still pending; for canonical entries the only mutation path is `modify` (incl. layer flip).
|
|
140
140
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Relate sub-flow — 知识图谱关联 (W3-C: 吸收原 fabric-connect)
|
|
2
|
+
|
|
3
|
+
`maintain` 模式的 **relate** 子流程:把孤立的 canonical 条目连成图,发现彼此**隐藏关联**(同一决策的正反面、pitfall↔规避它的 guideline、被取代↔取代),回写 frontmatter 的 `related: [<stable_id>...]` 图边(v2.2 H2)。下游 `fab_recall include_related:true` 据此一跳拉回连通知识。
|
|
4
|
+
|
|
5
|
+
`related` 是**有向引用**(A.related=[B] 表示「读 A 时也该看 B」),按需补反向边。
|
|
6
|
+
|
|
7
|
+
**默认不主动建边**:仅用户显式说「连一下 / 找相关条目 / 补 related 边 / 知识库连通性」时进入;不在任何 nudge 里主动提议(避免噪声边稀释图价值)。检索时临时拉关联直接 `fab_recall include_related:true`,无需建边。
|
|
8
|
+
|
|
9
|
+
## 关联类型(提议 related 边的判据)
|
|
10
|
+
|
|
11
|
+
| 类型 | 例 |
|
|
12
|
+
|---|---|
|
|
13
|
+
| 互补 | decision「用 JWT」 ↔ pitfall「JWT 过期未刷新踩坑」 |
|
|
14
|
+
| 规避 | pitfall「sprite 黑边」 ↔ guideline「premultiplyAlpha 正确设置」 |
|
|
15
|
+
| 取代 | 旧 decision ↔ 取代它的新 decision(配合 deprecated/superseded-by) |
|
|
16
|
+
| 同域 | 同一子系统 / 共 relevance_paths 的条目 |
|
|
17
|
+
| 引用链 | A 的 rationale 依赖 B 的结论 |
|
|
18
|
+
|
|
19
|
+
## 流程
|
|
20
|
+
|
|
21
|
+
1. `fab_recall(paths=[...])` 拿候选 + 现有 `related`(读 description.related 看已连状态)。
|
|
22
|
+
2. 对候选两两/成簇判隐藏关联(用上表判据);只提议**高置信**边,不为「话题相邻」乱连。
|
|
23
|
+
3. 每条提议 = `(源 id, 目标 id, 类型, 一句理由)`;按需提议反向边。
|
|
24
|
+
4. 落盘**复用既有 `fab_review` modify 写路径**(零新写面):在源条目 frontmatter 的 `related` inline 数组追加目标 stable_id;`fabric doctor --fix` reconcile 进 agents.meta。
|
|
25
|
+
5. 回报新增/反向边数 + 连通性变化(孤岛减少)。
|
|
26
|
+
|
|
27
|
+
## Constraints
|
|
28
|
+
|
|
29
|
+
- 本子流程**只提议 + 经 `fab_review` modify 写路径落盘**;不自行改 store `knowledge/`,不手改 store counters(派生态)。
|
|
30
|
+
- `related` MUST 只填**真实存在的 stable_id**(先 `fab_recall` 验证目标在库);NEVER 编造 / 指向 pending。
|
|
31
|
+
- **稀疏优于稠密**:宁缺毋滥。只连高置信关联;低置信「相邻」不连(信噪比 > 覆盖率)。
|
|
32
|
+
- 反向边按需补,不强制双向(有向语义:A 该带出 B ≠ B 该带出 A)。
|
|
33
|
+
- **§4 隐私铁律**:`KT→KP` FORBIDDEN(team 条目 MUST NOT 指向 personal id);不确定目标是否 personal 时 OMIT 该边。
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Retire sub-flow — 语义淘汰 canonical 条目 (W3-C: 吸收原 fabric-audit)
|
|
2
|
+
|
|
3
|
+
`maintain` 模式的 **retire** 子流程:把陈旧 / 孤儿 / 被取代的 **已 canonical** 条目按语义淘汰收口 —— 而不是一删了之。引擎是 `fabric doctor`(跑 lint、算 health、给 orphan/stale 信号);本子流程按用户意图挑动作,守两条红线,落盘仍走 `fab_review` 写路径(单一写路径,不自改 store `knowledge/`)。
|
|
4
|
+
|
|
5
|
+
写新条目用 default archive;批量审 pending 用 `pending` 模式;retire 专管 **已归档条目的退役**。
|
|
6
|
+
|
|
7
|
+
## 进入 retire 子流程
|
|
8
|
+
|
|
9
|
+
`maintain` 关键词命中「审计 / 体检知识库」「清理陈旧知识」「这些旧决策还要吗」「知识库瘦身」「淘汰旧决策」「deprecate 条目」,或 doctor 报了 orphan/stale/低 health 想逐条处置时。
|
|
10
|
+
|
|
11
|
+
## 两条红线(NON-NEGOTIABLE)
|
|
12
|
+
|
|
13
|
+
1. **deprecate-over-delete**:陈旧 ≠ 该删。一条「当时为什么这么决策」的 decision/pitfall 即使方案已换,其 rationale 仍是知识。退役 = 降 maturity(proven→verified→draft)/ 标 `deprecated` + 记 `superseded-by`(保留正文),而非 `rm`。删除只用于「从未成立 / 纯噪声 / 重复」的条目。
|
|
14
|
+
2. **rescue-before-delete**:任何 *打算删* 的条目,删前必做抢救检查 —— 它是否携带别处没有的独特 rationale / 反例 / 边界?有则先 merge 进取代它的条目(或在新条目加 `related` 边指回),再删空壳。抢救检查没做过,不许删。
|
|
15
|
+
|
|
16
|
+
## 意图 → 动作映射
|
|
17
|
+
|
|
18
|
+
| 意图 | 动作 |
|
|
19
|
+
|---|---|
|
|
20
|
+
| 体检 / 健康度 | `fabric doctor`(读 lint + health rollup);零阻断,只报告 |
|
|
21
|
+
| 找孤儿 / 陈旧条目 | `fabric doctor`(消费 orphan / stale / orphan-demote 信号) |
|
|
22
|
+
| 退役一条陈旧条目 | **不删** → 降 maturity 或标 deprecated + `superseded-by`;经 `fab_review` 落盘 |
|
|
23
|
+
| 删一条「从未成立 / 重复」条目 | 先跑 rescue 检查(独特 rationale?有则 merge/加 related);确认空壳后才删 |
|
|
24
|
+
| 被取代但有价值 | rescue:把独特 rationale merge 进取代条目,新条目加 `related` 边指回,再退役旧条目 |
|
|
25
|
+
|
|
26
|
+
## 流程(逐条处置)
|
|
27
|
+
|
|
28
|
+
1. `fabric doctor` 取 KB health + orphan/stale 候选清单(引擎给信号,不自算)。
|
|
29
|
+
2. 对每个候选判 **三态**:still-valid(留) / superseded(退役,走 deprecate) / never-valid(删,走 rescue 检查)。
|
|
30
|
+
3. superseded → deprecate:降 maturity 或标 deprecated + `superseded-by`,保留正文 rationale。
|
|
31
|
+
4. never-valid → rescue-before-delete:独特知识?有则 merge + `related`,无则删空壳。
|
|
32
|
+
5. 处置经 `fab_review` 写路径落盘(本子流程给决策,fab_review 做写入),保持单一写路径。
|
|
33
|
+
|
|
34
|
+
## Scope re-assignment(迁移 / backfill 后纠偏)
|
|
35
|
+
|
|
36
|
+
`fabric store migrate backfill` 给老条目补 `semantic_scope`,**默认把所有 team-layer 条目标成 `semantic_scope: team`** —— over-broad 的保守默认,会让项目专属知识错误暴露给所有项目。纠偏:
|
|
37
|
+
|
|
38
|
+
- **team-scope 判定测试**:「换一个**没有本 app 代码**的不同 repo,这条知识还成立吗?」—— 成立才是 `team`。app **内部**跨功能 / 跨玩法复用的共享组件(同一 app 多处用)**≠ team**,仍是 `project:<id>`(跨玩法复用 ≠ 跨项目复用,如 VoiceRoom)。
|
|
39
|
+
- **纠偏动作**:`fabric store migrate scope <store> --to project:<id> --id <id>`。
|
|
40
|
+
- 完整判定树 / worked examples 见单一真源:`fabric-archive/ref/phase-3-7-semantic-scope.md`。
|
|
41
|
+
|
|
42
|
+
## Constraints
|
|
43
|
+
|
|
44
|
+
- 本子流程**只读 + 给处置建议**;实际写入(降级 / 标记 / 删)经 `fab_review` 写路径,不自行改 store `knowledge/`。
|
|
45
|
+
- NEVER 绕过 rescue 检查直接删;删前 MUST 先跑抢救。删是最后手段,默认 deprecate。
|
|
46
|
+
- store counters 派生态严禁手改;退役改的是 markdown frontmatter(maturity / deprecated / superseded-by),再 `fabric doctor --fix` reconcile。
|
|
47
|
+
- health / orphan / stale 一律取自 `fabric doctor` JSON 输出,不在 skill 内重算(单一真源)。
|
|
@@ -10,7 +10,7 @@ Semantic check is the LLM's job — the MCP tool does NOT compare meaning.
|
|
|
10
10
|
|
|
11
11
|
For each pending entry to be presented:
|
|
12
12
|
|
|
13
|
-
1. Call `
|
|
13
|
+
1. Call `fab_pending action="search"` with `query=<title or summary keywords>` and `filters.type=<same type>` to fetch already-canonical entries of the same type.
|
|
14
14
|
2. Compare semantically (LLM judgment, not string match). 三类判断均为 LLM 主观判断 dup/subsumption;具体阈值不可量化(不使用百分比 / 相似度数值伪精度):
|
|
15
15
|
- **Duplicate** — same essential claim. 标题与摘要表达同一核心结论,pending 未提供新证据或新上下文。Flag: `⚠ Possible duplicate of <stable_id>`.
|
|
16
16
|
- **Contradiction** — opposing claims about the same subject. 例:一个 entry 说 "use X",pending 说 "avoid X",且作用域一致。Flag: `⚠ Contradicts <stable_id>`.
|
|
@@ -12,8 +12,8 @@ Inferred mode: `pending` (Step 1 keyword "review … pending").
|
|
|
12
12
|
|
|
13
13
|
Skill flow:
|
|
14
14
|
|
|
15
|
-
1. `
|
|
16
|
-
2. Semantic check on item 2 (`pending/decisions/single-cjs-hook.md`) — `
|
|
15
|
+
1. `fab_pending action="list"` → returns 3 pending items.
|
|
16
|
+
2. Semantic check on item 2 (`pending/decisions/single-cjs-hook.md`) — `fab_pending action="search"` with `query="single cjs hook"` filter `type=decisions` returns canonical `KT-D-0007--single-cjs-hook-across-clients.md` (similarity high).
|
|
17
17
|
3. Display block:
|
|
18
18
|
|
|
19
19
|
```md
|
|
@@ -36,7 +36,7 @@ Inferred mode: `revisit` (Step 1 keyword "look at <id>").
|
|
|
36
36
|
|
|
37
37
|
Skill flow:
|
|
38
38
|
|
|
39
|
-
1. Read the canonical path returned by `
|
|
39
|
+
1. Read the canonical path returned by `fab_pending search` for `KT-G-0003`. Display body to user.
|
|
40
40
|
2. AskUserQuestion `{options: ["approve", "modify", "reject", "skip"]}` — user picks `modify`.
|
|
41
41
|
3. Skill detects user-stated intent "actually personal not team" — surface AskUserQuestion `{options: ["team", "personal"]}` with current layer=team noted; user confirms `personal`.
|
|
42
42
|
4. Call:
|
|
@@ -60,7 +60,7 @@ Inferred mode: `health` (Step 1 keyword "stale").
|
|
|
60
60
|
|
|
61
61
|
Skill flow:
|
|
62
62
|
|
|
63
|
-
1. `
|
|
63
|
+
1. `fab_pending action="list"` (no filter) + tail events.jsonl for trailing-30d demoted/layer_changed counts.
|
|
64
64
|
2. Compute stale candidates: 3 pending entries with mtime >14d (KP-G-5 candidate-pending, KT-P-9 candidate-pending, KP-G-3 canonical draft with no evidence-append in 21d).
|
|
65
65
|
3. Render dashboard then loop per stale item.
|
|
66
66
|
4. Per-item AskUserQuestion fires:
|
|
@@ -74,7 +74,7 @@ Skill flow:
|
|
|
74
74
|
User: "review the pending knowledge".
|
|
75
75
|
|
|
76
76
|
Inferred mode: `pending`. Skill lists 5 pending entries; entry 3's frontmatter
|
|
77
|
-
shows `source_sessions[0] = "fabric-
|
|
77
|
+
shows `source_sessions[0] = "fabric-archive-source-2026-05-10"` → import-origin.
|
|
78
78
|
|
|
79
79
|
Display block prepends warning line. User picks `modify` on entry 3.
|
|
80
80
|
AskUserQuestion fires with extended options including `narrow scope`.
|