scene-capability-engine 3.6.32 → 3.6.37
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 +109 -11
- package/README.md +119 -122
- package/README.zh.md +123 -121
- package/bin/scene-capability-engine.js +12 -1
- package/docs/331-poc-adaptation-roadmap.md +3 -3
- package/docs/README.md +21 -32
- package/docs/auto-refactor-index.md +384 -0
- package/docs/command-reference.md +99 -7
- package/docs/faq.md +1 -1
- package/docs/interactive-customization/331-poc-sce-integration-checklist.md +3 -3
- package/docs/interactive-customization/moqui-interactive-template-playbook.md +4 -4
- package/docs/interactive-customization/phase-acceptance-evidence.md +2 -2
- package/docs/magicball-adaptation-task-checklist-v1.md +385 -0
- package/docs/magicball-app-bundle-sqlite-and-command-draft.md +539 -0
- package/docs/magicball-capability-iteration-api.md +2 -0
- package/docs/magicball-capability-iteration-ui.md +2 -0
- package/docs/magicball-capability-library.md +2 -0
- package/docs/magicball-cli-invocation-examples.md +336 -0
- package/docs/magicball-frontend-state-and-command-mapping.md +244 -0
- package/docs/magicball-integration-doc-index.md +137 -0
- package/docs/magicball-integration-issue-tracker.md +218 -0
- package/docs/magicball-mode-home-and-ontology-empty-state-playbook.md +249 -0
- package/docs/magicball-sce-adaptation-guide.md +203 -0
- package/docs/magicball-three-mode-alignment-plan.md +551 -0
- package/docs/magicball-ui-surface-checklist.md +126 -0
- package/docs/magicball-write-auth-adaptation-guide.md +328 -0
- package/docs/moqui-standard-rebuild-guide.md +6 -6
- package/docs/moqui-template-core-library-playbook.md +1 -1
- package/docs/refactor-completion-roadmap.md +116 -0
- package/docs/release-checklist.md +50 -27
- package/docs/releases/README.md +1 -0
- package/docs/releases/v3.6.37.md +22 -0
- package/docs/steering-strategy-guide.md +7 -7
- package/docs/troubleshooting.md +1 -1
- package/docs/zh/README.md +27 -30
- package/docs/zh/refactor-completion-roadmap.md +116 -0
- package/docs/zh/release-checklist.md +40 -17
- package/docs/zh/releases/README.md +1 -0
- package/docs/zh/releases/v3.6.37.md +22 -0
- package/lib/app/registry-config.js +73 -0
- package/lib/app/registry-sync-service.js +228 -0
- package/lib/auto/archive-schema-service.js +276 -0
- package/lib/auto/archive-summary.js +60 -0
- package/lib/auto/batch-goal-input-service.js +543 -0
- package/lib/auto/batch-output.js +201 -0
- package/lib/auto/batch-summary-storage-service.js +110 -0
- package/lib/auto/close-loop-batch-service.js +116 -0
- package/lib/auto/close-loop-controller-service.js +287 -0
- package/lib/auto/close-loop-program-service.js +283 -0
- package/lib/auto/close-loop-recovery-service.js +191 -0
- package/lib/auto/close-loop-session-storage-service.js +50 -0
- package/lib/auto/controller-lock-service.js +55 -0
- package/lib/auto/controller-output.js +32 -0
- package/lib/auto/controller-queue-service.js +127 -0
- package/lib/auto/controller-session-storage-service.js +105 -0
- package/lib/auto/governance-advisory-service.js +208 -0
- package/lib/auto/governance-close-loop-service.js +411 -0
- package/lib/auto/governance-maintenance-presenter.js +162 -0
- package/lib/auto/governance-maintenance-service.js +112 -0
- package/lib/auto/governance-session-presenter.js +70 -0
- package/lib/auto/governance-session-storage-service.js +198 -0
- package/lib/auto/governance-signals.js +139 -0
- package/lib/auto/governance-stats-presenter.js +337 -0
- package/lib/auto/governance-stats-service.js +115 -0
- package/lib/auto/governance-summary.js +703 -0
- package/lib/auto/handoff-capability-matrix-service.js +281 -0
- package/lib/auto/handoff-evidence-review-service.js +251 -0
- package/lib/auto/handoff-release-evidence-service.js +190 -0
- package/lib/auto/handoff-release-gate-history-loaders-service.js +502 -0
- package/lib/auto/handoff-release-gate-history-service.js +257 -0
- package/lib/auto/handoff-reporting-service.js +1407 -0
- package/lib/auto/handoff-run-service.js +486 -0
- package/lib/auto/handoff-snapshots-service.js +645 -0
- package/lib/auto/observability-service.js +132 -0
- package/lib/auto/output-writer.js +34 -0
- package/lib/auto/program-auto-remediation-service.js +130 -0
- package/lib/auto/program-diagnostics.js +138 -0
- package/lib/auto/program-governance-helpers.js +306 -0
- package/lib/auto/program-governance-loop-service.js +413 -0
- package/lib/auto/program-output.js +106 -0
- package/lib/auto/program-summary.js +183 -0
- package/lib/auto/recovery-memory-service.js +684 -0
- package/lib/auto/recovery-selection-service.js +52 -0
- package/lib/auto/retention-policy.js +98 -0
- package/lib/auto/session-persistence-service.js +106 -0
- package/lib/auto/session-presenter.js +105 -0
- package/lib/auto/session-prune-service.js +190 -0
- package/lib/auto/session-query-service.js +249 -0
- package/lib/auto/spec-protection.js +141 -0
- package/lib/commands/adopt.js +4 -4
- package/lib/commands/app.js +911 -0
- package/lib/commands/assurance.js +212 -0
- package/lib/commands/auto.js +1093 -11065
- package/lib/commands/mode.js +321 -0
- package/lib/commands/ontology.js +415 -0
- package/lib/commands/pm.js +422 -0
- package/lib/ontology/seed-profiles.js +160 -0
- package/lib/spec/bootstrap/context-collector.js +1 -1
- package/lib/state/sce-state-store.js +3369 -1200
- package/lib/steering/adoption-config.js +2 -2
- package/lib/steering/compliance-cache.js +2 -2
- package/lib/steering/steering-manager.js +4 -4
- package/lib/task/task-claimer.js +1 -2
- package/lib/workspace/multi/workspace-context-resolver.js +3 -3
- package/lib/workspace/multi/workspace-state-manager.js +0 -164
- package/lib/workspace/sce-tracking-audit.js +1 -1
- package/lib/workspace/takeover-baseline.js +1 -1
- package/package.json +1 -1
- package/template/.sce/README.md +1 -1
- package/template/.sce/steering/CORE_PRINCIPLES.md +1 -1
- package/bin/kse.js +0 -3
package/docs/zh/README.md
CHANGED
|
@@ -1,31 +1,42 @@
|
|
|
1
1
|
# SCE 文档总览
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
本页只保留高价值入口,帮助你从接入、集成到规模化交付快速找到主路径。
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
## 优先入口
|
|
8
8
|
|
|
9
9
|
- [快速开始](quick-start.md)
|
|
10
|
+
- [AI 工具快速开始](../quick-start-with-ai-tools.md)
|
|
10
11
|
- [命令参考](../command-reference.md)
|
|
11
12
|
- [常见问题](../faq.md)
|
|
12
13
|
- [故障排除](../troubleshooting.md)
|
|
13
14
|
|
|
14
15
|
---
|
|
15
16
|
|
|
16
|
-
##
|
|
17
|
+
## 核心交付路径
|
|
17
18
|
|
|
18
19
|
- [Spec 工作流](../spec-workflow.md)
|
|
19
20
|
- [自动闭环指南](../autonomous-control-guide.md)
|
|
20
21
|
- [多 Agent 协同指南](../multi-agent-coordination-guide.md)
|
|
21
|
-
- [
|
|
22
|
-
- [
|
|
22
|
+
- [场景运行时指南](../scene-runtime-guide.md)
|
|
23
|
+
- [Value 可观测指南](../value-observability-guide.md)
|
|
24
|
+
- [本轮重构完成总结与下一轮路线图](refactor-completion-roadmap.md)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 治理与发布
|
|
29
|
+
|
|
30
|
+
- [Errorbook 注册表指南](../errorbook-registry.md)
|
|
31
|
+
- [安全治理默认基线](../security-governance-default-baseline.md)
|
|
32
|
+
- [文档治理](../document-governance.md)
|
|
33
|
+
- [发布检查清单](../release-checklist.md)
|
|
34
|
+
- [发布归档](../releases/README.md)
|
|
23
35
|
|
|
24
36
|
---
|
|
25
37
|
|
|
26
38
|
## 场景化能力与 Moqui
|
|
27
39
|
|
|
28
|
-
- [场景运行时指南](../scene-runtime-guide.md)
|
|
29
40
|
- [Moqui 模板核心库 Playbook](../moqui-template-core-library-playbook.md)
|
|
30
41
|
- [Moqui 能力矩阵](../moqui-capability-matrix.md)
|
|
31
42
|
- [Moqui 标准重建指南](../moqui-standard-rebuild-guide.md)
|
|
@@ -33,27 +44,12 @@
|
|
|
33
44
|
|
|
34
45
|
---
|
|
35
46
|
|
|
36
|
-
##
|
|
37
|
-
|
|
38
|
-
- [文档治理](../document-governance.md)
|
|
39
|
-
- [安全治理默认基线](../security-governance-default-baseline.md)
|
|
40
|
-
- [Errorbook 注册表指南](../errorbook-registry.md)
|
|
41
|
-
- [发布检查清单](release-checklist.md)
|
|
42
|
-
- [发布归档](releases/README.md)
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## 平台管理与运维
|
|
47
|
+
## 平台与集成
|
|
47
48
|
|
|
48
49
|
- [环境管理指南](../environment-management-guide.md)
|
|
49
50
|
- [多仓库管理指南](../multi-repo-management-guide.md)
|
|
50
51
|
- [团队协作指南](../team-collaboration-guide.md)
|
|
51
52
|
- [手动工作流指南](../manual-workflows-guide.md)
|
|
52
|
-
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
## AI 工具集成
|
|
56
|
-
|
|
57
53
|
- [Cursor 集成](tools/cursor-guide.md)
|
|
58
54
|
- [Claude Code 集成](tools/claude-guide.md)
|
|
59
55
|
- [Windsurf 集成](tools/windsurf-guide.md)
|
|
@@ -62,20 +58,21 @@
|
|
|
62
58
|
|
|
63
59
|
---
|
|
64
60
|
|
|
65
|
-
##
|
|
61
|
+
## Language
|
|
66
62
|
|
|
67
|
-
- [
|
|
68
|
-
- [架构说明](../architecture.md)
|
|
69
|
-
- [开发者指南](../developer-guide.md)
|
|
70
|
-
- [社区入口](../community.md)
|
|
63
|
+
- [English Docs Hub](../README.md)
|
|
71
64
|
|
|
72
65
|
---
|
|
73
66
|
|
|
74
|
-
##
|
|
67
|
+
## 社区
|
|
75
68
|
|
|
76
|
-
- [
|
|
69
|
+
- [社区入口](../community.md)
|
|
70
|
+
- [GitHub Discussions](https://github.com/heguangyong/scene-capability-engine/discussions)
|
|
71
|
+
- [GitHub Issues](https://github.com/heguangyong/scene-capability-engine/issues)
|
|
77
72
|
|
|
78
73
|
---
|
|
79
74
|
|
|
80
|
-
**版本**:3.
|
|
81
|
-
**最后更新**:2026-03-
|
|
75
|
+
**版本**:3.6.34
|
|
76
|
+
**最后更新**:2026-03-08
|
|
77
|
+
|
|
78
|
+
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# 本轮重构完成总结与下一轮路线图
|
|
2
|
+
|
|
3
|
+
## 范围
|
|
4
|
+
|
|
5
|
+
本文件用于记录 `3.6.33` 这一轮重构的完成状态,并明确下一阶段的工程方向。
|
|
6
|
+
|
|
7
|
+
当前稳定提交:
|
|
8
|
+
|
|
9
|
+
- `0c9594d` `refactor(auto): finalize close-loop governance split and docs refresh`
|
|
10
|
+
- `0fb49b7` `refactor(handoff): extract capability matrix service`
|
|
11
|
+
- `8ebc5bc` `release: 3.6.33`
|
|
12
|
+
|
|
13
|
+
## 什么算完成
|
|
14
|
+
|
|
15
|
+
这一轮重构之所以可以判定为完成,不是因为 `lib/commands/auto.js` 里一个大函数都不剩,而是因为最核心的自动交付主链已经不再以它为中心。
|
|
16
|
+
|
|
17
|
+
本轮已完成下沉:
|
|
18
|
+
|
|
19
|
+
- `lib/auto/close-loop-controller-service.js`
|
|
20
|
+
- `lib/auto/close-loop-batch-service.js`
|
|
21
|
+
- `lib/auto/close-loop-program-service.js`
|
|
22
|
+
- `lib/auto/observability-service.js`
|
|
23
|
+
- `lib/auto/program-summary.js`
|
|
24
|
+
- `lib/auto/program-output.js`
|
|
25
|
+
- `lib/auto/batch-output.js`
|
|
26
|
+
- `lib/auto/program-governance-helpers.js`
|
|
27
|
+
- `lib/auto/program-governance-loop-service.js`
|
|
28
|
+
- `lib/auto/program-auto-remediation-service.js`
|
|
29
|
+
- `lib/auto/output-writer.js`
|
|
30
|
+
- `lib/auto/handoff-capability-matrix-service.js`
|
|
31
|
+
|
|
32
|
+
本轮同步完成的收口工作:
|
|
33
|
+
|
|
34
|
+
- README 与 docs hub 重组
|
|
35
|
+
- governance summary 真实回归修复
|
|
36
|
+
- governance weekly-ops session telemetry 修复
|
|
37
|
+
- session stats `criteria.days` 字段修复
|
|
38
|
+
|
|
39
|
+
## 架构变化
|
|
40
|
+
|
|
41
|
+
在本轮之前:
|
|
42
|
+
|
|
43
|
+
- `lib/commands/auto.js` 同时承担命令注册和大量主执行逻辑。
|
|
44
|
+
- program / governance 行为一旦调整,回归风险会很高,因为职责耦合过重。
|
|
45
|
+
|
|
46
|
+
在本轮之后:
|
|
47
|
+
|
|
48
|
+
- `lib/commands/auto.js` 更接近命令层壳子与 wrapper。
|
|
49
|
+
- 主要交付链路已经迁移到 `lib/auto/`。
|
|
50
|
+
- `auto-handoff` 也已经拥有了第一个完整专题边界。
|
|
51
|
+
|
|
52
|
+
这就是为什么即使 `auto.js` 仍然很大,这一轮也可以被定义为完成。
|
|
53
|
+
|
|
54
|
+
## 为什么有些工作被明确延后
|
|
55
|
+
|
|
56
|
+
不是 `auto.js` 里剩下的每个函数,都值得马上继续拆。
|
|
57
|
+
|
|
58
|
+
本轮明确延后的内容:
|
|
59
|
+
|
|
60
|
+
- 收益很低的 helper 搬运
|
|
61
|
+
- 一旦切出去就容易引入回归的 `auto-handoff` 零碎微边界
|
|
62
|
+
- 对长期维护性帮助不大的纯 cosmetic 收缩
|
|
63
|
+
|
|
64
|
+
本轮执行标准是:
|
|
65
|
+
|
|
66
|
+
- 保留能形成长期 service 边界的拆分
|
|
67
|
+
- 当下一刀的收益低于回归风险时,立即停止
|
|
68
|
+
|
|
69
|
+
## 剩余高价值方向
|
|
70
|
+
|
|
71
|
+
下一轮真正值得继续做的,不再是 close-loop 主链,而是 `auto-handoff` 及少量发布治理支持域。
|
|
72
|
+
|
|
73
|
+
剩余高价值主题:
|
|
74
|
+
|
|
75
|
+
1. `auto-handoff` release evidence 子域
|
|
76
|
+
2. `auto-handoff` release gate history 子域
|
|
77
|
+
3. `auto-handoff` release notes / evidence review 渲染子域
|
|
78
|
+
4. `auto-handoff` baseline / coverage snapshot 子域
|
|
79
|
+
|
|
80
|
+
## 建议的下一轮
|
|
81
|
+
|
|
82
|
+
下一轮建议明确命名为 `auto-handoff` 专题重构,而不是继续做泛化的 `auto.js` 清理。
|
|
83
|
+
|
|
84
|
+
建议顺序:
|
|
85
|
+
|
|
86
|
+
1. `release evidence` 子域
|
|
87
|
+
2. `release gate history` 子域
|
|
88
|
+
3. `release notes / evidence review` 渲染子域
|
|
89
|
+
4. `baseline / coverage snapshot` 子域
|
|
90
|
+
|
|
91
|
+
每个子域都沿用本轮的标准:
|
|
92
|
+
|
|
93
|
+
- 一次只切一个完整边界
|
|
94
|
+
- 命令行为保持不变
|
|
95
|
+
- 新模块必须有单测
|
|
96
|
+
- 通过关键 integration 回归后才保留
|
|
97
|
+
|
|
98
|
+
## 验证基线
|
|
99
|
+
|
|
100
|
+
本轮用于验收的最低基线:
|
|
101
|
+
|
|
102
|
+
- `npx jest tests/unit/auto --runInBand`
|
|
103
|
+
- `npx jest tests/unit/commands/auto.test.js --runInBand`
|
|
104
|
+
- `npx jest tests/integration/auto-close-loop-cli.integration.test.js tests/integration/version-cli.integration.test.js --runInBand`
|
|
105
|
+
- `npm run test:release`
|
|
106
|
+
|
|
107
|
+
下一轮建议继续沿用这套基线。
|
|
108
|
+
|
|
109
|
+
## 发布状态
|
|
110
|
+
|
|
111
|
+
当前稳定版本:
|
|
112
|
+
|
|
113
|
+
- version: `3.6.33`
|
|
114
|
+
- tag: `v3.6.33`
|
|
115
|
+
|
|
116
|
+
后续 `auto-handoff` 的继续演进,应以这个版本作为新的稳定基线。
|
|
@@ -100,28 +100,35 @@ node scripts/git-managed-gate.js --fail-on-violation --json
|
|
|
100
100
|
|
|
101
101
|
确认:
|
|
102
102
|
|
|
103
|
+
- 发布自动化是基于 tag,而不是普通 commit:
|
|
104
|
+
- `.github/workflows/release.yml` 只在 `push.tags: v*` 时触发
|
|
105
|
+
- 普通 `git push` 只会跑常规 CI,不会发布 npm 包,也不会创建 GitHub Release
|
|
106
|
+
- GitHub Actions 发版前置条件已配置:
|
|
107
|
+
- 仓库 Secret `NPM_TOKEN` 必须存在且有效,workflow 会用它执行 `npm publish --access public`
|
|
108
|
+
- workflow 的 release 资产/回读步骤依赖 `GITHUB_TOKEN`
|
|
103
109
|
- `package.json` 版本号正确;
|
|
110
|
+
- `package.json` 版本号必须大于 npm 当前已发布版本;
|
|
104
111
|
- `CHANGELOG.md` 已记录发布相关变化;
|
|
105
112
|
- 发布说明草稿已就绪(如 `docs/releases/vX.Y.Z.md`)。
|
|
106
113
|
- 可选:通过仓库变量配置 release evidence 门禁(`Settings -> Secrets and variables -> Actions -> Variables`):
|
|
107
|
-
- `
|
|
108
|
-
- `
|
|
109
|
-
- `
|
|
110
|
-
- `
|
|
111
|
-
- `
|
|
112
|
-
- `
|
|
113
|
-
- `
|
|
114
|
-
- `
|
|
115
|
-
- `
|
|
114
|
+
- `SCE_RELEASE_GATE_ENFORCE`:`true|false`(默认 advisory,不阻断发布)
|
|
115
|
+
- `SCE_RELEASE_GATE_REQUIRE_EVIDENCE`:是否要求存在 `handoff-runs.json` 摘要
|
|
116
|
+
- `SCE_RELEASE_GATE_REQUIRE_GATE_PASS`:是否要求 evidence gate `passed=true`(有 evidence 时默认要求)
|
|
117
|
+
- `SCE_RELEASE_GATE_MIN_SPEC_SUCCESS_RATE`:最小允许成功率(百分比)
|
|
118
|
+
- `SCE_RELEASE_GATE_MAX_RISK_LEVEL`:`low|medium|high|unknown`(默认 `unknown`)
|
|
119
|
+
- `SCE_RELEASE_GATE_MAX_UNMAPPED_RULES`:ontology 业务规则未映射最大允许值
|
|
120
|
+
- `SCE_RELEASE_GATE_MAX_UNDECIDED_DECISIONS`:ontology 决策未定最大允许值
|
|
121
|
+
- `SCE_RELEASE_GATE_REQUIRE_SCENE_BATCH_PASS`:是否要求 scene package publish-batch gate 必须通过(`true|false`,默认 `true`)
|
|
122
|
+
- `SCE_RELEASE_GATE_MAX_SCENE_BATCH_FAILURES`:scene package batch 失败数量最大允许值(默认 `0`)
|
|
116
123
|
- 可选:通过仓库变量调节 Release Notes 中的漂移告警阈值:
|
|
117
124
|
- CI 中漂移评估由 `scripts/release-drift-evaluate.js` 执行(历史读取、告警计算、gate 报告写回、enforce 退出码)。
|
|
118
|
-
- `
|
|
119
|
-
- `
|
|
120
|
-
- `
|
|
121
|
-
- `
|
|
122
|
-
- `
|
|
123
|
-
- `
|
|
124
|
-
- `
|
|
125
|
+
- `SCE_RELEASE_DRIFT_ENFORCE`:`true|false`(默认 `false`),触发 drift alert 时阻断发布
|
|
126
|
+
- `SCE_RELEASE_DRIFT_FAIL_STREAK_MIN`:触发告警的最小连续失败次数(默认 `2`)
|
|
127
|
+
- `SCE_RELEASE_DRIFT_HIGH_RISK_SHARE_MIN_PERCENT`:近 5 版 high 风险占比告警阈值(默认 `60`)
|
|
128
|
+
- `SCE_RELEASE_DRIFT_HIGH_RISK_SHARE_DELTA_MIN_PERCENT`:短期相对长期 high 风险占比增量阈值(默认 `25`)
|
|
129
|
+
- `SCE_RELEASE_DRIFT_PREFLIGHT_BLOCK_RATE_MIN_PERCENT`:近 5 版(有 preflight 信号)blocked 占比告警阈值(默认 `40`)
|
|
130
|
+
- `SCE_RELEASE_DRIFT_HARD_GATE_BLOCK_STREAK_MIN`:hard-gate preflight 连续 blocked 告警阈值(最近窗口,默认 `2`)
|
|
131
|
+
- `SCE_RELEASE_DRIFT_PREFLIGHT_UNAVAILABLE_STREAK_MIN`:release preflight 连续 unavailable 告警阈值(最近窗口,默认 `2`)
|
|
125
132
|
- 可选:发布资产 0 字节防护(workflow 默认开启)
|
|
126
133
|
- `scripts/release-asset-nonempty-normalize.js` 会在上传 GitHub Release 资产前,为可选 `.lines` / `.jsonl` 资产自动补齐占位内容,避免 422。
|
|
127
134
|
- 本地 dry-run 示例:
|
|
@@ -131,4 +138,20 @@ node scripts/git-managed-gate.js --fail-on-violation --json
|
|
|
131
138
|
- 可选本地预演 release gate 历史索引产物:
|
|
132
139
|
- `sce auto handoff gate-index --dir .sce/reports/release-evidence --out .sce/reports/release-evidence/release-gate-history.json --json`
|
|
133
140
|
|
|
134
|
-
|
|
141
|
+
然后再执行正式发布流程:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# 1. 先升级版本并提交
|
|
145
|
+
# 2. 先 push 分支代码
|
|
146
|
+
git push origin main
|
|
147
|
+
|
|
148
|
+
# 3. 再创建并 push 发版 tag
|
|
149
|
+
git tag vX.Y.Z
|
|
150
|
+
git push origin vX.Y.Z
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
预期:
|
|
154
|
+
|
|
155
|
+
- `git push origin main` 只跑常规 CI;
|
|
156
|
+
- `git push origin vX.Y.Z` 才会触发 GitHub Actions `Release` workflow;
|
|
157
|
+
- 只有 release workflow 全部门禁通过后,才会自动发布 npm 包并创建 GitHub Release。
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
## 历史版本归档
|
|
10
10
|
|
|
11
11
|
- [发布检查清单](../release-checklist.md)
|
|
12
|
+
- [v3.6.37 发布说明](./v3.6.37.md)
|
|
12
13
|
- [v1.46.2 发布说明](./v1.46.2.md)(历史归档)
|
|
13
14
|
- [v1.46.2 验证报告](./v1.46.2-validation.md)(历史归档)
|
|
14
15
|
- [GitHub Releases](https://github.com/heguangyong/scene-capability-engine/releases)(最新)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# v3.6.37 发布说明
|
|
2
|
+
|
|
3
|
+
发布日期:2026-03-12
|
|
4
|
+
|
|
5
|
+
## 重点变化
|
|
6
|
+
|
|
7
|
+
- 彻底移除了运行路径、模板、夹具和对外文档中的旧 `kse` 命令与内容,不再保留兼容桥接。
|
|
8
|
+
- 将 scene package / template 元数据与 fixture 路径统一到 `sce` 命名,避免新产物继续泄漏旧 `kse` 标识。
|
|
9
|
+
- 修复了 Windows 下 `scripts/git-managed-gate.js` 的 git 可执行文件解析问题,新增 `git.cmd` / `git.exe` 回退,避免发布前置门禁误判。
|
|
10
|
+
- 明确记录了真实发布方式:只有 `v*` tag push 才会触发 GitHub Actions 发版,且 workflow 发布依赖仓库 Secret `NPM_TOKEN`。
|
|
11
|
+
|
|
12
|
+
## 验证
|
|
13
|
+
|
|
14
|
+
- `npx jest tests/unit/workspace/workspace-context-resolver.test.js tests/unit/workspace/workspace-state-manager.test.js tests/unit/steering/compliance-cache.test.js tests/unit/scripts/moqui-lexicon-audit.test.js tests/unit/scripts/moqui-standard-rebuild.test.js tests/unit/scripts/moqui-metadata-extract.test.js tests/unit/task/task-claimer.test.js tests/unit/commands/auto.test.js tests/integration/auto-close-loop-cli.integration.test.js --runInBand`
|
|
15
|
+
- `node scripts/check-branding-consistency.js`
|
|
16
|
+
- `npx jest tests/unit/scripts/git-managed-gate.test.js --runInBand`
|
|
17
|
+
|
|
18
|
+
## 发布说明
|
|
19
|
+
|
|
20
|
+
- 普通 `git push` 不会发布本项目。
|
|
21
|
+
- 只有 `git push origin vX.Y.Z` 触发 `.github/workflows/release.yml` 后,才会进入自动发布流程。
|
|
22
|
+
- GitHub Actions 发版依赖仓库 Secret `NPM_TOKEN`。
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
|
+
|
|
4
|
+
const DEFAULT_APP_REGISTRY_CONFIG_PATH = path.join('.sce', 'config', 'app-registries.json');
|
|
5
|
+
|
|
6
|
+
const DEFAULT_APP_REGISTRY_CONFIG = Object.freeze({
|
|
7
|
+
version: '1.0',
|
|
8
|
+
bundle_registry: {
|
|
9
|
+
repo_url: 'https://github.com/heguangyong/magicball-app-bundle-registry.git',
|
|
10
|
+
branch: 'main',
|
|
11
|
+
index_url: 'https://raw.githubusercontent.com/heguangyong/magicball-app-bundle-registry/main/bundles/index.json'
|
|
12
|
+
},
|
|
13
|
+
service_catalog: {
|
|
14
|
+
repo_url: 'https://github.com/heguangyong/magicball-app-service-catalog.git',
|
|
15
|
+
branch: 'main',
|
|
16
|
+
index_url: 'https://raw.githubusercontent.com/heguangyong/magicball-app-service-catalog/main/catalog/index.json'
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
function normalizeString(value) {
|
|
21
|
+
if (typeof value !== 'string') {
|
|
22
|
+
return '';
|
|
23
|
+
}
|
|
24
|
+
return value.trim();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function mergeSection(base = {}, patch = {}) {
|
|
28
|
+
return {
|
|
29
|
+
...base,
|
|
30
|
+
...Object.fromEntries(
|
|
31
|
+
Object.entries(patch || {}).filter(([, value]) => value !== undefined)
|
|
32
|
+
)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function loadAppRegistryConfig(projectPath = process.cwd(), fileSystem = fs) {
|
|
37
|
+
const configPath = path.join(projectPath, DEFAULT_APP_REGISTRY_CONFIG_PATH);
|
|
38
|
+
let filePayload = {};
|
|
39
|
+
if (await fileSystem.pathExists(configPath)) {
|
|
40
|
+
filePayload = await fileSystem.readJson(configPath);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
config_path: DEFAULT_APP_REGISTRY_CONFIG_PATH,
|
|
44
|
+
config: {
|
|
45
|
+
version: normalizeString(filePayload.version) || DEFAULT_APP_REGISTRY_CONFIG.version,
|
|
46
|
+
bundle_registry: mergeSection(DEFAULT_APP_REGISTRY_CONFIG.bundle_registry, filePayload.bundle_registry),
|
|
47
|
+
service_catalog: mergeSection(DEFAULT_APP_REGISTRY_CONFIG.service_catalog, filePayload.service_catalog)
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function saveAppRegistryConfig(patch = {}, projectPath = process.cwd(), fileSystem = fs) {
|
|
53
|
+
const loaded = await loadAppRegistryConfig(projectPath, fileSystem);
|
|
54
|
+
const nextConfig = {
|
|
55
|
+
version: DEFAULT_APP_REGISTRY_CONFIG.version,
|
|
56
|
+
bundle_registry: mergeSection(loaded.config.bundle_registry, patch.bundle_registry),
|
|
57
|
+
service_catalog: mergeSection(loaded.config.service_catalog, patch.service_catalog)
|
|
58
|
+
};
|
|
59
|
+
const configPath = path.join(projectPath, DEFAULT_APP_REGISTRY_CONFIG_PATH);
|
|
60
|
+
await fileSystem.ensureDir(path.dirname(configPath));
|
|
61
|
+
await fileSystem.writeJson(configPath, nextConfig, { spaces: 2 });
|
|
62
|
+
return {
|
|
63
|
+
config_path: DEFAULT_APP_REGISTRY_CONFIG_PATH,
|
|
64
|
+
config: nextConfig
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
module.exports = {
|
|
69
|
+
DEFAULT_APP_REGISTRY_CONFIG_PATH,
|
|
70
|
+
DEFAULT_APP_REGISTRY_CONFIG,
|
|
71
|
+
loadAppRegistryConfig,
|
|
72
|
+
saveAppRegistryConfig
|
|
73
|
+
};
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
|
+
const { loadAppRegistryConfig } = require('./registry-config');
|
|
4
|
+
|
|
5
|
+
function normalizeString(value) {
|
|
6
|
+
if (typeof value !== 'string') {
|
|
7
|
+
return '';
|
|
8
|
+
}
|
|
9
|
+
return value.trim();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async function readJsonResource(resourceRef, dependencies = {}) {
|
|
13
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
14
|
+
const fetchImpl = dependencies.fetchImpl || global.fetch;
|
|
15
|
+
const normalized = normalizeString(resourceRef);
|
|
16
|
+
if (!normalized) {
|
|
17
|
+
throw new Error('resource reference is required');
|
|
18
|
+
}
|
|
19
|
+
if (/^https?:\/\//i.test(normalized)) {
|
|
20
|
+
if (typeof fetchImpl !== 'function') {
|
|
21
|
+
throw new Error(`fetch unavailable for remote resource: ${normalized}`);
|
|
22
|
+
}
|
|
23
|
+
const response = await fetchImpl(normalized);
|
|
24
|
+
if (!response || response.ok !== true) {
|
|
25
|
+
const status = response && typeof response.status !== 'undefined' ? response.status : 'unknown';
|
|
26
|
+
throw new Error(`failed to fetch ${normalized} (status=${status})`);
|
|
27
|
+
}
|
|
28
|
+
return response.json();
|
|
29
|
+
}
|
|
30
|
+
const resolvedPath = path.isAbsolute(normalized)
|
|
31
|
+
? normalized
|
|
32
|
+
: path.join(dependencies.projectPath || process.cwd(), normalized);
|
|
33
|
+
return fileSystem.readJson(resolvedPath);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function resolveChildResource(parentRef, childRef) {
|
|
37
|
+
const normalizedParent = normalizeString(parentRef);
|
|
38
|
+
const normalizedChild = normalizeString(childRef);
|
|
39
|
+
if (!normalizedChild) {
|
|
40
|
+
return normalizedParent;
|
|
41
|
+
}
|
|
42
|
+
if (/^https?:\/\//i.test(normalizedChild) || path.isAbsolute(normalizedChild)) {
|
|
43
|
+
return normalizedChild;
|
|
44
|
+
}
|
|
45
|
+
if (/^https?:\/\//i.test(normalizedParent)) {
|
|
46
|
+
return new URL(normalizedChild, normalizedParent).toString();
|
|
47
|
+
}
|
|
48
|
+
return path.join(path.dirname(normalizedParent), normalizedChild);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function graphToRegisterPayload(graph = {}) {
|
|
52
|
+
const bundle = graph.bundle || {};
|
|
53
|
+
const runtimeRelease = graph.runtime_release || {};
|
|
54
|
+
const ontologyBundle = graph.ontology_bundle || {};
|
|
55
|
+
const engineeringProject = graph.engineering_project || {};
|
|
56
|
+
return {
|
|
57
|
+
app_id: bundle.app_id,
|
|
58
|
+
app_key: bundle.app_key,
|
|
59
|
+
app_name: bundle.app_name,
|
|
60
|
+
app_slug: bundle.app_slug || undefined,
|
|
61
|
+
workspace_id: bundle.workspace_id || undefined,
|
|
62
|
+
runtime_release_id: bundle.runtime_release_id || undefined,
|
|
63
|
+
ontology_bundle_id: bundle.ontology_bundle_id || undefined,
|
|
64
|
+
engineering_project_id: bundle.engineering_project_id || undefined,
|
|
65
|
+
default_scene_id: bundle.default_scene_id || undefined,
|
|
66
|
+
environment: bundle.environment || undefined,
|
|
67
|
+
status: bundle.status || undefined,
|
|
68
|
+
source_origin: bundle.source_origin || undefined,
|
|
69
|
+
tags: Array.isArray(bundle.tags) ? bundle.tags : [],
|
|
70
|
+
metadata: bundle.metadata && typeof bundle.metadata === 'object' ? { ...bundle.metadata } : {},
|
|
71
|
+
runtime: runtimeRelease && runtimeRelease.release_id ? {
|
|
72
|
+
release_id: runtimeRelease.release_id,
|
|
73
|
+
runtime_version: runtimeRelease.runtime_version,
|
|
74
|
+
release_channel: runtimeRelease.release_channel,
|
|
75
|
+
release_status: runtimeRelease.release_status,
|
|
76
|
+
entrypoint: runtimeRelease.entrypoint,
|
|
77
|
+
runtime_status: runtimeRelease.runtime_status,
|
|
78
|
+
release_notes_file: runtimeRelease.release_notes_file,
|
|
79
|
+
release_evidence_file: runtimeRelease.release_evidence_file,
|
|
80
|
+
published_at: runtimeRelease.published_at,
|
|
81
|
+
source_updated_at: runtimeRelease.source_updated_at,
|
|
82
|
+
metadata: runtimeRelease.metadata || {}
|
|
83
|
+
} : undefined,
|
|
84
|
+
ontology: ontologyBundle && ontologyBundle.ontology_bundle_id ? {
|
|
85
|
+
ontology_bundle_id: ontologyBundle.ontology_bundle_id,
|
|
86
|
+
ontology_version: ontologyBundle.ontology_version,
|
|
87
|
+
template_version: ontologyBundle.template_version,
|
|
88
|
+
capability_catalog_version: ontologyBundle.capability_catalog_version,
|
|
89
|
+
triad_revision: ontologyBundle.triad_revision,
|
|
90
|
+
triad_status: ontologyBundle.triad_status,
|
|
91
|
+
publish_readiness: ontologyBundle.publish_readiness,
|
|
92
|
+
template_source: ontologyBundle.template_source,
|
|
93
|
+
capability_set: Array.isArray(ontologyBundle.capability_set) ? ontologyBundle.capability_set : [],
|
|
94
|
+
summary: ontologyBundle.summary || {},
|
|
95
|
+
metadata: ontologyBundle.metadata || {}
|
|
96
|
+
} : undefined,
|
|
97
|
+
engineering: engineeringProject && engineeringProject.engineering_project_id ? {
|
|
98
|
+
engineering_project_id: engineeringProject.engineering_project_id,
|
|
99
|
+
project_key: engineeringProject.project_key,
|
|
100
|
+
project_name: engineeringProject.project_name,
|
|
101
|
+
repo_url: engineeringProject.repo_url,
|
|
102
|
+
repo_provider: engineeringProject.repo_provider,
|
|
103
|
+
default_branch: engineeringProject.default_branch,
|
|
104
|
+
current_branch: engineeringProject.current_branch,
|
|
105
|
+
commit_sha: engineeringProject.commit_sha,
|
|
106
|
+
workspace_path: engineeringProject.workspace_path,
|
|
107
|
+
code_version: engineeringProject.code_version,
|
|
108
|
+
synced_runtime_release_id: engineeringProject.synced_runtime_release_id,
|
|
109
|
+
dirty_state: engineeringProject.dirty_state === true,
|
|
110
|
+
auth_policy: engineeringProject.auth_policy || {},
|
|
111
|
+
metadata: engineeringProject.metadata || {}
|
|
112
|
+
} : undefined,
|
|
113
|
+
scene_bindings: Array.isArray(graph.scene_bindings)
|
|
114
|
+
? graph.scene_bindings.map((item) => ({
|
|
115
|
+
scene_id: item.scene_id,
|
|
116
|
+
binding_role: item.binding_role,
|
|
117
|
+
source: item.source,
|
|
118
|
+
metadata: item.metadata || {}
|
|
119
|
+
}))
|
|
120
|
+
: []
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function syncBundleRegistry(options = {}, dependencies = {}) {
|
|
125
|
+
const projectPath = dependencies.projectPath || process.cwd();
|
|
126
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
127
|
+
const stateStore = dependencies.stateStore;
|
|
128
|
+
const loadedConfig = await loadAppRegistryConfig(projectPath, fileSystem);
|
|
129
|
+
const indexRef = normalizeString(options.indexUrl) || normalizeString(loadedConfig.config.bundle_registry.index_url);
|
|
130
|
+
const indexPayload = await readJsonResource(indexRef, dependencies);
|
|
131
|
+
const bundleItems = Array.isArray(indexPayload && indexPayload.bundles) ? indexPayload.bundles : [];
|
|
132
|
+
const synced = [];
|
|
133
|
+
for (const item of bundleItems) {
|
|
134
|
+
const resourceRef = normalizeString(item && item.url) || resolveChildResource(indexRef, item && item.file);
|
|
135
|
+
const bundlePayload = await readJsonResource(resourceRef, dependencies);
|
|
136
|
+
const graph = await stateStore.registerAppBundle(bundlePayload);
|
|
137
|
+
synced.push({
|
|
138
|
+
app_id: graph && graph.bundle ? graph.bundle.app_id : null,
|
|
139
|
+
app_key: graph && graph.bundle ? graph.bundle.app_key : null,
|
|
140
|
+
source: resourceRef
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return {
|
|
144
|
+
mode: 'app-registry-sync-bundles',
|
|
145
|
+
index_url: indexRef,
|
|
146
|
+
source_generated_at: indexPayload && indexPayload.generated_at ? indexPayload.generated_at : null,
|
|
147
|
+
synced_count: synced.length,
|
|
148
|
+
items: synced
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async function syncServiceCatalog(options = {}, dependencies = {}) {
|
|
153
|
+
const projectPath = dependencies.projectPath || process.cwd();
|
|
154
|
+
const fileSystem = dependencies.fileSystem || fs;
|
|
155
|
+
const stateStore = dependencies.stateStore;
|
|
156
|
+
const loadedConfig = await loadAppRegistryConfig(projectPath, fileSystem);
|
|
157
|
+
const indexRef = normalizeString(options.indexUrl) || normalizeString(loadedConfig.config.service_catalog.index_url);
|
|
158
|
+
const indexPayload = await readJsonResource(indexRef, dependencies);
|
|
159
|
+
const appItems = Array.isArray(indexPayload && indexPayload.apps) ? indexPayload.apps : [];
|
|
160
|
+
const synced = [];
|
|
161
|
+
for (const item of appItems) {
|
|
162
|
+
const resourceRef = normalizeString(item && item.url) || resolveChildResource(indexRef, item && item.file);
|
|
163
|
+
const appPayload = await readJsonResource(resourceRef, dependencies);
|
|
164
|
+
const appId = normalizeString(appPayload && appPayload.app_id);
|
|
165
|
+
const appKey = normalizeString(appPayload && appPayload.app_key);
|
|
166
|
+
const appName = normalizeString(appPayload && appPayload.app_name);
|
|
167
|
+
let graph = await stateStore.getAppBundleGraph(appId || appKey);
|
|
168
|
+
if (!graph) {
|
|
169
|
+
graph = await stateStore.registerAppBundle({
|
|
170
|
+
app_id: appId,
|
|
171
|
+
app_key: appKey,
|
|
172
|
+
app_name: appName || appKey || appId,
|
|
173
|
+
status: 'active',
|
|
174
|
+
environment: normalizeString(appPayload && appPayload.environment) || null,
|
|
175
|
+
source_origin: 'app-service-catalog-sync'
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
const nextPayload = graphToRegisterPayload(graph);
|
|
179
|
+
const releases = Array.isArray(appPayload && appPayload.releases) ? appPayload.releases : [];
|
|
180
|
+
const defaultReleaseId = normalizeString(appPayload && appPayload.default_release_id) || (releases[0] && normalizeString(releases[0].release_id)) || null;
|
|
181
|
+
const activeRelease = releases.find((entry) => normalizeString(entry && entry.release_id) === defaultReleaseId) || releases[0] || null;
|
|
182
|
+
nextPayload.metadata = nextPayload.metadata || {};
|
|
183
|
+
nextPayload.metadata.service_catalog = {
|
|
184
|
+
synced_at: new Date().toISOString(),
|
|
185
|
+
source: resourceRef,
|
|
186
|
+
app_name: appName || null,
|
|
187
|
+
default_release_id: defaultReleaseId,
|
|
188
|
+
releases
|
|
189
|
+
};
|
|
190
|
+
if (activeRelease) {
|
|
191
|
+
nextPayload.runtime_release_id = normalizeString(activeRelease.release_id);
|
|
192
|
+
nextPayload.runtime = {
|
|
193
|
+
release_id: normalizeString(activeRelease.release_id),
|
|
194
|
+
runtime_version: normalizeString(activeRelease.runtime_version),
|
|
195
|
+
release_channel: normalizeString(activeRelease.release_channel) || null,
|
|
196
|
+
release_status: normalizeString(activeRelease.release_status) || 'published',
|
|
197
|
+
entrypoint: normalizeString(activeRelease.entrypoint) || null,
|
|
198
|
+
runtime_status: normalizeString(activeRelease.runtime_status) || null,
|
|
199
|
+
release_notes_file: normalizeString(activeRelease.release_notes_file) || null,
|
|
200
|
+
release_evidence_file: normalizeString(activeRelease.release_evidence_file) || null,
|
|
201
|
+
published_at: normalizeString(activeRelease.published_at) || null,
|
|
202
|
+
metadata: activeRelease.metadata && typeof activeRelease.metadata === 'object' ? activeRelease.metadata : {}
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const updated = await stateStore.registerAppBundle(nextPayload);
|
|
206
|
+
synced.push({
|
|
207
|
+
app_id: updated && updated.bundle ? updated.bundle.app_id : appId,
|
|
208
|
+
app_key: updated && updated.bundle ? updated.bundle.app_key : appKey,
|
|
209
|
+
source: resourceRef,
|
|
210
|
+
release_count: releases.length,
|
|
211
|
+
default_release_id: defaultReleaseId || null
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
mode: 'app-registry-sync-service-catalog',
|
|
216
|
+
index_url: indexRef,
|
|
217
|
+
source_generated_at: indexPayload && indexPayload.generated_at ? indexPayload.generated_at : null,
|
|
218
|
+
synced_count: synced.length,
|
|
219
|
+
items: synced
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
module.exports = {
|
|
224
|
+
readJsonResource,
|
|
225
|
+
resolveChildResource,
|
|
226
|
+
syncBundleRegistry,
|
|
227
|
+
syncServiceCatalog
|
|
228
|
+
};
|