@fenglimg/fabric-cli 1.3.0 → 1.3.1

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 (33) hide show
  1. package/README.md +24 -22
  2. package/dist/{bootstrap-IUL4SAAK.js → bootstrap-3PUKUYTY.js} +4 -2
  3. package/dist/{chunk-N4DCTOXW.js → chunk-AZRKMFRY.js} +6 -6
  4. package/dist/{chunk-F2BXHPM5.js → chunk-N7EZORJZ.js} +9 -1
  5. package/dist/{chunk-6UUPKSDE.js → chunk-Q4LOVXML.js} +13 -8
  6. package/dist/{chunk-RUQCZA2Q.js → chunk-TKTWHAKV.js} +92 -115
  7. package/dist/{chunk-VMYPJPKV.js → chunk-VOQKQ6W2.js} +153 -21
  8. package/dist/{chunk-TO5RUB4R.js → chunk-XFSQM3LJ.js} +1 -1
  9. package/dist/{config-MKWKDE32.js → config-GINBGANU.js} +2 -2
  10. package/dist/index.js +11 -11
  11. package/dist/{init-BZ73IUHH.js → init-T3LGMGAO.js} +168 -52
  12. package/dist/{ledger-append-XZ5SX4O5.js → ledger-append-DULKJ6Q2.js} +1 -1
  13. package/dist/{pre-commit-AK55G73F.js → pre-commit-IK6SJOPT.js} +5 -5
  14. package/dist/{scan-WKDSKEBB.js → scan-43R3IBLR.js} +2 -2
  15. package/dist/{sync-meta-THZSEM7Y.js → sync-meta-LKVSO6TS.js} +1 -1
  16. package/dist/{update-JZPUJ36D.js → update-AN3FYF2O.js} +5 -5
  17. package/package.json +3 -3
  18. package/templates/agents-md/AGENTS.md.template +14 -13
  19. package/templates/agents-md/variants/cocos.md +20 -20
  20. package/templates/agents-md/variants/next.md +20 -20
  21. package/templates/agents-md/variants/vite.md +20 -20
  22. package/templates/bootstrap/CLAUDE.md +3 -5
  23. package/templates/bootstrap/GEMINI.md +3 -5
  24. package/templates/bootstrap/codex-AGENTS-header.md +3 -5
  25. package/templates/bootstrap/cursor-fabric-bootstrap.mdc +11 -11
  26. package/templates/bootstrap/roo-fabric.md +6 -6
  27. package/templates/bootstrap/windsurf-fabric.md +6 -6
  28. package/templates/claude-hooks/agents-md-init-reminder.cjs +18 -18
  29. package/templates/claude-skills/agents-md-init/SKILL.md +86 -86
  30. package/templates/fabric/human-lock.json +12 -12
  31. package/templates/husky/pre-commit +24 -24
  32. package/dist/{doctor-5KJGOV2P.js → doctor-QTSG2RWF.js} +3 -3
  33. package/dist/{serve-MMN4GYLM.js → serve-4J2CQY25.js} +4 -4
package/dist/index.js CHANGED
@@ -8,17 +8,17 @@ import { defineCommand, runMain } from "citty";
8
8
 
9
9
  // src/commands/index.ts
