devworkspace 0.2.2 → 0.3.1

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 (80) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/README.md +5 -4
  3. package/dist/agents/claude/adapter.d.ts +3 -14
  4. package/dist/agents/claude/adapter.js +46 -49
  5. package/dist/agents/claude/adapter.js.map +1 -1
  6. package/dist/agents/claude/content.js +1 -1
  7. package/dist/agents/claude/content.js.map +1 -1
  8. package/dist/agents/codex/adapter.d.ts +2 -0
  9. package/dist/agents/codex/adapter.js +61 -0
  10. package/dist/agents/codex/adapter.js.map +1 -0
  11. package/dist/agents/copilot/adapter.d.ts +2 -0
  12. package/dist/agents/copilot/adapter.js +62 -0
  13. package/dist/agents/copilot/adapter.js.map +1 -0
  14. package/dist/agents/cursor/adapter.d.ts +2 -0
  15. package/dist/agents/cursor/adapter.js +127 -0
  16. package/dist/agents/cursor/adapter.js.map +1 -0
  17. package/dist/agents/index.d.ts +15 -0
  18. package/dist/agents/index.js +54 -0
  19. package/dist/agents/index.js.map +1 -0
  20. package/dist/agents/shared.d.ts +20 -0
  21. package/dist/agents/shared.js +76 -0
  22. package/dist/agents/shared.js.map +1 -0
  23. package/dist/agents/types.d.ts +16 -1
  24. package/dist/agents/types.js.map +1 -1
  25. package/dist/cli/args.d.ts +3 -0
  26. package/dist/cli/args.js +1 -0
  27. package/dist/cli/args.js.map +1 -1
  28. package/dist/cli/help.js +15 -8
  29. package/dist/cli/help.js.map +1 -1
  30. package/dist/cli/render.d.ts +4 -1
  31. package/dist/cli/render.js +46 -0
  32. package/dist/cli/render.js.map +1 -1
  33. package/dist/cli/run.js +24 -6
  34. package/dist/cli/run.js.map +1 -1
  35. package/dist/discovery/cache.d.ts +19 -0
  36. package/dist/discovery/cache.js +50 -0
  37. package/dist/discovery/cache.js.map +1 -0
  38. package/dist/index.d.ts +4 -2
  39. package/dist/index.js +2 -1
  40. package/dist/index.js.map +1 -1
  41. package/dist/integrations/adapters/claudePlugin.d.ts +12 -0
  42. package/dist/integrations/adapters/claudePlugin.js +48 -10
  43. package/dist/integrations/adapters/claudePlugin.js.map +1 -1
  44. package/dist/integrations/adapters/pluginSkill.js +5 -0
  45. package/dist/integrations/adapters/pluginSkill.js.map +1 -1
  46. package/dist/security/files.js +10 -2
  47. package/dist/security/files.js.map +1 -1
  48. package/dist/security/redact.js +1 -1
  49. package/dist/security/redact.js.map +1 -1
  50. package/dist/services/agent.d.ts +12 -2
  51. package/dist/services/agent.js +96 -14
  52. package/dist/services/agent.js.map +1 -1
  53. package/dist/services/analysis.d.ts +7 -1
  54. package/dist/services/analysis.js +14 -7
  55. package/dist/services/analysis.js.map +1 -1
  56. package/dist/services/doctor.js +31 -14
  57. package/dist/services/doctor.js.map +1 -1
  58. package/dist/services/refresh.js +1 -1
  59. package/dist/services/refresh.js.map +1 -1
  60. package/dist/services/reset.js +45 -5
  61. package/dist/services/reset.js.map +1 -1
  62. package/dist/services/status.d.ts +2 -0
  63. package/dist/services/status.js +62 -10
  64. package/dist/services/status.js.map +1 -1
  65. package/dist/services/taskContext.d.ts +59 -0
  66. package/dist/services/taskContext.js +164 -0
  67. package/dist/services/taskContext.js.map +1 -0
  68. package/dist/services/tasks.js +6 -1
  69. package/dist/services/tasks.js.map +1 -1
  70. package/dist/tasks/routing.js +16 -10
  71. package/dist/tasks/routing.js.map +1 -1
  72. package/dist/tasks/task.js +6 -2
  73. package/dist/tasks/task.js.map +1 -1
  74. package/dist/verification/scope.js +1 -1
  75. package/dist/verification/scope.js.map +1 -1
  76. package/docs/agents.md +60 -0
  77. package/docs/architecture.md +2 -2
  78. package/docs/benchmarking.md +19 -0
  79. package/docs/knowledge.md +17 -0
  80. package/package.json +1 -1
@@ -1,24 +1,72 @@
1
1
  import path from 'node:path';
2
- import { claudeAdapter } from '../agents/claude/adapter.js';
2
+ import { AGENTS, getAgentAdapter, listAgentAdapters, detectAllAgentFiles, } from '../agents/index.js';
3
3
  import { DevWorkspaceError } from '../errors/index.js';
4
- import { atomicWriteFile } from '../utils/fs.js';
4
+ import { atomicWriteFile, readTextBounded } from '../utils/fs.js';
5
5
  import { assertNoSymlinkEscape, resolveInside } from '../utils/paths.js';
6
6
  import { loadProject, saveProject, requireWorkspace } from '../core/workspace.js';
7
7
  import { withLock } from '../utils/lock.js';
8
8
  import { isoNow } from './common.js';
