@fenglimg/fabric-cli 1.8.0-rc.3 → 2.0.0-rc.8

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 (46) hide show
  1. package/README.md +6 -6
  2. package/dist/chunk-6ICJICVU.js +10 -0
  3. package/dist/chunk-74SZWYPH.js +658 -0
  4. package/dist/chunk-EYIDD2YS.js +1000 -0
  5. package/dist/{chunk-QPCRBQ5Y.js → chunk-OBQU6NHO.js} +1 -52
  6. package/dist/chunk-WWNXR34K.js +49 -0
  7. package/dist/doctor-T7JWODKG.js +282 -0
  8. package/dist/hooks-Y74Y5LQS.js +12 -0
  9. package/dist/index.js +7 -5
  10. package/dist/{init-7EYGUJNJ.js → init-55WZSUK6.js} +312 -1022
  11. package/dist/plan-context-hint-QMUPAXIB.js +98 -0
  12. package/dist/scan-LMK3UCWL.js +22 -0
  13. package/dist/{serve-466QXQ5Q.js → serve-H554BHLG.js} +8 -4
  14. package/package.json +3 -3
  15. package/templates/agents-md/AGENTS.md.template +55 -17
  16. package/templates/bootstrap/CLAUDE.md +1 -1
  17. package/templates/bootstrap/codex-AGENTS-header.md +1 -1
  18. package/templates/bootstrap/cursor-fabric-bootstrap.mdc +1 -1
  19. package/templates/hooks/configs/README.md +73 -0
  20. package/templates/hooks/configs/claude-code.json +37 -0
  21. package/templates/hooks/configs/codex-hooks.json +20 -0
  22. package/templates/hooks/configs/cursor-hooks.json +20 -0
  23. package/templates/hooks/fabric-hint.cjs +1307 -0
  24. package/templates/hooks/knowledge-hint-broad.cjs +464 -0
  25. package/templates/hooks/knowledge-hint-narrow.cjs +826 -0
  26. package/templates/hooks/lib/session-digest-writer.cjs +172 -0
  27. package/templates/skills/fabric-archive/SKILL.md +486 -0
  28. package/templates/skills/fabric-import/SKILL.md +588 -0
  29. package/templates/skills/fabric-review/SKILL.md +382 -0
  30. package/dist/chunk-NMMUETVK.js +0 -216
  31. package/dist/doctor-F52XWWZC.js +0 -98
  32. package/dist/scan-NNBNGIZG.js +0 -12
  33. package/templates/agents-md/variants/cocos.md +0 -20
  34. package/templates/agents-md/variants/next.md +0 -20
  35. package/templates/agents-md/variants/vite.md +0 -20
  36. package/templates/bootstrap/GEMINI.md +0 -8
  37. package/templates/bootstrap/roo-fabric.md +0 -5
  38. package/templates/bootstrap/windsurf-fabric.md +0 -5
  39. package/templates/claude-hooks/fabric-init-reminder.cjs +0 -18
  40. package/templates/claude-skills/fabric-init/SKILL.md +0 -163
  41. package/templates/codex-hooks/fabric-session-start.cjs +0 -19
  42. package/templates/codex-hooks/fabric-stop-reminder.cjs +0 -18
  43. package/templates/codex-skills/fabric-init/SKILL.md +0 -162
  44. package/templates/husky/pre-commit +0 -9
  45. package/templates/skill-source/fabric-init/SOURCE.md +0 -157
  46. package/templates/skill-source/fabric-init/clients.json +0 -17
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ resolveDevMode
4
+ } from "./chunk-OBQU6NHO.js";
5
+
6
+ // src/commands/plan-context-hint.ts
7
+ import { defineCommand } from "citty";
8
+ import { planContext } from "@fenglimg/fabric-server";
9
+ var ALL_PATHS_SENTINEL = "**";
10
+ var planContextHintCommand = defineCommand({
11
+ meta: {
12
+ name: "plan-context-hint",
13
+ description: "Emit versioned knowledge hint JSON to stdout. Used by rc.6 hooks and the fabric-import skill."
14
+ },
15
+ args: {
16
+ paths: {
17
+ type: "string",
18
+ description: "Comma-separated list of file paths to compute narrow hints for."
19
+ },
20
+ all: {
21
+ type: "boolean",
22
+ description: "Return the full broad+narrow set with no path filter.",
23
+ default: false
24
+ },
25
+ target: {
26
+ type: "string",
27
+ description: "Override the project root (defaults to cwd / dev-mode resolution)."
28
+ }
29
+ },
30
+ async run({ args }) {
31
+ try {
32
+ const output = await runPlanContextHint({
33
+ paths: parsePathsArg(args.paths),
34
+ all: args.all === true,
35
+ target: args.target
36
+ });
37
+ process.stdout.write(`${JSON.stringify(output)}
38
+ `);
39
+ } catch (error) {
40
+ const message = error instanceof Error ? error.message : String(error);
41
+ process.stderr.write(`plan-context-hint failed: ${message}
42
+ `);
43
+ process.exitCode = 1;
44
+ }
45
+ }
46
+ });
47
+ var plan_context_hint_default = planContextHintCommand;
48
+ async function runPlanContextHint(opts) {
49
+ const all = opts.all === true;
50
+ const explicitPaths = (opts.paths ?? []).filter((p) => p.length > 0);
51
+ const targetPaths = all ? [ALL_PATHS_SENTINEL] : explicitPaths.length > 0 ? explicitPaths : [ALL_PATHS_SENTINEL];
52
+ const resolution = resolveDevMode(opts.target, process.cwd());
53
+ const result = await planContext(resolution.target, {
54
+ paths: targetPaths
55
+ });
56
+ const sharedIndex = result.shared.description_index;
57
+ const narrowSource = all ? sharedIndex : (
58
+ // Path mode: union of per-entry description_index across requested
59
+ // paths, deduped by stable_id. This is identical to `shared` for L0/L1
60
+ // entries (always included) and additionally captures L2 entries whose
61
+ // scope_glob matches the requested path.
62
+ dedupeByStableId(result.entries.flatMap((entry) => entry.description_index))
63
+ );
64
+ const narrow = narrowSource.map((item) => ({
65
+ id: item.stable_id,
66
+ type: item.type ?? item.description.knowledge_type ?? "",
67
+ maturity: item.maturity ?? item.description.maturity ?? "",
68
+ summary: item.description.summary
69
+ }));
70
+ return {
71
+ version: 1,
72
+ revision_hash: result.revision_hash,
73
+ target_paths: targetPaths,
74
+ narrow,
75
+ broad_count: sharedIndex.length
76
+ };
77
+ }
78
+ function parsePathsArg(raw) {
79
+ if (raw === void 0 || raw.length === 0) {
80
+ return [];
81
+ }
82
+ return raw.split(",").map((part) => part.trim()).filter((part) => part.length > 0);
83
+ }
84
+ function dedupeByStableId(items) {
85
+ const seen = /* @__PURE__ */ new Set();
86
+ const result = [];
87
+ for (const item of items) {
88
+ if (seen.has(item.stable_id)) continue;
89
+ seen.add(item.stable_id);
90
+ result.push(item);
91
+ }
92
+ return result;
93
+ }
94
+ export {
95
+ plan_context_hint_default as default,
96
+ planContextHintCommand,
97
+ runPlanContextHint
98
+ };
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ __testing__,
4
+ createScanReport,
5
+ deriveTagsFromForensic,
6
+ formatKnowledgeId,
7
+ runInitScan,
8
+ scanCommand,
9
+ scan_default
10
+ } from "./chunk-EYIDD2YS.js";
11
+ import "./chunk-WWNXR34K.js";
12
+ import "./chunk-6ICJICVU.js";
13
+ import "./chunk-OBQU6NHO.js";
14
+ export {
15
+ __testing__,
16
+ createScanReport,
17
+ scan_default as default,
18
+ deriveTagsFromForensic,
19
+ formatKnowledgeId,
20
+ runInitScan,
21
+ scanCommand
22
+ };
@@ -1,11 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- createDebugLogger,
4
3
  paint,
