devworkspace 0.3.0 → 0.3.2

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 (119) hide show
  1. package/CHANGELOG.md +42 -1
  2. package/README.md +8 -5
  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/codex/adapter.d.ts +2 -0
  7. package/dist/agents/codex/adapter.js +61 -0
  8. package/dist/agents/codex/adapter.js.map +1 -0
  9. package/dist/agents/copilot/adapter.d.ts +2 -0
  10. package/dist/agents/copilot/adapter.js +62 -0
  11. package/dist/agents/copilot/adapter.js.map +1 -0
  12. package/dist/agents/cursor/adapter.d.ts +2 -0
  13. package/dist/agents/cursor/adapter.js +127 -0
  14. package/dist/agents/cursor/adapter.js.map +1 -0
  15. package/dist/agents/index.d.ts +15 -0
  16. package/dist/agents/index.js +54 -0
  17. package/dist/agents/index.js.map +1 -0
  18. package/dist/agents/shared.d.ts +20 -0
  19. package/dist/agents/shared.js +76 -0
  20. package/dist/agents/shared.js.map +1 -0
  21. package/dist/agents/types.d.ts +16 -1
  22. package/dist/agents/types.js.map +1 -1
  23. package/dist/cli/args.d.ts +42 -0
  24. package/dist/cli/args.js +12 -0
  25. package/dist/cli/args.js.map +1 -1
  26. package/dist/cli/help.js +64 -10
  27. package/dist/cli/help.js.map +1 -1
  28. package/dist/cli/render.d.ts +12 -1
  29. package/dist/cli/render.js +188 -0
  30. package/dist/cli/render.js.map +1 -1
  31. package/dist/cli/run.js +100 -9
  32. package/dist/cli/run.js.map +1 -1
  33. package/dist/config/schemas.d.ts +6 -0
  34. package/dist/config/schemas.js +6 -0
  35. package/dist/config/schemas.js.map +1 -1
  36. package/dist/core/version.d.ts +7 -0
  37. package/dist/core/version.js +13 -0
  38. package/dist/core/version.js.map +1 -1
  39. package/dist/core/workspace.d.ts +1 -0
  40. package/dist/core/workspace.js +1 -0
  41. package/dist/core/workspace.js.map +1 -1
  42. package/dist/discovery/commands.d.ts +1 -0
  43. package/dist/discovery/commands.js +3 -1
  44. package/dist/discovery/commands.js.map +1 -1
  45. package/dist/features/schema.d.ts +3 -0
  46. package/dist/features/schema.js +79 -0
  47. package/dist/features/schema.js.map +1 -0
  48. package/dist/features/types.d.ts +77 -0
  49. package/dist/features/types.js +2 -0
  50. package/dist/features/types.js.map +1 -0
  51. package/dist/features/validate.d.ts +14 -0
  52. package/dist/features/validate.js +124 -0
  53. package/dist/features/validate.js.map +1 -0
  54. package/dist/index.d.ts +8 -2
  55. package/dist/index.js +4 -1
  56. package/dist/index.js.map +1 -1
  57. package/dist/integrations/adapters/claudePlugin.d.ts +12 -0
  58. package/dist/integrations/adapters/claudePlugin.js +37 -8
  59. package/dist/integrations/adapters/claudePlugin.js.map +1 -1
  60. package/dist/integrations/adapters/pluginSkill.js +5 -0
  61. package/dist/integrations/adapters/pluginSkill.js.map +1 -1
  62. package/dist/security/files.js +10 -2
  63. package/dist/security/files.js.map +1 -1
  64. package/dist/security/redact.js +1 -1
  65. package/dist/security/redact.js.map +1 -1
  66. package/dist/services/agent.d.ts +12 -2
  67. package/dist/services/agent.js +96 -14
  68. package/dist/services/agent.js.map +1 -1
  69. package/dist/services/analysis.js +3 -3
  70. package/dist/services/analysis.js.map +1 -1
  71. package/dist/services/doctor.js +65 -14
  72. package/dist/services/doctor.js.map +1 -1
  73. package/dist/services/drift.d.ts +21 -0
  74. package/dist/services/drift.js +89 -0
  75. package/dist/services/drift.js.map +1 -0
  76. package/dist/services/features.d.ts +22 -0
  77. package/dist/services/features.js +105 -0
  78. package/dist/services/features.js.map +1 -0
  79. package/dist/services/graph.d.ts +97 -0
  80. package/dist/services/graph.js +342 -0
  81. package/dist/services/graph.js.map +1 -0
  82. package/dist/services/refresh.js +15 -0
  83. package/dist/services/refresh.js.map +1 -1
  84. package/dist/services/reset.js +45 -5
  85. package/dist/services/reset.js.map +1 -1
  86. package/dist/services/setup.d.ts +56 -0
  87. package/dist/services/setup.js +116 -0
  88. package/dist/services/setup.js.map +1 -0
  89. package/dist/services/status.d.ts +8 -0
  90. package/dist/services/status.js +78 -10
  91. package/dist/services/status.js.map +1 -1
  92. package/dist/services/tasks.js +6 -1
  93. package/dist/services/tasks.js.map +1 -1
  94. package/dist/services/verify.d.ts +11 -0
  95. package/dist/services/verify.js +64 -2
  96. package/dist/services/verify.js.map +1 -1
  97. package/dist/tasks/routing.js +14 -10
  98. package/dist/tasks/routing.js.map +1 -1
  99. package/dist/tasks/task.js +6 -2
  100. package/dist/tasks/task.js.map +1 -1
  101. package/dist/verification/scope.js +1 -1
  102. package/dist/verification/scope.js.map +1 -1
  103. package/docs/agents.md +60 -0
  104. package/docs/architecture-report/01-executive-summary.md +168 -0
  105. package/docs/architecture-report/02-system-architecture.md +356 -0
  106. package/docs/architecture-report/03-tools-and-technologies.md +112 -0
  107. package/docs/architecture-report/04-execution-flows.md +257 -0
  108. package/docs/architecture-report/05-codebase-map.md +150 -0
  109. package/docs/architecture-report/06-command-reference.md +446 -0
  110. package/docs/architecture-report/07-data-flow-and-integrations.md +268 -0
  111. package/docs/architecture-report/08-build-test-deployment.md +185 -0
  112. package/docs/architecture-report/09-security-and-reliability.md +165 -0
  113. package/docs/architecture-report/10-feature-status.md +110 -0
  114. package/docs/architecture-report/11-glossary.md +97 -0
  115. package/docs/architecture-report/README.md +103 -0
  116. package/docs/architecture-report/diagrams.md +446 -0
  117. package/docs/architecture.md +2 -2
  118. package/docs/getting-started.md +38 -1
  119. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../src/services/refresh.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { SCHEMA_VERSION, validateAnalysisState, type AnalysisState } from '../config/schemas.js';\nimport { loadProject } from '../core/workspace.js';\nimport { readVersioned, writeVersioned } from '../core/versioned.js';\nimport { packageVersion } from '../core/version.js';\nimport { applyStaleness, evaluateStaleness, loadFacts, saveFacts } from '../knowledge/facts.js';\nimport { buildRefreshPrompt } from '../prompts/refresh.js';\nimport { pathExists, sha256Text, writeJsonIfChanged, writeTextIfChanged } from '../utils/fs.js';\nimport { applyDetectorFacts, runDiscovery, writeCommands } from './analysis.js';\nimport { isoNow, mutate, type ServiceOptions } from './common.js';\n\nexport interface RefreshResult {\n dryRun: boolean;\n headChanged: boolean;\n autoRefreshed: string[];\n retired: string[];\n stale: { key: string; value: string; reason: string }[];\n needsReview: { key: string; reason: string }[];\n prompt: string | null;\n}\n\n/**\n * Incremental refresh. Deterministic facts are re-derived on the spot; everything else is re-hashed against its cited\n * sources and only the facts whose evidence changed become STALE and enter the (optional) agent refresh prompt.\n */\nexport async function refreshWorkspace(o: ServiceOptions): Promise<RefreshResult> {\n return mutate(o, async (ws) => {\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 let previous: AnalysisState | null = null;\n if (await pathExists(ws.analysisState)) {\n previous = (await readVersioned(ws.analysisState, 'analysis', SCHEMA_VERSION, validateAnalysisState)).data;\n }\n const headChanged = !!previous && previous.gitHead !== run.gitHead;\n\n if (o.dryRun) {\n const facts = await loadFacts(ws);\n const view = await evaluateStaleness(ws.root, facts, now);\n const valueOf = (key: string): string => facts.facts.find((f) => f.key === key)?.value ?? '';\n return {\n dryRun: true,\n headChanged,\n autoRefreshed: [],\n retired: [],\n stale: [...view.recorded, ...view.detected].map((s) => ({ ...s, value: valueOf(s.key) })),\n needsReview: view.needsReview,\n prompt: null,\n };\n }\n\n await writeJsonIfChanged(ws.discovery, run.discovery);\n await writeCommands(ws, run.discovery.commands, { truncated: run.discovery.scan.truncated });\n const det = await applyDetectorFacts(ws, run.discovery, now);\n\n const facts = await loadFacts(ws);\n const rep = await applyStaleness(ws.root, facts, now);\n await saveFacts(ws, facts);\n\n const stale = facts.facts.filter((f) => f.status === 'STALE' && f.sourceType !== 'detector').map((f) => ({ key: f.key, value: f.value, reason: f.staleReason ?? 'evidence changed' }));\n let prompt: string | null = null;\n if (stale.length > 0 || rep.needsReview.length > 0) {\n await writeTextIfChanged(\n ws.refreshPrompt,\n buildRefreshPrompt({ projectName: project.name, stale, needsReview: rep.needsReview, autoRefreshed: det.written, cliVersion: packageVersion() }),\n );\n prompt = path.relative(ws.root, ws.refreshPrompt).replace(/\\\\/g, '/');\n }\n\n const state: AnalysisState = {\n schemaVersion: SCHEMA_VERSION,\n analyzedAt: previous?.analyzedAt ?? now,\n refreshedAt: now,\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, headChanged, autoRefreshed: det.written, retired: det.retired, stale, needsReview: rep.needsReview, prompt };\n });\n}\n"]}
