@fenglimg/fabric-cli 2.1.0-rc.2 → 2.2.0-rc.10

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.
Files changed (88) hide show
  1. package/README.md +8 -5
  2. package/dist/chunk-27HK6H5Y.js +69 -0
  3. package/dist/{chunk-BATF4PEJ.js → chunk-2KBCTMID.js} +31 -8
  4. package/dist/chunk-3D7B2UAZ.js +149 -0
  5. package/dist/{chunk-MF3OTILQ.js → chunk-3IOLS5EK.js} +48 -42
  6. package/dist/{plan-context-hint-FC6P3WFE.js → chunk-722JU5BP.js} +52 -12
  7. package/dist/{chunk-F46ORPOA.js → chunk-7ZDXBOOU.js} +271 -166
  8. package/dist/{doctor-QVNPHLJK.js → chunk-E7HJUU34.js} +248 -72
  9. package/dist/chunk-EOT63RDH.js +36 -0
  10. package/dist/chunk-FNHDQTPC.js +16 -0
  11. package/dist/chunk-HORSMSZL.js +26 -0
  12. package/dist/chunk-NLNH64A3.js +43 -0
  13. package/dist/{chunk-WU6GAPKH.js → chunk-PTGQAZEW.js} +12 -4
  14. package/dist/chunk-QFIVFZRH.js +13 -0
  15. package/dist/chunk-QPAW6IYT.js +387 -0
  16. package/dist/{chunk-COI5VDFU.js → chunk-WA3DYGSY.js} +1 -2
  17. package/dist/{config-XJIPZNUP.js → config-A3LTECAY.js} +4 -3
  18. package/dist/context-UJCGYOT6.js +117 -0
  19. package/dist/doctor-MDTZWKBK.js +24 -0
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.js +167 -16
  22. package/dist/info-7FKBTMVO.js +139 -0
  23. package/dist/install-v2-RINEA24K.js +3279 -0
  24. package/dist/{metrics-ACEQFPDU.js → metrics-HMFH4YHK.js} +22 -9
  25. package/dist/{onboard-coverage-MFCAEBDO.js → onboard-coverage-XSG77LL3.js} +48 -27
  26. package/dist/plan-context-hint-5TNGH3R4.js +12 -0
  27. package/dist/scope-explain-HLJZ2M33.js +48 -0
  28. package/dist/status-4R3TM4FJ.js +37 -0
  29. package/dist/store-HOCORVL3.js +563 -0
  30. package/dist/sync-DT5UJMMR.js +418 -0
  31. package/dist/{uninstall-TAXSUSKH.js → uninstall-IFN2KYBK.js} +128 -140
  32. package/dist/whoami-ITGEFWH4.js +49 -0
  33. package/package.json +7 -5
  34. package/templates/hooks/cite-policy-evict.cjs +412 -160
  35. package/templates/hooks/configs/README.md +14 -27
  36. package/templates/hooks/configs/claude-code.json +17 -2
  37. package/templates/hooks/configs/codex-hooks.json +15 -3
  38. package/templates/hooks/fabric-hint.cjs +573 -180
  39. package/templates/hooks/knowledge-hint-broad.cjs +648 -190
  40. package/templates/hooks/knowledge-hint-narrow.cjs +123 -77
  41. package/templates/hooks/lib/banner-i18n.cjs +31 -0
  42. package/templates/hooks/lib/bindings-snapshot-reader.cjs +118 -7
  43. package/templates/hooks/lib/cite-line-parser.cjs +12 -20
  44. package/templates/hooks/lib/client-adapter.cjs +66 -7
  45. package/templates/hooks/lib/injection-log.cjs +91 -0
  46. package/templates/hooks/lib/nudge-policy.cjs +117 -0
  47. package/templates/hooks/lib/state-store.cjs +90 -11
  48. package/templates/hooks/post-tooluse-mutation.cjs +386 -0
  49. package/templates/hooks/session-end-marker.cjs +140 -0
  50. package/templates/skills/fabric/SKILL.md +100 -0
  51. package/templates/skills/fabric-archive/SKILL.md +35 -24
  52. package/templates/skills/fabric-archive/ref/dry-run-scope.md +1 -1
  53. package/templates/skills/fabric-archive/ref/i18n-policy.md +2 -3
  54. package/templates/skills/fabric-archive/ref/phase-1-5-onboard.md +2 -3
  55. package/templates/skills/fabric-archive/ref/phase-1-cross-session.md +1 -1
  56. package/templates/skills/fabric-archive/ref/phase-2-5-viability.md +1 -1
  57. package/templates/skills/fabric-archive/ref/phase-3-6-related-edges.md +18 -0
  58. package/templates/skills/fabric-archive/ref/phase-3-7-semantic-scope.md +47 -0
  59. package/templates/skills/fabric-audit/SKILL.md +63 -0
  60. package/templates/skills/fabric-connect/SKILL.md +48 -0
  61. package/templates/skills/fabric-import/SKILL.md +7 -7
  62. package/templates/skills/fabric-import/ref/i18n-policy.md +2 -3
  63. package/templates/skills/fabric-import/ref/state-recovery.md +1 -2
  64. package/templates/skills/fabric-review/SKILL.md +16 -5
  65. package/templates/skills/fabric-review/ref/cite-contract.md +56 -0
  66. package/templates/skills/fabric-review/ref/i18n-policy.md +2 -3
  67. package/templates/skills/fabric-review/ref/output-contract.md +1 -1
  68. package/templates/skills/fabric-review/ref/per-mode-flows.md +2 -2
  69. package/templates/skills/fabric-review/ref/worked-examples.md +1 -1
  70. package/templates/skills/fabric-store/SKILL.md +44 -0
  71. package/templates/skills/fabric-sync/SKILL.md +1 -1
  72. package/templates/skills/lib/shared-policy.md +2 -2
  73. package/dist/chunk-HFQVXY6P.js +0 -86
  74. package/dist/chunk-L4Q55UC4.js +0 -52
  75. package/dist/chunk-LFIKMVY7.js +0 -27
  76. package/dist/chunk-PWLW3B57.js +0 -18
  77. package/dist/chunk-RYAFBNES.js +0 -33
  78. package/dist/chunk-T5RPGCCM.js +0 -40
  79. package/dist/chunk-WWNXR34K.js +0 -49
  80. package/dist/install-2HDO5FTQ.js +0 -2683
  81. package/dist/scope-explain-2F2R5URO.js +0 -33
  82. package/dist/status-GLQWLWH6.js +0 -23
  83. package/dist/store-XTSE5TY6.js +0 -105
  84. package/dist/sync-BJCWDPNC.js +0 -245
  85. package/dist/whoami-B6AEMSEV.js +0 -31
  86. package/templates/hooks/configs/cursor-hooks.json +0 -18
  87. package/templates/hooks/lib/cite-contract-reminder.cjs +0 -179
  88. package/templates/hooks/lib/summary-fallback.cjs +0 -210
