@devcortex/cli 1.3.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 (65) hide show
  1. package/dist/commands/export.d.ts +9 -0
  2. package/dist/commands/export.d.ts.map +1 -0
  3. package/dist/commands/export.js +49 -0
  4. package/dist/commands/export.js.map +1 -0
  5. package/dist/commands/import.d.ts +21 -0
  6. package/dist/commands/import.d.ts.map +1 -0
  7. package/dist/commands/import.js +237 -0
  8. package/dist/commands/import.js.map +1 -0
  9. package/dist/commands/init.d.ts +22 -0
  10. package/dist/commands/init.d.ts.map +1 -0
  11. package/dist/commands/init.js +225 -0
  12. package/dist/commands/init.js.map +1 -0
  13. package/dist/commands/issue.d.ts +8 -0
  14. package/dist/commands/issue.d.ts.map +1 -0
  15. package/dist/commands/issue.js +42 -0
  16. package/dist/commands/issue.js.map +1 -0
  17. package/dist/commands/keys.d.ts +23 -0
  18. package/dist/commands/keys.d.ts.map +1 -0
  19. package/dist/commands/keys.js +133 -0
  20. package/dist/commands/keys.js.map +1 -0
  21. package/dist/commands/list.d.ts +20 -0
  22. package/dist/commands/list.d.ts.map +1 -0
  23. package/dist/commands/list.js +163 -0
  24. package/dist/commands/list.js.map +1 -0
  25. package/dist/commands/login.d.ts +9 -0
  26. package/dist/commands/login.d.ts.map +1 -0
  27. package/dist/commands/login.js +91 -0
  28. package/dist/commands/login.js.map +1 -0
  29. package/dist/commands/logs.d.ts +22 -0
  30. package/dist/commands/logs.d.ts.map +1 -0
  31. package/dist/commands/logs.js +172 -0
  32. package/dist/commands/logs.js.map +1 -0
  33. package/dist/commands/start.d.ts +9 -0
  34. package/dist/commands/start.d.ts.map +1 -0
  35. package/dist/commands/start.js +88 -0
  36. package/dist/commands/start.js.map +1 -0
  37. package/dist/commands/status.d.ts +22 -0
  38. package/dist/commands/status.d.ts.map +1 -0
  39. package/dist/commands/status.js +179 -0
  40. package/dist/commands/status.js.map +1 -0
  41. package/dist/commands/test-mcp.d.ts +7 -0
  42. package/dist/commands/test-mcp.d.ts.map +1 -0
  43. package/dist/commands/test-mcp.js +115 -0
  44. package/dist/commands/test-mcp.js.map +1 -0
  45. package/dist/commands/update.d.ts +9 -0
  46. package/dist/commands/update.d.ts.map +1 -0
  47. package/dist/commands/update.js +124 -0
  48. package/dist/commands/update.js.map +1 -0
  49. package/dist/index.d.ts +4 -0
  50. package/dist/index.d.ts.map +1 -0
  51. package/dist/index.js +48 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/lib/api.d.ts +8 -0
  54. package/dist/lib/api.d.ts.map +1 -0
  55. package/dist/lib/api.js +30 -0
  56. package/dist/lib/api.js.map +1 -0
  57. package/dist/lib/auth.d.ts +20 -0
  58. package/dist/lib/auth.d.ts.map +1 -0
  59. package/dist/lib/auth.js +16 -0
  60. package/dist/lib/auth.js.map +1 -0
  61. package/dist/lib/config.d.ts +16 -0
  62. package/dist/lib/config.d.ts.map +1 -0
  63. package/dist/lib/config.js +29 -0
  64. package/dist/lib/config.js.map +1 -0
  65. package/package.json +41 -0
