scene-capability-engine 3.3.18 → 3.3.21

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,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.3.21] - 2026-02-27
11
+
12
+ ### Fixed
13
+ - `git-managed-gate` now supports CI tag/detached-HEAD release workflows by default:
14
+ - In CI context (`CI=1` or `GITHUB_ACTIONS=1`), branch/upstream sync checks are relaxed to avoid false blocking.
15
+ - Local release checks remain strict (clean worktree + branch/upstream sync).
16
+ - Added strict CI override: `SCE_GIT_MANAGEMENT_STRICT_CI=1` (or `--strict-ci`) for full enforcement in CI.
17
+
18
+ ### Changed
19
+ - Added CI-aware flags for `git-managed-gate`:
20
+ - `--ci-context` / `--no-ci-context`
21
+ - `--strict-ci` / `--no-strict-ci`
22
+ - Updated release and command documentation to clarify local-vs-CI gate behavior.
23
+
24
+ ## [3.3.19] - 2026-02-26
25
+
26
+ ### Added
27
+ - Errorbook release gate command and script:
28
+ - `sce errorbook release-gate --min-risk <low|medium|high> [--include-verified] [--fail-on-block]`
29
+ - `node scripts/errorbook-release-gate.js --fail-on-block`
30
+ - `package.json` script alias:
31
+ - `npm run gate:errorbook-release`
32
+ - Git managed release gate script and alias:
33
+ - `node scripts/git-managed-gate.js --fail-on-violation`
34
+ - `npm run gate:git-managed`
35
+
36
+ ### Changed
37
+ - `prepublishOnly` now enforces git-managed gate + errorbook release gate before interactive governance checks.
38
+ - Studio gate failures are now auto-recorded into `.sce/errorbook` as `candidate` entries (tagged `release-blocker`) to avoid manual reminders.
39
+ - Studio release preflight now includes `git-managed-gate` and `errorbook-release-gate` as required gate steps when scripts are available.
40
+
10
41
  ## [3.3.18] - 2026-02-26
11
42
 
12
43
  ### Added
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  > **⚠️ Important Clarification**: `scene-capability-engine` (`sce`) is an **npm package and CLI tool** for spec-driven development.
7
7
  > Primary command is `sce`. Compatibility aliases are preserved for migration.
8
8
 
9
- **A context provider for AI coding tools** - Structure your project requirements, design, and tasks so AI assistants can help you build better software.
9
+ **SCE (Scene Capability Engine) is an ontology-aware scene orchestration engine for AI agents** across plan, generate, patch, verify, and release workflows.
10
10
 
11
11
  **🚀 NEW: Autonomous Control** - Let AI independently manage entire development workflows from requirements to delivery.
12
12
 
@@ -16,7 +16,7 @@ English | [简体中文](README.zh.md)
16
16
 
17
17
  ## What is sce?
18
18
 
19
- **SCE (Scene Capability Engine) is a context management system for AI-assisted development.** It helps you organize project information into structured "Specs" (Requirements → Design → Tasks) that AI tools can understand and use effectively.
19
+ **SCE (Scene Capability Engine) is an ontology-aware scene orchestration engine for AI-assisted development.** It organizes project information into structured "Specs" (Requirements → Design → Tasks) and routes execution through plan generate → patch → verify → release workflows.
20
20
 
21
21
  Think of sce as a **librarian for your AI assistant** - it organizes and presents project context so your AI tool knows exactly what you're building, why, and how.
22
22
 
@@ -69,13 +69,16 @@ graph LR
69
69
  # 1) Adopt sce in current repo
70
70
  sce adopt
71
71
 
72
- # 2) Generate Spec workflow draft
73
- sce spec bootstrap --name 01-00-demo-feature --non-interactive
72
+ # 2) Open primary scene session
73
+ sce studio plan --scene scene.demo --from-chat session-demo --goal "demo workflow bootstrap" --json
74
74
 
75
- # 3) Generate KPI input sample
75
+ # 3) Generate Spec workflow draft
76
+ sce spec bootstrap --name 01-00-demo-feature --scene scene.demo --non-interactive
77
+
78
+ # 4) Generate KPI input sample
76
79
  sce value metrics sample --out ./kpi-input.json --json