5
- resolveDevMode,
6
- symbol,
4
+ symbol
5
+ } from "./chunk-WWNXR34K.js";
6
+ import {
7
7
  t
8
- } from "./chunk-QPCRBQ5Y.js";
8
+ } from "./chunk-6ICJICVU.js";
9
+ import {
10
+ createDebugLogger,
11
+ resolveDevMode
12
+ } from "./chunk-OBQU6NHO.js";
9
13
 
10
14
  // src/commands/serve.ts
11
15
  import { defineCommand } from "citty";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fenglimg/fabric-cli",
3
- "version": "1.8.0-rc.3",
3
+ "version": "2.0.0-rc.8",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "fab": "dist/index.js",
@@ -20,8 +20,8 @@
20
20
  "tree-sitter-javascript": "^0.25.0",
21
21
  "tree-sitter-typescript": "^0.23.2",
22
22
  "web-tree-sitter": "^0.26.8",
23
- "@fenglimg/fabric-server": "1.8.0-rc.3",
24
- "@fenglimg/fabric-shared": "1.8.0-rc.3"
23
+ "@fenglimg/fabric-server": "2.0.0-rc.8",
24
+ "@fenglimg/fabric-shared": "2.0.0-rc.8"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/node": "^22.15.0",
@@ -1,21 +1,59 @@
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/rules/` as the source of truth for all Fabric rule bodies.
7
- MUST: Before ANY code reading, architecture planning, or logic modification, call `fab_plan_context(paths=[<target file>])`, then call `fab_get_rule_sections`.
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/rules/`, `.fabric/agents.meta.json`, `fab_plan_context`, `fab_get_rule_sections`, `rule sources`, `rule source 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/knowledge/` as the source of truth for all Fabric knowledge entries.
7
+ MUST: Before ANY code reading, architecture planning, or logic modification, call `fab_plan_context(paths=[<target file>])`, then call `fab_get_knowledge_sections`.
8
+ MUST: When creating or changing a knowledge entry, keep `.fabric/agents.meta.json` synchronized through Fabric tooling (never hand-edit).
9
+ MUST: Preserve protected tokens exactly: `AGENTS.md`, `.fabric/knowledge/`, `.fabric/agents.meta.json`, `fab_plan_context`, `fab_get_knowledge_sections`, `knowledge sources`, `MUST`, `NEVER`.
10
+ NEVER: Add import-style directive lines to this bootstrap file.
11
+ NEVER: Put domain knowledge bodies, framework rules, or repository specifics in this file.
12
+ NEVER: Create colocated `AGENTS.md` knowledge files under source directories.
13
+ NEVER: Hand-edit anything under `.fabric/knowledge/pending/` outside of the proposal/review workflow.
14
+
14
15
  ## 使用说明 / Explanation
