scene-capability-engine 3.6.19 → 3.6.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,10 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [3.6.21] - 2026-03-06
11
+
12
+ ### Added
13
+ - Capability catalog list/search now supports `--release-ready` and `--missing-triad` filters for pre-publish triage.
14
+ - Magicball capability library docs now show list-level triage filter examples.
15
+
16
+ ## [3.6.20] - 2026-03-06
17
+
18
+ ### Added
19
+ - Capability catalog entries now expose pre-publish readiness UI fields for badge rendering and sorting.
20
+ - Magicball capability library guide now documents list-level publish readiness fields.
21
+
10
22
  ## [3.6.19] - 2026-03-06
11
23
 
12
24
  ### Added
13
25
  - Capability map/register payloads now expose `release_readiness` with structured blocking reasons for publish UI.
26
+ - Capability catalog payloads now expose `release_readiness_ui` for pre-publish status badges and sorting.
14
27
  - Magicball capability docs now define release blocker rendering for capability publish pages.
15
28
 
16
29
  ## [3.6.18] - 2026-03-06
package/README.md CHANGED
@@ -218,5 +218,5 @@ MIT. See [LICENSE](LICENSE).
218
218
 
219
219
  ---
220
220
 
221
- **Version**: 3.6.19
221
+ **Version**: 3.6.21
222
222
  **Last Updated**: 2026-03-05
package/README.zh.md CHANGED
@@ -218,5 +218,5 @@ MIT,见 [LICENSE](LICENSE)。
218
218
 
219
219
  ---
220
220
 
221
- **版本**:3.6.19
221
+ **版本**:3.6.21
222
222
  **最后更新**:2026-03-05
@@ -1898,10 +1898,13 @@ Schema references:
1898
1898
 
1899
1899
  `catalog/list/search/show/match/use` responses now include `ontology_core` and `ontology_core_ui` so UI can render triad readiness directly.
1900
1900
  `capability map/register` responses now include `release_readiness` so UI can render blocking reasons before publish.
1901
+ Catalog payloads also expose `release_readiness_ui` for pre-publish sorting and status badges.
1901
1902
 
1902
1903
  ```bash
1903
1904
  # List capability templates
1904
1905
  sce capability catalog list --json
1906
+ sce capability catalog list --release-ready true --json
1907
+ sce capability catalog list --missing-triad decision_strategy --json
1905
1908
 
1906
1909
  # Search capability templates
1907
1910
  sce capability catalog search "customer order" --json
@@ -20,7 +20,9 @@
20
20
 
21
21
  ```bash
22
22
  sce capability catalog list --json
23
- sce capability catalog search "customer order" --json
23
+ sce capability catalog list --release-ready true --json
24
+ sce capability catalog list --missing-triad decision_strategy --json
25
+ sce capability catalog search "customer order" --release-ready false --json
24
26
  sce capability catalog show <template-id> --json
25
27
  ```
26
28
 
@@ -146,6 +148,17 @@ sce capability use --template <template-id> --spec <spec-id> --apply --json
146
148
 
147
149
  若需要“自动落地写入 spec 任务”的强制执行模式,可以在后续版本加 `--apply` 开关。
148
150
 
151
+ ### release_readiness_ui(列表状态)
152
+ ```json
153
+ {
154
+ "publish_ready": false,
155
+ "blocking_count": 1,
156
+ "blocking_ids": ["ontology-core-triads"],
157
+ "blocking_reasons": ["missing required ontology triads"],
158
+ "blocking_missing": ["decision_strategy"]
159
+ }
160
+ ```
161
+
149
162
  ### release_readiness(发布阻断原因)
150
163
  ```json
