@fenglimg/fabric-cli 2.2.0-rc.1 → 2.2.0-rc.11
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-AOE6AYI7.js → chunk-2KBCTMID.js} +31 -8
- package/dist/chunk-3D7B2UAZ.js +149 -0
- package/dist/{chunk-XC5RUHLK.js → chunk-3IOLS5EK.js} +23 -38
- package/dist/{plan-context-hint-FC6P3WFE.js → chunk-722JU5BP.js} +52 -12
- package/dist/{chunk-2R55HNVD.js → chunk-7ZDXBOOU.js} +234 -206
- package/dist/{doctor-YONYXDX6.js → chunk-E7HJUU34.js} +215 -52
- package/dist/chunk-EOT63RDH.js +36 -0
- package/dist/chunk-FNHDQTPC.js +16 -0
- package/dist/{chunk-2CY4BMTH.js → chunk-HORSMSZL.js} +9 -5
- package/dist/{chunk-BO4XIZWZ.js → chunk-NLNH64A3.js} +5 -18
- 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-XYRBZJDU.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 +133 -22
- package/dist/info-7FKBTMVO.js +139 -0
- package/dist/install-v2-WLEJ5XHT.js +3279 -0
- package/dist/{metrics-RER6NLFC.js → metrics-HMFH4YHK.js} +1 -1
- package/dist/{onboard-coverage-JWQWDZW7.js → onboard-coverage-XSG77LL3.js} +48 -27
- package/dist/plan-context-hint-5TNGH3R4.js +12 -0
- package/dist/{scope-explain-CDIZESP5.js → scope-explain-HLJZ2M33.js} +17 -6
- package/dist/status-4R3TM4FJ.js +37 -0
- package/dist/store-HOCORVL3.js +563 -0
- package/dist/{sync-UJ4BBCZJ.js → sync-DT5UJMMR.js} +197 -30
- package/dist/{uninstall-C3QXKOO6.js → uninstall-IFN2KYBK.js} +97 -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 +742 -259
- package/templates/hooks/knowledge-hint-broad.cjs +577 -274
- package/templates/hooks/knowledge-hint-narrow.cjs +113 -73
- package/templates/hooks/lib/banner-i18n.cjs +50 -1
- 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/nudge-policy.cjs +117 -0
- package/templates/hooks/lib/state-store.cjs +60 -0
- 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 +47 -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 +13 -3
- package/templates/skills/fabric-connect/SKILL.md +3 -3
- 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 +14 -5
- package/templates/skills/fabric-review/ref/cite-contract.md +1 -1
- 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 +1 -1
- package/templates/skills/fabric-sync/SKILL.md +1 -1
- package/templates/skills/lib/shared-policy.md +2 -2
- package/dist/chunk-4R2CYEA4.js +0 -116
- package/dist/chunk-L4Q55UC4.js +0 -52
- package/dist/chunk-LFIKMVY7.js +0 -27
- package/dist/chunk-RYAFBNES.js +0 -33
- package/dist/chunk-T5RPGCCM.js +0 -40
- package/dist/install-74ANPCCP.js +0 -2737
- package/dist/status-GLQWLWH6.js +0 -23
- package/dist/store-XB3ADT65.js +0 -144
- package/dist/whoami-2MLO4Y37.js +0 -36
- 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
|
-
|
|
10
|
+
paint,
|
|
11
|
+
symbol
|
|
12
|
+
} from "./chunk-NLNH64A3.js";
|
|
12
13
|
import {
|
|
13
|
-
|
|
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,6 +413,8 @@ 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);
|
|
@@ -401,8 +447,11 @@ var doctorCommand = defineCommand({
|
|
|
401
447
|
if (args["dry-run"] === true) {
|
|
402
448
|
report = await runDoctorReport(resolution.target);
|
|
403
449
|
} else {
|
|
450
|
+
rootConfigMigration = migrateRootConfig(resolution.target);
|
|
451
|
+
unboundProjectFix = await backfillUnboundProject(resolution.target);
|
|
404
452
|
fixReport = await runDoctorFix(resolution.target);
|
|
405
453
|
report = fixReport.report;
|
|
454
|
+
syncStoreAliasLinks();
|
|
406
455
|
}
|
|
407
456
|
} else {
|
|
408
457
|
report = await runDoctorReport(resolution.target);
|
|
@@ -411,7 +460,12 @@ var doctorCommand = defineCommand({
|
|
|
411
460
|
if (args.json === true) {
|
|
412
461
|
writeStdout(
|
|
413
462
|
JSON.stringify(
|
|
414
|
-
{
|
|
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
|
+
},
|
|
415
469
|
null,
|
|
416
470
|
2
|
|
417
471
|
)
|
|
@@ -425,6 +479,19 @@ var doctorCommand = defineCommand({
|
|
|
425
479
|
renderFixKnowledgeMutations(fixKnowledgeReport, dt);
|
|
426
480
|
} else if (fixReport !== null) {
|
|
427
481
|
writeStdout(fixReport.message);
|
|
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
|
+
}
|
|
428
495
|
} else if ((fix || fixKnowledge) && args["dry-run"] === true) {
|
|
429
496
|
writeStdout(dt("cli.doctor.fix-dry-run-banner"));
|
|
430
497
|
}
|
|
@@ -456,6 +523,9 @@ function renderHumanReport(report, dt, verbose) {
|
|
|
456
523
|
writeStdout(`${renderStatus(report.status)} ${paint.ai("fabric doctor")} ${paint.human(report.summary.target)}`);
|
|
457
524
|
renderTldrHeader(report, dt, verbose);
|
|
458
525
|
for (const check of report.checks) {
|
|
526
|
+
if (!verbose && check.status === "ok") {
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
459
529
|
writeStdout(`${renderStatus(check.status)} ${check.name}: ${check.message}`);
|
|
460
530
|
}
|
|
461
531
|
const opts = { verbose, dt };
|
|
@@ -478,7 +548,7 @@ function renderStoreDiagnostics(diagnostics) {
|
|
|
478
548
|
writeStdout("");
|
|
479
549
|
writeStdout(paint.ai("store health"));
|
|
480
550
|
for (const diagnostic of diagnostics) {
|
|
481
|
-
const mark = diagnostic.severity === "warn" ? symbol.warn : "[info]";
|
|
551
|
+
const mark = diagnostic.severity === "error" ? symbol.error : diagnostic.severity === "warn" ? symbol.warn : "[info]";
|
|
482
552
|
const ref = diagnostic.ref === void 0 ? "" : ` [${diagnostic.ref}]`;
|
|
483
553
|
writeStdout(`${mark}${ref} ${diagnostic.message}`);
|
|
484
554
|
}
|
|
@@ -658,7 +728,6 @@ async function resolveFixKnowledgeConsent(options) {
|
|
|
658
728
|
var CITE_COVERAGE_CLIENT_FILTERS = /* @__PURE__ */ new Set([
|
|
659
729
|
"cc",
|
|
660
730
|
"codex",
|
|
661
|
-
"cursor",
|
|
662
731
|
"all"
|
|
663
732
|
]);
|
|
664
733
|
function isValidClientFilter(input) {
|
|
@@ -701,10 +770,42 @@ function renderCiteCoverageReport(report, jsonMode, dt) {
|
|
|
701
770
|
const complianceRate = report.metrics.cite_compliance_rate;
|
|
702
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)})`;
|
|
703
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}`);
|
|
704
776
|
const uncorrelatable = report.metrics.uncorrelatable_edits ?? 0;
|
|
705
777
|
if (uncorrelatable > 0) {
|
|
706
778
|
lines.push(` ${dt("doctor.cite.metric.uncorrelatableEdits")}: ${uncorrelatable}`);
|
|
707
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
|
+
}
|
|
708
809
|
if (report.per_client !== void 0 && Object.keys(report.per_client).length > 1) {
|
|
709
810
|
lines.push("");
|
|
710
811
|
lines.push(`### ${dt("doctor.cite.section.perClient")}`);
|
|
@@ -806,6 +907,38 @@ function appendContractSection(lines, report, dt) {
|
|
|
806
907
|
);
|
|
807
908
|
}
|
|
808
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
|
+
}
|
|
809
942
|
function renderEnrichDescriptionsReport(report, dt) {
|
|
810
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}`;
|
|
811
944
|
writeStdout(header);
|
|
@@ -925,9 +1058,39 @@ function formatTimestampForTable(iso) {
|
|
|
925
1058
|
d.getUTCHours()
|
|
926
1059
|
)}:${pad(d.getUTCMinutes())}`;
|
|
927
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
|
+
|
|
928
1090
|
export {
|
|
929
|
-
doctor_default as default,
|
|
930
1091
|
doctorCommand,
|
|
1092
|
+
doctor_default,
|
|
1093
|
+
renderTldrHeader,
|
|
931
1094
|
parseSinceDuration,
|
|
932
|
-
|
|
1095
|
+
renderDoctorFilteredHelp
|
|
933
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
|
+
};
|
|
@@ -3,13 +3,16 @@
|
|
|
3
3
|
// src/i18n.ts
|
|
4
4
|
import {
|
|
5
5
|
createTranslator,
|
|
6
|
-
|
|
7
|
-
resolveFabricLocale
|
|
6
|
+
resolveGlobalLocale
|
|
8
7
|
} from "@fenglimg/fabric-shared";
|
|
9
|
-
var locale =
|
|
8
|
+
var locale = resolveGlobalLocale();
|
|
10
9
|
var t = createTranslator(locale);
|
|
11
|
-
function
|
|
12
|
-
|
|
10
|
+
function refreshLocale() {
|
|
11
|
+
locale = resolveGlobalLocale();
|
|
12
|
+
t = createTranslator(locale);
|
|
13
|
+
}
|
|
14
|
+
function getProjectTranslator(_projectRoot = process.cwd()) {
|
|
15
|
+
return createTranslator(resolveGlobalLocale());
|
|
13
16
|
}
|
|
14
17
|
function getDoctorTranslator(projectRoot) {
|
|
15
18
|
return getProjectTranslator(projectRoot);
|
|
@@ -17,6 +20,7 @@ function getDoctorTranslator(projectRoot) {
|
|
|
17
20
|
|
|
18
21
|
export {
|
|
19
22
|
t,
|
|
23
|
+
refreshLocale,
|
|
20
24
|
getProjectTranslator,
|
|
21
25
|
getDoctorTranslator
|
|
22
26
|
};
|
|
@@ -11,7 +11,7 @@ function isColorEnabled() {
|
|
|
11
11
|
if (force !== void 0) {
|
|
12
12
|
return force !== "0" && force.toLowerCase() !== "false";
|
|
13
13
|
}
|
|
14
|
-
return Boolean(process.stdout.isTTY)
|
|
14
|
+
return Boolean(process.stdout.isTTY);
|
|
15
15
|
}
|
|
16
16
|
function colorize(painter) {
|
|
17
17
|
return (value) => isColorEnabled() ? painter(value) : value;
|
|
@@ -27,30 +27,17 @@ var paint = {
|
|
|
27
27
|
};
|
|
28
28
|
var symbol = {
|
|
29
29
|
get ok() {
|
|
30
|
-
return isColorEnabled() ? paint.success("\u2713") : "[ok]";
|
|
30
|
+
return isColorEnabled() ? paint.success("[ok] \u2713") : "[ok]";
|
|
31
31
|
},
|
|
32
32
|
get warn() {
|
|
33
|
-
return isColorEnabled() ? paint.warn("!") : "[warn]";
|
|
33
|
+
return isColorEnabled() ? paint.warn("[warn] !") : "[warn]";
|
|
34
34
|
},
|
|
35
35
|
get error() {
|
|
36
|
-
return isColorEnabled() ? paint.error("x") : "[error]";
|
|
36
|
+
return isColorEnabled() ? paint.error("[error] x") : "[error]";
|
|
37
37
|
}
|
|
38
38
|
};
|
|
39
|
-
function displayWidth(value) {
|
|
40
|
-
return stringWidth(value);
|
|
41
|
-
}
|
|
42
|
-
function padEnd(value, width, char = " ") {
|
|
43
|
-
const fill = char.length > 0 ? char : " ";
|
|
44
|
-
let result = value;
|
|
45
|
-
while (displayWidth(result) < width) {
|
|
46
|
-
result += fill;
|
|
47
|
-
}
|
|
48
|
-
return result;
|
|
49
|
-
}
|
|
50
39
|
|
|
51
40
|
export {
|
|
52
41
|
paint,
|
|
53
|
-
symbol
|
|
54
|
-
displayWidth,
|
|
55
|
-
padEnd
|
|
42
|
+
symbol
|
|
56
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
|