scene-capability-engine 3.6.36 → 3.6.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +37 -12
  2. package/bin/scene-capability-engine.js +1 -1
  3. package/docs/331-poc-adaptation-roadmap.md +3 -3
  4. package/docs/command-reference.md +5 -5
  5. package/docs/faq.md +1 -1
  6. package/docs/interactive-customization/331-poc-sce-integration-checklist.md +3 -3
  7. package/docs/interactive-customization/moqui-interactive-template-playbook.md +4 -4
  8. package/docs/interactive-customization/phase-acceptance-evidence.md +2 -2
  9. package/docs/moqui-standard-rebuild-guide.md +6 -6
  10. package/docs/moqui-template-core-library-playbook.md +1 -1
  11. package/docs/release-checklist.md +50 -27
  12. package/docs/releases/README.md +2 -0
  13. package/docs/releases/v3.6.37.md +22 -0
  14. package/docs/releases/v3.6.38.md +19 -0
  15. package/docs/steering-governance.md +112 -0
  16. package/docs/steering-strategy-guide.md +7 -7
  17. package/docs/troubleshooting.md +1 -1
  18. package/docs/zh/release-checklist.md +40 -17
  19. package/docs/zh/releases/README.md +2 -0
  20. package/docs/zh/releases/v3.6.37.md +22 -0
  21. package/docs/zh/releases/v3.6.38.md +19 -0
  22. package/lib/auto/governance-summary.js +2 -2
  23. package/lib/commands/adopt.js +4 -4
  24. package/lib/commands/auto.js +3 -3
  25. package/lib/spec/bootstrap/context-collector.js +1 -1
  26. package/lib/steering/adoption-config.js +2 -2
  27. package/lib/steering/compliance-cache.js +2 -2
  28. package/lib/steering/steering-manager.js +4 -4
  29. package/lib/task/task-claimer.js +1 -2
  30. package/lib/workspace/multi/workspace-context-resolver.js +3 -3
  31. package/lib/workspace/multi/workspace-state-manager.js +0 -164
  32. package/lib/workspace/sce-tracking-audit.js +1 -1
  33. package/lib/workspace/takeover-baseline.js +1 -1
  34. package/package.json +4 -2
  35. package/template/.sce/README.md +1 -1
  36. package/template/.sce/steering/CORE_PRINCIPLES.md +21 -211
  37. package/template/.sce/steering/CURRENT_CONTEXT.md +9 -27
  38. package/template/.sce/steering/ENVIRONMENT.md +18 -32
  39. package/template/.sce/steering/RULES_GUIDE.md +16 -44
  40. package/template/.sce/steering/manifest.yaml +50 -0
  41. package/bin/kse.js +0 -3
