scene-capability-engine 3.6.44 → 3.6.46

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 (61) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/bin/scene-capability-engine.js +36 -2
  3. package/docs/command-reference.md +5 -0
  4. package/docs/releases/README.md +2 -0
  5. package/docs/releases/v3.6.45.md +18 -0
  6. package/docs/releases/v3.6.46.md +23 -0
  7. package/docs/zh/releases/README.md +2 -0
  8. package/docs/zh/releases/v3.6.45.md +18 -0
  9. package/docs/zh/releases/v3.6.46.md +23 -0
  10. package/lib/workspace/collab-governance-audit.js +575 -0
  11. package/package.json +4 -2
  12. package/scripts/auto-strategy-router.js +231 -0
  13. package/scripts/capability-mapping-report.js +339 -0
  14. package/scripts/check-branding-consistency.js +140 -0
  15. package/scripts/check-sce-tracking.js +54 -0
  16. package/scripts/check-skip-allowlist.js +94 -0
  17. package/scripts/errorbook-registry-health-gate.js +172 -0
  18. package/scripts/errorbook-release-gate.js +132 -0
  19. package/scripts/failure-attribution-repair.js +317 -0
  20. package/scripts/git-managed-gate.js +464 -0
  21. package/scripts/interactive-approval-event-projection.js +400 -0
  22. package/scripts/interactive-approval-workflow.js +829 -0
  23. package/scripts/interactive-authorization-tier-evaluate.js +413 -0
  24. package/scripts/interactive-change-plan-gate.js +225 -0
  25. package/scripts/interactive-context-bridge.js +617 -0
  26. package/scripts/interactive-customization-loop.js +1690 -0
  27. package/scripts/interactive-dialogue-governance.js +842 -0
  28. package/scripts/interactive-feedback-log.js +253 -0
  29. package/scripts/interactive-flow-smoke.js +238 -0
  30. package/scripts/interactive-flow.js +1059 -0
  31. package/scripts/interactive-governance-report.js +1112 -0
  32. package/scripts/interactive-intent-build.js +707 -0
  33. package/scripts/interactive-loop-smoke.js +215 -0
  34. package/scripts/interactive-moqui-adapter.js +304 -0
  35. package/scripts/interactive-plan-build.js +426 -0
  36. package/scripts/interactive-runtime-policy-evaluate.js +495 -0
  37. package/scripts/interactive-work-order-build.js +552 -0
  38. package/scripts/matrix-regression-gate.js +167 -0
  39. package/scripts/moqui-core-regression-suite.js +397 -0
  40. package/scripts/moqui-lexicon-audit.js +651 -0
  41. package/scripts/moqui-matrix-remediation-phased-runner.js +865 -0
  42. package/scripts/moqui-matrix-remediation-queue.js +852 -0
  43. package/scripts/moqui-metadata-extract.js +1340 -0
  44. package/scripts/moqui-rebuild-gate.js +167 -0
  45. package/scripts/moqui-release-summary.js +729 -0
  46. package/scripts/moqui-standard-rebuild.js +1370 -0
  47. package/scripts/moqui-template-baseline-report.js +682 -0
  48. package/scripts/npm-package-runtime-asset-check.js +221 -0
  49. package/scripts/problem-closure-gate.js +441 -0
  50. package/scripts/release-asset-integrity-check.js +216 -0
  51. package/scripts/release-asset-nonempty-normalize.js +166 -0
  52. package/scripts/release-drift-evaluate.js +223 -0
  53. package/scripts/release-drift-signals.js +255 -0
  54. package/scripts/release-governance-snapshot-export.js +132 -0
  55. package/scripts/release-ops-weekly-summary.js +934 -0
  56. package/scripts/release-risk-remediation-bundle.js +315 -0
  57. package/scripts/release-weekly-ops-gate.js +423 -0
  58. package/scripts/state-migration-reconciliation-gate.js +110 -0
  59. package/scripts/state-storage-tiering-audit.js +337 -0
  60. package/scripts/steering-content-audit.js +393 -0
  61. package/scripts/symbol-evidence-locate.js +366 -0
