@fenglimg/fabric-cli 2.2.0-rc.1 → 2.2.0-rc.4

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 (35) hide show
  1. package/dist/chunk-5JG4QJLO.js +64 -0
  2. package/dist/chunk-5SSNE5GM.js +301 -0
  3. package/dist/chunk-EOT63RDH.js +36 -0
  4. package/dist/{chunk-AOE6AYI7.js → chunk-F6ITRM7T.js} +2 -2
  5. package/dist/{chunk-WU6GAPKH.js → chunk-H3FE6VIK.js} +3 -5
  6. package/dist/chunk-XCBVSGCS.js +25 -0
  7. package/dist/{chunk-2R55HNVD.js → chunk-XHHCRDIR.js} +71 -6
  8. package/dist/{config-XYRBZJDU.js → config-VJMXCLXW.js} +1 -1
  9. package/dist/{doctor-YONYXDX6.js → doctor-U5W4CX5I.js} +118 -7
  10. package/dist/index.js +13 -12
  11. package/dist/{install-74ANPCCP.js → install-7XJ64WSC.js} +252 -246
  12. package/dist/{plan-context-hint-FC6P3WFE.js → plan-context-hint-CHVZGOZ5.js} +21 -8
  13. package/dist/{scope-explain-CDIZESP5.js → scope-explain-BWRWBCCP.js} +14 -4
  14. package/dist/{status-GLQWLWH6.js → status-7UFLWRX7.js} +17 -6
  15. package/dist/store-ZEZMQVG7.js +817 -0
  16. package/dist/{sync-UJ4BBCZJ.js → sync-EA5HZMXM.js} +165 -21
  17. package/dist/{uninstall-C3QXKOO6.js → uninstall-F75MPKQC.js} +27 -1
  18. package/dist/{whoami-2MLO4Y37.js → whoami-3FRWYGML.js} +16 -5
  19. package/package.json +3 -3
  20. package/templates/hooks/cite-policy-evict.cjs +412 -160
  21. package/templates/hooks/configs/claude-code.json +17 -2
  22. package/templates/hooks/configs/codex-hooks.json +14 -2
  23. package/templates/hooks/configs/cursor-hooks.json +14 -2
  24. package/templates/hooks/fabric-hint.cjs +151 -15
  25. package/templates/hooks/knowledge-hint-broad.cjs +12 -1
  26. package/templates/hooks/knowledge-hint-narrow.cjs +54 -1
  27. package/templates/hooks/post-tooluse-mutation.cjs +285 -0
  28. package/templates/hooks/session-end-marker.cjs +140 -0
  29. package/templates/skills/fabric-archive/SKILL.md +7 -1
  30. package/dist/chunk-4R2CYEA4.js +0 -116
  31. package/dist/chunk-L4Q55UC4.js +0 -52
  32. package/dist/chunk-LFIKMVY7.js +0 -27
  33. package/dist/chunk-RYAFBNES.js +0 -33
  34. package/dist/chunk-T5RPGCCM.js +0 -40
  35. package/dist/store-XB3ADT65.js +0 -144
@@ -6,20 +6,21 @@ import {
6
6
  import {
7
7
  resolveDevMode
8
8
  } from "./chunk-COI5VDFU.js";
9
- import {
10
- missingRequiredStores
11
- } from "./chunk-4R2CYEA4.js";
12
9
  import {
13
10
  getDoctorTranslator,
14
11
  t
15
12
  } from "./chunk-2CY4BMTH.js";
16
13
  import {
17
- loadProjectConfig
18
- } from "./chunk-LFIKMVY7.js";
14
+ detectAliasLinkDrift,
15
+ missingRequiredStores,
16
+ syncStoreAliasLinks,
17
+ unboundAvailableStores
18
+ } from "./chunk-5SSNE5GM.js";
19
19
  import {
20
20
  loadGlobalConfig,
21
+ loadProjectConfig,
21
22
  resolveGlobalRoot
22
- } from "./chunk-RYAFBNES.js";
23
+ } from "./chunk-XCBVSGCS.js";
23
24
 
24
25
  // src/commands/doctor.ts
25
26
  import { confirm, isCancel } from "@clack/prompts";
