devworkspace 0.0.0-stage → 0.1.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 (190) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/LICENSE +21 -0
  3. package/README.md +128 -3
  4. package/dist/agents/claude/adapter.d.ts +15 -0
  5. package/dist/agents/claude/adapter.js +107 -0
  6. package/dist/agents/claude/adapter.js.map +1 -0
  7. package/dist/agents/claude/content.d.ts +7 -0
  8. package/dist/agents/claude/content.js +136 -0
  9. package/dist/agents/claude/content.js.map +1 -0
  10. package/dist/agents/types.d.ts +26 -0
  11. package/dist/agents/types.js +2 -0
  12. package/dist/agents/types.js.map +1 -0
  13. package/dist/cli/args.d.ts +197 -0
  14. package/dist/cli/args.js +94 -0
  15. package/dist/cli/args.js.map +1 -0
  16. package/dist/cli/help.d.ts +10 -0
  17. package/dist/cli/help.js +181 -0
  18. package/dist/cli/help.js.map +1 -0
  19. package/dist/cli/main.d.ts +2 -0
  20. package/dist/cli/main.js +19 -0
  21. package/dist/cli/main.js.map +1 -0
  22. package/dist/cli/render.d.ts +41 -0
  23. package/dist/cli/render.js +220 -0
  24. package/dist/cli/render.js.map +1 -0
  25. package/dist/cli/run.d.ts +10 -0
  26. package/dist/cli/run.js +339 -0
  27. package/dist/cli/run.js.map +1 -0
  28. package/dist/config/schemas.d.ts +76 -0
  29. package/dist/config/schemas.js +83 -0
  30. package/dist/config/schemas.js.map +1 -0
  31. package/dist/config/validate.d.ts +22 -0
  32. package/dist/config/validate.js +76 -0
  33. package/dist/config/validate.js.map +1 -0
  34. package/dist/core/migrations.d.ts +15 -0
  35. package/dist/core/migrations.js +34 -0
  36. package/dist/core/migrations.js.map +1 -0
  37. package/dist/core/version.d.ts +2 -0
  38. package/dist/core/version.js +12 -0
  39. package/dist/core/version.js.map +1 -0
  40. package/dist/core/versioned.d.ts +13 -0
  41. package/dist/core/versioned.js +16 -0
  42. package/dist/core/versioned.js.map +1 -0
  43. package/dist/core/workspace.d.ts +34 -0
  44. package/dist/core/workspace.js +92 -0
  45. package/dist/core/workspace.js.map +1 -0
  46. package/dist/decisions/decision.d.ts +31 -0
  47. package/dist/decisions/decision.js +123 -0
  48. package/dist/decisions/decision.js.map +1 -0
  49. package/dist/discovery/commands.d.ts +12 -0
  50. package/dist/discovery/commands.js +92 -0
  51. package/dist/discovery/commands.js.map +1 -0
  52. package/dist/discovery/detect.d.ts +72 -0
  53. package/dist/discovery/detect.js +421 -0
  54. package/dist/discovery/detect.js.map +1 -0
  55. package/dist/discovery/ignore.d.ts +6 -0
  56. package/dist/discovery/ignore.js +76 -0
  57. package/dist/discovery/ignore.js.map +1 -0
  58. package/dist/discovery/scan.d.ts +24 -0
  59. package/dist/discovery/scan.js +132 -0
  60. package/dist/discovery/scan.js.map +1 -0
  61. package/dist/errors/index.d.ts +25 -0
  62. package/dist/errors/index.js +39 -0
  63. package/dist/errors/index.js.map +1 -0
  64. package/dist/git/git.d.ts +27 -0
  65. package/dist/git/git.js +97 -0
  66. package/dist/git/git.js.map +1 -0
  67. package/dist/index.d.ts +26 -0
  68. package/dist/index.js +21 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/integrations/agent-skills.d.ts +10 -0
  71. package/dist/integrations/agent-skills.js +45 -0
  72. package/dist/integrations/agent-skills.js.map +1 -0
  73. package/dist/integrations/graphify.d.ts +7 -0
  74. package/dist/integrations/graphify.js +54 -0
  75. package/dist/integrations/graphify.js.map +1 -0
  76. package/dist/integrations/index.d.ts +6 -0
  77. package/dist/integrations/index.js +30 -0
  78. package/dist/integrations/index.js.map +1 -0
  79. package/dist/integrations/omniroute.d.ts +7 -0
  80. package/dist/integrations/omniroute.js +24 -0
  81. package/dist/integrations/omniroute.js.map +1 -0
  82. package/dist/integrations/ponytail.d.ts +10 -0
  83. package/dist/integrations/ponytail.js +58 -0
  84. package/dist/integrations/ponytail.js.map +1 -0
  85. package/dist/integrations/probe.d.ts +6 -0
  86. package/dist/integrations/probe.js +41 -0
  87. package/dist/integrations/probe.js.map +1 -0
  88. package/dist/integrations/types.d.ts +25 -0
  89. package/dist/integrations/types.js +2 -0
  90. package/dist/integrations/types.js.map +1 -0
  91. package/dist/knowledge/facts.d.ts +43 -0
  92. package/dist/knowledge/facts.js +195 -0
  93. package/dist/knowledge/facts.js.map +1 -0
  94. package/dist/portability/bundle.d.ts +22 -0
  95. package/dist/portability/bundle.js +102 -0
  96. package/dist/portability/bundle.js.map +1 -0
  97. package/dist/prompts/onboarding.d.ts +19 -0
  98. package/dist/prompts/onboarding.js +53 -0
  99. package/dist/prompts/onboarding.js.map +1 -0
  100. package/dist/prompts/refresh.d.ts +15 -0
  101. package/dist/prompts/refresh.js +33 -0
  102. package/dist/prompts/refresh.js.map +1 -0
  103. package/dist/prompts/requirements.d.ts +9 -0
  104. package/dist/prompts/requirements.js +34 -0
  105. package/dist/prompts/requirements.js.map +1 -0
  106. package/dist/security/files.d.ts +5 -0
  107. package/dist/security/files.js +44 -0
  108. package/dist/security/files.js.map +1 -0
  109. package/dist/security/redact.d.ts +13 -0
  110. package/dist/security/redact.js +43 -0
  111. package/dist/security/redact.js.map +1 -0
  112. package/dist/services/agent.d.ts +11 -0
  113. package/dist/services/agent.js +42 -0
  114. package/dist/services/agent.js.map +1 -0
  115. package/dist/services/analysis.d.ts +45 -0
  116. package/dist/services/analysis.js +151 -0
  117. package/dist/services/analysis.js.map +1 -0
  118. package/dist/services/common.d.ts +18 -0
  119. package/dist/services/common.js +18 -0
  120. package/dist/services/common.js.map +1 -0
  121. package/dist/services/doctor.d.ts +27 -0
  122. package/dist/services/doctor.js +223 -0
  123. package/dist/services/doctor.js.map +1 -0
  124. package/dist/services/init.d.ts +18 -0
  125. package/dist/services/init.js +135 -0
  126. package/dist/services/init.js.map +1 -0
  127. package/dist/services/knowledge.d.ts +40 -0
  128. package/dist/services/knowledge.js +72 -0
  129. package/dist/services/knowledge.js.map +1 -0
  130. package/dist/services/migrate.d.ts +16 -0
  131. package/dist/services/migrate.js +54 -0
  132. package/dist/services/migrate.js.map +1 -0
  133. package/dist/services/portability.d.ts +27 -0
  134. package/dist/services/portability.js +155 -0
  135. package/dist/services/portability.js.map +1 -0
  136. package/dist/services/records.d.ts +8 -0
  137. package/dist/services/records.js +26 -0
  138. package/dist/services/records.js.map +1 -0
  139. package/dist/services/refresh.d.ts +22 -0
  140. package/dist/services/refresh.js +64 -0
  141. package/dist/services/refresh.js.map +1 -0
  142. package/dist/services/reset.d.ts +23 -0
  143. package/dist/services/reset.js +96 -0
  144. package/dist/services/reset.js.map +1 -0
  145. package/dist/services/status.d.ts +57 -0
  146. package/dist/services/status.js +111 -0
  147. package/dist/services/status.js.map +1 -0
  148. package/dist/services/tasks.d.ts +44 -0
  149. package/dist/services/tasks.js +136 -0
  150. package/dist/services/tasks.js.map +1 -0
  151. package/dist/sessions/session.d.ts +19 -0
  152. package/dist/sessions/session.js +53 -0
  153. package/dist/sessions/session.js.map +1 -0
  154. package/dist/tasks/routing.d.ts +27 -0
  155. package/dist/tasks/routing.js +206 -0
  156. package/dist/tasks/routing.js.map +1 -0
  157. package/dist/tasks/task.d.ts +90 -0
  158. package/dist/tasks/task.js +275 -0
  159. package/dist/tasks/task.js.map +1 -0
  160. package/dist/utils/cleanup.d.ts +3 -0
  161. package/dist/utils/cleanup.js +18 -0
  162. package/dist/utils/cleanup.js.map +1 -0
  163. package/dist/utils/fs.d.ts +17 -0
  164. package/dist/utils/fs.js +164 -0
  165. package/dist/utils/fs.js.map +1 -0
  166. package/dist/utils/lock.d.ts +6 -0
  167. package/dist/utils/lock.js +77 -0
  168. package/dist/utils/lock.js.map +1 -0
  169. package/dist/utils/logger.d.ts +11 -0
  170. package/dist/utils/logger.js +18 -0
  171. package/dist/utils/logger.js.map +1 -0
  172. package/dist/utils/paths.d.ts +18 -0
  173. package/dist/utils/paths.js +95 -0
  174. package/dist/utils/paths.js.map +1 -0
  175. package/dist/utils/proc.d.ts +22 -0
  176. package/dist/utils/proc.js +74 -0
  177. package/dist/utils/proc.js.map +1 -0
  178. package/docs/architecture.md +53 -0
  179. package/docs/benchmarking.md +33 -0
  180. package/docs/claude.md +46 -0
  181. package/docs/contributing.md +64 -0
  182. package/docs/getting-started.md +79 -0
  183. package/docs/integrations.md +51 -0
  184. package/docs/knowledge.md +66 -0
  185. package/docs/portability.md +40 -0
  186. package/docs/routing.md +51 -0
  187. package/docs/security.md +44 -0
  188. package/docs/testing.md +58 -0
  189. package/docs/troubleshooting.md +27 -0
  190. package/package.json +68 -4
