scene-capability-engine 3.6.29 → 3.6.36

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 (99) hide show
  1. package/CHANGELOG.md +103 -1
  2. package/README.md +119 -122
  3. package/README.zh.md +123 -121
  4. package/bin/scene-capability-engine.js +11 -0
  5. package/docs/README.md +21 -32
  6. package/docs/agent-runtime/magicball-contract-index.md +25 -0
  7. package/docs/auto-refactor-index.md +384 -0
  8. package/docs/command-reference.md +96 -2
  9. package/docs/magicball-adaptation-task-checklist-v1.md +385 -0
  10. package/docs/magicball-app-bundle-sqlite-and-command-draft.md +539 -0
  11. package/docs/magicball-capability-iteration-api.md +2 -0
  12. package/docs/magicball-capability-iteration-ui.md +3 -0
  13. package/docs/magicball-capability-library.md +2 -0
  14. package/docs/magicball-cli-invocation-examples.md +336 -0
  15. package/docs/magicball-frontend-state-and-command-mapping.md +244 -0
  16. package/docs/magicball-integration-doc-index.md +137 -0
  17. package/docs/magicball-integration-issue-tracker.md +218 -0
  18. package/docs/magicball-mode-home-and-ontology-empty-state-playbook.md +249 -0
  19. package/docs/magicball-sce-adaptation-guide.md +203 -0
  20. package/docs/magicball-task-feedback-timeline-guide.md +8 -0
  21. package/docs/magicball-three-mode-alignment-plan.md +551 -0
  22. package/docs/magicball-ui-surface-checklist.md +126 -0
  23. package/docs/magicball-write-auth-adaptation-guide.md +328 -0
  24. package/docs/refactor-completion-roadmap.md +116 -0
  25. package/docs/zh/README.md +27 -30
  26. package/docs/zh/refactor-completion-roadmap.md +116 -0
  27. package/lib/app/registry-config.js +73 -0
  28. package/lib/app/registry-sync-service.js +228 -0
  29. package/lib/auto/archive-schema-service.js +276 -0
  30. package/lib/auto/archive-summary.js +60 -0
  31. package/lib/auto/batch-goal-input-service.js +543 -0
  32. package/lib/auto/batch-output.js +201 -0
  33. package/lib/auto/batch-summary-storage-service.js +110 -0
  34. package/lib/auto/close-loop-batch-service.js +116 -0
  35. package/lib/auto/close-loop-controller-service.js +287 -0
  36. package/lib/auto/close-loop-program-service.js +283 -0
  37. package/lib/auto/close-loop-recovery-service.js +191 -0
  38. package/lib/auto/close-loop-session-storage-service.js +50 -0
  39. package/lib/auto/controller-lock-service.js +55 -0
  40. package/lib/auto/controller-output.js +32 -0
  41. package/lib/auto/controller-queue-service.js +127 -0
  42. package/lib/auto/controller-session-storage-service.js +105 -0
  43. package/lib/auto/governance-advisory-service.js +208 -0
  44. package/lib/auto/governance-close-loop-service.js +411 -0
  45. package/lib/auto/governance-maintenance-presenter.js +162 -0
  46. package/lib/auto/governance-maintenance-service.js +112 -0
  47. package/lib/auto/governance-session-presenter.js +70 -0
  48. package/lib/auto/governance-session-storage-service.js +198 -0
  49. package/lib/auto/governance-signals.js +139 -0
  50. package/lib/auto/governance-stats-presenter.js +337 -0
  51. package/lib/auto/governance-stats-service.js +115 -0
  52. package/lib/auto/governance-summary.js +703 -0
  53. package/lib/auto/handoff-capability-matrix-service.js +281 -0
  54. package/lib/auto/handoff-evidence-review-service.js +251 -0
  55. package/lib/auto/handoff-release-evidence-service.js +190 -0
  56. package/lib/auto/handoff-release-gate-history-loaders-service.js +502 -0
  57. package/lib/auto/handoff-release-gate-history-service.js +257 -0
  58. package/lib/auto/handoff-reporting-service.js +1407 -0
  59. package/lib/auto/handoff-run-service.js +486 -0
  60. package/lib/auto/handoff-snapshots-service.js +645 -0
  61. package/lib/auto/observability-service.js +132 -0
  62. package/lib/auto/output-writer.js +34 -0
  63. package/lib/auto/program-auto-remediation-service.js +130 -0
  64. package/lib/auto/program-diagnostics.js +138 -0
  65. package/lib/auto/program-governance-helpers.js +306 -0
  66. package/lib/auto/program-governance-loop-service.js +413 -0
  67. package/lib/auto/program-output.js +106 -0
  68. package/lib/auto/program-summary.js +183 -0
  69. package/lib/auto/recovery-memory-service.js +684 -0
  70. package/lib/auto/recovery-selection-service.js +52 -0
  71. package/lib/auto/retention-policy.js +98 -0
  72. package/lib/auto/session-metrics.js +53 -0
  73. package/lib/auto/session-persistence-service.js +106 -0
  74. package/lib/auto/session-presenter.js +105 -0
  75. package/lib/auto/session-prune-service.js +190 -0
  76. package/lib/auto/session-query-service.js +249 -0
  77. package/lib/auto/spec-protection.js +141 -0
  78. package/lib/capability/catalog-service.js +248 -0
  79. package/lib/capability/inventory-service.js +100 -0
  80. package/lib/commands/app.js +911 -0
  81. package/lib/commands/assurance.js +212 -0
  82. package/lib/commands/auto.js +1091 -11063
  83. package/lib/commands/capability.js +81 -466
  84. package/lib/commands/mode.js +321 -0
  85. package/lib/commands/ontology.js +415 -0
  86. package/lib/commands/pm.js +422 -0
  87. package/lib/commands/scene.js +1 -1
  88. package/lib/commands/studio.js +147 -582
  89. package/lib/commands/timeline.js +6 -82
  90. package/lib/magicball/capability-inventory-view-model.js +213 -0
  91. package/lib/magicball/status-language.js +29 -0
  92. package/lib/magicball/task-feedback-model.js +113 -0
  93. package/lib/magicball/timeline-view-model.js +95 -0
  94. package/lib/ontology/seed-profiles.js +160 -0
  95. package/lib/scene/doctor-feedback.js +3541 -0
  96. package/lib/state/sce-state-store.js +3369 -1200
  97. package/lib/studio/task-envelope.js +269 -0
  98. package/lib/studio/task-intent.js +149 -0
  99. package/package.json +1 -1
