@clawplays/ospec-cli 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 (191) hide show
  1. package/.ospec/templates/hooks/post-merge +8 -0
  2. package/.ospec/templates/hooks/pre-commit +8 -0
  3. package/LICENSE +21 -0
  4. package/README.md +549 -0
  5. package/README.zh-CN.md +549 -0
  6. package/assets/for-ai/en-US/ai-guide.md +98 -0
  7. package/assets/for-ai/en-US/execution-protocol.md +64 -0
  8. package/assets/for-ai/zh-CN/ai-guide.md +102 -0
  9. package/assets/for-ai/zh-CN/execution-protocol.md +68 -0
  10. package/assets/git-hooks/post-merge +12 -0
  11. package/assets/git-hooks/pre-commit +12 -0
  12. package/assets/global-skills/claude/ospec-change/SKILL.md +116 -0
  13. package/assets/global-skills/codex/ospec-change/SKILL.md +117 -0
  14. package/assets/global-skills/codex/ospec-change/agents/openai.yaml +7 -0
  15. package/assets/global-skills/codex/ospec-change/skill.yaml +19 -0
  16. package/assets/project-conventions/en-US/development-guide.md +32 -0
  17. package/assets/project-conventions/en-US/naming-conventions.md +51 -0
  18. package/assets/project-conventions/en-US/skill-conventions.md +40 -0
  19. package/assets/project-conventions/en-US/workflow-conventions.md +70 -0
  20. package/assets/project-conventions/zh-CN/development-guide.md +32 -0
  21. package/assets/project-conventions/zh-CN/naming-conventions.md +51 -0
  22. package/assets/project-conventions/zh-CN/skill-conventions.md +40 -0
  23. package/assets/project-conventions/zh-CN/workflow-conventions.md +74 -0
  24. package/dist/adapters/codex-stitch-adapter.js +420 -0
  25. package/dist/adapters/gemini-stitch-adapter.js +408 -0
  26. package/dist/adapters/playwright-checkpoint-adapter.js +2260 -0
  27. package/dist/advanced/BatchOperations.d.ts +36 -0
  28. package/dist/advanced/BatchOperations.js +159 -0
  29. package/dist/advanced/CachingLayer.d.ts +66 -0
  30. package/dist/advanced/CachingLayer.js +136 -0
  31. package/dist/advanced/FeatureUpdater.d.ts +46 -0
  32. package/dist/advanced/FeatureUpdater.js +151 -0
  33. package/dist/advanced/PerformanceMonitor.d.ts +52 -0
  34. package/dist/advanced/PerformanceMonitor.js +129 -0
  35. package/dist/advanced/StatePersistence.d.ts +61 -0
  36. package/dist/advanced/StatePersistence.js +168 -0
  37. package/dist/advanced/index.d.ts +14 -0
  38. package/dist/advanced/index.js +22 -0
  39. package/dist/cli/commands/config.d.ts +5 -0
  40. package/dist/cli/commands/config.js +6 -0
  41. package/dist/cli/commands/feature.d.ts +5 -0
  42. package/dist/cli/commands/feature.js +6 -0
  43. package/dist/cli/commands/index.d.ts +5 -0
  44. package/dist/cli/commands/index.js +6 -0
  45. package/dist/cli/commands/project.d.ts +5 -0
  46. package/dist/cli/commands/project.js +6 -0
  47. package/dist/cli/commands/validate.d.ts +5 -0
  48. package/dist/cli/commands/validate.js +6 -0
  49. package/dist/cli/index.d.ts +5 -0
  50. package/dist/cli/index.js +6 -0
  51. package/dist/cli.d.ts +3 -0
  52. package/dist/cli.js +1007 -0
  53. package/dist/commands/ArchiveCommand.d.ts +14 -0
  54. package/dist/commands/ArchiveCommand.js +241 -0
  55. package/dist/commands/BaseCommand.d.ts +33 -0
  56. package/dist/commands/BaseCommand.js +46 -0
  57. package/dist/commands/BatchCommand.d.ts +5 -0
  58. package/dist/commands/BatchCommand.js +42 -0
  59. package/dist/commands/ChangesCommand.d.ts +3 -0
  60. package/dist/commands/ChangesCommand.js +71 -0
  61. package/dist/commands/DocsCommand.d.ts +5 -0
  62. package/dist/commands/DocsCommand.js +118 -0
  63. package/dist/commands/FinalizeCommand.d.ts +3 -0
  64. package/dist/commands/FinalizeCommand.js +24 -0
  65. package/dist/commands/IndexCommand.d.ts +5 -0
  66. package/dist/commands/IndexCommand.js +57 -0
  67. package/dist/commands/InitCommand.d.ts +5 -0
  68. package/dist/commands/InitCommand.js +65 -0
  69. package/dist/commands/NewCommand.d.ts +11 -0
  70. package/dist/commands/NewCommand.js +262 -0
  71. package/dist/commands/PluginsCommand.d.ts +58 -0
  72. package/dist/commands/PluginsCommand.js +2491 -0
  73. package/dist/commands/ProgressCommand.d.ts +5 -0
  74. package/dist/commands/ProgressCommand.js +103 -0
  75. package/dist/commands/QueueCommand.d.ts +10 -0
  76. package/dist/commands/QueueCommand.js +147 -0
  77. package/dist/commands/RunCommand.d.ts +13 -0
  78. package/dist/commands/RunCommand.js +200 -0
  79. package/dist/commands/SkillCommand.d.ts +31 -0
  80. package/dist/commands/SkillCommand.js +1216 -0
  81. package/dist/commands/SkillsCommand.d.ts +5 -0
  82. package/dist/commands/SkillsCommand.js +68 -0
  83. package/dist/commands/StatusCommand.d.ts +6 -0
  84. package/dist/commands/StatusCommand.js +140 -0
  85. package/dist/commands/UpdateCommand.d.ts +8 -0
  86. package/dist/commands/UpdateCommand.js +251 -0
  87. package/dist/commands/VerifyCommand.d.ts +5 -0
  88. package/dist/commands/VerifyCommand.js +278 -0
  89. package/dist/commands/WorkflowCommand.d.ts +12 -0
  90. package/dist/commands/WorkflowCommand.js +150 -0
  91. package/dist/commands/index.d.ts +43 -0
  92. package/dist/commands/index.js +85 -0
  93. package/dist/core/constants.d.ts +41 -0
  94. package/dist/core/constants.js +73 -0
  95. package/dist/core/errors.d.ts +36 -0
  96. package/dist/core/errors.js +72 -0
  97. package/dist/core/index.d.ts +7 -0
  98. package/dist/core/index.js +23 -0
  99. package/dist/core/types.d.ts +369 -0
  100. package/dist/core/types.js +3 -0
  101. package/dist/index.d.ts +11 -0
  102. package/dist/index.js +27 -0
  103. package/dist/presets/ProjectPresets.d.ts +41 -0
  104. package/dist/presets/ProjectPresets.js +190 -0
  105. package/dist/scaffolds/ProjectScaffoldPresets.d.ts +20 -0
  106. package/dist/scaffolds/ProjectScaffoldPresets.js +151 -0
  107. package/dist/services/ConfigManager.d.ts +14 -0
  108. package/dist/services/ConfigManager.js +386 -0
  109. package/dist/services/FeatureManager.d.ts +5 -0
  110. package/dist/services/FeatureManager.js +6 -0
  111. package/dist/services/FileService.d.ts +21 -0
  112. package/dist/services/FileService.js +152 -0
  113. package/dist/services/IndexBuilder.d.ts +12 -0
  114. package/dist/services/IndexBuilder.js +130 -0
  115. package/dist/services/Logger.d.ts +20 -0
  116. package/dist/services/Logger.js +48 -0
  117. package/dist/services/ProjectAssetRegistry.d.ts +12 -0
  118. package/dist/services/ProjectAssetRegistry.js +96 -0
  119. package/dist/services/ProjectAssetService.d.ts +49 -0
  120. package/dist/services/ProjectAssetService.js +223 -0
  121. package/dist/services/ProjectScaffoldCommandService.d.ts +73 -0
  122. package/dist/services/ProjectScaffoldCommandService.js +159 -0
  123. package/dist/services/ProjectScaffoldService.d.ts +44 -0
  124. package/dist/services/ProjectScaffoldService.js +507 -0
  125. package/dist/services/ProjectService.d.ts +209 -0
  126. package/dist/services/ProjectService.js +13239 -0
  127. package/dist/services/QueueService.d.ts +17 -0
  128. package/dist/services/QueueService.js +142 -0
  129. package/dist/services/RunService.d.ts +40 -0
  130. package/dist/services/RunService.js +420 -0
  131. package/dist/services/SkillParser.d.ts +30 -0
  132. package/dist/services/SkillParser.js +88 -0
  133. package/dist/services/StateManager.d.ts +16 -0
  134. package/dist/services/StateManager.js +127 -0
  135. package/dist/services/TemplateEngine.d.ts +43 -0
  136. package/dist/services/TemplateEngine.js +119 -0
  137. package/dist/services/TemplateGenerator.d.ts +40 -0
  138. package/dist/services/TemplateGenerator.js +273 -0
  139. package/dist/services/ValidationService.d.ts +19 -0
  140. package/dist/services/ValidationService.js +44 -0
  141. package/dist/services/Validator.d.ts +5 -0
  142. package/dist/services/Validator.js +6 -0
  143. package/dist/services/index.d.ts +52 -0
  144. package/dist/services/index.js +91 -0
  145. package/dist/services/templates/ExecutionTemplateBuilder.d.ts +12 -0
  146. package/dist/services/templates/ExecutionTemplateBuilder.js +300 -0
  147. package/dist/services/templates/ProjectTemplateBuilder.d.ts +38 -0
  148. package/dist/services/templates/ProjectTemplateBuilder.js +1897 -0
  149. package/dist/services/templates/TemplateBuilderBase.d.ts +19 -0
  150. package/dist/services/templates/TemplateBuilderBase.js +60 -0
  151. package/dist/services/templates/TemplateInputFactory.d.ts +16 -0
  152. package/dist/services/templates/TemplateInputFactory.js +298 -0
  153. package/dist/services/templates/templateTypes.d.ts +90 -0
  154. package/dist/services/templates/templateTypes.js +3 -0
  155. package/dist/tools/build-index.js +632 -0
  156. package/dist/utils/DateUtils.d.ts +18 -0
  157. package/dist/utils/DateUtils.js +40 -0
  158. package/dist/utils/PathUtils.d.ts +9 -0
  159. package/dist/utils/PathUtils.js +66 -0
  160. package/dist/utils/StringUtils.d.ts +26 -0
  161. package/dist/utils/StringUtils.js +47 -0
  162. package/dist/utils/helpers.d.ts +5 -0
  163. package/dist/utils/helpers.js +6 -0
  164. package/dist/utils/index.d.ts +7 -0
  165. package/dist/utils/index.js +23 -0
  166. package/dist/utils/logger.d.ts +5 -0
  167. package/dist/utils/logger.js +6 -0
  168. package/dist/utils/path.d.ts +5 -0
  169. package/dist/utils/path.js +6 -0
  170. package/dist/utils/subcommandHelp.d.ts +11 -0
  171. package/dist/utils/subcommandHelp.js +119 -0
  172. package/dist/workflow/ArchiveGate.d.ts +30 -0
  173. package/dist/workflow/ArchiveGate.js +93 -0
  174. package/dist/workflow/ConfigurableWorkflow.d.ts +89 -0
  175. package/dist/workflow/ConfigurableWorkflow.js +186 -0
  176. package/dist/workflow/HookSystem.d.ts +38 -0
  177. package/dist/workflow/HookSystem.js +66 -0
  178. package/dist/workflow/IndexRegenerator.d.ts +49 -0
  179. package/dist/workflow/IndexRegenerator.js +147 -0
  180. package/dist/workflow/PluginWorkflowComposer.d.ts +138 -0
  181. package/dist/workflow/PluginWorkflowComposer.js +239 -0
  182. package/dist/workflow/SkillUpdateEngine.d.ts +26 -0
  183. package/dist/workflow/SkillUpdateEngine.js +113 -0
  184. package/dist/workflow/VerificationSystem.d.ts +24 -0
  185. package/dist/workflow/VerificationSystem.js +116 -0
  186. package/dist/workflow/WorkflowEngine.d.ts +15 -0
  187. package/dist/workflow/WorkflowEngine.js +57 -0
  188. package/dist/workflow/index.d.ts +19 -0
  189. package/dist/workflow/index.js +32 -0
  190. package/package.json +78 -0
  191. package/scripts/postinstall.js +43 -0
