@fenglimg/fabric-cli 2.1.0-rc.2 → 2.2.0-rc.10
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 -5
- package/dist/chunk-27HK6H5Y.js +69 -0
- package/dist/{chunk-BATF4PEJ.js → chunk-2KBCTMID.js} +31 -8
- package/dist/chunk-3D7B2UAZ.js +149 -0
- package/dist/{chunk-MF3OTILQ.js → chunk-3IOLS5EK.js} +48 -42
- package/dist/{plan-context-hint-FC6P3WFE.js → chunk-722JU5BP.js} +52 -12
- package/dist/{chunk-F46ORPOA.js → chunk-7ZDXBOOU.js} +271 -166
- package/dist/{doctor-QVNPHLJK.js → chunk-E7HJUU34.js} +248 -72
- package/dist/chunk-EOT63RDH.js +36 -0
- package/dist/chunk-FNHDQTPC.js +16 -0
- package/dist/chunk-HORSMSZL.js +26 -0
- package/dist/chunk-NLNH64A3.js +43 -0
- package/dist/{chunk-WU6GAPKH.js → chunk-PTGQAZEW.js} +12 -4
- package/dist/chunk-QFIVFZRH.js +13 -0
- package/dist/chunk-QPAW6IYT.js +387 -0
- package/dist/{chunk-COI5VDFU.js → chunk-WA3DYGSY.js} +1 -2
- package/dist/{config-XJIPZNUP.js → config-A3LTECAY.js} +4 -3
- package/dist/context-UJCGYOT6.js +117 -0
- package/dist/doctor-MDTZWKBK.js +24 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +167 -16
- package/dist/info-7FKBTMVO.js +139 -0
- package/dist/install-v2-RINEA24K.js +3279 -0
- package/dist/{metrics-ACEQFPDU.js → metrics-HMFH4YHK.js} +22 -9
- package/dist/{onboard-coverage-MFCAEBDO.js → onboard-coverage-XSG77LL3.js} +48 -27
- package/dist/plan-context-hint-5TNGH3R4.js +12 -0
- package/dist/scope-explain-HLJZ2M33.js +48 -0
- package/dist/status-4R3TM4FJ.js +37 -0
- package/dist/store-HOCORVL3.js +563 -0
- package/dist/sync-DT5UJMMR.js +418 -0
- package/dist/{uninstall-TAXSUSKH.js → uninstall-IFN2KYBK.js} +128 -140
- package/dist/whoami-ITGEFWH4.js +49 -0
- package/package.json +7 -5
- package/templates/hooks/cite-policy-evict.cjs +412 -160
- package/templates/hooks/configs/README.md +14 -27
- package/templates/hooks/configs/claude-code.json +17 -2
- package/templates/hooks/configs/codex-hooks.json +15 -3
- package/templates/hooks/fabric-hint.cjs +573 -180
- package/templates/hooks/knowledge-hint-broad.cjs +648 -190
- package/templates/hooks/knowledge-hint-narrow.cjs +123 -77
- package/templates/hooks/lib/banner-i18n.cjs +31 -0
- package/templates/hooks/lib/bindings-snapshot-reader.cjs +118 -7
- package/templates/hooks/lib/cite-line-parser.cjs +12 -20
- package/templates/hooks/lib/client-adapter.cjs +66 -7
- package/templates/hooks/lib/injection-log.cjs +91 -0
- package/templates/hooks/lib/nudge-policy.cjs +117 -0
- package/templates/hooks/lib/state-store.cjs +90 -11
- package/templates/hooks/post-tooluse-mutation.cjs +386 -0
- package/templates/hooks/session-end-marker.cjs +140 -0
- package/templates/skills/fabric/SKILL.md +100 -0
- package/templates/skills/fabric-archive/SKILL.md +35 -24
- package/templates/skills/fabric-archive/ref/dry-run-scope.md +1 -1
- package/templates/skills/fabric-archive/ref/i18n-policy.md +2 -3
- package/templates/skills/fabric-archive/ref/phase-1-5-onboard.md +2 -3
- package/templates/skills/fabric-archive/ref/phase-1-cross-session.md +1 -1
- package/templates/skills/fabric-archive/ref/phase-2-5-viability.md +1 -1
- package/templates/skills/fabric-archive/ref/phase-3-6-related-edges.md +18 -0
- package/templates/skills/fabric-archive/ref/phase-3-7-semantic-scope.md +47 -0
- package/templates/skills/fabric-audit/SKILL.md +63 -0
- package/templates/skills/fabric-connect/SKILL.md +48 -0
- package/templates/skills/fabric-import/SKILL.md +7 -7
- package/templates/skills/fabric-import/ref/i18n-policy.md +2 -3
- package/templates/skills/fabric-import/ref/state-recovery.md +1 -2
- package/templates/skills/fabric-review/SKILL.md +16 -5
- package/templates/skills/fabric-review/ref/cite-contract.md +56 -0
- package/templates/skills/fabric-review/ref/i18n-policy.md +2 -3
- package/templates/skills/fabric-review/ref/output-contract.md +1 -1
- package/templates/skills/fabric-review/ref/per-mode-flows.md +2 -2
- package/templates/skills/fabric-review/ref/worked-examples.md +1 -1
- package/templates/skills/fabric-store/SKILL.md +44 -0
- package/templates/skills/fabric-sync/SKILL.md +1 -1
- package/templates/skills/lib/shared-policy.md +2 -2
- package/dist/chunk-HFQVXY6P.js +0 -86
- package/dist/chunk-L4Q55UC4.js +0 -52
- package/dist/chunk-LFIKMVY7.js +0 -27
- package/dist/chunk-PWLW3B57.js +0 -18
- package/dist/chunk-RYAFBNES.js +0 -33
- package/dist/chunk-T5RPGCCM.js +0 -40
- package/dist/chunk-WWNXR34K.js +0 -49
- package/dist/install-2HDO5FTQ.js +0 -2683
- package/dist/scope-explain-2F2R5URO.js +0 -33
- package/dist/status-GLQWLWH6.js +0 -23
- package/dist/store-XTSE5TY6.js +0 -105
- package/dist/sync-BJCWDPNC.js +0 -245
- package/dist/whoami-B6AEMSEV.js +0 -31
- package/templates/hooks/configs/cursor-hooks.json +0 -18
- package/templates/hooks/lib/cite-contract-reminder.cjs +0 -179
- package/templates/hooks/lib/summary-fallback.cjs +0 -210
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from "./chunk-
|
|
3
|
+
ensureStoreProjectBinding,
|
|
4
|
+
migrateRootConfig
|
|
5
|
+
} from "./chunk-3D7B2UAZ.js";
|
|
6
6
|
import {
|
|
7
7
|
resolveDevMode
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-WA3DYGSY.js";
|
|
9
9
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from "./chunk-
|
|
10
|
+
paint,
|
|
11
|
+
symbol
|
|
12
|
+
} from "./chunk-NLNH64A3.js";
|
|
13
13
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
detectAliasLinkDrift,
|
|
15
|
+
missingRequiredStores,
|
|
16
|
+
syncStoreAliasLinks,
|
|
17
|
+
unboundAvailableStores
|
|
18
|
+
} from "./chunk-QPAW6IYT.js";
|
|
16
19
|
import {
|
|
17
20
|
loadProjectConfig
|
|
18
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-QFIVFZRH.js";
|
|
19
22
|
import {
|
|
20
23
|
loadGlobalConfig,
|
|
21
24
|
resolveGlobalRoot
|
|
22
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-FNHDQTPC.js";
|
|
26
|
+
import {
|
|
27
|
+
getDoctorTranslator,
|
|
28
|
+
t
|
|
29
|
+
} from "./chunk-HORSMSZL.js";
|
|
23
30
|
|
|
24
31
|
// src/commands/doctor.ts
|
|
25
32
|
import { confirm, isCancel } from "@clack/prompts";
|
|
@@ -32,12 +39,28 @@ import {
|
|
|
32
39
|
runDoctorCiteCoverage,
|
|
33
40
|
runDoctorFix,
|
|
34
41
|
runDoctorHistoryAll,
|
|
35
|
-
runDoctorReport
|
|
42
|
+
runDoctorReport,
|
|
43
|
+
runDoctorConflictLint
|
|
36
44
|
} from "@fenglimg/fabric-server";
|
|
37
45
|
|
|
46
|
+
// src/install/backfill-unbound-project.ts
|
|
47
|
+
import { detectUnboundProject } from "@fenglimg/fabric-server";
|
|
48
|
+
async function backfillUnboundProject(projectRoot, globalRoot = resolveGlobalRoot()) {
|
|
49
|
+
const violation = detectUnboundProject(projectRoot);
|
|
50
|
+
if (violation === null) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
const result = await ensureStoreProjectBinding(projectRoot, violation.alias, { globalRoot });
|
|
54
|
+
return {
|
|
55
|
+
alias: violation.alias,
|
|
56
|
+
project_id: result.project_id,
|
|
57
|
+
active_project: result.active_project
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
38
61
|
// src/store/doctor-checks.ts
|
|
39
62
|
import { join } from "path";
|
|
40
|
-
import { findStoreExecutableViolations,
|
|
63
|
+
import { findStoreExecutableViolations, storeRelativePathForMount } from "@fenglimg/fabric-shared";
|
|
41
64
|
function storeDoctorChecks(projectRoot, globalRoot = resolveGlobalRoot()) {
|
|
42
65
|
const diagnostics = [];
|
|
43
66
|
const global = loadGlobalConfig(globalRoot);
|
|
@@ -57,6 +80,23 @@ function storeDoctorChecks(projectRoot, globalRoot = resolveGlobalRoot()) {
|
|
|
57
80
|
message: `required store '${missing.id}' is not mounted; run \`fabric store add\``
|
|
58
81
|
});
|
|
59
82
|
}
|
|
83
|
+
for (const store of unboundAvailableStores(projectRoot, globalRoot)) {
|
|
84
|
+
diagnostics.push({
|
|
85
|
+
code: "unbound_available_store",
|
|
86
|
+
severity: "info",
|
|
87
|
+
ref: store.alias,
|
|
88
|
+
message: `store '${store.alias}' is mounted but not bound to this project; run \`fabric store bind ${store.alias}\` to read its knowledge here (then \`fabric store switch-write ${store.alias}\` to write team knowledge into it)`
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
const aliasDrift = detectAliasLinkDrift(globalRoot);
|
|
92
|
+
if (aliasDrift.length > 0) {
|
|
93
|
+
diagnostics.push({
|
|
94
|
+
code: "store_alias_link_drift",
|
|
95
|
+
severity: "info",
|
|
96
|
+
ref: aliasDrift.join(", "),
|
|
97
|
+
message: `by-alias readability link(s) out of sync for ${aliasDrift.join(", ")}; run \`fabric doctor --fix\` to repair ~/.fabric/stores/by-alias/`
|
|
98
|
+
});
|
|
99
|
+
}
|
|
60
100
|
for (const store of global.stores) {
|
|
61
101
|
if (store.remote === void 0 && store.personal !== true) {
|
|
62
102
|
diagnostics.push({
|
|
@@ -66,7 +106,7 @@ function storeDoctorChecks(projectRoot, globalRoot = resolveGlobalRoot()) {
|
|
|
66
106
|
message: `store '${store.alias}' is local-only; add a git remote to back it up`
|
|
67
107
|
});
|
|
68
108
|
}
|
|
69
|
-
const violations = findStoreExecutableViolations(join(globalRoot,
|
|
109
|
+
const violations = findStoreExecutableViolations(join(globalRoot, storeRelativePathForMount(store)));
|
|
70
110
|
if (violations.length > 0) {
|
|
71
111
|
diagnostics.push({
|
|
72
112
|
code: "executable_in_store",
|
|
@@ -82,8 +122,6 @@ function storeDoctorChecks(projectRoot, globalRoot = resolveGlobalRoot()) {
|
|
|
82
122
|
// src/commands/doctor.ts
|
|
83
123
|
import { buildDebugBundle } from "@fenglimg/fabric-shared";
|
|
84
124
|
var FIX_KNOWLEDGE_CODE_LABELS = {
|
|
85
|
-
knowledge_orphan_demote_required: "demote (maturity)",
|
|
86
|
-
knowledge_stale_archive_required: "archive (git mv)",
|
|
87
125
|
knowledge_pending_auto_archive: "archive (git mv, pending)",
|
|
88
126
|
knowledge_index_drift: "counter bump (agents.meta)",
|
|
89
127
|
knowledge_session_hints_stale: "cache delete"
|
|
@@ -114,40 +152,28 @@ var doctorCommand = defineCommand({
|
|
|
114
152
|
description: t("cli.doctor.args.json.description"),
|
|
115
153
|
default: false
|
|
116
154
|
},
|
|
117
|
-
strict: {
|
|
118
|
-
type: "boolean",
|
|
119
|
-
description: t("cli.doctor.args.strict.description"),
|
|
120
|
-
default: false
|
|
121
|
-
},
|
|
122
155
|
// v2.1.0-rc.1 P6 (S40): emit a redacted diagnostic bundle (config + store
|
|
123
156
|
// diagnostics; events excluded by default). Every string is secret-redacted
|
|
124
157
|
// so the bundle is safe to paste into a bug report. Read-only.
|
|
158
|
+
// EPIC-009: hidden flag (internal debug tool).
|
|
125
159
|
"debug-bundle": {
|
|
126
160
|
type: "boolean",
|
|
127
161
|
description: "Emit a redacted diagnostic bundle (config + store health) for bug reports",
|
|
128
162
|
default: false
|
|
129
163
|
},
|
|
130
|
-
//
|
|
131
|
-
// non-tty invocation that wants to run --fix-knowledge without setting
|
|
132
|
-
// FABRIC_NONINTERACTIVE=1 in the environment.
|
|
164
|
+
// EPIC-009: hidden flag (CI automation).
|
|
133
165
|
yes: {
|
|
134
166
|
type: "boolean",
|
|
135
167
|
description: t("cli.doctor.args.yes.description"),
|
|
136
168
|
default: false
|
|
137
169
|
},
|
|
138
|
-
//
|
|
139
|
-
// default the renderer folds remediation strings that target Fabric
|
|
140
|
-
// contributors (edit `packages/cli/templates/...`, interpret G1-G5
|
|
141
|
-
// cite-goodhart codes, etc.) since npm end users have no actionable
|
|
142
|
-
// lever for them. --verbose shows them.
|
|
170
|
+
// EPIC-009: hidden flag (advanced output).
|
|
143
171
|
verbose: {
|
|
144
172
|
type: "boolean",
|
|
145
173
|
description: t("cli.doctor.args.verbose.description"),
|
|
146
174
|
default: false
|
|
147
175
|
},
|
|
148
|
-
//
|
|
149
|
-
// inspections entirely — different output surface. Mutually exclusive
|
|
150
|
-
// with --fix / --fix-knowledge (enforced in run()).
|
|
176
|
+
// EPIC-009: hidden flags (report surfaces).
|
|
151
177
|
"cite-coverage": {
|
|
152
178
|
type: "boolean",
|
|
153
179
|
description: t("cli.doctor.args.cite-coverage.description"),
|
|
@@ -162,20 +188,14 @@ var doctorCommand = defineCommand({
|
|
|
162
188
|
type: "string",
|
|
163
189
|
description: t("cli.doctor.args.client.description"),
|
|
164
190
|
default: "all",
|
|
165
|
-
valueHint: "cc|codex|
|
|
191
|
+
valueHint: "cc|codex|all"
|
|
166
192
|
},
|
|
167
|
-
// v2.0.0-rc.24 TASK-10: --layer filter for the cite contract audit. Pairs
|
|
168
|
-
// with --cite-coverage. Validated against {'team','personal','all'} at
|
|
169
|
-
// command entry; rejects 'both' (rc.20 plan-context vocabulary) explicitly.
|
|
170
193
|
layer: {
|
|
171
194
|
type: "string",
|
|
172
195
|
description: t("cli.doctor.args.layer.description"),
|
|
173
196
|
default: "all",
|
|
174
197
|
valueHint: "team|personal|all"
|
|
175
198
|
},
|
|
176
|
-
// rc.23 TASK-007 (a-C2): description-grade back-fill flag set. Read-side
|
|
177
|
-
// by default; `--auto` flips the writer arm on. Mutually exclusive with
|
|
178
|
-
// --fix / --fix-knowledge / --cite-coverage (different mutation surfaces).
|
|
179
199
|
"enrich-descriptions": {
|
|
180
200
|
type: "boolean",
|
|
181
201
|
description: t("cli.doctor.args.enrich-descriptions.description"),
|
|
@@ -191,23 +211,31 @@ var doctorCommand = defineCommand({
|
|
|
191
211
|
description: t("cli.doctor.args.dry-run.description"),
|
|
192
212
|
default: false
|
|
193
213
|
},
|
|
194
|
-
// v2.0.0-rc.25 TASK-10: --archive-history flag (parallel to rc.20
|
|
195
|
-
// --cite-coverage). Read-only; reads session_archive_attempted events
|
|
196
|
-
// and renders a per-session table. Pairs with the shared `--since` flag.
|
|
197
214
|
"archive-history": {
|
|
198
215
|
type: "boolean",
|
|
199
216
|
description: t("cli.doctor.args.archive-history.description"),
|
|
200
217
|
default: false
|
|
201
218
|
},
|
|
202
|
-
// rc.37 NEW-33: unified history view across archive / fix / all surfaces.
|
|
203
|
-
// Mode = `archive | fix | all` (the `archive` mode delegates to the
|
|
204
|
-
// existing runDoctorArchiveHistory; `fix` aggregates doctor_run events;
|
|
205
|
-
// `all` rolls up both into a per-day count table). Read-only; mutex
|
|
206
|
-
// with the mutation arms.
|
|
207
219
|
history: {
|
|
208
220
|
type: "string",
|
|
209
221
|
description: t("cli.doctor.args.history.description"),
|
|
210
222
|
valueHint: "archive|fix|all"
|
|
223
|
+
},
|
|
224
|
+
"lint-conflicts": {
|
|
225
|
+
type: "boolean",
|
|
226
|
+
description: t("cli.doctor.args.lint-conflicts.description"),
|
|
227
|
+
default: false
|
|
228
|
+
},
|
|
229
|
+
deep: {
|
|
230
|
+
type: "boolean",
|
|
231
|
+
description: t("cli.doctor.args.deep.description"),
|
|
232
|
+
default: false
|
|
233
|
+
},
|
|
234
|
+
// EPIC-009: hidden flag (strict mode for CI).
|
|
235
|
+
strict: {
|
|
236
|
+
type: "boolean",
|
|
237
|
+
description: t("cli.doctor.args.strict.description"),
|
|
238
|
+
default: false
|
|
211
239
|
}
|
|
212
240
|
},
|
|
213
241
|
async run({ args }) {
|
|
@@ -362,6 +390,22 @@ var doctorCommand = defineCommand({
|
|
|
362
390
|
renderCiteCoverageReport(report2, args.json === true, dt);
|
|
363
391
|
return;
|
|
364
392
|
}
|
|
393
|
+
if (args["lint-conflicts"] === true) {
|
|
394
|
+
if (fix || fixKnowledge || citeCoverage) {
|
|
395
|
+
writeStderr(dt("cli.doctor.errors.lint-conflicts-mutex"));
|
|
396
|
+
process.exitCode = 1;
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
const report2 = await runDoctorConflictLint(resolution.target, {
|
|
400
|
+
deep: args.deep === true
|
|
401
|
+
});
|
|
402
|
+
if (args.json === true) {
|
|
403
|
+
writeStdout(JSON.stringify(report2, null, 2));
|
|
404
|
+
} else {
|
|
405
|
+
renderConflictLintReport(report2, args.deep === true, dt);
|
|
406
|
+
}
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
365
409
|
if (fixKnowledge && fix) {
|
|
366
410
|
writeStderr(dt("cli.doctor.errors.fix-knowledge-fix-mutually-exclusive"));
|
|
367
411
|
process.exitCode = 1;
|
|
@@ -369,33 +413,45 @@ var doctorCommand = defineCommand({
|
|
|
369
413
|
}
|
|
370
414
|
let fixKnowledgeReport = null;
|
|
371
415
|
let fixReport = null;
|
|
416
|
+
let unboundProjectFix = null;
|
|
417
|
+
let rootConfigMigration = null;
|
|
372
418
|
let report;
|
|
373
419
|
if (fixKnowledge) {
|
|
374
420
|
const preReport = await runDoctorReport(resolution.target);
|
|
375
421
|
const plan = computeFixKnowledgePlan(preReport);
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
422
|
+
if (args["dry-run"] === true) {
|
|
423
|
+
if (plan.totalCount > 0) {
|
|
424
|
+
renderFixKnowledgePlan(plan);
|
|
425
|
+
}
|
|
426
|
+
report = preReport;
|
|
379
427
|
} else {
|
|
380
|
-
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
plan
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
428
|
+
const yesFlag = args.yes === true;
|
|
429
|
+
const envBypass = process.env.FABRIC_NONINTERACTIVE === "1";
|
|
430
|
+
if (plan.totalCount === 0) {
|
|
431
|
+
} else {
|
|
432
|
+
renderFixKnowledgePlan(plan);
|
|
433
|
+
const decision = await resolveFixKnowledgeConsent({
|
|
434
|
+
yesFlag,
|
|
435
|
+
envBypass,
|
|
436
|
+
plan
|
|
437
|
+
});
|
|
438
|
+
if (decision === "abort") {
|
|
439
|
+
process.exitCode = 1;
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
389
442
|
}
|
|
443
|
+
fixKnowledgeReport = await runDoctorFixKnowledge(resolution.target);
|
|
444
|
+
report = fixKnowledgeReport.report;
|
|
390
445
|
}
|
|
391
|
-
fixKnowledgeReport = await runDoctorFixKnowledge(resolution.target);
|
|
392
|
-
report = fixKnowledgeReport.report;
|
|
393
446
|
} else if (fix) {
|
|
394
447
|
if (args["dry-run"] === true) {
|
|
395
448
|
report = await runDoctorReport(resolution.target);
|
|
396
449
|
} else {
|
|
450
|
+
rootConfigMigration = migrateRootConfig(resolution.target);
|
|
451
|
+
unboundProjectFix = await backfillUnboundProject(resolution.target);
|
|
397
452
|
fixReport = await runDoctorFix(resolution.target);
|
|
398
453
|
report = fixReport.report;
|
|
454
|
+
syncStoreAliasLinks();
|
|
399
455
|
}
|
|
400
456
|
} else {
|
|
401
457
|
report = await runDoctorReport(resolution.target);
|
|
@@ -404,7 +460,12 @@ var doctorCommand = defineCommand({
|
|
|
404
460
|
if (args.json === true) {
|
|
405
461
|
writeStdout(
|
|
406
462
|
JSON.stringify(
|
|
407
|
-
{
|
|
463
|
+
{
|
|
464
|
+
...fixKnowledgeReport ?? fixReport ?? report,
|
|
465
|
+
store_diagnostics: storeDiagnostics,
|
|
466
|
+
...unboundProjectFix === null ? {} : { unbound_project_fix: unboundProjectFix },
|
|
467
|
+
...rootConfigMigration?.migrated === true ? { root_config_migration: rootConfigMigration } : {}
|
|
468
|
+
},
|
|
408
469
|
null,
|
|
409
470
|
2
|
|
410
471
|
)
|
|
@@ -418,7 +479,20 @@ var doctorCommand = defineCommand({
|
|
|
418
479
|
renderFixKnowledgeMutations(fixKnowledgeReport, dt);
|
|
419
480
|
} else if (fixReport !== null) {
|
|
420
481
|
writeStdout(fixReport.message);
|
|
421
|
-
|
|
482
|
+
if (unboundProjectFix !== null) {
|
|
483
|
+
writeStdout(
|
|
484
|
+
dt("cli.doctor.unbound-project-backfilled", {
|
|
485
|
+
alias: unboundProjectFix.alias,
|
|
486
|
+
project: unboundProjectFix.active_project
|
|
487
|
+
})
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
if (rootConfigMigration?.migrated === true) {
|
|
491
|
+
writeStdout(
|
|
492
|
+
`config: migrated legacy root fabric.config.json \u2192 .fabric/fabric-config.json${rootConfigMigration.mergedKeys.length > 0 ? ` (merged: ${rootConfigMigration.mergedKeys.join(", ")})` : ""}`
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
} else if ((fix || fixKnowledge) && args["dry-run"] === true) {
|
|
422
496
|
writeStdout(dt("cli.doctor.fix-dry-run-banner"));
|
|
423
497
|
}
|
|
424
498
|
renderHumanReport(report, dt, args.verbose === true);
|
|
@@ -447,8 +521,11 @@ var doctorCommand = defineCommand({
|
|
|
447
521
|
var doctor_default = doctorCommand;
|
|
448
522
|
function renderHumanReport(report, dt, verbose) {
|
|
449
523
|
writeStdout(`${renderStatus(report.status)} ${paint.ai("fabric doctor")} ${paint.human(report.summary.target)}`);
|
|
450
|
-
renderTldrHeader(report);
|
|
524
|
+
renderTldrHeader(report, dt, verbose);
|
|
451
525
|
for (const check of report.checks) {
|
|
526
|
+
if (!verbose && check.status === "ok") {
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
452
529
|
writeStdout(`${renderStatus(check.status)} ${check.name}: ${check.message}`);
|
|
453
530
|
}
|
|
454
531
|
const opts = { verbose, dt };
|
|
@@ -471,7 +548,7 @@ function renderStoreDiagnostics(diagnostics) {
|
|
|
471
548
|
writeStdout("");
|
|
472
549
|
writeStdout(paint.ai("store health"));
|
|
473
550
|
for (const diagnostic of diagnostics) {
|
|
474
|
-
const mark = diagnostic.severity === "warn" ? symbol.warn : "[info]";
|
|
551
|
+
const mark = diagnostic.severity === "error" ? symbol.error : diagnostic.severity === "warn" ? symbol.warn : "[info]";
|
|
475
552
|
const ref = diagnostic.ref === void 0 ? "" : ` [${diagnostic.ref}]`;
|
|
476
553
|
writeStdout(`${mark}${ref} ${diagnostic.message}`);
|
|
477
554
|
}
|
|
@@ -520,16 +597,16 @@ function writeIssueSection(title, issues, options) {
|
|
|
520
597
|
}
|
|
521
598
|
}
|
|
522
599
|
}
|
|
523
|
-
function renderTldrHeader(report) {
|
|
600
|
+
function renderTldrHeader(report, dt, verbose) {
|
|
524
601
|
const ranked = [];
|
|
525
602
|
for (const issue of report.fixable_errors) {
|
|
526
|
-
ranked.push({ severity: "fixable", code: issue.code, message: issue.message });
|
|
603
|
+
ranked.push({ severity: "fixable", code: issue.code, message: issue.message, actionHint: issue.actionHint, audience: issue.audience });
|
|
527
604
|
}
|
|
528
605
|
for (const issue of report.manual_errors) {
|
|
529
|
-
ranked.push({ severity: "manual", code: issue.code, message: issue.message });
|
|
606
|
+
ranked.push({ severity: "manual", code: issue.code, message: issue.message, actionHint: issue.actionHint, audience: issue.audience });
|
|
530
607
|
}
|
|
531
608
|
for (const issue of report.warnings) {
|
|
532
|
-
ranked.push({ severity: "warn", code: issue.code, message: issue.message });
|
|
609
|
+
ranked.push({ severity: "warn", code: issue.code, message: issue.message, actionHint: issue.actionHint, audience: issue.audience });
|
|
533
610
|
}
|
|
534
611
|
if (ranked.length === 0) {
|
|
535
612
|
writeStdout(`${symbol.ok} TL;DR: all 48 checks green \u2014 nothing to fix.`);
|
|
@@ -543,6 +620,11 @@ function renderTldrHeader(report) {
|
|
|
543
620
|
const marker = item.severity === "fixable" ? symbol.error : item.severity === "manual" ? symbol.error : symbol.warn;
|
|
544
621
|
const truncated = item.message.length > 140 ? `${item.message.slice(0, 137)}...` : item.message;
|
|
545
622
|
writeStdout(` ${marker} ${item.code}: ${truncated}`);
|
|
623
|
+
if (item.actionHint !== void 0 && item.actionHint.length > 0) {
|
|
624
|
+
writeStdout(
|
|
625
|
+
item.audience === "maintainer" && !verbose ? ` \u2192 ${dt("doctor.maintainer-hint-folded")}` : ` \u2192 ${item.actionHint}`
|
|
626
|
+
);
|
|
627
|
+
}
|
|
546
628
|
}
|
|
547
629
|
}
|
|
548
630
|
function renderStatus(status) {
|
|
@@ -646,7 +728,6 @@ async function resolveFixKnowledgeConsent(options) {
|
|
|
646
728
|
var CITE_COVERAGE_CLIENT_FILTERS = /* @__PURE__ */ new Set([
|
|
647
729
|
"cc",
|
|
648
730
|
"codex",
|
|
649
|
-
"cursor",
|
|
650
731
|
"all"
|
|
651
732
|
]);
|
|
652
733
|
function isValidClientFilter(input) {
|
|
@@ -689,10 +770,42 @@ function renderCiteCoverageReport(report, jsonMode, dt) {
|
|
|
689
770
|
const complianceRate = report.metrics.cite_compliance_rate;
|
|
690
771
|
const complianceStr = complianceRate === null || complianceRate === void 0 ? dt("doctor.cite.metric.complianceNA") : `${(complianceRate * 100).toFixed(1)}% (${report.metrics.compliant_cites ?? 0}/${(report.metrics.compliant_cites ?? 0) + (report.metrics.noncompliant_cites ?? 0)})`;
|
|
691
772
|
lines.push(` ${dt("doctor.cite.metric.complianceRate")}: ${complianceStr}`);
|
|
773
|
+
const recallRate = report.metrics.recall_coverage_rate;
|
|
774
|
+
const recallStr = recallRate === null || recallRate === void 0 ? dt("doctor.cite.metric.recallCoverageNA") : `${(recallRate * 100).toFixed(1)}% (${report.metrics.recall_backed_edits ?? 0}/${report.metrics.edits_touched})`;
|
|
775
|
+
lines.push(` ${dt("doctor.cite.metric.recallCoverage")}: ${recallStr}`);
|
|
692
776
|
const uncorrelatable = report.metrics.uncorrelatable_edits ?? 0;
|
|
693
777
|
if (uncorrelatable > 0) {
|
|
694
778
|
lines.push(` ${dt("doctor.cite.metric.uncorrelatableEdits")}: ${uncorrelatable}`);
|
|
695
779
|
}
|
|
780
|
+
if (report.metrics.exposed_and_mutated !== void 0) {
|
|
781
|
+
lines.push(
|
|
782
|
+
` ${dt("doctor.cite.metric.exposedAndMutated")}: ${report.metrics.exposed_and_mutated.count}`
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
if (report.metrics.mutations_observed !== void 0) {
|
|
786
|
+
lines.push(
|
|
787
|
+
` ${dt("doctor.cite.metric.mutationsObserved")}: ${report.metrics.mutations_observed.count}`
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
if (report.metrics.mutation_pool !== void 0) {
|
|
791
|
+
lines.push(
|
|
792
|
+
` ${dt("doctor.cite.metric.mutationPool")}: ${report.metrics.mutation_pool.attributed} / ${report.metrics.mutation_pool.unattributed_workspace_dirty} (attributed / unattributed_workspace_dirty)`
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
if (report.metrics.sessions_closed !== void 0) {
|
|
796
|
+
lines.push(
|
|
797
|
+
` ${dt("doctor.cite.metric.sessionsClosed")}: ${report.metrics.sessions_closed.count}`
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
if (report.metrics.by_store !== void 0) {
|
|
801
|
+
const storeKeys = Object.keys(report.metrics.by_store).sort();
|
|
802
|
+
if (storeKeys.length > 0) {
|
|
803
|
+
lines.push(` ${dt("doctor.cite.metric.byStore")}:`);
|
|
804
|
+
for (const store of storeKeys) {
|
|
805
|
+
lines.push(` ${store}: ${report.metrics.by_store[store].qualifying_cites}`);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
}
|
|
696
809
|
if (report.per_client !== void 0 && Object.keys(report.per_client).length > 1) {
|
|
697
810
|
lines.push("");
|
|
698
811
|
lines.push(`### ${dt("doctor.cite.section.perClient")}`);
|
|
@@ -794,6 +907,38 @@ function appendContractSection(lines, report, dt) {
|
|
|
794
907
|
);
|
|
795
908
|
}
|
|
796
909
|
}
|
|
910
|
+
function renderConflictLintReport(report, deepRequested, dt) {
|
|
911
|
+
const lines = [];
|
|
912
|
+
lines.push(dt("doctor.conflict.header"));
|
|
913
|
+
lines.push("");
|
|
914
|
+
if (report.candidate_count === 0) {
|
|
915
|
+
lines.push(` ${symbol.ok} ${dt("doctor.conflict.none")}`);
|
|
916
|
+
writeStdout(lines.join("\n"));
|
|
917
|
+
return;
|
|
918
|
+
}
|
|
919
|
+
lines.push(
|
|
920
|
+
` ${dt("doctor.conflict.summary", {
|
|
921
|
+
candidates: String(report.candidate_count),
|
|
922
|
+
conflicts: String(report.conflict_count),
|
|
923
|
+
threshold: report.threshold.toFixed(2)
|
|
924
|
+
})}`
|
|
925
|
+
);
|
|
926
|
+
if (deepRequested && !report.deep) {
|
|
927
|
+
lines.push(` ${symbol.warn} ${dt("doctor.conflict.deep_no_judge")}`);
|
|
928
|
+
}
|
|
929
|
+
lines.push("");
|
|
930
|
+
for (const pair of report.pairs) {
|
|
931
|
+
const sym = pair.verdict === "conflict" ? symbol.error : symbol.warn;
|
|
932
|
+
const verdictLabel = dt(`doctor.conflict.verdict.${pair.verdict}`);
|
|
933
|
+
const pct = `${(pair.similarity * 100).toFixed(0)}%`;
|
|
934
|
+
let line = ` ${sym} [${pair.a} \u2194 ${pair.b}] (${pair.knowledge_type}/${pair.layer}) ${pct} \u2014 ${verdictLabel}`;
|
|
935
|
+
if (pair.rationale !== void 0 && pair.rationale.length > 0) {
|
|
936
|
+
line += `: ${pair.rationale}`;
|
|
937
|
+
}
|
|
938
|
+
lines.push(line);
|
|
939
|
+
}
|
|
940
|
+
writeStdout(lines.join("\n"));
|
|
941
|
+
}
|
|
797
942
|
function renderEnrichDescriptionsReport(report, dt) {
|
|
798
943
|
const header = `${symbol.ok} ${paint.ai("fabric doctor --enrich-descriptions")} mode=${report.mode}${report.dryRun ? " (dry-run)" : ""} scanned=${report.scanned} modified=${report.modified} skipped=${report.skipped}`;
|
|
799
944
|
writeStdout(header);
|
|
@@ -913,8 +1058,39 @@ function formatTimestampForTable(iso) {
|
|
|
913
1058
|
d.getUTCHours()
|
|
914
1059
|
)}:${pad(d.getUTCMinutes())}`;
|
|
915
1060
|
}
|
|
1061
|
+
function renderDoctorFilteredHelp() {
|
|
1062
|
+
const lines = [];
|
|
1063
|
+
lines.push(paint.ai("fabric doctor") + " \u2014 Diagnose and fix Fabric workspace issues");
|
|
1064
|
+
lines.push("");
|
|
1065
|
+
lines.push(`${paint.human("USAGE")}`);
|
|
1066
|
+
lines.push(` fabric doctor [OPTIONS]`);
|
|
1067
|
+
lines.push("");
|
|
1068
|
+
lines.push(`${paint.human("OPTIONS")}`);
|
|
1069
|
+
lines.push("");
|
|
1070
|
+
const exposedOptions = [
|
|
1071
|
+
["--target <path>", "Override project root (defaults to cwd)"],
|
|
1072
|
+
["--fix", "Auto-fix derived-state issues (agents.meta.json)"],
|
|
1073
|
+
["--fix-knowledge", "Auto-fix knowledge entry issues (frontmatter + git mv)"],
|
|
1074
|
+
["--json", "Output as JSON for programmatic consumption"],
|
|
1075
|
+
["--verbose", "Show maintainer-audience action hints"]
|
|
1076
|
+
];
|
|
1077
|
+
for (const [flag, desc] of exposedOptions) {
|
|
1078
|
+
lines.push(` ${paint.ai(flag)} ${desc}`);
|
|
1079
|
+
}
|
|
1080
|
+
lines.push("");
|
|
1081
|
+
lines.push(`${paint.human("EXAMPLES")}`);
|
|
1082
|
+
lines.push(` ${paint.ai("fabric doctor")} # Run diagnostics`);
|
|
1083
|
+
lines.push(` ${paint.ai("fabric doctor --fix")} # Fix derived-state issues`);
|
|
1084
|
+
lines.push(` ${paint.ai("fabric doctor --fix-knowledge")} # Fix knowledge entry issues`);
|
|
1085
|
+
lines.push("");
|
|
1086
|
+
lines.push(paint.human("Run `fabric doctor` to see a full diagnostic report with 48 checks."));
|
|
1087
|
+
writeStdout(lines.join("\n"));
|
|
1088
|
+
}
|
|
1089
|
+
|
|
916
1090
|
export {
|
|
917
|
-
doctor_default as default,
|
|
918
1091
|
doctorCommand,
|
|
919
|
-
|
|
1092
|
+
doctor_default,
|
|
1093
|
+
renderTldrHeader,
|
|
1094
|
+
parseSinceDuration,
|
|
1095
|
+
renderDoctorFilteredHelp
|
|
920
1096
|
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/store/scope-explain.ts
|
|
4
|
+
import {
|
|
5
|
+
SCOPE_COORDINATE_PATTERN,
|
|
6
|
+
buildStoreResolveInput,
|
|
7
|
+
createStoreResolver,
|
|
8
|
+
resolveGlobalRoot
|
|
9
|
+
} from "@fenglimg/fabric-shared";
|
|
10
|
+
import { GenericConfigError } from "@fenglimg/fabric-shared/errors";
|
|
11
|
+
function buildResolveInput(projectRoot, globalRoot = resolveGlobalRoot()) {
|
|
12
|
+
return buildStoreResolveInput(projectRoot, globalRoot);
|
|
13
|
+
}
|
|
14
|
+
function scopeExplain(projectRoot, scope, globalRoot = resolveGlobalRoot()) {
|
|
15
|
+
if (!SCOPE_COORDINATE_PATTERN.test(scope)) {
|
|
16
|
+
throw new GenericConfigError(`invalid scope coordinate '${scope}'`, {
|
|
17
|
+
actionHint: "use ':'-joined lowercase [a-z0-9_-] segments, e.g. `team`, `personal`, `project:fabric-v2`, `org:acme:team:platform`",
|
|
18
|
+
details: { scope }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const input = buildResolveInput(projectRoot, globalRoot);
|
|
22
|
+
if (input === null) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const resolver = createStoreResolver();
|
|
26
|
+
return {
|
|
27
|
+
scope,
|
|
28
|
+
readSet: resolver.resolveReadSet(input),
|
|
29
|
+
writeTarget: resolver.resolveWriteTarget(input, scope).target
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
buildResolveInput,
|
|
35
|
+
scopeExplain
|
|
36
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/store/global-config-io.ts
|
|
4
|
+
import {
|
|
5
|
+
resolveGlobalRoot,
|
|
6
|
+
globalConfigPath,
|
|
7
|
+
loadGlobalConfig,
|
|
8
|
+
saveGlobalConfig
|
|
9
|
+
} from "@fenglimg/fabric-shared";
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
resolveGlobalRoot,
|
|
13
|
+
globalConfigPath,
|
|
14
|
+
loadGlobalConfig,
|
|
15
|
+
saveGlobalConfig
|
|
16
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/i18n.ts
|
|
4
|
+
import {
|
|
5
|
+
createTranslator,
|
|
6
|
+
resolveGlobalLocale
|
|
7
|
+
} from "@fenglimg/fabric-shared";
|
|
8
|
+
var locale = resolveGlobalLocale();
|
|
9
|
+
var t = createTranslator(locale);
|
|
10
|
+
function refreshLocale() {
|
|
11
|
+
locale = resolveGlobalLocale();
|
|
12
|
+
t = createTranslator(locale);
|
|
13
|
+
}
|
|
14
|
+
function getProjectTranslator(_projectRoot = process.cwd()) {
|
|
15
|
+
return createTranslator(resolveGlobalLocale());
|
|
16
|
+
}
|
|
17
|
+
function getDoctorTranslator(projectRoot) {
|
|
18
|
+
return getProjectTranslator(projectRoot);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
t,
|
|
23
|
+
refreshLocale,
|
|
24
|
+
getProjectTranslator,
|
|
25
|
+
getDoctorTranslator
|
|
26
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
if (process.env.NO_COLOR) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
const force = process.env.FORCE_COLOR;
|
|
11
|
+
if (force !== void 0) {
|
|
12
|
+
return force !== "0" && force.toLowerCase() !== "false";
|
|
13
|
+
}
|
|
14
|
+
return Boolean(process.stdout.isTTY);
|
|
15
|
+
}
|
|
16
|
+
function colorize(painter) {
|
|
17
|
+
return (value) => isColorEnabled() ? painter(value) : value;
|
|
18
|
+
}
|
|
19
|
+
var paint = {
|
|
20
|
+
success: colorize(pc.green),
|
|
21
|
+
warn: colorize(pc.yellow),
|
|
22
|
+
error: colorize(pc.red),
|
|
23
|
+
drift: colorize(pc.magenta),
|
|
24
|
+
ai: colorize(pc.blue),
|
|
25
|
+
human: colorize(pc.cyan),
|
|
26
|
+
muted: colorize(pc.dim)
|
|
27
|
+
};
|
|
28
|
+
var symbol = {
|
|
29
|
+
get ok() {
|
|
30
|
+
return isColorEnabled() ? paint.success("[ok] \u2713") : "[ok]";
|
|
31
|
+
},
|
|
32
|
+
get warn() {
|
|
33
|
+
return isColorEnabled() ? paint.warn("[warn] !") : "[warn]";
|
|
34
|
+
},
|
|
35
|
+
get error() {
|
|
36
|
+
return isColorEnabled() ? paint.error("[error] x") : "[error]";
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export {
|
|
41
|
+
paint,
|
|
42
|
+
symbol
|
|
43
|
+
};
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
buildResolveInput
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-EOT63RDH.js";
|
|
5
5
|
import {
|
|
6
6
|
loadProjectConfig
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QFIVFZRH.js";
|
|
8
8
|
import {
|
|
9
9
|
resolveGlobalRoot
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-FNHDQTPC.js";
|
|
11
11
|
|
|
12
12
|
// src/store/bindings-io.ts
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
resolveWorkspaceBindingId,
|
|
15
|
+
writeBindingsSnapshot
|
|
16
|
+
} from "@fenglimg/fabric-shared";
|
|
14
17
|
var DEFAULT_WRITE_SCOPE = "team";
|
|
15
18
|
function regenerateBindingsSnapshot(projectRoot, options) {
|
|
16
19
|
const globalRoot = options.globalRoot ?? resolveGlobalRoot();
|
|
@@ -22,9 +25,14 @@ function regenerateBindingsSnapshot(projectRoot, options) {
|
|
|
22
25
|
if (project?.project_id === void 0) {
|
|
23
26
|
return null;
|
|
24
27
|
}
|
|
28
|
+
const workspaceBindingId = resolveWorkspaceBindingId(project);
|
|
29
|
+
if (workspaceBindingId === void 0) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
25
32
|
return writeBindingsSnapshot({
|
|
26
33
|
globalRoot,
|
|
27
34
|
projectId: project.project_id,
|
|
35
|
+
workspaceBindingId,
|
|
28
36
|
resolveInput,
|
|
29
37
|
writeScope: options.writeScope ?? DEFAULT_WRITE_SCOPE,
|
|
30
38
|
now: options.now
|