@fenglimg/fabric-cli 1.3.1 → 1.5.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 +15 -11
- package/dist/approve-YT4DEABS.js +138 -0
- package/dist/{bootstrap-3PUKUYTY.js → bootstrap-VGL3AR26.js} +3 -3
- package/dist/{chunk-VOQKQ6W2.js → chunk-BEKSXO5N.js} +10 -2
- package/dist/{chunk-XFSQM3LJ.js → chunk-BVTMVW5M.js} +1 -1
- package/dist/{chunk-AZRKMFRY.js → chunk-QSAEGVKE.js} +2 -2
- package/dist/{chunk-TKTWHAKV.js → chunk-T2WJF5I3.js} +9 -9
- package/dist/{config-GINBGANU.js → config-EC5L2QNI.js} +2 -2
- package/dist/index.js +7 -6
- package/dist/{init-T3LGMGAO.js → init-YR7EVBYQ.js} +1088 -281
- package/dist/{scan-43R3IBLR.js → scan-QH76LC7Z.js} +1 -1
- package/dist/scanner/tree-sitter-probe.d.ts +24 -0
- package/dist/scanner/tree-sitter-probe.js +107 -0
- package/dist/{update-AN3FYF2O.js → update-M5M5PYKE.js} +7 -7
- package/package.json +7 -3
- package/templates/codex-hooks/fabric-session-start.cjs +19 -0
- package/templates/codex-hooks/fabric-stop-reminder.cjs +18 -0
- package/templates/codex-skills/fabric-init/SKILL.md +27 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
type TreeSitterProbeResult = {
|
|
2
|
+
ok: boolean;
|
|
3
|
+
node_version: string;
|
|
4
|
+
package_engines: "not-declared";
|
|
5
|
+
root_node_type: string;
|
|
6
|
+
has_error: boolean;
|
|
7
|
+
elapsed_ms: number;
|
|
8
|
+
wasm: {
|
|
9
|
+
runtime_path: string;
|
|
10
|
+
runtime_bytes: number;
|
|
11
|
+
javascript_grammar_path: string;
|
|
12
|
+
javascript_grammar_bytes: number;
|
|
13
|
+
};
|
|
14
|
+
decision: {
|
|
15
|
+
status: "feasible";
|
|
16
|
+
loading_strategy: "lazy";
|
|
17
|
+
bundle_size_impact: string;
|
|
18
|
+
grammar_strategy: string;
|
|
19
|
+
integration_note: string;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
declare function runTreeSitterProbe(source?: string): Promise<TreeSitterProbeResult>;
|
|
23
|
+
|
|
24
|
+
export { type TreeSitterProbeResult, runTreeSitterProbe };
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/scanner/tree-sitter-probe.ts
|
|
4
|
+
import { realpathSync, statSync } from "fs";
|
|
5
|
+
import { createRequire } from "module";
|
|
6
|
+
import { resolve } from "path";
|
|
7
|
+
import { performance } from "perf_hooks";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
var require2 = createRequire(import.meta.url);
|
|
10
|
+
var PROBE_SOURCE = `import { strict as assert } from "node:assert";
|
|
11
|
+
|
|
12
|
+
const users = [{ id: "1", name: "Ada" }];
|
|
13
|
+
|
|
14
|
+
export function findUser(id) {
|
|
15
|
+
return users.find((user) => user.id === id);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
assert.equal(findUser("1")?.name, "Ada");
|
|
19
|
+
console.log("parsed");`;
|
|
20
|
+
var treeSitterModulePromise = null;
|
|
21
|
+
var parserInitPromise = null;
|
|
22
|
+
var javascriptLanguagePromise = null;
|
|
23
|
+
async function runTreeSitterProbe(source = PROBE_SOURCE) {
|
|
24
|
+
const startedAt = performance.now();
|
|
25
|
+
const assets = resolveTreeSitterAssets();
|
|
26
|
+
const treeSitter = await loadTreeSitterModule();
|
|
27
|
+
await initParser(treeSitter, assets.runtimeWasmPath);
|
|
28
|
+
const language = await loadJavaScriptLanguage(treeSitter, assets.javascriptGrammarPath);
|
|
29
|
+
const parser = new treeSitter.Parser();
|
|
30
|
+
const runtimeBytes = statSync(assets.runtimeWasmPath).size;
|
|
31
|
+
const javascriptGrammarBytes = statSync(assets.javascriptGrammarPath).size;
|
|
32
|
+
let tree = null;
|
|
33
|
+
try {
|
|
34
|
+
parser.setLanguage(language);
|
|
35
|
+
tree = parser.parse(source);
|
|
36
|
+
if (tree === null) {
|
|
37
|
+
throw new Error("web-tree-sitter probe failed: parser returned null syntax tree");
|
|
38
|
+
}
|
|
39
|
+
const rootNode = tree.rootNode;
|
|
40
|
+
return {
|
|
41
|
+
ok: !rootNode.hasError,
|
|
42
|
+
node_version: process.version,
|
|
43
|
+
package_engines: "not-declared",
|
|
44
|
+
root_node_type: rootNode.type,
|
|
45
|
+
has_error: rootNode.hasError,
|
|
46
|
+
elapsed_ms: Math.round(performance.now() - startedAt),
|
|
47
|
+
wasm: {
|
|
48
|
+
runtime_path: assets.runtimeWasmPath,
|
|
49
|
+
runtime_bytes: runtimeBytes,
|
|
50
|
+
javascript_grammar_path: assets.javascriptGrammarPath,
|
|
51
|
+
javascript_grammar_bytes: javascriptGrammarBytes
|
|
52
|
+
},
|
|
53
|
+
decision: {
|
|
54
|
+
status: "feasible",
|
|
55
|
+
loading_strategy: "lazy",
|
|
56
|
+
bundle_size_impact: formatBundleImpact(runtimeBytes, javascriptGrammarBytes),
|
|
57
|
+
grammar_strategy: "Use tree-sitter-javascript WASM for JavaScript and TS-compatible syntax; evaluate tree-sitter-typescript before parsing TypeScript-only syntax.",
|
|
58
|
+
integration_note: "Keep web-tree-sitter behind a dynamic import at the forensic inferPatternHint() call site to avoid CLI startup cost."
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
} finally {
|
|
62
|
+
tree?.delete();
|
|
63
|
+
parser.delete();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function resolveTreeSitterAssets() {
|
|
67
|
+
return {
|
|
68
|
+
runtimeWasmPath: require2.resolve("web-tree-sitter/web-tree-sitter.wasm"),
|
|
69
|
+
javascriptGrammarPath: require2.resolve("tree-sitter-javascript/tree-sitter-javascript.wasm")
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function loadTreeSitterModule() {
|
|
73
|
+
treeSitterModulePromise ??= import("web-tree-sitter");
|
|
74
|
+
return treeSitterModulePromise;
|
|
75
|
+
}
|
|
76
|
+
function initParser(treeSitter, runtimeWasmPath) {
|
|
77
|
+
parserInitPromise ??= treeSitter.Parser.init({
|
|
78
|
+
locateFile: (scriptName) => scriptName.endsWith(".wasm") ? runtimeWasmPath : scriptName
|
|
79
|
+
});
|
|
80
|
+
return parserInitPromise;
|
|
81
|
+
}
|
|
82
|
+
function loadJavaScriptLanguage(treeSitter, javascriptGrammarPath) {
|
|
83
|
+
javascriptLanguagePromise ??= treeSitter.Language.load(javascriptGrammarPath);
|
|
84
|
+
return javascriptLanguagePromise;
|
|
85
|
+
}
|
|
86
|
+
function formatBundleImpact(runtimeBytes, javascriptGrammarBytes) {
|
|
87
|
+
const combinedBytes = runtimeBytes + javascriptGrammarBytes;
|
|
88
|
+
return `${formatBytes(combinedBytes)} combined WASM payload (${formatBytes(runtimeBytes)} runtime + ${formatBytes(javascriptGrammarBytes)} JavaScript grammar); package unpacked sizes are larger and acceptable only with lazy loading.`;
|
|
89
|
+
}
|
|
90
|
+
function formatBytes(bytes) {
|
|
91
|
+
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
92
|
+
}
|
|
93
|
+
var entrypoint = process.argv[1];
|
|
94
|
+
var currentFilePath = fileURLToPath(import.meta.url);
|
|
95
|
+
var isMainModule = entrypoint !== void 0 && realpathSync(resolve(entrypoint)) === currentFilePath;
|
|
96
|
+
if (isMainModule) {
|
|
97
|
+
runTreeSitterProbe().then((result) => {
|
|
98
|
+
console.log(JSON.stringify(result, null, 2));
|
|
99
|
+
}).catch((error) => {
|
|
100
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
101
|
+
console.error(`web-tree-sitter probe failed: ${message}`);
|
|
102
|
+
process.exitCode = 1;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
export {
|
|
106
|
+
runTreeSitterProbe
|
|
107
|
+
};
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
installMcpClients
|
|
4
|
-
} from "./chunk-XFSQM3LJ.js";
|
|
5
|
-
import "./chunk-VOQKQ6W2.js";
|
|
6
|
-
import {
|
|
7
|
-
installHooks
|
|
8
|
-
} from "./chunk-YDZJRLHL.js";
|
|
9
2
|
import {
|
|
10
3
|
resolveDevModeTarget
|
|
11
4
|
} from "./chunk-AEOYCVBG.js";
|
|
12
5
|
import {
|
|
13
6
|
paint
|
|
14
7
|
} from "./chunk-WWNXR34K.js";
|
|
8
|
+
import {
|
|
9
|
+
installMcpClients
|
|
10
|
+
} from "./chunk-BVTMVW5M.js";
|
|
11
|
+
import "./chunk-BEKSXO5N.js";
|
|
12
|
+
import {
|
|
13
|
+
installHooks
|
|
14
|
+
} from "./chunk-YDZJRLHL.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
|
+
"version": "1.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"fab": "dist/index.js",
|
|
@@ -13,13 +13,17 @@
|
|
|
13
13
|
"templates"
|
|
14
14
|
],
|
|
15
15
|
"dependencies": {
|
|
16
|
+
"@clack/prompts": "^1.2.0",
|
|
16
17
|
"@iarna/toml": "^2.2.5",
|
|
17
18
|
"citty": "^0.2.2",
|
|
18
19
|
"minimatch": "^10.0.1",
|
|
19
20
|
"picocolors": "^1.1.1",
|
|
20
21
|
"string-width": "^7.2.0",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
22
|
+
"tree-sitter-javascript": "^0.25.0",
|
|
23
|
+
"tree-sitter-typescript": "^0.23.2",
|
|
24
|
+
"web-tree-sitter": "^0.26.8",
|
|
25
|
+
"@fenglimg/fabric-server": "1.5.0",
|
|
26
|
+
"@fenglimg/fabric-shared": "1.5.0"
|
|
23
27
|
},
|
|
24
28
|
"devDependencies": {
|
|
25
29
|
"@types/iarna__toml": "^2.0.5",
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { existsSync } = require("node:fs");
|
|
3
|
+
const { join } = require("node:path");
|
|
4
|
+
|
|
5
|
+
const forensicPath = join(process.cwd(), ".fabric", "forensic.json");
|
|
6
|
+
const initContextPath = join(process.cwd(), ".fabric", "init-context.json");
|
|
7
|
+
|
|
8
|
+
if (!existsSync(forensicPath) || existsSync(initContextPath)) {
|
|
9
|
+
process.exit(0);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
process.stdout.write(
|
|
13
|
+
JSON.stringify({
|
|
14
|
+
hookSpecificOutput: {
|
|
15
|
+
additionalContext:
|
|
16
|
+
"Fabric initialization is still pending in this repository. Read .fabric/forensic.json, .fabric/bootstrap/README.md, and use the repo skill at .agents/skills/fabric-init/SKILL.md before proceeding. If Codex hooks are not firing, ensure features.codex_hooks = true is enabled in your Codex config.",
|
|
17
|
+
},
|
|
18
|
+
}),
|
|
19
|
+
);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { existsSync } = require("node:fs");
|
|
3
|
+
const { join } = require("node:path");
|
|
4
|
+
|
|
5
|
+
const forensicPath = join(process.cwd(), ".fabric", "forensic.json");
|
|
6
|
+
const initContextPath = join(process.cwd(), ".fabric", "init-context.json");
|
|
7
|
+
|
|
8
|
+
if (!existsSync(forensicPath) || existsSync(initContextPath)) {
|
|
9
|
+
process.exit(0);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
process.stdout.write(
|
|
13
|
+
JSON.stringify({
|
|
14
|
+
decision: "block",
|
|
15
|
+
reason:
|
|
16
|
+
"fab init has collected Fabric evidence, but initialization follow-up is still pending. Ensure features.codex_hooks = true is enabled, then use the repo skill at .agents/skills/fabric-init/SKILL.md and review .fabric/forensic.json plus .fabric/bootstrap/README.md before continuing.",
|
|
17
|
+
}),
|
|
18
|
+
);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fabric-init
|
|
3
|
+
description: Use this skill when `.fabric/forensic.json` exists and Fabric initialization follow-up still needs to be completed for this repository.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Hard Rules (DO NOT TRANSLATE)
|
|
7
|
+
|
|
8
|
+
MUST: Read `.fabric/forensic.json` before taking any other action.
|
|
9
|
+
MUST: Treat `.fabric/bootstrap/README.md` as the current bootstrap contract for this repository.
|
|
10
|
+
MUST: If `.fabric/init-context.json` already exists, stop and report that initialization follow-up appears complete.
|
|
11
|
+
MUST: Use evidence from `.fabric/forensic.json` and the repository layout to guide the initialization follow-up.
|
|
12
|
+
MUST: Preserve protected tokens exactly: `AGENTS.md`, `FABRIC.md`, `.fabric/agents.meta.json`, `.fabric/human-lock.json`, `.fabric/init-context.json`, `.fabric/forensic.json`, `MUST`, `NEVER`.
|
|
13
|
+
NEVER: Claim initialization is complete without checking `.fabric/init-context.json`.
|
|
14
|
+
NEVER: Rewrite or translate protected tokens.
|
|
15
|
+
NEVER: ignore `.fabric/bootstrap/README.md` while deciding next initialization steps.
|
|
16
|
+
|
|
17
|
+
## Purpose
|
|
18
|
+
|
|
19
|
+
Use this skill after `fab init` when Codex is working inside the repository and Fabric's evidence pack already exists. The goal is to continue the repository-specific initialization workflow using the generated forensic evidence and bootstrap contract.
|
|
20
|
+
|
|
21
|
+
## Workflow
|
|
22
|
+
|
|
23
|
+
1. Read `.fabric/forensic.json`.
|
|
24
|
+
2. Read `.fabric/bootstrap/README.md`.
|
|
25
|
+
3. Check whether `.fabric/init-context.json` exists.
|
|
26
|
+
4. If initialization is still pending, summarize the next repository-specific initialization actions Codex should take.
|
|
27
|
+
5. Keep the guidance tightly scoped to Fabric initialization follow-up for this repository.
|