77
80
 
78
- # 4) Produce machine-readable KPI snapshot
81
+ # 5) Produce machine-readable KPI snapshot
79
82
  sce value metrics snapshot --input ./kpi-input.json --json
80
83
  ```
81
84
 
@@ -559,13 +562,18 @@ sce auto schema check --json # Check autonomous archive schema compatibility
559
562
  sce auto schema migrate --apply --json # Backfill/migrate schema_version for autonomous archives
560
563
 
561
564
  # Spec workflow (recommended)
562
- sce spec bootstrap --name <spec> --non-interactive # Generate requirements/design/tasks draft
563
- sce spec pipeline run --spec <spec> # Run staged workflow for one Spec
564
- sce spec gate run --spec <spec> --json # Run standardized Spec gate checks
565
+ sce spec bootstrap --name <spec> --scene <scene-id> --non-interactive # Generate draft and bind as scene child session
566
+ sce spec pipeline run --spec <spec> --scene <scene-id> # Run pipeline and auto-archive spec child session
567
+ sce spec gate run --spec <spec> --scene <scene-id> --json # Run gate and auto-archive spec child session
565
568
  sce spec bootstrap --specs "<spec-a,spec-b>" --max-parallel <N> # Multi-Spec defaults to orchestrate
566
569
  sce spec pipeline run --specs "<spec-a,spec-b>" --max-parallel <N> # Multi-Spec defaults to orchestrate
567
570
  sce spec gate run --specs "<spec-a,spec-b>" --max-parallel <N> # Multi-Spec defaults to orchestrate
568
571
 
572
+ # Spec session governance default
573
+ # - spec bootstrap|pipeline run|gate run must bind to an active scene primary session.
574
+ # - Use --scene <scene-id> explicitly when multiple active scenes exist.
575
+ # - Multi-Spec orchestrate fallback (--specs ...) keeps the same scene binding and archives per-spec child sessions.
576
+
569
577
  # Context management
570
578
  sce context export <spec-name> # Export context for AI tools
571
579
  sce prompt generate <spec> <task> # Generate task-specific prompt
@@ -739,7 +747,8 @@ MIT License - see [LICENSE](LICENSE) file for details.
739
747
  ```bash
740
748
  npm install -g scene-capability-engine
741
749
  sce adopt
742
- sce spec bootstrap --name 01-00-my-first-feature --non-interactive
750
+ sce studio plan --scene scene.demo --from-chat session-demo --goal "bootstrap first feature" --json
751
+ sce spec bootstrap --name 01-00-my-first-feature --scene scene.demo --non-interactive
743
752
  ```
744
753
 
745
754
  ---
package/README.zh.md CHANGED
@@ -6,7 +6,7 @@
6
6
  > **⚠️ 重要说明**: `scene-capability-engine`(`sce`)是一个 **npm 包和 CLI 工具**,用于 Spec 驱动开发。
7
7
  > 主命令为 `sce`,兼容别名保留用于迁移。
8
8
 
9
- **AI 编码工具的上下文提供者** - 结构化你的项目需求、设计和任务,让 AI 助手帮你构建更好的软件。
9
+ **SCE(场景能力引擎)是一个面向 AI Agent 的本体感知场景编排引擎**,覆盖 plan、generate、patch、verify、release 全流程。
10
10
 
11
11
  [English](README.md) | 简体中文
12
12
 
@@ -14,7 +14,7 @@
14
14
 
15
15
  ## 什么是 sce?
16
16
 
17
- **SCE(场景能力引擎)是一个 AI 辅助开发的上下文管理系统。** 它帮助你将项目信息组织成结构化的 "Spec"(需求 → 设计 → 任务),让 AI 工具能够理解和有效使用。
17
+ **SCE(场景能力引擎)是一个面向 AI 辅助开发的本体感知场景编排引擎。** 它将项目信息组织成结构化 Spec(需求 → 设计 → 任务),并通过 plan → generate → patch → verify → release 的流程路由执行。
18
18
 
19
19
  把 sce 想象成 **AI 助手的图书管理员** - 它组织和呈现项目上下文,让你的 AI 工具准确知道你在构建什么、为什么构建以及如何构建。
20
20
 
@@ -67,13 +67,16 @@ graph LR
67
67
  # 1) 在当前仓库启用 sce
68
68
  sce adopt
69
69
 
70
- # 2) 生成 Spec 工作流草稿
71
- sce spec bootstrap --name 01-00-demo-feature --non-interactive
70
+ # 2) 打开主场景会话
71
+ sce studio plan --scene scene.demo --from-chat session-demo --goal "demo workflow bootstrap" --json
72
72
 
73
- # 3) 生成 KPI 输入样例
73
+ # 3) 生成 Spec 工作流草稿
74
+ sce spec bootstrap --name 01-00-demo-feature --scene scene.demo --non-interactive
75
+
76
+ # 4) 生成 KPI 输入样例
74
77
  sce value metrics sample --out ./kpi-input.json --json
75
78
 
76
- # 4) 产出机器可读 KPI 快照
79
+ # 5) 产出机器可读 KPI 快照
77
80
  sce value metrics snapshot --input ./kpi-input.json --json
78
81
  ```