@@ -1,14 +1,17 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ getProjectTranslator
4
+ } from "./chunk-HORSMSZL.js";
2
5
 
3
6
  // src/commands/metrics.ts
4
7
  import { resolve } from "path";
5
8
  import { defineCommand } from "citty";
6
9
  import { readMetrics } from "@fenglimg/fabric-server";
7
- function parseSinceArg(raw) {
10
+ function parseSinceArg(raw, t) {
8
11
  if (raw === void 0 || raw.length === 0) return 0;
9
12
  const match = /^(\d+)([smhd]?)$/u.exec(raw);
10
13
  if (match === null) {
11
- throw new Error(`--since: invalid duration "${raw}" (expected e.g. 24h, 7d, 30m)`);
14
+ throw new Error(t("cli.metrics.invalid-since", { raw }));
12
15
  }
13
16
  const n = Number.parseInt(match[1], 10);
14
17
  const unit = match[2] ?? "s";
@@ -36,6 +39,8 @@ function aggregate(rows, sinceMs, now) {
36
39
  }
37
40
  }
38
41
  return {
42
+ // Stable token (NOT localized) so the --json contract is locale-independent;
43
+ // renderText localizes "all-time" at presentation time only.
39
44
  windowDescription: sinceMs > 0 ? formatDuration(sinceMs) : "all-time",
40
45
  rowCount: filtered.length,
41
46
  totals,
@@ -50,17 +55,24 @@ function formatDuration(ms) {
50
55
  if (ms >= 6e4) return `${Math.round(ms / 6e4)}m`;
51
56
  return `${Math.round(ms / 1e3)}s`;
52
57
  }
53
- function renderText(agg) {
58
+ function renderText(agg, t) {
54
59
  const lines = [];
55
- lines.push(`Fabric metrics \u2014 window: ${agg.windowDescription}`);
60
+ const windowDisplay = agg.windowDescription === "all-time" ? t("cli.metrics.window-all-time") : agg.windowDescription;
61
+ lines.push(t("cli.metrics.window", { window: windowDisplay }));
56
62
  if (agg.rangeStart && agg.rangeEnd) {
57
- lines.push(` rows: ${agg.rowCount} (${agg.rangeStart} \u2192 ${agg.rangeEnd})`);
63
+ lines.push(
64
+ t("cli.metrics.rows-range", {
65
+ count: String(agg.rowCount),
66
+ start: agg.rangeStart,
67
+ end: agg.rangeEnd
68
+ })
69
+ );
58
70
  } else {
59
- lines.push(` rows: ${agg.rowCount}`);
71
+ lines.push(t("cli.metrics.rows", { count: String(agg.rowCount) }));
60
72
  }
61
73
  lines.push("");
62
74
  if (Object.keys(agg.totals).length === 0) {
63
- lines.push(" (no counter activity in window \u2014 server may be idle or just started)");
75
+ lines.push(t("cli.metrics.no-activity"));
64
76
  return lines.join("\n");
65
77
  }
66
78
  lines.push(" counter total");
@@ -103,14 +115,15 @@ var metricsCommand = defineCommand({
103
115
  },
104
116
  async run({ args }) {
105
117
  const projectRoot = resolve(args.target ?? process.cwd());
106
- const sinceMs = parseSinceArg(args.since);
118
+ const t = getProjectTranslator(projectRoot);
119
+ const sinceMs = parseSinceArg(args.since, t);
107
120
  const rows = await readMetrics(projectRoot);
108
121
  const aggregated = aggregate(rows, sinceMs, /* @__PURE__ */ new Date());
109
122
  if (args.json === true) {
110
123
  process.stdout.write(`${JSON.stringify(aggregated)}
111
124
  `);
112
125
  } else {
113
- process.stdout.write(`${renderText(aggregated)}
126
+ process.stdout.write(`${renderText(aggregated, t)}
114
127
  `);
115
128
  }
116
129
  }
@@ -1,15 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  t
4
- } from "./chunk-PWLW3B57.js";
4
+ } from "./chunk-HORSMSZL.js";
5
5
 
6
6
  // src/commands/onboard-coverage.ts
7
- import { existsSync, readdirSync, readFileSync } from "fs";
7
+ import { existsSync, readFileSync } from "fs";
8
8
  import { join, resolve } from "path";
9
9
  import { defineCommand } from "citty";
10
10
  import {
11
+ buildStoreResolveInput,
12
+ createStoreResolver,
11
13
  ONBOARD_SLOT_NAMES,
12
- ONBOARD_SLOT_TOTAL
14
+ ONBOARD_SLOT_TOTAL,
15
+ readKnowledgeAcrossStores,
16
+ resolveGlobalRoot,
17
+ storeRelativePathForMount
13
18
  } from "@fenglimg/fabric-shared";
14
19
  var KNOWLEDGE_TYPE_DIRS = [
15
20
  "decisions",
@@ -97,30 +102,46 @@ function readOptedOutSlots(projectRoot) {
97
102
  if (!Array.isArray(slots)) return [];
98
103
  return slots.filter((v) => typeof v === "string");
99
104
  }
100
- function runOnboardCoverage(projectRoot) {
105
+ function readSetStoreDirs(projectRoot) {
106
+ let input;
107
+ try {
108
+ input = buildStoreResolveInput(projectRoot);
109
+ } catch {
110
+ return [];
111
+ }
112
+ if (input === null) {
113
+ return [];
114
+ }
115
+ const readSet = createStoreResolver().resolveReadSet(input);
116
+ const globalRoot = resolveGlobalRoot();
117
+ return readSet.stores.map((store) => ({
118
+ store_uuid: store.store_uuid,
119
+ alias: store.alias,
120
+ // D4 two-layer layout: resolve via the mounted record (group + label), not
121
+ // the single-segment uuid path — mirrors the other read-set consumers.
122
+ dir: join(
123
+ globalRoot,
124
+ storeRelativePathForMount(
125
+ input.mountedStores.find((s) => s.store_uuid === store.store_uuid) ?? {
126
+ store_uuid: store.store_uuid
127
+ }
128
+ )
129
+ )
130
+ }));
131
+ }
132
+ function entryName(filePath) {
133
+ return filePath.split(/[\\/]/u).at(-1) ?? filePath;
134
+ }
135
+ async function runOnboardCoverage(projectRoot) {
101
136
  const filled = emptyFilled();
102
- const knowledgeRoot = join(projectRoot, ".fabric", "knowledge");
103
- if (existsSync(knowledgeRoot)) {
104
- for (const typeDir of KNOWLEDGE_TYPE_DIRS) {
105
- const dir = join(knowledgeRoot, typeDir);
106
- if (!existsSync(dir)) continue;
107
- let entries;
108
- try {
109
- entries = readdirSync(dir, { withFileTypes: true });
110
- } catch {
111
- continue;
112
- }
113
- for (const entry of entries) {
114
- if (!entry.isFile()) continue;
115
- if (!entry.name.endsWith(".md")) continue;
116
- const filePath = join(dir, entry.name);
117
- const slot = readOnboardSlotFrontmatter(filePath);
118
- if (slot === void 0) continue;
119
- if (!ONBOARD_SLOT_NAMES.includes(slot)) continue;
120
- const stableId = readStableIdFrontmatter(filePath, entry.name);
121
- filled[slot].push(stableId);
122
- }
123
- }
137
+ const refs = await readKnowledgeAcrossStores(readSetStoreDirs(projectRoot));
138
+ for (const ref of refs) {
139
+ if (!KNOWLEDGE_TYPE_DIRS.includes(ref.type)) continue;
140
+ const slot = readOnboardSlotFrontmatter(ref.file);
141
+ if (slot === void 0) continue;
142
+ if (!ONBOARD_SLOT_NAMES.includes(slot)) continue;
143
+ const stableId = readStableIdFrontmatter(ref.file, entryName(ref.file));
144
+ filled[slot].push(ref.alias.length === 0 ? stableId : `${ref.alias}:${stableId}`);
124
145
  }
125
146
  const optedOut = readOptedOutSlots(projectRoot);
126
147
  const missing = ONBOARD_SLOT_NAMES.filter((slot) => {
@@ -196,7 +217,7 @@ var onboardCoverageCommand = defineCommand({
196
217
  async run({ args }) {
197
218
  try {
198
219
  const projectRoot = resolve(args.target ?? process.cwd());
199
- const report = runOnboardCoverage(projectRoot);
220
+ const report = await runOnboardCoverage(projectRoot);
200
221
  if (args.json === true) {
201
222
  process.stdout.write(`${JSON.stringify(report)}
202
223
  `);
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ planContextHintCommand,
4
+ plan_context_hint_default,
5
+ runPlanContextHint
6
+ } from "./chunk-722JU5BP.js";
7
+ import "./chunk-WA3DYGSY.js";
8
+ export {
9
+ plan_context_hint_default as default,
10
+ planContextHintCommand,
11
+ runPlanContextHint
12
+ };
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ scopeExplain
4
+ } from "./chunk-EOT63RDH.js";
5
+ import {
6
+ getProjectTranslator
7
+ } from "./chunk-HORSMSZL.js";
8
+
9
+ // src/commands/scope-explain.ts
10
+ import { defineCommand } from "citty";
11
+ import { FabricError } from "@fenglimg/fabric-shared/errors";
12
+ var scope_explain_default = defineCommand({
13
+ meta: {
14
+ name: "scope-explain",
15
+ description: "[DEPRECATED] Use 'fabric info scope <path>' instead"
16
+ },
17
+ args: {
18
+ scope: {
19
+ type: "positional",
20
+ required: true,
21
+ description: "Scope coordinate (e.g. team, project:x, personal)"
22
+ }
23
+ },
24
+ run({ args }) {
25
+ console.error("\u26A0\uFE0F DEPRECATED: 'fabric scope-explain' is deprecated. Use 'fabric info scope <path>' instead.");
26
+ const projectRoot = process.cwd();
27
+ let result;
28
+ try {
29
+ result = scopeExplain(projectRoot, args.scope);
30
+ } catch (error) {
31
+ if (error instanceof FabricError) {
32
+ console.error(`${error.message}
33
+ \u2192 ${error.actionHint}`);
34
+ process.exitCode = 1;
35
+ return;
36
+ }
37
+ throw error;
38
+ }
39
+ if (result === null) {
40
+ console.log(getProjectTranslator(projectRoot)("cli.cmd.no-global-config"));
41
+ return;
42
+ }
43
+ console.log(JSON.stringify(result, null, 2));
44
+ }
45
+ });
46
+ export {
47
+ scope_explain_default as default
48
+ };
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ projectStatus,
4
+ warnUnknownFlags
5
+ } from "./chunk-27HK6H5Y.js";
6
+ import "./chunk-QPAW6IYT.js";
7
+ import "./chunk-QFIVFZRH.js";
8
+ import "./chunk-FNHDQTPC.js";
9
+
10
+ // src/commands/status.ts
11
+ import { defineCommand } from "citty";
12
+ var status_default = defineCommand({
13
+ meta: { name: "status", description: "[DEPRECATED] Use 'fabric info' instead" },
14
+ args: {
15
+ // F27: `--json` machine-readable output (was silently ignored pre-F27).
16
+ json: { type: "boolean", description: "Emit machine-readable JSON instead of text" }
17
+ },
18
+ run({ args }) {
19
+ warnUnknownFlags(["json"]);
20
+ console.error("\u26A0\uFE0F DEPRECATED: 'fabric status' is deprecated. Use 'fabric info' instead.");
21
+ const status = projectStatus(process.cwd());
22
+ if (args.json === true) {
23
+ console.log(JSON.stringify(status, null, 2));
24
+ return;
25
+ }
26
+ console.log(`uid: ${status.uid ?? "(no global config)"}`);
27
+ const projectIdLabel = status.project_id ?? (status.is_fabric_project ? "(unset)" : "(not a Fabric project)");
28
+ console.log(`project_id: ${projectIdLabel}`);
29
+ console.log(`mounted stores: ${status.mounted.length > 0 ? status.mounted.join(", ") : "(none)"}`);
30
+ console.log(`required: ${status.required.length > 0 ? status.required.join(", ") : "(none)"}`);
31
+ console.log(`default write: ${status.default_write_store ?? status.active_write_store ?? "(none \u2014 personal scope only)"}`);
32
+ console.log(`write routes: ${status.write_routes.length}`);
33
+ }
34
+ });
35
+ export {
36
+ status_default as default
37
+ };