@fenglimg/fabric-cli 2.0.0-rc.33 → 2.0.0-rc.34
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/{chunk-PNRWNUFX.js → chunk-5N3KXIVI.js} +73 -4
- package/dist/index.js +3 -3
- package/dist/{install-YSFVNY3T.js → install-XCRX34CX.js} +4 -2
- package/dist/{uninstall-VLLJG7JT.js → uninstall-Q7V55BXH.js} +1 -1
- package/package.json +3 -3
- package/templates/hooks/cite-policy-evict.cjs +242 -0
- package/templates/hooks/configs/claude-code.json +11 -0
- package/templates/hooks/fabric-hint.cjs +11 -1
- package/templates/hooks/knowledge-hint-broad.cjs +8 -0
- package/templates/skills/fabric-archive/SKILL.md +38 -255
- package/templates/skills/fabric-archive/ref/dry-run-scope.md +16 -0
- package/templates/skills/fabric-review/SKILL.md +55 -413
- package/templates/skills/fabric-review/ref/askuserquestion-policy.md +66 -0
- package/templates/skills/fabric-review/ref/modify-flow.md +95 -0
- package/templates/skills/fabric-review/ref/output-contract.md +58 -0
- package/templates/skills/fabric-review/ref/per-mode-flows.md +155 -0
- package/templates/skills/fabric-review/ref/semantic-check.md +26 -0
|
@@ -4,300 +4,104 @@ description: 归档对话洞察到 .fabric/knowledge/pending (NOT code review).
|
|
|
4
4
|
allowed-tools: Read, Glob, Grep, Bash, mcp__fabric__fab_extract_knowledge
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
> **Surface**:
|
|
7
|
+
> **Surface**: Skill (LLM judgment over session digests). See [`docs/surfaces.md`](https://github.com/fenglimg/fabric/blob/main/docs/surfaces.md).
|
|
8
8
|
|
|
9
9
|
## Precondition
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Invoke this skill ONLY when ONE of the following holds:
|
|
12
12
|
|
|
13
|
-
-
|
|
14
|
-
-
|
|
13
|
+
- Stop-hook printed stdout JSON `{"decision":"block","reason":"..."}` mentioning fabric-archive
|
|
14
|
+
- User typed an explicit archive request (e.g. "archive what we just did", "fabric archive")
|
|
15
15
|
- A task wrap-up moment where the agent itself判定 a worth-keeping insight has surfaced
|
|
16
16
|
|
|
17
|
-
If none
|
|
17
|
+
If none hold, stop the skill and tell the user (UX i18n Policy class 2):
|
|
18
18
|
|
|
19
19
|
- zh-CN: `没有触发归档信号;如需手动归档请显式调用 fabric-archive`
|
|
20
20
|
- en: `No archive signal detected; to manually archive, explicitly invoke fabric-archive`
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
Render per `fabric_language` resolved in Phase 0.5.
|
|
23
23
|
|
|
24
|
-
This skill is `Check-not-Ask`, not a preference interview
|
|
25
|
-
|
|
26
|
-
- **Phase 1.5 (rc.23 F8c) first-run onboard phase** — checks S5 onboard-slot coverage; if unclaimed slots remain, prompts user to fill / dismiss / skip before proceeding to normal archive flow
|
|
27
|
-
- Phase 2 proactively gathers candidate evidence from the session
|
|
28
|
-
- Phase 2.5 viability gate aborts the skill if the session lacks any archive-signal (anti-archive guard)
|
|
29
|
-
- Phase 3 classifies / layers / slugs each candidate and presents one batch review for user correction
|
|
30
|
-
- Phase 3.5 assigns `relevance_scope=narrow|broad` and derives `relevance_paths` from edit history (rc.5 single-signal source)
|
|
31
|
-
- Phase 4 calls `fab_extract_knowledge` once per confirmed candidate
|
|
24
|
+
This skill is `Check-not-Ask`, not a preference interview. Phase 2 proactively gathers evidence; Phase 2.5 viability gate aborts if no archive signal exists; Phase 3 classifies / layers / slugs + batch-review; Phase 4 persists via `fab_extract_knowledge` (one call per candidate).
|
|
32
25
|
|
|
33
26
|
## 执行流程 (1 User Review Round)
|
|
34
27
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
When the skill is invoked, the user's prompt may carry an explicit range hint —
|
|
38
|
-
a time window (`今日` / `last week`), a topic keyword (`rc.20`, `cite policy`),
|
|
39
|
-
or a literal session_id reference. This phase parses those hints and resolves
|
|
40
|
-
them to a concrete `session_id[]` set that constrains Phase 1 cross-session
|
|
41
|
-
digest collection. **Falls through silently** when no hint is detected — Phase
|
|
42
|
-
1 then sees the legacy "all distinct sessions since last anchor" behaviour.
|
|
43
|
-
|
|
44
|
-
This is the foundation of the **E4 (user-language range selection) entry
|
|
45
|
-
point** per rc.25 Q3.3. AI (Claude/Codex) interprets the rules below at runtime
|
|
46
|
-
— there is no parser code; the LLM IS the parser. Time-window patterns +
|
|
47
|
-
keyword extraction are LLM-native tasks; an `AskUserQuestion` fallback covers
|
|
48
|
-
the low-confidence case.
|
|
49
|
-
|
|
50
|
-
#### Confidence decision rule (rc.33 — explicit LLM-as-parser contract)
|
|
51
|
-
|
|
52
|
-
LLM-as-parser commits a result OR falls back to `AskUserQuestion` per these
|
|
53
|
-
deterministic criteria. **Confidence is not a vibe** — it is a checklist.
|
|
54
|
-
|
|
55
|
-
| Confidence | Conditions (ALL must hold) | Action |
|
|
56
|
-
|---|---|---|
|
|
57
|
-
| **HIGH (commit)** | (a) Time-window matches a row in the Step 2 bilingual pattern table verbatim (modulo case); AND (b) Topic-keywords are nouns from Step 3 retention rules (no ambiguous referents like `it`, `这个`); AND (c) No conflicting hints (e.g. `今日` + `上周` co-present) | Commit `time_window` + `topic_keywords[]` → Step 4 |
|
|
58
|
-
| **MEDIUM (commit with audit log)** | Exactly ONE category present (only time-window OR only keywords) AND remaining categories empty (not contradictory) | Commit with single-category filter; emit `low_confidence_parse=false` field |
|
|
59
|
-
| **LOW (AskUserQuestion)** | ANY of: (i) multiple competing time-windows; (ii) numeric N in `过去 N 天` parses outside 1..30; (iii) keyword set after Step 3 stop-word filter is empty BUT prompt clearly carried non-time intent (≥3 residual content words); (iv) literal `session_id=` substring present but malformed (not matching `[a-f0-9-]{36}` UUID); (v) entry = E2/E4 AND patterns yield BOTH time + keywords but they appear in unconnected clauses (LLM-judged separation) | Step 5 fallback (`AskUserQuestion` with structured options) |
|
|
60
|
-
| **PARSE-MISS (silent skip)** | None of above match AND entry ∈ {E1, E3, E5} | Fall through with `range = "all"` sentinel; no user prompt |
|
|
61
|
-
|
|
62
|
-
Implementation note: the LLM's evaluation MUST proceed top-to-bottom — HIGH
|
|
63
|
-
checks first, then MEDIUM, then LOW. The first match wins. Do not skip
|
|
64
|
-
categories or pick LOW preemptively to avoid commitment — that defeats the
|
|
65
|
-
deterministic-parser contract and reintroduces the rc.32 audit P0 (T4) issue.
|
|
66
|
-
|
|
67
|
-
#### Step 1 — Invocation context inspection
|
|
28
|
+
Phase chain: `0 → 0.5 → 1 → [1.5] → 2 → 2.5 → 3 → 3.5 → 4 → 4.5`. Each phase below is a navigator stub — full procedure, decision tables, and worked examples live in `ref/`.
|
|
68
29
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
| Source | Inspection | Yields |
|
|
72
|
-
|---|---|---|
|
|
73
|
-
| User prompt text (the natural-language string that triggered the skill) | Free-form parse for time words + topic keywords + literal `session_id=...` | Candidate `time_window`, `topic_keywords[]`, `explicit_session_ids[]` |
|
|
74
|
-
| Hook-context-marker (only when entry = E1 hook-triggered) | Already-parsed `{count, hours_since_last, sessions_since_last_proposed}` block emitted by archive-hint.cjs | Optional default scope = "since last archive" |
|
|
75
|
-
| User invocation type | E1 / E2 / E3 / E4 / E5 (per rc.25 5-entry model) | Decides whether to fall back to `AskUserQuestion` (E2/E4 only) |
|
|
76
|
-
|
|
77
|
-
If NONE of the three yields a usable hint AND `user_invocation_type ∉ {E2, E4}`,
|
|
78
|
-
fall through directly to Phase 0.5 with `range = "all"` sentinel (legacy
|
|
79
|
-
behaviour). E2 / E4 with no hint → proceed to Step 5 fallback.
|
|
80
|
-
|
|
81
|
-
#### Steps 2-6 (ref-only)
|
|
30
|
+
### Phase 0 — Range Resolution
|
|
82
31
|
|
|
83
|
-
|
|
32
|
+
Parse user's prompt for time-window (`今日` / `last week`), topic keyword (`rc.20`), or literal `session_id` reference; emit `session_id[]` OR `"all"` sentinel that constrains Phase 1 collection. LLM-as-parser contract — no parser code.
|
|
84
33
|
|
|
85
|
-
|
|
34
|
+
`Read ref/phase-0-range-resolution.md` for the HIGH/MEDIUM/LOW/PARSE-MISS confidence decision rule (rc.33), Step 1 inspection table, bilingual time-window patterns (zh-CN + en), topic-keyword extraction, session_id resolution pseudocode, AskUserQuestion fallback (E2/E4 only), and 3 worked examples.
|
|
86
35
|
|
|
87
36
|
### Phase 0.5 — Config Load
|
|
88
37
|
|
|
89
|
-
|
|
90
|
-
`.fabric/fabric-config.json` to resolve the following tunables (with documented
|
|
91
|
-
defaults if absent):
|
|
92
|
-
|
|
93
|
-
| Config field | Default | Used by |
|
|
94
|
-
|---|---|---|
|
|
95
|
-
| `archive_max_candidates_per_batch` | 8 | Phase 2 hard budget on candidates per Phase 3 batch |
|
|
96
|
-
| `archive_max_recent_paths` | 20 | Phase 2 cap on `recent_paths` enumeration |
|
|
97
|
-
| `archive_digest_max_sessions` | 10 | Phase 1 cap on cross-session digest load |
|
|
98
|
-
|
|
99
|
-
If `.fabric/fabric-config.json` is missing or unreadable, use defaults silently.
|
|
38
|
+
Read `.fabric/fabric-config.json`; resolve `archive_max_candidates_per_batch` (default 8), `archive_max_recent_paths` (default 20), `archive_digest_max_sessions` (default 10). Missing file → defaults silently.
|
|
100
39
|
|
|
101
40
|
### UX i18n Policy
|
|
102
41
|
|
|
103
|
-
Read
|
|
104
|
-
|
|
105
|
-
`AskUserQuestion` policy: `header` + `question` translate; `options[]` are routing keys — stay English regardless of locale.
|
|
106
|
-
|
|
107
|
-
**For the full 5-class taxonomy + edge cases:** `Read packages/cli/templates/skills/fabric-archive/ref/i18n-policy.md` (or `.claude/skills/fabric-archive/ref/i18n-policy.md` post-install).
|
|
42
|
+
Read `fabric_language` (`zh-CN` / `en` / `zh-CN-hybrid` / `match-existing`); emit user-facing prose in resolved variant. Protected tokens (MCP tool names, schema fields, the verbatim `强 team` / `强 personal` / `默认 team` heuristic) NEVER translated. `AskUserQuestion` policy: `header` + `question` translate; `options[]` stay English (routing keys).
|
|
108
43
|
|
|
44
|
+
`Read ref/i18n-policy.md` for the full 5-class taxonomy + edge cases.
|
|
109
45
|
|
|
110
46
|
### Phase 1 — Collect Cross-Session Digests
|
|
111
47
|
|
|
112
|
-
Stitch
|
|
48
|
+
Stitch context from every session accumulated since the last `knowledge_proposed` event. Tail-scan `.fabric/events.jsonl` → find anchor → forward-collect distinct `session_id`s → load per-session digests from `.fabric/.cache/session-digests/<session_id>.md` → concatenate into `### Cross-session digest` block, populating `source_sessions[]` + `session_context` for Phase 4. Cap at `archive_digest_max_sessions`.
|
|
113
49
|
|
|
114
|
-
|
|
50
|
+
`Read ref/phase-1-cross-session.md` for the Step 4.5 ledger filter state machine (rules a-f), `ANTI_LOOP_HOURS` / `HIGH_VALUE_EVENT_TYPES` / `NORMATIVE_KEYWORDS` constants, and 3 worked examples (user_dismissed / cooldown / re-scan-with-signal).
|
|
115
51
|
|
|
116
|
-
|
|
117
|
-
2. Walk backward → find most recent `knowledge_proposed` event as anchor (ts lower bound).
|
|
118
|
-
3. Forward-scan from anchor → collect distinct `session_id`s.
|
|
119
|
-
4. Load each `<session_id>.md` digest. Cap at `archive_digest_max_sessions` (default 10).
|
|
120
|
-
4.5. **(rc.25 TASK-05) Apply ledger filter state machine** — drop sessions per outcome ledger: `user_dismissed` (permanent), within 12h cooldown, or no high-value signal past `covered_through_ts`. Cross-session pending dedupe also gates Phase 3 candidate emission.
|
|
121
|
-
5. Concatenate digests into `### Cross-session digest` block; populate `source_sessions[]` + `session_context` for Phase 4.
|
|
122
|
-
|
|
123
|
-
For the full Step 4.5 ledger state machine (rules a-f), `ANTI_LOOP_HOURS` / `HIGH_VALUE_EVENT_TYPES` / `NORMATIVE_KEYWORDS` constants, and 3 worked examples (user_dismissed / cooldown / re-scan-with-signal), `Read packages/cli/templates/skills/fabric-archive/ref/phase-1-cross-session.md` (or `.claude/skills/fabric-archive/ref/phase-1-cross-session.md` post-install).
|
|
124
|
-
|
|
125
|
-
Graceful degradation: missing digest cache → empty context, Phase 2 single-session fallback. Missing `session_archive_attempted` events (pre-rc.25) → Step 4.5 rule (e) applies uniformly (legacy "scan everything since anchor").
|
|
52
|
+
Graceful degradation: missing digest cache → single-session fallback. Missing `session_archive_attempted` events (pre-rc.25) → legacy "scan everything since anchor" behaviour.
|
|
126
53
|
|
|
127
54
|
### Phase 1.5 — First-run Onboard (ref-only)
|
|
128
55
|
|
|
129
|
-
**SKIP this phase entirely unless** entry_point ∈ {E2_explicit_user_invoke, E4_user_range_rollback} AND
|
|
56
|
+
**SKIP this phase entirely unless** entry_point ∈ {E2_explicit_user_invoke, E4_user_range_rollback} AND `fab onboard-coverage --json` reports `missing.length > 0`. For E1/E3/E5, silently fall through to Phase 0.
|
|
130
57
|
|
|
131
|
-
|
|
58
|
+
`Read ref/phase-1-5-onboard.md` for the Step 1-4 coverage check → user prompt → tour-and-propose procedure.
|
|
132
59
|
|
|
133
60
|
### Phase 2 — Collect Candidates
|
|
134
61
|
|
|
135
|
-
Gather raw evidence
|
|
136
|
-
|
|
137
|
-
1. Read the tail of `.fabric/events.jsonl` since the last `knowledge_proposed` event.
|
|
138
|
-
- Use `Bash` with `tail -n 200 .fabric/events.jsonl` if the file is large.
|
|
139
|
-
- Tolerate ENOENT — empty ledger is a normal first-run state.
|
|
140
|
-
2. Enumerate `recent_paths`: workspace files touched by Read/Edit/Write in the current session. Cap at `archive_max_recent_paths` most-recent paths (config-resolved, default 20).
|
|
141
|
-
3. Distill `user_messages_summary`: a compact (≤500 char) prose summary of what the user asked for and what was decided. NOT a verbatim transcript.
|
|
142
|
-
4. Build a candidate list: each candidate is one observation that MIGHT be worth archiving.
|
|
143
|
-
|
|
144
|
-
Hard budget: `archive_max_candidates_per_batch` candidates max per Phase 3 batch (config-resolved, default 8). If more surface, keep the configured-N with strongest worth-archiving signals (see Phase 3 type definitions) and drop the rest.
|
|
62
|
+
Gather raw evidence: tail `.fabric/events.jsonl` since last `knowledge_proposed`; enumerate `recent_paths` (workspace files touched by Read/Edit/Write); distill `user_messages_summary` (≤500 char prose, NOT verbatim transcript); build candidate list. Hard budget: `archive_max_candidates_per_batch` per batch (default 8); drop weaker overage.
|
|
145
63
|
|
|
146
64
|
### Phase 2.5 — Viability Gate (Anti-Archive Guard)
|
|
147
65
|
|
|
148
|
-
Coarse viability check
|
|
149
|
-
|
|
150
|
-
**Archive signals (≥ 1 hit ⇒ gate PASS):**
|
|
151
|
-
|
|
152
|
-
1. Explicit normative language (`always`/`never`/`以后`/`下次注意`/`记一下`/`from now on`/`永远不要`).
|
|
153
|
-
2. Wrong-turn-and-revert (edit-then-undo with diagnosis).
|
|
154
|
-
3. Long diagnostic loop (> 15 min or > ~10 tool turns).
|
|
155
|
-
4. New dependency adoption (package.json / pyproject.toml diff adds dep).
|
|
156
|
-
5. New pattern emergence (named abstraction/convention).
|
|
157
|
-
6. Decision confirmation (≥ 2 alternatives + rationale).
|
|
158
|
-
7. Explicit dismissal-with-reason.
|
|
159
|
-
8. Process formalization (load-bearing step order).
|
|
160
|
-
|
|
161
|
-
**Anti-archive signals (force FAIL unless ≥ 1 archive signal also fires):** typo-only / pure refactor / narrow rename / duplicate-of-existing-canonical.
|
|
162
|
-
|
|
163
|
-
**Gate decision:**
|
|
66
|
+
Coarse viability check. **PASS conditions**: user_explicit_invoke OR ≥1 archive signal hit (normative language, wrong-turn-and-revert, long diagnostic loop, new dependency, new pattern, decision confirmation, dismissal-with-reason, process formalization). **FAIL → branch by entry_point**: E1/E3/E5 silent-skip (emit Phase 4.5 event `outcome='skipped_no_signal'`); E2/E4 render gate-FAIL message (emit `outcome='viability_failed'`).
|
|
164
67
|
|
|
165
|
-
|
|
166
|
-
IF user_explicit_invoke: gate = PASS
|
|
167
|
-
ELIF archive_signals_hit == 0: gate = FAIL (reason="no_signal")
|
|
168
|
-
ELSE: gate = PASS # any archive signal overrides anti-archive
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
**On gate FAIL — branch by entry_point:**
|
|
172
|
-
|
|
173
|
-
- `E1_hook` / `E3_ai_self_trigger` / `E5_cron` → SILENT-SKIP path. No message, no AskUserQuestion. Still emit Phase 4.5 `session_archive_attempted` event with `outcome='skipped_no_signal'`. Exit silently.
|
|
174
|
-
- `E2_explicit` / `E4_user_range` → User-active path. Render gate-FAIL message (i18n class 2, see ref). Emit Phase 4.5 event with `outcome='viability_failed'`. Exit.
|
|
175
|
-
|
|
176
|
-
**On gate PASS:** proceed to Phase 3 with carried-over candidates.
|
|
177
|
-
|
|
178
|
-
For verbose signal explanations, zh-CN/en gate-FAIL message bodies, and the events.jsonl 4KB POSIX atomicity constraint note (single-line + self-truncate rules), `Read packages/cli/templates/skills/fabric-archive/ref/phase-2-5-viability.md` (or `.claude/skills/fabric-archive/ref/phase-2-5-viability.md` post-install).
|
|
68
|
+
`Read ref/phase-2-5-viability.md` for verbose signal definitions, zh-CN/en gate-FAIL message bodies, anti-archive signals (typo / refactor / rename / duplicate), and the events.jsonl 4KB POSIX atomicity constraint.
|
|
179
69
|
|
|
180
70
|
### Phase 3 — Classify, Layer, Slug, Review
|
|
181
71
|
|
|
182
|
-
For each candidate, the
|
|
183
|
-
|
|
184
|
-
- **type** ∈ {model, decision, guideline, pitfall, process}
|
|
185
|
-
- **layer** ∈ {team, personal} via the verbatim heuristic below
|
|
186
|
-
- **slug** per the 5-rule naming guideline below
|
|
187
|
-
- **summary** (1-2 sentences, will become the entry body's lead paragraph)
|
|
188
|
-
|
|
189
|
-
#### Five Knowledge Types
|
|
190
|
-
|
|
191
|
-
`{model, decision, guideline, pitfall, process}` — singular noun = type concept. Pick one type per candidate; skip if none fits (not yet ripe is also a valid outcome).
|
|
192
|
-
|
|
193
|
-
For verbose worth-archive vs skip-it signals per type with positive/negative examples, see `ref/phase-3-classify.md`.
|
|
72
|
+
For each candidate, propose **type** ∈ {model, decision, guideline, pitfall, process}, **layer** ∈ {team, personal} via the verbatim heuristic below, **slug** (kebab-case 2-5 words, 20-40 chars, unique within type+layer bucket), **summary** (1-2 sentences).
|
|
194
73
|
|
|
195
|
-
#### Layer Classification Heuristic (
|
|
74
|
+
#### Layer Classification Heuristic (verbatim, contract-locked)
|
|
196
75
|
|
|
197
76
|
> - **强 team**: 引用本项目代码、团队共识用语("we decided")、fabric-import 路径产物、业务领域、绑定本项目代码的 pitfall
|
|
198
77
|
> - **强 personal**: 第一人称偏好、跨项目通用、工具/编辑器偏好、个人工作流
|
|
199
78
|
> - **默认 team**: 安全偏置——错标 team 在 PR review 中会被发现,错标 personal 静默丢失
|
|
200
79
|
|
|
201
|
-
Resolution
|
|
80
|
+
Resolution: 强 team first; assign personal only if 强 personal dominates AND no 强 team applies; else default team.
|
|
202
81
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
1. kebab-case (lowercase letters, digits, hyphens only).
|
|
206
|
-
2. 2-5 words.
|
|
207
|
-
3. 20-40 chars total.
|
|
208
|
-
4. Semantic core only (drop articles/generics).
|
|
209
|
-
5. Unique within (type, layer) bucket — collisions → add discriminator, NOT counter.
|
|
210
|
-
|
|
211
|
-
Pass/fail examples → see `ref/phase-3-classify.md`.
|
|
212
|
-
|
|
213
|
-
#### Decision Tree
|
|
214
|
-
|
|
215
|
-
```
|
|
216
|
-
Observation worth keeping?
|
|
217
|
-
NO → skip
|
|
218
|
-
YES → fits {model, decision, guideline, pitfall, process}?
|
|
219
|
-
NO → skip (not yet ripe)
|
|
220
|
-
YES → assign type → apply layer heuristic → propose slug
|
|
221
|
-
→ batch review → user confirm → Phase 4: fab_extract_knowledge per candidate
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
#### Batch Review
|
|
225
|
-
|
|
226
|
-
Single-screen presentation of all candidates. UX i18n Policy classes 1 + 3 — structure + `Confirm?` prompt bilingualized; protected tokens verbatim; data values (slugs, paths, enum strings) NOT translated.
|
|
227
|
-
|
|
228
|
-
For en + zh-CN batch review templates with example output, `Read packages/cli/templates/skills/fabric-archive/ref/phase-3-classify.md` (or `.claude/skills/fabric-archive/ref/phase-3-classify.md` post-install).
|
|
229
|
-
|
|
230
|
-
User MAY inline-edit `type` / `layer` / `slug` / `relevance_scope` / `relevance_paths` before confirming. Editing `[relevance_scope=...]` triggers re-derivation per Phase 3.5 (narrow ⇒ recompute from edit_paths; broad ⇒ force `[]`).
|
|
82
|
+
`Read ref/phase-3-classify.md` for per-type worth-archive vs skip signals with positive/negative examples, slug pass/fail samples, decision tree, en + zh-CN batch review templates. User MAY inline-edit `type` / `layer` / `slug` / `relevance_scope` / `relevance_paths` before confirming; scope edits trigger Phase 3.5 re-derivation.
|
|
231
83
|
|
|
232
84
|
### Phase 3.5 — Scope Decision + relevance_paths Derivation
|
|
233
85
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
#### Scope decision (narrow vs broad)
|
|
237
|
-
|
|
238
|
-
```
|
|
239
|
-
relevance_scope =
|
|
240
|
-
narrow IF the candidate is tied to a specific module / file / subsystem
|
|
241
|
-
AND there is explicit single-module evidence in edit_paths
|
|
242
|
-
(i.e. all worth-keeping edits in this session concentrated in one
|
|
243
|
-
module tree, OR the candidate explicitly references that module)
|
|
244
|
-
|
|
245
|
-
broad IF the candidate is cross-cutting / methodological / general
|
|
246
|
-
(applies regardless of which path the agent is working in)
|
|
247
|
-
|
|
248
|
-
broad (default, on uncertainty — safe偏置 per Q-1 in handoff)
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
Special case — Personal layer ALWAYS resolves to `relevance_scope=broad` with `relevance_paths=[]`. Rationale: personal knowledge crosses projects; paths from one project do not generalize. If `layer=personal` and a narrow scope was tentatively chosen, auto-flip to `broad` and clear `relevance_paths`.
|
|
252
|
-
|
|
253
|
-
##### Examples
|
|
254
|
-
|
|
255
|
-
- `decision: single-cjs-hook-script` → `narrow` (tied to `templates/claude-hooks/` + `packages/cli/src/commands/hooks.ts`)
|
|
256
|
-
- `pitfall: deepmerge-array-replace-trap` → `broad` (cross-cutting JSON merge gotcha, applies anywhere deepMerge is used)
|
|
257
|
-
- `guideline: slug-naming-rules` → `broad` (methodology, no specific module)
|
|
258
|
-
- `model: wave-1-parallel-task-dag` → `narrow` (tied to `packages/cli/src/commands/plan.ts`)
|
|
259
|
-
- `guideline: indent-style-by-language` (personal layer) → `broad + []` (personal forces broad)
|
|
260
|
-
|
|
261
|
-
#### relevance_paths derivation (rc.5 single-signal: edit_paths)
|
|
86
|
+
Assign `relevance_scope` ∈ {narrow, broad} + derive `relevance_paths` BEFORE batch review. **narrow** = candidate tied to specific module/file with single-module evidence in edit_paths; **broad** = cross-cutting/methodological/general (default on uncertainty). **Personal layer ALWAYS forces broad + `relevance_paths=[]`** (cross-project, paths don't generalize).
|
|
262
87
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
1. COLLECT edit_paths from session transcript.
|
|
266
|
-
2. DEDUPE.
|
|
267
|
-
3. BLACKLIST FILTER (drop repo-root single files like README.md, package.json; drop trivial `**/*.<ext>` globs; drop read-only paths).
|
|
268
|
-
4. PUBLIC-PREFIX GENERALIZE (group ≥ 2 siblings into glob, depth ≤ 2; singletons kept literal).
|
|
269
|
-
5. SCOPE GATE (broad → force `[]`; narrow → use Step 4 result).
|
|
270
|
-
6. ATTACH READ-ONLY EVIDENCE as `## Evidence` block (NOT in relevance_paths).
|
|
271
|
-
|
|
272
|
-
For full pseudocode, a worked generalization example (5 sample paths → glob + literal output), and inline-edit re-derivation rules (narrow↔broad transitions), `Read packages/cli/templates/skills/fabric-archive/ref/phase-3-5-scope.md` (or `.claude/skills/fabric-archive/ref/phase-3-5-scope.md` post-install).
|
|
88
|
+
`Read ref/phase-3-5-scope.md` for the 6-step relevance_paths derivation pseudocode (COLLECT → DEDUPE → BLACKLIST → PUBLIC-PREFIX GENERALIZE → SCOPE GATE → ATTACH READ-ONLY EVIDENCE), worked example (5 sample paths → glob + literal output), and narrow↔broad inline-edit re-derivation rules.
|
|
273
89
|
|
|
274
90
|
### Phase 4 — Persist via MCP
|
|
275
91
|
|
|
276
|
-
For each user-confirmed candidate, call `fab_extract_knowledge` ONCE.
|
|
277
|
-
|
|
278
|
-
#### Output Contract (essentials)
|
|
279
|
-
|
|
280
|
-
`fab_extract_knowledge` call carries: `source_sessions[]` (T5 array), `recent_paths[]` (cap 20), `user_messages_summary` (≤500 chars), `type` ∈ {decisions, pitfalls, guidelines, models, processes} (plural directory-form), `slug` (kebab-case 2-5 words), `layer` ∈ {team, personal}, `relevance_scope` ∈ {narrow, broad}, `relevance_paths[]` (narrow ⇒ derived; broad ⇒ `[]`), `proposed_reason` (enum: `explicit-user-mark` | `diagnostic-then-fix` | `decision-confirmation` | `wrong-turn-revert` | `new-dependency-or-pattern` | `dismissal-with-reason`), `session_context` (3-5 line narrative).
|
|
92
|
+
For each user-confirmed candidate, call `fab_extract_knowledge` ONCE (NEVER batch). Required: `source_sessions[]`, `recent_paths[]` (cap 20), `user_messages_summary`, `type` (plural form: decisions/pitfalls/guidelines/models/processes), `slug`, `layer`, `relevance_scope`, `relevance_paths[]`, `proposed_reason` (enum), `session_context` (3-5 line narrative). Four OPTIONAL rc.23 triage fields (`intent_clues`, `tech_stack`, `impact`, `must_read_if`) — populate when clean, **omit rather than guess**.
|
|
281
93
|
|
|
282
|
-
|
|
94
|
+
Server returns `{ pending_path, idempotency_key }`. Display `pending_path` for the user. `idempotency_key = sha256({source_session, type, slug})` — repeated calls SAFE (server merges evidence).
|
|
283
95
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
Server returns `{ pending_path, idempotency_key }`. Display `pending_path` for the user. `idempotency_key = sha256({source_session, type, slug})` — calling twice with the same triple is SAFE (server merges evidence).
|
|
96
|
+
`Read ref/phase-4-mcp-persist.md` for full TypeScript call shape, C1 triage-field inference table, Phase 2.5 signal → `proposed_reason` mapping, `session_context` format, T5 array-form idempotency notes.
|
|
287
97
|
|
|
288
98
|
### Phase 4.5 — Persist Archive Attempt
|
|
289
99
|
|
|
290
|
-
MANDATORY closing step on
|
|
291
|
-
|
|
292
|
-
#### Dry-run override
|
|
293
|
-
|
|
294
|
-
See the unified `## Dry-run Scope` section at the end of this file for the full catalogue of writes suspended in dry-run mode. Summary for Phase 4.5: dry-run SKIPS the `session_archive_attempted` emit entirely; the read-side machinery (Phase 1 digest, Phase 2.5 gate, Phase 3 preview) runs normally so the user sees what WOULD have been written.
|
|
295
|
-
|
|
296
|
-
#### Event emission summary
|
|
100
|
+
MANDATORY closing step on EVERY invocation (Phase 4 success path + every early-exit). Append ONE `session_archive_attempted` line to `.fabric/events.jsonl` per `session_id` in run scope (single-line JSON ≤4KB POSIX atomicity). Outcome ∈ {`proposed` | `viability_failed` | `user_dismissed` | `skipped_no_signal`}. `covered_through_ts` = max ts of events examined. Best-effort write: failure → stderr log only, skill still exits successfully.
|
|
297
101
|
|
|
298
|
-
|
|
102
|
+
**Dry-run override**: SKIPS the `session_archive_attempted` emit entirely; read-side runs normally so user previews what WOULD have been written. See unified `## Dry-run Scope` pointer below.
|
|
299
103
|
|
|
300
|
-
|
|
104
|
+
`Read ref/phase-4-5-emit.md` for the full event jsonc shape, 4-state outcome decision matrix (outcome × candidates_proposed × knowledge_proposed_ids), `covered_through_ts` watermark spec, multi-session emission rule, bash echo append pattern, and E5-cron silent-skip worked trace.
|
|
301
105
|
|
|
302
106
|
## Hard Rules (DO NOT TRANSLATE) — DISPLAY / WRITE Split
|
|
303
107
|
|
|
@@ -327,29 +131,8 @@ For the full jsonc event shape, the outcome decision matrix (4 terminal states
|
|
|
327
131
|
- NEVER paraphrase the verbatim layer heuristic block above — the Chinese text is contract-locked.
|
|
328
132
|
- MUST preserve protected tokens exactly: `stable_id`, `knowledge_proposed`, `knowledge_archive_aborted`, `knowledge_scope_degraded`, `.fabric/knowledge/pending/`, `fab_extract_knowledge`, `relevance_paths`, `relevance_scope`, `narrow`, `broad`, `edit_paths`, `source_sessions`, `proposed_reason`, `session_context`, `intent_clues`, `tech_stack`, `impact`, `must_read_if`, `pending_path`, `layer`, `team`, `personal`, `MUST`, `NEVER`, `强 team`, `强 personal`, `默认 team`.
|
|
329
133
|
|
|
330
|
-
## Worked Examples (ref-only)
|
|
331
|
-
|
|
332
|
-
Three end-to-end fab_extract_knowledge call examples (decision/team, pitfall/team, guideline/personal) live in `packages/cli/templates/skills/fabric-archive/ref/worked-examples.md` (or `.claude/skills/fabric-archive/ref/worked-examples.md` post-install). Load when you want to see all required + optional fields populated together in a realistic shape.
|
|
333
|
-
|
|
334
|
-
## E5 Scheduled Daily Recap (ref-only)
|
|
335
|
-
|
|
336
|
-
Only relevant when entry_point=E5_cron (OS cron, `/loop`, or scheduled trigger). For interactive invocations, Phase 0 has already routed past this — nothing to load.
|
|
337
|
-
|
|
338
|
-
When E5 fires: `Read packages/cli/templates/skills/fabric-archive/ref/e5-cron-recap.md` (or `.claude/skills/fabric-archive/ref/e5-cron-recap.md` post-install) for `/loop` vs OS cron tradeoffs + the `今日复盘` magic-phrase parse contract.
|
|
339
|
-
|
|
340
|
-
## Dry-run Scope (unified)
|
|
341
|
-
|
|
342
|
-
`dry_run = true` (per Phase 4.5 detection rule — substring match on `--dry-run` | `dry-run` | `dry_run` | `预览` token) suspends ALL side-effecting writes below; read-side machinery (Phase 1 digest collection, Phase 2.5 viability gate evaluation, Phase 3 candidate render) executes normally so the user can preview what WOULD happen.
|
|
343
|
-
|
|
344
|
-
| Write operation | Normal mode | Dry-run mode |
|
|
345
|
-
|---|---|---|
|
|
346
|
-
| `fab_extract_knowledge` MCP call (Phase 4) | One call per confirmed candidate, writes to `.fabric/knowledge/pending/<slug>.md` | SKIPPED. Phase 4 renders "would write N pending entries" preview table instead. |
|
|
347
|
-
| `session_archive_attempted` event (Phase 4.5) | Appended to `.fabric/events.jsonl` for every session in scope | SKIPPED entirely. No ledger entry. |
|
|
348
|
-
| `fab_review reject` (Phase 3 user-dismissed branch) | Invoked when user types `撤销` / `reject` after self-archive proposal | SKIPPED. The dismissal is rendered to console but no MCP write occurs. |
|
|
349
|
-
| `fab onboard-coverage` slot writes (Phase 1.5 fill-all / dismiss-all) | Each `Bash("fab config dismiss-slot <slot>")` invocation runs | SKIPPED. Slot decisions are shown as "would dismiss/propose" preview. |
|
|
350
|
-
| `.fabric/.cache/session-digests/<session_id>.md` reads | Read freely (read-side, safe) | Read freely — same as normal. |
|
|
351
|
-
| Stop-hook / archive-hint stdin/stdout | Read-only inspection of `.fabric/events.jsonl` | Same — no change. |
|
|
352
|
-
|
|
353
|
-
All user-facing output in dry-run mode MUST prefix `[DRY-RUN]` at the start of each Phase header (e.g. `[DRY-RUN] Phase 3 — Batch Review`). Exit message: `[DRY-RUN complete] would have written N entry/entries; no .fabric/ files were modified. Re-invoke without --dry-run to commit.`
|
|
134
|
+
## Worked Examples / E5 Cron / Dry-run (ref-only)
|
|
354
135
|
|
|
355
|
-
|
|
136
|
+
- **Worked examples** (3 end-to-end fab_extract_knowledge calls: decision/team, pitfall/team, guideline/personal): `Read ref/worked-examples.md`
|
|
137
|
+
- **E5 Scheduled Daily Recap** (only when entry_point=E5_cron — OS cron, `/loop`, or scheduled trigger): `Read ref/e5-cron-recap.md`
|
|
138
|
+
- **Dry-run Scope** (authoritative catalogue of all writes suspended by `--dry-run`): `Read ref/dry-run-scope.md`
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Dry-run Scope (unified)
|
|
2
|
+
|
|
3
|
+
`dry_run = true` (per Phase 4.5 detection rule — substring match on `--dry-run` | `dry-run` | `dry_run` | `预览` token) suspends ALL side-effecting writes below; read-side machinery (Phase 1 digest collection, Phase 2.5 viability gate evaluation, Phase 3 candidate render) executes normally so the user can preview what WOULD happen.
|
|
4
|
+
|
|
5
|
+
| Write operation | Normal mode | Dry-run mode |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| `fab_extract_knowledge` MCP call (Phase 4) | One call per confirmed candidate, writes to `.fabric/knowledge/pending/<slug>.md` | SKIPPED. Phase 4 renders "would write N pending entries" preview table instead. |
|
|
8
|
+
| `session_archive_attempted` event (Phase 4.5) | Appended to `.fabric/events.jsonl` for every session in scope | SKIPPED entirely. No ledger entry. |
|
|
9
|
+
| `fab_review reject` (Phase 3 user-dismissed branch) | Invoked when user types `撤销` / `reject` after self-archive proposal | SKIPPED. The dismissal is rendered to console but no MCP write occurs. |
|
|
10
|
+
| `fab onboard-coverage` slot writes (Phase 1.5 fill-all / dismiss-all) | Each `Bash("fab config dismiss-slot <slot>")` invocation runs | SKIPPED. Slot decisions are shown as "would dismiss/propose" preview. |
|
|
11
|
+
| `.fabric/.cache/session-digests/<session_id>.md` reads | Read freely (read-side, safe) | Read freely — same as normal. |
|
|
12
|
+
| Stop-hook / archive-hint stdin/stdout | Read-only inspection of `.fabric/events.jsonl` | Same — no change. |
|
|
13
|
+
|
|
14
|
+
All user-facing output in dry-run mode MUST prefix `[DRY-RUN]` at the start of each Phase header (e.g. `[DRY-RUN] Phase 3 — Batch Review`). Exit message: `[DRY-RUN complete] would have written N entry/entries; no .fabric/ files were modified. Re-invoke without --dry-run to commit.`
|
|
15
|
+
|
|
16
|
+
Cross-reference: Phase 4.5 `Dry-run override` section in SKILL.md holds the rationale. When adding a new write side-effect to any phase, update BOTH the phase section AND this table.
|