scene-capability-engine 3.6.29 → 3.6.32
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 +17 -0
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/docs/agent-runtime/magicball-contract-index.md +25 -0
- package/docs/command-reference.md +2 -0
- package/docs/magicball-capability-iteration-ui.md +1 -0
- package/docs/magicball-task-feedback-timeline-guide.md +8 -0
- package/lib/auto/session-metrics.js +53 -0
- package/lib/capability/catalog-service.js +248 -0
- package/lib/capability/inventory-service.js +100 -0
- package/lib/commands/auto.js +1 -1
- package/lib/commands/capability.js +81 -466
- package/lib/commands/scene.js +1 -1
- package/lib/commands/studio.js +147 -582
- package/lib/commands/timeline.js +6 -82
- package/lib/magicball/capability-inventory-view-model.js +213 -0
- package/lib/magicball/status-language.js +29 -0
- package/lib/magicball/task-feedback-model.js +113 -0
- package/lib/magicball/timeline-view-model.js +95 -0
- package/lib/scene/doctor-feedback.js +3541 -0
- package/lib/studio/task-envelope.js +269 -0
- package/lib/studio/task-intent.js +149 -0
- package/package.json +1 -1
|
@@ -15,6 +15,24 @@ const { DOMAIN_CHAIN_RELATIVE_PATH } = require('../spec/domain-modeling');
|
|
|
15
15
|
const { SceStateStore } = require('../state/sce-state-store');
|
|
16
16
|
const TemplateManager = require('../templates/template-manager');
|
|
17
17
|
const { TemplateError } = require('../templates/template-error');
|
|
18
|
+
const { buildMagicballStatusLanguage } = require('../magicball/status-language');
|
|
19
|
+
const {
|
|
20
|
+
buildCapabilityInventorySceneAdvice,
|
|
21
|
+
buildCapabilityInventorySummaryStats,
|
|
22
|
+
buildCapabilityInventorySummaryRecommendations,
|
|
23
|
+
buildCapabilityInventoryQuickFilters,
|
|
24
|
+
resolveCapabilityTriadPriority,
|
|
25
|
+
sortCapabilityInventoryEntries,
|
|
26
|
+
filterCapabilityInventoryEntries
|
|
27
|
+
} = require('../magicball/capability-inventory-view-model');
|
|
28
|
+
const { runCapabilityInventoryService } = require('../capability/inventory-service');
|
|
29
|
+
const {
|
|
30
|
+
listCapabilityCatalogService,
|
|
31
|
+
searchCapabilityCatalogService,
|
|
32
|
+
showCapabilityTemplateService,
|
|
33
|
+
matchCapabilityTemplatesService,
|
|
34
|
+
useCapabilityTemplateService
|
|
35
|
+
} = require('../capability/catalog-service');
|
|
18
36
|
const packageJson = require('../../package.json');
|
|
19
37
|
|
|
20
38
|
const DEFAULT_ITERATION_DIR = '.sce/reports/capability-iteration';
|
|
@@ -820,210 +838,8 @@ async function listCapabilityInventorySceneIds(options = {}, dependencies = {})
|
|
|
820
838
|
return [];
|
|
821
839
|
}
|
|
822
840
|
|
|
823
|
-
function resolveCapabilityTriadPriority(entry) {
|
|
824
|
-
const missing = Array.isArray(entry && entry.release_readiness_ui && entry.release_readiness_ui.blocking_missing)
|
|
825
|
-
? entry.release_readiness_ui.blocking_missing
|
|
826
|
-
: [];
|
|
827
|
-
if (missing.includes('decision_strategy')) {
|
|
828
|
-
return 0;
|
|
829
|
-
}
|
|
830
|
-
if (missing.includes('business_rules')) {
|
|
831
|
-
return 1;
|
|
832
|
-
}
|
|
833
|
-
if (missing.includes('entity_relation')) {
|
|
834
|
-
return 2;
|
|
835
|
-
}
|
|
836
|
-
return 3;
|
|
837
|
-
}
|
|
838
|
-
|
|
839
841
|
function buildCapabilityMagicballStatus(input = {}) {
|
|
840
|
-
|
|
841
|
-
return {
|
|
842
|
-
attention_level: attention,
|
|
843
|
-
status_tone: attention === 'critical' ? 'danger' : (attention === 'high' ? 'warning' : (attention === 'low' ? 'success' : 'info')),
|
|
844
|
-
status_label: normalizeText(input.status_label) || null,
|
|
845
|
-
blocking_summary: normalizeText(input.blocking_summary) || null,
|
|
846
|
-
recommended_action: normalizeText(input.recommended_action) || null
|
|
847
|
-
};
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
function buildCapabilityInventorySceneAdvice(entry) {
|
|
851
|
-
const sceneId = String(entry && entry.scene_id || 'scene.unknown');
|
|
852
|
-
const releaseUi = entry && entry.release_readiness_ui ? entry.release_readiness_ui : { publish_ready: true, blocking_missing: [] };
|
|
853
|
-
const missing = Array.isArray(releaseUi.blocking_missing) ? releaseUi.blocking_missing : [];
|
|
854
|
-
const valueScore = Number(entry && entry.score_preview && entry.score_preview.value_score || 0);
|
|
855
|
-
|
|
856
|
-
let attentionLevel = 'low';
|
|
857
|
-
let recommendedAction = '可直接发布';
|
|
858
|
-
let blockingSummary = '已满足发布前置条件';
|
|
859
|
-
let nextAction = 'publish';
|
|
860
|
-
|
|
861
|
-
if (!releaseUi.publish_ready) {
|
|
862
|
-
if (missing.includes('decision_strategy')) {
|
|
863
|
-
attentionLevel = 'critical';
|
|
864
|
-
recommendedAction = '补齐决策策略';
|
|
865
|
-
blockingSummary = '缺决策策略,暂不可发布';
|
|
866
|
-
nextAction = 'fill_decision_strategy';
|
|
867
|
-
} else if (missing.includes('business_rules')) {
|
|
868
|
-
attentionLevel = 'high';
|
|
869
|
-
recommendedAction = '补齐业务规则';
|
|
870
|
-
blockingSummary = '缺业务规则,暂不可发布';
|
|
871
|
-
nextAction = 'fill_business_rules';
|
|
872
|
-
} else if (missing.includes('entity_relation')) {
|
|
873
|
-
attentionLevel = 'medium';
|
|
874
|
-
recommendedAction = '补齐实体关系';
|
|
875
|
-
blockingSummary = '缺实体关系,暂不可发布';
|
|
876
|
-
nextAction = 'fill_entity_relation';
|
|
877
|
-
} else {
|
|
878
|
-
attentionLevel = 'medium';
|
|
879
|
-
recommendedAction = '补齐本体能力';
|
|
880
|
-
blockingSummary = '本体能力不完整,暂不可发布';
|
|
881
|
-
nextAction = 'repair_ontology_core';
|
|
882
|
-
}
|
|
883
|
-
} else if (valueScore >= 70) {
|
|
884
|
-
attentionLevel = 'low';
|
|
885
|
-
recommendedAction = '进入模板构建';
|
|
886
|
-
blockingSummary = '能力成熟度较高,可进入模板构建/发布';
|
|
887
|
-
nextAction = 'build_template';
|
|
888
|
-
} else {
|
|
889
|
-
attentionLevel = 'medium';
|
|
890
|
-
recommendedAction = '继续补充任务证据';
|
|
891
|
-
blockingSummary = '已可发布,但建议先补强任务与验证证据';
|
|
892
|
-
nextAction = 'strengthen_evidence';
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
return {
|
|
896
|
-
attention_level: attentionLevel,
|
|
897
|
-
recommended_action: recommendedAction,
|
|
898
|
-
blocking_summary: blockingSummary,
|
|
899
|
-
next_action: nextAction,
|
|
900
|
-
next_command: 'sce capability extract --scene ' + sceneId + ' --json',
|
|
901
|
-
mb_status: buildCapabilityMagicballStatus({
|
|
902
|
-
attention_level: attentionLevel,
|
|
903
|
-
status_label: releaseUi.publish_ready ? 'publish_ready' : 'blocked',
|
|
904
|
-
blocking_summary: blockingSummary,
|
|
905
|
-
recommended_action: recommendedAction
|
|
906
|
-
})
|
|
907
|
-
};
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
function buildCapabilityInventorySummaryStats(entries) {
|
|
911
|
-
const items = Array.isArray(entries) ? entries : [];
|
|
912
|
-
const summary = {
|
|
913
|
-
publish_ready_count: 0,
|
|
914
|
-
blocked_count: 0,
|
|
915
|
-
missing_triads: {
|
|
916
|
-
decision_strategy: 0,
|
|
917
|
-
business_rules: 0,
|
|
918
|
-
entity_relation: 0
|
|
919
|
-
}
|
|
920
|
-
};
|
|
921
|
-
|
|
922
|
-
for (const entry of items) {
|
|
923
|
-
const ready = Boolean(entry && entry.release_readiness_ui && entry.release_readiness_ui.publish_ready);
|
|
924
|
-
if (ready) {
|
|
925
|
-
summary.publish_ready_count += 1;
|
|
926
|
-
} else {
|
|
927
|
-
summary.blocked_count += 1;
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
const missing = Array.isArray(entry && entry.release_readiness_ui && entry.release_readiness_ui.blocking_missing)
|
|
931
|
-
? entry.release_readiness_ui.blocking_missing
|
|
932
|
-
: [];
|
|
933
|
-
for (const triad of Object.keys(summary.missing_triads)) {
|
|
934
|
-
if (missing.includes(triad)) {
|
|
935
|
-
summary.missing_triads[triad] += 1;
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
return summary;
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
function buildCapabilityInventorySummaryRecommendations(entries) {
|
|
944
|
-
const items = Array.isArray(entries) ? entries : [];
|
|
945
|
-
const recommendations = [];
|
|
946
|
-
const blocked = items.filter((item) => !(item && item.release_readiness_ui && item.release_readiness_ui.publish_ready));
|
|
947
|
-
const missingDecision = blocked.filter((item) => Array.isArray(item.release_readiness_ui && item.release_readiness_ui.blocking_missing) && item.release_readiness_ui.blocking_missing.includes('decision_strategy'));
|
|
948
|
-
const missingRules = blocked.filter((item) => Array.isArray(item.release_readiness_ui && item.release_readiness_ui.blocking_missing) && item.release_readiness_ui.blocking_missing.includes('business_rules'));
|
|
949
|
-
const readyScenes = items.filter((item) => item && item.release_readiness_ui && item.release_readiness_ui.publish_ready);
|
|
950
|
-
|
|
951
|
-
if (missingDecision.length > 0) {
|
|
952
|
-
recommendations.push('优先处理缺决策策略的 scene(' + missingDecision.length + ')');
|
|
953
|
-
}
|
|
954
|
-
if (missingRules.length > 0) {
|
|
955
|
-
recommendations.push('其次处理缺业务规则的 scene(' + missingRules.length + ')');
|
|
956
|
-
}
|
|
957
|
-
if (readyScenes.length > 0) {
|
|
958
|
-
recommendations.push('可优先推进可发布 scene 进入模板构建(' + readyScenes.length + ')');
|
|
959
|
-
}
|
|
960
|
-
if (blocked.length === 0 && readyScenes.length === 0 && items.length > 0) {
|
|
961
|
-
recommendations.push('当前 scene 已基本稳定,可继续补强验证证据');
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
return recommendations;
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
function buildCapabilityInventoryQuickFilters(summaryStats) {
|
|
968
|
-
const stats = summaryStats || { blocked_count: 0, missing_triads: {} };
|
|
969
|
-
const filters = [];
|
|
970
|
-
if (Number(stats.blocked_count || 0) > 0) {
|
|
971
|
-
filters.push({ id: 'blocked', label: '不可发布', query: { release_ready: false, missing_triad: null } });
|
|
972
|
-
}
|
|
973
|
-
for (const triad of ['decision_strategy', 'business_rules', 'entity_relation']) {
|
|
974
|
-
if (Number(stats.missing_triads && stats.missing_triads[triad] || 0) > 0) {
|
|
975
|
-
filters.push({ id: 'missing_' + triad, label: '缺' + triad, query: { release_ready: false, missing_triad: triad } });
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
if (Number(stats.publish_ready_count || 0) > 0) {
|
|
979
|
-
filters.push({ id: 'ready', label: '可发布', query: { release_ready: true, missing_triad: null } });
|
|
980
|
-
}
|
|
981
|
-
return filters;
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
function sortCapabilityInventoryEntries(entries) {
|
|
985
|
-
return [...(Array.isArray(entries) ? entries : [])].sort((left, right) => {
|
|
986
|
-
const leftReady = Boolean(left && left.release_readiness_ui && left.release_readiness_ui.publish_ready);
|
|
987
|
-
const rightReady = Boolean(right && right.release_readiness_ui && right.release_readiness_ui.publish_ready);
|
|
988
|
-
if (leftReady !== rightReady) {
|
|
989
|
-
return leftReady ? 1 : -1;
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
const triadDelta = resolveCapabilityTriadPriority(left) - resolveCapabilityTriadPriority(right);
|
|
993
|
-
if (triadDelta !== 0) {
|
|
994
|
-
return triadDelta;
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
const leftValue = Number(left && left.score_preview && left.score_preview.value_score || 0);
|
|
998
|
-
const rightValue = Number(right && right.score_preview && right.score_preview.value_score || 0);
|
|
999
|
-
if (leftValue !== rightValue) {
|
|
1000
|
-
return rightValue - leftValue;
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
return String(left && left.scene_id || '').localeCompare(String(right && right.scene_id || ''));
|
|
1004
|
-
});
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
function filterCapabilityInventoryEntries(entries, options = {}) {
|
|
1008
|
-
const normalizedMissingTriad = normalizeText(options.missingTriad || options.missing_triad).toLowerCase();
|
|
1009
|
-
const releaseReadyFilter = normalizeText(options.releaseReady || options.release_ready).toLowerCase();
|
|
1010
|
-
return (Array.isArray(entries) ? entries : []).filter((entry) => {
|
|
1011
|
-
if (releaseReadyFilter) {
|
|
1012
|
-
const expected = ['1', 'true', 'yes', 'ready'].includes(releaseReadyFilter);
|
|
1013
|
-
if (Boolean(entry.release_readiness_ui && entry.release_readiness_ui.publish_ready) !== expected) {
|
|
1014
|
-
return false;
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
if (normalizedMissingTriad) {
|
|
1018
|
-
const missing = Array.isArray(entry.release_readiness_ui && entry.release_readiness_ui.blocking_missing)
|
|
1019
|
-
? entry.release_readiness_ui.blocking_missing
|
|
1020
|
-
: [];
|
|
1021
|
-
if (!missing.includes(normalizedMissingTriad)) {
|
|
1022
|
-
return false;
|
|
1023
|
-
}
|
|
1024
|
-
}
|
|
1025
|
-
return true;
|
|
1026
|
-
});
|
|
842
|
+
return buildMagicballStatusLanguage(input);
|
|
1027
843
|
}
|
|
1028
844
|
|
|
1029
845
|
async function runCapabilityInventoryCommand(options = {}, dependencies = {}) {
|
|
@@ -1031,70 +847,27 @@ async function runCapabilityInventoryCommand(options = {}, dependencies = {}) {
|
|
|
1031
847
|
const fileSystem = dependencies.fileSystem || fs;
|
|
1032
848
|
const env = dependencies.env || process.env;
|
|
1033
849
|
const sceneIds = await listCapabilityInventorySceneIds(options, { projectPath, fileSystem, env });
|
|
1034
|
-
const
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
scene_id: sceneId,
|
|
1050
|
-
summary: candidate.summary,
|
|
1051
|
-
source: candidate.source,
|
|
1052
|
-
ontology_scope: candidate.ontology_scope,
|
|
1053
|
-
ontology_core: candidate.ontology_core,
|
|
1054
|
-
ontology_core_ui: buildOntologyCoreUiState(candidate.ontology_core),
|
|
1055
|
-
release_readiness: releaseReadiness,
|
|
1056
|
-
release_readiness_ui: buildCapabilityReleaseReadinessUi(releaseReadiness),
|
|
1057
|
-
score_preview: score
|
|
1058
|
-
};
|
|
1059
|
-
scenes.push({
|
|
1060
|
-
...sceneEntry,
|
|
1061
|
-
...buildCapabilityInventorySceneAdvice(sceneEntry)
|
|
1062
|
-
});
|
|
1063
|
-
}
|
|
1064
|
-
|
|
1065
|
-
const filteredScenes = sortCapabilityInventoryEntries(filterCapabilityInventoryEntries(scenes, options));
|
|
1066
|
-
const summaryStats = buildCapabilityInventorySummaryStats(filteredScenes);
|
|
1067
|
-
const releaseReadyFilterRaw = normalizeText(options.releaseReady || options.release_ready).toLowerCase();
|
|
1068
|
-
const payload = {
|
|
1069
|
-
mode: 'capability-inventory',
|
|
1070
|
-
generated_at: new Date().toISOString(),
|
|
1071
|
-
query: {
|
|
1072
|
-
protocol_version: '1.0',
|
|
1073
|
-
scene_id: normalizeText(options.scene || options.sceneId || options.scene_id) || null,
|
|
1074
|
-
limit: limit,
|
|
1075
|
-
sample_limit: toPositiveInteger(options.sample_limit, 5),
|
|
1076
|
-
filters: {
|
|
1077
|
-
release_ready: releaseReadyFilterRaw ? ['1', 'true', 'yes', 'ready'].includes(releaseReadyFilterRaw) : null,
|
|
1078
|
-
missing_triad: normalizeText(options.missingTriad || options.missing_triad) || null
|
|
1079
|
-
}
|
|
1080
|
-
},
|
|
1081
|
-
scene_total: scenes.length,
|
|
1082
|
-
scene_count: filteredScenes.length,
|
|
1083
|
-
summary_stats: summaryStats,
|
|
1084
|
-
summary_recommendations: buildCapabilityInventorySummaryRecommendations(filteredScenes),
|
|
1085
|
-
quick_filters: buildCapabilityInventoryQuickFilters(summaryStats),
|
|
1086
|
-
sort: {
|
|
1087
|
-
strategy: 'publish_ready -> missing_triad_priority -> value_score_desc -> scene_id',
|
|
1088
|
-
triad_priority: ['decision_strategy', 'business_rules', 'entity_relation']
|
|
1089
|
-
},
|
|
1090
|
-
scenes: filteredScenes
|
|
1091
|
-
};
|
|
850
|
+
const payload = await runCapabilityInventoryService(options, {
|
|
851
|
+
sceneIds,
|
|
852
|
+
buildCandidatePayload: buildCapabilityCandidatePayload,
|
|
853
|
+
buildScoreFromCandidate,
|
|
854
|
+
buildCapabilityReleaseReadiness,
|
|
855
|
+
buildOntologyCoreUiState,
|
|
856
|
+
buildCapabilityReleaseReadinessUi,
|
|
857
|
+
buildCapabilityInventorySceneAdvice,
|
|
858
|
+
buildCapabilityInventorySummaryStats,
|
|
859
|
+
buildCapabilityInventorySummaryRecommendations,
|
|
860
|
+
buildCapabilityInventoryQuickFilters,
|
|
861
|
+
sortCapabilityInventoryEntries,
|
|
862
|
+
filterCapabilityInventoryEntries,
|
|
863
|
+
runtime: dependencies
|
|
864
|
+
});
|
|
1092
865
|
|
|
1093
866
|
if (normalizeBoolean(options.json, false)) {
|
|
1094
867
|
return payload;
|
|
1095
868
|
}
|
|
1096
869
|
console.log(chalk.green('✅ Capability inventory generated'));
|
|
1097
|
-
console.log(chalk.gray(' Scenes: ' +
|
|
870
|
+
console.log(chalk.gray(' Scenes: ' + payload.scene_count));
|
|
1098
871
|
return payload;
|
|
1099
872
|
}
|
|
1100
873
|
|
|
@@ -1355,242 +1128,84 @@ function displayCapabilityCatalog(templates, options = {}) {
|
|
|
1355
1128
|
}
|
|
1356
1129
|
|
|
1357
1130
|
async function listCapabilityCatalog(options = {}) {
|
|
1358
|
-
const
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
templateType: 'capability-template',
|
|
1363
|
-
compatibleWith: options.compatibleWith,
|
|
1364
|
-
riskLevel: options.risk
|
|
1365
|
-
})).map((template) => enrichCapabilityTemplateForUi(template)), options);
|
|
1131
|
+
const payload = await listCapabilityCatalogService(options, {
|
|
1132
|
+
filterCapabilityCatalogEntries,
|
|
1133
|
+
enrichCapabilityTemplateForUi
|
|
1134
|
+
});
|
|
1366
1135
|
if (normalizeBoolean(options.json, false)) {
|
|
1367
|
-
return
|
|
1368
|
-
mode: 'capability-catalog-list',
|
|
1369
|
-
templates
|
|
1370
|
-
};
|
|
1136
|
+
return payload;
|
|
1371
1137
|
}
|
|
1372
|
-
displayCapabilityCatalog(templates, options);
|
|
1373
|
-
return { templates };
|
|
1138
|
+
displayCapabilityCatalog(payload.templates, options);
|
|
1139
|
+
return { templates: payload.templates };
|
|
1374
1140
|
}
|
|
1375
1141
|
|
|
1376
1142
|
async function searchCapabilityCatalog(keyword, options = {}) {
|
|
1377
|
-
const
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
templateType: 'capability-template',
|
|
1382
|
-
compatibleWith: options.compatibleWith,
|
|
1383
|
-
riskLevel: options.risk
|
|
1384
|
-
})).map((template) => enrichCapabilityTemplateForUi(template)), options);
|
|
1143
|
+
const payload = await searchCapabilityCatalogService(keyword, {
|
|
1144
|
+
filterCapabilityCatalogEntries,
|
|
1145
|
+
enrichCapabilityTemplateForUi
|
|
1146
|
+
});
|
|
1385
1147
|
if (normalizeBoolean(options.json, false)) {
|
|
1386
|
-
return
|
|
1387
|
-
mode: 'capability-catalog-search',
|
|
1388
|
-
keyword,
|
|
1389
|
-
templates
|
|
1390
|
-
};
|
|
1148
|
+
return payload;
|
|
1391
1149
|
}
|
|
1392
|
-
displayCapabilityCatalog(templates, options);
|
|
1393
|
-
return { templates };
|
|
1150
|
+
displayCapabilityCatalog(payload.templates, options);
|
|
1151
|
+
return { templates: payload.templates };
|
|
1394
1152
|
}
|
|
1395
1153
|
|
|
1396
1154
|
async function showCapabilityTemplate(templatePath, options = {}) {
|
|
1397
|
-
const
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
const sourcePath = manager.cacheManager.getSourceCachePath(sourceName);
|
|
1402
|
-
const templateDir = path.join(sourcePath, templateId);
|
|
1403
|
-
const capabilityFile = path.join(templateDir, 'capability-template.json');
|
|
1404
|
-
let templatePayload = null;
|
|
1405
|
-
if (await fs.pathExists(capabilityFile)) {
|
|
1406
|
-
try {
|
|
1407
|
-
templatePayload = await fs.readJson(capabilityFile);
|
|
1408
|
-
} catch (_error) {
|
|
1409
|
-
templatePayload = null;
|
|
1410
|
-
}
|
|
1411
|
-
}
|
|
1412
|
-
const result = {
|
|
1413
|
-
mode: 'capability-catalog-show',
|
|
1414
|
-
template,
|
|
1415
|
-
template_file: await fs.pathExists(capabilityFile) ? capabilityFile : null,
|
|
1416
|
-
payload: templatePayload
|
|
1417
|
-
};
|
|
1155
|
+
const payload = await showCapabilityTemplateService(templatePath, {
|
|
1156
|
+
parseTemplatePath,
|
|
1157
|
+
enrichCapabilityTemplateForUi
|
|
1158
|
+
});
|
|
1418
1159
|
if (normalizeBoolean(options.json, false)) {
|
|
1419
|
-
return
|
|
1160
|
+
return payload;
|
|
1420
1161
|
}
|
|
1421
1162
|
console.log(chalk.green('✅ Capability template loaded'));
|
|
1422
|
-
console.log(chalk.gray(
|
|
1423
|
-
console.log(chalk.gray(
|
|
1424
|
-
if (
|
|
1163
|
+
console.log(chalk.gray(' ID: ' + payload.template.id));
|
|
1164
|
+
console.log(chalk.gray(' Name: ' + payload.template.name));
|
|
1165
|
+
if (payload.payload) {
|
|
1425
1166
|
console.log(chalk.gray(' Payload: capability-template.json loaded'));
|
|
1426
1167
|
}
|
|
1427
|
-
return
|
|
1168
|
+
return payload;
|
|
1428
1169
|
}
|
|
1429
1170
|
|
|
1430
1171
|
async function matchCapabilityTemplates(options = {}) {
|
|
1431
|
-
const
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
throw new Error(`problem-domain-chain missing for spec ${specId}`);
|
|
1440
|
-
}
|
|
1441
|
-
if (chain.error && normalizeBoolean(options.strict, false)) {
|
|
1442
|
-
throw new Error(`problem-domain-chain invalid: ${chain.error}`);
|
|
1443
|
-
}
|
|
1444
|
-
const domainChain = chain.payload || {};
|
|
1445
|
-
const specScope = buildOntologyScopeFromChain(domainChain);
|
|
1446
|
-
const queryTokens = normalizeTokenList(options.query)
|
|
1447
|
-
.concat(normalizeTokenList(domainChain.problem && domainChain.problem.statement))
|
|
1448
|
-
.concat(normalizeTokenList(domainChain.scene_id));
|
|
1449
|
-
const manager = new TemplateManager();
|
|
1450
|
-
const templates = await manager.listTemplates({
|
|
1451
|
-
source: options.source,
|
|
1452
|
-
templateType: 'capability-template',
|
|
1453
|
-
compatibleWith: options.compatibleWith,
|
|
1454
|
-
riskLevel: options.risk
|
|
1172
|
+
const payload = await matchCapabilityTemplatesService(options, {
|
|
1173
|
+
loadSpecDomainChain,
|
|
1174
|
+
buildOntologyScopeFromChain,
|
|
1175
|
+
normalizeTokenList,
|
|
1176
|
+
buildOntologyOverlap,
|
|
1177
|
+
buildKeywordScore,
|
|
1178
|
+
buildCoreOntologySummary,
|
|
1179
|
+
buildOntologyCoreUiState
|
|
1455
1180
|
});
|
|
1456
|
-
const matches = templates.map((template) => {
|
|
1457
|
-
const overlap = buildOntologyOverlap(specScope, template.ontology_scope || {});
|
|
1458
|
-
const scenarioScore = template.applicable_scenarios && domainChain.scene_id
|
|
1459
|
-
? (template.applicable_scenarios.includes(domainChain.scene_id) ? 1 : 0)
|
|
1460
|
-
: 0;
|
|
1461
|
-
const keywordScore = buildKeywordScore(template, queryTokens);
|
|
1462
|
-
const totalScore = (overlap.score * 0.6) + (scenarioScore * 0.2) + (keywordScore * 0.2);
|
|
1463
|
-
return {
|
|
1464
|
-
template_id: template.id,
|
|
1465
|
-
source: template.source,
|
|
1466
|
-
name: template.name,
|
|
1467
|
-
description: template.description,
|
|
1468
|
-
category: template.category,
|
|
1469
|
-
risk_level: template.risk_level,
|
|
1470
|
-
ontology_core: template.ontology_core || buildCoreOntologySummary(template.ontology_scope || {}),
|
|
1471
|
-
ontology_core_ui: buildOntologyCoreUiState(template.ontology_core || buildCoreOntologySummary(template.ontology_scope || {})),
|
|
1472
|
-
score: Math.round(totalScore * 100),
|
|
1473
|
-
score_components: {
|
|
1474
|
-
ontology: Number(overlap.score.toFixed(3)),
|
|
1475
|
-
scenario: scenarioScore,
|
|
1476
|
-
keyword: Number(keywordScore.toFixed(3))
|
|
1477
|
-
},
|
|
1478
|
-
overlap
|
|
1479
|
-
};
|
|
1480
|
-
}).sort((a, b) => b.score - a.score);
|
|
1481
|
-
|
|
1482
|
-
const limit = toPositiveInteger(options.limit, 10);
|
|
1483
|
-
const payload = {
|
|
1484
|
-
mode: 'capability-match',
|
|
1485
|
-
spec_id: specId,
|
|
1486
|
-
scene_id: domainChain.scene_id || null,
|
|
1487
|
-
query: normalizeText(options.query) || null,
|
|
1488
|
-
ontology_source: chain.exists ? chain.path : null,
|
|
1489
|
-
match_count: matches.length,
|
|
1490
|
-
matches: matches.slice(0, limit),
|
|
1491
|
-
warnings: chain.exists ? [] : ['problem-domain-chain missing; ontology-based match unavailable']
|
|
1492
|
-
};
|
|
1493
1181
|
if (normalizeBoolean(options.json, false)) {
|
|
1494
1182
|
return payload;
|
|
1495
1183
|
}
|
|
1496
1184
|
console.log(chalk.green('✅ Capability match completed'));
|
|
1497
|
-
console.log(chalk.gray(
|
|
1498
|
-
console.log(chalk.gray(
|
|
1185
|
+
console.log(chalk.gray(' Spec: ' + payload.spec_id));
|
|
1186
|
+
console.log(chalk.gray(' Matches: ' + payload.matches.length));
|
|
1499
1187
|
return payload;
|
|
1500
1188
|
}
|
|
1501
1189
|
|
|
1502
1190
|
async function useCapabilityTemplate(options = {}) {
|
|
1503
|
-
const
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
throw new Error('cannot use --apply with --no-write');
|
|
1511
|
-
}
|
|
1512
|
-
const specId = normalizeText(options.spec || options.specId) || null;
|
|
1513
|
-
const manager = new TemplateManager();
|
|
1514
|
-
const template = await manager.showTemplate(templateId);
|
|
1515
|
-
const { sourceName, templateId: parsedTemplateId } = parseTemplatePath(templateId);
|
|
1516
|
-
await manager.ensureCached(sourceName);
|
|
1517
|
-
const sourcePath = manager.cacheManager.getSourceCachePath(sourceName);
|
|
1518
|
-
const templateDir = path.join(sourcePath, parsedTemplateId);
|
|
1519
|
-
const capabilityFile = path.join(templateDir, 'capability-template.json');
|
|
1520
|
-
let templatePayload = null;
|
|
1521
|
-
if (await fileSystem.pathExists(capabilityFile)) {
|
|
1522
|
-
try {
|
|
1523
|
-
templatePayload = await fileSystem.readJson(capabilityFile);
|
|
1524
|
-
} catch (_error) {
|
|
1525
|
-
templatePayload = null;
|
|
1526
|
-
}
|
|
1527
|
-
}
|
|
1528
|
-
|
|
1529
|
-
const recommendedTasks = [];
|
|
1530
|
-
if (templatePayload && templatePayload.source_candidate && Array.isArray(templatePayload.source_candidate.specs)) {
|
|
1531
|
-
templatePayload.source_candidate.specs.forEach((spec) => {
|
|
1532
|
-
const sample = Array.isArray(spec.task_sample) ? spec.task_sample : [];
|
|
1533
|
-
sample.forEach((task) => {
|
|
1534
|
-
if (task && task.title) {
|
|
1535
|
-
recommendedTasks.push({
|
|
1536
|
-
title: task.title,
|
|
1537
|
-
source_spec_id: spec.spec_id || null,
|
|
1538
|
-
source_task_id: task.id || null
|
|
1539
|
-
});
|
|
1540
|
-
}
|
|
1541
|
-
});
|
|
1542
|
-
});
|
|
1543
|
-
}
|
|
1544
|
-
if (recommendedTasks.length === 0) {
|
|
1545
|
-
recommendedTasks.push({ title: `Implement capability scope: ${template.name || parsedTemplateId}` });
|
|
1546
|
-
}
|
|
1547
|
-
|
|
1548
|
-
const plan = {
|
|
1549
|
-
mode: 'capability-use-plan',
|
|
1550
|
-
generated_at: new Date().toISOString(),
|
|
1551
|
-
template: {
|
|
1552
|
-
id: template.id,
|
|
1553
|
-
name: template.name,
|
|
1554
|
-
source: template.source,
|
|
1555
|
-
description: template.description,
|
|
1556
|
-
ontology_scope: template.ontology_scope || {},
|
|
1557
|
-
ontology_core: template.ontology_core || buildCoreOntologySummary(template.ontology_scope || {}),
|
|
1558
|
-
ontology_core_ui: buildOntologyCoreUiState(template.ontology_core || buildCoreOntologySummary(template.ontology_scope || {}))
|
|
1559
|
-
},
|
|
1560
|
-
spec_id: specId,
|
|
1561
|
-
recommended_tasks: recommendedTasks
|
|
1562
|
-
};
|
|
1563
|
-
|
|
1564
|
-
const outputPath = normalizeText(options.out) || buildDefaultUsePlanPath(specId || 'spec', template.id);
|
|
1565
|
-
if (normalizeBoolean(options.write, true)) {
|
|
1566
|
-
await fileSystem.ensureDir(path.dirname(path.join(projectPath, outputPath)));
|
|
1567
|
-
await fileSystem.writeJson(path.join(projectPath, outputPath), plan, { spaces: 2 });
|
|
1568
|
-
plan.output_file = outputPath;
|
|
1569
|
-
}
|
|
1570
|
-
|
|
1571
|
-
if (normalizeBoolean(options.apply, false)) {
|
|
1572
|
-
if (!specId) {
|
|
1573
|
-
throw new Error('spec is required for --apply');
|
|
1574
|
-
}
|
|
1575
|
-
plan.apply = await appendCapabilityPlanToSpecTasks({
|
|
1576
|
-
projectPath,
|
|
1577
|
-
spec: specId,
|
|
1578
|
-
sectionTitle: options.sectionTitle
|
|
1579
|
-
}, plan, fileSystem);
|
|
1580
|
-
}
|
|
1581
|
-
|
|
1191
|
+
const payload = await useCapabilityTemplateService(options, {
|
|
1192
|
+
parseTemplatePath,
|
|
1193
|
+
buildCoreOntologySummary,
|
|
1194
|
+
buildOntologyCoreUiState,
|
|
1195
|
+
buildDefaultUsePlanPath,
|
|
1196
|
+
appendCapabilityPlanToSpecTasks
|
|
1197
|
+
});
|
|
1582
1198
|
if (!normalizeBoolean(options.json, false)) {
|
|
1583
1199
|
console.log(chalk.green('✅ Capability use plan generated'));
|
|
1584
|
-
console.log(chalk.gray(
|
|
1585
|
-
if (
|
|
1586
|
-
console.log(chalk.gray(
|
|
1200
|
+
console.log(chalk.gray(' Template: ' + payload.template.id));
|
|
1201
|
+
if (payload.spec_id) {
|
|
1202
|
+
console.log(chalk.gray(' Spec: ' + payload.spec_id));
|
|
1587
1203
|
}
|
|
1588
|
-
if (
|
|
1589
|
-
console.log(chalk.gray(
|
|
1204
|
+
if (payload.output_file) {
|
|
1205
|
+
console.log(chalk.gray(' Output: ' + payload.output_file));
|
|
1590
1206
|
}
|
|
1591
1207
|
}
|
|
1592
|
-
|
|
1593
|
-
return plan;
|
|
1208
|
+
return payload;
|
|
1594
1209
|
}
|
|
1595
1210
|
|
|
1596
1211
|
function registerCapabilityCommands(program) {
|
package/lib/commands/scene.js
CHANGED