79
82
 
@@ -473,13 +476,18 @@ sce auto schema check --json # 检查自治归档 schema 兼容性
473
476
  sce auto schema migrate --apply --json # 回填/迁移自治归档 schema_version
474
477
 
475
478
  # Spec 工作流(推荐)
476
- sce spec bootstrap --name <spec> --non-interactive # 生成 requirements/design/tasks 初稿
477
- sce spec pipeline run --spec <spec> # 对单个 Spec 执行分阶段流程
478
- sce spec gate run --spec <spec> --json # 执行标准化 Spec 闸口检查
479
+ sce spec bootstrap --name <spec> --scene <scene-id> --non-interactive # 生成初稿并绑定 scene 子会话
480
+ sce spec pipeline run --spec <spec> --scene <scene-id> # 执行分阶段流程并自动归档子会话
481
+ sce spec gate run --spec <spec> --scene <scene-id> --json # 执行闸口并自动归档子会话
479
482
  sce spec bootstrap --specs "<spec-a,spec-b>" --max-parallel <N> # 多 Spec 默认转 orchestrate
480
483
  sce spec pipeline run --specs "<spec-a,spec-b>" --max-parallel <N> # 多 Spec 默认转 orchestrate
481
484
  sce spec gate run --specs "<spec-a,spec-b>" --max-parallel <N> # 多 Spec 默认转 orchestrate
482
485
 
486
+ # Spec 会话治理默认规则
487
+ # - spec bootstrap|pipeline run|gate run 必须绑定活动中的 scene 主会话
488
+ # - 当存在多个活动 scene 时,必须显式传入 --scene <scene-id>
489
+ # - 多 Spec orchestrate 回退路径同样按 scene 绑定并写入每个 spec 的子会话归档
490
+
483
491
  # 上下文管理
484
492
  sce context export <spec-name> # 为 AI 工具导出上下文
485
493
  sce prompt generate <spec> <task> # 生成任务特定提示
@@ -546,7 +554,8 @@ sce orchestrate run --specs "<spec列表>" --max-parallel <N> # 启动多 Agent
546
554
  sce orchestrate status # 查看编排进度
547
555
  sce orchestrate stop # 停止所有子 Agent
548
556
 
549
- # 说明:当使用 --specs 调用 sce spec bootstrap/pipeline run/gate run 时,会默认转到 orchestrate 模式
557
+ # 说明:当使用 --specs 调用 sce spec bootstrap/pipeline run/gate run 时,会默认转到 orchestrate 模式,
558
+ # 且仍要求绑定活动 scene 主会话(多活动 scene 时必须显式 --scene)
550
559
 
551
560
  # 发布基线(CI 默认)
552
561
  sce auto handoff preflight-check --require-pass --json # 硬门禁:preflight 不通过则阻断发布