@@ -0,0 +1,220 @@
1
+ import { nextRequiredStep } from '../tasks/task.js';
2
+ export function makeStyle(opts) {
3
+ const wrap = (code) => (s) => (opts.color ? `\u001b[${code}m${s}\u001b[0m` : s);
4
+ return {
5
+ ok: wrap(32),
6
+ warn: wrap(33),
7
+ fail: wrap(31),
8
+ dim: wrap(2),
9
+ bold: wrap(1),
10
+ sym: opts.ascii ? { ok: '[ok]', warn: '[warn]', fail: '[fail]', info: '-', arrow: '->' } : { ok: '✓', warn: '⚠', fail: '✗', info: '·', arrow: '→' },
11
+ };
12
+ }
13
+ const STATE_LABEL = {
14
+ READY: 'Ready',
15
+ PARTIAL: 'Partial',
16
+ NOT_DETECTED: 'Not detected',
17
+ UNVERIFIED: 'Unverified',
18
+ ERROR: 'Error',
19
+ };
20
+ function integrationLine(s, i) {
21
+ const mark = i.state === 'READY' ? s.ok(s.sym.ok) : i.optional ? s.sym.info : i.state === 'ERROR' ? s.fail(s.sym.fail) : s.warn(s.sym.warn);
22
+ return `${mark} ${i.name}: ${STATE_LABEL[i.state]}${i.optional ? ' (optional)' : ''}`;
23
+ }
24
+ export function renderStatus(s, r) {
25
+ if (!r.initialized) {
26
+ return [`${s.warn(s.sym.warn)} Workspace: Not initialized`, ' Run: devworkspace init'].join('\n');
27
+ }
28
+ const L = [];
29
+ L.push(`Project: ${r.project?.name ?? '(unreadable)'}`);
30
+ L.push(`Workspace: ${r.workspace}${r.workspaceProblem ? ` - ${r.workspaceProblem.split('\n')[0]}` : ''}`);
31
+ if (r.git.isRepo) {
32
+ L.push(`Git branch: ${r.git.branch ?? '(detached)'}`);
33
+ L.push(`Working tree: ${r.git.workingTree}${r.git.changes ? ` (${r.git.changes} change${r.git.changes === 1 ? '' : 's'})` : ''}`);
34
+ }
35
+ else
36
+ L.push(`Git: ${r.git.available ? 'not a repository' : 'not installed'}`);
37
+ L.push('');
38
+ L.push(`Knowledge: ${r.knowledge.state} (${r.knowledge.facts} fact${r.knowledge.facts === 1 ? '' : 's'}, ${r.knowledge.stale} stale)`);
39
+ L.push(`Onboarding: ${r.onboarding.ready ? 'Complete' : `Pending (instructions ${r.onboarding.instructionsInstalled ? 'installed' : 'missing'}, knowledge ${r.onboarding.knowledgeWritten ? 'written' : 'missing'})`}`);
40
+ for (const i of r.integrations)
41
+ L.push(integrationLine(s, i));
42
+ L.push('');
43
+ L.push(`Active tasks: ${r.activeTasks.length}`);
44
+ for (const t of r.activeTasks.slice(0, 8)) {
45
+ L.push(` ${t.id} [${t.status}] ${t.title}`);
46
+ L.push(` next: ${t.next}`);
47
+ }
48
+ if (r.lastSession)
49
+ L.push(`Last session: ${r.lastSession.goal} ${s.sym.arrow} next: ${r.lastSession.next || '(none recorded)'}`);
50
+ if (r.verification.length > 0) {
51
+ L.push('');
52
+ L.push('Verification:');
53
+ for (const v of r.verification) {
54
+ L.push(` ${v.id.padEnd(12)} ${v.available ? 'configured' : 'not available'}${v.command ? ` ${v.command}` : ''}${v.available && v.required !== 'no' ? ` [${v.required}]` : ''}`);
55
+ }
56
+ }
57
+ return L.join('\n');
58
+ }
59
+ export function renderDoctor(s, r) {
60
+ const L = [];
61
+ for (const c of r.checks) {
62
+ const mark = c.status === 'pass' ? s.ok(s.sym.ok) : c.status === 'warn' ? s.warn(s.sym.warn) : c.status === 'fail' ? s.fail(s.sym.fail) : s.sym.info;
63
+ const tag = c.status === 'pass' ? 'PASS' : c.status === 'warn' ? 'WARN' : c.status === 'fail' ? 'FAIL' : 'INFO';
64
+ L.push(`${mark} ${tag} ${c.message}`);
65
+ if (c.remediation && (c.status === 'warn' || c.status === 'fail'))
66
+ L.push(` ${s.sym.arrow} ${c.remediation}`);
67
+ }
68
+ L.push('');
69
+ for (const f of r.fixed)
70
+ L.push(`${s.ok(s.sym.ok)} Fixed: ${f}`);
71
+ L.push(`${r.counts.pass} passed, ${r.counts.warn} warning${r.counts.warn === 1 ? '' : 's'}, ${r.counts.fail} failure${r.counts.fail === 1 ? '' : 's'}`);
72
+ const verdict = !r.healthy ? 'UNHEALTHY' : r.ready ? 'READY' : r.counts.warn > 0 ? 'HEALTHY (with warnings)' : 'HEALTHY';
73
+ L.push(`Result: ${verdict}`);
74
+ return L.join('\n');
75
+ }
76
+ export function renderInit(s, r) {
77
+ const L = [];
78
+ const verb = r.dryRun ? 'Would create' : 'Created';
79
+ L.push(r.dryRun ? `${s.sym.info} Dry run: no files were written.` : r.alreadyInitialized ? `${s.ok(s.sym.ok)} DevWorkspace already initialized; nothing was overwritten.` : `${s.ok(s.sym.ok)} DevWorkspace initialized.`);
80
+ L.push(` Root: ${r.root}`);
81
+ if (r.created.length > 0)
82
+ L.push(` ${verb}:`, ...r.created.map((c) => ` + ${c}`));
83
+ for (const n of r.notes)
84
+ L.push(` ${s.sym.info} ${n}`);
85
+ L.push('', 'Integrations:', ...r.integrations.map((i) => ` ${integrationLine(s, i)}`));
86
+ L.push('', 'Next steps:', ...r.nextSteps.map((n, i) => ` ${i + 1}. ${n}`));
87
+ return L.join('\n');
88
+ }
89
+ export function renderAnalyze(s, r) {
90
+ const d = r.discovery;
91
+ const L = [];
92
+ L.push(r.dryRun ? `${s.sym.info} Dry run: no files were written.` : `${s.ok(s.sym.ok)} Analysis complete (deterministic discovery; no AI involved).`);
93
+ L.push(` Files scanned: ${d.scan.fileCount}${d.scan.truncated ? ' (truncated by limits)' : ''}`);
94
+ L.push(` Ecosystems: ${d.ecosystems.join(', ') || 'none detected'}${d.packageManager ? `; package manager: ${d.packageManager}` : ''}`);
95
+ if (d.frameworks.length)
96
+ L.push(` Frameworks/tools: ${d.frameworks.map((f) => f.name).join(', ')}`);
97
+ if (d.monorepo.tool)
98
+ L.push(` Monorepo: ${d.monorepo.tool} (${d.monorepo.packages.length} packages)`);
99
+ const avail = d.commands.filter((c) => c.available).map((c) => c.id);
100
+ L.push(` Verification commands found: ${avail.join(', ') || 'none'}`);
101
+ if (d.sensitiveFilesPresent.length)
102
+ L.push(` ${s.warn(s.sym.warn)} Credential-like files present (names only, never read): ${d.sensitiveFilesPresent.join(', ')}`);
103
+ for (const w of d.warnings.filter((w) => !w.startsWith('Credential-like')))
104
+ L.push(` ${s.warn(s.sym.warn)} ${w}`);
105
+ if (!r.dryRun) {
106
+ L.push('', 'Wrote:', ` ${r.files.discovery}`, ` ${r.files.commands}`, ` ${r.files.onboardingPrompt}`);
107
+ if (r.facts.written.length)
108
+ L.push(` ${r.facts.written.length} detected fact(s) recorded`);
109
+ }
110
+ L.push('', 'Next steps:', ...r.nextSteps.map((n, i) => ` ${i + 1}. ${n}`));
111
+ return L.join('\n');
112
+ }
113
+ export function renderRefresh(s, r) {
114
+ const L = [];
115
+ L.push(r.dryRun ? `${s.sym.info} Dry run: nothing was written.` : `${s.ok(s.sym.ok)} Refresh complete.`);
116
+ if (r.headChanged)
117
+ L.push(` Git HEAD changed since the last analysis.`);
118
+ L.push(` Deterministic facts updated: ${r.autoRefreshed.length}${r.retired.length ? `, retired: ${r.retired.length}` : ''}`);
119
+ if (r.stale.length === 0 && r.needsReview.length === 0)
120
+ L.push(` ${s.ok(s.sym.ok)} No stored knowledge is stale.`);
121
+ for (const x of r.stale)
122
+ L.push(` ${s.warn(s.sym.warn)} STALE ${x.key}: ${x.reason}`);
123
+ for (const x of r.needsReview)
124
+ L.push(` ${s.warn(s.sym.warn)} Review user decision ${x.key}: ${x.reason}`);
125
+ if (r.prompt)
126
+ L.push('', `Paste ${r.prompt} into Claude Code to re-validate the stale items.`);
127
+ return L.join('\n');
128
+ }
129
+ export function renderContext(s, r) {
130
+ const L = [`Project: ${r.project.name}`, ''];
131
+ L.push(`Facts${r.topic ? ` matching "${r.topic}"` : ''}: ${r.facts.length}${r.topic ? ` of ${r.totalFacts}` : ''}`);
132
+ for (const f of r.facts) {
133
+ L.push(` ${f.key} [${f.status}/${f.confidence}]`, ` ${f.value}`, ` source: ${f.source}${f.staleReason ? ` (stale: ${f.staleReason})` : ''}`);
134
+ }
135
+ if (r.testingContract.length) {
136
+ L.push('', 'Testing contract:');
137
+ for (const c of r.testingContract)
138
+ L.push(` ${c.id.padEnd(12)} ${c.available ? 'yes' : 'no '} ${(c.command ?? '-').padEnd(28)} required: ${c.required}`);
139
+ }
140
+ if (r.decisions.length)
141
+ L.push('', 'Decisions:', ...r.decisions.map((d) => ` ${String(d.number).padStart(4, '0')} [${d.status}] ${d.title} (decisions/${d.file})`));
142
+ if (r.activeTasks.length)
143
+ L.push('', 'Active tasks:', ...r.activeTasks.map((t) => ` ${t.id} [${t.status}] ${t.title}`));
144
+ if (r.documents.length)
145
+ L.push('', 'Context documents (read as needed; --full prints them):', ...r.documents.map((d) => ` context/${d.name} (${d.bytes} bytes)`));
146
+ if (r.content)
147
+ for (const [name, text] of Object.entries(r.content))
148
+ L.push('', `--- context/${name} ---`, text);
149
+ return L.join('\n');
150
+ }
151
+ export function renderTask(s, t, gate) {
152
+ const L = [`${t.id} [${t.status}] ${t.type}`, ` ${t.title}`];
153
+ if (t.constraints.length)
154
+ L.push(` constraints: ${t.constraints.join(', ')}`);
155
+ if (t.acceptanceCriteria.length)
156
+ L.push(' acceptance criteria:', ...t.acceptanceCriteria.map((c) => ` - ${c}`));
157
+ if (t.plan.length)
158
+ L.push(' plan:', ...t.plan.map((c, i) => ` ${i + 1}. ${c}`));
159
+ if (t.affectedAreas.length)
160
+ L.push(` areas: ${t.affectedAreas.join(', ')}`);
161
+ if (t.verification.length) {
162
+ L.push(' verification:');
163
+ for (const v of t.verification)
164
+ L.push(` ${v.status === 'PASS' ? s.sym.ok : v.status === 'FAIL' ? s.sym.fail : s.sym.info} ${v.check.padEnd(12)} ${v.status}${v.reason ? ` (${v.reason})` : ''}${v.required ? '' : ' [optional]'}`);
165
+ }
166
+ if (t.tests.baseline || t.tests.after) {
167
+ const f = (c) => (c ? `${c.passed} passed, ${c.failed} failed` : 'not recorded');
168
+ L.push(` tests: baseline ${f(t.tests.baseline)}; after ${f(t.tests.after)}`);
169
+ }
170
+ if (t.blockers.length)
171
+ L.push(' blockers:', ...t.blockers.map((b) => ` - ${b}`));
172
+ L.push(` next: ${nextRequiredStep(t)}`);
173
+ if (gate) {
174
+ L.push(` completion gate: ${gate.ok ? 'PASS' : 'NOT MET'}`);
175
+ for (const f of gate.failures)
176
+ L.push(` ${s.sym.fail} ${f}`);
177
+ for (const w of gate.warnings)
178
+ L.push(` ${s.sym.warn} ${w}`);
179
+ }
180
+ return L.join('\n');
181
+ }
182
+ export function renderAgentInstall(s, r) {
183
+ const L = [r.dryRun ? `${s.sym.info} Dry run: no files were written.` : `${s.ok(s.sym.ok)} ${r.agent} instructions processed.`];
184
+ for (const c of r.changes) {
185
+ const mark = c.kind === 'conflict' ? s.warn(s.sym.warn) : c.kind === 'unchanged' ? s.sym.info : s.ok(s.sym.ok);
186
+ L.push(` ${mark} ${c.kind.toUpperCase().padEnd(9)} ${c.path} - ${c.note}`);
187
+ }
188
+ if (r.conflicts > 0)
189
+ L.push(` ${s.warn(s.sym.warn)} ${r.conflicts} conflict(s) left untouched; resolve by hand and re-run.`);
190
+ return L.join('\n');
191
+ }
192
+ export function renderExport(s, r) {
193
+ if (r.dryRun)
194
+ return [`${s.sym.info} Dry run: would export ${r.fileCount} file(s) (${r.bytes} bytes):`, ...r.files.map((f) => ` ${f}`)].join('\n');
195
+ return `${s.ok(s.sym.ok)} Exported ${r.fileCount} file(s) to ${r.file}`;
196
+ }
197
+ export function renderImport(s, r) {
198
+ const L = [r.dryRun ? `${s.sym.info} Dry run: nothing was changed.` : `${s.ok(s.sym.ok)} Import complete.`];
199
+ L.push(` created: ${r.created.length}, updated: ${r.updated.length}, merged: ${r.merged.length}, unchanged: ${r.unchanged.length}, conflicts: ${r.conflicts.length}`);
200
+ for (const m of r.merged)
201
+ L.push(` merged ${m}`);
202
+ for (const c of r.conflicts)
203
+ L.push(` ${s.warn(s.sym.warn)} ${c.path}: ${c.reason}`);
204
+ return L.join('\n');
205
+ }
206
+ export function renderReset(s, r) {
207
+ const L = [r.executed ? `${s.ok(s.sym.ok)} DevWorkspace reset. Run "devworkspace init" to start fresh.` : `${s.warn(s.sym.warn)} Reset plan (nothing deleted yet):`];
208
+ for (const a of r.actions) {
209
+ const verb = a.action === 'skip' ? 'SKIP ' : a.action === 'remove-managed-section' ? 'EDIT ' : 'DELETE';
210
+ L.push(` ${verb} ${a.path} - ${a.note}`);
211
+ }
212
+ L.push(' Your application source files are never touched.');
213
+ return L.join('\n');
214
+ }
215
+ export function renderMigrate(s, r) {
216
+ if (r.migrated.length === 0)
217
+ return `${s.ok(s.sym.ok)} Workspace is up to date (${r.checked} file(s) checked).`;
218
+ return [r.dryRun ? `${s.sym.info} Dry run: would migrate:` : `${s.ok(s.sym.ok)} Migrated (backups in .devworkspace/local/backups):`, ...r.migrated.map((m) => ` ${m.file}: v${m.from} ${s.sym.arrow} v${m.to}`)].join('\n');
219
+ }
220
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/cli/render.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DoctorResult } from '../services/doctor.js';\nimport type { StatusResult } from '../services/status.js';\nimport type { InitResult } from '../services/init.js';\nimport type { AnalyzeResult } from '../services/analysis.js';\nimport type { RefreshResult } from '../services/refresh.js';\nimport type { ContextResult } from '../services/knowledge.js';\nimport type { Task, GateResult } from '../tasks/task.js';\nimport { nextRequiredStep } from '../tasks/task.js';\nimport type { AgentInstallResult } from '../services/agent.js';\nimport type { ImportResult, ExportResult } from '../services/portability.js';\nimport type { MigrateResult } from '../services/migrate.js';\nimport type { ResetResult } from '../services/reset.js';\nimport type { IntegrationStatus } from '../integrations/types.js';\n\nexport interface Style {\n ok(s: string): string;\n warn(s: string): string;\n fail(s: string): string;\n dim(s: string): string;\n bold(s: string): string;\n sym: { ok: string; warn: string; fail: string; info: string; arrow: string };\n}\n\nexport function makeStyle(opts: { color: boolean; ascii: boolean }): Style {\n const wrap = (code: number) => (s: string): string => (opts.color ? `\\u001b[${code}m${s}\\u001b[0m` : s);\n return {\n ok: wrap(32),\n warn: wrap(33),\n fail: wrap(31),\n dim: wrap(2),\n bold: wrap(1),\n sym: opts.ascii ? { ok: '[ok]', warn: '[warn]', fail: '[fail]', info: '-', arrow: '->' } : { ok: '✓', warn: '⚠', fail: '✗', info: '·', arrow: '→' },\n };\n}\n\nconst STATE_LABEL: Record<IntegrationStatus['state'], string> = {\n READY: 'Ready',\n PARTIAL: 'Partial',\n NOT_DETECTED: 'Not detected',\n UNVERIFIED: 'Unverified',\n ERROR: 'Error',\n};\n\nfunction integrationLine(s: Style, i: IntegrationStatus): string {\n const mark = i.state === 'READY' ? s.ok(s.sym.ok) : i.optional ? s.sym.info : i.state === 'ERROR' ? s.fail(s.sym.fail) : s.warn(s.sym.warn);\n return `${mark} ${i.name}: ${STATE_LABEL[i.state]}${i.optional ? ' (optional)' : ''}`;\n}\n\nexport function renderStatus(s: Style, r: StatusResult): string {\n if (!r.initialized) {\n return [`${s.warn(s.sym.warn)} Workspace: Not initialized`, ' Run: devworkspace init'].join('\\n');\n }\n const L: string[] = [];\n L.push(`Project: ${r.project?.name ?? '(unreadable)'}`);\n L.push(`Workspace: ${r.workspace}${r.workspaceProblem ? ` - ${r.workspaceProblem.split('\\n')[0]}` : ''}`);\n if (r.git.isRepo) {\n L.push(`Git branch: ${r.git.branch ?? '(detached)'}`);\n L.push(`Working tree: ${r.git.workingTree}${r.git.changes ? ` (${r.git.changes} change${r.git.changes === 1 ? '' : 's'})` : ''}`);\n } else L.push(`Git: ${r.git.available ? 'not a repository' : 'not installed'}`);\n L.push('');\n L.push(`Knowledge: ${r.knowledge.state} (${r.knowledge.facts} fact${r.knowledge.facts === 1 ? '' : 's'}, ${r.knowledge.stale} stale)`);\n L.push(`Onboarding: ${r.onboarding.ready ? 'Complete' : `Pending (instructions ${r.onboarding.instructionsInstalled ? 'installed' : 'missing'}, knowledge ${r.onboarding.knowledgeWritten ? 'written' : 'missing'})`}`);\n for (const i of r.integrations) L.push(integrationLine(s, i));\n L.push('');\n L.push(`Active tasks: ${r.activeTasks.length}`);\n for (const t of r.activeTasks.slice(0, 8)) {\n L.push(` ${t.id} [${t.status}] ${t.title}`);\n L.push(` next: ${t.next}`);\n }\n if (r.lastSession) L.push(`Last session: ${r.lastSession.goal} ${s.sym.arrow} next: ${r.lastSession.next || '(none recorded)'}`);\n if (r.verification.length > 0) {\n L.push('');\n L.push('Verification:');\n for (const v of r.verification) {\n L.push(` ${v.id.padEnd(12)} ${v.available ? 'configured' : 'not available'}${v.command ? ` ${v.command}` : ''}${v.available && v.required !== 'no' ? ` [${v.required}]` : ''}`);\n }\n }\n return L.join('\\n');\n}\n\nexport function renderDoctor(s: Style, r: DoctorResult): string {\n const L: string[] = [];\n for (const c of r.checks) {\n const mark = c.status === 'pass' ? s.ok(s.sym.ok) : c.status === 'warn' ? s.warn(s.sym.warn) : c.status === 'fail' ? s.fail(s.sym.fail) : s.sym.info;\n const tag = c.status === 'pass' ? 'PASS' : c.status === 'warn' ? 'WARN' : c.status === 'fail' ? 'FAIL' : 'INFO';\n L.push(`${mark} ${tag} ${c.message}`);\n if (c.remediation && (c.status === 'warn' || c.status === 'fail')) L.push(` ${s.sym.arrow} ${c.remediation}`);\n }\n L.push('');\n for (const f of r.fixed) L.push(`${s.ok(s.sym.ok)} Fixed: ${f}`);\n L.push(`${r.counts.pass} passed, ${r.counts.warn} warning${r.counts.warn === 1 ? '' : 's'}, ${r.counts.fail} failure${r.counts.fail === 1 ? '' : 's'}`);\n const verdict = !r.healthy ? 'UNHEALTHY' : r.ready ? 'READY' : r.counts.warn > 0 ? 'HEALTHY (with warnings)' : 'HEALTHY';\n L.push(`Result: ${verdict}`);\n return L.join('\\n');\n}\n\nexport function renderInit(s: Style, r: InitResult): string {\n const L: string[] = [];\n const verb = r.dryRun ? 'Would create' : 'Created';\n L.push(r.dryRun ? `${s.sym.info} Dry run: no files were written.` : r.alreadyInitialized ? `${s.ok(s.sym.ok)} DevWorkspace already initialized; nothing was overwritten.` : `${s.ok(s.sym.ok)} DevWorkspace initialized.`);\n L.push(` Root: ${r.root}`);\n if (r.created.length > 0) L.push(` ${verb}:`, ...r.created.map((c) => ` + ${c}`));\n for (const n of r.notes) L.push(` ${s.sym.info} ${n}`);\n L.push('', 'Integrations:', ...r.integrations.map((i) => ` ${integrationLine(s, i)}`));\n L.push('', 'Next steps:', ...r.nextSteps.map((n, i) => ` ${i + 1}. ${n}`));\n return L.join('\\n');\n}\n\nexport function renderAnalyze(s: Style, r: AnalyzeResult): string {\n const d = r.discovery;\n const L: string[] = [];\n L.push(r.dryRun ? `${s.sym.info} Dry run: no files were written.` : `${s.ok(s.sym.ok)} Analysis complete (deterministic discovery; no AI involved).`);\n L.push(` Files scanned: ${d.scan.fileCount}${d.scan.truncated ? ' (truncated by limits)' : ''}`);\n L.push(` Ecosystems: ${d.ecosystems.join(', ') || 'none detected'}${d.packageManager ? `; package manager: ${d.packageManager}` : ''}`);\n if (d.frameworks.length) L.push(` Frameworks/tools: ${d.frameworks.map((f) => f.name).join(', ')}`);\n if (d.monorepo.tool) L.push(` Monorepo: ${d.monorepo.tool} (${d.monorepo.packages.length} packages)`);\n const avail = d.commands.filter((c) => c.available).map((c) => c.id);\n L.push(` Verification commands found: ${avail.join(', ') || 'none'}`);\n if (d.sensitiveFilesPresent.length) L.push(` ${s.warn(s.sym.warn)} Credential-like files present (names only, never read): ${d.sensitiveFilesPresent.join(', ')}`);\n for (const w of d.warnings.filter((w) => !w.startsWith('Credential-like'))) L.push(` ${s.warn(s.sym.warn)} ${w}`);\n if (!r.dryRun) {\n L.push('', 'Wrote:', ` ${r.files.discovery}`, ` ${r.files.commands}`, ` ${r.files.onboardingPrompt}`);\n if (r.facts.written.length) L.push(` ${r.facts.written.length} detected fact(s) recorded`);\n }\n L.push('', 'Next steps:', ...r.nextSteps.map((n, i) => ` ${i + 1}. ${n}`));\n return L.join('\\n');\n}\n\nexport function renderRefresh(s: Style, r: RefreshResult): string {\n const L: string[] = [];\n L.push(r.dryRun ? `${s.sym.info} Dry run: nothing was written.` : `${s.ok(s.sym.ok)} Refresh complete.`);\n if (r.headChanged) L.push(` Git HEAD changed since the last analysis.`);\n L.push(` Deterministic facts updated: ${r.autoRefreshed.length}${r.retired.length ? `, retired: ${r.retired.length}` : ''}`);\n if (r.stale.length === 0 && r.needsReview.length === 0) L.push(` ${s.ok(s.sym.ok)} No stored knowledge is stale.`);\n for (const x of r.stale) L.push(` ${s.warn(s.sym.warn)} STALE ${x.key}: ${x.reason}`);\n for (const x of r.needsReview) L.push(` ${s.warn(s.sym.warn)} Review user decision ${x.key}: ${x.reason}`);\n if (r.prompt) L.push('', `Paste ${r.prompt} into Claude Code to re-validate the stale items.`);\n return L.join('\\n');\n}\n\nexport function renderContext(s: Style, r: ContextResult): string {\n const L: string[] = [`Project: ${r.project.name}`, ''];\n L.push(`Facts${r.topic ? ` matching \"${r.topic}\"` : ''}: ${r.facts.length}${r.topic ? ` of ${r.totalFacts}` : ''}`);\n for (const f of r.facts) {\n L.push(` ${f.key} [${f.status}/${f.confidence}]`, ` ${f.value}`, ` source: ${f.source}${f.staleReason ? ` (stale: ${f.staleReason})` : ''}`);\n }\n if (r.testingContract.length) {\n L.push('', 'Testing contract:');\n for (const c of r.testingContract) L.push(` ${c.id.padEnd(12)} ${c.available ? 'yes' : 'no '} ${(c.command ?? '-').padEnd(28)} required: ${c.required}`);\n }\n if (r.decisions.length) L.push('', 'Decisions:', ...r.decisions.map((d) => ` ${String(d.number).padStart(4, '0')} [${d.status}] ${d.title} (decisions/${d.file})`));\n if (r.activeTasks.length) L.push('', 'Active tasks:', ...r.activeTasks.map((t) => ` ${t.id} [${t.status}] ${t.title}`));\n if (r.documents.length) L.push('', 'Context documents (read as needed; --full prints them):', ...r.documents.map((d) => ` context/${d.name} (${d.bytes} bytes)`));\n if (r.content) for (const [name, text] of Object.entries(r.content)) L.push('', `--- context/${name} ---`, text);\n return L.join('\\n');\n}\n\nexport function renderTask(s: Style, t: Task, gate?: GateResult): string {\n const L: string[] = [`${t.id} [${t.status}] ${t.type}`, ` ${t.title}`];\n if (t.constraints.length) L.push(` constraints: ${t.constraints.join(', ')}`);\n if (t.acceptanceCriteria.length) L.push(' acceptance criteria:', ...t.acceptanceCriteria.map((c) => ` - ${c}`));\n if (t.plan.length) L.push(' plan:', ...t.plan.map((c, i) => ` ${i + 1}. ${c}`));\n if (t.affectedAreas.length) L.push(` areas: ${t.affectedAreas.join(', ')}`);\n if (t.verification.length) {\n L.push(' verification:');\n for (const v of t.verification) L.push(` ${v.status === 'PASS' ? s.sym.ok : v.status === 'FAIL' ? s.sym.fail : s.sym.info} ${v.check.padEnd(12)} ${v.status}${v.reason ? ` (${v.reason})` : ''}${v.required ? '' : ' [optional]'}`);\n }\n if (t.tests.baseline || t.tests.after) {\n const f = (c?: { passed: number; failed: number }): string => (c ? `${c.passed} passed, ${c.failed} failed` : 'not recorded');\n L.push(` tests: baseline ${f(t.tests.baseline)}; after ${f(t.tests.after)}`);\n }\n if (t.blockers.length) L.push(' blockers:', ...t.blockers.map((b) => ` - ${b}`));\n L.push(` next: ${nextRequiredStep(t)}`);\n if (gate) {\n L.push(` completion gate: ${gate.ok ? 'PASS' : 'NOT MET'}`);\n for (const f of gate.failures) L.push(` ${s.sym.fail} ${f}`);\n for (const w of gate.warnings) L.push(` ${s.sym.warn} ${w}`);\n }\n return L.join('\\n');\n}\n\nexport function renderAgentInstall(s: Style, r: AgentInstallResult): string {\n const L: string[] = [r.dryRun ? `${s.sym.info} Dry run: no files were written.` : `${s.ok(s.sym.ok)} ${r.agent} instructions processed.`];\n for (const c of r.changes) {\n const mark = c.kind === 'conflict' ? s.warn(s.sym.warn) : c.kind === 'unchanged' ? s.sym.info : s.ok(s.sym.ok);\n L.push(` ${mark} ${c.kind.toUpperCase().padEnd(9)} ${c.path} - ${c.note}`);\n }\n if (r.conflicts > 0) L.push(` ${s.warn(s.sym.warn)} ${r.conflicts} conflict(s) left untouched; resolve by hand and re-run.`);\n return L.join('\\n');\n}\n\nexport function renderExport(s: Style, r: ExportResult): string {\n if (r.dryRun) return [`${s.sym.info} Dry run: would export ${r.fileCount} file(s) (${r.bytes} bytes):`, ...r.files.map((f) => ` ${f}`)].join('\\n');\n return `${s.ok(s.sym.ok)} Exported ${r.fileCount} file(s) to ${r.file}`;\n}\n\nexport function renderImport(s: Style, r: ImportResult): string {\n const L: string[] = [r.dryRun ? `${s.sym.info} Dry run: nothing was changed.` : `${s.ok(s.sym.ok)} Import complete.`];\n L.push(` created: ${r.created.length}, updated: ${r.updated.length}, merged: ${r.merged.length}, unchanged: ${r.unchanged.length}, conflicts: ${r.conflicts.length}`);\n for (const m of r.merged) L.push(` merged ${m}`);\n for (const c of r.conflicts) L.push(` ${s.warn(s.sym.warn)} ${c.path}: ${c.reason}`);\n return L.join('\\n');\n}\n\nexport function renderReset(s: Style, r: ResetResult): string {\n const L: string[] = [r.executed ? `${s.ok(s.sym.ok)} DevWorkspace reset. Run \"devworkspace init\" to start fresh.` : `${s.warn(s.sym.warn)} Reset plan (nothing deleted yet):`];\n for (const a of r.actions) {\n const verb = a.action === 'skip' ? 'SKIP ' : a.action === 'remove-managed-section' ? 'EDIT ' : 'DELETE';\n L.push(` ${verb} ${a.path} - ${a.note}`);\n }\n L.push(' Your application source files are never touched.');\n return L.join('\\n');\n}\n\nexport function renderMigrate(s: Style, r: MigrateResult): string {\n if (r.migrated.length === 0) return `${s.ok(s.sym.ok)} Workspace is up to date (${r.checked} file(s) checked).`;\n return [r.dryRun ? `${s.sym.info} Dry run: would migrate:` : `${s.ok(s.sym.ok)} Migrated (backups in .devworkspace/local/backups):`, ...r.migrated.map((m) => ` ${m.file}: v${m.from} ${s.sym.arrow} v${m.to}`)].join('\\n');\n}\n"]}
@@ -0,0 +1,10 @@
1
+ export interface CliIO {
2
+ stdout: (s: string) => void;
3
+ stderr: (s: string) => void;
4
+ cwd: string;
5
+ env: NodeJS.ProcessEnv;
6
+ isTTY: boolean;
7
+ }
8
+ export declare function defaultIO(): CliIO;
9
+ /** Run the CLI and return the process exit code. Never calls process.exit, so it is directly testable. */
10
+ export declare function run(argv: string[], io?: CliIO): Promise<number>;
@@ -0,0 +1,339 @@
1
+ import path from 'node:path';
2
+ import { DevWorkspaceError, EXIT, formatError, isDevWorkspaceError } from '../errors/index.js';
3
+ import { packageVersion } from '../core/version.js';
4
+ import { createLogger } from '../utils/logger.js';
5
+ import { bool, int, list, parseCli, str } from './args.js';
6
+ import { COMMANDS, commandHelp, topHelp } from './help.js';
7
+ import { makeStyle, renderAgentInstall, renderAnalyze, renderContext, renderDoctor, renderExport, renderImport, renderInit, renderMigrate, renderRefresh, renderReset, renderStatus, renderTask, } from './render.js';
8
+ import { requireWorkspace } from '../core/workspace.js';
9
+ import { analyzeWorkspace } from '../services/analysis.js';
10
+ import { installAgent } from '../services/agent.js';
11
+ import { mutate } from '../services/common.js';
12
+ import { runDoctor } from '../services/doctor.js';
13
+ import { initWorkspace } from '../services/init.js';
14
+ import { addFact, getContext, removeFactByKey, verifyFactByKey } from '../services/knowledge.js';
15
+ import { migrateWorkspace } from '../services/migrate.js';
16
+ import { exportWorkspace, importWorkspace } from '../services/portability.js';
17
+ import { getDecision, getDecisions, getSessions, recordDecision, recordSession } from '../services/records.js';
18
+ import { refreshWorkspace } from '../services/refresh.js';
19
+ import { resetWorkspace } from '../services/reset.js';
20
+ import { getStatus } from '../services/status.js';
21
+ import { attestTask, createTask, listTasksService, recordTests, recordVerification, setTaskStatus, showTask, updateTask, } from '../services/tasks.js';
22
+ import { CONFIDENCE, FACT_STATUS, SOURCE_TYPES } from '../config/schemas.js';
23
+ import { loadFacts } from '../knowledge/facts.js';
24
+ export function defaultIO() {
25
+ return {
26
+ stdout: (s) => process.stdout.write(s),
27
+ stderr: (s) => process.stderr.write(s),
28
+ cwd: process.cwd(),
29
+ env: process.env,
30
+ isTTY: !!process.stdout.isTTY,
31
+ };
32
+ }
33
+ function need(v, flag) {
34
+ if (!v)
35
+ throw new DevWorkspaceError('USAGE', `Missing required option --${flag}.`, { hint: 'Run "devworkspace <command> --help".' });
36
+ return v;
37
+ }
38
+ function oneOf(v, allowed, flag, fallback) {
39
+ const x = v ?? fallback;
40
+ if (x === undefined || !allowed.includes(x)) {
41
+ throw new DevWorkspaceError('USAGE', `--${flag} must be one of: ${allowed.join(', ')}.`);
42
+ }
43
+ return x;
44
+ }
45
+ const handlers = {
46
+ async init(c) {
47
+ const r = await initWorkspace({ ...c.svc, root: str(c.args.values, 'root') });
48
+ c.data(r, renderInit(c.style, r));
49
+ },
50
+ async analyze(c) {
51
+ const ws = await requireWorkspace(c.svc.cwd);
52
+ const r = c.svc.dryRun ? await analyzeWorkspace(ws, c.svc) : await mutate(c.svc, (w) => analyzeWorkspace(w, c.svc));
53
+ c.data(r, renderAnalyze(c.style, r));
54
+ },
55
+ async status(c) {
56
+ const r = await getStatus(c.svc);
57
+ c.data(r, renderStatus(c.style, r));
58
+ if (!r.initialized || r.workspace === 'Unreadable')
59
+ c.exit = EXIT.FAILURE;
60
+ else if (bool(c.args.values, 'strict') && (r.workspace !== 'Healthy' || r.knowledge.stale > 0 || !r.onboarding.ready))
61
+ c.exit = EXIT.WARNINGS;
62
+ },
63
+ async doctor(c) {
64
+ const r = await runDoctor({ ...c.svc, fix: bool(c.args.values, 'fix') });
65
+ c.data(r, renderDoctor(c.style, r));
66
+ if (!r.healthy)
67
+ c.exit = EXIT.FAILURE;
68
+ else if (bool(c.args.values, 'strict') && r.counts.warn > 0)
69
+ c.exit = EXIT.WARNINGS;
70
+ },
71
+ async refresh(c) {
72
+ const r = await refreshWorkspace(c.svc);
73
+ c.data(r, renderRefresh(c.style, r));
74
+ },
75
+ async context(c) {
76
+ const r = await getContext(c.svc, { topic: str(c.args.values, 'topic'), full: bool(c.args.values, 'full') });
77
+ c.data(r, renderContext(c.style, r));
78
+ },
79
+ async fact(c) {
80
+ const sub = c.rest[0];
81
+ const v = c.args.values;
82
+ if (sub === 'add') {
83
+ const sourceType = oneOf(str(v, 'source-type'), SOURCE_TYPES, 'source-type', 'ai');
84
+ const input = {
85
+ key: need(str(v, 'key'), 'key'),
86
+ value: need(str(v, 'value'), 'value'),
87
+ source: need(str(v, 'source'), 'source'),
88
+ sourceType,
89
+ sources: list(v, 'file'),
90
+ confidence: oneOf(str(v, 'confidence')?.toUpperCase(), CONFIDENCE, 'confidence', 'MEDIUM'),
91
+ status: str(v, 'status') ? oneOf(str(v, 'status').toUpperCase(), FACT_STATUS, 'status') : undefined,
92
+ };
93
+ const r = await addFact(c.svc, input);
94
+ c.data(r, `${c.style.ok(c.style.sym.ok)} Fact ${r.action}: ${r.fact.key} [${r.fact.status}/${r.fact.confidence}]`);
95
+ }
96
+ else if (sub === 'verify') {
97
+ const f = await verifyFactByKey(c.svc, need(c.rest[1], 'key (positional)'));
98
+ c.data(f, `${c.style.ok(c.style.sym.ok)} Verified ${f.key} [${f.status}]`);
99
+ }
100
+ else if (sub === 'remove') {
101
+ const key = need(c.rest[1], 'key (positional)');
102
+ const removed = await removeFactByKey(c.svc, key);
103
+ if (!removed)
104
+ throw new DevWorkspaceError('NOT_FOUND', `No fact with key "${key}".`);
105
+ c.data({ removed: key }, `${c.style.ok(c.style.sym.ok)} Removed ${key}`);
106
+ }
107
+ else if (sub === 'list' || sub === undefined) {
108
+ const ws = await requireWorkspace(c.svc.cwd);
109
+ const facts = (await loadFacts(ws)).facts;
110
+ c.data(facts, facts.length ? facts.map((f) => `${f.key} [${f.status}] ${f.value}`).join('\n') : 'No facts recorded yet.');
111
+ }
112
+ else
113
+ throw new DevWorkspaceError('USAGE', `Unknown fact subcommand "${sub}".`, { hint: 'Use: add, verify, remove, list.' });
114
+ },
115
+ async task(c) {
116
+ const v = c.args.values;
117
+ let sub = c.rest[0];
118
+ const known = ['new', 'list', 'show', 'status', 'update', 'verify', 'tests', 'attest'];
119
+ // `devworkspace task "<description>"` is shorthand for `task new`.
120
+ if (sub !== undefined && !known.includes(sub)) {
121
+ c.rest.unshift('new');
122
+ sub = 'new';
123
+ }
124
+ const id = c.rest[1];
125
+ switch (sub) {
126
+ case 'new': {
127
+ const text = c.rest.slice(1).join(' ').trim();
128
+ if (!text)
129
+ throw new DevWorkspaceError('USAGE', 'Describe the task: devworkspace task new "<request>"');
130
+ const r = await createTask(c.svc, { text, type: str(v, 'type'), title: str(v, 'title') });
131
+ const checks = r.task.verification.map((x) => `${x.check}${x.status === 'SKIPPED' ? ' (skipped: user override)' : ''}`).join(', ') || 'none';
132
+ c.data(r, [
133
+ `${c.style.ok(c.style.sym.ok)} Created ${r.task.id}`,
134
+ ` type: ${r.task.type} (${r.classification.confidence === 'high' ? 'classified' : 'low confidence - confirm with the user'})${r.classification.readOnly ? ' - read-only request' : ''}`,
135
+ ` required verification: ${checks}`,
136
+ ` workflow: ${r.workflow.steps[0]}`,
137
+ ].join('\n'));
138
+ break;
139
+ }
140
+ case 'list': {
141
+ const { tasks, corrupt } = await listTasksService(c.svc, bool(v, 'all'));
142
+ const text = tasks.length ? tasks.map((t) => `${t.id} ${t.status.padEnd(11)} ${t.type.padEnd(13)} ${t.title}`).join('\n') : 'No tasks.';
143
+ c.data({ tasks, corrupt }, text + (corrupt.length ? `\n${c.style.sym.warn} ${corrupt.length} unreadable task file(s); run: devworkspace doctor` : ''));
144
+ break;
145
+ }
146
+ case 'show': {
147
+ const r = await showTask(c.svc, need(id, 'id (positional)'));
148
+ c.data(r, renderTask(c.style, r.task, r.gate));
149
+ break;
150
+ }
151
+ case 'status': {
152
+ const r = await setTaskStatus(c.svc, need(id, 'id (positional)'), need(c.rest[2], 'status (positional)'), str(v, 'note'));
153
+ const warn = r.gate?.warnings.map((w) => `\n ${c.style.sym.warn} ${w}`).join('') ?? '';
154
+ c.data(r, `${c.style.ok(c.style.sym.ok)} ${r.task.id} is now ${r.task.status}${warn}`);
155
+ break;
156
+ }
157
+ case 'update': {
158
+ const t = await updateTask(c.svc, need(id, 'id (positional)'), {
159
+ title: str(v, 'title'),
160
+ summary: str(v, 'summary'),
161
+ criteria: list(v, 'criteria'),
162
+ plan: list(v, 'plan'),
163
+ areas: list(v, 'area'),
164
+ decisions: list(v, 'decision-note'),
165
+ blockers: list(v, 'blocker'),
166
+ clearBlockers: bool(v, 'clear-blockers'),
167
+ require: list(v, 'require'),
168
+ });
169
+ c.data(t, renderTask(c.style, t));
170
+ break;
171
+ }
172
+ case 'verify': {
173
+ const t = await recordVerification(c.svc, need(id, 'id (positional)'), need(c.rest[2], 'check (positional)'), need(c.rest[3], 'result (positional: pass|fail|skip|pending)'), {
174
+ reason: str(v, 'reason'),
175
+ detail: str(v, 'detail'),
176
+ });
177
+ c.data(t, renderTask(c.style, t));
178
+ break;
179
+ }
180
+ case 'tests': {
181
+ const phase = oneOf(str(v, 'phase'), ['baseline', 'after'], 'phase');
182
+ const t = await recordTests(c.svc, need(id, 'id (positional)'), phase, int(v, 'passed') ?? NaN, int(v, 'failed') ?? NaN);
183
+ c.data(t, renderTask(c.style, t));
184
+ break;
185
+ }
186
+ case 'attest': {
187
+ const t = await attestTask(c.svc, need(id, 'id (positional)'), {
188
+ userWorkIntact: bool(v, 'user-work-intact') || undefined,
189
+ knowledgeReviewed: bool(v, 'knowledge-reviewed') || undefined,
190
+ finalStateInspected: bool(v, 'final-state-inspected') || undefined,
191
+ });
192
+ c.data(t, renderTask(c.style, t));
193
+ break;
194
+ }
195
+ default:
196
+ throw new DevWorkspaceError('USAGE', 'Missing task subcommand.', { hint: 'Run "devworkspace task --help".' });
197
+ }
198
+ },
199
+ async decision(c) {
200
+ const v = c.args.values;
201
+ const sub = c.rest[0] ?? 'list';
202
+ if (sub === 'add') {
203
+ const d = await recordDecision(c.svc, {
204
+ title: need(str(v, 'title'), 'title'),
205
+ context: need(str(v, 'context'), 'context'),
206
+ decision: need(str(v, 'decision'), 'decision'),
207
+ consequences: need(str(v, 'consequences'), 'consequences'),
208
+ supersedes: int(v, 'supersedes'),
209
+ });
210
+ c.data(d, `${c.style.ok(c.style.sym.ok)} Recorded decision ${String(d.number).padStart(4, '0')}: ${d.title}`);
211
+ }
212
+ else if (sub === 'list') {
213
+ const ds = await getDecisions(c.svc);
214
+ c.data(ds, ds.length ? ds.map((d) => `${String(d.number).padStart(4, '0')} [${d.status}] ${d.date} ${d.title}`).join('\n') : 'No decisions recorded.');
215
+ }
216
+ else if (sub === 'show') {
217
+ const d = await getDecision(c.svc, Number(need(c.rest[1], 'number (positional)')));
218
+ c.data(d, `# ${d.number}. ${d.title} [${d.status}] ${d.date}\n\nContext:\n${d.context}\n\nDecision:\n${d.decision}\n\nConsequences:\n${d.consequences}`);
219
+ }
220
+ else
221
+ throw new DevWorkspaceError('USAGE', `Unknown decision subcommand "${sub}".`, { hint: 'Use: add, list, show.' });
222
+ },
223
+ async session(c) {
224
+ const v = c.args.values;
225
+ const sub = c.rest[0] ?? 'list';
226
+ if (sub === 'save') {
227
+ const s = await recordSession(c.svc, {
228
+ goal: need(str(v, 'goal'), 'goal'),
229
+ completed: list(v, 'done'),
230
+ areas: list(v, 'area'),
231
+ testsRun: list(v, 'tests-run'),
232
+ decisions: list(v, 'decision-note'),
233
+ remaining: list(v, 'remaining'),
234
+ next: str(v, 'next') ?? '',
235
+ taskId: str(v, 'task'),
236
+ });
237
+ c.data(s, `${c.style.ok(c.style.sym.ok)} Saved session ${s.id}`);
238
+ }
239
+ else if (sub === 'list') {
240
+ const ss = await getSessions(c.svc, int(v, 'limit') ?? 10);
241
+ c.data(ss, ss.length ? ss.map((s) => `${s.id} ${s.goal} ${c.style.sym.arrow} ${s.next || '(no next step)'}`).join('\n') : 'No sessions saved.');
242
+ }
243
+ else
244
+ throw new DevWorkspaceError('USAGE', `Unknown session subcommand "${sub}".`, { hint: 'Use: save, list.' });
245
+ },
246
+ async agent(c) {
247
+ if (c.rest[0] !== 'install')
248
+ throw new DevWorkspaceError('USAGE', 'Usage: devworkspace agent install [--agent claude]');
249
+ const r = await installAgent(c.svc, str(c.args.values, 'agent') ?? 'claude');
250
+ c.data(r, renderAgentInstall(c.style, r));
251
+ },
252
+ async export(c) {
253
+ const r = await exportWorkspace(c.svc, str(c.args.values, 'out'));
254
+ c.data(r, renderExport(c.style, r));
255
+ },
256
+ async import(c) {
257
+ const file = need(c.rest[0], 'file (positional)');
258
+ const r = await importWorkspace({ ...c.svc, overwrite: bool(c.args.values, 'overwrite'), allowDifferentProject: bool(c.args.values, 'allow-different-project') }, file);
259
+ c.data(r, renderImport(c.style, r));
260
+ },
261
+ async reset(c) {
262
+ const r = await resetWorkspace({ ...c.svc, confirm: bool(c.args.values, 'yes'), includeAgentFiles: bool(c.args.values, 'include-agent-files') });
263
+ c.data(r, renderReset(c.style, r));
264
+ if (!r.executed && !c.svc.dryRun) {
265
+ if (!c.json)
266
+ c.out('\nNothing was deleted. Re-run with --yes to confirm.');
267
+ c.exit = EXIT.USAGE;
268
+ }
269
+ },
270
+ async migrate(c) {
271
+ const r = await migrateWorkspace(c.svc);
272
+ c.data(r, renderMigrate(c.style, r));
273
+ },
274
+ };
275
+ const ALIASES = { tasks: 'task' };
276
+ /** Run the CLI and return the process exit code. Never calls process.exit, so it is directly testable. */
277
+ export async function run(argv, io = defaultIO()) {
278
+ let debug = argv.includes('--debug');
279
+ let json = argv.includes('--json');
280
+ try {
281
+ const args = parseCli(argv);
282
+ const v = args.values;
283
+ debug = bool(v, 'debug');
284
+ json = bool(v, 'json');
285
+ const color = io.isTTY && !io.env.NO_COLOR && !bool(v, 'no-color') && io.env.TERM !== 'dumb';
286
+ const ascii = bool(v, 'ascii') || !!io.env.DEVWORKSPACE_ASCII;
287
+ const style = makeStyle({ color, ascii });
288
+ const logger = createLogger(debug ? 'debug' : 'warn', (l) => io.stderr(l + '\n'));
289
+ if (bool(v, 'version') || args.positionals[0] === 'version') {
290
+ io.stdout(packageVersion() + '\n');
291
+ return EXIT.OK;
292
+ }
293
+ const [rawCmd, ...rest] = args.positionals;
294
+ const cmd = rawCmd ? (ALIASES[rawCmd] ?? rawCmd) : undefined;
295
+ if (rawCmd === 'tasks')
296
+ rest.unshift('list');
297
+ if (!cmd || cmd === 'help') {
298
+ const target = cmd === 'help' ? COMMANDS.find((c) => c.name === rest[0]) : undefined;
299
+ io.stdout((target ? commandHelp(target) : topHelp(packageVersion())) + '\n');
300
+ return EXIT.OK;
301
+ }
302
+ const help = COMMANDS.find((c) => c.name === cmd);
303
+ const handler = handlers[cmd];
304
+ if (!help || !handler) {
305
+ throw new DevWorkspaceError('USAGE', `Unknown command "${rawCmd}".`, { hint: 'Run "devworkspace --help" to see available commands.' });
306
+ }
307
+ if (bool(v, 'help')) {
308
+ io.stdout(commandHelp(help) + '\n');
309
+ return EXIT.OK;
310
+ }
311
+ const cwd = path.resolve(io.cwd, str(v, 'cwd') ?? '.');
312
+ const ctx = {
313
+ args,
314
+ rest,
315
+ svc: { cwd, dryRun: bool(v, 'dry-run'), env: io.env, ...(io.env.DEVWORKSPACE_HOME ? { homeDir: io.env.DEVWORKSPACE_HOME } : {}) },
316
+ json,
317
+ style,
318
+ exit: EXIT.OK,
319
+ out: (t) => io.stdout(t + '\n'),
320
+ data: (value, text) => io.stdout((json ? JSON.stringify(value, null, 2) : text) + '\n'),
321
+ };
322
+ logger.debug(`command=${cmd} cwd=${cwd}`);
323
+ await handler(ctx);
324
+ return ctx.exit;
325
+ }
326
+ catch (e) {
327
+ if (json) {
328
+ const err = isDevWorkspaceError(e)
329
+ ? { code: e.code, message: e.message, hint: e.hint ?? null, stateChanged: e.stateChanged }
330
+ : { code: 'INTERNAL', message: e instanceof Error ? e.message : String(e), hint: null, stateChanged: false };
331
+ io.stdout(JSON.stringify({ error: err }, null, 2) + '\n');
332
+ }
333
+ else {
334
+ io.stderr(formatError(e, debug) + '\n');
335
+ }
336
+ return isDevWorkspaceError(e) ? e.exitCode : EXIT.FAILURE;
337
+ }
338
+ }
339
+ //# sourceMappingURL=run.js.map