popeye-cli 1.7.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/README.md +148 -7
  2. package/cheatsheet.md +440 -0
  3. package/dist/cli/commands/db.d.ts +10 -0
  4. package/dist/cli/commands/db.d.ts.map +1 -0
  5. package/dist/cli/commands/db.js +240 -0
  6. package/dist/cli/commands/db.js.map +1 -0
  7. package/dist/cli/commands/doctor.d.ts +18 -0
  8. package/dist/cli/commands/doctor.d.ts.map +1 -0
  9. package/dist/cli/commands/doctor.js +255 -0
  10. package/dist/cli/commands/doctor.js.map +1 -0
  11. package/dist/cli/commands/index.d.ts +3 -0
  12. package/dist/cli/commands/index.d.ts.map +1 -1
  13. package/dist/cli/commands/index.js +3 -0
  14. package/dist/cli/commands/index.js.map +1 -1
  15. package/dist/cli/commands/review.d.ts +31 -0
  16. package/dist/cli/commands/review.d.ts.map +1 -0
  17. package/dist/cli/commands/review.js +156 -0
  18. package/dist/cli/commands/review.js.map +1 -0
  19. package/dist/cli/index.d.ts.map +1 -1
  20. package/dist/cli/index.js +4 -1
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/cli/interactive.d.ts.map +1 -1
  23. package/dist/cli/interactive.js +218 -61
  24. package/dist/cli/interactive.js.map +1 -1
  25. package/dist/generators/admin-wizard.d.ts +25 -0
  26. package/dist/generators/admin-wizard.d.ts.map +1 -0
  27. package/dist/generators/admin-wizard.js +123 -0
  28. package/dist/generators/admin-wizard.js.map +1 -0
  29. package/dist/generators/all.d.ts.map +1 -1
  30. package/dist/generators/all.js +10 -3
  31. package/dist/generators/all.js.map +1 -1
  32. package/dist/generators/database.d.ts +58 -0
  33. package/dist/generators/database.d.ts.map +1 -0
  34. package/dist/generators/database.js +229 -0
  35. package/dist/generators/database.js.map +1 -0
  36. package/dist/generators/fullstack.d.ts.map +1 -1
  37. package/dist/generators/fullstack.js +23 -7
  38. package/dist/generators/fullstack.js.map +1 -1
  39. package/dist/generators/index.d.ts +2 -0
  40. package/dist/generators/index.d.ts.map +1 -1
  41. package/dist/generators/index.js +2 -0
  42. package/dist/generators/index.js.map +1 -1
  43. package/dist/generators/templates/admin-wizard-python.d.ts +32 -0
  44. package/dist/generators/templates/admin-wizard-python.d.ts.map +1 -0
  45. package/dist/generators/templates/admin-wizard-python.js +425 -0
  46. package/dist/generators/templates/admin-wizard-python.js.map +1 -0
  47. package/dist/generators/templates/admin-wizard-react.d.ts +48 -0
  48. package/dist/generators/templates/admin-wizard-react.d.ts.map +1 -0
  49. package/dist/generators/templates/admin-wizard-react.js +554 -0
  50. package/dist/generators/templates/admin-wizard-react.js.map +1 -0
  51. package/dist/generators/templates/database-docker.d.ts +23 -0
  52. package/dist/generators/templates/database-docker.d.ts.map +1 -0
  53. package/dist/generators/templates/database-docker.js +221 -0
  54. package/dist/generators/templates/database-docker.js.map +1 -0
  55. package/dist/generators/templates/database-python.d.ts +54 -0
  56. package/dist/generators/templates/database-python.d.ts.map +1 -0
  57. package/dist/generators/templates/database-python.js +723 -0
  58. package/dist/generators/templates/database-python.js.map +1 -0
  59. package/dist/generators/templates/database-typescript.d.ts +34 -0
  60. package/dist/generators/templates/database-typescript.d.ts.map +1 -0
  61. package/dist/generators/templates/database-typescript.js +232 -0
  62. package/dist/generators/templates/database-typescript.js.map +1 -0
  63. package/dist/generators/templates/fullstack.d.ts.map +1 -1
  64. package/dist/generators/templates/fullstack.js +29 -0
  65. package/dist/generators/templates/fullstack.js.map +1 -1
  66. package/dist/generators/templates/index.d.ts +5 -0
  67. package/dist/generators/templates/index.d.ts.map +1 -1
  68. package/dist/generators/templates/index.js +5 -0
  69. package/dist/generators/templates/index.js.map +1 -1
  70. package/dist/state/index.d.ts +10 -0
  71. package/dist/state/index.d.ts.map +1 -1
  72. package/dist/state/index.js +21 -0
  73. package/dist/state/index.js.map +1 -1
  74. package/dist/types/audit.d.ts +623 -0
  75. package/dist/types/audit.d.ts.map +1 -0
  76. package/dist/types/audit.js +240 -0
  77. package/dist/types/audit.js.map +1 -0
  78. package/dist/types/database-runtime.d.ts +86 -0
  79. package/dist/types/database-runtime.d.ts.map +1 -0
  80. package/dist/types/database-runtime.js +61 -0
  81. package/dist/types/database-runtime.js.map +1 -0
  82. package/dist/types/database.d.ts +85 -0
  83. package/dist/types/database.d.ts.map +1 -0
  84. package/dist/types/database.js +71 -0
  85. package/dist/types/database.js.map +1 -0
  86. package/dist/types/index.d.ts +2 -0
  87. package/dist/types/index.d.ts.map +1 -1
  88. package/dist/types/index.js +4 -0
  89. package/dist/types/index.js.map +1 -1
  90. package/dist/types/workflow.d.ts +36 -0
  91. package/dist/types/workflow.d.ts.map +1 -1
  92. package/dist/types/workflow.js +7 -0
  93. package/dist/types/workflow.js.map +1 -1
  94. package/dist/workflow/audit-analyzer.d.ts +58 -0
  95. package/dist/workflow/audit-analyzer.d.ts.map +1 -0
  96. package/dist/workflow/audit-analyzer.js +420 -0
  97. package/dist/workflow/audit-analyzer.js.map +1 -0
  98. package/dist/workflow/audit-mode.d.ts +28 -0
  99. package/dist/workflow/audit-mode.d.ts.map +1 -0
  100. package/dist/workflow/audit-mode.js +169 -0
  101. package/dist/workflow/audit-mode.js.map +1 -0
  102. package/dist/workflow/audit-recovery.d.ts +61 -0
  103. package/dist/workflow/audit-recovery.d.ts.map +1 -0
  104. package/dist/workflow/audit-recovery.js +242 -0
  105. package/dist/workflow/audit-recovery.js.map +1 -0
  106. package/dist/workflow/audit-reporter.d.ts +65 -0
  107. package/dist/workflow/audit-reporter.d.ts.map +1 -0
  108. package/dist/workflow/audit-reporter.js +301 -0
  109. package/dist/workflow/audit-reporter.js.map +1 -0
  110. package/dist/workflow/audit-scanner.d.ts +87 -0
  111. package/dist/workflow/audit-scanner.d.ts.map +1 -0
  112. package/dist/workflow/audit-scanner.js +768 -0
  113. package/dist/workflow/audit-scanner.js.map +1 -0
  114. package/dist/workflow/db-setup-runner.d.ts +63 -0
  115. package/dist/workflow/db-setup-runner.d.ts.map +1 -0
  116. package/dist/workflow/db-setup-runner.js +336 -0
  117. package/dist/workflow/db-setup-runner.js.map +1 -0
  118. package/dist/workflow/db-state-machine.d.ts +30 -0
  119. package/dist/workflow/db-state-machine.d.ts.map +1 -0
  120. package/dist/workflow/db-state-machine.js +51 -0
  121. package/dist/workflow/db-state-machine.js.map +1 -0
  122. package/dist/workflow/index.d.ts +7 -0
  123. package/dist/workflow/index.d.ts.map +1 -1
  124. package/dist/workflow/index.js +7 -0
  125. package/dist/workflow/index.js.map +1 -1
  126. package/package.json +1 -1
  127. package/src/cli/commands/db.ts +281 -0
  128. package/src/cli/commands/doctor.ts +273 -0
  129. package/src/cli/commands/index.ts +3 -0
  130. package/src/cli/commands/review.ts +187 -0
  131. package/src/cli/index.ts +6 -0
  132. package/src/cli/interactive.ts +174 -4
  133. package/src/generators/admin-wizard.ts +146 -0
  134. package/src/generators/all.ts +10 -3
  135. package/src/generators/database.ts +286 -0
  136. package/src/generators/fullstack.ts +26 -9
  137. package/src/generators/index.ts +12 -0
  138. package/src/generators/templates/admin-wizard-python.ts +431 -0
  139. package/src/generators/templates/admin-wizard-react.ts +560 -0
  140. package/src/generators/templates/database-docker.ts +227 -0
  141. package/src/generators/templates/database-python.ts +734 -0
  142. package/src/generators/templates/database-typescript.ts +238 -0
  143. package/src/generators/templates/fullstack.ts +29 -0
  144. package/src/generators/templates/index.ts +5 -0
  145. package/src/state/index.ts +28 -0
  146. package/src/types/audit.ts +294 -0
  147. package/src/types/database-runtime.ts +69 -0
  148. package/src/types/database.ts +84 -0
  149. package/src/types/index.ts +29 -0
  150. package/src/types/workflow.ts +20 -0
  151. package/src/workflow/audit-analyzer.ts +491 -0
  152. package/src/workflow/audit-mode.ts +240 -0
  153. package/src/workflow/audit-recovery.ts +284 -0
  154. package/src/workflow/audit-reporter.ts +370 -0
  155. package/src/workflow/audit-scanner.ts +873 -0
  156. package/src/workflow/db-setup-runner.ts +391 -0
  157. package/src/workflow/db-state-machine.ts +58 -0
  158. package/src/workflow/index.ts +7 -0
  159. package/tests/cli/commands/review.test.ts +52 -0
  160. package/tests/generators/admin-wizard-orchestrator.test.ts +64 -0
  161. package/tests/generators/admin-wizard-templates.test.ts +366 -0
  162. package/tests/generators/cross-phase-integration.test.ts +383 -0
  163. package/tests/generators/database.test.ts +456 -0
  164. package/tests/generators/fe-be-db-integration.test.ts +613 -0
  165. package/tests/types/audit.test.ts +250 -0
  166. package/tests/types/database-runtime.test.ts +158 -0
  167. package/tests/types/database.test.ts +187 -0
  168. package/tests/workflow/audit-analyzer.test.ts +281 -0
  169. package/tests/workflow/audit-mode.test.ts +114 -0
  170. package/tests/workflow/audit-recovery.test.ts +237 -0
  171. package/tests/workflow/audit-reporter.test.ts +254 -0
  172. package/tests/workflow/audit-scanner.test.ts +270 -0
  173. package/tests/workflow/db-setup-runner.test.ts +211 -0
  174. package/tests/workflow/db-state-machine.test.ts +117 -0