@@ -631,7 +640,8 @@ MIT 许可证 - 详见 [LICENSE](LICENSE) 文件。
631
640
  ```bash
632
641
  npm install -g scene-capability-engine
633
642
  sce adopt
634
- sce spec bootstrap --name 01-00-my-first-feature --non-interactive
643
+ sce studio plan --scene scene.demo --from-chat session-demo --goal "bootstrap first feature" --json
644
+ sce spec bootstrap --name 01-00-my-first-feature --scene scene.demo --non-interactive
635
645
  ```
636
646
 
637
647
  ---
@@ -49,17 +49,20 @@ sce doctor
49
49
  ### Spec Management
50
50
 
51
51
  ```bash
52
+ # Ensure an active scene primary session exists first
53
+ sce studio plan --scene scene.customer-order-inventory --from-chat session-20260226 --goal "spec delivery cycle" --json
54
+
52
55
  # Legacy low-level: create spec directory only
53
56
  sce create-spec 01-00-feature-name
54
57
 
55
58
  # Bootstrap full Spec draft (requirements/design/tasks)
56
- sce spec bootstrap --name 01-00-feature-name --non-interactive
59
+ sce spec bootstrap --name 01-00-feature-name --scene scene.customer-order-inventory --non-interactive
57
60
 
58
61
  # Run pipeline for one Spec
59
- sce spec pipeline run --spec 01-00-feature-name
62
+ sce spec pipeline run --spec 01-00-feature-name --scene scene.customer-order-inventory
60
63
 
61
64
  # Run gate for one Spec
62
- sce spec gate run --spec 01-00-feature-name --json
65
+ sce spec gate run --spec 01-00-feature-name --scene scene.customer-order-inventory --json
63
66
 
64
67
  # Multi-Spec mode defaults to orchestrate routing
65
68
  sce spec bootstrap --specs "spec-a,spec-b" --max-parallel 3
@@ -70,6 +73,11 @@ sce spec gate run --specs "spec-a,spec-b" --max-parallel 3
70
73
  sce status --verbose
71
74
  ```
72
75
 
76
+ Spec session governance:
77
+ - `spec bootstrap|pipeline run|gate run` must bind to an active scene primary session (`--scene <scene-id>` or implicit binding from latest/unique active scene).
78
+ - When multiple active scenes exist, you must pass `--scene` explicitly.
79
+ - Multi-Spec orchestrate fallback (`--specs ...`) follows the same scene binding and writes per-spec child-session archive records.
80
+
73
81
  ### Value Metrics
74
82
 
75
83
  ```bash
@@ -152,6 +160,11 @@ sce session snapshot release-20260224 --summary "post-gate checkpoint" --payload
152
160
  sce session show release-20260224 --json
153
161
  ```
154
162
 
163
+ Session governance defaults:
164
+ - `1 scene = 1 primary session` (managed by `studio plan --scene ...`)
165
+ - `spec` runs can bind as child sessions (`spec bootstrap|pipeline --scene <scene-id>`)
166
+ - successful `studio release` auto-archives current scene session and opens next cycle session
167
+
155
168
  ### Watch Mode
156
169
 
157
170
  ```bash
@@ -347,6 +360,12 @@ sce errorbook deprecate <entry-id> --reason "superseded by v2 policy" --json
347
360
 
348
361
  # Requalify deprecated entry after remediation review
349
362
  sce errorbook requalify <entry-id> --status verified --json
363
+
364
+ # Release hard gate (default in prepublish and studio release preflight)
365
+ sce errorbook release-gate --min-risk high --fail-on-block --json
366
+
367
+ # Git managed hard gate (default in prepublish and studio release preflight)
368
+ node scripts/git-managed-gate.js --fail-on-violation --json
350
369
  ```
351
370
 
352
371
  Curated quality policy (`宁缺毋滥,优胜略汰`) defaults:
@@ -360,14 +379,25 @@ Curated quality policy (`宁缺毋滥,优胜略汰`) defaults:
360
379
  - `quality_score >= 75`
361
380
  - `deprecate` requires explicit `--reason` to preserve elimination traceability.
362
381
  - `requalify` only accepts `candidate|verified`; `promoted` must still go through `promote` gate.