1
+ {"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../src/services/refresh.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'node:path';\nimport { SCHEMA_VERSION, validateAnalysisState, type AnalysisState } from '../config/schemas.js';\nimport { loadProject } from '../core/workspace.js';\nimport { readVersioned, writeVersioned } from '../core/versioned.js';\nimport { packageVersion } from '../core/version.js';\nimport { applyStaleness, evaluateStaleness, loadFacts, saveFacts } from '../knowledge/facts.js';\nimport { loadFeatures, saveFeatures } from './features.js';\nimport { validateFeature } from '../features/validate.js';\nimport { buildRefreshPrompt } from '../prompts/refresh.js';\nimport { pathExists, sha256Text, writeJsonIfChanged, writeTextIfChanged } from '../utils/fs.js';\nimport { applyDetectorFacts, runDiscovery, writeCommands } from './analysis.js';\nimport { isoNow, mutate, type ServiceOptions } from './common.js';\n\nexport interface RefreshResult {\n dryRun: boolean;\n headChanged: boolean;\n autoRefreshed: string[];\n retired: string[];\n stale: { key: string; value: string; reason: string }[];\n needsReview: { key: string; reason: string }[];\n prompt: string | null;\n}\n\n/**\n * Incremental refresh. Deterministic facts are re-derived on the spot; everything else is re-hashed against its cited\n * sources and only the facts whose evidence changed become STALE and enter the (optional) agent refresh prompt.\n */\nexport async function refreshWorkspace(o: ServiceOptions): Promise<RefreshResult> {\n return mutate(o, async (ws) => {\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 let previous: AnalysisState | null = null;\n if (await pathExists(ws.analysisState)) {\n previous = (await readVersioned(ws.analysisState, 'analysis', SCHEMA_VERSION, validateAnalysisState)).data;\n }\n const headChanged = !!previous && previous.gitHead !== run.gitHead;\n\n if (o.dryRun) {\n const facts = await loadFacts(ws);\n const view = await evaluateStaleness(ws.root, facts, now);\n const valueOf = (key: string): string => facts.facts.find((f) => f.key === key)?.value ?? '';\n return {\n dryRun: true,\n headChanged,\n autoRefreshed: [],\n retired: [],\n stale: [...view.recorded, ...view.detected].map((s) => ({ ...s, value: valueOf(s.key) })),\n needsReview: view.needsReview,\n prompt: null,\n };\n }\n\n await writeJsonIfChanged(ws.discovery, run.discovery);\n await writeCommands(ws, run.discovery.commands, { truncated: run.discovery.scan.truncated });\n const det = await applyDetectorFacts(ws, run.discovery, now);\n\n const facts = await loadFacts(ws);\n const rep = await applyStaleness(ws.root, facts, now);\n await saveFacts(ws, facts);\n\n if (await pathExists(ws.features)) {\n try {\n const featuresFile = await loadFeatures(ws);\n for (const feat of featuresFile.features) {\n const checked = await validateFeature(ws.root, feat);\n feat.status = checked.status;\n }\n await saveFeatures(ws, featuresFile);\n } catch {\n // preserve existing features on error\n }\n }\n\n const stale = facts.facts.filter((f) => f.status === 'STALE' && f.sourceType !== 'detector').map((f) => ({ key: f.key, value: f.value, reason: f.staleReason ?? 'evidence changed' }));\n let prompt: string | null = null;\n if (stale.length > 0 || rep.needsReview.length > 0) {\n await writeTextIfChanged(\n ws.refreshPrompt,\n buildRefreshPrompt({ projectName: project.name, stale, needsReview: rep.needsReview, autoRefreshed: det.written, cliVersion: packageVersion() }),\n );\n prompt = path.relative(ws.root, ws.refreshPrompt).replace(/\\\\/g, '/');\n }\n\n const state: AnalysisState = {\n schemaVersion: SCHEMA_VERSION,\n analyzedAt: previous?.analyzedAt ?? now,\n refreshedAt: now,\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, headChanged, autoRefreshed: det.written, retired: det.retired, stale, needsReview: rep.needsReview, prompt };\n });\n}\n"]}
@@ -3,7 +3,7 @@ import path from 'node:path';
3
3
  import { removeManagedSection } from '../agents/claude/adapter.js';
4
4
  import { SKILL_MARKER, SKILL_PATH } from '../agents/claude/content.js';
5
5
  import { DevWorkspaceError } from '../errors/index.js';
6
- import { findWorkspaceRoot, WORKSPACE_DIR, wsPaths } from '../core/workspace.js';
6
+ import { findWorkspaceRoot, loadProject, WORKSPACE_DIR, wsPaths } from '../core/workspace.js';
7
7
  import { atomicWriteFile, pathExists } from '../utils/fs.js';
8
8
  import { isInside } from '../utils/paths.js';
9
9
  import { withLock } from '../utils/lock.js';
@@ -45,7 +45,27 @@ export async function resetWorkspace(o) {
45
45
  ];
46
46
  const pending = [];
