@fenglimg/fabric-cli 2.0.1 → 2.1.0-rc.2
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/{chunk-D25XJ4BC.js → chunk-F46ORPOA.js} +23 -0
- package/dist/chunk-HFQVXY6P.js +86 -0
- package/dist/chunk-L4Q55UC4.js +52 -0
- package/dist/chunk-LFIKMVY7.js +27 -0
- package/dist/chunk-RYAFBNES.js +33 -0
- package/dist/chunk-T5RPGCCM.js +40 -0
- package/dist/chunk-WU6GAPKH.js +36 -0
- package/dist/{doctor-EJDSEJSS.js → doctor-QVNPHLJK.js} +111 -1
- package/dist/index.js +12 -4
- package/dist/{install-EKWMFLUU.js → install-2HDO5FTQ.js} +242 -51
- package/dist/scope-explain-2F2R5URO.js +33 -0
- package/dist/status-GLQWLWH6.js +23 -0
- package/dist/store-XTSE5TY6.js +105 -0
- package/dist/sync-BJCWDPNC.js +245 -0
- package/dist/{uninstall-MH7ZIB6M.js → uninstall-TAXSUSKH.js} +14 -5
- package/dist/whoami-B6AEMSEV.js +31 -0
- package/package.json +3 -3
- package/templates/hooks/fabric-hint.cjs +40 -0
- package/templates/hooks/knowledge-hint-broad.cjs +40 -0
- package/templates/hooks/knowledge-hint-narrow.cjs +39 -0
- package/templates/hooks/lib/bindings-snapshot-reader.cjs +81 -0
- package/templates/hooks/lib/cite-contract-reminder.cjs +15 -9
- package/templates/hooks/lib/cite-line-parser.cjs +48 -26
- package/templates/skills/fabric-archive/SKILL.md +4 -0
- package/templates/skills/fabric-import/SKILL.md +4 -0
- package/templates/skills/fabric-review/SKILL.md +4 -0
- package/templates/skills/fabric-sync/SKILL.md +46 -0
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
installMcpClients
|
|
4
|
-
} from "./chunk-BATF4PEJ.js";
|
|
5
2
|
import {
|
|
6
3
|
cleanupDeprecatedSkills,
|
|
7
4
|
installArchiveHintHook,
|
|
@@ -9,6 +6,7 @@ import {
|
|
|
9
6
|
installFabricArchiveSkill,
|
|
10
7
|
installFabricImportSkill,
|
|
11
8
|
installFabricReviewSkill,
|
|
9
|
+
installFabricSyncSkill,
|
|
12
10
|
installHookLibs,
|
|
13
11
|
installKnowledgeHintBroadHook,
|
|
14
12
|
installKnowledgeHintNarrowHook,
|
|
@@ -21,10 +19,7 @@ import {
|
|
|
21
19
|
writeCodexBootstrapManagedBlock,
|
|
22
20
|
writeCursorBootstrapManagedBlock,
|
|
23
21
|
writeFabricAgentsSnapshot
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import {
|
|
26
|
-
detectClientSupports
|
|
27
|
-
} from "./chunk-MF3OTILQ.js";
|
|
22
|
+
} from "./chunk-F46ORPOA.js";
|
|
28
23
|
import {
|
|
29
24
|
displayWidth,
|
|
30
25
|
padEnd,
|
|
@@ -34,16 +29,28 @@ import {
|
|
|
34
29
|
createDebugLogger,
|
|
35
30
|
resolveDevMode
|
|
36
31
|
} from "./chunk-COI5VDFU.js";
|
|
32
|
+
import {
|
|
33
|
+
installMcpClients
|
|
34
|
+
} from "./chunk-BATF4PEJ.js";
|
|
35
|
+
import {
|
|
36
|
+
detectClientSupports
|
|
37
|
+
} from "./chunk-MF3OTILQ.js";
|
|
37
38
|
import {
|
|
38
39
|
t
|
|
39
40
|
} from "./chunk-PWLW3B57.js";
|
|
41
|
+
import {
|
|
42
|
+
globalConfigPath,
|
|
43
|
+
loadGlobalConfig,
|
|
44
|
+
resolveGlobalRoot,
|
|
45
|
+
saveGlobalConfig
|
|
46
|
+
} from "./chunk-RYAFBNES.js";
|
|
40
47
|
|
|
41
48
|
// src/commands/install.ts
|
|
42
|
-
import { randomUUID } from "crypto";
|
|
49
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
43
50
|
import { homedir } from "os";
|
|
44
51
|
import * as childProcess from "child_process";
|
|
45
|
-
import { appendFileSync, existsSync as existsSync4, mkdirSync, readFileSync as readFileSync3, rmSync, statSync as statSync4, writeFileSync } from "fs";
|
|
46
|
-
import { dirname, isAbsolute as isAbsolute3, join as
|
|
52
|
+
import { appendFileSync, existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync3, rmSync as rmSync2, statSync as statSync4, writeFileSync } from "fs";
|
|
53
|
+
import { dirname, isAbsolute as isAbsolute3, join as join6, resolve as resolve3 } from "path";
|
|
47
54
|
import { cancel, confirm, group, intro, isCancel, log, note, outro, select } from "@clack/prompts";
|
|
48
55
|
import { defaultAgentsMetaCounters } from "@fenglimg/fabric-shared";
|
|
49
56
|
import { atomicWriteJson } from "@fenglimg/fabric-shared/node/atomic-write";
|
|
@@ -59,6 +66,7 @@ async function installHooks(target, _options = {}) {
|
|
|
59
66
|
results.push(...await runStep(() => installFabricArchiveSkill(normalizedTarget)));
|
|
60
67
|
results.push(...await runStep(() => installFabricReviewSkill(normalizedTarget)));
|
|
61
68
|
results.push(...await runStep(() => installFabricImportSkill(normalizedTarget)));
|
|
69
|
+
results.push(...await runStep(() => installFabricSyncSkill(normalizedTarget)));
|
|
62
70
|
results.push(...await runStep(() => installSharedSkillLib(normalizedTarget)));
|
|
63
71
|
results.push(...await runStep(() => installArchiveHintHook(normalizedTarget)));
|
|
64
72
|
results.push(...await runStep(() => installKnowledgeHintBroadHook(normalizedTarget)));
|
|
@@ -182,20 +190,190 @@ function assertExistingDirectory(target) {
|
|
|
182
190
|
}
|
|
183
191
|
}
|
|
184
192
|
|
|
193
|
+
// src/install/run-global-install.ts
|
|
194
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
195
|
+
import { randomUUID } from "crypto";
|
|
196
|
+
import { mkdirSync, mkdtempSync, renameSync } from "fs";
|
|
197
|
+
import { tmpdir } from "os";
|
|
198
|
+
import { join as join3 } from "path";
|
|
199
|
+
import { STORES_ROOT_DIR as STORES_ROOT_DIR2, addMountedStore, readStoreIdentity } from "@fenglimg/fabric-shared";
|
|
200
|
+
|
|
201
|
+
// src/store/uid.ts
|
|
202
|
+
import { execFileSync } from "child_process";
|
|
203
|
+
import { createHash } from "crypto";
|
|
204
|
+
function deriveUid() {
|
|
205
|
+
let email = "";
|
|
206
|
+
try {
|
|
207
|
+
email = execFileSync("git", ["config", "user.email"], {
|
|
208
|
+
encoding: "utf8",
|
|
209
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
210
|
+
}).trim();
|
|
211
|
+
} catch {
|
|
212
|
+
email = "";
|
|
213
|
+
}
|
|
214
|
+
if (email === "") {
|
|
215
|
+
return "u-anon";
|
|
216
|
+
}
|
|
217
|
+
const hash = createHash("sha256").update(email.toLowerCase()).digest("hex").slice(0, 12);
|
|
218
|
+
return `u-${hash}`;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// src/install/install-global.ts
|
|
222
|
+
import { rmSync } from "fs";
|
|
223
|
+
import { join as join2 } from "path";
|
|
224
|
+
import {
|
|
225
|
+
STORES_ROOT_DIR,
|
|
226
|
+
globalConfigSchema,
|
|
227
|
+
initStore
|
|
228
|
+
} from "@fenglimg/fabric-shared";
|
|
229
|
+
|
|
230
|
+
// src/install/transaction.ts
|
|
231
|
+
function errorMessage(error) {
|
|
232
|
+
return error instanceof Error ? error.message : String(error);
|
|
233
|
+
}
|
|
234
|
+
async function runInstallTransaction(steps) {
|
|
235
|
+
const receipt = { ok: true, steps: [] };
|
|
236
|
+
const applied = [];
|
|
237
|
+
for (let i = 0; i < steps.length; i++) {
|
|
238
|
+
const step = steps[i];
|
|
239
|
+
try {
|
|
240
|
+
await step.apply();
|
|
241
|
+
applied.push(step);
|
|
242
|
+
receipt.steps.push({ name: step.name, status: "applied" });
|
|
243
|
+
} catch (error) {
|
|
244
|
+
receipt.ok = false;
|
|
245
|
+
receipt.failedStep = step.name;
|
|
246
|
+
receipt.error = errorMessage(error);
|
|
247
|
+
receipt.steps.push({ name: step.name, status: "failed", error: errorMessage(error) });
|
|
248
|
+
for (let j = i + 1; j < steps.length; j++) {
|
|
249
|
+
receipt.steps.push({ name: steps[j].name, status: "skipped" });
|
|
250
|
+
}
|
|
251
|
+
for (const done of [...applied].reverse()) {
|
|
252
|
+
const entry = receipt.steps.find((s) => s.name === done.name);
|
|
253
|
+
try {
|
|
254
|
+
await done.rollback();
|
|
255
|
+
if (entry !== void 0) {
|
|
256
|
+
entry.status = "rolled_back";
|
|
257
|
+
}
|
|
258
|
+
} catch (rollbackError) {
|
|
259
|
+
if (entry !== void 0) {
|
|
260
|
+
entry.status = "rollback_failed";
|
|
261
|
+
entry.error = errorMessage(rollbackError);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return receipt;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return receipt;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// src/install/install-global.ts
|
|
272
|
+
async function installGlobalCore(options) {
|
|
273
|
+
const existing = loadGlobalConfig(options.globalRoot);
|
|
274
|
+
if (existing !== null) {
|
|
275
|
+
return {
|
|
276
|
+
receipt: { ok: true, steps: [{ name: "already-installed", status: "applied" }] },
|
|
277
|
+
config: existing,
|
|
278
|
+
alreadyInstalled: true
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
const alias = options.personalAlias ?? "personal";
|
|
282
|
+
const personalDir = join2(options.globalRoot, STORES_ROOT_DIR, options.personalStoreUuid);
|
|
283
|
+
let config = null;
|
|
284
|
+
const receipt = await runInstallTransaction([
|
|
285
|
+
{
|
|
286
|
+
name: "init-personal-store",
|
|
287
|
+
apply: () => {
|
|
288
|
+
initStore(
|
|
289
|
+
personalDir,
|
|
290
|
+
{
|
|
291
|
+
store_uuid: options.personalStoreUuid,
|
|
292
|
+
created_at: options.now,
|
|
293
|
+
canonical_alias: alias
|
|
294
|
+
},
|
|
295
|
+
{ git: options.git }
|
|
296
|
+
);
|
|
297
|
+
},
|
|
298
|
+
rollback: () => {
|
|
299
|
+
rmSync(personalDir, { recursive: true, force: true });
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
name: "write-global-config",
|
|
304
|
+
apply: () => {
|
|
305
|
+
const next = globalConfigSchema.parse({
|
|
306
|
+
uid: options.uid,
|
|
307
|
+
stores: [{ store_uuid: options.personalStoreUuid, alias, personal: true }]
|
|
308
|
+
});
|
|
309
|
+
saveGlobalConfig(next, options.globalRoot);
|
|
310
|
+
config = next;
|
|
311
|
+
},
|
|
312
|
+
rollback: () => {
|
|
313
|
+
rmSync(globalConfigPath(options.globalRoot), { force: true });
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
]);
|
|
317
|
+
return { receipt, config, alreadyInstalled: false };
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// src/install/run-global-install.ts
|
|
321
|
+
function gitClone(url, dest) {
|
|
322
|
+
execFileSync2("git", ["clone", url, dest], { stdio: ["ignore", "ignore", "pipe"] });
|
|
323
|
+
}
|
|
324
|
+
function mountStoreFromRemote(url, globalRoot) {
|
|
325
|
+
const storesRoot = join3(globalRoot, STORES_ROOT_DIR2);
|
|
326
|
+
mkdirSync(storesRoot, { recursive: true });
|
|
327
|
+
const tmp = mkdtempSync(join3(tmpdir(), "fabric-clone-"));
|
|
328
|
+
const cloneDest = join3(tmp, "store");
|
|
329
|
+
gitClone(url, cloneDest);
|
|
330
|
+
const identity = readStoreIdentity(cloneDest);
|
|
331
|
+
if (identity === null) {
|
|
332
|
+
throw new Error(`cloned store at ${url} has no valid store.json (not a Fabric store)`);
|
|
333
|
+
}
|
|
334
|
+
const finalDir = join3(storesRoot, identity.store_uuid);
|
|
335
|
+
renameSync(cloneDest, finalDir);
|
|
336
|
+
const config = loadGlobalConfig(globalRoot);
|
|
337
|
+
if (config === null) {
|
|
338
|
+
throw new Error("global config missing after install");
|
|
339
|
+
}
|
|
340
|
+
const alias = identity.canonical_alias ?? "team";
|
|
341
|
+
saveGlobalConfig(
|
|
342
|
+
addMountedStore(config, { store_uuid: identity.store_uuid, alias, remote: url }),
|
|
343
|
+
globalRoot
|
|
344
|
+
);
|
|
345
|
+
console.log(`mounted store '${alias}' (${identity.store_uuid}) from ${url}`);
|
|
346
|
+
}
|
|
347
|
+
async function runGlobalInstall(options = {}, globalRoot = resolveGlobalRoot()) {
|
|
348
|
+
const uid = options.uid ?? deriveUid();
|
|
349
|
+
const personalStoreUuid = options.personalStoreUuid ?? randomUUID();
|
|
350
|
+
const now = options.now ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
351
|
+
const result = await installGlobalCore({ globalRoot, uid, personalStoreUuid, now });
|
|
352
|
+
if (!result.receipt.ok) {
|
|
353
|
+
throw new Error(`global install failed at step '${result.receipt.failedStep}': ${result.receipt.error}`);
|
|
354
|
+
}
|
|
355
|
+
console.log(
|
|
356
|
+
result.alreadyInstalled ? "global Fabric already installed" : `installed global Fabric (uid ${uid})`
|
|
357
|
+
);
|
|
358
|
+
if (options.url !== void 0) {
|
|
359
|
+
mountStoreFromRemote(options.url, globalRoot);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
185
363
|
// src/lib/detect-language.ts
|
|
186
364
|
import { existsSync as existsSync2, readdirSync, readFileSync, statSync as statSync2 } from "fs";
|
|
187
|
-
import { join as
|
|
365
|
+
import { join as join4 } from "path";
|
|
188
366
|
function detectExistingLanguage(target) {
|
|
189
367
|
const ZH_CN_RATIO_THRESHOLD = 0.3;
|
|
190
368
|
const samples = [];
|
|
191
|
-
const readmePath =
|
|
369
|
+
const readmePath = join4(target, "README.md");
|
|
192
370
|
if (existsSync2(readmePath)) {
|
|
193
371
|
try {
|
|
194
372
|
samples.push(readFileSync(readmePath, "utf8"));
|
|
195
373
|
} catch {
|
|
196
374
|
}
|
|
197
375
|
}
|
|
198
|
-
const docsDir =
|
|
376
|
+
const docsDir = join4(target, "docs");
|
|
199
377
|
if (existsSync2(docsDir)) {
|
|
200
378
|
try {
|
|
201
379
|
const stat = statSync2(docsDir);
|
|
@@ -204,7 +382,7 @@ function detectExistingLanguage(target) {
|
|
|
204
382
|
if (!entry.isFile()) continue;
|
|
205
383
|
if (!/\.(md|mdx|txt)$/iu.test(entry.name)) continue;
|
|
206
384
|
try {
|
|
207
|
-
samples.push(readFileSync(
|
|
385
|
+
samples.push(readFileSync(join4(docsDir, entry.name), "utf8"));
|
|
208
386
|
} catch {
|
|
209
387
|
}
|
|
210
388
|
}
|
|
@@ -236,10 +414,10 @@ function detectExistingLanguage(target) {
|
|
|
236
414
|
}
|
|
237
415
|
|
|
238
416
|
// src/scanner/forensic.ts
|
|
239
|
-
import { execFileSync } from "child_process";
|
|
417
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
240
418
|
import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync2, statSync as statSync3 } from "fs";
|
|
241
419
|
import { createRequire } from "module";
|
|
242
|
-
import { basename, extname, isAbsolute as isAbsolute2, join as
|
|
420
|
+
import { basename, extname, isAbsolute as isAbsolute2, join as join5, posix, relative, resolve as resolve2, sep } from "path";
|
|
243
421
|
import {
|
|
244
422
|
forensicReportSchema
|
|
245
423
|
} from "@fenglimg/fabric-shared";
|
|
@@ -383,7 +561,7 @@ function buildTopology(root) {
|
|
|
383
561
|
continue;
|
|
384
562
|
}
|
|
385
563
|
for (const entry of readdirSync2(current, { withFileTypes: true })) {
|
|
386
|
-
const absolutePath =
|
|
564
|
+
const absolutePath = join5(current, entry.name);
|
|
387
565
|
const relativePath = toPosixPath(relative(root, absolutePath));
|
|
388
566
|
if (relativePath.length === 0) {
|
|
389
567
|
continue;
|
|
@@ -471,7 +649,7 @@ function getEntryPointReason(relativePath) {
|
|
|
471
649
|
async function buildCodeSamples(target, entryPoints, frameworkKind, topology, packageDependencies) {
|
|
472
650
|
const samples = [];
|
|
473
651
|
for (const entryPoint of entryPoints.slice(0, SAMPLE_LIMIT)) {
|
|
474
|
-
const absolutePath =
|
|
652
|
+
const absolutePath = join5(target, ...entryPoint.path.split("/"));
|
|
475
653
|
const sample = readFirstLines(absolutePath, SAMPLE_LINE_LIMIT);
|
|
476
654
|
const patternAnalysis = await inferPatternHint(entryPoint.path, sample.snippet, {
|
|
477
655
|
frameworkKind,
|
|
@@ -508,7 +686,7 @@ function readFirstLines(path, lineLimit) {
|
|
|
508
686
|
}
|
|
509
687
|
}
|
|
510
688
|
function readPackageDependencies(target) {
|
|
511
|
-
const packageJsonPath =
|
|
689
|
+
const packageJsonPath = join5(target, "package.json");
|
|
512
690
|
if (!existsSync3(packageJsonPath)) {
|
|
513
691
|
return /* @__PURE__ */ new Map();
|
|
514
692
|
}
|
|
@@ -526,7 +704,7 @@ function readPackageDependencies(target) {
|
|
|
526
704
|
}
|
|
527
705
|
function readGitChurnWeight(target, relativePath) {
|
|
528
706
|
try {
|
|
529
|
-
const output =
|
|
707
|
+
const output = execFileSync3("git", ["log", "--follow", "--oneline", "-20", "--", relativePath], {
|
|
530
708
|
cwd: target,
|
|
531
709
|
encoding: "utf8",
|
|
532
710
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -849,8 +1027,8 @@ function scoreFrameworkConfidence(input) {
|
|
|
849
1027
|
return input.configCount > 0 || input.packageCount > 0 ? "MEDIUM" : "LOW";
|
|
850
1028
|
}
|
|
851
1029
|
function readReadmeInfo(target) {
|
|
852
|
-
const readmePath =
|
|
853
|
-
const hasContributing = existsSync3(
|
|
1030
|
+
const readmePath = join5(target, "README.md");
|
|
1031
|
+
const hasContributing = existsSync3(join5(target, "CONTRIBUTING.md"));
|
|
854
1032
|
if (!existsSync3(readmePath)) {
|
|
855
1033
|
return {
|
|
856
1034
|
quality: "missing",
|
|
@@ -1336,7 +1514,7 @@ function buildSkillRecommendations(frameworkKind, topology, readme) {
|
|
|
1336
1514
|
return recommendations;
|
|
1337
1515
|
}
|
|
1338
1516
|
function readProjectName(target) {
|
|
1339
|
-
const packageJsonPath =
|
|
1517
|
+
const packageJsonPath = join5(target, "package.json");
|
|
1340
1518
|
if (existsSync3(packageJsonPath)) {
|
|
1341
1519
|
try {
|
|
1342
1520
|
const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf8"));
|
|
@@ -1350,7 +1528,7 @@ function readProjectName(target) {
|
|
|
1350
1528
|
return basename(target);
|
|
1351
1529
|
}
|
|
1352
1530
|
function getCliVersion() {
|
|
1353
|
-
return true ? "2.0.
|
|
1531
|
+
return true ? "2.1.0-rc.2" : "unknown";
|
|
1354
1532
|
}
|
|
1355
1533
|
function sortRecord(record) {
|
|
1356
1534
|
return Object.fromEntries(Object.entries(record).sort(([left], [right]) => left.localeCompare(right)));
|
|
@@ -1360,7 +1538,7 @@ function toPosixPath(path) {
|
|
|
1360
1538
|
}
|
|
1361
1539
|
|
|
1362
1540
|
// src/commands/install.ts
|
|
1363
|
-
var LOCAL_FABRIC_SERVER_PATH =
|
|
1541
|
+
var LOCAL_FABRIC_SERVER_PATH = join6("node_modules", "@fenglimg", "fabric-server", "dist", "index.js");
|
|
1364
1542
|
var FABRIC_SERVER_PACKAGE = "@fenglimg/fabric-server";
|
|
1365
1543
|
var INIT_WIZARD_GROUP_CANCELLED = /* @__PURE__ */ Symbol("init-wizard-group-cancelled");
|
|
1366
1544
|
var installCommand = defineCommand({
|
|
@@ -1397,6 +1575,15 @@ var installCommand = defineCommand({
|
|
|
1397
1575
|
type: "boolean",
|
|
1398
1576
|
description: t("cli.install.args.force-hooks-only.description"),
|
|
1399
1577
|
default: false
|
|
1578
|
+
},
|
|
1579
|
+
global: {
|
|
1580
|
+
type: "boolean",
|
|
1581
|
+
description: "Set up global Fabric (~/.fabric: uid + personal store + config)",
|
|
1582
|
+
default: false
|
|
1583
|
+
},
|
|
1584
|
+
url: {
|
|
1585
|
+
type: "string",
|
|
1586
|
+
description: "With --global: clone + mount this shared store remote"
|
|
1400
1587
|
}
|
|
1401
1588
|
},
|
|
1402
1589
|
async run({ args }) {
|
|
@@ -1406,7 +1593,7 @@ var installCommand = defineCommand({
|
|
|
1406
1593
|
var install_default = installCommand;
|
|
1407
1594
|
async function runSkillsOnlyRefresh(targetInput) {
|
|
1408
1595
|
const target = normalizeTarget3(targetInput);
|
|
1409
|
-
const metaPath =
|
|
1596
|
+
const metaPath = join6(target, ".fabric", "agents.meta.json");
|
|
1410
1597
|
if (!existsSync4(metaPath)) {
|
|
1411
1598
|
const message = t("cli.install.force-skills-only.uninitialised.message");
|
|
1412
1599
|
const hint = t("cli.install.force-skills-only.uninitialised.hint");
|
|
@@ -1449,7 +1636,7 @@ ${hint}
|
|
|
1449
1636
|
}
|
|
1450
1637
|
async function runHooksOnlyRefresh(targetInput) {
|
|
1451
1638
|
const target = normalizeTarget3(targetInput);
|
|
1452
|
-
const metaPath =
|
|
1639
|
+
const metaPath = join6(target, ".fabric", "agents.meta.json");
|
|
1453
1640
|
if (!existsSync4(metaPath)) {
|
|
1454
1641
|
const message = t("cli.install.force-hooks-only.uninitialised.message");
|
|
1455
1642
|
const hint = t("cli.install.force-hooks-only.uninitialised.hint");
|
|
@@ -1478,6 +1665,10 @@ ${hint}
|
|
|
1478
1665
|
}
|
|
1479
1666
|
async function runInitCommand(args) {
|
|
1480
1667
|
const logger = createDebugLogger(args.debug);
|
|
1668
|
+
if (args.global === true) {
|
|
1669
|
+
await runGlobalInstall({ url: args.url });
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1481
1672
|
const resolution = resolveDevMode(args.target, process.cwd());
|
|
1482
1673
|
if (args["force-skills-only"] === true) {
|
|
1483
1674
|
await runSkillsOnlyRefresh(resolution.target);
|
|
@@ -1516,7 +1707,7 @@ async function runInitCommand(args) {
|
|
|
1516
1707
|
return result;
|
|
1517
1708
|
}
|
|
1518
1709
|
function writeDefaultFabricConfig(fabricDir, targetRoot) {
|
|
1519
|
-
const target =
|
|
1710
|
+
const target = join6(fabricDir, "fabric-config.json");
|
|
1520
1711
|
if (existsSync4(target)) return;
|
|
1521
1712
|
const detectedLanguage = detectExistingLanguage(targetRoot);
|
|
1522
1713
|
const FABRIC_CONFIG_DEFAULTS = {
|
|
@@ -1578,7 +1769,7 @@ function writeDefaultFabricConfig(fabricDir, targetRoot) {
|
|
|
1578
1769
|
// is considered stale by fabric-review. Default 14.
|
|
1579
1770
|
review_stale_pending_days: 14
|
|
1580
1771
|
};
|
|
1581
|
-
|
|
1772
|
+
mkdirSync2(fabricDir, { recursive: true });
|
|
1582
1773
|
writeFileSync(target, JSON.stringify(FABRIC_CONFIG_DEFAULTS, null, 2) + "\n", "utf8");
|
|
1583
1774
|
log.info(
|
|
1584
1775
|
`Detected and fixated fabric_language = ${detectedLanguage}; edit ${target} to override.`
|
|
@@ -1709,14 +1900,14 @@ function resolvePersonalFabricRoot() {
|
|
|
1709
1900
|
}
|
|
1710
1901
|
async function buildInitFabricPlan(target, options) {
|
|
1711
1902
|
assertExistingDirectory3(target);
|
|
1712
|
-
const fabricDir =
|
|
1713
|
-
const agentsMdPath =
|
|
1903
|
+
const fabricDir = join6(target, ".fabric");
|
|
1904
|
+
const agentsMdPath = join6(target, "AGENTS.md");
|
|
1714
1905
|
const agentsMdAction = existsSync4(agentsMdPath) ? "preserved" : "created";
|
|
1715
|
-
const knowledgeDir =
|
|
1716
|
-
const personalKnowledgeDir =
|
|
1717
|
-
const forensicPath =
|
|
1718
|
-
const eventsPath =
|
|
1719
|
-
const metaPath =
|
|
1906
|
+
const knowledgeDir = join6(fabricDir, "knowledge");
|
|
1907
|
+
const personalKnowledgeDir = join6(resolvePersonalFabricRoot(), ".fabric", "knowledge");
|
|
1908
|
+
const forensicPath = join6(fabricDir, "forensic.json");
|
|
1909
|
+
const eventsPath = join6(fabricDir, "events.jsonl");
|
|
1910
|
+
const metaPath = join6(fabricDir, "agents.meta.json");
|
|
1720
1911
|
const replaceFabricDir = shouldReplaceWritableDirectory(fabricDir, options);
|
|
1721
1912
|
const knowledgeDirAction = existsSync4(knowledgeDir) ? "overwritten" : "created";
|
|
1722
1913
|
const metaClassification = classifyFreshPath(metaPath, "structural");
|
|
@@ -1752,23 +1943,23 @@ async function buildInitFabricPlan(target, options) {
|
|
|
1752
1943
|
}
|
|
1753
1944
|
async function executeInitFabricPlan(plan) {
|
|
1754
1945
|
if (plan.replaceFabricDir) {
|
|
1755
|
-
|
|
1946
|
+
rmSync2(plan.fabricDir, { force: true });
|
|
1756
1947
|
}
|
|
1757
|
-
|
|
1948
|
+
mkdirSync2(plan.fabricDir, { recursive: true });
|
|
1758
1949
|
writeDefaultFabricConfig(plan.fabricDir, plan.target);
|
|
1759
|
-
|
|
1950
|
+
mkdirSync2(plan.knowledgeDir, { recursive: true });
|
|
1760
1951
|
for (const sub of KNOWLEDGE_SUBDIRS) {
|
|
1761
|
-
const teamSubDir =
|
|
1762
|
-
|
|
1763
|
-
const teamGitkeep =
|
|
1952
|
+
const teamSubDir = join6(plan.knowledgeDir, sub);
|
|
1953
|
+
mkdirSync2(teamSubDir, { recursive: true });
|
|
1954
|
+
const teamGitkeep = join6(teamSubDir, ".gitkeep");
|
|
1764
1955
|
if (!existsSync4(teamGitkeep)) {
|
|
1765
1956
|
writeFileSync(teamGitkeep, "", "utf8");
|
|
1766
1957
|
}
|
|
1767
1958
|
}
|
|
1768
1959
|
try {
|
|
1769
|
-
|
|
1960
|
+
mkdirSync2(plan.personalKnowledgeDir, { recursive: true });
|
|
1770
1961
|
for (const sub of KNOWLEDGE_SUBDIRS) {
|
|
1771
|
-
|
|
1962
|
+
mkdirSync2(join6(plan.personalKnowledgeDir, sub), { recursive: true });
|
|
1772
1963
|
}
|
|
1773
1964
|
} catch {
|
|
1774
1965
|
}
|
|
@@ -1778,7 +1969,7 @@ async function executeInitFabricPlan(plan) {
|
|
|
1778
1969
|
}
|
|
1779
1970
|
if (plan.eventsState === "missing") {
|
|
1780
1971
|
preparePlannedPath(plan.eventsPath, plan.eventsAction);
|
|
1781
|
-
|
|
1972
|
+
mkdirSync2(dirname(plan.eventsPath), { recursive: true });
|
|
1782
1973
|
writeFileSync(plan.eventsPath, "", "utf8");
|
|
1783
1974
|
}
|
|
1784
1975
|
preparePlannedPath(plan.forensicPath, plan.forensicAction);
|
|
@@ -2050,9 +2241,9 @@ function formatDiffFileState(state) {
|
|
|
2050
2241
|
return t(`cli.install.diff.state.${state}`);
|
|
2051
2242
|
}
|
|
2052
2243
|
function preparePlannedPath(path, action) {
|
|
2053
|
-
|
|
2244
|
+
mkdirSync2(dirname(path), { recursive: true });
|
|
2054
2245
|
if (action === "overwritten" && existsSync4(path)) {
|
|
2055
|
-
|
|
2246
|
+
rmSync2(path, { recursive: true, force: true });
|
|
2056
2247
|
}
|
|
2057
2248
|
}
|
|
2058
2249
|
function createDefaultInitWizardAdapter() {
|
|
@@ -2211,13 +2402,13 @@ function assertExistingDirectory3(target) {
|
|
|
2211
2402
|
}
|
|
2212
2403
|
function detectPackageManager(cwd) {
|
|
2213
2404
|
const workspaceRoot = resolve3(cwd);
|
|
2214
|
-
if (existsSync4(
|
|
2405
|
+
if (existsSync4(join6(workspaceRoot, "pnpm-lock.yaml"))) {
|
|
2215
2406
|
return "pnpm";
|
|
2216
2407
|
}
|
|
2217
|
-
if (existsSync4(
|
|
2408
|
+
if (existsSync4(join6(workspaceRoot, "yarn.lock"))) {
|
|
2218
2409
|
return "yarn";
|
|
2219
2410
|
}
|
|
2220
|
-
if (existsSync4(
|
|
2411
|
+
if (existsSync4(join6(workspaceRoot, "package-lock.json"))) {
|
|
2221
2412
|
return "npm";
|
|
2222
2413
|
}
|
|
2223
2414
|
return "npm";
|
|
@@ -2240,7 +2431,7 @@ function createInitialMeta() {
|
|
|
2240
2431
|
function appendInstallDiffLedgerEvent(eventsPath, payload) {
|
|
2241
2432
|
const event = {
|
|
2242
2433
|
kind: "fabric-event",
|
|
2243
|
-
id: `event:${
|
|
2434
|
+
id: `event:${randomUUID2()}`,
|
|
2244
2435
|
ts: Date.now(),
|
|
2245
2436
|
schema_version: 1,
|
|
2246
2437
|
event_type: "install_diff_applied",
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
scopeExplain
|
|
4
|
+
} from "./chunk-L4Q55UC4.js";
|
|
5
|
+
import "./chunk-LFIKMVY7.js";
|
|
6
|
+
import "./chunk-RYAFBNES.js";
|
|
7
|
+
|
|
8
|
+
// src/commands/scope-explain.ts
|
|
9
|
+
import { defineCommand } from "citty";
|
|
10
|
+
var scope_explain_default = defineCommand({
|
|
11
|
+
meta: {
|
|
12
|
+
name: "scope-explain",
|
|
13
|
+
description: "Explain the resolved read-set and write target for a scope"
|
|
14
|
+
},
|
|
15
|
+
args: {
|
|
16
|
+
scope: {
|
|
17
|
+
type: "positional",
|
|
18
|
+
required: true,
|
|
19
|
+
description: "Scope coordinate (e.g. team, project:x, personal)"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
run({ args }) {
|
|
23
|
+
const result = scopeExplain(process.cwd(), args.scope);
|
|
24
|
+
if (result === null) {
|
|
25
|
+
console.log("no global Fabric config \u2014 run `fabric install --global <url>` first");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
console.log(JSON.stringify(result, null, 2));
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
export {
|
|
32
|
+
scope_explain_default as default
|
|
33
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
projectStatus
|
|
4
|
+
} from "./chunk-T5RPGCCM.js";
|
|
5
|
+
import "./chunk-LFIKMVY7.js";
|
|
6
|
+
import "./chunk-RYAFBNES.js";
|
|
7
|
+
|
|
8
|
+
// src/commands/status.ts
|
|
9
|
+
import { defineCommand } from "citty";
|
|
10
|
+
var status_default = defineCommand({
|
|
11
|
+
meta: { name: "status", description: "Show this project's Fabric store status" },
|
|
12
|
+
run() {
|
|
13
|
+
const status = projectStatus(process.cwd());
|
|
14
|
+
console.log(`uid: ${status.uid ?? "(no global config)"}`);
|
|
15
|
+
console.log(`project_id: ${status.project_id ?? "(not a Fabric project)"}`);
|
|
16
|
+
console.log(`mounted stores: ${status.mounted.length > 0 ? status.mounted.join(", ") : "(none)"}`);
|
|
17
|
+
console.log(`required: ${status.required.length > 0 ? status.required.join(", ") : "(none)"}`);
|
|
18
|
+
console.log(`active write: ${status.active_write_store ?? "(none \u2014 personal scope only)"}`);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
export {
|
|
22
|
+
status_default as default
|
|
23
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
storeAdd,
|
|
4
|
+
storeBind,
|
|
5
|
+
storeExplain,
|
|
6
|
+
storeList,
|
|
7
|
+
storeRemove,
|
|
8
|
+
storeSwitchWrite
|
|
9
|
+
} from "./chunk-HFQVXY6P.js";
|
|
10
|
+
import {
|
|
11
|
+
regenerateBindingsSnapshot
|
|
12
|
+
} from "./chunk-WU6GAPKH.js";
|
|
13
|
+
import "./chunk-L4Q55UC4.js";
|
|
14
|
+
import "./chunk-LFIKMVY7.js";
|
|
15
|
+
import "./chunk-RYAFBNES.js";
|
|
16
|
+
|
|
17
|
+
// src/commands/store.ts
|
|
18
|
+
import { defineCommand } from "citty";
|
|
19
|
+
var listCommand = defineCommand({
|
|
20
|
+
meta: { name: "list", description: "List mounted knowledge stores" },
|
|
21
|
+
run() {
|
|
22
|
+
const stores = storeList();
|
|
23
|
+
if (stores.length === 0) {
|
|
24
|
+
console.log("(no stores mounted)");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
for (const store of stores) {
|
|
28
|
+
console.log(`${store.alias} ${store.store_uuid} ${store.remote ?? "(local-only)"}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
var addCommand = defineCommand({
|
|
33
|
+
meta: { name: "add", description: "Mount a knowledge store into the global registry" },
|
|
34
|
+
args: {
|
|
35
|
+
uuid: { type: "string", required: true, description: "Intrinsic store UUID" },
|
|
36
|
+
alias: { type: "string", required: true, description: "Local alias for this store" },
|
|
37
|
+
remote: { type: "string", description: "Git remote locator (omit for local-only)" }
|
|
38
|
+
},
|
|
39
|
+
run({ args }) {
|
|
40
|
+
const store = args.remote === void 0 ? { store_uuid: args.uuid, alias: args.alias } : { store_uuid: args.uuid, alias: args.alias, remote: args.remote };
|
|
41
|
+
const next = storeAdd(store);
|
|
42
|
+
console.log(`mounted '${args.alias}' (${next.stores.length} store(s) total)`);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
var removeCommand = defineCommand({
|
|
46
|
+
meta: { name: "remove", description: "Detach a store from the registry (does NOT delete it)" },
|
|
47
|
+
args: {
|
|
48
|
+
alias: { type: "positional", required: true, description: "Alias to detach" }
|
|
49
|
+
},
|
|
50
|
+
run({ args }) {
|
|
51
|
+
const { detached } = storeRemove(args.alias);
|
|
52
|
+
console.log(
|
|
53
|
+
detached === null ? `no store aliased '${args.alias}'` : `detached '${args.alias}' \u2014 on-disk store tree left intact (detach \u2260 delete)`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
var explainCommand = defineCommand({
|
|
58
|
+
meta: { name: "explain", description: "Explain how a store alias resolves" },
|
|
59
|
+
args: {
|
|
60
|
+
alias: { type: "positional", required: true, description: "Alias to explain" }
|
|
61
|
+
},
|
|
62
|
+
run({ args }) {
|
|
63
|
+
const explanation = storeExplain(args.alias);
|
|
64
|
+
console.log(
|
|
65
|
+
explanation === null ? `no store aliased '${args.alias}'` : JSON.stringify(explanation, null, 2)
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
var bindCommand = defineCommand({
|
|
70
|
+
meta: { name: "bind", description: "Declare a required store on this project's config" },
|
|
71
|
+
args: {
|
|
72
|
+
id: { type: "positional", required: true, description: "Store alias/UUID to require" },
|
|
73
|
+
remote: { type: "string", description: "Suggested remote for clone onboarding" }
|
|
74
|
+
},
|
|
75
|
+
run({ args }) {
|
|
76
|
+
const entry = args.remote === void 0 ? { id: args.id } : { id: args.id, suggested_remote: args.remote };
|
|
77
|
+
const next = storeBind(process.cwd(), entry);
|
|
78
|
+
console.log(`bound required store '${args.id}' (${next.required_stores?.length ?? 0} required)`);
|
|
79
|
+
regenerateBindingsSnapshot(process.cwd(), { now: (/* @__PURE__ */ new Date()).toISOString() });
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
var switchWriteCommand = defineCommand({
|
|
83
|
+
meta: { name: "switch-write", description: "Set the active write store for non-personal scopes" },
|
|
84
|
+
args: {
|
|
85
|
+
alias: { type: "positional", required: true, description: "Alias of the store to write to" }
|
|
86
|
+
},
|
|
87
|
+
run({ args }) {
|
|
88
|
+
storeSwitchWrite(process.cwd(), args.alias);
|
|
89
|
+
console.log(`active write store set to '${args.alias}' for this project`);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
var store_default = defineCommand({
|
|
93
|
+
meta: { name: "store", description: "Manage mounted Fabric knowledge stores" },
|
|
94
|
+
subCommands: {
|
|
95
|
+
list: listCommand,
|
|
96
|
+
add: addCommand,
|
|
97
|
+
remove: removeCommand,
|
|
98
|
+
explain: explainCommand,
|
|
99
|
+
bind: bindCommand,
|
|
100
|
+
"switch-write": switchWriteCommand
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
export {
|
|
104
|
+
store_default as default
|
|
105
|
+
};
|