scene-capability-engine 3.6.60 → 3.6.62
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 +15 -0
- package/README.md +4 -4
- package/README.zh.md +4 -4
- package/docs/command-reference.md +37 -4
- package/docs/magicball-adaptation-task-checklist-v1.md +14 -0
- package/docs/magicball-cli-invocation-examples.md +2 -0
- package/docs/magicball-frontend-state-and-command-mapping.md +5 -0
- package/docs/magicball-integration-issue-tracker.md +2 -2
- package/docs/magicball-project-portfolio-contract.md +60 -4
- package/docs/magicball-sce-adaptation-guide.md +2 -0
- package/docs/magicball-task-feedback-timeline-guide.md +0 -1
- package/docs/magicball-ui-surface-checklist.md +2 -0
- package/docs/release-checklist.md +1 -1
- package/docs/releases/README.md +2 -0
- package/docs/releases/v3.6.61.md +21 -0
- package/docs/releases/v3.6.62.md +32 -0
- package/docs/zh/release-checklist.md +1 -1
- package/docs/zh/releases/README.md +2 -0
- package/docs/zh/releases/v3.6.61.md +21 -0
- package/docs/zh/releases/v3.6.62.md +32 -0
- package/lib/commands/project.js +52 -0
- package/lib/commands/studio.js +1 -319
- package/lib/project/candidate-inspection-service.js +216 -0
- package/lib/project/root-onboarding-service.js +350 -0
- package/package.json +1 -1
- package/scripts/magicball-project-contract-audit.js +17 -4
- package/template/.sce/README.md +2 -2
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
|
+
const WorkspaceStateManager = require('../workspace/multi/workspace-state-manager');
|
|
4
|
+
const SmartOrchestrator = require('../adoption/smart-orchestrator');
|
|
5
|
+
const { applyTakeoverBaseline } = require('../workspace/takeover-baseline');
|
|
6
|
+
const {
|
|
7
|
+
PROJECT_CANDIDATE_REASON_CODES,
|
|
8
|
+
inspectProjectCandidate
|
|
9
|
+
} = require('./candidate-inspection-service');
|
|
10
|
+
const {
|
|
11
|
+
buildWorkspaceProjectId
|
|
12
|
+
} = require('./portfolio-projection-service');
|
|
13
|
+
|
|
14
|
+
const PROJECT_ONBOARDING_REASON_CODES = {
|
|
15
|
+
MISSING_ROOT: 'project.onboarding.blocked.missing_root',
|
|
16
|
+
BLOCKED_BY_CANDIDATE: 'project.onboarding.blocked.candidate_state',
|
|
17
|
+
ROOT_ACCEPTED: 'project.onboarding.root_accepted',
|
|
18
|
+
IMPORT_NO_ACTIVATE: 'project.onboarding.import_no_activate',
|
|
19
|
+
REGISTERED: 'project.onboarding.registered',
|
|
20
|
+
ADOPTED: 'project.onboarding.adopted',
|
|
21
|
+
SCAFFOLD_REUSED: 'project.onboarding.scaffold_reused',
|
|
22
|
+
ADOPTION_FAILED: 'project.onboarding.adoption_failed'
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function normalizeString(value) {
|
|
26
|
+
if (typeof value !== 'string') {
|
|
27
|
+
return '';
|
|
28
|
+
}
|
|
29
|
+
return value.trim();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function buildStep(key, status, detail, reasonCode) {
|
|
33
|
+
return {
|
|
34
|
+
key,
|
|
35
|
+
status,
|
|
36
|
+
...(reasonCode ? { reasonCode } : {}),
|
|
37
|
+
...(detail ? { detail } : {})
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function buildWorkspaceNameCandidate(rootDir) {
|
|
42
|
+
const base = path.basename(rootDir).trim().toLowerCase();
|
|
43
|
+
const normalized = base.replace(/[^a-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '');
|
|
44
|
+
return normalized || 'project';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function allocateWorkspaceId(rootDir, stateManager) {
|
|
48
|
+
const base = buildWorkspaceNameCandidate(rootDir);
|
|
49
|
+
if (!await stateManager.hasWorkspace(base)) {
|
|
50
|
+
return base;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
for (let index = 2; index < 1000; index += 1) {
|
|
54
|
+
const candidate = `${base}-${index}`;
|
|
55
|
+
if (!await stateManager.hasWorkspace(candidate)) {
|
|
56
|
+
return candidate;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
throw new Error(`unable to allocate workspace id for root: ${rootDir}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function buildFailureEnvelope(rootInspection, steps, detail, reasonCode) {
|
|
64
|
+
return {
|
|
65
|
+
mode: 'import',
|
|
66
|
+
generated_at: new Date().toISOString(),
|
|
67
|
+
success: false,
|
|
68
|
+
preview: rootInspection,
|
|
69
|
+
summary: rootInspection,
|
|
70
|
+
steps,
|
|
71
|
+
error: {
|
|
72
|
+
reasonCode,
|
|
73
|
+
detail
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function runWithSuppressedConsole(callback, enabled) {
|
|
79
|
+
if (!enabled) {
|
|
80
|
+
return callback();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const originalLog = console.log;
|
|
84
|
+
const originalInfo = console.info;
|
|
85
|
+
const originalWarn = console.warn;
|
|
86
|
+
console.log = () => {};
|
|
87
|
+
console.info = () => {};
|
|
88
|
+
console.warn = () => {};
|
|
89
|
+
try {
|
|
90
|
+
return await callback();
|
|
91
|
+
} finally {
|
|
92
|
+
console.log = originalLog;
|
|
93
|
+
console.info = originalInfo;
|
|
94
|
+
console.warn = originalWarn;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function runProjectRootOnboardingImport(options = {}, dependencies = {}) {
|
|
99
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
100
|
+
const stateManager = dependencies.stateManager || new WorkspaceStateManager(dependencies.workspaceStatePath);
|
|
101
|
+
const root = normalizeString(options.root || options.rootDir);
|
|
102
|
+
if (!root) {
|
|
103
|
+
throw new Error('--root is required');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const rootInspection = await inspectProjectCandidate({ root }, {
|
|
107
|
+
...dependencies,
|
|
108
|
+
fileSystem,
|
|
109
|
+
stateManager
|
|
110
|
+
});
|
|
111
|
+
const steps = [];
|
|
112
|
+
|
|
113
|
+
if (rootInspection.kind === 'invalid') {
|
|
114
|
+
steps.push(buildStep(
|
|
115
|
+
'register',
|
|
116
|
+
'failed',
|
|
117
|
+
'Root directory cannot be onboarded.',
|
|
118
|
+
PROJECT_ONBOARDING_REASON_CODES.BLOCKED_BY_CANDIDATE
|
|
119
|
+
));
|
|
120
|
+
steps.push(buildStep(
|
|
121
|
+
'attach',
|
|
122
|
+
'failed',
|
|
123
|
+
'Local root is not accessible as a project directory.',
|
|
124
|
+
PROJECT_CANDIDATE_REASON_CODES.ROOT_INACCESSIBLE
|
|
125
|
+
));
|
|
126
|
+
steps.push(buildStep(
|
|
127
|
+
'hydrate',
|
|
128
|
+
'failed',
|
|
129
|
+
'Onboarding cannot continue until the root is valid.',
|
|
130
|
+
PROJECT_ONBOARDING_REASON_CODES.BLOCKED_BY_CANDIDATE
|
|
131
|
+
));
|
|
132
|
+
steps.push(buildStep(
|
|
133
|
+
'activate',
|
|
134
|
+
'skipped',
|
|
135
|
+
'Import does not activate invalid roots.',
|
|
136
|
+
PROJECT_ONBOARDING_REASON_CODES.IMPORT_NO_ACTIVATE
|
|
137
|
+
));
|
|
138
|
+
steps.push(buildStep(
|
|
139
|
+
'scaffold',
|
|
140
|
+
'skipped',
|
|
141
|
+
'Scaffold is blocked until the root becomes valid.',
|
|
142
|
+
PROJECT_ONBOARDING_REASON_CODES.BLOCKED_BY_CANDIDATE
|
|
143
|
+
));
|
|
144
|
+
return buildFailureEnvelope(
|
|
145
|
+
rootInspection,
|
|
146
|
+
steps,
|
|
147
|
+
'Root inspection reported an invalid candidate state.',
|
|
148
|
+
PROJECT_ONBOARDING_REASON_CODES.BLOCKED_BY_CANDIDATE
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (rootInspection.reasonCodes.includes(PROJECT_CANDIDATE_REASON_CODES.INVALID_PROJECT_METADATA)) {
|
|
153
|
+
steps.push(buildStep(
|
|
154
|
+
'register',
|
|
155
|
+
'failed',
|
|
156
|
+
'Root contains invalid SCE metadata and cannot be imported safely.',
|
|
157
|
+
PROJECT_CANDIDATE_REASON_CODES.INVALID_PROJECT_METADATA
|
|
158
|
+
));
|
|
159
|
+
steps.push(buildStep(
|
|
160
|
+
'attach',
|
|
161
|
+
'done',
|
|
162
|
+
'Local root is reachable.',
|
|
163
|
+
PROJECT_ONBOARDING_REASON_CODES.ROOT_ACCEPTED
|
|
164
|
+
));
|
|
165
|
+
steps.push(buildStep(
|
|
166
|
+
'hydrate',
|
|
167
|
+
'failed',
|
|
168
|
+
'Existing project metadata must be repaired before import.',
|
|
169
|
+
PROJECT_CANDIDATE_REASON_CODES.INVALID_PROJECT_METADATA
|
|
170
|
+
));
|
|
171
|
+
steps.push(buildStep(
|
|
172
|
+
'activate',
|
|
173
|
+
'skipped',
|
|
174
|
+
'Import does not activate blocked projects.',
|
|
175
|
+
PROJECT_ONBOARDING_REASON_CODES.IMPORT_NO_ACTIVATE
|
|
176
|
+
));
|
|
177
|
+
steps.push(buildStep(
|
|
178
|
+
'scaffold',
|
|
179
|
+
'skipped',
|
|
180
|
+
'Scaffold is blocked by invalid project metadata.',
|
|
181
|
+
PROJECT_CANDIDATE_REASON_CODES.INVALID_PROJECT_METADATA
|
|
182
|
+
));
|
|
183
|
+
return buildFailureEnvelope(
|
|
184
|
+
rootInspection,
|
|
185
|
+
steps,
|
|
186
|
+
'Existing project metadata is invalid.',
|
|
187
|
+
PROJECT_CANDIDATE_REASON_CODES.INVALID_PROJECT_METADATA
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
let onboardingPreview = { ...rootInspection };
|
|
192
|
+
let importResult = null;
|
|
193
|
+
let takeoverBaseline = null;
|
|
194
|
+
|
|
195
|
+
if (rootInspection.kind === 'directory-candidate') {
|
|
196
|
+
const orchestrator = dependencies.smartOrchestrator || new SmartOrchestrator();
|
|
197
|
+
importResult = await runWithSuppressedConsole(() => orchestrator.orchestrate(rootInspection.rootDir, {
|
|
198
|
+
dryRun: false,
|
|
199
|
+
verbose: false,
|
|
200
|
+
skipBackup: false,
|
|
201
|
+
skipUpdate: false
|
|
202
|
+
}), options.json === true);
|
|
203
|
+
|
|
204
|
+
if (!importResult.success) {
|
|
205
|
+
steps.push(buildStep(
|
|
206
|
+
'register',
|
|
207
|
+
'failed',
|
|
208
|
+
'Workspace registration was not attempted because adoption failed.',
|
|
209
|
+
PROJECT_ONBOARDING_REASON_CODES.ADOPTION_FAILED
|
|
210
|
+
));
|
|
211
|
+
steps.push(buildStep(
|
|
212
|
+
'attach',
|
|
213
|
+
'done',
|
|
214
|
+
'Local root is reachable.',
|
|
215
|
+
PROJECT_ONBOARDING_REASON_CODES.ROOT_ACCEPTED
|
|
216
|
+
));
|
|
217
|
+
steps.push(buildStep(
|
|
218
|
+
'hydrate',
|
|
219
|
+
'failed',
|
|
220
|
+
(importResult.errors || []).join('; ') || 'Adoption failed.',
|
|
221
|
+
PROJECT_ONBOARDING_REASON_CODES.ADOPTION_FAILED
|
|
222
|
+
));
|
|
223
|
+
steps.push(buildStep(
|
|
224
|
+
'activate',
|
|
225
|
+
'skipped',
|
|
226
|
+
'Import does not activate failed onboarding results.',
|
|
227
|
+
PROJECT_ONBOARDING_REASON_CODES.IMPORT_NO_ACTIVATE
|
|
228
|
+
));
|
|
229
|
+
steps.push(buildStep(
|
|
230
|
+
'scaffold',
|
|
231
|
+
'failed',
|
|
232
|
+
'SCE baseline could not be applied to the root directory.',
|
|
233
|
+
PROJECT_ONBOARDING_REASON_CODES.ADOPTION_FAILED
|
|
234
|
+
));
|
|
235
|
+
return buildFailureEnvelope(
|
|
236
|
+
rootInspection,
|
|
237
|
+
steps,
|
|
238
|
+
(importResult.errors || []).join('; ') || 'Adoption failed.',
|
|
239
|
+
PROJECT_ONBOARDING_REASON_CODES.ADOPTION_FAILED
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const packageJson = require('../../package.json');
|
|
244
|
+
takeoverBaseline = await applyTakeoverBaseline(rootInspection.rootDir, {
|
|
245
|
+
apply: true,
|
|
246
|
+
writeReport: true,
|
|
247
|
+
sceVersion: packageJson.version
|
|
248
|
+
});
|
|
249
|
+
onboardingPreview = await inspectProjectCandidate({ root: rootInspection.rootDir }, {
|
|
250
|
+
...dependencies,
|
|
251
|
+
fileSystem,
|
|
252
|
+
stateManager
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
let workspaceId = rootInspection.workspaceId || null;
|
|
257
|
+
if (!workspaceId) {
|
|
258
|
+
workspaceId = await allocateWorkspaceId(rootInspection.rootDir, stateManager);
|
|
259
|
+
await stateManager.createWorkspace(workspaceId, rootInspection.rootDir);
|
|
260
|
+
onboardingPreview = {
|
|
261
|
+
...onboardingPreview,
|
|
262
|
+
kind: 'workspace-backed',
|
|
263
|
+
projectId: buildWorkspaceProjectId(workspaceId),
|
|
264
|
+
workspaceId,
|
|
265
|
+
readiness: onboardingPreview.kind === 'directory-candidate' ? 'ready' : onboardingPreview.readiness,
|
|
266
|
+
availability: 'accessible',
|
|
267
|
+
localCandidate: false,
|
|
268
|
+
reasonCodes: Array.from(new Set([
|
|
269
|
+
PROJECT_CANDIDATE_REASON_CODES.WORKSPACE_REGISTERED,
|
|
270
|
+
...onboardingPreview.reasonCodes
|
|
271
|
+
]))
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
steps.push(buildStep(
|
|
276
|
+
'register',
|
|
277
|
+
'done',
|
|
278
|
+
rootInspection.workspaceId
|
|
279
|
+
? 'Workspace was already registered.'
|
|
280
|
+
: `Workspace registered as ${workspaceId}.`,
|
|
281
|
+
rootInspection.workspaceId
|
|
282
|
+
? PROJECT_CANDIDATE_REASON_CODES.WORKSPACE_REGISTERED
|
|
283
|
+
: PROJECT_ONBOARDING_REASON_CODES.REGISTERED
|
|
284
|
+
));
|
|
285
|
+
steps.push(buildStep(
|
|
286
|
+
'attach',
|
|
287
|
+
'done',
|
|
288
|
+
'Local root is accepted as the canonical onboarding source.',
|
|
289
|
+
PROJECT_ONBOARDING_REASON_CODES.ROOT_ACCEPTED
|
|
290
|
+
));
|
|
291
|
+
steps.push(buildStep(
|
|
292
|
+
'hydrate',
|
|
293
|
+
'done',
|
|
294
|
+
rootInspection.kind === 'directory-candidate'
|
|
295
|
+
? 'SCE baseline and project hydration were applied to the root directory.'
|
|
296
|
+
: 'Existing SCE project root is ready for portfolio import.',
|
|
297
|
+
rootInspection.kind === 'directory-candidate'
|
|
298
|
+
? PROJECT_ONBOARDING_REASON_CODES.ADOPTED
|
|
299
|
+
: PROJECT_CANDIDATE_REASON_CODES.SCE_PRESENT
|
|
300
|
+
));
|
|
301
|
+
steps.push(buildStep(
|
|
302
|
+
'activate',
|
|
303
|
+
'skipped',
|
|
304
|
+
'Import keeps active workspace selection unchanged in phase-1.',
|
|
305
|
+
PROJECT_ONBOARDING_REASON_CODES.IMPORT_NO_ACTIVATE
|
|
306
|
+
));
|
|
307
|
+
steps.push(buildStep(
|
|
308
|
+
'scaffold',
|
|
309
|
+
rootInspection.kind === 'directory-candidate' ? 'done' : 'skipped',
|
|
310
|
+
rootInspection.kind === 'directory-candidate'
|
|
311
|
+
? 'Applied SCE baseline files to the project root.'
|
|
312
|
+
: 'Existing SCE baseline is reused; no scaffold rewrite was required.',
|
|
313
|
+
rootInspection.kind === 'directory-candidate'
|
|
314
|
+
? PROJECT_ONBOARDING_REASON_CODES.ADOPTED
|
|
315
|
+
: PROJECT_ONBOARDING_REASON_CODES.SCAFFOLD_REUSED
|
|
316
|
+
));
|
|
317
|
+
|
|
318
|
+
return {
|
|
319
|
+
mode: 'import',
|
|
320
|
+
generated_at: new Date().toISOString(),
|
|
321
|
+
success: true,
|
|
322
|
+
preview: onboardingPreview,
|
|
323
|
+
summary: onboardingPreview,
|
|
324
|
+
steps,
|
|
325
|
+
result: {
|
|
326
|
+
rootDir: onboardingPreview.rootDir,
|
|
327
|
+
projectId: onboardingPreview.projectId || null,
|
|
328
|
+
workspaceId: onboardingPreview.workspaceId || null,
|
|
329
|
+
...(importResult ? {
|
|
330
|
+
adoption: {
|
|
331
|
+
mode: importResult.mode || null,
|
|
332
|
+
backupId: importResult.backup ? importResult.backup.id : null,
|
|
333
|
+
changes: importResult.changes || { created: [], updated: [], deleted: [], preserved: [] },
|
|
334
|
+
warnings: importResult.warnings || []
|
|
335
|
+
}
|
|
336
|
+
} : {}),
|
|
337
|
+
...(takeoverBaseline ? {
|
|
338
|
+
takeoverBaseline: {
|
|
339
|
+
reportFile: takeoverBaseline.report_file || null,
|
|
340
|
+
summary: takeoverBaseline.summary || {}
|
|
341
|
+
}
|
|
342
|
+
} : {})
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
module.exports = {
|
|
348
|
+
PROJECT_ONBOARDING_REASON_CODES,
|
|
349
|
+
runProjectRootOnboardingImport
|
|
350
|
+
};
|
package/package.json
CHANGED
|
@@ -8,19 +8,21 @@ const REQUIRED_CHECKS = [
|
|
|
8
8
|
{
|
|
9
9
|
path: 'README.md',
|
|
10
10
|
requiredSnippets: [
|
|
11
|
-
'`sce project portfolio show|target resolve|supervision show`'
|
|
11
|
+
'`sce project portfolio show|candidate inspect|onboarding import|target resolve|supervision show`'
|
|
12
12
|
]
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
path: 'README.zh.md',
|
|
16
16
|
requiredSnippets: [
|
|
17
|
-
'`sce project portfolio show|target resolve|supervision show`'
|
|
17
|
+
'`sce project portfolio show|candidate inspect|onboarding import|target resolve|supervision show`'
|
|
18
18
|
]
|
|
19
19
|
},
|
|
20
20
|
{
|
|
21
21
|
path: 'docs/command-reference.md',
|
|
22
22
|
requiredSnippets: [
|
|
23
23
|
'sce project portfolio show [options]',
|
|
24
|
+
'sce project candidate inspect --root <path> [options]',
|
|
25
|
+
'sce project onboarding import --root <path> [options]',
|
|
24
26
|
'sce project target resolve [options]',
|
|
25
27
|
'sce project supervision show --project <id> [options]'
|
|
26
28
|
]
|
|
@@ -45,6 +47,8 @@ const REQUIRED_CHECKS = [
|
|
|
45
47
|
path: 'docs/magicball-project-portfolio-contract.md',
|
|
46
48
|
requiredSnippets: [
|
|
47
49
|
'sce project portfolio show --json',
|
|
50
|
+
'sce project candidate inspect --root <path> --json',
|
|
51
|
+
'sce project onboarding import --root <path> --json',
|
|
48
52
|
'sce project target resolve --json',
|
|
49
53
|
'sce project supervision show --project <project-id> --json'
|
|
50
54
|
]
|
|
@@ -53,7 +57,11 @@ const REQUIRED_CHECKS = [
|
|
|
53
57
|
path: 'docs/magicball-frontend-state-and-command-mapping.md',
|
|
54
58
|
requiredSnippets: [
|
|
55
59
|
'projectPortfolio: Record<string, unknown> | null',
|
|
60
|
+
'projectCandidate: Record<string, unknown> | null',
|
|
61
|
+
'projectOnboarding: Record<string, unknown> | null',
|
|
56
62
|
'`sce project portfolio show --json`',
|
|
63
|
+
'`sce project candidate inspect --root <path> --json`',
|
|
64
|
+
'`sce project onboarding import --root <path> --json`',
|
|
57
65
|
'`sce project target resolve --request <text> --current-project <project-id> --json`',
|
|
58
66
|
'`sce project supervision show --project <project-id> --json`'
|
|
59
67
|
]
|
|
@@ -62,6 +70,8 @@ const REQUIRED_CHECKS = [
|
|
|
62
70
|
path: 'docs/magicball-cli-invocation-examples.md',
|
|
63
71
|
requiredSnippets: [
|
|
64
72
|
'sce project portfolio show --json',
|
|
73
|
+
'sce project candidate inspect --root "C:/workspace/customer-order-demo" --json',
|
|
74
|
+
'sce project onboarding import --root "C:/workspace/customer-order-demo" --json',
|
|
65
75
|
'sce project target resolve --request "continue customer-order-demo" --json',
|
|
66
76
|
'sce project supervision show --project workspace:customer-order-demo --json'
|
|
67
77
|
]
|
|
@@ -71,6 +81,8 @@ const REQUIRED_CHECKS = [
|
|
|
71
81
|
requiredSnippets: [
|
|
72
82
|
'## Phase 0: Multi-project Workspace Shell',
|
|
73
83
|
'sce project portfolio show --json',
|
|
84
|
+
'sce project candidate inspect --root "<path>" --json',
|
|
85
|
+
'sce project onboarding import --root "<path>" --json',
|
|
74
86
|
'sce project target resolve --request "<text>" --current-project <project-id> --json',
|
|
75
87
|
'sce project supervision show --project <project-id> --json'
|
|
76
88
|
]
|
|
@@ -80,14 +92,15 @@ const REQUIRED_CHECKS = [
|
|
|
80
92
|
requiredSnippets: [
|
|
81
93
|
'- `docs/magicball-project-portfolio-contract.md`',
|
|
82
94
|
'- project switcher from `project portfolio show`',
|
|
95
|
+
'- local-root candidate receipt from `project candidate inspect`',
|
|
83
96
|
'- project health summary from `project supervision show`'
|
|
84
97
|
]
|
|
85
98
|
},
|
|
86
99
|
{
|
|
87
100
|
path: 'docs/magicball-integration-issue-tracker.md',
|
|
88
101
|
requiredSnippets: [
|
|
89
|
-
'- `project portfolio show/target resolve/supervision show`',
|
|
90
|
-
'5. treat `project portfolio / target resolve / supervision` as the default multi-project shell truth'
|
|
102
|
+
'- `project portfolio show/candidate inspect/onboarding import/target resolve/supervision show`',
|
|
103
|
+
'5. treat `project portfolio / candidate inspect / onboarding import / target resolve / supervision` as the default multi-project shell truth'
|
|
91
104
|
]
|
|
92
105
|
},
|
|
93
106
|
{
|
package/template/.sce/README.md
CHANGED
|
@@ -243,6 +243,6 @@ A Spec is a complete feature definition with three parts:
|
|
|
243
243
|
---
|
|
244
244
|
|
|
245
245
|
**Project Type**: Spec-driven development
|
|
246
|
-
**sce Version**: 3.6.
|
|
247
|
-
**Last Updated**: 2026-03-
|
|
246
|
+
**sce Version**: 3.6.62
|
|
247
|
+
**Last Updated**: 2026-03-21
|
|
248
248
|
**Purpose**: Guide AI tools to work effectively with this project
|