scene-capability-engine 3.6.57 → 3.6.59
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 +18 -0
- package/README.md +5 -3
- package/README.zh.md +5 -3
- package/bin/scene-capability-engine.js +2 -0
- package/docs/command-reference.md +72 -0
- package/docs/magicball-adaptation-task-checklist-v1.md +65 -10
- package/docs/magicball-cli-invocation-examples.md +53 -8
- package/docs/magicball-engineering-projection-contract.md +175 -0
- package/docs/magicball-frontend-state-and-command-mapping.md +42 -5
- package/docs/magicball-integration-doc-index.md +19 -5
- package/docs/magicball-integration-issue-tracker.md +15 -5
- package/docs/magicball-mode-home-and-ontology-empty-state-playbook.md +13 -5
- package/docs/magicball-project-portfolio-contract.md +216 -0
- package/docs/magicball-sce-adaptation-guide.md +18 -4
- package/docs/magicball-ui-surface-checklist.md +25 -0
- package/docs/magicball-write-auth-adaptation-guide.md +3 -1
- package/docs/release-checklist.md +8 -0
- package/docs/releases/README.md +2 -0
- package/docs/releases/v3.6.58.md +27 -0
- package/docs/releases/v3.6.59.md +18 -0
- package/docs/zh/release-checklist.md +8 -0
- package/docs/zh/releases/README.md +2 -0
- package/docs/zh/releases/v3.6.58.md +27 -0
- package/docs/zh/releases/v3.6.59.md +18 -0
- package/lib/app/engineering-scaffold-service.js +154 -0
- package/lib/commands/app.js +442 -13
- package/lib/commands/project.js +105 -0
- package/lib/commands/scene.js +16 -0
- package/lib/project/portfolio-projection-service.js +389 -0
- package/lib/project/supervision-projection-service.js +329 -0
- package/lib/project/target-resolution-service.js +180 -0
- package/lib/scene/delivery-projection-service.js +650 -0
- package/package.json +6 -2
- package/scripts/magicball-engineering-contract-audit.js +347 -0
- package/scripts/magicball-project-contract-audit.js +254 -0
- package/template/.sce/README.md +2 -2
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { buildProjectPortfolioProjection } = require('./portfolio-projection-service');
|
|
3
|
+
|
|
4
|
+
function normalizeString(value) {
|
|
5
|
+
if (typeof value !== 'string') {
|
|
6
|
+
return '';
|
|
7
|
+
}
|
|
8
|
+
return value.trim();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function normalizeText(value) {
|
|
12
|
+
return normalizeString(value).toLowerCase();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function collectProjectAliases(project = {}) {
|
|
16
|
+
const aliases = [];
|
|
17
|
+
const fields = [
|
|
18
|
+
project.projectId,
|
|
19
|
+
project.workspaceId,
|
|
20
|
+
project.projectName,
|
|
21
|
+
project.appKey,
|
|
22
|
+
project.projectRoot ? path.basename(project.projectRoot) : null
|
|
23
|
+
];
|
|
24
|
+
for (const field of fields) {
|
|
25
|
+
const normalized = normalizeText(field);
|
|
26
|
+
if (!normalized || aliases.includes(normalized)) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
aliases.push(normalized);
|
|
30
|
+
}
|
|
31
|
+
return aliases;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function scoreProjectMatch(requestText, project = {}) {
|
|
35
|
+
const normalizedRequest = normalizeText(requestText);
|
|
36
|
+
if (!normalizedRequest) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const aliases = collectProjectAliases(project);
|
|
41
|
+
let bestScore = 0;
|
|
42
|
+
let reasonCode = 'target.request_match';
|
|
43
|
+
|
|
44
|
+
for (const alias of aliases) {
|
|
45
|
+
if (normalizedRequest === alias) {
|
|
46
|
+
bestScore = Math.max(bestScore, 1);
|
|
47
|
+
reasonCode = 'target.alias_exact_match';
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (normalizedRequest.includes(alias) && alias.length >= 2) {
|
|
51
|
+
bestScore = Math.max(bestScore, 0.96);
|
|
52
|
+
reasonCode = 'target.alias_contained_match';
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (alias.includes(normalizedRequest) && normalizedRequest.length >= 3) {
|
|
56
|
+
bestScore = Math.max(bestScore, 0.84);
|
|
57
|
+
reasonCode = 'target.alias_prefix_match';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (bestScore <= 0) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
projectId: project.projectId,
|
|
67
|
+
workspaceId: project.workspaceId || null,
|
|
68
|
+
projectName: project.projectName || null,
|
|
69
|
+
appKey: project.appKey || null,
|
|
70
|
+
confidence: Number(bestScore.toFixed(2)),
|
|
71
|
+
reasonCode
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function buildResolutionCallerContext(options = {}, portfolio = {}) {
|
|
76
|
+
const portfolioContext = portfolio && portfolio.callerContext && typeof portfolio.callerContext === 'object'
|
|
77
|
+
? portfolio.callerContext
|
|
78
|
+
: {};
|
|
79
|
+
const explicitCurrentProject = normalizeString(options.currentProject);
|
|
80
|
+
const explicitDeviceId = normalizeString(options.device);
|
|
81
|
+
const explicitToolInstanceId = normalizeString(options.toolInstanceId);
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
...(explicitCurrentProject || portfolioContext.projectId
|
|
85
|
+
? { currentProjectId: explicitCurrentProject || portfolioContext.projectId }
|
|
86
|
+
: {}),
|
|
87
|
+
...(portfolioContext.workspaceId ? { workspaceId: portfolioContext.workspaceId } : {}),
|
|
88
|
+
...(explicitDeviceId || portfolioContext.deviceId
|
|
89
|
+
? { deviceId: explicitDeviceId || portfolioContext.deviceId }
|
|
90
|
+
: {}),
|
|
91
|
+
...(explicitToolInstanceId ? { toolInstanceId: explicitToolInstanceId } : {})
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function resolveProjectTarget(options = {}, dependencies = {}) {
|
|
96
|
+
const requestText = normalizeString(options.request);
|
|
97
|
+
const portfolio = await buildProjectPortfolioProjection({
|
|
98
|
+
workspace: options.workspace
|
|
99
|
+
}, dependencies);
|
|
100
|
+
const callerContext = buildResolutionCallerContext(options, portfolio);
|
|
101
|
+
const currentProjectId = normalizeString(callerContext.currentProjectId);
|
|
102
|
+
const visibleProjects = Array.isArray(portfolio.projects) ? portfolio.projects : [];
|
|
103
|
+
const currentProject = visibleProjects.find((project) => project.projectId === currentProjectId) || null;
|
|
104
|
+
|
|
105
|
+
if (!requestText) {
|
|
106
|
+
if (currentProject) {
|
|
107
|
+
return {
|
|
108
|
+
resolvedAt: new Date().toISOString(),
|
|
109
|
+
callerContext,
|
|
110
|
+
status: 'current-project',
|
|
111
|
+
currentProjectId,
|
|
112
|
+
resolvedProjectId: currentProjectId,
|
|
113
|
+
confidence: 1,
|
|
114
|
+
reasonCode: 'target.current_project'
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
resolvedAt: new Date().toISOString(),
|
|
119
|
+
callerContext,
|
|
120
|
+
status: 'unresolved',
|
|
121
|
+
...(currentProjectId ? { currentProjectId } : {}),
|
|
122
|
+
reasonCode: currentProjectId
|
|
123
|
+
? 'target.current_project_unavailable'
|
|
124
|
+
: 'target.no_request_or_current_project'
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const matches = visibleProjects
|
|
129
|
+
.map((project) => scoreProjectMatch(requestText, project))
|
|
130
|
+
.filter(Boolean)
|
|
131
|
+
.sort((left, right) => {
|
|
132
|
+
if (right.confidence !== left.confidence) {
|
|
133
|
+
return right.confidence - left.confidence;
|
|
134
|
+
}
|
|
135
|
+
return `${left.projectId}`.localeCompare(`${right.projectId}`);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (matches.length === 0) {
|
|
139
|
+
return {
|
|
140
|
+
resolvedAt: new Date().toISOString(),
|
|
141
|
+
callerContext,
|
|
142
|
+
status: 'unresolved',
|
|
143
|
+
...(currentProjectId ? { currentProjectId } : {}),
|
|
144
|
+
reasonCode: 'target.no_match'
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const best = matches[0];
|
|
149
|
+
const second = matches[1];
|
|
150
|
+
const ambiguous = second && Math.abs(best.confidence - second.confidence) < 0.05;
|
|
151
|
+
|
|
152
|
+
if (ambiguous) {
|
|
153
|
+
return {
|
|
154
|
+
resolvedAt: new Date().toISOString(),
|
|
155
|
+
callerContext,
|
|
156
|
+
status: 'ambiguous',
|
|
157
|
+
...(currentProjectId ? { currentProjectId } : {}),
|
|
158
|
+
confidence: best.confidence,
|
|
159
|
+
reasonCode: 'target.ambiguous',
|
|
160
|
+
candidates: matches.slice(0, 5)
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
resolvedAt: new Date().toISOString(),
|
|
166
|
+
callerContext,
|
|
167
|
+
status: currentProjectId && best.projectId === currentProjectId
|
|
168
|
+
? 'current-project'
|
|
169
|
+
: 'resolved-other-project',
|
|
170
|
+
...(currentProjectId ? { currentProjectId } : {}),
|
|
171
|
+
resolvedProjectId: best.projectId,
|
|
172
|
+
confidence: best.confidence,
|
|
173
|
+
reasonCode: best.reasonCode,
|
|
174
|
+
candidates: [best]
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
module.exports = {
|
|
179
|
+
resolveProjectTarget
|
|
180
|
+
};
|