scene-capability-engine 3.6.21 → 3.6.22
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 +7 -0
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/docs/command-reference.md +7 -0
- package/docs/magicball-capability-iteration-api.md +33 -8
- package/docs/magicball-capability-iteration-ui.md +7 -1
- package/lib/commands/capability.js +168 -44
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,9 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [3.6.22] - 2026-03-06
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- New `sce capability inventory` command provides scene-level triad/readiness aggregation for homepage views.
|
|
14
|
+
- Magicball capability iteration docs now define homepage inventory API and triage usage.
|
|
15
|
+
|
|
10
16
|
## [3.6.21] - 2026-03-06
|
|
11
17
|
|
|
12
18
|
### Added
|
|
19
|
+
- New `sce capability inventory` command provides scene-level triad/readiness aggregation for homepage views.
|
|
13
20
|
- Capability catalog list/search now supports `--release-ready` and `--missing-triad` filters for pre-publish triage.
|
|
14
21
|
- Magicball capability library docs now show list-level triage filter examples.
|
|
15
22
|
|
package/README.md
CHANGED
package/README.zh.md
CHANGED
|
@@ -1869,6 +1869,13 @@ sce scene template-render --package scene-erp --values '{"entity_name":"Order"}'
|
|
|
1869
1869
|
|
|
1870
1870
|
### Capability Iteration (scene -> template -> ontology)
|
|
1871
1871
|
|
|
1872
|
+
```bash
|
|
1873
|
+
# 0) Build scene-level homepage inventory
|
|
1874
|
+
sce capability inventory --json
|
|
1875
|
+
sce capability inventory --release-ready false --missing-triad decision_strategy --json
|
|
1876
|
+
```
|
|
1877
|
+
|
|
1878
|
+
|
|
1872
1879
|
Capability candidates are now evaluated against the ontology core triad by default:
|
|
1873
1880
|
- entity + relation
|
|
1874
1881
|
- business rule
|
|
@@ -15,7 +15,31 @@
|
|
|
15
15
|
|
|
16
16
|
## 2. 建议 API 列表
|
|
17
17
|
|
|
18
|
-
### 2.1
|
|
18
|
+
### 2.1 Inventory
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
POST /api/capability/inventory
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
请求:
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"release_ready": false,
|
|
28
|
+
"missing_triad": "decision_strategy"
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
执行 CLI:
|
|
33
|
+
```bash
|
|
34
|
+
sce capability inventory --release-ready false --missing-triad decision_strategy --json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
响应:
|
|
38
|
+
- 返回 `capability-inventory` payload,重点消费 `scenes[].ontology_core_ui` 与 `scenes[].release_readiness_ui`
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
### 2.2 Extract
|
|
19
43
|
|
|
20
44
|
```
|
|
21
45
|
POST /api/capability/extract
|
|
@@ -40,7 +64,7 @@ sce capability extract --scene <scene_id> --specs <specs> --sample-limit <n> --j
|
|
|
40
64
|
|
|
41
65
|
---
|
|
42
66
|
|
|
43
|
-
### 2.
|
|
67
|
+
### 2.3 Score
|
|
44
68
|
|
|
45
69
|
```
|
|
46
70
|
POST /api/capability/score
|
|
@@ -63,7 +87,7 @@ sce capability score --input <candidate_file> --json
|
|
|
63
87
|
|
|
64
88
|
---
|
|
65
89
|
|
|
66
|
-
### 2.
|
|
90
|
+
### 2.4 Map
|
|
67
91
|
|
|
68
92
|
```
|
|
69
93
|
POST /api/capability/map
|
|
@@ -91,7 +115,7 @@ sce capability map --input <candidate_file> --mapping <ontology_file> \
|
|
|
91
115
|
|
|
92
116
|
---
|
|
93
117
|
|
|
94
|
-
### 2.
|
|
118
|
+
### 2.5 Register
|
|
95
119
|
|
|
96
120
|
```
|
|
97
121
|
POST /api/capability/register
|
|
@@ -147,8 +171,9 @@ sce capability register --input <template_file> --risk-level <level> --difficult
|
|
|
147
171
|
|
|
148
172
|
## 5. 推荐顺序
|
|
149
173
|
|
|
150
|
-
1. `/api/capability/
|
|
151
|
-
2. `/api/capability/
|
|
152
|
-
3. `/api/capability/
|
|
153
|
-
4. `/api/capability/
|
|
174
|
+
1. `/api/capability/inventory`
|
|
175
|
+
2. `/api/capability/extract`
|
|
176
|
+
3. `/api/capability/score`
|
|
177
|
+
4. `/api/capability/map`
|
|
178
|
+
5. `/api/capability/register`
|
|
154
179
|
|
|
@@ -98,7 +98,13 @@
|
|
|
98
98
|
|
|
99
99
|
## 4. SCE 接口参数(CLI 可封装)
|
|
100
100
|
|
|
101
|
-
### 4.1
|
|
101
|
+
### 4.1 Scene 盘点首页聚合
|
|
102
|
+
```bash
|
|
103
|
+
sce capability inventory --json
|
|
104
|
+
sce capability inventory --release-ready false --missing-triad decision_strategy --json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 4.2 提取候选能力
|
|
102
108
|
```bash
|
|
103
109
|
sce capability extract --scene <sceneId> --json
|
|
104
110
|
```
|
|
@@ -723,46 +723,10 @@ function buildTemplateCandidate(candidate, mapping, options) {
|
|
|
723
723
|
};
|
|
724
724
|
}
|
|
725
725
|
|
|
726
|
-
function
|
|
727
|
-
const riskLevel = normalizeText(options && options.risk_level) || 'medium';
|
|
728
|
-
const difficulty = normalizeText(options && options.difficulty) || 'intermediate';
|
|
729
|
-
const applicable = normalizeStringArray(options && options.applicable_scenarios);
|
|
730
|
-
const tags = normalizeStringArray(options && options.tags);
|
|
731
|
-
const sceneId = buildSceneIdFromCandidate(templateCandidate);
|
|
732
|
-
const safeTags = tags.length > 0 ? tags : ['capability', sceneId];
|
|
733
|
-
const safeApplicable = applicable.length > 0 ? applicable : [sceneId];
|
|
734
|
-
|
|
735
|
-
return {
|
|
736
|
-
id: templateCandidate.template_id,
|
|
737
|
-
name: templateCandidate.name,
|
|
738
|
-
category: templateCandidate.category,
|
|
739
|
-
description: templateCandidate.description,
|
|
740
|
-
difficulty,
|
|
741
|
-
tags: safeTags,
|
|
742
|
-
applicable_scenarios: safeApplicable,
|
|
743
|
-
files: ['capability-template.json'],
|
|
744
|
-
template_type: 'capability-template',
|
|
745
|
-
min_sce_version: packageJson.version,
|
|
746
|
-
max_sce_version: null,
|
|
747
|
-
risk_level: riskLevel,
|
|
748
|
-
rollback_contract: {
|
|
749
|
-
supported: false,
|
|
750
|
-
strategy: 'n/a'
|
|
751
|
-
},
|
|
752
|
-
ontology_scope: templateCandidate.ontology_scope
|
|
753
|
-
};
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
async function runCapabilityExtractCommand(options = {}, dependencies = {}) {
|
|
726
|
+
async function buildCapabilityCandidatePayload(sceneId, options = {}, dependencies = {}) {
|
|
757
727
|
const projectPath = dependencies.projectPath || process.cwd();
|
|
758
728
|
const fileSystem = dependencies.fileSystem || fs;
|
|
759
729
|
const env = dependencies.env || process.env;
|
|
760
|
-
const sceneId = normalizeText(options.scene || options.sceneId || options.scene_id);
|
|
761
|
-
const writeOutput = normalizeBoolean(options.write, true);
|
|
762
|
-
|
|
763
|
-
if (!sceneId) {
|
|
764
|
-
throw new Error('scene is required for capability extract');
|
|
765
|
-
}
|
|
766
730
|
|
|
767
731
|
const specResolution = await resolveSceneSpecs(sceneId, {
|
|
768
732
|
specs: options.specs
|
|
@@ -816,7 +780,7 @@ async function runCapabilityExtractCommand(options = {}, dependencies = {}) {
|
|
|
816
780
|
|
|
817
781
|
const ontologyScope = mergeOntologyScopes(ontologyScopes);
|
|
818
782
|
const ontologyCore = buildCoreOntologySummary(ontologyScope);
|
|
819
|
-
|
|
783
|
+
return {
|
|
820
784
|
mode: 'capability-extract',
|
|
821
785
|
scene_id: sceneId,
|
|
822
786
|
generated_at: new Date().toISOString(),
|
|
@@ -835,7 +799,138 @@ async function runCapabilityExtractCommand(options = {}, dependencies = {}) {
|
|
|
835
799
|
ontology_missing_triads: ontologyCore.missing
|
|
836
800
|
}
|
|
837
801
|
};
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
async function listCapabilityInventorySceneIds(options = {}, dependencies = {}) {
|
|
805
|
+
const projectPath = dependencies.projectPath || process.cwd();
|
|
806
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
807
|
+
const env = dependencies.env || process.env;
|
|
808
|
+
const explicitScene = normalizeText(options.scene || options.sceneId || options.scene_id);
|
|
809
|
+
if (explicitScene) {
|
|
810
|
+
return [explicitScene];
|
|
811
|
+
}
|
|
812
|
+
const fromFile = await loadSceneIndexFromFile(projectPath, fileSystem);
|
|
813
|
+
if (fromFile && fromFile.data && fromFile.data.scenes) {
|
|
814
|
+
return Object.keys(fromFile.data.scenes).sort();
|
|
815
|
+
}
|
|
816
|
+
const fromState = await loadSceneIndexFromState(projectPath, fileSystem, env);
|
|
817
|
+
if (fromState && fromState.data && fromState.data.scenes) {
|
|
818
|
+
return Object.keys(fromState.data.scenes).sort();
|
|
819
|
+
}
|
|
820
|
+
return [];
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
function filterCapabilityInventoryEntries(entries, options = {}) {
|
|
824
|
+
const normalizedMissingTriad = normalizeText(options.missingTriad || options.missing_triad).toLowerCase();
|
|
825
|
+
const releaseReadyFilter = normalizeText(options.releaseReady || options.release_ready).toLowerCase();
|
|
826
|
+
return (Array.isArray(entries) ? entries : []).filter((entry) => {
|
|
827
|
+
if (releaseReadyFilter) {
|
|
828
|
+
const expected = ['1', 'true', 'yes', 'ready'].includes(releaseReadyFilter);
|
|
829
|
+
if (Boolean(entry.release_readiness_ui && entry.release_readiness_ui.publish_ready) !== expected) {
|
|
830
|
+
return false;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
if (normalizedMissingTriad) {
|
|
834
|
+
const missing = Array.isArray(entry.release_readiness_ui && entry.release_readiness_ui.blocking_missing)
|
|
835
|
+
? entry.release_readiness_ui.blocking_missing
|
|
836
|
+
: [];
|
|
837
|
+
if (!missing.includes(normalizedMissingTriad)) {
|
|
838
|
+
return false;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
return true;
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
async function runCapabilityInventoryCommand(options = {}, dependencies = {}) {
|
|
846
|
+
const projectPath = dependencies.projectPath || process.cwd();
|
|
847
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
848
|
+
const env = dependencies.env || process.env;
|
|
849
|
+
const sceneIds = await listCapabilityInventorySceneIds(options, { projectPath, fileSystem, env });
|
|
850
|
+
const limit = toPositiveInteger(options.limit, sceneIds.length || 20);
|
|
851
|
+
const scenes = [];
|
|
852
|
+
|
|
853
|
+
for (const sceneId of sceneIds.slice(0, limit)) {
|
|
854
|
+
const candidate = await buildCapabilityCandidatePayload(sceneId, {
|
|
855
|
+
specs: options.specs,
|
|
856
|
+
sample_limit: options.sample_limit
|
|
857
|
+
}, dependencies);
|
|
858
|
+
const score = buildScoreFromCandidate(candidate);
|
|
859
|
+
const releaseReadiness = buildCapabilityReleaseReadiness({
|
|
860
|
+
scene_id: sceneId,
|
|
861
|
+
ontology_scope: candidate.ontology_scope,
|
|
862
|
+
ontology_core: candidate.ontology_core
|
|
863
|
+
});
|
|
864
|
+
scenes.push({
|
|
865
|
+
scene_id: sceneId,
|
|
866
|
+
summary: candidate.summary,
|
|
867
|
+
source: candidate.source,
|
|
868
|
+
ontology_scope: candidate.ontology_scope,
|
|
869
|
+
ontology_core: candidate.ontology_core,
|
|
870
|
+
ontology_core_ui: buildOntologyCoreUiState(candidate.ontology_core),
|
|
871
|
+
release_readiness: releaseReadiness,
|
|
872
|
+
release_readiness_ui: buildCapabilityReleaseReadinessUi(releaseReadiness),
|
|
873
|
+
score_preview: score
|
|
874
|
+
});
|
|
875
|
+
}
|
|
838
876
|
|
|
877
|
+
const filteredScenes = filterCapabilityInventoryEntries(scenes, options);
|
|
878
|
+
const payload = {
|
|
879
|
+
mode: 'capability-inventory',
|
|
880
|
+
generated_at: new Date().toISOString(),
|
|
881
|
+
scene_count: filteredScenes.length,
|
|
882
|
+
scenes: filteredScenes
|
|
883
|
+
};
|
|
884
|
+
|
|
885
|
+
if (normalizeBoolean(options.json, false)) {
|
|
886
|
+
return payload;
|
|
887
|
+
}
|
|
888
|
+
console.log(chalk.green('✅ Capability inventory generated'));
|
|
889
|
+
console.log(chalk.gray(' Scenes: ' + filteredScenes.length));
|
|
890
|
+
return payload;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
function buildRegistryEntry(templateCandidate, options) {
|
|
894
|
+
const riskLevel = normalizeText(options && options.risk_level) || 'medium';
|
|
895
|
+
const difficulty = normalizeText(options && options.difficulty) || 'intermediate';
|
|
896
|
+
const applicable = normalizeStringArray(options && options.applicable_scenarios);
|
|
897
|
+
const tags = normalizeStringArray(options && options.tags);
|
|
898
|
+
const sceneId = buildSceneIdFromCandidate(templateCandidate);
|
|
899
|
+
const safeTags = tags.length > 0 ? tags : ['capability', sceneId];
|
|
900
|
+
const safeApplicable = applicable.length > 0 ? applicable : [sceneId];
|
|
901
|
+
|
|
902
|
+
return {
|
|
903
|
+
id: templateCandidate.template_id,
|
|
904
|
+
name: templateCandidate.name,
|
|
905
|
+
category: templateCandidate.category,
|
|
906
|
+
description: templateCandidate.description,
|
|
907
|
+
difficulty,
|
|
908
|
+
tags: safeTags,
|
|
909
|
+
applicable_scenarios: safeApplicable,
|
|
910
|
+
files: ['capability-template.json'],
|
|
911
|
+
template_type: 'capability-template',
|
|
912
|
+
min_sce_version: packageJson.version,
|
|
913
|
+
max_sce_version: null,
|
|
914
|
+
risk_level: riskLevel,
|
|
915
|
+
rollback_contract: {
|
|
916
|
+
supported: false,
|
|
917
|
+
strategy: 'n/a'
|
|
918
|
+
},
|
|
919
|
+
ontology_scope: templateCandidate.ontology_scope
|
|
920
|
+
};
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
async function runCapabilityExtractCommand(options = {}, dependencies = {}) {
|
|
924
|
+
const projectPath = dependencies.projectPath || process.cwd();
|
|
925
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
926
|
+
const sceneId = normalizeText(options.scene || options.sceneId || options.scene_id);
|
|
927
|
+
const writeOutput = normalizeBoolean(options.write, true);
|
|
928
|
+
|
|
929
|
+
if (!sceneId) {
|
|
930
|
+
throw new Error('scene is required for capability extract');
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
const payload = await buildCapabilityCandidatePayload(sceneId, options, dependencies);
|
|
839
934
|
const outputPath = normalizeText(options.out) || buildDefaultCandidatePath(sceneId);
|
|
840
935
|
if (writeOutput) {
|
|
841
936
|
await fileSystem.ensureDir(path.dirname(path.join(projectPath, outputPath)));
|
|
@@ -845,17 +940,16 @@ async function runCapabilityExtractCommand(options = {}, dependencies = {}) {
|
|
|
845
940
|
|
|
846
941
|
if (!normalizeBoolean(options.json, false)) {
|
|
847
942
|
console.log(chalk.green('✅ Capability candidate extracted'));
|
|
848
|
-
console.log(chalk.gray(
|
|
849
|
-
console.log(chalk.gray(
|
|
850
|
-
console.log(chalk.gray(
|
|
943
|
+
console.log(chalk.gray(' Scene: ' + sceneId));
|
|
944
|
+
console.log(chalk.gray(' Specs: ' + payload.summary.spec_count));
|
|
945
|
+
console.log(chalk.gray(' Tasks: ' + payload.summary.task_total));
|
|
851
946
|
if (payload.output_file) {
|
|
852
|
-
console.log(chalk.gray(
|
|
947
|
+
console.log(chalk.gray(' Output: ' + payload.output_file));
|
|
853
948
|
}
|
|
854
949
|
}
|
|
855
950
|
|
|
856
951
|
return payload;
|
|
857
952
|
}
|
|
858
|
-
|
|
859
953
|
async function runCapabilityScoreCommand(options = {}, dependencies = {}) {
|
|
860
954
|
const projectPath = dependencies.projectPath || process.cwd();
|
|
861
955
|
const fileSystem = dependencies.fileSystem || fs;
|
|
@@ -1319,6 +1413,34 @@ function registerCapabilityCommands(program) {
|
|
|
1319
1413
|
});
|
|
1320
1414
|
});
|
|
1321
1415
|
|
|
1416
|
+
capabilityCmd
|
|
1417
|
+
.command('inventory')
|
|
1418
|
+
.description('Build scene-level capability inventory for homepage views')
|
|
1419
|
+
.option('--scene <scene-id>', 'Single scene identifier')
|
|
1420
|
+
.option('--sample-limit <n>', 'Max tasks per spec in sample', '5')
|
|
1421
|
+
.option('--limit <n>', 'Max scenes to include')
|
|
1422
|
+
.option('--release-ready <bool>', 'Filter by publish readiness')
|
|
1423
|
+
.option('--missing-triad <name>', 'Filter by missing triad (entity_relation|business_rules|decision_strategy)')
|
|
1424
|
+
.option('--json', 'Output JSON to stdout')
|
|
1425
|
+
.action(async (options) => {
|
|
1426
|
+
try {
|
|
1427
|
+
const payload = await runCapabilityInventoryCommand({
|
|
1428
|
+
scene: options.scene,
|
|
1429
|
+
sample_limit: options.sampleLimit,
|
|
1430
|
+
limit: options.limit,
|
|
1431
|
+
releaseReady: options.releaseReady,
|
|
1432
|
+
missingTriad: options.missingTriad,
|
|
1433
|
+
json: options.json
|
|
1434
|
+
});
|
|
1435
|
+
if (options.json) {
|
|
1436
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
1437
|
+
}
|
|
1438
|
+
} catch (error) {
|
|
1439
|
+
console.log();
|
|
1440
|
+
console.log(chalk.red('❌ Error:'), error.message);
|
|
1441
|
+
process.exit(1);
|
|
1442
|
+
}
|
|
1443
|
+
});
|
|
1322
1444
|
capabilityCmd
|
|
1323
1445
|
.command('score')
|
|
1324
1446
|
.description('Score a capability candidate')
|
|
@@ -1530,6 +1652,7 @@ module.exports = {
|
|
|
1530
1652
|
runCapabilityScoreCommand,
|
|
1531
1653
|
runCapabilityMapCommand,
|
|
1532
1654
|
runCapabilityRegisterCommand,
|
|
1655
|
+
runCapabilityInventoryCommand,
|
|
1533
1656
|
listCapabilityCatalog,
|
|
1534
1657
|
searchCapabilityCatalog,
|
|
1535
1658
|
showCapabilityTemplate,
|
|
@@ -1537,5 +1660,6 @@ module.exports = {
|
|
|
1537
1660
|
useCapabilityTemplate,
|
|
1538
1661
|
enrichCapabilityTemplateForUi,
|
|
1539
1662
|
buildCapabilityReleaseReadinessUi,
|
|
1540
|
-
filterCapabilityCatalogEntries
|
|
1663
|
+
filterCapabilityCatalogEntries,
|
|
1664
|
+
filterCapabilityInventoryEntries
|
|
1541
1665
|
};
|
package/package.json
CHANGED