9
- export const AGENTS = { claude: claudeAdapter };
9
+ import { SECTION_END, SECTION_START } from '../agents/shared.js';
10
+ export { AGENTS, getAgentAdapter, listAgentAdapters, detectAllAgentFiles };
11
+ const strip = (c) => ({
12
+ path: c.path,
13
+ kind: c.kind,
14
+ mode: c.mode,
15
+ note: c.note,
16
+ });
10
17
  export async function installAgent(o, agentId = 'claude') {
11
- const adapter = AGENTS[agentId];
12
- if (!adapter) {
13
- throw new DevWorkspaceError('USAGE', `Unknown agent "${agentId}".`, { hint: `Supported: ${Object.keys(AGENTS).join(', ')}.` });
14
- }
18
+ const normId = agentId.toLowerCase();
15
19
  const ws = await requireWorkspace(o.cwd);
16
20
  const project = await loadProject(ws);
21
+ if (normId === 'all') {
22
+ const adapters = listAgentAdapters();
23
+ const allChanges = [];
24
+ const changeByPath = new Map();
25
+ for (const adapter of adapters) {
26
+ const plan = await adapter.plan({ root: ws.root, projectName: project.name });
27
+ for (const c of plan) {
28
+ allChanges.push(c);
29
+ changeByPath.set(c.path, { change: c, adapterId: adapter.id });
30
+ }
31
+ }
32
+ const conflicts = allChanges.filter((c) => c.kind === 'conflict').length;
33
+ if (o.dryRun) {
34
+ return { agent: 'all', dryRun: true, changes: allChanges.map(strip), conflicts };
35
+ }
36
+ await withLock(ws.dir, async () => {
37
+ for (const c of allChanges) {
38
+ if (c.kind !== 'create' && c.kind !== 'update')
39
+ continue;
40
+ const full = resolveInside(ws.root, c.path);
41
+ await assertNoSymlinkEscape(ws.root, full);
42
+ await atomicWriteFile(full, c.content);
43
+ }
44
+ const fresh = await loadProject(ws);
45
+ const tracked = new Map(fresh.managedFiles.map((m) => [m.path, m]));
46
+ for (const [p, item] of changeByPath) {
47
+ if (item.change.kind !== 'conflict') {
48
+ tracked.set(p, { path: p, mode: item.change.mode, agent: item.adapterId });
49
+ }
50
+ }
51
+ await saveProject(ws, {
52
+ ...fresh,
53
+ managedFiles: [...tracked.values()].sort((a, b) => a.path.localeCompare(b.path)),
54
+ updatedAt: isoNow(o),
55
+ });
56
+ });
57
+ return { agent: 'all', dryRun: false, changes: allChanges.map(strip), conflicts };
58
+ }
59
+ const adapter = getAgentAdapter(normId);
60
+ if (!adapter) {
61
+ const supported = [...new Set([...listAgentAdapters().map((a) => a.id), 'all'])].sort().join(', ');
62
+ throw new DevWorkspaceError('USAGE', `Unknown agent "${agentId}".`, {
63
+ hint: `Supported: ${supported}.`,
64
+ });
65
+ }
17
66
  const plan = await adapter.plan({ root: ws.root, projectName: project.name });
18
- const strip = (c) => ({ path: c.path, kind: c.kind, mode: c.mode, note: c.note });
19
67
  const conflicts = plan.filter((c) => c.kind === 'conflict').length;
20
68
  if (o.dryRun)
21
- return { agent: agentId, dryRun: true, changes: plan.map(strip), conflicts };
69
+ return { agent: adapter.id, dryRun: true, changes: plan.map(strip), conflicts };
22
70
  await withLock(ws.dir, async () => {
23
71
  for (const c of plan) {
24
72
  if (c.kind !== 'create' && c.kind !== 'update')
@@ -29,12 +77,46 @@ export async function installAgent(o, agentId = 'claude') {
29
77
  }
30
78
  const fresh = await loadProject(ws);
31
79
  const tracked = new Map(fresh.managedFiles.map((m) => [m.path, m]));
32
- for (const c of plan)
33
- if (c.kind !== 'conflict')
34
- tracked.set(c.path, { path: c.path, mode: c.mode, agent: agentId });
35
- await saveProject(ws, { ...fresh, managedFiles: [...tracked.values()].sort((a, b) => a.path.localeCompare(b.path)), updatedAt: isoNow(o) });
80
+ for (const c of plan) {
81
+ if (c.kind !== 'conflict') {
82
+ tracked.set(c.path, { path: c.path, mode: c.mode, agent: adapter.id });
83
+ }
84
+ }
85
+ await saveProject(ws, {
86
+ ...fresh,
87
+ managedFiles: [...tracked.values()].sort((a, b) => a.path.localeCompare(b.path)),
88
+ updatedAt: isoNow(o),
89
+ });
36
90
  });
37
- return { agent: agentId, dryRun: false, changes: plan.map(strip), conflicts };
91
+ return { agent: adapter.id, dryRun: false, changes: plan.map(strip), conflicts };
92
+ }
93
+ export async function listAgents(o) {
94
+ const ws = await requireWorkspace(o.cwd);
95
+ const project = await loadProject(ws);
96
+ const trackedByAgent = new Set(project.managedFiles.map((m) => m.agent).filter(Boolean));
97
+ const results = [];
98
+ for (const adapter of listAgentAdapters()) {
99
+ const detected = await adapter.detectExisting(ws.root);
100
+ let installed = trackedByAgent.has(adapter.id);
101
+ if (!installed) {
102
+ for (const rel of detected) {
103
+ const full = path.join(ws.root, ...rel.split('/'));
104
+ const text = await readTextBounded(full, 256 * 1024);
105
+ if (text && text.includes(SECTION_START) && text.includes(SECTION_END)) {
106
+ installed = true;
107
+ break;
108
+ }
109
+ }
110
+ }
111
+ results.push({
112
+ id: adapter.id,
113
+ displayName: adapter.displayName,
114
+ capabilities: adapter.capabilities,
115
+ detectedFiles: detected,
116
+ installed,
117
+ });
118
+ }
119
+ return results;
38
120
  }
39
121
  export function relPath(root, p) {
40
122
  return path.relative(root, p).replace(/\\/g, '/');
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/services/agent.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { claudeAdapter } from '../agents/claude/adapter.js';\nimport type { AgentAdapter, PlannedChange } from '../agents/types.js';\nimport { DevWorkspaceError } from '../errors/index.js';\nimport { atomicWriteFile } from '../utils/fs.js';\nimport { assertNoSymlinkEscape, resolveInside } from '../utils/paths.js';\nimport { loadProject, saveProject, requireWorkspace } from '../core/workspace.js';\nimport { withLock } from '../utils/lock.js';\nimport { isoNow, type ServiceOptions } from './common.js';\n\nexport const AGENTS: Record<string, AgentAdapter> = { claude: claudeAdapter };\n\nexport interface AgentInstallResult {\n agent: string;\n dryRun: boolean;\n changes: Omit<PlannedChange, 'content'>[];\n conflicts: number;\n}\n\nexport async function installAgent(o: ServiceOptions, agentId = 'claude'): Promise<AgentInstallResult> {\n const adapter = AGENTS[agentId];\n if (!adapter) {\n throw new DevWorkspaceError('USAGE', `Unknown agent \"${agentId}\".`, { hint: `Supported: ${Object.keys(AGENTS).join(', ')}.` });\n }\n const ws = await requireWorkspace(o.cwd);\n const project = await loadProject(ws);\n const plan = await adapter.plan({ root: ws.root, projectName: project.name });\n const strip = (c: PlannedChange): Omit<PlannedChange, 'content'> => ({ path: c.path, kind: c.kind, mode: c.mode, note: c.note });\n const conflicts = plan.filter((c) => c.kind === 'conflict').length;\n if (o.dryRun) return { agent: agentId, dryRun: true, changes: plan.map(strip), conflicts };\n\n await withLock(ws.dir, async () => {\n for (const c of plan) {\n if (c.kind !== 'create' && c.kind !== 'update') continue;\n const full = resolveInside(ws.root, c.path);\n await assertNoSymlinkEscape(ws.root, full);\n await atomicWriteFile(full, c.content);\n }\n const fresh = await loadProject(ws);\n const tracked = new Map(fresh.managedFiles.map((m) => [m.path, m]));\n for (const c of plan) if (c.kind !== 'conflict') tracked.set(c.path, { path: c.path, mode: c.mode, agent: agentId });\n await saveProject(ws, { ...fresh, managedFiles: [...tracked.values()].sort((a, b) => a.path.localeCompare(b.path)), updatedAt: isoNow(o) });\n });\n return { agent: agentId, dryRun: false, changes: plan.map(strip), conflicts };\n}\n\nexport function relPath(root: string, p: string): string {\n return path.relative(root, p).replace(/\\\\/g, '/');\n}\n"]}
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/services/agent.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport {\n AGENTS,\n getAgentAdapter,\n listAgentAdapters,\n detectAllAgentFiles,\n} from '../agents/index.js';\nimport type { AgentCapabilities, PlannedChange } from '../agents/types.js';\nexport type { AgentAdapter, AgentCapabilities, PlannedChange } from '../agents/types.js';\nimport { DevWorkspaceError } from '../errors/index.js';\nimport { atomicWriteFile, readTextBounded } from '../utils/fs.js';\nimport { assertNoSymlinkEscape, resolveInside } from '../utils/paths.js';\nimport { loadProject, saveProject, requireWorkspace } from '../core/workspace.js';\nimport { withLock } from '../utils/lock.js';\nimport { isoNow, type ServiceOptions } from './common.js';\nimport { SECTION_END, SECTION_START } from '../agents/shared.js';\n\nexport { AGENTS, getAgentAdapter, listAgentAdapters, detectAllAgentFiles };\n\nexport interface AgentInstallResult {\n agent: string;\n dryRun: boolean;\n changes: Omit<PlannedChange, 'content'>[];\n conflicts: number;\n}\n\nexport interface AgentInfo {\n id: string;\n displayName: string;\n capabilities: AgentCapabilities;\n detectedFiles: string[];\n installed: boolean;\n}\n\nconst strip = (c: PlannedChange): Omit<PlannedChange, 'content'> => ({\n path: c.path,\n kind: c.kind,\n mode: c.mode,\n note: c.note,\n});\n\nexport async function installAgent(o: ServiceOptions, agentId = 'claude'): Promise<AgentInstallResult> {\n const normId = agentId.toLowerCase();\n const ws = await requireWorkspace(o.cwd);\n const project = await loadProject(ws);\n\n if (normId === 'all') {\n const adapters = listAgentAdapters();\n const allChanges: PlannedChange[] = [];\n const changeByPath = new Map<string, { change: PlannedChange; adapterId: string }>();\n\n for (const adapter of adapters) {\n const plan = await adapter.plan({ root: ws.root, projectName: project.name });\n for (const c of plan) {\n allChanges.push(c);\n changeByPath.set(c.path, { change: c, adapterId: adapter.id });\n }\n }\n\n const conflicts = allChanges.filter((c) => c.kind === 'conflict').length;\n if (o.dryRun) {\n return { agent: 'all', dryRun: true, changes: allChanges.map(strip), conflicts };\n }\n\n await withLock(ws.dir, async () => {\n for (const c of allChanges) {\n if (c.kind !== 'create' && c.kind !== 'update') continue;\n const full = resolveInside(ws.root, c.path);\n await assertNoSymlinkEscape(ws.root, full);\n await atomicWriteFile(full, c.content);\n }\n const fresh = await loadProject(ws);\n const tracked = new Map(fresh.managedFiles.map((m) => [m.path, m]));\n for (const [p, item] of changeByPath) {\n if (item.change.kind !== 'conflict') {\n tracked.set(p, { path: p, mode: item.change.mode, agent: item.adapterId });\n }\n }\n await saveProject(ws, {\n ...fresh,\n managedFiles: [...tracked.values()].sort((a, b) => a.path.localeCompare(b.path)),\n updatedAt: isoNow(o),\n });\n });\n\n return { agent: 'all', dryRun: false, changes: allChanges.map(strip), conflicts };\n }\n\n const adapter = getAgentAdapter(normId);\n if (!adapter) {\n const supported = [...new Set([...listAgentAdapters().map((a) => a.id), 'all'])].sort().join(', ');\n throw new DevWorkspaceError('USAGE', `Unknown agent \"${agentId}\".`, {\n hint: `Supported: ${supported}.`,\n });\n }\n\n const plan = await adapter.plan({ root: ws.root, projectName: project.name });\n const conflicts = plan.filter((c) => c.kind === 'conflict').length;\n if (o.dryRun) return { agent: adapter.id, dryRun: true, changes: plan.map(strip), conflicts };\n\n await withLock(ws.dir, async () => {\n for (const c of plan) {\n if (c.kind !== 'create' && c.kind !== 'update') continue;\n const full = resolveInside(ws.root, c.path);\n await assertNoSymlinkEscape(ws.root, full);\n await atomicWriteFile(full, c.content);\n }\n const fresh = await loadProject(ws);\n const tracked = new Map(fresh.managedFiles.map((m) => [m.path, m]));\n for (const c of plan) {\n if (c.kind !== 'conflict') {\n tracked.set(c.path, { path: c.path, mode: c.mode, agent: adapter.id });\n }\n }\n await saveProject(ws, {\n ...fresh,\n managedFiles: [...tracked.values()].sort((a, b) => a.path.localeCompare(b.path)),\n updatedAt: isoNow(o),\n });\n });\n\n return { agent: adapter.id, dryRun: false, changes: plan.map(strip), conflicts };\n}\n\nexport async function listAgents(o: ServiceOptions): Promise<AgentInfo[]> {\n const ws = await requireWorkspace(o.cwd);\n const project = await loadProject(ws);\n const trackedByAgent = new Set(project.managedFiles.map((m) => m.agent).filter(Boolean));\n const results: AgentInfo[] = [];\n\n for (const adapter of listAgentAdapters()) {\n const detected = await adapter.detectExisting(ws.root);\n let installed = trackedByAgent.has(adapter.id);\n if (!installed) {\n for (const rel of detected) {\n const full = path.join(ws.root, ...rel.split('/'));\n const text = await readTextBounded(full, 256 * 1024);\n if (text && text.includes(SECTION_START) && text.includes(SECTION_END)) {\n installed = true;\n break;\n }\n }\n }\n results.push({\n id: adapter.id,\n displayName: adapter.displayName,\n capabilities: adapter.capabilities,\n detectedFiles: detected,\n installed,\n });\n }\n\n return results;\n}\n\nexport function relPath(root: string, p: string): string {\n return path.relative(root, p).replace(/\\\\/g, '/');\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { type CommandEntry } from '../config/schemas.js';
2
2
  import { type DiscoveryReport } from '../discovery/detect.js';
3
+ import { type CacheStatus } from '../discovery/cache.js';
3
4
  import { type IntegrationReport } from '../integrations/index.js';
4
5
  import { type FactInput } from '../knowledge/facts.js';
5
6
  import type { Ws } from '../core/workspace.js';
@@ -13,8 +14,13 @@ export interface DiscoveryRun {
13
14
  dirty: boolean;
14
15
  changedFiles: number;
15
16
  };
17
+ /** Whether detection was reused from the project-local cache (same scan and manifest content) or recomputed. */
18
+ cache: CacheStatus;
16
19
  }
17
- export declare function runDiscovery(ws: Ws, projectName: string, maxFiles?: number): Promise<DiscoveryRun>;
20
+ /** The scan and the Git query are independent, so they run concurrently. Read-only runs (dry-run) never write the cache. */
21
+ export declare function runDiscovery(ws: Ws, projectName: string, maxFiles?: number, opts?: {
22
+ writeCache?: boolean;
23
+ }): Promise<DiscoveryRun>;
18
24
  /** Facts derived purely from deterministic detection. They are re-derived on every analyze/refresh. */
19
25
  export declare function detectorFacts(d: DiscoveryReport): FactInput[];
20
26
  export declare function applyDetectorFacts(ws: Ws, d: DiscoveryReport, now: string): Promise<{
@@ -4,6 +4,7 @@ import { SCHEMA_VERSION, validateCommands } from '../config/schemas.js';
4
4
  import { TRUST_NOTE, mergeContract } from '../discovery/commands.js';
5
5
  import { detectProject } from '../discovery/detect.js';
6
6
  import { scanProject } from '../discovery/scan.js';
7
+ import { discoveryKey, readDiscoveryCache, writeDiscoveryCache } from '../discovery/cache.js';
7
8
  import { getGitState } from '../git/git.js';
8
9
  import { inspectAll } from '../integrations/index.js';
9
10
  import { buildFact, loadFacts, saveFacts, upsertFact } from '../knowledge/facts.js';
@@ -13,15 +14,21 @@ import { packageVersion } from '../core/version.js';
13
14
  import { pathExists, sha256Text, writeJsonIfChanged, writeTextIfChanged } from '../utils/fs.js';
14
15
  import { isSensitiveFile } from '../security/files.js';
15
16
  import { buildOnboardingPrompt } from '../prompts/onboarding.js';
16
- import { claudeAdapter } from '../agents/claude/adapter.js';
17
+ import { detectAllAgentFiles } from '../agents/index.js';
17
18
  import { isoNow, managerEnv } from './common.js';
18
- export async function runDiscovery(ws, projectName, maxFiles) {
19
- const scan = await scanProject(ws.root, maxFiles ? { maxFiles } : {});
20
- const [discovery, git] = await Promise.all([detectProject({ root: ws.root, projectName, scan }), getGitState(ws.root)]);
19
+ /** The scan and the Git query are independent, so they run concurrently. Read-only runs (dry-run) never write the cache. */
20
+ export async function runDiscovery(ws, projectName, maxFiles, opts = {}) {
21
+ const [scan, git] = await Promise.all([scanProject(ws.root, maxFiles ? { maxFiles } : {}), getGitState(ws.root)]);
22
+ const key = await discoveryKey(ws.root, projectName, scan, maxFiles);
23
+ const cached = await readDiscoveryCache(ws, key);
24
+ const discovery = cached.report ?? (await detectProject({ root: ws.root, projectName, scan }));
25
+ if (!cached.report && opts.writeCache)
26
+ await writeDiscoveryCache(ws, key, discovery);
21
27
  return {
22
28
  discovery,
23
29
  gitHead: git.head,
24
30
  git: { isRepo: git.isRepo, branch: git.branch, dirty: git.dirty, changedFiles: git.entries.length },
31
+ cache: cached.status,
25
32
  };
26
33
  }
27
34
  function existingFiles(files, max = 10) {
@@ -112,9 +119,9 @@ export async function writeCommands(ws, detected, opts = {}) {
112
119
  export async function analyzeWorkspace(ws, o) {
113
120
  const project = await loadProject(ws);
114
121
  const now = isoNow(o);
115
- const run = await runDiscovery(ws, project.name, project.settings.maxFiles);
122
+ const run = await runDiscovery(ws, project.name, project.settings.maxFiles, { writeCache: !o.dryRun });
116
123
  const integrations = await inspectAll(ws, managerEnv(o, ws.root), { deep: false });
117
- const existingAgentFiles = await claudeAdapter.detectExisting(ws.root);
124
+ const existingAgentFiles = await detectAllAgentFiles(ws.root);
118
125
  const prompt = buildOnboardingPrompt({
119
126
  projectName: project.name,
120
127
  discovery: run.discovery,
@@ -127,7 +134,7 @@ export async function analyzeWorkspace(ws, o) {
127
134
  const files = { discovery: rel(ws.discovery), onboardingPrompt: rel(ws.onboardingPrompt), commands: rel(ws.commands) };
128
135
  const nextSteps = [
129
136
  `Open ${files.onboardingPrompt}`,
130
- 'Paste it into Claude Code (or Claude in VS Code) in this project and let it finish onboarding.',
137
+ 'Paste it into your coding agent (Claude Code, Cursor, Copilot, Codex, etc.) in this project and let it finish onboarding.',
131
138
  'Then run: devworkspace doctor',
132
139
  ];
133
140
  if (o.dryRun) {
@@ -1 +1 @@
1
- {"version":3,"file":"analysis.js","sourceRoot":"","sources":["../../src/services/analysis.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { SCHEMA_VERSION, validateCommands, type AnalysisState, type CommandEntry, type CommandsFile } from '../config/schemas.js';\nimport { TRUST_NOTE, mergeContract } from '../discovery/commands.js';\nimport { detectProject, type DiscoveryReport } from '../discovery/detect.js';\nimport { scanProject } from '../discovery/scan.js';\nimport { getGitState } from '../git/git.js';\nimport { inspectAll, type IntegrationReport } from '../integrations/index.js';\nimport { buildFact, loadFacts, saveFacts, upsertFact, type FactInput } from '../knowledge/facts.js';\nimport { loadProject } from '../core/workspace.js';\nimport { readVersioned, writeVersioned } from '../core/versioned.js';\nimport { packageVersion } from '../core/version.js';\nimport { pathExists, sha256Text, writeJsonIfChanged, writeTextIfChanged } from '../utils/fs.js';\nimport { isSensitiveFile } from '../security/files.js';\nimport { buildOnboardingPrompt } from '../prompts/onboarding.js';\nimport { claudeAdapter } from '../agents/claude/adapter.js';\nimport type { Ws } from '../core/workspace.js';\nimport { isoNow, managerEnv, type ServiceOptions } from './common.js';\n\nexport interface DiscoveryRun {\n discovery: DiscoveryReport;\n gitHead: string | null;\n git: { isRepo: boolean; branch: string | null; dirty: boolean; changedFiles: number };\n}\n\nexport async function runDiscovery(ws: Ws, projectName: string, maxFiles?: number): Promise<DiscoveryRun> {\n const scan = await scanProject(ws.root, maxFiles ? { maxFiles } : {});\n const [discovery, git] = await Promise.all([detectProject({ root: ws.root, projectName, scan }), getGitState(ws.root)]);\n return {\n discovery,\n gitHead: git.head,\n git: { isRepo: git.isRepo, branch: git.branch, dirty: git.dirty, changedFiles: git.entries.length },\n };\n}\n\nfunction existingFiles(files: string[], max = 10): string[] {\n return files.filter((f) => !isSensitiveFile(f)).slice(0, max);\n}\n\n/** Facts derived purely from deterministic detection. They are re-derived on every analyze/refresh. */\nexport function detectorFacts(d: DiscoveryReport): FactInput[] {\n const out: FactInput[] = [];\n const add = (key: string, value: string, source: string, sources: string[] = []): void => {\n out.push({ key, value, source, sourceType: 'detector', sources, confidence: 'HIGH', status: 'DETECTED' });\n };\n if (d.ecosystems.length > 0) {\n add('stack.ecosystems', d.ecosystems.join(', '), 'repository manifests', d.manifests.slice(0, 20));\n }\n if (d.languages.length > 0) {\n add('stack.languages', d.languages.slice(0, 6).map((l) => `${l.name} (${l.files} files)`).join(', '), 'file extension counts');\n }\n if (d.packageManager) add('stack.package-manager', d.packageManager, 'lockfiles / package manifests');\n if (d.frameworks.length > 0) {\n add('stack.frameworks', d.frameworks.map((f) => f.name).join(', '), 'dependency manifests', [...new Set(d.frameworks.map((f) => f.evidence))].slice(0, 10));\n }\n if (d.monorepo.packages.length > 0) {\n add('repo.packages', d.monorepo.packages.slice(0, 40).map((p) => `${p.path} (${p.ecosystem}${p.packageManager ? `, ${p.packageManager}` : ''})`).join(', '), 'package manifests', d.manifests.slice(0, 20));\n }\n if (d.monorepo.tool) {\n add('repo.monorepo', `${d.monorepo.tool}: ${d.monorepo.packages.map((p) => p.path).slice(0, 30).join(', ') || 'packages not enumerated'}`, 'workspace configuration');\n }\n if ((d.entryPoints ?? []).length > 0) {\n const eps = d.entryPoints.slice(0, 30);\n add('repo.entry-points', eps.map((e) => `${e.cwd === '.' ? '' : `${e.cwd}/`}${e.path} (${e.kind})`).join(', '), 'package scripts, main and bin', eps.map((e) => (e.cwd === '.' ? e.path : `${e.cwd}/${e.path}`)).slice(0, 10));\n }\n if (d.docs.length > 0) add('repo.docs', d.docs.slice(0, 20).join(', '), 'documentation files', existingFiles(d.docs, 20));\n if (d.ci.length > 0) add('repo.ci', d.ci.join(', '), 'CI configuration', existingFiles(d.ci));\n if (d.docker.length > 0) add('repo.docker', d.docker.join(', '), 'container files', existingFiles(d.docker));\n if (d.deployment.length > 0) add('repo.deployment-hints', d.deployment.join(', '), 'deployment configuration', existingFiles(d.deployment));\n if (d.testConfigs.length > 0) add('repo.test-configs', d.testConfigs.join(', '), 'test configuration files', existingFiles(d.testConfigs));\n if (d.aiInstructions.length > 0) add('repo.ai-instructions', d.aiInstructions.join(', '), 'existing agent instruction files', existingFiles(d.aiInstructions));\n return out;\n}\n\nexport async function applyDetectorFacts(ws: Ws, d: DiscoveryReport, now: string): Promise<{ written: string[]; skipped: string[]; retired: string[] }> {\n const facts = await loadFacts(ws);\n const written: string[] = [];\n const skipped: string[] = [];\n const keys = new Set<string>();\n for (const input of detectorFacts(d)) {\n keys.add(input.key);\n const existing = facts.facts.find((f) => f.key === input.key);\n try {\n const fact = await buildFact(ws.root, input, now, existing);\n const action = upsertFact(facts, fact);\n if (action !== 'unchanged') written.push(input.key);\n } catch {\n skipped.push(input.key);\n }\n }\n // Detector facts that no longer apply are dropped: they are derived data, recreated if the evidence returns,\n // and leaving them as STALE would produce a warning that no human or agent action can clear.\n const retired = facts.facts.filter((f) => f.sourceType === 'detector' && !keys.has(f.key)).map((f) => f.key);\n if (retired.length > 0) facts.facts = facts.facts.filter((f) => !retired.includes(f.key));\n await saveFacts(ws, facts);\n return { written, skipped, retired };\n}\n\nexport interface ContractWrite {\n preservedUser: number;\n preservedStale: number;\n incomplete: boolean;\n}\n\n/**\n * Write the testing contract. Commands a person confirmed (origin \"user\") are never dropped, even when this analysis\n * finds nothing; see mergeContract for the exact rules.\n */\nexport async function writeCommands(ws: Ws, detected: CommandEntry[], opts: { truncated?: boolean } = {}): Promise<ContractWrite> {\n let previous: CommandsFile | null = null;\n if (await pathExists(ws.commands)) {\n previous = (await readVersioned(ws.commands, 'commands', SCHEMA_VERSION, validateCommands)).data;\n }\n const merged = mergeContract(previous?.checks ?? null, detected, opts);\n const file: CommandsFile = { schemaVersion: SCHEMA_VERSION, trustNote: TRUST_NOTE, checks: merged.checks };\n validateCommands(file);\n await writeVersioned(ws, ws.commands, file);\n return { preservedUser: merged.preservedUser, preservedStale: merged.preservedStale, incomplete: merged.incomplete };\n}\n\nexport interface AnalyzeResult {\n dryRun: boolean;\n projectName: string;\n files: { discovery: string; onboardingPrompt: string; commands: string };\n discovery: DiscoveryReport;\n facts: { written: string[]; skipped: string[]; retired: string[] };\n contract: ContractWrite | null;\n integrations: IntegrationReport[];\n promptBytes: number;\n nextSteps: string[];\n}\n\nexport async function analyzeWorkspace(ws: Ws, o: ServiceOptions): Promise<AnalyzeResult> {\n const project = await loadProject(ws);\n const now = isoNow(o);\n const run = await runDiscovery(ws, project.name, project.settings.maxFiles);\n const integrations = await inspectAll(ws, managerEnv(o, ws.root), { deep: false });\n const existingAgentFiles = await claudeAdapter.detectExisting(ws.root);\n const prompt = buildOnboardingPrompt({\n projectName: project.name,\n discovery: run.discovery,\n integrations,\n git: run.git,\n existingAgentFiles,\n cliVersion: packageVersion(),\n });\n const rel = (p: string): string => path.relative(ws.root, p).replace(/\\\\/g, '/');\n const files = { discovery: rel(ws.discovery), onboardingPrompt: rel(ws.onboardingPrompt), commands: rel(ws.commands) };\n const nextSteps = [\n `Open ${files.onboardingPrompt}`,\n 'Paste it into Claude Code (or Claude in VS Code) in this project and let it finish onboarding.',\n 'Then run: devworkspace doctor',\n ];\n if (o.dryRun) {\n return { dryRun: true, projectName: project.name, files, discovery: run.discovery, facts: { written: [], skipped: [], retired: [] }, contract: null, integrations, promptBytes: prompt.length, nextSteps };\n }\n\n await writeJsonIfChanged(ws.discovery, run.discovery);\n const contract = await writeCommands(ws, run.discovery.commands, { truncated: run.discovery.scan.truncated });\n const facts = await applyDetectorFacts(ws, run.discovery, now);\n await writeTextIfChanged(ws.onboardingPrompt, prompt);\n const state: AnalysisState = {\n schemaVersion: SCHEMA_VERSION,\n analyzedAt: now,\n refreshedAt: null,\n gitHead: run.gitHead,\n fileCount: run.discovery.scan.fileCount,\n truncated: run.discovery.scan.truncated,\n discoveryHash: sha256Text(JSON.stringify(run.discovery)),\n };\n await writeVersioned(ws, ws.analysisState, state);\n return { dryRun: false, projectName: project.name, files, discovery: run.discovery, facts, contract, integrations, promptBytes: prompt.length, nextSteps };\n}\n\nexport function newProjectId(): string {\n return randomUUID();\n}\n"]}
1
+ {"version":3,"file":"analysis.js","sourceRoot":"","sources":["../../src/services/analysis.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { SCHEMA_VERSION, validateCommands, type AnalysisState, type CommandEntry, type CommandsFile } from '../config/schemas.js';\nimport { TRUST_NOTE, mergeContract } from '../discovery/commands.js';\nimport { detectProject, type DiscoveryReport } from '../discovery/detect.js';\nimport { scanProject } from '../discovery/scan.js';\nimport { discoveryKey, readDiscoveryCache, writeDiscoveryCache, type CacheStatus } from '../discovery/cache.js';\nimport { getGitState } from '../git/git.js';\nimport { inspectAll, type IntegrationReport } from '../integrations/index.js';\nimport { buildFact, loadFacts, saveFacts, upsertFact, type FactInput } from '../knowledge/facts.js';\nimport { loadProject } from '../core/workspace.js';\nimport { readVersioned, writeVersioned } from '../core/versioned.js';\nimport { packageVersion } from '../core/version.js';\nimport { pathExists, sha256Text, writeJsonIfChanged, writeTextIfChanged } from '../utils/fs.js';\nimport { isSensitiveFile } from '../security/files.js';\nimport { buildOnboardingPrompt } from '../prompts/onboarding.js';\nimport { detectAllAgentFiles } from '../agents/index.js';\nimport type { Ws } from '../core/workspace.js';\nimport { isoNow, managerEnv, type ServiceOptions } from './common.js';\n\nexport interface DiscoveryRun {\n discovery: DiscoveryReport;\n gitHead: string | null;\n git: { isRepo: boolean; branch: string | null; dirty: boolean; changedFiles: number };\n /** Whether detection was reused from the project-local cache (same scan and manifest content) or recomputed. */\n cache: CacheStatus;\n}\n\n/** The scan and the Git query are independent, so they run concurrently. Read-only runs (dry-run) never write the cache. */\nexport async function runDiscovery(ws: Ws, projectName: string, maxFiles?: number, opts: { writeCache?: boolean } = {}): Promise<DiscoveryRun> {\n const [scan, git] = await Promise.all([scanProject(ws.root, maxFiles ? { maxFiles } : {}), getGitState(ws.root)]);\n const key = await discoveryKey(ws.root, projectName, scan, maxFiles);\n const cached = await readDiscoveryCache(ws, key);\n const discovery = cached.report ?? (await detectProject({ root: ws.root, projectName, scan }));\n if (!cached.report && opts.writeCache) await writeDiscoveryCache(ws, key, discovery);\n return {\n discovery,\n gitHead: git.head,\n git: { isRepo: git.isRepo, branch: git.branch, dirty: git.dirty, changedFiles: git.entries.length },\n cache: cached.status,\n };\n}\n\nfunction existingFiles(files: string[], max = 10): string[] {\n return files.filter((f) => !isSensitiveFile(f)).slice(0, max);\n}\n\n/** Facts derived purely from deterministic detection. They are re-derived on every analyze/refresh. */\nexport function detectorFacts(d: DiscoveryReport): FactInput[] {\n const out: FactInput[] = [];\n const add = (key: string, value: string, source: string, sources: string[] = []): void => {\n out.push({ key, value, source, sourceType: 'detector', sources, confidence: 'HIGH', status: 'DETECTED' });\n };\n if (d.ecosystems.length > 0) {\n add('stack.ecosystems', d.ecosystems.join(', '), 'repository manifests', d.manifests.slice(0, 20));\n }\n if (d.languages.length > 0) {\n add('stack.languages', d.languages.slice(0, 6).map((l) => `${l.name} (${l.files} files)`).join(', '), 'file extension counts');\n }\n if (d.packageManager) add('stack.package-manager', d.packageManager, 'lockfiles / package manifests');\n if (d.frameworks.length > 0) {\n add('stack.frameworks', d.frameworks.map((f) => f.name).join(', '), 'dependency manifests', [...new Set(d.frameworks.map((f) => f.evidence))].slice(0, 10));\n }\n if (d.monorepo.packages.length > 0) {\n add('repo.packages', d.monorepo.packages.slice(0, 40).map((p) => `${p.path} (${p.ecosystem}${p.packageManager ? `, ${p.packageManager}` : ''})`).join(', '), 'package manifests', d.manifests.slice(0, 20));\n }\n if (d.monorepo.tool) {\n add('repo.monorepo', `${d.monorepo.tool}: ${d.monorepo.packages.map((p) => p.path).slice(0, 30).join(', ') || 'packages not enumerated'}`, 'workspace configuration');\n }\n if ((d.entryPoints ?? []).length > 0) {\n const eps = d.entryPoints.slice(0, 30);\n add('repo.entry-points', eps.map((e) => `${e.cwd === '.' ? '' : `${e.cwd}/`}${e.path} (${e.kind})`).join(', '), 'package scripts, main and bin', eps.map((e) => (e.cwd === '.' ? e.path : `${e.cwd}/${e.path}`)).slice(0, 10));\n }\n if (d.docs.length > 0) add('repo.docs', d.docs.slice(0, 20).join(', '), 'documentation files', existingFiles(d.docs, 20));\n if (d.ci.length > 0) add('repo.ci', d.ci.join(', '), 'CI configuration', existingFiles(d.ci));\n if (d.docker.length > 0) add('repo.docker', d.docker.join(', '), 'container files', existingFiles(d.docker));\n if (d.deployment.length > 0) add('repo.deployment-hints', d.deployment.join(', '), 'deployment configuration', existingFiles(d.deployment));\n if (d.testConfigs.length > 0) add('repo.test-configs', d.testConfigs.join(', '), 'test configuration files', existingFiles(d.testConfigs));\n if (d.aiInstructions.length > 0) add('repo.ai-instructions', d.aiInstructions.join(', '), 'existing agent instruction files', existingFiles(d.aiInstructions));\n return out;\n}\n\nexport async function applyDetectorFacts(ws: Ws, d: DiscoveryReport, now: string): Promise<{ written: string[]; skipped: string[]; retired: string[] }> {\n const facts = await loadFacts(ws);\n const written: string[] = [];\n const skipped: string[] = [];\n const keys = new Set<string>();\n for (const input of detectorFacts(d)) {\n keys.add(input.key);\n const existing = facts.facts.find((f) => f.key === input.key);\n try {\n const fact = await buildFact(ws.root, input, now, existing);\n const action = upsertFact(facts, fact);\n if (action !== 'unchanged') written.push(input.key);\n } catch {\n skipped.push(input.key);\n }\n }\n // Detector facts that no longer apply are dropped: they are derived data, recreated if the evidence returns,\n // and leaving them as STALE would produce a warning that no human or agent action can clear.\n const retired = facts.facts.filter((f) => f.sourceType === 'detector' && !keys.has(f.key)).map((f) => f.key);\n if (retired.length > 0) facts.facts = facts.facts.filter((f) => !retired.includes(f.key));\n await saveFacts(ws, facts);\n return { written, skipped, retired };\n}\n\nexport interface ContractWrite {\n preservedUser: number;\n preservedStale: number;\n incomplete: boolean;\n}\n\n/**\n * Write the testing contract. Commands a person confirmed (origin \"user\") are never dropped, even when this analysis\n * finds nothing; see mergeContract for the exact rules.\n */\nexport async function writeCommands(ws: Ws, detected: CommandEntry[], opts: { truncated?: boolean } = {}): Promise<ContractWrite> {\n let previous: CommandsFile | null = null;\n if (await pathExists(ws.commands)) {\n previous = (await readVersioned(ws.commands, 'commands', SCHEMA_VERSION, validateCommands)).data;\n }\n const merged = mergeContract(previous?.checks ?? null, detected, opts);\n const file: CommandsFile = { schemaVersion: SCHEMA_VERSION, trustNote: TRUST_NOTE, checks: merged.checks };\n validateCommands(file);\n await writeVersioned(ws, ws.commands, file);\n return { preservedUser: merged.preservedUser, preservedStale: merged.preservedStale, incomplete: merged.incomplete };\n}\n\nexport interface AnalyzeResult {\n dryRun: boolean;\n projectName: string;\n files: { discovery: string; onboardingPrompt: string; commands: string };\n discovery: DiscoveryReport;\n facts: { written: string[]; skipped: string[]; retired: string[] };\n contract: ContractWrite | null;\n integrations: IntegrationReport[];\n promptBytes: number;\n nextSteps: string[];\n}\n\nexport async function analyzeWorkspace(ws: Ws, o: ServiceOptions): Promise<AnalyzeResult> {\n const project = await loadProject(ws);\n const now = isoNow(o);\n const run = await runDiscovery(ws, project.name, project.settings.maxFiles, { writeCache: !o.dryRun });\n const integrations = await inspectAll(ws, managerEnv(o, ws.root), { deep: false });\n const existingAgentFiles = await detectAllAgentFiles(ws.root);\n const prompt = buildOnboardingPrompt({\n projectName: project.name,\n discovery: run.discovery,\n integrations,\n git: run.git,\n existingAgentFiles,\n cliVersion: packageVersion(),\n });\n const rel = (p: string): string => path.relative(ws.root, p).replace(/\\\\/g, '/');\n const files = { discovery: rel(ws.discovery), onboardingPrompt: rel(ws.onboardingPrompt), commands: rel(ws.commands) };\n const nextSteps = [\n `Open ${files.onboardingPrompt}`,\n 'Paste it into your coding agent (Claude Code, Cursor, Copilot, Codex, etc.) in this project and let it finish onboarding.',\n 'Then run: devworkspace doctor',\n ];\n if (o.dryRun) {\n return { dryRun: true, projectName: project.name, files, discovery: run.discovery, facts: { written: [], skipped: [], retired: [] }, contract: null, integrations, promptBytes: prompt.length, nextSteps };\n }\n\n await writeJsonIfChanged(ws.discovery, run.discovery);\n const contract = await writeCommands(ws, run.discovery.commands, { truncated: run.discovery.scan.truncated });\n const facts = await applyDetectorFacts(ws, run.discovery, now);\n await writeTextIfChanged(ws.onboardingPrompt, prompt);\n const state: AnalysisState = {\n schemaVersion: SCHEMA_VERSION,\n analyzedAt: now,\n refreshedAt: null,\n gitHead: run.gitHead,\n fileCount: run.discovery.scan.fileCount,\n truncated: run.discovery.scan.truncated,\n discoveryHash: sha256Text(JSON.stringify(run.discovery)),\n };\n await writeVersioned(ws, ws.analysisState, state);\n return { dryRun: false, projectName: project.name, files, discovery: run.discovery, facts, contract, integrations, promptBytes: prompt.length, nextSteps };\n}\n\nexport function newProjectId(): string {\n return randomUUID();\n}\n"]}
@@ -15,10 +15,9 @@ import { ensureDir, listFilesRecursive, pathExists, readJsonFile, readTextBounde
15
15
  import { ALWAYS_SKIP_DIRS } from '../discovery/scan.js';
16
16
  import { isAuxPath } from '../discovery/detect.js';
17
17
  import { findAbsolutePaths } from '../utils/paths.js';
18
- import { instructionsInstalled, knowledgeWritten } from './status.js';
18
+ import { detectInstalledAgents, instructionsInstalled, knowledgeWritten } from './status.js';
19
19
  import { managerEnv } from './common.js';
20
20
  import { withLock } from '../utils/lock.js';
21
- import { claudeAdapter } from '../agents/claude/adapter.js';
22
21
  export const MIN_NODE_MAJOR = 20;
23
22
  export async function runDoctor(o) {
24
23
  const checks = [];
@@ -164,23 +163,41 @@ export async function runDoctor(o) {
164
163
  add('onboarding-prompt', 'fail', `Onboarding prompt is missing: ${missing.join(', ')}`, 'Re-run: devworkspace analyze');
165
164
  }
166
165
  // Agent wiring.
167
- if (await instructionsInstalled(ws))
168
- add('agent-instructions', 'pass', 'Claude instructions and skill installed');
169
- else
170
- add('agent-instructions', 'warn', 'Claude instructions are not installed (or the managed section is missing)', 'Run: devworkspace agent install');
171
- if (await instructionsInstalled(ws)) {
166
+ const installedAgents = await detectInstalledAgents(ws);
167
+ if (installedAgents.length > 0) {
168
+ const names = installedAgents.map((a) => a.displayName).join(', ');
169
+ const msg = installedAgents.length === 1 && installedAgents[0].id === 'claude'
170
+ ? 'Claude instructions and skill installed'
171
+ : `${names} instructions installed`;
172
+ add('agent-instructions', 'pass', msg);
172
173
  // Read-only: plan() only computes what an install would write; nothing is touched here.
173
- const planned = await claudeAdapter.plan({ root, projectName: (await loadProject(ws).catch(() => null))?.name ?? path.basename(root) });
174
- const outdated = planned.filter((c) => c.kind === 'update').map((c) => c.path);
175
- if (outdated.length > 0)
176
- add('agent-freshness', 'warn', `Installed Claude instructions are older than this DevWorkspace version (${outdated.join(', ')})`, 'Run: devworkspace agent install (add --dry-run to preview; only the managed block and the devworkspace skill change).');
177
- else
178
- add('agent-freshness', 'pass', 'Installed Claude instructions and skill match this DevWorkspace version');
174
+ const projectName = (await loadProject(ws).catch(() => null))?.name ?? path.basename(root);
175
+ const outdatedByAgent = [];
176
+ for (const adapter of installedAgents) {
177
+ const planned = await adapter.plan({ root, projectName });
178
+ const outdated = planned.filter((c) => c.kind === 'update').map((c) => c.path);
179
+ if (outdated.length > 0) {
180
+ outdatedByAgent.push({ agent: adapter, paths: outdated });
181
+ }
182
+ }
183
+ if (outdatedByAgent.length > 0) {
184
+ const allPaths = outdatedByAgent.flatMap((x) => x.paths);
185
+ const namesStale = outdatedByAgent.map((x) => x.agent.displayName).join(', ');
186
+ add('agent-freshness', 'warn', `Installed ${namesStale} instructions are older than this DevWorkspace version (${allPaths.join(', ')})`, 'Run: devworkspace agent install (add --dry-run to preview; only the managed block and the devworkspace skill change).');
187
+ }
188
+ else {
189
+ add('agent-freshness', 'pass', installedAgents.length === 1 && installedAgents[0].id === 'claude'
190
+ ? 'Installed Claude instructions and skill match this DevWorkspace version'
191
+ : `Installed ${names} instructions match this DevWorkspace version`);
192
+ }
193
+ }
194
+ else {
195
+ add('agent-instructions', 'warn', 'Agent instructions are not installed (or the managed section is missing)', 'Run: devworkspace agent install');
179
196
  }
180
197
  if (await knowledgeWritten(ws))
181
198
  add('onboarding', 'pass', 'Architecture knowledge written');
182
199
  else
183
- add('onboarding', 'warn', 'Onboarding is not complete: .devworkspace/context/architecture.md is missing or empty', 'Paste .devworkspace/analysis/onboarding-prompt.md into Claude Code.');
200
+ add('onboarding', 'warn', 'Onboarding is not complete: .devworkspace/context/architecture.md is missing or empty', 'Paste .devworkspace/analysis/onboarding-prompt.md into your coding agent (Claude Code, Cursor, Copilot, Codex, etc.).');
184
201
  // Security and portability.
185
202
  const wsFiles = (await listFilesRecursive(ws.dir, 3000)).filter((f) => !f.startsWith(ws.localDir) && !/\.tmp$/.test(f));
186
203
  const secretHits = [];
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/services/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC/F,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,WAAW,EAAE,OAAO,EAAW,MAAM,sBAAsB,CAAC;AACzG,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,SAAS,EAA0B,MAAM,0BAA0B,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACrF,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC3H,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,UAAU,EAAuB,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AA8B5D,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AAEjC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,CAAgB;IAC9C,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,CAAC,EAAU,EAAE,MAAmB,EAAE,OAAe,EAAE,WAAoB,EAAQ,EAAE;QAC3F,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAChF,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,CAAC,CAAC,YAAY,IAAI,cAAc,CAAC;IACjD,IAAI,KAAK,IAAI,OAAO;QAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;;QACzE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,OAAO,CAAC,QAAQ,CAAC,IAAI,+BAA+B,OAAO,EAAE,EAAE,mBAAmB,OAAO,iCAAiC,CAAC,CAAC;IAEhK,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;IACpC,IAAI,MAAM;QAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,kBAAkB,CAAC,CAAC;;QAC9C,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,2BAA2B,EAAE,oFAAoF,CAAC,CAAC;IAE3I,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC;YACxD,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,2EAA2E,EAAE,4GAA4G,CAAC,CAAC;QACtN,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,uDAAuD,EAAE,wBAAwB,CAAC,CAAC;QAC9G,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAE5C,2CAA2C;IAC3C,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,0BAA0B,GAAG,KAAK,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,WAAW,CAAC,EAAE,CAAC,CAAC;QAChC,SAAS,GAAG,IAAI,CAAC;QACjB,0BAA0B,GAAG,CAAC,CAAC,QAAQ,CAAC,yBAAyB,KAAK,IAAI,CAAC;QAC3E,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,+BAA+B,CAAC,CAAC,aAAa,QAAQ,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;IAC3G,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,GAAI,CAAuB,CAAC,IAAI,CAAC;QAC3C,GAAG,CAAC,SAAS,EAAE,MAAM,EAAG,CAAW,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,EAAE,IAAI,KAAK,gBAAgB,CAAC,CAAC,CAAC,0DAA0D,CAAC,CAAC,CAAC,+GAA+G,CAAC,CAAC;IACzQ,CAAC;IAED,UAAU;IACV,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,YAAY,EAAE,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC9H,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,MAAM,CAAC,IAAI,IAAI;QAAE,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,CAAC,CAAC,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtE,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,2BAA2B,CAAC,CAAC;SAC5E,IAAI,CAAC,CAAC,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,MAAM,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,IAAI,EAAE;YAChC,KAAK,MAAM,CAAC,IAAI,WAAW;gBAAE,MAAM,SAAS,CAAC,CAAC,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC,WAAW,WAAW,CAAC,MAAM,oBAAoB,CAAC,CAAC;QAC9D,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,WAAW,CAAC,MAAM,oBAAoB,CAAC,CAAC;IAC7E,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,oBAAoB,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,gCAAgC,CAAC,CAAC;IACrI,CAAC;IAED,gBAAgB;IAChB,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,IAAI,CACvD,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,QAAQ,CAAC,EAC5D,GAAG,EAAE,CAAC,KAAK,CACZ,CAAC;IACF,IAAI,IAAI;QAAE,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,oCAAoC,CAAC,CAAC;SACvE,IAAI,CAAC,CAAC,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,MAAM,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;QACrD,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAC7C,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,gCAAgC,CAAC,CAAC;IAChE,CAAC;;QAAM,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,iDAAiD,EAAE,gCAAgC,CAAC,CAAC;IAExH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC;QACxE,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YAClF,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,4FAA4F,EAAE,kFAAkF,CAAC,CAAC;QAC/M,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,wBAAwB;IAC1B,CAAC;IAED,0BAA0B;IAC1B,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,EAAE,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;QAC/E,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnD,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,iBAAiB,CAAC,CAAC;QAC7D,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,mBAAmB,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,mFAAmF,CAAC,CAAC;aACtO,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,yBAAyB,CAAC,CAAC;IACvF,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,OAAO,EAAE,MAAM,EAAG,CAAW,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,EAAE,kGAAkG,CAAC,CAAC;IACjK,CAAC;IAED,IAAI,MAAM,UAAU,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,CAAC,MAAM,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;YAChG,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,0BAA0B,CAAC,CAAC;YACpD,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,IAAI,CAAC,CAAC,SAAS,CAAC;gBAAE,GAAG,CAAC,iBAAiB,EAAE,MAAM,EAAE,+BAA+B,EAAE,wGAAwG,CAAC,CAAC;YACrO,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,IAAI,CAAC,CAAC,SAAS,CAAC;gBAAE,GAAG,CAAC,iBAAiB,EAAE,MAAM,EAAE,2BAA2B,CAAC,CAAC;YACxH,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACvD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;gBACtD,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACxF,GAAG,CAAC,uBAAuB,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,sCAAsC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5J,CAAC;iBAAM,IAAI,0BAA0B,EAAE,CAAC;gBACtC,GAAG,CAAC,uBAAuB,EAAE,MAAM,EAAE,6FAA6F,CAAC,CAAC;YACtI,CAAC;iBAAM,CAAC;gBACN,GAAG,CACD,uBAAuB,EACvB,MAAM,EACN,mHAAmH,EACnH,uJAAuJ,CACxJ,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,GAAG,CAAC,UAAU,EAAE,MAAM,EAAG,CAAW,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,EAAE,mDAAmD,CAAC,CAAC;QACrH,CAAC;IACH,CAAC;;QAAM,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,oCAAoC,EAAE,2BAA2B,CAAC,CAAC;IAElG,MAAM,cAAc,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAE9B,IAAI,MAAM,UAAU,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,CAAC,MAAM,aAAa,CAAC,EAAE,CAAC,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC;YAC1G,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9G,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,GAAG,CAAC,UAAU,EAAE,MAAM,EAAG,CAAW,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,EAAE,8BAA8B,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;;QAAM,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,kCAAkC,EAAE,2BAA2B,CAAC,CAAC;IAEhG,iCAAiC;IACjC,IAAI,MAAM,UAAU,CAAC,EAAE,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,CAAC,MAAM,eAAe,CAAC,EAAE,CAAC,gBAAgB,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7E,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,EAAE,uBAAuB,CAAC,CAAC;QAC9D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,GAAG,CAAC,mBAAmB,EAAE,MAAM,EAAE,0DAA0D,CAAC,CAAC;;YAClH,GAAG,CAAC,mBAAmB,EAAE,MAAM,EAAE,iCAAiC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,8BAA8B,CAAC,CAAC;IAC/H,CAAC;IAED,gBAAgB;IAChB,IAAI,MAAM,qBAAqB,CAAC,EAAE,CAAC;QAAE,GAAG,CAAC,oBAAoB,EAAE,MAAM,EAAE,yCAAyC,CAAC,CAAC;;QAC7G,GAAG,CAAC,oBAAoB,EAAE,MAAM,EAAE,2EAA2E,EAAE,iCAAiC,CAAC,CAAC;IACvJ,IAAI,MAAM,qBAAqB,CAAC,EAAE,CAAC,EAAE,CAAC;QACpC,wFAAwF;QACxF,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,MAAM,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACxI,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/E,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,iBAAiB,EAAE,MAAM,EAAE,2EAA2E,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,uHAAuH,CAAC,CAAC;;YAC/Q,GAAG,CAAC,iBAAiB,EAAE,MAAM,EAAE,yEAAyE,CAAC,CAAC;IACjH,CAAC;IACD,IAAI,MAAM,gBAAgB,CAAC,EAAE,CAAC;QAAE,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,gCAAgC,CAAC,CAAC;;QACvF,GAAG,CAAC,YAAY,EAAE,MAAM,EAAE,uFAAuF,EAAE,qEAAqE,CAAC,CAAC;IAE/L,4BAA4B;IAC5B,MAAM,OAAO,GAAG,CAAC,MAAM,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACxH,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;YAAE,SAAS;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACzD,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvD,IAAI,GAAG,KAAK,+BAA+B,IAAI,GAAG,KAAK,4BAA4B,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/I,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,wCAAwC,CAAC,CAAC;;QACzF,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,gCAAgC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,6EAA6E,CAAC,CAAC;IACpK,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,0DAA0D,CAAC,CAAC;;QAC5G,GAAG,CAAC,aAAa,EAAE,MAAM,EAAE,4BAA4B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,0FAA0F,CAAC,CAAC;IAE9K,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,GAAG,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9D,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,iBAAiB,EAAE,MAAM,EAAE,6CAA6C,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,wFAAwF,CAAC,CAAC;;YACnN,GAAG,CAAC,iBAAiB,EAAE,MAAM,EAAE,yCAAyC,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,CAAC,MAAM,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1F,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,uDAAuD,EAAE,2BAA2B,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAErQ,uBAAuB;IACvB,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,EAAE,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,6BAA6B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,kDAAkD,CAAC,CAAC;;QACnL,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,mBAAmB,CAAC,CAAC;IAC9D,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC;IACpC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,gCAAgC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,2BAA2B,CAAC,CAAC;IAElJ,OAAO,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,KAAK,UAAU,MAAM,CAAC,IAAmB,EAAE,MAAqB,EAAE,KAAe,EAAE,EAAkB,EAAE,CAAgB;IACrH,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IACtD,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IAC3C,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,MAAM,WAAW,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IAC3F,IAAI,EAAE;QAAE,KAAK,GAAG,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,WAAW,IAAI,CAAC,MAAM,qBAAqB,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC;IACtH,wIAAwI;IACxI,MAAM,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjG,MAAM,CAAC,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC;IAClC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,EAAE,QAAQ,EAAE,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC;AAC/M,CAAC;AAED,uHAAuH;AACvH,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,sBAAsB,EAAE,qBAAqB,EAAE,uBAAuB,CAAC,CAAC,CAAC;AAE3G,2FAA2F;AAC3F,KAAK,UAAU,mBAAmB,CAAC,IAAY;IAC7C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,GAAW,EAAW,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IACjI,KAAK,UAAU,IAAI,CAAC,GAAW;QAC7B,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9M,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IACD,KAAK,MAAM,EAAE,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QAChC,IAAI,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,cAAc,CAAC,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;QAC5F,KAAK,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;YAAE,IAAI,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,cAAc,CAAC,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IAC/I,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,EAAM,EAAE,GAAqF;IACzH,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;QAAE,OAAO,CAAC,uDAAuD;IACtG,IAAI,CAA8K,CAAC;IACnL,IAAI,CAAC;QACH,CAAC,GAAG,CAAC,MAAM,YAAY,CAAC,EAAE,CAAC,SAAS,CAAC,CAAa,CAAC;IACrD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,GAAG,CAAC,qBAAqB,EAAE,MAAM,EAAG,CAAW,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,EAAE,8BAA8B,CAAC,CAAC;QACzG,OAAO;IACT,CAAC;IACD,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACzD,qHAAqH;IACrH,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,IAAI,EAAE;QAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC;IAChF,IAAI,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,CAAC,MAAM,mBAAmB,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACjF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,GAAG,CACD,sBAAsB,EACtB,MAAM,EACN,4EAA4E,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,EAC9I,+GAA+G,CAChH,CAAC;IACJ,CAAC;SAAM,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpD,GAAG,CACD,qBAAqB,EACrB,MAAM,EACN,sCAAsC,CAAC,CAAC,IAAI,EAAE,SAAS,IAAI,SAAS,wBAAwB,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,yCAAyC,EACrK,wIAAwI,CACzI,CAAC;IACJ,CAAC;SAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC,CAAC;QAC5C,GAAG,CAAC,qBAAqB,EAAE,MAAM,EAAE,YAAY,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACzH,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,qBAAqB,EAAE,MAAM,EAAE,uCAAuC,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { SCHEMA_VERSION, validateAnalysisState, validateCommands } from '../config/schemas.js';\nimport { findWorkspaceRoot, LOCAL_GITIGNORE, loadProject, wsPaths, type Ws } from '../core/workspace.js';\nimport { readVersioned } from '../core/versioned.js';\nimport { getGitState, gitAvailable, gitTrackedFiles } from '../git/git.js';\nimport { inspectAll, summarize, type IntegrationReport } from '../integrations/index.js';\nimport { evaluateStaleness, loadFacts } from '../knowledge/facts.js';\nimport { ONBOARDING_REQUIREMENTS, validatePrompt } from '../prompts/requirements.js';\nimport { isSensitiveFile } from '../security/files.js';\nimport { findSecrets } from '../security/redact.js';\nimport { listDecisions } from '../decisions/decision.js';\nimport { listTasks } from '../tasks/task.js';\nimport { ensureDir, listFilesRecursive, pathExists, readJsonFile, readTextBounded, atomicWriteFile } from '../utils/fs.js';\nimport { ALWAYS_SKIP_DIRS } from '../discovery/scan.js';\nimport { isAuxPath } from '../discovery/detect.js';\nimport { findAbsolutePaths } from '../utils/paths.js';\nimport { instructionsInstalled, knowledgeWritten } from './status.js';\nimport { managerEnv, type ServiceOptions } from './common.js';\nimport { withLock } from '../utils/lock.js';\nimport { claudeAdapter } from '../agents/claude/adapter.js';\n\nexport type CheckStatus = 'pass' | 'warn' | 'fail' | 'info';\n\nexport interface DoctorCheck {\n id: string;\n status: CheckStatus;\n message: string;\n remediation?: string;\n}\n\nexport interface DoctorResult {\n root: string | null;\n checks: DoctorCheck[];\n counts: { pass: number; warn: number; fail: number; info: number };\n /** Core workspace has no failing checks. */\n healthy: boolean;\n /** Core workspace is onboarded: instructions installed and architecture knowledge written. */\n ready: boolean;\n fixed: string[];\n /** Observed integration state, kept separate from core readiness. */\n integrations: IntegrationReport[];\n integrationSummary: { complete: boolean; required: number; verified: number };\n}\n\nexport interface DoctorOptions extends ServiceOptions {\n fix?: boolean;\n minNodeMajor?: number;\n}\n\nexport const MIN_NODE_MAJOR = 20;\n\nexport async function runDoctor(o: DoctorOptions): Promise<DoctorResult> {\n const checks: DoctorCheck[] = [];\n const fixed: string[] = [];\n const add = (id: string, status: CheckStatus, message: string, remediation?: string): void => {\n checks.push({ id, status, message, ...(remediation ? { remediation } : {}) });\n };\n\n const major = Number(process.versions.node.split('.')[0]);\n const minNode = o.minNodeMajor ?? MIN_NODE_MAJOR;\n if (major >= minNode) add('node', 'pass', `Node.js ${process.versions.node}`);\n else add('node', 'fail', `Node.js ${process.versions.node} is older than the required ${minNode}`, `Install Node.js ${minNode} or newer (https://nodejs.org).`);\n\n const hasGit = await gitAvailable();\n if (hasGit) add('git', 'pass', 'Git is available');\n else add('git', 'warn', 'Git was not found on PATH', 'Install Git; DevWorkspace works without it but cannot protect uncommitted changes.');\n\n const root = await findWorkspaceRoot(o.cwd);\n if (!root) {\n if (await pathExists(path.join(o.cwd, '.devworkspace'))) {\n add('workspace', 'fail', 'Partial initialization: .devworkspace/ exists but project.json is missing', 'Restore project.json from Git, or run \"devworkspace init\" to complete the setup (existing files are kept).');\n } else {\n add('workspace', 'fail', 'No DevWorkspace found in this directory or any parent', 'Run: devworkspace init');\n }\n return finish(null, checks, fixed, undefined, o);\n }\n const ws = wsPaths(root);\n add('workspace', 'pass', 'Workspace found');\n\n // Project config and schema compatibility.\n let projectOk = false;\n let acknowledgedNoVerification = false;\n try {\n const p = await loadProject(ws);\n projectOk = true;\n acknowledgedNoVerification = p.settings.acknowledgeNoVerification === true;\n add('project', 'pass', `project.json valid (schema v${p.schemaVersion}, id ${p.projectId.slice(0, 8)})`);\n } catch (e) {\n const code = (e as { code?: string }).code;\n add('project', 'fail', (e as Error).message.split('\\n')[0]!, code === 'SCHEMA_TOO_NEW' ? 'Upgrade DevWorkspace: npm install -g devworkspace@latest' : 'Restore .devworkspace/project.json from Git, or re-run \"devworkspace init\" after moving the broken file away.');\n }\n\n // Layout.\n const dirs = [ws.contextDir, ws.decisionsDir, ws.tasksActive, ws.tasksCompleted, ws.sessionsDir, ws.analysisDir, ws.stateDir];\n const missingDirs: string[] = [];\n for (const d of dirs) if (!(await pathExists(d))) missingDirs.push(d);\n if (missingDirs.length === 0) add('layout', 'pass', 'Workspace folders present');\n else if (o.fix && projectOk) {\n await withLock(ws.dir, async () => {\n for (const d of missingDirs) await ensureDir(d);\n });\n fixed.push(`created ${missingDirs.length} missing folder(s)`);\n add('layout', 'pass', `Recreated ${missingDirs.length} missing folder(s)`);\n } else {\n add('layout', 'warn', `Missing folders: ${missingDirs.map((d) => path.basename(d)).join(', ')}`, 'Run: devworkspace doctor --fix');\n }\n\n // Ignore rules.\n const giOk = await fs.readFile(ws.gitignore, 'utf8').then(\n (gi) => gi.split(/\\r?\\n/).some((l) => l.trim() === 'local/'),\n () => false,\n );\n if (giOk) add('ignore-local', 'pass', 'Machine-local state is git-ignored');\n else if (o.fix && projectOk) {\n await atomicWriteFile(ws.gitignore, LOCAL_GITIGNORE);\n fixed.push('wrote .devworkspace/.gitignore');\n add('ignore-local', 'pass', 'Wrote .devworkspace/.gitignore');\n } else add('ignore-local', 'fail', '.devworkspace/.gitignore does not ignore local/', 'Run: devworkspace doctor --fix');\n\n try {\n const rootGi = await fs.readFile(path.join(root, '.gitignore'), 'utf8');\n if (rootGi.split(/\\r?\\n/).some((l) => /^\\/?\\.devworkspace\\/?\\*?$/.test(l.trim()))) {\n add('ignore-root', 'warn', 'The root .gitignore ignores all of .devworkspace/, so project knowledge will not be shared', 'Remove that rule; .devworkspace/.gitignore already excludes machine-local files.');\n }\n } catch {\n /* no root .gitignore */\n }\n\n // Knowledge and contract.\n try {\n const facts = await loadFacts(ws);\n const view = await evaluateStaleness(ws.root, facts, new Date().toISOString());\n const stale = [...view.recorded, ...view.detected];\n add('facts', 'pass', `${facts.facts.length} fact(s) stored`);\n if (stale.length > 0) add('staleness', 'warn', `${stale.length} stale fact(s): ${stale.slice(0, 5).map((f) => `${f.key} (${f.reason})`).join('; ')}`, 'Run: devworkspace refresh, then re-check the listed facts against the repository.');\n else if (facts.facts.length > 0) add('staleness', 'pass', 'No stale facts recorded');\n } catch (e) {\n add('facts', 'fail', (e as Error).message.split('\\n')[0]!, 'Restore .devworkspace/context/facts.json from Git or a backup under .devworkspace/local/backups.');\n }\n\n if (await pathExists(ws.commands)) {\n try {\n const c = (await readVersioned(ws.commands, 'commands', SCHEMA_VERSION, validateCommands)).data;\n add('contract', 'pass', 'Testing contract present');\n if (!c.checks.some((x) => x.id === 'unit' && x.available)) add('tests-available', 'warn', 'No unit-test command detected', 'Add a test script or edit .devworkspace/context/commands.json; tasks will not be able to demand tests.');\n if (!c.checks.some((x) => x.id === 'build' && x.available)) add('build-available', 'info', 'No build command detected');\n const configured = c.checks.filter((x) => x.available);\n if (configured.length > 0) {\n const ids = [...new Set(configured.map((x) => x.id))];\n const dirs = [...new Set(configured.map((x) => x.cwd).filter((d): d is string => !!d))];\n add('verification-commands', 'pass', `${ids.length} verification check(s) configured: ${ids.join(', ')}${dirs.length ? ` (in ${dirs.join(', ')})` : ''}`);\n } else if (acknowledgedNoVerification) {\n add('verification-commands', 'info', 'No verification commands; acknowledged in project.json (settings.acknowledgeNoVerification)');\n } else {\n add(\n 'verification-commands',\n 'warn',\n 'No verification commands (tests, lint, typecheck, build) are configured, so tasks cannot require any verification',\n 'Run: devworkspace analyze. If the project intentionally has none, set \"acknowledgeNoVerification\": true under settings in .devworkspace/project.json.',\n );\n }\n } catch (e) {\n add('contract', 'fail', (e as Error).message.split('\\n')[0]!, 'Fix commands.json or re-run: devworkspace analyze');\n }\n } else add('contract', 'warn', 'Testing contract not generated yet', 'Run: devworkspace analyze');\n\n await checkDiscovery(ws, add);\n\n if (await pathExists(ws.analysisState)) {\n try {\n const a = (await readVersioned(ws.analysisState, 'analysis', SCHEMA_VERSION, validateAnalysisState)).data;\n add('analysis', 'pass', `Last analysis ${a.analyzedAt}${a.truncated ? ' (partial: size limits hit)' : ''}`);\n } catch (e) {\n add('analysis', 'fail', (e as Error).message.split('\\n')[0]!, 'Re-run: devworkspace analyze');\n }\n } else add('analysis', 'warn', 'Repository has not been analyzed', 'Run: devworkspace analyze');\n\n // Prompt quality (when present).\n if (await pathExists(ws.onboardingPrompt)) {\n const text = (await readTextBounded(ws.onboardingPrompt, 1024 * 1024)) ?? '';\n const missing = validatePrompt(text, ONBOARDING_REQUIREMENTS);\n if (missing.length === 0) add('onboarding-prompt', 'pass', 'Onboarding prompt satisfies all behavioural requirements');\n else add('onboarding-prompt', 'fail', `Onboarding prompt is missing: ${missing.join(', ')}`, 'Re-run: devworkspace analyze');\n }\n\n // Agent wiring.\n if (await instructionsInstalled(ws)) add('agent-instructions', 'pass', 'Claude instructions and skill installed');\n else add('agent-instructions', 'warn', 'Claude instructions are not installed (or the managed section is missing)', 'Run: devworkspace agent install');\n if (await instructionsInstalled(ws)) {\n // Read-only: plan() only computes what an install would write; nothing is touched here.\n const planned = await claudeAdapter.plan({ root, projectName: (await loadProject(ws).catch(() => null))?.name ?? path.basename(root) });\n const outdated = planned.filter((c) => c.kind === 'update').map((c) => c.path);\n if (outdated.length > 0) add('agent-freshness', 'warn', `Installed Claude instructions are older than this DevWorkspace version (${outdated.join(', ')})`, 'Run: devworkspace agent install (add --dry-run to preview; only the managed block and the devworkspace skill change).');\n else add('agent-freshness', 'pass', 'Installed Claude instructions and skill match this DevWorkspace version');\n }\n if (await knowledgeWritten(ws)) add('onboarding', 'pass', 'Architecture knowledge written');\n else add('onboarding', 'warn', 'Onboarding is not complete: .devworkspace/context/architecture.md is missing or empty', 'Paste .devworkspace/analysis/onboarding-prompt.md into Claude Code.');\n\n // Security and portability.\n const wsFiles = (await listFilesRecursive(ws.dir, 3000)).filter((f) => !f.startsWith(ws.localDir) && !/\\.tmp$/.test(f));\n const secretHits: string[] = [];\n const absHits: string[] = [];\n for (const f of wsFiles) {\n if (!/\\.(json|md)$/.test(f)) continue;\n const rel = path.relative(ws.dir, f).replace(/\\\\/g, '/');\n const text = await readTextBounded(f, 1024 * 1024);\n if (!text) continue;\n if (findSecrets(text).length > 0) secretHits.push(rel);\n if (rel !== 'analysis/onboarding-prompt.md' && rel !== 'analysis/refresh-prompt.md' && findAbsolutePaths(text).length > 0) absHits.push(rel);\n }\n if (secretHits.length === 0) add('secrets', 'pass', 'No secret-like values in .devworkspace');\n else add('secrets', 'fail', `Secret-like values found in: ${secretHits.join(', ')}`, 'Remove the values, rotate the credential if it was real, and re-run doctor.');\n if (absHits.length === 0) add('portability', 'pass', 'No machine-specific absolute paths in portable knowledge');\n else add('portability', 'warn', `Absolute paths found in: ${absHits.join(', ')}`, 'Replace them with project-relative paths so the workspace works after the project moves.');\n\n const git = await getGitState(root);\n if (git.isRepo) {\n const tracked = await gitTrackedFiles(root);\n const bad = (tracked ?? []).filter((f) => isSensitiveFile(f));\n if (bad.length > 0) add('tracked-secrets', 'warn', `Credential-like files are tracked by Git: ${bad.slice(0, 5).join(', ')}`, 'Remove them from Git history if they hold real secrets (git rm --cached, then rotate).');\n else add('tracked-secrets', 'pass', 'No credential-like files tracked by Git');\n }\n\n const leftovers = wsFiles.filter((f) => f.endsWith('.tmp'));\n const allTmp = (await listFilesRecursive(ws.dir, 3000)).filter((f) => f.endsWith('.tmp'));\n if (allTmp.length > 0 || leftovers.length > 0) add('tmp-files', 'warn', `${allTmp.length} leftover temporary file(s) from an interrupted write`, 'They are safe to delete: ' + allTmp.slice(0, 3).map((f) => path.relative(root, f).replace(/\\\\/g, '/')).join(', '));\n\n // Tasks and decisions.\n const { tasks, corrupt } = await listTasks(ws, { includeCompleted: true });\n if (corrupt.length > 0) add('tasks', 'fail', `${corrupt.length} unreadable task file(s): ${corrupt.map((c) => c.file).join(', ')}`, 'Restore them from Git or delete the broken file.');\n else add('tasks', 'pass', `${tasks.length} task(s) readable`);\n const dec = await listDecisions(ws);\n if (dec.unreadable.length > 0) add('decisions', 'warn', `Unreadable decision file(s): ${dec.unreadable.join(', ')}`, 'Check their front matter.');\n\n return finish(root, checks, fixed, ws, o);\n}\n\nasync function finish(root: string | null, checks: DoctorCheck[], fixed: string[], ws: Ws | undefined, o: DoctorOptions): Promise<DoctorResult> {\n const counts = { pass: 0, warn: 0, fail: 0, info: 0 };\n for (const c of checks) counts[c.status]++;\n let ready = false;\n const discoveryOk = !checks.some((c) => DISCOVERY_CHECKS.has(c.id) && c.status === 'warn');\n if (ws) ready = counts.fail === 0 && discoveryOk && (await instructionsInstalled(ws)) && (await knowledgeWritten(ws));\n // Integrations are observed (tools are run), and reported separately: a missing optional tool never makes the core workspace unhealthy.\n const integrations = root && ws ? await inspectAll(ws, managerEnv(o, root), { deep: true }) : [];\n const s = summarize(integrations);\n return { root, checks, counts, healthy: counts.fail === 0, ready, fixed, integrations, integrationSummary: { complete: integrations.length > 0 && s.complete, required: s.required, verified: s.verified } };\n}\n\n/** Doctor checks that say whether the repository was actually understood, as opposed to the folder merely existing. */\nconst DISCOVERY_CHECKS = new Set(['discovery-incomplete', 'discovery-ecosystem', 'verification-commands']);\n\n/** package.json files near the top of the tree (two levels), found without a full scan. */\nasync function findNearbyManifests(root: string): Promise<string[]> {\n const found: string[] = [];\n const skip = (name: string, rel: string): boolean => name.startsWith('.') || ALWAYS_SKIP_DIRS.has(name) || isAuxPath(`${rel}/x`);\n async function dirs(rel: string): Promise<string[]> {\n try {\n return (await fs.readdir(path.join(root, rel), { withFileTypes: true })).filter((e) => e.isDirectory() && !skip(e.name, rel ? `${rel}/${e.name}` : e.name)).map((e) => (rel ? `${rel}/${e.name}` : e.name));\n } catch {\n return [];\n }\n }\n for (const d1 of await dirs('')) {\n if (await pathExists(path.join(root, d1, 'package.json'))) found.push(`${d1}/package.json`);\n for (const d2 of (await dirs(d1)).slice(0, 100)) if (await pathExists(path.join(root, d2, 'package.json'))) found.push(`${d2}/package.json`);\n }\n return found.sort();\n}\n\nasync function checkDiscovery(ws: Ws, add: (id: string, status: CheckStatus, message: string, remediation?: string) => void): Promise<void> {\n if (!(await pathExists(ws.discovery))) return; // \"not analyzed yet\" is reported by the analysis check\n let d: { ecosystems?: string[]; languages?: { name: string; files: number }[]; manifests?: string[]; monorepo?: { packages?: { path: string }[] }; scan?: { fileCount?: number } };\n try {\n d = (await readJsonFile(ws.discovery)) as typeof d;\n } catch (e) {\n add('discovery-ecosystem', 'fail', (e as Error).message.split('\\n')[0]!, 'Re-run: devworkspace analyze');\n return;\n }\n const eco = d.ecosystems ?? [];\n const languages = (d.languages ?? []).map((l) => l.name);\n // Manifests the analysis recorded. Older reports lack the list, so reconstruct it from the packages they did record.\n const known = new Set<string>(d.manifests ?? []);\n for (const p of d.monorepo?.packages ?? []) known.add(`${p.path}/package.json`);\n if (eco.includes('node')) known.add('package.json');\n const missed = (await findNearbyManifests(ws.root)).filter((m) => !known.has(m));\n if (missed.length > 0) {\n add(\n 'discovery-incomplete',\n 'warn',\n `The repository has package manifest(s) the last analysis did not record: ${missed.slice(0, 4).join(', ')}${missed.length > 4 ? ', ...' : ''}`,\n 'Run: devworkspace analyze (current versions detect nested packages). Commands you confirmed earlier are kept.',\n );\n } else if (eco.length === 0 && languages.length > 0) {\n add(\n 'discovery-ecosystem',\n 'warn',\n `No ecosystem was detected although ${d.scan?.fileCount ?? 'several'} files were scanned (${languages.slice(0, 3).join(', ')}), so build and test tooling is unknown`,\n 'Run: devworkspace analyze. If the project has no package manifest, record its commands by hand in .devworkspace/context/commands.json.',\n );\n } else if (eco.length > 0) {\n const n = d.monorepo?.packages?.length ?? 0;\n add('discovery-ecosystem', 'pass', `Detected ${eco.join(', ')}${n > 0 ? ` (${n} package${n === 1 ? '' : 's'})` : ''}`);\n } else {\n add('discovery-ecosystem', 'info', 'No source files or manifests detected');\n }\n}\n"]}
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/services/doctor.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { SCHEMA_VERSION, validateAnalysisState, validateCommands } from '../config/schemas.js';\nimport { findWorkspaceRoot, LOCAL_GITIGNORE, loadProject, wsPaths, type Ws } from '../core/workspace.js';\nimport { readVersioned } from '../core/versioned.js';\nimport { getGitState, gitAvailable, gitTrackedFiles } from '../git/git.js';\nimport { inspectAll, summarize, type IntegrationReport } from '../integrations/index.js';\nimport { evaluateStaleness, loadFacts } from '../knowledge/facts.js';\nimport { ONBOARDING_REQUIREMENTS, validatePrompt } from '../prompts/requirements.js';\nimport { isSensitiveFile } from '../security/files.js';\nimport { findSecrets } from '../security/redact.js';\nimport { listDecisions } from '../decisions/decision.js';\nimport { listTasks } from '../tasks/task.js';\nimport { ensureDir, listFilesRecursive, pathExists, readJsonFile, readTextBounded, atomicWriteFile } from '../utils/fs.js';\nimport { ALWAYS_SKIP_DIRS } from '../discovery/scan.js';\nimport { isAuxPath } from '../discovery/detect.js';\nimport { findAbsolutePaths } from '../utils/paths.js';\nimport { detectInstalledAgents, instructionsInstalled, knowledgeWritten } from './status.js';\nimport { managerEnv, type ServiceOptions } from './common.js';\nimport { withLock } from '../utils/lock.js';\nimport type { AgentAdapter } from '../agents/types.js';\n\nexport type CheckStatus = 'pass' | 'warn' | 'fail' | 'info';\n\nexport interface DoctorCheck {\n id: string;\n status: CheckStatus;\n message: string;\n remediation?: string;\n}\n\nexport interface DoctorResult {\n root: string | null;\n checks: DoctorCheck[];\n counts: { pass: number; warn: number; fail: number; info: number };\n /** Core workspace has no failing checks. */\n healthy: boolean;\n /** Core workspace is onboarded: instructions installed and architecture knowledge written. */\n ready: boolean;\n fixed: string[];\n /** Observed integration state, kept separate from core readiness. */\n integrations: IntegrationReport[];\n integrationSummary: { complete: boolean; required: number; verified: number };\n}\n\nexport interface DoctorOptions extends ServiceOptions {\n fix?: boolean;\n minNodeMajor?: number;\n}\n\nexport const MIN_NODE_MAJOR = 20;\n\nexport async function runDoctor(o: DoctorOptions): Promise<DoctorResult> {\n const checks: DoctorCheck[] = [];\n const fixed: string[] = [];\n const add = (id: string, status: CheckStatus, message: string, remediation?: string): void => {\n checks.push({ id, status, message, ...(remediation ? { remediation } : {}) });\n };\n\n const major = Number(process.versions.node.split('.')[0]);\n const minNode = o.minNodeMajor ?? MIN_NODE_MAJOR;\n if (major >= minNode) add('node', 'pass', `Node.js ${process.versions.node}`);\n else add('node', 'fail', `Node.js ${process.versions.node} is older than the required ${minNode}`, `Install Node.js ${minNode} or newer (https://nodejs.org).`);\n\n const hasGit = await gitAvailable();\n if (hasGit) add('git', 'pass', 'Git is available');\n else add('git', 'warn', 'Git was not found on PATH', 'Install Git; DevWorkspace works without it but cannot protect uncommitted changes.');\n\n const root = await findWorkspaceRoot(o.cwd);\n if (!root) {\n if (await pathExists(path.join(o.cwd, '.devworkspace'))) {\n add('workspace', 'fail', 'Partial initialization: .devworkspace/ exists but project.json is missing', 'Restore project.json from Git, or run \"devworkspace init\" to complete the setup (existing files are kept).');\n } else {\n add('workspace', 'fail', 'No DevWorkspace found in this directory or any parent', 'Run: devworkspace init');\n }\n return finish(null, checks, fixed, undefined, o);\n }\n const ws = wsPaths(root);\n add('workspace', 'pass', 'Workspace found');\n\n // Project config and schema compatibility.\n let projectOk = false;\n let acknowledgedNoVerification = false;\n try {\n const p = await loadProject(ws);\n projectOk = true;\n acknowledgedNoVerification = p.settings.acknowledgeNoVerification === true;\n add('project', 'pass', `project.json valid (schema v${p.schemaVersion}, id ${p.projectId.slice(0, 8)})`);\n } catch (e) {\n const code = (e as { code?: string }).code;\n add('project', 'fail', (e as Error).message.split('\\n')[0]!, code === 'SCHEMA_TOO_NEW' ? 'Upgrade DevWorkspace: npm install -g devworkspace@latest' : 'Restore .devworkspace/project.json from Git, or re-run \"devworkspace init\" after moving the broken file away.');\n }\n\n // Layout.\n const dirs = [ws.contextDir, ws.decisionsDir, ws.tasksActive, ws.tasksCompleted, ws.sessionsDir, ws.analysisDir, ws.stateDir];\n const missingDirs: string[] = [];\n for (const d of dirs) if (!(await pathExists(d))) missingDirs.push(d);\n if (missingDirs.length === 0) add('layout', 'pass', 'Workspace folders present');\n else if (o.fix && projectOk) {\n await withLock(ws.dir, async () => {\n for (const d of missingDirs) await ensureDir(d);\n });\n fixed.push(`created ${missingDirs.length} missing folder(s)`);\n add('layout', 'pass', `Recreated ${missingDirs.length} missing folder(s)`);\n } else {\n add('layout', 'warn', `Missing folders: ${missingDirs.map((d) => path.basename(d)).join(', ')}`, 'Run: devworkspace doctor --fix');\n }\n\n // Ignore rules.\n const giOk = await fs.readFile(ws.gitignore, 'utf8').then(\n (gi) => gi.split(/\\r?\\n/).some((l) => l.trim() === 'local/'),\n () => false,\n );\n if (giOk) add('ignore-local', 'pass', 'Machine-local state is git-ignored');\n else if (o.fix && projectOk) {\n await atomicWriteFile(ws.gitignore, LOCAL_GITIGNORE);\n fixed.push('wrote .devworkspace/.gitignore');\n add('ignore-local', 'pass', 'Wrote .devworkspace/.gitignore');\n } else add('ignore-local', 'fail', '.devworkspace/.gitignore does not ignore local/', 'Run: devworkspace doctor --fix');\n\n try {\n const rootGi = await fs.readFile(path.join(root, '.gitignore'), 'utf8');\n if (rootGi.split(/\\r?\\n/).some((l) => /^\\/?\\.devworkspace\\/?\\*?$/.test(l.trim()))) {\n add('ignore-root', 'warn', 'The root .gitignore ignores all of .devworkspace/, so project knowledge will not be shared', 'Remove that rule; .devworkspace/.gitignore already excludes machine-local files.');\n }\n } catch {\n /* no root .gitignore */\n }\n\n // Knowledge and contract.\n try {\n const facts = await loadFacts(ws);\n const view = await evaluateStaleness(ws.root, facts, new Date().toISOString());\n const stale = [...view.recorded, ...view.detected];\n add('facts', 'pass', `${facts.facts.length} fact(s) stored`);\n if (stale.length > 0) add('staleness', 'warn', `${stale.length} stale fact(s): ${stale.slice(0, 5).map((f) => `${f.key} (${f.reason})`).join('; ')}`, 'Run: devworkspace refresh, then re-check the listed facts against the repository.');\n else if (facts.facts.length > 0) add('staleness', 'pass', 'No stale facts recorded');\n } catch (e) {\n add('facts', 'fail', (e as Error).message.split('\\n')[0]!, 'Restore .devworkspace/context/facts.json from Git or a backup under .devworkspace/local/backups.');\n }\n\n if (await pathExists(ws.commands)) {\n try {\n const c = (await readVersioned(ws.commands, 'commands', SCHEMA_VERSION, validateCommands)).data;\n add('contract', 'pass', 'Testing contract present');\n if (!c.checks.some((x) => x.id === 'unit' && x.available)) add('tests-available', 'warn', 'No unit-test command detected', 'Add a test script or edit .devworkspace/context/commands.json; tasks will not be able to demand tests.');\n if (!c.checks.some((x) => x.id === 'build' && x.available)) add('build-available', 'info', 'No build command detected');\n const configured = c.checks.filter((x) => x.available);\n if (configured.length > 0) {\n const ids = [...new Set(configured.map((x) => x.id))];\n const dirs = [...new Set(configured.map((x) => x.cwd).filter((d): d is string => !!d))];\n add('verification-commands', 'pass', `${ids.length} verification check(s) configured: ${ids.join(', ')}${dirs.length ? ` (in ${dirs.join(', ')})` : ''}`);\n } else if (acknowledgedNoVerification) {\n add('verification-commands', 'info', 'No verification commands; acknowledged in project.json (settings.acknowledgeNoVerification)');\n } else {\n add(\n 'verification-commands',\n 'warn',\n 'No verification commands (tests, lint, typecheck, build) are configured, so tasks cannot require any verification',\n 'Run: devworkspace analyze. If the project intentionally has none, set \"acknowledgeNoVerification\": true under settings in .devworkspace/project.json.',\n );\n }\n } catch (e) {\n add('contract', 'fail', (e as Error).message.split('\\n')[0]!, 'Fix commands.json or re-run: devworkspace analyze');\n }\n } else add('contract', 'warn', 'Testing contract not generated yet', 'Run: devworkspace analyze');\n\n await checkDiscovery(ws, add);\n\n if (await pathExists(ws.analysisState)) {\n try {\n const a = (await readVersioned(ws.analysisState, 'analysis', SCHEMA_VERSION, validateAnalysisState)).data;\n add('analysis', 'pass', `Last analysis ${a.analyzedAt}${a.truncated ? ' (partial: size limits hit)' : ''}`);\n } catch (e) {\n add('analysis', 'fail', (e as Error).message.split('\\n')[0]!, 'Re-run: devworkspace analyze');\n }\n } else add('analysis', 'warn', 'Repository has not been analyzed', 'Run: devworkspace analyze');\n\n // Prompt quality (when present).\n if (await pathExists(ws.onboardingPrompt)) {\n const text = (await readTextBounded(ws.onboardingPrompt, 1024 * 1024)) ?? '';\n const missing = validatePrompt(text, ONBOARDING_REQUIREMENTS);\n if (missing.length === 0) add('onboarding-prompt', 'pass', 'Onboarding prompt satisfies all behavioural requirements');\n else add('onboarding-prompt', 'fail', `Onboarding prompt is missing: ${missing.join(', ')}`, 'Re-run: devworkspace analyze');\n }\n\n // Agent wiring.\n const installedAgents = await detectInstalledAgents(ws);\n if (installedAgents.length > 0) {\n const names = installedAgents.map((a) => a.displayName).join(', ');\n const msg = installedAgents.length === 1 && installedAgents[0]!.id === 'claude'\n ? 'Claude instructions and skill installed'\n : `${names} instructions installed`;\n add('agent-instructions', 'pass', msg);\n\n // Read-only: plan() only computes what an install would write; nothing is touched here.\n const projectName = (await loadProject(ws).catch(() => null))?.name ?? path.basename(root);\n const outdatedByAgent: { agent: AgentAdapter; paths: string[] }[] = [];\n for (const adapter of installedAgents) {\n const planned = await adapter.plan({ root, projectName });\n const outdated = planned.filter((c) => c.kind === 'update').map((c) => c.path);\n if (outdated.length > 0) {\n outdatedByAgent.push({ agent: adapter, paths: outdated });\n }\n }\n if (outdatedByAgent.length > 0) {\n const allPaths = outdatedByAgent.flatMap((x) => x.paths);\n const namesStale = outdatedByAgent.map((x) => x.agent.displayName).join(', ');\n add(\n 'agent-freshness',\n 'warn',\n `Installed ${namesStale} instructions are older than this DevWorkspace version (${allPaths.join(', ')})`,\n 'Run: devworkspace agent install (add --dry-run to preview; only the managed block and the devworkspace skill change).',\n );\n } else {\n add(\n 'agent-freshness',\n 'pass',\n installedAgents.length === 1 && installedAgents[0]!.id === 'claude'\n ? 'Installed Claude instructions and skill match this DevWorkspace version'\n : `Installed ${names} instructions match this DevWorkspace version`,\n );\n }\n } else {\n add(\n 'agent-instructions',\n 'warn',\n 'Agent instructions are not installed (or the managed section is missing)',\n 'Run: devworkspace agent install',\n );\n }\n if (await knowledgeWritten(ws)) add('onboarding', 'pass', 'Architecture knowledge written');\n else add('onboarding', 'warn', 'Onboarding is not complete: .devworkspace/context/architecture.md is missing or empty', 'Paste .devworkspace/analysis/onboarding-prompt.md into your coding agent (Claude Code, Cursor, Copilot, Codex, etc.).');\n\n // Security and portability.\n const wsFiles = (await listFilesRecursive(ws.dir, 3000)).filter((f) => !f.startsWith(ws.localDir) && !/\\.tmp$/.test(f));\n const secretHits: string[] = [];\n const absHits: string[] = [];\n for (const f of wsFiles) {\n if (!/\\.(json|md)$/.test(f)) continue;\n const rel = path.relative(ws.dir, f).replace(/\\\\/g, '/');\n const text = await readTextBounded(f, 1024 * 1024);\n if (!text) continue;\n if (findSecrets(text).length > 0) secretHits.push(rel);\n if (rel !== 'analysis/onboarding-prompt.md' && rel !== 'analysis/refresh-prompt.md' && findAbsolutePaths(text).length > 0) absHits.push(rel);\n }\n if (secretHits.length === 0) add('secrets', 'pass', 'No secret-like values in .devworkspace');\n else add('secrets', 'fail', `Secret-like values found in: ${secretHits.join(', ')}`, 'Remove the values, rotate the credential if it was real, and re-run doctor.');\n if (absHits.length === 0) add('portability', 'pass', 'No machine-specific absolute paths in portable knowledge');\n else add('portability', 'warn', `Absolute paths found in: ${absHits.join(', ')}`, 'Replace them with project-relative paths so the workspace works after the project moves.');\n\n const git = await getGitState(root);\n if (git.isRepo) {\n const tracked = await gitTrackedFiles(root);\n const bad = (tracked ?? []).filter((f) => isSensitiveFile(f));\n if (bad.length > 0) add('tracked-secrets', 'warn', `Credential-like files are tracked by Git: ${bad.slice(0, 5).join(', ')}`, 'Remove them from Git history if they hold real secrets (git rm --cached, then rotate).');\n else add('tracked-secrets', 'pass', 'No credential-like files tracked by Git');\n }\n\n const leftovers = wsFiles.filter((f) => f.endsWith('.tmp'));\n const allTmp = (await listFilesRecursive(ws.dir, 3000)).filter((f) => f.endsWith('.tmp'));\n if (allTmp.length > 0 || leftovers.length > 0) add('tmp-files', 'warn', `${allTmp.length} leftover temporary file(s) from an interrupted write`, 'They are safe to delete: ' + allTmp.slice(0, 3).map((f) => path.relative(root, f).replace(/\\\\/g, '/')).join(', '));\n\n // Tasks and decisions.\n const { tasks, corrupt } = await listTasks(ws, { includeCompleted: true });\n if (corrupt.length > 0) add('tasks', 'fail', `${corrupt.length} unreadable task file(s): ${corrupt.map((c) => c.file).join(', ')}`, 'Restore them from Git or delete the broken file.');\n else add('tasks', 'pass', `${tasks.length} task(s) readable`);\n const dec = await listDecisions(ws);\n if (dec.unreadable.length > 0) add('decisions', 'warn', `Unreadable decision file(s): ${dec.unreadable.join(', ')}`, 'Check their front matter.');\n\n return finish(root, checks, fixed, ws, o);\n}\n\nasync function finish(root: string | null, checks: DoctorCheck[], fixed: string[], ws: Ws | undefined, o: DoctorOptions): Promise<DoctorResult> {\n const counts = { pass: 0, warn: 0, fail: 0, info: 0 };\n for (const c of checks) counts[c.status]++;\n let ready = false;\n const discoveryOk = !checks.some((c) => DISCOVERY_CHECKS.has(c.id) && c.status === 'warn');\n if (ws) ready = counts.fail === 0 && discoveryOk && (await instructionsInstalled(ws)) && (await knowledgeWritten(ws));\n // Integrations are observed (tools are run), and reported separately: a missing optional tool never makes the core workspace unhealthy.\n const integrations = root && ws ? await inspectAll(ws, managerEnv(o, root), { deep: true }) : [];\n const s = summarize(integrations);\n return { root, checks, counts, healthy: counts.fail === 0, ready, fixed, integrations, integrationSummary: { complete: integrations.length > 0 && s.complete, required: s.required, verified: s.verified } };\n}\n\n/** Doctor checks that say whether the repository was actually understood, as opposed to the folder merely existing. */\nconst DISCOVERY_CHECKS = new Set(['discovery-incomplete', 'discovery-ecosystem', 'verification-commands']);\n\n/** package.json files near the top of the tree (two levels), found without a full scan. */\nasync function findNearbyManifests(root: string): Promise<string[]> {\n const found: string[] = [];\n const skip = (name: string, rel: string): boolean => name.startsWith('.') || ALWAYS_SKIP_DIRS.has(name) || isAuxPath(`${rel}/x`);\n async function dirs(rel: string): Promise<string[]> {\n try {\n return (await fs.readdir(path.join(root, rel), { withFileTypes: true })).filter((e) => e.isDirectory() && !skip(e.name, rel ? `${rel}/${e.name}` : e.name)).map((e) => (rel ? `${rel}/${e.name}` : e.name));\n } catch {\n return [];\n }\n }\n for (const d1 of await dirs('')) {\n if (await pathExists(path.join(root, d1, 'package.json'))) found.push(`${d1}/package.json`);\n for (const d2 of (await dirs(d1)).slice(0, 100)) if (await pathExists(path.join(root, d2, 'package.json'))) found.push(`${d2}/package.json`);\n }\n return found.sort();\n}\n\nasync function checkDiscovery(ws: Ws, add: (id: string, status: CheckStatus, message: string, remediation?: string) => void): Promise<void> {\n if (!(await pathExists(ws.discovery))) return; // \"not analyzed yet\" is reported by the analysis check\n let d: { ecosystems?: string[]; languages?: { name: string; files: number }[]; manifests?: string[]; monorepo?: { packages?: { path: string }[] }; scan?: { fileCount?: number } };\n try {\n d = (await readJsonFile(ws.discovery)) as typeof d;\n } catch (e) {\n add('discovery-ecosystem', 'fail', (e as Error).message.split('\\n')[0]!, 'Re-run: devworkspace analyze');\n return;\n }\n const eco = d.ecosystems ?? [];\n const languages = (d.languages ?? []).map((l) => l.name);\n // Manifests the analysis recorded. Older reports lack the list, so reconstruct it from the packages they did record.\n const known = new Set<string>(d.manifests ?? []);\n for (const p of d.monorepo?.packages ?? []) known.add(`${p.path}/package.json`);\n if (eco.includes('node')) known.add('package.json');\n const missed = (await findNearbyManifests(ws.root)).filter((m) => !known.has(m));\n if (missed.length > 0) {\n add(\n 'discovery-incomplete',\n 'warn',\n `The repository has package manifest(s) the last analysis did not record: ${missed.slice(0, 4).join(', ')}${missed.length > 4 ? ', ...' : ''}`,\n 'Run: devworkspace analyze (current versions detect nested packages). Commands you confirmed earlier are kept.',\n );\n } else if (eco.length === 0 && languages.length > 0) {\n add(\n 'discovery-ecosystem',\n 'warn',\n `No ecosystem was detected although ${d.scan?.fileCount ?? 'several'} files were scanned (${languages.slice(0, 3).join(', ')}), so build and test tooling is unknown`,\n 'Run: devworkspace analyze. If the project has no package manifest, record its commands by hand in .devworkspace/context/commands.json.',\n );\n } else if (eco.length > 0) {\n const n = d.monorepo?.packages?.length ?? 0;\n add('discovery-ecosystem', 'pass', `Detected ${eco.join(', ')}${n > 0 ? ` (${n} package${n === 1 ? '' : 's'})` : ''}`);\n } else {\n add('discovery-ecosystem', 'info', 'No source files or manifests detected');\n }\n}\n"]}