382
+ - `release-gate` blocks release when unresolved high-risk `candidate` entries remain.
383
+ - `git-managed-gate` blocks release when:
384
+ - worktree has uncommitted changes
385
+ - branch has no upstream
386
+ - branch is ahead/behind upstream
387
+ - upstream is not a GitHub/GitLab remote (when such remotes exist)
388
+ - If project has no GitHub/GitLab remote, gate passes by default (can hard-enforce with `--no-allow-no-remote` or `SCE_GIT_MANAGEMENT_ALLOW_NO_REMOTE=0`).
389
+ - In CI/tag detached-HEAD context (`CI=1` or `GITHUB_ACTIONS=1`), branch/upstream sync checks are relaxed by default.
390
+ Use `SCE_GIT_MANAGEMENT_STRICT_CI=1` (or `--strict-ci`) to enforce full local-level branch checks in CI.
363
391
 
364
392
  ### Studio Workflow
365
393
 
366
394
  ```bash
367
- # Build a plan from chat/session context
368
- sce studio plan --from-chat session-20260226 --goal "customer+order+inventory demo" --json
395
+ # Build a plan from chat/session context (scene is mandatory and becomes the primary session anchor)
396
+ sce studio plan --scene scene.customer-order-inventory --from-chat session-20260226 --goal "customer+order+inventory demo" --json
369
397
 
370
- # Generate patch bundle metadata for a target scene
398
+ # Generate patch bundle metadata (scene is inherited from plan)
399
+ sce studio generate --target 331 --json
400
+ # Optional explicit scene check (must match planned scene)
371
401
  sce studio generate --scene scene.customer-order-inventory --target 331 --json
372
402
 
373
403
  # Apply generated patch metadata
@@ -395,6 +425,8 @@ SCE_STUDIO_REQUIRE_AUTH=1 SCE_STUDIO_AUTH_PASSWORD=top-secret sce studio apply -
395
425
  ```
396
426
 
397
427
  Stage guardrails are enforced by default:
428
+ - `plan` requires `--scene`; SCE binds one active primary session per scene
429
+ - successful `release` auto-archives current scene session and auto-opens the next scene cycle session
398
430
  - `generate` requires `plan`
399
431
  - `apply` requires `generate`
400
432
  - `verify` requires `apply`
@@ -402,8 +434,9 @@ Stage guardrails are enforced by default:
402
434
 
403
435
  Studio gate execution defaults:
404
436
  - `verify --profile standard` runs executable gates (unit test script when available, interactive governance report when present, scene package publish-batch dry-run when handoff manifest exists)
405
- - `release --profile standard` runs executable release preflight (npm pack dry-run, weekly ops gate when summary exists, release asset integrity when evidence directory exists, scene package publish-batch ontology gate, handoff capability matrix gate)
437
+ - `release --profile standard` runs executable release preflight (npm pack dry-run, git managed gate, errorbook release gate, weekly ops gate when summary exists, release asset integrity when evidence directory exists, scene package publish-batch ontology gate, handoff capability matrix gate)
406
438
  - `verify/release --profile strict` fails when any required gate step is skipped (for example missing manifest/evidence/scripts)
439
+ - Required gate failures are auto-recorded into `.sce/errorbook` as `candidate` entries (tagged `release-blocker`) for follow-up triage.
407
440
 
408
441
  Authorization model (optional, policy-driven):
409
442
  - Enable policy: `SCE_STUDIO_REQUIRE_AUTH=1`
@@ -1662,18 +1695,24 @@ sce --version
1662
1695
  ### Starting a New Feature
1663
1696
 
1664
1697
  ```bash
1698
+ # 0. Open a scene primary session
1699
+ sce studio plan --scene scene.customer-order-inventory --from-chat session-20260226 --goal "new feature delivery" --json
1700
+
1665
1701
  # 1. Bootstrap spec draft
1666
- sce spec bootstrap --name 01-00-my-feature --non-interactive
1702
+ sce spec bootstrap --name 01-00-my-feature --scene scene.customer-order-inventory --non-interactive
1667
1703
 
1668
1704
  # 2. Run spec pipeline
1669
- sce spec pipeline run --spec 01-00-my-feature
1705
+ sce spec pipeline run --spec 01-00-my-feature --scene scene.customer-order-inventory
1706
+
1707
+ # 3. Run spec gate
1708
+ sce spec gate run --spec 01-00-my-feature --scene scene.customer-order-inventory --json
1670
1709
 
1671
- # 3. Export context
1710
+ # 4. Export context
1672
1711
  sce context export 01-00-my-feature
1673
1712
 
1674
- # 4. Work on tasks...
1713
+ # 5. Work on tasks...
1675
1714
 
1676
- # 5. Sync progress
1715
+ # 6. Sync progress
1677
1716
  sce workspace sync
1678
1717
  ```