@@ -0,0 +1,14 @@
1
+ import { BaseCommand } from './BaseCommand';
2
+ interface ArchiveCommandOptions {
3
+ checkOnly?: boolean;
4
+ }
5
+ export declare class ArchiveCommand extends BaseCommand {
6
+ execute(featurePath?: string, options?: ArchiveCommandOptions): Promise<void>;
7
+ run(featurePath?: string, options?: ArchiveCommandOptions): Promise<string | void>;
8
+ private performArchive;
9
+ private updateProposalStatus;
10
+ private resolveArchiveDirName;
11
+ private toRelativePath;
12
+ }
13
+ export {};
14
+ //# sourceMappingURL=ArchiveCommand.d.ts.map
@@ -0,0 +1,241 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.ArchiveCommand = void 0;
40
+ const path = __importStar(require("path"));
41
+ const gray_matter_1 = __importDefault(require("gray-matter"));
42
+ const constants_1 = require("../core/constants");
43
+ const services_1 = require("../services");
44
+ const ArchiveGate_1 = require("../workflow/ArchiveGate");
45
+ const PluginWorkflowComposer_1 = require("../workflow/PluginWorkflowComposer");
46
+ const BaseCommand_1 = require("./BaseCommand");
47
+ class ArchiveCommand extends BaseCommand_1.BaseCommand {
48
+ async execute(featurePath, options = {}) {
49
+ await this.run(featurePath, options);
50
+ }
51
+ async run(featurePath, options = {}) {
52
+ try {
53
+ const targetPath = path.resolve(featurePath || process.cwd());
54
+ const checkOnly = options.checkOnly === true;
55
+ this.logger.info(`${checkOnly ? 'Checking archive readiness' : 'Archiving change'} at ${targetPath}`);
56
+ const statePath = path.join(targetPath, constants_1.FILE_NAMES.STATE);
57
+ const proposalPath = path.join(targetPath, constants_1.FILE_NAMES.PROPOSAL);
58
+ const tasksPath = path.join(targetPath, constants_1.FILE_NAMES.TASKS);
59
+ const verificationPath = path.join(targetPath, constants_1.FILE_NAMES.VERIFICATION);
60
+ const projectRoot = path.resolve(targetPath, '..', '..', '..');
61
+ const expectedParent = path.join(projectRoot, constants_1.DIR_NAMES.CHANGES, constants_1.DIR_NAMES.ACTIVE);
62
+ if (path.dirname(targetPath) !== expectedParent) {
63
+ throw new Error('Archive target must be a change directory under changes/active.');
64
+ }
65
+ if (!(await services_1.services.fileService.exists(statePath))) {
66
+ throw new Error('Change state file not found.');
67
+ }
68
+ const featureState = await services_1.services.fileService.readJSON(statePath);
69
+ const config = await services_1.services.configManager.loadConfig(projectRoot);
70
+ const workflow = new PluginWorkflowComposer_1.PluginWorkflowComposer(config);
71
+ const proposal = (0, gray_matter_1.default)(await services_1.services.fileService.readFile(proposalPath));
72
+ const tasks = (0, gray_matter_1.default)(await services_1.services.fileService.readFile(tasksPath));
73
+ const verification = (0, gray_matter_1.default)(await services_1.services.fileService.readFile(verificationPath));
74
+ const flags = Array.isArray(proposal.data.flags) ? proposal.data.flags : [];
75
+ const activatedSteps = workflow.getActivatedSteps(flags);
76
+ const tasksOptionalSteps = Array.isArray(tasks.data.optional_steps)
77
+ ? tasks.data.optional_steps
78
+ : [];
79
+ const verificationOptionalSteps = Array.isArray(verification.data.optional_steps)
80
+ ? verification.data.optional_steps
81
+ : [];
82
+ const passedOptionalSteps = Array.isArray(verification.data.passed_optional_steps)
83
+ ? verification.data.passed_optional_steps
84
+ : [];
85
+ const archiveConfig = config.workflow?.archive_gate || {
86
+ require_verification: true,
87
+ require_skill_update: true,
88
+ require_index_regenerated: true,
89
+ require_optional_steps_passed: true,
90
+ };
91
+ const result = await ArchiveGate_1.archiveGate.checkArchiveReadiness(featureState, archiveConfig, {
92
+ activatedSteps,
93
+ tasksOptionalSteps,
94
+ verificationOptionalSteps,
95
+ passedOptionalSteps,
96
+ tasksComplete: !/- \[ \]/.test(tasks.content),
97
+ verificationComplete: !/- \[ \]/.test(verification.content),
98
+ });
99
+ if (activatedSteps.includes('stitch_design_review')) {
100
+ const approvalPath = path.join(targetPath, 'artifacts', 'stitch', 'approval.json');
101
+ const approvalExists = await services_1.services.fileService.exists(approvalPath);
102
+ if (!approvalExists) {
103
+ result.blockers.push('artifacts/stitch/approval.json is required before archiving');
104
+ }
105
+ else {
106
+ const approval = await services_1.services.fileService.readJSON(approvalPath);
107
+ const approvalStatus = typeof approval.status === 'string' ? approval.status : 'pending';
108
+ const hasPreviewUrl = typeof approval.preview_url === 'string' && approval.preview_url.trim().length > 0;
109
+ const hasSubmittedAt = typeof approval.submitted_at === 'string' && approval.submitted_at.trim().length > 0;
110
+ if (approval.step !== 'stitch_design_review') {
111
+ result.blockers.push('Stitch approval artifact step must be stitch_design_review');
112
+ }
113
+ if (!hasPreviewUrl) {
114
+ result.blockers.push('Stitch preview URL must be recorded before archiving');
115
+ }
116
+ if (!hasSubmittedAt) {
117
+ result.blockers.push('Stitch submission timestamp must be recorded before archiving');
118
+ }
119
+ if (approvalStatus !== 'approved') {
120
+ result.blockers.push(`Stitch design review must be approved before archiving (current: ${approvalStatus})`);
121
+ }
122
+ }
123
+ }
124
+ const activeCheckpointSteps = activatedSteps.filter(step => step === 'checkpoint_ui_review' || step === 'checkpoint_flow_check');
125
+ if (activeCheckpointSteps.length > 0) {
126
+ const checkpointDir = path.join(targetPath, 'artifacts', 'checkpoint');
127
+ const gatePath = path.join(checkpointDir, 'gate.json');
128
+ const resultPath = path.join(checkpointDir, 'result.json');
129
+ const summaryPath = path.join(checkpointDir, 'summary.md');
130
+ const gateExists = await services_1.services.fileService.exists(gatePath);
131
+ if (!gateExists) {
132
+ result.blockers.push('artifacts/checkpoint/gate.json is required before archiving');
133
+ }
134
+ else {
135
+ const gate = await services_1.services.fileService.readJSON(gatePath);
136
+ if (gate.plugin !== 'checkpoint') {
137
+ result.blockers.push('Checkpoint gate artifact plugin must be checkpoint');
138
+ }
139
+ if (gate.status !== 'passed') {
140
+ result.blockers.push(`Checkpoint gate must be passed before archiving (current: ${gate.status || 'missing'})`);
141
+ }
142
+ for (const stepName of activeCheckpointSteps) {
143
+ const stepStatus = gate.steps?.[stepName]?.status || 'missing';
144
+ if (stepStatus !== 'passed') {
145
+ result.blockers.push(`Checkpoint step ${stepName} must be passed before archiving (current: ${stepStatus})`);
146
+ }
147
+ }
148
+ }
149
+ const resultExists = await services_1.services.fileService.exists(resultPath);
150
+ const summaryExists = await services_1.services.fileService.exists(summaryPath);
151
+ if (!resultExists && !summaryExists) {
152
+ result.blockers.push('Checkpoint result.json or summary.md is required before archiving');
153
+ }
154
+ }
155
+ result.canArchive = result.blockers.length === 0;
156
+ console.log('\nArchive Gate Check:');
157
+ console.log('===================\n');
158
+ for (const check of result.checks) {
159
+ const icon = check.passed ? 'PASS' : 'FAIL';
160
+ console.log(`${icon} ${check.name}`);
161
+ console.log(` ${check.message}\n`);
162
+ }
163
+ if (result.blockers.length > 0) {
164
+ console.log('Blockers:');
165
+ result.blockers.forEach(blocker => {
166
+ console.log(` - ${blocker}`);
167
+ });
168
+ console.log();
169
+ }
170
+ if (result.warnings.length > 0) {
171
+ console.log('Warnings:');
172
+ result.warnings.forEach(warning => {
173
+ console.log(` - ${warning}`);
174
+ });
175
+ console.log();
176
+ }
177
+ console.log('='.repeat(21) + '\n');
178
+ if (result.canArchive) {
179
+ if (checkOnly) {
180
+ this.success('Change is ready to archive');
181
+ return;
182
+ }
183
+ const archivePath = await this.performArchive(targetPath, projectRoot, featureState);
184
+ this.success(`Change archived to ${archivePath}`);
185
+ return archivePath;
186
+ }
187
+ else {
188
+ this.error('Change cannot be archived. Please resolve blockers.');
189
+ process.exit(1);
190
+ }
191
+ }
192
+ catch (error) {
193
+ this.error(`Archive check failed: ${error}`);
194
+ throw error;
195
+ }
196
+ }
197
+ async performArchive(targetPath, projectRoot, featureState) {
198
+ const archivedRoot = path.join(projectRoot, constants_1.DIR_NAMES.CHANGES, constants_1.DIR_NAMES.ARCHIVED);
199
+ await services_1.services.fileService.ensureDir(archivedRoot);
200
+ const archiveDirName = await this.resolveArchiveDirName(archivedRoot, featureState.feature);
201
+ const archivePath = path.join(archivedRoot, archiveDirName);
202
+ const nextState = {
203
+ ...featureState,
204
+ status: 'archived',
205
+ current_step: 'archived',
206
+ completed: Array.from(new Set([...featureState.completed, 'archived'])).sort((a, b) => a.localeCompare(b)),
207
+ pending: featureState.pending.filter(step => step !== 'archived'),
208
+ blocked_by: [],
209
+ };
210
+ await services_1.services.fileService.move(targetPath, archivePath);
211
+ await services_1.services.stateManager.writeState(archivePath, nextState);
212
+ await this.updateProposalStatus(archivePath, 'archived');
213
+ await services_1.services.projectService.rebuildIndex(projectRoot);
214
+ return this.toRelativePath(projectRoot, archivePath);
215
+ }
216
+ async updateProposalStatus(targetPath, status) {
217
+ const proposalPath = path.join(targetPath, constants_1.FILE_NAMES.PROPOSAL);
218
+ if (!(await services_1.services.fileService.exists(proposalPath))) {
219
+ return;
220
+ }
221
+ const proposal = (0, gray_matter_1.default)(await services_1.services.fileService.readFile(proposalPath));
222
+ proposal.data.status = status;
223
+ await services_1.services.fileService.writeFile(proposalPath, gray_matter_1.default.stringify(proposal.content, proposal.data));
224
+ }
225
+ async resolveArchiveDirName(archivedRoot, featureName) {
226
+ const datePrefix = new Date().toISOString().slice(0, 10);
227
+ const baseName = `${datePrefix}-${featureName}`;
228
+ let candidate = baseName;
229
+ let index = 2;
230
+ while (await services_1.services.fileService.exists(path.join(archivedRoot, candidate))) {
231
+ candidate = `${baseName}-${index}`;
232
+ index += 1;
233
+ }
234
+ return candidate;
235
+ }
236
+ toRelativePath(rootDir, targetPath) {
237
+ return path.relative(rootDir, targetPath).replace(/\\/g, '/');
238
+ }
239
+ }
240
+ exports.ArchiveCommand = ArchiveCommand;
241
+ //# sourceMappingURL=ArchiveCommand.js.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * 命令基类
3
+ */
4
+ import { Logger } from '../services/Logger';
5
+ export declare abstract class BaseCommand {
6
+ protected logger: Logger;
7
+ constructor();
8
+ /**
9
+ * 执行命令
10
+ */
11
+ abstract execute(...args: any[]): Promise<void>;
12
+ /**
13
+ * 验证命令参数
14
+ */
15
+ protected validateArgs(args: any[], requiredCount: number): void;
16
+ /**
17
+ * 打印成功信息
18
+ */
19
+ protected success(message: string): void;
20
+ /**
21
+ * 打印信息
22
+ */
23
+ protected info(message: string): void;
24
+ /**
25
+ * 打印错误信息
26
+ */
27
+ protected error(message: string): void;
28
+ /**
29
+ * 打印警告信息
30
+ */
31
+ protected warn(message: string): void;
32
+ }
33
+ //# sourceMappingURL=BaseCommand.d.ts.map
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ /**
3
+ * 命令基类
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BaseCommand = void 0;
7
+ const services_1 = require("../services");
8
+ class BaseCommand {
9
+ constructor() {
10
+ this.logger = services_1.services.logger;
11
+ }
12
+ /**
13
+ * 验证命令参数
14
+ */
15
+ validateArgs(args, requiredCount) {
16
+ if (args.length < requiredCount) {
17
+ throw new Error(`Invalid arguments. Expected at least ${requiredCount} arguments.`);
18
+ }
19
+ }
20
+ /**
21
+ * 打印成功信息
22
+ */
23
+ success(message) {
24
+ console.log(`✓ ${message}`);
25
+ }
26
+ /**
27
+ * 打印信息
28
+ */
29
+ info(message) {
30
+ console.log(message);
31
+ }
32
+ /**
33
+ * 打印错误信息
34
+ */
35
+ error(message) {
36
+ console.error(`✗ ${message}`);
37
+ }
38
+ /**
39
+ * 打印警告信息
40
+ */
41
+ warn(message) {
42
+ console.warn(`⚠ ${message}`);
43
+ }
44
+ }
45
+ exports.BaseCommand = BaseCommand;
46
+ //# sourceMappingURL=BaseCommand.js.map
@@ -0,0 +1,5 @@
1
+ import { BaseCommand } from './BaseCommand';
2
+ export declare class BatchCommand extends BaseCommand {
3
+ execute(action: string, projectPath?: string): Promise<void>;
4
+ }
5
+ //# sourceMappingURL=BatchCommand.d.ts.map
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BatchCommand = void 0;
4
+ const advanced_1 = require("../advanced");
5
+ const subcommandHelp_1 = require("../utils/subcommandHelp");
6
+ const BaseCommand_1 = require("./BaseCommand");
7
+ class BatchCommand extends BaseCommand_1.BaseCommand {
8
+ async execute(action, projectPath) {
9
+ try {
10
+ if ((0, subcommandHelp_1.isHelpAction)(action)) {
11
+ this.info((0, subcommandHelp_1.getBatchHelpText)());
12
+ return;
13
+ }
14
+ const targetPath = projectPath || process.cwd();
15
+ switch (action) {
16
+ case 'export': {
17
+ const result = await advanced_1.batchOperations.exportFeatures(targetPath, {});
18
+ console.log(`\nExported ${result.count} features\n`);
19
+ break;
20
+ }
21
+ case 'stats': {
22
+ const stats = await advanced_1.batchOperations.getStatistics(targetPath);
23
+ console.log('\nStatistics:');
24
+ console.log(`Total: ${stats.total}\n`);
25
+ for (const [status, count] of Object.entries(stats.byStatus)) {
26
+ console.log(`${status}: ${count}`);
27
+ }
28
+ console.log();
29
+ break;
30
+ }
31
+ default:
32
+ this.info((0, subcommandHelp_1.getBatchHelpText)());
33
+ }
34
+ }
35
+ catch (error) {
36
+ this.error(`Batch operation failed: ${error}`);
37
+ throw error;
38
+ }
39
+ }
40
+ }
41
+ exports.BatchCommand = BatchCommand;
42
+ //# sourceMappingURL=BatchCommand.js.map
@@ -0,0 +1,3 @@
1
+ export declare class ChangesCommand {
2
+ execute(action?: string, projectPath?: string): Promise<void>;
3
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChangesCommand = void 0;
4
+ const services_1 = require("../services");
5
+ const BaseCommand_1 = require("./BaseCommand");
6
+ class ChangesCommand extends BaseCommand_1.BaseCommand {
7
+ async execute(action = 'status', projectPath) {
8
+ try {
9
+ const targetPath = projectPath || process.cwd();
10
+ switch (action) {
11
+ case 'status':
12
+ default: {
13
+ const [report, queuedChanges] = await Promise.all([
14
+ services_1.services.projectService.getActiveChangeStatusReport(targetPath),
15
+ services_1.services.queueService.getQueuedChanges(targetPath),
16
+ ]);
17
+ console.log('');
18
+ console.log('Active Changes');
19
+ console.log('==============');
20
+ console.log('');
21
+ console.log(`Total: ${report.totalActiveChanges}`);
22
+ console.log(`Queued: ${queuedChanges.length}`);
23
+ console.log(`PASS ${report.totals.pass} | WARN ${report.totals.warn} | FAIL ${report.totals.fail}`);
24
+ console.log('');
25
+ if (report.changes.length === 0) {
26
+ console.log('No active changes.');
27
+ if (queuedChanges.length > 0) {
28
+ console.log('Queued changes are waiting.');
29
+ }
30
+ console.log('');
31
+ return;
32
+ }
33
+ for (const change of report.changes) {
34
+ console.log(`${change.summaryStatus.toUpperCase()} ${change.name} [${change.status}] ${change.progress}%`);
35
+ console.log(` Path: ${change.path}`);
36
+ console.log(` Step: ${change.currentStep}`);
37
+ if (change.flags.length > 0) {
38
+ console.log(` Flags: ${change.flags.join(', ')}`);
39
+ }
40
+ const issues = change.checks.filter(check => check.status !== 'pass');
41
+ if (issues.length === 0) {
42
+ console.log(' Checks: all pass');
43
+ }
44
+ else {
45
+ for (const issue of issues.slice(0, 5)) {
46
+ console.log(` ${issue.status.toUpperCase()} ${issue.name}: ${issue.message}`);
47
+ }
48
+ }
49
+ console.log('');
50
+ }
51
+ if (queuedChanges.length > 0) {
52
+ console.log('Queued Changes');
53
+ console.log('--------------');
54
+ queuedChanges.forEach(change => {
55
+ console.log(`QUEUED ${change.name} [${change.status}]`);
56
+ console.log(` Path: ${change.path}`);
57
+ console.log(` Step: ${change.currentStep}`);
58
+ });
59
+ console.log('');
60
+ }
61
+ }
62
+ }
63
+ }
64
+ catch (error) {
65
+ this.error(`Changes command failed: ${error}`);
66
+ throw error;
67
+ }
68
+ }
69
+ }
70
+ exports.ChangesCommand = ChangesCommand;
71
+ //# sourceMappingURL=ChangesCommand.js.map
@@ -0,0 +1,5 @@
1
+ import { BaseCommand } from './BaseCommand';
2
+ export declare class DocsCommand extends BaseCommand {
3
+ execute(action?: string, projectPath?: string): Promise<void>;
4
+ }
5
+ //# sourceMappingURL=DocsCommand.d.ts.map
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DocsCommand = void 0;
4
+ const services_1 = require("../services");
5
+ const subcommandHelp_1 = require("../utils/subcommandHelp");
6
+ const BaseCommand_1 = require("./BaseCommand");
7
+ class DocsCommand extends BaseCommand_1.BaseCommand {
8
+ async execute(action = 'status', projectPath) {
9
+ try {
10
+ if ((0, subcommandHelp_1.isHelpAction)(action)) {
11
+ this.info((0, subcommandHelp_1.getDocsHelpText)());
12
+ return;
13
+ }
14
+ const targetPath = projectPath || process.cwd();
15
+ switch (action) {
16
+ case 'generate': {
17
+ const structure = await services_1.services.projectService.detectProjectStructure(targetPath);
18
+ if (!structure.initialized) {
19
+ throw new Error('Project is not initialized. Run "ospec init" first.');
20
+ }
21
+ const result = await services_1.services.projectService.generateProjectKnowledge(targetPath);
22
+ console.log('\nProject Knowledge Generated');
23
+ console.log('=========================\n');
24
+ console.log(`Project: ${result.projectName}`);
25
+ console.log(`Mode: ${result.mode}`);
26
+ console.log(`Created files: ${result.createdFiles.length}`);
27
+ console.log(`Refreshed files: ${result.refreshedFiles.length}`);
28
+ console.log(`Skipped existing files: ${result.skippedFiles.length}`);
29
+ console.log(`Direct-copy assets created: ${result.directCopyCreatedFiles.length}`);
30
+ console.log(`Hooks installed: ${result.hookInstalledFiles.length}`);
31
+ console.log(`Runtime-generated files: ${result.runtimeGeneratedFiles.join(', ') || '-'}`);
32
+ console.log('Business scaffold: not applied by docs generate');
33
+ console.log('Bootstrap summary: not generated by docs generate');
34
+ if (result.firstChangeSuggestion) {
35
+ console.log(`Suggested first change: ${result.firstChangeSuggestion.name}`);
36
+ }
37
+ console.log('');
38
+ break;
39
+ }
40
+ case 'sync-protocol': {
41
+ const structure = await services_1.services.projectService.detectProjectStructure(targetPath);
42
+ if (!structure.initialized) {
43
+ throw new Error('Project is not initialized. Run "ospec init" first.');
44
+ }
45
+ const result = await services_1.services.projectService.syncProtocolGuidance(targetPath);
46
+ console.log('\nProtocol Guidance Synced');
47
+ console.log('========================\n');
48
+ console.log(`Project: ${result.projectName}`);
49
+ console.log(`Mode: ${result.mode}`);
50
+ console.log(`Document language: ${result.documentLanguage}`);
51
+ console.log(`Created files: ${result.createdFiles.length}`);
52
+ console.log(`Refreshed files: ${result.refreshedFiles.length}`);
53
+ console.log(`Skipped files: ${result.skippedFiles.length}`);
54
+ if (result.refreshedFiles.length > 0) {
55
+ console.log(`Refreshed: ${result.refreshedFiles.join(', ')}`);
56
+ }
57
+ if (result.createdFiles.length > 0) {
58
+ console.log(`Created: ${result.createdFiles.join(', ')}`);
59
+ }
60
+ console.log('Scope: protocol/AI guidance only; existing changes are not migrated.');
61
+ console.log('');
62
+ break;
63
+ }
64
+ case 'status': {
65
+ const docs = await services_1.services.projectService.getDocsStatus(targetPath);
66
+ console.log('\nDocs Status');
67
+ console.log('===========\n');
68
+ console.log(`Coverage: ${docs.coverage}% (${docs.existing}/${docs.total})`);
69
+ console.log(`Updated: ${docs.updatedAt ?? 'unknown'}`);
70
+ console.log('\nTracked docs:');
71
+ for (const item of docs.items) {
72
+ console.log(` ${item.exists ? '✓' : '✗'} ${item.path}`);
73
+ }
74
+ if (docs.apiDocs.length > 0) {
75
+ console.log('\nAPI docs:');
76
+ for (const item of docs.apiDocs) {
77
+ console.log(` ✓ ${item.path}`);
78
+ }
79
+ }
80
+ if (docs.designDocs.length > 0) {
81
+ console.log('\nDesign docs:');
82
+ for (const item of docs.designDocs) {
83
+ console.log(` ✓ ${item.path}`);
84
+ }
85
+ }
86
+ if (docs.planningDocs.length > 0) {
87
+ console.log('\nPlanning docs:');
88
+ for (const item of docs.planningDocs) {
89
+ console.log(` ✓ ${item.path}`);
90
+ }
91
+ }
92
+ if (docs.missingRequired.length > 0) {
93
+ console.log('\nMissing required docs:');
94
+ for (const item of docs.missingRequired) {
95
+ console.log(` - ${item}`);
96
+ }
97
+ }
98
+ if (docs.missingRecommended.length > 0) {
99
+ console.log('\nMissing recommended docs:');
100
+ for (const item of docs.missingRecommended) {
101
+ console.log(` - ${item}`);
102
+ }
103
+ }
104
+ console.log('');
105
+ break;
106
+ }
107
+ default:
108
+ this.info((0, subcommandHelp_1.getDocsHelpText)());
109
+ }
110
+ }
111
+ catch (error) {
112
+ this.error(`Docs command failed: ${error}`);
113
+ throw error;
114
+ }
115
+ }
116
+ }
117
+ exports.DocsCommand = DocsCommand;
118
+ //# sourceMappingURL=DocsCommand.js.map
@@ -0,0 +1,3 @@
1
+ export declare class FinalizeCommand {
2
+ execute(featurePath?: string): Promise<void>;
3
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FinalizeCommand = void 0;
4
+ const path = require("path");
5
+ const services_1 = require("../services");
6
+ const BaseCommand_1 = require("./BaseCommand");
7
+ const VerifyCommand_1 = require("./VerifyCommand");
8
+ class FinalizeCommand extends BaseCommand_1.BaseCommand {
9
+ async execute(featurePath) {
10
+ try {
11
+ const targetPath = featurePath || process.cwd();
12
+ this.info(`Finalizing change at ${targetPath}`);
13
+ const verifyCmd = new VerifyCommand_1.VerifyCommand();
14
+ await verifyCmd.execute(targetPath);
15
+ const result = await services_1.services.projectService.finalizeChange(path.resolve(targetPath));
16
+ this.success(`Change finalized: ${result.archivePath}`);
17
+ }
18
+ catch (error) {
19
+ this.error(`Finalize failed: ${error}`);
20
+ throw error;
21
+ }
22
+ }
23
+ }
24
+ exports.FinalizeCommand = FinalizeCommand;
@@ -0,0 +1,5 @@
1
+ import { BaseCommand } from './BaseCommand';
2
+ export declare class IndexCommand extends BaseCommand {
3
+ execute(action?: string, projectPath?: string): Promise<void>;
4
+ }
5
+ //# sourceMappingURL=IndexCommand.d.ts.map