@@ -0,0 +1,552 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const path = require('path');
5
+ const fs = require('fs-extra');
6
+ const crypto = require('crypto');
7
+
8
+ const DEFAULT_OUT = '.sce/reports/interactive-work-order.json';
9
+ const DEFAULT_MARKDOWN_OUT = '.sce/reports/interactive-work-order.md';
10
+
11
+ function parseArgs(argv) {
12
+ const options = {
13
+ sessionId: null,
14
+ goal: null,
15
+ dialogue: null,
16
+ intent: null,
17
+ plan: null,
18
+ gate: null,
19
+ runtime: null,
20
+ authorizationTier: null,
21
+ approvalState: null,
22
+ runtimeMode: null,
23
+ runtimeEnvironment: null,
24
+ executionAttempted: false,
25
+ executionBlocked: false,
26
+ executionResult: null,
27
+ executionReason: null,
28
+ executionId: null,
29
+ out: DEFAULT_OUT,
30
+ markdownOut: DEFAULT_MARKDOWN_OUT,
31
+ json: false
32
+ };
33
+
34
+ for (let index = 0; index < argv.length; index += 1) {
35
+ const token = argv[index];
36
+ const next = argv[index + 1];
37
+
38
+ if (token === '--session-id' && next) {
39
+ options.sessionId = next;
40
+ index += 1;
41
+ } else if (token === '--goal' && next) {
42
+ options.goal = next;
43
+ index += 1;
44
+ } else if (token === '--dialogue' && next) {
45
+ options.dialogue = next;
46
+ index += 1;
47
+ } else if (token === '--intent' && next) {
48
+ options.intent = next;
49
+ index += 1;
50
+ } else if (token === '--plan' && next) {
51
+ options.plan = next;
52
+ index += 1;
53
+ } else if (token === '--gate' && next) {
54
+ options.gate = next;
55
+ index += 1;
56
+ } else if (token === '--runtime' && next) {
57
+ options.runtime = next;
58
+ index += 1;
59
+ } else if (token === '--authorization-tier' && next) {
60
+ options.authorizationTier = next;
61
+ index += 1;
62
+ } else if (token === '--approval-state' && next) {
63
+ options.approvalState = next;
64
+ index += 1;
65
+ } else if (token === '--runtime-mode' && next) {
66
+ options.runtimeMode = next;
67
+ index += 1;
68
+ } else if (token === '--runtime-environment' && next) {
69
+ options.runtimeEnvironment = next;
70
+ index += 1;
71
+ } else if (token === '--execution-attempted') {
72
+ options.executionAttempted = true;
73
+ } else if (token === '--execution-blocked') {
74
+ options.executionBlocked = true;
75
+ } else if (token === '--execution-result' && next) {
76
+ options.executionResult = next;
77
+ index += 1;
78
+ } else if (token === '--execution-reason' && next) {
79
+ options.executionReason = next;
80
+ index += 1;
81
+ } else if (token === '--execution-id' && next) {
82
+ options.executionId = next;
83
+ index += 1;
84
+ } else if (token === '--out' && next) {
85
+ options.out = next;
86
+ index += 1;
87
+ } else if (token === '--markdown-out' && next) {
88
+ options.markdownOut = next;
89
+ index += 1;
90
+ } else if (token === '--json') {
91
+ options.json = true;
92
+ } else if (token === '--help' || token === '-h') {
93
+ printHelpAndExit(0);
94
+ }
95
+ }
96
+
97
+ if (!options.plan) {
98
+ throw new Error('--plan is required.');
99
+ }
100
+
101
+ return options;
102
+ }
103
+
104
+ function printHelpAndExit(code) {
105
+ const lines = [
106
+ 'Usage: node scripts/interactive-work-order-build.js --plan <path> [options]',
107
+ '',
108
+ 'Options:',
109
+ ' --plan <path> Change plan JSON file (required)',
110
+ ' --dialogue <path> Dialogue governance JSON file',
111
+ ' --intent <path> Change intent JSON file',
112
+ ' --gate <path> Change plan gate report JSON file',
113
+ ' --runtime <path> Runtime policy evaluation JSON file',
114
+ ' --authorization-tier <path> Authorization tier evaluation JSON file',
115
+ ' --approval-state <path> Approval workflow state JSON file',
116
+ ' --session-id <id> Session identifier',
117
+ ' --goal <text> Optional goal override',
118
+ ' --runtime-mode <name> Optional runtime mode override',
119
+ ' --runtime-environment <name> Optional runtime environment override',
120
+ ' --execution-attempted Mark execution as attempted',
121
+ ' --execution-blocked Mark execution as blocked',
122
+ ' --execution-result <value> Execution result (for example success|blocked|failed)',
123
+ ' --execution-reason <text> Execution reason/details',
124
+ ' --execution-id <id> Execution ID',
125
+ ` --out <path> Work-order JSON output path (default: ${DEFAULT_OUT})`,
126
+ ` --markdown-out <path> Work-order markdown output path (default: ${DEFAULT_MARKDOWN_OUT})`,
127
+ ' --json Print payload to stdout',
128
+ ' -h, --help Show this help'
129
+ ];
130
+ console.log(lines.join('\n'));
131
+ process.exit(code);
132
+ }
133
+
134
+ function resolvePath(cwd, value) {
135
+ return path.isAbsolute(value) ? value : path.resolve(cwd, value);
136
+ }
137
+
138
+ async function tryReadJsonFile(filePath) {
139
+ if (!filePath) {
140
+ return null;
141
+ }
142
+ if (!(await fs.pathExists(filePath))) {
143
+ return null;
144
+ }
145
+ const raw = await fs.readFile(filePath, 'utf8');
146
+ try {
147
+ return JSON.parse(raw);
148
+ } catch (error) {
149
+ throw new Error(`invalid JSON in ${filePath}: ${error.message}`);
150
+ }
151
+ }
152
+
153
+ function normalizeRiskLevel(value) {
154
+ const normalized = `${value || ''}`.trim().toLowerCase();
155
+ if (['high', 'critical'].includes(normalized)) {
156
+ return 'high';
157
+ }
158
+ if (normalized === 'medium') {
159
+ return 'medium';
160
+ }
161
+ return 'low';
162
+ }
163
+
164
+ function normalizeDecision(value, fallback = 'unknown') {
165
+ const normalized = `${value || ''}`.trim().toLowerCase();
166
+ return normalized || fallback;
167
+ }
168
+
169
+ function normalizeStatus(value, fallback = 'unknown') {
170
+ return normalizeDecision(value, fallback);
171
+ }
172
+
173
+ function inferWorkOrderStatus({
174
+ dialogueDecision,
175
+ gateDecision,
176
+ runtimeDecision,
177
+ authorizationTierDecision,
178
+ approvalStatus,
179
+ executionAttempted,
180
+ executionBlocked,
181
+ executionResult
182
+ }) {
183
+ if (
184
+ dialogueDecision === 'deny' ||
185
+ gateDecision === 'deny' ||
186
+ runtimeDecision === 'deny' ||
187
+ authorizationTierDecision === 'deny'
188
+ ) {
189
+ return 'blocked';
190
+ }
191
+ if (executionAttempted && executionBlocked) {
192
+ return 'blocked';
193
+ }
194
+ if (executionAttempted && executionResult === 'success') {
195
+ return 'completed';
196
+ }
197
+ if (
198
+ gateDecision === 'review-required' ||
199
+ runtimeDecision === 'review-required' ||
200
+ authorizationTierDecision === 'review-required'
201
+ ) {
202
+ return 'pending-review';
203
+ }
204
+ if (['draft', 'submitted', 'rejected'].includes(approvalStatus)) {
205
+ return 'pending-review';
206
+ }
207
+ if (['approved', 'verified', 'archived'].includes(approvalStatus)) {
208
+ return 'ready-for-apply';
209
+ }
210
+ if (gateDecision === 'allow' && runtimeDecision === 'allow') {
211
+ return 'ready-for-apply';
212
+ }
213
+ return 'pending-review';
214
+ }
215
+
216
+ function inferPriority(riskLevel, gateDecision, runtimeDecision, authorizationTierDecision) {
217
+ if (
218
+ gateDecision === 'deny' ||
219
+ runtimeDecision === 'deny' ||
220
+ authorizationTierDecision === 'deny' ||
221
+ riskLevel === 'high'
222
+ ) {
223
+ return 'high';
224
+ }
225
+ if (
226
+ gateDecision === 'review-required' ||
227
+ runtimeDecision === 'review-required' ||
228
+ authorizationTierDecision === 'review-required' ||
229
+ riskLevel === 'medium'
230
+ ) {
231
+ return 'medium';
232
+ }
233
+ return 'low';
234
+ }
235
+
236
+ function inferNextActions({
237
+ dialogueDecision,
238
+ gateDecision,
239
+ runtimeDecision,
240
+ authorizationTierDecision,
241
+ approvalStatus,
242
+ executionAttempted,
243
+ executionBlocked,
244
+ executionResult,
245
+ runtimeRequirements,
246
+ authorizationTierRequirements
247
+ }) {
248
+ const actions = [];
249
+ if (dialogueDecision === 'deny') {
250
+ actions.push('Rewrite goal to satisfy dialogue governance and rerun planning.');
251
+ return actions;
252
+ }
253
+ if (gateDecision === 'deny') {
254
+ actions.push('Refactor plan actions and pass interactive-change-plan-gate again.');
255
+ return actions;
256
+ }
257
+ if (runtimeDecision === 'deny') {
258
+ actions.push('Switch runtime mode/environment or lower risk/action set before apply.');
259
+ return actions;
260
+ }
261
+ if (authorizationTierDecision === 'deny') {
262
+ actions.push('Use system-maintainer profile and satisfy step-up authorization requirements before apply.');
263
+ return actions;
264
+ }
265
+ if (
266
+ gateDecision === 'review-required' ||
267
+ runtimeDecision === 'review-required' ||
268
+ authorizationTierDecision === 'review-required'
269
+ ) {
270
+ actions.push('Create review ticket and complete manual review/approval before apply.');
271
+ }
272
+ if (runtimeRequirements && runtimeRequirements.require_work_order === true) {
273
+ actions.push('Keep this work-order in audit trail and link approval/execution evidence.');
274
+ }
275
+ if (authorizationTierRequirements && authorizationTierRequirements.require_password_for_apply === true) {
276
+ actions.push('Provide one-time password authorization for apply execution.');
277
+ }
278
+ if (authorizationTierRequirements && authorizationTierRequirements.require_role_policy === true) {
279
+ actions.push('Provide approval role policy and actor role mapping for apply execution.');
280
+ }
281
+ if (authorizationTierRequirements && authorizationTierRequirements.require_distinct_actor_roles === true) {
282
+ actions.push('Use distinct operator role and approver role to satisfy separation-of-duties.');
283
+ }
284
+ if (!executionAttempted) {
285
+ actions.push('Run apply path only after review checks and approval are satisfied.');
286
+ } else if (executionBlocked) {
287
+ actions.push('Investigate blocked reason and rerun after governance conditions are satisfied.');
288
+ } else if (executionResult === 'success') {
289
+ actions.push('Collect user feedback and close work-order after verification.');
290
+ }
291
+ if (!['approved', 'verified', 'archived'].includes(approvalStatus)) {
292
+ actions.push('Complete approval workflow state transition to approved/verified.');
293
+ }
294
+ return actions;
295
+ }
296
+
297
+ function buildMarkdown(payload) {
298
+ const workOrder = payload.work_order;
299
+ const scope = workOrder.scope || {};
300
+ const governance = workOrder.governance || {};
301
+ const execution = workOrder.execution || {};
302
+ const runtime = workOrder.runtime || {};
303
+ const authorization = workOrder.authorization || {};
304
+
305
+ const lines = [];
306
+ lines.push('# Interactive Work Order');
307
+ lines.push('');
308
+ lines.push(`- Work-order ID: ${workOrder.work_order_id}`);
309
+ lines.push(`- Session ID: ${workOrder.session_id || 'n/a'}`);
310
+ lines.push(`- Status: ${workOrder.status}`);
311
+ lines.push(`- Priority: ${workOrder.priority}`);
312
+ lines.push(`- Runtime: ${runtime.mode || 'n/a'} @ ${runtime.environment || 'n/a'}`);
313
+ lines.push(`- Runtime decision: ${runtime.decision || 'unknown'}`);
314
+ lines.push(`- Authorization tier decision: ${authorization.decision || 'unknown'}`);
315
+ lines.push('');
316
+ lines.push('## Scope');
317
+ lines.push('');
318
+ lines.push(`- Product: ${scope.product || 'n/a'}`);
319
+ lines.push(`- Module: ${scope.module || 'n/a'}`);
320
+ lines.push(`- Page: ${scope.page || 'n/a'}`);
321
+ lines.push(`- Entity: ${scope.entity || 'n/a'}`);
322
+ lines.push(`- Scene: ${scope.scene_id || 'n/a'}`);
323
+ lines.push('');
324
+ lines.push('## Governance');
325
+ lines.push('');
326
+ lines.push(`- Dialogue: ${governance.dialogue_decision || 'unknown'}`);
327
+ lines.push(`- Gate: ${governance.gate_decision || 'unknown'}`);
328
+ lines.push(`- Runtime: ${governance.runtime_decision || 'unknown'}`);
329
+ lines.push(`- Authorization tier: ${governance.authorization_tier_decision || 'unknown'}`);
330
+ lines.push(`- Approval: ${governance.approval_status || 'unknown'}`);
331
+ lines.push(`- Risk level: ${governance.risk_level || 'unknown'}`);
332
+ lines.push('');
333
+ lines.push('## Authorization Tier');
334
+ lines.push('');
335
+ lines.push(`- Profile: ${authorization.profile || 'n/a'}`);
336
+ lines.push(`- Runtime environment: ${authorization.runtime_environment || 'n/a'}`);
337
+ lines.push(`- Decision: ${authorization.decision || 'unknown'}`);
338
+ lines.push(`- Require secondary authorization: ${authorization.requirements && authorization.requirements.require_secondary_authorization ? 'yes' : 'no'}`);
339
+ lines.push(`- Require password for apply: ${authorization.requirements && authorization.requirements.require_password_for_apply ? 'yes' : 'no'}`);
340
+ lines.push(`- Require role policy: ${authorization.requirements && authorization.requirements.require_role_policy ? 'yes' : 'no'}`);
341
+ lines.push(`- Require distinct actor roles: ${authorization.requirements && authorization.requirements.require_distinct_actor_roles ? 'yes' : 'no'}`);
342
+ lines.push('');
343
+ lines.push('## Execution');
344
+ lines.push('');
345
+ lines.push(`- Attempted: ${execution.attempted ? 'yes' : 'no'}`);
346
+ lines.push(`- Blocked: ${execution.blocked ? 'yes' : 'no'}`);
347
+ lines.push(`- Result: ${execution.result || 'n/a'}`);
348
+ lines.push(`- Execution ID: ${execution.execution_id || 'n/a'}`);
349
+ lines.push(`- Reason: ${execution.reason || 'n/a'}`);
350
+ lines.push('');
351
+ lines.push('## Actions');
352
+ lines.push('');
353
+ lines.push('| Action ID | Type | Sensitive | Privilege Escalation | Irreversible |');
354
+ lines.push('| --- | --- | --- | --- | --- |');
355
+ for (const action of workOrder.actions) {
356
+ lines.push(`| ${action.action_id || 'n/a'} | ${action.type || 'unknown'} | ${action.touches_sensitive_data ? 'yes' : 'no'} | ${action.requires_privilege_escalation ? 'yes' : 'no'} | ${action.irreversible ? 'yes' : 'no'} |`);
357
+ }
358
+ lines.push('');
359
+ lines.push('## Next Actions');
360
+ lines.push('');
361
+ if (Array.isArray(workOrder.next_actions) && workOrder.next_actions.length > 0) {
362
+ workOrder.next_actions.forEach(item => lines.push(`- ${item}`));
363
+ } else {
364
+ lines.push('- none');
365
+ }
366
+ return `${lines.join('\n')}\n`;
367
+ }
368
+
369
+ async function main() {
370
+ const options = parseArgs(process.argv.slice(2));
371
+ const cwd = process.cwd();
372
+
373
+ const planPath = resolvePath(cwd, options.plan);
374
+ const dialoguePath = options.dialogue ? resolvePath(cwd, options.dialogue) : null;
375
+ const intentPath = options.intent ? resolvePath(cwd, options.intent) : null;
376
+ const gatePath = options.gate ? resolvePath(cwd, options.gate) : null;
377
+ const runtimePath = options.runtime ? resolvePath(cwd, options.runtime) : null;
378
+ const authorizationTierPath = options.authorizationTier ? resolvePath(cwd, options.authorizationTier) : null;
379
+ const approvalStatePath = options.approvalState ? resolvePath(cwd, options.approvalState) : null;
380
+ const outPath = resolvePath(cwd, options.out);
381
+ const markdownOutPath = resolvePath(cwd, options.markdownOut);
382
+
383
+ const [dialogue, intent, plan, gate, runtime, authorizationTier, approvalState] = await Promise.all([
384
+ tryReadJsonFile(dialoguePath),
385
+ tryReadJsonFile(intentPath),
386
+ tryReadJsonFile(planPath),
387
+ tryReadJsonFile(gatePath),
388
+ tryReadJsonFile(runtimePath),
389
+ tryReadJsonFile(authorizationTierPath),
390
+ tryReadJsonFile(approvalStatePath)
391
+ ]);
392
+
393
+ if (!plan) {
394
+ throw new Error(`plan not found or invalid: ${planPath}`);
395
+ }
396
+
397
+ const dialogueDecision = normalizeDecision(dialogue && dialogue.decision, 'unknown');
398
+ const gateDecision = normalizeDecision(gate && gate.decision, 'unknown');
399
+ const runtimeDecision = normalizeDecision(runtime && runtime.decision, 'unknown');
400
+ const authorizationTierDecision = normalizeDecision(authorizationTier && authorizationTier.decision, 'unknown');
401
+ const approvalStatus = normalizeStatus(approvalState && approvalState.status, 'unknown');
402
+ const executionResult = normalizeDecision(options.executionResult, '');
403
+ const riskLevel = normalizeRiskLevel(plan.risk_level);
404
+ const runtimeMode = `${options.runtimeMode || (runtime && runtime.runtime_mode) || ''}`.trim() || null;
405
+ const runtimeEnvironment = `${options.runtimeEnvironment || (runtime && runtime.runtime_environment) || ''}`.trim() || null;
406
+
407
+ const status = inferWorkOrderStatus({
408
+ dialogueDecision,
409
+ gateDecision,
410
+ runtimeDecision,
411
+ authorizationTierDecision,
412
+ approvalStatus,
413
+ executionAttempted: options.executionAttempted,
414
+ executionBlocked: options.executionBlocked,
415
+ executionResult
416
+ });
417
+ const priority = inferPriority(riskLevel, gateDecision, runtimeDecision, authorizationTierDecision);
418
+ const runtimeRequirements = runtime && runtime.requirements && typeof runtime.requirements === 'object'
419
+ ? runtime.requirements
420
+ : {};
421
+ const authorizationTierContext = authorizationTier && authorizationTier.context && typeof authorizationTier.context === 'object'
422
+ ? authorizationTier.context
423
+ : {};
424
+ const authorizationTierRequirements = authorizationTier && authorizationTier.requirements && typeof authorizationTier.requirements === 'object'
425
+ ? authorizationTier.requirements
426
+ : {};
427
+ const nextActions = inferNextActions({
428
+ dialogueDecision,
429
+ gateDecision,
430
+ runtimeDecision,
431
+ authorizationTierDecision,
432
+ approvalStatus,
433
+ executionAttempted: options.executionAttempted,
434
+ executionBlocked: options.executionBlocked,
435
+ executionResult,
436
+ runtimeRequirements,
437
+ authorizationTierRequirements
438
+ });
439
+
440
+ const scope = plan.scope && typeof plan.scope === 'object' ? plan.scope : {};
441
+ const actions = Array.isArray(plan.actions) ? plan.actions : [];
442
+ const goalText = `${options.goal || (intent && intent.business_goal) || ''}`.trim();
443
+
444
+ const workOrder = {
445
+ work_order_id: `wo-${crypto.randomUUID()}`,
446
+ session_id: options.sessionId || null,
447
+ title: goalText || `Interactive change for ${scope.module || scope.product || 'unknown-scope'}`,
448
+ status,
449
+ priority,
450
+ phase: runtimeMode || 'runtime-unspecified',
451
+ intent_id: intent && intent.intent_id ? intent.intent_id : (plan.intent_id || null),
452
+ plan_id: plan.plan_id || null,
453
+ workflow_id: approvalState && approvalState.workflow_id ? approvalState.workflow_id : null,
454
+ scope: {
455
+ product: scope.product || null,
456
+ module: scope.module || null,
457
+ page: scope.page || null,
458
+ entity: scope.entity || null,
459
+ scene_id: scope.scene_id || null
460
+ },
461
+ governance: {
462
+ dialogue_decision: dialogueDecision,
463
+ gate_decision: gateDecision,
464
+ runtime_decision: runtimeDecision,
465
+ authorization_tier_decision: authorizationTierDecision,
466
+ approval_status: approvalStatus,
467
+ risk_level: riskLevel
468
+ },
469
+ runtime: {
470
+ mode: runtimeMode,
471
+ environment: runtimeEnvironment,
472
+ decision: runtimeDecision,
473
+ reasons: Array.isArray(runtime && runtime.reasons) ? runtime.reasons : [],
474
+ requirements: runtimeRequirements
475
+ },
476
+ authorization: {
477
+ profile: authorizationTierContext.dialogue_profile || null,
478
+ runtime_environment: authorizationTierContext.runtime_environment || runtimeEnvironment,
479
+ decision: authorizationTierDecision,
480
+ reasons: Array.isArray(authorizationTier && authorizationTier.reasons) ? authorizationTier.reasons : [],
481
+ requirements: authorizationTierRequirements
482
+ },
483
+ execution: {
484
+ attempted: options.executionAttempted,
485
+ blocked: options.executionBlocked,
486
+ result: executionResult || null,
487
+ reason: options.executionReason || null,
488
+ execution_id: options.executionId || null
489
+ },
490
+ verification_checks: Array.isArray(plan.verification_checks) ? plan.verification_checks : [],
491
+ rollback_plan: plan.rollback_plan || {},
492
+ actions,
493
+ next_actions: nextActions,
494
+ created_at: new Date().toISOString()
495
+ };
496
+
497
+ const payload = {
498
+ mode: 'interactive-work-order-build',
499
+ generated_at: new Date().toISOString(),
500
+ work_order: workOrder,
501
+ inputs: {
502
+ dialogue: dialoguePath ? (path.relative(cwd, dialoguePath) || '.') : null,
503
+ intent: intentPath ? (path.relative(cwd, intentPath) || '.') : null,
504
+ plan: path.relative(cwd, planPath) || '.',
505
+ gate: gatePath ? (path.relative(cwd, gatePath) || '.') : null,
506
+ runtime: runtimePath ? (path.relative(cwd, runtimePath) || '.') : null,
507
+ authorization_tier: authorizationTierPath ? (path.relative(cwd, authorizationTierPath) || '.') : null,
508
+ approval_state: approvalStatePath ? (path.relative(cwd, approvalStatePath) || '.') : null
509
+ },
510
+ output: {
511
+ json: path.relative(cwd, outPath) || '.',
512
+ markdown: path.relative(cwd, markdownOutPath) || '.'
513
+ }
514
+ };
515
+
516
+ await fs.ensureDir(path.dirname(outPath));
517
+ await fs.writeJson(outPath, payload, { spaces: 2 });
518
+ await fs.ensureDir(path.dirname(markdownOutPath));
519
+ await fs.writeFile(markdownOutPath, buildMarkdown(payload), 'utf8');
520
+
521
+ if (options.json) {
522
+ process.stdout.write(`${JSON.stringify(payload, null, 2)}\n`);
523
+ } else {
524
+ process.stdout.write(`Interactive work-order generated: ${workOrder.status}\n`);
525
+ process.stdout.write(`- Work-order: ${workOrder.work_order_id}\n`);
526
+ process.stdout.write(`- JSON: ${payload.output.json}\n`);
527
+ process.stdout.write(`- Markdown: ${payload.output.markdown}\n`);
528
+ }
529
+ }
530
+
531
+ if (require.main === module) {
532
+ main().catch((error) => {
533
+ console.error(`Interactive work-order build failed: ${error.message}`);
534
+ process.exit(1);
535
+ });
536
+ }
537
+
538
+ module.exports = {
539
+ DEFAULT_OUT,
540
+ DEFAULT_MARKDOWN_OUT,
541
+ parseArgs,
542
+ resolvePath,
543
+ tryReadJsonFile,
544
+ normalizeRiskLevel,
545
+ normalizeDecision,
546
+ normalizeStatus,
547
+ inferWorkOrderStatus,
548
+ inferPriority,
549
+ inferNextActions,
550
+ buildMarkdown,
551
+ main
552
+ };