@@ -0,0 +1,156 @@
1
+ /**
2
+ * CLI command: popeye review
3
+ *
4
+ * Runs a post-build audit/review of the project, producing a structured
5
+ * report with findings and optional recovery tasks.
6
+ *
7
+ * Pattern follows doctor.ts command factory.
8
+ */
9
+ import { Command } from 'commander';
10
+ import path from 'node:path';
11
+ import { printHeader, printSuccess, printError, printWarning, printInfo, printKeyValue, printSection, } from '../output.js';
12
+ import { runAuditMode } from '../../workflow/audit-mode.js';
13
+ // ---------------------------------------------------------------------------
14
+ // Run audit (exported for testability + slash command reuse)
15
+ // ---------------------------------------------------------------------------
16
+ /**
17
+ * Execute the audit and print results to the console.
18
+ *
19
+ * @param projectDir - Absolute path to the project directory.
20
+ * @param options - CLI options.
21
+ * @returns The audit result.
22
+ */
23
+ export async function runReview(projectDir, options = {}) {
24
+ printHeader('Project Audit / Review');
25
+ const auditOptions = {
26
+ projectDir,
27
+ depth: options.depth ?? 2,
28
+ runTests: true,
29
+ strict: options.strict ?? false,
30
+ format: options.format ?? 'both',
31
+ autoRecover: options.recover ?? true,
32
+ target: (options.target ?? 'all'),
33
+ onProgress: (stage, message) => {
34
+ printInfo(`[${stage}] ${message}`);
35
+ },
36
+ };
37
+ const result = await runAuditMode(auditOptions);
38
+ if (!result.success) {
39
+ printError(`Audit failed: ${result.error}`);
40
+ return result;
41
+ }
42
+ // Print summary
43
+ console.log();
44
+ printSection('Summary');
45
+ printKeyValue('Project', result.summary.projectName);
46
+ printKeyValue('Language', result.summary.language);
47
+ printKeyValue('Source files', result.summary.totalSourceFiles);
48
+ printKeyValue('Test files', result.summary.totalTestFiles);
49
+ printKeyValue('Lines of code', result.summary.totalLinesOfCode);
50
+ printKeyValue('Components', result.summary.componentCount);
51
+ // Print score
52
+ console.log();
53
+ printSection('Audit Score');
54
+ const score = result.audit.overallScore;
55
+ if (score >= 80) {
56
+ printSuccess(`Overall: ${score}/100`);
57
+ }
58
+ else if (score >= 60) {
59
+ printWarning(`Overall: ${score}/100`);
60
+ }
61
+ else {
62
+ printError(`Overall: ${score}/100`);
63
+ }
64
+ // Print finding counts
65
+ if (result.audit.criticalCount > 0) {
66
+ printError(`Critical: ${result.audit.criticalCount}`);
67
+ }
68
+ if (result.audit.majorCount > 0) {
69
+ printWarning(`Major: ${result.audit.majorCount}`);
70
+ }
71
+ if (result.audit.minorCount > 0) {
72
+ printInfo(`Minor: ${result.audit.minorCount}`);
73
+ }
74
+ if (result.audit.infoCount > 0) {
75
+ printInfo(`Info: ${result.audit.infoCount}`);
76
+ }
77
+ // Recommendation
78
+ console.log();
79
+ const rec = result.audit.recommendation;
80
+ if (rec === 'pass') {
81
+ printSuccess(`Recommendation: ${rec}`);
82
+ }
83
+ else if (rec === 'fix-and-recheck') {
84
+ printWarning(`Recommendation: ${rec}`);
85
+ }
86
+ else {
87
+ printError(`Recommendation: ${rec}`);
88
+ }
89
+ // Report paths
90
+ if (Object.keys(result.reportPaths).length > 0) {
91
+ console.log();
92
+ printSection('Reports');
93
+ if (result.reportPaths.auditMd) {
94
+ printInfo(`Markdown: ${result.reportPaths.auditMd}`);
95
+ }
96
+ if (result.reportPaths.auditJson) {
97
+ printInfo(`JSON: ${result.reportPaths.auditJson}`);
98
+ }
99
+ if (result.reportPaths.recoveryMd) {
100
+ printWarning(`Recovery plan: ${result.reportPaths.recoveryMd}`);
101
+ }
102
+ }
103
+ // Recovery info
104
+ if (result.recovery) {
105
+ console.log();
106
+ printSection('Recovery Plan');
107
+ printWarning(`${result.recovery.milestones.length} recovery milestone(s), estimated ${result.recovery.estimatedEffort}`);
108
+ if (auditOptions.autoRecover) {
109
+ printSuccess('Recovery milestones injected — run /resume to execute.');
110
+ }
111
+ else {
112
+ printInfo('Run without --no-recover to auto-inject recovery milestones.');
113
+ }
114
+ }
115
+ return result;
116
+ }
117
+ // ---------------------------------------------------------------------------
118
+ // Commander command factory
119
+ // ---------------------------------------------------------------------------
120
+ /**
121
+ * Create the `popeye review` CLI command.
122
+ *
123
+ * @returns Commander command instance.
124
+ */
125
+ export function createReviewCommand() {
126
+ const cmd = new Command('review')
127
+ .alias('audit')
128
+ .description('Run a post-build audit/review of the project')
129
+ .argument('[directory]', 'Project directory', '.')
130
+ .option('-d, --depth <level>', 'Audit depth: 1=shallow, 2=standard, 3=deep', '2')
131
+ .option('-s, --strict', 'Enable strict mode (higher standards)', false)
132
+ .option('-f, --format <type>', 'Output format: json, md, both', 'both')
133
+ .option('--no-recover', 'Skip auto-injection of recovery milestones')
134
+ .option('-t, --target <kind>', 'Audit target: all, frontend, backend, website', 'all')
135
+ .action(async (directory, opts) => {
136
+ const projectDir = path.resolve(directory);
137
+ try {
138
+ const result = await runReview(projectDir, {
139
+ depth: parseInt(opts.depth, 10),
140
+ strict: opts.strict,
141
+ format: opts.format,
142
+ recover: opts.recover,
143
+ target: opts.target,
144
+ });
145
+ if (!result.success) {
146
+ process.exit(1);
147
+ }
148
+ }
149
+ catch (err) {
150
+ printError(err instanceof Error ? err.message : 'Audit failed');
151
+ process.exit(1);
152
+ }
153
+ });
154
+ return cmd;
155
+ }
156
+ //# sourceMappingURL=review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.js","sourceRoot":"","sources":["../../../src/cli/commands/review.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiBpC,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AAOpC,eAAO,MAAM,OAAO,EAAE,MAA4B,CAAC;AAEnD;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAuCvC;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CASzE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAoBpC,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AAOpC,eAAO,MAAM,OAAO,EAAE,MAA4B,CAAC;AAEnD;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CA0CvC;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CASzE"}
package/dist/cli/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { Command } from 'commander';
6
6
  import { createRequire } from 'node:module';
