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,393 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const yaml = require('js-yaml');
|
|
7
|
+
|
|
8
|
+
const DEFAULT_GOVERNANCE = {
|
|
9
|
+
review_cadence: 'weekly',
|
|
10
|
+
stable_layers: [
|
|
11
|
+
'CORE_PRINCIPLES.md',
|
|
12
|
+
'ENVIRONMENT.md',
|
|
13
|
+
'RULES_GUIDE.md'
|
|
14
|
+
],
|
|
15
|
+
files: {
|
|
16
|
+
'CORE_PRINCIPLES.md': {
|
|
17
|
+
max_lines: 96,
|
|
18
|
+
max_headings: 16,
|
|
19
|
+
max_history_entries: 0,
|
|
20
|
+
allow_spec_refs: false,
|
|
21
|
+
allow_version_markers: false,
|
|
22
|
+
allow_checklists: false
|
|
23
|
+
},
|
|
24
|
+
'ENVIRONMENT.md': {
|
|
25
|
+
max_lines: 36,
|
|
26
|
+
max_headings: 8,
|
|
27
|
+
max_history_entries: 0,
|
|
28
|
+
allow_spec_refs: false,
|
|
29
|
+
allow_version_markers: false,
|
|
30
|
+
allow_checklists: false
|
|
31
|
+
},
|
|
32
|
+
'CURRENT_CONTEXT.md': {
|
|
33
|
+
max_lines: 24,
|
|
34
|
+
max_headings: 6,
|
|
35
|
+
max_history_entries: 3,
|
|
36
|
+
allow_spec_refs: true,
|
|
37
|
+
allow_version_markers: true,
|
|
38
|
+
allow_checklists: false
|
|
39
|
+
},
|
|
40
|
+
'RULES_GUIDE.md': {
|
|
41
|
+
max_lines: 36,
|
|
42
|
+
max_headings: 8,
|
|
43
|
+
max_history_entries: 0,
|
|
44
|
+
allow_spec_refs: false,
|
|
45
|
+
allow_version_markers: false,
|
|
46
|
+
allow_checklists: false
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
canonical_terms: {
|
|
50
|
+
errorbook: {
|
|
51
|
+
aliases: ['错题', '错题本'],
|
|
52
|
+
guidance: 'Reuse the existing errorbook capability instead of inventing a parallel mistake-book mode in steering.'
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
relocation_targets: {
|
|
56
|
+
long_lived_principles: '.sce/steering/CORE_PRINCIPLES.md',
|
|
57
|
+
project_operating_rules: '.sce/steering/ENVIRONMENT.md',
|
|
58
|
+
active_delivery_context: '.sce/steering/CURRENT_CONTEXT.md',
|
|
59
|
+
detailed_workflow_and_examples: 'docs/steering-governance.md',
|
|
60
|
+
transient_task_state: '.sce/specs/<spec>/tasks.md',
|
|
61
|
+
historical_decisions_and_evidence: '.sce/specs/<spec>/custom/'
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
function parseArgs(argv = process.argv.slice(2)) {
|
|
66
|
+
const options = {
|
|
67
|
+
projectPath: process.cwd(),
|
|
68
|
+
json: false,
|
|
69
|
+
failOnError: false,
|
|
70
|
+
failOnWarning: false,
|
|
71
|
+
out: null
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
75
|
+
const value = argv[index];
|
|
76
|
+
if (value === '--json') {
|
|
77
|
+
options.json = true;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (value === '--fail-on-error') {
|
|
81
|
+
options.failOnError = true;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (value === '--fail-on-warning') {
|
|
85
|
+
options.failOnWarning = true;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (value === '--project-path') {
|
|
89
|
+
options.projectPath = path.resolve(argv[index + 1] || process.cwd());
|
|
90
|
+
index += 1;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (value === '--out') {
|
|
94
|
+
options.out = path.resolve(argv[index + 1] || '');
|
|
95
|
+
index += 1;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return options;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function mergeGovernance(manifestGovernance = {}) {
|
|
104
|
+
const mergedFiles = { ...DEFAULT_GOVERNANCE.files };
|
|
105
|
+
const manifestFiles = manifestGovernance.files || {};
|
|
106
|
+
for (const [name, config] of Object.entries(manifestFiles)) {
|
|
107
|
+
mergedFiles[name] = {
|
|
108
|
+
...(mergedFiles[name] || {}),
|
|
109
|
+
...(config || {})
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
...DEFAULT_GOVERNANCE,
|
|
115
|
+
...manifestGovernance,
|
|
116
|
+
stable_layers: Array.isArray(manifestGovernance.stable_layers)
|
|
117
|
+
? manifestGovernance.stable_layers.slice()
|
|
118
|
+
: DEFAULT_GOVERNANCE.stable_layers.slice(),
|
|
119
|
+
canonical_terms: {
|
|
120
|
+
...DEFAULT_GOVERNANCE.canonical_terms,
|
|
121
|
+
...(manifestGovernance.canonical_terms || {})
|
|
122
|
+
},
|
|
123
|
+
relocation_targets: {
|
|
124
|
+
...DEFAULT_GOVERNANCE.relocation_targets,
|
|
125
|
+
...(manifestGovernance.relocation_targets || {})
|
|
126
|
+
},
|
|
127
|
+
files: mergedFiles
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function loadSteeringManifest(projectPath) {
|
|
132
|
+
const steeringDir = path.join(projectPath, '.sce', 'steering');
|
|
133
|
+
const manifestPath = path.join(steeringDir, 'manifest.yaml');
|
|
134
|
+
let manifest = {};
|
|
135
|
+
|
|
136
|
+
if (fs.existsSync(manifestPath)) {
|
|
137
|
+
manifest = yaml.load(fs.readFileSync(manifestPath, 'utf8')) || {};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const governance = mergeGovernance(manifest.governance || {});
|
|
141
|
+
const layers = manifest.layers || {
|
|
142
|
+
core_principles: 'CORE_PRINCIPLES.md',
|
|
143
|
+
environment: 'ENVIRONMENT.md',
|
|
144
|
+
current_context: 'CURRENT_CONTEXT.md',
|
|
145
|
+
rules_guide: 'RULES_GUIDE.md'
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
steeringDir,
|
|
150
|
+
manifestPath,
|
|
151
|
+
manifest,
|
|
152
|
+
governance,
|
|
153
|
+
layers
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function countMatches(text, regex) {
|
|
158
|
+
const matches = text.match(regex);
|
|
159
|
+
return matches ? matches.length : 0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function collectMetrics(fileName, content) {
|
|
163
|
+
const lines = content.split(/\r?\n/);
|
|
164
|
+
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
|
165
|
+
|
|
166
|
+
return {
|
|
167
|
+
file: fileName,
|
|
168
|
+
lines: lines.length,
|
|
169
|
+
words: content.trim().length === 0 ? 0 : content.trim().split(/\s+/).filter(Boolean).length,
|
|
170
|
+
headings: countMatches(content, /^#{1,6}\s+/gm),
|
|
171
|
+
historyEntries: countMatches(content, /^v\d+\.\d+(?:\.\d+)?\s+\|/gm),
|
|
172
|
+
checklistItems: countMatches(content, /^\s*[-*]\s+\[[ xX]\]/gm),
|
|
173
|
+
specRefs: countMatches(content, /\bSpec\s+\d+\b|\b\d{2,3}-\d{2}-[a-z0-9-]+\b/gi),
|
|
174
|
+
versionMarkers: countMatches(content, /\bv\d+\.\d+(?:\.\d+)?\b/g),
|
|
175
|
+
nonEmptyLines: nonEmptyLines.length
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function pushViolation(violations, severity, file, rule, message, suggestion) {
|
|
180
|
+
violations.push({
|
|
181
|
+
severity,
|
|
182
|
+
file,
|
|
183
|
+
rule,
|
|
184
|
+
message,
|
|
185
|
+
suggestion
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function auditSteeringContent(options = {}) {
|
|
190
|
+
const projectPath = path.resolve(options.projectPath || process.cwd());
|
|
191
|
+
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
192
|
+
const packageVersion = fs.existsSync(packageJsonPath)
|
|
193
|
+
? JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')).version
|
|
194
|
+
: null;
|
|
195
|
+
const loaded = loadSteeringManifest(projectPath);
|
|
196
|
+
const {
|
|
197
|
+
steeringDir,
|
|
198
|
+
governance,
|
|
199
|
+
layers
|
|
200
|
+
} = loaded;
|
|
201
|
+
|
|
202
|
+
const fileNames = Array.from(new Set(Object.values(layers)));
|
|
203
|
+
const files = [];
|
|
204
|
+
const violations = [];
|
|
205
|
+
|
|
206
|
+
for (const fileName of fileNames) {
|
|
207
|
+
const absolutePath = path.join(steeringDir, fileName);
|
|
208
|
+
if (!fs.existsSync(absolutePath)) {
|
|
209
|
+
pushViolation(
|
|
210
|
+
violations,
|
|
211
|
+
'error',
|
|
212
|
+
fileName,
|
|
213
|
+
'missing_file',
|
|
214
|
+
`Missing steering layer file: ${fileName}`,
|
|
215
|
+
`Restore ${fileName} under ${steeringDir}.`
|
|
216
|
+
);
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const content = fs.readFileSync(absolutePath, 'utf8');
|
|
221
|
+
const metrics = collectMetrics(fileName, content);
|
|
222
|
+
const config = governance.files[fileName] || {};
|
|
223
|
+
files.push({
|
|
224
|
+
file: fileName,
|
|
225
|
+
path: absolutePath,
|
|
226
|
+
metrics,
|
|
227
|
+
config
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
if (typeof config.max_lines === 'number' && metrics.lines > config.max_lines) {
|
|
231
|
+
pushViolation(
|
|
232
|
+
violations,
|
|
233
|
+
'error',
|
|
234
|
+
fileName,
|
|
235
|
+
'line_budget_exceeded',
|
|
236
|
+
`${fileName} has ${metrics.lines} lines, above the ${config.max_lines}-line budget.`,
|
|
237
|
+
`Move detailed procedures or historical detail to ${governance.relocation_targets.detailed_workflow_and_examples} or a Spec archive.`
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (typeof config.max_headings === 'number' && metrics.headings > config.max_headings) {
|
|
242
|
+
pushViolation(
|
|
243
|
+
violations,
|
|
244
|
+
'warning',
|
|
245
|
+
fileName,
|
|
246
|
+
'heading_budget_exceeded',
|
|
247
|
+
`${fileName} has ${metrics.headings} headings, above the ${config.max_headings}-heading budget.`,
|
|
248
|
+
'Merge related sections and keep only durable decisions in steering.'
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (typeof config.max_history_entries === 'number' && metrics.historyEntries > config.max_history_entries) {
|
|
253
|
+
pushViolation(
|
|
254
|
+
violations,
|
|
255
|
+
'error',
|
|
256
|
+
fileName,
|
|
257
|
+
'history_budget_exceeded',
|
|
258
|
+
`${fileName} contains ${metrics.historyEntries} historical version entries, above the ${config.max_history_entries}-entry budget.`,
|
|
259
|
+
`Archive historical progress into ${governance.relocation_targets.historical_decisions_and_evidence}.`
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (config.allow_checklists === false && metrics.checklistItems > 0) {
|
|
264
|
+
pushViolation(
|
|
265
|
+
violations,
|
|
266
|
+
'error',
|
|
267
|
+
fileName,
|
|
268
|
+
'task_checklist_in_steering',
|
|
269
|
+
`${fileName} contains ${metrics.checklistItems} checklist item(s).`,
|
|
270
|
+
`Move executable task state into ${governance.relocation_targets.transient_task_state}.`
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (config.allow_spec_refs === false && metrics.specRefs > 0) {
|
|
275
|
+
pushViolation(
|
|
276
|
+
violations,
|
|
277
|
+
'warning',
|
|
278
|
+
fileName,
|
|
279
|
+
'spec_reference_in_stable_layer',
|
|
280
|
+
`${fileName} contains ${metrics.specRefs} Spec or spec-id reference(s).`,
|
|
281
|
+
`Move volatile delivery detail into ${governance.relocation_targets.active_delivery_context} or a Spec archive.`
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (config.allow_version_markers === false && metrics.versionMarkers > 0) {
|
|
286
|
+
pushViolation(
|
|
287
|
+
violations,
|
|
288
|
+
'warning',
|
|
289
|
+
fileName,
|
|
290
|
+
'version_marker_in_stable_layer',
|
|
291
|
+
`${fileName} contains ${metrics.versionMarkers} version marker(s).`,
|
|
292
|
+
'Remove release-history footers from stable steering layers; keep version tracking in CHANGELOG or release notes.'
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (fileName === 'CURRENT_CONTEXT.md' && packageVersion) {
|
|
297
|
+
const versionMatch = content.match(/\*\*版本\*\*:\s*`([^`]+)`/);
|
|
298
|
+
if (versionMatch && versionMatch[1].trim() !== packageVersion) {
|
|
299
|
+
pushViolation(
|
|
300
|
+
violations,
|
|
301
|
+
'warning',
|
|
302
|
+
fileName,
|
|
303
|
+
'stale_context_version',
|
|
304
|
+
`CURRENT_CONTEXT.md tracks version ${versionMatch[1].trim()} but package.json is ${packageVersion}.`,
|
|
305
|
+
'Refresh CURRENT_CONTEXT.md after version bumps or release completion.'
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
for (const [canonicalName, definition] of Object.entries(governance.canonical_terms || {})) {
|
|
311
|
+
const aliases = Array.isArray(definition.aliases) ? definition.aliases : [];
|
|
312
|
+
for (const alias of aliases) {
|
|
313
|
+
const escaped = `${alias}`.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
314
|
+
const aliasCount = countMatches(content, new RegExp(escaped, 'g'));
|
|
315
|
+
if (aliasCount > 0) {
|
|
316
|
+
pushViolation(
|
|
317
|
+
violations,
|
|
318
|
+
'warning',
|
|
319
|
+
fileName,
|
|
320
|
+
'non_canonical_mechanism_alias',
|
|
321
|
+
`${fileName} uses non-canonical mechanism alias "${alias}" (${aliasCount} occurrence(s)); canonical term is "${canonicalName}".`,
|
|
322
|
+
definition.guidance || `Use the canonical term "${canonicalName}" and reference the existing SCE capability.`
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const errorCount = violations.filter((item) => item.severity === 'error').length;
|
|
330
|
+
const warningCount = violations.filter((item) => item.severity === 'warning').length;
|
|
331
|
+
|
|
332
|
+
return {
|
|
333
|
+
mode: 'steering-content-audit',
|
|
334
|
+
passed: errorCount === 0,
|
|
335
|
+
project_path: projectPath,
|
|
336
|
+
steering_path: steeringDir,
|
|
337
|
+
review_cadence: governance.review_cadence,
|
|
338
|
+
error_count: errorCount,
|
|
339
|
+
warning_count: warningCount,
|
|
340
|
+
files: files.map((entry) => ({
|
|
341
|
+
file: entry.file,
|
|
342
|
+
metrics: entry.metrics,
|
|
343
|
+
config: entry.config
|
|
344
|
+
})),
|
|
345
|
+
violations
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function printHumanReport(result) {
|
|
350
|
+
if (result.violations.length === 0) {
|
|
351
|
+
console.log('Steering content audit passed: steering layers are within hygiene budgets.');
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
console.error(`Steering content audit found ${result.error_count} error(s) and ${result.warning_count} warning(s).`);
|
|
356
|
+
for (const violation of result.violations) {
|
|
357
|
+
console.error(`- [${violation.severity}] ${violation.file} / ${violation.rule}: ${violation.message}`);
|
|
358
|
+
if (violation.suggestion) {
|
|
359
|
+
console.error(` suggestion: ${violation.suggestion}`);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function maybeWriteReport(outputPath, result) {
|
|
365
|
+
if (!outputPath) {
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
369
|
+
fs.writeFileSync(outputPath, `${JSON.stringify(result, null, 2)}\n`, 'utf8');
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (require.main === module) {
|
|
373
|
+
const options = parseArgs(process.argv.slice(2));
|
|
374
|
+
const result = auditSteeringContent(options);
|
|
375
|
+
maybeWriteReport(options.out, result);
|
|
376
|
+
|
|
377
|
+
if (options.json) {
|
|
378
|
+
process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
|
379
|
+
} else {
|
|
380
|
+
printHumanReport(result);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if ((options.failOnWarning && result.warning_count > 0) || (options.failOnError && result.error_count > 0)) {
|
|
384
|
+
process.exit(1);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
module.exports = {
|
|
389
|
+
DEFAULT_GOVERNANCE,
|
|
390
|
+
auditSteeringContent,
|
|
391
|
+
loadSteeringManifest,
|
|
392
|
+
parseArgs
|
|
393
|
+
};
|