scene-capability-engine 3.6.64 → 3.6.67

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.
Files changed (125) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +17 -6
  3. package/README.zh.md +18 -6
  4. package/bin/scene-capability-engine.js +4 -0
  5. package/docs/README.md +2 -2
  6. package/docs/command-reference.md +385 -8
  7. package/docs/document-governance.md +3 -2
  8. package/docs/integration-modes.md +62 -478
  9. package/docs/integration-philosophy.md +56 -263
  10. package/docs/magicball-cli-invocation-examples.md +1 -0
  11. package/docs/magicball-project-portfolio-contract.md +125 -4
  12. package/docs/project-management/README.md +14 -0
  13. package/docs/project-management/assurance/backup.md +3 -0
  14. package/docs/project-management/assurance/config.md +3 -0
  15. package/docs/project-management/assurance/evidence/README.md +3 -0
  16. package/docs/project-management/assurance/incidents/README.md +3 -0
  17. package/docs/project-management/assurance/logs.md +3 -0
  18. package/docs/project-management/assurance/overview.md +3 -0
  19. package/docs/project-management/assurance/recovery/README.md +3 -0
  20. package/docs/project-management/assurance/resource.md +3 -0
  21. package/docs/project-management/assurance/runbooks/README.md +3 -0
  22. package/docs/project-management/delivery/acceptance/README.md +3 -0
  23. package/docs/project-management/delivery/acceptance/evidence/README.md +3 -0
  24. package/docs/project-management/delivery/acceptance/exceptions/README.md +3 -0
  25. package/docs/project-management/delivery/acceptance/reports/README.md +3 -0
  26. package/docs/project-management/delivery/documents/changes.md +3 -0
  27. package/docs/project-management/delivery/documents/issues.md +3 -0
  28. package/docs/project-management/delivery/documents/overview.md +3 -0
  29. package/docs/project-management/delivery/documents/planning.md +3 -0
  30. package/docs/project-management/delivery/documents/requirements.md +3 -0
  31. package/docs/project-management/delivery/documents/tracking.md +3 -0
  32. package/docs/project-management/delivery/handoffs/README.md +3 -0
  33. package/docs/project-management/delivery/handoffs/evidence/README.md +3 -0
  34. package/docs/project-management/delivery/handoffs/records/README.md +3 -0
  35. package/docs/project-management/delivery/overview.md +10 -0
  36. package/docs/project-management/delivery/releases/README.md +3 -0
  37. package/docs/project-management/delivery/releases/baselines/README.md +3 -0
  38. package/docs/project-management/delivery/releases/evidence/README.md +3 -0
  39. package/docs/project-management/delivery/tables/changes.md +3 -0
  40. package/docs/project-management/delivery/tables/issues.md +3 -0
  41. package/docs/project-management/delivery/tables/planning.md +3 -0
  42. package/docs/project-management/delivery/tables/requirements.md +3 -0
  43. package/docs/project-management/delivery/tables/tracking.md +3 -0
  44. package/docs/project-management/environment/agent-discovery.md +3 -0
  45. package/docs/project-management/environment/development.md +3 -0
  46. package/docs/project-management/environment/overview.md +10 -0
  47. package/docs/project-management/environment/testing.md +3 -0
  48. package/docs/project-management/environment/version-alignment.md +3 -0
  49. package/docs/quick-start-with-ai-tools.md +68 -308
  50. package/docs/releases/README.md +3 -0
  51. package/docs/releases/v3.6.65.md +25 -0
  52. package/docs/releases/v3.6.66.md +23 -0
  53. package/docs/releases/v3.6.67.md +23 -0
  54. package/docs/steering-governance.md +64 -2
  55. package/docs/zh/README.md +2 -2
  56. package/docs/zh/releases/README.md +3 -0
  57. package/docs/zh/releases/v3.6.65.md +25 -0
  58. package/docs/zh/releases/v3.6.66.md +23 -0
  59. package/docs/zh/releases/v3.6.67.md +23 -0
  60. package/lib/commands/adopt.js +24 -0
  61. package/lib/commands/native.js +158 -0
  62. package/lib/commands/project.js +96 -0
  63. package/lib/commands/semantic.js +1459 -0
  64. package/lib/commands/session.js +74 -3
  65. package/lib/commands/spec-bootstrap.js +10 -1
  66. package/lib/commands/spec-gate.js +10 -1
  67. package/lib/commands/spec-pipeline.js +10 -1
  68. package/lib/commands/studio.js +405 -30
  69. package/lib/commands/task.js +141 -7
  70. package/lib/governance/supreme-principles.js +530 -0
  71. package/lib/problem/problem-evaluator.js +4 -0
  72. package/lib/project/candidate-inspection-service.js +24 -1
  73. package/lib/project/portfolio-projection-service.js +315 -5
  74. package/lib/project/project-channel-output.js +94 -0
  75. package/lib/project/project-channel-projection.js +181 -0
  76. package/lib/project/root-onboarding-service.js +107 -7
  77. package/lib/project/semantic-shared-source-projection.js +150 -0
  78. package/lib/project/supervision-action-model.js +277 -0
  79. package/lib/project/supervision-projection-service.js +305 -5
  80. package/lib/project/target-resolution-service.js +70 -5
  81. package/lib/project/visibility-policy.js +93 -0
  82. package/lib/runtime/multi-spec-scene-session.js +8 -1
  83. package/lib/runtime/project-channel-context-store.js +387 -0
  84. package/lib/runtime/project-channel-context.js +406 -0
  85. package/lib/runtime/scene-session-binding.js +46 -0
  86. package/lib/runtime/session-store.js +186 -0
  87. package/lib/runtime/steering-contract.js +7 -1
  88. package/lib/semantic/archive-report.js +283 -0
  89. package/lib/semantic/archive-routing.js +67 -0
  90. package/lib/semantic/backflow-report.js +245 -0
  91. package/lib/semantic/capability-contract.js +30 -0
  92. package/lib/semantic/delta-export.js +145 -0
  93. package/lib/semantic/interaction-observer.js +254 -0
  94. package/lib/semantic/kernel-loader.js +881 -0
  95. package/lib/semantic/native-runtime.js +359 -0
  96. package/lib/semantic/progress-ledger.js +433 -0
  97. package/lib/semantic/replay-evaluator.js +382 -0
  98. package/lib/semantic/shared-publication.js +592 -0
  99. package/lib/semantic/shared-source-config.js +183 -0
  100. package/lib/semantic/shared-source-connect.js +139 -0
  101. package/lib/semantic/shared-source-discovery.js +98 -0
  102. package/lib/semantic/shared-sync-export.js +413 -0
  103. package/lib/semantic/shared-sync-intake.js +592 -0
  104. package/lib/semantic/shared-sync-merge.js +547 -0
  105. package/lib/semantic/shared-sync-release.js +463 -0
  106. package/lib/semantic/supreme-intent-report.js +300 -0
  107. package/lib/state/sce-state-store.js +1360 -0
  108. package/lib/steering/context-sync-manager.js +276 -25
  109. package/lib/studio/spec-intake-governor.js +39 -3
  110. package/lib/studio/task-envelope.js +35 -2
  111. package/lib/workspace/takeover-baseline.js +342 -83
  112. package/package.json +7 -2
  113. package/scripts/agent-governance-baseline-audit.js +395 -0
  114. package/scripts/clarification-first-audit.js +9 -9
  115. package/scripts/deprecated-entry-audit.js +240 -0
  116. package/scripts/release-doc-version-audit.js +24 -0
  117. package/scripts/release-posture-report.js +262 -0
  118. package/template/.sce/README.md +62 -228
  119. package/template/.sce/config/semantic-shared-sources.json +5 -0
  120. package/template/.sce/config/supreme-principles-policy.json +105 -0
  121. package/template/.sce/config/takeover-baseline.json +7 -0
  122. package/template/.sce/steering/CORE_PRINCIPLES.md +23 -63
  123. package/template/.sce/steering/CURRENT_CONTEXT.md +4 -0
  124. package/template/.sce/steering/RULES_GUIDE.md +17 -9
  125. package/template/README.md +32 -96
