@fenglimg/fabric-cli 1.5.2 → 1.7.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 +8 -14
- package/dist/{chunk-QSAEGVKE.js → chunk-NMMUETVK.js} +4 -8
- package/dist/{chunk-AEOYCVBG.js → chunk-QPCRBQ5Y.js} +52 -5
- package/dist/doctor-XP4OQOTX.js +92 -0
- package/dist/index.js +5 -20
- package/dist/{init-FDTUWEZX.js → init-WMB3WLXM.js} +1153 -144
- package/dist/{scan-QH76LC7Z.js → scan-NNBNGIZG.js} +2 -4
- package/dist/{serve-4J2CQY25.js → serve-7AXYKBIT.js} +3 -7
- package/package.json +3 -3
- package/templates/agents-md/AGENTS.md.template +7 -7
- package/templates/agents-md/variants/cocos.md +7 -7
- package/templates/agents-md/variants/next.md +7 -7
- package/templates/agents-md/variants/vite.md +7 -7
- package/templates/bootstrap/CLAUDE.md +3 -1
- package/templates/bootstrap/GEMINI.md +3 -1
- package/templates/bootstrap/codex-AGENTS-header.md +3 -1
- package/templates/bootstrap/cursor-fabric-bootstrap.mdc +5 -6
- package/templates/bootstrap/roo-fabric.md +5 -6
- package/templates/bootstrap/windsurf-fabric.md +5 -6
- package/templates/claude-skills/agents-md-init/SKILL.md +1 -1
- package/templates/codex-skills/fabric-init/SKILL.md +1 -1
- package/templates/husky/pre-commit +9 -24
- package/dist/approve-YT4DEABS.js +0 -138
- package/dist/bootstrap-VGL3AR26.js +0 -16
- package/dist/chunk-2YW5CJ32.js +0 -147
- package/dist/chunk-6ICJICVU.js +0 -10
- package/dist/chunk-BEKSXO5N.js +0 -442
- package/dist/chunk-BVTMVW5M.js +0 -159
- package/dist/chunk-KOAEIH72.js +0 -270
- package/dist/chunk-L43IGJ6X.js +0 -106
- package/dist/chunk-T2WJF5I3.js +0 -254
- package/dist/chunk-WWNXR34K.js +0 -49
- package/dist/chunk-YDZJRLHL.js +0 -155
- package/dist/config-EC5L2QNI.js +0 -16
- package/dist/doctor-4BPYHV7V.js +0 -134
- package/dist/hooks-ZSWVH2JD.js +0 -12
- package/dist/human-lint-YSFOZHZ7.js +0 -13
- package/dist/ledger-append-3MDNR3GU.js +0 -10
- package/dist/pre-commit-53ENJDRZ.js +0 -98
- package/dist/sync-meta-IZR2WLIL.js +0 -16
- package/dist/update-M5M5PYKE.js +0 -116
- package/templates/fabric/human-lock.json +0 -12
|
@@ -3,10 +3,8 @@ import {
|
|
|
3
3
|
createScanReport,
|
|
4
4
|
scanCommand,
|
|
5
5
|
scan_default
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-WWNXR34K.js";
|
|
9
|
-
import "./chunk-6ICJICVU.js";
|
|
6
|
+
} from "./chunk-NMMUETVK.js";
|
|
7
|
+
import "./chunk-QPCRBQ5Y.js";
|
|
10
8
|
export {
|
|
11
9
|
createScanReport,
|
|
12
10
|
scan_default as default,
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
createDebugLogger,
|
|
4
|
-
resolveDevMode
|
|
5
|
-
} from "./chunk-AEOYCVBG.js";
|
|
6
|
-
import {
|
|
7
4
|
paint,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import {
|
|
5
|
+
resolveDevMode,
|
|
6
|
+
symbol,
|
|
11
7
|
t
|
|
12
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-QPCRBQ5Y.js";
|
|
13
9
|
|
|
14
10
|
// src/commands/serve.ts
|
|
15
11
|
import { defineCommand } from "citty";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fenglimg/fabric-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"fab": "dist/index.js",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"tree-sitter-javascript": "^0.25.0",
|
|
23
23
|
"tree-sitter-typescript": "^0.23.2",
|
|
24
24
|
"web-tree-sitter": "^0.26.8",
|
|
25
|
-
"@fenglimg/fabric-server": "1.
|
|
26
|
-
"@fenglimg/fabric-shared": "1.
|
|
25
|
+
"@fenglimg/fabric-server": "1.7.0",
|
|
26
|
+
"@fenglimg/fabric-shared": "1.7.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/iarna__toml": "^2.0.5",
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
## CORE RULES (DO NOT TRANSLATE)
|
|
4
4
|
|
|
5
5
|
MUST: Treat this file as the Fabric Protocol bootstrap for this repository.
|
|
6
|
-
MUST: Treat `.fabric/
|
|
7
|
-
MUST: Before ANY code reading, architecture planning, or logic modification, call `
|
|
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/
|
|
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
10
|
NEVER: Add import-style directive lines to this bootstrap file.
|
|
11
11
|
NEVER: Put framework, domain, repository rule bodies, or submodule rules in this file.
|
|
12
12
|
NEVER: Create colocated `AGENTS.md` rule files under source directories.
|
|
@@ -16,6 +16,6 @@ NEVER: Create colocated `AGENTS.md` rule files under source directories.
|
|
|
16
16
|
- 本文件只负责启动 Fabric Bootstrap Protocol,不承载项目业务规则。
|
|
17
17
|
- 详细 bootstrap 说明位于 `.fabric/bootstrap/README.md`。
|
|
18
18
|
- Detected framework kind: `{ frameworkKind }`.
|
|
19
|
-
- This repository uses `
|
|
20
|
-
- 根级规则应放在 `.fabric/
|
|
21
|
-
- If `.fabric/
|
|
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.
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
## CORE RULES (DO NOT TRANSLATE)
|
|
4
4
|
|
|
5
5
|
MUST: Treat this file as the Fabric Protocol bootstrap for this repository.
|
|
6
|
-
MUST: Treat `.fabric/
|
|
7
|
-
MUST: Before ANY code reading, architecture planning, or logic modification, call `
|
|
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/
|
|
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
10
|
NEVER: Add import-style directive lines to this bootstrap file.
|
|
11
11
|
NEVER: Put Cocos, asset, prefab, scene, repository rule bodies, or submodule rules in this file.
|
|
12
12
|
NEVER: Create colocated `AGENTS.md` rule files under source directories.
|
|
@@ -15,6 +15,6 @@ NEVER: Create colocated `AGENTS.md` rule files under source directories.
|
|
|
15
15
|
|
|
16
16
|
- 本文件只负责启动 Fabric Bootstrap Protocol,不承载 Cocos 业务或编辑器规则。
|
|
17
17
|
- Detected framework kind: `cocos-creator`.
|
|
18
|
-
- This repository uses `
|
|
19
|
-
- 根级规则应放在 `.fabric/
|
|
20
|
-
- If `.fabric/
|
|
18
|
+
- This repository uses `rule source mirroring`: source directories contain ZERO rule files, while `.fabric/rules/` mirrors source paths for AI constraints.
|
|
19
|
+
- 根级规则应放在 `.fabric/rules/root.md`;跨领域规则应放在 `.fabric/rules/_cross/`。
|
|
20
|
+
- If `.fabric/rules/root.md` is missing, continue with the Fabric initialization flow before normal coding.
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
## CORE RULES (DO NOT TRANSLATE)
|
|
4
4
|
|
|
5
5
|
MUST: Treat this file as the Fabric Protocol bootstrap for this repository.
|
|
6
|
-
MUST: Treat `.fabric/
|
|
7
|
-
MUST: Before ANY code reading, architecture planning, or logic modification, call `
|
|
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/
|
|
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
10
|
NEVER: Add import-style directive lines to this bootstrap file.
|
|
11
11
|
NEVER: Put Next.js, route, repository rule bodies, or submodule rules in this file.
|
|
12
12
|
NEVER: Create colocated `AGENTS.md` rule files under source directories.
|
|
@@ -15,6 +15,6 @@ NEVER: Create colocated `AGENTS.md` rule files under source directories.
|
|
|
15
15
|
|
|
16
16
|
- 本文件只负责启动 Fabric Bootstrap Protocol,不承载 Next.js 业务或路由规则。
|
|
17
17
|
- Detected framework kind: `next`.
|
|
18
|
-
- This repository uses `
|
|
19
|
-
- 根级规则应放在 `.fabric/
|
|
20
|
-
- If `.fabric/
|
|
18
|
+
- This repository uses `rule source mirroring`: source directories contain ZERO rule files, while `.fabric/rules/` mirrors source paths for AI constraints.
|
|
19
|
+
- 根级规则应放在 `.fabric/rules/root.md`;跨领域规则应放在 `.fabric/rules/_cross/`。
|
|
20
|
+
- If `.fabric/rules/root.md` is missing, continue with the Fabric initialization flow before normal coding.
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
## CORE RULES (DO NOT TRANSLATE)
|
|
4
4
|
|
|
5
5
|
MUST: Treat this file as the Fabric Protocol bootstrap for this repository.
|
|
6
|
-
MUST: Treat `.fabric/
|
|
7
|
-
MUST: Before ANY code reading, architecture planning, or logic modification, call `
|
|
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/
|
|
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
10
|
NEVER: Add import-style directive lines to this bootstrap file.
|
|
11
11
|
NEVER: Put Vite, browser, repository rule bodies, or submodule rules in this file.
|
|
12
12
|
NEVER: Create colocated `AGENTS.md` rule files under source directories.
|
|
@@ -15,6 +15,6 @@ NEVER: Create colocated `AGENTS.md` rule files under source directories.
|
|
|
15
15
|
|
|
16
16
|
- 本文件只负责启动 Fabric Bootstrap Protocol,不承载 Vite 业务或浏览器规则。
|
|
17
17
|
- Detected framework kind: `vite`.
|
|
18
|
-
- This repository uses `
|
|
19
|
-
- 根级规则应放在 `.fabric/
|
|
20
|
-
- If `.fabric/
|
|
18
|
+
- This repository uses `rule source mirroring`: source directories contain ZERO rule files, while `.fabric/rules/` mirrors source paths for AI constraints.
|
|
19
|
+
- 根级规则应放在 `.fabric/rules/root.md`;跨领域规则应放在 `.fabric/rules/_cross/`。
|
|
20
|
+
- If `.fabric/rules/root.md` is missing, continue with the Fabric initialization flow before normal coding.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Fabric Bootstrap
|
|
2
2
|
- 主说明文档已收敛到 `.fabric/bootstrap/README.md`。
|
|
3
3
|
- 项目级 bootstrap 入口仍然是 `AGENTS.md`。
|
|
4
|
-
- 修改任何文件前必须调用 `
|
|
4
|
+
- 修改任何文件前必须调用 `fab_plan_context(paths=[<被改文件>])`,再调用 `fab_get_rule_sections` 获取规则段落。
|
|
5
|
+
MCP 和 doctor 会写入 `.fabric/events.jsonl`。
|
|
6
|
+
- 规则 baseline 变更通过 `fabric doctor --fix` 接受。
|
|
5
7
|
|
|
6
8
|
@AGENTS.md
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Fabric Bootstrap
|
|
2
2
|
- 主说明文档已收敛到 `.fabric/bootstrap/README.md`。
|
|
3
3
|
- 项目级 bootstrap 入口仍然是 `AGENTS.md`。
|
|
4
|
-
- 修改任何文件前必须调用 `
|
|
4
|
+
- 修改任何文件前必须调用 `fab_plan_context(paths=[<被改文件>])`,再调用 `fab_get_rule_sections` 获取规则段落。
|
|
5
|
+
MCP 和 doctor 会写入 `.fabric/events.jsonl`。
|
|
6
|
+
- 规则 baseline 变更通过 `fabric doctor --fix` 接受。
|
|
5
7
|
|
|
6
8
|
@AGENTS.md
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
# Fabric Bootstrap
|
|
2
2
|
- 主说明文档已收敛到 `.fabric/bootstrap/README.md`。
|
|
3
3
|
- 此 header 仅用于把 Codex 引导到 Fabric 项目级规则入口。
|
|
4
|
-
- 修改任何文件前必须调用 `
|
|
4
|
+
- 修改任何文件前必须调用 `fab_plan_context(paths=[<被改文件>])`,再调用 `fab_get_rule_sections` 获取规则段落。
|
|
5
|
+
MCP 和 doctor 会写入 `.fabric/events.jsonl`。
|
|
6
|
+
- 规则 baseline 变更通过 `fabric doctor --fix` 接受。
|
|
@@ -3,9 +3,8 @@ alwaysApply: true
|
|
|
3
3
|
description: Fabric Protocol bootstrap rules
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Fabric Bootstrap
|
|
7
|
-
- 本项目使用 Fabric Protocol 管理规则。
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
- 每次完整任务结束,调 `fab_append_intent` 写一条意图记录。
|
|
6
|
+
# Fabric Bootstrap
|
|
7
|
+
- 本项目使用 Fabric Protocol 管理规则。
|
|
8
|
+
- **任何文件修改前**,必须先调 MCP tool `fab_plan_context(paths=[<被改文件>])`,再调 `fab_get_rule_sections` 获取规则段落。
|
|
9
|
+
- 新建或调整 L1/L2 节点时,修改规则源文件后运行 `fabric doctor --fix` 接受 baseline,**严禁**直接编辑 `.fabric/agents.meta.json`。
|
|
10
|
+
Fabric 会把 MCP 和 doctor 行为写入 `.fabric/events.jsonl`。
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
# Fabric Bootstrap
|
|
2
|
-
- 本项目使用 Fabric Protocol 管理规则。
|
|
3
|
-
-
|
|
4
|
-
-
|
|
5
|
-
|
|
6
|
-
- 每次完整任务结束,调 `fab_append_intent` 写一条意图记录。
|
|
1
|
+
# Fabric Bootstrap
|
|
2
|
+
- 本项目使用 Fabric Protocol 管理规则。
|
|
3
|
+
- **任何文件修改前**,必须先调 MCP tool `fab_plan_context(paths=[<被改文件>])`,再调 `fab_get_rule_sections` 获取规则段落。
|
|
4
|
+
- 新建或调整 L1/L2 节点时,修改规则源文件后运行 `fabric doctor --fix` 接受 baseline,**严禁**直接编辑 `.fabric/agents.meta.json`。
|
|
5
|
+
Fabric 会把 MCP 和 doctor 行为写入 `.fabric/events.jsonl`。
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
# Fabric Bootstrap
|
|
2
|
-
- 本项目使用 Fabric Protocol 管理规则。
|
|
3
|
-
-
|
|
4
|
-
-
|
|
5
|
-
|
|
6
|
-
- 每次完整任务结束,调 `fab_append_intent` 写一条意图记录。
|
|
1
|
+
# Fabric Bootstrap
|
|
2
|
+
- 本项目使用 Fabric Protocol 管理规则。
|
|
3
|
+
- **任何文件修改前**,必须先调 MCP tool `fab_plan_context(paths=[<被改文件>])`,再调 `fab_get_rule_sections` 获取规则段落。
|
|
4
|
+
- 新建或调整 L1/L2 节点时,修改规则源文件后运行 `fabric doctor --fix` 接受 baseline,**严禁**直接编辑 `.fabric/agents.meta.json`。
|
|
5
|
+
Fabric 会把 MCP 和 doctor 行为写入 `.fabric/events.jsonl`。
|
|
@@ -9,7 +9,7 @@ MUST: 先读取 `.fabric/forensic.json`,再做其他动作。
|
|
|
9
9
|
MUST: 把 `.fabric/bootstrap/README.md` 视为当前仓库的初始化说明。
|
|
10
10
|
MUST: 如果 `.fabric/init-context.json` 已存在,立即停止并报告当前仓库看起来已经完成后续初始化。
|
|
11
11
|
MUST: 使用 `.fabric/forensic.json` 和仓库结构中的依据,判断接下来该做什么。
|
|
12
|
-
MUST: Preserve protected tokens exactly: `AGENTS.md`, `FABRIC.md`, `.fabric/agents.meta.json`, `.fabric/
|
|
12
|
+
MUST: Preserve protected tokens exactly: `AGENTS.md`, `FABRIC.md`, `.fabric/agents.meta.json`, `.fabric/init-context.json`, `.fabric/forensic.json`, `MUST`, `NEVER`.
|
|
13
13
|
NEVER: 在没有检查 `.fabric/init-context.json` 的情况下声称初始化已经完成。
|
|
14
14
|
NEVER: 改写或翻译受保护 token。
|
|
15
15
|
NEVER: 在判断下一步初始化动作时忽略 `.fabric/bootstrap/README.md`。
|
|
@@ -1,24 +1,9 @@
|
|
|
1
|
-
#!/bin/sh
|
|
2
|
-
# Fabric pre-commit hook
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
exit 1
|
|
11
|
-
fi
|
|
12
|
-
|
|
13
|
-
# Single Node invocation covering all three checks + meta guard.
|
|
14
|
-
# The `pre-commit` meta-command chains sync-meta/human-lint/ledger-append
|
|
15
|
-
# inside one process for minimal startup overhead.
|
|
16
|
-
"$FAB_BIN" pre-commit || exit $?
|
|
17
|
-
|
|
18
|
-
# Guard: block manual edits to .fabric/agents.meta.json
|
|
19
|
-
if git diff --cached --name-only | grep -q '^\.fabric/agents\.meta\.json$'; then
|
|
20
|
-
if [ "$FAB_ALLOW_META_EDIT" != '1' ]; then
|
|
21
|
-
echo '.fabric/agents.meta.json cannot be manually edited; use fab_update_registry or set FAB_ALLOW_META_EDIT=1' >&2
|
|
22
|
-
exit 1
|
|
23
|
-
fi
|
|
24
|
-
fi
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Fabric pre-commit hook: block manual edits to generated metadata.
|
|
3
|
+
|
|
4
|
+
if git diff --cached --name-only | grep -q '^\.fabric/agents\.meta\.json$'; then
|
|
5
|
+
if [ "$FAB_ALLOW_META_EDIT" != '1' ]; then
|
|
6
|
+
echo '.fabric/agents.meta.json cannot be manually edited; update .fabric/rules and run fabric doctor --fix, or set FAB_ALLOW_META_EDIT=1' >&2
|
|
7
|
+
exit 1
|
|
8
|
+
fi
|
|
9
|
+
fi
|
package/dist/approve-YT4DEABS.js
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
padEnd
|
|
4
|
-
} from "./chunk-WWNXR34K.js";
|
|
5
|
-
import {
|
|
6
|
-
t
|
|
7
|
-
} from "./chunk-6ICJICVU.js";
|
|
8
|
-
|
|
9
|
-
// src/commands/approve.ts
|
|
10
|
-
import { createInterface } from "readline/promises";
|
|
11
|
-
import { stdin as input, stdout as output } from "process";
|
|
12
|
-
import { isAbsolute, resolve } from "path";
|
|
13
|
-
import { approveHumanLock, readHumanLock } from "@fenglimg/fabric-server";
|
|
14
|
-
import { defineCommand, renderUsage } from "citty";
|
|
15
|
-
var approveCommand = defineCommand({
|
|
16
|
-
meta: {
|
|
17
|
-
name: "approve",
|
|
18
|
-
description: t("cli.approve.description")
|
|
19
|
-
},
|
|
20
|
-
args: {
|
|
21
|
-
all: {
|
|
22
|
-
type: "boolean",
|
|
23
|
-
description: t("cli.approve.args.all.description"),
|
|
24
|
-
default: false
|
|
25
|
-
},
|
|
26
|
-
interactive: {
|
|
27
|
-
type: "boolean",
|
|
28
|
-
description: t("cli.approve.args.interactive.description"),
|
|
29
|
-
default: false
|
|
30
|
-
},
|
|
31
|
-
target: {
|
|
32
|
-
type: "string",
|
|
33
|
-
description: t("cli.approve.args.target.description"),
|
|
34
|
-
default: process.cwd()
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
async run({ args }) {
|
|
38
|
-
const target = normalizeTarget(args.target);
|
|
39
|
-
if (args.all === args.interactive) {
|
|
40
|
-
writeStdout(await renderUsage(approveCommand));
|
|
41
|
-
process.exitCode = 1;
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
if (args.all) {
|
|
45
|
-
await runApproveAll(target);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
await runApproveInteractive(target);
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
var approve_default = approveCommand;
|
|
52
|
-
async function runApproveAll(projectRoot) {
|
|
53
|
-
const driftEntries = await readDriftEntries(projectRoot);
|
|
54
|
-
if (driftEntries.length === 0) {
|
|
55
|
-
writeStdout(t("cli.approve.no-drift"));
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
let approvedCount = 0;
|
|
59
|
-
for (const entry of driftEntries) {
|
|
60
|
-
await approveEntry(projectRoot, entry);
|
|
61
|
-
approvedCount += 1;
|
|
62
|
-
}
|
|
63
|
-
writeStdout(t("cli.approve.summary", { approved: String(approvedCount), skipped: "0", total: String(driftEntries.length) }));
|
|
64
|
-
}
|
|
65
|
-
async function runApproveInteractive(projectRoot) {
|
|
66
|
-
const driftEntries = await readDriftEntries(projectRoot);
|
|
67
|
-
if (driftEntries.length === 0) {
|
|
68
|
-
writeStdout(t("cli.approve.no-drift"));
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
const rl = createInterface({ input, output });
|
|
72
|
-
let approvedCount = 0;
|
|
73
|
-
let skippedCount = 0;
|
|
74
|
-
try {
|
|
75
|
-
for (const entry of driftEntries) {
|
|
76
|
-
writeStdout(formatEntry(entry));
|
|
77
|
-
const answer = (await rl.question(t("cli.approve.prompt"))).trim().toLowerCase();
|
|
78
|
-
if (answer === "y" || answer === "yes") {
|
|
79
|
-
await approveEntry(projectRoot, entry);
|
|
80
|
-
approvedCount += 1;
|
|
81
|
-
writeStdout(t("cli.approve.approved-one", { location: formatLocation(entry) }));
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
skippedCount += 1;
|
|
85
|
-
writeStdout(t("cli.approve.skipped-one", { location: formatLocation(entry) }));
|
|
86
|
-
}
|
|
87
|
-
} finally {
|
|
88
|
-
rl.close();
|
|
89
|
-
}
|
|
90
|
-
writeStdout(
|
|
91
|
-
t("cli.approve.summary", {
|
|
92
|
-
approved: String(approvedCount),
|
|
93
|
-
skipped: String(skippedCount),
|
|
94
|
-
total: String(driftEntries.length)
|
|
95
|
-
})
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
async function readDriftEntries(projectRoot) {
|
|
99
|
-
const entries = await readHumanLock(projectRoot);
|
|
100
|
-
return entries.filter((entry) => entry.drift);
|
|
101
|
-
}
|
|
102
|
-
async function approveEntry(projectRoot, entry) {
|
|
103
|
-
await approveHumanLock(projectRoot, {
|
|
104
|
-
file: entry.file,
|
|
105
|
-
start_line: entry.start_line,
|
|
106
|
-
end_line: entry.end_line,
|
|
107
|
-
new_hash: entry.current_hash
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
function normalizeTarget(targetInput) {
|
|
111
|
-
return isAbsolute(targetInput) ? targetInput : resolve(process.cwd(), targetInput);
|
|
112
|
-
}
|
|
113
|
-
function formatEntry(entry) {
|
|
114
|
-
return [
|
|
115
|
-
formatLocation(entry),
|
|
116
|
-
`${padEnd(t("cli.approve.table.expected"), 10)} ${shortenHash(entry.hash)}`,
|
|
117
|
-
`${padEnd(t("cli.approve.table.current"), 10)} ${shortenHash(entry.current_hash)}`
|
|
118
|
-
].join("\n");
|
|
119
|
-
}
|
|
120
|
-
function formatLocation(entry) {
|
|
121
|
-
return `${entry.file}:${entry.start_line}-${entry.end_line}`;
|
|
122
|
-
}
|
|
123
|
-
function shortenHash(value) {
|
|
124
|
-
if (value === "missing") {
|
|
125
|
-
return t("cli.shared.missing");
|
|
126
|
-
}
|
|
127
|
-
return value.slice(0, 15);
|
|
128
|
-
}
|
|
129
|
-
function writeStdout(message) {
|
|
130
|
-
process.stdout.write(`${message}
|
|
131
|
-
`);
|
|
132
|
-
}
|
|
133
|
-
export {
|
|
134
|
-
approveCommand,
|
|
135
|
-
approve_default as default,
|
|
136
|
-
runApproveAll,
|
|
137
|
-
runApproveInteractive
|
|
138
|
-
};
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
bootstrapCommand,
|
|
4
|
-
bootstrap_default,
|
|
5
|
-
installBootstrap
|
|
6
|
-
} from "./chunk-T2WJF5I3.js";
|
|
7
|
-
import "./chunk-QSAEGVKE.js";
|
|
8
|
-
import "./chunk-AEOYCVBG.js";
|
|
9
|
-
import "./chunk-WWNXR34K.js";
|
|
10
|
-
import "./chunk-BEKSXO5N.js";
|
|
11
|
-
import "./chunk-6ICJICVU.js";
|
|
12
|
-
export {
|
|
13
|
-
bootstrapCommand,
|
|
14
|
-
bootstrap_default as default,
|
|
15
|
-
installBootstrap
|
|
16
|
-
};
|
package/dist/chunk-2YW5CJ32.js
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
t
|
|
4
|
-
} from "./chunk-6ICJICVU.js";
|
|
5
|
-
|
|
6
|
-
// src/commands/ledger-append.ts
|
|
7
|
-
import { execSync } from "child_process";
|
|
8
|
-
import { appendFileSync, existsSync, mkdirSync, readFileSync, statSync } from "fs";
|
|
9
|
-
import { basename, isAbsolute, resolve } from "path";
|
|
10
|
-
import { getLedgerPath, getLegacyLedgerPath, LEGACY_LEDGER_PATH, LEDGER_PATH } from "@fenglimg/fabric-server";
|
|
11
|
-
import { defineCommand } from "citty";
|
|
12
|
-
var INITIAL_PARENT_SHA = "root";
|
|
13
|
-
var ledgerAppendCommand = defineCommand({
|
|
14
|
-
meta: {
|
|
15
|
-
name: "ledger-append",
|
|
16
|
-
description: t("cli.ledger-append.description")
|
|
17
|
-
},
|
|
18
|
-
args: {
|
|
19
|
-
target: {
|
|
20
|
-
type: "string",
|
|
21
|
-
description: t("cli.ledger-append.args.target.description"),
|
|
22
|
-
default: process.cwd()
|
|
23
|
-
},
|
|
24
|
-
staged: {
|
|
25
|
-
type: "boolean",
|
|
26
|
-
description: t("cli.ledger-append.args.staged.description"),
|
|
27
|
-
default: false
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
async run({ args }) {
|
|
31
|
-
const target = normalizeTarget(args.target);
|
|
32
|
-
assertExistingDirectory(target);
|
|
33
|
-
if (!args.staged) {
|
|
34
|
-
writeStderr(t("cli.ledger-append.requires-staged"));
|
|
35
|
-
process.exitCode = 1;
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
const stagedFiles = getStagedFiles(target).filter((file) => file !== LEGACY_LEDGER_PATH && file !== LEDGER_PATH);
|
|
39
|
-
if (stagedFiles.length === 0) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
const intent = deriveIntent(stagedFiles);
|
|
43
|
-
const diffStat = readDiffStat(target).trim();
|
|
44
|
-
const entry = {
|
|
45
|
-
ts: Date.now(),
|
|
46
|
-
source: "human",
|
|
47
|
-
parent_sha: readParentSha(target),
|
|
48
|
-
intent,
|
|
49
|
-
affected_paths: stagedFiles,
|
|
50
|
-
diff_stat: diffStat
|
|
51
|
-
};
|
|
52
|
-
if (hasMatchingTailEntry(target, entry)) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
const ledgerPath = getLedgerPath(target);
|
|
56
|
-
mkdirSync(resolve(target, ".fabric"), { recursive: true });
|
|
57
|
-
appendFileSync(ledgerPath, `${JSON.stringify(entry)}
|
|
58
|
-
`, "utf8");
|
|
59
|
-
execGit(target, `git add ${LEDGER_PATH}`);
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
var ledger_append_default = ledgerAppendCommand;
|
|
63
|
-
function normalizeTarget(targetInput) {
|
|
64
|
-
return isAbsolute(targetInput) ? targetInput : resolve(process.cwd(), targetInput);
|
|
65
|
-
}
|
|
66
|
-
function assertExistingDirectory(target) {
|
|
67
|
-
if (!existsSync(target) || !statSync(target).isDirectory()) {
|
|
68
|
-
throw new Error(t("cli.shared.target-invalid", { target }));
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
function getStagedFiles(target) {
|
|
72
|
-
const output = execGit(target, "git diff --cached --name-only --no-renames");
|
|
73
|
-
return output.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
74
|
-
}
|
|
75
|
-
function readDiffStat(target) {
|
|
76
|
-
return execGit(target, "git diff --cached --stat");
|
|
77
|
-
}
|
|
78
|
-
function readParentSha(target) {
|
|
79
|
-
try {
|
|
80
|
-
return execGit(target, "git rev-parse --short HEAD").trim();
|
|
81
|
-
} catch {
|
|
82
|
-
return INITIAL_PARENT_SHA;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
function deriveIntent(stagedFiles) {
|
|
86
|
-
const explicitIntent = process.env.FABRIC_INTENT?.trim();
|
|
87
|
-
if (explicitIntent) {
|
|
88
|
-
return explicitIntent;
|
|
89
|
-
}
|
|
90
|
-
const uniqueNames = Array.from(new Set(stagedFiles.map((file) => basename(file))));
|
|
91
|
-
const head = uniqueNames.slice(0, 2).join(", ");
|
|
92
|
-
const suffix = uniqueNames.length > 2 ? t("cli.ledger-append.intent.auto-more", { count: String(uniqueNames.length - 2) }) : "";
|
|
93
|
-
return t("cli.ledger-append.intent.auto", { head, suffix });
|
|
94
|
-
}
|
|
95
|
-
function hasMatchingTailEntry(target, entry) {
|
|
96
|
-
const ledgerPath = resolveTailLedgerPath(target);
|
|
97
|
-
if (!existsSync(ledgerPath)) {
|
|
98
|
-
return false;
|
|
99
|
-
}
|
|
100
|
-
const tail = readFileSync(ledgerPath, "utf8").trim().split(/\r?\n/).filter(Boolean).reverse().find((line) => isLedgerEntryLine(line));
|
|
101
|
-
if (!tail) {
|
|
102
|
-
return false;
|
|
103
|
-
}
|
|
104
|
-
try {
|
|
105
|
-
const parsed = JSON.parse(tail);
|
|
106
|
-
return parsed.parent_sha === entry.parent_sha && parsed.intent === entry.intent && Array.isArray(parsed.affected_paths) && parsed.affected_paths.length === entry.affected_paths.length && parsed.affected_paths.every((value, index) => value === entry.affected_paths[index]) && normalizeDiffStat(parsed.diff_stat) === normalizeDiffStat(entry.diff_stat);
|
|
107
|
-
} catch {
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
function resolveTailLedgerPath(target) {
|
|
112
|
-
const canonicalPath = getLedgerPath(target);
|
|
113
|
-
if (existsSync(canonicalPath)) {
|
|
114
|
-
return canonicalPath;
|
|
115
|
-
}
|
|
116
|
-
return getLegacyLedgerPath(target);
|
|
117
|
-
}
|
|
118
|
-
function isLedgerEntryLine(line) {
|
|
119
|
-
try {
|
|
120
|
-
const parsed = JSON.parse(line);
|
|
121
|
-
return parsed.kind !== "mcp-event";
|
|
122
|
-
} catch {
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
function normalizeDiffStat(diffStat) {
|
|
127
|
-
if (typeof diffStat !== "string") {
|
|
128
|
-
return "";
|
|
129
|
-
}
|
|
130
|
-
return diffStat.split(/\r?\n/).map((line) => line.trim()).map((line) => line.replace(/\s+\|\s+/g, " | ")).map((line) => line.replace(/\s+/g, " ")).filter((line) => line.length > 0).filter((line) => !line.includes(LEGACY_LEDGER_PATH)).filter((line) => !line.includes(LEDGER_PATH)).filter((line) => !/\d+ files? changed(?:, \d+ insertions?\(\+\))?(?:, \d+ deletions?\(-\))?$/.test(line.trim())).join("\n");
|
|
131
|
-
}
|
|
132
|
-
function execGit(target, command) {
|
|
133
|
-
return execSync(command, {
|
|
134
|
-
cwd: target,
|
|
135
|
-
encoding: "utf8",
|
|
136
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
function writeStderr(message) {
|
|
140
|
-
process.stderr.write(`${message}
|
|
141
|
-
`);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export {
|
|
145
|
-
ledgerAppendCommand,
|
|
146
|
-
ledger_append_default
|
|
147
|
-
};
|