7
- import { createAuthCommand, createCreateCommand, createStatusCommand, createValidateCommand, createSummaryCommand, createResumeCommand, createResetCommand, createCancelCommand, createConfigCommand, } from './commands/index.js';
7
+ import { createAuthCommand, createCreateCommand, createStatusCommand, createValidateCommand, createSummaryCommand, createResumeCommand, createResetCommand, createCancelCommand, createConfigCommand, createDbCommand, createDoctorCommand, createReviewCommand, } from './commands/index.js';
8
8
  import { startInteractiveMode } from './interactive.js';
9
9
  import { printError } from './output.js';
10
10
  // Re-export
@@ -38,6 +38,9 @@ export function createProgram() {
38
38
  program.addCommand(createResetCommand());
39
39
  program.addCommand(createCancelCommand());
40
40
  program.addCommand(createConfigCommand());
41
+ program.addCommand(createDbCommand());
42
+ program.addCommand(createDoctorCommand());
43
+ program.addCommand(createReviewCommand());
41
44
  // Interactive mode command
42
45
  program
43
46
  .command('interactive')
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../../src/cli/interactive.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA8tEH;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA2B7E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BrF;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA4EhE;AAiVD;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CA4E1D"}
1
+ {"version":3,"file":"interactive.d.ts","sourceRoot":"","sources":["../../src/cli/interactive.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAw4EH;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA2B7E;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BrF;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA4EhE;AAiVD;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CA4E1D"}
@@ -697,6 +697,9 @@ function showHelp() {
697
697
  ['/new <idea>', 'Force start a new project (skips existing check)'],
698
698
  ['/resume', 'Resume interrupted project'],
699
699
  ['/overview [fix]', 'Project review with analysis; fix to auto-discover docs'],
700
+ ['/db [action]', 'Database management (status/configure/apply)'],
701
+ ['/doctor', 'Run database and project readiness checks'],
702
+ ['/review', 'Run post-build audit/review with findings and recovery'],
700
703
  ['/clear', 'Clear screen'],
701
704
  ['/exit', 'Exit Popeye'],
702
705
  ];
@@ -838,6 +841,16 @@ async function handleInput(input, state) {
838
841
  await handleNewProject(args.join(' '), state);
839
842
  }
840
843
  break;
844
+ case '/db':
845
+ await handleDbSlashCommand(state, args);
846
+ break;
847
+ case '/doctor':
848
+ await handleDoctorSlashCommand(state);
849
+ break;
850
+ case '/review':
851
+ case '/audit':
852
+ await handleReviewSlashCommand(state, args);
853
+ break;
841
854
  default:
842
855
  printError(`Unknown command: ${cmd}`);
843
856
  printInfo('Type /help for available commands');
@@ -872,6 +885,134 @@ async function handleStatus(state) {
872
885
  const summary = await getWorkflowSummary(state.projectDir);
873
886
  console.log(summary);
874
887
  }
888
+ /**
889
+ * Handle /db slash command - database management
890
+ */
891
+ async function handleDbSlashCommand(state, args) {
892
+ if (!state.projectDir) {
893
+ printError('No active project. Create or resume a project first.');
894
+ return;
895
+ }
896
+ const action = args[0] || 'status';
897
+ switch (action) {
898
+ case 'status': {
899
+ try {
900
+ const { loadProject } = await import('../state/index.js');
901
+ const { DEFAULT_DB_CONFIG } = await import('../types/database.js');
902
+ const projectState = await loadProject(state.projectDir);
903
+ const dbConfig = projectState.dbConfig || { ...DEFAULT_DB_CONFIG, designed: false };
904
+ console.log();
905
+ printInfo('Database Status:');
906
+ console.log(` Designed: ${dbConfig.designed ? 'Yes' : 'No'}`);
907
+ console.log(` Status: ${dbConfig.status}`);
908
+ console.log(` Mode: ${dbConfig.mode || 'not set'}`);
909
+ console.log(` Vector: ${dbConfig.vectorRequired ? 'Yes' : 'No'}`);
910
+ console.log(` Migrations: ${dbConfig.migrationsApplied}`);
911
+ if (dbConfig.lastError) {
912
+ printError(` Last Error: ${dbConfig.lastError}`);
913
+ }
914
+ console.log();
915
+ }
916
+ catch (err) {
917
+ printError(err instanceof Error ? err.message : 'Failed to load project state');
918
+ }
919
+ break;
920
+ }
921
+ case 'configure': {
922
+ printInfo('Use "popeye db configure" from the CLI for interactive configuration.');
923
+ printInfo('Or set DATABASE_URL in apps/backend/.env manually.');
924
+ break;
925
+ }
926
+ case 'apply': {
927
+ printInfo('Use "popeye db apply" from the CLI to run the setup pipeline.');
928
+ break;
929
+ }
930
+ default:
931
+ printError(`Unknown db action: ${action}`);
932
+ printInfo('Usage: /db [status|configure|apply]');
933
+ }
934
+ }
935
+ /**
936
+ * Handle /doctor slash command - readiness checks
937
+ */
938
+ async function handleDoctorSlashCommand(state) {
939
+ if (!state.projectDir) {
940
+ printError('No active project. Create or resume a project first.');
941
+ return;
942
+ }
943
+ try {
944
+ const { runDoctorChecks } = await import('./commands/doctor.js');
945
+ console.log();
946
+ printInfo('Running readiness checks...');
947
+ console.log();
948
+ const result = await runDoctorChecks(state.projectDir);
949
+ for (const check of result.checks) {
950
+ const label = check.passed ? '[PASS]' : check.severity === 'info' ? '[SKIP]' : '[FAIL]';
951
+ if (check.passed) {
952
+ printSuccess(` ${label} ${check.name}: ${check.message}`);
953
+ }
954
+ else if (check.severity === 'info') {
955
+ printInfo(` ${label} ${check.name}: ${check.message}`);
956
+ }
957
+ else if (check.severity === 'warning') {
958
+ printWarning(` ${label} ${check.name}: ${check.message}`);
959
+ }
960
+ else {
961
+ printError(` ${label} ${check.name}: ${check.message}`);
962
+ }
963
+ }
964
+ console.log();
965
+ if (result.healthy) {
966
+ printSuccess('All critical checks passed.');
967
+ }
968
+ else {
969
+ printWarning('Some critical checks failed. See above for details.');
970
+ }
971
+ }
972
+ catch (err) {
973
+ printError(err instanceof Error ? err.message : 'Doctor checks failed');
974
+ }
975
+ }
976
+ /**
977
+ * Handle /review or /audit slash command - post-build project audit
978
+ */
979
+ async function handleReviewSlashCommand(state, args = []) {
980
+ if (!state.projectDir) {
981
+ printError('No active project. Create or resume a project first.');
982
+ return;
983
+ }
984
+ // Parse CLI-style flags from args
985
+ const options = {};
986
+ for (let i = 0; i < args.length; i++) {
987
+ const arg = args[i];
988
+ if ((arg === '--depth' || arg === '-d') && args[i + 1]) {
989
+ options.depth = parseInt(args[++i], 10);
990
+ }
991
+ else if (arg === '--strict' || arg === '-s') {
992
+ options.strict = true;
993
+ }
994
+ else if ((arg === '--format' || arg === '-f') && args[i + 1]) {
995
+ options.format = args[++i];
996
+ }
997
+ else if (arg === '--no-recover') {
998
+ options.recover = false;
999
+ }
1000
+ else if (arg === '--recover') {
1001
+ options.recover = true;
1002
+ }
1003
+ else if ((arg === '--target' || arg === '-t') && args[i + 1]) {
1004
+ options.target = args[++i];
1005
+ }
1006
+ }
1007
+ try {
1008
+ const { runReview } = await import('./commands/review.js');
1009
+ console.log();
1010
+ await runReview(state.projectDir, options);
1011
+ }
1012
+ catch (err) {
1013
+ printError(err instanceof Error ? err.message : 'Audit failed');
1014
+ }
1015
+ }
875
1016
  /**
876
1017
  * Handle /overview command - full project plan and milestone review
877
1018
  */
@@ -1468,73 +1609,89 @@ async function handleResume(state, args) {
1468
1609
  printError('Authentication required. Run /auth first.');
1469
1610
  return;
1470
1611
  }
1471
- // Discover all projects (registered + scanned in current directory)
1472
- console.log();
1473
- printInfo('Scanning for projects...');
1474
- const { all: allProjects } = await discoverProjects(state.projectDir || process.cwd());
1475
- // If projects found, let user select one
1476
- if (allProjects.length > 0) {
1477
- console.log();
1478
- console.log(theme.primary.bold(' Found Projects:'));
1479
- console.log();
1480
- // Show project list with numbers
1481
- const displayProjects = allProjects.slice(0, 10); // Limit to 10
1482
- for (let i = 0; i < displayProjects.length; i++) {
1483
- const project = displayProjects[i];
1484
- const info = formatProjectForDisplay(project);
1485
- const statusColor = project.status === 'complete' ? theme.success :
1486
- project.status === 'failed' ? theme.error :
1487
- project.status === 'in-progress' ? theme.warning : theme.dim;
1488
- console.log(` ${theme.primary(`${i + 1}.`)} ${theme.secondary(info.name)}`);
1489
- console.log(` ${statusColor(info.status)} ${theme.dim('|')} ${info.age}`);
1490
- console.log(` ${theme.dim(info.path)}`);
1491
- if (project.idea) {
1492
- console.log(` ${theme.dim(project.idea.slice(0, 60))}${project.idea.length > 60 ? '...' : ''}`);
1612
+ // Reason: If there's already an active project with pending work (e.g., from /review recovery),
1613
+ // skip project discovery and go straight to resuming.
1614
+ if (state.projectDir) {
1615
+ const activeStatus = await getWorkflowStatus(state.projectDir);
1616
+ if (activeStatus.exists && activeStatus.state) {
1617
+ const { phase, status: pStatus } = activeStatus.state;
1618
+ const hasPendingWork = phase !== 'complete' || pStatus !== 'complete';
1619
+ if (hasPendingWork) {
1620
+ printInfo(`Resuming active project: ${activeStatus.state.name}`);
1621
+ // Fall through to the resume logic below (skip discovery)
1493
1622
  }
1494
- console.log();
1495
1623
  }
1496
- if (allProjects.length > 10) {
1497
- console.log(theme.dim(` ... and ${allProjects.length - 10} more projects`));
1624
+ }
1625
+ // Only discover projects if no active project with pending work
1626
+ if (!state.projectDir || (await getWorkflowStatus(state.projectDir)).state?.phase === 'complete') {
1627
+ // Discover all projects (registered + scanned in current directory)
1628
+ console.log();
1629
+ printInfo('Scanning for projects...');
1630
+ const { all: allProjects } = await discoverProjects(state.projectDir || process.cwd());
1631
+ // If projects found, let user select one
1632
+ if (allProjects.length > 0) {
1498
1633
  console.log();
1499
- }
1500
- // Let user select
1501
- const selection = await promptSelection('Select a project to resume:', [
1502
- ...displayProjects.map((p, i) => ({
1503
- value: String(i),
1504
- label: `${p.name} (${formatProjectForDisplay(p).age})`,
1505
- })),
1506
- { value: 'scan', label: 'Scan for more projects...' },
1507
- { value: 'cancel', label: 'Cancel' },
1508
- ], '0');
1509
- if (selection === 'cancel') {
1510
- printInfo('Cancelled');
1511
- return;
1512
- }
1513
- if (selection === 'scan') {
1514
- // Scan deeper in current directory
1515
- printInfo('Scanning subdirectories...');
1516
- const { all: deepScan } = await discoverProjects(state.projectDir || process.cwd());
1517
- if (deepScan.length === allProjects.length) {
1518
- printWarning('No additional projects found');
1634
+ console.log(theme.primary.bold(' Found Projects:'));
1635
+ console.log();
1636
+ // Show project list with numbers
1637
+ const displayProjects = allProjects.slice(0, 10); // Limit to 10
1638
+ for (let i = 0; i < displayProjects.length; i++) {
1639
+ const project = displayProjects[i];
1640
+ const info = formatProjectForDisplay(project);
1641
+ const statusColor = project.status === 'complete' ? theme.success :
1642
+ project.status === 'failed' ? theme.error :
1643
+ project.status === 'in-progress' ? theme.warning : theme.dim;
1644
+ console.log(` ${theme.primary(`${i + 1}.`)} ${theme.secondary(info.name)}`);
1645
+ console.log(` ${statusColor(info.status)} ${theme.dim('|')} ${info.age}`);
1646
+ console.log(` ${theme.dim(info.path)}`);
1647
+ if (project.idea) {
1648
+ console.log(` ${theme.dim(project.idea.slice(0, 60))}${project.idea.length > 60 ? '...' : ''}`);
1649
+ }
1650
+ console.log();
1519
1651
  }
1520
- else {
1521
- printSuccess(`Found ${deepScan.length - allProjects.length} additional projects`);
1652
+ if (allProjects.length > 10) {
1653
+ console.log(theme.dim(` ... and ${allProjects.length - 10} more projects`));
1654
+ console.log();
1522
1655
  }
1523
- // Recursively call handleResume to show updated list
1524
- await handleResume(state, args);
1525
- return;
1526
- }
1527
- const selectedIndex = parseInt(selection, 10);
1528
- const selectedProject = displayProjects[selectedIndex];
1529
- if (!selectedProject) {
1530
- printError('Invalid selection');
1531
- return;
1656
+ // Let user select
1657
+ const selection = await promptSelection('Select a project to resume:', [
1658
+ ...displayProjects.map((p, i) => ({
1659
+ value: String(i),
1660
+ label: `${p.name} (${formatProjectForDisplay(p).age})`,
1661
+ })),
1662
+ { value: 'scan', label: 'Scan for more projects...' },
1663
+ { value: 'cancel', label: 'Cancel' },
1664
+ ], '0');
1665
+ if (selection === 'cancel') {
1666
+ printInfo('Cancelled');
1667
+ return;
1668
+ }
1669
+ if (selection === 'scan') {
1670
+ // Scan deeper in current directory
1671
+ printInfo('Scanning subdirectories...');
1672
+ const { all: deepScan } = await discoverProjects(state.projectDir || process.cwd());
1673
+ if (deepScan.length === allProjects.length) {
1674
+ printWarning('No additional projects found');
1675
+ }
1676
+ else {
1677
+ printSuccess(`Found ${deepScan.length - allProjects.length} additional projects`);
1678
+ }
1679
+ // Recursively call handleResume to show updated list
1680
+ await handleResume(state, args);
1681
+ return;
1682
+ }
1683
+ const selectedIndex = parseInt(selection, 10);
1684
+ const selectedProject = displayProjects[selectedIndex];
1685
+ if (!selectedProject) {
1686
+ printError('Invalid selection');
1687
+ return;
1688
+ }
1689
+ // Set the project directory and continue
1690
+ state.projectDir = selectedProject.path;
1691
+ console.log();
1692
+ printInfo(`Selected: ${selectedProject.name}`);
1532
1693
  }
1533
- // Set the project directory and continue
1534
- state.projectDir = selectedProject.path;
1535
- console.log();
1536
- printInfo(`Selected: ${selectedProject.name}`);
1537
- }
1694
+ } // end: project discovery block
1538
1695
  // Now check for formal project state at the selected/current directory
1539
1696
  if (!state.projectDir) {
1540
1697
  printError('No project directory set');