1679
1718
 
@@ -95,12 +95,18 @@ rg -n "github.com/scene-capability-engine/sce" README.md README.zh.md docs START
95
95
  ```bash
96
96
  git status -sb
97
97
  git log --oneline -n 15
98
+
99
+ # Mandatory managed-repo gate (default in prepublish/release preflight)
100
+ node scripts/git-managed-gate.js --fail-on-violation --json
98
101
  ```
99
102
 
100
103
  Verify:
101
104
 
102
105
  - Working tree is clean.
103
106
  - Commits are logically grouped and messages are release-ready.
107
+ - If GitHub/GitLab remote exists, current branch is upstream-tracked and fully synced (ahead=0, behind=0).
108
+ - If customer has no GitHub/GitLab, gate can be bypassed by policy (`SCE_GIT_MANAGEMENT_ALLOW_NO_REMOTE=1`, default).
109
+ - In CI/tag detached-HEAD contexts, branch/upstream sync checks are relaxed by default; enforce strict mode with `SCE_GIT_MANAGEMENT_STRICT_CI=1` when needed.
104
110
 
105
111
  ---
106
112
 
@@ -80,12 +80,18 @@ rg -n "github.com/scene-capability-engine/sce" README.md README.zh.md docs START
80
80
  ```bash
81
81
  git status -sb
82
82
  git log --oneline -n 15
83
+
84
+ # 强制托管门禁(prepublish/release preflight 默认执行)
85
+ node scripts/git-managed-gate.js --fail-on-violation --json
83
86
  ```
84
87
 
85
88
  确认:
86
89
 
87
90
  - 工作区干净;
88
91
  - 提交分组清晰、提交信息可直接用于发布记录。
92
+ - 若配置了 GitHub/GitLab 远端:当前分支必须已设置 upstream 且与远端完全同步(ahead=0, behind=0)。
93
+ - 若客户确实没有 GitHub/GitLab:可通过策略放行(`SCE_GIT_MANAGEMENT_ALLOW_NO_REMOTE=1`,默认开启)。
94
+ - 在 CI/tag 的 detached HEAD 场景下,默认放宽分支/upstream 同步检查;如需强制严格校验,设置 `SCE_GIT_MANAGEMENT_STRICT_CI=1`。
89
95
 
90
96
  ---
91
97
 
@@ -37,6 +37,17 @@ const ONTOLOGY_TAG_ALIASES = Object.freeze({
37
37
  action_chain: 'execution_flow'
38
38
  });
39
39
  const DEFAULT_PROMOTE_MIN_QUALITY = 75;
40
+ const ERRORBOOK_RISK_LEVELS = Object.freeze(['low', 'medium', 'high']);
41
+ const HIGH_RISK_SIGNAL_TAGS = Object.freeze([
42
+ 'release-blocker',
43
+ 'security',
44
+ 'auth',
45
+ 'payment',
46
+ 'data-loss',
47
+ 'integrity',
48
+ 'compliance',
49
+ 'incident'
50
+ ]);
40
51
 