@@ -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
- - `KSE_RELEASE_GATE_ENFORCE`:`true|false`(默认 advisory,不阻断发布)
108
- - `KSE_RELEASE_GATE_REQUIRE_EVIDENCE`:是否要求存在 `handoff-runs.json` 摘要
109
- - `KSE_RELEASE_GATE_REQUIRE_GATE_PASS`:是否要求 evidence gate `passed=true`(有 evidence 时默认要求)
110
- - `KSE_RELEASE_GATE_MIN_SPEC_SUCCESS_RATE`:最小允许成功率(百分比)
111
- - `KSE_RELEASE_GATE_MAX_RISK_LEVEL`:`low|medium|high|unknown`(默认 `unknown`)
112
- - `KSE_RELEASE_GATE_MAX_UNMAPPED_RULES`:ontology 业务规则未映射最大允许值
113
- - `KSE_RELEASE_GATE_MAX_UNDECIDED_DECISIONS`:ontology 决策未定最大允许值
114
- - `KSE_RELEASE_GATE_REQUIRE_SCENE_BATCH_PASS`:是否要求 scene package publish-batch gate 必须通过(`true|false`,默认 `true`)
115
- - `KSE_RELEASE_GATE_MAX_SCENE_BATCH_FAILURES`:scene package batch 失败数量最大允许值(默认 `0`)
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
- - `KSE_RELEASE_DRIFT_ENFORCE`:`true|false`(默认 `false`),触发 drift alert 时阻断发布
119
- - `KSE_RELEASE_DRIFT_FAIL_STREAK_MIN`:触发告警的最小连续失败次数(默认 `2`)
120
- - `KSE_RELEASE_DRIFT_HIGH_RISK_SHARE_MIN_PERCENT`:近 5 版 high 风险占比告警阈值(默认 `60`)
121
- - `KSE_RELEASE_DRIFT_HIGH_RISK_SHARE_DELTA_MIN_PERCENT`:短期相对长期 high 风险占比增量阈值(默认 `25`)
122
- - `KSE_RELEASE_DRIFT_PREFLIGHT_BLOCK_RATE_MIN_PERCENT`:近 5 版(有 preflight 信号)blocked 占比告警阈值(默认 `40`)
123
- - `KSE_RELEASE_DRIFT_HARD_GATE_BLOCK_STREAK_MIN`:hard-gate preflight 连续 blocked 告警阈值(最近窗口,默认 `2`)
124
- - `KSE_RELEASE_DRIFT_PREFLIGHT_UNAVAILABLE_STREAK_MIN`:release preflight 连续 unavailable 告警阈值(最近窗口,默认 `2`)
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
- 然后再执行你的正式发布流程(打 tag、push、npm publish、GitHub Release)。
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,8 @@
9
9
  ## 历史版本归档
10
10
 
11
11
  - [发布检查清单](../release-checklist.md)
12
+ - [v3.6.38 发布说明](./v3.6.38.md)
13
+ - [v3.6.37 发布说明](./v3.6.37.md)
12
14
  - [v1.46.2 发布说明](./v1.46.2.md)(历史归档)
13
15
  - [v1.46.2 验证报告](./v1.46.2-validation.md)(历史归档)