151
164
  {
@@ -432,10 +432,27 @@ function enrichCapabilityTemplateForUi(template) {
432
432
  const ontologyCore = template && template.ontology_core
433
433
  ? template.ontology_core
434
434
  : buildCoreOntologySummary(template && template.ontology_scope ? template.ontology_scope : createEmptyOntologyScope());
435
+ const releaseReadiness = template && template.release_readiness
436
+ ? template.release_readiness
437
+ : {
438
+ ready: ontologyCore.ready === true,
439
+ blockers: ontologyCore.ready === true
440
+ ? []
441
+ : [{
442
+ id: 'ontology-core-triads',
443
+ severity: 'blocking',
444
+ reason: 'missing required ontology triads',
445
+ missing: Array.isArray(ontologyCore.missing) ? ontologyCore.missing : []
446
+ }],
447
+ ontology_core: ontologyCore,
448
+ ontology_core_ui: buildOntologyCoreUiState(ontologyCore)
449
+ };
435
450
  return {
436
451
  ...template,
437
452
  ontology_core: ontologyCore,
438
- ontology_core_ui: buildOntologyCoreUiState(ontologyCore)
453
+ ontology_core_ui: buildOntologyCoreUiState(ontologyCore),
454
+ release_readiness: releaseReadiness,
455
+ release_readiness_ui: buildCapabilityReleaseReadinessUi(releaseReadiness)
439
456
  };
440
457
  }
441
458
 
@@ -464,6 +481,20 @@ function buildCapabilityReleaseReadiness(templateCandidate) {
464
481
  };
465
482
  }
466
483
 