@@ -0,0 +1,172 @@
1
+ import { Chalk } from 'chalk';
2
+ import { io } from 'socket.io-client';
3
+ // Force colours even in non-TTY environments (piped output, tests)
4
+ const chalk = new Chalk({ level: 3 });
5
+ import { readLinkFile } from './init.js';
6
+ import { apiJson } from '../lib/api.js';
7
+ import { getToken } from '../lib/config.js';
8
+ // Reverse-lookup cache: DB cuid → human-readable reqId (e.g. "REQ-001")
9
+ const reqIdCache = new Map();
10
+ export function formatEvent(event) {
11
+ const ts = new Date(event.createdAt).toLocaleTimeString('en-US', { hour12: false });
12
+ const actor = event.actorType ?? 'SYSTEM';
13
+ const reqLabel = event.payload?.['reqId'] ?? '';
14
+ const desc = buildDescription(event);
15
+ // Append reqId suffix so it's always visible; skip if already in desc
16
+ const suffix = reqLabel && !desc.includes(reqLabel) ? ` ${reqLabel}` : '';
17
+ // AC-3: Colours
18
+ let line = `[${ts}] ${actor.padEnd(6)} ${desc}${suffix}`;
19
+ if (actor === 'AGENT')
20
+ line = chalk.blue(line);
21
+ else if (actor === 'HUMAN')
22
+ line = chalk.green(line);
23
+ else if (event.eventType.includes('ISSUE'))
24
+ line = chalk.yellow(line);
25
+ else if (event.eventType.includes('ERROR'))
26
+ line = chalk.red(line);
27
+ return line;
28
+ }
29
+ function buildDescription(event) {
30
+ const { eventType, payload } = event;
31
+ // reqId may be in payload; for REQUIREMENT_STATUS_CHANGED it is not — look it up from cache
32
+ const reqId = payload?.['reqId']
33
+ ?? (event.requirementId ? reqIdCache.get(event.requirementId) : undefined);
34
+ if (reqId) {
35
+ if (eventType === 'REQUIREMENT_STATUS_CHANGED') {
36
+ const to = payload?.['to'] ?? '';
37
+ return `${reqId} → ${to}`;
38
+ }
39
+ if (eventType === 'AC_VERIFIED') {
40
+ const acId = payload?.['acId'] ?? '';
41
+ const result = payload?.['result'] ?? '';
42
+ return `${reqId} ${acId} → ${result}`;
43
+ }
44
+ }
45
+ if (eventType === 'ISSUE_CREATED') {
46
+ const issueId = payload?.['issueId'] ?? '';
47
+ const severity = payload?.['severity'] ?? '';
48
+ return `${issueId} created · ${severity}${reqId ? ` · ${reqId}` : ''}`;
49
+ }
50
+ return eventType;
51
+ }
52
+ function matchesReq(event, reqId, dbId) {
53
+ // Match by DB cuid (most reliable — set on all requirement-related events)
54
+ if (dbId) {
55
+ if (event.requirementId === dbId)
56
+ return true;
57
+ if (event.entityId === dbId)
58
+ return true;
59
+ }
60
+ // Fallback: match human-readable reqId in payload
61
+ if (event.payload?.['reqId'] === reqId)
62
+ return true;
63
+ if (event.payload && JSON.stringify(event.payload).includes(reqId))
64
+ return true;
65
+ return false;
66
+ }
67
+ async function fetchRequirements(orgSlug, projectId, apiUrl) {
68
+ const res = await apiJson(`/organisations/${orgSlug}/projects/${projectId}/requirements`, {}, apiUrl);
69
+ const reqs = res.data ?? [];
70
+ // Populate reverse-lookup cache so buildDescription can resolve requirementId → reqId
71
+ for (const r of reqs)
72
+ reqIdCache.set(r.id, r.reqId);
73
+ return reqs;
74
+ }
75
+ async function resolveReqDbId(orgSlug, projectId, reqId, apiUrl) {
76
+ try {
77
+ const reqs = await fetchRequirements(orgSlug, projectId, apiUrl);
78
+ return reqs.find((r) => r.reqId === reqId)?.id;
79
+ }
80
+ catch {
81
+ return undefined;
82
+ }
83
+ }
84
+ export async function runLogs(opts, cwd = process.cwd()) {
85
+ const link = readLinkFile(cwd);
86
+ if (!link) {
87
+ console.error('✗ No project linked. Run dcx init first.');
88
+ process.exit(1);
89
+ }
90
+ const apiUrlOverride = opts.apiUrl ?? link.apiUrl;
91
+ const follow = opts.noFollow ? false : (opts.follow ?? true);
92
+ // Always populate reqIdCache so REQUIREMENT_STATUS_CHANGED descriptions show REQ-NNN.
93
+ // When --req is specified, also resolve the DB cuid for accurate event filtering.
94
+ let reqDbId;
95
+ if (opts.req) {
96
+ reqDbId = await resolveReqDbId(link.orgSlug, link.projectId, opts.req, apiUrlOverride);
97
+ }
98
+ else {
99
+ try {
100
+ await fetchRequirements(link.orgSlug, link.projectId, apiUrlOverride);
101
+ }
102
+ catch { /* best-effort */ }
103
+ }
104
+ // AC-5: --no-follow: fetch recent events and exit
105
+ if (!follow) {
106
+ const params = new URLSearchParams({ limit: '50' });
107
+ // ISS-006: audit endpoint rejects query params — fetch all and filter client-side
108
+ const events = await apiJson(`/organisations/${link.orgSlug}/projects/${link.projectId}/audit-events?${params}`, {}, apiUrlOverride);
109
+ const list = events.events ?? events.data ?? [];
110
+ for (const e of list.reverse()) {
111
+ // AC-4: Filter client-side to match reqId in any field
112
+ if (opts.req && !matchesReq(e, opts.req, reqDbId))
113
+ continue;
114
+ console.log(formatEvent(e));
115
+ }
116
+ return;
117
+ }
118
+ // AC-1: Connect to Socket.io WebSocket
119
+ const token = getToken();
120
+ const wsUrl = `${link.apiUrl}/events`;
121
+ const socket = io(wsUrl, {
122
+ transports: ['websocket'],
123
+ reconnectionDelay: 1000,
124
+ reconnectionDelayMax: 10000,
125
+ });
126
+ let reconnectCount = 0;
127
+ socket.on('connect', () => {
128
+ socket.emit('join-project', {
129
+ projectId: link.projectId,
130
+ token,
131
+ });
132
+ });
133
+ socket.on('audit-event', (event) => {
134
+ // AC-4: req filter client-side (ISS-006: server rejects query params)
135
+ if (opts.req && !matchesReq(event, opts.req, reqDbId))
136
+ return;
137
+ console.log(formatEvent(event));
138
+ });
139
+ // AC-7: Reconnection with backoff
140
+ socket.on('disconnect', () => {
141
+ reconnectCount++;
142
+ process.stderr.write(`[reconnecting... attempt ${reconnectCount}]\n`);
143
+ });
144
+ socket.on('connect_error', (e) => {
145
+ console.log('[logs] error:', e.message);
146
+ process.stderr.write('[connection error — retrying...]\n');
147
+ });
148
+ // AC-6: Clean disconnect on Ctrl+C
149
+ process.on('SIGINT', () => {
150
+ socket.disconnect();
151
+ process.exit(0);
152
+ });
153
+ }
154
+ export function registerLogs(program) {
155
+ program
156
+ .command('logs')
157
+ .description('Stream live audit events to the terminal')
158
+ .option('--req <reqId>', 'Filter to one requirement')
159
+ .option('--since <duration>', 'Events from last duration (e.g. 1h)')
160
+ .option('--follow', 'Keep streaming (default: true)')
161
+ .option('--no-follow', 'Show recent events and exit')
162
+ .option('--api-url <url>', 'API URL override')
163
+ .action(async (opts) => {
164
+ const token = getToken();
165
+ if (!token) {
166
+ console.error('✗ Not logged in — run dcx login first');
167
+ process.exit(1);
168
+ }
169
+ await runLogs(opts);
170
+ });
171
+ }
172
+ //# sourceMappingURL=logs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.js","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { Command } from 'commander';
2
+ export interface StartOptions {
3
+ agent?: string;
4
+ noInit?: boolean;
5
+ apiUrl?: string;
6
+ }
7
+ export declare function runStart(opts: StartOptions, cwd?: string): Promise<void>;
8
+ export declare function registerStart(program: Command): void;
9
+ //# sourceMappingURL=start.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAeD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,SAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwDrF;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAWpD"}
@@ -0,0 +1,88 @@
1
+ import * as clack from '@clack/prompts';
2
+ import { spawnSync } from 'node:child_process';
3
+ import { existsSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { runUpdate } from './update.js';
6
+ function detectAgent() {
7
+ const claudeResult = spawnSync('which', ['claude'], { encoding: 'utf8' });
8
+ const opencodeResult = spawnSync('which', ['opencode'], { encoding: 'utf8' });
9
+ const hasC = claudeResult.status === 0;
10
+ const hasO = opencodeResult.status === 0;
11
+ if (hasC && !hasO)
12
+ return 'claude';
13
+ if (hasO && !hasC)
14
+ return 'opencode';
15
+ if (hasC && hasO)
16
+ return null; // need user selection
17
+ return null;
18
+ }
19
+ export async function runStart(opts, cwd = process.cwd()) {
20
+ // AC-5: Check link file
21
+ const linkPath = join(cwd, '.devcortex-link.json');
22
+ if (!existsSync(linkPath)) {
23
+ console.error('✗ No project linked. Run dcx init first.');
24
+ process.exit(1);
25
+ }
26
+ // AC-1: Refresh CLAUDE.md first
27
+ if (!opts.noInit) {
28
+ try {
29
+ await runUpdate({ agent: opts.agent, apiUrl: opts.apiUrl }, cwd);
30
+ }
31
+ catch {
32
+ // non-fatal — proceed with existing CLAUDE.md
33
+ }
34
+ }
35
+ // AC-2/3: Agent detection or explicit flag
36
+ let agentCmd = opts.agent;
37
+ if (!agentCmd) {
38
+ const detected = detectAgent();
39
+ if (detected === null) {
40
+ // Both found — prompt
41
+ const claudeResult = spawnSync('which', ['claude'], { encoding: 'utf8' });
42
+ const opencodeResult = spawnSync('which', ['opencode'], { encoding: 'utf8' });
43
+ if (claudeResult.status === 0 && opencodeResult.status === 0) {
44
+ const choice = await clack.select({
45
+ message: 'Multiple agents found. Which would you like to use?',
46
+ options: [
47
+ { value: 'claude', label: 'Claude Code' },
48
+ { value: 'opencode', label: 'OpenCode' },
49
+ ],
50
+ });
51
+ if (clack.isCancel(choice)) {
52
+ clack.cancel('Cancelled');
53
+ process.exit(0);
54
+ }
55
+ agentCmd = choice;
56
+ }
57
+ else {
58
+ // AC-4: Neither found
59
+ console.error('✗ No agent found. Install Claude Code or OpenCode:');
60
+ console.error(' Claude Code: npm install -g @anthropic-ai/claude-code');
61
+ console.error(' OpenCode: npm install -g @opencode-ai/opencode');
62
+ process.exit(1);
63
+ }
64
+ }
65
+ else {
66
+ agentCmd = detected;
67
+ }
68
+ }
69
+ clack.note(`✔ Launching ${agentCmd}...`);
70
+ // AC-6: Launch as child process inheriting stdio
71
+ const result = spawnSync(agentCmd, [], { stdio: 'inherit', cwd });
72
+ // AC-7: Show exit message
73
+ console.log('\n✔ Agent session ended. Run dcx status to see updates.');
74
+ process.exit(result.status ?? 0);
75
+ }
76
+ export function registerStart(program) {
77
+ program
78
+ .command('start')
79
+ .description('Refresh CLAUDE.md and launch the configured AI agent')
80
+ .option('--agent <name>', 'Agent to launch: claude | opencode')
81
+ .option('--no-init', 'Skip dcx update, launch agent immediately')
82
+ .option('--api-url <url>', 'API URL override')
83
+ .action(async (opts) => {
84
+ clack.intro('DevCortex Start');
85
+ await runStart(opts);
86
+ });
87
+ }
88
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { Command } from 'commander';
2
+ export interface StatusOptions {
3
+ json?: boolean;
4
+ apiUrl?: string;
5
+ }
6
+ export interface StatusResult {
7
+ projectName: string;
8
+ orgSlug: string;
9
+ specVersion: string;
10
+ specStatus: string;
11
+ reqTotal: number;
12
+ reqVerified: number;
13
+ issuesOpen: number;
14
+ issuesHigh: number;
15
+ issuesMedium: number;
16
+ lastActivity: string;
17
+ mcpEndpoint: string;
18
+ mcpReachable: boolean;
19
+ }
20
+ export declare function runStatus(opts: StatusOptions, cwd?: string): Promise<StatusResult>;
21
+ export declare function registerStatus(program: Command): void;
22
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOzC,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA6CD,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AA4CD,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,SAAgB,GAAG,OAAO,CAAC,YAAY,CAAC,CAsH/F;AAWD,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAWrD"}
@@ -0,0 +1,179 @@
1
+ import { readLinkFile } from './init.js';
2
+ import { apiJson, isApiReachable } from '../lib/api.js';
3
+ import { getToken } from '../lib/config.js';
4
+ import { readFileSync, existsSync } from 'node:fs';
5
+ import { join } from 'node:path';
6
+ function readApiKey(cwd) {
7
+ const mcpPath = join(cwd, '.mcp.json');
8
+ if (!existsSync(mcpPath))
9
+ return null;
10
+ try {
11
+ const mcp = JSON.parse(readFileSync(mcpPath, 'utf8'));
12
+ return mcp?.mcpServers?.devcortex?.headers?.['x-api-key'] ?? null;
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ function decodeJwtExpiry(token) {
19
+ try {
20
+ const parts = token.split('.');
21
+ if (parts.length !== 3)
22
+ return { valid: false };
23
+ const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf8'));
24
+ if (!payload.exp)
25
+ return { valid: true };
26
+ const expiresAt = new Date(payload.exp * 1000);
27
+ const expired = expiresAt < new Date();
28
+ return { valid: true, expiresAt, expired };
29
+ }
30
+ catch {
31
+ return { valid: false };
32
+ }
33
+ }
34
+ function formatTimeRemaining(expiresAt) {
35
+ const diff = expiresAt.getTime() - Date.now();
36
+ if (diff <= 0)
37
+ return 'EXPIRED';
38
+ const totalMins = Math.floor(diff / 60000);
39
+ const days = Math.floor(totalMins / 1440);
40
+ const hours = Math.floor((totalMins % 1440) / 60);
41
+ const mins = totalMins % 60;
42
+ if (days > 0)
43
+ return `${days}d ${hours}h`;
44
+ if (hours > 0)
45
+ return `${hours}h ${mins}m`;
46
+ return `${mins}m`;
47
+ }
48
+ export async function runStatus(opts, cwd = process.cwd()) {
49
+ // AC-5: Check link file
50
+ const link = readLinkFile(cwd);
51
+ if (!link) {
52
+ console.error('✗ No project linked. Run dcx init first.');
53
+ process.exit(1);
54
+ }
55
+ const apiUrlOverride = opts.apiUrl ?? link.apiUrl;
56
+ const token = getToken();
57
+ const apiKey = readApiKey(cwd);
58
+ // Decode token expiry without making an API call
59
+ const tokenInfo = token ? decodeJwtExpiry(token) : { valid: false };
60
+ // Fetch all data in parallel
61
+ const [summary, issues, audit, mcpOk, mcpHealth] = await Promise.allSettled([
62
+ apiJson(`/organisations/${link.orgSlug}/projects/${link.projectId}/summary`, {}, apiUrlOverride),
63
+ apiJson(`/organisations/${link.orgSlug}/projects/${link.projectId}/issues`, {}, apiUrlOverride),
64
+ apiJson(`/organisations/${link.orgSlug}/projects/${link.projectId}/audit-events`, {}, apiUrlOverride),
65
+ isApiReachable(apiUrlOverride),
66
+ apiKey
67
+ ? fetch(`${apiUrlOverride}/health/mcp`, { headers: { 'x-api-key': apiKey } })
68
+ .then((r) => (r.ok ? r.json() : null))
69
+ .catch(() => null)
70
+ : Promise.resolve(null),
71
+ ]);
72
+ const summaryData = summary.status === 'fulfilled' ? summary.value : null;
73
+ const issueList = issues.status === 'fulfilled'
74
+ ? (issues.value.data ?? issues.value.issues ?? [])
75
+ : [];
76
+ const auditData = audit.status === 'fulfilled'
77
+ ? (audit.value.events ?? audit.value.data ?? [])
78
+ : [];
79
+ const reachable = mcpOk.status === 'fulfilled' ? mcpOk.value : false;
80
+ const mcpData = mcpHealth.status === 'fulfilled' ? mcpHealth.value : null;
81
+ const result = {
82
+ projectName: link.projectName,
83
+ orgSlug: link.orgSlug,
84
+ specVersion: summaryData?.latestSpec?.version ?? 'none',
85
+ specStatus: summaryData?.latestSpec?.status ?? 'NONE',
86
+ reqTotal: summaryData?.requirementsTotal ?? 0,
87
+ reqVerified: summaryData?.requirementsVerified ?? 0,
88
+ issuesOpen: issueList.length,
89
+ issuesHigh: issueList.filter((i) => i.severity === 'HIGH' || i.severity === 'CRITICAL').length,
90
+ issuesMedium: issueList.filter((i) => i.severity === 'MEDIUM').length,
91
+ lastActivity: auditData[0]
92
+ ? `${auditData[0].reqId ?? auditData[0].eventType} (${timeAgo(auditData[0].createdAt)})`
93
+ : 'no activity',
94
+ mcpEndpoint: `${link.apiUrl}/mcp`,
95
+ mcpReachable: reachable,
96
+ };
97
+ if (opts.json) {
98
+ // AC-4: Machine-readable output
99
+ console.log(JSON.stringify(result));
100
+ return result;
101
+ }
102
+ // REQ-088: Box-format output
103
+ const verifiedPct = result.reqTotal > 0
104
+ ? Math.round((result.reqVerified / result.reqTotal) * 100)
105
+ : 0;
106
+ const tokenLine = (() => {
107
+ if (!token || !tokenInfo.valid)
108
+ return 'not logged in';
109
+ if (tokenInfo.expired)
110
+ return 'EXPIRED — run: dcx login';
111
+ if (tokenInfo.expiresAt) {
112
+ const remaining = formatTimeRemaining(tokenInfo.expiresAt);
113
+ const nearExpiry = tokenInfo.expiresAt.getTime() - Date.now() < 24 * 60 * 60 * 1000;
114
+ return `valid — expires in ${remaining}${nearExpiry ? ' ⚠' : ''}`;
115
+ }
116
+ return 'valid';
117
+ })();
118
+ const mcpLine = mcpData
119
+ ? `✔ reachable (${mcpData.toolsRegistered ?? '?'} tools)`
120
+ : '✗ not reachable';
121
+ const reqsLine = `${result.reqTotal} total · ${result.issuesOpen} issues · ${verifiedPct}% verified`;
122
+ const issuesLine = `${result.issuesOpen} open · ${result.issuesHigh} high · ${result.issuesMedium} medium`;
123
+ const lastUpdated = link['lastUpdated'];
124
+ const lines = [
125
+ ` Org: ${result.orgSlug}`,
126
+ ` Project: ${result.projectName}`,
127
+ ` API: ${apiUrlOverride}`,
128
+ ` Token: ${tokenLine}`,
129
+ ` MCP: ${mcpLine}`,
130
+ ` Spec: v${result.specVersion} ${result.specStatus}`,
131
+ ` Requirements: ${reqsLine}`,
132
+ ` Issues: ${issuesLine}`,
133
+ ` Updated: ${lastUpdated ?? 'never'}`,
134
+ ];
135
+ const width = Math.max(...lines.map((l) => l.length)) + 2;
136
+ const bar = '─'.repeat(width - 2);
137
+ console.log(`┌─ DevCortex Status ${bar.slice(18)}┐`);
138
+ for (const line of lines) {
139
+ const pad = width - line.length - 1;
140
+ console.log(`│${line}${' '.repeat(pad)}│`);
141
+ }
142
+ console.log(`└${'─'.repeat(width - 1)}┘`);
143
+ // Token expiry warnings
144
+ if (token && tokenInfo.valid && tokenInfo.expiresAt) {
145
+ if (tokenInfo.expired) {
146
+ console.log(`\n✗ Token EXPIRED — run: dcx login`);
147
+ }
148
+ else if (tokenInfo.expiresAt.getTime() - Date.now() < 24 * 60 * 60 * 1000) {
149
+ console.log(`\n⚠ Token expires soon — run: dcx login to refresh`);
150
+ }
151
+ }
152
+ return result;
153
+ }
154
+ function timeAgo(iso) {
155
+ const diff = Date.now() - new Date(iso).getTime();
156
+ const mins = Math.floor(diff / 60000);
157
+ if (mins < 1)
158
+ return 'just now';
159
+ if (mins < 60)
160
+ return `${mins} minute${mins === 1 ? '' : 's'} ago`;
161
+ const hrs = Math.floor(mins / 60);
162
+ return `${hrs} hour${hrs === 1 ? '' : 's'} ago`;
163
+ }
164
+ export function registerStatus(program) {
165
+ program
166
+ .command('status')
167
+ .description('Show project health summary')
168
+ .option('--json', 'Machine-readable JSON output')
169
+ .option('--api-url <url>', 'API URL override')
170
+ .action(async (opts) => {
171
+ const token = getToken();
172
+ if (!token) {
173
+ console.error('✗ Not logged in — run dcx login first');
174
+ process.exit(1);
175
+ }
176
+ await runStatus(opts);
177
+ });
178
+ }
179
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Command } from 'commander';
2
+ export interface TestMcpOptions {
3
+ apiUrl?: string;
4
+ }
5
+ export declare function runTestMcp(opts: TestMcpOptions, cwd?: string): Promise<boolean>;
6
+ export declare function registerTestMcp(program: Command): void;
7
+ //# sourceMappingURL=test-mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-mcp.d.ts","sourceRoot":"","sources":["../../src/commands/test-mcp.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMzC,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAiCD,wBAAsB,UAAU,CAC9B,IAAI,EAAE,cAAc,EACpB,GAAG,SAAgB,GAClB,OAAO,CAAC,OAAO,CAAC,CAiGlB;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAStD"}
@@ -0,0 +1,115 @@
1
+ import { readFileSync, existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { readLinkFile } from './init.js';
4
+ import { getApiUrl } from '../lib/config.js';
5
+ function readApiKey(cwd) {
6
+ const mcpPath = join(cwd, '.mcp.json');
7
+ if (!existsSync(mcpPath))
8
+ return null;
9
+ try {
10
+ const mcp = JSON.parse(readFileSync(mcpPath, 'utf8'));
11
+ return mcp?.mcpServers?.devcortex?.headers?.['x-api-key'] ?? null;
12
+ }
13
+ catch {
14
+ return null;
15
+ }
16
+ }
17
+ export async function runTestMcp(opts, cwd = process.cwd()) {
18
+ const link = readLinkFile(cwd);
19
+ if (!link) {
20
+ console.error('✗ No project linked — run: dcx init to link a project');
21
+ return false;
22
+ }
23
+ const apiUrl = opts.apiUrl ?? link.apiUrl ?? getApiUrl();
24
+ const apiKey = readApiKey(cwd);
25
+ let allPass = true;
26
+ // Check 1: API reachable
27
+ let apiReachable = false;
28
+ try {
29
+ const res = await fetch(`${apiUrl}/health`);
30
+ apiReachable = res.ok;
31
+ }
32
+ catch {
33
+ apiReachable = false;
34
+ }
35
+ if (apiReachable) {
36
+ console.log(`✔ 1. API reachable`);
37
+ }
38
+ else {
39
+ console.error(`✗ Cannot connect to DevCortex API at ${apiUrl}`);
40
+ return false;
41
+ }
42
+ if (!apiKey) {
43
+ console.log(`✗ 2. API key valid`);
44
+ console.error(` No API key found — run: dcx init to generate an API key`);
45
+ console.log(`✗ 3. Project accessible`);
46
+ console.log(`✗ 4. MCP tools available`);
47
+ return false;
48
+ }
49
+ // Check 2-4: MCP health endpoint
50
+ let health = null;
51
+ let mcpStatus = 0;
52
+ try {
53
+ const res = await fetch(`${apiUrl}/health/mcp`, {
54
+ headers: { 'x-api-key': apiKey },
55
+ });
56
+ mcpStatus = res.status;
57
+ if (res.ok) {
58
+ health = (await res.json());
59
+ }
60
+ }
61
+ catch {
62
+ mcpStatus = 0;
63
+ }
64
+ // Check 2: API key valid
65
+ if (mcpStatus === 401) {
66
+ console.error(`✗ API key invalid — run: dcx keys regenerate`);
67
+ return false;
68
+ }
69
+ if (mcpStatus === 404) {
70
+ console.log(`✔ 2. API key valid`);
71
+ console.log(`✗ 3. Project accessible`);
72
+ console.error(` Project not found — run: dcx init to relink`);
73
+ console.log(`✗ 4. MCP tools available`);
74
+ return false;
75
+ }
76
+ if (!health) {
77
+ console.error(`✗ API key invalid — run: dcx keys regenerate`);
78
+ return false;
79
+ }
80
+ console.log(`✔ 2. API key valid`);
81
+ // Check 3: Project accessible
82
+ if (health.projectId) {
83
+ console.log(`✔ 3. Project accessible`);
84
+ }
85
+ else {
86
+ console.log(`✗ 3. Project accessible`);
87
+ console.error(` Project not found — run: dcx init to relink`);
88
+ allPass = false;
89
+ }
90
+ // Check 4: MCP tools available
91
+ if (health.toolsRegistered > 0) {
92
+ console.log(`✔ 4. MCP tools available`);
93
+ }
94
+ else {
95
+ console.log(`✗ 4. MCP tools available`);
96
+ console.error(` No MCP tools registered — check API configuration`);
97
+ allPass = false;
98
+ }
99
+ if (allPass) {
100
+ console.log(`\n✔ MCP connection healthy — ${health.toolsRegistered} tools registered for ${health.orgSlug}/${link.projectName}`);
101
+ }
102
+ return allPass;
103
+ }
104
+ export function registerTestMcp(program) {
105
+ program
106
+ .command('test-mcp')
107
+ .description('Self-diagnose MCP connection health')
108
+ .option('--api-url <url>', 'API URL override')
109
+ .action(async (opts) => {
110
+ const ok = await runTestMcp(opts);
111
+ if (!ok)
112
+ process.exit(1);
113
+ });
114
+ }
115
+ //# sourceMappingURL=test-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-mcp.js","sourceRoot":"","sources":["../../src/commands/test-mcp.ts"],"names":[],"mappings":"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"}