@fenglimg/fabric-cli 2.2.0-rc.8 → 2.2.0

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.
@@ -22,9 +22,8 @@ var ROOT_AUTHORITATIVE_KEYS = /* @__PURE__ */ new Set([
22
22
  "embed_model",
23
23
  "embed_weight",
24
24
  "plan_context_top_k",
25
+ "recall_relevance_ratio",
25
26
  "mcpPayloadLimits",
26
- "retrieval_budget_profile",
27
- "recall_body_budget_bytes",
28
27
  "selection_token_ttl_ms",
29
28
  "orphan_demote_proven_days",
30
29
  "orphan_demote_verified_days",
@@ -97,6 +97,8 @@ async function runPlanContextHint(opts) {
97
97
  () => ({
98
98
  by_type: {},
99
99
  by_layer: { team: 0, personal: 0, project: 0 },
100
+ broad_by_type: {},
101
+ narrow_total: 0,
100
102
  dropped_other_project: 0,
101
103
  total: 0
102
104
  })
@@ -52,6 +52,11 @@ import {
52
52
  BOOTSTRAP_MARKER_END,
53
53
  BOOTSTRAP_REGEX
54
54
  } from "@fenglimg/fabric-shared/templates/bootstrap-canonical";
55
+ var SKILL_ROUTER_TEMPLATE_REL = "skills/fabric/SKILL.md";
56
+ var ROUTER_INTENT_MARKER_BEGIN = "<!-- fabric:router-intent:begin -->";
57
+ var ROUTER_INTENT_MARKER_END = "<!-- fabric:router-intent:end -->";
58
+ var ROUTER_INTENT_GENERATED_NOTE = "<!-- \u672C\u5757\u7531 `fabric install` \u4ECE 7 \u4E2A leaf skill \u7684 description Triggers \u5B50\u53E5\u751F\u6210\u3002\u4E25\u7981\u624B\u7F16;\u6539 leaf description \u540E\u91CD\u8DD1 `fabric install`\u3002 -->";
59
+ var ROUTER_INTENT_REGEX = /<!-- fabric:router-intent:begin -->[\s\S]*?<!-- fabric:router-intent:end -->/u;
55
60
  var SKILL_TEMPLATE_REL = "skills/fabric-archive/SKILL.md";
56
61
  var SKILL_REVIEW_TEMPLATE_REL = "skills/fabric-review/SKILL.md";
57
62
  var SKILL_IMPORT_TEMPLATE_REL = "skills/fabric-import/SKILL.md";
@@ -69,6 +74,12 @@ var HOOK_LIB_TEMPLATE_DIR_REL = "hooks/lib";
69
74
  var CLAUDE_HOOK_CONFIG_TEMPLATE_REL = "hooks/configs/claude-code.json";
70
75
  var CODEX_HOOK_CONFIG_TEMPLATE_REL = "hooks/configs/codex-hooks.json";
71
76
  var SKILL_DESTINATIONS = {
77
+ // B2 skill-router: the fabric/ router skill — single-file (no ref/), installed
78
+ // alongside the 7 leaf skills as the human-facing dispatch entry point.
79
+ fabricRouter: [
80
+ ".claude/skills/fabric/SKILL.md",
81
+ ".codex/skills/fabric/SKILL.md"
82
+ ],
72
83
  fabricArchive: [
73
84
  ".claude/skills/fabric-archive/SKILL.md",
74
85
  ".codex/skills/fabric-archive/SKILL.md"
@@ -106,6 +117,12 @@ var SKILL_DESTINATIONS = {
106
117
  ]
107
118
  };
108
119
  var FABRIC_SKILL_INSTALL_SPECS = {
120
+ fabricRouter: {
121
+ slug: "fabric",
122
+ templateRel: SKILL_ROUTER_TEMPLATE_REL,
123
+ destinations: SKILL_DESTINATIONS.fabricRouter,
124
+ step: "skill-router"
125
+ },
109
126
  fabricArchive: {
110
127
  slug: "fabric-archive",
111
128
  templateRel: SKILL_TEMPLATE_REL,
@@ -306,6 +323,66 @@ async function installFabricAuditSkill(projectRoot, _options = {}) {
306
323
  async function installFabricConnectSkill(projectRoot, _options = {}) {
307
324
  return installFabricSkill(projectRoot, FABRIC_SKILL_INSTALL_SPECS.fabricConnect);
308
325
  }
326
+ function extractSkillMdDescription(skillMd) {
327
+ const fm = skillMd.match(/^---\n([\s\S]*?)\n---/u);
328
+ if (!fm) return "";
329
+ const desc = fm[1].match(/^description:\s*(.+?)\s*$/mu);
330
+ if (!desc) return "";
331
+ return desc[1].replace(/^["'](.+)["']$/u, "$1").trim();
332
+ }
333
+ function extractTriggersClause(description) {
334
+ const m = description.match(/Triggers?\s+([\s\S]+)$/u);
335
+ if (!m) return "";
336
+ return m[1].trim().replace(/[.。]\s*$/u, "").replace(/\|/gu, "\\|");
337
+ }
338
+ function renderRouterIntentBlock(leaves) {
339
+ const rows = leaves.map((l) => `| ${l.triggers} | \`${l.slug}\` |`).join("\n");
340
+ const enumVals = leaves.map((l) => l.slug.replace(/^fabric-/u, "")).join(" | ");
341
+ return [
342
+ ROUTER_INTENT_MARKER_BEGIN,
343
+ ROUTER_INTENT_GENERATED_NOTE,
344
+ "",
345
+ "| \u7528\u6237\u610F\u56FE(leaf description Triggers) | \u4E0B\u6E38 skill |",
346
+ "| --- | --- |",
347
+ rows,
348
+ "",
349
+ `\`S_CLASSIFY\` \u7684 \`task_type\` \u679A\u4E3E:\`${enumVals}\``,
350
+ ROUTER_INTENT_MARKER_END
351
+ ].join("\n");
352
+ }
353
+ async function buildRouterSkillSource() {
354
+ const template = await readTemplate(SKILL_ROUTER_TEMPLATE_REL);
355
+ if (!ROUTER_INTENT_REGEX.test(template)) {
356
+ throw new Error(
357
+ `fabric/SKILL.md is missing the ${ROUTER_INTENT_MARKER_BEGIN} \u2026 ${ROUTER_INTENT_MARKER_END} marker pair \u2014 cannot regenerate the Intent Map. This is a Fabric release bug (router template was hand-edited away from the managed-block contract).`
358
+ );
359
+ }
360
+ const leafSpecs = Object.values(FABRIC_SKILL_INSTALL_SPECS).filter(
361
+ (spec) => spec.slug !== "fabric"
362
+ );
363
+ const leaves = [];
364
+ for (const spec of leafSpecs) {
365
+ const leafMd = await readTemplate(spec.templateRel);
366
+ leaves.push({ slug: spec.slug, triggers: extractTriggersClause(extractSkillMdDescription(leafMd)) });
367
+ }
368
+ return template.replace(ROUTER_INTENT_REGEX, renderRouterIntentBlock(leaves));
369
+ }
370
+ async function installFabricRouterSkill(projectRoot, _options = {}) {
371
+ const source = await buildRouterSkillSource();
372
+ validateSkillCanonicalSize(source, "fabric");
373
+ const spec = FABRIC_SKILL_INSTALL_SPECS.fabricRouter;
374
+ const targets = spec.destinations.map((rel) => join2(projectRoot, rel));
375
+ const results = [];
376
+ for (const target of targets) {
377
+ const staleMsg = inspectStaleInstall(target, source);
378
+ const result = await copyTextIdempotent(spec.step, source, target);
379
+ if (staleMsg && result.status === "written") {
380
+ result.message = result.message ? `${staleMsg}; ${result.message}` : staleMsg;
381
+ }
382
+ results.push(result);
383
+ }
384
+ return results;
385
+ }
309
386
  async function cleanupDeprecatedSkills(projectRoot) {
310
387
  const results = [];
311
388
  for (const rel of DEPRECATED_SKILL_DIRS) {
@@ -914,6 +991,7 @@ export {
914
991
  installFabricStoreSkill,
915
992
  installFabricAuditSkill,
916
993
  installFabricConnectSkill,
994
+ installFabricRouterSkill,
917
995
  cleanupDeprecatedSkills,
918
996
  installSharedSkillLib,
919
997
  installArchiveHintHook,
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  ensureStoreProjectBinding,
4
4
  migrateRootConfig
5
- } from "./chunk-FEOPLBGA.js";
5
+ } from "./chunk-3D7B2UAZ.js";
6
6
  import {
7
7
  resolveDevMode
8
8
  } from "./chunk-WA3DYGSY.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runPlanContextHint
4
- } from "./chunk-YM4XATJF.js";
4
+ } from "./chunk-722JU5BP.js";
5
5
  import "./chunk-WA3DYGSY.js";
6
6
 
7
7
  // src/commands/context.ts
@@ -5,8 +5,8 @@ import {
5
5
  parseSinceDuration,
6
6
  renderDoctorFilteredHelp,
7
7
  renderTldrHeader
8
- } from "./chunk-JTHWLUD3.js";
9
- import "./chunk-FEOPLBGA.js";
8
+ } from "./chunk-E7HJUU34.js";
9
+ import "./chunk-3D7B2UAZ.js";
10
10
  import "./chunk-WA3DYGSY.js";
11
11
  import "./chunk-NLNH64A3.js";
12
12
  import "./chunk-PTGQAZEW.js";
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  renderDoctorFilteredHelp
4
- } from "./chunk-JTHWLUD3.js";
5
- import "./chunk-FEOPLBGA.js";
4
+ } from "./chunk-E7HJUU34.js";
5
+ import "./chunk-3D7B2UAZ.js";
6
6
  import "./chunk-WA3DYGSY.js";
7
7
  import "./chunk-NLNH64A3.js";
8
8
  import "./chunk-PTGQAZEW.js";
@@ -23,7 +23,7 @@ import { defineCommand, renderUsage, runCommand, runMain } from "citty";
23
23
  // src/commands/index.ts
24
24
  var allCommands = {
25
25
  // v2.2.0-rc.5: pipeline-based install with TUI renderer (EPIC-005/006/007/008)
26
- install: () => import("./install-v2-2COC3DO3.js").then((module) => module.installCommand),
26
+ install: () => import("./install-v2-3KJX3YRO.js").then((module) => module.installCommand),
27
27
  // v2.1.0-rc.1 P3: multi-store lifecycle command group (list/add/remove/explain).
28
28
  store: () => import("./store-HOCORVL3.js").then((module) => module.default),
29
29
  // v2.1.0-rc.1 P3 (S9/S17/S37): multi-store pull --rebase + push, conflict resume.
@@ -35,10 +35,10 @@ var allCommands = {
35
35
  whoami: () => import("./whoami-ITGEFWH4.js").then((module) => module.default),
36
36
  status: () => import("./status-4R3TM4FJ.js").then((module) => module.default),
37
37
  "scope-explain": () => import("./scope-explain-HLJZ2M33.js").then((module) => module.default),
38
- doctor: () => import("./doctor-REZDNH4A.js").then((module) => module.default),
39
- uninstall: () => import("./uninstall-62F4LNKI.js").then((module) => module.default),
38
+ doctor: () => import("./doctor-MDTZWKBK.js").then((module) => module.default),
39
+ uninstall: () => import("./uninstall-IFN2KYBK.js").then((module) => module.default),
40
40
  config: () => import("./config-A3LTECAY.js").then((module) => module.default),
41
- "plan-context-hint": () => import("./plan-context-hint-G75R4P4J.js").then((module) => module.default),
41
+ "plan-context-hint": () => import("./plan-context-hint-5TNGH3R4.js").then((module) => module.default),
42
42
  // v2.0.0-rc.23 TASK-014 (F8c): S5 onboard-slot coverage. Used by the
43
43
  // fabric-archive Skill's first-run phase to detect unclaimed slots.
44
44
  "onboard-coverage": () => import("./onboard-coverage-XSG77LL3.js").then((module) => module.default),
@@ -46,7 +46,7 @@ var allCommands = {
46
46
  metrics: () => import("./metrics-HMFH4YHK.js").then((module) => module.default),
47
47
  // Block 5 (Option X): show what SessionStart injects (shared renderer with the
48
48
  // hook → byte-identical). --explain for per-entry provenance.
49
- context: () => import("./context-7NUKXDB6.js").then((module) => module.default)
49
+ context: () => import("./context-UJCGYOT6.js").then((module) => module.default)
50
50
  };
51
51
 
52
52
  // src/lib/error-render.ts
@@ -153,7 +153,7 @@ async function customShowUsageGrouped(cmd, parent, version) {
153
153
  var main = defineCommand({
154
154
  meta: {
155
155
  name: "fabric",
156
- version: "2.2.0-rc.8",
156
+ version: "2.2.0",
157
157
  description: t("cli.main.description")
158
158
  },
159
159
  subCommands: allCommands
@@ -165,7 +165,7 @@ async function customShowUsage(cmd, parent) {
165
165
  return;
166
166
  }
167
167
  if (cmdMeta?.name === "fabric" && parent === void 0) {
168
- await customShowUsageGrouped(cmd, parent, "2.2.0-rc.8");
168
+ await customShowUsageGrouped(cmd, parent, "2.2.0");
169
169
  return;
170
170
  }
171
171
  console.log(await renderUsage(cmd, parent) + "\n");
@@ -8,6 +8,7 @@ import {
8
8
  installFabricConnectSkill,
9
9
  installFabricImportSkill,
10
10
  installFabricReviewSkill,
11
+ installFabricRouterSkill,
11
12
  installFabricStoreSkill,
12
13
  installFabricSyncSkill,
13
14
  installHookLibs,
@@ -21,13 +22,13 @@ import {
21
22
  writeClaudeBootstrapThinShell,
22
23
  writeCodexBootstrapManagedBlock,
23
24
  writeFabricAgentsSnapshot
24
- } from "./chunk-CMDW3PYK.js";
25
+ } from "./chunk-7ZDXBOOU.js";
25
26
  import {
26
27
  ensureStoreProjectBinding,
27
28
  migrateRootConfig,
28
29
  normalizeStoreProjectId,
29
30
  suggestStoreProjectId
30
- } from "./chunk-FEOPLBGA.js";
31
+ } from "./chunk-3D7B2UAZ.js";
31
32
  import {
32
33
  createDebugLogger,
33
34
  resolveDevMode
@@ -1737,7 +1738,7 @@ function readProjectName(target) {
1737
1738
  return basename(target);
1738
1739
  }
1739
1740
  function getCliVersion() {
1740
- return true ? "2.2.0-rc.8" : "unknown";
1741
+ return true ? "2.2.0" : "unknown";
1741
1742
  }
1742
1743
  function sortRecord(record) {
1743
1744
  return Object.fromEntries(Object.entries(record).sort(([left], [right]) => left.localeCompare(right)));
@@ -2356,6 +2357,7 @@ var HooksStage = class {
2356
2357
  const target = context.target;
2357
2358
  const installResults = [];
2358
2359
  installResults.push(...await this.runBestEffort("skill-deprecated-cleanup", () => cleanupDeprecatedSkills(target)));
2360
+ installResults.push(...await this.runBestEffort("skill-router-install", () => installFabricRouterSkill(target)));
2359
2361
  installResults.push(...await this.runBestEffort("skill-install", () => installFabricArchiveSkill(target)));
2360
2362
  installResults.push(...await this.runBestEffort("skill-review-install", () => installFabricReviewSkill(target)));
2361
2363
  installResults.push(...await this.runBestEffort("skill-import-install", () => installFabricImportSkill(target)));
@@ -3,7 +3,7 @@ import {
3
3
  planContextHintCommand,
4
4
  plan_context_hint_default,
5
5
  runPlanContextHint
6
- } from "./chunk-YM4XATJF.js";
6
+ } from "./chunk-722JU5BP.js";
7
7
  import "./chunk-WA3DYGSY.js";
8
8
  export {
9
9
  plan_context_hint_default as default,
@@ -7,7 +7,7 @@ import {
7
7
  HOOK_SCRIPT_DESTINATIONS,
8
8
  SKILL_DESTINATIONS,
9
9
  fabricAgentsSnapshotPath
10
- } from "./chunk-CMDW3PYK.js";
10
+ } from "./chunk-7ZDXBOOU.js";
11
11
  import {
12
12
  createDebugLogger,
13
13
  resolveDevMode
@@ -37,6 +37,9 @@ import { readdir, readFile, rm, rmdir } from "fs/promises";
37
37
  import { dirname, join } from "path";
38
38
  import { atomicWriteJson, atomicWriteText } from "@fenglimg/fabric-shared/node/atomic-write";
39
39
  import { BOOTSTRAP_REGEX } from "@fenglimg/fabric-shared/templates/bootstrap-canonical";
40
+ async function uninstallFabricRouterSkill(projectRoot) {
41
+ return removeSkill("skill-router", SKILL_DESTINATIONS.fabricRouter, projectRoot);
42
+ }
40
43
  async function uninstallFabricArchiveSkill(projectRoot) {
41
44
  return removeSkill("skill", SKILL_DESTINATIONS.fabricArchive, projectRoot);
42
45
  }
@@ -345,6 +348,12 @@ async function uninstallBootstrapStage(projectRoot, _opts = {}) {
345
348
  projectRoot,
346
349
  () => uninstallFabricArchiveSkill(projectRoot)
347
350
  );
351
+ await runAndCollect(
352
+ results,
353
+ "skill-router",
354
+ projectRoot,
355
+ () => uninstallFabricRouterSkill(projectRoot)
356
+ );
348
357
  return results;
349
358
  }
350
359
  async function runAndCollect(results, step, projectRoot, fn) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fenglimg/fabric-cli",
3
- "version": "2.2.0-rc.8",
3
+ "version": "2.2.0",
4
4
  "description": "Fabric CLI — installs the MCP server + skills + hooks for Claude Code and Codex CLI; runs doctor / knowledge maintenance.",
5
5
  "license": "MIT",
6
6
  "author": "wangzhichao <fenglimg90@gmail.com>",
@@ -46,8 +46,8 @@
46
46
  "tree-sitter-javascript": "^0.25.0",
47
47
  "tree-sitter-typescript": "^0.23.2",
48
48
  "web-tree-sitter": "^0.26.8",
49
- "@fenglimg/fabric-shared": "2.2.0-rc.8",
50
- "@fenglimg/fabric-server": "2.2.0-rc.8"
49
+ "@fenglimg/fabric-server": "2.2.0",
50
+ "@fenglimg/fabric-shared": "2.2.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/node": "^22.15.0",