@polymorphism-tech/morph-spec 4.7.1 → 4.8.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 (138) hide show
  1. package/.morph/analytics/threads-log.jsonl +54 -0
  2. package/.morph/state.json +198 -0
  3. package/LICENSE +1 -2
  4. package/README.md +379 -414
  5. package/bin/morph-spec.js +57 -403
  6. package/bin/validate.js +2 -26
  7. package/claude-plugin.json +2 -2
  8. package/docs/ARCHITECTURE.md +43 -46
  9. package/docs/CHEATSHEET.md +203 -221
  10. package/docs/COMMAND-FLOWS.md +319 -289
  11. package/docs/QUICKSTART.md +2 -8
  12. package/docs/plans/2026-02-22-claude-docs-morph-alignment-analysis.md +2 -0
  13. package/docs/plans/2026-02-22-claude-settings.md +2 -0
  14. package/docs/plans/2026-02-22-morph-cc-alignment-impl.md +2 -0
  15. package/docs/plans/2026-02-22-morph-spec-next.md +2 -0
  16. package/docs/plans/2026-02-22-native-alignment-design.md +2 -0
  17. package/docs/plans/2026-02-22-native-alignment-impl.md +2 -0
  18. package/docs/plans/2026-02-22-native-enrichment-design.md +2 -0
  19. package/docs/plans/2026-02-22-native-enrichment.md +2 -0
  20. package/docs/plans/2026-02-23-ddd-architecture-refactor.md +2 -0
  21. package/docs/plans/2026-02-23-ddd-nextsteps.md +2 -0
  22. package/docs/plans/2026-02-23-infra-architect-refactor.md +2 -0
  23. package/docs/plans/2026-02-23-nextjs-code-review-design.md +2 -1
  24. package/docs/plans/2026-02-23-nextjs-code-review-impl.md +2 -0
  25. package/docs/plans/2026-02-23-nextjs-standards-design.md +2 -1
  26. package/docs/plans/2026-02-23-nextjs-standards-impl.md +2 -0
  27. package/docs/plans/2026-02-24-cli-radical-simplification.md +592 -0
  28. package/docs/plans/2026-02-24-framework-failure-points.md +125 -0
  29. package/docs/plans/2026-02-24-morph-init-design.md +337 -0
  30. package/docs/plans/2026-02-24-morph-init-impl.md +1269 -0
  31. package/docs/plans/2026-02-24-tutorial-command-design.md +71 -0
  32. package/docs/plans/2026-02-24-tutorial-command.md +298 -0
  33. package/framework/CLAUDE.md +2 -2
  34. package/framework/commands/morph-proposal.md +3 -3
  35. package/framework/hooks/README.md +11 -10
  36. package/framework/hooks/claude-code/notification/approval-reminder.js +2 -0
  37. package/framework/hooks/claude-code/post-tool-use/dispatch.js +1 -1
  38. package/framework/hooks/claude-code/pre-tool-use/protect-readonly-files.js +4 -55
  39. package/framework/hooks/claude-code/session-start/inject-morph-context.js +20 -5
  40. package/framework/hooks/claude-code/statusline.py +6 -1
  41. package/framework/hooks/claude-code/stop/validate-completion.js +1 -1
  42. package/framework/hooks/claude-code/user-prompt/enrich-prompt.js +1 -1
  43. package/framework/hooks/dev/check-sync-health.js +117 -0
  44. package/framework/hooks/dev/guard-version-numbers.js +57 -0
  45. package/framework/hooks/dev/sync-standards-registry.js +60 -0
  46. package/framework/hooks/dev/sync-template-registry.js +60 -0
  47. package/framework/hooks/dev/validate-skill-format.js +70 -0
  48. package/framework/hooks/dev/validate-standard-format.js +73 -0
  49. package/framework/hooks/shared/payload-utils.js +39 -0
  50. package/framework/hooks/shared/state-reader.js +25 -1
  51. package/framework/rules/morph-workflow.md +1 -1
  52. package/framework/skills/level-0-meta/morph-init/SKILL.md +216 -0
  53. package/framework/skills/level-0-meta/morph-replicate/SKILL.md +4 -4
  54. package/framework/skills/level-0-meta/tool-usage-guide/SKILL.md +4 -4
  55. package/framework/skills/level-0-meta/verification-before-completion/SKILL.md +1 -1
  56. package/framework/skills/level-1-workflows/phase-clarify/SKILL.md +192 -191
  57. package/framework/skills/level-1-workflows/phase-codebase-analysis/SKILL.md +181 -180
  58. package/framework/skills/level-1-workflows/phase-design/SKILL.md +339 -338
  59. package/framework/skills/level-1-workflows/phase-implement/SKILL.md +254 -253
  60. package/framework/skills/level-1-workflows/phase-setup/SKILL.md +168 -170
  61. package/framework/skills/level-1-workflows/phase-tasks/SKILL.md +284 -283
  62. package/framework/skills/level-1-workflows/phase-uiux/SKILL.md +246 -245
  63. package/framework/templates/examples/design-system-examples.md +1 -1
  64. package/framework/templates/ui/FluentDesignTheme.cs +1 -1
  65. package/framework/templates/ui/MudTheme.cs +1 -1
  66. package/framework/templates/ui/design-system.css +1 -1
  67. package/package.json +4 -2
  68. package/scripts/bump-version.js +248 -0
  69. package/scripts/install-dev-hooks.js +138 -0
  70. package/src/commands/agents/index.js +1 -2
  71. package/src/commands/index.js +13 -16
  72. package/src/commands/project/doctor.js +100 -14
  73. package/src/commands/project/index.js +7 -10
  74. package/src/commands/project/init.js +398 -555
  75. package/src/commands/project/install-plugin-cmd.js +28 -0
  76. package/src/commands/project/setup-infra-cmd.js +12 -0
  77. package/src/commands/project/tutorial.js +115 -0
  78. package/src/commands/project/update.js +22 -37
  79. package/src/commands/state/approve.js +213 -221
  80. package/src/commands/state/index.js +0 -1
  81. package/src/commands/state/state.js +337 -365
  82. package/src/commands/templates/index.js +0 -4
  83. package/src/commands/trust/trust.js +1 -93
  84. package/src/commands/utils/index.js +1 -5
  85. package/src/commands/validation/index.js +1 -5
  86. package/src/core/registry/command-registry.js +11 -285
  87. package/src/core/state/state-manager.js +5 -2
  88. package/src/lib/detectors/index.js +81 -87
  89. package/src/lib/detectors/structure-detector.js +275 -273
  90. package/src/lib/generators/recap-generator.js +232 -225
  91. package/src/lib/installers/mcp-installer.js +18 -3
  92. package/src/scripts/global-install.js +34 -0
  93. package/src/scripts/install-plugin.js +126 -0
  94. package/src/scripts/setup-infra.js +203 -0
  95. package/src/utils/agents-installer.js +10 -1
  96. package/src/utils/hooks-installer.js +70 -17
  97. package/CLAUDE.md +0 -77
  98. package/docs/claude-alignment-report.md +0 -137
  99. package/docs/examples/order-management/contracts.cs +0 -84
  100. package/docs/examples/order-management/proposal.md +0 -24
  101. package/docs/examples/order-management/spec.md +0 -162
  102. package/src/commands/feature/create-story.js +0 -362
  103. package/src/commands/feature/index.js +0 -6
  104. package/src/commands/feature/shard-spec.js +0 -225
  105. package/src/commands/feature/sprint-status.js +0 -250
  106. package/src/commands/generation/generate-onboarding.js +0 -169
  107. package/src/commands/generation/generate.js +0 -276
  108. package/src/commands/generation/index.js +0 -5
  109. package/src/commands/learning/capture-pattern.js +0 -121
  110. package/src/commands/learning/index.js +0 -5
  111. package/src/commands/learning/search-patterns.js +0 -126
  112. package/src/commands/mcp/mcp.js +0 -102
  113. package/src/commands/project/changes.js +0 -66
  114. package/src/commands/project/cost.js +0 -179
  115. package/src/commands/project/detect.js +0 -114
  116. package/src/commands/project/diff.js +0 -278
  117. package/src/commands/project/revert.js +0 -173
  118. package/src/commands/project/standards.js +0 -80
  119. package/src/commands/project/sync.js +0 -167
  120. package/src/commands/project/update-agents.js +0 -23
  121. package/src/commands/state/rollback-phase.js +0 -185
  122. package/src/commands/templates/template-customize.js +0 -87
  123. package/src/commands/templates/template-list.js +0 -114
  124. package/src/commands/templates/template-show.js +0 -129
  125. package/src/commands/templates/template-validate.js +0 -91
  126. package/src/commands/utils/troubleshoot.js +0 -222
  127. package/src/commands/validation/analyze-blazor-concurrency.js +0 -193
  128. package/src/commands/validation/lint-fluent.js +0 -352
  129. package/src/commands/validation/validate-blazor-state.js +0 -210
  130. package/src/commands/validation/validate-blazor.js +0 -156
  131. package/src/commands/validation/validate-css.js +0 -84
  132. package/src/lib/detectors/conversation-analyzer.js +0 -163
  133. package/src/lib/learning/index.js +0 -7
  134. package/src/lib/learning/learning-system.js +0 -520
  135. package/src/lib/troubleshooting/index.js +0 -8
  136. package/src/lib/troubleshooting/troubleshoot-grep.js +0 -198
  137. package/src/lib/troubleshooting/troubleshoot-index.js +0 -144
  138. package/src/llm/environment-detector.js +0 -43