15
16
 
16
- - 本文件只负责启动 Fabric Bootstrap Protocol,不承载项目业务规则。
17
+ - 本文件只负责启动 Fabric Bootstrap Protocol,不承载项目业务知识。
17
18
  - 详细 bootstrap 说明位于 `.fabric/bootstrap/README.md`。
18
19
  - Detected framework kind: `{ frameworkKind }`.
19
- - This repository uses `rule source mirroring`: source directories contain ZERO rule files, while `.fabric/rules/` mirrors source paths for AI constraints.
20
- - 根级规则应放在 `.fabric/rules/root.md`;跨领域规则应放在 `.fabric/rules/_cross/`。
21
- - If `.fabric/rules/root.md` is missing, continue with the Fabric initialization flow before normal coding.
20
+ - This repository uses `knowledge mirroring`: source directories contain ZERO knowledge files, while `.fabric/knowledge/` holds all AI-facing constraints, organized by knowledge type.
21
+ - 跨领域、根级知识应放在对应的 `.fabric/knowledge/{type}/` 子目录下。
22
+ - If `.fabric/knowledge/` is empty after init, continue with the Fabric initialization flow before normal coding.
23
+
24
+ ## Knowledge layer (v2)
25
+
26
+ Fabric v2 organises every AI-facing knowledge entry along three orthogonal axes: **type**, **maturity**, and **layer**. All entries live as flat markdown files with YAML frontmatter — no nesting, no implicit hierarchies.
27
+
28
+ ### 5 knowledge types
29
+
30
+ Each entry lives in exactly one of these subdirectories of `.fabric/knowledge/`:
31
+
32
+ - `decisions/` — architectural / design decisions (the "why" behind a choice, with rejected alternatives)
33
+ - `pitfalls/` — known traps, footguns, and "do-not-do-X" lessons learned the hard way
34
+ - `guidelines/` — actionable rules and conventions the AI should follow when generating or modifying code
35
+ - `models/` — domain models, data shapes, and conceptual abstractions (entities, invariants)
36
+ - `processes/` — multi-step workflows, runbooks, and operational sequences
37
+
38
+ ### 3 maturity levels
39
+
40
+ The `maturity` frontmatter field expresses how trusted an entry is:
41
+
42
+ - `draft` — newly captured, not yet reviewed; the AI may consult it but should treat it as provisional
43
+ - `verified` — reviewed and confirmed correct in the current codebase; safe to rely on
44
+ - `proven` — verified and battle-tested across multiple changes; treat as authoritative
45
+
46
+ Promotion is one-way (`draft` → `verified` → `proven`); demotion happens only via the review workflow.
47
+
48
+ ### 2 layers (dual-root)
49
+
50
+ Knowledge lives in two physical roots that share the same schema:
51
+
52
+ - `~/.fabric/knowledge/` — **personal layer** (per-user, NOT committed). Entries here use the `KP-` stable_id prefix. Use this layer for individual preferences, scratch notes, and cross-project habits.
53
+ - `<repo>/.fabric/knowledge/` — **team layer** (committed to the repo). Entries here use the `KT-` stable_id prefix. Use this layer for anything every contributor (human or AI) should respect.
54
+
55
+ A given entry belongs to exactly one layer; layer-flip (KP ↔ KT) is the only legal mutation of stable_id.
56
+
57
+ ### Proposal staging: `pending/`
58
+
59
+ `.fabric/knowledge/pending/` is the staging area for proposed entries awaiting review. The async-review workflow (`fabric-review` skill, rc.3) promotes pending entries into one of the 5 type subdirectories once accepted, or archives them on rejection. **Never** hand-edit files under `pending/` directly — use the proposal tooling.
@@ -1,7 +1,7 @@
1
1
  # Fabric Bootstrap