47
47
  if (o.includeAgentFiles) {
48
- for (const rel of ['CLAUDE.md', '.claude/CLAUDE.md']) {
48
+ const candidateFiles = [
49
+ 'CLAUDE.md',
50
+ '.claude/CLAUDE.md',
51
+ 'AGENTS.md',
52
+ '.cursorrules',
53
+ '.cursor/rules/devworkspace.mdc',
54
+ '.github/copilot-instructions.md',
55
+ ];
56
+ try {
57
+ const p = await loadProject(ws);
58
+ for (const m of p.managedFiles) {
59
+ if (!candidateFiles.includes(m.path))
60
+ candidateFiles.push(m.path);
61
+ }
62
+ }
63
+ catch {
64
+ /* project.json might be missing */
65
+ }
66
+ for (const rel of candidateFiles) {
67
+ if (rel === SKILL_PATH)
68
+ continue;
49
69
  const full = path.join(root, ...rel.split('/'));
50
70
  const text = await fs.readFile(full, 'utf8').catch(() => null);
51
71
  if (text === null)
@@ -57,9 +77,29 @@ export async function resetWorkspace(o) {
57
77
  }
58
78
  continue;
59
79
  }
60
- if (removed.empty) {
80
+ // Check if remaining content is empty or contains only cursor rule frontmatter
81
+ const cleanContent = removed.content
82
+ .replace(/^---\r?\ndescription:[^\r\n]*\r?\nalwaysApply:[^\r\n]*\r?\n---\r?\n?/m, '')
83
+ .trim();
84
+ const isEmpty = removed.empty || cleanContent.length === 0;
85
+ if (isEmpty) {
61
86
  actions.push({ path: rel, action: 'delete-file', note: 'contained only the DevWorkspace block' });
62
- pending.push(() => fs.rm(full, { force: true }));
87
+ pending.push(async () => {
88
+ await fs.rm(full, { force: true });
89
+ const parent = path.dirname(full);
90
+ if (parent !== root) {
91
+ const siblings = await fs.readdir(parent).catch(() => []);
92
+ if (siblings.length === 0) {
93
+ await fs.rmdir(parent).catch(() => undefined);
94
+ const grand = path.dirname(parent);
95
+ if (grand !== root) {
96
+ const grandSiblings = await fs.readdir(grand).catch(() => []);
97
+ if (grandSiblings.length === 0)
98
+ await fs.rmdir(grand).catch(() => undefined);
99
+ }
100
+ }
101
+ }
102
+ });
63
103
  }
64
104
  else {
65
105
  actions.push({ path: rel, action: 'remove-managed-section', note: 'your own content is kept' });
@@ -71,7 +111,7 @@ export async function resetWorkspace(o) {
71
111
  if (skill !== null) {
72
112
  if (skill.includes(SKILL_MARKER)) {
73
113
  const dir = path.dirname(skillFile);
74
- const others = (await fs.readdir(dir)).filter((n) => n !== 'SKILL.md');
114
+ const others = (await fs.readdir(dir).catch(() => [])).filter((n) => n !== 'SKILL.md');
75
115
  actions.push({ path: SKILL_PATH, action: 'delete-file', note: 'DevWorkspace-managed skill' });
76
116
  pending.push(async () => {
77
117
  await fs.rm(skillFile, { force: true });
@@ -1 +1 @@
1
- {"version":3,"file":"reset.js","sourceRoot":"","sources":["../../src/services/reset.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { removeManagedSection } from '../agents/claude/adapter.js';\nimport { SKILL_MARKER, SKILL_PATH } from '../agents/claude/content.js';\nimport { DevWorkspaceError } from '../errors/index.js';\nimport { findWorkspaceRoot, WORKSPACE_DIR, wsPaths } from '../core/workspace.js';\nimport { atomicWriteFile, pathExists } from '../utils/fs.js';\nimport { isInside } from '../utils/paths.js';\nimport { withLock } from '../utils/lock.js';\nimport type { ServiceOptions } from './common.js';\n\nexport interface ResetOptions extends ServiceOptions {\n /** Actually delete. Without it, reset only reports what it would remove. */\n confirm?: boolean;\n /** Also remove the DevWorkspace block from CLAUDE.md and the managed devworkspace skill. */\n includeAgentFiles?: boolean;\n}\n\nexport interface ResetAction {\n path: string;\n action: 'delete-folder' | 'remove-managed-section' | 'delete-file' | 'skip';\n note: string;\n}\n\nexport interface ResetResult {\n root: string;\n executed: boolean;\n actions: ResetAction[];\n fileCount: number;\n}\n\nasync function countFiles(dir: string): Promise<number> {\n let n = 0;\n for (const e of await fs.readdir(dir, { withFileTypes: true })) {\n if (e.isDirectory()) n += await countFiles(path.join(dir, e.name));\n else n++;\n }\n return n;\n}\n\n/**\n * Remove .devworkspace/ so the user can start again with `init`. Only DevWorkspace's own folder is ever deleted;\n * application files are never touched, and with includeAgentFiles only the managed block / managed skill are removed.\n */\nexport async function resetWorkspace(o: ResetOptions): Promise<ResetResult> {\n let root = await findWorkspaceRoot(o.cwd);\n if (!root && (await pathExists(path.join(o.cwd, WORKSPACE_DIR)))) root = path.resolve(o.cwd); // half-initialised workspace\n if (!root) {\n throw new DevWorkspaceError('NOT_FOUND', 'No .devworkspace folder found in this directory or any parent.', { hint: 'Nothing to reset.' });\n }\n const ws = wsPaths(root);\n const st = await fs.lstat(ws.dir);\n if (st.isSymbolicLink() || !st.isDirectory()) {\n throw new DevWorkspaceError('UNSAFE_PATH', '.devworkspace is a symlink or not a directory; refusing to delete it.', {\n hint: 'Remove it by hand if you are sure.',\n });\n }\n const real = await fs.realpath(ws.dir);\n if (!isInside(await fs.realpath(root), real) || path.basename(real) !== WORKSPACE_DIR) {\n throw new DevWorkspaceError('UNSAFE_PATH', 'Resolved workspace path is outside the project; refusing to delete it.');\n }\n\n const fileCount = await countFiles(ws.dir);\n const actions: ResetAction[] = [\n { path: `${WORKSPACE_DIR}/`, action: 'delete-folder', note: `${fileCount} file(s): knowledge, decisions, tasks, sessions, analysis and local state` },\n ];\n const pending: (() => Promise<void>)[] = [];\n\n if (o.includeAgentFiles) {\n for (const rel of ['CLAUDE.md', '.claude/CLAUDE.md']) {\n const full = path.join(root, ...rel.split('/'));\n const text = await fs.readFile(full, 'utf8').catch(() => null);\n if (text === null) continue;\n const removed = removeManagedSection(text);\n if (!removed) {\n if (text.includes('<!-- devworkspace:start') || text.includes('<!-- devworkspace:end')) {\n actions.push({ path: rel, action: 'skip', note: 'managed markers are unbalanced; edit by hand' });\n }\n continue;\n }\n if (removed.empty) {\n actions.push({ path: rel, action: 'delete-file', note: 'contained only the DevWorkspace block' });\n pending.push(() => fs.rm(full, { force: true }));\n } else {\n actions.push({ path: rel, action: 'remove-managed-section', note: 'your own content is kept' });\n pending.push(() => atomicWriteFile(full, removed.content));\n }\n }\n const skillFile = path.join(root, ...SKILL_PATH.split('/'));\n const skill = await fs.readFile(skillFile, 'utf8').catch(() => null);\n if (skill !== null) {\n if (skill.includes(SKILL_MARKER)) {\n const dir = path.dirname(skillFile);\n const others = (await fs.readdir(dir)).filter((n) => n !== 'SKILL.md');\n actions.push({ path: SKILL_PATH, action: 'delete-file', note: 'DevWorkspace-managed skill' });\n pending.push(async () => {\n await fs.rm(skillFile, { force: true });\n if (others.length === 0) await fs.rmdir(dir).catch(() => undefined);\n });\n } else {\n actions.push({ path: SKILL_PATH, action: 'skip', note: 'not managed by DevWorkspace (no marker); left alone' });\n }\n }\n }\n\n if (!o.confirm || o.dryRun) return { root, executed: false, actions, fileCount };\n\n await withLock(ws.dir, async () => {\n for (const w of pending) await w();\n });\n await fs.rm(ws.dir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });\n return { root, executed: true, actions, fileCount };\n}\n"]}
1
+ {"version":3,"file":"reset.js","sourceRoot":"","sources":["../../src/services/reset.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { removeManagedSection } from '../agents/claude/adapter.js';\nimport { SKILL_MARKER, SKILL_PATH } from '../agents/claude/content.js';\nimport { DevWorkspaceError } from '../errors/index.js';\nimport { findWorkspaceRoot, loadProject, WORKSPACE_DIR, wsPaths } from '../core/workspace.js';\nimport { atomicWriteFile, pathExists } from '../utils/fs.js';\nimport { isInside } from '../utils/paths.js';\nimport { withLock } from '../utils/lock.js';\nimport type { ServiceOptions } from './common.js';\n\nexport interface ResetOptions extends ServiceOptions {\n /** Actually delete. Without it, reset only reports what it would remove. */\n confirm?: boolean;\n /** Also remove the DevWorkspace block from CLAUDE.md and the managed devworkspace skill. */\n includeAgentFiles?: boolean;\n}\n\nexport interface ResetAction {\n path: string;\n action: 'delete-folder' | 'remove-managed-section' | 'delete-file' | 'skip';\n note: string;\n}\n\nexport interface ResetResult {\n root: string;\n executed: boolean;\n actions: ResetAction[];\n fileCount: number;\n}\n\nasync function countFiles(dir: string): Promise<number> {\n let n = 0;\n for (const e of await fs.readdir(dir, { withFileTypes: true })) {\n if (e.isDirectory()) n += await countFiles(path.join(dir, e.name));\n else n++;\n }\n return n;\n}\n\n/**\n * Remove .devworkspace/ so the user can start again with `init`. Only DevWorkspace's own folder is ever deleted;\n * application files are never touched, and with includeAgentFiles only the managed block / managed skill are removed.\n */\nexport async function resetWorkspace(o: ResetOptions): Promise<ResetResult> {\n let root = await findWorkspaceRoot(o.cwd);\n if (!root && (await pathExists(path.join(o.cwd, WORKSPACE_DIR)))) root = path.resolve(o.cwd); // half-initialised workspace\n if (!root) {\n throw new DevWorkspaceError('NOT_FOUND', 'No .devworkspace folder found in this directory or any parent.', { hint: 'Nothing to reset.' });\n }\n const ws = wsPaths(root);\n const st = await fs.lstat(ws.dir);\n if (st.isSymbolicLink() || !st.isDirectory()) {\n throw new DevWorkspaceError('UNSAFE_PATH', '.devworkspace is a symlink or not a directory; refusing to delete it.', {\n hint: 'Remove it by hand if you are sure.',\n });\n }\n const real = await fs.realpath(ws.dir);\n if (!isInside(await fs.realpath(root), real) || path.basename(real) !== WORKSPACE_DIR) {\n throw new DevWorkspaceError('UNSAFE_PATH', 'Resolved workspace path is outside the project; refusing to delete it.');\n }\n\n const fileCount = await countFiles(ws.dir);\n const actions: ResetAction[] = [\n { path: `${WORKSPACE_DIR}/`, action: 'delete-folder', note: `${fileCount} file(s): knowledge, decisions, tasks, sessions, analysis and local state` },\n ];\n const pending: (() => Promise<void>)[] = [];\n\n if (o.includeAgentFiles) {\n const candidateFiles = [\n 'CLAUDE.md',\n '.claude/CLAUDE.md',\n 'AGENTS.md',\n '.cursorrules',\n '.cursor/rules/devworkspace.mdc',\n '.github/copilot-instructions.md',\n ];\n try {\n const p = await loadProject(ws);\n for (const m of p.managedFiles) {\n if (!candidateFiles.includes(m.path)) candidateFiles.push(m.path);\n }\n } catch {\n /* project.json might be missing */\n }\n\n for (const rel of candidateFiles) {\n if (rel === SKILL_PATH) continue;\n const full = path.join(root, ...rel.split('/'));\n const text = await fs.readFile(full, 'utf8').catch(() => null);\n if (text === null) continue;\n const removed = removeManagedSection(text);\n if (!removed) {\n if (text.includes('<!-- devworkspace:start') || text.includes('<!-- devworkspace:end')) {\n actions.push({ path: rel, action: 'skip', note: 'managed markers are unbalanced; edit by hand' });\n }\n continue;\n }\n // Check if remaining content is empty or contains only cursor rule frontmatter\n const cleanContent = removed.content\n .replace(/^---\\r?\\ndescription:[^\\r\\n]*\\r?\\nalwaysApply:[^\\r\\n]*\\r?\\n---\\r?\\n?/m, '')\n .trim();\n const isEmpty = removed.empty || cleanContent.length === 0;\n\n if (isEmpty) {\n actions.push({ path: rel, action: 'delete-file', note: 'contained only the DevWorkspace block' });\n pending.push(async () => {\n await fs.rm(full, { force: true });\n const parent = path.dirname(full);\n if (parent !== root) {\n const siblings = await fs.readdir(parent).catch(() => []);\n if (siblings.length === 0) {\n await fs.rmdir(parent).catch(() => undefined);\n const grand = path.dirname(parent);\n if (grand !== root) {\n const grandSiblings = await fs.readdir(grand).catch(() => []);\n if (grandSiblings.length === 0) await fs.rmdir(grand).catch(() => undefined);\n }\n }\n }\n });\n } else {\n actions.push({ path: rel, action: 'remove-managed-section', note: 'your own content is kept' });\n pending.push(() => atomicWriteFile(full, removed.content));\n }\n }\n const skillFile = path.join(root, ...SKILL_PATH.split('/'));\n const skill = await fs.readFile(skillFile, 'utf8').catch(() => null);\n if (skill !== null) {\n if (skill.includes(SKILL_MARKER)) {\n const dir = path.dirname(skillFile);\n const others = (await fs.readdir(dir).catch(() => [])).filter((n) => n !== 'SKILL.md');\n actions.push({ path: SKILL_PATH, action: 'delete-file', note: 'DevWorkspace-managed skill' });\n pending.push(async () => {\n await fs.rm(skillFile, { force: true });\n if (others.length === 0) await fs.rmdir(dir).catch(() => undefined);\n });\n } else {\n actions.push({ path: SKILL_PATH, action: 'skip', note: 'not managed by DevWorkspace (no marker); left alone' });\n }\n }\n }\n\n if (!o.confirm || o.dryRun) return { root, executed: false, actions, fileCount };\n\n await withLock(ws.dir, async () => {\n for (const w of pending) await w();\n });\n await fs.rm(ws.dir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });\n return { root, executed: true, actions, fileCount };\n}\n"]}
@@ -0,0 +1,56 @@
1
+ import { type ServiceOptions } from './common.js';
2
+ import type { ContractDriftItem } from '../discovery/commands.js';
3
+ export type CliExecutionMode = 'source-checkout' | 'installed-package' | 'npx-cache';
4
+ export interface CliProvenance {
5
+ version: string;
6
+ path: string;
7
+ mode: CliExecutionMode;
8
+ }
9
+ export declare function detectCliProvenance(): CliProvenance;
10
+ export interface ProjectSetupResult {
11
+ root: string;
12
+ os: string;
13
+ nodeVersion: string;
14
+ cli: CliProvenance;
15
+ initialized: boolean;
16
+ isFirstRun: boolean;
17
+ projectName: string;
18
+ packages: {
19
+ path: string;
20
+ ecosystem: string;
21
+ packageManager?: string;
22
+ }[];
23
+ frameworks: string[];
24
+ verification: {
25
+ total: number;
26
+ available: number;
27
+ checks: string[];
28
+ drift: ContractDriftItem[];
29
+ };
30
+ features: {
31
+ present: boolean;
32
+ total: number;
33
+ verified: number;
34
+ unknown: number;
35
+ } | null;
36
+ integrations: {
37
+ id: string;
38
+ name: string;
39
+ status: string;
40
+ required: boolean;
41
+ }[];
42
+ doctor: {
43
+ healthy: boolean;
44
+ passed: number;
45
+ warnings: number;
46
+ failures: number;
47
+ };
48
+ nextSteps: string[];
49
+ }
50
+ /**
51
+ * Single-command setup workflow.
52
+ * Idempotently inspects repository, initializes or safely updates .devworkspace/,
53
+ * discovers packages & commands, checks for drift, validates feature map if present,
54
+ * observes optional integrations, and runs safe diagnostics.
55
+ */
56
+ export declare function setupProject(o: ServiceOptions): Promise<ProjectSetupResult>;
@@ -0,0 +1,116 @@
1
+ import os from 'node:os';
2
+ import path from 'node:path';
3
+ import { packageVersion } from '../core/version.js';
4
+ import { findWorkspaceRoot, loadProject, wsPaths } from '../core/workspace.js';
5
+ import { detectContractDrift } from '../discovery/commands.js';
6
+ import { inspectAll } from '../integrations/index.js';
7
+ import { pathExists } from '../utils/fs.js';
8
+ import { analyzeWorkspace } from './analysis.js';
9
+ import { managerEnv } from './common.js';
10
+ import { runDoctor } from './doctor.js';
11
+ import { loadFeatures } from './features.js';
12
+ import { initWorkspace } from './init.js';
13
+ import { validateFeatureMap } from '../features/validate.js';
14
+ export function detectCliProvenance() {
15
+ const cliPath = process.argv[1] ? path.resolve(process.argv[1]) : 'unknown';
16
+ const norm = cliPath.replace(/\\/g, '/');
17
+ let mode = 'installed-package';
18
+ if (norm.includes('/_npx/') || norm.includes('\\_npx\\')) {
19
+ mode = 'npx-cache';
20
+ }
21
+ else if (norm.includes('/devworkspace/dist/') || norm.endsWith('/dist/cli/main.js') || norm.endsWith('/src/cli/main.ts')) {
22
+ mode = 'source-checkout';
23
+ }
24
+ return { version: packageVersion(), path: cliPath, mode };
25
+ }
26
+ /**
27
+ * Single-command setup workflow.
28
+ * Idempotently inspects repository, initializes or safely updates .devworkspace/,
29
+ * discovers packages & commands, checks for drift, validates feature map if present,
30
+ * observes optional integrations, and runs safe diagnostics.
31
+ */
32
+ export async function setupProject(o) {
33
+ const startDir = o.cwd ? path.resolve(o.cwd) : process.cwd();
34
+ const existingRoot = await findWorkspaceRoot(startDir);
35
+ const root = existingRoot ?? startDir;
36
+ const isFirstRun = !existingRoot;
37
+ const cli = detectCliProvenance();
38
+ // 1. Initialize workspace non-destructively
39
+ await initWorkspace({ ...o, cwd: root, root });
40
+ // 2. Discover packages, commands, frameworks, entrypoints, and derive detector facts
41
+ const ws = wsPaths(root);
42
+ const analysis = await analyzeWorkspace(ws, { ...o, cwd: root });
43
+ // 3. Inspect configured verification commands and detect contract drift
44
+ const driftReport = await detectContractDrift(ws.root, analysis.discovery.commands);
45
+ const availableChecks = analysis.discovery.commands.filter((c) => c.available);
46
+ // 4. Validate feature map if present
47
+ let featuresSummary = null;
48
+ if (await pathExists(ws.features)) {
49
+ try {
50
+ const f = await loadFeatures(ws);
51
+ const rep = await validateFeatureMap(ws.root, f.features);
52
+ featuresSummary = {
53
+ present: true,
54
+ total: rep.total,
55
+ verified: rep.verified,
56
+ unknown: rep.unknown,
57
+ };
58
+ }
59
+ catch {
60
+ featuresSummary = { present: true, total: 0, verified: 0, unknown: 0 };
61
+ }
62
+ }
63
+ // 5. Shallowly observe optional integrations (Graphify, Agent Skills, Ponytail, OmniRoute)
64
+ const integrationsReports = await inspectAll(ws, managerEnv(o, root), { deep: false });
65
+ const integrations = integrationsReports.map((r) => ({
66
+ id: r.id,
67
+ name: r.name,
68
+ status: r.status,
69
+ required: r.required,
70
+ }));
71
+ // 6. Run doctor diagnostics
72
+ const doctorResult = await runDoctor({ ...o, cwd: root });
73
+ // 7. Compile next steps
74
+ const nextSteps = [];
75
+ if (driftReport.hasDrift) {
76
+ nextSteps.push('Review verification contract drift: run "devworkspace refresh" or edit .devworkspace/context/commands.json.');
77
+ }
78
+ const missingRequired = integrationsReports.filter((r) => r.required && r.status === 'NOT_INSTALLED');
79
+ if (missingRequired.length > 0) {
80
+ nextSteps.push(`Optional integrations: run "devworkspace setup --integrations --yes" to install ${missingRequired.map((m) => m.name).join(', ')}.`);
81
+ }
82
+ nextSteps.push('Check overall workspace health: run "devworkspace status".');
83
+ nextSteps.push('Start your first engineering task: run "devworkspace task new <request>".');
84
+ const project = await loadProject(ws);
85
+ return {
86
+ root,
87
+ os: `${os.type()} ${os.release()} (${process.platform})`,
88
+ nodeVersion: process.versions.node,
89
+ cli,
90
+ initialized: true,
91
+ isFirstRun,
92
+ projectName: project.name,
93
+ packages: analysis.discovery.monorepo.packages.map((p) => ({
94
+ path: p.path,
95
+ ecosystem: p.ecosystem,
96
+ packageManager: p.packageManager,
97
+ })),
98
+ frameworks: analysis.discovery.frameworks.map((f) => f.name),
99
+ verification: {
100
+ total: analysis.discovery.commands.length,
101
+ available: availableChecks.length,
102
+ checks: [...new Set(availableChecks.map((c) => c.id))],
103
+ drift: driftReport.issues,
104
+ },
105
+ features: featuresSummary,
106
+ integrations,
107
+ doctor: {
108
+ healthy: doctorResult.healthy,
109
+ passed: doctorResult.counts.pass,
110
+ warnings: doctorResult.counts.warn,
111
+ failures: doctorResult.counts.fail,
112
+ },
113
+ nextSteps,
114
+ };
115
+ }
116
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/services/setup.ts"],"names":[],"mappings":"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","sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\nimport { packageVersion } from '../core/version.js';\nimport { findWorkspaceRoot, loadProject, wsPaths } from '../core/workspace.js';\nimport { detectContractDrift } from '../discovery/commands.js';\nimport { inspectAll } from '../integrations/index.js';\nimport { pathExists } from '../utils/fs.js';\nimport { analyzeWorkspace } from './analysis.js';\nimport { managerEnv, type ServiceOptions } from './common.js';\nimport { runDoctor } from './doctor.js';\nimport { loadFeatures } from './features.js';\nimport { initWorkspace } from './init.js';\nimport { validateFeatureMap } from '../features/validate.js';\nimport type { ContractDriftItem } from '../discovery/commands.js';\n\nexport type CliExecutionMode = 'source-checkout' | 'installed-package' | 'npx-cache';\n\nexport interface CliProvenance {\n version: string;\n path: string;\n mode: CliExecutionMode;\n}\n\nexport function detectCliProvenance(): CliProvenance {\n const cliPath = process.argv[1] ? path.resolve(process.argv[1]) : 'unknown';\n const norm = cliPath.replace(/\\\\/g, '/');\n let mode: CliExecutionMode = 'installed-package';\n if (norm.includes('/_npx/') || norm.includes('\\\\_npx\\\\')) {\n mode = 'npx-cache';\n } else if (norm.includes('/devworkspace/dist/') || norm.endsWith('/dist/cli/main.js') || norm.endsWith('/src/cli/main.ts')) {\n mode = 'source-checkout';\n }\n return { version: packageVersion(), path: cliPath, mode };\n}\n\nexport interface ProjectSetupResult {\n root: string;\n os: string;\n nodeVersion: string;\n cli: CliProvenance;\n initialized: boolean;\n isFirstRun: boolean;\n projectName: string;\n packages: { path: string; ecosystem: string; packageManager?: string }[];\n frameworks: string[];\n verification: {\n total: number;\n available: number;\n checks: string[];\n drift: ContractDriftItem[];\n };\n features: {\n present: boolean;\n total: number;\n verified: number;\n unknown: number;\n } | null;\n integrations: {\n id: string;\n name: string;\n status: string;\n required: boolean;\n }[];\n doctor: {\n healthy: boolean;\n passed: number;\n warnings: number;\n failures: number;\n };\n nextSteps: string[];\n}\n\n/**\n * Single-command setup workflow.\n * Idempotently inspects repository, initializes or safely updates .devworkspace/,\n * discovers packages & commands, checks for drift, validates feature map if present,\n * observes optional integrations, and runs safe diagnostics.\n */\nexport async function setupProject(o: ServiceOptions): Promise<ProjectSetupResult> {\n const startDir = o.cwd ? path.resolve(o.cwd) : process.cwd();\n const existingRoot = await findWorkspaceRoot(startDir);\n const root = existingRoot ?? startDir;\n const isFirstRun = !existingRoot;\n const cli = detectCliProvenance();\n\n // 1. Initialize workspace non-destructively\n await initWorkspace({ ...o, cwd: root, root });\n\n // 2. Discover packages, commands, frameworks, entrypoints, and derive detector facts\n const ws = wsPaths(root);\n const analysis = await analyzeWorkspace(ws, { ...o, cwd: root });\n\n // 3. Inspect configured verification commands and detect contract drift\n const driftReport = await detectContractDrift(ws.root, analysis.discovery.commands);\n const availableChecks = analysis.discovery.commands.filter((c) => c.available);\n\n // 4. Validate feature map if present\n let featuresSummary: ProjectSetupResult['features'] = null;\n if (await pathExists(ws.features)) {\n try {\n const f = await loadFeatures(ws);\n const rep = await validateFeatureMap(ws.root, f.features);\n featuresSummary = {\n present: true,\n total: rep.total,\n verified: rep.verified,\n unknown: rep.unknown,\n };\n } catch {\n featuresSummary = { present: true, total: 0, verified: 0, unknown: 0 };\n }\n }\n\n // 5. Shallowly observe optional integrations (Graphify, Agent Skills, Ponytail, OmniRoute)\n const integrationsReports = await inspectAll(ws, managerEnv(o, root), { deep: false });\n const integrations = integrationsReports.map((r) => ({\n id: r.id,\n name: r.name,\n status: r.status,\n required: r.required,\n }));\n\n // 6. Run doctor diagnostics\n const doctorResult = await runDoctor({ ...o, cwd: root });\n\n // 7. Compile next steps\n const nextSteps: string[] = [];\n if (driftReport.hasDrift) {\n nextSteps.push('Review verification contract drift: run \"devworkspace refresh\" or edit .devworkspace/context/commands.json.');\n }\n const missingRequired = integrationsReports.filter((r) => r.required && r.status === 'NOT_INSTALLED');\n if (missingRequired.length > 0) {\n nextSteps.push(`Optional integrations: run \"devworkspace setup --integrations --yes\" to install ${missingRequired.map((m) => m.name).join(', ')}.`);\n }\n nextSteps.push('Check overall workspace health: run \"devworkspace status\".');\n nextSteps.push('Start your first engineering task: run \"devworkspace task new <request>\".');\n\n const project = await loadProject(ws);\n\n return {\n root,\n os: `${os.type()} ${os.release()} (${process.platform})`,\n nodeVersion: process.versions.node,\n cli,\n initialized: true,\n isFirstRun,\n projectName: project.name,\n packages: analysis.discovery.monorepo.packages.map((p) => ({\n path: p.path,\n ecosystem: p.ecosystem,\n packageManager: p.packageManager,\n })),\n frameworks: analysis.discovery.frameworks.map((f) => f.name),\n verification: {\n total: analysis.discovery.commands.length,\n available: availableChecks.length,\n checks: [...new Set(availableChecks.map((c) => c.id))],\n drift: driftReport.issues,\n },\n features: featuresSummary,\n integrations,\n doctor: {\n healthy: doctorResult.healthy,\n passed: doctorResult.counts.pass,\n warnings: doctorResult.counts.warn,\n failures: doctorResult.counts.fail,\n },\n nextSteps,\n };\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { type Ws } from '../core/workspace.js';
2
2
  import { type IntegrationReport } from '../integrations/index.js';
3
+ import type { AgentAdapter } from '../agents/types.js';
3
4
  import { type ServiceOptions } from './common.js';
4
5
  export interface TaskBrief {
5
6
  id: string;
@@ -53,6 +54,12 @@ export interface StatusResult {
53
54
  cwd?: string;
54
55
  mutates?: boolean;
55
56
  }[];
57
+ features?: {
58
+ total: number;
59
+ verified: number;
60
+ inferred: number;
61
+ unknown: number;
62
+ } | null;
56
63
  lastSession: {
57
64
  id: string;
58
65
  goal: string;
@@ -60,6 +67,7 @@ export interface StatusResult {
60
67
  } | null;
61
68
  corruptTasks: number;
62
69
  }
70
+ export declare function detectInstalledAgents(ws: Ws): Promise<AgentAdapter[]>;
63
71
  export declare function instructionsInstalled(ws: Ws): Promise<boolean>;
64
72
  export declare function knowledgeWritten(ws: Ws): Promise<boolean>;
65
73
  /** Cheap overview: small workspace files, Git status and a fingerprint check of the few files facts cite. Never scans the repository. */
@@ -9,22 +9,75 @@ import { evaluateStaleness, loadFacts } from '../knowledge/facts.js';
9
9
  import { listSessions } from '../sessions/session.js';
10
10
  import { listTasks, nextRequiredStep } from '../tasks/task.js';
11
11
  import { pathExists } from '../utils/fs.js';
12
- import { SECTION_END } from '../agents/claude/content.js';
12
+ import { SECTION_START, SECTION_END } from '../agents/shared.js';
13
13
  import { SKILL_PATH } from '../agents/claude/content.js';
14
+ import { listAgentAdapters } from '../agents/index.js';
15
+ import { loadFeatures } from './features.js';
14
16
  import { isoNow, managerEnv } from './common.js';
15
17
  const brief = (t) => ({ id: t.id, title: t.title, type: t.type, status: t.status, updatedAt: t.updatedAt, next: nextRequiredStep(t) });
16
- export async function instructionsInstalled(ws) {
17
- for (const rel of ['CLAUDE.md', '.claude/CLAUDE.md']) {
18
- try {
19
- const text = await fs.readFile(path.join(ws.root, ...rel.split('/')), 'utf8');
20
- if (text.includes('<!-- devworkspace:start') && text.includes(SECTION_END) && (await pathExists(path.join(ws.root, ...SKILL_PATH.split('/')))))
21
- return true;
18
+ export async function detectInstalledAgents(ws) {
19
+ const installed = [];
20
+ for (const adapter of listAgentAdapters()) {
21
+ if (adapter.id === 'claude') {
22
+ let claudeFound = false;
23
+ for (const rel of ['CLAUDE.md', '.claude/CLAUDE.md']) {
24
+ try {
25
+ const text = await fs.readFile(path.join(ws.root, ...rel.split('/')), 'utf8');
26
+ if (text.includes(SECTION_START) && text.includes(SECTION_END) && (await pathExists(path.join(ws.root, ...SKILL_PATH.split('/'))))) {
27
+ claudeFound = true;
28
+ break;
29
+ }
30
+ }
31
+ catch {
32
+ /* try next */
33
+ }
34
+ }
35
+ if (claudeFound)
36
+ installed.push(adapter);
22
37
  }
23
- catch {
24
- /* try next */
38
+ else if (adapter.id === 'codex') {
39
+ try {
40
+ const text = await fs.readFile(path.join(ws.root, 'AGENTS.md'), 'utf8');
41
+ if (text.includes(SECTION_START) && text.includes(SECTION_END))
42
+ installed.push(adapter);
43
+ }
44
+ catch {
45
+ /* not found */
46
+ }
47
+ }
48
+ else if (adapter.id === 'cursor') {
49
+ let cursorFound = false;
50
+ for (const rel of ['.cursor/rules/devworkspace.mdc', '.cursorrules']) {
51
+ try {
52
+ const text = await fs.readFile(path.join(ws.root, ...rel.split('/')), 'utf8');
53
+ if (text.includes(SECTION_START) && text.includes(SECTION_END)) {
54
+ cursorFound = true;
55
+ break;
56
+ }
57
+ }
58
+ catch {
59
+ /* try next */
60
+ }
61
+ }
62
+ if (cursorFound)
63
+ installed.push(adapter);
64
+ }
65
+ else if (adapter.id === 'copilot') {
66
+ try {
67
+ const text = await fs.readFile(path.join(ws.root, '.github', 'copilot-instructions.md'), 'utf8');
68
+ if (text.includes(SECTION_START) && text.includes(SECTION_END))
69
+ installed.push(adapter);
70
+ }
71
+ catch {
72
+ /* not found */
73
+ }
25
74
  }
26
75
  }
27
- return false;
76
+ return installed;
77
+ }
78
+ export async function instructionsInstalled(ws) {
79
+ const installed = await detectInstalledAgents(ws);
80
+ return installed.length > 0;
28
81
  }
29
82
  export async function knowledgeWritten(ws) {
30
83
  try {
@@ -104,6 +157,21 @@ export async function getStatus(o, opts = {}) {
104
157
  const sessions = await listSessions(ws, 1);
105
158
  if (sessions[0])
106
159
  base.lastSession = { id: sessions[0].id, goal: sessions[0].goal, next: sessions[0].next };
160
+ if (await pathExists(ws.features)) {
161
+ try {
162
+ const f = await loadFeatures(ws);
163
+ const v = f.features.filter((x) => x.status === 'verified').length;
164
+ const inf = f.features.filter((x) => x.status === 'inferred').length;
165
+ const unk = f.features.filter((x) => x.status === 'unknown').length;
166
+ base.features = { total: f.features.length, verified: v, inferred: inf, unknown: unk };
167
+ }
168
+ catch {
169
+ base.features = null;
170
+ }
171
+ }
172
+ else {
173
+ base.features = null;
174
+ }
107
175
  base.integrations = await inspectAll(ws, managerEnv(o, root), { deep: !!opts.deep });
108
176
  base.onboarding.instructionsInstalled = await instructionsInstalled(ws);
109
177
  base.onboarding.knowledgeWritten = await knowledgeWritten(ws);
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/services/status.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, type CommandEntry } from '../config/schemas.js';\nimport { findWorkspaceRoot, loadProject, wsPaths, type Ws } from '../core/workspace.js';\nimport { readVersioned } from '../core/versioned.js';\nimport { getGitState } from '../git/git.js';\nimport { inspectAll, type IntegrationReport } from '../integrations/index.js';\nimport { evaluateStaleness, loadFacts } from '../knowledge/facts.js';\nimport { listSessions } from '../sessions/session.js';\nimport { listTasks, nextRequiredStep, type Task } from '../tasks/task.js';\nimport { pathExists } from '../utils/fs.js';\nimport { SECTION_END } from '../agents/claude/content.js';\nimport { SKILL_PATH } from '../agents/claude/content.js';\nimport { isoNow, managerEnv, type ServiceOptions } from './common.js';\n\nexport interface TaskBrief {\n id: string;\n title: string;\n type: string;\n status: string;\n updatedAt: string;\n next: string;\n}\n\nexport interface StatusResult {\n initialized: boolean;\n root: string | null;\n project: { name: string; id: string } | null;\n workspace: 'Healthy' | 'Needs attention' | 'Not initialized' | 'Unreadable';\n workspaceProblem?: string;\n git: { available: boolean; isRepo: boolean; branch: string | null; workingTree: 'Clean' | 'Modified' | 'Unknown'; changes: number };\n knowledge: { state: 'Current' | 'Stale' | 'Empty' | 'Unknown'; facts: number; stale: number; analyzedAt: string | null; staleItems: { key: string; reason: string; recorded: boolean }[]; needsReview: number };\n onboarding: { instructionsInstalled: boolean; knowledgeWritten: boolean; ready: boolean };\n /** Shallow observation (files and PATH only; never VERIFIED). Run doctor or `integrations status` to verify. */\n integrations: IntegrationReport[];\n activeTasks: TaskBrief[];\n verification: { id: string; available: boolean; command: string | null; required: string; cwd?: string; mutates?: boolean }[];\n lastSession: { id: string; goal: string; next: string } | null;\n corruptTasks: number;\n}\n\nconst brief = (t: Task): TaskBrief => ({ id: t.id, title: t.title, type: t.type, status: t.status, updatedAt: t.updatedAt, next: nextRequiredStep(t) });\n\nexport async function instructionsInstalled(ws: Ws): Promise<boolean> {\n for (const rel of ['CLAUDE.md', '.claude/CLAUDE.md']) {\n try {\n const text = await fs.readFile(path.join(ws.root, ...rel.split('/')), 'utf8');\n if (text.includes('<!-- devworkspace:start') && text.includes(SECTION_END) && (await pathExists(path.join(ws.root, ...SKILL_PATH.split('/'))))) return true;\n } catch {\n /* try next */\n }\n }\n return false;\n}\n\nexport async function knowledgeWritten(ws: Ws): Promise<boolean> {\n try {\n return (await fs.stat(path.join(ws.contextDir, 'architecture.md'))).size >= 200;\n } catch {\n return false;\n }\n}\n\n/** Cheap overview: small workspace files, Git status and a fingerprint check of the few files facts cite. Never scans the repository. */\nexport async function getStatus(o: ServiceOptions, opts: { deep?: boolean } = {}): Promise<StatusResult> {\n const root = await findWorkspaceRoot(o.cwd);\n const git = await getGitState(root ?? o.cwd);\n const gitBrief: StatusResult['git'] = {\n available: git.available,\n isRepo: git.isRepo,\n branch: git.branch,\n workingTree: git.isRepo ? (git.dirty ? 'Modified' : 'Clean') : 'Unknown',\n changes: git.entries.length,\n };\n const base: StatusResult = {\n initialized: false,\n root,\n project: null,\n workspace: 'Not initialized',\n git: gitBrief,\n knowledge: { state: 'Unknown', facts: 0, stale: 0, analyzedAt: null, staleItems: [], needsReview: 0 },\n onboarding: { instructionsInstalled: false, knowledgeWritten: false, ready: false },\n integrations: [],\n activeTasks: [],\n verification: [],\n lastSession: null,\n corruptTasks: 0,\n };\n if (!root) return base;\n\n const ws = wsPaths(root);\n base.initialized = true;\n try {\n const project = await loadProject(ws);\n base.project = { name: project.name, id: project.projectId };\n base.workspace = 'Healthy';\n } catch (e) {\n return { ...base, workspace: 'Unreadable', workspaceProblem: (e as Error).message };\n }\n\n try {\n const facts = await loadFacts(ws);\n const view = await evaluateStaleness(ws.root, facts, isoNow(o));\n const items = [...view.recorded.map((x) => ({ ...x, recorded: true })), ...view.detected.map((x) => ({ ...x, recorded: false }))];\n const stale = items.length;\n let analyzedAt: string | null = null;\n if (await pathExists(ws.analysisState)) {\n analyzedAt = (await readVersioned(ws.analysisState, 'analysis', SCHEMA_VERSION, validateAnalysisState)).data.analyzedAt;\n }\n base.knowledge = { facts: facts.facts.length, stale, analyzedAt, staleItems: items, needsReview: view.needsReview.length, state: facts.facts.length === 0 ? 'Empty' : stale > 0 ? 'Stale' : 'Current' };\n } catch (e) {\n base.workspace = 'Needs attention';\n base.workspaceProblem = (e as Error).message;\n }\n\n if (await pathExists(ws.commands)) {\n try {\n const commands = (await readVersioned(ws.commands, 'commands', SCHEMA_VERSION, validateCommands)).data;\n base.verification = commands.checks.map((c: CommandEntry) => ({ id: c.id, available: c.available, command: c.command, required: c.required, ...(c.cwd ? { cwd: c.cwd } : {}), ...(c.mutates !== undefined ? { mutates: c.mutates } : {}) }));\n } catch (e) {\n base.workspace = 'Needs attention';\n base.workspaceProblem ??= (e as Error).message;\n }\n }\n\n const { tasks, corrupt } = await listTasks(ws);\n base.activeTasks = tasks.map(brief);\n base.corruptTasks = corrupt.length;\n if (corrupt.length > 0) base.workspace = 'Needs attention';\n const sessions = await listSessions(ws, 1);\n if (sessions[0]) base.lastSession = { id: sessions[0].id, goal: sessions[0].goal, next: sessions[0].next };\n\n base.integrations = await inspectAll(ws, managerEnv(o, root), { deep: !!opts.deep });\n base.onboarding.instructionsInstalled = await instructionsInstalled(ws);\n base.onboarding.knowledgeWritten = await knowledgeWritten(ws);\n base.onboarding.ready = base.onboarding.instructionsInstalled && base.onboarding.knowledgeWritten && base.knowledge.state !== 'Empty';\n return base;\n}\n"]}
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/services/status.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,EAAqB,MAAM,sBAAsB,CAAC;AAClH,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,OAAO,EAAW,MAAM,sBAAsB,CAAC;AACxF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAA0B,MAAM,0BAA0B,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAa,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,UAAU,EAAuB,MAAM,aAAa,CAAC;AA6BtE,MAAM,KAAK,GAAG,CAAC,CAAO,EAAa,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAExJ,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,EAAM;IAChD,MAAM,SAAS,GAAmB,EAAE,CAAC;IACrC,KAAK,MAAM,OAAO,IAAI,iBAAiB,EAAE,EAAE,CAAC;QAC1C,IAAI,OAAO,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;YAC5B,IAAI,WAAW,GAAG,KAAK,CAAC;YACxB,KAAK,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,mBAAmB,CAAC,EAAE,CAAC;gBACrD,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;oBAC9E,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;wBACnI,WAAW,GAAG,IAAI,CAAC;wBACnB,MAAM;oBACR,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,cAAc;gBAChB,CAAC;YACH,CAAC;YACD,IAAI,WAAW;gBAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3C,CAAC;aAAM,IAAI,OAAO,CAAC,EAAE,KAAK,OAAO,EAAE,CAAC;YAClC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;gBACxE,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;oBAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1F,CAAC;YAAC,MAAM,CAAC;gBACP,eAAe;YACjB,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;YACnC,IAAI,WAAW,GAAG,KAAK,CAAC;YACxB,KAAK,MAAM,GAAG,IAAI,CAAC,gCAAgC,EAAE,cAAc,CAAC,EAAE,CAAC;gBACrE,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;oBAC9E,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;wBAC/D,WAAW,GAAG,IAAI,CAAC;wBACnB,MAAM;oBACR,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,cAAc;gBAChB,CAAC;YACH,CAAC;YACD,IAAI,WAAW;gBAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3C,CAAC;aAAM,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YACpC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,yBAAyB,CAAC,EAAE,MAAM,CAAC,CAAC;gBACjG,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;oBAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1F,CAAC;YAAC,MAAM,CAAC;gBACP,eAAe;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,EAAM;IAChD,MAAM,SAAS,GAAG,MAAM,qBAAqB,CAAC,EAAE,CAAC,CAAC;IAClD,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EAAM;IAC3C,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC;IAClF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,yIAAyI;AACzI,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,CAAiB,EAAE,OAA2B,EAAE;IAC9E,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAwB;QACpC,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;QACxE,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM;KAC5B,CAAC;IACF,MAAM,IAAI,GAAiB;QACzB,WAAW,EAAE,KAAK;QAClB,IAAI;QACJ,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,iBAAiB;QAC5B,GAAG,EAAE,QAAQ;QACb,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE;QACrG,UAAU,EAAE,EAAE,qBAAqB,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;QACnF,YAAY,EAAE,EAAE;QAChB,WAAW,EAAE,EAAE;QACf,YAAY,EAAE,EAAE;QAChB,WAAW,EAAE,IAAI;QACjB,YAAY,EAAE,CAAC;KAChB,CAAC;IACF,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC;QAC7D,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,gBAAgB,EAAG,CAAW,CAAC,OAAO,EAAE,CAAC;IACtF,CAAC;IAED,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,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAChE,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAClI,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;QAC3B,IAAI,UAAU,GAAkB,IAAI,CAAC;QACrC,IAAI,MAAM,UAAU,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC;YACvC,UAAU,GAAG,CAAC,MAAM,aAAa,CAAC,EAAE,CAAC,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;QAC1H,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;IAC1M,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,SAAS,GAAG,iBAAiB,CAAC;QACnC,IAAI,CAAC,gBAAgB,GAAI,CAAW,CAAC,OAAO,CAAC;IAC/C,CAAC;IAED,IAAI,MAAM,UAAU,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,CAAC,MAAM,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;YACvG,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAe,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/O,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,SAAS,GAAG,iBAAiB,CAAC;YACnC,IAAI,CAAC,gBAAgB,KAAM,CAAW,CAAC,OAAO,CAAC;QACjD,CAAC;IACH,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,EAAE,CAAC,CAAC;IAC/C,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IACnC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,IAAI,CAAC,SAAS,GAAG,iBAAiB,CAAC;IAC3D,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3C,IAAI,QAAQ,CAAC,CAAC,CAAC;QAAE,IAAI,CAAC,WAAW,GAAG,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAE3G,IAAI,MAAM,UAAU,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,YAAY,CAAC,EAAE,CAAC,CAAC;YACjC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,MAAM,CAAC;YACnE,MAAM,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,MAAM,CAAC;YACrE,MAAM,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;YACpE,IAAI,CAAC,QAAQ,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QACzF,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACvB,CAAC;IACH,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;IACvB,CAAC;IAED,IAAI,CAAC,YAAY,GAAG,MAAM,UAAU,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACrF,IAAI,CAAC,UAAU,CAAC,qBAAqB,GAAG,MAAM,qBAAqB,CAAC,EAAE,CAAC,CAAC;IACxE,IAAI,CAAC,UAAU,CAAC,gBAAgB,GAAG,MAAM,gBAAgB,CAAC,EAAE,CAAC,CAAC;IAC9D,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,qBAAqB,IAAI,IAAI,CAAC,UAAU,CAAC,gBAAgB,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,KAAK,OAAO,CAAC;IACtI,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { SCHEMA_VERSION, validateAnalysisState, validateCommands, type CommandEntry } from '../config/schemas.js';\nimport { findWorkspaceRoot, loadProject, wsPaths, type Ws } from '../core/workspace.js';\nimport { readVersioned } from '../core/versioned.js';\nimport { getGitState } from '../git/git.js';\nimport { inspectAll, type IntegrationReport } from '../integrations/index.js';\nimport { evaluateStaleness, loadFacts } from '../knowledge/facts.js';\nimport { listSessions } from '../sessions/session.js';\nimport { listTasks, nextRequiredStep, type Task } from '../tasks/task.js';\nimport { pathExists } from '../utils/fs.js';\nimport { SECTION_START, SECTION_END } from '../agents/shared.js';\nimport { SKILL_PATH } from '../agents/claude/content.js';\nimport { listAgentAdapters } from '../agents/index.js';\nimport type { AgentAdapter } from '../agents/types.js';\nimport { loadFeatures } from './features.js';\nimport { isoNow, managerEnv, type ServiceOptions } from './common.js';\n\nexport interface TaskBrief {\n id: string;\n title: string;\n type: string;\n status: string;\n updatedAt: string;\n next: string;\n}\n\nexport interface StatusResult {\n initialized: boolean;\n root: string | null;\n project: { name: string; id: string } | null;\n workspace: 'Healthy' | 'Needs attention' | 'Not initialized' | 'Unreadable';\n workspaceProblem?: string;\n git: { available: boolean; isRepo: boolean; branch: string | null; workingTree: 'Clean' | 'Modified' | 'Unknown'; changes: number };\n knowledge: { state: 'Current' | 'Stale' | 'Empty' | 'Unknown'; facts: number; stale: number; analyzedAt: string | null; staleItems: { key: string; reason: string; recorded: boolean }[]; needsReview: number };\n onboarding: { instructionsInstalled: boolean; knowledgeWritten: boolean; ready: boolean };\n /** Shallow observation (files and PATH only; never VERIFIED). Run doctor or `integrations status` to verify. */\n integrations: IntegrationReport[];\n activeTasks: TaskBrief[];\n verification: { id: string; available: boolean; command: string | null; required: string; cwd?: string; mutates?: boolean }[];\n features?: { total: number; verified: number; inferred: number; unknown: number } | null;\n lastSession: { id: string; goal: string; next: string } | null;\n corruptTasks: number;\n}\n\nconst brief = (t: Task): TaskBrief => ({ id: t.id, title: t.title, type: t.type, status: t.status, updatedAt: t.updatedAt, next: nextRequiredStep(t) });\n\nexport async function detectInstalledAgents(ws: Ws): Promise<AgentAdapter[]> {\n const installed: AgentAdapter[] = [];\n for (const adapter of listAgentAdapters()) {\n if (adapter.id === 'claude') {\n let claudeFound = false;\n for (const rel of ['CLAUDE.md', '.claude/CLAUDE.md']) {\n try {\n const text = await fs.readFile(path.join(ws.root, ...rel.split('/')), 'utf8');\n if (text.includes(SECTION_START) && text.includes(SECTION_END) && (await pathExists(path.join(ws.root, ...SKILL_PATH.split('/'))))) {\n claudeFound = true;\n break;\n }\n } catch {\n /* try next */\n }\n }\n if (claudeFound) installed.push(adapter);\n } else if (adapter.id === 'codex') {\n try {\n const text = await fs.readFile(path.join(ws.root, 'AGENTS.md'), 'utf8');\n if (text.includes(SECTION_START) && text.includes(SECTION_END)) installed.push(adapter);\n } catch {\n /* not found */\n }\n } else if (adapter.id === 'cursor') {\n let cursorFound = false;\n for (const rel of ['.cursor/rules/devworkspace.mdc', '.cursorrules']) {\n try {\n const text = await fs.readFile(path.join(ws.root, ...rel.split('/')), 'utf8');\n if (text.includes(SECTION_START) && text.includes(SECTION_END)) {\n cursorFound = true;\n break;\n }\n } catch {\n /* try next */\n }\n }\n if (cursorFound) installed.push(adapter);\n } else if (adapter.id === 'copilot') {\n try {\n const text = await fs.readFile(path.join(ws.root, '.github', 'copilot-instructions.md'), 'utf8');\n if (text.includes(SECTION_START) && text.includes(SECTION_END)) installed.push(adapter);\n } catch {\n /* not found */\n }\n }\n }\n return installed;\n}\n\nexport async function instructionsInstalled(ws: Ws): Promise<boolean> {\n const installed = await detectInstalledAgents(ws);\n return installed.length > 0;\n}\n\nexport async function knowledgeWritten(ws: Ws): Promise<boolean> {\n try {\n return (await fs.stat(path.join(ws.contextDir, 'architecture.md'))).size >= 200;\n } catch {\n return false;\n }\n}\n\n/** Cheap overview: small workspace files, Git status and a fingerprint check of the few files facts cite. Never scans the repository. */\nexport async function getStatus(o: ServiceOptions, opts: { deep?: boolean } = {}): Promise<StatusResult> {\n const root = await findWorkspaceRoot(o.cwd);\n const git = await getGitState(root ?? o.cwd);\n const gitBrief: StatusResult['git'] = {\n available: git.available,\n isRepo: git.isRepo,\n branch: git.branch,\n workingTree: git.isRepo ? (git.dirty ? 'Modified' : 'Clean') : 'Unknown',\n changes: git.entries.length,\n };\n const base: StatusResult = {\n initialized: false,\n root,\n project: null,\n workspace: 'Not initialized',\n git: gitBrief,\n knowledge: { state: 'Unknown', facts: 0, stale: 0, analyzedAt: null, staleItems: [], needsReview: 0 },\n onboarding: { instructionsInstalled: false, knowledgeWritten: false, ready: false },\n integrations: [],\n activeTasks: [],\n verification: [],\n lastSession: null,\n corruptTasks: 0,\n };\n if (!root) return base;\n\n const ws = wsPaths(root);\n base.initialized = true;\n try {\n const project = await loadProject(ws);\n base.project = { name: project.name, id: project.projectId };\n base.workspace = 'Healthy';\n } catch (e) {\n return { ...base, workspace: 'Unreadable', workspaceProblem: (e as Error).message };\n }\n\n try {\n const facts = await loadFacts(ws);\n const view = await evaluateStaleness(ws.root, facts, isoNow(o));\n const items = [...view.recorded.map((x) => ({ ...x, recorded: true })), ...view.detected.map((x) => ({ ...x, recorded: false }))];\n const stale = items.length;\n let analyzedAt: string | null = null;\n if (await pathExists(ws.analysisState)) {\n analyzedAt = (await readVersioned(ws.analysisState, 'analysis', SCHEMA_VERSION, validateAnalysisState)).data.analyzedAt;\n }\n base.knowledge = { facts: facts.facts.length, stale, analyzedAt, staleItems: items, needsReview: view.needsReview.length, state: facts.facts.length === 0 ? 'Empty' : stale > 0 ? 'Stale' : 'Current' };\n } catch (e) {\n base.workspace = 'Needs attention';\n base.workspaceProblem = (e as Error).message;\n }\n\n if (await pathExists(ws.commands)) {\n try {\n const commands = (await readVersioned(ws.commands, 'commands', SCHEMA_VERSION, validateCommands)).data;\n base.verification = commands.checks.map((c: CommandEntry) => ({ id: c.id, available: c.available, command: c.command, required: c.required, ...(c.cwd ? { cwd: c.cwd } : {}), ...(c.mutates !== undefined ? { mutates: c.mutates } : {}) }));\n } catch (e) {\n base.workspace = 'Needs attention';\n base.workspaceProblem ??= (e as Error).message;\n }\n }\n\n const { tasks, corrupt } = await listTasks(ws);\n base.activeTasks = tasks.map(brief);\n base.corruptTasks = corrupt.length;\n if (corrupt.length > 0) base.workspace = 'Needs attention';\n const sessions = await listSessions(ws, 1);\n if (sessions[0]) base.lastSession = { id: sessions[0].id, goal: sessions[0].goal, next: sessions[0].next };\n\n if (await pathExists(ws.features)) {\n try {\n const f = await loadFeatures(ws);\n const v = f.features.filter((x) => x.status === 'verified').length;\n const inf = f.features.filter((x) => x.status === 'inferred').length;\n const unk = f.features.filter((x) => x.status === 'unknown').length;\n base.features = { total: f.features.length, verified: v, inferred: inf, unknown: unk };\n } catch {\n base.features = null;\n }\n } else {\n base.features = null;\n }\n\n base.integrations = await inspectAll(ws, managerEnv(o, root), { deep: !!opts.deep });\n base.onboarding.instructionsInstalled = await instructionsInstalled(ws);\n base.onboarding.knowledgeWritten = await knowledgeWritten(ws);\n base.onboarding.ready = base.onboarding.instructionsInstalled && base.onboarding.knowledgeWritten && base.knowledge.state !== 'Empty';\n return base;\n}\n"]}
@@ -25,7 +25,12 @@ export async function createTask(o, input) {
25
25
  skipChecks.add('e2e');
26
26
  if (classification.constraints.includes('no-tests'))
27
27
  skipChecks.add('unit').add('integration').add('e2e');
28
- verification = verification.map((v) => (skipChecks.has(v.check) ? { ...v, status: 'SKIPPED', reason: 'user-override' } : v));
28
+ if (classification.readOnly) {
29
+ verification = verification.map((v) => ({ ...v, status: 'SKIPPED', reason: 'user-override' }));
30
+ }
31
+ else {
32
+ verification = verification.map((v) => (skipChecks.has(v.check) ? { ...v, status: 'SKIPPED', reason: 'user-override' } : v));
33
+ }
29
34
  const title = (input.title ?? input.text).replace(/\s+/g, ' ').trim().slice(0, 100);
30
35
  const task = createTaskObject({ title, type, description: input.text, verification, constraints: classification.constraints }, isoNow(o));
31
36
  task.scope = await captureScope(ws.root, isoNow(o));