10
10
  var allCommands = {
11
- init: () => import("./init-BZ73IUHH.js").then((module) => module.default),
12
- update: () => import("./update-JZPUJ36D.js").then((module) => module.default),
13
- scan: () => import("./scan-WKDSKEBB.js").then((module) => module.default),
14
- serve: () => import("./serve-MMN4GYLM.js").then((module) => module.default),
15
- doctor: () => import("./doctor-5KJGOV2P.js").then((module) => module.default),
16
- "sync-meta": () => import("./sync-meta-THZSEM7Y.js").then((module) => module.default),
11
+ init: () => import("./init-T3LGMGAO.js").then((module) => module.default),
12
+ update: () => import("./update-AN3FYF2O.js").then((module) => module.default),
13
+ scan: () => import("./scan-43R3IBLR.js").then((module) => module.default),
14
+ serve: () => import("./serve-4J2CQY25.js").then((module) => module.default),
15
+ doctor: () => import("./doctor-QTSG2RWF.js").then((module) => module.default),
16
+ "sync-meta": () => import("./sync-meta-LKVSO6TS.js").then((module) => module.default),
17
17
  "human-lint": () => import("./human-lint-YSFOZHZ7.js").then((module) => module.default),
18
- "ledger-append": () => import("./ledger-append-XZ5SX4O5.js").then((module) => module.default),
19
- "pre-commit": () => import("./pre-commit-AK55G73F.js").then((module) => module.default),
20
- bootstrap: () => import("./bootstrap-IUL4SAAK.js").then((module) => module.default),
21
- config: () => import("./config-MKWKDE32.js").then((module) => module.configCmd),
18
+ "ledger-append": () => import("./ledger-append-DULKJ6Q2.js").then((module) => module.default),
19
+ "pre-commit": () => import("./pre-commit-IK6SJOPT.js").then((module) => module.default),
20
+ bootstrap: () => import("./bootstrap-3PUKUYTY.js").then((module) => module.default),
21
+ config: () => import("./config-GINBGANU.js").then((module) => module.configCmd),
22
22
  hooks: () => import("./hooks-ZSWVH2JD.js").then((module) => ({
23
23
  ...module.default,
24
24
  meta: {
@@ -32,7 +32,7 @@ var allCommands = {
32
32
  var main = defineCommand({
33
33
  meta: {
34
34
  name: "fabric",
35
- version: "1.3.0",
35
+ version: "1.3.1",
36
36
  description: 'Initialize and manage Fabric projects. Use "fabric init" for one-shot setup.'
37
37
  },
38
38
  subCommands: allCommands
@@ -1,25 +1,29 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ buildFabricBootstrapGuide,
3
4
  installBootstrap
4
- } from "./chunk-RUQCZA2Q.js";
5
+ } from "./chunk-TKTWHAKV.js";
5
6
  import {
6
- createScanReport,
7
7
  detectFramework
8
- } from "./chunk-N4DCTOXW.js";
8
+ } from "./chunk-AZRKMFRY.js";
9
9
  import {
10
10
  installMcpClients
11
- } from "./chunk-TO5RUB4R.js";
12
- import "./chunk-VMYPJPKV.js";
11
+ } from "./chunk-XFSQM3LJ.js";
12
+ import {
13
+ detectClientSupports
14
+ } from "./chunk-VOQKQ6W2.js";
13
15
  import {
14
16
  installHooks
15
17
  } from "./chunk-YDZJRLHL.js";
16
- import {
17
- paint
18
- } from "./chunk-WWNXR34K.js";
19
18
  import {
20
19
  createDebugLogger,
21
20
  resolveDevMode
22
21
  } from "./chunk-AEOYCVBG.js";
22
+ import {
23
+ displayWidth,
24
+ padEnd,
25
+ paint
26
+ } from "./chunk-WWNXR34K.js";
23
27
  import {
24
28
  t
25
29
  } from "./chunk-6ICJICVU.js";
@@ -852,7 +856,7 @@ function readProjectName(target) {
852
856
  return basename(target);
853
857
  }
854
858
  function getCliVersion() {
855
- return true ? "1.3.0" : "unknown";
859
+ return true ? "1.3.1" : "unknown";
856
860
  }
857
861
  function sortRecord(record) {
858
862
  return Object.fromEntries(Object.entries(record).sort(([left], [right]) => left.localeCompare(right)));
@@ -862,11 +866,6 @@ function toPosixPath(path) {
862
866
  }
863
867
 
864
868
  // src/commands/init.ts
865
- var AGENTS_TEMPLATE_BY_FRAMEWORK = {
866
- "cocos-creator": "templates/agents-md/variants/cocos.md",
867
- vite: "templates/agents-md/variants/vite.md",
868
- next: "templates/agents-md/variants/next.md"
869
- };
870
869
  var CLAUDE_INIT_SKILL_TEMPLATE = "templates/claude-skills/agents-md-init/SKILL.md";
871
870
  var CLAUDE_INIT_REMINDER_HOOK_TEMPLATE = "templates/claude-hooks/agents-md-init-reminder.cjs";
872
871
  var CLAUDE_INIT_REMINDER_COMMAND = ".claude/hooks/agents-md-init-reminder.cjs";
@@ -907,6 +906,11 @@ var initCommand = defineCommand({
907
906
  default: true,
908
907
  negativeDescription: t("cli.init.args.no-hooks.description")
909
908
  },
909
+ interactive: {
910
+ type: "boolean",
911
+ description: t("cli.init.args.interactive.description"),
912
+ default: true
913
+ },
910
914
  "mcp-install": {
911
915
  type: "string",
912
916
  default: "global",
@@ -928,11 +932,16 @@ var initCommand = defineCommand({
928
932
  for (const step of resolution.chain) {
929
933
  logger(step);
930
934
  }
935
+ const supports = detectClientSupports(target);
936
+ const interactive = args.interactive !== false && isInteractiveInit();
931
937
  if (options.force) {
932
938
  writeStderr(t("cli.init.force.warning", { path: target }));
933
939
  }
940
+ if (interactive) {
941
+ printInitPlanSummary(target, options, mcpInstallMode, supports);
942
+ }
934
943
  const created = initFabric(target, options);
935
- console.log(formatInitPathAction(created.agentsPath, created.agentsAction));
944
+ console.log(formatInitPathAction(created.bootstrapPath, created.bootstrapAction));
936
945
  console.log(formatInitPathAction(created.metaPath, created.metaAction));
937
946
  console.log(formatInitPathAction(created.humanLockPath, created.humanLockAction));
938
947
  console.log(formatInitPathAction(created.forensicPath, created.forensicAction));
@@ -1020,37 +1029,37 @@ var initCommand = defineCommand({
1020
1029
  console.log(
1021
1030
  t("cli.init.reason-message", {
1022
1031
  label: reasonLabel(),
1023
- message: paint.muted(t("cli.init.reason-message.body"))
1032
+ message: paint.muted(formatInitReasonMessage(supports))
1024
1033
  })
1025
1034
  );
1026
1035
  printInitStageSummary(stageResults);
1036
+ printInitCapabilitySummary(supports, stageResults, options);
1027
1037
  }
1028
1038
  });
1029
1039
  var init_default = initCommand;
1030
1040
  function initFabric(target, options) {
1031
1041
  assertExistingDirectory2(target);
1032
- const agentsPath = join2(target, "AGENTS.md");
1033
1042
  const fabricDir = join2(target, ".fabric");
1043
+ const bootstrapPath = join2(fabricDir, "bootstrap", "README.md");
1034
1044
  const forensicPath = join2(fabricDir, "forensic.json");
1035
1045
  const claudeSkillPath = join2(target, ".claude", "skills", "agents-md-init", "SKILL.md");
1036
1046
  const claudeHookPath = join2(target, ".claude", "hooks", "agents-md-init-reminder.cjs");
1037
1047
  const claudeSettingsPath = join2(target, ".claude", "settings.json");
1038
- const forensicGuardAction = prepareFreshPath(forensicPath, options);
1039
- const agentsAction = prepareFreshPath(agentsPath, options);
1040
- const fabricDirAction = prepareFreshPath(fabricDir, options);
1041
- const forensicAction = forensicGuardAction === "overwritten" || fabricDirAction === "overwritten" ? "overwritten" : "created";
1042
- const scanReport = createScanReport(target);
1043
- const forensicReport = buildForensicReport(target);
1044
- const template = readFileSync2(findAgentsTemplatePath(scanReport.framework.kind), "utf8");
1045
- const humanLockTemplate = readFileSync2(findTemplatePath("templates/fabric/human-lock.json"), "utf8");
1046
- const packageName = readPackageName(target) ?? parse(target).base;
1047
- const agentsContent = template.replaceAll("{ projectName }", packageName).replaceAll("{ frameworkKind }", scanReport.framework.kind);
1048
- const agentsHash = sha256(agentsContent);
1049
- const meta = createInitialMeta(agentsHash);
1050
1048
  const metaPath = join2(fabricDir, "agents.meta.json");
1051
1049
  const humanLockPath = join2(fabricDir, "human-lock.json");
1052
- mkdirSync(fabricDir, { recursive: false });
1053
- writeNewFile(agentsPath, agentsContent, options);
1050
+ prepareWritableDirectory(fabricDir, options);
1051
+ const bootstrapAction = prepareFreshPath(bootstrapPath, options);
1052
+ const metaAction = prepareFreshPath(metaPath, options);
1053
+ const humanLockAction = prepareFreshPath(humanLockPath, options);
1054
+ const forensicAction = prepareFreshPath(forensicPath, options);
1055
+ const forensicReport = buildForensicReport(target);
1056
+ const humanLockTemplate = readFileSync2(findTemplatePath("templates/fabric/human-lock.json"), "utf8");
1057
+ const bootstrapContent = buildFabricBootstrapGuide(target);
1058
+ const bootstrapHash = sha256(bootstrapContent);
1059
+ const meta = createInitialMeta(bootstrapHash);
1060
+ mkdirSync(fabricDir, { recursive: true });
1061
+ mkdirSync(dirname(bootstrapPath), { recursive: true });
1062
+ writeNewFile(bootstrapPath, bootstrapContent, options);
1054
1063
  writeNewFile(metaPath, `${JSON.stringify(meta, null, 2)}
1055
1064
  `, options);
1056
1065
  writeNewFile(humanLockPath, humanLockTemplate.endsWith("\n") ? humanLockTemplate : `${humanLockTemplate}
@@ -1065,12 +1074,12 @@ function initFabric(target, options) {
1065
1074
  );
1066
1075
  const claudeSettingsAction = mergeClaudeStopHook(claudeSettingsPath, options);
1067
1076
  return {
1068
- agentsPath,
1069
- agentsAction,
1077
+ bootstrapPath,
1078
+ bootstrapAction,
1070
1079
  metaPath,
1071
- metaAction: fabricDirAction,
1080
+ metaAction,
1072
1081
  humanLockPath,
1073
- humanLockAction: fabricDirAction,
1082
+ humanLockAction,
1074
1083
  forensicPath,
1075
1084
  forensicAction,
1076
1085
  claudeSkillPath,
@@ -1081,10 +1090,6 @@ function initFabric(target, options) {
1081
1090
  claudeSettingsAction
1082
1091
  };
1083
1092
  }
1084
- function findAgentsTemplatePath(frameworkKind) {
1085
- const relativePath = AGENTS_TEMPLATE_BY_FRAMEWORK[frameworkKind] ?? "templates/agents-md/AGENTS.md.template";
1086
- return findTemplatePath(relativePath);
1087
- }
1088
1093
  function normalizeTarget2(targetInput) {
1089
1094
  return isAbsolute2(targetInput) ? targetInput : resolve2(process.cwd(), targetInput);
1090
1095
  }
@@ -1126,7 +1131,7 @@ function createInitialMeta(agentsHash) {
1126
1131
  revision: sha256(agentsHash),
1127
1132
  nodes: {
1128
1133
  L0: {
1129
- file: "AGENTS.md",
1134
+ file: ".fabric/bootstrap/README.md",
1130
1135
  scope_glob: "**",
1131
1136
  deps: [],
1132
1137
  priority: "high",
@@ -1137,18 +1142,6 @@ function createInitialMeta(agentsHash) {
1137
1142
  }
1138
1143
  };
1139
1144
  }
1140
- function readPackageName(target) {
1141
- const packageJsonPath = join2(target, "package.json");
1142
- if (!existsSync2(packageJsonPath)) {
1143
- return void 0;
1144
- }
1145
- try {
1146
- const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf8"));
1147
- return packageJson.name;
1148
- } catch {
1149
- return void 0;
1150
- }
1151
- }
1152
1145
  function findTemplatePath(relativePath) {
1153
1146
  const currentModuleDir = dirname(fileURLToPath(import.meta.url));
1154
1147
  const candidates = [
@@ -1185,6 +1178,15 @@ function prepareFreshPath(path, options) {
1185
1178
  rmSync(path, { recursive: true, force: true });
1186
1179
  return "overwritten";
1187
1180
  }
1181
+ function prepareWritableDirectory(path, options) {
1182
+ if (!existsSync2(path) || statSync2(path).isDirectory()) {
1183
+ return;
1184
+ }
1185
+ if (!options?.force) {
1186
+ throw new Error(t("cli.init.errors.abort-existing", { path }));
1187
+ }
1188
+ rmSync(path, { force: true });
1189
+ }
1188
1190
  function writeNewFile(path, content, options) {
1189
1191
  const existed = existsSync2(path);
1190
1192
  if (existed && !options?.force) {
@@ -1329,6 +1331,120 @@ function collectInitStageNames(stageResults, disposition) {
1329
1331
  function shouldPrintHooksNextStep(options, stageResults) {
1330
1332
  return Boolean(options.skipHooks) || stageResults.some((stage) => stage.name === "hooks" && stage.disposition === "failed");
1331
1333
  }
1334
+ function isInteractiveInit() {
1335
+ return Boolean(process.stdout.isTTY) && Boolean(process.stderr.isTTY);
1336
+ }
1337
+ function printInitPlanSummary(target, options, mcpInstallMode, supports) {
1338
+ console.log(t("cli.init.plan.title"));
1339
+ console.log(t("cli.init.plan.target", { target }));
1340
+ console.log(
1341
+ t("cli.init.plan.actions", {
1342
+ bootstrap: yesNoLabel(!options.skipBootstrap),
1343
+ mcp: yesNoLabel(!options.skipMcp),
1344
+ hooks: yesNoLabel(!options.skipHooks),
1345
+ mcpInstall: mcpInstallMode
1346
+ })
1347
+ );
1348
+ const detected = supports.filter((support) => support.detected);
1349
+ console.log(
1350
+ t("cli.init.plan.detected", {
1351
+ clients: detected.length > 0 ? detected.map((support) => support.label).join(", ") : t("cli.shared.none")
1352
+ })
1353
+ );
1354
+ console.log(t("cli.init.plan.writes"));
1355
+ console.log(` - ${target}/.fabric/bootstrap/README.md`);
1356
+ console.log(` - ${target}/.fabric/agents.meta.json`);
1357
+ console.log(` - ${target}/.fabric/human-lock.json`);
1358
+ console.log(` - ${target}/.fabric/forensic.json`);
1359
+ }
1360
+ function printInitCapabilitySummary(supports, stageResults, options) {
1361
+ const detected = supports.filter((support) => support.detected);
1362
+ if (detected.length === 0) {
1363
+ console.log(t("cli.init.capabilities.none"));
1364
+ return;
1365
+ }
1366
+ console.log(t("cli.init.capabilities.title"));
1367
+ const rows = detected.map((support) => toCapabilityRow(support, stageResults, options));
1368
+ const headers = {
1369
+ client: t("cli.init.capabilities.header.client"),
1370
+ bootstrap: t("cli.init.capabilities.header.bootstrap"),
1371
+ mcp: t("cli.init.capabilities.header.mcp"),
1372
+ hook: t("cli.init.capabilities.header.hook"),
1373
+ skill: t("cli.init.capabilities.header.skill"),
1374
+ followUp: t("cli.init.capabilities.header.follow-up")
1375
+ };
1376
+ const widths = {
1377
+ client: Math.max(displayWidth(headers.client), ...rows.map((row) => displayWidth(row.client))),
1378
+ bootstrap: Math.max(displayWidth(headers.bootstrap), ...rows.map((row) => displayWidth(row.bootstrap))),
1379
+ mcp: Math.max(displayWidth(headers.mcp), ...rows.map((row) => displayWidth(row.mcp))),
1380
+ hook: Math.max(displayWidth(headers.hook), ...rows.map((row) => displayWidth(row.hook))),
1381
+ skill: Math.max(displayWidth(headers.skill), ...rows.map((row) => displayWidth(row.skill))),
1382
+ followUp: Math.max(displayWidth(headers.followUp), ...rows.map((row) => displayWidth(row.followUp)))
1383
+ };
1384
+ console.log(formatCapabilityTableRow(headers, widths));
1385
+ console.log(formatCapabilityDivider(widths));
1386
+ for (const row of rows) {
1387
+ console.log(formatCapabilityTableRow(row, widths));
1388
+ }
1389
+ }
1390
+ function toCapabilityRow(support, stageResults, options) {
1391
+ const stage = (name) => stageResults.find((entry) => entry.name === name)?.disposition ?? null;
1392
+ const bootstrap = support.capabilities.bootstrap ? capabilityStatus(options.skipBootstrap ? "skipped" : stage("bootstrap")) : t("cli.init.capabilities.status.na");
1393
+ const mcp = support.capabilities.mcp ? capabilityStatus(options.skipMcp ? "skipped" : stage("mcp")) : t("cli.init.capabilities.status.na");
1394
+ const hook = support.capabilities.hook ? capabilityStatus("ran") : t("cli.init.capabilities.status.na");
1395
+ const skill = support.capabilities.skill ? t("cli.init.capabilities.status.installed") : t("cli.init.capabilities.status.manual");
1396
+ return {
1397
+ client: support.label,
1398
+ bootstrap,
1399
+ mcp,
1400
+ hook,
1401
+ skill,
1402
+ followUp: support.capabilities.skill ? t("cli.init.capabilities.follow-up.ready") : t("cli.init.capabilities.follow-up.manual")
1403
+ };
1404
+ }
1405
+ function capabilityStatus(disposition) {
1406
+ switch (disposition) {
1407
+ case "ran":
1408
+ return t("cli.init.capabilities.status.ready");
1409
+ case "skipped":
1410
+ return t("cli.init.capabilities.status.skipped");
1411
+ case "failed":
1412
+ return t("cli.init.capabilities.status.failed");
1413
+ case null:
1414
+ return t("cli.init.capabilities.status.na");
1415
+ default:
1416
+ return t("cli.init.capabilities.status.ready");
1417
+ }
1418
+ }
1419
+ function formatCapabilityTableRow(row, widths) {
1420
+ return [
1421
+ padEnd(row.client, widths.client),
1422
+ padEnd(row.bootstrap, widths.bootstrap),
1423
+ padEnd(row.mcp, widths.mcp),
1424
+ padEnd(row.hook, widths.hook),
1425
+ padEnd(row.skill, widths.skill),
1426
+ padEnd(row.followUp, widths.followUp)
1427
+ ].join(" ");
1428
+ }
1429
+ function formatCapabilityDivider(widths) {
1430
+ return [
1431
+ "".padEnd(widths.client, "-"),
1432
+ "".padEnd(widths.bootstrap, "-"),
1433
+ "".padEnd(widths.mcp, "-"),
1434
+ "".padEnd(widths.hook, "-"),
1435
+ "".padEnd(widths.skill, "-"),
1436
+ "".padEnd(widths.followUp, "-")
1437
+ ].join(" ");
1438
+ }
1439
+ function formatInitReasonMessage(supports) {
1440
+ if (supports.some((support) => support.detected && support.capabilities.skill)) {
1441
+ return t("cli.init.reason-message.body");
1442
+ }
1443
+ return t("cli.init.reason-message.manual-body");
1444
+ }
1445
+ function yesNoLabel(value) {
1446
+ return value ? t("cli.shared.yes") : t("cli.shared.no");
1447
+ }
1332
1448
  function formatInitPathAction(path, action) {
1333
1449
  return t("cli.init.created-path", { label: labelForInitWriteAction(action), path });
1334
1450
  }
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  ledgerAppendCommand,
4
4
  ledger_append_default
5
- } from "./chunk-F2BXHPM5.js";
5
+ } from "./chunk-N7EZORJZ.js";
6
6
  import "./chunk-6ICJICVU.js";
7
7
  export {
8
8
  ledger_append_default as default,
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  sync_meta_default
4
- } from "./chunk-6UUPKSDE.js";
4
+ } from "./chunk-Q4LOVXML.js";
5
5
  import {
6
6
  human_lint_default
7
7
  } from "./chunk-L43IGJ6X.js";
8
8
  import {
9
9
  ledger_append_default
10
- } from "./chunk-F2BXHPM5.js";
11
- import "./chunk-WWNXR34K.js";
10
+ } from "./chunk-N7EZORJZ.js";
12
11
  import {
13
12
  resolveDevModeTarget
14
13
  } from "./chunk-AEOYCVBG.js";
14
+ import "./chunk-WWNXR34K.js";
15
15
  import {
16
16
  t
17
17
  } from "./chunk-6ICJICVU.js";
@@ -57,9 +57,9 @@ function tryReadAgentsMeta(target) {
57
57
  }
58
58
  }
59
59
  function matchesFabricScope(stagedFiles, meta) {
60
- const scopeGlobs = Object.values(meta.nodes).filter((node) => node.file !== "AGENTS.md").map((node) => node.scope_glob);
60
+ const scopeGlobs = Object.values(meta.nodes).filter((node) => node.file !== ".fabric/bootstrap/README.md" && node.file !== "AGENTS.md").map((node) => node.scope_glob);
61
61
  return stagedFiles.some(
62
- (file) => file === "AGENTS.md" || file === ".fabric/agents.meta.json" || file === ".fabric/human-lock.json" || file === ".intent-ledger.jsonl" || scopeGlobs.some((pattern) => minimatch(file, pattern, { dot: true }))
62
+ (file) => file === ".fabric/bootstrap/README.md" || file === "AGENTS.md" || file === ".fabric/agents.meta.json" || file === ".fabric/human-lock.json" || file === ".intent-ledger.jsonl" || scopeGlobs.some((pattern) => minimatch(file, pattern, { dot: true }))
63
63
  );
64
64
  }
65
65
  var pre_commit_default = defineCommand({
@@ -3,9 +3,9 @@ import {
3
3
  createScanReport,
4
4
  scanCommand,
5
5
  scan_default
6
- } from "./chunk-N4DCTOXW.js";
7
- import "./chunk-WWNXR34K.js";
6
+ } from "./chunk-AZRKMFRY.js";
8
7
  import "./chunk-AEOYCVBG.js";
8
+ import "./chunk-WWNXR34K.js";
9
9
  import "./chunk-6ICJICVU.js";
10
10
  export {
11
11
  createScanReport,
@@ -5,7 +5,7 @@ import {
5
5
  deriveTopologyType,
6
6
  syncMetaCommand,
7
7
  sync_meta_default
8
- } from "./chunk-6UUPKSDE.js";
8
+ } from "./chunk-Q4LOVXML.js";
9
9
  import "./chunk-6ICJICVU.js";
10
10
  export {
11
11
  computeAgentsMeta,
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  installMcpClients
4
- } from "./chunk-TO5RUB4R.js";
5
- import "./chunk-VMYPJPKV.js";
4
+ } from "./chunk-XFSQM3LJ.js";
5
+ import "./chunk-VOQKQ6W2.js";
6
6
  import {
7
7
  installHooks
8
8
  } from "./chunk-YDZJRLHL.js";
9
- import {
10
- paint
11
- } from "./chunk-WWNXR34K.js";
12
9
  import {
13
10
  resolveDevModeTarget
14
11
  } from "./chunk-AEOYCVBG.js";
12
+ import {
13
+ paint
14
+ } from "./chunk-WWNXR34K.js";
15
15
  import {
16
16
  t
17
17
  } from "./chunk-6ICJICVU.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fenglimg/fabric-cli",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "fab": "dist/index.js",
@@ -18,8 +18,8 @@
18
18
  "minimatch": "^10.0.1",
19
19
  "picocolors": "^1.1.1",
20
20
  "string-width": "^7.2.0",
21
- "@fenglimg/fabric-server": "1.3.0",
22
- "@fenglimg/fabric-shared": "1.3.0"
21
+ "@fenglimg/fabric-shared": "1.3.1",
22
+ "@fenglimg/fabric-server": "1.3.1"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/iarna__toml": "^2.0.5",
@@ -1,19 +1,20 @@
1
- # { projectName } — Fabric Bootstrap Protocol
2
-
3
- ## CORE RULES (DO NOT TRANSLATE)
4
-
5
- MUST: Treat this file as the Fabric Protocol bootstrap for this repository.
6
- MUST: Treat `.fabric/agents/` as the authoritative home for all AI shadow constraints.
7
- MUST: Before ANY code reading, architecture planning, or logic modification, call `fab_get_rules(path=<target file>)`.
8
- MUST: When creating or changing an L1/L2 rule node, keep `.fabric/agents.meta.json` synchronized through Fabric tooling.
9
- MUST: Preserve protected tokens exactly: `AGENTS.md`, `.fabric/agents/`, `.fabric/agents.meta.json`, `fab_get_rules`, `shadow constraints`, `Shadow Mirroring`, `MUST`, `NEVER`.
10
- NEVER: Add import-style directive lines to this bootstrap file.
11
- NEVER: Put framework, domain, repository rule bodies, or submodule rules in this file.
12
- NEVER: Create colocated `AGENTS.md` rule files under source directories.
13
-
1
+ # { projectName } — Fabric Bootstrap Protocol
2
+
3
+ ## CORE RULES (DO NOT TRANSLATE)
4
+
5
+ MUST: Treat this file as the Fabric Protocol bootstrap for this repository.
6
+ MUST: Treat `.fabric/agents/` as the authoritative home for all AI shadow constraints.
7
+ MUST: Before ANY code reading, architecture planning, or logic modification, call `fab_get_rules(path=<target file>)`.
8
+ MUST: When creating or changing an L1/L2 rule node, keep `.fabric/agents.meta.json` synchronized through Fabric tooling.
9
+ MUST: Preserve protected tokens exactly: `AGENTS.md`, `.fabric/agents/`, `.fabric/agents.meta.json`, `fab_get_rules`, `shadow constraints`, `Shadow Mirroring`, `MUST`, `NEVER`.
10
+ NEVER: Add import-style directive lines to this bootstrap file.
11
+ NEVER: Put framework, domain, repository rule bodies, or submodule rules in this file.
12
+ NEVER: Create colocated `AGENTS.md` rule files under source directories.
13
+
14
14
  ## 使用说明 / Explanation
15
15
 
16
16
  - 本文件只负责启动 Fabric Bootstrap Protocol,不承载项目业务规则。
17
+ - 详细 bootstrap 说明位于 `.fabric/bootstrap/README.md`。
17
18
  - Detected framework kind: `{ frameworkKind }`.
18
19
  - This repository uses `Shadow Mirroring`: source directories contain ZERO rule files, while `.fabric/agents/` mirrors source paths for AI constraints.
19
20
  - 根级规则应放在 `.fabric/agents/root.md`;跨领域规则应放在 `.fabric/agents/_cross/`。
@@ -1,20 +1,20 @@
1
- # { projectName } — Fabric Bootstrap Protocol
2
-
3
- ## CORE RULES (DO NOT TRANSLATE)
4
-
5
- MUST: Treat this file as the Fabric Protocol bootstrap for this repository.
6
- MUST: Treat `.fabric/agents/` as the authoritative home for all AI shadow constraints.
7
- MUST: Before ANY code reading, architecture planning, or logic modification, call `fab_get_rules(path=<target file>)`.
8
- MUST: When creating or changing an L1/L2 rule node, keep `.fabric/agents.meta.json` synchronized through Fabric tooling.
9
- MUST: Preserve protected tokens exactly: `AGENTS.md`, `.fabric/agents/`, `.fabric/agents.meta.json`, `fab_get_rules`, `shadow constraints`, `Shadow Mirroring`, `MUST`, `NEVER`.
10
- NEVER: Add import-style directive lines to this bootstrap file.
11
- NEVER: Put Cocos, asset, prefab, scene, repository rule bodies, or submodule rules in this file.
12
- NEVER: Create colocated `AGENTS.md` rule files under source directories.
13
-
14
- ## 使用说明 / Explanation
15
-
16
- - 本文件只负责启动 Fabric Bootstrap Protocol,不承载 Cocos 业务或编辑器规则。
17
- - Detected framework kind: `cocos-creator`.
18
- - This repository uses `Shadow Mirroring`: source directories contain ZERO rule files, while `.fabric/agents/` mirrors source paths for AI constraints.
19
- - 根级规则应放在 `.fabric/agents/root.md`;跨领域规则应放在 `.fabric/agents/_cross/`。
20
- - If `.fabric/agents/root.md` is missing, stop normal coding and run the initialization flow that creates shadow constraints.
1
+ # { projectName } — Fabric Bootstrap Protocol
2
+
3
+ ## CORE RULES (DO NOT TRANSLATE)
4
+
5
+ MUST: Treat this file as the Fabric Protocol bootstrap for this repository.
6
+ MUST: Treat `.fabric/agents/` as the authoritative home for all AI shadow constraints.
7
+ MUST: Before ANY code reading, architecture planning, or logic modification, call `fab_get_rules(path=<target file>)`.
8
+ MUST: When creating or changing an L1/L2 rule node, keep `.fabric/agents.meta.json` synchronized through Fabric tooling.
9
+ MUST: Preserve protected tokens exactly: `AGENTS.md`, `.fabric/agents/`, `.fabric/agents.meta.json`, `fab_get_rules`, `shadow constraints`, `Shadow Mirroring`, `MUST`, `NEVER`.
10
+ NEVER: Add import-style directive lines to this bootstrap file.
11
+ NEVER: Put Cocos, asset, prefab, scene, repository rule bodies, or submodule rules in this file.
12
+ NEVER: Create colocated `AGENTS.md` rule files under source directories.
13
+
14
+ ## 使用说明 / Explanation
15
+
16
+ - 本文件只负责启动 Fabric Bootstrap Protocol,不承载 Cocos 业务或编辑器规则。
17
+ - Detected framework kind: `cocos-creator`.
18
+ - This repository uses `Shadow Mirroring`: source directories contain ZERO rule files, while `.fabric/agents/` mirrors source paths for AI constraints.
19
+ - 根级规则应放在 `.fabric/agents/root.md`;跨领域规则应放在 `.fabric/agents/_cross/`。
20
+ - If `.fabric/agents/root.md` is missing, stop normal coding and run the initialization flow that creates shadow constraints.
@@ -1,20 +1,20 @@
1
- # { projectName } — Fabric Bootstrap Protocol
2
-
3
- ## CORE RULES (DO NOT TRANSLATE)
4
-
5
- MUST: Treat this file as the Fabric Protocol bootstrap for this repository.
6
- MUST: Treat `.fabric/agents/` as the authoritative home for all AI shadow constraints.
7
- MUST: Before ANY code reading, architecture planning, or logic modification, call `fab_get_rules(path=<target file>)`.
8
- MUST: When creating or changing an L1/L2 rule node, keep `.fabric/agents.meta.json` synchronized through Fabric tooling.
9
- MUST: Preserve protected tokens exactly: `AGENTS.md`, `.fabric/agents/`, `.fabric/agents.meta.json`, `fab_get_rules`, `shadow constraints`, `Shadow Mirroring`, `MUST`, `NEVER`.
10
- NEVER: Add import-style directive lines to this bootstrap file.
11
- NEVER: Put Next.js, route, repository rule bodies, or submodule rules in this file.
12
- NEVER: Create colocated `AGENTS.md` rule files under source directories.
13
-
14
- ## 使用说明 / Explanation
15
-
16
- - 本文件只负责启动 Fabric Bootstrap Protocol,不承载 Next.js 业务或路由规则。
17
- - Detected framework kind: `next`.
18
- - This repository uses `Shadow Mirroring`: source directories contain ZERO rule files, while `.fabric/agents/` mirrors source paths for AI constraints.
19
- - 根级规则应放在 `.fabric/agents/root.md`;跨领域规则应放在 `.fabric/agents/_cross/`。
20
- - If `.fabric/agents/root.md` is missing, stop normal coding and run the initialization flow that creates shadow constraints.
1
+ # { projectName } — Fabric Bootstrap Protocol
2
+
3
+ ## CORE RULES (DO NOT TRANSLATE)
4
+
5
+ MUST: Treat this file as the Fabric Protocol bootstrap for this repository.
6
+ MUST: Treat `.fabric/agents/` as the authoritative home for all AI shadow constraints.
7
+ MUST: Before ANY code reading, architecture planning, or logic modification, call `fab_get_rules(path=<target file>)`.
8
+ MUST: When creating or changing an L1/L2 rule node, keep `.fabric/agents.meta.json` synchronized through Fabric tooling.
9
+ MUST: Preserve protected tokens exactly: `AGENTS.md`, `.fabric/agents/`, `.fabric/agents.meta.json`, `fab_get_rules`, `shadow constraints`, `Shadow Mirroring`, `MUST`, `NEVER`.
10
+ NEVER: Add import-style directive lines to this bootstrap file.
11
+ NEVER: Put Next.js, route, repository rule bodies, or submodule rules in this file.
12
+ NEVER: Create colocated `AGENTS.md` rule files under source directories.
13
+
14
+ ## 使用说明 / Explanation
15
+
16
+ - 本文件只负责启动 Fabric Bootstrap Protocol,不承载 Next.js 业务或路由规则。
17
+ - Detected framework kind: `next`.
18
+ - This repository uses `Shadow Mirroring`: source directories contain ZERO rule files, while `.fabric/agents/` mirrors source paths for AI constraints.
19
+ - 根级规则应放在 `.fabric/agents/root.md`;跨领域规则应放在 `.fabric/agents/_cross/`。
20
+ - If `.fabric/agents/root.md` is missing, stop normal coding and run the initialization flow that creates shadow constraints.
@@ -1,20 +1,20 @@
1
- # { projectName } — Fabric Bootstrap Protocol
2
-
3
- ## CORE RULES (DO NOT TRANSLATE)
4
-
5
- MUST: Treat this file as the Fabric Protocol bootstrap for this repository.
6
- MUST: Treat `.fabric/agents/` as the authoritative home for all AI shadow constraints.
7
- MUST: Before ANY code reading, architecture planning, or logic modification, call `fab_get_rules(path=<target file>)`.
8
- MUST: When creating or changing an L1/L2 rule node, keep `.fabric/agents.meta.json` synchronized through Fabric tooling.
9
- MUST: Preserve protected tokens exactly: `AGENTS.md`, `.fabric/agents/`, `.fabric/agents.meta.json`, `fab_get_rules`, `shadow constraints`, `Shadow Mirroring`, `MUST`, `NEVER`.
10
- NEVER: Add import-style directive lines to this bootstrap file.
11
- NEVER: Put Vite, browser, repository rule bodies, or submodule rules in this file.
12
- NEVER: Create colocated `AGENTS.md` rule files under source directories.
13
-
14
- ## 使用说明 / Explanation
15
-
16
- - 本文件只负责启动 Fabric Bootstrap Protocol,不承载 Vite 业务或浏览器规则。
17
- - Detected framework kind: `vite`.
18
- - This repository uses `Shadow Mirroring`: source directories contain ZERO rule files, while `.fabric/agents/` mirrors source paths for AI constraints.
19
- - 根级规则应放在 `.fabric/agents/root.md`;跨领域规则应放在 `.fabric/agents/_cross/`。
20
- - If `.fabric/agents/root.md` is missing, stop normal coding and run the initialization flow that creates shadow constraints.
1
+ # { projectName } — Fabric Bootstrap Protocol
2
+
3
+ ## CORE RULES (DO NOT TRANSLATE)
4
+
5
+ MUST: Treat this file as the Fabric Protocol bootstrap for this repository.
6
+ MUST: Treat `.fabric/agents/` as the authoritative home for all AI shadow constraints.
7
+ MUST: Before ANY code reading, architecture planning, or logic modification, call `fab_get_rules(path=<target file>)`.
8
+ MUST: When creating or changing an L1/L2 rule node, keep `.fabric/agents.meta.json` synchronized through Fabric tooling.
9
+ MUST: Preserve protected tokens exactly: `AGENTS.md`, `.fabric/agents/`, `.fabric/agents.meta.json`, `fab_get_rules`, `shadow constraints`, `Shadow Mirroring`, `MUST`, `NEVER`.
10
+ NEVER: Add import-style directive lines to this bootstrap file.
11
+ NEVER: Put Vite, browser, repository rule bodies, or submodule rules in this file.
12
+ NEVER: Create colocated `AGENTS.md` rule files under source directories.
13
+
14
+ ## 使用说明 / Explanation
15
+
16
+ - 本文件只负责启动 Fabric Bootstrap Protocol,不承载 Vite 业务或浏览器规则。
17
+ - Detected framework kind: `vite`.
18
+ - This repository uses `Shadow Mirroring`: source directories contain ZERO rule files, while `.fabric/agents/` mirrors source paths for AI constraints.
19
+ - 根级规则应放在 `.fabric/agents/root.md`;跨领域规则应放在 `.fabric/agents/_cross/`。
20
+ - If `.fabric/agents/root.md` is missing, stop normal coding and run the initialization flow that creates shadow constraints.
@@ -1,8 +1,6 @@
1
1
  # Fabric Bootstrap
2
- - 本项目使用 Fabric Protocol 管理规则。
3
- - **任何文件修改前**,必须调 MCP tool `fab_get_rules(path=<被改文件>)` 获取规则。
4
- - 新建 L1/L2 节点时,必须调 `fab_update_registry`,**严禁**直接编辑 `.fabric/agents.meta.json`。
5
- - 涉及 @HUMAN 段(`.fabric/human-lock.json` 中列出)时,必须停下来请示人类。
6
- - 每次完整任务结束,调 `fab_append_intent` 写一条意图记录。
2
+ - 主说明文档已收敛到 `.fabric/bootstrap/README.md`。
3
+ - 项目级 bootstrap 入口仍然是 `AGENTS.md`。
4
+ - 修改任何文件前必须调用 `fab_get_rules(path=<被改文件>)`。
7
5
 
8
6
  @AGENTS.md