scene-capability-engine 3.3.26 → 3.4.5
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 +62 -0
- package/README.md +81 -719
- package/README.zh.md +85 -586
- package/bin/scene-capability-engine.js +103 -0
- package/docs/README.md +47 -249
- package/docs/command-reference.md +49 -4
- package/docs/spec-workflow.md +35 -4
- package/docs/zh/README.md +44 -331
- package/lib/adoption/adoption-strategy.js +4 -0
- package/lib/adoption/detection-engine.js +4 -0
- package/lib/adoption/file-classifier.js +5 -1
- package/lib/adoption/smart-orchestrator.js +4 -0
- package/lib/commands/adopt.js +32 -0
- package/lib/commands/errorbook.js +409 -2
- package/lib/commands/spec-domain.js +78 -2
- package/lib/commands/studio.js +251 -3
- package/lib/commands/upgrade.js +16 -0
- package/lib/problem/problem-evaluator.js +620 -0
- package/lib/spec/domain-modeling.js +217 -1
- package/lib/workspace/takeover-baseline.js +446 -0
- package/package.json +1 -1
- package/template/.sce/config/problem-eval-policy.json +36 -0
- package/template/.sce/config/session-governance.json +8 -0
- package/template/.sce/config/spec-domain-policy.json +6 -0
- package/template/.sce/config/takeover-baseline.json +33 -0
|
@@ -5,6 +5,17 @@ const DOMAIN_MAP_RELATIVE_PATH = path.join('custom', 'problem-domain-map.md');
|
|
|
5
5
|
const SCENE_SPEC_RELATIVE_PATH = path.join('custom', 'scene-spec.md');
|
|
6
6
|
const DOMAIN_CHAIN_RELATIVE_PATH = path.join('custom', 'problem-domain-chain.json');
|
|
7
7
|
const DOMAIN_CHAIN_API_VERSION = 'sce.problem-domain-chain/v0.1';
|
|
8
|
+
const DOMAIN_RESEARCH_DIMENSIONS = Object.freeze([
|
|
9
|
+
'scene_boundary',
|
|
10
|
+
'entity',
|
|
11
|
+
'relation',
|
|
12
|
+
'business_rule',
|
|
13
|
+
'decision_policy',
|
|
14
|
+
'execution_flow',
|
|
15
|
+
'failure_signal',
|
|
16
|
+
'debug_evidence_plan',
|
|
17
|
+
'verification_gate'
|
|
18
|
+
]);
|
|
8
19
|
|
|
9
20
|
function normalizeText(value) {
|
|
10
21
|
if (typeof value !== 'string') {
|
|
@@ -79,6 +90,20 @@ mindmap
|
|
|
79
90
|
4. Produce candidate fixes and risk tradeoffs.
|
|
80
91
|
5. Define verification path and measurable acceptance.
|
|
81
92
|
|
|
93
|
+
## Closed-Loop Research Coverage Matrix
|
|
94
|
+
|
|
95
|
+
| Dimension | Coverage Goal | Status |
|
|
96
|
+
| --- | --- | --- |
|
|
97
|
+
| Scene Boundary | Entry, scope, excluded boundaries are explicit | [ ] |
|
|
98
|
+
| Entity | Key entities are listed and scoped | [ ] |
|
|
99
|
+
| Relation | Entity relations and direction are explicit | [ ] |
|
|
100
|
+
| Business Rule | Enforceable rules are mapped | [ ] |
|
|
101
|
+
| Decision Policy | Decision branches and conditions are explicit | [ ] |
|
|
102
|
+
| Execution Flow | End-to-end action chain is explicit | [ ] |
|
|
103
|
+
| Failure Signal | Wrong-direction signals are listed | [ ] |
|
|
104
|
+
| Debug Evidence Plan | Debug-log/diagnostic evidence path is defined | [ ] |
|
|
105
|
+
| Verification Gate | Acceptance and gate criteria are explicit | [ ] |
|
|
106
|
+
|
|
82
107
|
## Correction Loop
|
|
83
108
|
|
|
84
109
|
- Expected Wrong-Direction Signals:
|
|
@@ -140,6 +165,12 @@ function buildSceneSpec(specId, options = {}) {
|
|
|
140
165
|
4. Expected outputs and side effects.
|
|
141
166
|
5. Failure path and rollback criteria.
|
|
142
167
|
|
|
168
|
+
## Closed-Loop Research Contract
|
|
169
|
+
|
|
170
|
+
- This Scene Spec is invalid if the domain mind map coverage matrix is missing.
|
|
171
|
+
- Decision and execution statements must map to ontology fields in \`problem-domain-chain.json\`.
|
|
172
|
+
- If two remediation rounds fail, debug evidence and diagnostic logs are mandatory before another patch round.
|
|
173
|
+
|
|
143
174
|
## Acceptance & Gate
|
|
144
175
|
|
|
145
176
|
- Functional acceptance: define testable behaviors.
|
|
@@ -208,6 +239,22 @@ function buildProblemDomainChain(specId, options = {}) {
|
|
|
208
239
|
expected_result: 'TBD: side effect and data change'
|
|
209
240
|
}
|
|
210
241
|
],
|
|
242
|
+
research_coverage: {
|
|
243
|
+
mode: 'scene-closed-loop',
|
|
244
|
+
required_dimensions: [...DOMAIN_RESEARCH_DIMENSIONS],
|
|
245
|
+
checklist: {
|
|
246
|
+
scene_boundary: true,
|
|
247
|
+
entity: true,
|
|
248
|
+
relation: true,
|
|
249
|
+
business_rule: true,
|
|
250
|
+
decision_policy: true,
|
|
251
|
+
execution_flow: true,
|
|
252
|
+
failure_signal: true,
|
|
253
|
+
debug_evidence_plan: true,
|
|
254
|
+
verification_gate: true
|
|
255
|
+
},
|
|
256
|
+
status: 'draft'
|
|
257
|
+
},
|
|
211
258
|
correction_loop: {
|
|
212
259
|
triggers: [
|
|
213
260
|
'gate failure',
|
|
@@ -236,6 +283,7 @@ function validateProblemDomainMapContent(content = '') {
|
|
|
236
283
|
hasRootProblem: /##\s+Root Problem/i.test(content),
|
|
237
284
|
hasMindMapBlock: /```mermaid[\s\S]*mindmap/i.test(content),
|
|
238
285
|
hasLayeredExplorationChain: /##\s+Layered Exploration Chain/i.test(content),
|
|
286
|
+
hasCoverageMatrix: /##\s+Closed-Loop Research Coverage Matrix/i.test(content),
|
|
239
287
|
hasCorrectionLoop: /##\s+Correction Loop/i.test(content)
|
|
240
288
|
};
|
|
241
289
|
const passed = Object.values(checks).every(Boolean);
|
|
@@ -247,6 +295,7 @@ function validateSceneSpecContent(content = '') {
|
|
|
247
295
|
hasSceneDefinition: /##\s+Scene Definition/i.test(content),
|
|
248
296
|
hasOntologyCoverage: /##\s+Ontology Coverage/i.test(content),
|
|
249
297
|
hasDecisionExecutionPath: /##\s+Decision & Execution Path/i.test(content),
|
|
298
|
+
hasClosedLoopResearchContract: /##\s+Closed-Loop Research Contract/i.test(content),
|
|
250
299
|
hasAcceptanceGate: /##\s+Acceptance & Gate/i.test(content)
|
|
251
300
|
};
|
|
252
301
|
const passed = Object.values(checks).every(Boolean);
|
|
@@ -261,7 +310,41 @@ function hasNonEmptyStringArray(value) {
|
|
|
261
310
|
return Array.isArray(value) && value.some((item) => isNonEmptyString(item));
|
|
262
311
|
}
|
|
263
312
|
|
|
313
|
+
function isObject(value) {
|
|
314
|
+
return value && typeof value === 'object' && !Array.isArray(value);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function isMeaningfulText(value) {
|
|
318
|
+
if (!isNonEmptyString(value)) {
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
const normalized = value.trim();
|
|
322
|
+
return !/^(tbd|todo|n\/a|na|待补|待定|待完善|placeholder)\b/i.test(normalized);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function hasMeaningfulStringArray(value) {
|
|
326
|
+
return Array.isArray(value) && value.some((item) => isMeaningfulText(item));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function hasResearchCoverageChecklist(value) {
|
|
330
|
+
if (!isObject(value)) {
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
return DOMAIN_RESEARCH_DIMENSIONS.every((dimension) => typeof value[dimension] === 'boolean');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function hasResearchCoverageDimensions(value) {
|
|
337
|
+
if (!Array.isArray(value)) {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
const normalized = new Set(value.map((item) => `${item || ''}`.trim()).filter(Boolean));
|
|
341
|
+
return DOMAIN_RESEARCH_DIMENSIONS.every((dimension) => normalized.has(dimension));
|
|
342
|
+
}
|
|
343
|
+
|
|
264
344
|
function validateProblemDomainChainPayload(payload = {}, specId = '') {
|
|
345
|
+
const researchCoverage = payload && isObject(payload.research_coverage)
|
|
346
|
+
? payload.research_coverage
|
|
347
|
+
: null;
|
|
265
348
|
const checks = {
|
|
266
349
|
apiVersion: isNonEmptyString(payload.api_version),
|
|
267
350
|
sceneId: isNonEmptyString(payload.scene_id),
|
|
@@ -275,6 +358,10 @@ function validateProblemDomainChainPayload(payload = {}, specId = '') {
|
|
|
275
358
|
hasHypotheses: Array.isArray(payload.hypotheses) && payload.hypotheses.length > 0,
|
|
276
359
|
hasRisks: Array.isArray(payload.risks) && payload.risks.length > 0,
|
|
277
360
|
hasDecisionPath: Array.isArray(payload.decision_execution_path) && payload.decision_execution_path.length >= 3,
|
|
361
|
+
hasResearchCoverageObject: Boolean(researchCoverage),
|
|
362
|
+
hasResearchCoverageMode: isNonEmptyString(researchCoverage && researchCoverage.mode),
|
|
363
|
+
hasResearchCoverageDimensions: hasResearchCoverageDimensions(researchCoverage && researchCoverage.required_dimensions),
|
|
364
|
+
hasResearchCoverageChecklist: hasResearchCoverageChecklist(researchCoverage && researchCoverage.checklist),
|
|
278
365
|
hasCorrectionTriggers: hasNonEmptyStringArray(payload?.correction_loop?.triggers),
|
|
279
366
|
hasCorrectionActions: hasNonEmptyStringArray(payload?.correction_loop?.actions),
|
|
280
367
|
hasVerificationGates: hasNonEmptyStringArray(payload?.verification?.gates)
|
|
@@ -285,6 +372,104 @@ function validateProblemDomainChainPayload(payload = {}, specId = '') {
|
|
|
285
372
|
};
|
|
286
373
|
}
|
|
287
374
|
|
|
375
|
+
function buildDomainCoverageItems(chainPayload = {}, validation = null) {
|
|
376
|
+
const ontology = isObject(chainPayload && chainPayload.ontology) ? chainPayload.ontology : {};
|
|
377
|
+
const correctionLoop = isObject(chainPayload && chainPayload.correction_loop) ? chainPayload.correction_loop : {};
|
|
378
|
+
const verification = isObject(chainPayload && chainPayload.verification) ? chainPayload.verification : {};
|
|
379
|
+
const researchCoverage = isObject(chainPayload && chainPayload.research_coverage)
|
|
380
|
+
? chainPayload.research_coverage
|
|
381
|
+
: {};
|
|
382
|
+
|
|
383
|
+
const structuralItems = [];
|
|
384
|
+
if (validation && isObject(validation.details)) {
|
|
385
|
+
structuralItems.push({
|
|
386
|
+
id: 'map_structure',
|
|
387
|
+
label: 'problem-domain-map structure',
|
|
388
|
+
covered: Boolean(validation.details.domain_map && validation.details.domain_map.exists && validation.details.domain_map.checks && Object.values(validation.details.domain_map.checks).every(Boolean)),
|
|
389
|
+
evidence: DOMAIN_MAP_RELATIVE_PATH
|
|
390
|
+
});
|
|
391
|
+
structuralItems.push({
|
|
392
|
+
id: 'scene_structure',
|
|
393
|
+
label: 'scene-spec structure',
|
|
394
|
+
covered: Boolean(validation.details.scene_spec && validation.details.scene_spec.exists && validation.details.scene_spec.checks && Object.values(validation.details.scene_spec.checks).every(Boolean)),
|
|
395
|
+
evidence: SCENE_SPEC_RELATIVE_PATH
|
|
396
|
+
});
|
|
397
|
+
structuralItems.push({
|
|
398
|
+
id: 'chain_structure',
|
|
399
|
+
label: 'problem-domain-chain structure',
|
|
400
|
+
covered: Boolean(validation.details.domain_chain && validation.details.domain_chain.exists && validation.details.domain_chain.checks && Object.values(validation.details.domain_chain.checks).every(Boolean)),
|
|
401
|
+
evidence: DOMAIN_CHAIN_RELATIVE_PATH
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const domainItems = [
|
|
406
|
+
{
|
|
407
|
+
id: 'scene_boundary',
|
|
408
|
+
label: 'Scene boundary',
|
|
409
|
+
covered: isMeaningfulText(chainPayload?.problem?.statement) && isMeaningfulText(chainPayload?.problem?.scope),
|
|
410
|
+
evidence: 'problem.statement + problem.scope'
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
id: 'entity',
|
|
414
|
+
label: 'Ontology entity coverage',
|
|
415
|
+
covered: hasMeaningfulStringArray(ontology.entity),
|
|
416
|
+
evidence: 'ontology.entity[]'
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
id: 'relation',
|
|
420
|
+
label: 'Ontology relation coverage',
|
|
421
|
+
covered: hasMeaningfulStringArray(ontology.relation),
|
|
422
|
+
evidence: 'ontology.relation[]'
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
id: 'business_rule',
|
|
426
|
+
label: 'Business rule coverage',
|
|
427
|
+
covered: hasMeaningfulStringArray(ontology.business_rule),
|
|
428
|
+
evidence: 'ontology.business_rule[]'
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
id: 'decision_policy',
|
|
432
|
+
label: 'Decision policy coverage',
|
|
433
|
+
covered: hasMeaningfulStringArray(ontology.decision_policy),
|
|
434
|
+
evidence: 'ontology.decision_policy[]'
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
id: 'execution_flow',
|
|
438
|
+
label: 'Execution flow coverage',
|
|
439
|
+
covered: hasMeaningfulStringArray(ontology.execution_flow),
|
|
440
|
+
evidence: 'ontology.execution_flow[]'
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
id: 'failure_signal',
|
|
444
|
+
label: 'Failure-signal coverage',
|
|
445
|
+
covered: hasMeaningfulStringArray(correctionLoop.triggers),
|
|
446
|
+
evidence: 'correction_loop.triggers[]'
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
id: 'debug_evidence_plan',
|
|
450
|
+
label: 'Debug evidence plan',
|
|
451
|
+
covered: Array.isArray(correctionLoop.actions)
|
|
452
|
+
&& correctionLoop.actions.some((item) => /debug|diagnostic|日志|evidence/i.test(`${item || ''}`)),
|
|
453
|
+
evidence: 'correction_loop.actions[]'
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
id: 'verification_gate',
|
|
457
|
+
label: 'Verification gate coverage',
|
|
458
|
+
covered: hasMeaningfulStringArray(verification.gates),
|
|
459
|
+
evidence: 'verification.gates[]'
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
id: 'research_contract',
|
|
463
|
+
label: 'Research contract checklist',
|
|
464
|
+
covered: hasResearchCoverageChecklist(researchCoverage.checklist)
|
|
465
|
+
&& hasResearchCoverageDimensions(researchCoverage.required_dimensions),
|
|
466
|
+
evidence: 'research_coverage.required_dimensions + checklist'
|
|
467
|
+
}
|
|
468
|
+
];
|
|
469
|
+
|
|
470
|
+
return [...structuralItems, ...domainItems];
|
|
471
|
+
}
|
|
472
|
+
|
|
288
473
|
async function ensureSpecDomainArtifacts(projectPath, specId, options = {}) {
|
|
289
474
|
const fileSystem = options.fileSystem || fs;
|
|
290
475
|
const dryRun = options.dryRun === true;
|
|
@@ -426,14 +611,45 @@ async function validateSpecDomainArtifacts(projectPath, specId, fileSystem = fs)
|
|
|
426
611
|
};
|
|
427
612
|
}
|
|
428
613
|
|
|
614
|
+
async function analyzeSpecDomainCoverage(projectPath, specId, fileSystem = fs) {
|
|
615
|
+
const validation = await validateSpecDomainArtifacts(projectPath, specId, fileSystem);
|
|
616
|
+
const paths = resolveSpecPaths(projectPath, specId);
|
|
617
|
+
let chainPayload = null;
|
|
618
|
+
|
|
619
|
+
if (await fileSystem.pathExists(paths.domainChainPath)) {
|
|
620
|
+
try {
|
|
621
|
+
chainPayload = await fileSystem.readJson(paths.domainChainPath);
|
|
622
|
+
} catch (_error) {
|
|
623
|
+
chainPayload = null;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
const items = buildDomainCoverageItems(chainPayload || {}, validation);
|
|
628
|
+
const coveredCount = items.filter((item) => item.covered).length;
|
|
629
|
+
const totalCount = items.length;
|
|
630
|
+
const uncovered = items.filter((item) => !item.covered).map((item) => item.id);
|
|
631
|
+
|
|
632
|
+
return {
|
|
633
|
+
passed: uncovered.length === 0,
|
|
634
|
+
coverage_ratio: totalCount > 0 ? coveredCount / totalCount : 0,
|
|
635
|
+
covered_count: coveredCount,
|
|
636
|
+
total_count: totalCount,
|
|
637
|
+
uncovered,
|
|
638
|
+
items,
|
|
639
|
+
validation
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
|
|
429
643
|
module.exports = {
|
|
430
644
|
DOMAIN_MAP_RELATIVE_PATH,
|
|
431
645
|
SCENE_SPEC_RELATIVE_PATH,
|
|
432
646
|
DOMAIN_CHAIN_RELATIVE_PATH,
|
|
433
647
|
DOMAIN_CHAIN_API_VERSION,
|
|
648
|
+
DOMAIN_RESEARCH_DIMENSIONS,
|
|
434
649
|
buildProblemDomainMindMap,
|
|
435
650
|
buildSceneSpec,
|
|
436
651
|
buildProblemDomainChain,
|
|
437
652
|
ensureSpecDomainArtifacts,
|
|
438
|
-
validateSpecDomainArtifacts
|
|
653
|
+
validateSpecDomainArtifacts,
|
|
654
|
+
analyzeSpecDomainCoverage
|
|
439
655
|
};
|