scene-capability-engine 3.6.51 → 3.6.53

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 CHANGED
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.6.53] - 2026-03-16
11
+
12
+ ### Added
13
+ - Added a tracked project-shared high-value errorbook projection at `.sce/knowledge/errorbook/project-shared-registry.json`, seeded by default in template/takeover baselines so same-project work on another computer can recover curated `verified` and `promoted` knowledge through Git without committing raw `.sce/errorbook/**`.
14
+
15
+ ### Changed
16
+ - Errorbook mutation commands now auto-refresh the tracked project-shared projection, and registry-inclusive lookup can search that local file in `remote` mode without requiring an index.
17
+ - Co-work governance auditing now treats the project-shared errorbook projection as a required closure artifact: config must stay enabled, the project-shared source must exist, the projection file must parse, and it must be Git-tracked.
18
+
19
+ ## [3.6.52] - 2026-03-16
20
+
21
+ ### Added
22
+ - Added `sce app runtime uninstall` with active-release protection, explicit installed-vs-active runtime projection fields, and MagicBall-facing runtime uninstall/auth documentation.
23
+ - Extended co-work governance auditing so shared `errorbook` registry baseline and managed `errorbook_convergence` defaults are now checked alongside multi-agent/runtime-state drift.
24
+
10
25
  ## [3.6.51] - 2026-03-15
11
26
 
12
27
  ### Changed
package/README.md CHANGED
@@ -165,7 +165,7 @@ MagicBall-specific integration surfaces now also include:
165
165
 
166
166
  - `sce app bundle list|show|register`
167
167
  - `sce app registry status|configure|sync*`
168
- - `sce app runtime show|releases|install|activate`
168
+ - `sce app runtime show|releases|install|activate|uninstall`
169
169
  - `sce app engineering show|attach|hydrate|activate`
170
170
  - `sce mode application|ontology|engineering home`
171
171
  - `sce pm requirement|tracking|planning|change|issue ... --json`
@@ -218,5 +218,5 @@ MIT. See [LICENSE](LICENSE).
218
218
 
219
219
  ---
220
220
 
221
- **Version**: 3.6.51
222
- **Last Updated**: 2026-03-15
221
+ **Version**: 3.6.53
222
+ **Last Updated**: 2026-03-16
package/README.zh.md CHANGED
@@ -170,7 +170,7 @@ SCE 默认是强治理的。
170
170
 
171
171
  - `sce app bundle list|show|register`
172
172
  - `sce app registry status|configure|sync*`
173
- - `sce app runtime show|releases|install|activate`
173
+ - `sce app runtime show|releases|install|activate|uninstall`
174
174
  - `sce app engineering show|attach|hydrate|activate`
175
175
  - `sce mode application|ontology|engineering home`
176
176
  - `sce pm requirement|tracking|planning|change|issue ... --json`
@@ -223,5 +223,5 @@ MIT,见 [LICENSE](LICENSE)。
223
223
 
224
224
  ---
225
225
 
226
- **版本**:3.6.51
227
- **最后更新**:2026-03-15
226
+ **版本**:3.6.53
227
+ **最后更新**:2026-03-16
@@ -2,8 +2,8 @@
2
2
 
3
3
  > Quick reference for all `sce` commands
4
4
 
5
- **Version**: 3.6.51
6
- **Last Updated**: 2026-03-15
5
+ **Version**: 3.6.52
6
+ **Last Updated**: 2026-03-16
7
7
 
8
8
  ---
9
9
 
@@ -135,7 +135,7 @@ Timeline policy:
135
135
  - default enabled with local retention under `.sce/timeline/snapshots/`
136
136
  - stage/key-event checkpoints are automatically captured for `studio` and `session` commands
137
137
  - interval auto-checkpoints are integrated in the same flow via timeline checkpoint capture
138
- - `timeline push` now blocks before snapshot/push when collaboration governance drifts, so tracked runtime state, missing co-work ignore rules, legacy `.kiro*` references, invalid multi-agent config, or steering boundary drift cannot pass through managed push flow
138
+ - `timeline push` now blocks before snapshot/push when collaboration governance drifts, so tracked runtime state, missing co-work ignore rules, missing shared `errorbook` registry baseline, missing tracked project-shared errorbook projection, invalid multi-agent config, legacy `.kiro*` references, or steering boundary drift cannot pass through managed push flow
139
139
 
140
140
  ### Value Metrics
141
141
 
@@ -348,7 +348,7 @@ sce workspace legacy-migrate --dry-run --json
348
348
  sce workspace tracking-audit
