@dsh-cc/command-doctor 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/LICENSE +201 -0
  2. package/README.i18n.yaml +6 -0
  3. package/README.md +47 -0
  4. package/README.zh.md +47 -0
  5. package/lib/checks/env.d.ts +12 -0
  6. package/lib/checks/env.d.ts.map +1 -0
  7. package/lib/checks/env.js +71 -0
  8. package/lib/checks/env.js.map +1 -0
  9. package/lib/checks/git.d.ts +26 -0
  10. package/lib/checks/git.d.ts.map +1 -0
  11. package/lib/checks/git.js +94 -0
  12. package/lib/checks/git.js.map +1 -0
  13. package/lib/checks/hooks.d.ts +33 -0
  14. package/lib/checks/hooks.d.ts.map +1 -0
  15. package/lib/checks/hooks.js +138 -0
  16. package/lib/checks/hooks.js.map +1 -0
  17. package/lib/checks/mcp.d.ts +24 -0
  18. package/lib/checks/mcp.d.ts.map +1 -0
  19. package/lib/checks/mcp.js +107 -0
  20. package/lib/checks/mcp.js.map +1 -0
  21. package/lib/checks/models.d.ts +57 -0
  22. package/lib/checks/models.d.ts.map +1 -0
  23. package/lib/checks/models.js +190 -0
  24. package/lib/checks/models.js.map +1 -0
  25. package/lib/checks/plugins.d.ts +24 -0
  26. package/lib/checks/plugins.d.ts.map +1 -0
  27. package/lib/checks/plugins.js +55 -0
  28. package/lib/checks/plugins.js.map +1 -0
  29. package/lib/checks/seams.d.ts +12 -0
  30. package/lib/checks/seams.d.ts.map +1 -0
  31. package/lib/checks/seams.js +44 -0
  32. package/lib/checks/seams.js.map +1 -0
  33. package/lib/checks/session.d.ts +10 -0
  34. package/lib/checks/session.d.ts.map +1 -0
  35. package/lib/checks/session.js +88 -0
  36. package/lib/checks/session.js.map +1 -0
  37. package/lib/checks/storage.d.ts +13 -0
  38. package/lib/checks/storage.d.ts.map +1 -0
  39. package/lib/checks/storage.js +53 -0
  40. package/lib/checks/storage.js.map +1 -0
  41. package/lib/checks/web.d.ts +12 -0
  42. package/lib/checks/web.d.ts.map +1 -0
  43. package/lib/checks/web.js +128 -0
  44. package/lib/checks/web.js.map +1 -0
  45. package/lib/collect.d.ts +28 -0
  46. package/lib/collect.d.ts.map +1 -0
  47. package/lib/collect.js +76 -0
  48. package/lib/collect.js.map +1 -0
  49. package/lib/doctor.d.ts +8 -0
  50. package/lib/doctor.d.ts.map +1 -0
  51. package/lib/doctor.js +7 -0
  52. package/lib/doctor.js.map +1 -0
  53. package/lib/flags.d.ts +23 -0
  54. package/lib/flags.d.ts.map +1 -0
  55. package/lib/flags.js +36 -0
  56. package/lib/flags.js.map +1 -0
  57. package/lib/index.d.ts +20 -0
  58. package/lib/index.d.ts.map +1 -0
  59. package/lib/index.js +71 -0
  60. package/lib/index.js.map +1 -0
  61. package/lib/invariant.d.ts +16 -0
  62. package/lib/invariant.d.ts.map +1 -0
  63. package/lib/invariant.js +23 -0
  64. package/lib/invariant.js.map +1 -0
  65. package/lib/json.d.ts +19 -0
  66. package/lib/json.d.ts.map +1 -0
  67. package/lib/json.js +27 -0
  68. package/lib/json.js.map +1 -0
  69. package/lib/last-model.d.ts +23 -0
  70. package/lib/last-model.d.ts.map +1 -0
  71. package/lib/last-model.js +30 -0
  72. package/lib/last-model.js.map +1 -0
  73. package/lib/redact.d.ts +14 -0
  74. package/lib/redact.d.ts.map +1 -0
  75. package/lib/redact.js +53 -0
  76. package/lib/redact.js.map +1 -0
  77. package/lib/render.d.ts +17 -0
  78. package/lib/render.d.ts.map +1 -0
  79. package/lib/render.js +60 -0
  80. package/lib/render.js.map +1 -0
  81. package/lib/report.d.ts +60 -0
  82. package/lib/report.d.ts.map +1 -0
  83. package/lib/report.js +18 -0
  84. package/lib/report.js.map +1 -0
  85. package/lib/version.d.ts +29 -0
  86. package/lib/version.d.ts.map +1 -0
  87. package/lib/version.js +62 -0
  88. package/lib/version.js.map +1 -0
  89. package/package.json +51 -0