41
52
  function resolveErrorbookPaths(projectPath = process.cwd()) {
42
53
  const baseDir = path.join(projectPath, '.sce', 'errorbook');
@@ -458,6 +469,117 @@ function scoreSearchMatch(entry, queryTokens) {
458
469
  return Number(score.toFixed(3));
459
470
  }
460
471
 
472
+ function normalizeRiskLevel(value, fallback = 'high') {
473
+ const normalized = normalizeText(`${value || ''}`).toLowerCase();
474
+ if (!normalized) {
475
+ return fallback;
476
+ }
477
+ if (!ERRORBOOK_RISK_LEVELS.includes(normalized)) {
478
+ throw new Error(`risk level must be one of: ${ERRORBOOK_RISK_LEVELS.join(', ')}`);
479
+ }
480
+ return normalized;
481
+ }
482
+
483
+ function riskRank(level) {
484
+ const normalized = normalizeRiskLevel(level, 'high');
485
+ if (normalized === 'high') {
486
+ return 3;
487
+ }
488
+ if (normalized === 'medium') {
489
+ return 2;
490
+ }
491
+ return 1;
492
+ }
493
+
494
+ function evaluateEntryRisk(entry = {}) {
495
+ const status = normalizeStatus(entry.status, 'candidate');
496
+ if (status === 'promoted' || status === 'deprecated') {
497
+ return 'low';
498
+ }
499
+
500
+ const qualityScore = Number(entry.quality_score || 0);
501
+ const tags = normalizeStringList(entry.tags).map((item) => item.toLowerCase());
502
+ const ontologyTags = normalizeOntologyTags(entry.ontology_tags);
503
+ const hasHighRiskTag = tags.some((tag) => HIGH_RISK_SIGNAL_TAGS.includes(tag));
504
+
505
+ if (hasHighRiskTag) {
506
+ return 'high';
507
+ }
508
+ if (status === 'candidate' && qualityScore >= 85) {
509
+ return 'high';
510
+ }
511
+ if (status === 'candidate' && qualityScore >= 75 && ontologyTags.includes('decision_policy')) {
512
+ return 'high';
513
+ }
514
+ if (status === 'candidate') {
515
+ return 'medium';
516
+ }
517
+ if (qualityScore >= 85 && ontologyTags.includes('decision_policy')) {
518
+ return 'high';
519
+ }
520
+ return 'medium';
521
+ }
522
+
523
+ async function evaluateErrorbookReleaseGate(options = {}, dependencies = {}) {
524
+ const projectPath = dependencies.projectPath || process.cwd();
525
+ const fileSystem = dependencies.fileSystem || fs;
526
+ const paths = resolveErrorbookPaths(projectPath);
527
+ const index = await readErrorbookIndex(paths, fileSystem);
528
+ const minRisk = normalizeRiskLevel(options.minRisk || options.min_risk || 'high', 'high');
529
+ const includeVerified = options.includeVerified === true;
530
+
531
+ const inspected = [];
532
+ for (const summary of index.entries) {
533
+ const entry = await readErrorbookEntry(paths, summary.id, fileSystem);
534
+ if (!entry) {
535
+ continue;
536
+ }
537
+
538
+ const status = normalizeStatus(entry.status, 'candidate');
539
+ const unresolved = status === 'candidate' || (includeVerified && status === 'verified');
540
+ if (!unresolved) {
541
+ continue;
542
+ }
543
+
544
+ const risk = evaluateEntryRisk(entry);
545
+ inspected.push({
546
+ id: entry.id,
547
+ title: entry.title,
548
+ status,
549
+ risk,
550
+ quality_score: Number(entry.quality_score || 0),
551
+ tags: normalizeStringList(entry.tags),
552
+ updated_at: entry.updated_at
553
+ });
554
+ }
555
+
556
+ const blocked = inspected
557
+ .filter((item) => riskRank(item.risk) >= riskRank(minRisk))
558
+ .sort((left, right) => {
559
+ const riskDiff = riskRank(right.risk) - riskRank(left.risk);
560
+ if (riskDiff !== 0) {
561
+ return riskDiff;
562
+ }
563
+ const qualityDiff = Number(right.quality_score || 0) - Number(left.quality_score || 0);
564
+ if (qualityDiff !== 0) {
565
+ return qualityDiff;
566
+ }
567
+ return `${right.updated_at || ''}`.localeCompare(`${left.updated_at || ''}`);
568
+ });
569
+
570
+ return {
571
+ mode: 'errorbook-release-gate',
572
+ gate: {
573
+ min_risk: minRisk,
574
+ include_verified: includeVerified
575
+ },
576
+ passed: blocked.length === 0,
577
+ inspected_count: inspected.length,
578
+ blocked_count: blocked.length,
579
+ blocked_entries: blocked
580
+ };
581
+ }
582
+
461
583
  function validatePromoteCandidate(entry, minQuality = DEFAULT_PROMOTE_MIN_QUALITY) {
462
584
  const missing = [];
463
585
  if (!normalizeText(entry.root_cause)) {
@@ -789,6 +911,33 @@ async function runErrorbookPromoteCommand(options = {}, dependencies = {}) {
789
911
  return result;
790
912
  }
791
913
 
914
+ async function runErrorbookReleaseGateCommand(options = {}, dependencies = {}) {
915
+ const payload = await evaluateErrorbookReleaseGate(options, dependencies);
916
+
917
+ if (options.json) {
918
+ console.log(JSON.stringify(payload, null, 2));
919
+ } else if (!options.silent) {
920
+ if (payload.passed) {
921
+ console.log(chalk.green('✓ Errorbook release gate passed'));
922
+ console.log(chalk.gray(` inspected: ${payload.inspected_count}`));
923
+ return payload;
924
+ }
925
+ console.log(chalk.red('✗ Errorbook release gate blocked'));
926
+ console.log(chalk.gray(` blocked: ${payload.blocked_count}`));
927
+ payload.blocked_entries.slice(0, 10).forEach((item) => {
928
+ console.log(chalk.gray(` - ${item.id} [${item.risk}] ${item.title}`));
929
+ });
930
+ }
931
+
932
+ if (options.failOnBlock && !payload.passed) {
933
+ throw new Error(
934
+ `errorbook release gate blocked: ${payload.blocked_count} unresolved entries (min-risk=${payload.gate.min_risk})`
935
+ );
936
+ }
937
+
938
+ return payload;
939
+ }
940
+
792
941
  async function runErrorbookDeprecateCommand(options = {}, dependencies = {}) {
793
942
  const projectPath = dependencies.projectPath || process.cwd();
794
943
  const fileSystem = dependencies.fileSystem || fs;
@@ -1028,6 +1177,21 @@ function registerErrorbookCommands(program) {
1028
1177
  }
1029
1178
  });
1030
1179
 
1180
+ errorbook
1181
+ .command('release-gate')
1182
+ .description('Block release on unresolved high-risk candidate entries')
1183
+ .option('--min-risk <level>', 'Risk threshold (low|medium|high)', 'high')
1184
+ .option('--include-verified', 'Also inspect verified (non-promoted) entries')
1185
+ .option('--fail-on-block', 'Exit with error when gate is blocked')
1186
+ .option('--json', 'Emit machine-readable JSON')
1187
+ .action(async (options) => {
1188
+ try {
1189
+ await runErrorbookReleaseGateCommand(options);
1190
+ } catch (error) {
1191
+ emitCommandError(error, options.json);
1192
+ }
1193
+ });
1194
+
1031
1195
  errorbook
1032
1196
  .command('deprecate <id>')
1033
1197
  .description('Deprecate low-value or obsolete entry')
@@ -1059,16 +1223,21 @@ function registerErrorbookCommands(program) {
1059
1223
  module.exports = {
1060
1224
  ERRORBOOK_STATUSES,
1061
1225
  ERRORBOOK_ONTOLOGY_TAGS,
1226
+ ERRORBOOK_RISK_LEVELS,
1227
+ HIGH_RISK_SIGNAL_TAGS,
1062
1228
  DEFAULT_PROMOTE_MIN_QUALITY,
1063
1229
  resolveErrorbookPaths,
1064
1230
  normalizeOntologyTags,
1065
1231
  normalizeRecordPayload,
1066
1232
  scoreQuality,
1233
+ evaluateEntryRisk,
1234
+ evaluateErrorbookReleaseGate,
1067
1235
  runErrorbookRecordCommand,
1068
1236
  runErrorbookListCommand,
1069
1237
  runErrorbookShowCommand,
1070
1238
  runErrorbookFindCommand,
1071
1239
  runErrorbookPromoteCommand,
1240
+ runErrorbookReleaseGateCommand,
1072
1241
  runErrorbookDeprecateCommand,
1073
1242
  runErrorbookRequalifyCommand,
1074
1243
  registerErrorbookCommands