scene-capability-engine 3.6.0 → 3.6.2
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 +9 -0
- package/README.md +3 -2
- package/README.zh.md +3 -2
- package/docs/command-reference.md +1 -1
- package/docs/release-checklist.md +3 -3
- package/docs/zh/release-checklist.md +3 -3
- package/lib/commands/studio.js +133 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [3.6.2] - 2026-03-04
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Release default test gate now runs integration tests only (`npm run test:release`) for faster online publish verification.
|
|
14
|
+
- `prepublishOnly` now uses `test:release` instead of `test:full`.
|
|
15
|
+
- GitHub `release.yml` test job now runs integration-only release tests and skips coverage in release path.
|
|
16
|
+
- Studio task-stream schema now includes normalized task-intent fields (`title_norm`, `raw_request`, `sub_goals`, `acceptance_criteria`, `needs_split`, `confidence`) while preserving existing task fields for compatibility.
|
|
17
|
+
- Added version CLI integration coverage (`tests/integration/version-cli.integration.test.js`) to ensure `--version` output remains deterministic and package-aligned.
|
|
18
|
+
|
|
10
19
|
## [3.6.0] - 2026-03-04
|
|
11
20
|
|
|
12
21
|
### Added
|
package/README.md
CHANGED
|
@@ -130,7 +130,7 @@ SCE is tool-agnostic and works with Codex, Claude Code, Cursor, Windsurf, VS Cod
|
|
|
130
130
|
|
|
131
131
|
Studio task-stream output contract (default):
|
|
132
132
|
- IDs: `sessionId`, `sceneId`, `specId`, `taskId`, `taskRef`, `eventId`
|
|
133
|
-
- Task: `task.goal`, `task.status`, `task.summary` (3-line), `task.handoff`, `task.next_action`
|
|
133
|
+
- Task: `task.task_ref`, `task.title_norm`, `task.raw_request`, `task.goal`, `task.sub_goals`, `task.acceptance_criteria`, `task.needs_split`, `task.confidence`, `task.status`, `task.summary` (3-line), `task.handoff`, `task.next_action`
|
|
134
134
|
- File refs: `task.file_changes[]` with `path`, `line`, `diffRef`
|
|
135
135
|
- Command logs: `task.commands[]` with `cmd`, `exit_code`, `stdout`, `stderr`, `log_path`
|
|
136
136
|
- Errors: `task.errors[]` with `message`, `error_bundle` (copy-ready)
|
|
@@ -150,6 +150,7 @@ Studio task-stream output contract (default):
|
|
|
150
150
|
|
|
151
151
|
## Important Version Changes
|
|
152
152
|
|
|
153
|
+
- `3.6.2`: Added release-level version integration tests (`tests/integration/version-cli.integration.test.js`) and switched release default verification to integration-only gate (`npm run test:release`) for faster publish feedback.
|
|
153
154
|
- `3.6.0`: Added hierarchical task references (`taskRef`, format `SS.PP.TT`) backed by SQLite state store `.sce/state/sce-state.sqlite`, plus new task commands (`sce task ref/show/rerun`) for reference lookup and deterministic rerun.
|
|
154
155
|
- `3.5.2`: Introduced task-stream output contract for Studio commands (`sessionId/sceneId/specId/taskId/eventId`, structured `task.*` fields, `event[]` audit stream) and added OpenHands raw-event bridge via `sce studio events --openhands-events <path>`.
|
|
155
156
|
- `3.5.1`: Enforced stricter Studio intake defaults (`--manual-spec` and `--no-spec-governance` blocked unless policy override), added historical spec scene backfill command (`sce studio backfill-spec-scenes`) and persisted override mapping (`.sce/spec-governance/spec-scene-overrides.json`) for portfolio/related-spec alignment.
|
|
@@ -200,5 +201,5 @@ MIT. See [LICENSE](LICENSE).
|
|
|
200
201
|
|
|
201
202
|
---
|
|
202
203
|
|
|
203
|
-
**Version**: 3.6.
|
|
204
|
+
**Version**: 3.6.2
|
|
204
205
|
**Last Updated**: 2026-03-04
|
package/README.zh.md
CHANGED
|
@@ -130,7 +130,7 @@ SCE 对工具无锁定,可接入 Codex、Claude Code、Cursor、Windsurf、VS
|
|
|
130
130
|
|
|
131
131
|
Studio 任务流输出契约(默认):
|
|
132
132
|
- ID 字段:`sessionId`、`sceneId`、`specId`、`taskId`、`taskRef`、`eventId`
|
|
133
|
-
- 任务主体:`task.goal`、`task.status`、`task.summary`(固定三行)、`task.handoff`、`task.next_action`
|
|
133
|
+
- 任务主体:`task.task_ref`、`task.title_norm`、`task.raw_request`、`task.goal`、`task.sub_goals`、`task.acceptance_criteria`、`task.needs_split`、`task.confidence`、`task.status`、`task.summary`(固定三行)、`task.handoff`、`task.next_action`
|
|
134
134
|
- 文件引用:`task.file_changes[]`(`path`、`line`、`diffRef`)
|
|
135
135
|
- 命令执行:`task.commands[]`(`cmd`、`exit_code`、`stdout`、`stderr`、`log_path`)
|
|
136
136
|
- 错误复制:`task.errors[]`(`message`、`error_bundle`,可直接复制给 AI 修复)
|
|
@@ -150,6 +150,7 @@ Studio 任务流输出契约(默认):
|
|
|
150
150
|
|
|
151
151
|
## 重要版本变更
|
|
152
152
|
|
|
153
|
+
- `3.6.2`:新增发布版本号集成测试(`tests/integration/version-cli.integration.test.js`),并将发布默认验证切换为仅 integration 门禁(`npm run test:release`),加速发布反馈。
|
|
153
154
|
- `3.6.0`:新增分层任务引用(`taskRef`,格式 `SS.PP.TT`),持久化到 SQLite 状态库 `.sce/state/sce-state.sqlite`;新增 `sce task ref/show/rerun` 用于引用查询与可重放执行。
|
|
154
155
|
- `3.5.2`:新增 Studio 任务流输出契约(`sessionId/sceneId/specId/taskId/eventId`、结构化 `task.*` 字段、`event[]` 审计流),并新增 OpenHands 原始事件桥接能力:`sce studio events --openhands-events <path>`。
|
|
155
156
|
- `3.5.1`:默认强化 Studio intake 治理(`--manual-spec`、`--no-spec-governance` 在未显式放开策略时会被阻断),新增历史 spec 场景回填命令 `sce studio backfill-spec-scenes`,并写入 `.sce/spec-governance/spec-scene-overrides.json` 以统一 portfolio 与 related-spec 的场景映射。
|
|
@@ -200,5 +201,5 @@ MIT,见 [LICENSE](LICENSE)。
|
|
|
200
201
|
|
|
201
202
|
---
|
|
202
203
|
|
|
203
|
-
**版本**:3.6.
|
|
204
|
+
**版本**:3.6.2
|
|
204
205
|
**最后更新**:2026-03-04
|
|
@@ -587,7 +587,7 @@ SCE_STUDIO_REQUIRE_AUTH=1 SCE_STUDIO_AUTH_PASSWORD=top-secret sce studio apply -
|
|
|
587
587
|
|
|
588
588
|
Studio JSON output now includes a stable UI-oriented task stream contract (in addition to existing `job_*` fields):
|
|
589
589
|
- root IDs: `sessionId`, `sceneId`, `specId`, `taskId`, `taskRef`, `eventId`
|
|
590
|
-
- `task.goal`, `task.status`, `task.summary` (fixed 3-line summary), `task.handoff`, `task.next_action`
|
|
590
|
+
- `task.task_ref`, `task.title_norm`, `task.raw_request`, `task.goal`, `task.sub_goals`, `task.acceptance_criteria`, `task.needs_split`, `task.confidence`, `task.status`, `task.summary` (fixed 3-line summary), `task.handoff`, `task.next_action`
|
|
591
591
|
- `task.file_changes[]`: `path`, `line`, `diffRef`
|
|
592
592
|
- `task.commands[]`: `cmd`, `exit_code`, `stdout`, `stderr`, `log_path`
|
|
593
593
|
- `task.errors[]`: `message`, `error_bundle` (copy-ready diagnostic bundle)
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
## 1. Functional Verification
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
#
|
|
11
|
-
npm run test:
|
|
10
|
+
# Default release test gate (integration-only)
|
|
11
|
+
npm run test:release
|
|
12
12
|
|
|
13
|
-
#
|
|
13
|
+
# Optional full regression suite (unit + integration + properties)
|
|
14
14
|
npm run test:full
|
|
15
15
|
|
|
16
16
|
# Guardrail: fail on newly introduced .skip tests
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
## 1. 功能验证
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
#
|
|
11
|
-
npm run test:
|
|
10
|
+
# 默认发布测试门禁(仅 integration)
|
|
11
|
+
npm run test:release
|
|
12
12
|
|
|
13
|
-
#
|
|
13
|
+
# 可选全量回归(unit + integration + properties)
|
|
14
14
|
npm run test:full
|
|
15
15
|
|
|
16
16
|
# 防回归:禁止新增 .skip 测试
|
package/lib/commands/studio.js
CHANGED
|
@@ -1336,6 +1336,129 @@ function buildTaskSummaryLines(job = {}, stageName = '', taskStatus = '', nextAc
|
|
|
1336
1336
|
];
|
|
1337
1337
|
}
|
|
1338
1338
|
|
|
1339
|
+
function truncateTaskText(value = '', maxLength = 96) {
|
|
1340
|
+
const normalized = normalizeString(value).replace(/\s+/g, ' ');
|
|
1341
|
+
if (!normalized) {
|
|
1342
|
+
return '';
|
|
1343
|
+
}
|
|
1344
|
+
if (normalized.length <= maxLength) {
|
|
1345
|
+
return normalized;
|
|
1346
|
+
}
|
|
1347
|
+
return `${normalized.slice(0, Math.max(0, maxLength - 3)).trim()}...`;
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
function dedupeTaskList(items = [], limit = 3) {
|
|
1351
|
+
const seen = new Set();
|
|
1352
|
+
const result = [];
|
|
1353
|
+
for (const item of items) {
|
|
1354
|
+
const normalized = truncateTaskText(item, 120);
|
|
1355
|
+
if (!normalized) {
|
|
1356
|
+
continue;
|
|
1357
|
+
}
|
|
1358
|
+
const key = normalized.toLowerCase();
|
|
1359
|
+
if (seen.has(key)) {
|
|
1360
|
+
continue;
|
|
1361
|
+
}
|
|
1362
|
+
seen.add(key);
|
|
1363
|
+
result.push(normalized);
|
|
1364
|
+
if (result.length >= limit) {
|
|
1365
|
+
break;
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
return result;
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
function splitTaskRawRequest(rawRequest = '') {
|
|
1372
|
+
const normalized = normalizeString(rawRequest).replace(/\s+/g, ' ');
|
|
1373
|
+
if (!normalized) {
|
|
1374
|
+
return [];
|
|
1375
|
+
}
|
|
1376
|
+
const chunks = normalized
|
|
1377
|
+
.split(/(?:\r?\n|[;;。!?!?]|(?:\s+\band\b\s+)|(?:\s+\bthen\b\s+)|(?:\s+\balso\b\s+)|(?:\s*并且\s*)|(?:\s*同时\s*)|(?:\s*以及\s*)|(?:\s*然后\s*))/gi)
|
|
1378
|
+
.map((item) => normalizeString(item).replace(/^(?:and|then|also)\s+/i, ''))
|
|
1379
|
+
.filter(Boolean);
|
|
1380
|
+
return dedupeTaskList(chunks, 3);
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
function deriveTaskIntentShape(rawRequest = '', stageName = '') {
|
|
1384
|
+
const normalizedRaw = normalizeString(rawRequest).replace(/\s+/g, ' ');
|
|
1385
|
+
const clauses = splitTaskRawRequest(normalizedRaw);
|
|
1386
|
+
const hasRaw = normalizedRaw.length > 0;
|
|
1387
|
+
const inferredSubGoals = clauses.length > 1 ? clauses.slice(0, 3) : [];
|
|
1388
|
+
const needsSplit = inferredSubGoals.length > 1;
|
|
1389
|
+
const titleSource = clauses.length > 0
|
|
1390
|
+
? clauses[0]
|
|
1391
|
+
: (hasRaw ? normalizedRaw : `Studio ${stageName || 'task'} execution`);
|
|
1392
|
+
|
|
1393
|
+
let confidence = hasRaw ? 0.9 : 0.6;
|
|
1394
|
+
if (needsSplit) {
|
|
1395
|
+
confidence = 0.72;
|
|
1396
|
+
}
|
|
1397
|
+
if (normalizeString(stageName) && normalizeString(stageName) !== 'plan') {
|
|
1398
|
+
confidence = Math.min(0.95, confidence + 0.03);
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
return {
|
|
1402
|
+
title_norm: truncateTaskText(titleSource, 96) || `Studio ${stageName || 'task'} execution`,
|
|
1403
|
+
raw_request: hasRaw ? normalizedRaw : null,
|
|
1404
|
+
sub_goals: inferredSubGoals,
|
|
1405
|
+
needs_split: needsSplit,
|
|
1406
|
+
confidence: Number(confidence.toFixed(2))
|
|
1407
|
+
};
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
function buildTaskAcceptanceCriteria(stageName = '', job = {}, nextAction = '') {
|
|
1411
|
+
const normalizedStage = normalizeString(stageName) || 'task';
|
|
1412
|
+
const artifacts = job && job.artifacts ? job.artifacts : {};
|
|
1413
|
+
const criteriaByStage = {
|
|
1414
|
+
plan: [
|
|
1415
|
+
'Scene/spec binding is resolved and persisted in studio job metadata.',
|
|
1416
|
+
'Plan stage problem evaluation passes with no blockers.',
|
|
1417
|
+
`Next action is executable (${nextAction || 'sce studio generate --job <job-id>'}).`
|
|
1418
|
+
],
|
|
1419
|
+
generate: [
|
|
1420
|
+
'Patch bundle id is produced for downstream apply stage.',
|
|
1421
|
+
'Generate stage report is written to artifacts.',
|
|
1422
|
+
`Next action is executable (${nextAction || 'sce studio apply --patch-bundle <id> --job <job-id>'}).`
|
|
1423
|
+
],
|
|
1424
|
+
apply: [
|
|
1425
|
+
'Authorization requirements are satisfied for apply stage.',
|
|
1426
|
+
'Apply stage completes without policy blockers.',
|
|
1427
|
+
`Next action is executable (${nextAction || 'sce studio verify --job <job-id>'}).`
|
|
1428
|
+
],
|
|
1429
|
+
verify: [
|
|
1430
|
+
'Verification gates finish with no required-step failures.',
|
|
1431
|
+
`Verify report is available (${normalizeString(artifacts.verify_report) || 'artifact pending'}).`,
|
|
1432
|
+
`Next action is executable (${nextAction || 'sce studio release --job <job-id>'}).`
|
|
1433
|
+
],
|
|
1434
|
+
release: [
|
|
1435
|
+
'Release gates pass under configured release profile.',
|
|
1436
|
+
`Release reference is emitted (${normalizeString(artifacts.release_ref) || 'artifact pending'}).`,
|
|
1437
|
+
`Next action is executable (${nextAction || 'complete'}).`
|
|
1438
|
+
],
|
|
1439
|
+
rollback: [
|
|
1440
|
+
'Rollback stage transitions job status to rolled_back.',
|
|
1441
|
+
'Rollback evidence is appended to studio event stream.',
|
|
1442
|
+
`Recovery next action is executable (${nextAction || 'sce studio plan --scene <scene-id> --from-chat <session>'}).`
|
|
1443
|
+
],
|
|
1444
|
+
events: [
|
|
1445
|
+
'Events stream payload is available for task-level audit.',
|
|
1446
|
+
'Task envelope preserves normalized IDs and handoff fields.',
|
|
1447
|
+
`Next action is explicit (${nextAction || 'n/a'}).`
|
|
1448
|
+
],
|
|
1449
|
+
resume: [
|
|
1450
|
+
'Current job status and stage progress are restored deterministically.',
|
|
1451
|
+
'Task envelope remains schema-compatible for downstream UI.',
|
|
1452
|
+
`Next action is explicit (${nextAction || 'n/a'}).`
|
|
1453
|
+
]
|
|
1454
|
+
};
|
|
1455
|
+
return criteriaByStage[normalizedStage] || [
|
|
1456
|
+
'Task envelope contains normalized identifiers and task contract fields.',
|
|
1457
|
+
'Task output preserves evidence, command logs, and error bundles.',
|
|
1458
|
+
`Next action is explicit (${nextAction || 'n/a'}).`
|
|
1459
|
+
];
|
|
1460
|
+
}
|
|
1461
|
+
|
|
1339
1462
|
function buildTaskEnvelope(mode, job, options = {}) {
|
|
1340
1463
|
const stageName = resolveTaskStage(mode, job, options.stageName);
|
|
1341
1464
|
const stageState = stageName && job && job.stages && job.stages[stageName]
|
|
@@ -1359,8 +1482,10 @@ function buildTaskEnvelope(mode, job, options = {}) {
|
|
|
1359
1482
|
|| (normalizeString(job && job.job_id)
|
|
1360
1483
|
? `${job.job_id}:${stageName || 'task'}`
|
|
1361
1484
|
: null);
|
|
1362
|
-
const
|
|
1485
|
+
const rawRequest = normalizeString(job?.source?.goal);
|
|
1486
|
+
const goal = rawRequest
|
|
1363
1487
|
|| `Studio ${stageName || 'task'} execution`;
|
|
1488
|
+
const taskIntent = deriveTaskIntentShape(rawRequest, stageName);
|
|
1364
1489
|
const sessionId = normalizeString(job?.session?.scene_session_id) || null;
|
|
1365
1490
|
const sceneId = normalizeString(job?.scene?.id) || null;
|
|
1366
1491
|
const specId = normalizeString(job?.scene?.spec_id) || normalizeString(job?.source?.spec_id) || null;
|
|
@@ -1400,7 +1525,14 @@ function buildTaskEnvelope(mode, job, options = {}) {
|
|
|
1400
1525
|
eventId: normalizeString(latestEvent && latestEvent.event_id) || null,
|
|
1401
1526
|
task: {
|
|
1402
1527
|
ref: taskRef,
|
|
1528
|
+
task_ref: taskRef,
|
|
1529
|
+
title_norm: taskIntent.title_norm,
|
|
1530
|
+
raw_request: taskIntent.raw_request,
|
|
1403
1531
|
goal,
|
|
1532
|
+
sub_goals: taskIntent.sub_goals,
|
|
1533
|
+
acceptance_criteria: buildTaskAcceptanceCriteria(stageName, job, nextAction),
|
|
1534
|
+
needs_split: taskIntent.needs_split,
|
|
1535
|
+
confidence: taskIntent.confidence,
|
|
1404
1536
|
status: taskStatus,
|
|
1405
1537
|
summary: buildTaskSummaryLines(job, stageName, taskStatus, nextAction, taskRef),
|
|
1406
1538
|
handoff: normalizedHandoff,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scene-capability-engine",
|
|
3
|
-
"version": "3.6.
|
|
3
|
+
"version": "3.6.2",
|
|
4
4
|
"description": "SCE (Scene Capability Engine) - A CLI tool and npm package for spec-driven development with AI coding assistants.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"test:ci": "npx jest --config=jest.config.ci.js",
|
|
30
30
|
"test:unit": "npx jest tests/unit",
|
|
31
31
|
"test:integration": "npx jest tests/integration",
|
|
32
|
+
"test:release": "npm run test:integration -- --runInBand",
|
|
32
33
|
"test:properties": "npx jest tests/properties",
|
|
33
34
|
"test:orchestrator-429": "npx jest tests/orchestrator/orchestration-engine.test.js tests/orchestrator/orchestrate-command.status-events.test.js --runInBand",
|
|
34
35
|
"test:handles": "npx jest --config=jest.config.js --runInBand --detectOpenHandles",
|
|
@@ -74,7 +75,7 @@
|
|
|
74
75
|
"gate:release-asset-integrity": "node scripts/release-asset-integrity-check.js",
|
|
75
76
|
"report:release-risk-remediation": "node scripts/release-risk-remediation-bundle.js --json",
|
|
76
77
|
"report:moqui-core-regression": "node scripts/moqui-core-regression-suite.js --json",
|
|
77
|
-
"prepublishOnly": "npm run test:
|
|
78
|
+
"prepublishOnly": "npm run test:release && npm run test:skip-audit && npm run test:sce-tracking && npm run test:brand-consistency && npm run gate:git-managed && npm run gate:errorbook-registry-health && npm run gate:errorbook-release && npm run report:interactive-governance -- --fail-on-alert",
|
|
78
79
|
"publish:manual": "npm publish --access public",
|
|
79
80
|
"install-global": "npm install -g .",
|
|
80
81
|
"uninstall-global": "npm uninstall -g scene-capability-engine"
|