peaks-cli 1.0.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 (143) hide show
  1. package/LICENSE +52 -0
  2. package/README.md +417 -0
  3. package/bin/peaks.js +2 -0
  4. package/dist/src/cli/cli-helpers.d.ts +25 -0
  5. package/dist/src/cli/cli-helpers.js +78 -0
  6. package/dist/src/cli/commands/capability-commands.d.ts +5 -0
  7. package/dist/src/cli/commands/capability-commands.js +46 -0
  8. package/dist/src/cli/commands/capability-worker-config-sc-commands.d.ts +3 -0
  9. package/dist/src/cli/commands/capability-worker-config-sc-commands.js +10 -0
  10. package/dist/src/cli/commands/config-commands.d.ts +3 -0
  11. package/dist/src/cli/commands/config-commands.js +212 -0
  12. package/dist/src/cli/commands/core-artifact-commands.d.ts +3 -0
  13. package/dist/src/cli/commands/core-artifact-commands.js +200 -0
  14. package/dist/src/cli/commands/sc-commands.d.ts +3 -0
  15. package/dist/src/cli/commands/sc-commands.js +37 -0
  16. package/dist/src/cli/commands/worker-commands.d.ts +3 -0
  17. package/dist/src/cli/commands/worker-commands.js +52 -0
  18. package/dist/src/cli/commands/workflow-commands.d.ts +3 -0
  19. package/dist/src/cli/commands/workflow-commands.js +257 -0
  20. package/dist/src/cli/index.d.ts +1 -0
  21. package/dist/src/cli/index.js +14 -0
  22. package/dist/src/cli/program.d.ts +4 -0
  23. package/dist/src/cli/program.js +13 -0
  24. package/dist/src/services/artifacts/artifact-service.d.ts +43 -0
  25. package/dist/src/services/artifacts/artifact-service.js +97 -0
  26. package/dist/src/services/artifacts/workspace-service.d.ts +33 -0
  27. package/dist/src/services/artifacts/workspace-service.js +254 -0
  28. package/dist/src/services/config/config-service.d.ts +29 -0
  29. package/dist/src/services/config/config-service.js +501 -0
  30. package/dist/src/services/config/config-types.d.ts +63 -0
  31. package/dist/src/services/config/config-types.js +16 -0
  32. package/dist/src/services/config/model-routing.d.ts +4 -0
  33. package/dist/src/services/config/model-routing.js +15 -0
  34. package/dist/src/services/doctor/doctor-service.d.ts +18 -0
  35. package/dist/src/services/doctor/doctor-service.js +68 -0
  36. package/dist/src/services/memory/project-memory-service.d.ts +79 -0
  37. package/dist/src/services/memory/project-memory-service.js +306 -0
  38. package/dist/src/services/profiles/profile-service.d.ts +6 -0
  39. package/dist/src/services/profiles/profile-service.js +19 -0
  40. package/dist/src/services/providers/minimax-provider-service.d.ts +24 -0
  41. package/dist/src/services/providers/minimax-provider-service.js +143 -0
  42. package/dist/src/services/providers/minimax-worker-service.d.ts +21 -0
  43. package/dist/src/services/providers/minimax-worker-service.js +80 -0
  44. package/dist/src/services/proxy/proxy-service.d.ts +7 -0
  45. package/dist/src/services/proxy/proxy-service.js +31 -0
  46. package/dist/src/services/rd/rd-service.d.ts +88 -0
  47. package/dist/src/services/rd/rd-service.js +370 -0
  48. package/dist/src/services/recommendations/capability-availability.d.ts +5 -0
  49. package/dist/src/services/recommendations/capability-availability.js +40 -0
  50. package/dist/src/services/recommendations/capability-map-service.d.ts +7 -0
  51. package/dist/src/services/recommendations/capability-map-service.js +131 -0
  52. package/dist/src/services/recommendations/capability-seed-items.d.ts +2 -0
  53. package/dist/src/services/recommendations/capability-seed-items.js +131 -0
  54. package/dist/src/services/recommendations/capability-seed-mappings.d.ts +2 -0
  55. package/dist/src/services/recommendations/capability-seed-mappings.js +42 -0
  56. package/dist/src/services/recommendations/capability-seed-sources.d.ts +2 -0
  57. package/dist/src/services/recommendations/capability-seed-sources.js +35 -0
  58. package/dist/src/services/recommendations/recommendation-service.d.ts +8 -0
  59. package/dist/src/services/recommendations/recommendation-service.js +106 -0
  60. package/dist/src/services/recommendations/recommendation-types.d.ts +129 -0
  61. package/dist/src/services/recommendations/recommendation-types.js +1 -0
  62. package/dist/src/services/recommendations/seed-capability-catalog.d.ts +3 -0
  63. package/dist/src/services/recommendations/seed-capability-catalog.js +3 -0
  64. package/dist/src/services/refactor/refactor-service.d.ts +9 -0
  65. package/dist/src/services/refactor/refactor-service.js +33 -0
  66. package/dist/src/services/sc/index.d.ts +1 -0
  67. package/dist/src/services/sc/index.js +1 -0
  68. package/dist/src/services/sc/sc-service.d.ts +79 -0
  69. package/dist/src/services/sc/sc-service.js +223 -0
  70. package/dist/src/services/skills/skill-registry.d.ts +17 -0
  71. package/dist/src/services/skills/skill-registry.js +40 -0
  72. package/dist/src/services/standards/project-standards-service.d.ts +82 -0
  73. package/dist/src/services/standards/project-standards-service.js +383 -0
  74. package/dist/src/services/tech/tech-service.d.ts +69 -0
  75. package/dist/src/services/tech/tech-service.js +236 -0
  76. package/dist/src/services/workflow/workflow-autonomous-service.d.ts +99 -0
  77. package/dist/src/services/workflow/workflow-autonomous-service.js +526 -0
  78. package/dist/src/services/workflow/workflow-router-service.d.ts +85 -0
  79. package/dist/src/services/workflow/workflow-router-service.js +213 -0
  80. package/dist/src/shared/change-id.d.ts +15 -0
  81. package/dist/src/shared/change-id.js +76 -0
  82. package/dist/src/shared/frontmatter.d.ts +6 -0
  83. package/dist/src/shared/frontmatter.js +47 -0
  84. package/dist/src/shared/fs-utils.d.ts +4 -0
  85. package/dist/src/shared/fs-utils.js +16 -0
  86. package/dist/src/shared/fs.d.ts +4 -0
  87. package/dist/src/shared/fs.js +26 -0
  88. package/dist/src/shared/path-utils.d.ts +13 -0
  89. package/dist/src/shared/path-utils.js +56 -0
  90. package/dist/src/shared/paths.d.ts +6 -0
  91. package/dist/src/shared/paths.js +40 -0
  92. package/dist/src/shared/planner-response.d.ts +21 -0
  93. package/dist/src/shared/planner-response.js +26 -0
  94. package/dist/src/shared/platform.d.ts +6 -0
  95. package/dist/src/shared/platform.js +11 -0
  96. package/dist/src/shared/process.d.ts +5 -0
  97. package/dist/src/shared/process.js +12 -0
  98. package/dist/src/shared/result.d.ts +13 -0
  99. package/dist/src/shared/result.js +32 -0
  100. package/package.json +49 -0
  101. package/schemas/approval-record.schema.json +14 -0
  102. package/schemas/artifact-manifest.schema.json +16 -0
  103. package/schemas/artifact-retention-report.schema.json +17 -0
  104. package/schemas/artifact-workspace.schema.json +22 -0
  105. package/schemas/capability-availability.schema.json +36 -0
  106. package/schemas/capability-item.schema.json +37 -0
  107. package/schemas/capability-source.schema.json +30 -0
  108. package/schemas/change-impact.schema.json +15 -0
  109. package/schemas/context-capsule.schema.json +16 -0
  110. package/schemas/recommendation-plan.schema.json +37 -0
  111. package/schemas/refactor-slice-spec.schema.json +19 -0
  112. package/scripts/clean-dist.mjs +8 -0
  113. package/scripts/install-skills.mjs +76 -0
  114. package/scripts/watch.mjs +389 -0
  115. package/skills/peaks-prd/SKILL.md +42 -0
  116. package/skills/peaks-prd/references/artifact-contracts.md +3 -0
  117. package/skills/peaks-prd/references/command-migration.md +3 -0
  118. package/skills/peaks-prd/references/workflow.md +11 -0
  119. package/skills/peaks-qa/SKILL.md +45 -0
  120. package/skills/peaks-qa/references/artifact-contracts.md +3 -0
  121. package/skills/peaks-qa/references/command-migration.md +3 -0
  122. package/skills/peaks-qa/references/regression-gates.md +16 -0
  123. package/skills/peaks-rd/SKILL.md +56 -0
  124. package/skills/peaks-rd/references/artifact-contracts.md +3 -0
  125. package/skills/peaks-rd/references/command-migration.md +3 -0
  126. package/skills/peaks-rd/references/refactor-workflow.md +31 -0
  127. package/skills/peaks-sc/SKILL.md +30 -0
  128. package/skills/peaks-sc/references/artifact-contracts.md +3 -0
  129. package/skills/peaks-sc/references/artifact-retention.md +14 -0
  130. package/skills/peaks-sc/references/command-migration.md +3 -0
  131. package/skills/peaks-solo/SKILL.md +63 -0
  132. package/skills/peaks-solo/references/artifact-contracts.md +3 -0
  133. package/skills/peaks-solo/references/command-migration.md +3 -0
  134. package/skills/peaks-solo/references/refactor-mode.md +22 -0
  135. package/skills/peaks-solo/references/workflow.md +14 -0
  136. package/skills/peaks-txt/SKILL.md +48 -0
  137. package/skills/peaks-txt/references/artifact-contracts.md +3 -0
  138. package/skills/peaks-txt/references/command-migration.md +3 -0
  139. package/skills/peaks-txt/references/context-capsule.md +20 -0
  140. package/skills/peaks-ui/SKILL.md +35 -0
  141. package/skills/peaks-ui/references/artifact-contracts.md +3 -0
  142. package/skills/peaks-ui/references/command-migration.md +3 -0
  143. package/skills/peaks-ui/references/workflow.md +11 -0