2
2
  - 主说明文档已收敛到 `.fabric/bootstrap/README.md`。
3
3
  - 项目级 bootstrap 入口仍然是 `AGENTS.md`。
4
- - 修改任何文件前必须调用 `fab_plan_context(paths=[<被改文件>])`,再调用 `fab_get_rule_sections` 获取规则段落。
4
+ - 修改任何文件前必须调用 `fab_plan_context(paths=[<被改文件>])`,再调用 `fab_get_knowledge_sections` 获取规则段落。
5
5
  MCP 和 doctor 会写入 `.fabric/events.jsonl`。
6
6
  - 规则 baseline 变更通过 `fabric doctor --fix` 接受。
7
7
 
@@ -1,6 +1,6 @@
1
1
  # Fabric Bootstrap
2
2
  - 主说明文档已收敛到 `.fabric/bootstrap/README.md`。
3
3
  - 此 header 仅用于把 Codex 引导到 Fabric 项目级规则入口。
4
- - 修改任何文件前必须调用 `fab_plan_context(paths=[<被改文件>])`,再调用 `fab_get_rule_sections` 获取规则段落。
4
+ - 修改任何文件前必须调用 `fab_plan_context(paths=[<被改文件>])`,再调用 `fab_get_knowledge_sections` 获取规则段落。
5
5
  MCP 和 doctor 会写入 `.fabric/events.jsonl`。
