@fenglimg/fabric-cli 2.0.0-rc.35 → 2.0.0-rc.36

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/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import { defineCommand, runMain } from "citty";
11
11
 
12
12
  // src/commands/index.ts
13
13
  var allCommands = {
14
- install: () => import("./install-HOTE5BPA.js").then((module) => module.default),
14
+ install: () => import("./install-XSUIX6AD.js").then((module) => module.default),
15
15
  doctor: () => import("./doctor-2FCRAWDZ.js").then((module) => module.default),
16
16
  serve: () => import("./serve-43JTEM3U.js").then((module) => module.default),
17
17
  uninstall: () => import("./uninstall-BIJ5GLEU.js").then((module) => module.default),
@@ -26,7 +26,7 @@ var allCommands = {
26
26
  var main = defineCommand({
27
27
  meta: {
28
28
  name: "fabric",
29
- version: "2.0.0-rc.35",
29
+ version: "2.0.0-rc.36",
30
30
  description: t("cli.main.description")
31
31
  },
32
32
  subCommands: allCommands
@@ -1351,7 +1351,7 @@ function readProjectName(target) {
1351
1351
  return basename(target);
1352
1352
  }
1353
1353
  function getCliVersion() {
1354
- return true ? "2.0.0-rc.35" : "unknown";
1354
+ return true ? "2.0.0-rc.36" : "unknown";
1355
1355
  }
1356
1356
  function sortRecord(record) {
1357
1357
  return Object.fromEntries(Object.entries(record).sort(([left], [right]) => left.localeCompare(right)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fenglimg/fabric-cli",
3
- "version": "2.0.0-rc.35",
3
+ "version": "2.0.0-rc.36",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "fabric": "dist/index.js"
@@ -19,8 +19,8 @@
19
19
  "tree-sitter-javascript": "^0.25.0",
20
20
  "tree-sitter-typescript": "^0.23.2",
21
21
  "web-tree-sitter": "^0.26.8",
22
- "@fenglimg/fabric-server": "2.0.0-rc.35",
23
- "@fenglimg/fabric-shared": "2.0.0-rc.35"
22
+ "@fenglimg/fabric-server": "2.0.0-rc.36",
23
+ "@fenglimg/fabric-shared": "2.0.0-rc.36"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@types/node": "^22.15.0",
@@ -4,232 +4,144 @@ description: 冷启动从 git log + docs/*.md 回灌 .fabric/knowledge/pending (
4
4
  allowed-tools: Read, Glob, Grep, Bash, mcp__fabric__fab_extract_knowledge, mcp__fabric__fab_review
5
5
  ---
6
6
 
7
- > **Surface**: This is a Skill (AI-driven, LLM judgment over git log + docs for cold-start enrichment). See [`docs/surfaces.md`](https://github.com/fenglimg/fabric/blob/main/docs/surfaces.md) for the CLI / Skill / MCP boundary.
7
+ > **Surface**: Skill (LLM judgment over git + docs). See [`docs/surfaces.md`](https://github.com/fenglimg/fabric/blob/main/docs/surfaces.md).
8
8
 
9
9
  ## Purpose
10
10
 
11
- `fabric-import` is a one-time (per project) cold-start skill that lifts existing project artifacts — git commit history and Markdown documentation — into the knowledge layer as pending entries. It is the bridge between a brand-new Fabric installation (which only has the 4–7 baseline entries produced by `fabric install`'s deterministic scan) and a useful corpus that reflects accumulated team thinking. Run it once when adopting Fabric on an existing repo, or after a major refactor that invalidates large chunks of canonical knowledge. Default layer is `team`: project artifacts in git/docs are team-shared by definition; the user can later layer-flip individual entries to `personal` via `fabric-review` modify.
11
+ One-time per-project cold-start: lift git commits + `docs/*.md` into `.fabric/knowledge/pending/` as `team`-layer entries. Bridges `fabric install`'s 4-7 baseline accumulated corpus. Run once on adoption or after major refactor.
12
12
 
13
13
  ## Precondition
14
14
 
15
- This skill is invoked when one of the following holds:
15
+ Invoke only when ANY: user explicit ("import knowledge" / "bootstrap fabric" / "mine changelog"); user named skill; SessionStart hook fired `shouldRecommendImport()`.
16
16
 
17
- - The user typed an explicit import request (e.g. "import knowledge from git history", "bootstrap fabric for this repo", "mine the changelog into pending", "fabric import")
18
- - The user explicitly mentioned this skill by name (`fabric-import`)
19
- - A `fabric import` CLI command was run (rc.4 wires this if shipped; otherwise treat as user prompt)
17
+ Else stop: `没有触发 import 信号;如需手动 import 请显式调用 fabric-import` / `No import signal detected; to manually import, explicitly invoke fabric-import` (per `fabric_language`).
20
18
 
21
- If none of the above hold, stop the skill immediately and tell the user:
19
+ SKIP when: `.fabric/` missing (→ `fabric install`); canonical > `import_skip_canonical_threshold` (default 50); state file `phase=complete` + `last_checkpoint_at <24h`.
22
20
 
23
- - zh-CN: `没有触发 import 信号;如需手动 import 请显式调用 fabric-import`
24
- - en: `No import signal detected; to manually import, explicitly invoke fabric-import`
21
+ Required: `.fabric/` exists, `agents.meta.json` present, MCP `fab_extract_knowledge` + `fab_review` registered, working tree reasonably clean.
25
22
 
26
- (Render per `fabric_language` resolved in Phase 0.5 Config Load below class 2 of the UX i18n Policy.)
23
+ ## Phase 0 — Init
27
24
 
28
- > **Recommendation source (rc.8+)**: 过去版本的 `.fabric/.import-requested` sentinel 机制已下线;推荐由 SessionStart hook 的 underseed 自检触发(`templates/hooks/knowledge-hint-broad.cjs` `shouldRecommendImport()`:`agents.meta.json` 存在 + canonical 节点数 < `underseed_node_threshold` + `.import-state.json` 缺失三条件齐备时一次性提示)。本 skill 不再读写 sentinel 文件,也不需要在 Phase 3 完成时手动清理它。
25
+ Read/init `.fabric/.import-state.json`. Scan stale `.tmp-import-*`. State-corruption recovery `Read .../ref/state-recovery.md`.
29
26
 
30
- This skill SHOULD be skipped (warn the user, do not proceed) when:
27
+ > `.fabric/.import-requested` sentinel 机制已下线 (rc.8+);推荐由 SessionStart hook underseed 自检触发(`shouldRecommendImport()`)。本 skill 不再读写 sentinel。
31
28
 
32
- - `.fabric/` does not exist direct the user to run `fabric install` first; `fabric-import` is NOT a substitute for the deterministic install-scan
33
- - `.fabric/knowledge/` already holds **>`import_skip_canonical_threshold` canonical entries (config-resolved, default 50)** across all types — the project is mature; use `fabric-archive` (per-session capture) and `fabric-review` (lifecycle review) instead; bulk import would just create dup churn
34
- - `.fabric/.import-state.json` exists with `phase: "complete"` and `last_checkpoint_at` is **<24h ago** — the user just ran import; surface the prior result rather than re-running
29
+ ## Phase 0.5Config Load
35
30
 
36
- Required preconditions before any MCP call:
31
+ Read `.fabric/fabric-config.json` for tunables (defaults if absent):
37
32
 
38
- - `.fabric/` directory exists in the project root
39
- - `.fabric/agents.meta.json` is present (init produced it; the id allocator reads it on later approve)
40
- - `.fabric/events.jsonl` exists (tolerate ENOENT — empty ledger is normal first-run)
41
- - `mcp__fabric__fab_extract_knowledge` AND `mcp__fabric__fab_review` MCP tools are registered and reachable
42
- - Working tree is reasonably clean (large uncommitted churn pollutes git-log mining; warn but allow)
33
+ | Field | Default |
34
+ |---|---|
35
+ | `import_window_first_run_months` | 60 |
36
+ | `import_window_rerun_months` | 2 |
37
+ | `import_max_pending_per_run` | 10 |
38
+ | `import_max_commits_scan` | 500 |
39
+ | `import_skip_canonical_threshold` | 50 |
43
40
 
44
- ### Phase 0 Init (state-recovery ref-only)
41
+ First-run vs re-run by state file (ENOENT or `phase != complete && proposed == 0` → first-run window).
45
42
 
46
- On invocation: read/initialize `.fabric/.import-state.json` (resumable phase tracker — see Checkpoint Logic section below for schema). Scan workspace for stale `.tmp-import-*` residues (`.fabric/.import-state.json.tmp-*`). For details on the .tmp scan + state corruption recovery (rare — only triggers when a prior import crashed mid-phase), `Read packages/cli/templates/skills/fabric-import/ref/state-recovery.md` (or `.claude/skills/fabric-import/ref/state-recovery.md` post-install).
43
+ ## UX i18n Policy
47
44
 
48
- ### Phase 0.5 Config Load
45
+ Read `fabric_language` (`zh-CN` / `en` / `zh-CN-hybrid` / `match-existing`). Emit prose per variant. Protected tokens NEVER translate (`fab_extract_knowledge`, `fab_review`, `.fabric/.import-state.json`, all enum strings, `MUST`/`NEVER`). Full 5-class taxonomy `Read .../ref/i18n-policy.md`.
49
46
 
50
- Before any Phase 1 work, the skill MUST read `.fabric/fabric-config.json`
51
- to resolve the following tunables (with documented defaults if absent):
47
+ ## 3-Phase Pipeline
52
48
 
53
- | Config field | Default | Used by |
54
- |---|---|---|
55
- | `import_window_first_run_months` | 60 | Step 2.1 (--since arg construction, first-run window) |
56
- | `import_window_rerun_months` | 2 | Step 2.1 (--since arg construction, re-run window) |
57
- | `import_max_pending_per_run` | 10 | Step 2.1/2.2 hard cap on new pending entries per run |
58
- | `import_max_commits_scan` | 500 | Step 2.1 `-n` arg (commit-scan budget) |
59
- | `import_skip_canonical_threshold` | 50 | Precondition skip gate (canonical-entry maturity check) |
49
+ Strict P1→P2→P3 order. State write after every sub-step. Infer-not-Ask.
60
50
 
61
- If `.fabric/fabric-config.json` is missing or unreadable, use defaults silently.
62
- Whether the run is "first-run" vs "re-run" is decided by inspecting
63
- `.fabric/.import-state.json`: ENOENT (or any state with `phase != "complete"`
64
- and `final_summary.proposed == 0`) → first-run window; otherwise re-run window.
51
+ ### Phase 1 Init-Scan Reference (NO RE-IMPLEMENT)
65
52
 
66
- ### UX i18n Policy
53
+ `fabric install` produced baseline. Phase 1 REFERENCES, does NOT redo.
67
54
 
68
- Read `.fabric/fabric-config.json` `fabric_language` (`zh-CN` / `en` / `zh-CN-hybrid` / `match-existing`). Emit user-facing prose in the resolved variant. Protected tokens (`fab_extract_knowledge`, `fab_review`, `.fabric/.import-state.json`, schema/scope/layer enum values) are NEVER translated.
55
+ 1. Read `agents.meta.json` confirm baseline counters.
56
+ 2. Glob `.fabric/knowledge/team/**/*.md` → titles for P2 negative filter.
57
+ 3. If meta missing OR team/ empty: STOP. Tell user `请先运行 fabric install 完成基线扫描` / `Please run fabric install first` and exit.
58
+ 4. State: `phase=P1-done`, `p1_baseline_titles=[...]`, `last_checkpoint_at=<ISO>`.
69
59
 
70
- `AskUserQuestion` policy: `header` + `question` translate; `options[]` are routing keys — stay English regardless of locale.
60
+ No MCP calls.
71
61
 
72
- **For the full 5-class taxonomy + edge cases:** `Read packages/cli/templates/skills/fabric-import/ref/i18n-policy.md` (or `.claude/skills/fabric-import/ref/i18n-policy.md` post-install).
62
+ ### Phase 2 LLM-Driven Mining
73
63
 
74
- ## 3-Phase Pipeline (P1 reference / P2 mine / P3 dedup)
64
+ Classify each candidate into 5 types (decisions/pitfalls/guidelines/models/processes), draft slug, propose via `fab_extract_knowledge`. Layer: `team`.
75
65
 
76
- The pipeline runs strictly in order. Each phase reads the prior phase's outputs and updates `.fabric/.import-state.json` after every successful sub-step (not just at phase end). The skill is `Infer-not-Ask` for which phase to run (always all three when starting fresh, or resumes from the checkpoint phase).
66
+ #### Mandatory Scope Rule broad + empty paths (NON-NEGOTIABLE)
77
67
 
78
- ### Phase 1 Init-Scan Reference (NO RE-IMPLEMENTATION)
68
+ Every call MUST `relevance_scope="broad"` AND `relevance_paths=[]`. No exceptions. Why: import is LLM-driven (not session-driven); LLM-inferred narrow → false-narrow that silently hides knowledge. Narrowing deferred to `fab_review.modify` post-import. Full rationale + prohibitions + doctor lint #23 → `Read .../ref/phase-2-mining.md`.
79
69
 
80
- > Verbatim boundary: `fabric install` (v2.0+, deterministic CLI) already produces the baseline scan. Phase 1 of this skill **REFERENCES** that output. It does NOT redo the scan.
70
+ #### Step 2.1 Git Mining
81
71
 
82
- The deterministic init-scan has already populated `.fabric/knowledge/team/` with 4–7 baseline entries derived from:
72
+ `git log --since="<window> months ago" --pretty=format:"%H%n%s%n%b%n---ENDCOMMIT---" -n <cap>`. Conventional prefix → type signal (feat→decision/model, fix→pitfall, refactor→decision, docs→guideline; chore/test/ci skip). Extract observation Skip Tree → `fab_extract_knowledge` (broad+[]). Cap: `import_max_pending_per_run`.
83
73
 
84
- - `package.json` (tech stack, scripts, key dependencies)
85
- - `README.md` first paragraph (project elevator pitch)
86
- - Build configuration (`tsconfig.json`, `pyproject.toml`, `Cargo.toml`, etc.)
87
- - Code style (`.editorconfig`, lint config)
88
- - CI configuration (`.github/workflows/`, `.gitlab-ci.yml`, etc.) when present
89
- - The first sentence of any top-level `LICENSE` (rare baseline signal)
74
+ #### Step 2.1.5 Proposed Reason
90
75
 
91
- Phase 1 actions performed by THIS skill:
76
+ Infer one of: `decision-confirmation` | `new-dependency-or-pattern` | `wrong-turn-revert` | `diagnostic-then-fix` | `explicit-user-mark` | `dismissal-with-reason`. Fallback: `new-dependency-or-pattern`. 11-row table → ref.
92
77
 
93
- 1. Read `.fabric/agents.meta.json` to confirm baseline counters exist (each type's `next_id` should be `>1` if init-scan landed entries; `=1` means init produced zero entries of that type informational, not an error).
94
- 2. Glob `.fabric/knowledge/team/**/*.md` to enumerate baseline entry titles. Capture the list — Phase 2 uses these titles as a **negative filter** (signals already covered by init-scan should be skipped, not re-proposed).
95
- 3. If `.fabric/agents.meta.json` is missing OR `.fabric/knowledge/team/` is empty: STOP. Tell the user (UX i18n Policy class 2 — errors/preconditions):
78
+ #### Step 2.2Docs Mining
96
79
 
97
- - zh-CN: `请先运行 fabric install 完成基线扫描,再调用 fabric-import`
98
- - en: `Please run fabric install first to complete the baseline scan, then invoke fabric-import`
99
-
100
- …and exit.
101
- 4. Update `.fabric/.import-state.json`: `phase = "P1-done"`, `p1_baseline_titles = [<list>]`, `last_checkpoint_at = <ISO8601 now>`.
102
-
103
- **Phase 1 produces no MCP calls.** It only reads the on-disk init-scan output.
104
-
105
- ### Phase 2 — LLM-Driven Git + Doc Mining
106
-
107
- For each candidate signal mined from git or docs, the skill classifies into one of the 5 types (`decisions / pitfalls / guidelines / models / processes`), drafts a slug per the 5-rule naming guideline (see fabric-archive for the canonical rules), and proposes a pending entry via `fab_extract_knowledge`. Default layer for every Phase 2 proposal: `team`.
108
-
109
- #### Mandatory Scope Rule — Always Broad + Empty Paths (Q-1 Resolution)
110
-
111
- **EVERY `fab_extract_knowledge` call issued from this skill MUST set:**
112
-
113
- - `relevance_scope = "broad"`
114
- - `relevance_paths = []`
115
-
116
- This is non-negotiable. Applies to BOTH Step 2.1 (git mining) AND Step 2.2 (docs mining). No exceptions, no per-candidate override, no Agent judgment.
117
-
118
- **Why broad-only:** fabric-import is LLM-driven (mines git/docs), not session-driven. Git's touched-files list is the commit's effect-surface, not the observation's applicability-surface; LLM-inferred narrow bindings produce false-narrow that silently hides knowledge. Doc observations are usually cross-cutting. Narrowing of imported entries is deferred to `fab_review.modify` (user decision, post-import).
119
-
120
- For the full rationale + strict prohibitions list + fabric-archive cross-reference + post-import narrowing path + doctor lint #23 backstop, `Read packages/cli/templates/skills/fabric-import/ref/phase-2-mining.md` (or `.claude/skills/fabric-import/ref/phase-2-mining.md` post-install) §"Mandatory Scope Rule".
121
-
122
- #### Step 2.1 — Git Log Mining (summary)
123
-
124
- Run `git log --since="<window> months ago" --pretty=format:"%H%n%s%n%b%n---ENDCOMMIT---" -n <commits-cap>` (window/cap from Phase 0.5 config). For each commit: inspect conventional-commit prefix → infer type signal (feat→decision/model, fix→pitfall, refactor→decision, docs→guideline; chore/test/ci usually skip) → read body → extract core observation → apply Skip Decision Tree → classify type/slug/summary → call `fab_extract_knowledge` with broad+[] scope. Hard cap: `import_max_pending_per_run` (default 10) per run.
125
-
126
- #### Step 2.1.5 — Proposed Reason Inference
127
-
128
- Infer one of 6 enum values: `decision-confirmation` | `new-dependency-or-pattern` | `wrong-turn-revert` | `diagnostic-then-fix` | `explicit-user-mark` | `dismissal-with-reason`. Fallback: `new-dependency-or-pattern`. Full source-signal × body-cue mapping table in ref.
129
-
130
- #### Step 2.2 — Docs Mining (summary)
131
-
132
- `find docs/ -maxdepth 3 -name '*.md'` + root `*.md`. Skip README.md / CHANGELOG.md / LICENSE.md / CODE_OF_CONDUCT.md / CONTRIBUTING.md / files <300 bytes. Identify decision/guideline/pitfall/process/model heading patterns. Same `fab_extract_knowledge` call shape as Step 2.1. Cap shared with Step 2.1.
80
+ `find docs/ -maxdepth 3 -name '*.md'` + root `*.md`. Skip README / CHANGELOG / LICENSE / CODE_OF_CONDUCT / CONTRIBUTING / <300B files. Same call shape. Shared cap.
133
81
 
134
82
  #### Skip Decision Tree
135
83
 
136
- Skip if: cosmetic-only, metadata-only body, already in init-scan baseline, not classifiable to 5 types, or slug not derivable to 2-5 kebab words. Otherwise propose.
84
+ Skip if: cosmetic-only / metadata-only / in baseline / not classifiable / slug not derivable to 2-5 kebab words.
137
85
 
138
- #### Dry-Run Mode
86
+ #### Dry-Run
139
87
 
140
- `dry-run` / `预览` / `--dry-run` keyword → skip MCP calls, render bilingual preview table instead. Every row Scope column shows `broad+[]` (constant for fabric-import). State file NOT written. Phase 3 also skipped.
88
+ Keyword `dry-run` / `预览` / `--dry-run` → skip MCP, render bilingual preview table (every Scope row `broad+[]`). State NOT written. P3 skipped.
141
89
 
142
- For full Step 2.1 MCP call shape (all rc.7/rc.23 fields), the Step 2.1.5 inference table (11 rows), bilingual dry-run templates (zh-CN + en), and T5 array-form idempotency notes, `Read packages/cli/templates/skills/fabric-import/ref/phase-2-mining.md` (or `.claude/skills/fabric-import/ref/phase-2-mining.md` post-install).
90
+ Full MCP call shape, Step 2.1.5 table, dry-run templates, T5 idempotency `Read .../ref/phase-2-mining.md`.
143
91
 
144
- ### Phase 3 — LLM-Driven Dedup vs Canonical
92
+ ### Phase 3 — LLM-Driven Dedup
145
93
 
146
- For each pending entry created in Phase 2, check if it duplicates / contradicts / is subsumed by an existing canonical entry. **Semantic comparison is the LLM's job — `fab_review` does not compare meaning.**
94
+ For each P2 pending: check vs canonical. Semantic compare is LLM's job — `fab_review` does NOT compare meaning.
147
95
 
148
- **4-step summary:**
96
+ 1. **3.1** — `fab_review action="search"` filter by `type`, top 5.
97
+ 2. **3.2** — Classify each pair: `duplicate` (reject pending) | `subsumption` (reject pending) | `subsumption-with-novelty` (modify canonical + reject pending) | `contradiction` (leave + flag) | `genuinely-new` (keep).
98
+ 3. **3.3** — Issue `fab_review` reject / modify.
99
+ 4. **3.4** — `phase=complete` + `final_summary` + roll-up.
149
100
 
150
- 1. **Step 3.1** `fab_review action="search"` filtered by `type`, cap top 5 canonical results.
151
- 2. **Step 3.2** — LLM classifies each (pending, canonical) pair: `duplicate` (reject pending) | `subsumption` (reject pending) | `subsumption-with-novelty` (modify canonical + reject pending) | `contradiction` (leave + flag) | `genuinely-new` (keep).
152
- 3. **Step 3.3** — Issue `fab_review` reject / modify MCP calls per classification.
153
- 4. **Step 3.4** — Update state to `phase="complete"` + write `final_summary`. Render roll-up.
101
+ Full call shapes + 5-way classification `Read .../ref/phase-3-dedup.md`.
154
102
 
155
- For full Step 3.1/3.3 MCP call shapes, the 5-way semantic compare classification with action-per-case, and the rc.8 sentinel-removal note, `Read packages/cli/templates/skills/fabric-import/ref/phase-3-dedup.md` (or `.claude/skills/fabric-import/ref/phase-3-dedup.md` post-install).
103
+ ## Checkpoint Logic
156
104
 
157
- ## Checkpoint Logic — `.fabric/.import-state.json`
105
+ State file `.fabric/.import-state.json` is single resumability source. Atomic write: Step A `Write .tmp` → Step B `Bash mv` (POSIX `rename(2)`). `Write` alone NOT atomic.
158
106
 
159
- State file `.fabric/.import-state.json` is the single source of resumability. Every write uses the 2-step atomic pattern: **Step A** `Write` to `.fabric/.import-state.json.tmp` **Step B** `Bash: mv .tmp` to commit. POSIX `rename(2)` guarantees atomicity. `Write` alone is NOT atomic.
107
+ Resume contract: re-invoke MUST NOT dup-propose / re-dedup. By `phase`: `P1-done`→2.1, `P2-done`→3.1, `complete <24h`→skip, `≥24h`→confirm.
160
108
 
161
- Resume contract: re-invoking fabric-import after ANY interruption (Ctrl-C, crash, MCP network blip) MUST NOT propose duplicates and MUST NOT redo completed dedup. Resume per `phase` field: `P1-done` → resume Phase 2.1; `P2-done` → resume Phase 3.1; `complete` AND <24h → skip; ≥24h → confirm with user.
109
+ Full rationale + 4KB POSIX constraint + state schema + 6-step Resume `Read .../ref/checkpoint-state.md`.
162
110
 
163
- For the full Atomic State Write rationale + crash-safety reasoning, the events.jsonl 4KB POSIX atomicity constraint (single-line + self-truncate rules), the complete `.import-state.json` JSON schema, and the 6-step Resume Logic state machine, `Read packages/cli/templates/skills/fabric-import/ref/checkpoint-state.md` (or `.claude/skills/fabric-import/ref/checkpoint-state.md` post-install).
111
+ ## Default Knobs
164
112
 
165
- ## Default Behavior & Knobs
113
+ Layer `team` / scope `broad` / paths `[]` are contract-locked (no override). Max pending = config / dry-run via keyword / re-run <24h blocked. Full table → ref.
166
114
 
167
- | Knob | Default | Override |
168
- |-------------------------------------|-------------|----------------------------------------------------------------|
169
- | Layer for new entries | `team` | User explicit instruction ("import these as personal") |
170
- | `relevance_scope` for new entries | `broad` | NONE — contract-locked; narrowing deferred to `fab_review.modify` post-import |
171
- | `relevance_paths` for new entries | `[]` | NONE — contract-locked; populating deferred to `fab_review.modify` post-import |
172
- | Max new pending entries per P2 run | config-resolved (default 10, max 50) | `import_max_pending_per_run` in `.fabric/fabric-config.json`; user explicit ("import up to 25") |
173
- | Git log window | config-resolved (default 60 first-run / 2 re-run, months) | `import_window_first_run_months` / `import_window_rerun_months`; user explicit ("import the full year") |
174
- | Git log commit-scan cap | config-resolved (default 500) | `import_max_commits_scan` in `.fabric/fabric-config.json` |
175
- | Skip-import canonical threshold | config-resolved (default 50) | `import_skip_canonical_threshold` in `.fabric/fabric-config.json` |
176
- | Docs scan depth | `3` | User explicit ("scan docs/ recursively") |
177
- | Dry-run mode | OFF | User keyword `dry-run` / `预览` / `--dry-run` |
178
- | Re-run within 24h of complete | BLOCKED | User keyword `re-run import` / `reset import` |
115
+ ## Hard Rules
179
116
 
180
- ## Hard Rules — DISPLAY / WRITE Split
117
+ ### DISPLAY (per entry)
181
118
 
182
- ### DISPLAY Rules
119
+ `[type=...]` `[layer=team]` `[scope=broad]` `slug=...` `src=<sha7-or-path>` + `pending_path`. zh-CN body + EN headings. Roll-up: proposed / kept / rejected_dup / merged / contradictions_flagged. Final `phase` on exit. Never hide source / show `idempotency_key` / auto-classify `personal`.
183
120
 
184
- - MUST present every proposed pending entry with explicit `[type=...]`, `[layer=team]`, `[scope=broad]`, `slug=...`, AND `src=<commit-sha7 or doc-path>` so the user can audit the provenance and the (constant) scope.
185
- - MUST display zh-CN body for proposed summaries (M3 style consistent with fabric-archive / fabric-review).
186
- - MUST display EN section headings.
187
- - MUST surface the resolved `pending_path` returned by `fab_extract_knowledge` in the per-entry display block.
188
- - MUST display the final roll-up with proposed / kept / rejected_dup / merged / contradictions_flagged counts.
189
- - MUST display the `.fabric/.import-state.json` `phase` value when the skill exits (so the user knows whether re-invocation is required).
190
- - NEVER hide the source signal; provenance is the only audit trail for bulk-imported entries.
191
- - NEVER classify a Phase 2 candidate as `personal` automatically — default `team` is contract-locked; only flip layer at the user's explicit instruction (and even then, do it post-import via fabric-review).
192
- - NEVER show raw `idempotency_key` to the user (internal server-side concern).
121
+ ### WRITE
193
122
 
194
- ### WRITE Rules
123
+ NEVER write entry via `Edit`/`Write`/`Bash` — only `fab_extract_knowledge` (P2) + `fab_review` (P3).
195
124
 
196
- - NEVER write a knowledge entry directly via `Edit` / `Write` / `Bash`; the only legal write paths are `mcp__fabric__fab_extract_knowledge` (Phase 2) and `mcp__fabric__fab_review` (Phase 3).
197
- - NEVER batch multiple Phase 2 candidates into a single `fab_extract_knowledge` call; one call per candidate.
198
- - NEVER skip the Phase 1 reference step — even if init-scan landed zero entries, the skill MUST verify `.fabric/agents.meta.json` is present.
199
- - NEVER call `fab_review action="approve"` from this skill — promotion of pending → canonical is `fabric-review`'s concern, not import's. Imported entries land in `pending/` and wait for normal review flow.
200
- - NEVER call `git mv` directly — layer flips during Phase 3 dedup go through `fab_review action="modify"` with `changes.layer`, which is a server-side transaction.
201
- - NEVER infer a layer-flip target without explicit user instruction — fabric-import defaults `team`; if the user later wants `personal` for an entry, that's a `fabric-review` modify call, not an import-time decision.
202
- - NEVER overwrite `.fabric/.import-state.json` non-atomically — use the 2-step `.tmp` + `mv` pattern documented in "Atomic State Write" under Checkpoint Logic (Step A: `Write` to `.fabric/.import-state.json.tmp`; Step B: `Bash: mv` to commit).
203
- - NEVER exceed the 10-entry-per-run hard cap without explicit user override.
204
- - NEVER pass `relevance_scope = "narrow"` to `fab_extract_knowledge` — every call from this skill MUST use `relevance_scope: "broad"`. No heuristic, no Agent judgment, no per-candidate override (see "Mandatory Scope Rule" in Phase 2).
205
- - NEVER populate `relevance_paths` with a non-empty array on import — every call from this skill MUST pass `relevance_paths: []`. Do not derive paths from `git log --name-only`, `git show --stat`, commit subjects/bodies, or the path of a mined Markdown file.
206
- - NEVER copy fabric-archive's Phase 1.5 scope-decision logic (narrow-vs-broad rules, public-prefix generalization, glob blacklist) into this skill — that logic requires a live `edit_paths` signal from an active session, which fabric-import does not have.
207
- - Narrowing of imported entries happens out-of-band through `fab_review action="modify"` (issued by user via `fabric-review`), NOT inside this skill.
208
- - MUST preserve protected tokens exactly: `stable_id`, `pending_path`, `layer`, `team`, `personal`, `knowledge_proposed`, `fab_extract_knowledge`, `fab_review`, `MUST`, `NEVER`, `phase`, `.import-state.json`, `relevance_scope`, `relevance_paths`, `broad`, `narrow`, `source_sessions`, `proposed_reason`, `session_context`, `intent_clues`, `tech_stack`, `impact`, `must_read_if`.
125
+ NEVER batch P2 candidates / skip P1 ref / call `fab_review.approve` / `git mv` directly / infer layer-flip / non-atomic state / exceed cap / `relevance_scope="narrow"` / non-empty `relevance_paths` / copy fabric-archive Phase 1.5 logic.
209
126
 
210
- ## Output Contract
127
+ Narrowing post-import = `fab_review.modify` (out-of-band).
211
128
 
212
- After Phase 3 completes (or on any phase exit due to cap / error / interrupt), the skill MUST produce a roll-up. UX i18n Policy class 1 — render either en or zh-CN variant per `fabric_language`. Section names: `Phase 2 — Mining` (commits scanned / docs scanned / pending proposed / scope confirmation), `Phase 3 — Dedup` (kept / rejected_dup / modified-then-rejected / contradictions_flagged), `State` (phase + last_checkpoint_at), `Next Steps` (fabric-review for kept entries; manual resolve for contradictions; narrowing via `fab_review action="modify"`).
129
+ Protected tokens (verbatim, no translate): `stable_id`, `pending_path`, `layer`, `team`, `personal`, `knowledge_proposed`, `fab_extract_knowledge`, `fab_review`, `MUST`, `NEVER`, `phase`, `.import-state.json`, `relevance_scope`, `relevance_paths`, `broad`, `narrow`, `source_sessions`, `proposed_reason`, `session_context`, `intent_clues`, `tech_stack`, `impact`, `must_read_if`.
213
130
 
214
- For the full bilingual roll-up templates (zh-CN + en) with all section/field placeholders, `Read packages/cli/templates/skills/fabric-import/ref/output-contract.md` (or `.claude/skills/fabric-import/ref/output-contract.md` post-install).
131
+ ## Output Contract
215
132
 
216
- Also surface a one-line `git status` of `.fabric/knowledge/` so the user sees the new pending files appear (and any canonical files modified by dedup-merge).
133
+ Roll-up sections (per `fabric_language`): `Phase 2 — Mining` | `Phase 3 Dedup` | `State` | `Next Steps`. Plus one-line `git status .fabric/knowledge/`. Bilingual templates → `Read .../ref/output-contract.md`.
217
134
 
218
135
  ## Worked Examples
219
136
 
220
- Four end-to-end examples — (A) feat commit pitfall entry showing broad+[] discipline and the "WRONG" counter-example; (B) docs/architecture.md decision entry; (C) Phase 3 dedup finds duplicate reject MCP call; (D) post-import narrowing via `fab_review.modify` (out-of-band, NOT this skill) live in `packages/cli/templates/skills/fabric-import/ref/worked-examples.md` (or `.claude/skills/fabric-import/ref/worked-examples.md` post-install). Load when you want to see complete MCP call shapes + state file deltas in realistic scenarios.
137
+ 4 end-to-end (A feat→pitfall + WRONG counter-ex; B docs→decision; C P3 dup→reject; D out-of-band narrow) `Read .../ref/worked-examples.md`.
221
138
 
222
139
  ## Failure Recovery
223
140
 
224
- - **Phase 2 mid-run failure** (e.g. `fab_extract_knowledge` errors on commit 5 of 10): state already records commits 1–4; rerun resumes at commit 5 by skipping any sha in `p2_processed_commits[]`. Error appended to `errors[]`.
225
- - **Phase 3 mid-run failure** (e.g. `fab_review action="search"` MCP timeout on dedup pair 3 of 7): state records pairs 1–2 in `p3_dedup_completed[]`; rerun resumes at pair 3.
226
- - **Cumulative `errors[].length > 5`**: skill halts; asks free-text confirmation (UX i18n Policy class 3 confirmation prompts):
227
- - zh-CN: `继续 (y) / 中止并保留 state (n)`
228
- - en: `Continue (y) / Abort and keep state (n)`
229
- - **State file corruption**: handled by Phase 0.1 — Phase 0.1 detects corruption (JSON parse error / missing required fields / phase enum violation), renames the file to `.fabric/.import-state.json.corrupt-<ISO8601>`, and restarts from Phase 1. See "Phase 0.1 — State Corruption Recovery" above.
230
- - **MCP tool unreachable**: skill halts before any work; surfaces (UX i18n Policy class 2 — errors/preconditions):
231
- - zh-CN: `MCP 工具未注册;请检查 fabric server 是否运行`
232
- - en: `MCP tool not registered; please check that the fabric server is running`
233
- …and exits without writing state.
234
-
235
- The skill is `Check-not-Ask` for recovery: it inspects state and resumes deterministically; it does NOT ask the user where to resume from.
141
+ - P2 mid-fail: state has `p2_processed_commits[]`; rerun skips them.
142
+ - P3 mid-fail: state has `p3_dedup_completed[]`; rerun resumes.
143
+ - `errors.length > 5`: halt + ask `继续 (y) / 中止并保留 state (n)` / `Continue (y) / Abort and keep state (n)`.
144
+ - State corruption: P0 detects rename `.json.corrupt-<ISO>` → restart P1.
145
+ - MCP unreachable: halt + `MCP 工具未注册;请检查 fabric server 是否运行` / `MCP tool not registered; please check that the fabric server is running` → exit without state write.
146
+
147
+ Check-not-Ask: inspect state, resume deterministically.