@fenglimg/fabric-cli 2.0.0-rc.11 → 2.0.0-rc.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/dist/chunk-AIB54QRT.js +82 -0
- package/dist/{chunk-5MQ52F42.js → chunk-AXIFEVAS.js} +16 -219
- package/dist/{chunk-WWNXR34K.js → chunk-G2CIOLD4.js} +16 -1
- package/dist/{chunk-HQLEHH4O.js → chunk-SKSYUHKK.js} +267 -40
- package/dist/chunk-UTF4YBDN.js +366 -0
- package/dist/config-7YD365I3.js +13 -0
- package/dist/{doctor-RILCO5OG.js → doctor-6XHLQJXB.js} +67 -50
- package/dist/index.js +8 -9
- package/dist/{init-C56PWHID.js → install-JLDCHAXV.js} +409 -416
- package/dist/{plan-context-hint-QMUPAXIB.js → plan-context-hint-73U4FGKO.js} +6 -1
- package/dist/{serve-NGLXHDYC.js → serve-L3X5UHG2.js} +15 -10
- package/dist/{uninstall-DBAR2JBS.js → uninstall-DD6FIFCI.js} +81 -179
- package/package.json +3 -3
- package/templates/hooks/configs/README.md +10 -6
- package/templates/hooks/configs/cursor-hooks.json +7 -10
- package/templates/hooks/knowledge-hint-broad.cjs +28 -107
- package/templates/skills/fabric-archive/SKILL.md +15 -15
- package/templates/skills/fabric-import/SKILL.md +26 -26
- package/templates/skills/fabric-review/SKILL.md +19 -19
- package/dist/chunk-AW3G7ZH5.js +0 -576
- package/dist/chunk-WPTA74BY.js +0 -184
- package/dist/hooks-NX32PPEN.js +0 -13
- package/dist/scan-66EKMNAY.js +0 -24
|
@@ -49,41 +49,22 @@
|
|
|
49
49
|
const { spawnSync } = require("node:child_process");
|
|
50
50
|
const {
|
|
51
51
|
existsSync,
|
|
52
|
-
mkdirSync,
|
|
53
52
|
readdirSync,
|
|
54
53
|
readFileSync,
|
|
55
|
-
writeFileSync,
|
|
56
54
|
} = require("node:fs");
|
|
57
|
-
const {
|
|
55
|
+
const { join } = require("node:path");
|
|
58
56
|
|
|
59
57
|
// -----------------------------------------------------------------------------
|
|
60
|
-
// rc.
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
// update sidecar.
|
|
68
|
-
//
|
|
69
|
-
// The revision_hash is supplied by `fabric plan-context-hint --all`'s JSON
|
|
70
|
-
// payload (carried in payload.revision_hash since rc.5). Reusing the existing
|
|
71
|
-
// hash primitive keeps the gating predicate exactly aligned with the "is the
|
|
72
|
-
// knowledge graph different from last time?" question — no second hashing
|
|
73
|
-
// scheme to maintain. computeRevisionHash() is not needed at this layer; we
|
|
74
|
-
// compare the strings the CLI hands us.
|
|
75
|
-
//
|
|
76
|
-
// rc.8 underseed self-check: the retired `.fabric/.import-requested` sentinel
|
|
77
|
-
// mechanism is replaced by a deterministic three-condition probe in
|
|
78
|
-
// shouldRecommendImport(). When the probe says "recommend", a one-line
|
|
79
|
-
// `/fabric-import` banner is appended to the broad-injection output and
|
|
80
|
-
// the revision_hash gate is bypassed FOR THE BANNER ONLY (the broad-summary
|
|
81
|
-
// body itself remains hash-gated). See shouldRecommendImport() below for
|
|
82
|
-
// the full truth table.
|
|
58
|
+
// rc.12: SessionStart broad-menu is now unconditionally emitted on every
|
|
59
|
+
// SessionStart fire (matching Skill-style progressive disclosure). Prior
|
|
60
|
+
// versions (rc.5-rc.11) wrote `.fabric/.cache/sessionstart-last-hash` as a
|
|
61
|
+
// revision_hash cooldown sidecar to suppress re-emission on unchanged
|
|
62
|
+
// knowledge graphs; that gate was removed in rc.12. Orphaned sidecar files
|
|
63
|
+
// on existing dogfood repos are harmless dead state and are intentionally
|
|
64
|
+
// NOT cleaned up (zero-user clean-slate — no migration logic needed).
|
|
83
65
|
// -----------------------------------------------------------------------------
|
|
84
66
|
|
|
85
67
|
const FABRIC_DIR_REL = ".fabric";
|
|
86
|
-
const SESSIONSTART_HASH_CACHE_FILE = join(".fabric", ".cache", "sessionstart-last-hash");
|
|
87
68
|
|
|
88
69
|
// rc.8 underseed self-check constants (mirror fabric-hint.cjs ~line 76 / 83).
|
|
89
70
|
// Intentionally duplicated inline — hooks are independent .cjs files and
|
|
@@ -102,41 +83,6 @@ const KNOWLEDGE_CANONICAL_TYPES = [
|
|
|
102
83
|
];
|
|
103
84
|
const DEFAULT_UNDERSEED_NODE_THRESHOLD = 10;
|
|
104
85
|
|
|
105
|
-
/**
|
|
106
|
-
* Read the previously-emitted revision_hash from
|
|
107
|
-
* `.fabric/.cache/sessionstart-last-hash`. Missing file / read failure /
|
|
108
|
-
* empty file → null (treat as "no prior emit", forces re-emit).
|
|
109
|
-
*
|
|
110
|
-
* NEVER throws — best-effort read.
|
|
111
|
-
*/
|
|
112
|
-
function readSessionStartLastHash(projectRoot) {
|
|
113
|
-
try {
|
|
114
|
-
const p = join(projectRoot, SESSIONSTART_HASH_CACHE_FILE);
|
|
115
|
-
if (!existsSync(p)) return null;
|
|
116
|
-
const raw = readFileSync(p, "utf8").trim();
|
|
117
|
-
return raw.length > 0 ? raw : null;
|
|
118
|
-
} catch {
|
|
119
|
-
return null;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Write `hash` to `.fabric/.cache/sessionstart-last-hash` so subsequent
|
|
125
|
-
* SessionStart fires can compare. Creates the directory if missing.
|
|
126
|
-
* Best-effort: any write failure is swallowed so a read-only .fabric/
|
|
127
|
-
* never blocks session start.
|
|
128
|
-
*/
|
|
129
|
-
function writeSessionStartLastHash(projectRoot, hash) {
|
|
130
|
-
try {
|
|
131
|
-
if (typeof hash !== "string" || hash.length === 0) return;
|
|
132
|
-
const p = join(projectRoot, SESSIONSTART_HASH_CACHE_FILE);
|
|
133
|
-
mkdirSync(dirname(p), { recursive: true });
|
|
134
|
-
writeFileSync(p, hash, "utf8");
|
|
135
|
-
} catch {
|
|
136
|
-
// Silent — sidecar failure must never block session start.
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
86
|
// -----------------------------------------------------------------------------
|
|
141
87
|
// rc.8 underseed self-check helpers.
|
|
142
88
|
//
|
|
@@ -488,15 +434,21 @@ function renderTruncated(narrow) {
|
|
|
488
434
|
* (empty narrow set) so callers know to stay silent.
|
|
489
435
|
*/
|
|
490
436
|
function renderSummary(payload) {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
437
|
+
// Local rebind: `payload.narrow` in `--all` mode degenerates to the full
|
|
438
|
+
// shared index (every broad-scoped entry), so the field name `narrow` is
|
|
439
|
+
// misleading at this rendering layer. We rename the local variable to
|
|
440
|
+
// `entries` to avoid name confusion when reading renderSummary in isolation.
|
|
441
|
+
// The CLI protocol field name (`payload.narrow`) is unchanged — a wire-shape
|
|
442
|
+
// rename is a deferred independent task.
|
|
443
|
+
const entries = Array.isArray(payload && payload.narrow) ? payload.narrow : [];
|
|
444
|
+
if (entries.length === 0) return [];
|
|
445
|
+
|
|
446
|
+
const truncated = entries.length > TRUNCATION_THRESHOLD;
|
|
495
447
|
const banner = truncated
|
|
496
|
-
? `[fabric] Session start — ${
|
|
497
|
-
: `[fabric] Session start — ${
|
|
448
|
+
? `[fabric] Session start — ${entries.length} broad-scoped knowledge entries available (truncated):`
|
|
449
|
+
: `[fabric] Session start — ${entries.length} broad-scoped knowledge entries available:`;
|
|
498
450
|
|
|
499
|
-
const body = truncated ? renderTruncated(
|
|
451
|
+
const body = truncated ? renderTruncated(entries) : renderFull(entries);
|
|
500
452
|
|
|
501
453
|
const lines = [banner, ...body];
|
|
502
454
|
const revHash = typeof payload.revision_hash === "string" ? payload.revision_hash : null;
|
|
@@ -524,32 +476,15 @@ function main(env, stdio) {
|
|
|
524
476
|
if (payload === null || payload === undefined) return; // silent
|
|
525
477
|
|
|
526
478
|
// rc.8 underseed self-check: decide whether to surface the one-line
|
|
527
|
-
// `/fabric-import` recommendation
|
|
528
|
-
// revision_hash gate so the banner can bypass it (an unchanged
|
|
529
|
-
// knowledge graph would otherwise hide the recommendation forever).
|
|
530
|
-
// The broad-summary BODY itself remains hash-gated below — only the
|
|
531
|
-
// banner line is unconditionally emitted when the probe says so.
|
|
479
|
+
// `/fabric-import` recommendation banner alongside the broad summary.
|
|
532
480
|
const recommendImport = shouldRecommendImport(cwd);
|
|
533
481
|
|
|
534
|
-
// rc.
|
|
535
|
-
//
|
|
536
|
-
//
|
|
537
|
-
//
|
|
538
|
-
//
|
|
539
|
-
const
|
|
540
|
-
typeof payload.revision_hash === "string" ? payload.revision_hash : "";
|
|
541
|
-
let bodySuppressed = false;
|
|
542
|
-
if (currentHash.length > 0) {
|
|
543
|
-
const lastHash = readSessionStartLastHash(cwd);
|
|
544
|
-
if (lastHash !== null && lastHash === currentHash) {
|
|
545
|
-
bodySuppressed = true;
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
// Build emitted lines. When the body is hash-suppressed we skip the
|
|
550
|
-
// broad summary entirely; only the import banner (if applicable) goes
|
|
551
|
-
// to stderr in that case.
|
|
552
|
-
const lines = bodySuppressed ? [] : renderSummary(payload);
|
|
482
|
+
// rc.12: broad-summary body is unconditionally rendered on every
|
|
483
|
+
// SessionStart fire (Skill-style progressive disclosure). The prior
|
|
484
|
+
// revision_hash cooldown gate (rc.7 T8 — rc.11) was removed because
|
|
485
|
+
// compact/clear-triggered SessionStart re-fires must re-inject the menu
|
|
486
|
+
// for the agent's working memory.
|
|
487
|
+
const lines = renderSummary(payload);
|
|
553
488
|
|
|
554
489
|
if (recommendImport) {
|
|
555
490
|
lines.push(IMPORT_RECOMMENDATION_BANNER);
|
|
@@ -560,16 +495,6 @@ function main(env, stdio) {
|
|
|
560
495
|
for (const line of lines) {
|
|
561
496
|
err.write(`${line}\n`);
|
|
562
497
|
}
|
|
563
|
-
|
|
564
|
-
// Update sidecar AFTER successful emit. We only persist the hash when
|
|
565
|
-
// the broad-summary body actually went out (i.e. the gate let the body
|
|
566
|
-
// through). If the body was suppressed but the banner emitted on its
|
|
567
|
-
// own, we deliberately do NOT bump the sidecar — the next session
|
|
568
|
-
// should still get to compare against the prior canonical-graph hash
|
|
569
|
-
// and re-emit the body when the graph actually changes.
|
|
570
|
-
if (!bodySuppressed && currentHash.length > 0) {
|
|
571
|
-
writeSessionStartLastHash(cwd, currentHash);
|
|
572
|
-
}
|
|
573
498
|
} catch {
|
|
574
499
|
// Silent — never block session start on hook failure.
|
|
575
500
|
}
|
|
@@ -583,9 +508,6 @@ module.exports = {
|
|
|
583
508
|
renderTruncated,
|
|
584
509
|
renderSummary,
|
|
585
510
|
truncateSummary,
|
|
586
|
-
// rc.7 T8: revision_hash gating sidecar helpers (exported for unit testing).
|
|
587
|
-
readSessionStartLastHash,
|
|
588
|
-
writeSessionStartLastHash,
|
|
589
511
|
// rc.8 underseed self-check helpers (exported for unit testing).
|
|
590
512
|
countCanonicalNodes,
|
|
591
513
|
readUnderseedThreshold,
|
|
@@ -599,7 +521,6 @@ module.exports = {
|
|
|
599
521
|
MATURITY_PROVEN,
|
|
600
522
|
MATURITY_VERIFIED,
|
|
601
523
|
MATURITY_DRAFT,
|
|
602
|
-
SESSIONSTART_HASH_CACHE_FILE,
|
|
603
524
|
DEFAULT_UNDERSEED_NODE_THRESHOLD,
|
|
604
525
|
KNOWLEDGE_CANONICAL_TYPES,
|
|
605
526
|
IMPORT_RECOMMENDATION_BANNER,
|
|
@@ -19,7 +19,7 @@ If none of the above hold, stop the skill immediately and tell the user (UX i18n
|
|
|
19
19
|
- zh-CN: `没有触发归档信号;如需手动归档请显式调用 fabric-archive`
|
|
20
20
|
- en: `No archive signal detected; to manually archive, explicitly invoke fabric-archive`
|
|
21
21
|
|
|
22
|
-
(Render per `
|
|
22
|
+
(Render per `fabric_language` resolved in Phase 0.6 Config Load below.)
|
|
23
23
|
|
|
24
24
|
This skill is `Check-not-Ask`, not a preference interview:
|
|
25
25
|
|
|
@@ -47,9 +47,10 @@ If `.fabric/fabric-config.json` is missing or unreadable, use defaults silently.
|
|
|
47
47
|
|
|
48
48
|
### UX i18n Policy (5-class bilingualization)
|
|
49
49
|
|
|
50
|
-
The skill consults `
|
|
50
|
+
The skill consults `fabric_language` from `.fabric/fabric-config.json`
|
|
51
51
|
(固化于 init 时,via `scan.ts:detectExistingLanguage`; default `"en"` when no
|
|
52
|
-
CJK signal is detected in README + docs
|
|
52
|
+
CJK signal is detected in README + docs/; may resolve to `"match-existing"`,
|
|
53
|
+
`"zh-CN"`, `"en"`, or `"zh-CN-hybrid"`). All user-facing text in the
|
|
53
54
|
following 5 categories MUST be rendered in the resolved language:
|
|
54
55
|
|
|
55
56
|
1. **Roll-up templates** — the `# Archive Review — N candidates` batch
|
|
@@ -73,11 +74,10 @@ following 5 categories MUST be rendered in the resolved language:
|
|
|
73
74
|
|
|
74
75
|
Rendering rule:
|
|
75
76
|
|
|
76
|
-
- `
|
|
77
|
-
- `
|
|
78
|
-
-
|
|
79
|
-
|
|
80
|
-
or fully en.
|
|
77
|
+
- `fabric_language === "zh-CN"` → emit the zh-CN variant; pure monolingual, no language mixing inside a single user-facing block.
|
|
78
|
+
- `fabric_language === "en"` → emit the en variant; pure monolingual, no language mixing inside a single user-facing block.
|
|
79
|
+
- `fabric_language === "zh-CN-hybrid"` → emit Chinese narrative prose with English technical terms preserved. Protected tokens (always EN): MCP tool names (e.g. `fab_get_knowledge_sections`), CLI command names (e.g. `fab install`), file paths, technical concepts (`Skill`, `SessionStart`, `hook`, `MCP`, `revision_hash`, `pending`, `proven`, `verified`, `draft`).
|
|
80
|
+
- `fabric_language === "match-existing"` or any other value → emit the en variant; pure monolingual.
|
|
81
81
|
|
|
82
82
|
Protected tokens (`fab_extract_knowledge`, `relevance_scope`,
|
|
83
83
|
`relevance_paths`, `narrow`, `broad`, `source_sessions`, `proposed_reason`,
|
|
@@ -91,21 +91,21 @@ bilingualization scope is prose ONLY.
|
|
|
91
91
|
|
|
92
92
|
When a skill (this one or any sibling skill the user is composing with)
|
|
93
93
|
issues an `AskUserQuestion`, the `header` and `question` strings are
|
|
94
|
-
user-facing prose → translated per `
|
|
94
|
+
user-facing prose → translated per `fabric_language`. The `options[]`
|
|
95
95
|
array entries (e.g. `["approve", "reject", "modify", "defer", "skip"]` in
|
|
96
96
|
fabric-review, or `["team", "personal"]` for a layer-flip target) are
|
|
97
97
|
**routing keys** consumed by the skill state machine — they MUST remain
|
|
98
|
-
English regardless of `
|
|
98
|
+
English regardless of `fabric_language`.
|
|
99
99
|
|
|
100
100
|
```ts
|
|
101
|
-
// EN (
|
|
101
|
+
// EN (fabric_language === "en")
|
|
102
102
|
AskUserQuestion({
|
|
103
103
|
header: "Layer-flip target",
|
|
104
104
|
question: "Move '{title}' to which layer? (current: {current_layer})",
|
|
105
105
|
options: ["team", "personal"]
|
|
106
106
|
})
|
|
107
107
|
|
|
108
|
-
// zh-CN (
|
|
108
|
+
// zh-CN (fabric_language === "zh-CN")
|
|
109
109
|
AskUserQuestion({
|
|
110
110
|
header: "Layer 切换目标",
|
|
111
111
|
question: "将 '{title}' 切换到哪一层?(当前: {current_layer})",
|
|
@@ -214,7 +214,7 @@ ELSE:
|
|
|
214
214
|
|
|
215
215
|
#### On gate FAIL
|
|
216
216
|
|
|
217
|
-
Stop the skill with the gate-FAIL message (UX i18n Policy class 2 — errors/preconditions; render per `
|
|
217
|
+
Stop the skill with the gate-FAIL message (UX i18n Policy class 2 — errors/preconditions; render per `fabric_language`):
|
|
218
218
|
|
|
219
219
|
zh-CN variant:
|
|
220
220
|
|
|
@@ -317,7 +317,7 @@ Recent session contains an observation worth keeping?
|
|
|
317
317
|
|
|
318
318
|
Present all candidates in a single screen. UX i18n Policy classes 1 + 3 — the roll-up structure AND the per-candidate `Confirm?` prompt are bilingualized; protected tokens (`relevance_scope`, `relevance_paths`, `narrow`, `broad`, `layer`, `team`, `personal`, `pending_path`, etc.) appear verbatim in BOTH variants. Field VALUES (slugs, file paths, type/layer enum strings like `decision` / `team`) are data and are NOT translated.
|
|
319
319
|
|
|
320
|
-
en variant (`
|
|
320
|
+
en variant (`fabric_language === "en"`):
|
|
321
321
|
|
|
322
322
|
```md
|
|
323
323
|
# Archive Review — N candidates
|
|
@@ -337,7 +337,7 @@ relevance_paths: []
|
|
|
337
337
|
Confirm? ...
|
|
338
338
|
```
|
|
339
339
|
|
|
340
|
-
zh-CN variant (`
|
|
340
|
+
zh-CN variant (`fabric_language === "zh-CN"`):
|
|
341
341
|
|
|
342
342
|
```md
|
|
343
343
|
# 归档 Review — N 条候选
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: fabric-import
|
|
3
|
-
description: Use this skill for cold-start enrichment of `.fabric/knowledge/` from existing project artifacts — mines `git log` and `docs/*.md` for candidate observations, proposes pending entries via `fab_extract_knowledge`, then deduplicates against canonical entries via `fab_review action
|
|
3
|
+
description: Use this skill for cold-start enrichment of `.fabric/knowledge/` from existing project artifacts — mines `git log` and `docs/*.md` for candidate observations, proposes pending entries via `fab_extract_knowledge`, then deduplicates against canonical entries via `fab_review action=search` (rejecting obvious duplicates, modifying-to-merge marginal duplicates). Triggered by user prompts like "import knowledge from git history" / "bootstrap fabric for this repo" or by an explicit fabric-import skill mention. Default layer is `team` (project artifacts are team-shared). The 3-phase pipeline is resumable via `.fabric/.import-state.json`.
|
|
4
4
|
allowed-tools: Read, Glob, Grep, Bash, mcp__fabric__fab_extract_knowledge, mcp__fabric__fab_review
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ allowed-tools: Read, Glob, Grep, Bash, mcp__fabric__fab_extract_knowledge, mcp__
|
|
|
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
|
|
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.
|
|
12
12
|
|
|
13
13
|
## Precondition
|
|
14
14
|
|
|
@@ -23,13 +23,13 @@ If none of the above hold, stop the skill immediately and tell the user:
|
|
|
23
23
|
- zh-CN: `没有触发 import 信号;如需手动 import 请显式调用 fabric-import`
|
|
24
24
|
- en: `No import signal detected; to manually import, explicitly invoke fabric-import`
|
|
25
25
|
|
|
26
|
-
(Render per `
|
|
26
|
+
(Render per `fabric_language` resolved in Phase 0.5 Config Load below — class 2 of the UX i18n Policy.)
|
|
27
27
|
|
|
28
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 完成时手动清理它。
|
|
29
29
|
|
|
30
30
|
This skill SHOULD be skipped (warn the user, do not proceed) when:
|
|
31
31
|
|
|
32
|
-
- `.fabric/` does not exist — direct the user to run `fabric
|
|
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
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
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
|
|
35
35
|
|
|
@@ -114,15 +114,16 @@ and `final_summary.proposed == 0`) → first-run window; otherwise re-run window
|
|
|
114
114
|
|
|
115
115
|
### UX i18n Policy (5-class bilingualization)
|
|
116
116
|
|
|
117
|
-
The skill consults `
|
|
118
|
-
(固化于
|
|
119
|
-
CJK signal is detected in README + docs
|
|
117
|
+
The skill consults `fabric_language` from `.fabric/fabric-config.json`
|
|
118
|
+
(固化于 install 时,via `scan.ts:detectExistingLanguage`; default `"en"` when no
|
|
119
|
+
CJK signal is detected in README + docs/; may resolve to `"match-existing"`,
|
|
120
|
+
`"zh-CN"`, `"en"`, or `"zh-CN-hybrid"`). All user-facing text in the
|
|
120
121
|
following 5 categories MUST be rendered in the resolved language:
|
|
121
122
|
|
|
122
123
|
1. **Roll-up templates** — final summary blocks (`# Import Summary — phase=...`,
|
|
123
124
|
`## Phase 2 — Mining`, `## Phase 3 — Dedup`, etc.). zh-CN ↔ en mirror.
|
|
124
125
|
2. **Errors / Preconditions warnings** — abort + gate-fail messages (e.g.
|
|
125
|
-
"请先运行 fabric
|
|
126
|
+
"请先运行 fabric install 完成基线扫描…" / "Please run fabric install first…").
|
|
126
127
|
zh-CN ↔ en mirror.
|
|
127
128
|
3. **Confirmation prompts** — re-run-within-24h prompt, reset prompts, etc.
|
|
128
129
|
zh-CN ↔ en mirror.
|
|
@@ -136,11 +137,10 @@ following 5 categories MUST be rendered in the resolved language:
|
|
|
136
137
|
|
|
137
138
|
Rendering rule:
|
|
138
139
|
|
|
139
|
-
- `
|
|
140
|
-
- `
|
|
141
|
-
-
|
|
142
|
-
|
|
143
|
-
or fully en.
|
|
140
|
+
- `fabric_language === "zh-CN"` → emit the zh-CN variant; pure monolingual, no language mixing inside a single user-facing block.
|
|
141
|
+
- `fabric_language === "en"` → emit the en variant; pure monolingual, no language mixing inside a single user-facing block.
|
|
142
|
+
- `fabric_language === "zh-CN-hybrid"` → emit Chinese narrative prose with English technical terms preserved. Protected tokens (always EN): MCP tool names (e.g. `fab_get_knowledge_sections`), CLI command names (e.g. `fab install`), file paths, technical concepts (`Skill`, `SessionStart`, `hook`, `MCP`, `revision_hash`, `pending`, `proven`, `verified`, `draft`).
|
|
143
|
+
- `fabric_language === "match-existing"` or any other value → emit the en variant; pure monolingual.
|
|
144
144
|
|
|
145
145
|
Protected tokens (`fab_extract_knowledge`, `fab_review`, `relevance_scope`,
|
|
146
146
|
`relevance_paths`, `broad`, `narrow`, `source_sessions`, `proposed_reason`,
|
|
@@ -153,20 +153,20 @@ The bilingualization scope is prose ONLY.
|
|
|
153
153
|
|
|
154
154
|
When a skill (this one or any sibling skill the user is composing with)
|
|
155
155
|
issues an `AskUserQuestion`, the `header` and `question` strings are
|
|
156
|
-
user-facing prose → translated per `
|
|
156
|
+
user-facing prose → translated per `fabric_language`. The `options[]`
|
|
157
157
|
array entries (e.g. `["approve", "reject", "modify", "defer", "skip"]` in
|
|
158
158
|
fabric-review) are **routing keys** consumed by the skill state machine —
|
|
159
|
-
they MUST remain English regardless of `
|
|
159
|
+
they MUST remain English regardless of `fabric_language`.
|
|
160
160
|
|
|
161
161
|
```ts
|
|
162
|
-
// EN (
|
|
162
|
+
// EN (fabric_language === "en")
|
|
163
163
|
AskUserQuestion({
|
|
164
164
|
header: "Review pending entry",
|
|
165
165
|
question: "What action for '{title}'?",
|
|
166
166
|
options: ["approve", "reject", "modify", "defer", "skip"]
|
|
167
167
|
})
|
|
168
168
|
|
|
169
|
-
// zh-CN (
|
|
169
|
+
// zh-CN (fabric_language === "zh-CN")
|
|
170
170
|
AskUserQuestion({
|
|
171
171
|
header: "审核 pending 条目",
|
|
172
172
|
question: "对 '{title}' 执行什么操作?",
|
|
@@ -186,7 +186,7 @@ The pipeline runs strictly in order. Each phase reads the prior phase's outputs
|
|
|
186
186
|
|
|
187
187
|
### Phase 1 — Init-Scan Reference (NO RE-IMPLEMENTATION)
|
|
188
188
|
|
|
189
|
-
> Verbatim boundary: `fabric
|
|
189
|
+
> 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.
|
|
190
190
|
|
|
191
191
|
The deterministic init-scan has already populated `.fabric/knowledge/team/` with 4–7 baseline entries derived from:
|
|
192
192
|
|
|
@@ -203,8 +203,8 @@ Phase 1 actions performed by THIS skill:
|
|
|
203
203
|
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).
|
|
204
204
|
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):
|
|
205
205
|
|
|
206
|
-
- zh-CN: `请先运行 fabric
|
|
207
|
-
- en: `Please run fabric
|
|
206
|
+
- zh-CN: `请先运行 fabric install 完成基线扫描,再调用 fabric-import`
|
|
207
|
+
- en: `Please run fabric install first to complete the baseline scan, then invoke fabric-import`
|
|
208
208
|
|
|
209
209
|
…and exit.
|
|
210
210
|
4. Update `.fabric/.import-state.json`: `phase = "P1-done"`, `p1_baseline_titles = [<list>]`, `last_checkpoint_at = <ISO8601 now>`.
|
|
@@ -288,7 +288,7 @@ For each commit:
|
|
|
288
288
|
- `refactor(...)` with body → likely **decision** (architectural choice was made)
|
|
289
289
|
- `docs(...)` → usually a **guideline** if the body announces a convention; skip if it's just typo/reformat
|
|
290
290
|
- `chore(...)`, `test(...)`, `ci(...)` → almost always skip (mechanical; no reusable insight)
|
|
291
|
-
2. Read the commit body. Extract the LLM-judged "core observation" — what would a future engineer want to know about this commit beyond the diff? Aim for 1–2 sentences in zh-CN (project
|
|
291
|
+
2. Read the commit body. Extract the LLM-judged "core observation" — what would a future engineer want to know about this commit beyond the diff? Aim for 1–2 sentences in zh-CN (project fabric_language; mirror fabric-archive M3 style).
|
|
292
292
|
3. Apply the **Skip Decision Tree** below. If the commit is skip-worthy, record it in `p2_processed_commits[]` with `skipped: true` and move on.
|
|
293
293
|
4. For non-skipped commits, classify type / propose slug / draft summary. Then call `fab_extract_knowledge` with the **mandatory broad + [] scope** (see "Mandatory Scope Rule" above):
|
|
294
294
|
|
|
@@ -394,7 +394,7 @@ After Step 2.2 completes (or hits the cap), update `.fabric/.import-state.json`:
|
|
|
394
394
|
|
|
395
395
|
When the user invocation includes `dry-run` / `预览` / `--dry-run` keywords, Phase 2 runs WITHOUT calling `fab_extract_knowledge`. Instead it prints a table. UX i18n Policy class 4 — dry-run table headers; the header + column titles are bilingualized; row content (slug / commit sha / doc path) is data and is NOT translated. The protected tokens `broad`, `relevance_scope`, `relevance_paths` appear verbatim in both variants:
|
|
396
396
|
|
|
397
|
-
zh-CN variant (`
|
|
397
|
+
zh-CN variant (`fabric_language === "zh-CN"`):
|
|
398
398
|
|
|
399
399
|
```md
|
|
400
400
|
# Import 预览 — 将提议 N 条 pending 条目(全部 relevance_scope=broad, relevance_paths=[])
|
|
@@ -406,7 +406,7 @@ zh-CN variant (`knowledge_language === "zh-CN"`):
|
|
|
406
406
|
| 3 | git 50367b5 | pitfalls | thundering-herd-no-backoff | broad+[] | 重试无指数回退导致雪崩;必须 jittered exponential backoff。|
|
|
407
407
|
```
|
|
408
408
|
|
|
409
|
-
en variant (`
|
|
409
|
+
en variant (`fabric_language === "en"`):
|
|
410
410
|
|
|
411
411
|
```md
|
|
412
412
|
# Import Dry Run — would propose N pending entries (all relevance_scope=broad, relevance_paths=[])
|
|
@@ -648,9 +648,9 @@ The contract: re-invoking fabric-import after ANY interruption (Ctrl-C, crash, n
|
|
|
648
648
|
|
|
649
649
|
## Output Contract
|
|
650
650
|
|
|
651
|
-
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 the en variant or the zh-CN variant per `
|
|
651
|
+
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 the en variant or the zh-CN variant per `fabric_language`; the protected tokens (`relevance_scope`, `relevance_paths`, `broad`, `pending_path`, `layer`, `team`, `personal`, `fab_review`, `.fabric/.import-state.json`, etc.) appear verbatim in BOTH variants.
|
|
652
652
|
|
|
653
|
-
en variant (`
|
|
653
|
+
en variant (`fabric_language === "en"`):
|
|
654
654
|
|
|
655
655
|
```md
|
|
656
656
|
# Import Summary — phase=<P1-done | P2-done | complete>
|
|
@@ -678,7 +678,7 @@ en variant (`knowledge_language === "en"`):
|
|
|
678
678
|
- If any kept entry is actually narrow-scoped, narrow it via `fab_review action="modify"` with `changes.relevance_scope="narrow"` + `changes.relevance_paths=[...]` (this skill cannot narrow — see Mandatory Scope Rule in Phase 2).
|
|
679
679
|
```
|
|
680
680
|
|
|
681
|
-
zh-CN variant (`
|
|
681
|
+
zh-CN variant (`fabric_language === "zh-CN"`):
|
|
682
682
|
|
|
683
683
|
```md
|
|
684
684
|
# Import 汇总 — phase=<P1-done | P2-done | complete>
|
|
@@ -19,7 +19,7 @@ If none of the above hold, stop the skill immediately and tell the user (UX i18n
|
|
|
19
19
|
- zh-CN: `没有触发 review 信号;如需手动 review 请显式调用 fabric-review`
|
|
20
20
|
- en: `No review signal detected; to manually review, explicitly invoke fabric-review`
|
|
21
21
|
|
|
22
|
-
(Render per `
|
|
22
|
+
(Render per `fabric_language` resolved in Config Load below.)
|
|
23
23
|
|
|
24
24
|
This skill is `Infer-not-Ask` for mode and `Ask-when-genuine` for per-item actions:
|
|
25
25
|
|
|
@@ -51,9 +51,10 @@ If `.fabric/fabric-config.json` is missing or unreadable, use defaults silently.
|
|
|
51
51
|
|
|
52
52
|
### UX i18n Policy (5-class bilingualization)
|
|
53
53
|
|
|
54
|
-
The skill consults `
|
|
54
|
+
The skill consults `fabric_language` from `.fabric/fabric-config.json`
|
|
55
55
|
(固化于 init 时,via `scan.ts:detectExistingLanguage`; default `"en"` when no
|
|
56
|
-
CJK signal is detected in README + docs
|
|
56
|
+
CJK signal is detected in README + docs/; may resolve to `"match-existing"`,
|
|
57
|
+
`"zh-CN"`, `"en"`, or `"zh-CN-hybrid"`). All user-facing text in the
|
|
57
58
|
following 5 categories MUST be rendered in the resolved language:
|
|
58
59
|
|
|
59
60
|
1. **Roll-up templates** — the `# Review Summary — mode={...}` final block,
|
|
@@ -77,11 +78,10 @@ following 5 categories MUST be rendered in the resolved language:
|
|
|
77
78
|
|
|
78
79
|
Rendering rule:
|
|
79
80
|
|
|
80
|
-
- `
|
|
81
|
-
- `
|
|
82
|
-
-
|
|
83
|
-
|
|
84
|
-
or fully en.
|
|
81
|
+
- `fabric_language === "zh-CN"` → emit the zh-CN variant; pure monolingual, no language mixing inside a single user-facing block.
|
|
82
|
+
- `fabric_language === "en"` → emit the en variant; pure monolingual, no language mixing inside a single user-facing block.
|
|
83
|
+
- `fabric_language === "zh-CN-hybrid"` → emit Chinese narrative prose with English technical terms preserved. Protected tokens (always EN): MCP tool names (e.g. `fab_get_knowledge_sections`), CLI command names (e.g. `fab install`), file paths, technical concepts (`Skill`, `SessionStart`, `hook`, `MCP`, `revision_hash`, `pending`, `proven`, `verified`, `draft`).
|
|
84
|
+
- `fabric_language === "match-existing"` or any other value → emit the en variant; pure monolingual.
|
|
85
85
|
|
|
86
86
|
Protected tokens (`fab_review`, `relevance_scope`, `relevance_paths`,
|
|
87
87
|
`narrow`, `broad`, `source_sessions`, `proposed_reason`, `session_context`,
|
|
@@ -93,9 +93,9 @@ prose ONLY.
|
|
|
93
93
|
### AskUserQuestion i18n Policy (value vs label)
|
|
94
94
|
|
|
95
95
|
When this skill issues an `AskUserQuestion`, the `header` and `question`
|
|
96
|
-
strings are user-facing prose → translated per `
|
|
96
|
+
strings are user-facing prose → translated per `fabric_language`. The
|
|
97
97
|
`options[]` array entries are **routing keys** consumed by the skill
|
|
98
|
-
state machine — they MUST remain English regardless of `
|
|
98
|
+
state machine — they MUST remain English regardless of `fabric_language`.
|
|
99
99
|
|
|
100
100
|
Canonical options arrays used by this skill (every value below stays
|
|
101
101
|
English in BOTH language variants):
|
|
@@ -109,14 +109,14 @@ English in BOTH language variants):
|
|
|
109
109
|
Worked example — per-item action (the most common AskUserQuestion in this skill):
|
|
110
110
|
|
|
111
111
|
```ts
|
|
112
|
-
// EN (
|
|
112
|
+
// EN (fabric_language === "en")
|
|
113
113
|
AskUserQuestion({
|
|
114
114
|
header: "Review pending entry",
|
|
115
115
|
question: "What action for '{title}'? ({pending_path})",
|
|
116
116
|
options: ["approve", "reject", "modify", "defer", "skip"]
|
|
117
117
|
})
|
|
118
118
|
|
|
119
|
-
// zh-CN (
|
|
119
|
+
// zh-CN (fabric_language === "zh-CN")
|
|
120
120
|
AskUserQuestion({
|
|
121
121
|
header: "审核 pending 条目",
|
|
122
122
|
question: "对 '{title}' 执行什么操作?({pending_path})",
|
|
@@ -210,7 +210,7 @@ Each mode produces user-facing output, then routes per-item or per-batch decisio
|
|
|
210
210
|
templates; protected tokens (`pending_path`, `layer`, `team`, `decisions`,
|
|
211
211
|
`proposed_reason`, `Tags`, etc.) appear verbatim in BOTH variants:
|
|
212
212
|
|
|
213
|
-
en variant (`
|
|
213
|
+
en variant (`fabric_language === "en"`):
|
|
214
214
|
|
|
215
215
|
```md
|
|
216
216
|
## [type=decisions] [layer=team] pending_path=knowledge/pending/decisions/single-cjs-hook.md
|
|
@@ -222,7 +222,7 @@ Each mode produces user-facing output, then routes per-item or per-batch decisio
|
|
|
222
222
|
⚠ Possible duplicate of KT-D-0007 (LLM subjective dup/subsumption judgement; thresholds intentionally not quantified)
|
|
223
223
|
```
|
|
224
224
|
|
|
225
|
-
zh-CN variant (`
|
|
225
|
+
zh-CN variant (`fabric_language === "zh-CN"`):
|
|
226
226
|
|
|
227
227
|
```md
|
|
228
228
|
## [type=decisions] [layer=team] pending_path=knowledge/pending/decisions/single-cjs-hook.md
|
|
@@ -286,7 +286,7 @@ Each mode produces user-facing output, then routes per-item or per-batch decisio
|
|
|
286
286
|
1. Call `fab_review action="list"` with `filters.maturity="draft"` (or no filter for full corpus inspection).
|
|
287
287
|
2. Tail `.fabric/events.jsonl` for layer_changed / demoted / rejected counts in the trailing 30 days.
|
|
288
288
|
3. Compute stale candidates: pending entries with mtime older than `review_stale_pending_days` (config-resolved, default 14) OR maturity=draft entries with no recent evidence-append events.
|
|
289
|
-
4. Render a corpus dashboard. UX i18n Policy class 1 — roll-up templates; render per `
|
|
289
|
+
4. Render a corpus dashboard. UX i18n Policy class 1 — roll-up templates; render per `fabric_language`:
|
|
290
290
|
|
|
291
291
|
en variant:
|
|
292
292
|
|
|
@@ -471,7 +471,7 @@ mcp__fabric__fab_review({
|
|
|
471
471
|
|
|
472
472
|
### Per-Item Question Phrasing Template
|
|
473
473
|
|
|
474
|
-
UX i18n Policy class 5 — `header` + `question` translated per `
|
|
474
|
+
UX i18n Policy class 5 — `header` + `question` translated per `fabric_language`; `options[]` arrays remain English routing keys in BOTH variants. Choose the variant matching the resolved language; the structure (field names, options) is identical.
|
|
475
475
|
|
|
476
476
|
en variant:
|
|
477
477
|
|
|
@@ -556,9 +556,9 @@ Pending entry presented for review
|
|
|
556
556
|
|
|
557
557
|
## Output Contract
|
|
558
558
|
|
|
559
|
-
After each invocation, the skill MUST produce a brief roll-up to the user. UX i18n Policy class 1 — roll-up templates; render per `
|
|
559
|
+
After each invocation, the skill MUST produce a brief roll-up to the user. UX i18n Policy class 1 — roll-up templates; render per `fabric_language`. Protected tokens (event-type strings such as `knowledge_promoted` / `knowledge_layer_changed` / `knowledge_rejected` / `knowledge_deferred`, plus `.fabric/events.jsonl`) appear verbatim in BOTH variants:
|
|
560
560
|
|
|
561
|
-
en variant (`
|
|
561
|
+
en variant (`fabric_language === "en"`):
|
|
562
562
|
|
|
563
563
|
```md
|
|
564
564
|
# Review Summary — mode={pending|topic|health|revisit}
|
|
@@ -577,7 +577,7 @@ en variant (`knowledge_language === "en"`):
|
|
|
577
577
|
- knowledge_deferred ×D
|
|
578
578
|
```
|
|
579
579
|
|
|
580
|
-
zh-CN variant (`
|
|
580
|
+
zh-CN variant (`fabric_language === "zh-CN"`):
|
|
581
581
|
|
|
582
582
|
```md
|
|
583
583
|
# Review 汇总 — mode={pending|topic|health|revisit}
|