@@ -0,0 +1,257 @@
1
+ import { createRdSwarmPlan } from '../../services/rd/rd-service.js';
2
+ import { createTechPlan, getTechStatus } from '../../services/tech/tech-service.js';
3
+ import { createWorkflowRouterPlan, isSoloMode, isWorkflowMode } from '../../services/workflow/workflow-router-service.js';
4
+ import { createAutonomousWorkflowPlan } from '../../services/workflow/workflow-autonomous-service.js';
5
+ import { createRecommendationPlan } from '../../services/recommendations/recommendation-service.js';
6
+ import { createRefactorDryRun } from '../../services/refactor/refactor-service.js';
7
+ import { getCurrentWorkspaceConfig, readConfig } from '../../services/config/config-service.js';
8
+ import { getEconomyAwareExecutionModelId } from '../../services/config/model-routing.js';
9
+ import { getLocalArtifactPath } from '../../services/artifacts/workspace-service.js';
10
+ import { fail, ok } from '../../shared/result.js';
11
+ import { addJsonOption, failUnsupportedNonDryRun, getErrorMessage, isRecommendationWorkflow, printResult } from '../cli-helpers.js';
12
+ function getWorkspaceContext() {
13
+ const workspace = getCurrentWorkspaceConfig();
14
+ if (!workspace)
15
+ return {};
16
+ return { workspace, artifactWorkspacePath: getLocalArtifactPath(workspace) };
17
+ }
18
+ function parseMaxWorkers(io, command, value, asJson) {
19
+ const maxWorkers = Number(value);
20
+ if (!Number.isInteger(maxWorkers) || maxWorkers < 1) {
21
+ printResult(io, fail(command, 'INVALID_MAX_WORKERS', 'max-workers must be a positive integer', {}, ['Use --max-workers with a positive integer value']), asJson);
22
+ process.exitCode = 1;
23
+ return null;
24
+ }
25
+ return maxWorkers;
26
+ }
27
+ function parseSoloMode(io, command, mode, soloMode, asJson) {
28
+ if (mode !== 'solo' && soloMode) {
29
+ printResult(io, fail(command, 'SOLO_MODE_REQUIRES_SOLO_WORKFLOW', '--solo-mode can only be used with --mode solo', {}, ['Remove --solo-mode or use --mode solo']), asJson);
30
+ process.exitCode = 1;
31
+ return null;
32
+ }
33
+ if (mode !== 'solo' || !soloMode) {
34
+ return undefined;
35
+ }
36
+ if (!isSoloMode(soloMode)) {
37
+ printResult(io, fail(command, 'UNSUPPORTED_SOLO_MODE', `Unsupported solo mode ${soloMode}`, {}, ['Use --solo-mode full-auto, guided, or rnd']), asJson);
38
+ process.exitCode = 1;
39
+ return null;
40
+ }
41
+ return soloMode;
42
+ }
43
+ function runTechPlan(io, options) {
44
+ if (options.dryRun === false) {
45
+ failUnsupportedNonDryRun(io, 'tech.plan', options.json);
46
+ return;
47
+ }
48
+ try {
49
+ const workspaceContext = getWorkspaceContext();
50
+ const plan = createTechPlan({
51
+ changeId: options.changeId,
52
+ goal: options.goal,
53
+ swarm: options.swarm ?? false,
54
+ dryRun: true,
55
+ ...workspaceContext
56
+ });
57
+ printResult(io, ok('tech.plan', plan), options.json);
58
+ }
59
+ catch (error) {
60
+ printResult(io, fail('tech.plan', 'INVALID_CHANGE_ID_OR_GOAL', getErrorMessage(error), {}, ['Use a safe change id and a non-empty goal']), options.json);
61
+ process.exitCode = 1;
62
+ }
63
+ }
64
+ function runTechStatus(io, options) {
65
+ try {
66
+ const workspaceContext = getWorkspaceContext();
67
+ printResult(io, ok('tech.status', getTechStatus({ changeId: options.changeId, ...workspaceContext })), options.json);
68
+ }
69
+ catch (error) {
70
+ printResult(io, fail('tech.status', 'INVALID_CHANGE_ID', getErrorMessage(error), {}, ['Use a safe change id']), options.json);
71
+ process.exitCode = 1;
72
+ }
73
+ }
74
+ function runWorkflowRoute(io, options) {
75
+ if (options.dryRun === false) {
76
+ failUnsupportedNonDryRun(io, 'workflow.route', options.json);
77
+ return;
78
+ }
79
+ if (!isWorkflowMode(options.mode)) {
80
+ printResult(io, fail('workflow.route', 'UNSUPPORTED_WORKFLOW_MODE', `Unsupported workflow mode ${options.mode}`, {}, ['Use --mode solo or --mode team']), options.json);
81
+ process.exitCode = 1;
82
+ return;
83
+ }
84
+ const maxWorkers = parseMaxWorkers(io, 'workflow.route', options.maxWorkers, options.json);
85
+ if (maxWorkers === null)
86
+ return;
87
+ const soloMode = parseSoloMode(io, 'workflow.route', options.mode, options.soloMode, options.json);
88
+ if (soloMode === null)
89
+ return;
90
+ try {
91
+ const workspaceContext = getWorkspaceContext();
92
+ const plan = createWorkflowRouterPlan({
93
+ changeId: options.changeId,
94
+ goal: options.goal,
95
+ mode: options.mode,
96
+ ...(soloMode ? { soloMode } : {}),
97
+ maxWorkers,
98
+ dryRun: true,
99
+ config: readConfig(),
100
+ ...workspaceContext
101
+ });
102
+ printResult(io, ok('workflow.route', plan), options.json);
103
+ }
104
+ catch (error) {
105
+ printResult(io, fail('workflow.route', 'INVALID_CHANGE_ID_OR_GOAL', getErrorMessage(error), {}, ['Use a safe change id and a non-empty goal']), options.json);
106
+ process.exitCode = 1;
107
+ }
108
+ }
109
+ function runAutonomousWorkflow(io, options) {
110
+ if (options.dryRun === false) {
111
+ failUnsupportedNonDryRun(io, 'workflow.autonomous', options.json);
112
+ return;
113
+ }
114
+ if (!isWorkflowMode(options.mode)) {
115
+ printResult(io, fail('workflow.autonomous', 'UNSUPPORTED_WORKFLOW_MODE', `Unsupported workflow mode ${options.mode}`, {}, ['Use --mode solo or --mode team']), options.json);
116
+ process.exitCode = 1;
117
+ return;
118
+ }
119
+ const maxWorkers = parseMaxWorkers(io, 'workflow.autonomous', options.maxWorkers, options.json);
120
+ if (maxWorkers === null)
121
+ return;
122
+ const soloMode = parseSoloMode(io, 'workflow.autonomous', options.mode, options.soloMode, options.json);
123
+ if (soloMode === null)
124
+ return;
125
+ try {
126
+ const workspaceContext = getWorkspaceContext();
127
+ const plan = createAutonomousWorkflowPlan({
128
+ changeId: options.changeId,
129
+ goal: options.goal,
130
+ mode: options.mode,
131
+ ...(soloMode ? { soloMode } : {}),
132
+ maxWorkers,
133
+ dryRun: true,
134
+ config: readConfig(),
135
+ ...workspaceContext
136
+ });
137
+ printResult(io, ok('workflow.autonomous', plan), options.json);
138
+ }
139
+ catch (error) {
140
+ printResult(io, fail('workflow.autonomous', 'INVALID_CHANGE_ID_OR_GOAL', getErrorMessage(error), {}, ['Use a safe change id and a non-empty goal']), options.json);
141
+ process.exitCode = 1;
142
+ }
143
+ }
144
+ function runSwarmPlan(io, options) {
145
+ if ((options.skill ?? 'rd') !== 'rd') {
146
+ printResult(io, fail('swarm.plan', 'UNSUPPORTED_SWARM_SKILL', `Unsupported skill ${options.skill}`, {}, ['Use --skill rd']), options.json);
147
+ process.exitCode = 1;
148
+ return;
149
+ }
150
+ if (options.dryRun === false) {
151
+ failUnsupportedNonDryRun(io, 'swarm.plan', options.json);
152
+ return;
153
+ }
154
+ const maxWorkers = parseMaxWorkers(io, 'swarm.plan', options.maxWorkers, options.json);
155
+ if (maxWorkers === null)
156
+ return;
157
+ try {
158
+ const workspaceContext = getWorkspaceContext();
159
+ const config = readConfig();
160
+ const plan = createRdSwarmPlan({
161
+ skill: 'rd',
162
+ changeId: options.changeId,
163
+ goal: options.goal,
164
+ maxWorkers,
165
+ dryRun: true,
166
+ swarmMode: config.swarmMode,
167
+ executionModelId: getEconomyAwareExecutionModelId(config),
168
+ ...workspaceContext
169
+ });
170
+ printResult(io, ok('swarm.plan', plan), options.json);
171
+ }
172
+ catch (error) {
173
+ printResult(io, fail('swarm.plan', 'INVALID_CHANGE_ID_OR_GOAL', getErrorMessage(error), {}, ['Use a safe change id and a non-empty goal']), options.json);
174
+ process.exitCode = 1;
175
+ }
176
+ }
177
+ function addTechPlanOptions(command) {
178
+ return addJsonOption(command
179
+ .description('Generate a technical dry-run graph')
180
+ .requiredOption('--change-id <id>', 'change identifier')
181
+ .requiredOption('--goal <goal>', 'planning goal')
182
+ .option('--swarm', 'opt into swarm-oriented planning')
183
+ .option('--dry-run', 'preview without writing files', true)
184
+ .option('--no-dry-run', 'unsupported: do not execute tech planning from this CLI'));
185
+ }
186
+ function addTechStatusOptions(command) {
187
+ return addJsonOption(command.description('Inspect technical approval status').requiredOption('--change-id <id>', 'change identifier'));
188
+ }
189
+ function addWorkflowRouteOptions(command, description) {
190
+ return addJsonOption(command
191
+ .description(description)
192
+ .requiredOption('--mode <mode>', 'workflow mode: solo or team')
193
+ .requiredOption('--change-id <id>', 'change identifier')
194
+ .requiredOption('--goal <goal>', 'planning goal')
195
+ .option('--solo-mode <mode>', 'solo mode: full-auto, guided, or rnd')
196
+ .option('--max-workers <count>', 'maximum worker count', '40')
197
+ .option('--dry-run', 'preview without writing files', true)
198
+ .option('--no-dry-run', 'unsupported: do not execute workflow planning from this CLI'));
199
+ }
200
+ function addSwarmPlanOptions(command, includeSkill) {
201
+ const configured = command
202
+ .description('Plan an RD swarm dry-run graph')
203
+ .requiredOption('--change-id <id>', 'change identifier')
204
+ .requiredOption('--goal <goal>', 'planning goal')
205
+ .option('--max-workers <count>', 'maximum worker count', '40')
206
+ .option('--dry-run', 'preview without writing files', true)
207
+ .option('--no-dry-run', 'unsupported: do not execute RD planning from this CLI');
208
+ if (includeSkill) {
209
+ configured.requiredOption('--skill <skill>', 'skill to plan for');
210
+ }
211
+ return addJsonOption(configured);
212
+ }
213
+ export function registerWorkflowCommands(program, io) {
214
+ const refactor = program.command('refactor').description('Plan a Peaks refactor run without modifying code');
215
+ addJsonOption(refactor
216
+ .option('--solo', 'use peaks-solo orchestration mode')
217
+ .option('--rd', 'use peaks-rd direct mode')
218
+ .option('--dry-run', 'print gates and required artifacts', true)
219
+ .option('--no-dry-run', 'unsupported: do not modify code from this command')).action((options) => {
220
+ if (options.dryRun === false) {
221
+ failUnsupportedNonDryRun(io, 'refactor', options.json);
222
+ return;
223
+ }
224
+ if (options.solo && options.rd) {
225
+ printResult(io, fail('refactor', 'CONFLICTING_REFACTOR_MODE', 'Choose either --solo or --rd, not both', {}, ['Run peaks refactor --solo --dry-run']), options.json);
226
+ process.exitCode = 1;
227
+ return;
228
+ }
229
+ const mode = options.rd ? 'rd' : 'solo';
230
+ printResult(io, ok('refactor', createRefactorDryRun(mode), [], ['This dry run never edits code']), options.json);
231
+ });
232
+ const tech = program.command('tech').description('Plan and inspect technical dry-run gates');
233
+ addTechPlanOptions(tech.command('plan')).action((options) => runTechPlan(io, options));
234
+ addTechStatusOptions(tech.command('status')).action((options) => runTechStatus(io, options));
235
+ addTechPlanOptions(program.command('tech-plan')).action((options) => runTechPlan(io, options));
236
+ addTechStatusOptions(program.command('tech-status')).action((options) => runTechStatus(io, options));
237
+ const workflow = program.command('workflow').description('Plan workflow routing dry-run graphs');
238
+ addWorkflowRouteOptions(workflow.command('route'), 'Plan a workflow routing dry-run summary').action((options) => runWorkflowRoute(io, options));
239
+ addWorkflowRouteOptions(program.command('route'), 'Plan a workflow routing dry-run summary').action((options) => runWorkflowRoute(io, options));
240
+ addWorkflowRouteOptions(workflow.command('autonomous'), 'Plan an autonomous workflow handoff summary').action((options) => runAutonomousWorkflow(io, options));
241
+ addWorkflowRouteOptions(program.command('autonomous'), 'Plan an autonomous workflow handoff summary').action((options) => runAutonomousWorkflow(io, options));
242
+ const swarm = program.command('swarm').description('Plan RD swarm dry-run graphs');
243
+ addSwarmPlanOptions(swarm.command('plan'), true).action((options) => runSwarmPlan(io, options));
244
+ addSwarmPlanOptions(program.command('swarm-plan'), false).action((options) => runSwarmPlan(io, options));
245
+ addJsonOption(program
246
+ .command('recommend')
247
+ .description('Create a dry-run recommendation plan for a workflow')
248
+ .requiredOption('--workflow <workflow>', 'workflow: code-refactor, product-refactor, or frontend-design')
249
+ .option('--language <language>', 'human presentation language', 'en')).action((options) => {
250
+ if (!isRecommendationWorkflow(options.workflow)) {
251
+ printResult(io, fail('recommend', 'UNSUPPORTED_RECOMMENDATION_WORKFLOW', `Unsupported recommendation workflow ${options.workflow}`, {}, ['Use --workflow code-refactor, product-refactor, or frontend-design']), options.json);
252
+ process.exitCode = 1;
253
+ return;
254
+ }
255
+ printResult(io, ok('recommend', createRecommendationPlan({ workflow: options.workflow, language: options.language })), options.json);
256
+ });
257
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ import { createProgram } from './program.js';
2
+ import { getErrorMessage } from '../shared/result.js';
3
+ createProgram().parseAsync(process.argv).catch((error) => {
4
+ console.error(JSON.stringify({
5
+ ok: false,
6
+ command: 'cli',
7
+ code: 'UNHANDLED_ERROR',
8
+ message: getErrorMessage(error),
9
+ data: {},
10
+ warnings: [],
11
+ nextActions: []
12
+ }, null, 2));
13
+ process.exitCode = 1;
14
+ });
@@ -0,0 +1,4 @@
1
+ import { Command } from 'commander';
2
+ import type { ProgramIO } from './cli-helpers.js';
3
+ export { printResult, type ProgramIO } from './cli-helpers.js';
4
+ export declare function createProgram(io?: ProgramIO): Command;
@@ -0,0 +1,13 @@
1
+ import { Command } from 'commander';
2
+ import { registerCoreAndArtifactCommands } from './commands/core-artifact-commands.js';
3
+ import { registerWorkflowCommands } from './commands/workflow-commands.js';
4
+ import { registerCapabilityWorkerConfigAndSCCommands } from './commands/capability-worker-config-sc-commands.js';
5
+ export { printResult } from './cli-helpers.js';
6
+ export function createProgram(io = { stdout: (text) => console.log(text), stderr: (text) => console.error(text) }) {
7
+ const program = new Command();
8
+ program.name('peaks').description('Peaks CLI and short skill family runtime manager').version('0.1.0').exitOverride();
9
+ registerCoreAndArtifactCommands(program, io);
10
+ registerWorkflowCommands(program, io);
11
+ registerCapabilityWorkerConfigAndSCCommands(program, io);
12
+ return program;
13
+ }
@@ -0,0 +1,43 @@
1
+ export type ArtifactProvider = 'github' | 'gitlab';
2
+ export type ArtifactInitPlan = {
3
+ provider: ArtifactProvider;
4
+ name: string;
5
+ visibility: 'private';
6
+ localPath: string;
7
+ remoteFirst: boolean;
8
+ dryRun: boolean;
9
+ plannedActions: string[];
10
+ tokenPolicy: string;
11
+ };
12
+ export type GuidedArtifactSetup = {
13
+ step: 'detect' | 'configure' | 'validate' | 'complete';
14
+ workspaceId: string | null;
15
+ workspacePath: string | null;
16
+ provider: ArtifactProvider | null;
17
+ repoOwner: string | null;
18
+ repoName: string | null;
19
+ localPath: string;
20
+ remoteUrl: string | null;
21
+ validationResult: {
22
+ workspaceExists: boolean;
23
+ gitAvailable: boolean;
24
+ ghTokenAvailable: boolean;
25
+ sshKeyAvailable: boolean;
26
+ };
27
+ nextStep: string;
28
+ guidance: string[];
29
+ };
30
+ export declare function createArtifactInitPlan(options: {
31
+ provider: ArtifactProvider;
32
+ name: string;
33
+ localPath?: string;
34
+ dryRun?: boolean;
35
+ }): ArtifactInitPlan;
36
+ export declare function createGuidedArtifactSetup(): GuidedArtifactSetup;
37
+ export declare function getArtifactStatus(): {
38
+ mode: string;
39
+ supportedProviders: ArtifactProvider[];
40
+ localPath: string;
41
+ configured: boolean;
42
+ nextActions: string[];
43
+ };
@@ -0,0 +1,97 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { execFileSync } from 'node:child_process';
3
+ import { homedir } from 'node:os';
4
+ import { resolve } from 'node:path';
5
+ import { getCurrentWorkspaceConfig } from '../config/config-service.js';
6
+ import { getLocalArtifactPath } from './workspace-service.js';
7
+ function getRemoteUrl(artifactRepo) {
8
+ if (!artifactRepo)
9
+ return null;
10
+ if (artifactRepo.provider === 'github') {
11
+ return `https://github.com/${artifactRepo.owner}/${artifactRepo.name}.git`;
12
+ }
13
+ return `https://gitlab.com/${artifactRepo.owner}/${artifactRepo.name}.git`;
14
+ }
15
+ function hasGit() {
16
+ try {
17
+ execFileSync('git', ['--version']);
18
+ return true;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ function hasSshKey() {
25
+ const sshDir = resolve(process.env.HOME ?? homedir(), '.ssh');
26
+ const keyNames = ['id_ed25519', 'id_rsa', 'id_ecdsa', 'id_dsa'];
27
+ return keyNames.some((keyName) => existsSync(resolve(sshDir, keyName)));
28
+ }
29
+ export function createArtifactInitPlan(options) {
30
+ return {
31
+ provider: options.provider,
32
+ name: options.name,
33
+ visibility: 'private',
34
+ localPath: options.localPath ?? '.peaks-artifacts',
35
+ remoteFirst: true,
36
+ dryRun: options.dryRun ?? true,
37
+ plannedActions: [
38
+ `confirm creation of private ${options.provider} artifact repository`,
39
+ 'verify authentication without storing tokens',
40
+ `create or link remote artifact repository ${options.name}`,
41
+ `prepare local working copy at ${options.localPath ?? '.peaks-artifacts'}`,
42
+ 'write artifact repository creation report'
43
+ ],
44
+ tokenPolicy: 'Use provider auth/CLI or environment tokens only; never write tokens to skills, artifacts, config, or reports.'
45
+ };
46
+ }
47
+ export function createGuidedArtifactSetup() {
48
+ const workspace = getCurrentWorkspaceConfig();
49
+ const artifactRepo = workspace?.artifactRepo ?? null;
50
+ const validationResult = {
51
+ workspaceExists: workspace !== null,
52
+ gitAvailable: hasGit(),
53
+ ghTokenAvailable: Boolean(process.env.GH_TOKEN?.trim()),
54
+ sshKeyAvailable: hasSshKey()
55
+ };
56
+ const localPath = workspace ? getLocalArtifactPath(workspace) : '.peaks-artifacts';
57
+ const remoteUrl = getRemoteUrl(artifactRepo ?? undefined);
58
+ return {
59
+ step: 'detect',
60
+ workspaceId: workspace?.workspaceId ?? null,
61
+ workspacePath: workspace?.rootPath ?? null,
62
+ provider: artifactRepo?.provider ?? null,
63
+ repoOwner: artifactRepo?.owner ?? null,
64
+ repoName: artifactRepo?.name ?? null,
65
+ localPath,
66
+ remoteUrl,
67
+ validationResult,
68
+ nextStep: workspace ? (artifactRepo ? 'validate' : 'configure') : 'configure',
69
+ guidance: [
70
+ 'Step 1: Detect current workspace and environment',
71
+ ` - Workspace: ${workspace?.workspaceId ?? 'not configured'}`,
72
+ ` - Git available: ${validationResult.gitAvailable ? 'yes' : 'no'}`,
73
+ ` - GH_TOKEN environment variable: ${validationResult.ghTokenAvailable ? 'available' : 'not set'}`,
74
+ ` - SSH key for code push: ${validationResult.sshKeyAvailable ? 'available' : 'not found'}`,
75
+ '',
76
+ 'Step 2: Configure artifact repository',
77
+ ' - Run: peaks artifacts init --provider github --name <repo> --dry-run',
78
+ ' - Or add to workspace: peaks config workspace add --id <id> --provider github --repo-owner <owner> --repo-name <name>',
79
+ '',
80
+ 'Step 3: Validate setup',
81
+ ' - Run: peaks sc status',
82
+ ' - Run: peaks artifacts workspace',
83
+ '',
84
+ 'Step 4: Complete',
85
+ ' - Artifact sync is ready when workspace has artifactRepo configured'
86
+ ]
87
+ };
88
+ }
89
+ export function getArtifactStatus() {
90
+ return {
91
+ mode: 'remote-first',
92
+ supportedProviders: ['github', 'gitlab'],
93
+ localPath: '.peaks-artifacts',
94
+ configured: false,
95
+ nextActions: ['Run peaks artifacts init --provider gitlab --name <repo> --dry-run']
96
+ };
97
+ }
@@ -0,0 +1,33 @@
1
+ import type { WorkspaceConfig } from '../config/config-types.js';
2
+ export type SyncStatus = 'synced' | 'pending' | 'out-of-sync' | 'unknown';
3
+ export type ArtifactWorkspaceStatus = {
4
+ workspaceId: string;
5
+ localPath: string;
6
+ configured: boolean;
7
+ syncStatus: SyncStatus;
8
+ lastSync: string | null;
9
+ hasLocalChanges: boolean;
10
+ artifactRepo: WorkspaceConfig['artifactRepo'] | null;
11
+ nextActions: string[];
12
+ };
13
+ export type SyncResult = {
14
+ workspaceId: string;
15
+ success: boolean;
16
+ localPath: string;
17
+ remoteUrl: string | null;
18
+ commands: string[];
19
+ output: string[];
20
+ error?: string;
21
+ };
22
+ export declare function getLocalArtifactPath(workspace: WorkspaceConfig): string;
23
+ export declare function isArtifactWorkspaceOutsideTarget(workspace: WorkspaceConfig, artifactWorkspacePath?: string): boolean;
24
+ export declare function hasValidArtifactWorkspace(workspace: WorkspaceConfig, artifactWorkspacePath?: string): boolean;
25
+ export declare function executeArtifactSync(workspaceId?: string): Promise<SyncResult>;
26
+ export declare function getArtifactWorkspaceStatus(workspaceId?: string): ArtifactWorkspaceStatus;
27
+ export declare function planArtifactSync(workspaceId?: string, dryRun?: boolean): {
28
+ workspaceId: string;
29
+ dryRun: boolean;
30
+ localPath: string;
31
+ remoteUrl: string | null;
32
+ plannedCommands: string[];
33
+ };