@@ -12,6 +12,11 @@ const path = require('path');
12
12
  const fs = require('fs-extra');
13
13
  const fsUtils = require('../utils/fs-utils');
14
14
  const { MultiAgentConfig } = require('../collab/multi-agent-config');
15
+ const {
16
+ getFocusedChannelState,
17
+ listChannelIds,
18
+ normalizeProjectChannelContext
19
+ } = require('../runtime/project-channel-context');
15
20
 
16
21
  const STEERING_DIR = '.sce/steering';
17
22
  const CONTEXT_FILENAME = 'CURRENT_CONTEXT.md';
@@ -44,7 +49,7 @@ class ContextSyncManager {
44
49
  return { success: true };
45
50
  }
46
51
 
47
- await this._steeringFileLock.withLock(CONTEXT_FILENAME, async () => {
52
+ await this._withContextLock(async () => {
48
53
  const context = await this.readContext();
49
54
  context.specs[specName] = {
50
55
  status: entry.status,
@@ -57,16 +62,39 @@ class ContextSyncManager {
57
62
  return { success: true };
58
63
  }
59
64
 
65
+ /**
66
+ * Update CURRENT_CONTEXT project/channel summary without overwriting richer context sections.
67
+ *
68
+ * @param {string} projectId
69
+ * @param {object} projectChannelContext
70
+ * @returns {Promise<{success: boolean}>}
71
+ */
72
+ async updateProjectChannelSummary(projectId, projectChannelContext) {
73
+ const normalizedProjectId = `${projectId || ''}`.trim();
74
+ if (!normalizedProjectId) {
75
+ throw new Error('projectId is required');
76
+ }
77
+
78
+ const summary = this._summarizeProjectChannelContext(projectChannelContext, normalizedProjectId);
79
+ await this._withContextLock(async () => {
80
+ const context = await this.readContext();
81
+ context.projectChannels[normalizedProjectId] = summary;
82
+ await this.writeContext(context);
83
+ });
84
+
85
+ return { success: true };
86
+ }
87
+
60
88
  /**
61
89
  * Read and parse CURRENT_CONTEXT.md into a structured object.
62
90
  * Returns default empty object if file doesn't exist.
63
91
  *
64
- * @returns {Promise<{version: string|null, globalStatus: string|null, specs: object}>}
92
+ * @returns {Promise<object>}
65
93
  */
66
94
  async readContext() {
67
95
  const exists = await fs.pathExists(this._contextPath);
68
96
  if (!exists) {
69
- return { version: null, globalStatus: null, specs: {} };
97
+ return this._createEmptyContext();
70
98
  }
71
99
 
72
100
  try {
@@ -74,7 +102,7 @@ class ContextSyncManager {
74
102
  return this.parseContext(content);
75
103
  } catch (err) {
76
104
  console.warn(`[ContextSyncManager] Failed to read ${this._contextPath}: ${err.message}`);
77
- return { version: null, globalStatus: null, specs: {} };
105
+ return this._createEmptyContext();
78
106
  }
79
107
  }
80
108
 
@@ -82,7 +110,7 @@ class ContextSyncManager {
82
110
  * Write a structured context object back to CURRENT_CONTEXT.md.
83
111
  * Uses atomic write for file integrity.
84
112
  *
85
- * @param {{version: string|null, globalStatus: string|null, specs: object}} context
113
+ * @param {object} context
86
114
  * @returns {Promise<void>}
87
115
  */
88
116
  async writeContext(context) {
@@ -117,52 +145,162 @@ class ContextSyncManager {
117
145
 
118
146
  /**
119
147
  * Parse CURRENT_CONTEXT.md Markdown content into a structured object.
120
- * Handles both old single-agent format and new multi-agent table format.
148
+ * Handles both old single-agent format and richer multi-section format.
121
149
  *
122
150
  * @param {string} content
123
- * @returns {{version: string|null, globalStatus: string|null, specs: object}}
151
+ * @returns {object}
124
152
  */
125
153
  parseContext(content) {
126
- const result = { version: null, globalStatus: null, specs: {} };
154
+ const result = this._createEmptyContext();
127
155
 
128
156
  if (!content || typeof content !== 'string') {
129
157
  return result;
130
158
  }
131
159
 
132
160
  const lines = content.split('\n');
161
+ let activeListKey = null;
162
+ let inSpecTable = false;
163
+ let inProjectChannelTable = false;
133
164
 
134
165
  for (const line of lines) {
135
166
  const trimmed = line.trim();
136
167
 
137
- // Parse version line: **版本**: ...
138
- const versionMatch = trimmed.match(/^\*\*版本\*\*:\s*(.+)$/);
168
+ if (!trimmed) {
169
+ activeListKey = null;
170
+ continue;
171
+ }
172
+
173
+ const versionMatch = trimmed.match(/^\*\*版本\*\*[::]\s*(.+)$/);
139
174
  if (versionMatch) {
140
175
  result.version = versionMatch[1].trim();
141
176
  continue;
142
177
  }
143
178
 
144
- // Parse global status line: **状态**: ...
145
- const statusMatch = trimmed.match(/^\*\*状态\*\*:\s*(.+)$/);
179
+ const statusMatch = trimmed.match(/^\*\*状态\*\*[::]\s*(.+)$/);
146
180
  if (statusMatch) {
147
181
  result.globalStatus = statusMatch[1].trim();
148
182
  continue;
149
183
  }
150
184
 
151
- // Parse table rows for Spec progress
152
- // Format: | spec-name | status | progress% | summary |
153
- if (trimmed.startsWith('|') && !trimmed.startsWith('|---') && !trimmed.startsWith('| Spec')) {
154
- const cells = trimmed.split('|').map(c => c.trim()).filter(c => c.length > 0);
185
+ const mainlineMatch = trimmed.match(/^\*\*当前主线\*\*[::]\s*(.+)$/);
186
+ if (mainlineMatch) {
187
+ result.currentMainline = mainlineMatch[1].trim();
188
+ continue;
189
+ }
190
+
191
+ const collaborationMatch = trimmed.match(/^\*\*当前协作模型\*\*[::]\s*(.+)$/);
192
+ if (collaborationMatch) {
193
+ result.collaborationModel = collaborationMatch[1].trim();
194
+ continue;
195
+ }
196
+
197
+ if (trimmed === '**本轮重点**:') {
198
+ activeListKey = 'highlights';
199
+ inSpecTable = false;
200
+ inProjectChannelTable = false;
201
+ continue;
202
+ }
203
+
204
+ if (trimmed === '**后续候选主线**:') {
205
+ activeListKey = 'nextCandidates';
206
+ inSpecTable = false;
207
+ inProjectChannelTable = false;
208
+ continue;
209
+ }
210
+
211
+ if (trimmed === '## Spec 进度') {
212
+ activeListKey = null;
213
+ inSpecTable = false;
214
+ inProjectChannelTable = false;
215
+ continue;
216
+ }
217
+
218
+ if (trimmed === '## 项目通道快照') {
219
+ activeListKey = null;
220
+ inSpecTable = false;
221
+ inProjectChannelTable = false;
222
+ continue;
223
+ }
224
+
225
+ if (activeListKey && trimmed.startsWith('- ')) {
226
+ result[activeListKey].push(trimmed.slice(2).trim());
227
+ continue;
228
+ }
229
+
230
+ if (trimmed === '| Spec | 状态 | 进度 | 摘要 |') {
231
+ activeListKey = null;
232
+ inSpecTable = true;
233
+ inProjectChannelTable = false;
234
+ continue;
235
+ }
236
+
237
+ if (
238
+ trimmed === '| Project | Focused Channel | Active Scene | Active Spec | Active Doc | Channels | Updated |'
239
+ || trimmed === '| Project | Focused Channel | Active Spec | Active Doc | Channels | Updated |'
240
+ ) {
241
+ activeListKey = null;
242
+ inSpecTable = false;
243
+ inProjectChannelTable = true;
244
+ continue;
245
+ }
246
+
247
+ if (inSpecTable && trimmed.startsWith('|') && !trimmed.startsWith('|---')) {
248
+ const cells = trimmed.split('|').map((cell) => cell.trim()).filter((cell) => cell.length > 0);
155
249
  if (cells.length >= 4) {
156
250
  const specName = cells[0];
157
251
  const status = cells[1];
158
- const progressStr = cells[2].replace('%', '');
159
- const progress = parseInt(progressStr, 10);
252
+ const progress = parseInt(cells[2].replace('%', ''), 10);
160
253
  const summary = cells[3];
161
254
 
162
- if (specName && status && !isNaN(progress)) {
255
+ if (specName && status && !Number.isNaN(progress)) {
163
256
  result.specs[specName] = { status, progress, summary };
164
257
  }
165
258
  }
259
+ continue;
260
+ }
261
+
262
+ if (inProjectChannelTable && trimmed.startsWith('|') && !trimmed.startsWith('|---')) {
263
+ const cells = trimmed.split('|').map((cell) => cell.trim()).filter((cell) => cell.length > 0);
264
+ if (cells.length >= 7) {
265
+ const projectId = cells[0];
266
+ const channels = cells[5]
267
+ .split(',')
268
+ .map((item) => item.trim())
269
+ .filter(Boolean);
270
+ if (projectId) {
271
+ result.projectChannels[projectId] = {
272
+ projectId,
273
+ focusedChannelId: cells[1],
274
+ activeScene: cells[2],
275
+ activeSpecId: cells[3],
276
+ activeDoc: cells[4],
277
+ channelCount: channels.length,
278
+ channels,
279
+ updatedAt: cells[6]
280
+ };
281
+ }
282
+ continue;
283
+ }
284
+
285
+ if (cells.length >= 6) {
286
+ const projectId = cells[0];
287
+ const channels = cells[4]
288
+ .split(',')
289
+ .map((item) => item.trim())
290
+ .filter(Boolean);
291
+ if (projectId) {
292
+ result.projectChannels[projectId] = {
293
+ projectId,
294
+ focusedChannelId: cells[1],
295
+ activeScene: '',
296
+ activeSpecId: cells[2],
297
+ activeDoc: cells[3],
298
+ channelCount: channels.length,
299
+ channels,
300
+ updatedAt: cells[5]
301
+ };
302
+ }
303
+ }
166
304
  }
167
305
  }
168
306
 
@@ -172,23 +310,54 @@ class ContextSyncManager {
172
310
  /**
173
311
  * Format a structured context object into CURRENT_CONTEXT.md Markdown.
174
312
  *
175
- * @param {{version: string|null, globalStatus: string|null, specs: object}} context
313
+ * @param {object} context
176
314
  * @returns {string}
177
315
  */
178
316
  formatContext(context) {
317
+ const normalized = this._normalizeContext(context);
179
318
  const lines = [];
180
319
 
181
320
  lines.push('# 当前场景');
182
321
  lines.push('');
183
322
 
184
- if (context.version) {
185
- lines.push(`**版本**: ${context.version}`);
323
+ if (normalized.version) {
324
+ lines.push(`**版本**: ${normalized.version}`);
186
325
  }
187
- if (context.globalStatus) {
188
- lines.push(`**状态**: ${context.globalStatus}`);
326
+ if (normalized.globalStatus) {
327
+ lines.push(`**状态**: ${normalized.globalStatus}`);
328
+ }
329
+ if (normalized.currentMainline) {
330
+ lines.push(`**当前主线**: ${normalized.currentMainline}`);
331
+ }
332
+ if (normalized.collaborationModel) {
333
+ lines.push(`**当前协作模型**: ${normalized.collaborationModel}`);
334
+ }
335
+
336
+ if (normalized.highlights.length > 0) {
337
+ lines.push('');
338
+ lines.push('**本轮重点**:');
339
+ for (const item of normalized.highlights) {
340
+ lines.push(`- ${item}`);
341
+ }
342
+ }
343
+
344
+ const projectChannelEntries = Object.values(normalized.projectChannels)
345
+ .sort((left, right) => left.projectId.localeCompare(right.projectId));
346
+ if (projectChannelEntries.length > 0) {
347
+ lines.push('');
348
+ lines.push('## 项目通道快照');
349
+ lines.push('');
350
+ lines.push('| Project | Focused Channel | Active Scene | Active Spec | Active Doc | Channels | Updated |');
351
+ lines.push('|---------|-----------------|--------------|-------------|------------|----------|---------|');
352
+
353
+ for (const entry of projectChannelEntries) {
354
+ lines.push(
355
+ `| ${entry.projectId} | ${entry.focusedChannelId || ''} | ${entry.activeScene || ''} | ${entry.activeSpecId || ''} | ${entry.activeDoc || ''} | ${(entry.channels || []).join(', ')} | ${entry.updatedAt || ''} |`
356
+ );
357
+ }
189
358
  }
190
359
 
191
- const specEntries = Object.entries(context.specs || {});
360
+ const specEntries = Object.entries(normalized.specs || {});
192
361
  if (specEntries.length > 0) {
193
362
  lines.push('');
194
363
  lines.push('## Spec 进度');
@@ -204,6 +373,14 @@ class ContextSyncManager {
204
373
  }
205
374
  }
206
375
 
376
+ if (normalized.nextCandidates.length > 0) {
377
+ lines.push('');
378
+ lines.push('**后续候选主线**:');
379
+ for (const item of normalized.nextCandidates) {
380
+ lines.push(`- ${item}`);
381
+ }
382
+ }
383
+
207
384
  lines.push('');
208
385
  lines.push('---');
209
386
  lines.push('');
@@ -217,6 +394,80 @@ class ContextSyncManager {
217
394
 
218
395
  // ── Private helpers ──────────────────────────────────────────────
219
396
 
397
+ _createEmptyContext() {
398
+ return {
399
+ version: null,
400
+ globalStatus: null,
401
+ currentMainline: null,
402
+ collaborationModel: null,
403
+ highlights: [],
404
+ nextCandidates: [],
405
+ specs: {},
406
+ projectChannels: {}
407
+ };
408
+ }
409
+
410
+ _normalizeContext(context = {}) {
411
+ const payload = context && typeof context === 'object' ? context : {};
412
+
413
+ const normalizeText = (value) => {
414
+ if (typeof value !== 'string') {
415
+ return null;
416
+ }
417
+ const trimmed = value.trim();
418
+ return trimmed || null;
419
+ };
420
+
421
+ const normalizeList = (values) => {
422
+ if (!Array.isArray(values)) {
423
+ return [];
424
+ }
425
+ return values
426
+ .map((item) => (typeof item === 'string' ? item.trim() : ''))
427
+ .filter(Boolean);
428
+ };
429
+
430
+ return {
431
+ version: normalizeText(payload.version),
432
+ globalStatus: normalizeText(payload.globalStatus),
433
+ currentMainline: normalizeText(payload.currentMainline),
434
+ collaborationModel: normalizeText(payload.collaborationModel),
435
+ highlights: normalizeList(payload.highlights),
436
+ nextCandidates: normalizeList(payload.nextCandidates),
437
+ specs: payload.specs && typeof payload.specs === 'object' ? payload.specs : {},
438
+ projectChannels: payload.projectChannels && typeof payload.projectChannels === 'object'
439
+ ? payload.projectChannels
440
+ : {}
441
+ };
442
+ }
443
+
444
+ async _withContextLock(work) {
445
+ if (this._steeringFileLock && typeof this._steeringFileLock.withLock === 'function') {
446
+ return this._steeringFileLock.withLock(CONTEXT_FILENAME, work);
447
+ }
448
+ return work();
449
+ }
450
+
451
+ _summarizeProjectChannelContext(projectChannelContext, projectId) {
452
+ const normalized = normalizeProjectChannelContext(projectChannelContext, {
453
+ projectId,
454
+ allowDefaultChannelSynthesis: false
455
+ });
456
+ const focused = getFocusedChannelState(normalized);
457
+ const channels = listChannelIds(normalized);
458
+
459
+ return {
460
+ projectId: normalized.projectId,
461
+ focusedChannelId: normalized.focusedChannelId,
462
+ activeScene: focused && focused.activeScene ? focused.activeScene : '',
463
+ activeSpecId: focused && focused.activeSpecId ? focused.activeSpecId : '',
464
+ activeDoc: focused && focused.activeDoc ? focused.activeDoc : '',
465
+ channelCount: channels.length,
466
+ channels,
467
+ updatedAt: focused && focused.updatedAt ? focused.updatedAt : new Date().toISOString()
468
+ };
469
+ }
470
+
220
471
  /**
221
472
  * Compute progress from tasks.md content.
222
473
  * Counts only leaf tasks (lines with checkbox patterns that have no sub-tasks).
@@ -21,6 +21,23 @@ const DEFAULT_STUDIO_SCENE_BACKFILL_RULES = Object.freeze([
21
21
  scene_id: 'scene.moqui-core',
22
22
  keywords: ['moqui']
23
23
  },
24
+ {
25
+ id: 'semantic-kernel',
26
+ scene_id: 'scene.sce-semantic-kernel',
27
+ keywords: [
28
+ 'semantic',
29
+ 'dialogue',
30
+ 'conversation',
31
+ 'reply',
32
+ 'prompt',
33
+ 'self-eval',
34
+ 'simulation',
35
+ 'codex cli',
36
+ 'claude code',
37
+ 'kiro',
38
+ 'standalone sce'
39
+ ]
40
+ },
24
41
  {
25
42
  id: 'orchestration',
26
43
  scene_id: 'scene.sce-orchestration',
@@ -692,6 +709,10 @@ async function runStudioAutoIntake(options = {}, dependencies = {}) {
692
709
  const fileSystem = dependencies.fileSystem || fs;
693
710
  const sceneId = normalizeText(options.scene_id || options.sceneId);
694
711
  const goal = normalizeText(options.goal);
712
+ const supremeAssessment = options.supreme_principles && typeof options.supreme_principles === 'object'
713
+ ? options.supreme_principles
714
+ : null;
715
+ const effectiveGoal = normalizeText(supremeAssessment && supremeAssessment.effective_text) || goal;
695
716
  const fromChat = normalizeText(options.from_chat || options.fromChat);
696
717
  const explicitSpecId = normalizeText(options.explicit_spec_id || options.spec_id || options.specId);
697
718
  const apply = options.apply === true;
@@ -702,9 +723,9 @@ async function runStudioAutoIntake(options = {}, dependencies = {}) {
702
723
  : await loadStudioIntakePolicy(projectPath, fileSystem);
703
724
 
704
725
  const policy = loadedPolicy.policy;
705
- const intent = classifyStudioGoalIntent(goal, policy);
726
+ const intent = classifyStudioGoalIntent(effectiveGoal, policy);
706
727
  const decision = resolveStudioSpecIntakeDecision({
707
- goal,
728
+ goal: effectiveGoal,
708
729
  explicit_spec_id: explicitSpecId,
709
730
  domain_chain_binding: options.domain_chain_binding || {},
710
731
  related_specs: options.related_specs || {},
@@ -721,6 +742,8 @@ async function runStudioAutoIntake(options = {}, dependencies = {}) {
721
742
  scene_id: sceneId || null,
722
743
  from_chat: fromChat || null,
723
744
  goal: goal || null,
745
+ effective_goal: effectiveGoal || null,
746
+ supreme_principles: supremeAssessment,
724
747
  intent,
725
748
  decision: {
726
749
  ...decision
@@ -749,6 +772,19 @@ async function runStudioAutoIntake(options = {}, dependencies = {}) {
749
772
  return payload;
750
773
  }
751
774
 
775
+ if (supremeAssessment && normalizeText(supremeAssessment.action) === 'refuse') {
776
+ payload.decision = {
777
+ action: 'refuse',
778
+ reason: normalizeText(supremeAssessment.message) || 'blocked by supreme principles',
779
+ confidence: 'high',
780
+ spec_id: null,
781
+ source: 'supreme-principles',
782
+ intent
783
+ };
784
+ payload.selected_spec_id = null;
785
+ return payload;
786
+ }
787
+
752
788
  if (decision.action === 'create_spec') {
753
789
  const existingSpecIds = await listExistingSpecIds(projectPath, fileSystem);
754
790
  const autoSpecId = createAutoSpecId(sceneId, goal, existingSpecIds, policy);
@@ -758,7 +794,7 @@ async function runStudioAutoIntake(options = {}, dependencies = {}) {
758
794
  const createdSpec = await materializeIntakeSpec(projectPath, {
759
795
  scene_id: sceneId,
760
796
  from_chat: fromChat,
761
- goal,
797
+ goal: effectiveGoal,
762
798
  spec_id: autoSpecId
763
799
  }, {
764
800
  fileSystem
@@ -3,6 +3,31 @@ function buildStudioTaskKey(stageName = '') {
3
3
  return 'studio:' + normalizedStage;
4
4
  }
5
5
 
6
+ function extractProjectChannel(job = {}, normalizeString) {
7
+ const binding = job && job.session && job.session.project_channel && typeof job.session.project_channel === 'object'
8
+ ? job.session.project_channel
9
+ : null;
10
+ if (!binding) {
11
+ return null;
12
+ }
13
+
14
+ const projectChannel = {
15
+ project_id: normalizeString(binding.project_id) || null,
16
+ channel_id: normalizeString(binding.channel_id) || null,
17
+ focused_channel_id: normalizeString(binding.focused_channel_id) || null,
18
+ active_session_path: normalizeString(binding.active_session_path) || null,
19
+ active_scene: normalizeString(binding.active_scene) || null,
20
+ active_spec_id: normalizeString(binding.active_spec_id) || null,
21
+ active_doc: normalizeString(binding.active_doc) || null
22
+ };
23
+
24
+ if (!projectChannel.project_id && !projectChannel.channel_id) {
25
+ return null;
26
+ }
27
+
28
+ return projectChannel;
29
+ }
30
+
6
31
  async function resolveTaskReference(mode, job, options = {}, dependencies = {}) {
7
32
  const normalizeString = dependencies.normalizeString;
8
33
  const resolveTaskStage = dependencies.resolveTaskStage;
@@ -23,6 +48,7 @@ async function resolveTaskReference(mode, job, options = {}, dependencies = {})
23
48
  const taskKey = normalizeString(options.taskKey) || buildStudioTaskKey(stageName);
24
49
  const projectPath = normalizeString(options.projectPath) || process.cwd();
25
50
  const taskRefRegistry = options.taskRefRegistry || new TaskRefRegistry(projectPath, { fileSystem });
51
+ const projectChannel = extractProjectChannel(job, normalizeString);
26
52
 
27
53
  try {
28
54
  const taskRef = await taskRefRegistry.resolveOrCreateRef({
@@ -33,7 +59,10 @@ async function resolveTaskReference(mode, job, options = {}, dependencies = {})
33
59
  metadata: {
34
60
  mode: normalizeString(mode) || null,
35
61
  stage: stageName || null,
36
- job_id: normalizeString(job && job.job_id) || null
62
+ job_id: normalizeString(job && job.job_id) || null,
63
+ project_id: projectChannel ? projectChannel.project_id : null,
64
+ channel_id: projectChannel ? projectChannel.channel_id : null,
65
+ project_channel: projectChannel
37
66
  }
38
67
  });
39
68
  return taskRef.task_ref;
@@ -183,6 +212,7 @@ function buildTaskEnvelope(mode, job, options = {}, dependencies = {}) {
183
212
  const sceneId = normalizeString(job && job.scene && job.scene.id) || null;
184
213
  const specId = normalizeString(job && job.scene && job.scene.spec_id) || normalizeString(job && job.source && job.source.spec_id) || null;
185
214
  const taskRef = normalizeString(options.taskRef) || null;
215
+ const projectChannel = extractProjectChannel(job, normalizeString);
186
216
 
187
217
  const commands = normalizeTaskCommands([
188
218
  ...(Array.isArray(stageMetadata.commands) ? stageMetadata.commands : []),
@@ -206,7 +236,8 @@ function buildTaskEnvelope(mode, job, options = {}, dependencies = {}) {
206
236
 
207
237
  const normalizedHandoff = {
208
238
  ...handoff,
209
- task_ref: taskRef
239
+ task_ref: taskRef,
240
+ project_channel: projectChannel
210
241
  };
211
242
 
212
243
  return {
@@ -215,6 +246,7 @@ function buildTaskEnvelope(mode, job, options = {}, dependencies = {}) {
215
246
  specId,
216
247
  taskId,
217
248
  taskRef,
249
+ project_channel: projectChannel,
218
250
  eventId: normalizeString(latestEvent && latestEvent.event_id) || null,
219
251
  task: {
220
252
  ref: taskRef,
@@ -228,6 +260,7 @@ function buildTaskEnvelope(mode, job, options = {}, dependencies = {}) {
228
260
  confidence: taskIntent.confidence,
229
261
  status: taskStatus,
230
262
  summary: buildTaskSummaryLines(job, stageName, taskStatus, nextAction, taskRef, dependencies.buildProgress),
263
+ project_channel: projectChannel,
231
264
  handoff: normalizedHandoff,
232
265
  next_action: nextAction,
233
266
  file_changes: fileChanges,