scene-capability-engine 3.4.6 → 3.5.0
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 +20 -0
- package/README.md +4 -1
- package/README.zh.md +4 -1
- package/docs/command-reference.md +37 -1
- package/lib/adoption/adoption-strategy.js +1 -0
- package/lib/adoption/detection-engine.js +1 -0
- package/lib/adoption/file-classifier.js +2 -1
- package/lib/adoption/smart-orchestrator.js +1 -0
- package/lib/commands/studio.js +269 -18
- package/lib/studio/spec-intake-governor.js +992 -0
- package/lib/workspace/takeover-baseline.js +56 -0
- package/package.json +1 -1
- package/template/.sce/config/studio-intake-policy.json +68 -0
- package/template/.sce/config/takeover-baseline.json +88 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [3.5.0] - 2026-03-02
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Studio automatic intake + spec governance baseline:
|
|
14
|
+
- new policy: `.sce/config/studio-intake-policy.json` (template/adopt/takeover managed)
|
|
15
|
+
- `studio plan` now auto-detects goal intent and resolves spec by bind/create strategy
|
|
16
|
+
- new commands:
|
|
17
|
+
- `sce studio intake`
|
|
18
|
+
- `sce studio portfolio`
|
|
19
|
+
- plan stage now auto-writes scene portfolio governance artifacts:
|
|
20
|
+
- `.sce/spec-governance/scene-portfolio.latest.json`
|
|
21
|
+
- `.sce/spec-governance/scene-index.json`
|
|
22
|
+
- New intake/governance module:
|
|
23
|
+
- `lib/studio/spec-intake-governor.js`
|
|
24
|
+
- scene-level duplicate/overflow/stale spec governance summary for portfolio management
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- Takeover/adoption managed config baseline now includes `config/studio-intake-policy.json` by default.
|
|
28
|
+
- README/README.zh/command reference updated for auto intake and scene-organized spec governance workflow.
|
|
29
|
+
|
|
10
30
|
## [3.4.6] - 2026-03-02
|
|
11
31
|
|
|
12
32
|
### Added
|
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ SCE is designed for teams that want AI agents to deliver software end-to-end wit
|
|
|
26
26
|
| Capability | What SCE Provides | Outcome |
|
|
27
27
|
| --- | --- | --- |
|
|
28
28
|
| Scene + Spec model | Scene-governed sessions and Spec lifecycle (`requirements/design/tasks`) | Stable context across long AI runs |
|
|
29
|
+
| Auto intake + Spec governance | Goal intent detection, auto spec bind/create, scene portfolio governance | Automatic scene-to-spec tracking with bounded spec growth |
|
|
29
30
|
| Studio workflow | `studio plan -> generate -> apply -> verify -> release` | Structured chat-to-release execution |
|
|
30
31
|
| Autonomous delivery | `auto close-loop`, `close-loop-program`, `close-loop-controller` | Unattended bounded convergence |
|
|
31
32
|
| Multi-agent orchestration | DAG scheduling, retries, 429 adaptive parallel control | Reliable parallel execution at scale |
|
|
@@ -106,6 +107,7 @@ SCE now enforces a domain-closed diagnosis and repair route by default:
|
|
|
106
107
|
Hard rule defaults:
|
|
107
108
|
- After two failed rounds on the same problem fingerprint, debug evidence is required in subsequent attempts.
|
|
108
109
|
- `studio verify/release` run `problem-closure-gate` by default when a spec is bound.
|
|
110
|
+
- `studio plan` auto-runs goal intake (`bind existing spec` or `create spec`) and writes scene portfolio governance snapshots by default.
|
|
109
111
|
|
|
110
112
|
---
|
|
111
113
|
|
|
@@ -128,6 +130,7 @@ SCE is tool-agnostic and works with Codex, Claude Code, Cursor, Windsurf, VS Cod
|
|
|
128
130
|
|
|
129
131
|
## Important Version Changes
|
|
130
132
|
|
|
133
|
+
- `3.5.0`: Added Studio automatic goal intake + scene spec portfolio governance (`sce studio intake`, `sce studio portfolio`), including default intake policy baseline and governance artifacts for bounded scene spec growth.
|
|
131
134
|
- `3.4.6`: Added default `problem-closure-gate` + `problem-contract` baseline and strengthened mandatory problem evaluation dimensions (`problem_contract`/`ontology_alignment`/`convergence`) for verify/release convergence control.
|
|
132
135
|
- `3.4.5`: `git-managed-gate` now treats worktree checks as advisory in default relaxed CI mode (`CI/GITHUB_ACTIONS`, non-strict), preventing false release blocking.
|
|
133
136
|
- `3.4.4`: Added `SCE_GIT_MANAGEMENT_ALLOW_UNTRACKED=1` / `--allow-untracked`; release workflow uses it for npm publish after generating release evidence artifacts.
|
|
@@ -174,5 +177,5 @@ MIT. See [LICENSE](LICENSE).
|
|
|
174
177
|
|
|
175
178
|
---
|
|
176
179
|
|
|
177
|
-
**Version**: 3.
|
|
180
|
+
**Version**: 3.5.0
|
|
178
181
|
**Last Updated**: 2026-03-02
|
package/README.zh.md
CHANGED
|
@@ -26,6 +26,7 @@ SCE 面向希望让 AI Agent 端到端推进交付、同时保持治理可控的
|
|
|
26
26
|
| 能力 | SCE 提供什么 | 结果 |
|
|
27
27
|
| --- | --- | --- |
|
|
28
28
|
| Scene + Spec 模型 | 场景主会话治理 + Spec 生命周期(需求/设计/任务) | 长周期 AI 上下文稳定 |
|
|
29
|
+
| 自动 intake + Spec 治理 | 目标意图识别、自动绑定/创建 spec、按 scene 组合治理 | 场景需求自动纳管,spec 增长可控 |
|
|
29
30
|
| Studio 工作流 | `studio plan -> generate -> apply -> verify -> release` | 对话到发布路径结构化 |
|
|
30
31
|
| 自动闭环交付 | `auto close-loop`、`close-loop-program`、`close-loop-controller` | 无人值守有界收敛 |
|
|
31
32
|
| 多 Agent 编排 | DAG 调度、重试、429 自适应并行 | 并行执行稳定可控 |
|
|
@@ -106,6 +107,7 @@ SCE 默认按“问题域闭环”推进诊断与修复:
|
|
|
106
107
|
默认硬规则:
|
|
107
108
|
- 同一问题指纹失败两轮后,后续尝试必须补充 debug 证据。
|
|
108
109
|
- 当 spec 绑定时,`studio verify/release` 默认执行 `problem-closure-gate`。
|
|
110
|
+
- `studio plan` 默认执行目标 intake(自动绑定已有 spec 或新建 spec),并自动写入 scene 维度的 spec 治理快照。
|
|
109
111
|
|
|
110
112
|
---
|
|
111
113
|
|
|
@@ -128,6 +130,7 @@ SCE 对工具无锁定,可接入 Codex、Claude Code、Cursor、Windsurf、VS
|
|
|
128
130
|
|
|
129
131
|
## 重要版本变更
|
|
130
132
|
|
|
133
|
+
- `3.5.0`:新增 Studio 目标自动 intake + 场景 spec 组合治理(`sce studio intake`、`sce studio portfolio`),并默认启用 intake 策略基线与治理快照产物,控制场景内 spec 无序增长。
|
|
131
134
|
- `3.4.6`:新增默认 `problem-closure-gate` + `problem-contract` 基线,并强化问题评估强制维度(`problem_contract`/`ontology_alignment`/`convergence`),提升 verify/release 收敛控制。
|
|
132
135
|
- `3.4.5`:`git-managed-gate` 在默认 CI 放宽模式下(`CI/GITHUB_ACTIONS` 且非 strict)对工作区变更改为告警,不再误阻断发布。
|
|
133
136
|
- `3.4.4`:新增 `SCE_GIT_MANAGEMENT_ALLOW_UNTRACKED=1` / `--allow-untracked`;发布工作流在 npm publish 前生成证据资产时可放行未跟踪文件。
|
|
@@ -174,5 +177,5 @@ MIT,见 [LICENSE](LICENSE)。
|
|
|
174
177
|
|
|
175
178
|
---
|
|
176
179
|
|
|
177
|
-
**版本**:3.
|
|
180
|
+
**版本**:3.5.0
|
|
178
181
|
**最后更新**:2026-03-02
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Quick reference for all `sce` commands
|
|
4
4
|
|
|
5
|
-
**Version**: 3.
|
|
5
|
+
**Version**: 3.5.0
|
|
6
6
|
**Last Updated**: 2026-03-02
|
|
7
7
|
|
|
8
8
|
---
|
|
@@ -523,6 +523,13 @@ Curated quality policy (`宁缺毋滥,优胜略汰`) defaults:
|
|
|
523
523
|
sce studio plan --scene scene.customer-order-inventory --from-chat session-20260226 --goal "customer+order+inventory demo" --json
|
|
524
524
|
# Recommended: bind spec explicitly so Studio can ingest problem-domain-chain deterministically
|
|
525
525
|
sce studio plan --scene scene.customer-order-inventory --spec 01-00-customer-order-inventory --from-chat session-20260226 --goal "customer+order+inventory demo" --json
|
|
526
|
+
# Disable auto intake for emergency/manual mode
|
|
527
|
+
sce studio plan --scene scene.customer-order-inventory --from-chat session-20260226 --goal "customer+order+inventory demo" --manual-spec --json
|
|
528
|
+
|
|
529
|
+
# Analyze intake decision only (no write by default)
|
|
530
|
+
sce studio intake --scene scene.customer-order-inventory --from-chat session-20260226 --goal "optimize checkout retry flow" --json
|
|
531
|
+
# Apply intake and create spec when decision is create_spec
|
|
532
|
+
sce studio intake --scene scene.customer-order-inventory --from-chat session-20260226 --goal "optimize checkout retry flow" --apply --json
|
|
526
533
|
|
|
527
534
|
# Generate patch bundle metadata (scene is inherited from plan)
|
|
528
535
|
sce studio generate --target 331 --json
|
|
@@ -549,15 +556,26 @@ sce studio events --job <job-id> --limit 50 --json
|
|
|
549
556
|
# Rollback a job after apply/release
|
|
550
557
|
sce studio rollback --job <job-id> --reason "manual-check-failed" --json
|
|
551
558
|
|
|
559
|
+
# Build scene-organized spec governance portfolio
|
|
560
|
+
sce studio portfolio --json
|
|
561
|
+
sce studio portfolio --scene scene.customer-order-inventory --strict --json
|
|
562
|
+
|
|
552
563
|
# Enforce authorization for a protected action
|
|
553
564
|
SCE_STUDIO_REQUIRE_AUTH=1 SCE_STUDIO_AUTH_PASSWORD=top-secret sce studio apply --job <job-id> --auth-password top-secret --json
|
|
554
565
|
```
|
|
555
566
|
|
|
556
567
|
Stage guardrails are enforced by default:
|
|
557
568
|
- `plan` requires `--scene`; SCE binds one active primary session per scene
|
|
569
|
+
- `plan` runs auto intake by default (`.sce/config/studio-intake-policy.json`):
|
|
570
|
+
- detect goal intent (`change_request` vs `analysis_only`)
|
|
571
|
+
- resolve spec via explicit binding / scene latest / related specs / auto-create
|
|
572
|
+
- auto-create spec artifacts when no suitable spec is found and policy requires tracking
|
|
558
573
|
- `plan --spec <id>` (recommended) ingests `.sce/specs/<spec>/custom/problem-domain-chain.json` into studio job context
|
|
559
574
|
- when `--spec` is omitted, `plan` auto-resolves the latest matching spec chain by `scene_id` when available
|
|
560
575
|
- `plan` auto-searches related historical specs by `scene + goal` and writes top candidates into job metadata (`source.related_specs`)
|
|
576
|
+
- `plan` auto-runs scene spec governance snapshot and writes:
|
|
577
|
+
- `.sce/spec-governance/scene-portfolio.latest.json`
|
|
578
|
+
- `.sce/spec-governance/scene-index.json`
|
|
561
579
|
- successful `release` auto-archives current scene session and auto-opens the next scene cycle session
|
|
562
580
|
- `generate` requires `plan`
|
|
563
581
|
- `generate` consumes the plan-stage domain-chain context and writes chain-aware metadata/report (`.sce/reports/studio/generate-<job-id>.json`)
|
|
@@ -632,6 +650,24 @@ Default policy file (recommended to commit): `.sce/config/studio-security.json`
|
|
|
632
650
|
}
|
|
633
651
|
```
|
|
634
652
|
|
|
653
|
+
Studio intake policy file (default, recommended to commit): `.sce/config/studio-intake-policy.json`
|
|
654
|
+
|
|
655
|
+
```json
|
|
656
|
+
{
|
|
657
|
+
"enabled": true,
|
|
658
|
+
"auto_create_spec": true,
|
|
659
|
+
"force_spec_for_studio_plan": true,
|
|
660
|
+
"prefer_existing_scene_spec": true,
|
|
661
|
+
"related_spec_min_score": 45,
|
|
662
|
+
"governance": {
|
|
663
|
+
"auto_run_on_plan": true,
|
|
664
|
+
"max_active_specs_per_scene": 3,
|
|
665
|
+
"stale_days": 14,
|
|
666
|
+
"duplicate_similarity_threshold": 0.66
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
```
|
|
670
|
+
|
|
635
671
|
### Capability Matrix Utilities
|
|
636
672
|
|
|
637
673
|
```bash
|
|
@@ -120,6 +120,7 @@ class AdoptionStrategy {
|
|
|
120
120
|
'config/spec-domain-policy.json',
|
|
121
121
|
'config/problem-eval-policy.json',
|
|
122
122
|
'config/problem-closure-policy.json',
|
|
123
|
+
'config/studio-intake-policy.json',
|
|
123
124
|
'specs/SPEC_WORKFLOW_GUIDE.md',
|
|
124
125
|
'hooks/sync-tasks-on-edit.sce.hook',
|
|
125
126
|
'hooks/check-spec-on-create.sce.hook',
|
|
@@ -169,6 +169,7 @@ class DetectionEngine {
|
|
|
169
169
|
'config/spec-domain-policy.json',
|
|
170
170
|
'config/problem-eval-policy.json',
|
|
171
171
|
'config/problem-closure-policy.json',
|
|
172
|
+
'config/studio-intake-policy.json',
|
|
172
173
|
'README.md',
|
|
173
174
|
'ultrawork-application-guide.md',
|
|
174
175
|
'ultrawork-integration-summary.md',
|
|
@@ -70,7 +70,8 @@ class FileClassifier {
|
|
|
70
70
|
'config/session-governance.json',
|
|
71
71
|
'config/spec-domain-policy.json',
|
|
72
72
|
'config/problem-eval-policy.json',
|
|
73
|
-
'config/problem-closure-policy.json'
|
|
73
|
+
'config/problem-closure-policy.json',
|
|
74
|
+
'config/studio-intake-policy.json'
|
|
74
75
|
];
|
|
75
76
|
|
|
76
77
|
// Generated directory patterns
|
package/lib/commands/studio.js
CHANGED
|
@@ -11,6 +11,10 @@ const {
|
|
|
11
11
|
const { findRelatedSpecs } = require('../spec/related-specs');
|
|
12
12
|
const { captureTimelineCheckpoint } = require('../runtime/project-timeline');
|
|
13
13
|
const { runProblemEvaluation } = require('../problem/problem-evaluator');
|
|
14
|
+
const {
|
|
15
|
+
runStudioAutoIntake,
|
|
16
|
+
runStudioSpecGovernance
|
|
17
|
+
} = require('../studio/spec-intake-governor');
|
|
14
18
|
|
|
15
19
|
const STUDIO_JOB_API_VERSION = 'sce.studio.job/v0.1';
|
|
16
20
|
const STAGE_ORDER = ['plan', 'generate', 'apply', 'verify', 'release'];
|
|
@@ -1343,6 +1347,9 @@ async function runStudioPlanCommand(options = {}, dependencies = {}) {
|
|
|
1343
1347
|
const fromChat = normalizeString(options.fromChat);
|
|
1344
1348
|
const sceneId = normalizeString(options.scene);
|
|
1345
1349
|
const specId = normalizeString(options.spec);
|
|
1350
|
+
const goal = normalizeString(options.goal);
|
|
1351
|
+
const manualSpecMode = options.manualSpec === true;
|
|
1352
|
+
const skipSpecGovernance = options.specGovernance === false;
|
|
1346
1353
|
|
|
1347
1354
|
if (!fromChat) {
|
|
1348
1355
|
throw new Error('--from-chat is required');
|
|
@@ -1350,16 +1357,18 @@ async function runStudioPlanCommand(options = {}, dependencies = {}) {
|
|
|
1350
1357
|
if (!sceneId) {
|
|
1351
1358
|
throw new Error('--scene is required');
|
|
1352
1359
|
}
|
|
1353
|
-
|
|
1360
|
+
|
|
1361
|
+
let domainChainBinding = await resolveDomainChainBinding({
|
|
1354
1362
|
sceneId,
|
|
1355
1363
|
specId,
|
|
1356
|
-
goal
|
|
1364
|
+
goal
|
|
1357
1365
|
}, {
|
|
1358
1366
|
projectPath,
|
|
1359
1367
|
fileSystem
|
|
1360
1368
|
});
|
|
1361
|
-
|
|
1362
|
-
|
|
1369
|
+
|
|
1370
|
+
let relatedSpecLookup = await findRelatedSpecs({
|
|
1371
|
+
query: goal,
|
|
1363
1372
|
sceneId,
|
|
1364
1373
|
limit: 8,
|
|
1365
1374
|
excludeSpecId: domainChainBinding.spec_id || specId || null
|
|
@@ -1367,6 +1376,45 @@ async function runStudioPlanCommand(options = {}, dependencies = {}) {
|
|
|
1367
1376
|
projectPath,
|
|
1368
1377
|
fileSystem
|
|
1369
1378
|
});
|
|
1379
|
+
|
|
1380
|
+
const intake = await runStudioAutoIntake({
|
|
1381
|
+
scene_id: sceneId,
|
|
1382
|
+
from_chat: fromChat,
|
|
1383
|
+
goal,
|
|
1384
|
+
explicit_spec_id: specId,
|
|
1385
|
+
domain_chain_binding: domainChainBinding,
|
|
1386
|
+
related_specs: relatedSpecLookup,
|
|
1387
|
+
apply: !manualSpecMode,
|
|
1388
|
+
skip: manualSpecMode
|
|
1389
|
+
}, {
|
|
1390
|
+
projectPath,
|
|
1391
|
+
fileSystem
|
|
1392
|
+
});
|
|
1393
|
+
|
|
1394
|
+
const intakeSpecId = normalizeString(intake && intake.selected_spec_id);
|
|
1395
|
+
const effectiveSpecId = intakeSpecId || normalizeString(domainChainBinding.spec_id) || specId || null;
|
|
1396
|
+
|
|
1397
|
+
if (effectiveSpecId && effectiveSpecId !== normalizeString(domainChainBinding.spec_id)) {
|
|
1398
|
+
domainChainBinding = await resolveDomainChainBinding({
|
|
1399
|
+
sceneId,
|
|
1400
|
+
specId: effectiveSpecId,
|
|
1401
|
+
goal
|
|
1402
|
+
}, {
|
|
1403
|
+
projectPath,
|
|
1404
|
+
fileSystem
|
|
1405
|
+
});
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
relatedSpecLookup = await findRelatedSpecs({
|
|
1409
|
+
query: goal,
|
|
1410
|
+
sceneId,
|
|
1411
|
+
limit: 8,
|
|
1412
|
+
excludeSpecId: effectiveSpecId || null
|
|
1413
|
+
}, {
|
|
1414
|
+
projectPath,
|
|
1415
|
+
fileSystem
|
|
1416
|
+
});
|
|
1417
|
+
|
|
1370
1418
|
const relatedSpecItems = Array.isArray(relatedSpecLookup.related_specs)
|
|
1371
1419
|
? relatedSpecLookup.related_specs.map((item) => ({
|
|
1372
1420
|
spec_id: item.spec_id,
|
|
@@ -1387,7 +1435,7 @@ async function runStudioPlanCommand(options = {}, dependencies = {}) {
|
|
|
1387
1435
|
domainChainBinding.problem_contract || {},
|
|
1388
1436
|
{
|
|
1389
1437
|
scene_id: sceneId,
|
|
1390
|
-
goal
|
|
1438
|
+
goal,
|
|
1391
1439
|
problem_statement: normalizeString(domainChainBinding?.summary?.problem_statement),
|
|
1392
1440
|
verification_plan: normalizeString(domainChainBinding?.summary?.verification_plan)
|
|
1393
1441
|
}
|
|
@@ -1396,11 +1444,11 @@ async function runStudioPlanCommand(options = {}, dependencies = {}) {
|
|
|
1396
1444
|
job_id: jobId,
|
|
1397
1445
|
scene: {
|
|
1398
1446
|
id: sceneId,
|
|
1399
|
-
spec_id:
|
|
1447
|
+
spec_id: effectiveSpecId
|
|
1400
1448
|
},
|
|
1401
1449
|
source: {
|
|
1402
|
-
goal:
|
|
1403
|
-
spec_id:
|
|
1450
|
+
goal: goal || null,
|
|
1451
|
+
spec_id: effectiveSpecId,
|
|
1404
1452
|
problem_contract: problemContract,
|
|
1405
1453
|
problem_contract_path: domainChainBinding.problem_contract_path || null,
|
|
1406
1454
|
domain_chain: {
|
|
@@ -1415,8 +1463,8 @@ async function runStudioPlanCommand(options = {}, dependencies = {}) {
|
|
|
1415
1463
|
};
|
|
1416
1464
|
const planProblemEvaluation = await enforceProblemEvaluationForStage(planShadowJob, 'plan', {
|
|
1417
1465
|
scene_id: sceneId,
|
|
1418
|
-
spec_id:
|
|
1419
|
-
goal:
|
|
1466
|
+
spec_id: effectiveSpecId,
|
|
1467
|
+
goal: goal || null,
|
|
1420
1468
|
problem_contract: problemContract,
|
|
1421
1469
|
domain_chain: {
|
|
1422
1470
|
resolved: domainChainBinding.resolved === true,
|
|
@@ -1444,16 +1492,35 @@ async function runStudioPlanCommand(options = {}, dependencies = {}) {
|
|
|
1444
1492
|
const sessionStore = dependencies.sessionStore || new SessionStore(projectPath);
|
|
1445
1493
|
const sceneSessionBinding = await sessionStore.beginSceneSession({
|
|
1446
1494
|
sceneId,
|
|
1447
|
-
objective:
|
|
1495
|
+
objective: goal || `Studio scene cycle for ${sceneId}`,
|
|
1448
1496
|
tool: normalizeString(options.tool) || 'generic'
|
|
1449
1497
|
});
|
|
1498
|
+
|
|
1499
|
+
let governanceSnapshot = null;
|
|
1500
|
+
let governanceWarning = '';
|
|
1501
|
+
const autoRunGovernance = !(skipSpecGovernance)
|
|
1502
|
+
&& (!intake || !intake.policy || !intake.policy.governance || intake.policy.governance.auto_run_on_plan !== false);
|
|
1503
|
+
if (autoRunGovernance) {
|
|
1504
|
+
try {
|
|
1505
|
+
governanceSnapshot = await runStudioSpecGovernance({
|
|
1506
|
+
apply: true,
|
|
1507
|
+
scene: sceneId
|
|
1508
|
+
}, {
|
|
1509
|
+
projectPath,
|
|
1510
|
+
fileSystem
|
|
1511
|
+
});
|
|
1512
|
+
} catch (error) {
|
|
1513
|
+
governanceWarning = normalizeString(error && error.message);
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1450
1517
|
stages.plan = {
|
|
1451
1518
|
status: 'completed',
|
|
1452
1519
|
completed_at: now,
|
|
1453
1520
|
metadata: {
|
|
1454
1521
|
from_chat: fromChat,
|
|
1455
1522
|
scene_id: sceneId,
|
|
1456
|
-
spec_id:
|
|
1523
|
+
spec_id: effectiveSpecId,
|
|
1457
1524
|
scene_session_id: sceneSessionBinding.session.session_id,
|
|
1458
1525
|
scene_cycle: sceneSessionBinding.scene_cycle,
|
|
1459
1526
|
domain_chain_resolved: domainChainBinding.resolved === true,
|
|
@@ -1463,7 +1530,18 @@ async function runStudioPlanCommand(options = {}, dependencies = {}) {
|
|
|
1463
1530
|
domain_chain_summary: domainChainBinding.summary || null,
|
|
1464
1531
|
domain_chain_reason: domainChainBinding.reason || null,
|
|
1465
1532
|
problem_contract: problemContract,
|
|
1533
|
+
intake: intake ? {
|
|
1534
|
+
enabled: intake.enabled === true,
|
|
1535
|
+
intent_type: intake.intent ? intake.intent.intent_type : null,
|
|
1536
|
+
decision_action: intake.decision ? intake.decision.action : null,
|
|
1537
|
+
decision_reason: intake.decision ? intake.decision.reason : null,
|
|
1538
|
+
selected_spec_id: intake.selected_spec_id || effectiveSpecId || null,
|
|
1539
|
+
created_spec_id: intake.created_spec && intake.created_spec.created ? intake.created_spec.spec_id : null,
|
|
1540
|
+
policy_path: intake.policy_path || null
|
|
1541
|
+
} : null,
|
|
1466
1542
|
problem_evaluation: summarizeProblemEvaluation(planProblemEvaluation),
|
|
1543
|
+
spec_governance: governanceSnapshot ? governanceSnapshot.summary : null,
|
|
1544
|
+
spec_governance_warning: governanceWarning || null,
|
|
1467
1545
|
related_specs_total: Number(relatedSpecLookup.total_candidates || 0),
|
|
1468
1546
|
related_specs_top: relatedSpecItems
|
|
1469
1547
|
}
|
|
@@ -1477,15 +1555,24 @@ async function runStudioPlanCommand(options = {}, dependencies = {}) {
|
|
|
1477
1555
|
status: 'planned',
|
|
1478
1556
|
source: {
|
|
1479
1557
|
from_chat: fromChat,
|
|
1480
|
-
goal:
|
|
1481
|
-
spec_id:
|
|
1558
|
+
goal: goal || null,
|
|
1559
|
+
spec_id: effectiveSpecId,
|
|
1482
1560
|
problem_contract: problemContract,
|
|
1483
1561
|
problem_contract_path: domainChainBinding.problem_contract_path || null,
|
|
1562
|
+
intake: intake ? {
|
|
1563
|
+
enabled: intake.enabled === true,
|
|
1564
|
+
policy_path: intake.policy_path || null,
|
|
1565
|
+
policy_loaded_from: intake.policy_loaded_from || null,
|
|
1566
|
+
intent: intake.intent || null,
|
|
1567
|
+
decision: intake.decision || null,
|
|
1568
|
+
selected_spec_id: intake.selected_spec_id || effectiveSpecId || null,
|
|
1569
|
+
created_spec: intake.created_spec || null
|
|
1570
|
+
} : null,
|
|
1484
1571
|
domain_chain: {
|
|
1485
1572
|
resolved: domainChainBinding.resolved === true,
|
|
1486
1573
|
source: domainChainBinding.source || 'none',
|
|
1487
1574
|
reason: domainChainBinding.reason || null,
|
|
1488
|
-
spec_id: domainChainBinding.spec_id || null,
|
|
1575
|
+
spec_id: effectiveSpecId || domainChainBinding.spec_id || null,
|
|
1489
1576
|
chain_path: domainChainBinding.chain_path || null,
|
|
1490
1577
|
candidate_count: Number.isFinite(Number(domainChainBinding.candidate_count))
|
|
1491
1578
|
? Number(domainChainBinding.candidate_count)
|
|
@@ -1500,11 +1587,20 @@ async function runStudioPlanCommand(options = {}, dependencies = {}) {
|
|
|
1500
1587
|
scene_id: relatedSpecLookup.scene_id || null,
|
|
1501
1588
|
total_candidates: Number(relatedSpecLookup.total_candidates || 0),
|
|
1502
1589
|
items: relatedSpecItems
|
|
1503
|
-
}
|
|
1590
|
+
},
|
|
1591
|
+
spec_governance: governanceSnapshot
|
|
1592
|
+
? {
|
|
1593
|
+
status: governanceSnapshot.summary ? governanceSnapshot.summary.status : null,
|
|
1594
|
+
alert_count: governanceSnapshot.summary ? Number(governanceSnapshot.summary.alert_count || 0) : 0,
|
|
1595
|
+
report_file: governanceSnapshot.report_file || null,
|
|
1596
|
+
scene_index_file: governanceSnapshot.scene_index_file || null
|
|
1597
|
+
}
|
|
1598
|
+
: null,
|
|
1599
|
+
spec_governance_warning: governanceWarning || null
|
|
1504
1600
|
},
|
|
1505
1601
|
scene: {
|
|
1506
1602
|
id: sceneId,
|
|
1507
|
-
spec_id:
|
|
1603
|
+
spec_id: effectiveSpecId,
|
|
1508
1604
|
related_spec_ids: relatedSpecItems.map((item) => item.spec_id)
|
|
1509
1605
|
},
|
|
1510
1606
|
session: {
|
|
@@ -1520,6 +1616,12 @@ async function runStudioPlanCommand(options = {}, dependencies = {}) {
|
|
|
1520
1616
|
patch_bundle_id: null,
|
|
1521
1617
|
verify_report: null,
|
|
1522
1618
|
release_ref: null,
|
|
1619
|
+
spec_portfolio_report: governanceSnapshot && governanceSnapshot.report_file
|
|
1620
|
+
? governanceSnapshot.report_file
|
|
1621
|
+
: null,
|
|
1622
|
+
spec_scene_index: governanceSnapshot && governanceSnapshot.scene_index_file
|
|
1623
|
+
? governanceSnapshot.scene_index_file
|
|
1624
|
+
: null,
|
|
1523
1625
|
problem_eval_reports: {
|
|
1524
1626
|
plan: normalizeString(planProblemEvaluation.report_file) || null
|
|
1525
1627
|
}
|
|
@@ -1530,7 +1632,7 @@ async function runStudioPlanCommand(options = {}, dependencies = {}) {
|
|
|
1530
1632
|
await appendStudioEvent(paths, job, 'stage.plan.completed', {
|
|
1531
1633
|
from_chat: fromChat,
|
|
1532
1634
|
scene_id: sceneId,
|
|
1533
|
-
spec_id:
|
|
1635
|
+
spec_id: effectiveSpecId,
|
|
1534
1636
|
scene_session_id: sceneSessionBinding.session.session_id,
|
|
1535
1637
|
scene_cycle: sceneSessionBinding.scene_cycle,
|
|
1536
1638
|
target: job.target,
|
|
@@ -1539,13 +1641,27 @@ async function runStudioPlanCommand(options = {}, dependencies = {}) {
|
|
|
1539
1641
|
domain_chain_spec_id: domainChainBinding.spec_id || null,
|
|
1540
1642
|
domain_chain_path: domainChainBinding.chain_path || null,
|
|
1541
1643
|
problem_contract: problemContract,
|
|
1644
|
+
intake_action: intake && intake.decision ? intake.decision.action : null,
|
|
1645
|
+
intake_reason: intake && intake.decision ? intake.decision.reason : null,
|
|
1646
|
+
intake_selected_spec_id: intake ? intake.selected_spec_id || effectiveSpecId || null : effectiveSpecId,
|
|
1647
|
+
intake_created_spec_id: intake && intake.created_spec && intake.created_spec.created
|
|
1648
|
+
? intake.created_spec.spec_id
|
|
1649
|
+
: null,
|
|
1542
1650
|
problem_evaluation: summarizeProblemEvaluation(planProblemEvaluation),
|
|
1651
|
+
spec_governance: governanceSnapshot ? governanceSnapshot.summary : null,
|
|
1652
|
+
spec_governance_warning: governanceWarning || null,
|
|
1543
1653
|
related_specs_total: Number(relatedSpecLookup.total_candidates || 0),
|
|
1544
1654
|
related_spec_ids: relatedSpecItems.map((item) => item.spec_id)
|
|
1545
1655
|
}, fileSystem);
|
|
1546
1656
|
await writeLatestJob(paths, jobId, fileSystem);
|
|
1547
1657
|
|
|
1548
1658
|
const payload = buildCommandPayload('studio-plan', job);
|
|
1659
|
+
payload.scene = {
|
|
1660
|
+
id: sceneId,
|
|
1661
|
+
spec_id: effectiveSpecId
|
|
1662
|
+
};
|
|
1663
|
+
payload.intake = job.source && job.source.intake ? job.source.intake : null;
|
|
1664
|
+
payload.spec_governance = governanceSnapshot ? governanceSnapshot.summary : null;
|
|
1549
1665
|
printStudioPayload(payload, options);
|
|
1550
1666
|
return payload;
|
|
1551
1667
|
}
|
|
@@ -2178,6 +2294,116 @@ async function runStudioEventsCommand(options = {}, dependencies = {}) {
|
|
|
2178
2294
|
return payload;
|
|
2179
2295
|
}
|
|
2180
2296
|
|
|
2297
|
+
function printStudioIntakePayload(payload, options = {}) {
|
|
2298
|
+
if (options.json) {
|
|
2299
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
2300
|
+
return;
|
|
2301
|
+
}
|
|
2302
|
+
|
|
2303
|
+
console.log(chalk.blue('Studio intake'));
|
|
2304
|
+
console.log(` Scene: ${payload.scene_id || 'n/a'}`);
|
|
2305
|
+
console.log(` Goal: ${payload.goal || '(empty)'}`);
|
|
2306
|
+
console.log(` Intent: ${payload.intent && payload.intent.intent_type ? payload.intent.intent_type : 'unknown'}`);
|
|
2307
|
+
console.log(` Decision: ${payload.decision && payload.decision.action ? payload.decision.action : 'none'}`);
|
|
2308
|
+
console.log(` Spec: ${payload.selected_spec_id || 'n/a'}`);
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
async function runStudioIntakeCommand(options = {}, dependencies = {}) {
|
|
2312
|
+
const projectPath = dependencies.projectPath || process.cwd();
|
|
2313
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
2314
|
+
const sceneId = normalizeString(options.scene);
|
|
2315
|
+
const fromChat = normalizeString(options.fromChat);
|
|
2316
|
+
const goal = normalizeString(options.goal);
|
|
2317
|
+
const specId = normalizeString(options.spec);
|
|
2318
|
+
|
|
2319
|
+
if (!sceneId) {
|
|
2320
|
+
throw new Error('--scene is required');
|
|
2321
|
+
}
|
|
2322
|
+
if (!fromChat) {
|
|
2323
|
+
throw new Error('--from-chat is required');
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2326
|
+
const domainChainBinding = await resolveDomainChainBinding({
|
|
2327
|
+
sceneId,
|
|
2328
|
+
specId,
|
|
2329
|
+
goal
|
|
2330
|
+
}, {
|
|
2331
|
+
projectPath,
|
|
2332
|
+
fileSystem
|
|
2333
|
+
});
|
|
2334
|
+
|
|
2335
|
+
const relatedSpecLookup = await findRelatedSpecs({
|
|
2336
|
+
query: goal,
|
|
2337
|
+
sceneId,
|
|
2338
|
+
limit: 8,
|
|
2339
|
+
excludeSpecId: domainChainBinding.spec_id || specId || null
|
|
2340
|
+
}, {
|
|
2341
|
+
projectPath,
|
|
2342
|
+
fileSystem
|
|
2343
|
+
});
|
|
2344
|
+
|
|
2345
|
+
const intake = await runStudioAutoIntake({
|
|
2346
|
+
scene_id: sceneId,
|
|
2347
|
+
from_chat: fromChat,
|
|
2348
|
+
goal,
|
|
2349
|
+
explicit_spec_id: specId,
|
|
2350
|
+
domain_chain_binding: domainChainBinding,
|
|
2351
|
+
related_specs: relatedSpecLookup,
|
|
2352
|
+
apply: options.apply === true,
|
|
2353
|
+
skip: options.manualSpec === true
|
|
2354
|
+
}, {
|
|
2355
|
+
projectPath,
|
|
2356
|
+
fileSystem
|
|
2357
|
+
});
|
|
2358
|
+
|
|
2359
|
+
const payload = {
|
|
2360
|
+
...intake,
|
|
2361
|
+
domain_chain_source: domainChainBinding.source || 'none',
|
|
2362
|
+
domain_chain_spec_id: domainChainBinding.spec_id || null,
|
|
2363
|
+
related_specs_total: Number(relatedSpecLookup.total_candidates || 0)
|
|
2364
|
+
};
|
|
2365
|
+
printStudioIntakePayload(payload, options);
|
|
2366
|
+
return payload;
|
|
2367
|
+
}
|
|
2368
|
+
|
|
2369
|
+
function printStudioPortfolioPayload(payload, options = {}) {
|
|
2370
|
+
if (options.json) {
|
|
2371
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
2372
|
+
return;
|
|
2373
|
+
}
|
|
2374
|
+
const summary = payload.summary || {};
|
|
2375
|
+
console.log(chalk.blue('Studio portfolio governance'));
|
|
2376
|
+
console.log(` Status: ${summary.status || 'unknown'}`);
|
|
2377
|
+
console.log(` Scenes: ${summary.scene_count || 0}`);
|
|
2378
|
+
console.log(` Specs: ${summary.total_specs || 0}`);
|
|
2379
|
+
console.log(` Active: ${summary.active_specs || 0}`);
|
|
2380
|
+
console.log(` Completed: ${summary.completed_specs || 0}`);
|
|
2381
|
+
console.log(` Stale: ${summary.stale_specs || 0}`);
|
|
2382
|
+
console.log(` Duplicate pairs: ${summary.duplicate_pairs || 0}`);
|
|
2383
|
+
console.log(` Overflow scenes: ${summary.overflow_scenes || 0}`);
|
|
2384
|
+
}
|
|
2385
|
+
|
|
2386
|
+
async function runStudioPortfolioCommand(options = {}, dependencies = {}) {
|
|
2387
|
+
const projectPath = dependencies.projectPath || process.cwd();
|
|
2388
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
2389
|
+
const payload = await runStudioSpecGovernance({
|
|
2390
|
+
scene: normalizeString(options.scene),
|
|
2391
|
+
apply: options.apply !== false
|
|
2392
|
+
}, {
|
|
2393
|
+
projectPath,
|
|
2394
|
+
fileSystem
|
|
2395
|
+
});
|
|
2396
|
+
|
|
2397
|
+
if (options.strict && payload.summary && Number(payload.summary.alert_count || 0) > 0) {
|
|
2398
|
+
throw new Error(
|
|
2399
|
+
`studio portfolio governance has alerts: ${payload.summary.alert_count} (duplicate/stale/overflow)`
|
|
2400
|
+
);
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2403
|
+
printStudioPortfolioPayload(payload, options);
|
|
2404
|
+
return payload;
|
|
2405
|
+
}
|
|
2406
|
+
|
|
2181
2407
|
async function runStudioCommand(handler, options, stageName = '') {
|
|
2182
2408
|
try {
|
|
2183
2409
|
const stage = normalizeString(stageName) || 'unknown';
|
|
@@ -2221,11 +2447,34 @@ function registerStudioCommands(program) {
|
|
|
2221
2447
|
.requiredOption('--from-chat <session>', 'Chat session identifier or transcript reference')
|
|
2222
2448
|
.option('--spec <spec-id>', 'Optional spec binding for domain-chain context ingestion')
|
|
2223
2449
|
.option('--goal <goal>', 'Optional goal summary')
|
|
2450
|
+
.option('--manual-spec', 'Disable auto intake and only use explicit --spec or existing scene binding')
|
|
2224
2451
|
.option('--target <target>', 'Target integration profile', 'default')
|
|
2452
|
+
.option('--no-spec-governance', 'Skip auto portfolio governance snapshot on plan stage')
|
|
2225
2453
|
.option('--job <job-id>', 'Reuse an explicit studio job id')
|
|
2226
2454
|
.option('--json', 'Print machine-readable JSON output')
|
|
2227
2455
|
.action(async (options) => runStudioCommand(runStudioPlanCommand, options, 'plan'));
|
|
2228
2456
|
|
|
2457
|
+
studio
|
|
2458
|
+
.command('intake')
|
|
2459
|
+
.description('Analyze chat goal and auto-resolve spec binding/create decision')
|
|
2460
|
+
.requiredOption('--scene <scene-id>', 'Scene identifier')
|
|
2461
|
+
.requiredOption('--from-chat <session>', 'Chat session identifier or transcript reference')
|
|
2462
|
+
.option('--spec <spec-id>', 'Optional explicit spec id')
|
|
2463
|
+
.option('--goal <goal>', 'Goal text used for intent classification')
|
|
2464
|
+
.option('--apply', 'Create spec when decision is create_spec')
|
|
2465
|
+
.option('--manual-spec', 'Disable auto intake and keep explicit/manual binding only')
|
|
2466
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
2467
|
+
.action(async (options) => runStudioCommand(runStudioIntakeCommand, options, 'intake'));
|
|
2468
|
+
|
|
2469
|
+
studio
|
|
2470
|
+
.command('portfolio')
|
|
2471
|
+
.description('Build scene-organized spec governance portfolio')
|
|
2472
|
+
.option('--scene <scene-id>', 'Optional scene filter')
|
|
2473
|
+
.option('--no-apply', 'Do not write portfolio/index artifacts to .sce/spec-governance/')
|
|
2474
|
+
.option('--strict', 'Fail when governance alerts are detected')
|
|
2475
|
+
.option('--json', 'Print machine-readable JSON output')
|
|
2476
|
+
.action(async (options) => runStudioCommand(runStudioPortfolioCommand, options, 'portfolio'));
|
|
2477
|
+
|
|
2229
2478
|
studio
|
|
2230
2479
|
.command('generate')
|
|
2231
2480
|
.description('Generate patch bundle metadata for a planned studio job (scene inherited from plan)')
|
|
@@ -2310,12 +2559,14 @@ module.exports = {
|
|
|
2310
2559
|
resolveNextAction,
|
|
2311
2560
|
buildProgress,
|
|
2312
2561
|
runStudioPlanCommand,
|
|
2562
|
+
runStudioIntakeCommand,
|
|
2313
2563
|
runStudioGenerateCommand,
|
|
2314
2564
|
runStudioApplyCommand,
|
|
2315
2565
|
runStudioVerifyCommand,
|
|
2316
2566
|
runStudioReleaseCommand,
|
|
2317
2567
|
runStudioRollbackCommand,
|
|
2318
2568
|
runStudioEventsCommand,
|
|
2569
|
+
runStudioPortfolioCommand,
|
|
2319
2570
|
runStudioResumeCommand,
|
|
2320
2571
|
registerStudioCommands
|
|
2321
2572
|
};
|