scene-capability-engine 3.6.45 → 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.
- package/CHANGELOG.md +11 -0
- package/docs/releases/README.md +1 -0
- package/docs/releases/v3.6.46.md +23 -0
- package/docs/zh/releases/README.md +1 -0
- package/docs/zh/releases/v3.6.46.md +23 -0
- package/package.json +4 -2
- package/scripts/auto-strategy-router.js +231 -0
- package/scripts/capability-mapping-report.js +339 -0
- package/scripts/check-branding-consistency.js +140 -0
- package/scripts/check-sce-tracking.js +54 -0
- package/scripts/check-skip-allowlist.js +94 -0
- package/scripts/errorbook-registry-health-gate.js +172 -0
- package/scripts/errorbook-release-gate.js +132 -0
- package/scripts/failure-attribution-repair.js +317 -0
- package/scripts/git-managed-gate.js +464 -0
- package/scripts/interactive-approval-event-projection.js +400 -0
- package/scripts/interactive-approval-workflow.js +829 -0
- package/scripts/interactive-authorization-tier-evaluate.js +413 -0
- package/scripts/interactive-change-plan-gate.js +225 -0
- package/scripts/interactive-context-bridge.js +617 -0
- package/scripts/interactive-customization-loop.js +1690 -0
- package/scripts/interactive-dialogue-governance.js +842 -0
- package/scripts/interactive-feedback-log.js +253 -0
- package/scripts/interactive-flow-smoke.js +238 -0
- package/scripts/interactive-flow.js +1059 -0
- package/scripts/interactive-governance-report.js +1112 -0
- package/scripts/interactive-intent-build.js +707 -0
- package/scripts/interactive-loop-smoke.js +215 -0
- package/scripts/interactive-moqui-adapter.js +304 -0
- package/scripts/interactive-plan-build.js +426 -0
- package/scripts/interactive-runtime-policy-evaluate.js +495 -0
- package/scripts/interactive-work-order-build.js +552 -0
- package/scripts/matrix-regression-gate.js +167 -0
- package/scripts/moqui-core-regression-suite.js +397 -0
- package/scripts/moqui-lexicon-audit.js +651 -0
- package/scripts/moqui-matrix-remediation-phased-runner.js +865 -0
- package/scripts/moqui-matrix-remediation-queue.js +852 -0
- package/scripts/moqui-metadata-extract.js +1340 -0
- package/scripts/moqui-rebuild-gate.js +167 -0
- package/scripts/moqui-release-summary.js +729 -0
- package/scripts/moqui-standard-rebuild.js +1370 -0
- package/scripts/moqui-template-baseline-report.js +682 -0
- package/scripts/npm-package-runtime-asset-check.js +221 -0
- package/scripts/problem-closure-gate.js +441 -0
- package/scripts/release-asset-integrity-check.js +216 -0
- package/scripts/release-asset-nonempty-normalize.js +166 -0
- package/scripts/release-drift-evaluate.js +223 -0
- package/scripts/release-drift-signals.js +255 -0
- package/scripts/release-governance-snapshot-export.js +132 -0
- package/scripts/release-ops-weekly-summary.js +934 -0
- package/scripts/release-risk-remediation-bundle.js +315 -0
- package/scripts/release-weekly-ops-gate.js +423 -0
- package/scripts/state-migration-reconciliation-gate.js +110 -0
- package/scripts/state-storage-tiering-audit.js +337 -0
- package/scripts/steering-content-audit.js +393 -0
- package/scripts/symbol-evidence-locate.js +366 -0
|
@@ -0,0 +1,1059 @@
|
|
|
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
|
+
const { spawnSync } = require('child_process');
|
|
8
|
+
const {
|
|
9
|
+
DEFAULT_BUSINESS_MODE_POLICY,
|
|
10
|
+
BUSINESS_MODES,
|
|
11
|
+
normalizeBusinessMode,
|
|
12
|
+
applyBusinessModePolicy
|
|
13
|
+
} = require('../lib/runtime/business-mode-resolver');
|
|
14
|
+
|
|
15
|
+
const DEFAULT_PROVIDER = 'moqui';
|
|
16
|
+
const DEFAULT_OUT_DIR = '.sce/reports/interactive-flow';
|
|
17
|
+
const DEFAULT_USER_ID = 'anonymous-user';
|
|
18
|
+
const DEFAULT_FEEDBACK_CHANNEL = 'ui';
|
|
19
|
+
const DEFAULT_MATRIX_SIGNALS = '.sce/reports/interactive-matrix-signals.jsonl';
|
|
20
|
+
const DEFAULT_MATRIX_MIN_SCORE = 70;
|
|
21
|
+
const DEFAULT_MATRIX_MIN_VALID_RATE = 100;
|
|
22
|
+
const DEFAULT_AUTH_PASSWORD_HASH_ENV = 'SCE_INTERACTIVE_AUTH_PASSWORD_SHA256';
|
|
23
|
+
const FEEDBACK_CHANNELS = new Set(['ui', 'cli', 'api', 'other']);
|
|
24
|
+
const DEFAULT_DIALOGUE_PROFILE = 'business-user';
|
|
25
|
+
const DIALOGUE_PROFILES = new Set(['business-user', 'system-maintainer']);
|
|
26
|
+
const UI_MODES = new Set(['user-app', 'ops-console']);
|
|
27
|
+
const DEFAULT_RUNTIME_MODE = 'ops-fix';
|
|
28
|
+
const DEFAULT_RUNTIME_ENVIRONMENT = 'staging';
|
|
29
|
+
const RUNTIME_MODES = new Set(['user-assist', 'ops-fix', 'feature-dev']);
|
|
30
|
+
const RUNTIME_ENVIRONMENTS = new Set(['dev', 'staging', 'prod']);
|
|
31
|
+
|
|
32
|
+
const SCRIPT_CONTEXT_BRIDGE = path.resolve(__dirname, 'interactive-context-bridge.js');
|
|
33
|
+
const SCRIPT_INTERACTIVE_LOOP = path.resolve(__dirname, 'interactive-customization-loop.js');
|
|
34
|
+
const SCRIPT_MOQUI_BASELINE = path.resolve(__dirname, 'moqui-template-baseline-report.js');
|
|
35
|
+
|
|
36
|
+
function parseArgs(argv) {
|
|
37
|
+
const explicitKeys = new Set();
|
|
38
|
+
const options = {
|
|
39
|
+
input: null,
|
|
40
|
+
provider: DEFAULT_PROVIDER,
|
|
41
|
+
goal: null,
|
|
42
|
+
goalFile: null,
|
|
43
|
+
userId: DEFAULT_USER_ID,
|
|
44
|
+
sessionId: null,
|
|
45
|
+
executionMode: 'suggestion',
|
|
46
|
+
businessMode: null,
|
|
47
|
+
businessModePolicy: DEFAULT_BUSINESS_MODE_POLICY,
|
|
48
|
+
allowModeOverride: false,
|
|
49
|
+
policy: null,
|
|
50
|
+
catalog: null,
|
|
51
|
+
dialoguePolicy: null,
|
|
52
|
+
dialogueProfile: DEFAULT_DIALOGUE_PROFILE,
|
|
53
|
+
uiMode: null,
|
|
54
|
+
dialogueOut: null,
|
|
55
|
+
runtimeMode: DEFAULT_RUNTIME_MODE,
|
|
56
|
+
runtimeEnvironment: DEFAULT_RUNTIME_ENVIRONMENT,
|
|
57
|
+
runtimePolicy: null,
|
|
58
|
+
runtimeOut: null,
|
|
59
|
+
authorizationTierPolicy: null,
|
|
60
|
+
authorizationTierOut: null,
|
|
61
|
+
contextContract: null,
|
|
62
|
+
strictContract: true,
|
|
63
|
+
moquiConfig: null,
|
|
64
|
+
outDir: DEFAULT_OUT_DIR,
|
|
65
|
+
out: null,
|
|
66
|
+
loopOut: null,
|
|
67
|
+
workOrderOut: null,
|
|
68
|
+
workOrderMarkdownOut: null,
|
|
69
|
+
bridgeOutContext: null,
|
|
70
|
+
bridgeOutReport: null,
|
|
71
|
+
approvalActor: null,
|
|
72
|
+
approvalActorRole: null,
|
|
73
|
+
approverActor: null,
|
|
74
|
+
approverActorRole: null,
|
|
75
|
+
approvalRolePolicy: null,
|
|
76
|
+
skipSubmit: false,
|
|
77
|
+
autoApproveLowRisk: false,
|
|
78
|
+
autoExecuteLowRisk: false,
|
|
79
|
+
allowSuggestionApply: false,
|
|
80
|
+
liveApply: false,
|
|
81
|
+
dryRun: true,
|
|
82
|
+
feedbackScore: null,
|
|
83
|
+
feedbackComment: null,
|
|
84
|
+
feedbackTags: [],
|
|
85
|
+
feedbackChannel: DEFAULT_FEEDBACK_CHANNEL,
|
|
86
|
+
authPassword: null,
|
|
87
|
+
authPasswordHash: null,
|
|
88
|
+
authPasswordEnv: null,
|
|
89
|
+
failOnDialogueDeny: false,
|
|
90
|
+
failOnGateDeny: false,
|
|
91
|
+
failOnGateNonAllow: false,
|
|
92
|
+
failOnRuntimeNonAllow: false,
|
|
93
|
+
failOnExecuteBlocked: false,
|
|
94
|
+
matrix: true,
|
|
95
|
+
matrixTemplateDir: null,
|
|
96
|
+
matrixMatch: null,
|
|
97
|
+
matrixIncludeAll: false,
|
|
98
|
+
matrixMinScore: DEFAULT_MATRIX_MIN_SCORE,
|
|
99
|
+
matrixMinValidRate: DEFAULT_MATRIX_MIN_VALID_RATE,
|
|
100
|
+
matrixCompareWith: null,
|
|
101
|
+
matrixOut: null,
|
|
102
|
+
matrixMarkdownOut: null,
|
|
103
|
+
matrixSignals: DEFAULT_MATRIX_SIGNALS,
|
|
104
|
+
matrixFailOnPortfolioFail: false,
|
|
105
|
+
matrixFailOnRegression: false,
|
|
106
|
+
matrixFailOnError: false,
|
|
107
|
+
json: false
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
111
|
+
const token = argv[index];
|
|
112
|
+
const next = argv[index + 1];
|
|
113
|
+
|
|
114
|
+
if (token === '--input' && next) {
|
|
115
|
+
options.input = next;
|
|
116
|
+
index += 1;
|
|
117
|
+
} else if (token === '--provider' && next) {
|
|
118
|
+
options.provider = next;
|
|
119
|
+
index += 1;
|
|
120
|
+
} else if (token === '--goal' && next) {
|
|
121
|
+
options.goal = next;
|
|
122
|
+
index += 1;
|
|
123
|
+
} else if (token === '--goal-file' && next) {
|
|
124
|
+
options.goalFile = next;
|
|
125
|
+
index += 1;
|
|
126
|
+
} else if (token === '--user-id' && next) {
|
|
127
|
+
options.userId = next;
|
|
128
|
+
index += 1;
|
|
129
|
+
} else if (token === '--session-id' && next) {
|
|
130
|
+
options.sessionId = next;
|
|
131
|
+
index += 1;
|
|
132
|
+
} else if (token === '--execution-mode' && next) {
|
|
133
|
+
options.executionMode = next;
|
|
134
|
+
explicitKeys.add('executionMode');
|
|
135
|
+
index += 1;
|
|
136
|
+
} else if (token === '--business-mode' && next) {
|
|
137
|
+
options.businessMode = next;
|
|
138
|
+
index += 1;
|
|
139
|
+
} else if (token === '--business-mode-policy' && next) {
|
|
140
|
+
options.businessModePolicy = next;
|
|
141
|
+
index += 1;
|
|
142
|
+
} else if (token === '--allow-mode-override') {
|
|
143
|
+
options.allowModeOverride = true;
|
|
144
|
+
} else if (token === '--policy' && next) {
|
|
145
|
+
options.policy = next;
|
|
146
|
+
index += 1;
|
|
147
|
+
} else if (token === '--catalog' && next) {
|
|
148
|
+
options.catalog = next;
|
|
149
|
+
index += 1;
|
|
150
|
+
} else if (token === '--dialogue-policy' && next) {
|
|
151
|
+
options.dialoguePolicy = next;
|
|
152
|
+
index += 1;
|
|
153
|
+
} else if (token === '--dialogue-profile' && next) {
|
|
154
|
+
options.dialogueProfile = next;
|
|
155
|
+
explicitKeys.add('dialogueProfile');
|
|
156
|
+
index += 1;
|
|
157
|
+
} else if (token === '--ui-mode' && next) {
|
|
158
|
+
options.uiMode = next;
|
|
159
|
+
explicitKeys.add('uiMode');
|
|
160
|
+
index += 1;
|
|
161
|
+
} else if (token === '--dialogue-out' && next) {
|
|
162
|
+
options.dialogueOut = next;
|
|
163
|
+
index += 1;
|
|
164
|
+
} else if (token === '--runtime-mode' && next) {
|
|
165
|
+
options.runtimeMode = next;
|
|
166
|
+
explicitKeys.add('runtimeMode');
|
|
167
|
+
index += 1;
|
|
168
|
+
} else if (token === '--runtime-environment' && next) {
|
|
169
|
+
options.runtimeEnvironment = next;
|
|
170
|
+
explicitKeys.add('runtimeEnvironment');
|
|
171
|
+
index += 1;
|
|
172
|
+
} else if (token === '--runtime-policy' && next) {
|
|
173
|
+
options.runtimePolicy = next;
|
|
174
|
+
index += 1;
|
|
175
|
+
} else if (token === '--runtime-out' && next) {
|
|
176
|
+
options.runtimeOut = next;
|
|
177
|
+
index += 1;
|
|
178
|
+
} else if (token === '--authorization-tier-policy' && next) {
|
|
179
|
+
options.authorizationTierPolicy = next;
|
|
180
|
+
index += 1;
|
|
181
|
+
} else if (token === '--authorization-tier-out' && next) {
|
|
182
|
+
options.authorizationTierOut = next;
|
|
183
|
+
index += 1;
|
|
184
|
+
} else if (token === '--context-contract' && next) {
|
|
185
|
+
options.contextContract = next;
|
|
186
|
+
index += 1;
|
|
187
|
+
} else if (token === '--no-strict-contract') {
|
|
188
|
+
options.strictContract = false;
|
|
189
|
+
} else if (token === '--moqui-config' && next) {
|
|
190
|
+
options.moquiConfig = next;
|
|
191
|
+
index += 1;
|
|
192
|
+
} else if (token === '--out-dir' && next) {
|
|
193
|
+
options.outDir = next;
|
|
194
|
+
index += 1;
|
|
195
|
+
} else if (token === '--out' && next) {
|
|
196
|
+
options.out = next;
|
|
197
|
+
index += 1;
|
|
198
|
+
} else if (token === '--loop-out' && next) {
|
|
199
|
+
options.loopOut = next;
|
|
200
|
+
index += 1;
|
|
201
|
+
} else if (token === '--work-order-out' && next) {
|
|
202
|
+
options.workOrderOut = next;
|
|
203
|
+
index += 1;
|
|
204
|
+
} else if (token === '--work-order-markdown-out' && next) {
|
|
205
|
+
options.workOrderMarkdownOut = next;
|
|
206
|
+
index += 1;
|
|
207
|
+
} else if (token === '--bridge-out-context' && next) {
|
|
208
|
+
options.bridgeOutContext = next;
|
|
209
|
+
index += 1;
|
|
210
|
+
} else if (token === '--bridge-out-report' && next) {
|
|
211
|
+
options.bridgeOutReport = next;
|
|
212
|
+
index += 1;
|
|
213
|
+
} else if (token === '--approval-actor' && next) {
|
|
214
|
+
options.approvalActor = next;
|
|
215
|
+
index += 1;
|
|
216
|
+
} else if (token === '--approval-actor-role' && next) {
|
|
217
|
+
options.approvalActorRole = next;
|
|
218
|
+
index += 1;
|
|
219
|
+
} else if (token === '--approver-actor' && next) {
|
|
220
|
+
options.approverActor = next;
|
|
221
|
+
index += 1;
|
|
222
|
+
} else if (token === '--approver-actor-role' && next) {
|
|
223
|
+
options.approverActorRole = next;
|
|
224
|
+
index += 1;
|
|
225
|
+
} else if (token === '--approval-role-policy' && next) {
|
|
226
|
+
options.approvalRolePolicy = next;
|
|
227
|
+
index += 1;
|
|
228
|
+
} else if (token === '--skip-submit') {
|
|
229
|
+
options.skipSubmit = true;
|
|
230
|
+
} else if (token === '--auto-approve-low-risk') {
|
|
231
|
+
options.autoApproveLowRisk = true;
|
|
232
|
+
} else if (token === '--auto-execute-low-risk') {
|
|
233
|
+
options.autoExecuteLowRisk = true;
|
|
234
|
+
explicitKeys.add('autoExecuteLowRisk');
|
|
235
|
+
} else if (token === '--allow-suggestion-apply') {
|
|
236
|
+
options.allowSuggestionApply = true;
|
|
237
|
+
} else if (token === '--live-apply') {
|
|
238
|
+
options.liveApply = true;
|
|
239
|
+
} else if (token === '--no-dry-run') {
|
|
240
|
+
options.dryRun = false;
|
|
241
|
+
} else if (token === '--feedback-score' && next) {
|
|
242
|
+
options.feedbackScore = Number(next);
|
|
243
|
+
index += 1;
|
|
244
|
+
} else if (token === '--feedback-comment' && next) {
|
|
245
|
+
options.feedbackComment = next;
|
|
246
|
+
index += 1;
|
|
247
|
+
} else if (token === '--feedback-tags' && next) {
|
|
248
|
+
options.feedbackTags = next.split(',').map(item => item.trim()).filter(Boolean);
|
|
249
|
+
index += 1;
|
|
250
|
+
} else if (token === '--feedback-channel' && next) {
|
|
251
|
+
options.feedbackChannel = next;
|
|
252
|
+
index += 1;
|
|
253
|
+
} else if (token === '--auth-password' && next) {
|
|
254
|
+
options.authPassword = next;
|
|
255
|
+
index += 1;
|
|
256
|
+
} else if (token === '--auth-password-hash' && next) {
|
|
257
|
+
options.authPasswordHash = next;
|
|
258
|
+
index += 1;
|
|
259
|
+
} else if (token === '--auth-password-env' && next) {
|
|
260
|
+
options.authPasswordEnv = next;
|
|
261
|
+
index += 1;
|
|
262
|
+
} else if (token === '--fail-on-dialogue-deny') {
|
|
263
|
+
options.failOnDialogueDeny = true;
|
|
264
|
+
} else if (token === '--fail-on-gate-deny') {
|
|
265
|
+
options.failOnGateDeny = true;
|
|
266
|
+
} else if (token === '--fail-on-gate-non-allow') {
|
|
267
|
+
options.failOnGateNonAllow = true;
|
|
268
|
+
} else if (token === '--fail-on-runtime-non-allow') {
|
|
269
|
+
options.failOnRuntimeNonAllow = true;
|
|
270
|
+
} else if (token === '--fail-on-execute-blocked') {
|
|
271
|
+
options.failOnExecuteBlocked = true;
|
|
272
|
+
} else if (token === '--no-matrix') {
|
|
273
|
+
options.matrix = false;
|
|
274
|
+
} else if (token === '--matrix-template-dir' && next) {
|
|
275
|
+
options.matrixTemplateDir = next;
|
|
276
|
+
index += 1;
|
|
277
|
+
} else if (token === '--matrix-match' && next) {
|
|
278
|
+
options.matrixMatch = next;
|
|
279
|
+
index += 1;
|
|
280
|
+
} else if (token === '--matrix-include-all') {
|
|
281
|
+
options.matrixIncludeAll = true;
|
|
282
|
+
} else if (token === '--matrix-min-score' && next) {
|
|
283
|
+
options.matrixMinScore = Number(next);
|
|
284
|
+
index += 1;
|
|
285
|
+
} else if (token === '--matrix-min-valid-rate' && next) {
|
|
286
|
+
options.matrixMinValidRate = Number(next);
|
|
287
|
+
index += 1;
|
|
288
|
+
} else if (token === '--matrix-compare-with' && next) {
|
|
289
|
+
options.matrixCompareWith = next;
|
|
290
|
+
index += 1;
|
|
291
|
+
} else if (token === '--matrix-out' && next) {
|
|
292
|
+
options.matrixOut = next;
|
|
293
|
+
index += 1;
|
|
294
|
+
} else if (token === '--matrix-markdown-out' && next) {
|
|
295
|
+
options.matrixMarkdownOut = next;
|
|
296
|
+
index += 1;
|
|
297
|
+
} else if (token === '--matrix-signals' && next) {
|
|
298
|
+
options.matrixSignals = next;
|
|
299
|
+
index += 1;
|
|
300
|
+
} else if (token === '--matrix-fail-on-portfolio-fail') {
|
|
301
|
+
options.matrixFailOnPortfolioFail = true;
|
|
302
|
+
} else if (token === '--matrix-fail-on-regression') {
|
|
303
|
+
options.matrixFailOnRegression = true;
|
|
304
|
+
} else if (token === '--matrix-fail-on-error') {
|
|
305
|
+
options.matrixFailOnError = true;
|
|
306
|
+
} else if (token === '--json') {
|
|
307
|
+
options.json = true;
|
|
308
|
+
} else if (token === '--help' || token === '-h') {
|
|
309
|
+
printHelpAndExit(0);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
options.input = `${options.input || ''}`.trim();
|
|
314
|
+
options.provider = `${options.provider || ''}`.trim().toLowerCase() || DEFAULT_PROVIDER;
|
|
315
|
+
options.goal = `${options.goal || ''}`.trim();
|
|
316
|
+
options.goalFile = `${options.goalFile || ''}`.trim();
|
|
317
|
+
options.userId = `${options.userId || ''}`.trim() || DEFAULT_USER_ID;
|
|
318
|
+
options.sessionId = `${options.sessionId || ''}`.trim() || null;
|
|
319
|
+
options.executionMode = `${options.executionMode || ''}`.trim().toLowerCase() || 'suggestion';
|
|
320
|
+
options.businessMode = normalizeBusinessMode(options.businessMode);
|
|
321
|
+
options.businessModePolicy = `${options.businessModePolicy || ''}`.trim() || DEFAULT_BUSINESS_MODE_POLICY;
|
|
322
|
+
options.policy = `${options.policy || ''}`.trim() || null;
|
|
323
|
+
options.catalog = `${options.catalog || ''}`.trim() || null;
|
|
324
|
+
options.dialoguePolicy = `${options.dialoguePolicy || ''}`.trim() || null;
|
|
325
|
+
options.dialogueProfile = `${options.dialogueProfile || ''}`.trim().toLowerCase() || DEFAULT_DIALOGUE_PROFILE;
|
|
326
|
+
options.uiMode = `${options.uiMode || ''}`.trim().toLowerCase()
|
|
327
|
+
|| (options.dialogueProfile === 'system-maintainer' ? 'ops-console' : 'user-app');
|
|
328
|
+
options.dialogueOut = `${options.dialogueOut || ''}`.trim() || null;
|
|
329
|
+
options.runtimeMode = `${options.runtimeMode || ''}`.trim().toLowerCase() || DEFAULT_RUNTIME_MODE;
|
|
330
|
+
options.runtimeEnvironment = `${options.runtimeEnvironment || ''}`.trim().toLowerCase() || DEFAULT_RUNTIME_ENVIRONMENT;
|
|
331
|
+
options.runtimePolicy = `${options.runtimePolicy || ''}`.trim() || null;
|
|
332
|
+
options.runtimeOut = `${options.runtimeOut || ''}`.trim() || null;
|
|
333
|
+
options.authorizationTierPolicy = `${options.authorizationTierPolicy || ''}`.trim() || null;
|
|
334
|
+
options.authorizationTierOut = `${options.authorizationTierOut || ''}`.trim() || null;
|
|
335
|
+
options.contextContract = `${options.contextContract || ''}`.trim() || null;
|
|
336
|
+
options.moquiConfig = `${options.moquiConfig || ''}`.trim() || null;
|
|
337
|
+
options.outDir = `${options.outDir || ''}`.trim() || DEFAULT_OUT_DIR;
|
|
338
|
+
options.out = `${options.out || ''}`.trim() || null;
|
|
339
|
+
options.loopOut = `${options.loopOut || ''}`.trim() || null;
|
|
340
|
+
options.workOrderOut = `${options.workOrderOut || ''}`.trim() || null;
|
|
341
|
+
options.workOrderMarkdownOut = `${options.workOrderMarkdownOut || ''}`.trim() || null;
|
|
342
|
+
options.bridgeOutContext = `${options.bridgeOutContext || ''}`.trim() || null;
|
|
343
|
+
options.bridgeOutReport = `${options.bridgeOutReport || ''}`.trim() || null;
|
|
344
|
+
options.approvalActor = `${options.approvalActor || ''}`.trim() || null;
|
|
345
|
+
options.approvalActorRole = `${options.approvalActorRole || ''}`.trim().toLowerCase() || null;
|
|
346
|
+
options.approverActor = `${options.approverActor || ''}`.trim() || null;
|
|
347
|
+
options.approverActorRole = `${options.approverActorRole || ''}`.trim().toLowerCase() || null;
|
|
348
|
+
options.approvalRolePolicy = `${options.approvalRolePolicy || ''}`.trim() || null;
|
|
349
|
+
options.feedbackComment = `${options.feedbackComment || ''}`.trim() || null;
|
|
350
|
+
options.feedbackChannel = `${options.feedbackChannel || ''}`.trim().toLowerCase() || DEFAULT_FEEDBACK_CHANNEL;
|
|
351
|
+
options.feedbackTags = Array.from(new Set(options.feedbackTags.map(item => `${item || ''}`.trim().toLowerCase()).filter(Boolean)));
|
|
352
|
+
options.authPassword = options.authPassword == null ? null : `${options.authPassword}`;
|
|
353
|
+
options.authPasswordHash = options.authPasswordHash == null
|
|
354
|
+
? null
|
|
355
|
+
: `${options.authPasswordHash}`.trim().toLowerCase();
|
|
356
|
+
options.authPasswordEnv = `${options.authPasswordEnv || ''}`.trim() || null;
|
|
357
|
+
options.matrix = options.matrix !== false;
|
|
358
|
+
options.matrixTemplateDir = `${options.matrixTemplateDir || ''}`.trim() || null;
|
|
359
|
+
options.matrixMatch = `${options.matrixMatch || ''}`.trim() || null;
|
|
360
|
+
options.matrixCompareWith = `${options.matrixCompareWith || ''}`.trim() || null;
|
|
361
|
+
options.matrixOut = `${options.matrixOut || ''}`.trim() || null;
|
|
362
|
+
options.matrixMarkdownOut = `${options.matrixMarkdownOut || ''}`.trim() || null;
|
|
363
|
+
options.matrixSignals = `${options.matrixSignals || ''}`.trim() || DEFAULT_MATRIX_SIGNALS;
|
|
364
|
+
|
|
365
|
+
if (!options.input) {
|
|
366
|
+
throw new Error('--input is required.');
|
|
367
|
+
}
|
|
368
|
+
if (!options.goal && !options.goalFile) {
|
|
369
|
+
throw new Error('either --goal or --goal-file is required.');
|
|
370
|
+
}
|
|
371
|
+
if (!['moqui', 'generic'].includes(options.provider)) {
|
|
372
|
+
throw new Error('--provider must be one of: moqui, generic');
|
|
373
|
+
}
|
|
374
|
+
if (options.businessMode && !BUSINESS_MODES.has(options.businessMode)) {
|
|
375
|
+
throw new Error(`--business-mode must be one of: ${Array.from(BUSINESS_MODES).join(', ')}`);
|
|
376
|
+
}
|
|
377
|
+
options.businessModeState = applyBusinessModePolicy(options, explicitKeys, process.cwd());
|
|
378
|
+
if (!['suggestion', 'apply'].includes(options.executionMode)) {
|
|
379
|
+
throw new Error('--execution-mode must be one of: suggestion, apply');
|
|
380
|
+
}
|
|
381
|
+
if (!DIALOGUE_PROFILES.has(options.dialogueProfile)) {
|
|
382
|
+
throw new Error(`--dialogue-profile must be one of: ${Array.from(DIALOGUE_PROFILES).join(', ')}`);
|
|
383
|
+
}
|
|
384
|
+
if (!UI_MODES.has(options.uiMode)) {
|
|
385
|
+
throw new Error(`--ui-mode must be one of: ${Array.from(UI_MODES).join(', ')}`);
|
|
386
|
+
}
|
|
387
|
+
if (!RUNTIME_MODES.has(options.runtimeMode)) {
|
|
388
|
+
throw new Error(`--runtime-mode must be one of: ${Array.from(RUNTIME_MODES).join(', ')}`);
|
|
389
|
+
}
|
|
390
|
+
if (!RUNTIME_ENVIRONMENTS.has(options.runtimeEnvironment)) {
|
|
391
|
+
throw new Error(`--runtime-environment must be one of: ${Array.from(RUNTIME_ENVIRONMENTS).join(', ')}`);
|
|
392
|
+
}
|
|
393
|
+
if (options.feedbackScore != null) {
|
|
394
|
+
if (!Number.isFinite(options.feedbackScore) || options.feedbackScore < 0 || options.feedbackScore > 5) {
|
|
395
|
+
throw new Error('--feedback-score must be between 0 and 5.');
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
if (!FEEDBACK_CHANNELS.has(options.feedbackChannel)) {
|
|
399
|
+
throw new Error(`--feedback-channel must be one of: ${Array.from(FEEDBACK_CHANNELS).join(', ')}`);
|
|
400
|
+
}
|
|
401
|
+
if (options.authPasswordHash != null && !/^[a-fA-F0-9]{64}$/.test(options.authPasswordHash)) {
|
|
402
|
+
throw new Error('--auth-password-hash must be a sha256 hex string (64 chars).');
|
|
403
|
+
}
|
|
404
|
+
if (options.authPasswordEnv != null && `${options.authPasswordEnv || ''}`.trim().length === 0) {
|
|
405
|
+
throw new Error('--auth-password-env cannot be empty.');
|
|
406
|
+
}
|
|
407
|
+
if (!Number.isFinite(options.matrixMinScore) || options.matrixMinScore < 0 || options.matrixMinScore > 100) {
|
|
408
|
+
throw new Error('--matrix-min-score must be between 0 and 100.');
|
|
409
|
+
}
|
|
410
|
+
if (!Number.isFinite(options.matrixMinValidRate) || options.matrixMinValidRate < 0 || options.matrixMinValidRate > 100) {
|
|
411
|
+
throw new Error('--matrix-min-valid-rate must be between 0 and 100.');
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
return options;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function printHelpAndExit(code) {
|
|
418
|
+
const lines = [
|
|
419
|
+
'Usage: node scripts/interactive-flow.js --input <path> (--goal <text> | --goal-file <path>) [options]',
|
|
420
|
+
'',
|
|
421
|
+
'Pipeline:',
|
|
422
|
+
' context-bridge -> interactive-loop',
|
|
423
|
+
'',
|
|
424
|
+
'Options:',
|
|
425
|
+
' --input <path> Raw provider payload JSON path (required)',
|
|
426
|
+
` --provider <name> Provider dialect (moqui|generic, default: ${DEFAULT_PROVIDER})`,
|
|
427
|
+
' --goal <text> Business goal text',
|
|
428
|
+
' --goal-file <path> File containing business goal text',
|
|
429
|
+
` --user-id <id> User identifier (default: ${DEFAULT_USER_ID})`,
|
|
430
|
+
' --session-id <id> Session id (default: auto-generated)',
|
|
431
|
+
' --execution-mode <mode> suggestion|apply (default: suggestion)',
|
|
432
|
+
' --business-mode <mode> user-mode|ops-mode|dev-mode (preset routing profile)',
|
|
433
|
+
` --business-mode-policy <path> Business mode policy override (default: ${DEFAULT_BUSINESS_MODE_POLICY})`,
|
|
434
|
+
' --allow-mode-override Allow option overrides that conflict with business mode preset',
|
|
435
|
+
' --policy <path> Guardrail policy override',
|
|
436
|
+
' --catalog <path> High-risk catalog override',
|
|
437
|
+
' --dialogue-policy <path> Dialogue governance policy override',
|
|
438
|
+
` --dialogue-profile <name> business-user|system-maintainer (default: ${DEFAULT_DIALOGUE_PROFILE})`,
|
|
439
|
+
` --ui-mode <name> user-app|ops-console (default by dialogue profile)`,
|
|
440
|
+
' --dialogue-out <path> Dialogue governance report output path',
|
|
441
|
+
` --runtime-mode <name> user-assist|ops-fix|feature-dev (default: ${DEFAULT_RUNTIME_MODE})`,
|
|
442
|
+
` --runtime-environment <name> dev|staging|prod (default: ${DEFAULT_RUNTIME_ENVIRONMENT})`,
|
|
443
|
+
' --runtime-policy <path> Runtime mode/environment policy override',
|
|
444
|
+
' --runtime-out <path> Runtime policy evaluation output path',
|
|
445
|
+
' --authorization-tier-policy <path> Authorization tier policy override',
|
|
446
|
+
' --authorization-tier-out <path> Authorization tier evaluation output path',
|
|
447
|
+
' --context-contract <path> Context contract override',
|
|
448
|
+
' --no-strict-contract Do not fail when context contract validation has issues',
|
|
449
|
+
' --moqui-config <path> Moqui adapter runtime config',
|
|
450
|
+
` --out-dir <path> Flow artifact root (default: ${DEFAULT_OUT_DIR})`,
|
|
451
|
+
' --bridge-out-context <path> Bridge normalized context output path',
|
|
452
|
+
' --bridge-out-report <path> Bridge report output path',
|
|
453
|
+
' --loop-out <path> Interactive-loop summary output path',
|
|
454
|
+
' --work-order-out <path> Work-order JSON output path',
|
|
455
|
+
' --work-order-markdown-out <path> Work-order markdown output path',
|
|
456
|
+
' --out <path> Flow summary output path',
|
|
457
|
+
' --approval-actor <id> Approval workflow actor',
|
|
458
|
+
' --approval-actor-role <name> Approval workflow actor role',
|
|
459
|
+
' --approver-actor <id> Auto-approve actor',
|
|
460
|
+
' --approver-actor-role <name> Auto-approve actor role',
|
|
461
|
+
' --approval-role-policy <path> Approval role policy JSON path',
|
|
462
|
+
' --skip-submit Skip approval submit step',
|
|
463
|
+
' --auto-approve-low-risk Auto-approve low-risk allow plans',
|
|
464
|
+
' --auto-execute-low-risk Auto-run low-risk apply for allow+low plans',
|
|
465
|
+
' --allow-suggestion-apply Allow applying plans generated in suggestion mode',
|
|
466
|
+
' --live-apply Enable live apply mode',
|
|
467
|
+
' --no-dry-run Disable dry-run simulation',
|
|
468
|
+
' --feedback-score <0..5> Optional feedback score',
|
|
469
|
+
' --feedback-comment <text> Optional feedback comment',
|
|
470
|
+
' --feedback-tags <csv> Optional feedback tags',
|
|
471
|
+
` --feedback-channel <name> ui|cli|api|other (default: ${DEFAULT_FEEDBACK_CHANNEL})`,
|
|
472
|
+
' --auth-password <text> One-time password for protected execute action',
|
|
473
|
+
' --auth-password-hash <sha256> Password verifier hash override',
|
|
474
|
+
` --auth-password-env <name> Password hash env name (default: ${DEFAULT_AUTH_PASSWORD_HASH_ENV})`,
|
|
475
|
+
' --fail-on-dialogue-deny Exit code 2 if dialogue decision is deny',
|
|
476
|
+
' --fail-on-gate-deny Exit code 2 if gate decision is deny',
|
|
477
|
+
' --fail-on-gate-non-allow Exit code 2 if gate decision is deny/review-required',
|
|
478
|
+
' --fail-on-runtime-non-allow Exit code 2 if runtime decision is deny/review-required',
|
|
479
|
+
' --fail-on-execute-blocked Exit code 2 if auto execute is blocked/non-success',
|
|
480
|
+
' --no-matrix Disable matrix baseline snapshot stage',
|
|
481
|
+
' --matrix-template-dir <path> Template library path for matrix stage',
|
|
482
|
+
' --matrix-match <regex> Matrix selector regex',
|
|
483
|
+
' --matrix-include-all Score all templates in matrix stage',
|
|
484
|
+
` --matrix-min-score <0..100> Matrix min semantic score (default: ${DEFAULT_MATRIX_MIN_SCORE})`,
|
|
485
|
+
` --matrix-min-valid-rate <0..100> Matrix min valid-rate (default: ${DEFAULT_MATRIX_MIN_VALID_RATE})`,
|
|
486
|
+
' --matrix-compare-with <path> Previous matrix baseline report for regression comparison',
|
|
487
|
+
' --matrix-out <path> Matrix JSON report output path',
|
|
488
|
+
' --matrix-markdown-out <path> Matrix markdown report output path',
|
|
489
|
+
` --matrix-signals <path> Matrix signal stream JSONL (default: ${DEFAULT_MATRIX_SIGNALS})`,
|
|
490
|
+
' --matrix-fail-on-portfolio-fail Exit non-zero when matrix portfolio gate fails',
|
|
491
|
+
' --matrix-fail-on-regression Exit code 2 when matrix regressions are detected',
|
|
492
|
+
' --matrix-fail-on-error Exit non-zero when matrix stage fails unexpectedly',
|
|
493
|
+
' --json Print flow payload as JSON',
|
|
494
|
+
' -h, --help Show this help'
|
|
495
|
+
];
|
|
496
|
+
console.log(lines.join('\n'));
|
|
497
|
+
process.exit(code);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
function resolvePath(cwd, value) {
|
|
501
|
+
return path.isAbsolute(value) ? value : path.resolve(cwd, value);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function normalizeSessionId(value) {
|
|
505
|
+
const raw = `${value || ''}`.trim();
|
|
506
|
+
if (raw.length > 0) {
|
|
507
|
+
return raw.replace(/[^\w.-]/g, '-');
|
|
508
|
+
}
|
|
509
|
+
return `session-${crypto.randomUUID()}`;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function toRelative(cwd, absolutePath) {
|
|
513
|
+
return path.relative(cwd, absolutePath) || '.';
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function parseJsonOutput(text, label) {
|
|
517
|
+
const raw = `${text || ''}`.trim();
|
|
518
|
+
if (!raw) {
|
|
519
|
+
throw new Error(`${label} produced empty stdout`);
|
|
520
|
+
}
|
|
521
|
+
try {
|
|
522
|
+
return JSON.parse(raw);
|
|
523
|
+
} catch (error) {
|
|
524
|
+
throw new Error(`${label} returned invalid JSON: ${error.message}`);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
function tryParseJsonOutput(text) {
|
|
529
|
+
const raw = `${text || ''}`.trim();
|
|
530
|
+
if (!raw) {
|
|
531
|
+
return null;
|
|
532
|
+
}
|
|
533
|
+
try {
|
|
534
|
+
return JSON.parse(raw);
|
|
535
|
+
} catch (_error) {
|
|
536
|
+
return null;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
function buildCommandString(scriptPath, args, redactFlags = []) {
|
|
541
|
+
const redacted = new Set(redactFlags);
|
|
542
|
+
const maskedArgs = [];
|
|
543
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
544
|
+
const token = args[index];
|
|
545
|
+
maskedArgs.push(token);
|
|
546
|
+
if (redacted.has(token)) {
|
|
547
|
+
if (index + 1 < args.length) {
|
|
548
|
+
maskedArgs.push('***');
|
|
549
|
+
index += 1;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return [process.execPath, scriptPath, ...maskedArgs].join(' ');
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
function runScript(label, scriptPath, args, cwd, redactFlags = []) {
|
|
557
|
+
const result = spawnSync(process.execPath, [scriptPath, ...args], {
|
|
558
|
+
cwd,
|
|
559
|
+
encoding: 'utf8'
|
|
560
|
+
});
|
|
561
|
+
return {
|
|
562
|
+
exitCode: Number.isInteger(result.status) ? result.status : 1,
|
|
563
|
+
stdout: `${result.stdout || ''}`,
|
|
564
|
+
stderr: `${result.stderr || ''}`,
|
|
565
|
+
error: result.error || null,
|
|
566
|
+
command: buildCommandString(scriptPath, args, redactFlags)
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
async function appendJsonLine(filePath, payload) {
|
|
571
|
+
await fs.ensureDir(path.dirname(filePath));
|
|
572
|
+
await fs.appendFile(filePath, `${JSON.stringify(payload)}\n`, 'utf8');
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
async function main() {
|
|
576
|
+
const options = parseArgs(process.argv.slice(2));
|
|
577
|
+
const cwd = process.cwd();
|
|
578
|
+
const sessionId = normalizeSessionId(options.sessionId);
|
|
579
|
+
const outRoot = resolvePath(cwd, options.outDir);
|
|
580
|
+
const sessionDir = path.join(outRoot, sessionId);
|
|
581
|
+
|
|
582
|
+
const bridgeOutContextPath = options.bridgeOutContext
|
|
583
|
+
? resolvePath(cwd, options.bridgeOutContext)
|
|
584
|
+
: path.join(sessionDir, 'interactive-page-context.normalized.json');
|
|
585
|
+
const bridgeOutReportPath = options.bridgeOutReport
|
|
586
|
+
? resolvePath(cwd, options.bridgeOutReport)
|
|
587
|
+
: path.join(sessionDir, 'interactive-context-bridge.json');
|
|
588
|
+
const loopOutPath = options.loopOut
|
|
589
|
+
? resolvePath(cwd, options.loopOut)
|
|
590
|
+
: path.join(sessionDir, 'interactive-customization-loop.summary.json');
|
|
591
|
+
const flowOutPath = options.out
|
|
592
|
+
? resolvePath(cwd, options.out)
|
|
593
|
+
: path.join(sessionDir, 'interactive-flow.summary.json');
|
|
594
|
+
const matrixOutPath = options.matrixOut
|
|
595
|
+
? resolvePath(cwd, options.matrixOut)
|
|
596
|
+
: path.join(sessionDir, 'moqui-template-baseline.json');
|
|
597
|
+
const matrixMarkdownOutPath = options.matrixMarkdownOut
|
|
598
|
+
? resolvePath(cwd, options.matrixMarkdownOut)
|
|
599
|
+
: path.join(sessionDir, 'moqui-template-baseline.md');
|
|
600
|
+
const matrixSignalsPath = resolvePath(cwd, options.matrixSignals);
|
|
601
|
+
const matrixSignalPath = path.join(sessionDir, 'interactive-matrix-signal.json');
|
|
602
|
+
|
|
603
|
+
await fs.ensureDir(sessionDir);
|
|
604
|
+
|
|
605
|
+
const inputPath = resolvePath(cwd, options.input);
|
|
606
|
+
const bridgeArgs = [
|
|
607
|
+
'--input', inputPath,
|
|
608
|
+
'--provider', options.provider,
|
|
609
|
+
'--out-context', bridgeOutContextPath,
|
|
610
|
+
'--out-report', bridgeOutReportPath,
|
|
611
|
+
'--json'
|
|
612
|
+
];
|
|
613
|
+
if (options.contextContract) {
|
|
614
|
+
bridgeArgs.push('--context-contract', resolvePath(cwd, options.contextContract));
|
|
615
|
+
}
|
|
616
|
+
if (!options.strictContract) {
|
|
617
|
+
bridgeArgs.push('--no-strict-contract');
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
const bridgeResult = runScript('interactive-context-bridge', SCRIPT_CONTEXT_BRIDGE, bridgeArgs, cwd);
|
|
621
|
+
if (bridgeResult.error) {
|
|
622
|
+
throw new Error(`interactive-context-bridge failed: ${bridgeResult.error.message}`);
|
|
623
|
+
}
|
|
624
|
+
if (bridgeResult.exitCode !== 0) {
|
|
625
|
+
const stderr = bridgeResult.stderr.trim();
|
|
626
|
+
throw new Error(
|
|
627
|
+
`interactive-context-bridge failed with exit code ${bridgeResult.exitCode}${stderr ? `: ${stderr}` : ''}`
|
|
628
|
+
);
|
|
629
|
+
}
|
|
630
|
+
const bridgePayload = parseJsonOutput(bridgeResult.stdout, 'interactive-context-bridge');
|
|
631
|
+
|
|
632
|
+
const loopArgs = [
|
|
633
|
+
'--context', bridgeOutContextPath,
|
|
634
|
+
'--execution-mode', options.executionMode,
|
|
635
|
+
'--user-id', options.userId,
|
|
636
|
+
'--session-id', sessionId,
|
|
637
|
+
'--out', loopOutPath,
|
|
638
|
+
'--json'
|
|
639
|
+
];
|
|
640
|
+
if (options.businessModeState && options.businessModeState.mode_explicit === true) {
|
|
641
|
+
loopArgs.push('--business-mode', options.businessMode);
|
|
642
|
+
if (options.businessModePolicy) {
|
|
643
|
+
loopArgs.push('--business-mode-policy', resolvePath(cwd, options.businessModePolicy));
|
|
644
|
+
}
|
|
645
|
+
if (options.allowModeOverride) {
|
|
646
|
+
loopArgs.push('--allow-mode-override');
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
if (options.goal) {
|
|
650
|
+
loopArgs.push('--goal', options.goal);
|
|
651
|
+
} else {
|
|
652
|
+
loopArgs.push('--goal-file', resolvePath(cwd, options.goalFile));
|
|
653
|
+
}
|
|
654
|
+
if (options.policy) {
|
|
655
|
+
loopArgs.push('--policy', resolvePath(cwd, options.policy));
|
|
656
|
+
}
|
|
657
|
+
if (options.catalog) {
|
|
658
|
+
loopArgs.push('--catalog', resolvePath(cwd, options.catalog));
|
|
659
|
+
}
|
|
660
|
+
if (options.dialoguePolicy) {
|
|
661
|
+
loopArgs.push('--dialogue-policy', resolvePath(cwd, options.dialoguePolicy));
|
|
662
|
+
}
|
|
663
|
+
if (options.dialogueProfile) {
|
|
664
|
+
loopArgs.push('--dialogue-profile', options.dialogueProfile);
|
|
665
|
+
}
|
|
666
|
+
if (options.uiMode) {
|
|
667
|
+
loopArgs.push('--ui-mode', options.uiMode);
|
|
668
|
+
}
|
|
669
|
+
if (options.dialogueOut) {
|
|
670
|
+
loopArgs.push('--dialogue-out', resolvePath(cwd, options.dialogueOut));
|
|
671
|
+
}
|
|
672
|
+
if (options.runtimeMode) {
|
|
673
|
+
loopArgs.push('--runtime-mode', options.runtimeMode);
|
|
674
|
+
}
|
|
675
|
+
if (options.runtimeEnvironment) {
|
|
676
|
+
loopArgs.push('--runtime-environment', options.runtimeEnvironment);
|
|
677
|
+
}
|
|
678
|
+
if (options.runtimePolicy) {
|
|
679
|
+
loopArgs.push('--runtime-policy', resolvePath(cwd, options.runtimePolicy));
|
|
680
|
+
}
|
|
681
|
+
if (options.runtimeOut) {
|
|
682
|
+
loopArgs.push('--runtime-out', resolvePath(cwd, options.runtimeOut));
|
|
683
|
+
}
|
|
684
|
+
if (options.authorizationTierPolicy) {
|
|
685
|
+
loopArgs.push('--authorization-tier-policy', resolvePath(cwd, options.authorizationTierPolicy));
|
|
686
|
+
}
|
|
687
|
+
if (options.authorizationTierOut) {
|
|
688
|
+
loopArgs.push('--authorization-tier-out', resolvePath(cwd, options.authorizationTierOut));
|
|
689
|
+
}
|
|
690
|
+
if (options.contextContract) {
|
|
691
|
+
loopArgs.push('--context-contract', resolvePath(cwd, options.contextContract));
|
|
692
|
+
}
|
|
693
|
+
if (!options.strictContract) {
|
|
694
|
+
loopArgs.push('--no-strict-contract');
|
|
695
|
+
}
|
|
696
|
+
if (options.moquiConfig) {
|
|
697
|
+
loopArgs.push('--moqui-config', resolvePath(cwd, options.moquiConfig));
|
|
698
|
+
}
|
|
699
|
+
if (options.workOrderOut) {
|
|
700
|
+
loopArgs.push('--work-order-out', resolvePath(cwd, options.workOrderOut));
|
|
701
|
+
}
|
|
702
|
+
if (options.workOrderMarkdownOut) {
|
|
703
|
+
loopArgs.push('--work-order-markdown-out', resolvePath(cwd, options.workOrderMarkdownOut));
|
|
704
|
+
}
|
|
705
|
+
if (options.approvalActor) {
|
|
706
|
+
loopArgs.push('--approval-actor', options.approvalActor);
|
|
707
|
+
}
|
|
708
|
+
if (options.approvalActorRole) {
|
|
709
|
+
loopArgs.push('--approval-actor-role', options.approvalActorRole);
|
|
710
|
+
}
|
|
711
|
+
if (options.approverActor) {
|
|
712
|
+
loopArgs.push('--approver-actor', options.approverActor);
|
|
713
|
+
}
|
|
714
|
+
if (options.approverActorRole) {
|
|
715
|
+
loopArgs.push('--approver-actor-role', options.approverActorRole);
|
|
716
|
+
}
|
|
717
|
+
if (options.approvalRolePolicy) {
|
|
718
|
+
loopArgs.push('--approval-role-policy', resolvePath(cwd, options.approvalRolePolicy));
|
|
719
|
+
}
|
|
720
|
+
if (options.skipSubmit) {
|
|
721
|
+
loopArgs.push('--skip-submit');
|
|
722
|
+
}
|
|
723
|
+
if (options.autoApproveLowRisk) {
|
|
724
|
+
loopArgs.push('--auto-approve-low-risk');
|
|
725
|
+
}
|
|
726
|
+
if (options.autoExecuteLowRisk) {
|
|
727
|
+
loopArgs.push('--auto-execute-low-risk');
|
|
728
|
+
}
|
|
729
|
+
if (options.allowSuggestionApply) {
|
|
730
|
+
loopArgs.push('--allow-suggestion-apply');
|
|
731
|
+
}
|
|
732
|
+
if (options.liveApply) {
|
|
733
|
+
loopArgs.push('--live-apply');
|
|
734
|
+
}
|
|
735
|
+
if (!options.dryRun) {
|
|
736
|
+
loopArgs.push('--no-dry-run');
|
|
737
|
+
}
|
|
738
|
+
if (options.feedbackScore != null) {
|
|
739
|
+
loopArgs.push('--feedback-score', String(options.feedbackScore));
|
|
740
|
+
}
|
|
741
|
+
if (options.feedbackComment) {
|
|
742
|
+
loopArgs.push('--feedback-comment', options.feedbackComment);
|
|
743
|
+
}
|
|
744
|
+
if (options.feedbackTags.length > 0) {
|
|
745
|
+
loopArgs.push('--feedback-tags', options.feedbackTags.join(','));
|
|
746
|
+
}
|
|
747
|
+
if (options.feedbackChannel) {
|
|
748
|
+
loopArgs.push('--feedback-channel', options.feedbackChannel);
|
|
749
|
+
}
|
|
750
|
+
if (options.authPassword) {
|
|
751
|
+
loopArgs.push('--auth-password', options.authPassword);
|
|
752
|
+
}
|
|
753
|
+
if (options.authPasswordHash) {
|
|
754
|
+
loopArgs.push('--auth-password-hash', options.authPasswordHash);
|
|
755
|
+
}
|
|
756
|
+
if (options.authPasswordEnv) {
|
|
757
|
+
loopArgs.push('--auth-password-env', options.authPasswordEnv);
|
|
758
|
+
}
|
|
759
|
+
if (options.failOnDialogueDeny) {
|
|
760
|
+
loopArgs.push('--fail-on-dialogue-deny');
|
|
761
|
+
}
|
|
762
|
+
if (options.failOnGateDeny) {
|
|
763
|
+
loopArgs.push('--fail-on-gate-deny');
|
|
764
|
+
}
|
|
765
|
+
if (options.failOnGateNonAllow) {
|
|
766
|
+
loopArgs.push('--fail-on-gate-non-allow');
|
|
767
|
+
}
|
|
768
|
+
if (options.failOnRuntimeNonAllow) {
|
|
769
|
+
loopArgs.push('--fail-on-runtime-non-allow');
|
|
770
|
+
}
|
|
771
|
+
if (options.failOnExecuteBlocked) {
|
|
772
|
+
loopArgs.push('--fail-on-execute-blocked');
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
const loopResult = runScript(
|
|
776
|
+
'interactive-customization-loop',
|
|
777
|
+
SCRIPT_INTERACTIVE_LOOP,
|
|
778
|
+
loopArgs,
|
|
779
|
+
cwd,
|
|
780
|
+
['--auth-password', '--auth-password-hash']
|
|
781
|
+
);
|
|
782
|
+
if (loopResult.error) {
|
|
783
|
+
throw new Error(`interactive-customization-loop failed: ${loopResult.error.message}`);
|
|
784
|
+
}
|
|
785
|
+
const loopPayload = parseJsonOutput(loopResult.stdout, 'interactive-customization-loop');
|
|
786
|
+
|
|
787
|
+
let matrixResult = null;
|
|
788
|
+
let matrixPayload = null;
|
|
789
|
+
let matrixSignal = null;
|
|
790
|
+
let matrixStageStatus = 'skipped';
|
|
791
|
+
if (options.matrix) {
|
|
792
|
+
const matrixArgs = [
|
|
793
|
+
'--out', matrixOutPath,
|
|
794
|
+
'--markdown-out', matrixMarkdownOutPath,
|
|
795
|
+
'--min-score', String(options.matrixMinScore),
|
|
796
|
+
'--min-valid-rate', String(options.matrixMinValidRate),
|
|
797
|
+
'--json'
|
|
798
|
+
];
|
|
799
|
+
if (options.matrixTemplateDir) {
|
|
800
|
+
matrixArgs.push('--template-dir', resolvePath(cwd, options.matrixTemplateDir));
|
|
801
|
+
}
|
|
802
|
+
if (options.matrixMatch) {
|
|
803
|
+
matrixArgs.push('--match', options.matrixMatch);
|
|
804
|
+
}
|
|
805
|
+
if (options.matrixIncludeAll) {
|
|
806
|
+
matrixArgs.push('--include-all');
|
|
807
|
+
}
|
|
808
|
+
if (options.matrixCompareWith) {
|
|
809
|
+
matrixArgs.push('--compare-with', resolvePath(cwd, options.matrixCompareWith));
|
|
810
|
+
}
|
|
811
|
+
if (options.matrixFailOnPortfolioFail) {
|
|
812
|
+
matrixArgs.push('--fail-on-portfolio-fail');
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
matrixResult = runScript('moqui-template-baseline', SCRIPT_MOQUI_BASELINE, matrixArgs, cwd);
|
|
816
|
+
if (matrixResult.error) {
|
|
817
|
+
matrixStageStatus = 'error';
|
|
818
|
+
if (options.matrixFailOnError) {
|
|
819
|
+
throw new Error(`moqui-template-baseline failed: ${matrixResult.error.message}`);
|
|
820
|
+
}
|
|
821
|
+
} else {
|
|
822
|
+
matrixPayload = tryParseJsonOutput(matrixResult.stdout);
|
|
823
|
+
matrixStageStatus = matrixResult.exitCode === 0 ? 'completed' : 'non-zero-exit';
|
|
824
|
+
if (!matrixPayload && options.matrixFailOnError) {
|
|
825
|
+
throw new Error('moqui-template-baseline returned invalid JSON payload.');
|
|
826
|
+
}
|
|
827
|
+
if (matrixPayload) {
|
|
828
|
+
const summary = matrixPayload && matrixPayload.summary ? matrixPayload.summary : {};
|
|
829
|
+
const compare = matrixPayload && matrixPayload.compare ? matrixPayload.compare : {};
|
|
830
|
+
const regressions = Array.isArray(compare.coverage_matrix_regressions)
|
|
831
|
+
? compare.coverage_matrix_regressions
|
|
832
|
+
: [];
|
|
833
|
+
|
|
834
|
+
matrixSignal = {
|
|
835
|
+
mode: 'interactive-matrix-signal',
|
|
836
|
+
generated_at: new Date().toISOString(),
|
|
837
|
+
session_id: sessionId,
|
|
838
|
+
provider: options.provider,
|
|
839
|
+
matrix: {
|
|
840
|
+
stage_status: matrixStageStatus,
|
|
841
|
+
exit_code: matrixResult.exitCode,
|
|
842
|
+
scoped_templates: Number.isFinite(Number(summary.scoped_templates))
|
|
843
|
+
? Number(summary.scoped_templates)
|
|
844
|
+
: null,
|
|
845
|
+
portfolio_passed: summary.portfolio_passed === true,
|
|
846
|
+
avg_score: Number.isFinite(Number(summary.avg_score))
|
|
847
|
+
? Number(summary.avg_score)
|
|
848
|
+
: null,
|
|
849
|
+
valid_rate_percent: Number.isFinite(Number(summary.valid_rate_percent))
|
|
850
|
+
? Number(summary.valid_rate_percent)
|
|
851
|
+
: null,
|
|
852
|
+
baseline_failed: Number.isFinite(Number(summary.baseline_failed))
|
|
853
|
+
? Number(summary.baseline_failed)
|
|
854
|
+
: null,
|
|
855
|
+
regression_count: regressions.length,
|
|
856
|
+
regressions: regressions.map((item) => ({
|
|
857
|
+
metric: item && item.metric ? String(item.metric) : null,
|
|
858
|
+
delta_rate_percent: Number.isFinite(Number(item && item.delta_rate_percent))
|
|
859
|
+
? Number(item.delta_rate_percent)
|
|
860
|
+
: null
|
|
861
|
+
})),
|
|
862
|
+
thresholds: {
|
|
863
|
+
min_score: options.matrixMinScore,
|
|
864
|
+
min_valid_rate_percent: options.matrixMinValidRate
|
|
865
|
+
},
|
|
866
|
+
compare_with: options.matrixCompareWith
|
|
867
|
+
? toRelative(cwd, resolvePath(cwd, options.matrixCompareWith))
|
|
868
|
+
: null,
|
|
869
|
+
output_json: toRelative(cwd, matrixOutPath),
|
|
870
|
+
output_markdown: toRelative(cwd, matrixMarkdownOutPath)
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
|
|
874
|
+
await fs.ensureDir(path.dirname(matrixSignalPath));
|
|
875
|
+
await fs.writeJson(matrixSignalPath, matrixSignal, { spaces: 2 });
|
|
876
|
+
await appendJsonLine(matrixSignalsPath, matrixSignal);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
const matrixRegressionCount = matrixSignal && matrixSignal.matrix
|
|
882
|
+
? Number(matrixSignal.matrix.regression_count || 0)
|
|
883
|
+
: null;
|
|
884
|
+
const matrixPortfolioPassed = matrixSignal && matrixSignal.matrix
|
|
885
|
+
? matrixSignal.matrix.portfolio_passed === true
|
|
886
|
+
: null;
|
|
887
|
+
|
|
888
|
+
const flowPayload = {
|
|
889
|
+
mode: 'interactive-flow',
|
|
890
|
+
generated_at: new Date().toISOString(),
|
|
891
|
+
session_id: sessionId,
|
|
892
|
+
provider: options.provider,
|
|
893
|
+
routing: {
|
|
894
|
+
business_mode: options.businessMode,
|
|
895
|
+
mode_explicit: options.businessModeState ? options.businessModeState.mode_explicit === true : false,
|
|
896
|
+
allow_mode_override: options.allowModeOverride === true,
|
|
897
|
+
policy: options.businessModeState
|
|
898
|
+
? toRelative(cwd, options.businessModeState.policy_path)
|
|
899
|
+
: toRelative(cwd, resolvePath(cwd, options.businessModePolicy)),
|
|
900
|
+
policy_source: options.businessModeState ? options.businessModeState.policy_source : 'unknown'
|
|
901
|
+
},
|
|
902
|
+
pipeline: {
|
|
903
|
+
bridge: {
|
|
904
|
+
exit_code: bridgeResult.exitCode,
|
|
905
|
+
command: bridgeResult.command,
|
|
906
|
+
payload: bridgePayload
|
|
907
|
+
},
|
|
908
|
+
loop: {
|
|
909
|
+
exit_code: loopResult.exitCode,
|
|
910
|
+
command: loopResult.command,
|
|
911
|
+
payload: loopPayload
|
|
912
|
+
},
|
|
913
|
+
matrix: {
|
|
914
|
+
enabled: options.matrix,
|
|
915
|
+
status: matrixStageStatus,
|
|
916
|
+
exit_code: matrixResult ? matrixResult.exitCode : null,
|
|
917
|
+
command: matrixResult ? matrixResult.command : null,
|
|
918
|
+
payload: matrixPayload
|
|
919
|
+
}
|
|
920
|
+
},
|
|
921
|
+
summary: {
|
|
922
|
+
status: loopPayload && loopPayload.summary ? loopPayload.summary.status : null,
|
|
923
|
+
dialogue_decision: loopPayload && loopPayload.dialogue ? loopPayload.dialogue.decision : null,
|
|
924
|
+
dialogue_authorization_decision: loopPayload && loopPayload.summary
|
|
925
|
+
? loopPayload.summary.dialogue_authorization_decision || null
|
|
926
|
+
: null,
|
|
927
|
+
ui_mode: loopPayload && loopPayload.summary ? loopPayload.summary.ui_mode || null : options.uiMode,
|
|
928
|
+
dialogue_profile: loopPayload && loopPayload.dialogue ? loopPayload.dialogue.profile || null : null,
|
|
929
|
+
gate_decision: loopPayload && loopPayload.gate ? loopPayload.gate.decision : null,
|
|
930
|
+
runtime_decision: loopPayload && loopPayload.runtime ? loopPayload.runtime.decision : null,
|
|
931
|
+
authorization_tier_decision: loopPayload && loopPayload.authorization_tier
|
|
932
|
+
? loopPayload.authorization_tier.decision || null
|
|
933
|
+
: null,
|
|
934
|
+
runtime_mode: loopPayload && loopPayload.runtime ? loopPayload.runtime.mode : null,
|
|
935
|
+
runtime_environment: loopPayload && loopPayload.runtime ? loopPayload.runtime.environment : null,
|
|
936
|
+
execution_result: loopPayload && loopPayload.execution ? loopPayload.execution.result : null,
|
|
937
|
+
execution_reason: loopPayload && loopPayload.execution ? loopPayload.execution.reason || null : null,
|
|
938
|
+
execution_block_reason_category: loopPayload && loopPayload.summary
|
|
939
|
+
? loopPayload.summary.execution_block_reason_category || null
|
|
940
|
+
: null,
|
|
941
|
+
business_mode: options.businessMode,
|
|
942
|
+
execution_block_remediation_hint: loopPayload && loopPayload.summary
|
|
943
|
+
? loopPayload.summary.execution_block_remediation_hint || null
|
|
944
|
+
: null,
|
|
945
|
+
work_order_id: loopPayload && loopPayload.work_order ? loopPayload.work_order.work_order_id || null : null,
|
|
946
|
+
work_order_status: loopPayload && loopPayload.work_order ? loopPayload.work_order.status || null : null,
|
|
947
|
+
authorization_password_required: loopPayload && loopPayload.approval && loopPayload.approval.authorization
|
|
948
|
+
? loopPayload.approval.authorization.password_required === true
|
|
949
|
+
: null,
|
|
950
|
+
authorization_password_verified: loopPayload && loopPayload.approval && loopPayload.approval.authorization
|
|
951
|
+
? loopPayload.approval.authorization.password_verified === true
|
|
952
|
+
: null,
|
|
953
|
+
authorization_execute_roles: loopPayload &&
|
|
954
|
+
loopPayload.approval &&
|
|
955
|
+
loopPayload.approval.authorization &&
|
|
956
|
+
loopPayload.approval.authorization.role_requirements &&
|
|
957
|
+
Array.isArray(loopPayload.approval.authorization.role_requirements.execute)
|
|
958
|
+
? loopPayload.approval.authorization.role_requirements.execute
|
|
959
|
+
: [],
|
|
960
|
+
matrix_status: matrixStageStatus,
|
|
961
|
+
matrix_portfolio_passed: matrixPortfolioPassed,
|
|
962
|
+
matrix_regression_count: matrixRegressionCount
|
|
963
|
+
},
|
|
964
|
+
artifacts: {
|
|
965
|
+
input: toRelative(cwd, inputPath),
|
|
966
|
+
bridge_context_json: toRelative(cwd, bridgeOutContextPath),
|
|
967
|
+
bridge_report_json: toRelative(cwd, bridgeOutReportPath),
|
|
968
|
+
dialogue_json: loopPayload && loopPayload.artifacts ? loopPayload.artifacts.dialogue_json || null : null,
|
|
969
|
+
runtime_json: loopPayload && loopPayload.artifacts ? loopPayload.artifacts.runtime_json || null : null,
|
|
970
|
+
authorization_tier_json: loopPayload && loopPayload.artifacts ? loopPayload.artifacts.authorization_tier_json || null : null,
|
|
971
|
+
work_order_json: loopPayload && loopPayload.artifacts ? loopPayload.artifacts.work_order_json || null : null,
|
|
972
|
+
work_order_markdown: loopPayload && loopPayload.artifacts ? loopPayload.artifacts.work_order_md || null : null,
|
|
973
|
+
loop_summary_json: toRelative(cwd, loopOutPath),
|
|
974
|
+
flow_summary_json: toRelative(cwd, flowOutPath),
|
|
975
|
+
matrix_summary_json: options.matrix ? toRelative(cwd, matrixOutPath) : null,
|
|
976
|
+
matrix_summary_markdown: options.matrix ? toRelative(cwd, matrixMarkdownOutPath) : null,
|
|
977
|
+
matrix_signal_json: options.matrix && matrixSignal ? toRelative(cwd, matrixSignalPath) : null,
|
|
978
|
+
matrix_signals_jsonl: options.matrix && matrixSignal ? toRelative(cwd, matrixSignalsPath) : null
|
|
979
|
+
}
|
|
980
|
+
};
|
|
981
|
+
|
|
982
|
+
await fs.ensureDir(path.dirname(flowOutPath));
|
|
983
|
+
await fs.writeJson(flowOutPath, flowPayload, { spaces: 2 });
|
|
984
|
+
|
|
985
|
+
if (options.json) {
|
|
986
|
+
process.stdout.write(`${JSON.stringify(flowPayload, null, 2)}\n`);
|
|
987
|
+
} else {
|
|
988
|
+
process.stdout.write('Interactive flow completed.\n');
|
|
989
|
+
process.stdout.write(`- Session: ${flowPayload.session_id}\n`);
|
|
990
|
+
process.stdout.write(`- Status: ${flowPayload.summary.status || 'unknown'}\n`);
|
|
991
|
+
process.stdout.write(`- Dialogue decision: ${flowPayload.summary.dialogue_decision || 'n/a'}\n`);
|
|
992
|
+
process.stdout.write(`- Dialogue authorization: ${flowPayload.summary.dialogue_authorization_decision || 'n/a'}\n`);
|
|
993
|
+
process.stdout.write(`- UI mode: ${flowPayload.summary.ui_mode || 'n/a'}\n`);
|
|
994
|
+
process.stdout.write(`- Authorization tier: ${flowPayload.summary.authorization_tier_decision || 'n/a'}\n`);
|
|
995
|
+
process.stdout.write(`- Gate decision: ${flowPayload.summary.gate_decision || 'n/a'}\n`);
|
|
996
|
+
process.stdout.write(`- Runtime decision: ${flowPayload.summary.runtime_decision || 'n/a'}\n`);
|
|
997
|
+
process.stdout.write(`- Work-order: ${flowPayload.summary.work_order_status || 'n/a'} (${flowPayload.summary.work_order_id || 'n/a'})\n`);
|
|
998
|
+
if (options.matrix) {
|
|
999
|
+
process.stdout.write(`- Matrix status: ${flowPayload.summary.matrix_status || 'unknown'}\n`);
|
|
1000
|
+
process.stdout.write(`- Matrix portfolio pass: ${flowPayload.summary.matrix_portfolio_passed === true ? 'yes' : 'no'}\n`);
|
|
1001
|
+
process.stdout.write(`- Matrix regressions: ${flowPayload.summary.matrix_regression_count == null ? 'n/a' : flowPayload.summary.matrix_regression_count}\n`);
|
|
1002
|
+
}
|
|
1003
|
+
process.stdout.write(`- Bridge context: ${flowPayload.artifacts.bridge_context_json}\n`);
|
|
1004
|
+
process.stdout.write(`- Flow summary: ${flowPayload.artifacts.flow_summary_json}\n`);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
let finalExitCode = 0;
|
|
1008
|
+
if (loopResult.exitCode !== 0) {
|
|
1009
|
+
finalExitCode = loopResult.exitCode;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
if (options.matrix) {
|
|
1013
|
+
if (matrixResult && matrixResult.error && options.matrixFailOnError && finalExitCode === 0) {
|
|
1014
|
+
finalExitCode = 2;
|
|
1015
|
+
}
|
|
1016
|
+
if (matrixResult && !matrixResult.error && finalExitCode === 0) {
|
|
1017
|
+
if (options.matrixFailOnError && matrixResult.exitCode !== 0) {
|
|
1018
|
+
finalExitCode = matrixResult.exitCode;
|
|
1019
|
+
} else if (options.matrixFailOnPortfolioFail && matrixResult.exitCode !== 0) {
|
|
1020
|
+
finalExitCode = matrixResult.exitCode;
|
|
1021
|
+
}
|
|
1022
|
+
if (options.matrixFailOnRegression && Number(matrixRegressionCount) > 0 && finalExitCode === 0) {
|
|
1023
|
+
finalExitCode = 2;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
if (finalExitCode !== 0) {
|
|
1029
|
+
process.exitCode = finalExitCode;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
if (require.main === module) {
|
|
1034
|
+
main().catch((error) => {
|
|
1035
|
+
console.error(`Interactive flow failed: ${error.message}`);
|
|
1036
|
+
process.exit(1);
|
|
1037
|
+
});
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
module.exports = {
|
|
1041
|
+
DEFAULT_PROVIDER,
|
|
1042
|
+
DEFAULT_OUT_DIR,
|
|
1043
|
+
DEFAULT_USER_ID,
|
|
1044
|
+
DEFAULT_DIALOGUE_PROFILE,
|
|
1045
|
+
DEFAULT_RUNTIME_MODE,
|
|
1046
|
+
DEFAULT_RUNTIME_ENVIRONMENT,
|
|
1047
|
+
DIALOGUE_PROFILES,
|
|
1048
|
+
RUNTIME_MODES,
|
|
1049
|
+
RUNTIME_ENVIRONMENTS,
|
|
1050
|
+
parseArgs,
|
|
1051
|
+
resolvePath,
|
|
1052
|
+
normalizeSessionId,
|
|
1053
|
+
parseJsonOutput,
|
|
1054
|
+
tryParseJsonOutput,
|
|
1055
|
+
buildCommandString,
|
|
1056
|
+
runScript,
|
|
1057
|
+
appendJsonLine,
|
|
1058
|
+
main
|
|
1059
|
+
};
|