@@ -1,221 +1,213 @@
1
- import { Command } from 'commander';
2
- import chalk from 'chalk';
3
- import { getFeature, setApprovalGate, getApprovalGate, getApprovalHistory } from '../../core/state/state-manager.js';
4
-
5
- /**
6
- * Approval Commands - Manage approval gates for MORPH workflow
7
- *
8
- * Commands:
9
- * - approve: Mark a gate as approved
10
- * - reject: Reject a gate with reason
11
- * - approval-status: Show approval status for all gates
12
- */
13
-
14
- const program = new Command();
15
-
16
- /**
17
- * Valid approval gate names
18
- */
19
- const VALID_GATES = ['proposal', 'uiux', 'design', 'tasks'];
20
-
21
- /**
22
- * Approve action function - Mark a gate as approved
23
- */
24
- export async function approveCommand(featureName, gateName, options = {}) {
25
- try {
26
- // Validate gate name
27
- if (!VALID_GATES.includes(gateName)) {
28
- console.error(chalk.red(`\n❌ Invalid gate: ${gateName}`));
29
- console.log(chalk.gray(`Valid gates: ${VALID_GATES.join(', ')}\n`));
30
- process.exit(1);
31
- }
32
-
33
- // Get feature state
34
- const feature = getFeature(featureName);
35
- if (!feature) {
36
- console.error(chalk.red(`\n❌ Feature not found: ${featureName}\n`));
37
- process.exit(1);
38
- }
39
-
40
- // Check if already approved
41
- const currentStatus = getApprovalGate(featureName, gateName);
42
- if (currentStatus?.approved) {
43
- console.log(chalk.yellow(`\n⚠️ Gate "${gateName}" is already approved`));
44
- console.log(chalk.gray(`Approved at: ${currentStatus.timestamp}`));
45
- console.log(chalk.gray(`Approved by: ${currentStatus.approvedBy || 'Unknown'}\n`));
46
- return;
47
- }
48
-
49
- // Set approval
50
- setApprovalGate(featureName, gateName, true, {
51
- approvedBy: options.approver || process.env.USER || process.env.USERNAME || 'user',
52
- approvedAt: new Date().toISOString(),
53
- notes: options.notes
54
- });
55
-
56
- console.log(chalk.green(`\n✅ Gate "${gateName}" approved for feature: ${featureName}`));
57
- console.log(chalk.gray(`Workflow can now proceed past ${gateName} phase\n`));
58
-
59
- } catch (error) {
60
- console.error(chalk.red(`\n❌ Error approving gate: ${error.message}\n`));
61
- process.exit(1);
62
- }
63
- }
64
-
65
- /**
66
- * Approve command - Mark a gate as approved
67
- */
68
- program
69
- .command('approve <feature> <gate>')
70
- .description('Approve a phase gate to allow workflow progression')
71
- .action(approveCommand);
72
-
73
- /**
74
- * Reject action function - Reject a gate with optional reason
75
- */
76
- export async function rejectCommand(featureName, gateName, reason, options = {}) {
77
- try {
78
- // Validate gate name
79
- if (!VALID_GATES.includes(gateName)) {
80
- console.error(chalk.red(`\n❌ Invalid gate: ${gateName}`));
81
- console.log(chalk.gray(`Valid gates: ${VALID_GATES.join(', ')}\n`));
82
- process.exit(1);
83
- }
84
-
85
- // Get feature state
86
- const feature = getFeature(featureName);
87
- if (!feature) {
88
- console.error(chalk.red(`\n❌ Feature not found: ${featureName}\n`));
89
- process.exit(1);
90
- }
91
-
92
- // Set rejection
93
- setApprovalGate(featureName, gateName, false, {
94
- rejectedBy: process.env.USER || process.env.USERNAME || 'user',
95
- rejectedAt: new Date().toISOString(),
96
- reason: reason || 'No reason provided'
97
- });
98
-
99
- console.log(chalk.red(`\n❌ Gate "${gateName}" rejected for feature: ${featureName}`));
100
- if (reason) {
101
- console.log(chalk.gray(`Reason: ${reason}`));
102
- }
103
- console.log(chalk.yellow(`\n⚠️ Address the concerns and request approval again\n`));
104
-
105
- } catch (error) {
106
- console.error(chalk.red(`\n❌ Error rejecting gate: ${error.message}\n`));
107
- process.exit(1);
108
- }
109
- }
110
-
111
- /**
112
- * Reject command - Reject a gate with optional reason
113
- */
114
- program
115
- .command('reject <feature> <gate> [reason]')
116
- .description('Reject a phase gate with optional reason')
117
- .action(rejectCommand);
118
-
119
- /**
120
- * Approval status action function - Show all gates and their status
121
- */
122
- export async function approvalStatusCommand(featureName, options = {}) {
123
- try {
124
- // Get feature state
125
- const feature = getFeature(featureName);
126
- if (!feature) {
127
- console.error(chalk.red(`\n❌ Feature not found: ${featureName}\n`));
128
- process.exit(1);
129
- }
130
-
131
- // JSON output
132
- if (options.json) {
133
- const status = {
134
- feature: featureName,
135
- phase: feature.phase,
136
- status: feature.status,
137
- gates: {}
138
- };
139
-
140
- for (const gateName of VALID_GATES) {
141
- status.gates[gateName] = getApprovalGate(featureName, gateName) || { approved: false };
142
- }
143
-
144
- console.log(JSON.stringify(status, null, 2));
145
- return;
146
- }
147
-
148
- console.log(chalk.bold(`\n📋 Approval Status for: ${featureName}`));
149
- console.log('━'.repeat(60));
150
-
151
- // Show current phase
152
- console.log(chalk.cyan(`\nCurrent Phase: ${feature.phase || 'unknown'}`));
153
- console.log(chalk.gray(`Feature Status: ${feature.status || 'unknown'}\n`));
154
-
155
- // Show each gate
156
- console.log(chalk.bold('Approval Gates:'));
157
-
158
- for (const gateName of VALID_GATES) {
159
- const gateStatus = getApprovalGate(featureName, gateName);
160
-
161
- if (!gateStatus) {
162
- console.log(` ${chalk.gray('○')} ${gateName}: ${chalk.gray('Not yet evaluated')}`);
163
- continue;
164
- }
165
-
166
- if (gateStatus.approved) {
167
- console.log(` ${chalk.green('')} ${gateName}: ${chalk.green('Approved')}`);
168
- if (gateStatus.timestamp) {
169
- console.log(chalk.gray(` Approved at: ${gateStatus.timestamp}`));
170
- }
171
- if (gateStatus.approvedBy) {
172
- console.log(chalk.gray(` Approved by: ${gateStatus.approvedBy}`));
173
- }
174
- } else {
175
- console.log(` ${chalk.red('✗')} ${gateName}: ${chalk.red('Rejected / Not Approved')}`);
176
- if (gateStatus.reason) {
177
- console.log(chalk.gray(` Reason: ${gateStatus.reason}`));
178
- }
179
- if (gateStatus.timestamp) {
180
- console.log(chalk.gray(` Rejected at: ${gateStatus.timestamp}`));
181
- }
182
- }
183
- }
184
-
185
- // Show approval history if available
186
- const history = getApprovalHistory(featureName);
187
- if (history && history.length > 0) {
188
- console.log(chalk.bold('\nApproval History:'));
189
- history.slice(-5).forEach(entry => {
190
- const status = entry.approved ? chalk.green('✓ Approved') : chalk.red('✗ Rejected');
191
- console.log(` ${status} ${entry.gate} - ${entry.timestamp}`);
192
- });
193
- }
194
-
195
- console.log('\n' + '━'.repeat(60) + '\n');
196
-
197
- } catch (error) {
198
- console.error(chalk.red(`\n❌ Error showing approval status: ${error.message}\n`));
199
- process.exit(1);
200
- }
201
- }
202
-
203
- /**
204
- * Approval status command - Show all gates and their status
205
- */
206
- program
207
- .command('approval-status <feature>')
208
- .alias('status')
209
- .description('Show approval status for all gates')
210
- .action(approvalStatusCommand);
211
-
212
- // Only parse if run directly (not imported as module)
213
- if (import.meta.url === `file://${process.argv[1]}`) {
214
- if (process.argv.length > 2) {
215
- program.parse(process.argv);
216
- } else {
217
- program.help();
218
- }
219
- }
220
-
221
- export default program;
1
+ import { Command } from 'commander';
2
+ import chalk from 'chalk';
3
+ import { getFeature, setApprovalGate, getApprovalGate, getApprovalHistory } from '../../core/state/state-manager.js';
4
+
5
+ /**
6
+ * Unapprove action function - Revoke a previously approved gate
7
+ */
8
+ export async function unapproveCommand(featureName, gateName, options = {}) {
9
+ try {
10
+ if (!VALID_GATES.includes(gateName)) {
11
+ console.error(chalk.red(`\n❌ Invalid gate: ${gateName}`));
12
+ console.log(chalk.gray(`Valid gates: ${VALID_GATES.join(', ')}\n`));
13
+ process.exit(1);
14
+ }
15
+
16
+ const feature = getFeature(featureName);
17
+ if (!feature) {
18
+ console.error(chalk.red(`\n❌ Feature not found: ${featureName}\n`));
19
+ process.exit(1);
20
+ }
21
+
22
+ const currentStatus = getApprovalGate(featureName, gateName);
23
+ if (!currentStatus?.approved) {
24
+ console.log(chalk.yellow(`\n⚠️ Gate "${gateName}" is not currently approved nothing to revoke\n`));
25
+ return;
26
+ }
27
+
28
+ setApprovalGate(featureName, gateName, false, {
29
+ revokedBy: options.revoker || process.env.USER || process.env.USERNAME || 'user',
30
+ revokedAt: new Date().toISOString(),
31
+ reason: options.reason
32
+ });
33
+
34
+ console.log(chalk.yellow(`\n↩️ Gate "${gateName}" approval revoked for feature: ${featureName}`));
35
+ console.log(chalk.gray(`Workflow is now blocked at the ${gateName} gate\n`));
36
+
37
+ } catch (error) {
38
+ console.error(chalk.red(`\n❌ Error revoking gate: ${error.message}\n`));
39
+ process.exit(1);
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Approval Commands - Manage approval gates for MORPH workflow
45
+ *
46
+ * Commands:
47
+ * - approve: Mark a gate as approved
48
+ * - unapprove: Revoke a gate approval
49
+ * - approval-status: Show approval status for all gates
50
+ */
51
+
52
+ const program = new Command();
53
+
54
+ /**
55
+ * Valid approval gate names
56
+ */
57
+ const VALID_GATES = ['proposal', 'uiux', 'design', 'tasks'];
58
+
59
+ /**
60
+ * Approve action function - Mark a gate as approved
61
+ */
62
+ export async function approveCommand(featureName, gateName, options = {}) {
63
+ try {
64
+ // Validate gate name
65
+ if (!VALID_GATES.includes(gateName)) {
66
+ console.error(chalk.red(`\n❌ Invalid gate: ${gateName}`));
67
+ console.log(chalk.gray(`Valid gates: ${VALID_GATES.join(', ')}\n`));
68
+ process.exit(1);
69
+ }
70
+
71
+ // Get feature state
72
+ const feature = getFeature(featureName);
73
+ if (!feature) {
74
+ console.error(chalk.red(`\n❌ Feature not found: ${featureName}\n`));
75
+ process.exit(1);
76
+ }
77
+
78
+ // Check if already approved
79
+ const currentStatus = getApprovalGate(featureName, gateName);
80
+ if (currentStatus?.approved) {
81
+ console.log(chalk.yellow(`\n⚠️ Gate "${gateName}" is already approved`));
82
+ console.log(chalk.gray(`Approved at: ${currentStatus.timestamp}`));
83
+ console.log(chalk.gray(`Approved by: ${currentStatus.approvedBy || 'Unknown'}\n`));
84
+ return;
85
+ }
86
+
87
+ // Set approval
88
+ setApprovalGate(featureName, gateName, true, {
89
+ approvedBy: options.approver || process.env.USER || process.env.USERNAME || 'user',
90
+ approvedAt: new Date().toISOString(),
91
+ notes: options.notes
92
+ });
93
+
94
+ console.log(chalk.green(`\n✅ Gate "${gateName}" approved for feature: ${featureName}`));
95
+ console.log(chalk.gray(`Workflow can now proceed past ${gateName} phase\n`));
96
+
97
+ } catch (error) {
98
+ console.error(chalk.red(`\n❌ Error approving gate: ${error.message}\n`));
99
+ process.exit(1);
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Approve command - Mark a gate as approved
105
+ */
106
+ program
107
+ .command('approve <feature> <gate>')
108
+ .description('Approve a phase gate to allow workflow progression')
109
+ .action(approveCommand);
110
+
111
+ /**
112
+ * Approval status action function - Show all gates and their status
113
+ */
114
+ export async function approvalStatusCommand(featureName, options = {}) {
115
+ try {
116
+ // Get feature state
117
+ const feature = getFeature(featureName);
118
+ if (!feature) {
119
+ console.error(chalk.red(`\n❌ Feature not found: ${featureName}\n`));
120
+ process.exit(1);
121
+ }
122
+
123
+ // JSON output
124
+ if (options.json) {
125
+ const status = {
126
+ feature: featureName,
127
+ phase: feature.phase,
128
+ status: feature.status,
129
+ gates: {}
130
+ };
131
+
132
+ for (const gateName of VALID_GATES) {
133
+ status.gates[gateName] = getApprovalGate(featureName, gateName) || { approved: false };
134
+ }
135
+
136
+ console.log(JSON.stringify(status, null, 2));
137
+ return;
138
+ }
139
+
140
+ console.log(chalk.bold(`\n📋 Approval Status for: ${featureName}`));
141
+ console.log('━'.repeat(60));
142
+
143
+ // Show current phase
144
+ console.log(chalk.cyan(`\nCurrent Phase: ${feature.phase || 'unknown'}`));
145
+ console.log(chalk.gray(`Feature Status: ${feature.status || 'unknown'}\n`));
146
+
147
+ // Show each gate
148
+ console.log(chalk.bold('Approval Gates:'));
149
+
150
+ for (const gateName of VALID_GATES) {
151
+ const gateStatus = getApprovalGate(featureName, gateName);
152
+
153
+ if (!gateStatus) {
154
+ console.log(` ${chalk.gray('○')} ${gateName}: ${chalk.gray('Not yet evaluated')}`);
155
+ continue;
156
+ }
157
+
158
+ if (gateStatus.approved) {
159
+ console.log(` ${chalk.green('✓')} ${gateName}: ${chalk.green('Approved')}`);
160
+ if (gateStatus.timestamp) {
161
+ console.log(chalk.gray(` Approved at: ${gateStatus.timestamp}`));
162
+ }
163
+ if (gateStatus.approvedBy) {
164
+ console.log(chalk.gray(` Approved by: ${gateStatus.approvedBy}`));
165
+ }
166
+ } else {
167
+ console.log(` ${chalk.red('')} ${gateName}: ${chalk.red('Rejected / Not Approved')}`);
168
+ if (gateStatus.reason) {
169
+ console.log(chalk.gray(` Reason: ${gateStatus.reason}`));
170
+ }
171
+ if (gateStatus.timestamp) {
172
+ console.log(chalk.gray(` Rejected at: ${gateStatus.timestamp}`));
173
+ }
174
+ }
175
+ }
176
+
177
+ // Show approval history if available
178
+ const history = getApprovalHistory(featureName);
179
+ if (history && history.length > 0) {
180
+ console.log(chalk.bold('\nApproval History:'));
181
+ history.slice(-5).forEach(entry => {
182
+ const status = entry.approved ? chalk.green('✓ Approved') : chalk.red('✗ Rejected');
183
+ console.log(` ${status} ${entry.gate} - ${entry.timestamp}`);
184
+ });
185
+ }
186
+
187
+ console.log('\n' + '━'.repeat(60) + '\n');
188
+
189
+ } catch (error) {
190
+ console.error(chalk.red(`\n❌ Error showing approval status: ${error.message}\n`));
191
+ process.exit(1);
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Approval status command - Show all gates and their status
197
+ */
198
+ program
199
+ .command('approval-status <feature>')
200
+ .alias('status')
201
+ .description('Show approval status for all gates')
202
+ .action(approvalStatusCommand);
203
+
204
+ // Only parse if run directly (not imported as module)
205
+ if (import.meta.url === `file://${process.argv[1]}`) {
206
+ if (process.argv.length > 2) {
207
+ program.parse(process.argv);
208
+ } else {
209
+ program.help();
210
+ }
211
+ }
212
+
213
+ export default program;
@@ -3,6 +3,5 @@
3
3
  */
4
4
  export { stateCommand } from './state.js';
5
5
  export { advancePhaseCommand } from './advance-phase.js';
6
- export { rollbackPhaseCommand } from './rollback-phase.js';
7
6
  export { approveCommand, rejectCommand, approvalStatusCommand } from './approve.js';
8
7
  export { validatePhaseCommand } from './validate-phase.js';