@fenglimg/fabric-cli 2.0.0-rc.1 → 2.0.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.
- package/README.md +6 -6
- package/dist/chunk-6ICJICVU.js +10 -0
- package/dist/chunk-74SZWYPH.js +658 -0
- package/dist/{chunk-UHNP7T7W.js → chunk-EYIDD2YS.js} +346 -86
- package/dist/{chunk-5LOYBXWD.js → chunk-OBQU6NHO.js} +2 -52
- package/dist/chunk-WWNXR34K.js +49 -0
- package/dist/doctor-T7JWODKG.js +282 -0
- package/dist/hooks-Y74Y5LQS.js +12 -0
- package/dist/index.js +7 -5
- package/dist/{init-DRHUYHYA.js → init-BIRSIOXO.js} +212 -271
- package/dist/plan-context-hint-QMUPAXIB.js +98 -0
- package/dist/{scan-HU2EGITF.js → scan-LMK3UCWL.js} +4 -2
- package/dist/{serve-3LXXSBFR.js → serve-H554BHLG.js} +8 -4
- package/package.json +3 -3
- package/templates/bootstrap/CLAUDE.md +1 -1
- package/templates/bootstrap/codex-AGENTS-header.md +1 -1
- package/templates/bootstrap/cursor-fabric-bootstrap.mdc +1 -1
- package/templates/hooks/configs/README.md +73 -0
- package/templates/hooks/configs/claude-code.json +37 -0
- package/templates/hooks/configs/codex-hooks.json +20 -0
- package/templates/hooks/configs/cursor-hooks.json +20 -0
- package/templates/hooks/fabric-hint.cjs +1307 -0
- package/templates/hooks/knowledge-hint-broad.cjs +464 -0
- package/templates/hooks/knowledge-hint-narrow.cjs +826 -0
- package/templates/hooks/lib/session-digest-writer.cjs +172 -0
- package/templates/skills/fabric-archive/SKILL.md +486 -0
- package/templates/skills/fabric-import/SKILL.md +588 -0
- package/templates/skills/fabric-review/SKILL.md +382 -0
- package/dist/doctor-DUHWLAYD.js +0 -98
|
@@ -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
|
+
};
|
|
@@ -7,8 +7,10 @@ import {
|
|
|
7
7
|
runInitScan,
|
|
8
8
|
scanCommand,
|
|
9
9
|
scan_default
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-EYIDD2YS.js";
|
|
11
|
+
import "./chunk-WWNXR34K.js";
|
|
12
|
+
import "./chunk-6ICJICVU.js";
|
|
13
|
+
import "./chunk-OBQU6NHO.js";
|
|
12
14
|
export {
|
|
13
15
|
__testing__,
|
|
14
16
|
createScanReport,
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
createDebugLogger,
|
|
4
3
|
paint,
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
symbol
|
|
5
|
+
} from "./chunk-WWNXR34K.js";
|
|
6
|
+
import {
|
|
7
7
|
t
|
|
8
|
-
} from "./chunk-
|
|
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": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
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": "2.0.0
|
|
24
|
-
"@fenglimg/fabric-shared": "2.0.0
|
|
23
|
+
"@fenglimg/fabric-server": "2.0.0",
|
|
24
|
+
"@fenglimg/fabric-shared": "2.0.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^22.15.0",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Fabric Bootstrap
|
|
2
2
|
- 主说明文档已收敛到 `.fabric/bootstrap/README.md`。
|
|
3
3
|
- 项目级 bootstrap 入口仍然是 `AGENTS.md`。
|
|
4
|
-
- 修改任何文件前必须调用 `fab_plan_context(paths=[<被改文件>])`,再调用 `
|
|
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=[<被改文件>])`,再调用 `
|
|
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=[<被改文件>])`,再调 `
|
|
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
|
+
}
|