349
349
  sce workspace tracking-audit --json
350
350
 
351
- # Audit collaboration governance boundaries and legacy naming drift
351
+ # Audit collaboration governance boundaries, shared errorbook closure, and legacy naming drift
352
352
  sce workspace collab-governance-audit
353
353
  sce workspace collab-governance-audit --json
354
354
  sce workspace collab-governance-audit --strict
@@ -393,6 +393,7 @@ sce app runtime show --app customer-order-demo --json
393
393
  sce app runtime releases --app customer-order-demo --json
394
394
  sce app runtime install --app customer-order-demo --release <release-id> --json
395
395
  sce app runtime activate --app customer-order-demo --release <release-id> --json
396
+ sce app runtime uninstall --app customer-order-demo --release <release-id> --json
396
397
 
397
398
  # Engineering projection
398
399
  sce app engineering show --app customer-order-demo --json
@@ -637,8 +638,10 @@ Curated quality policy (`宁缺毋滥,优胜略汰`) defaults:
637
638
  - missing exit/cleanup/deadline metadata
638
639
  - expired mitigation deadline
639
640
  - `export` outputs a machine-readable registry bundle from curated local entries (recommended default: `promoted`, `quality>=75`).
641
+ - managed same-project sharing now uses a tracked projection file at `.sce/knowledge/errorbook/project-shared-registry.json`, refreshed automatically after `record`, `promote`, `deprecate`, and `requalify`
640
642
  - `sync-registry` pulls external registry JSON into local cache (`.sce/errorbook/registry-cache.json`) for unified `find` retrieval.
641
643
  - `find --include-registry --registry-mode remote` supports direct remote query for large registries (no full local sync required).
644
+ - registry-inclusive lookup can also search the tracked project-shared local file in `remote` mode without a shard index.
642
645
  - Recommended for large registries: maintain a remote index file (`registry/errorbook-registry.index.json`) and shard files, then provide `index_url` in registry config.
643
646
  - Since `v3.3.23`, `sce init` / `sce adopt` default baseline includes enabled central registry config in `.sce/config/errorbook-registry.json`.
644
647
  - `health-registry` validates config readability, source/index accessibility, and index-to-shard resolution before release.
@@ -72,12 +72,23 @@ Create `.sce/config/errorbook-registry.json`:
72
72
  "enabled": true,
73
73
  "search_mode": "remote",
74
74
  "cache_file": ".sce/errorbook/registry-cache.json",
75
+ "project_shared_projection": {
76
+ "enabled": true,
77
+ "file": ".sce/knowledge/errorbook/project-shared-registry.json",
78
+ "statuses": ["verified", "promoted"],
79
+ "min_quality": 75
80
+ },
75
81
  "sources": [
76
82
  {
77
83
  "name": "central",
78
84
  "enabled": true,
79
85
  "url": "https://raw.githubusercontent.com/heguangyong/sce-errorbook-registry/main/registry/errorbook-registry.json",
80
86
  "index_url": "https://raw.githubusercontent.com/heguangyong/sce-errorbook-registry/main/registry/errorbook-registry.index.json"
87
+ },
88
+ {
89
+ "name": "project-shared",
90
+ "enabled": true,
91
+ "file": ".sce/knowledge/errorbook/project-shared-registry.json"
81
92
  }
82
93
  ]
83
94
  }
@@ -87,23 +98,30 @@ Notes:
87
98
  - `url` must be a raw JSON URL (`raw.githubusercontent.com`) or use a local file path.
88
99
  - `search_mode` supports `cache|remote|hybrid` (recommended: `remote` for very large registries).
89
100
  - Local cache file is used by cache/hybrid mode.
90
- - Since `v3.3.23`, `sce init` / `sce adopt` template baselines include this config by default (central source enabled).
101
+ - `project_shared_projection` is the Git-tracked same-project sharing path used for cross-computer co-work continuity.
102
+ - Since `v3.3.23`, `sce init` / `sce adopt` template baselines include registry config by default; current baseline also seeds the tracked project-shared projection file.
91
103
 
92
104
  ## 4) Daily Workflow
93
105
 
94
- 1. Export curated local entries:
106
+ 1. Keep project-shared same-project knowledge current:
107
+ ```bash
108
+ # SCE refreshes this automatically after record/promote/deprecate/requalify
109
+ .sce/knowledge/errorbook/project-shared-registry.json
110
+ ```
111
+
112
+ 2. Export curated local entries for central cross-project publication:
95
113
  ```bash
96
114
  sce errorbook export --status promoted --min-quality 75 --out .sce/errorbook/exports/registry.json --json
97
115
  ```