6
6
  - 规则 baseline 变更通过 `fabric doctor --fix` 接受。
@@ -5,6 +5,6 @@ description: Fabric Protocol bootstrap rules
5
5
 
6
6
  # Fabric Bootstrap
7
7
  - 本项目使用 Fabric Protocol 管理规则。
8
- - **任何文件修改前**,必须先调 MCP tool `fab_plan_context(paths=[<被改文件>])`,再调 `fab_get_rule_sections` 获取规则段落。
8
+ - **任何文件修改前**,必须先调 MCP tool `fab_plan_context(paths=[<被改文件>])`,再调 `fab_get_knowledge_sections` 获取规则段落。
9
9
  - 新建或调整 L1/L2 节点时,修改规则源文件后运行 `fabric doctor --fix` 接受 baseline,**严禁**直接编辑 `.fabric/agents.meta.json`。
10
10
  Fabric 会把 MCP 和 doctor 行为写入 `.fabric/events.jsonl`。
@@ -0,0 +1,73 @@
1
+ # Client hook config templates
2
+
3
+ These JSON files are **fragment templates** consumed by `fabric init` and
4
+ `fabric hooks install`. They are not standalone client config files.
5
+
6
+ The supported clients are pinned by `packages/shared/src/schemas/fabric-config.ts`
7
+ to Claude Code, Cursor, and Codex CLI. Adding a new client requires extending
8
+ that schema first.
9
+
10
+ ## claude-code.json
11
+
12
+ Deep-merged into the user repo's `.claude/settings.json` by the init pipeline.
13
+ Registers `fabric-hint.cjs` under `hooks.Stop[]` with `matcher: "*"`. The
14
+ existing `mcpServers`, `permissions`, and any other top-level keys in the user's
15
+ settings.json are preserved.
16
+
17
+ The `hooks.Stop[]` array merge needs special-case handling (array-append with
18
+ dedupe by `command` string) because `packages/cli/src/config/json.ts:18` default
19
+ `deepMerge` REPLACES arrays. The mergeClaudeCodeHookConfig helper owns that
20
+ wiring.
21
+
22
+ ## codex-hooks.json
23
+
24
+ Written to (or merged into) the user repo's `.codex/hooks.json`. NOTE: Codex
25
+ project-level hooks file is JSON, **not** TOML — only the user-level Codex MCP
26
+ config (`~/.codex/config.toml`) is TOML.
27
+
28
+ ## cursor-hooks.json
29
+
30
+ Written to (or merged into) the user repo's `.cursor/hooks.json`. Mirrors the
31
+ Codex `events.Stop[]` envelope shape — Cursor's hook event vocabulary is
32
+ not stable across releases, so the canonical Stop-on-tool-finish lifecycle hook
33
+ is the only entry we register today. SessionStart / PreToolUse slots are left
34
+ unfilled for rc.6 to add when their semantics stabilise.
35
+
36
+ ## fabric-hint.cjs script paths
37
+
38
+ - Claude: `.claude/hooks/fabric-hint.cjs` (project-relative)
39
+ - Codex: `.codex/hooks/fabric-hint.cjs` (project-relative)
40
+ - Cursor: `.cursor/hooks/fabric-hint.cjs` (project-relative)
41
+
42
+ The single shared script lives at `packages/cli/templates/hooks/fabric-hint.cjs`
43
+ in this repo and is copied into all three `<client>/hooks/` destinations by the
44
+ install wiring. The script emits stdout JSON
45
+ `{decision:"block", reason, signal, recommended_skill}` with exit 0 when one of
46
+ three signals trips:
47
+
48
+ - **archive** (rc.5 TASK-015): 24h elapsed since last `knowledge_proposed`
49
+ event. Silent on a never-archived workspace (that case is the **import**
50
+ signal's domain). Recommends the `fabric-archive` skill. The previous
51
+ `5 plan_contexts` count branch (rc.2) was dropped because rc.5+ hooks
52
+ auto-fire plan_context events; rc.6 will reintroduce an Edit-count signal
53
+ via a PreToolUse sidecar.
54
+ - **review** (rc.3): pending knowledge count >= 10, OR oldest pending entry >= 7
55
+ days old. Recommends the `fabric-review` skill.
56
+ - **import** (rc.5): canonical knowledge node count < `underseed_node_threshold`
57
+ (default 10) AND `init_scan_completed` event >= 24h ago AND no
58
+ `knowledge_proposed` event in last 24h. Recommends the `fabric-import` skill.
59
+
60
+ Precedence: archive > review > import. After firing, the hook stays silent for
61
+ `archive_hint_cooldown_hours` (default 12h, keyed by `signal` so the three
62
+ signals share a cache file but throttle independently).
63
+
64
+ The script is silent + exit 0 when no signal trips. It NEVER blocks tool
65
+ execution on its own failure — any read/parse error is swallowed.
66
+
67
+ ## Historical note: archive-hint.cjs rename
68
+
69
+ Pre-rc.5, this script was named `archive-hint.cjs` (only the archive signal
70
+ existed). rc.5 TASK-010 renamed it to `fabric-hint.cjs` to reflect its expanded
71
+ three-signal scope. The cooldown cache file is intentionally still named
72
+ `archive-hint-shown.json` so an in-place upgrade does not flush the user's
73
+ existing throttle state.
@@ -0,0 +1,37 @@
1
+ {
2
+ "hooks": {
3
+ "Stop": [
4
+ {
5
+ "matcher": "*",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": ".claude/hooks/fabric-hint.cjs"
10
+ }
11
+ ]
12
+ }
13
+ ],
14
+ "SessionStart": [
15
+ {
16
+ "matcher": "*",
17
+ "hooks": [
18
+ {
19
+ "type": "command",
20
+ "command": ".claude/hooks/knowledge-hint-broad.cjs"
21
+ }
22
+ ]
23
+ }
24
+ ],
25
+ "PreToolUse": [
26
+ {
27
+ "matcher": "Edit|Write|MultiEdit",
28
+ "hooks": [
29
+ {
30
+ "type": "command",
31
+ "command": ".claude/hooks/knowledge-hint-narrow.cjs"
32
+ }
33
+ ]
34
+ }
35
+ ]
36
+ }
37
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "events": {
3
+ "Stop": [
4
+ {
5
+ "command": ".codex/hooks/fabric-hint.cjs"
6
+ }
7
+ ],
8
+ "SessionStart": [
9
+ {
10
+ "command": ".codex/hooks/knowledge-hint-broad.cjs"
11
+ }
12
+ ],
13
+ "PreToolUse": [
14
+ {
15
+ "matcher": "Edit|Write|MultiEdit",
16
+ "command": ".codex/hooks/knowledge-hint-narrow.cjs"
17
+ }
18
+ ]
19
+ }
20
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "events": {
3
+ "Stop": [
4
+ {
5
+ "command": ".cursor/hooks/fabric-hint.cjs"
6
+ }
7
+ ],
8
+ "SessionStart": [
9
+ {
10
+ "command": ".cursor/hooks/knowledge-hint-broad.cjs"
11
+ }
12
+ ],
13
+ "PreToolUse": [
14
+ {
15
+ "matcher": "Edit|Write|MultiEdit",
16
+ "command": ".cursor/hooks/knowledge-hint-narrow.cjs"
17
+ }
18
+ ]
19
+ }
20
+ }