@fenglimg/fabric-cli 2.0.0-rc.35 → 2.0.0-rc.37
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/LICENSE +21 -0
- package/dist/{chunk-XVS4F3P6.js → chunk-D25XJ4BC.js} +49 -5
- package/dist/{chunk-G2CIOLD4.js → chunk-WWNXR34K.js} +1 -16
- package/dist/{doctor-2FCRAWDZ.js → doctor-764NFF3X.js} +112 -16
- package/dist/index.js +7 -6
- package/dist/{install-HOTE5BPA.js → install-U7MGIJ2L.js} +50 -22
- package/dist/metrics-ACEQFPDU.js +122 -0
- package/dist/{uninstall-BIJ5GLEU.js → uninstall-MH7ZIB6M.js} +6 -18
- package/package.json +30 -4
- package/templates/hooks/cite-policy-evict.cjs +80 -91
- package/templates/hooks/configs/README.md +19 -0
- package/templates/hooks/configs/codex-hooks.json +3 -0
- package/templates/hooks/configs/cursor-hooks.json +2 -1
- package/templates/hooks/fabric-hint.cjs +146 -8
- package/templates/hooks/knowledge-hint-broad.cjs +65 -104
- package/templates/hooks/knowledge-hint-narrow.cjs +122 -5
- package/templates/hooks/lib/cite-line-parser.cjs +7 -1
- package/templates/hooks/lib/client-adapter.cjs +106 -0
- package/templates/hooks/lib/config-cache.cjs +107 -0
- package/templates/hooks/lib/state-store.cjs +84 -0
- package/templates/skills/fabric-archive/SKILL.md +29 -7
- package/templates/skills/fabric-archive/ref/dry-run-scope.md +1 -1
- package/templates/skills/fabric-archive/ref/i18n-policy.md +6 -0
- package/templates/skills/fabric-archive/ref/phase-1-5-onboard.md +1 -1
- package/templates/skills/fabric-archive/ref/phase-1-cross-session.md +2 -0
- package/templates/skills/fabric-archive/ref/phase-2-5-viability.md +25 -11
- package/templates/skills/fabric-archive/ref/phase-3-5-scope.md +43 -15
- package/templates/skills/fabric-import/SKILL.md +75 -163
- package/templates/skills/fabric-import/ref/i18n-policy.md +6 -0
- package/templates/skills/fabric-import/ref/phase-2-mining.md +2 -2
- package/templates/skills/fabric-review/SKILL.md +31 -25
- package/templates/skills/fabric-review/ref/i18n-policy.md +6 -0
- package/templates/skills/fabric-review/ref/modify-flow.md +9 -1
- package/templates/skills/fabric-review/ref/per-mode-flows.md +1 -1
- package/templates/skills/lib/shared-policy.md +69 -0
- package/dist/serve-43JTEM3U.js +0 -142
|
@@ -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**:
|
|
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
|
-
|
|
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
|
-
|
|
15
|
+
Invoke only when ANY: user explicit ("import knowledge" / "bootstrap fabric" / "mine changelog"); user named skill; SessionStart hook fired `shouldRecommendImport()`.
|
|
16
16
|
|
|
17
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
23
|
+
## Phase 0 — Init
|
|
27
24
|
|
|
28
|
-
|
|
25
|
+
Read/init `.fabric/.import-state.json`. Scan stale `.tmp-import-*`. State-corruption recovery → `Read .../ref/state-recovery.md`.
|
|
29
26
|
|
|
30
|
-
|
|
27
|
+
> 旧 `.fabric/.import-requested` sentinel 机制已下线 (rc.8+);推荐由 SessionStart hook 的 underseed 自检触发(`shouldRecommendImport()`)。本 skill 不再读写 sentinel。
|
|
31
28
|
|
|
32
|
-
|
|
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.5 — Config Load
|
|
35
30
|
|
|
36
|
-
|
|
31
|
+
Read `.fabric/fabric-config.json` for tunables (defaults if absent):
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
41
|
+
First-run vs re-run by state file (ENOENT or `phase != complete && proposed == 0` → first-run window).
|
|
45
42
|
|
|
46
|
-
|
|
43
|
+
## UX i18n Policy
|
|
47
44
|
|
|
48
|
-
|
|
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
|
-
|
|
51
|
-
to resolve the following tunables (with documented defaults if absent):
|
|
47
|
+
## 3-Phase Pipeline
|
|
52
48
|
|
|
53
|
-
|
|
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
|
-
|
|
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
|
-
|
|
53
|
+
`fabric install` produced baseline. Phase 1 REFERENCES, does NOT redo.
|
|
67
54
|
|
|
68
|
-
|
|
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
|
-
|
|
60
|
+
No MCP calls.
|
|
71
61
|
|
|
72
|
-
|
|
62
|
+
### Phase 2 — LLM-Driven Mining
|
|
73
63
|
|
|
74
|
-
|
|
64
|
+
Classify each candidate into 5 types (decisions/pitfalls/guidelines/models/processes), draft slug, propose via `fab_extract_knowledge`. Layer: `team`.
|
|
75
65
|
|
|
76
|
-
|
|
66
|
+
#### Mandatory Scope Rule — broad + empty paths (NON-NEGOTIABLE)
|
|
77
67
|
|
|
78
|
-
|
|
68
|
+
Every call MUST `relevance_scope="broad"` AND `relevance_paths=[]`. No exceptions. Why: import is LLM-driven (not session-driven); LLM-inferred narrow lies about applicability. Post-rc.37 A1 the server returns every selectable entry regardless of scope, so false-narrow no longer hides knowledge — but it still poisons doctor lint accounting + downstream consumers that read `relevance_paths` literally. Narrowing deferred to `fab_review.modify` post-import when the user has the real applicability surface. Full rationale + prohibitions + doctor lint #23 → `Read .../ref/phase-2-mining.md`.
|
|
79
69
|
|
|
80
|
-
|
|
70
|
+
#### Step 2.1 — Git Mining
|
|
81
71
|
|
|
82
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.2 — Docs Mining
|
|
96
79
|
|
|
97
|
-
|
|
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
|
|
84
|
+
Skip if: cosmetic-only / metadata-only / in baseline / not classifiable / slug not derivable to 2-5 kebab words.
|
|
137
85
|
|
|
138
|
-
#### Dry-Run
|
|
86
|
+
#### Dry-Run
|
|
139
87
|
|
|
140
|
-
|
|
88
|
+
Explicit token `--dry-run` in invocation → skip MCP, render bilingual preview table (every Scope row `broad+[]`). State NOT written. P3 skipped. v2.0.0-rc.37 NEW-10 dropped legacy substring fallback on bare `dry-run` / `预览` (false-positive on incidental mentions).
|
|
141
89
|
|
|
142
|
-
|
|
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
|
|
92
|
+
### Phase 3 — LLM-Driven Dedup
|
|
145
93
|
|
|
146
|
-
For each pending
|
|
94
|
+
For each P2 pending: check vs canonical. Semantic compare is LLM's job — `fab_review` does NOT compare meaning.
|
|
147
95
|
|
|
148
|
-
**
|
|
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
|
-
|
|
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
|
-
|
|
103
|
+
## Checkpoint Logic
|
|
156
104
|
|
|
157
|
-
|
|
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
|
-
|
|
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
|
-
|
|
109
|
+
Full rationale + 4KB POSIX constraint + state schema + 6-step Resume → `Read .../ref/checkpoint-state.md`.
|
|
162
110
|
|
|
163
|
-
|
|
111
|
+
## Default Knobs
|
|
164
112
|
|
|
165
|
-
|
|
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
|
-
|
|
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
|
-
|
|
117
|
+
### DISPLAY (per entry)
|
|
181
118
|
|
|
182
|
-
|
|
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
|
-
|
|
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
|
-
|
|
123
|
+
NEVER write entry via `Edit`/`Write`/`Bash` — only `fab_extract_knowledge` (P2) + `fab_review` (P3).
|
|
195
124
|
|
|
196
|
-
|
|
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
|
-
|
|
127
|
+
Narrowing post-import = `fab_review.modify` (out-of-band).
|
|
211
128
|
|
|
212
|
-
|
|
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
|
-
|
|
131
|
+
## Output Contract
|
|
215
132
|
|
|
216
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
225
|
-
-
|
|
226
|
-
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
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
|
+
Resume policy: inspect existing state and continue from the last completed phase — do not prompt the user mid-flow.
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# UX i18n Policy — fabric-import full reference
|
|
2
2
|
|
|
3
|
+
> **Shared core (rc.37 NEW-13):** the cross-skill invariants — protected-token
|
|
4
|
+
> NEVER-translate list, AskUserQuestion routing-key rule, layer heuristic, and
|
|
5
|
+
> events-emit convention — live once in `../../lib/shared-policy.md`. This file
|
|
6
|
+
> keeps only the fabric-import-specific 5-class examples. Read the shared lib
|
|
7
|
+
> for the common rules; do not fork them here.
|
|
8
|
+
|
|
3
9
|
> **Loaded on demand.** Only consult when you need to disambiguate which of the 5 classes a given string belongs to. SKILL.md gives the operative rule.
|
|
4
10
|
|
|
5
11
|
## UX i18n Policy (5-class bilingualization)
|
|
@@ -15,7 +15,7 @@ This is non-negotiable and applies to BOTH Step 2.1 (git mining) AND Step 2.2 (d
|
|
|
15
15
|
|
|
16
16
|
1. `fabric-import` 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
|
-
3. LLM-inferred `relevance_paths` from historical commit metadata produces false-narrow bindings —
|
|
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/`).
|
|
20
20
|
|
|
21
21
|
**Strict prohibitions — DO NOT attempt any of the following:**
|
|
@@ -174,7 +174,7 @@ After Step 2.2 completes (or hits the cap), update `.fabric/.import-state.json`:
|
|
|
174
174
|
|
|
175
175
|
## Dry-Run Mode
|
|
176
176
|
|
|
177
|
-
When the user invocation
|
|
177
|
+
When the user invocation carries the verbatim token `--dry-run`, Phase 2 runs WITHOUT calling `fab_extract_knowledge`. 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
|
|
|
@@ -48,46 +48,46 @@ Read `fabric_language` (`zh-CN` / `en` / `zh-CN-hybrid` / `match-existing`); emi
|
|
|
48
48
|
|
|
49
49
|
## Mode Inference (System Infers — NEVER Ask)
|
|
50
50
|
|
|
51
|
-
>
|
|
52
|
-
> "review 永远走 fabric-review skill,**模式从上下文推断**(4 种 mode:pending queue / by topic / health overview / revisit existing)"
|
|
51
|
+
> Locked decision (KT-DEC-0006): "Review mode inferred from context, not solicited via AskUserQuestion."
|
|
53
52
|
> "**AskUserQuestion 仅在真有选择时用**——'何种 mode' 不是真选择(系统能推断),'approve/reject/modify 单条' 是真选择"
|
|
54
53
|
|
|
55
|
-
The skill MUST infer one of
|
|
54
|
+
The skill MUST infer one of **2 modes** BEFORE any user-facing output (v2.0.0-rc.37 NEW-12 simplified 4 → 2):
|
|
56
55
|
|
|
57
|
-
|
|
56
|
+
- **`pending`** — triage the write-side backlog (`.fabric/knowledge/pending/`): approve / reject / modify / defer per item. The dominant entry point.
|
|
57
|
+
- **`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.
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
### 2-Step Inference Algorithm
|
|
60
|
+
|
|
61
|
+
**Step 1 — Recent user message keyword scan:**
|
|
60
62
|
|
|
61
63
|
| Keywords (zh-CN + en) | Inferred mode |
|
|
62
64
|
|---|---|
|
|
63
65
|
| "approve", "review pending", "promote", "what's queued", "审核 pending", "通过" | `pending` |
|
|
64
|
-
| "search
|
|
65
|
-
| "what's stale", "demote old", "health check", "过期的", "陈旧的", "整理一下" | `health` |
|
|
66
|
-
| "look at <id>", "revisit KT-…", "show <slug>", "再看下 <id>", "回顾" | `revisit` |
|
|
67
|
-
|
|
68
|
-
Exactly one row matches → lock mode, skip to Step 3.
|
|
69
|
-
|
|
70
|
-
**Step 2 — events.jsonl tail scan.** If Step 1 yielded 0 or >1 matches, tail (last 200 lines) `.fabric/events.jsonl`:
|
|
66
|
+
| "search/find about <topic>", "what's stale", "demote old", "health check", "look at <id>", "revisit KT-…", "关于…的知识", "过期的", "陈旧的", "整理一下", "再看下 <id>", "回顾" | `maintain` |
|
|
71
67
|
|
|
72
|
-
|
|
73
|
-
- `≥1` `knowledge_demoted` or `lint` events in 24h → `health` (corpus quality signal).
|
|
74
|
-
- Recent `knowledge_layer_changed` for the entry user referenced → `revisit`.
|
|
68
|
+
A `maintain`-row match → lock `maintain`. A `pending`-row match (or 0/ambiguous) → fall to Step 2.
|
|
75
69
|
|
|
76
|
-
**Step
|
|
70
|
+
**Step 2 — Backlog default.** Glob `.fabric/knowledge/pending/**/*.md`:
|
|
77
71
|
|
|
78
72
|
- 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
73
|
- Otherwise → default `pending` (most common review entry point).
|
|
80
74
|
|
|
81
|
-
|
|
75
|
+
> Back-compat: the legacy 4-mode names (`topic` / `health` / `revisit`) still resolve — they all map to `maintain`. Old session traces / muscle memory keep working.
|
|
76
|
+
|
|
77
|
+
`Read ref/per-mode-flows.md` for inference examples and anti-pattern restatement.
|
|
82
78
|
|
|
83
79
|
## Per-Mode Flow
|
|
84
80
|
|
|
85
81
|
Each mode produces user-facing output, then routes per-item or per-batch decisions through `fab_review` actions. Display body = zh-CN summaries (M3 style); section headings = EN.
|
|
86
82
|
|
|
87
|
-
- **`pending`** — list pending entries → run Semantic Check (see `ref/semantic-check.md`) → per-item AskUserQuestion `{approve, reject, modify, defer, skip}` → route per choice
|
|
88
|
-
-
|
|
89
|
-
-
|
|
90
|
-
-
|
|
83
|
+
- **`pending`** — list pending entries → run Semantic Check (see `ref/semantic-check.md`) → per-item AskUserQuestion `{approve, reject, modify, defer, skip}` → route per choice. The modify branch chooses between two explicit actions (rc.37 NEW-12):
|
|
84
|
+
- `fab_review action="modify-content"` — edit scalars (title/summary/maturity/tags/relevance_*); NEVER flips layer.
|
|
85
|
+
- `fab_review action="modify-layer"` — the dedicated layer-flip path (`changes.layer` required); may reallocate the stable_id + emit an id-redirect.
|
|
86
|
+
- (Legacy `action="modify"` still works — it routes by whether `changes.layer` is present.) See `ref/modify-flow.md`.
|
|
87
|
+
- **`maintain`** — sub-flow inferred from the same keywords:
|
|
88
|
+
- *browse-by-topic*: extract keywords → `fab_review action="search"` → render top-N (cap `review_topic_result_cap`) → AskUserQuestion only on an action verb.
|
|
89
|
+
- *health/staleness*: `fab_review action="list"` + tail events → compute stale → render dashboard → per-stale AskUserQuestion `{defer, demote, skip}`.
|
|
90
|
+
- *revisit*: user referenced a specific id/slug → `Read` canonical file directly OR `fab_review action="list"` with narrow filters → display body + history → AskUserQuestion only if actionable.
|
|
91
91
|
|
|
92
92
|
`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.
|
|
93
93
|
|
|
@@ -97,11 +97,17 @@ Each mode produces user-facing output, then routes per-item or per-batch decisio
|
|
|
97
97
|
|
|
98
98
|
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_review action="search"` scoped by `filters.type` → LLM judges semantically against returned canonical entries → surface one of three flags as informational:
|
|
99
99
|
|
|
100
|
-
- `⚠ Possible duplicate of <stable_id
|
|
101
|
-
- `⚠ Contradicts <stable_id
|
|
102
|
-
- `⚠ Subsumed by <stable_id
|
|
100
|
+
- `⚠ Possible duplicate of <stable_id> (overlap: high)` — same essential claim
|
|
101
|
+
- `⚠ Contradicts <stable_id> (overlap: high)` — opposing claims, same scope
|
|
102
|
+
- `⚠ Subsumed by <stable_id> (overlap: medium+); consider modify-to-merge` — fully covered
|
|
103
|
+
|
|
104
|
+
**Quantified overlap band (rc.37 NEW-12).** The LLM still judges meaning (no embedding %), but MUST tag each flag with a 3-level band so the signal is comparable across entries and the user can triage at a glance:
|
|
105
|
+
|
|
106
|
+
- `high` — ≥ ~80% of the candidate's essential claim is restated; near-certain dup/contradiction. Recommend reject-as-duplicate or modify-to-merge.
|
|
107
|
+
- `medium` — substantial conceptual overlap but the new entry adds a distinct facet (different path scope, added caveat). Recommend modify-to-harmonize.
|
|
108
|
+
- `low` — adjacent topic, not a real overlap. Do NOT raise a flag at `low` — it is below the surfacing threshold (suppresses noise).
|
|
103
109
|
|
|
104
|
-
|
|
110
|
+
Only `medium`+ flags are surfaced. User decides: still-approve (flag informational), modify-to-harmonize, or reject-as-duplicate (reason MUST cite existing stable_id).
|
|
105
111
|
|
|
106
112
|
DO NOT AskUserQuestion "is this a duplicate?" — LLM already judged. User only chooses approve/reject/modify.
|
|
107
113
|
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# UX i18n Policy — fabric-review full reference
|
|
2
2
|
|
|
3
|
+
> **Shared core (rc.37 NEW-13):** the cross-skill invariants — protected-token
|
|
4
|
+
> NEVER-translate list, AskUserQuestion routing-key rule, layer heuristic, and
|
|
5
|
+
> events-emit convention — live once in `../../lib/shared-policy.md`. This file
|
|
6
|
+
> keeps only the fabric-review-specific 5-class examples. Read the shared lib
|
|
7
|
+
> for the common rules; do not fork them here.
|
|
8
|
+
|
|
3
9
|
> **Loaded on demand.** Only consult when you need to disambiguate which of the 5 classes a given string belongs to. SKILL.md gives the operative rule.
|
|
4
10
|
|
|
5
11
|
## UX i18n Policy (5-class bilingualization)
|
|
@@ -2,7 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## Modify Sub-Flow
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The modify family is the only action group that mutates frontmatter or stable_id. It accepts `changes` of shape `{title?, summary?, layer?, maturity?, tags?, relevance_scope?, relevance_paths?}`.
|
|
6
|
+
|
|
7
|
+
**v2.0.0-rc.37 NEW-12 — explicit split.** Prefer the dedicated action over the legacy combined `modify`:
|
|
8
|
+
|
|
9
|
+
- `action="modify-content"` — scalar edits (title/summary/tags/maturity/relevance_*); stable_id PRESERVED; the server STRIPS any `changes.layer` so this path can never flip layer. Emits `knowledge_slug_renamed` only when slug derives from title.
|
|
10
|
+
- `action="modify-layer"` — the dedicated layer-flip path; `changes.layer` is REQUIRED. The ONLY legal stable_id mutation in the system (see Layer-Flip Rules below).
|
|
11
|
+
- `action="modify"` (legacy alias) — still accepted; routes to content-edit OR layer-flip by whether `changes.layer` is present. New call sites should use the explicit pair.
|
|
12
|
+
|
|
13
|
+
Server semantics (identical regardless of which action selected the path):
|
|
6
14
|
|
|
7
15
|
- **title / summary / tags / maturity changes** → in-place rewrite; stable_id PRESERVED; emits `knowledge_slug_renamed` only when slug derives from title.
|
|
8
16
|
- **layer change** → the ONLY legal stable_id mutation in the system.
|
|
@@ -152,4 +152,4 @@ Full bilingual rendering blocks + step-by-step procedures for the four modes ref
|
|
|
152
152
|
|
|
153
153
|
### Anti-Pattern (Hard Rule restatement)
|
|
154
154
|
|
|
155
|
-
NEVER emit an `AskUserQuestion` whose options include {pending, topic, health, revisit}. The user does not pick the mode. If inference is genuinely ambiguous after
|
|
155
|
+
NEVER emit an `AskUserQuestion` whose options include {pending, maintain} (or the legacy {topic, health, revisit} aliases). The user does not pick the mode. If inference is genuinely ambiguous after both steps, default to `pending` and proceed; the user can always cancel and redirect. (rc.37 NEW-12 collapsed the 4 legacy modes to 2: `pending` + `maintain`.)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Shared skill policy — cross-skill canonical core (rc.37 NEW-13)
|
|
2
|
+
|
|
3
|
+
> **Single source of truth** for the policy invariants that fabric-archive,
|
|
4
|
+
> fabric-review, and fabric-import all depend on. Each skill's `ref/` keeps
|
|
5
|
+
> only its skill-specific examples and points here (`../../lib/shared-policy.md`)
|
|
6
|
+
> for the common rules. Edit invariants HERE — never fork them per skill.
|
|
7
|
+
|
|
8
|
+
## 1. Protected tokens — NEVER translated
|
|
9
|
+
|
|
10
|
+
When rendering bilingual (zh-CN ↔ en) output, prose is translated but the
|
|
11
|
+
following classes of token appear **verbatim in both variants**:
|
|
12
|
+
|
|
13
|
+
- **MCP tool + field names**: `fab_extract_knowledge`, `fab_review`,
|
|
14
|
+
`fab_recall`, `fab_plan_context`, `fab_get_knowledge_sections`,
|
|
15
|
+
`relevance_scope`, `relevance_paths`, `source_sessions`, `proposed_reason`,
|
|
16
|
+
`session_context`, `intent_clues`, `tech_stack`, `impact`, `must_read_if`,
|
|
17
|
+
`evidence_paths`, `tags`, `pending_path`, `layer`.
|
|
18
|
+
- **Enum / routing values**: `narrow`, `broad`, `team`, `personal`, `draft`,
|
|
19
|
+
`verified`, `proven`, `knowledge_scope_degraded`.
|
|
20
|
+
- **Imperatives + paths**: `MUST`, `NEVER`, `.fabric/knowledge/`, file paths.
|
|
21
|
+
|
|
22
|
+
The authoritative machine-checked list is `PROTECTED_TOKENS` in
|
|
23
|
+
`@fenglimg/fabric-shared` (enforced by `scripts/lint-protected-tokens.ts`).
|
|
24
|
+
Bilingualization scope is **prose ONLY**.
|
|
25
|
+
|
|
26
|
+
## 2. AskUserQuestion routing-key invariant
|
|
27
|
+
|
|
28
|
+
When any skill issues an `AskUserQuestion`:
|
|
29
|
+
|
|
30
|
+
- `header` + `question` → user-facing prose → **translated** per
|
|
31
|
+
`.fabric/fabric-config.json` → `fabric_language`.
|
|
32
|
+
- `options[]` entries → **routing keys** consumed by the skill's `switch`
|
|
33
|
+
over the returned choice → stay **English** in BOTH variants.
|
|
34
|
+
|
|
35
|
+
Canonical option arrays (English in every locale):
|
|
36
|
+
|
|
37
|
+
- Per-item review action: `["approve", "reject", "modify", "defer", "skip"]`
|
|
38
|
+
- Stale-item action (review health mode): `["defer", "demote", "skip"]`
|
|
39
|
+
- Layer-flip target: `["team", "personal"]`
|
|
40
|
+
|
|
41
|
+
A skill that translates `options[]` MUST then dual-string-match
|
|
42
|
+
(`choice === "approve" || choice === "通过"`); avoid this — keep options
|
|
43
|
+
English so the state machine stays single-string.
|
|
44
|
+
|
|
45
|
+
## 3. Layer heuristic (team vs personal)
|
|
46
|
+
|
|
47
|
+
Default classification when archiving / proposing knowledge:
|
|
48
|
+
|
|
49
|
+
- **强 team** — cross-cutting decisions, architecture, shared pitfalls,
|
|
50
|
+
conventions the whole repo depends on.
|
|
51
|
+
- **强 personal** — individual workflow preferences, local environment quirks,
|
|
52
|
+
notes scoped to one contributor (`KP-*` ids, in-repo `~/.fabric` root).
|
|
53
|
+
- **默认 team** — when ambiguous, default to `team` (shared visibility is the
|
|
54
|
+
safer default; a mis-scoped personal entry hides knowledge from the team).
|
|
55
|
+
|
|
56
|
+
This block is itself a protected token sequence — render `强 team` /
|
|
57
|
+
`强 personal` / `默认 team` verbatim.
|
|
58
|
+
|
|
59
|
+
## 4. Events emit convention
|
|
60
|
+
|
|
61
|
+
Skills persist lifecycle via MCP tools (which emit the canonical events) —
|
|
62
|
+
they do NOT hand-write `.fabric/events.jsonl`:
|
|
63
|
+
|
|
64
|
+
- `fab_extract_knowledge` → `knowledge_proposed` (+ archive-attempt events).
|
|
65
|
+
- `fab_review` approve → `knowledge_promote_started` → `knowledge_promoted`.
|
|
66
|
+
- `fab_review` modify-layer → `knowledge_layer_changed` (+ id-redirect).
|
|
67
|
+
|
|
68
|
+
Never instruct the user to delete or hand-edit the event ledger; it is the
|
|
69
|
+
append-only audit trail. Counter rollups live in `.fabric/metrics.jsonl`.
|