98
116
 
99
- 2. Merge approved entries into central repo `registry/errorbook-registry.json`.
117
+ 3. Merge approved entries into central repo `registry/errorbook-registry.json`.
100
118
 
101
- 3. Sync central registry into local cache:
119
+ 4. Sync central registry into local cache:
102
120
  ```bash
103
121
  sce errorbook sync-registry --source https://raw.githubusercontent.com/heguangyong/sce-errorbook-registry/main/registry/errorbook-registry.json --json
104
122
  ```
105
123
 
106
- 4. Search local + shared entries:
124
+ 5. Search local + shared entries:
107
125
  ```bash
108
126
  sce errorbook find --query "approve order timeout" --include-registry --json
109
127
  sce errorbook find --query "approve order timeout" --include-registry --registry-mode remote --json
@@ -116,6 +134,7 @@ SCE_REGISTRY_HEALTH_STRICT=1 node scripts/errorbook-registry-health-gate.js --js
116
134
 
117
135
  ## 5) Governance Rules
118
136
 
137
+ - Same-project co-work should rely on the tracked project-shared projection instead of committing raw `.sce/errorbook/**`.
119
138
  - Publish to central registry only curated entries (recommended: `status=promoted` and `quality>=75`).
120
139
  - Do not publish sensitive tenant/customer data.
121
140
  - Temporary mitigation entries must remain bounded and governed (exit criteria, cleanup task, deadline).
@@ -70,6 +70,8 @@ Important fields:
70
70
  - `summary.app_name`
71
71
  - `summary.runtime_version`
72
72
  - `summary.install_status`
73
+ - `summary.installed_release_id`
74
+ - `summary.active_release_id`
73
75
  - `summary.release_count`
74
76
  - `view_model.current_release`
75
77
  - `view_model.entrypoint`
@@ -84,6 +86,7 @@ sce app runtime releases --app customer-order-demo --json
84
86
  Expected UI:
85
87
  - release table/list
86
88
  - active/default release marker
89
+ - installed marker
87
90
  - runtime version
88
91
  - release status
89
92
  - entrypoint
@@ -113,6 +116,19 @@ Done when:
113
116
  - active release changes in UI
114
117
  - `mode application home` reflects the new active release after refresh
115
118
 
119
+ ### Task 2.5
120
+ Wire uninstall action for installed-but-not-active release.
121
+
122
+ Command:
123
+ ```bash
124
+ sce app runtime uninstall --app customer-order-demo --release <release-id> --json
125
+ ```
126
+
127
+ Done when:
128
+ - uninstall button is shown only for installed and non-active release
129
+ - uninstall removes local installed state after refresh
130
+ - the same release can be installed again through existing install flow
131
+
116
132
  ## Phase 3: Ontology Mode
117
133
 
118
134
  ### Task 3.1
@@ -288,6 +304,7 @@ Commands that matter now:
288
304
  - `sce app engineering activate`
289
305
  - `sce app runtime install`
290
306
  - `sce app runtime activate`
307
+ - `sce app runtime uninstall`
291
308
  - `sce pm * upsert`
292
309
  - `sce ontology * upsert`
293
310
 
@@ -371,7 +388,7 @@ MagicBall can be considered adapted to the current SCE version when:
371
388
  4. Ontology Mode reads `sce ontology *`
372
389
  5. Assurance tabs read `sce assurance *`
373
390
  6. write actions pass `--auth-lease`
374
- 7. install / activate / attach / hydrate actions work from the UI
391
+ 7. install / activate / uninstall / attach / hydrate actions work from the UI
375
392
 
376
393
  ## Practical Conclusion
377
394
 
@@ -55,6 +55,8 @@ Typical fields MagicBall cares about:
55
55
  - `summary.app_name`
56
56
  - `summary.runtime_version`
57
57
  - `summary.install_status`
58
+ - `summary.installed_release_id`
59
+ - `summary.active_release_id`
58
60
  - `summary.release_count`
59
61
  - `view_model.current_release`
60
62
 
@@ -73,6 +75,11 @@ sce app runtime install --app customer-order-demo --release rel-2026-03 --json
73
75
  sce app runtime activate --app customer-order-demo --release rel-2026-03 --json
74
76
  ```
75
77
 
78
+ ### 2.5 Uninstall a non-active installed release
79
+ ```bash
80
+ sce app runtime uninstall --app customer-order-demo --release rel-2026-03 --json
81
+ ```
82
+
76
83
  ## 3. Ontology Mode Examples
77
84
 
78
85
  ### 3.1 Read ontology home
@@ -22,7 +22,7 @@ SCE changes completed and now available for MagicBall:
22
22
  - `mode ontology home --app ... --json`
23
23
  - `mode engineering home --app ... --json`
24
24
  - `app registry status/configure/sync*`
25
- - `app runtime show/releases/install/activate`
25
+ - `app runtime show/releases/install/activate/uninstall`
26
26
  - `app engineering show/attach/hydrate/activate`
27
27
  - `pm requirement/tracking/planning/change/issue` data plane
28
28
  - `ontology er/br/dl` + `ontology triad summary`
@@ -33,7 +33,7 @@ SCE changes completed and now available for MagicBall:
33
33
  ### Current recommended MagicBall consumption order
34
34
  1. consume `mode * home` as the top-level source for the three modes
35
35
  2. consume `pm`, `ontology`, and `assurance` table payloads
36
- 3. wire runtime install/activate and engineering attach/hydrate/activate actions
36
+ 3. wire runtime install/activate/uninstall and engineering attach/hydrate/activate actions
37
37
  4. use demo app: `customer-order-demo`
38
38
 
39
39
  ### Related SCE docs
@@ -25,7 +25,7 @@ Use these documents together:
25
25
  SCE currently provides MagicBall-facing support for:
26
26
  1. `app bundle registry`
27
27
  2. `application / ontology / engineering home projections`
28
- 3. `app runtime install / activate`
28
+ 3. `app runtime install / activate / uninstall`
29
29
  4. `app engineering attach / hydrate / activate`
30
30
  5. `pm` delivery data plane
31
31
  6. `ontology` triad data plane
@@ -100,7 +100,7 @@ Use `docs/magicball-cli-invocation-examples.md` for copy-ready commands.
100
100
  - `sce app engineering show`
101
101
 
102
102
  ### Runtime and engineering control
103
- - `sce app runtime show/releases/install/activate`
103
+ - `sce app runtime show/releases/install/activate/uninstall`
104
104
  - `sce app engineering show/attach/hydrate/activate`
105
105
  - `sce app registry status/configure/sync*`
106
106
 
@@ -67,6 +67,7 @@ Current implemented write flows in SCE imply these practical action families:
67
67
  - `app:engineering:activate`
68
68
  - `app:runtime:install`
69
69
  - `app:runtime:activate`
70
+ - `app:runtime:uninstall`
70
71
 
71
72
  ### Engineering mode PM data plane
72
73
  - `pm:requirement:upsert`
@@ -176,6 +177,7 @@ Recommended UI steps:
176
177
  | Activate engineering workspace | `sce app engineering activate` | `app:engineering:activate` |
177
178
  | Install runtime release | `sce app runtime install` | `app:runtime:install` |
178
179
  | Activate runtime release | `sce app runtime activate` | `app:runtime:activate` |
180
+ | Uninstall runtime release | `sce app runtime uninstall` | `app:runtime:uninstall` |
179
181
  | Save requirement | `sce pm requirement upsert` | `pm:requirement:upsert` |
180
182
  | Save tracking item | `sce pm tracking upsert` | `pm:tracking:upsert` |
181
183
  | Save plan | `sce pm planning upsert` | `pm:planning:upsert` |
@@ -196,6 +198,11 @@ Recommended UI steps:
196
198
  sce auth grant --scope app:runtime:activate --reason "activate selected runtime release" --json
197
199
  ```
198
200
 
201
+ ### Runtime uninstall lease
202
+ ```bash
203
+ sce auth grant --scope app:runtime:uninstall --reason "remove non-active installed runtime release" --json
204
+ ```
205
+
199
206
  ### Multiple scopes if one workflow batches mutations
200
207
  ```bash
201
208
  sce auth grant --scope app:engineering:attach,app:engineering:hydrate,app:engineering:activate --reason "initialize engineering workspace" --json
@@ -2,8 +2,8 @@
2
2
 
3
3
  > Enable multiple AI agents to work on the same sce project simultaneously without conflicts.
4
4
 
5
- **Version**: 3.6.51
6
- **Last Updated**: 2026-03-15
5
+ **Version**: 3.6.52
6
+ **Last Updated**: 2026-03-16
7
7
 
8
8
  ---
9
9
 
@@ -0,0 +1,20 @@
1
+ # v3.6.52 Release Notes
2
+
3
+ Release date: 2026-03-16
4
+
5
+ ## Highlights
6
+
7
+ - Added `sce app runtime uninstall` so MagicBall and CLI users can remove a non-active installed runtime release without editing local SCE state by hand.
8
+ - Split runtime projection semantics so installed release and active release are exposed separately in runtime/app-home payloads.
9
+ - Extended co-work governance auditing to enforce shared `errorbook` registry availability and managed `errorbook_convergence` defaults as part of the default collaboration baseline.
10
+
11
+ ## Validation
12
+
13
+ - `npx jest tests/unit/commands/app-mode.test.js --runInBand`
14
+ - `npx jest tests/unit/workspace/collab-governance-audit.test.js tests/unit/scripts/collab-governance-gate.test.js --runInBand`
15
+ - `node scripts/collab-governance-gate.js --json`
16
+
17
+ ## Release Notes
18
+
19
+ - This patch closes two integration gaps: MagicBall can now offer uninstall/reinstall flows cleanly, and co-work governance now treats shared failure-learning resources as a real default baseline instead of a merely available optional capability.
20
+ - The runtime model is still a single-installation-slot design; multiple release selection is supported, but multiple local installed runtime versions per app are not introduced in this patch.
@@ -0,0 +1,19 @@
1
+ # v3.6.53 Release Notes
2
+
3
+ Release date: 2026-03-16
4
+
5
+ ## Highlights
6
+
7
+ - Closed the co-work loop for same-project high-value `errorbook` knowledge by adding a tracked shared projection at `.sce/knowledge/errorbook/project-shared-registry.json`.
8
+ - Baseline/template projects now seed the shared projection source by default, so another computer can recover historical specs and curated project errorbook knowledge after normal Git sync.
9
+ - Collaboration governance now blocks managed push/publish when the shared project errorbook projection is missing, disabled, invalid, or not Git-tracked.
10
+
11
+ ## Validation
12
+
13
+ - `npx jest tests/unit/commands/errorbook.test.js tests/unit/workspace/takeover-baseline.test.js tests/unit/workspace/collab-governance-audit.test.js tests/integration/takeover-baseline-cli.integration.test.js --runInBand`
14
+ - `node scripts/release-doc-version-audit.js --fail-on-error`
15
+ - `node scripts/collab-governance-gate.js --fail-on-violation --json`
16
+
17
+ ## Release Notes
18
+
19
+ - This patch turns “shared errorbook experience” from a config-level promise into a real same-project continuity path. Historical specs stay Git-shared as before, while high-value `verified/promoted` errorbook knowledge now has a dedicated tracked projection instead of leaking raw `.sce/errorbook/**` runtime state into version control.
@@ -0,0 +1,20 @@
1
+ # v3.6.52 发布说明
2
+
3
+ 发布日期:2026-03-16
4
+
5
+ ## 重点变化
6
+
7
+ - 新增 `sce app runtime uninstall`,MagicBall 和 CLI 现在都可以在不手改本地状态的前提下卸载“已安装但未激活”的运行时版本。
8
+ - 运行时投影语义已拆分为“已安装版本”和“当前激活版本”,前端不再需要自行猜测 installed / active 状态。
9
+ - co-work 治理审计已扩展为默认检查共享 `errorbook` registry 是否可用,以及 managed 项目的 `errorbook_convergence` 基线是否漂移。
10
+
11
+ ## 验证
12
+
13
+ - `npx jest tests/unit/commands/app-mode.test.js --runInBand`
14
+ - `npx jest tests/unit/workspace/collab-governance-audit.test.js tests/unit/scripts/collab-governance-gate.test.js --runInBand`
15
+ - `node scripts/collab-governance-gate.js --json`
16
+
17
+ ## 发布说明
18
+
19
+ - 这个补丁版补上了两个真实缺口:一是 MagicBall 运行时版本管理终于具备卸载/重装闭环,二是 co-work 默认协作基线开始真正把共享错题经验资源视为必备能力,而不是“仓库里有这个功能就算支持”。
20
+ - 当前运行时仍然是“单安装槽位”模型;本次支持多版本选择,但不引入同一 app 多个本地安装版本并存。
@@ -0,0 +1,19 @@
1
+ # v3.6.53 发布说明
2
+
3
+ 发布日期:2026-03-16
4
+
5
+ ## 重点变化
6
+
7
+ - 补齐了同一项目 co-work 下高价值 `errorbook` 经验的闭环,新增 Git 跟踪投影文件 `.sce/knowledge/errorbook/project-shared-registry.json`。
8
+ - baseline / template 现在默认带上这个共享投影源,另一台电脑正常 `git pull` 后即可同时拿到历史 spec 和项目级高价值错题经验。
9
+ - 协作治理现在会阻断缺失、禁用、损坏或未纳入 Git 跟踪的项目共享错题投影,避免“能力存在但默认不生效”。
10
+
11
+ ## 验证
12
+
13
+ - `npx jest tests/unit/commands/errorbook.test.js tests/unit/workspace/takeover-baseline.test.js tests/unit/workspace/collab-governance-audit.test.js tests/integration/takeover-baseline-cli.integration.test.js --runInBand`
14
+ - `node scripts/release-doc-version-audit.js --fail-on-error`
15
+ - `node scripts/collab-governance-gate.js --fail-on-violation --json`
16
+
17
+ ## 发布说明
18
+
19
+ - 这个补丁版把“共享错题经验”从配置层能力补成了真正可落地的同项目跨电脑延续机制。历史 spec 仍按原方式走 Git 共享,而高价值 `verified/promoted` 错题经验则通过单独的受控投影文件同步,不再把 `.sce/errorbook/**` 运行态数据直接带入版本库。
@@ -89,17 +89,77 @@ function buildBundleSummary(graph = {}) {
89
89
  };
90
90
  }
91
91
 
92
- function buildRuntimeSummary(graph = {}) {
92
+ function getRuntimeProjectionState(graph = {}) {
93
93
  const bundle = graph.bundle || {};
94
94
  const runtimeRelease = graph.runtime_release || {};
95
95
  const metadata = bundle.metadata && typeof bundle.metadata === 'object' ? bundle.metadata : {};
96
96
  const installation = metadata.runtime_installation && typeof metadata.runtime_installation === 'object'
97
97
  ? metadata.runtime_installation
98
98
  : {};
99
+ const runtimeActivation = metadata.runtime_activation && typeof metadata.runtime_activation === 'object'
100
+ ? metadata.runtime_activation
101
+ : {};
99
102
  const serviceCatalog = metadata.service_catalog && typeof metadata.service_catalog === 'object'
100
103
  ? metadata.service_catalog
101
104
  : {};
102
105
  const releases = Array.isArray(serviceCatalog.releases) ? serviceCatalog.releases : [];
106
+ const installStatus = normalizeString(installation.status) || 'not-installed';
107
+ const installedReleaseId = installStatus === 'installed'
108
+ ? (normalizeString(installation.release_id) || null)
109
+ : null;
110
+ const activeReleaseId = normalizeString(
111
+ bundle.runtime_release_id
112
+ || runtimeRelease.release_id
113
+ || runtimeActivation.active_release_id
114
+ ) || null;
115
+
116
+ return {
117
+ metadata,
118
+ installation,
119
+ runtimeActivation,
120
+ serviceCatalog,
121
+ releases,
122
+ installStatus,
123
+ installedReleaseId,
124
+ activeReleaseId
125
+ };
126
+ }
127
+
128
+ function buildRuntimeReleaseItems(graph = {}) {
129
+ const state = getRuntimeProjectionState(graph);
130
+ return state.releases.map((item) => {
131
+ const releaseId = normalizeString(item && item.release_id) || null;
132
+ const installed = Boolean(releaseId && state.installedReleaseId && releaseId === state.installedReleaseId);
133
+ const active = Boolean(releaseId && state.activeReleaseId && releaseId === state.activeReleaseId);
134
+ const availableActions = [];
135
+
136
+ if (!installed) {
137
+ availableActions.push('install');
138
+ }
139
+ if (!active) {
140
+ availableActions.push('activate');
141
+ }
142
+ if (installed && !active) {
143
+ availableActions.push('uninstall');
144
+ }
145
+
146
+ return {
147
+ ...item,
148
+ installed,
149
+ active,
150
+ installation_status: installed ? state.installStatus : 'not-installed',
151
+ can_install: !installed,
152
+ can_activate: !active,
153
+ can_uninstall: installed && !active,
154
+ available_actions: availableActions
155
+ };
156
+ });
157
+ }
158
+
159
+ function buildRuntimeSummary(graph = {}) {
160
+ const bundle = graph.bundle || {};
161
+ const runtimeRelease = graph.runtime_release || {};
162
+ const state = getRuntimeProjectionState(graph);
103
163
  return {
104
164
  app_id: bundle.app_id || null,
105
165
  app_name: bundle.app_name || null,
@@ -107,10 +167,11 @@ function buildRuntimeSummary(graph = {}) {
107
167
  runtime_version: runtimeRelease.runtime_version || null,
108
168
  release_status: runtimeRelease.release_status || null,
109
169
  runtime_status: runtimeRelease.runtime_status || null,
110
- install_status: installation.status || 'not-installed',
111
- install_root: installation.install_root || null,
112
- release_count: releases.length,
113
- active_release_id: installation.release_id || bundle.runtime_release_id || runtimeRelease.release_id || null
170
+ install_status: state.installStatus,
171
+ install_root: state.installation.install_root || null,
172
+ release_count: state.releases.length,
173
+ installed_release_id: state.installedReleaseId,
174
+ active_release_id: state.activeReleaseId
114
175
  };
115
176
  }
116
177
 
@@ -564,8 +625,7 @@ async function runAppRuntimeShowCommand(options = {}, dependencies = {}) {
564
625
  throw new Error('--app is required');
565
626
  }
566
627
  const { graph } = await requireAppGraph(appRef, dependencies);
567
- const metadata = graph.bundle && graph.bundle.metadata && typeof graph.bundle.metadata === 'object' ? graph.bundle.metadata : {};
568
- const serviceCatalog = metadata.service_catalog && typeof metadata.service_catalog === 'object' ? metadata.service_catalog : {};
628
+ const state = getRuntimeProjectionState(graph);
569
629
  const payload = {
570
630
  mode: 'app-runtime-show',
571
631
  generated_at: new Date().toISOString(),
@@ -575,12 +635,14 @@ async function runAppRuntimeShowCommand(options = {}, dependencies = {}) {
575
635
  summary: buildRuntimeSummary(graph),
576
636
  bundle: graph.bundle,
577
637
  runtime_release: graph.runtime_release,
578
- runtime_installation: metadata.runtime_installation || null,
638
+ runtime_installation: Object.keys(state.installation).length > 0 ? state.installation : null,
639
+ runtime_activation: Object.keys(state.runtimeActivation).length > 0 ? state.runtimeActivation : null,
579
640
  service_catalog: {
580
- default_release_id: serviceCatalog.default_release_id || null,
581
- release_count: Array.isArray(serviceCatalog.releases) ? serviceCatalog.releases.length : 0,
582
- source: serviceCatalog.source || null
583
- }
641
+ default_release_id: state.serviceCatalog.default_release_id || null,
642
+ release_count: state.releases.length,
643
+ source: state.serviceCatalog.source || null
644
+ },
645
+ releases: buildRuntimeReleaseItems(graph)
584
646
  };
585
647
  printPayload(payload, options, 'App Runtime Show');
586
648
  return payload;
@@ -592,9 +654,8 @@ async function runAppRuntimeReleasesCommand(options = {}, dependencies = {}) {
592
654
  throw new Error('--app is required');
593
655
  }
594
656
  const { graph } = await requireAppGraph(appRef, dependencies);
595
- const metadata = graph.bundle && graph.bundle.metadata && typeof graph.bundle.metadata === 'object' ? graph.bundle.metadata : {};
596
- const serviceCatalog = metadata.service_catalog && typeof metadata.service_catalog === 'object' ? metadata.service_catalog : {};
597
- const releases = Array.isArray(serviceCatalog.releases) ? serviceCatalog.releases : [];
657
+ const state = getRuntimeProjectionState(graph);
658
+ const releases = buildRuntimeReleaseItems(graph);
598
659
  const payload = {
599
660
  mode: 'app-runtime-releases',
600
661
  generated_at: new Date().toISOString(),
@@ -603,12 +664,14 @@ async function runAppRuntimeReleasesCommand(options = {}, dependencies = {}) {
603
664
  },
604
665
  summary: {
605
666
  total: releases.length,
606
- default_release_id: serviceCatalog.default_release_id || null
667
+ default_release_id: state.serviceCatalog.default_release_id || null,
668
+ installed_release_id: state.installedReleaseId,
669
+ active_release_id: state.activeReleaseId
607
670
  },
608
671
  items: releases,
609
672
  view_model: {
610
673
  type: 'table',
611
- columns: ['release_id', 'runtime_version', 'release_channel', 'release_status', 'runtime_status', 'published_at']
674
+ columns: ['release_id', 'runtime_version', 'release_channel', 'release_status', 'runtime_status', 'installed', 'active', 'published_at']
612
675
  },
613
676
  mb_status: graph.runtime_release && graph.runtime_release.runtime_status ? graph.runtime_release.runtime_status : (graph.bundle && graph.bundle.status ? graph.bundle.status : 'unknown')
614
677
  };
@@ -704,6 +767,58 @@ async function runAppRuntimeActivateCommand(options = {}, dependencies = {}) {
704
767
  return payload;
705
768
  }
706
769
 
770
+ async function runAppRuntimeUninstallCommand(options = {}, dependencies = {}) {
771
+ const appRef = normalizeString(options.app);
772
+ if (!appRef) {
773
+ throw new Error('--app is required');
774
+ }
775
+ await ensureAuthorized('app:runtime:uninstall', options, dependencies);
776
+ const fileSystem = dependencies.fileSystem || fs;
777
+ const { store, graph } = await requireAppGraph(appRef, dependencies);
778
+ const nextPayload = graphToRegisterPayload(graph);
779
+ const state = getRuntimeProjectionState(graph);
780
+ const installedReleaseId = state.installedReleaseId;
781
+ const targetReleaseId = normalizeString(options.release) || installedReleaseId;
782
+
783
+ if (!installedReleaseId) {
784
+ throw new Error('no installed runtime release found for this app');
785
+ }
786
+ if (!targetReleaseId || targetReleaseId !== installedReleaseId) {
787
+ throw new Error(`runtime release is not installed: ${targetReleaseId || '<unknown>'}`);
788
+ }
789
+ if (state.activeReleaseId && targetReleaseId === state.activeReleaseId) {
790
+ throw new Error(`cannot uninstall active runtime release ${targetReleaseId}; activate another release first`);
791
+ }
792
+
793
+ const installRoot = normalizeString(state.installation.install_root);
794
+ if (installRoot) {
795
+ await fileSystem.remove(installRoot);
796
+ }
797
+
798
+ nextPayload.metadata = nextPayload.metadata || {};
799
+ nextPayload.metadata.runtime_installation = {
800
+ status: 'not-installed',
801
+ release_id: null,
802
+ install_root: null,
803
+ uninstalled_at: new Date().toISOString(),
804
+ source: 'sce app runtime uninstall',
805
+ previous_release_id: targetReleaseId
806
+ };
807
+
808
+ const updated = await store.registerAppBundle(nextPayload);
809
+ const updatedState = getRuntimeProjectionState(updated);
810
+ const payload = {
811
+ mode: 'app-runtime-uninstall',
812
+ success: true,
813
+ summary: buildRuntimeSummary(updated),
814
+ uninstalled_release_id: targetReleaseId,
815
+ removed_install_root: installRoot || null,
816
+ runtime_installation: updatedState.installation
817
+ };
818
+ printPayload(payload, options, 'App Runtime Uninstall');
819
+ return payload;
820
+ }
821
+
707
822
  function safeRun(handler, options = {}, context = 'app command') {
708
823
  Promise.resolve(handler(options))
709
824
  .catch((error) => {
@@ -839,6 +954,17 @@ function registerAppCommands(program) {
839
954
  .option('--json', 'Print machine-readable JSON output')
840
955
  .action((options) => safeRun(runAppRuntimeActivateCommand, options, 'app runtime activate'));
841
956
 
957
+ runtime
958
+ .command('uninstall')
959
+ .description('Uninstall runtime release for one app bundle')
960
+ .requiredOption('--app <app-id-or-key>', 'App id or app key')
961
+ .option('--release <release-id>', 'Installed runtime release id')
962
+ .option('--auth-lease <lease-id>', 'Write authorization lease id')
963
+ .option('--auth-password <password>', 'Inline auth password if policy allows')
964
+ .option('--actor <actor>', 'Audit actor override')
965
+ .option('--json', 'Print machine-readable JSON output')
966
+ .action((options) => safeRun(runAppRuntimeUninstallCommand, options, 'app runtime uninstall'));
967
+
842
968
  const engineering = app
843
969
  .command('engineering')
844
970
  .description('Manage engineering project projection for one app bundle');
@@ -903,6 +1029,7 @@ module.exports = {
903
1029
  runAppRuntimeReleasesCommand,
904
1030
  runAppRuntimeInstallCommand,
905
1031
  runAppRuntimeActivateCommand,
1032
+ runAppRuntimeUninstallCommand,
906
1033
  runAppEngineeringShowCommand,
907
1034
  runAppEngineeringAttachCommand,
908
1035
  runAppEngineeringHydrateCommand,