@@ -32,7 +33,8 @@ import {
32
33
  runDoctorCiteCoverage,
33
34
  runDoctorFix,
34
35
  runDoctorHistoryAll,
35
- runDoctorReport
36
+ runDoctorReport,
37
+ runDoctorConflictLint
36
38
  } from "@fenglimg/fabric-server";
37
39
 
38
40
  // src/store/doctor-checks.ts
@@ -57,6 +59,23 @@ function storeDoctorChecks(projectRoot, globalRoot = resolveGlobalRoot()) {
57
59
  message: `required store '${missing.id}' is not mounted; run \`fabric store add\``
58
60
  });
59
61
  }
62
+ for (const store of unboundAvailableStores(projectRoot, globalRoot)) {
63
+ diagnostics.push({
64
+ code: "unbound_available_store",
65
+ severity: "info",
66
+ ref: store.alias,
67
+ message: `store '${store.alias}' is mounted but not bound to this project; run \`fabric store bind ${store.alias}\` to read its knowledge here (then \`fabric store switch-write ${store.alias}\` to write team knowledge into it)`
68
+ });
69
+ }
70
+ const aliasDrift = detectAliasLinkDrift(globalRoot);
71
+ if (aliasDrift.length > 0) {
72
+ diagnostics.push({
73
+ code: "store_alias_link_drift",
74
+ severity: "info",
75
+ ref: aliasDrift.join(", "),
76
+ message: `by-alias readability link(s) out of sync for ${aliasDrift.join(", ")}; run \`fabric doctor --fix\` to repair ~/.fabric/stores/by-alias/`
77
+ });
78
+ }
60
79
  for (const store of global.stores) {
61
80
  if (store.remote === void 0 && store.personal !== true) {
62
81
  diagnostics.push({
@@ -208,6 +227,17 @@ var doctorCommand = defineCommand({
208
227
  type: "string",
209
228
  description: t("cli.doctor.args.history.description"),
210
229
  valueHint: "archive|fix|all"
230
+ },
231
+ // v2.1 ④ conflict-detection (P4): knowledge-conflict lint surface.
232
+ "lint-conflicts": {
233
+ type: "boolean",
234
+ description: t("cli.doctor.args.lint-conflicts.description"),
235
+ default: false
236
+ },
237
+ deep: {
238
+ type: "boolean",
239
+ description: t("cli.doctor.args.deep.description"),
240
+ default: false
211
241
  }
212
242
  },
213
243
  async run({ args }) {
@@ -362,6 +392,22 @@ var doctorCommand = defineCommand({
362
392
  renderCiteCoverageReport(report2, args.json === true, dt);
363
393
  return;
364
394
  }
395
+ if (args["lint-conflicts"] === true) {
396
+ if (fix || fixKnowledge || citeCoverage) {
397
+ writeStderr(dt("cli.doctor.errors.lint-conflicts-mutex"));
398
+ process.exitCode = 1;
399
+ return;
400
+ }
401
+ const report2 = await runDoctorConflictLint(resolution.target, {
402
+ deep: args.deep === true
403
+ });
404
+ if (args.json === true) {
405
+ writeStdout(JSON.stringify(report2, null, 2));
406
+ } else {
407
+ renderConflictLintReport(report2, args.deep === true, dt);
408
+ }
409
+ return;
410
+ }
365
411
  if (fixKnowledge && fix) {
366
412
  writeStderr(dt("cli.doctor.errors.fix-knowledge-fix-mutually-exclusive"));
367
413
  process.exitCode = 1;
@@ -403,6 +449,7 @@ var doctorCommand = defineCommand({
403
449
  } else {
404
450
  fixReport = await runDoctorFix(resolution.target);
405
451
  report = fixReport.report;
452
+ syncStoreAliasLinks();
406
453
  }
407
454
  } else {
408
455
  report = await runDoctorReport(resolution.target);
@@ -701,10 +748,42 @@ function renderCiteCoverageReport(report, jsonMode, dt) {
701
748
  const complianceRate = report.metrics.cite_compliance_rate;
702
749
  const complianceStr = complianceRate === null || complianceRate === void 0 ? dt("doctor.cite.metric.complianceNA") : `${(complianceRate * 100).toFixed(1)}% (${report.metrics.compliant_cites ?? 0}/${(report.metrics.compliant_cites ?? 0) + (report.metrics.noncompliant_cites ?? 0)})`;
703
750
  lines.push(` ${dt("doctor.cite.metric.complianceRate")}: ${complianceStr}`);
751
+ const recallRate = report.metrics.recall_coverage_rate;
752
+ const recallStr = recallRate === null || recallRate === void 0 ? dt("doctor.cite.metric.recallCoverageNA") : `${(recallRate * 100).toFixed(1)}% (${report.metrics.recall_backed_edits ?? 0}/${report.metrics.edits_touched})`;
753
+ lines.push(` ${dt("doctor.cite.metric.recallCoverage")}: ${recallStr}`);
704
754
  const uncorrelatable = report.metrics.uncorrelatable_edits ?? 0;
705
755
  if (uncorrelatable > 0) {
706
756
  lines.push(` ${dt("doctor.cite.metric.uncorrelatableEdits")}: ${uncorrelatable}`);
707
757
  }
758
+ if (report.metrics.exposed_and_mutated !== void 0) {
759
+ lines.push(
760
+ ` ${dt("doctor.cite.metric.exposedAndMutated")}: ${report.metrics.exposed_and_mutated.count}`
761
+ );
762
+ }
763
+ if (report.metrics.mutations_observed !== void 0) {
764
+ lines.push(
765
+ ` ${dt("doctor.cite.metric.mutationsObserved")}: ${report.metrics.mutations_observed.count}`
766
+ );
767
+ }
768
+ if (report.metrics.mutation_pool !== void 0) {
769
+ lines.push(
770
+ ` ${dt("doctor.cite.metric.mutationPool")}: ${report.metrics.mutation_pool.attributed} / ${report.metrics.mutation_pool.unattributed_workspace_dirty} (attributed / unattributed_workspace_dirty)`
771
+ );
772
+ }
773
+ if (report.metrics.sessions_closed !== void 0) {
774
+ lines.push(
775
+ ` ${dt("doctor.cite.metric.sessionsClosed")}: ${report.metrics.sessions_closed.count}`
776
+ );
777
+ }
778
+ if (report.metrics.by_store !== void 0) {
779
+ const storeKeys = Object.keys(report.metrics.by_store).sort();
780
+ if (storeKeys.length > 0) {
781
+ lines.push(` ${dt("doctor.cite.metric.byStore")}:`);
782
+ for (const store of storeKeys) {
783
+ lines.push(` ${store}: ${report.metrics.by_store[store].qualifying_cites}`);
784
+ }
785
+ }
786
+ }
708
787
  if (report.per_client !== void 0 && Object.keys(report.per_client).length > 1) {
709
788
  lines.push("");
710
789
  lines.push(`### ${dt("doctor.cite.section.perClient")}`);
@@ -806,6 +885,38 @@ function appendContractSection(lines, report, dt) {
806
885
  );
807
886
  }
808
887
  }
888
+ function renderConflictLintReport(report, deepRequested, dt) {
889
+ const lines = [];
890
+ lines.push(dt("doctor.conflict.header"));
891
+ lines.push("");
892
+ if (report.candidate_count === 0) {
893
+ lines.push(` ${symbol.ok} ${dt("doctor.conflict.none")}`);
894
+ writeStdout(lines.join("\n"));
895
+ return;
896
+ }
897
+ lines.push(
898
+ ` ${dt("doctor.conflict.summary", {
899
+ candidates: String(report.candidate_count),
900
+ conflicts: String(report.conflict_count),
901
+ threshold: report.threshold.toFixed(2)
902
+ })}`
903
+ );
904
+ if (deepRequested && !report.deep) {
905
+ lines.push(` ${symbol.warn} ${dt("doctor.conflict.deep_no_judge")}`);
906
+ }
907
+ lines.push("");
908
+ for (const pair of report.pairs) {
909
+ const sym = pair.verdict === "conflict" ? symbol.error : symbol.warn;
910
+ const verdictLabel = dt(`doctor.conflict.verdict.${pair.verdict}`);
911
+ const pct = `${(pair.similarity * 100).toFixed(0)}%`;
912
+ let line = ` ${sym} [${pair.a} \u2194 ${pair.b}] (${pair.knowledge_type}/${pair.layer}) ${pct} \u2014 ${verdictLabel}`;
913
+ if (pair.rationale !== void 0 && pair.rationale.length > 0) {
914
+ line += `: ${pair.rationale}`;
915
+ }
916
+ lines.push(line);
917
+ }
918
+ writeStdout(lines.join("\n"));
919
+ }
809
920
  function renderEnrichDescriptionsReport(report, dt) {
810
921
  const header = `${symbol.ok} ${paint.ai("fabric doctor --enrich-descriptions")} mode=${report.mode}${report.dryRun ? " (dry-run)" : ""} scanned=${report.scanned} modified=${report.modified} skipped=${report.skipped}`;
811
922
  writeStdout(header);
package/dist/index.js CHANGED
@@ -11,19 +11,19 @@ import { defineCommand, runCommand, runMain } from "citty";
11
11
 
12
12
  // src/commands/index.ts
13
13
  var allCommands = {
14
- install: () => import("./install-74ANPCCP.js").then((module) => module.default),
14
+ install: () => import("./install-7XJ64WSC.js").then((module) => module.default),
15
15
  // v2.1.0-rc.1 P3: multi-store lifecycle command group (list/add/remove/explain).
16
- store: () => import("./store-XB3ADT65.js").then((module) => module.default),
16
+ store: () => import("./store-ZEZMQVG7.js").then((module) => module.default),
17
17
  // v2.1.0-rc.1 P3 (S9/S17/S37): multi-store pull --rebase + push, conflict resume.
18
- sync: () => import("./sync-UJ4BBCZJ.js").then((module) => module.default),
18
+ sync: () => import("./sync-EA5HZMXM.js").then((module) => module.default),
19
19
  // v2.1.0-rc.1 P3 (F5): read-only identity/status info commands.
20
- whoami: () => import("./whoami-2MLO4Y37.js").then((module) => module.default),
21
- status: () => import("./status-GLQWLWH6.js").then((module) => module.default),
22
- "scope-explain": () => import("./scope-explain-CDIZESP5.js").then((module) => module.default),
23
- doctor: () => import("./doctor-YONYXDX6.js").then((module) => module.default),
24
- uninstall: () => import("./uninstall-C3QXKOO6.js").then((module) => module.default),
25
- config: () => import("./config-XYRBZJDU.js").then((module) => module.default),
26
- "plan-context-hint": () => import("./plan-context-hint-FC6P3WFE.js").then((module) => module.default),
20
+ whoami: () => import("./whoami-3FRWYGML.js").then((module) => module.default),
21
+ status: () => import("./status-7UFLWRX7.js").then((module) => module.default),
22
+ "scope-explain": () => import("./scope-explain-BWRWBCCP.js").then((module) => module.default),
23
+ doctor: () => import("./doctor-U5W4CX5I.js").then((module) => module.default),
24
+ uninstall: () => import("./uninstall-F75MPKQC.js").then((module) => module.default),
25
+ config: () => import("./config-VJMXCLXW.js").then((module) => module.default),
26
+ "plan-context-hint": () => import("./plan-context-hint-CHVZGOZ5.js").then((module) => module.default),
27
27
  // v2.0.0-rc.23 TASK-014 (F8c): S5 onboard-slot coverage. Used by the
28
28
  // fabric-archive Skill's first-run phase to detect unclaimed slots.
29
29
  "onboard-coverage": () => import("./onboard-coverage-JWQWDZW7.js").then((module) => module.default),
@@ -55,7 +55,7 @@ function renderTopLevelError(err, stream = process.stderr) {
55
55
  var main = defineCommand({
56
56
  meta: {
57
57
  name: "fabric",
58
- version: "2.2.0-rc.1",
58
+ version: "2.2.0-rc.4",
59
59
  description: t("cli.main.description")
60
60
  },
61
61
  subCommands: allCommands
@@ -75,7 +75,8 @@ async function run() {
75
75
  process.exit(1);
76
76
  }
77
77
  const code = err !== null && typeof err === "object" ? err.code : void 0;
78
- if (typeof code === "string" && code.startsWith("E_")) {
78
+ const isCittyUsageError = err instanceof Error && err.name === "CLIError" || typeof code === "string" && (code.startsWith("E_") || code.startsWith("EARG") || code === "EUSAGE");
79
+ if (isCittyUsageError) {
79
80
  await runMain(main, { rawArgs });
80
81
  return;
81
82
  }