14
16
  - [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,19 @@
1
+ # v3.6.38 发布说明
2
+
3
+ 发布日期:2026-03-12
4
+
5
+ ## 重点变化
6
+
7
+ - 新增 steering 自治理审计,检查内容预算、历史堆积、checklist 泄漏、稳定层 Spec 泄漏,以及非规范治理别名。
8
+ - 重构了当前 steering 基线和模板 steering,使其长期保持精简、分层明确、便于刷新。
9
+ - 将 steering 卫生检查接入常规 CI、`prepublishOnly` 和每周 GitHub Actions 定时任务。
10
+
11
+ ## 验证
12
+
13
+ - `npm run audit:steering`
14
+ - `npx jest tests/unit/steering/steering-compliance-checker.test.js tests/unit/scripts/steering-content-audit.test.js tests/unit/scripts/git-managed-gate.test.js --runInBand`
15
+
16
+ ## 发布说明
17
+
18
+ - steering 现在通过周期审计持续自我净化,而不是靠人工想起来时再清理。
19
+ - 稳定层应保持“原则长期有效、内容尽量精简”的状态,避免再回到大而杂的历史堆积。
@@ -1,4 +1,4 @@
1
- const { parseAutoHandoffGateBoolean, normalizeHandoffText } = require('./governance-signals');
1
+ const { parseAutoHandoffGateBoolean, normalizeHandoffText } = require('./governance-signals');
2
2
  const { buildMoquiRegressionRecoverySequenceLines } = require('./moqui-recovery-sequence');
3
3
 
4
4
  function deriveGovernanceRiskLevel(summary) {
@@ -575,7 +575,7 @@ function buildGovernanceRecommendations(summary) {
575
575
  }
576
576
  if (Number.isFinite(weeklyOpsConfigWarningsTotal) && weeklyOpsConfigWarningsTotal > 0) {
577
577
  recommendations.push(
578
- 'Fix invalid weekly ops threshold variables (`KSE_RELEASE_WEEKLY_OPS_*`) and rerun release gates ' +
578
+ 'Fix invalid weekly ops threshold variables (`SCE_RELEASE_WEEKLY_OPS_*`) and rerun release gates ' +
579
579
  'to clear config warnings.'
580
580
  );
581
581
  }
@@ -449,7 +449,7 @@ async function adoptInteractive(projectPath, options) {
449
449
  // Prompt for strategy
450
450
  steeringStrategy = await steeringManager.promptStrategy(detection.steeringDetection);
451
451
 
452
- if (steeringStrategy === 'use-kse') {
452
+ if (steeringStrategy === 'use-sce') {
453
453
  // Backup existing steering files
454
454
  console.log(chalk.blue('📦 Backing up existing steering files...'));
455
455
  const backupResult = await steeringManager.backupSteering(projectPath);
@@ -460,7 +460,7 @@ async function adoptInteractive(projectPath, options) {
460
460
 
461
461
  // Install sce steering files
462
462
  console.log(chalk.blue('📝 Installing sce steering files...'));
463
- const installResult = await steeringManager.installKseSteering(projectPath);
463
+ const installResult = await steeringManager.installSceSteering(projectPath);
464
464
 
465
465
  if (installResult.success) {
466
466
  console.log(chalk.green(`✅ Installed ${installResult.filesInstalled} sce steering file(s)`));
@@ -711,7 +711,7 @@ async function adoptInteractive(projectPath, options) {
711
711
  *
712
712
  * @param {string} projectPath - Project root path
713
713
  */
714
- async function setupKiroMcpConfig(projectPath) {
714
+ async function setupSceMcpConfig(projectPath) {
715
715
  const mcpConfigPath = path.join(projectPath, '.sce', 'settings', 'mcp.json');
716
716
 
717
717
  // Don't overwrite existing config
@@ -767,7 +767,7 @@ async function offerAutomationSetup(projectPath) {
767
767
 
768
768
  // If AI IDE detected, create default MCP settings
769
769
  if (toolDetection.primaryTool === 'SCE') {
770
- await setupKiroMcpConfig(projectPath);
770
+ await setupSceMcpConfig(projectPath);
771
771
  }
772
772
  } catch (toolError) {
773
773
  // Tool detection is optional, don't fail adoption if it errors
@@ -1,4 +1,4 @@
1
- /**
1
+ /**
2
2
  * Autonomous Control CLI Commands
3
3
  */
4
4
 
@@ -8615,7 +8615,7 @@ function buildAutoHandoffRunRecommendations(projectPath, result) {
8615
8615
  observabilityWeeklyOps.config_warning_positive_sessions > 0
8616
8616
  ) {
8617
8617
  push(
8618
- 'Fix invalid weekly ops threshold variables (`KSE_RELEASE_WEEKLY_OPS_*`) and rerun release gates ' +
8618
+ 'Fix invalid weekly ops threshold variables (`SCE_RELEASE_WEEKLY_OPS_*`) and rerun release gates ' +
8619
8619
  'to clear config warnings.'
8620
8620
  );
8621
8621
  }
@@ -13073,7 +13073,7 @@ function buildGovernanceCloseLoopRecommendations(finalAssessment, stopReason, st
13073
13073
  }
13074
13074
  if (reasons.some(item => `${item}`.includes('weekly-ops-config-warnings'))) {
13075
13075
  base.push(
13076
- 'Fix invalid weekly ops threshold variables (`KSE_RELEASE_WEEKLY_OPS_*`) and rerun release gates ' +
13076
+ 'Fix invalid weekly ops threshold variables (`SCE_RELEASE_WEEKLY_OPS_*`) and rerun release gates ' +
13077
13077
  'to clear config warnings.'
13078
13078
  );
13079
13079
  }
@@ -35,7 +35,7 @@ class ContextCollector {
35
35
  }
36
36
 
37
37
  _detectLanguagePreference() {
38
- const lang = `${process.env.KSE_LANG || process.env.LANG || ''}`.toLowerCase();
38
+ const lang = `${process.env.SCE_LANG || process.env.LANG || ''}`.toLowerCase();
39
39
  if (lang.includes('zh')) {
40
40
  return 'zh';
41
41
  }
@@ -60,7 +60,7 @@ class AdoptionConfig {
60
60
  /**
61
61
  * 更新 steering 策略配置
62
62
  *
63
- * @param {string} strategy - 策略 ('use-kse' | 'use-project')
63
+ * @param {string} strategy - 策略 ('use-sce' | 'use-project')
64
64
  * @param {string|null} backupId - 备份 ID(如果有)
65
65
  * @returns {Promise<boolean>} 是否成功
66
66
  */
@@ -152,7 +152,7 @@ class AdoptionConfig {
152
152
  const config = {
153
153
  version: '1.0.0',
154
154
  adoptedAt: new Date().toISOString(),
155
- steeringStrategy: options.steeringStrategy || 'use-kse',
155
+ steeringStrategy: options.steeringStrategy || 'use-sce',
156
156
  multiUserMode: options.multiUserMode || false,
157
157
  ...options
158
158
  };
@@ -21,11 +21,11 @@ class ComplianceCache {
21
21
  /**
22
22
  * Get the default cache file path
23
23
  *
24
- * @returns {string} Path to ~/.kse/steering-check-cache.json
24
+ * @returns {string} Path to ~/.sce/steering-check-cache.json
25
25
  */
26
26
  getDefaultCachePath() {
27
27
  const homeDir = os.homedir();
28
- return path.join(homeDir, '.kse', 'steering-check-cache.json');
28
+ return path.join(homeDir, '.sce', 'steering-check-cache.json');
29
29
  }
30
30
 
31
31
  /**
@@ -65,12 +65,12 @@ class SteeringManager {
65
65
  * 提示用户选择 steering 策略
66
66
  *
67
67
  * @param {Object} detection - detectSteering 的返回结果
68
- * @returns {Promise<string>} 选择的策略 ('use-kse' | 'use-project')
68
+ * @returns {Promise<string>} 选择的策略 ('use-sce' | 'use-project')
69
69
  */
70
70
  async promptStrategy(detection) {
71
71
  if (!detection.hasExistingSteering) {
72
72
  // 没有现有 steering 文件,默认使用 sce
73
- return 'use-kse';
73
+ return 'use-sce';
74
74
  }
75
75
 
76
76
  console.log('\n⚠️ Steering Conflict Detected');
@@ -94,7 +94,7 @@ class SteeringManager {
94
94
  choices: [
95
95
  {
96
96
  name: 'Use sce steering (backup existing files) - Recommended for new sce users',
97
- value: 'use-kse'
97
+ value: 'use-sce'
98
98
  },
99
99
  {
100
100
  name: 'Keep existing steering (skip sce steering) - For projects with custom steering rules',
@@ -167,7 +167,7 @@ class SteeringManager {
167
167
  * @param {string} projectPath - 项目根目录路径
168
168
  * @returns {Promise<Object>} 安装结果
169
169
  */
170
- async installKseSteering(projectPath) {
170
+ async installSceSteering(projectPath) {
171
171
  const steeringPath = path.join(projectPath, this.steeringDir);
172
172
  const templatePath = path.join(__dirname, '../../template/.sce/steering');
173
173
 
@@ -97,8 +97,7 @@ class TaskClaimer {
97
97
  return [];
98
98
  }
99
99
 
100
- // Accept both legacy and current section headers to keep existing specs readable.
101
- const markerHeaderRegex = /^\s*##\s+(?:(?:sce|kse)\s+)?Status\s+Markers\s*$/i;
100
+ const markerHeaderRegex = /^\s*##\s+(?:sce\s+)?Status\s+Markers\s*$/i;
102
101
  const sectionHeaderRegex = /^\s*##\s+/;
103
102
 
104
103
  const markerLine = lines.findIndex((line) => markerHeaderRegex.test(String(line || '')));
@@ -92,7 +92,7 @@ class WorkspaceContextResolver {
92
92
  * @param {string} dirPath - Directory path to check
93
93
  * @returns {Promise<boolean>} True if directory contains .sce/ structure
94
94
  */
95
- async isValidKseDirectory(dirPath) {
95
+ async isValidSceDirectory(dirPath) {
96
96
  try {
97
97
  const kiroPath = path.join(dirPath, '.sce');
98
98
  const exists = await fs.pathExists(kiroPath);
@@ -184,7 +184,7 @@ class WorkspaceContextResolver {
184
184
  const targetDir = currentDir || process.cwd();
185
185
 
186
186
  // Check if it's a valid sce directory
187
- const isValid = await this.isValidKseDirectory(targetDir);
187
+ const isValid = await this.isValidSceDirectory(targetDir);
188
188
  if (!isValid) {
189
189
  return false;
190
190
  }
@@ -210,7 +210,7 @@ class WorkspaceContextResolver {
210
210
 
211
211
  if (!workspace) {
212
212
  const targetDir = currentDir || process.cwd();
213
- const isValid = await this.isValidKseDirectory(targetDir);
213
+ const isValid = await this.isValidSceDirectory(targetDir);
214
214
 
215
215
  if (isValid) {
216
216
  throw new Error(
@@ -48,62 +48,20 @@ class WorkspaceStateManager {
48
48
  return path.join(homeDir, '.sce', 'workspace-state.json');
49
49
  }
50
50
 
51
- /**
52
- * Get the legacy state file path used by prior versions
53
- *
54
- * @returns {string} Path to ~/.kse/workspace-state.json
55
- */
56
- getLegacyStatePath() {
57
- const homeDir = os.homedir();
58
- return path.join(homeDir, '.kse', 'workspace-state.json');
59
- }
60
-
61
- /**
62
- * Whether state manager is operating on the default state path.
63
- *
64
- * Automatic legacy migration should only run in this mode.
65
- *
66
- * @returns {boolean}
67
- */
68
- isDefaultStatePath() {
69
- return path.resolve(this.statePath) === path.resolve(this.getDefaultStatePath());
70
- }
71
-
72
51
  /**
73
52
  * Load workspace state from disk
74
53
  *
75
- * Supports automatic migration from legacy format (workspaces.json + config.json)
76
- *
77
54
  * @returns {Promise<boolean>} True if loaded successfully
78
55
  */
79
56
  async load() {
80
57
  try {
81
- // Try loading new format
82
58
  const exists = await fs.pathExists(this.statePath);
83
-
84
59
  if (exists) {
85
60
  await this.loadNewFormat();
86
61
  this.loaded = true;
87
62
  return true;
88
63
  }
89
64
 
90
- // Migrate legacy single-file state from ~/.kse/workspace-state.json
91
- if (await this.hasLegacyStateFile()) {
92
- console.log('Migrating workspace state to new .sce directory...');
93
- await this.migrateFromLegacyStateFile();
94
- await this.loadNewFormat();
95
- this.loaded = true;
96
- return true;
97
- }
98
-
99
- // Check for legacy format and migrate
100
- if (await this.hasLegacyFiles()) {
101
- console.log('Migrating workspace configuration to new format...');
102
- await this.migrateFromLegacy();
103
- this.loaded = true;
104
- return true;
105
- }
106
-
107
65
  // Initialize empty state
108
66
  this.state = {
109
67
  version: '1.0',
@@ -160,128 +118,6 @@ class WorkspaceStateManager {
160
118
  };
161
119
  }
162
120
 
163
- /**
164
- * Check if legacy configuration files exist
165
- *
166
- * @private
167
- * @returns {Promise<boolean>}
168
- */
169
- async hasLegacyFiles() {
170
- if (!this.isDefaultStatePath()) {
171
- return false;
172
- }
173
-
174
- const homeDir = os.homedir();
175
- const legacyWorkspacesPath = path.join(homeDir, '.kse', 'workspaces.json');
176
- const legacyConfigPath = path.join(homeDir, '.kse', 'config.json');
177
-
178
- const workspacesExists = await fs.pathExists(legacyWorkspacesPath);
179
- const configExists = await fs.pathExists(legacyConfigPath);
180
-
181
- return workspacesExists || configExists;
182
- }
183
-
184
- /**
185
- * Check whether legacy single-file state exists
186
- *
187
- * @private
188
- * @returns {Promise<boolean>}
189
- */
190
- async hasLegacyStateFile() {
191
- if (!this.isDefaultStatePath()) {
192
- return false;
193
- }
194
-
195
- const legacyStatePath = this.getLegacyStatePath();
196
- return fs.pathExists(legacyStatePath);
197
- }
198
-
199
- /**
200
- * Copy legacy single-file state into the new default location.
201
- *
202
- * @private
203
- * @returns {Promise<void>}
204
- */
205
- async migrateFromLegacyStateFile() {
206
- const legacyStatePath = this.getLegacyStatePath();
207
- const stateDir = path.dirname(this.statePath);
208
- await fs.ensureDir(stateDir);
209
- await fs.copy(legacyStatePath, this.statePath);
210
- }
211
-
212
- /**
213
- * Migrate from legacy format (workspaces.json + config.json)
214
- *
215
- * @private
216
- */
217
- async migrateFromLegacy() {
218
- const homeDir = os.homedir();
219
- const legacyWorkspacesPath = path.join(homeDir, '.kse', 'workspaces.json');
220
- const legacyConfigPath = path.join(homeDir, '.kse', 'config.json');
221
-
222
- // Load legacy workspaces
223
- let legacyWorkspaces = [];
224
- if (await fs.pathExists(legacyWorkspacesPath)) {
225
- const content = await fs.readFile(legacyWorkspacesPath, 'utf8');
226
- const data = JSON.parse(content);
227
- legacyWorkspaces = data.workspaces || [];
228
- }
229
-
230
- // Load legacy config
231
- let legacyActiveWorkspace = null;
232
- let legacyPreferences = {};
233
- if (await fs.pathExists(legacyConfigPath)) {
234
- const content = await fs.readFile(legacyConfigPath, 'utf8');
235
- const data = JSON.parse(content);
236
- legacyActiveWorkspace = data.active_workspace || null;
237
- legacyPreferences = data.preferences || {};
238
- }
239
-
240
- // Merge into new format
241
- this.state.activeWorkspace = legacyActiveWorkspace;
242
- this.state.workspaces = new Map();
243
-
244
- for (const workspaceData of legacyWorkspaces) {
245
- const workspace = Workspace.fromDict(workspaceData);
246
- this.state.workspaces.set(workspace.name, workspace);
247
- }
248
-
249
- this.state.preferences = {
250
- autoDetectWorkspace: legacyPreferences.auto_detect_workspace ?? true,
251
- confirmDestructiveOperations: legacyPreferences.confirm_destructive_operations ?? true
252
- };
253
-
254
- // Save to new format
255
- await this.save();
256
-
257
- // Backup legacy files
258
- await this.backupLegacyFiles();
259
- }
260
-
261
- /**
262
- * Backup legacy configuration files
263
- *
264
- * @private
265
- */
266
- async backupLegacyFiles() {
267
- const homeDir = os.homedir();
268
- const legacyWorkspacesPath = path.join(homeDir, '.kse', 'workspaces.json');
269
- const legacyConfigPath = path.join(homeDir, '.kse', 'config.json');
270
- const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
271
-
272
- if (await fs.pathExists(legacyWorkspacesPath)) {
273
- const backupPath = path.join(homeDir, '.kse', `workspaces.json.backup-${timestamp}`);
274
- await fs.copy(legacyWorkspacesPath, backupPath);
275
- await fs.remove(legacyWorkspacesPath);
276
- }
277
-
278
- if (await fs.pathExists(legacyConfigPath)) {
279
- const backupPath = path.join(homeDir, '.kse', `config.json.backup-${timestamp}`);
280
- await fs.copy(legacyConfigPath, backupPath);
281
- await fs.remove(legacyConfigPath);
282
- }
283
- }
284
-
285
121
  /**
286
122
  * Save workspace state to disk (atomic operation)
287
123
  *
@@ -4,7 +4,7 @@ const FIXTURE_ROOT = 'tests/fixtures/moqui-core-regression/workspace/.sce';
4
4
  const REQUIRED_TRACKED_FILES = [
5
5
  `${FIXTURE_ROOT}/specs/60-10-moqui-core-order-query/custom/scene-package.json`,
6
6
  `${FIXTURE_ROOT}/specs/60-10-moqui-core-order-query/custom/scene.yaml`,
7
- `${FIXTURE_ROOT}/templates/scene-packages/kse.scene--erp-order-query-read--0.1.0/scene-package.json`,
7
+ `${FIXTURE_ROOT}/templates/scene-packages/sce.scene--erp-order-query-read--0.1.0/scene-package.json`,
8
8
  ];
9
9
  const DISALLOWED_TRACKED_PREFIXES = [
10
10
  `${FIXTURE_ROOT}/reports/`,
@@ -303,7 +303,7 @@ function _buildAdoptionConfig(existing, nowIso, sceVersion) {
303
303
  adoptedAt,
304
304
  steeringStrategy: typeof base.steeringStrategy === 'string' && base.steeringStrategy.trim()
305
305
  ? base.steeringStrategy
306
- : 'use-kse',
306
+ : 'use-sce',
307
307
  multiUserMode: base.multiUserMode === true,
308
308
  runtimePolicy: {
309
309
  agent_parity_permissions: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scene-capability-engine",
3
- "version": "3.6.36",
3
+ "version": "3.6.38",
4
4
  "description": "SCE (Scene Capability Engine) - A CLI tool and npm package for spec-driven development with AI coding assistants.",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -38,6 +38,8 @@
38
38
  "test:skip-audit": "node scripts/check-skip-allowlist.js",
39
39
  "test:sce-tracking": "node scripts/check-sce-tracking.js",
40
40
  "test:brand-consistency": "node scripts/check-branding-consistency.js",
41
+ "audit:steering": "node scripts/steering-content-audit.js --fail-on-error",
42
+ "report:steering-audit": "node scripts/steering-content-audit.js --json",
41
43
  "test:watch": "npx jest --watch",
42
44
  "coverage": "npx jest --coverage",
43
45
  "report:moqui-metadata": "node scripts/moqui-metadata-extract.js --json",
@@ -76,7 +78,7 @@
76
78
  "gate:release-asset-integrity": "node scripts/release-asset-integrity-check.js",
77
79
  "report:release-risk-remediation": "node scripts/release-risk-remediation-bundle.js --json",
78
80
  "report:moqui-core-regression": "node scripts/moqui-core-regression-suite.js --json",
79
- "prepublishOnly": "npm run test:release && npm run test:skip-audit && npm run test:sce-tracking && npm run test:brand-consistency && npm run gate:git-managed && npm run gate:errorbook-registry-health && npm run gate:errorbook-release && npm run report:interactive-governance -- --fail-on-alert",
81
+ "prepublishOnly": "npm run test:release && npm run test:skip-audit && npm run test:sce-tracking && npm run test:brand-consistency && npm run audit:steering && npm run gate:git-managed && npm run gate:errorbook-registry-health && npm run gate:errorbook-release && npm run report:interactive-governance -- --fail-on-alert",
80
82
  "publish:manual": "npm publish --access public",
81
83
  "install-global": "npm install -g .",
82
84
  "uninstall-global": "npm uninstall -g scene-capability-engine"
@@ -45,7 +45,7 @@ This project uses **Spec-driven development** - a structured approach where:
45
45
 
46
46
  ### Workspace Management
47
47
  - `sce workspace create/list/switch/info/remove` — Manage multiple sce projects
48
- - Global state: `~/.kse/workspace-state.json`
48
+ - Global state: `~/.sce/workspace-state.json`
49
49
 
50
50
  ### Environment Configuration
51
51
  - `sce env list/switch/info/register/unregister/rollback/verify/run` — Multi-environment management