484
+ function buildCapabilityReleaseReadinessUi(readiness) {
485
+ const details = readiness && typeof readiness === 'object'
486
+ ? readiness
487
+ : { ready: true, blockers: [] };
488
+ const blockers = Array.isArray(details.blockers) ? details.blockers : [];
489
+ return {
490
+ publish_ready: details.ready === true,
491
+ blocking_count: blockers.length,
492
+ blocking_ids: blockers.map((item) => item && item.id).filter(Boolean),
493
+ blocking_reasons: blockers.map((item) => item && item.reason).filter(Boolean),
494
+ blocking_missing: blockers.flatMap((item) => Array.isArray(item && item.missing) ? item.missing : [])
495
+ };
496
+ }
497
+
467
498
  async function loadSceneIndexFromFile(projectPath, fileSystem) {
468
499
  const indexPath = path.join(projectPath, '.sce', 'spec-governance', 'scene-index.json');
469
500
  if (!await fileSystem.pathExists(indexPath)) {
@@ -970,6 +1001,34 @@ async function runCapabilityRegisterCommand(options = {}, dependencies = {}) {
970
1001
  return result;
971
1002
  }
972
1003
 
1004
+ function filterCapabilityCatalogEntries(templates, options = {}) {
1005
+ const entries = Array.isArray(templates) ? templates : [];
1006
+ const normalizedMissingTriad = normalizeText(options.missingTriad || options.missing_triad).toLowerCase();
1007
+ const releaseReadyFilter = normalizeText(options.releaseReady || options.release_ready).toLowerCase();
1008
+
1009
+ return entries.filter((entry) => {
1010
+ const template = enrichCapabilityTemplateForUi(entry);
1011
+
1012
+ if (releaseReadyFilter) {
1013
+ const expected = ['1', 'true', 'yes', 'ready'].includes(releaseReadyFilter);
1014
+ if (template.release_readiness_ui.publish_ready !== expected) {
1015
+ return false;
1016
+ }
1017
+ }
1018
+
1019
+ if (normalizedMissingTriad) {
1020
+ const missing = Array.isArray(template.release_readiness_ui.blocking_missing)
1021
+ ? template.release_readiness_ui.blocking_missing
1022
+ : [];
1023
+ if (!missing.includes(normalizedMissingTriad)) {
1024
+ return false;
1025
+ }
1026
+ }
1027
+
1028
+ return true;
1029
+ });
1030
+ }
1031
+
973
1032
  function displayCapabilityCatalog(templates, options = {}) {
974
1033
  const total = Array.isArray(templates) ? templates.length : 0;
975
1034
  console.log(chalk.red('🔥') + ' Capability Library');
@@ -995,13 +1054,13 @@ function displayCapabilityCatalog(templates, options = {}) {
995
1054
 
996
1055
  async function listCapabilityCatalog(options = {}) {
997
1056
  const manager = new TemplateManager();
998
- const templates = (await manager.listTemplates({
1057
+ const templates = filterCapabilityCatalogEntries((await manager.listTemplates({
999
1058
  category: options.category,
1000
1059
  source: options.source,
1001
1060
  templateType: 'capability-template',
1002
1061
  compatibleWith: options.compatibleWith,
1003
1062
  riskLevel: options.risk
1004
- })).map((template) => enrichCapabilityTemplateForUi(template));
1063
+ })).map((template) => enrichCapabilityTemplateForUi(template)), options);
1005
1064
  if (normalizeBoolean(options.json, false)) {
1006
1065
  return {
1007
1066
  mode: 'capability-catalog-list',
@@ -1014,13 +1073,13 @@ async function listCapabilityCatalog(options = {}) {
1014
1073
 
1015
1074
  async function searchCapabilityCatalog(keyword, options = {}) {
1016
1075
  const manager = new TemplateManager();
1017
- const templates = (await manager.searchTemplates(keyword, {
1076
+ const templates = filterCapabilityCatalogEntries((await manager.searchTemplates(keyword, {
1018
1077
  category: options.category,
1019
1078
  source: options.source,
1020
1079
  templateType: 'capability-template',
1021
1080
  compatibleWith: options.compatibleWith,
1022
1081
  riskLevel: options.risk
1023
- })).map((template) => enrichCapabilityTemplateForUi(template));
1082
+ })).map((template) => enrichCapabilityTemplateForUi(template)), options);
1024
1083
  if (normalizeBoolean(options.json, false)) {
1025
1084
  return {
1026
1085
  mode: 'capability-catalog-search',
@@ -1330,6 +1389,8 @@ function registerCapabilityCommands(program) {
1330
1389
  .option('--category <name>', 'Template category filter')
1331
1390
  .option('--compatible-with <semver>', 'SCE version compatibility')
1332
1391
  .option('--risk <level>', 'Risk level filter')
1392
+ .option('--release-ready <bool>', 'Filter by publish readiness')
1393
+ .option('--missing-triad <name>', 'Filter by missing triad (entity_relation|business_rules|decision_strategy)')
1333
1394
  .option('--json', 'Output JSON to stdout')
1334
1395
  .action(async (options) => {
1335
1396
  try {
@@ -1338,6 +1399,8 @@ function registerCapabilityCommands(program) {
1338
1399
  category: options.category,
1339
1400
  compatibleWith: options.compatibleWith,
1340
1401
  risk: options.risk,
1402
+ releaseReady: options.releaseReady,
1403
+ missingTriad: options.missingTriad,
1341
1404
  json: options.json
1342
1405
  });
1343
1406
  if (options.json) {
@@ -1362,6 +1425,8 @@ function registerCapabilityCommands(program) {
1362
1425
  .option('--category <name>', 'Template category filter')
1363
1426
  .option('--compatible-with <semver>', 'SCE version compatibility')
1364
1427
  .option('--risk <level>', 'Risk level filter')
1428
+ .option('--release-ready <bool>', 'Filter by publish readiness')
1429
+ .option('--missing-triad <name>', 'Filter by missing triad (entity_relation|business_rules|decision_strategy)')
1365
1430
  .option('--json', 'Output JSON to stdout')
1366
1431
  .action(async (keyword, options) => {
1367
1432
  try {
@@ -1370,6 +1435,8 @@ function registerCapabilityCommands(program) {
1370
1435
  category: options.category,
1371
1436
  compatibleWith: options.compatibleWith,
1372
1437
  risk: options.risk,
1438
+ releaseReady: options.releaseReady,
1439
+ missingTriad: options.missingTriad,
1373
1440
  json: options.json
1374
1441
  });
1375
1442
  if (options.json) {
@@ -1462,5 +1529,13 @@ module.exports = {
1462
1529
  runCapabilityExtractCommand,
1463
1530
  runCapabilityScoreCommand,
1464
1531
  runCapabilityMapCommand,
1465
- runCapabilityRegisterCommand
1532
+ runCapabilityRegisterCommand,
1533
+ listCapabilityCatalog,
1534
+ searchCapabilityCatalog,
1535
+ showCapabilityTemplate,
1536
+ matchCapabilityTemplates,
1537
+ useCapabilityTemplate,
1538
+ enrichCapabilityTemplateForUi,
1539
+ buildCapabilityReleaseReadinessUi,
1540
+ filterCapabilityCatalogEntries
1466
1541
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scene-capability-engine",
3
- "version": "3.6.19",
3
+ "version": "3.6.21",
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": {