scene-capability-engine 3.6.28 → 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 +23 -0
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/docs/agent-runtime/magicball-contract-index.md +25 -0
- package/docs/agent-runtime/magicball-status.schema.json +33 -0
- package/docs/agent-runtime/magicball-task-feedback.schema.json +79 -0
- package/docs/agent-runtime/magicball-timeline-view.schema.json +51 -0
- package/docs/command-reference.md +5 -0
- package/docs/magicball-capability-iteration-ui.md +2 -0
- package/docs/magicball-capability-library.md +2 -0
- package/docs/magicball-task-feedback-timeline-guide.md +14 -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
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
function buildStudioTaskKey(stageName = '') {
|
|
2
|
+
const normalizedStage = (typeof stageName === 'string' ? stageName.trim() : '') || 'task';
|
|
3
|
+
return 'studio:' + normalizedStage;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
async function resolveTaskReference(mode, job, options = {}, dependencies = {}) {
|
|
7
|
+
const normalizeString = dependencies.normalizeString;
|
|
8
|
+
const resolveTaskStage = dependencies.resolveTaskStage;
|
|
9
|
+
const TaskRefRegistry = dependencies.TaskRefRegistry;
|
|
10
|
+
const fileSystem = dependencies.fileSystem;
|
|
11
|
+
const explicitTaskRef = normalizeString(options.taskRef);
|
|
12
|
+
if (explicitTaskRef) {
|
|
13
|
+
return explicitTaskRef;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const sceneId = normalizeString(job && job.scene && job.scene.id);
|
|
17
|
+
const specId = normalizeString(job && job.scene && job.scene.spec_id) || normalizeString(job && job.source && job.source.spec_id);
|
|
18
|
+
if (!sceneId || !specId) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const stageName = resolveTaskStage(mode, job, options.stageName);
|
|
23
|
+
const taskKey = normalizeString(options.taskKey) || buildStudioTaskKey(stageName);
|
|
24
|
+
const projectPath = normalizeString(options.projectPath) || process.cwd();
|
|
25
|
+
const taskRefRegistry = options.taskRefRegistry || new TaskRefRegistry(projectPath, { fileSystem });
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const taskRef = await taskRefRegistry.resolveOrCreateRef({
|
|
29
|
+
sceneId,
|
|
30
|
+
specId,
|
|
31
|
+
taskKey,
|
|
32
|
+
source: 'studio-stage',
|
|
33
|
+
metadata: {
|
|
34
|
+
mode: normalizeString(mode) || null,
|
|
35
|
+
stage: stageName || null,
|
|
36
|
+
job_id: normalizeString(job && job.job_id) || null
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
return taskRef.task_ref;
|
|
40
|
+
} catch (_error) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function collectTaskFileChanges(job = {}, stageName = '', stageMetadata = {}, dependencies = {}) {
|
|
46
|
+
const normalizeString = dependencies.normalizeString;
|
|
47
|
+
const normalizeTaskFileChanges = dependencies.normalizeTaskFileChanges;
|
|
48
|
+
const fileChanges = [];
|
|
49
|
+
if (Array.isArray(stageMetadata && stageMetadata.file_changes)) {
|
|
50
|
+
fileChanges.push(...stageMetadata.file_changes);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const createdSpec = job && job.source && job.source.intake && job.source.intake.created_spec;
|
|
54
|
+
const createdSpecId = createdSpec && createdSpec.created
|
|
55
|
+
? normalizeString(createdSpec.spec_id)
|
|
56
|
+
: '';
|
|
57
|
+
if (stageName === 'plan' && createdSpecId) {
|
|
58
|
+
fileChanges.push(
|
|
59
|
+
{ path: '.sce/specs/' + createdSpecId + '/requirements.md', line: 1 },
|
|
60
|
+
{ path: '.sce/specs/' + createdSpecId + '/design.md', line: 1 },
|
|
61
|
+
{ path: '.sce/specs/' + createdSpecId + '/tasks.md', line: 1 },
|
|
62
|
+
{ path: '.sce/specs/' + createdSpecId + '/custom/problem-domain-chain.json', line: 1 },
|
|
63
|
+
{ path: '.sce/specs/' + createdSpecId + '/custom/problem-contract.json', line: 1 }
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const artifacts = job && job.artifacts ? job.artifacts : {};
|
|
68
|
+
if (stageName === 'plan') {
|
|
69
|
+
if (normalizeString(artifacts.spec_portfolio_report)) {
|
|
70
|
+
fileChanges.push({ path: artifacts.spec_portfolio_report, line: 1 });
|
|
71
|
+
}
|
|
72
|
+
if (normalizeString(artifacts.spec_scene_index)) {
|
|
73
|
+
fileChanges.push({ path: artifacts.spec_scene_index, line: 1 });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (stageName === 'generate' && normalizeString(artifacts.generate_report)) {
|
|
77
|
+
fileChanges.push({ path: artifacts.generate_report, line: 1 });
|
|
78
|
+
}
|
|
79
|
+
if (stageName === 'verify' && normalizeString(artifacts.verify_report)) {
|
|
80
|
+
fileChanges.push({ path: artifacts.verify_report, line: 1 });
|
|
81
|
+
}
|
|
82
|
+
if (stageName === 'release' && normalizeString(artifacts.release_report)) {
|
|
83
|
+
fileChanges.push({ path: artifacts.release_report, line: 1 });
|
|
84
|
+
}
|
|
85
|
+
return normalizeTaskFileChanges(fileChanges);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function collectTaskEvidence(job = {}, stageName = '', stageMetadata = {}, dependencies = {}) {
|
|
89
|
+
const normalizeString = dependencies.normalizeString;
|
|
90
|
+
const normalizeTaskEvidence = dependencies.normalizeTaskEvidence;
|
|
91
|
+
const evidence = [];
|
|
92
|
+
const stageReport = normalizeString(stageMetadata && stageMetadata.report);
|
|
93
|
+
if (stageReport) {
|
|
94
|
+
evidence.push({ type: 'stage-report', ref: stageReport, detail: stageName });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const artifacts = job && job.artifacts ? job.artifacts : {};
|
|
98
|
+
if (stageName && artifacts.problem_eval_reports && artifacts.problem_eval_reports[stageName]) {
|
|
99
|
+
evidence.push({
|
|
100
|
+
type: 'problem-evaluation-report',
|
|
101
|
+
ref: artifacts.problem_eval_reports[stageName],
|
|
102
|
+
detail: stageName
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (normalizeString(job && job.source && job.source.domain_chain && job.source.domain_chain.chain_path)) {
|
|
107
|
+
evidence.push({
|
|
108
|
+
type: 'domain-chain',
|
|
109
|
+
ref: job.source.domain_chain.chain_path,
|
|
110
|
+
detail: stageName
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
if (normalizeString(job && job.source && job.source.problem_contract_path)) {
|
|
114
|
+
evidence.push({
|
|
115
|
+
type: 'problem-contract',
|
|
116
|
+
ref: job.source.problem_contract_path,
|
|
117
|
+
detail: stageName
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
if (Array.isArray(stageMetadata && stageMetadata.auto_errorbook_records)) {
|
|
121
|
+
for (const item of stageMetadata.auto_errorbook_records) {
|
|
122
|
+
const entryId = normalizeString(item && item.entry_id);
|
|
123
|
+
if (!entryId) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
evidence.push({
|
|
127
|
+
type: 'errorbook-entry',
|
|
128
|
+
ref: entryId,
|
|
129
|
+
detail: normalizeString(item && item.step_id) || null
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (normalizeString(job && job.job_id)) {
|
|
135
|
+
evidence.push({
|
|
136
|
+
type: 'event-log',
|
|
137
|
+
ref: '.sce/state/sce-state.sqlite',
|
|
138
|
+
detail: 'studio_event_stream:job_id=' + job.job_id
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return normalizeTaskEvidence(evidence);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function buildTaskEnvelope(mode, job, options = {}, dependencies = {}) {
|
|
146
|
+
const resolveTaskStage = dependencies.resolveTaskStage;
|
|
147
|
+
const resolveNextAction = dependencies.resolveNextAction;
|
|
148
|
+
const normalizeString = dependencies.normalizeString;
|
|
149
|
+
const normalizeTaskCommands = dependencies.normalizeTaskCommands;
|
|
150
|
+
const normalizeTaskErrors = dependencies.normalizeTaskErrors;
|
|
151
|
+
const extractCommandsFromStageMetadata = dependencies.extractCommandsFromStageMetadata;
|
|
152
|
+
const extractErrorsFromStageMetadata = dependencies.extractErrorsFromStageMetadata;
|
|
153
|
+
const deriveTaskIntentShape = dependencies.deriveTaskIntentShape;
|
|
154
|
+
const buildTaskSummaryLines = dependencies.buildTaskSummaryLines;
|
|
155
|
+
const buildTaskAcceptanceCriteria = dependencies.buildTaskAcceptanceCriteria;
|
|
156
|
+
|
|
157
|
+
const stageName = resolveTaskStage(mode, job, options.stageName);
|
|
158
|
+
const stageState = stageName && job && job.stages && job.stages[stageName]
|
|
159
|
+
? job.stages[stageName]
|
|
160
|
+
: {};
|
|
161
|
+
const stageMetadata = stageState && typeof stageState.metadata === 'object' && stageState.metadata
|
|
162
|
+
? stageState.metadata
|
|
163
|
+
: {};
|
|
164
|
+
const nextAction = resolveNextAction(job);
|
|
165
|
+
|
|
166
|
+
const events = Array.isArray(options.events)
|
|
167
|
+
? options.events
|
|
168
|
+
: (options.event ? [options.event] : []);
|
|
169
|
+
const latestEvent = events.length > 0 ? events[events.length - 1] : null;
|
|
170
|
+
|
|
171
|
+
const taskStatus = normalizeString(stageState && stageState.status)
|
|
172
|
+
|| (stageName === 'rollback' && normalizeString(job && job.status) === 'rolled_back'
|
|
173
|
+
? 'completed'
|
|
174
|
+
: normalizeString(job && job.status) || 'unknown');
|
|
175
|
+
const taskId = normalizeString(options.taskId)
|
|
176
|
+
|| (normalizeString(job && job.job_id)
|
|
177
|
+
? job.job_id + ':' + (stageName || 'task')
|
|
178
|
+
: null);
|
|
179
|
+
const rawRequest = normalizeString(job && job.source && job.source.goal);
|
|
180
|
+
const goal = rawRequest || ('Studio ' + (stageName || 'task') + ' execution');
|
|
181
|
+
const taskIntent = deriveTaskIntentShape(rawRequest, stageName);
|
|
182
|
+
const sessionId = normalizeString(job && job.session && job.session.scene_session_id) || null;
|
|
183
|
+
const sceneId = normalizeString(job && job.scene && job.scene.id) || null;
|
|
184
|
+
const specId = normalizeString(job && job.scene && job.scene.spec_id) || normalizeString(job && job.source && job.source.spec_id) || null;
|
|
185
|
+
const taskRef = normalizeString(options.taskRef) || null;
|
|
186
|
+
|
|
187
|
+
const commands = normalizeTaskCommands([
|
|
188
|
+
...(Array.isArray(stageMetadata.commands) ? stageMetadata.commands : []),
|
|
189
|
+
...extractCommandsFromStageMetadata(stageMetadata)
|
|
190
|
+
]);
|
|
191
|
+
const errors = normalizeTaskErrors(
|
|
192
|
+
extractErrorsFromStageMetadata(stageState, stageMetadata)
|
|
193
|
+
);
|
|
194
|
+
const fileChanges = collectTaskFileChanges(job, stageName, stageMetadata, dependencies);
|
|
195
|
+
const evidence = collectTaskEvidence(job, stageName, stageMetadata, dependencies);
|
|
196
|
+
|
|
197
|
+
const handoff = stageMetadata.handoff && typeof stageMetadata.handoff === 'object'
|
|
198
|
+
? stageMetadata.handoff
|
|
199
|
+
: {
|
|
200
|
+
stage: stageName,
|
|
201
|
+
status: taskStatus,
|
|
202
|
+
completed_at: normalizeString(stageState && stageState.completed_at) || null,
|
|
203
|
+
report: normalizeString(stageMetadata.report) || null,
|
|
204
|
+
release_ref: normalizeString(stageMetadata.release_ref) || normalizeString(job && job.artifacts && job.artifacts.release_ref) || null
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const normalizedHandoff = {
|
|
208
|
+
...handoff,
|
|
209
|
+
task_ref: taskRef
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
return {
|
|
213
|
+
sessionId,
|
|
214
|
+
sceneId,
|
|
215
|
+
specId,
|
|
216
|
+
taskId,
|
|
217
|
+
taskRef,
|
|
218
|
+
eventId: normalizeString(latestEvent && latestEvent.event_id) || null,
|
|
219
|
+
task: {
|
|
220
|
+
ref: taskRef,
|
|
221
|
+
task_ref: taskRef,
|
|
222
|
+
title_norm: taskIntent.title_norm,
|
|
223
|
+
raw_request: taskIntent.raw_request,
|
|
224
|
+
goal,
|
|
225
|
+
sub_goals: taskIntent.sub_goals,
|
|
226
|
+
acceptance_criteria: buildTaskAcceptanceCriteria(stageName, job, nextAction),
|
|
227
|
+
needs_split: taskIntent.needs_split,
|
|
228
|
+
confidence: taskIntent.confidence,
|
|
229
|
+
status: taskStatus,
|
|
230
|
+
summary: buildTaskSummaryLines(job, stageName, taskStatus, nextAction, taskRef, dependencies.buildProgress),
|
|
231
|
+
handoff: normalizedHandoff,
|
|
232
|
+
next_action: nextAction,
|
|
233
|
+
file_changes: fileChanges,
|
|
234
|
+
commands,
|
|
235
|
+
errors,
|
|
236
|
+
evidence
|
|
237
|
+
},
|
|
238
|
+
event: events
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
async function buildCommandPayload(mode, job, options = {}, dependencies = {}) {
|
|
243
|
+
const taskRef = await resolveTaskReference(mode, job, options, dependencies);
|
|
244
|
+
const base = {
|
|
245
|
+
mode,
|
|
246
|
+
success: true,
|
|
247
|
+
job_id: job.job_id,
|
|
248
|
+
status: job.status,
|
|
249
|
+
progress: dependencies.buildProgress(job),
|
|
250
|
+
next_action: dependencies.resolveNextAction(job),
|
|
251
|
+
artifacts: { ...job.artifacts }
|
|
252
|
+
};
|
|
253
|
+
return dependencies.attachTaskFeedbackModel({
|
|
254
|
+
...base,
|
|
255
|
+
...buildTaskEnvelope(mode, job, {
|
|
256
|
+
...options,
|
|
257
|
+
taskRef
|
|
258
|
+
}, dependencies)
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
module.exports = {
|
|
263
|
+
buildStudioTaskKey,
|
|
264
|
+
resolveTaskReference,
|
|
265
|
+
collectTaskFileChanges,
|
|
266
|
+
collectTaskEvidence,
|
|
267
|
+
buildTaskEnvelope,
|
|
268
|
+
buildCommandPayload
|
|
269
|
+
};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
function normalizeString(value) {
|
|
2
|
+
if (typeof value !== 'string') {
|
|
3
|
+
return '';
|
|
4
|
+
}
|
|
5
|
+
return value.trim();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function truncateTaskText(value = '', maxLength = 96) {
|
|
9
|
+
const normalized = normalizeString(value).replace(/\s+/g, ' ');
|
|
10
|
+
if (!normalized) {
|
|
11
|
+
return '';
|
|
12
|
+
}
|
|
13
|
+
if (normalized.length <= maxLength) {
|
|
14
|
+
return normalized;
|
|
15
|
+
}
|
|
16
|
+
return normalized.slice(0, Math.max(0, maxLength - 3)).trim() + '...';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function dedupeTaskList(items = [], limit = 3) {
|
|
20
|
+
const seen = new Set();
|
|
21
|
+
const result = [];
|
|
22
|
+
for (const item of items) {
|
|
23
|
+
const normalized = truncateTaskText(item, 120);
|
|
24
|
+
if (!normalized) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const key = normalized.toLowerCase();
|
|
28
|
+
if (seen.has(key)) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
seen.add(key);
|
|
32
|
+
result.push(normalized);
|
|
33
|
+
if (result.length >= limit) {
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function splitTaskRawRequest(rawRequest = '') {
|
|
41
|
+
const normalized = normalizeString(rawRequest).replace(/\s+/g, ' ');
|
|
42
|
+
if (!normalized) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
const chunks = normalized
|
|
46
|
+
.split(/(?:\r?\n|[;;。!?!?]|(?:\s+\band\b\s+)|(?:\s+\bthen\b\s+)|(?:\s+\balso\b\s+)|(?:\s*并且\s*)|(?:\s*同时\s*)|(?:\s*以及\s*)|(?:\s*然后\s*))/gi)
|
|
47
|
+
.map((item) => normalizeString(item).replace(/^(?:and|then|also)\s+/i, ''))
|
|
48
|
+
.filter(Boolean);
|
|
49
|
+
return dedupeTaskList(chunks, 3);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function deriveTaskIntentShape(rawRequest = '', stageName = '') {
|
|
53
|
+
const normalizedRaw = normalizeString(rawRequest).replace(/\s+/g, ' ');
|
|
54
|
+
const clauses = splitTaskRawRequest(normalizedRaw);
|
|
55
|
+
const hasRaw = normalizedRaw.length > 0;
|
|
56
|
+
const inferredSubGoals = clauses.length > 1 ? clauses.slice(0, 3) : [];
|
|
57
|
+
const needsSplit = inferredSubGoals.length > 1;
|
|
58
|
+
const titleSource = clauses.length > 0
|
|
59
|
+
? clauses[0]
|
|
60
|
+
: (hasRaw ? normalizedRaw : 'Studio ' + (stageName || 'task') + ' execution');
|
|
61
|
+
|
|
62
|
+
let confidence = hasRaw ? 0.9 : 0.6;
|
|
63
|
+
if (needsSplit) {
|
|
64
|
+
confidence = 0.72;
|
|
65
|
+
}
|
|
66
|
+
if (normalizeString(stageName) && normalizeString(stageName) !== 'plan') {
|
|
67
|
+
confidence = Math.min(0.95, confidence + 0.03);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
title_norm: truncateTaskText(titleSource, 96) || ('Studio ' + (stageName || 'task') + ' execution'),
|
|
72
|
+
raw_request: hasRaw ? normalizedRaw : null,
|
|
73
|
+
sub_goals: inferredSubGoals,
|
|
74
|
+
needs_split: needsSplit,
|
|
75
|
+
confidence: Number(confidence.toFixed(2))
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function buildTaskSummaryLines(job = {}, stageName = '', taskStatus = '', nextAction = '', taskRef = '', buildProgress) {
|
|
80
|
+
const sceneId = normalizeString(job && job.scene && job.scene.id) || 'scene.n/a';
|
|
81
|
+
const specId = normalizeString(job && job.scene && job.scene.spec_id) || normalizeString(job && job.source && job.source.spec_id) || 'spec.n/a';
|
|
82
|
+
const progress = typeof buildProgress === 'function' ? buildProgress(job) : { completed: 0, total: 0 };
|
|
83
|
+
return [
|
|
84
|
+
'Stage: ' + (stageName || 'plan') + ' | Status: ' + (taskStatus || 'unknown') + (taskRef ? (' | Ref: ' + taskRef) : ''),
|
|
85
|
+
'Scene: ' + sceneId + ' | Spec: ' + specId + ' | Progress: ' + progress.completed + '/' + progress.total,
|
|
86
|
+
'Next: ' + (nextAction || 'n/a')
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function buildTaskAcceptanceCriteria(stageName = '', job = {}, nextAction = '') {
|
|
91
|
+
const normalizedStage = normalizeString(stageName) || 'task';
|
|
92
|
+
const artifacts = job && job.artifacts ? job.artifacts : {};
|
|
93
|
+
const criteriaByStage = {
|
|
94
|
+
plan: [
|
|
95
|
+
'Scene/spec binding is resolved and persisted in studio job metadata.',
|
|
96
|
+
'Plan stage problem evaluation passes with no blockers.',
|
|
97
|
+
'Next action is executable (' + (nextAction || 'sce studio generate --job <job-id>') + ').'
|
|
98
|
+
],
|
|
99
|
+
generate: [
|
|
100
|
+
'Patch bundle id is produced for downstream apply stage.',
|
|
101
|
+
'Generate stage report is written to artifacts.',
|
|
102
|
+
'Next action is executable (' + (nextAction || 'sce studio apply --patch-bundle <id> --job <job-id>') + ').'
|
|
103
|
+
],
|
|
104
|
+
apply: [
|
|
105
|
+
'Authorization requirements are satisfied for apply stage.',
|
|
106
|
+
'Apply stage completes without policy blockers.',
|
|
107
|
+
'Next action is executable (' + (nextAction || 'sce studio verify --job <job-id>') + ').'
|
|
108
|
+
],
|
|
109
|
+
verify: [
|
|
110
|
+
'Verification gates finish with no required-step failures.',
|
|
111
|
+
'Verify report is available (' + (normalizeString(artifacts.verify_report) || 'artifact pending') + ').',
|
|
112
|
+
'Next action is executable (' + (nextAction || 'sce studio release --job <job-id>') + ').'
|
|
113
|
+
],
|
|
114
|
+
release: [
|
|
115
|
+
'Release gates pass under configured release profile.',
|
|
116
|
+
'Release reference is emitted (' + (normalizeString(artifacts.release_ref) || 'artifact pending') + ').',
|
|
117
|
+
'Next action is executable (' + (nextAction || 'complete') + ').'
|
|
118
|
+
],
|
|
119
|
+
rollback: [
|
|
120
|
+
'Rollback stage transitions job status to rolled_back.',
|
|
121
|
+
'Rollback evidence is appended to studio event stream.',
|
|
122
|
+
'Recovery next action is executable (' + (nextAction || 'sce studio plan --scene <scene-id> --from-chat <session>') + ').'
|
|
123
|
+
],
|
|
124
|
+
events: [
|
|
125
|
+
'Events stream payload is available for task-level audit.',
|
|
126
|
+
'Task envelope preserves normalized IDs and handoff fields.',
|
|
127
|
+
'Next action is explicit (' + (nextAction || 'n/a') + ').'
|
|
128
|
+
],
|
|
129
|
+
resume: [
|
|
130
|
+
'Current job status and stage progress are restored deterministically.',
|
|
131
|
+
'Task envelope remains schema-compatible for downstream UI.',
|
|
132
|
+
'Next action is explicit (' + (nextAction || 'n/a') + ').'
|
|
133
|
+
]
|
|
134
|
+
};
|
|
135
|
+
return criteriaByStage[normalizedStage] || [
|
|
136
|
+
'Task envelope contains normalized identifiers and task contract fields.',
|
|
137
|
+
'Task output preserves evidence, command logs, and error bundles.',
|
|
138
|
+
'Next action is explicit (' + (nextAction || 'n/a') + ').'
|
|
139
|
+
];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
module.exports = {
|
|
143
|
+
deriveTaskIntentShape,
|
|
144
|
+
buildTaskSummaryLines,
|
|
145
|
+
buildTaskAcceptanceCriteria,
|
|
146
|
+
truncateTaskText,
|
|
147
|
+
dedupeTaskList,
|
|
148
|
+
splitTaskRawRequest
|
|
149
|
+
};
|
package/package.json
CHANGED