@@ -0,0 +1,138 @@
1
+ /**
2
+ * `hooks` checks for `/doctor`: the hook bridge load report, flag defaults,
3
+ * and the verbose-only `serena-hooks` PATH probe.
4
+ * @module @dsh-cc/command-doctor/checks/hooks
5
+ */
6
+ import { existsSync, statSync } from 'node:fs';
7
+ import { delimiter, join } from 'node:path';
8
+ /** Collect the hooks group checks. */
9
+ export function hookChecks(ctx, options) {
10
+ const status = ctx.get('hookBridgeStatus');
11
+ const checks = [];
12
+ if (status === undefined) {
13
+ checks.push({
14
+ id: 'hooks.bridge',
15
+ group: 'hooks',
16
+ status: 'skip',
17
+ summary: 'hookBridgeStatus seam not mounted',
18
+ });
19
+ checks.push(discoveryCheck());
20
+ return checks;
21
+ }
22
+ checks.push(status.error === undefined
23
+ ? {
24
+ id: 'hooks.source',
25
+ group: 'hooks',
26
+ status: 'ok',
27
+ summary: status.sourcePath,
28
+ evidence: { sourcePath: status.sourcePath },
29
+ }
30
+ : {
31
+ id: 'hooks.source',
32
+ group: 'hooks',
33
+ status: 'fail',
34
+ summary: String(status.error),
35
+ detail: `no hooks are registered (${status.sourcePath})`,
36
+ fix: 'fix the hook configuration so it parses',
37
+ evidence: { sourcePath: status.sourcePath },
38
+ });
39
+ checks.push(status.events.length === 0
40
+ ? { id: 'hooks.events', group: 'hooks', status: 'info', summary: 'no hook events registered' }
41
+ : {
42
+ id: 'hooks.events',
43
+ group: 'hooks',
44
+ status: 'ok',
45
+ summary: status.events.map(event => `${event.name}: ${event.groups}/${event.hooks}`).join(', '),
46
+ evidence: { events: status.events.length },
47
+ });
48
+ checks.push(status.skipped.length === 0
49
+ ? { id: 'hooks.skipped', group: 'hooks', status: 'ok', summary: 'none' }
50
+ : {
51
+ id: 'hooks.skipped',
52
+ group: 'hooks',
53
+ status: 'warn',
54
+ summary: `${status.skipped.length} skipped hook entries`,
55
+ detail: status.skipped
56
+ .map(skip => `${skip.event ?? '?'}: ${skip.type ?? '?'} — ${skip.reason ?? 'malformed'}`)
57
+ .join('; '),
58
+ evidence: { skipped: status.skipped.length },
59
+ });
60
+ checks.push(status.enablePromptHooks === false && status.enableAgentHooks === false
61
+ ? {
62
+ id: 'hooks.prompt-agent',
63
+ group: 'hooks',
64
+ status: 'info',
65
+ summary: 'prompt/agent hooks are disabled (expected default-off)',
66
+ }
67
+ : {
68
+ id: 'hooks.prompt-agent',
69
+ group: 'hooks',
70
+ status: 'ok',
71
+ summary: `prompt hooks ${status.enablePromptHooks ? 'on' : 'off'}, agent hooks ${status.enableAgentHooks ? 'on' : 'off'}`,
72
+ });
73
+ checks.push(serenaHooksCheck(status, options.verbose));
74
+ checks.push(discoveryCheck());
75
+ return checks;
76
+ }
77
+ /** The always-present info note on unimplemented CC discovery semantics. */
78
+ function discoveryCheck() {
79
+ return {
80
+ id: 'hooks.discovery',
81
+ group: 'hooks',
82
+ status: 'info',
83
+ summary: 'CC layered project/user discovery and live reload are not implemented',
84
+ };
85
+ }
86
+ /**
87
+ * `serena-hooks` availability. Default: report "not probed (use --verbose)"
88
+ * when referenced, skip when not referenced. Verbose: a pure-fs PATH scan
89
+ * (no `which`).
90
+ */
91
+ function serenaHooksCheck(status, verbose) {
92
+ const referenced = (status.commands ?? []).some(command => command.includes('serena-hooks'));
93
+ if (!referenced) {
94
+ return { id: 'hooks.serena-hooks', group: 'hooks', status: 'skip', summary: 'not referenced' };
95
+ }
96
+ if (!verbose) {
97
+ return { id: 'hooks.serena-hooks', group: 'hooks', status: 'info', summary: 'not probed (use --verbose)' };
98
+ }
99
+ const found = scanPath('serena-hooks');
100
+ return found === undefined
101
+ ? {
102
+ id: 'hooks.serena-hooks',
103
+ group: 'hooks',
104
+ status: 'fail',
105
+ summary: 'serena-hooks is referenced by a loaded hook but not on PATH',
106
+ fix: 'install serena-hooks or extend PATH',
107
+ }
108
+ : {
109
+ id: 'hooks.serena-hooks',
110
+ group: 'hooks',
111
+ status: 'ok',
112
+ summary: `found at ${found}`,
113
+ evidence: { path: found },
114
+ };
115
+ }
116
+ /** Pure-fs PATH scan; appends platform executable suffixes. */
117
+ export function scanPath(binary) {
118
+ const path = process.env.PATH ?? '';
119
+ const suffixes = process.platform === 'win32' ? ['', '.cmd', '.exe'] : [''];
120
+ for (const dir of path.split(delimiter)) {
121
+ if (dir.length === 0)
122
+ continue;
123
+ for (const suffix of suffixes) {
124
+ const candidate = join(dir, `${binary}${suffix}`);
125
+ if (existsSync(candidate)) {
126
+ try {
127
+ if (statSync(candidate).isFile())
128
+ return candidate;
129
+ }
130
+ catch {
131
+ // Vanished between existsSync and stat; keep scanning.
132
+ }
133
+ }
134
+ }
135
+ }
136
+ return undefined;
137
+ }
138
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/checks/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * `mcp` checks for `/doctor`: per-connection status rows and the Serena
3
+ * cross-check, duck-typing the `mcpConnections` seam.
4
+ * @module @dsh-cc/command-doctor/checks/mcp
5
+ */
6
+ import type { Context } from '@deepseek-ai/cordis';
7
+ import type { Check } from '../report.ts';
8
+ import type { GitInfo } from './git.ts';
9
+ /** Duck-typed `mcpConnections` entry face used here. */
10
+ export interface McpEntry {
11
+ readonly name: string;
12
+ readonly state: string;
13
+ readonly error?: string;
14
+ readonly toolCount?: number;
15
+ readonly eagerCount?: number;
16
+ readonly deferredCount?: number;
17
+ readonly authRequired?: boolean;
18
+ }
19
+ /** Collect the mcp group checks. */
20
+ export declare function mcpChecks(ctx: Context, options?: {
21
+ git?: GitInfo;
22
+ verbose?: boolean;
23
+ }): Check[];
24
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/checks/mcp.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAEvC,wDAAwD;AACxD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAChC;AAED,oCAAoC;AACpC,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,KAAK,EAAE,CAuBnG"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * `mcp` checks for `/doctor`: per-connection status rows and the Serena
3
+ * cross-check, duck-typing the `mcpConnections` seam.
4
+ * @module @dsh-cc/command-doctor/checks/mcp
5
+ */
6
+ /** Collect the mcp group checks. */
7
+ export function mcpChecks(ctx, options = {}) {
8
+ const connections = ctx.get('mcpConnections');
9
+ if (connections?.entries === undefined) {
10
+ return [{
11
+ id: 'mcp.registry',
12
+ group: 'mcp',
13
+ status: 'skip',
14
+ summary: 'mcpConnections not mounted',
15
+ }];
16
+ }
17
+ const entries = connections.entries();
18
+ const checks = [{
19
+ id: 'mcp.overview',
20
+ group: 'mcp',
21
+ status: 'ok',
22
+ summary: `${entries.length} servers`,
23
+ evidence: { count: entries.length },
24
+ }];
25
+ for (const entry of entries)
26
+ checks.push(entryCheck(entry));
27
+ checks.push(serenaCheck(entries, options));
28
+ return checks;
29
+ }
30
+ /** Map one connection entry to its check row. */
31
+ function entryCheck(entry) {
32
+ const id = `mcp.server.${entry.name}`;
33
+ if (entry.authRequired === true) {
34
+ return warn(id, `${entry.name}: authentication required`);
35
+ }
36
+ if (entry.state === 'ready') {
37
+ if ((entry.toolCount ?? 0) > 0) {
38
+ return {
39
+ id,
40
+ group: 'mcp',
41
+ status: 'ok',
42
+ summary: `${entry.name}: ready with ${entry.toolCount} tools`,
43
+ detail: toolBreakdown(entry),
44
+ evidence: { state: entry.state, toolCount: entry.toolCount ?? 0 },
45
+ };
46
+ }
47
+ return warn(id, `${entry.name}: ready with 0 tools`);
48
+ }
49
+ if (entry.state === 'connecting') {
50
+ return {
51
+ id,
52
+ group: 'mcp',
53
+ status: 'info',
54
+ summary: `${entry.name}: connecting`,
55
+ evidence: { state: entry.state },
56
+ };
57
+ }
58
+ return {
59
+ id,
60
+ group: 'mcp',
61
+ status: 'fail',
62
+ summary: `${entry.name}: ${entry.state}`,
63
+ detail: entry.error,
64
+ fix: 'check the server command/logs or run /mcp reconnect',
65
+ evidence: { state: entry.state },
66
+ };
67
+ }
68
+ /** Render eager/deferred breakdown when the entry exposes it. */
69
+ function toolBreakdown(entry) {
70
+ if (entry.eagerCount === undefined && entry.deferredCount === undefined)
71
+ return undefined;
72
+ return `eager ${entry.eagerCount ?? 0}, deferred ${entry.deferredCount ?? 0}`;
73
+ }
74
+ function warn(id, summary) {
75
+ return { id, group: 'mcp', status: 'warn', summary };
76
+ }
77
+ /** The Serena-specific row: present and not ready is a fail. */
78
+ function serenaCheck(entries, options) {
79
+ const serena = entries.find(entry => /serena/i.test(entry.name));
80
+ if (serena === undefined) {
81
+ return { id: 'mcp.serena', group: 'mcp', status: 'skip', summary: 'no serena server' };
82
+ }
83
+ const base = serena.state === 'ready'
84
+ ? {
85
+ id: 'mcp.serena',
86
+ group: 'mcp',
87
+ status: 'ok',
88
+ summary: `${serena.name}: ready`,
89
+ evidence: { state: serena.state },
90
+ }
91
+ : {
92
+ id: 'mcp.serena',
93
+ group: 'mcp',
94
+ status: 'fail',
95
+ summary: `${serena.name}: ${serena.state}`,
96
+ detail: serena.error,
97
+ fix: 'run /mcp reconnect or start the Serena server',
98
+ evidence: { state: serena.state },
99
+ };
100
+ const crossNote = options.git?.worktree === true && options.git.hasSerena === false
101
+ ? 'this cwd looks like a git worktree without a .serena directory; Serena project memory may resolve against the main checkout'
102
+ : undefined;
103
+ if (crossNote === undefined)
104
+ return base;
105
+ return { ...base, detail: [base.detail, crossNote].filter(part => part !== undefined).join(' — ') };
106
+ }
107
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/checks/mcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * `models` checks for `/doctor`: peer-deduped alias routes, the last request,
3
+ * and (verbose) the LLM catalog validation.
4
+ * @module @dsh-cc/command-doctor/checks/models
5
+ */
6
+ import type { Context } from '@deepseek-ai/cordis';
7
+ import type { CommandInvocation } from '@deepseek-ai/dsh-commands';
8
+ import type { Check } from '../report.ts';
9
+ /** Duck-typed alias inspection, matching `ccModelRoutes.inspect`. */
10
+ export interface AliasInspection {
11
+ readonly kind: string;
12
+ readonly route?: {
13
+ provider?: string;
14
+ model?: string;
15
+ reasoningEffort?: string;
16
+ };
17
+ readonly via?: string;
18
+ readonly hop?: string;
19
+ }
20
+ /** Duck-typed ccModelRoutes face used here. */
21
+ export interface ModelRoutesSeam {
22
+ inspect?(name: string): AliasInspection;
23
+ }
24
+ /** One advertised reasoning effort: a string id, or `{ id }` from the TUI catalog. */
25
+ type EffortEntry = string | {
26
+ id?: string;
27
+ };
28
+ /** Duck-typed llm catalog face used here. `listModels` / `resolveModelInfo` are async in the TUI. */
29
+ export interface LlmSeam {
30
+ listProviders?(): {
31
+ id: string;
32
+ }[] | Promise<{
33
+ id: string;
34
+ }[]>;
35
+ listModels?(provider: string): {
36
+ id?: string;
37
+ name?: string;
38
+ }[] | Promise<{
39
+ id?: string;
40
+ name?: string;
41
+ }[]>;
42
+ resolveModelInfo?(provider: string, model: string): {
43
+ reasoning?: {
44
+ efforts?: readonly EffortEntry[];
45
+ };
46
+ } | Promise<{
47
+ reasoning?: {
48
+ efforts?: readonly EffortEntry[];
49
+ };
50
+ } | undefined>;
51
+ }
52
+ /** Collect the models group checks. */
53
+ export declare function modelChecks(ctx: Context, invocation: CommandInvocation, options: {
54
+ verbose: boolean;
55
+ }): Promise<Check[]>;
56
+ export {};
57
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/checks/models.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAElE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAEzC,qEAAqE;AACrE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAChF,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,+CAA+C;AAC/C,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAA;CACxC;AAED,sFAAsF;AACtF,KAAK,WAAW,GAAG,MAAM,GAAG;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3C,qGAAqG;AACrG,MAAM,WAAW,OAAO;IACtB,aAAa,CAAC,IAAI;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC,CAAA;IAC9D,UAAU,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,OAAO,CAAC;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC,CAAA;IAC3G,gBAAgB,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAC7C;QAAE,SAAS,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;SAAE,CAAA;KAAE,GACpD,OAAO,CAAC;QAAE,SAAS,CAAC,EAAE;YAAE,OAAO,CAAC,EAAE,SAAS,WAAW,EAAE,CAAA;SAAE,CAAA;KAAE,GAAG,SAAS,CAAC,CAAA;CAC9E;AAUD,uCAAuC;AACvC,wBAAsB,WAAW,CAC/B,GAAG,EAAE,OAAO,EACZ,UAAU,EAAE,iBAAiB,EAC7B,OAAO,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAC5B,OAAO,CAAC,KAAK,EAAE,CAAC,CA2BlB"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * `models` checks for `/doctor`: peer-deduped alias routes, the last request,
3
+ * and (verbose) the LLM catalog validation.
4
+ * @module @dsh-cc/command-doctor/checks/models
5
+ */
6
+ import { lastModel } from "../last-model.js";
7
+ /** Canonical peer lanes: `lane → peer alias` (copied from LANE_PEERS). */
8
+ const LANES = [
9
+ { lane: 'sketch', peer: 'haiku' },
10
+ { lane: 'draft', peer: 'sonnet' },
11
+ { lane: 'blueprint', peer: 'opus' },
12
+ { lane: 'masterplan', peer: 'fable' },
13
+ ];
14
+ /** Collect the models group checks. */
15
+ export async function modelChecks(ctx, invocation, options) {
16
+ const routes = ctx.get('ccModelRoutes');
17
+ if (routes?.inspect === undefined) {
18
+ return [{
19
+ id: 'models.routes',
20
+ group: 'models',
21
+ status: 'skip',
22
+ summary: 'ccModelRoutes not mounted',
23
+ }];
24
+ }
25
+ const inspect = routes.inspect.bind(routes);
26
+ const checks = [];
27
+ for (const { lane, peer } of LANES) {
28
+ checks.push(aliasCheck(inspect, peer, `${peer} (+ ${lane})`));
29
+ }
30
+ checks.push(aliasCheck(inspect, 'architect', 'architect'));
31
+ for (const { lane } of LANES) {
32
+ const laneInspection = inspect(lane);
33
+ if (laneInspection.via === 'configured' || laneInspection.via === 'one-hop') {
34
+ checks.push(aliasCheck(inspect, lane, lane));
35
+ }
36
+ }
37
+ checks.push(lastRequestCheck(invocation));
38
+ if (options.verbose) {
39
+ checks.push(...await catalogChecks(ctx, checks));
40
+ }
41
+ return checks;
42
+ }
43
+ /** One peer-deduped alias row. */
44
+ function aliasCheck(inspect, name, label) {
45
+ const inspection = inspect(name);
46
+ const via = inspection.via === undefined ? '' : ` (via ${inspection.via})`;
47
+ const hop = inspection.hop === undefined ? '' : ` -> ${inspection.hop}`;
48
+ const provenance = `${via}${hop}`;
49
+ if (inspection.kind === 'inherit') {
50
+ return {
51
+ id: `models.alias.${name}`,
52
+ group: 'models',
53
+ status: 'info',
54
+ summary: `${label}: inherit${provenance}`,
55
+ detail: inspection.route === undefined ? undefined : JSON.stringify(inspection.route),
56
+ evidence: { via: inspection.via ?? null, hop: inspection.hop ?? null },
57
+ };
58
+ }
59
+ const route = inspection.route;
60
+ const target = route?.model === undefined
61
+ ? 'no route'
62
+ : `${route.provider ?? '?'}/${route.model}`;
63
+ return {
64
+ id: `models.alias.${name}`,
65
+ group: 'models',
66
+ status: 'ok',
67
+ summary: `${label}: ${target}${provenance}`,
68
+ detail: route?.reasoningEffort === undefined ? undefined : `effort ${route.reasoningEffort}`,
69
+ evidence: {
70
+ provider: route?.provider ?? null,
71
+ model: route?.model ?? null,
72
+ via: inspection.via ?? null,
73
+ hop: inspection.hop ?? null,
74
+ },
75
+ };
76
+ }
77
+ /** Fold the last `request/header` into `models.last-request`. */
78
+ function lastRequestCheck(invocation) {
79
+ const modelRef = lastModel(invocation.agent.session.events);
80
+ if (modelRef === undefined) {
81
+ return {
82
+ id: 'models.last-request',
83
+ group: 'models',
84
+ status: 'skip',
85
+ summary: 'no request/header in this session',
86
+ };
87
+ }
88
+ return {
89
+ id: 'models.last-request',
90
+ group: 'models',
91
+ status: 'ok',
92
+ summary: `Last request: ${modelRef.provider}/${modelRef.model}`,
93
+ detail: modelRef.reasoningEffort === undefined ? undefined : `effort ${modelRef.reasoningEffort}`,
94
+ evidence: {
95
+ provider: modelRef.provider,
96
+ model: modelRef.model,
97
+ reasoningEffort: modelRef.reasoningEffort ?? null,
98
+ },
99
+ };
100
+ }
101
+ /** Verbose-only LLM catalog validation over the ok route rows. */
102
+ async function catalogChecks(ctx, checks) {
103
+ const llm = ctx.get('llm');
104
+ if (llm?.listProviders === undefined) {
105
+ return [{
106
+ id: 'models.catalog',
107
+ group: 'models',
108
+ status: 'skip',
109
+ summary: 'llm seam not mounted',
110
+ }];
111
+ }
112
+ const providerIds = new Set((await Promise.resolve(llm.listProviders())).map(provider => provider.id));
113
+ const modelCache = new Map();
114
+ const effortCache = new Map();
115
+ const rows = checks.filter(check => check.group === 'models'
116
+ && check.id.startsWith('models.alias.')
117
+ && check.status === 'ok'
118
+ && typeof check.evidence?.provider === 'string'
119
+ && typeof check.evidence?.model === 'string');
120
+ const results = await Promise.all(rows.map(async (check) => {
121
+ const provider = check.evidence.provider;
122
+ const model = check.evidence.model;
123
+ if (!providerIds.has(provider)) {
124
+ return { id: catalogId(check.id), status: 'fail', message: `provider ${provider} missing from listProviders` };
125
+ }
126
+ let modelIds = modelCache.get(provider);
127
+ if (modelIds === undefined) {
128
+ try {
129
+ const listed = llm.listModels === undefined
130
+ ? []
131
+ : (await Promise.resolve(llm.listModels(provider))) ?? [];
132
+ modelIds = new Set(listed.map(entry => entry.id ?? entry.name ?? '').filter(id => id.length > 0));
133
+ }
134
+ catch (error) {
135
+ return { id: catalogId(check.id), status: 'fail', message: `listModels(${provider}) threw: ${String(error)}` };
136
+ }
137
+ modelCache.set(provider, modelIds);
138
+ }
139
+ if (modelIds.size > 0 && !modelIds.has(model)) {
140
+ return { id: catalogId(check.id), status: 'warn', message: `model ${model} missing from listModels(${provider}) (custom provider catalogs can be incomplete)` };
141
+ }
142
+ const cacheKey = `${provider}/${model}`;
143
+ if (!effortCache.has(cacheKey)) {
144
+ try {
145
+ const info = llm.resolveModelInfo === undefined
146
+ ? undefined
147
+ : await Promise.resolve(llm.resolveModelInfo(provider, model));
148
+ effortCache.set(cacheKey, effortIds(info?.reasoning?.efforts));
149
+ }
150
+ catch {
151
+ effortCache.set(cacheKey, undefined);
152
+ }
153
+ }
154
+ const efforts = effortCache.get(cacheKey);
155
+ if (efforts === undefined || efforts.length === 0) {
156
+ return { id: catalogId(check.id), status: 'skip', message: 'effort list unavailable (cannot attribute)' };
157
+ }
158
+ const routeEffort = readRouteEffort(check);
159
+ if (routeEffort !== undefined && !efforts.includes(routeEffort)) {
160
+ return { id: catalogId(check.id), status: 'warn', message: `effort ${routeEffort} not in reasoning.efforts` };
161
+ }
162
+ return { id: catalogId(check.id), status: 'ok', message: `${provider}/${model} in catalog` };
163
+ }));
164
+ return results.map(result => ({
165
+ id: result.id,
166
+ group: 'models',
167
+ status: result.status,
168
+ summary: result.message,
169
+ }));
170
+ }
171
+ /** Catalog check id: the cheap lane gets its own id; others suffix the alias row. */
172
+ function catalogId(aliasId) {
173
+ return aliasId === 'models.alias.haiku' ? 'models.catalog.haiku' : `${aliasId}.catalog`;
174
+ }
175
+ /** Read the effort recorded on the alias row's detail, if any. */
176
+ function readRouteEffort(check) {
177
+ const match = /^effort (.+)$/u.exec(check.detail ?? '');
178
+ return match?.[1];
179
+ }
180
+ /** Normalize string ids and `{ id }` effort entries into a list of ids. */
181
+ function effortIds(efforts) {
182
+ if (efforts === undefined)
183
+ return undefined;
184
+ return efforts.flatMap(entry => {
185
+ if (typeof entry === 'string')
186
+ return entry.length > 0 ? [entry] : [];
187
+ return typeof entry.id === 'string' && entry.id.length > 0 ? [entry.id] : [];
188
+ });
189
+ }
190
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/checks/models.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * `plugins` checks for `/doctor`: per-plugin component load results,
3
+ * duck-typing the `ccPlugins` seam (same spirit as `/plugin`).
4
+ * @module @dsh-cc/command-doctor/checks/plugins
5
+ */
6
+ import type { Context } from '@deepseek-ai/cordis';
7
+ import type { Check } from '../report.ts';
8
+ /** Duck-typed `ccPlugins` component face used here. */
9
+ export interface PluginComponent {
10
+ readonly kind: string;
11
+ readonly loaded: number;
12
+ readonly skipped: number;
13
+ readonly failed: number;
14
+ readonly reasons?: readonly string[];
15
+ }
16
+ /** Duck-typed `ccPlugins` entry face used here. */
17
+ export interface PluginEntry {
18
+ readonly name: string;
19
+ readonly root: string;
20
+ readonly components: readonly PluginComponent[];
21
+ }
22
+ /** Collect the plugins group checks. */
23
+ export declare function pluginChecks(ctx: Context): Check[];
24
+ //# sourceMappingURL=plugins.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../../src/checks/plugins.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAEzC,uDAAuD;AACvD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC;AAED,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,UAAU,EAAE,SAAS,eAAe,EAAE,CAAA;CAChD;AAED,wCAAwC;AACxC,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,EAAE,CAsBlD"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * `plugins` checks for `/doctor`: per-plugin component load results,
3
+ * duck-typing the `ccPlugins` seam (same spirit as `/plugin`).
4
+ * @module @dsh-cc/command-doctor/checks/plugins
5
+ */
6
+ /** Collect the plugins group checks. */
7
+ export function pluginChecks(ctx) {
8
+ const plugins = ctx.get('ccPlugins');
9
+ if (plugins?.list === undefined) {
10
+ return [{
11
+ id: 'plugins.registry',
12
+ group: 'plugins',
13
+ status: 'skip',
14
+ summary: 'cc-shell-glue absent',
15
+ }];
16
+ }
17
+ const entries = plugins.list();
18
+ const checks = [{
19
+ id: 'plugins.overview',
20
+ group: 'plugins',
21
+ status: 'ok',
22
+ summary: `${entries.length} plugins`,
23
+ evidence: { count: entries.length },
24
+ }];
25
+ for (const entry of entries)
26
+ checks.push(entryCheck(entry));
27
+ return checks;
28
+ }
29
+ /** One plugin row: warn when any component skipped or failed. */
30
+ function entryCheck(entry) {
31
+ const id = `plugins.${entry.name}`;
32
+ const bad = entry.components.filter(component => component.skipped > 0 || component.failed > 0);
33
+ if (bad.length === 0) {
34
+ return {
35
+ id,
36
+ group: 'plugins',
37
+ status: 'ok',
38
+ summary: `${entry.name}: all components loaded`,
39
+ evidence: { root: entry.root },
40
+ };
41
+ }
42
+ const reasons = bad.flatMap(component => component.reasons ?? []);
43
+ return {
44
+ id,
45
+ group: 'plugins',
46
+ status: 'warn',
47
+ summary: `${entry.name}: ${bad.length} component kind(s) with skipped/failed entries`,
48
+ detail: bad
49
+ .map(component => `${component.kind}: skipped ${component.skipped}, failed ${component.failed}`)
50
+ .join('; '),
51
+ fix: reasons.length === 0 ? undefined : `review reasons: ${reasons.join('; ')}`,
52
+ evidence: { root: entry.root, skipped: bad.reduce((total, c) => total + c.skipped, 0) },
53
+ };
54
+ }
55
+ //# sourceMappingURL=plugins.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugins.js","sourceRoot":"","sources":["../../src/checks/plugins.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAqBH,wCAAwC;AACxC,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,WAAW,CAEtB,CAAA;IACb,IAAI,OAAO,EAAE,IAAI,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,CAAC;gBACN,EAAE,EAAE,kBAAkB;gBACtB,KAAK,EAAE,SAAS;gBAChB,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,sBAAsB;aAChC,CAAC,CAAA;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAA;IAC9B,MAAM,MAAM,GAAY,CAAC;YACvB,EAAE,EAAE,kBAAkB;YACtB,KAAK,EAAE,SAAS;YAChB,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,UAAU;YACpC,QAAQ,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE;SACpC,CAAC,CAAA;IACF,KAAK,MAAM,KAAK,IAAI,OAAO;QAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAA;IAC3D,OAAO,MAAM,CAAA;AACf,CAAC;AAED,iEAAiE;AACjE,SAAS,UAAU,CAAC,KAAkB;IACpC,MAAM,EAAE,GAAG,WAAW,KAAK,CAAC,IAAI,EAAE,CAAA;IAClC,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,GAAG,CAAC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAC/F,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO;YACL,EAAE;YACF,KAAK,EAAE,SAAS;YAChB,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE,GAAG,KAAK,CAAC,IAAI,yBAAyB;YAC/C,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE;SAC/B,CAAA;IACH,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,IAAI,EAAE,CAAC,CAAA;IACjE,OAAO;QACL,EAAE;QACF,KAAK,EAAE,SAAS;QAChB,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,GAAG,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,gDAAgD;QACrF,MAAM,EAAE,GAAG;aACR,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,IAAI,aAAa,SAAS,CAAC,OAAO,YAAY,SAAS,CAAC,MAAM,EAAE,CAAC;aAC/F,IAAI,CAAC,IAAI,CAAC;QACb,GAAG,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,mBAAmB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAC/E,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE;KACxF,CAAA;AACH,CAAC"}