@fenglimg/fabric-cli 0.1.4 → 1.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/dist/{bootstrap-HUDJ2E3Q.js → bootstrap-PMIA4W6G.js} +16 -12
- package/dist/{chunk-T3WQUWW4.js → chunk-5BSTO745.js} +9 -6
- package/dist/chunk-6ICJICVU.js +10 -0
- package/dist/chunk-AEOYCVBG.js +0 -0
- package/dist/chunk-DKQ3HOTK.js +206 -0
- package/dist/{chunk-U376IPKT.js → chunk-F2BXHPM5.js} +11 -7
- package/dist/{chunk-CZ7U6ULM.js → chunk-L43IGJ6X.js} +17 -7
- package/dist/chunk-P4KVFB2T.js +0 -0
- package/dist/{chunk-N7TTCGJA.js → chunk-VMYPJPKV.js} +1 -0
- package/dist/chunk-WWNXR34K.js +49 -0
- package/dist/{config-YKDWIRCT.js → config-PXEEXWLM.js} +14 -11
- package/dist/{hooks-VXXO4VZP.js → hooks-5S5IRVQE.js} +15 -12
- package/dist/human-lint-YSFOZHZ7.js +13 -0
- package/dist/index.js +15 -11
- package/dist/init-G6Q3OOMC.js +601 -0
- package/dist/{ledger-append-EGIKSMU5.js → ledger-append-XZ5SX4O5.js} +2 -1
- package/dist/{pre-commit-CXPH7BZH.js → pre-commit-IEIXHKOD.js} +13 -7
- package/dist/{scan-UASZQLQP.js → scan-6CURGC3D.js} +3 -1
- package/dist/serve-4J2CQY25.js +112 -0
- package/dist/{sync-meta-YTG5V3Y6.js → sync-meta-L6M4AEUT.js} +2 -1
- package/package.json +12 -8
- package/templates/agents-md/AGENTS.md.template +17 -11
- package/templates/agents-md/variants/cocos.md +37 -0
- package/templates/agents-md/variants/next.md +37 -0
- package/templates/agents-md/variants/vite.md +37 -0
- package/templates/claude-hooks/agents-md-init-reminder.cjs +18 -0
- package/templates/claude-skills/agents-md-init/SKILL.md +86 -0
- package/dist/chunk-BWZHNZG6.js +0 -236
- package/dist/human-lint-II6TBGP4.js +0 -9
- package/dist/init-IBS7KO7A.js +0 -149
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
resolveClients
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-VMYPJPKV.js";
|
|
5
5
|
import {
|
|
6
6
|
readFabricConfig
|
|
7
7
|
} from "./chunk-AEOYCVBG.js";
|
|
8
|
+
import {
|
|
9
|
+
t
|
|
10
|
+
} from "./chunk-6ICJICVU.js";
|
|
8
11
|
|
|
9
12
|
// src/commands/bootstrap.ts
|
|
10
13
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -50,18 +53,18 @@ var CLIENT_TARGET_MAP = {
|
|
|
50
53
|
var bootstrapCommand = defineCommand({
|
|
51
54
|
meta: {
|
|
52
55
|
name: "bootstrap",
|
|
53
|
-
description: "
|
|
56
|
+
description: t("cli.bootstrap.description")
|
|
54
57
|
},
|
|
55
58
|
subCommands: {
|
|
56
59
|
install: defineCommand({
|
|
57
60
|
meta: {
|
|
58
61
|
name: "install",
|
|
59
|
-
description: "
|
|
62
|
+
description: t("cli.bootstrap.install.description")
|
|
60
63
|
},
|
|
61
64
|
args: {
|
|
62
65
|
clients: {
|
|
63
66
|
type: "string",
|
|
64
|
-
description: "
|
|
67
|
+
description: t("cli.bootstrap.install.args.clients.description")
|
|
65
68
|
}
|
|
66
69
|
},
|
|
67
70
|
async run({ args }) {
|
|
@@ -72,7 +75,8 @@ var bootstrapCommand = defineCommand({
|
|
|
72
75
|
const clients = selectedClients ?? detectedClients;
|
|
73
76
|
if (clients.size === 0) {
|
|
74
77
|
process.stderr.write(
|
|
75
|
-
"
|
|
78
|
+
`${t("cli.bootstrap.install.no-targets")}
|
|
79
|
+
`
|
|
76
80
|
);
|
|
77
81
|
return;
|
|
78
82
|
}
|
|
@@ -93,7 +97,7 @@ function parseClientFilter(value) {
|
|
|
93
97
|
const alias = rawClient.trim().toLowerCase();
|
|
94
98
|
const client = CLIENT_ALIASES[alias];
|
|
95
99
|
if (client === void 0) {
|
|
96
|
-
throw new Error(
|
|
100
|
+
throw new Error(t("cli.bootstrap.errors.unknown-client", { client: rawClient }));
|
|
97
101
|
}
|
|
98
102
|
clients.add(client);
|
|
99
103
|
}
|
|
@@ -138,26 +142,26 @@ function installBootstrap(client, workspaceRoot) {
|
|
|
138
142
|
return;
|
|
139
143
|
}
|
|
140
144
|
writeFileSync(targetPath, ensureTrailingNewline(template), "utf8");
|
|
141
|
-
process.stderr.write(
|
|
145
|
+
process.stderr.write(`${t("cli.bootstrap.install.installed", { path: targetPath })}
|
|
142
146
|
`);
|
|
143
147
|
}
|
|
144
148
|
function writeCodexBootstrap(targetPath, template) {
|
|
145
149
|
const nextContent = ensureTrailingNewline(template);
|
|
146
150
|
if (!existsSync(targetPath)) {
|
|
147
151
|
writeFileSync(targetPath, nextContent, "utf8");
|
|
148
|
-
process.stderr.write(
|
|
152
|
+
process.stderr.write(`${t("cli.bootstrap.install.installed", { path: targetPath })}
|
|
149
153
|
`);
|
|
150
154
|
return;
|
|
151
155
|
}
|
|
152
156
|
const existing = readFileSync(targetPath, "utf8");
|
|
153
157
|
if (existing.includes("# Fabric Bootstrap")) {
|
|
154
|
-
process.stderr.write(
|
|
158
|
+
process.stderr.write(`${t("cli.bootstrap.install.skipped-header", { path: targetPath })}
|
|
155
159
|
`);
|
|
156
160
|
return;
|
|
157
161
|
}
|
|
158
162
|
const separator = existing.startsWith("\n") || existing.length === 0 ? "" : "\n";
|
|
159
163
|
writeFileSync(targetPath, `${nextContent}${separator}${existing}`, "utf8");
|
|
160
|
-
process.stderr.write(
|
|
164
|
+
process.stderr.write(`${t("cli.bootstrap.install.prepended", { path: targetPath })}
|
|
161
165
|
`);
|
|
162
166
|
}
|
|
163
167
|
function ensureTrailingNewline(content) {
|
|
@@ -175,7 +179,7 @@ function findTemplatePath(relativePath) {
|
|
|
175
179
|
return candidate;
|
|
176
180
|
}
|
|
177
181
|
}
|
|
178
|
-
throw new Error(
|
|
182
|
+
throw new Error(t("cli.shared.template-not-found", { path: relativePath }));
|
|
179
183
|
}
|
|
180
184
|
function templateCandidatesFrom(start, relativePath) {
|
|
181
185
|
const candidates = [];
|
|
@@ -188,7 +192,7 @@ function templateCandidatesFrom(start, relativePath) {
|
|
|
188
192
|
}
|
|
189
193
|
current = parent;
|
|
190
194
|
}
|
|
191
|
-
return candidates;
|
|
195
|
+
return candidates.reverse();
|
|
192
196
|
}
|
|
193
197
|
export {
|
|
194
198
|
bootstrapCommand,
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
resolveIgnores
|
|
4
4
|
} from "./chunk-P4KVFB2T.js";
|
|
5
|
+
import {
|
|
6
|
+
t
|
|
7
|
+
} from "./chunk-6ICJICVU.js";
|
|
5
8
|
|
|
6
9
|
// src/commands/sync-meta.ts
|
|
7
10
|
import { createHash } from "crypto";
|
|
@@ -11,17 +14,17 @@ import { defineCommand } from "citty";
|
|
|
11
14
|
var syncMetaCommand = defineCommand({
|
|
12
15
|
meta: {
|
|
13
16
|
name: "sync-meta",
|
|
14
|
-
description: "
|
|
17
|
+
description: t("cli.sync-meta.description")
|
|
15
18
|
},
|
|
16
19
|
args: {
|
|
17
20
|
target: {
|
|
18
21
|
type: "string",
|
|
19
|
-
description: "
|
|
22
|
+
description: t("cli.sync-meta.args.target.description"),
|
|
20
23
|
default: process.cwd()
|
|
21
24
|
},
|
|
22
25
|
"check-only": {
|
|
23
26
|
type: "boolean",
|
|
24
|
-
description: "
|
|
27
|
+
description: t("cli.sync-meta.args.check-only.description"),
|
|
25
28
|
default: false
|
|
26
29
|
}
|
|
27
30
|
},
|
|
@@ -32,7 +35,7 @@ var syncMetaCommand = defineCommand({
|
|
|
32
35
|
const existingMeta = readExistingMeta(metaPath);
|
|
33
36
|
if (args["check-only"]) {
|
|
34
37
|
if (!existingMeta || stableStringify(existingMeta) !== stableStringify(computedMeta)) {
|
|
35
|
-
writeStderr("
|
|
38
|
+
writeStderr(t("cli.sync-meta.drift-detected"));
|
|
36
39
|
process.exitCode = 1;
|
|
37
40
|
}
|
|
38
41
|
return;
|
|
@@ -43,7 +46,7 @@ var syncMetaCommand = defineCommand({
|
|
|
43
46
|
mkdirSync(join(target, ".fabric"), { recursive: true });
|
|
44
47
|
writeFileSync(metaPath, `${JSON.stringify(computedMeta, null, 2)}
|
|
45
48
|
`, "utf8");
|
|
46
|
-
writeStderr(
|
|
49
|
+
writeStderr(t("cli.sync-meta.updated", { label: t("cli.shared.updated"), path: metaPath }));
|
|
47
50
|
}
|
|
48
51
|
});
|
|
49
52
|
var sync_meta_default = syncMetaCommand;
|
|
@@ -77,7 +80,7 @@ function normalizeTarget(targetInput) {
|
|
|
77
80
|
}
|
|
78
81
|
function assertExistingDirectory(target) {
|
|
79
82
|
if (!existsSync(target) || !statSync(target).isDirectory()) {
|
|
80
|
-
throw new Error(
|
|
83
|
+
throw new Error(t("cli.shared.target-invalid", { target }));
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
86
|
function readExistingMeta(metaPath) {
|
package/dist/chunk-AEOYCVBG.js
CHANGED
|
File without changes
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
createDebugLogger,
|
|
4
|
+
readFabricConfig,
|
|
5
|
+
resolveDevMode
|
|
6
|
+
} from "./chunk-AEOYCVBG.js";
|
|
7
|
+
import {
|
|
8
|
+
resolveIgnores
|
|
9
|
+
} from "./chunk-P4KVFB2T.js";
|
|
10
|
+
import {
|
|
11
|
+
displayWidth,
|
|
12
|
+
padEnd,
|
|
13
|
+
paint,
|
|
14
|
+
symbol
|
|
15
|
+
} from "./chunk-WWNXR34K.js";
|
|
16
|
+
import {
|
|
17
|
+
t
|
|
18
|
+
} from "./chunk-6ICJICVU.js";
|
|
19
|
+
|
|
20
|
+
// src/commands/scan.ts
|
|
21
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
22
|
+
import { isAbsolute, join, relative, resolve, sep } from "path";
|
|
23
|
+
import { defineCommand } from "citty";
|
|
24
|
+
|
|
25
|
+
// src/scanner/detector.ts
|
|
26
|
+
import { detectFramework } from "@fenglimg/fabric-shared";
|
|
27
|
+
|
|
28
|
+
// src/commands/scan.ts
|
|
29
|
+
function createScanReport(targetInput = process.cwd(), fabricConfig) {
|
|
30
|
+
const target = normalizeTarget(targetInput);
|
|
31
|
+
const framework = detectFramework(target);
|
|
32
|
+
const readmeQuality = getReadmeQuality(target);
|
|
33
|
+
const hasContributing = existsSync(join(target, "CONTRIBUTING.md"));
|
|
34
|
+
const hasExistingFabric = existsSync(join(target, "AGENTS.md")) || existsSync(join(target, ".fabric"));
|
|
35
|
+
const walkResult = walkFiles(target, resolveIgnores(fabricConfig));
|
|
36
|
+
return {
|
|
37
|
+
target,
|
|
38
|
+
framework,
|
|
39
|
+
readmeQuality,
|
|
40
|
+
hasContributing,
|
|
41
|
+
fileCount: walkResult.fileCount,
|
|
42
|
+
ignoredCount: walkResult.ignoredCount,
|
|
43
|
+
hasExistingFabric,
|
|
44
|
+
recommendations: buildRecommendations({
|
|
45
|
+
framework,
|
|
46
|
+
readmeQuality,
|
|
47
|
+
hasContributing,
|
|
48
|
+
hasExistingFabric
|
|
49
|
+
})
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
var scanCommand = defineCommand({
|
|
53
|
+
meta: {
|
|
54
|
+
name: "scan",
|
|
55
|
+
description: t("cli.scan.description")
|
|
56
|
+
},
|
|
57
|
+
args: {
|
|
58
|
+
target: {
|
|
59
|
+
type: "string",
|
|
60
|
+
description: t("cli.scan.args.target.description")
|
|
61
|
+
},
|
|
62
|
+
debug: {
|
|
63
|
+
type: "boolean",
|
|
64
|
+
description: t("cli.scan.args.debug.description"),
|
|
65
|
+
default: false
|
|
66
|
+
},
|
|
67
|
+
json: {
|
|
68
|
+
type: "boolean",
|
|
69
|
+
description: t("cli.scan.args.json.description"),
|
|
70
|
+
default: false
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
async run({ args }) {
|
|
74
|
+
const workspaceRoot = process.cwd();
|
|
75
|
+
const logger = createDebugLogger(args.debug);
|
|
76
|
+
const resolution = resolveDevMode(args.target, workspaceRoot);
|
|
77
|
+
const fabricConfig = readFabricConfig(workspaceRoot);
|
|
78
|
+
logger(`scan target source: ${resolution.source}`);
|
|
79
|
+
for (const step of resolution.chain) {
|
|
80
|
+
logger(step);
|
|
81
|
+
}
|
|
82
|
+
const report = createScanReport(resolution.target, fabricConfig);
|
|
83
|
+
if (args.json) {
|
|
84
|
+
console.log(JSON.stringify(report, null, 2));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
printPrettyReport(report, Boolean(args.debug));
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
var scan_default = scanCommand;
|
|
91
|
+
function normalizeTarget(targetInput) {
|
|
92
|
+
return isAbsolute(targetInput) ? targetInput : resolve(process.cwd(), targetInput);
|
|
93
|
+
}
|
|
94
|
+
function getReadmeQuality(target) {
|
|
95
|
+
const readmePath = join(target, "README.md");
|
|
96
|
+
if (!existsSync(readmePath)) {
|
|
97
|
+
return "stub";
|
|
98
|
+
}
|
|
99
|
+
const wordCount = readFileSync(readmePath, "utf8").trim().split(/\s+/).filter(Boolean).length;
|
|
100
|
+
return wordCount >= 200 ? "ok" : "stub";
|
|
101
|
+
}
|
|
102
|
+
function walkFiles(root, ignorePatterns) {
|
|
103
|
+
if (!existsSync(root) || !statSync(root).isDirectory()) {
|
|
104
|
+
throw new Error(t("cli.shared.target-invalid", { target: root }));
|
|
105
|
+
}
|
|
106
|
+
let fileCount = 0;
|
|
107
|
+
let ignoredCount = 0;
|
|
108
|
+
const stack = [root];
|
|
109
|
+
while (stack.length > 0) {
|
|
110
|
+
const current = stack.pop();
|
|
111
|
+
if (current === void 0) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
for (const entry of readdirSync(current, { withFileTypes: true })) {
|
|
115
|
+
const absolutePath = join(current, entry.name);
|
|
116
|
+
const relativePath = toPosixPath(relative(root, absolutePath));
|
|
117
|
+
if (shouldIgnore(relativePath, entry.isDirectory(), ignorePatterns)) {
|
|
118
|
+
ignoredCount += 1;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (entry.isDirectory()) {
|
|
122
|
+
stack.push(absolutePath);
|
|
123
|
+
} else if (entry.isFile()) {
|
|
124
|
+
fileCount += 1;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return { fileCount, ignoredCount };
|
|
129
|
+
}
|
|
130
|
+
function shouldIgnore(relativePath, isDirectory, ignorePatterns) {
|
|
131
|
+
return ignorePatterns.some((pattern) => matchesIgnorePattern(relativePath, isDirectory, pattern));
|
|
132
|
+
}
|
|
133
|
+
function matchesIgnorePattern(relativePath, isDirectory, pattern) {
|
|
134
|
+
const normalizedPattern = toPosixPath(pattern);
|
|
135
|
+
if (normalizedPattern === "**/*.meta") {
|
|
136
|
+
return relativePath.endsWith(".meta");
|
|
137
|
+
}
|
|
138
|
+
if (normalizedPattern.endsWith("/**")) {
|
|
139
|
+
const directoryPrefix = normalizedPattern.slice(0, -3);
|
|
140
|
+
return relativePath === directoryPrefix || relativePath.startsWith(`${directoryPrefix}/`) || isDirectory && `${relativePath}/` === directoryPrefix;
|
|
141
|
+
}
|
|
142
|
+
return relativePath === normalizedPattern;
|
|
143
|
+
}
|
|
144
|
+
function toPosixPath(path) {
|
|
145
|
+
return path.split(sep).join("/");
|
|
146
|
+
}
|
|
147
|
+
function buildRecommendations(input) {
|
|
148
|
+
const recommendations = [];
|
|
149
|
+
if (!input.hasExistingFabric) {
|
|
150
|
+
recommendations.push(t("cli.scan.recommendation.init"));
|
|
151
|
+
}
|
|
152
|
+
if (input.readmeQuality === "stub") {
|
|
153
|
+
recommendations.push(t("cli.scan.recommendation.readme"));
|
|
154
|
+
}
|
|
155
|
+
if (!input.hasContributing) {
|
|
156
|
+
recommendations.push(t("cli.scan.recommendation.contributing"));
|
|
157
|
+
}
|
|
158
|
+
if (input.framework.kind === "unknown") {
|
|
159
|
+
recommendations.push(t("cli.scan.recommendation.unknown-framework"));
|
|
160
|
+
} else {
|
|
161
|
+
recommendations.push(t("cli.scan.recommendation.framework-dirs", { framework: input.framework.kind }));
|
|
162
|
+
}
|
|
163
|
+
return recommendations;
|
|
164
|
+
}
|
|
165
|
+
function printPrettyReport(report, debug) {
|
|
166
|
+
console.log(paint.ai(t("cli.scan.report.title")));
|
|
167
|
+
const rows = [
|
|
168
|
+
[t("cli.scan.report.target"), paint.human(report.target)],
|
|
169
|
+
[t("cli.scan.report.framework"), paint.ai(report.framework.kind)],
|
|
170
|
+
[
|
|
171
|
+
t("cli.scan.report.readme-quality"),
|
|
172
|
+
report.readmeQuality === "ok" ? paint.success(t("cli.scan.readme-quality.ok")) : paint.warn(t("cli.scan.readme-quality.stub"))
|
|
173
|
+
],
|
|
174
|
+
[
|
|
175
|
+
t("cli.scan.report.contributing"),
|
|
176
|
+
report.hasContributing ? paint.success(t("cli.shared.present")) : paint.warn(t("cli.shared.absent"))
|
|
177
|
+
],
|
|
178
|
+
[t("cli.scan.report.files-counted"), String(report.fileCount)],
|
|
179
|
+
[t("cli.scan.report.ignored-entries"), report.ignoredCount > 0 ? paint.muted(String(report.ignoredCount)) : "0"],
|
|
180
|
+
[
|
|
181
|
+
t("cli.scan.report.existing-fabric"),
|
|
182
|
+
report.hasExistingFabric ? paint.warn(t("cli.shared.yes")) : paint.success(t("cli.shared.no"))
|
|
183
|
+
]
|
|
184
|
+
];
|
|
185
|
+
if (debug) {
|
|
186
|
+
rows.splice(2, 0, [
|
|
187
|
+
t("cli.scan.report.evidence"),
|
|
188
|
+
report.framework.evidence.length > 0 ? paint.muted(report.framework.evidence.join(", ")) : paint.muted(t("cli.shared.none"))
|
|
189
|
+
]);
|
|
190
|
+
}
|
|
191
|
+
const labelWidth = Math.max(...rows.map(([key]) => displayWidth(key)));
|
|
192
|
+
for (const [key, value] of rows) {
|
|
193
|
+
console.log(`${paint.muted(padEnd(key, labelWidth))} ${value}`);
|
|
194
|
+
}
|
|
195
|
+
console.log(paint.muted(t("cli.scan.report.recommendations")));
|
|
196
|
+
for (const recommendation of report.recommendations) {
|
|
197
|
+
console.log(`${symbol.warn} ${paint.drift(recommendation)}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export {
|
|
202
|
+
detectFramework,
|
|
203
|
+
createScanReport,
|
|
204
|
+
scanCommand,
|
|
205
|
+
scan_default
|
|
206
|
+
};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
t
|
|
4
|
+
} from "./chunk-6ICJICVU.js";
|
|
2
5
|
|
|
3
6
|
// src/commands/ledger-append.ts
|
|
4
7
|
import { execSync } from "child_process";
|
|
@@ -10,17 +13,17 @@ var INITIAL_PARENT_SHA = "root";
|
|
|
10
13
|
var ledgerAppendCommand = defineCommand({
|
|
11
14
|
meta: {
|
|
12
15
|
name: "ledger-append",
|
|
13
|
-
description: "
|
|
16
|
+
description: t("cli.ledger-append.description")
|
|
14
17
|
},
|
|
15
18
|
args: {
|
|
16
19
|
target: {
|
|
17
20
|
type: "string",
|
|
18
|
-
description: "
|
|
21
|
+
description: t("cli.ledger-append.args.target.description"),
|
|
19
22
|
default: process.cwd()
|
|
20
23
|
},
|
|
21
24
|
staged: {
|
|
22
25
|
type: "boolean",
|
|
23
|
-
description: "
|
|
26
|
+
description: t("cli.ledger-append.args.staged.description"),
|
|
24
27
|
default: false
|
|
25
28
|
}
|
|
26
29
|
},
|
|
@@ -28,7 +31,7 @@ var ledgerAppendCommand = defineCommand({
|
|
|
28
31
|
const target = normalizeTarget(args.target);
|
|
29
32
|
assertExistingDirectory(target);
|
|
30
33
|
if (!args.staged) {
|
|
31
|
-
writeStderr("requires
|
|
34
|
+
writeStderr(t("cli.ledger-append.requires-staged"));
|
|
32
35
|
process.exitCode = 1;
|
|
33
36
|
return;
|
|
34
37
|
}
|
|
@@ -40,6 +43,7 @@ var ledgerAppendCommand = defineCommand({
|
|
|
40
43
|
const diffStat = readDiffStat(target).trim();
|
|
41
44
|
const entry = {
|
|
42
45
|
ts: Date.now(),
|
|
46
|
+
source: "human",
|
|
43
47
|
parent_sha: readParentSha(target),
|
|
44
48
|
intent,
|
|
45
49
|
affected_paths: stagedFiles,
|
|
@@ -59,7 +63,7 @@ function normalizeTarget(targetInput) {
|
|
|
59
63
|
}
|
|
60
64
|
function assertExistingDirectory(target) {
|
|
61
65
|
if (!existsSync(target) || !statSync(target).isDirectory()) {
|
|
62
|
-
throw new Error(
|
|
66
|
+
throw new Error(t("cli.shared.target-invalid", { target }));
|
|
63
67
|
}
|
|
64
68
|
}
|
|
65
69
|
function getStagedFiles(target) {
|
|
@@ -83,8 +87,8 @@ function deriveIntent(stagedFiles) {
|
|
|
83
87
|
}
|
|
84
88
|
const uniqueNames = Array.from(new Set(stagedFiles.map((file) => basename(file))));
|
|
85
89
|
const head = uniqueNames.slice(0, 2).join(", ");
|
|
86
|
-
const suffix = uniqueNames.length > 2 ?
|
|
87
|
-
return
|
|
90
|
+
const suffix = uniqueNames.length > 2 ? t("cli.ledger-append.intent.auto-more", { count: String(uniqueNames.length - 2) }) : "";
|
|
91
|
+
return t("cli.ledger-append.intent.auto", { head, suffix });
|
|
88
92
|
}
|
|
89
93
|
function hasMatchingTailEntry(target, entry) {
|
|
90
94
|
const ledgerPath = join(target, LEDGER_FILE);
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
padEnd
|
|
4
|
+
} from "./chunk-WWNXR34K.js";
|
|
5
|
+
import {
|
|
6
|
+
t
|
|
7
|
+
} from "./chunk-6ICJICVU.js";
|
|
2
8
|
|
|
3
9
|
// src/commands/human-lint.ts
|
|
4
10
|
import { createHash } from "crypto";
|
|
@@ -6,15 +12,16 @@ import { existsSync } from "fs";
|
|
|
6
12
|
import { readFile } from "fs/promises";
|
|
7
13
|
import { isAbsolute, join, resolve } from "path";
|
|
8
14
|
import { defineCommand } from "citty";
|
|
15
|
+
import { humanLockEntrySchema } from "@fenglimg/fabric-shared";
|
|
9
16
|
var humanLintCommand = defineCommand({
|
|
10
17
|
meta: {
|
|
11
18
|
name: "human-lint",
|
|
12
|
-
description: "
|
|
19
|
+
description: t("cli.human-lint.description")
|
|
13
20
|
},
|
|
14
21
|
args: {
|
|
15
22
|
target: {
|
|
16
23
|
type: "string",
|
|
17
|
-
description: "
|
|
24
|
+
description: t("cli.human-lint.args.target.description"),
|
|
18
25
|
default: process.cwd()
|
|
19
26
|
}
|
|
20
27
|
},
|
|
@@ -60,11 +67,13 @@ var humanLintCommand = defineCommand({
|
|
|
60
67
|
if (violations.length === 0) {
|
|
61
68
|
return;
|
|
62
69
|
}
|
|
63
|
-
writeStderr("
|
|
64
|
-
writeStderr(
|
|
70
|
+
writeStderr(t("cli.human-lint.drift-detected"));
|
|
71
|
+
writeStderr(
|
|
72
|
+
`${padEnd(t("cli.human-lint.table.location"), 32)} ${padEnd(t("cli.human-lint.table.expected"), 18)} ${t("cli.human-lint.table.got")}`
|
|
73
|
+
);
|
|
65
74
|
for (const violation of violations) {
|
|
66
75
|
writeStderr(
|
|
67
|
-
`${violation.location
|
|
76
|
+
`${padEnd(violation.location, 32)} ${padEnd(violation.expected, 18)} ${violation.actual}`
|
|
68
77
|
);
|
|
69
78
|
}
|
|
70
79
|
process.exitCode = 1;
|
|
@@ -81,7 +90,7 @@ function hashLockedContent(content, entry) {
|
|
|
81
90
|
}
|
|
82
91
|
function shortenHash(value) {
|
|
83
92
|
if (value === "missing") {
|
|
84
|
-
return
|
|
93
|
+
return t("cli.shared.missing");
|
|
85
94
|
}
|
|
86
95
|
return value.slice(0, 15);
|
|
87
96
|
}
|
|
@@ -92,5 +101,6 @@ function writeStderr(message) {
|
|
|
92
101
|
|
|
93
102
|
export {
|
|
94
103
|
humanLintCommand,
|
|
95
|
-
human_lint_default
|
|
104
|
+
human_lint_default,
|
|
105
|
+
humanLockEntrySchema
|
|
96
106
|
};
|
package/dist/chunk-P4KVFB2T.js
CHANGED
|
File without changes
|
|
@@ -240,6 +240,7 @@ var CodexTOMLConfigWriter = class {
|
|
|
240
240
|
};
|
|
241
241
|
|
|
242
242
|
// src/config/resolver.ts
|
|
243
|
+
import { clientPathsSchema, fabricConfigSchema } from "@fenglimg/fabric-shared";
|
|
243
244
|
function hasExplicitPath(clientPaths, key) {
|
|
244
245
|
return typeof clientPaths?.[key] === "string" && clientPaths[key].trim().length > 0;
|
|
245
246
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/colors.ts
|
|
4
|
+
import pc from "picocolors";
|
|
5
|
+
import stringWidth from "string-width";
|
|
6
|
+
function isColorEnabled() {
|
|
7
|
+
return !process.env.NO_COLOR && Boolean(process.stdout.isTTY) && Boolean(process.stderr.isTTY);
|
|
8
|
+
}
|
|
9
|
+
function colorize(painter) {
|
|
10
|
+
return (value) => isColorEnabled() ? painter(value) : value;
|
|
11
|
+
}
|
|
12
|
+
var paint = {
|
|
13
|
+
success: colorize(pc.green),
|
|
14
|
+
warn: colorize(pc.yellow),
|
|
15
|
+
error: colorize(pc.red),
|
|
16
|
+
drift: colorize(pc.magenta),
|
|
17
|
+
ai: colorize(pc.blue),
|
|
18
|
+
human: colorize(pc.cyan),
|
|
19
|
+
muted: colorize(pc.dim)
|
|
20
|
+
};
|
|
21
|
+
var symbol = {
|
|
22
|
+
get ok() {
|
|
23
|
+
return isColorEnabled() ? paint.success("\u2713") : "[ok]";
|
|
24
|
+
},
|
|
25
|
+
get warn() {
|
|
26
|
+
return isColorEnabled() ? paint.warn("!") : "[warn]";
|
|
27
|
+
},
|
|
28
|
+
get error() {
|
|
29
|
+
return isColorEnabled() ? paint.error("x") : "[error]";
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
function displayWidth(value) {
|
|
33
|
+
return stringWidth(value);
|
|
34
|
+
}
|
|
35
|
+
function padEnd(value, width, char = " ") {
|
|
36
|
+
const fill = char.length > 0 ? char : " ";
|
|
37
|
+
let result = value;
|
|
38
|
+
while (displayWidth(result) < width) {
|
|
39
|
+
result += fill;
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export {
|
|
45
|
+
paint,
|
|
46
|
+
symbol,
|
|
47
|
+
displayWidth,
|
|
48
|
+
padEnd
|
|
49
|
+
};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
resolveClients
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-VMYPJPKV.js";
|
|
5
|
+
import {
|
|
6
|
+
t
|
|
7
|
+
} from "./chunk-6ICJICVU.js";
|
|
5
8
|
|
|
6
9
|
// src/commands/config.ts
|
|
7
10
|
import { existsSync } from "fs";
|
|
@@ -37,7 +40,7 @@ function parseClientFilter(value) {
|
|
|
37
40
|
const alias = rawClient.trim().toLowerCase();
|
|
38
41
|
const clientKind = CLIENT_ALIASES[alias];
|
|
39
42
|
if (clientKind === void 0) {
|
|
40
|
-
throw new Error(
|
|
43
|
+
throw new Error(t("cli.config.errors.unknown-client", { client: rawClient }));
|
|
41
44
|
}
|
|
42
45
|
clients.add(clientKind);
|
|
43
46
|
}
|
|
@@ -50,7 +53,7 @@ async function loadFabricConfig(workspaceRoot) {
|
|
|
50
53
|
}
|
|
51
54
|
const parsed = JSON.parse(await readFile(configPath, "utf8"));
|
|
52
55
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
53
|
-
throw new Error(
|
|
56
|
+
throw new Error(t("cli.config.errors.expected-object", { path: configPath }));
|
|
54
57
|
}
|
|
55
58
|
return parsed;
|
|
56
59
|
}
|
|
@@ -65,22 +68,22 @@ function writeStderr(message) {
|
|
|
65
68
|
var configCmd = defineCommand({
|
|
66
69
|
meta: {
|
|
67
70
|
name: "config",
|
|
68
|
-
description: "
|
|
71
|
+
description: t("cli.config.description")
|
|
69
72
|
},
|
|
70
73
|
subCommands: {
|
|
71
74
|
install: defineCommand({
|
|
72
75
|
meta: {
|
|
73
76
|
name: "install",
|
|
74
|
-
description: "
|
|
77
|
+
description: t("cli.config.install.description")
|
|
75
78
|
},
|
|
76
79
|
args: {
|
|
77
80
|
clients: {
|
|
78
81
|
type: "string",
|
|
79
|
-
description: "
|
|
82
|
+
description: t("cli.config.install.args.clients.description")
|
|
80
83
|
},
|
|
81
84
|
"dry-run": {
|
|
82
85
|
type: "boolean",
|
|
83
|
-
description: "
|
|
86
|
+
description: t("cli.config.install.args.dry-run.description"),
|
|
84
87
|
default: false
|
|
85
88
|
}
|
|
86
89
|
},
|
|
@@ -93,21 +96,21 @@ var configCmd = defineCommand({
|
|
|
93
96
|
(writer) => selectedClients === null ? true : selectedClients.has(writer.clientKind)
|
|
94
97
|
);
|
|
95
98
|
if (writers.length === 0) {
|
|
96
|
-
writeStderr("
|
|
99
|
+
writeStderr(t("cli.config.install.no-configs"));
|
|
97
100
|
return;
|
|
98
101
|
}
|
|
99
102
|
for (const writer of writers) {
|
|
100
103
|
const configPath = await writer.detect(workspaceRoot);
|
|
101
104
|
if (configPath === null) {
|
|
102
|
-
writeStderr(
|
|
105
|
+
writeStderr(t("cli.config.install.no-config-path", { client: writer.clientKind }));
|
|
103
106
|
continue;
|
|
104
107
|
}
|
|
105
108
|
if (args["dry-run"]) {
|
|
106
|
-
writeStderr(
|
|
109
|
+
writeStderr(t("cli.config.install.dry-run", { client: writer.clientKind, path: configPath }));
|
|
107
110
|
continue;
|
|
108
111
|
}
|
|
109
112
|
await writer.write(serverPath, workspaceRoot);
|
|
110
|
-
writeStderr(
|
|
113
|
+
writeStderr(t("cli.config.install.wrote", { client: writer.clientKind, path: configPath }));
|
|
111
114
|
}
|
|
112
115
|
}
|
|
113
116
|
})
|