@@ -0,0 +1,422 @@
1
+ const chalk = require('chalk');
2
+ const fs = require('fs-extra');
3
+ const { ensureWriteAuthorization } = require('../security/write-authorization');
4
+ const { getSceStateStore } = require('../state/sce-state-store');
5
+
6
+ function normalizeString(value) {
7
+ if (typeof value !== 'string') {
8
+ return '';
9
+ }
10
+ return value.trim();
11
+ }
12
+
13
+ function normalizePositiveInteger(value, fallback = 100, max = 1000) {
14
+ const parsed = Number.parseInt(`${value}`, 10);
15
+ if (!Number.isFinite(parsed) || parsed <= 0) {
16
+ return fallback;
17
+ }
18
+ return Math.min(parsed, max);
19
+ }
20
+
21
+ function createStore(dependencies = {}) {
22
+ const projectPath = dependencies.projectPath || process.cwd();
23
+ const fileSystem = dependencies.fileSystem || fs;
24
+ const env = dependencies.env || process.env;
25
+ return dependencies.stateStore || getSceStateStore(projectPath, {
26
+ fileSystem,
27
+ env
28
+ });
29
+ }
30
+
31
+ function countBy(items = [], key = 'status') {
32
+ return items.reduce((acc, item) => {
33
+ const value = normalizeString(item && item[key]) || 'unknown';
34
+ acc[value] = (acc[value] || 0) + 1;
35
+ return acc;
36
+ }, {});
37
+ }
38
+
39
+ function buildStatus(statusLabel, attentionLevel, blockingSummary = '', recommendedAction = '') {
40
+ return {
41
+ attention_level: attentionLevel,
42
+ status_tone: attentionLevel === 'high' ? 'warning' : (attentionLevel === 'medium' ? 'info' : 'success'),
43
+ status_label: statusLabel,
44
+ blocking_summary: blockingSummary,
45
+ recommended_action: recommendedAction
46
+ };
47
+ }
48
+
49
+ function attachRequirementViewModel(items = []) {
50
+ return items.map((item) => ({
51
+ ...item,
52
+ mb_status: buildStatus(
53
+ item.status === 'done' ? '已完成' : '待推进',
54
+ item.issue_count > 0 ? 'high' : (item.priority === 'P0' ? 'medium' : 'low'),
55
+ item.issue_count > 0 ? `关联问题 ${item.issue_count} 个` : '',
56
+ item.acceptance_summary || '继续推进需求澄清与验收标准收敛'
57
+ )
58
+ }));
59
+ }
60
+
61
+ function attachTrackingViewModel(items = []) {
62
+ return items.map((item) => ({
63
+ ...item,
64
+ mb_status: buildStatus(
65
+ item.status === 'blocked' ? '已阻塞' : (item.status === 'done' ? '已完成' : '正常推进'),
66
+ item.status === 'blocked' ? 'high' : (item.status === 'at_risk' ? 'medium' : 'low'),
67
+ item.blocking_summary || '',
68
+ item.next_action || '继续推进'
69
+ )
70
+ }));
71
+ }
72
+
73
+ function attachPlanViewModel(items = []) {
74
+ return items.map((item) => ({
75
+ ...item,
76
+ mb_status: buildStatus(
77
+ item.status === 'blocked' ? '已阻塞' : (item.status === 'done' ? '已完成' : '进行中'),
78
+ item.status === 'blocked' ? 'high' : (item.risk_level === 'high' ? 'medium' : 'low'),
79
+ item.next_checkpoint || '',
80
+ item.progress_summary || '继续推进计划执行'
81
+ )
82
+ }));
83
+ }
84
+
85
+ function attachChangeViewModel(items = []) {
86
+ return items.map((item) => ({
87
+ ...item,
88
+ mb_status: buildStatus(
89
+ item.status === 'done' ? '已实施' : (item.status === 'approved' ? '已同意' : '评估中'),
90
+ item.risk_level === 'high' ? 'high' : 'medium',
91
+ item.impact_scope || '',
92
+ item.decision || '继续评估变更影响'
93
+ )
94
+ }));
95
+ }
96
+
97
+ function attachIssueViewModel(items = []) {
98
+ return items.map((item) => ({
99
+ ...item,
100
+ mb_status: buildStatus(
101
+ item.status === 'closed' ? '已关闭' : (item.status === 'resolved' ? '已修复' : '待处理'),
102
+ item.severity === 'critical' || item.severity === 'high' ? 'high' : 'medium',
103
+ item.actual_result || '',
104
+ item.latest_action || item.verify_result || '继续修复并验证'
105
+ )
106
+ }));
107
+ }
108
+
109
+ function buildTablePayload(mode, query, items, columns) {
110
+ return {
111
+ mode,
112
+ query,
113
+ summary: {
114
+ total: items.length,
115
+ by_status: countBy(items, 'status')
116
+ },
117
+ items,
118
+ filters: [],
119
+ sort: [{ key: 'updated_at', direction: 'desc' }],
120
+ view_model: {
121
+ type: 'table',
122
+ columns
123
+ },
124
+ mb_status: {
125
+ status_label: items.length > 0 ? '有数据' : '空状态',
126
+ attention_level: items.length > 0 ? 'low' : 'medium'
127
+ }
128
+ };
129
+ }
130
+
131
+ function printPayload(payload, options = {}, title = 'PM') {
132
+ if (options.json) {
133
+ console.log(JSON.stringify(payload, null, 2));
134
+ return;
135
+ }
136
+ console.log(chalk.blue(title));
137
+ if (payload.mode) console.log(` Mode: ${payload.mode}`);
138
+ if (payload.summary && typeof payload.summary === 'object') {
139
+ for (const [key, value] of Object.entries(payload.summary)) {
140
+ console.log(` ${key}: ${typeof value === 'object' ? JSON.stringify(value) : value}`);
141
+ }
142
+ }
143
+ if (Array.isArray(payload.items)) {
144
+ payload.items.forEach((item) => {
145
+ console.log(` - ${item.title || item.requirement_id || item.plan_id || item.change_id || item.issue_id}`);
146
+ });
147
+ }
148
+ }
149
+
150
+ async function ensureAuthorized(action, options = {}, dependencies = {}) {
151
+ const projectPath = dependencies.projectPath || process.cwd();
152
+ const fileSystem = dependencies.fileSystem || fs;
153
+ const env = dependencies.env || process.env;
154
+ await ensureWriteAuthorization(action, {
155
+ authLease: options.authLease,
156
+ authPassword: options.authPassword,
157
+ actor: options.actor
158
+ }, {
159
+ projectPath,
160
+ fileSystem,
161
+ env
162
+ });
163
+ }
164
+
165
+ async function readInputJson(inputFile, dependencies = {}) {
166
+ const projectPath = dependencies.projectPath || process.cwd();
167
+ const fileSystem = dependencies.fileSystem || fs;
168
+ const resolved = require('path').isAbsolute(inputFile)
169
+ ? inputFile
170
+ : require('path').join(projectPath, inputFile);
171
+ return {
172
+ resolved,
173
+ payload: await fileSystem.readJson(resolved)
174
+ };
175
+ }
176
+
177
+ async function runPmRequirementListCommand(options = {}, dependencies = {}) {
178
+ const store = createStore(dependencies);
179
+ const items = attachRequirementViewModel(await store.listPmRequirements({
180
+ limit: normalizePositiveInteger(options.limit, 100, 1000),
181
+ status: options.status,
182
+ priority: options.priority,
183
+ query: options.query
184
+ }) || []);
185
+ const payload = buildTablePayload('pm-requirement-list', {
186
+ space: normalizeString(options.space) || 'engineering',
187
+ resource: 'requirement'
188
+ }, items, ['requirement_id', 'title', 'priority', 'status', 'owner', 'tracking_stage', 'acceptance_summary', 'issue_count', 'updated_at']);
189
+ printPayload(payload, options, 'PM Requirement List');
190
+ return payload;
191
+ }
192
+
193
+ async function runPmRequirementShowCommand(options = {}, dependencies = {}) {
194
+ const id = normalizeString(options.id);
195
+ if (!id) throw new Error('--id is required');
196
+ const store = createStore(dependencies);
197
+ const item = await store.getPmRequirement(id);
198
+ if (!item) throw new Error(`requirement not found: ${id}`);
199
+ const payload = {
200
+ mode: 'pm-requirement-show',
201
+ query: { id },
202
+ item: attachRequirementViewModel([item])[0]
203
+ };
204
+ printPayload(payload, options, 'PM Requirement Show');
205
+ return payload;
206
+ }
207
+
208
+ async function runPmRequirementUpsertCommand(options = {}, dependencies = {}) {
209
+ const input = normalizeString(options.input);
210
+ if (!input) throw new Error('--input is required');
211
+ await ensureAuthorized('pm:requirement:upsert', options, dependencies);
212
+ const { resolved, payload } = await readInputJson(input, dependencies);
213
+ const store = createStore(dependencies);
214
+ const item = await store.upsertPmRequirement(payload);
215
+ const result = { mode: 'pm-requirement-upsert', success: true, input_file: resolved, item: attachRequirementViewModel([item])[0] };
216
+ printPayload(result, options, 'PM Requirement Upsert');
217
+ return result;
218
+ }
219
+
220
+ async function runPmTrackingBoardCommand(options = {}, dependencies = {}) {
221
+ const store = createStore(dependencies);
222
+ const items = attachTrackingViewModel(await store.listPmTracking({
223
+ limit: normalizePositiveInteger(options.limit, 100, 1000),
224
+ status: options.status,
225
+ currentStage: options.currentStage,
226
+ query: options.query
227
+ }) || []);
228
+ const payload = buildTablePayload('pm-tracking-board', { space: normalizeString(options.space) || 'engineering', resource: 'tracking' }, items, ['tracking_id', 'requirement_id', 'current_stage', 'status', 'latest_action', 'blocking_summary', 'next_action', 'owner', 'updated_at']);
229
+ printPayload(payload, options, 'PM Tracking Board');
230
+ return payload;
231
+ }
232
+
233
+ async function runPmTrackingShowCommand(options = {}, dependencies = {}) {
234
+ const id = normalizeString(options.id);
235
+ if (!id) throw new Error('--id is required');
236
+ const store = createStore(dependencies);
237
+ const item = await store.getPmTracking(id);
238
+ if (!item) throw new Error(`tracking not found: ${id}`);
239
+ const payload = { mode: 'pm-tracking-show', query: { id }, item: attachTrackingViewModel([item])[0] };
240
+ printPayload(payload, options, 'PM Tracking Show');
241
+ return payload;
242
+ }
243
+
244
+ async function runPmTrackingUpsertCommand(options = {}, dependencies = {}) {
245
+ const input = normalizeString(options.input);
246
+ if (!input) throw new Error('--input is required');
247
+ await ensureAuthorized('pm:tracking:upsert', options, dependencies);
248
+ const { resolved, payload } = await readInputJson(input, dependencies);
249
+ const store = createStore(dependencies);
250
+ const item = await store.upsertPmTracking(payload);
251
+ const result = { mode: 'pm-tracking-upsert', success: true, input_file: resolved, item: attachTrackingViewModel([item])[0] };
252
+ printPayload(result, options, 'PM Tracking Upsert');
253
+ return result;
254
+ }
255
+
256
+ async function runPmPlanningBoardCommand(options = {}, dependencies = {}) {
257
+ const store = createStore(dependencies);
258
+ const items = attachPlanViewModel(await store.listPmPlans({
259
+ limit: normalizePositiveInteger(options.limit, 100, 1000),
260
+ status: options.status,
261
+ query: options.query
262
+ }) || []);
263
+ const payload = buildTablePayload('pm-planning-board', { space: normalizeString(options.space) || 'engineering', resource: 'planning' }, items, ['plan_id', 'title', 'scope', 'start_date', 'due_date', 'status', 'owner', 'milestone', 'progress_summary', 'updated_at']);
264
+ printPayload(payload, options, 'PM Planning Board');
265
+ return payload;
266
+ }
267
+
268
+ async function runPmPlanningShowCommand(options = {}, dependencies = {}) {
269
+ const id = normalizeString(options.id);
270
+ if (!id) throw new Error('--id is required');
271
+ const store = createStore(dependencies);
272
+ const item = await store.getPmPlan(id);
273
+ if (!item) throw new Error(`plan not found: ${id}`);
274
+ const payload = { mode: 'pm-planning-show', query: { id }, item: attachPlanViewModel([item])[0] };
275
+ printPayload(payload, options, 'PM Planning Show');
276
+ return payload;
277
+ }
278
+
279
+ async function runPmPlanningUpsertCommand(options = {}, dependencies = {}) {
280
+ const input = normalizeString(options.input);
281
+ if (!input) throw new Error('--input is required');
282
+ await ensureAuthorized('pm:planning:upsert', options, dependencies);
283
+ const { resolved, payload } = await readInputJson(input, dependencies);
284
+ const store = createStore(dependencies);
285
+ const item = await store.upsertPmPlan(payload);
286
+ const result = { mode: 'pm-planning-upsert', success: true, input_file: resolved, item: attachPlanViewModel([item])[0] };
287
+ printPayload(result, options, 'PM Planning Upsert');
288
+ return result;
289
+ }
290
+
291
+ async function runPmChangeListCommand(options = {}, dependencies = {}) {
292
+ const store = createStore(dependencies);
293
+ const items = attachChangeViewModel(await store.listPmChanges({
294
+ limit: normalizePositiveInteger(options.limit, 100, 1000),
295
+ status: options.status,
296
+ query: options.query
297
+ }) || []);
298
+ const payload = buildTablePayload('pm-change-list', { space: normalizeString(options.space) || 'engineering', resource: 'change' }, items, ['change_id', 'title', 'change_type', 'impact_scope', 'decision', 'status', 'owner', 'updated_at']);
299
+ printPayload(payload, options, 'PM Change List');
300
+ return payload;
301
+ }
302
+
303
+ async function runPmChangeShowCommand(options = {}, dependencies = {}) {
304
+ const id = normalizeString(options.id);
305
+ if (!id) throw new Error('--id is required');
306
+ const store = createStore(dependencies);
307
+ const item = await store.getPmChange(id);
308
+ if (!item) throw new Error(`change not found: ${id}`);
309
+ const payload = { mode: 'pm-change-show', query: { id }, item: attachChangeViewModel([item])[0] };
310
+ printPayload(payload, options, 'PM Change Show');
311
+ return payload;
312
+ }
313
+
314
+ async function runPmChangeUpsertCommand(options = {}, dependencies = {}) {
315
+ const input = normalizeString(options.input);
316
+ if (!input) throw new Error('--input is required');
317
+ await ensureAuthorized('pm:change:upsert', options, dependencies);
318
+ const { resolved, payload } = await readInputJson(input, dependencies);
319
+ const store = createStore(dependencies);
320
+ const item = await store.upsertPmChange(payload);
321
+ const result = { mode: 'pm-change-upsert', success: true, input_file: resolved, item: attachChangeViewModel([item])[0] };
322
+ printPayload(result, options, 'PM Change Upsert');
323
+ return result;
324
+ }
325
+
326
+ async function runPmIssueBoardCommand(options = {}, dependencies = {}) {
327
+ const store = createStore(dependencies);
328
+ const items = attachIssueViewModel(await store.listPmIssues({
329
+ limit: normalizePositiveInteger(options.limit, 100, 1000),
330
+ status: options.status,
331
+ severity: options.severity,
332
+ query: options.query
333
+ }) || []);
334
+ const payload = buildTablePayload('pm-issue-board', { space: normalizeString(options.space) || 'engineering', resource: 'issue' }, items, ['issue_id', 'title', 'source', 'severity', 'status', 'requirement_id', 'latest_action', 'verify_result', 'updated_at']);
335
+ printPayload(payload, options, 'PM Issue Board');
336
+ return payload;
337
+ }
338
+
339
+ async function runPmIssueShowCommand(options = {}, dependencies = {}) {
340
+ const id = normalizeString(options.id);
341
+ if (!id) throw new Error('--id is required');
342
+ const store = createStore(dependencies);
343
+ const item = await store.getPmIssue(id);
344
+ if (!item) throw new Error(`issue not found: ${id}`);
345
+ const payload = { mode: 'pm-issue-show', query: { id }, item: attachIssueViewModel([item])[0] };
346
+ printPayload(payload, options, 'PM Issue Show');
347
+ return payload;
348
+ }
349
+
350
+ async function runPmIssueUpsertCommand(options = {}, dependencies = {}) {
351
+ const input = normalizeString(options.input);
352
+ if (!input) throw new Error('--input is required');
353
+ await ensureAuthorized('pm:issue:upsert', options, dependencies);
354
+ const { resolved, payload } = await readInputJson(input, dependencies);
355
+ const store = createStore(dependencies);
356
+ const item = await store.upsertPmIssue(payload);
357
+ const result = { mode: 'pm-issue-upsert', success: true, input_file: resolved, item: attachIssueViewModel([item])[0] };
358
+ printPayload(result, options, 'PM Issue Upsert');
359
+ return result;
360
+ }
361
+
362
+ function safeRun(handler, options = {}, context = 'pm command') {
363
+ Promise.resolve(handler(options))
364
+ .catch((error) => {
365
+ if (options.json) {
366
+ console.log(JSON.stringify({ success: false, error: error.message }, null, 2));
367
+ } else {
368
+ console.error(chalk.red(`${context} failed:`), error.message);
369
+ }
370
+ process.exitCode = 1;
371
+ });
372
+ }
373
+
374
+ function registerPmCommands(program) {
375
+ const pm = program
376
+ .command('pm')
377
+ .description('Engineering delivery data plane for MagicBall engineering mode');
378
+
379
+ const requirement = pm.command('requirement').description('Manage requirements');
380
+ requirement.command('list').option('--space <space>', 'Space name', 'engineering').option('--limit <n>', 'Maximum rows', '100').option('--status <status>', 'Filter by status').option('--priority <priority>', 'Filter by priority').option('--query <text>', 'Free-text query').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmRequirementListCommand, options, 'pm requirement list'));
381
+ requirement.command('show').requiredOption('--id <requirement-id>', 'Requirement id').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmRequirementShowCommand, options, 'pm requirement show'));
382
+ requirement.command('upsert').requiredOption('--input <path>', 'Requirement JSON file').option('--auth-lease <lease-id>', 'Write authorization lease id').option('--auth-password <password>', 'Inline auth password if policy allows').option('--actor <actor>', 'Audit actor override').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmRequirementUpsertCommand, options, 'pm requirement upsert'));
383
+
384
+ const tracking = pm.command('tracking').description('Manage tracking board items');
385
+ tracking.command('board').option('--space <space>', 'Space name', 'engineering').option('--limit <n>', 'Maximum rows', '100').option('--status <status>', 'Filter by status').option('--current-stage <stage>', 'Filter by current stage').option('--query <text>', 'Free-text query').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmTrackingBoardCommand, options, 'pm tracking board'));
386
+ tracking.command('show').requiredOption('--id <tracking-id>', 'Tracking id').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmTrackingShowCommand, options, 'pm tracking show'));
387
+ tracking.command('upsert').requiredOption('--input <path>', 'Tracking JSON file').option('--auth-lease <lease-id>', 'Write authorization lease id').option('--auth-password <password>', 'Inline auth password if policy allows').option('--actor <actor>', 'Audit actor override').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmTrackingUpsertCommand, options, 'pm tracking upsert'));
388
+
389
+ const planning = pm.command('planning').description('Manage delivery plans');
390
+ planning.command('board').option('--space <space>', 'Space name', 'engineering').option('--limit <n>', 'Maximum rows', '100').option('--status <status>', 'Filter by status').option('--query <text>', 'Free-text query').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmPlanningBoardCommand, options, 'pm planning board'));
391
+ planning.command('show').requiredOption('--id <plan-id>', 'Plan id').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmPlanningShowCommand, options, 'pm planning show'));
392
+ planning.command('upsert').requiredOption('--input <path>', 'Plan JSON file').option('--auth-lease <lease-id>', 'Write authorization lease id').option('--auth-password <password>', 'Inline auth password if policy allows').option('--actor <actor>', 'Audit actor override').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmPlanningUpsertCommand, options, 'pm planning upsert'));
393
+
394
+ const change = pm.command('change').description('Manage change requests');
395
+ change.command('list').option('--space <space>', 'Space name', 'engineering').option('--limit <n>', 'Maximum rows', '100').option('--status <status>', 'Filter by status').option('--query <text>', 'Free-text query').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmChangeListCommand, options, 'pm change list'));
396
+ change.command('show').requiredOption('--id <change-id>', 'Change id').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmChangeShowCommand, options, 'pm change show'));
397
+ change.command('upsert').requiredOption('--input <path>', 'Change JSON file').option('--auth-lease <lease-id>', 'Write authorization lease id').option('--auth-password <password>', 'Inline auth password if policy allows').option('--actor <actor>', 'Audit actor override').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmChangeUpsertCommand, options, 'pm change upsert'));
398
+
399
+ const issue = pm.command('issue').description('Manage issue board items');
400
+ issue.command('board').option('--space <space>', 'Space name', 'engineering').option('--limit <n>', 'Maximum rows', '100').option('--status <status>', 'Filter by status').option('--severity <severity>', 'Filter by severity').option('--query <text>', 'Free-text query').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmIssueBoardCommand, options, 'pm issue board'));
401
+ issue.command('show').requiredOption('--id <issue-id>', 'Issue id').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmIssueShowCommand, options, 'pm issue show'));
402
+ issue.command('upsert').requiredOption('--input <path>', 'Issue JSON file').option('--auth-lease <lease-id>', 'Write authorization lease id').option('--auth-password <password>', 'Inline auth password if policy allows').option('--actor <actor>', 'Audit actor override').option('--json', 'Print machine-readable JSON output').action((options) => safeRun(runPmIssueUpsertCommand, options, 'pm issue upsert'));
403
+ }
404
+
405
+ module.exports = {
406
+ runPmRequirementListCommand,
407
+ runPmRequirementShowCommand,
408
+ runPmRequirementUpsertCommand,
409
+ runPmTrackingBoardCommand,
410
+ runPmTrackingShowCommand,
411
+ runPmTrackingUpsertCommand,
412
+ runPmPlanningBoardCommand,
413
+ runPmPlanningShowCommand,
414
+ runPmPlanningUpsertCommand,
415
+ runPmChangeListCommand,
416
+ runPmChangeShowCommand,
417
+ runPmChangeUpsertCommand,
418
+ runPmIssueBoardCommand,
419
+ runPmIssueShowCommand,
420
+ runPmIssueUpsertCommand,
421
+ registerPmCommands
422
+ };
@@ -1,4 +1,4 @@
1
- const path = require('path');
1
+ const path = require('path');
2
2
  const zlib = require('zlib');
3
3
  const crypto = require('crypto');
4
4
  const { spawnSync } = require('child_process');