scene-capability-engine 3.6.64 → 3.6.67

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 (125) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +17 -6
  3. package/README.zh.md +18 -6
  4. package/bin/scene-capability-engine.js +4 -0
  5. package/docs/README.md +2 -2
  6. package/docs/command-reference.md +385 -8
  7. package/docs/document-governance.md +3 -2
  8. package/docs/integration-modes.md +62 -478
  9. package/docs/integration-philosophy.md +56 -263
  10. package/docs/magicball-cli-invocation-examples.md +1 -0
  11. package/docs/magicball-project-portfolio-contract.md +125 -4
  12. package/docs/project-management/README.md +14 -0
  13. package/docs/project-management/assurance/backup.md +3 -0
  14. package/docs/project-management/assurance/config.md +3 -0
  15. package/docs/project-management/assurance/evidence/README.md +3 -0
  16. package/docs/project-management/assurance/incidents/README.md +3 -0
  17. package/docs/project-management/assurance/logs.md +3 -0
  18. package/docs/project-management/assurance/overview.md +3 -0
  19. package/docs/project-management/assurance/recovery/README.md +3 -0
  20. package/docs/project-management/assurance/resource.md +3 -0
  21. package/docs/project-management/assurance/runbooks/README.md +3 -0
  22. package/docs/project-management/delivery/acceptance/README.md +3 -0
  23. package/docs/project-management/delivery/acceptance/evidence/README.md +3 -0
  24. package/docs/project-management/delivery/acceptance/exceptions/README.md +3 -0
  25. package/docs/project-management/delivery/acceptance/reports/README.md +3 -0
  26. package/docs/project-management/delivery/documents/changes.md +3 -0
  27. package/docs/project-management/delivery/documents/issues.md +3 -0
  28. package/docs/project-management/delivery/documents/overview.md +3 -0
  29. package/docs/project-management/delivery/documents/planning.md +3 -0
  30. package/docs/project-management/delivery/documents/requirements.md +3 -0
  31. package/docs/project-management/delivery/documents/tracking.md +3 -0
  32. package/docs/project-management/delivery/handoffs/README.md +3 -0
  33. package/docs/project-management/delivery/handoffs/evidence/README.md +3 -0
  34. package/docs/project-management/delivery/handoffs/records/README.md +3 -0
  35. package/docs/project-management/delivery/overview.md +10 -0
  36. package/docs/project-management/delivery/releases/README.md +3 -0
  37. package/docs/project-management/delivery/releases/baselines/README.md +3 -0
  38. package/docs/project-management/delivery/releases/evidence/README.md +3 -0
  39. package/docs/project-management/delivery/tables/changes.md +3 -0
  40. package/docs/project-management/delivery/tables/issues.md +3 -0
  41. package/docs/project-management/delivery/tables/planning.md +3 -0
  42. package/docs/project-management/delivery/tables/requirements.md +3 -0
  43. package/docs/project-management/delivery/tables/tracking.md +3 -0
  44. package/docs/project-management/environment/agent-discovery.md +3 -0
  45. package/docs/project-management/environment/development.md +3 -0
  46. package/docs/project-management/environment/overview.md +10 -0
  47. package/docs/project-management/environment/testing.md +3 -0
  48. package/docs/project-management/environment/version-alignment.md +3 -0
  49. package/docs/quick-start-with-ai-tools.md +68 -308
  50. package/docs/releases/README.md +3 -0
  51. package/docs/releases/v3.6.65.md +25 -0
  52. package/docs/releases/v3.6.66.md +23 -0
  53. package/docs/releases/v3.6.67.md +23 -0
  54. package/docs/steering-governance.md +64 -2
  55. package/docs/zh/README.md +2 -2
  56. package/docs/zh/releases/README.md +3 -0
  57. package/docs/zh/releases/v3.6.65.md +25 -0
  58. package/docs/zh/releases/v3.6.66.md +23 -0
  59. package/docs/zh/releases/v3.6.67.md +23 -0
  60. package/lib/commands/adopt.js +24 -0
  61. package/lib/commands/native.js +158 -0
  62. package/lib/commands/project.js +96 -0
  63. package/lib/commands/semantic.js +1459 -0
  64. package/lib/commands/session.js +74 -3
  65. package/lib/commands/spec-bootstrap.js +10 -1
  66. package/lib/commands/spec-gate.js +10 -1
  67. package/lib/commands/spec-pipeline.js +10 -1
  68. package/lib/commands/studio.js +405 -30
  69. package/lib/commands/task.js +141 -7
  70. package/lib/governance/supreme-principles.js +530 -0
  71. package/lib/problem/problem-evaluator.js +4 -0
  72. package/lib/project/candidate-inspection-service.js +24 -1
  73. package/lib/project/portfolio-projection-service.js +315 -5
  74. package/lib/project/project-channel-output.js +94 -0
  75. package/lib/project/project-channel-projection.js +181 -0
  76. package/lib/project/root-onboarding-service.js +107 -7
  77. package/lib/project/semantic-shared-source-projection.js +150 -0
  78. package/lib/project/supervision-action-model.js +277 -0
  79. package/lib/project/supervision-projection-service.js +305 -5
  80. package/lib/project/target-resolution-service.js +70 -5
  81. package/lib/project/visibility-policy.js +93 -0
  82. package/lib/runtime/multi-spec-scene-session.js +8 -1
  83. package/lib/runtime/project-channel-context-store.js +387 -0
  84. package/lib/runtime/project-channel-context.js +406 -0
  85. package/lib/runtime/scene-session-binding.js +46 -0
  86. package/lib/runtime/session-store.js +186 -0
  87. package/lib/runtime/steering-contract.js +7 -1
  88. package/lib/semantic/archive-report.js +283 -0
  89. package/lib/semantic/archive-routing.js +67 -0
  90. package/lib/semantic/backflow-report.js +245 -0
  91. package/lib/semantic/capability-contract.js +30 -0
  92. package/lib/semantic/delta-export.js +145 -0
  93. package/lib/semantic/interaction-observer.js +254 -0
  94. package/lib/semantic/kernel-loader.js +881 -0
  95. package/lib/semantic/native-runtime.js +359 -0
  96. package/lib/semantic/progress-ledger.js +433 -0
  97. package/lib/semantic/replay-evaluator.js +382 -0
  98. package/lib/semantic/shared-publication.js +592 -0
  99. package/lib/semantic/shared-source-config.js +183 -0
  100. package/lib/semantic/shared-source-connect.js +139 -0
  101. package/lib/semantic/shared-source-discovery.js +98 -0
  102. package/lib/semantic/shared-sync-export.js +413 -0
  103. package/lib/semantic/shared-sync-intake.js +592 -0
  104. package/lib/semantic/shared-sync-merge.js +547 -0
  105. package/lib/semantic/shared-sync-release.js +463 -0
  106. package/lib/semantic/supreme-intent-report.js +300 -0
  107. package/lib/state/sce-state-store.js +1360 -0
  108. package/lib/steering/context-sync-manager.js +276 -25
  109. package/lib/studio/spec-intake-governor.js +39 -3
  110. package/lib/studio/task-envelope.js +35 -2
  111. package/lib/workspace/takeover-baseline.js +342 -83
  112. package/package.json +7 -2
  113. package/scripts/agent-governance-baseline-audit.js +395 -0
  114. package/scripts/clarification-first-audit.js +9 -9
  115. package/scripts/deprecated-entry-audit.js +240 -0
  116. package/scripts/release-doc-version-audit.js +24 -0
  117. package/scripts/release-posture-report.js +262 -0
  118. package/template/.sce/README.md +62 -228
  119. package/template/.sce/config/semantic-shared-sources.json +5 -0
  120. package/template/.sce/config/supreme-principles-policy.json +105 -0
  121. package/template/.sce/config/takeover-baseline.json +7 -0
  122. package/template/.sce/steering/CORE_PRINCIPLES.md +23 -63
  123. package/template/.sce/steering/CURRENT_CONTEXT.md +4 -0
  124. package/template/.sce/steering/RULES_GUIDE.md +17 -9
  125. package/template/README.md +32 -96
@@ -152,6 +152,11 @@ class SceStateStore {
152
152
  timeline_snapshots: {},
153
153
  scene_session_cycles: {},
154
154
  agent_runtime: {},
155
+ supreme_intent_assessments: {},
156
+ semantic_observations: {},
157
+ semantic_lesson_candidates: {},
158
+ semantic_evaluation_runs: {},
159
+ semantic_capability_ledgers: {},
155
160
  errorbook_entry_index: {},
156
161
  errorbook_incident_index: {},
157
162
  governance_spec_scene_override: {},
@@ -374,6 +379,176 @@ class SceStateStore {
374
379
  CREATE INDEX IF NOT EXISTS idx_agent_runtime_registry_status
375
380
  ON agent_runtime_registry(status);
376
381
 
382
+ CREATE TABLE IF NOT EXISTS supreme_intent_assessment_registry (
383
+ assessment_id TEXT PRIMARY KEY,
384
+ project_id TEXT,
385
+ channel_id TEXT,
386
+ session_id TEXT,
387
+ scene_id TEXT,
388
+ spec_id TEXT,
389
+ job_id TEXT,
390
+ source_kind TEXT NOT NULL,
391
+ action TEXT NOT NULL,
392
+ planning_allowed INTEGER NOT NULL,
393
+ execution_allowed INTEGER NOT NULL,
394
+ policy_path TEXT,
395
+ policy_loaded_from TEXT,
396
+ original_text TEXT,
397
+ effective_text TEXT,
398
+ message TEXT,
399
+ evidence_path TEXT,
400
+ worldview_json TEXT NOT NULL,
401
+ lifeview_json TEXT NOT NULL,
402
+ values_json TEXT NOT NULL,
403
+ methodology_json TEXT NOT NULL,
404
+ matched_rules_json TEXT NOT NULL,
405
+ clarification_questions_json TEXT NOT NULL,
406
+ metadata_json TEXT NOT NULL,
407
+ created_at TEXT NOT NULL,
408
+ updated_at TEXT NOT NULL
409
+ );
410
+
411
+ CREATE INDEX IF NOT EXISTS idx_supreme_intent_assessment_registry_project_ts
412
+ ON supreme_intent_assessment_registry(project_id, updated_at DESC);
413
+
414
+ CREATE INDEX IF NOT EXISTS idx_supreme_intent_assessment_registry_context
415
+ ON supreme_intent_assessment_registry(scene_id, spec_id, session_id, updated_at DESC);
416
+
417
+ CREATE INDEX IF NOT EXISTS idx_supreme_intent_assessment_registry_action
418
+ ON supreme_intent_assessment_registry(source_kind, action, updated_at DESC);
419
+
420
+ CREATE TABLE IF NOT EXISTS semantic_observation_registry (
421
+ observation_id TEXT PRIMARY KEY,
422
+ project_id TEXT,
423
+ channel_id TEXT,
424
+ session_id TEXT,
425
+ scene_id TEXT,
426
+ spec_id TEXT,
427
+ task_ref TEXT,
428
+ source_runtime TEXT NOT NULL,
429
+ source_kind TEXT,
430
+ host_session_id TEXT,
431
+ event_kind TEXT NOT NULL,
432
+ role TEXT,
433
+ intent TEXT,
434
+ summary TEXT,
435
+ outcome TEXT,
436
+ quality_signal TEXT,
437
+ raw_ref TEXT,
438
+ raw_payload_json TEXT NOT NULL,
439
+ normalized_payload_json TEXT NOT NULL,
440
+ created_at TEXT NOT NULL,
441
+ updated_at TEXT NOT NULL
442
+ );
443
+
444
+ CREATE INDEX IF NOT EXISTS idx_semantic_observation_registry_project_ts
445
+ ON semantic_observation_registry(project_id, updated_at DESC);
446
+
447
+ CREATE INDEX IF NOT EXISTS idx_semantic_observation_registry_context
448
+ ON semantic_observation_registry(scene_id, spec_id, task_ref, updated_at DESC);
449
+
450
+ CREATE INDEX IF NOT EXISTS idx_semantic_observation_registry_runtime
451
+ ON semantic_observation_registry(source_runtime, event_kind, updated_at DESC);
452
+
453
+ CREATE TABLE IF NOT EXISTS semantic_lesson_candidate_registry (
454
+ lesson_id TEXT PRIMARY KEY,
455
+ project_id TEXT,
456
+ scene_id TEXT,
457
+ spec_id TEXT,
458
+ source_runtime TEXT,
459
+ fingerprint TEXT,
460
+ lesson_type TEXT NOT NULL,
461
+ title TEXT,
462
+ summary TEXT,
463
+ heuristic TEXT,
464
+ confidence REAL,
465
+ status TEXT,
466
+ evidence_json TEXT,
467
+ metadata_json TEXT,
468
+ created_at TEXT NOT NULL,
469
+ updated_at TEXT NOT NULL
470
+ );
471
+
472
+ CREATE INDEX IF NOT EXISTS idx_semantic_lesson_candidate_registry_project_status
473
+ ON semantic_lesson_candidate_registry(project_id, status, updated_at DESC);
474
+
475
+ CREATE INDEX IF NOT EXISTS idx_semantic_lesson_candidate_registry_fingerprint
476
+ ON semantic_lesson_candidate_registry(fingerprint, updated_at DESC);
477
+
478
+ CREATE TABLE IF NOT EXISTS semantic_evaluation_run_registry (
479
+ evaluation_run_id TEXT PRIMARY KEY,
480
+ project_id TEXT,
481
+ channel_id TEXT,
482
+ session_id TEXT,
483
+ scene_id TEXT,
484
+ spec_id TEXT,
485
+ lesson_id TEXT,
486
+ source_runtime TEXT,
487
+ release_gate TEXT,
488
+ baseline_evaluation_run_id TEXT,
489
+ candidate_kind TEXT NOT NULL,
490
+ candidate_label TEXT,
491
+ candidate_payload_json TEXT NOT NULL,
492
+ observation_ids_json TEXT NOT NULL,
493
+ replay_summary_json TEXT NOT NULL,
494
+ score REAL,
495
+ threshold REAL,
496
+ verdict TEXT,
497
+ regression_detected INTEGER,
498
+ drift_level TEXT,
499
+ regression_reasons_json TEXT,
500
+ evidence_json TEXT,
501
+ governance_json TEXT,
502
+ created_at TEXT NOT NULL,
503
+ updated_at TEXT NOT NULL
504
+ );
505
+
506
+ CREATE INDEX IF NOT EXISTS idx_semantic_evaluation_run_registry_project_ts
507
+ ON semantic_evaluation_run_registry(project_id, updated_at DESC);
508
+
509
+ CREATE INDEX IF NOT EXISTS idx_semantic_evaluation_run_registry_context
510
+ ON semantic_evaluation_run_registry(scene_id, spec_id, session_id, updated_at DESC);
511
+
512
+ CREATE INDEX IF NOT EXISTS idx_semantic_evaluation_run_registry_verdict
513
+ ON semantic_evaluation_run_registry(verdict, regression_detected, updated_at DESC);
514
+
515
+ CREATE TABLE IF NOT EXISTS semantic_capability_ledger_registry (
516
+ capability_id TEXT PRIMARY KEY,
517
+ lesson_id TEXT,
518
+ evaluation_run_id TEXT,
519
+ project_id TEXT,
520
+ channel_id TEXT,
521
+ session_id TEXT,
522
+ scene_id TEXT,
523
+ spec_id TEXT,
524
+ target_library TEXT,
525
+ capability_status TEXT,
526
+ publish_state TEXT,
527
+ activation_count INTEGER,
528
+ activation_success_count INTEGER,
529
+ activation_mixed_count INTEGER,
530
+ activation_negative_count INTEGER,
531
+ quarantine_count INTEGER,
532
+ last_activated_at TEXT,
533
+ last_quality_signal TEXT,
534
+ last_runtime TEXT,
535
+ rank_score REAL,
536
+ lineage_json TEXT NOT NULL,
537
+ publication_json TEXT NOT NULL,
538
+ metrics_json TEXT NOT NULL,
539
+ created_at TEXT NOT NULL,
540
+ updated_at TEXT NOT NULL
541
+ );
542
+
543
+ CREATE INDEX IF NOT EXISTS idx_semantic_capability_ledger_registry_project_ts
544
+ ON semantic_capability_ledger_registry(project_id, updated_at DESC);
545
+
546
+ CREATE INDEX IF NOT EXISTS idx_semantic_capability_ledger_registry_status
547
+ ON semantic_capability_ledger_registry(capability_status, publish_state, updated_at DESC);
548
+
549
+ CREATE INDEX IF NOT EXISTS idx_semantic_capability_ledger_registry_lesson
550
+ ON semantic_capability_ledger_registry(lesson_id, updated_at DESC);
551
+
377
552
  CREATE TABLE IF NOT EXISTS state_migration_registry (
378
553
  migration_id TEXT PRIMARY KEY,
379
554
  component_id TEXT NOT NULL,
@@ -1116,6 +1291,163 @@ class SceStateStore {
1116
1291
  };
1117
1292
  }
1118
1293
 
1294
+ _mapSupremeIntentAssessmentRow(row) {
1295
+ if (!row) {
1296
+ return null;
1297
+ }
1298
+ return {
1299
+ assessment_id: normalizeString(row.assessment_id),
1300
+ project_id: normalizeString(row.project_id) || null,
1301
+ channel_id: normalizeString(row.channel_id) || null,
1302
+ session_id: normalizeString(row.session_id) || null,
1303
+ scene_id: normalizeString(row.scene_id) || null,
1304
+ spec_id: normalizeString(row.spec_id) || null,
1305
+ job_id: normalizeString(row.job_id) || null,
1306
+ source_kind: normalizeString(row.source_kind) || null,
1307
+ action: normalizeString(row.action) || null,
1308
+ planning_allowed: normalizeBooleanValue(row.planning_allowed, false),
1309
+ execution_allowed: normalizeBooleanValue(row.execution_allowed, false),
1310
+ policy_path: normalizeString(row.policy_path) || null,
1311
+ policy_loaded_from: normalizeString(row.policy_loaded_from) || null,
1312
+ original_text: normalizeString(row.original_text) || null,
1313
+ effective_text: normalizeString(row.effective_text) || null,
1314
+ message: normalizeString(row.message) || null,
1315
+ evidence_path: normalizeString(row.evidence_path) || null,
1316
+ worldview: parseJsonSafe(row.worldview_json, {}) || {},
1317
+ lifeview: parseJsonSafe(row.lifeview_json, {}) || {},
1318
+ values: parseJsonSafe(row.values_json, {}) || {},
1319
+ methodology: parseJsonSafe(row.methodology_json, {}) || {},
1320
+ matched_rules: parseJsonSafe(row.matched_rules_json, {}) || {},
1321
+ clarification_questions: normalizeStringArray(parseJsonSafe(row.clarification_questions_json, []), []),
1322
+ metadata: parseJsonSafe(row.metadata_json, {}) || {},
1323
+ created_at: normalizeIsoTimestamp(row.created_at) || null,
1324
+ updated_at: normalizeIsoTimestamp(row.updated_at) || null
1325
+ };
1326
+ }
1327
+
1328
+ _mapSemanticObservationRow(row) {
1329
+ if (!row) {
1330
+ return null;
1331
+ }
1332
+ return {
1333
+ observation_id: normalizeString(row.observation_id),
1334
+ project_id: normalizeString(row.project_id) || null,
1335
+ channel_id: normalizeString(row.channel_id) || null,
1336
+ session_id: normalizeString(row.session_id) || null,
1337
+ scene_id: normalizeString(row.scene_id) || null,
1338
+ spec_id: normalizeString(row.spec_id) || null,
1339
+ task_ref: normalizeString(row.task_ref) || null,
1340
+ source_runtime: normalizeString(row.source_runtime) || null,
1341
+ source_kind: normalizeString(row.source_kind) || null,
1342
+ host_session_id: normalizeString(row.host_session_id) || null,
1343
+ event_kind: normalizeString(row.event_kind) || null,
1344
+ role: normalizeString(row.role) || null,
1345
+ intent: normalizeString(row.intent) || null,
1346
+ summary: normalizeString(row.summary) || null,
1347
+ outcome: normalizeString(row.outcome) || null,
1348
+ quality_signal: normalizeString(row.quality_signal) || null,
1349
+ raw_ref: normalizeString(row.raw_ref) || null,
1350
+ raw_payload: parseJsonSafe(row.raw_payload_json, {}) || {},
1351
+ normalized_payload: parseJsonSafe(row.normalized_payload_json, {}) || {},
1352
+ created_at: normalizeIsoTimestamp(row.created_at) || null,
1353
+ updated_at: normalizeIsoTimestamp(row.updated_at) || null
1354
+ };
1355
+ }
1356
+
1357
+ _mapSemanticLessonCandidateRow(row) {
1358
+ if (!row) {
1359
+ return null;
1360
+ }
1361
+ const confidence = Number(row.confidence);
1362
+ return {
1363
+ lesson_id: normalizeString(row.lesson_id),
1364
+ project_id: normalizeString(row.project_id) || null,
1365
+ scene_id: normalizeString(row.scene_id) || null,
1366
+ spec_id: normalizeString(row.spec_id) || null,
1367
+ source_runtime: normalizeString(row.source_runtime) || null,
1368
+ fingerprint: normalizeString(row.fingerprint) || null,
1369
+ lesson_type: normalizeString(row.lesson_type) || null,
1370
+ title: normalizeString(row.title) || null,
1371
+ summary: normalizeString(row.summary) || null,
1372
+ heuristic: normalizeString(row.heuristic) || null,
1373
+ confidence: Number.isFinite(confidence) ? confidence : null,
1374
+ status: normalizeString(row.status) || null,
1375
+ evidence: parseJsonSafe(row.evidence_json, {}) || {},
1376
+ metadata: parseJsonSafe(row.metadata_json, {}) || {},
1377
+ created_at: normalizeIsoTimestamp(row.created_at) || null,
1378
+ updated_at: normalizeIsoTimestamp(row.updated_at) || null
1379
+ };
1380
+ }
1381
+
1382
+ _mapSemanticEvaluationRunRow(row) {
1383
+ if (!row) {
1384
+ return null;
1385
+ }
1386
+ const score = Number(row.score);
1387
+ const threshold = Number(row.threshold);
1388
+ return {
1389
+ evaluation_run_id: normalizeString(row.evaluation_run_id),
1390
+ project_id: normalizeString(row.project_id) || null,
1391
+ channel_id: normalizeString(row.channel_id) || null,
1392
+ session_id: normalizeString(row.session_id) || null,
1393
+ scene_id: normalizeString(row.scene_id) || null,
1394
+ spec_id: normalizeString(row.spec_id) || null,
1395
+ lesson_id: normalizeString(row.lesson_id) || null,
1396
+ source_runtime: normalizeString(row.source_runtime) || null,
1397
+ release_gate: normalizeString(row.release_gate) || null,
1398
+ baseline_evaluation_run_id: normalizeString(row.baseline_evaluation_run_id) || null,
1399
+ candidate_kind: normalizeString(row.candidate_kind) || null,
1400
+ candidate_label: normalizeString(row.candidate_label) || null,
1401
+ candidate_payload: parseJsonSafe(row.candidate_payload_json, {}) || {},
1402
+ observation_ids: normalizeStringArray(parseJsonSafe(row.observation_ids_json, []), []),
1403
+ replay_summary: parseJsonSafe(row.replay_summary_json, {}) || {},
1404
+ score: Number.isFinite(score) ? Number(score.toFixed(2)) : null,
1405
+ threshold: Number.isFinite(threshold) ? Number(threshold.toFixed(2)) : null,
1406
+ verdict: normalizeString(row.verdict) || null,
1407
+ regression_detected: normalizeBooleanValue(row.regression_detected, false),
1408
+ drift_level: normalizeString(row.drift_level) || null,
1409
+ regression_reasons: normalizeStringArray(parseJsonSafe(row.regression_reasons_json, []), []),
1410
+ evidence: parseJsonSafe(row.evidence_json, {}) || {},
1411
+ governance: parseJsonSafe(row.governance_json, {}) || {},
1412
+ created_at: normalizeIsoTimestamp(row.created_at) || null,
1413
+ updated_at: normalizeIsoTimestamp(row.updated_at) || null
1414
+ };
1415
+ }
1416
+
1417
+ _mapSemanticCapabilityLedgerRow(row) {
1418
+ if (!row) {
1419
+ return null;
1420
+ }
1421
+ const rankScore = Number(row.rank_score);
1422
+ return {
1423
+ capability_id: normalizeString(row.capability_id),
1424
+ lesson_id: normalizeString(row.lesson_id) || null,
1425
+ evaluation_run_id: normalizeString(row.evaluation_run_id) || null,
1426
+ project_id: normalizeString(row.project_id) || null,
1427
+ channel_id: normalizeString(row.channel_id) || null,
1428
+ session_id: normalizeString(row.session_id) || null,
1429
+ scene_id: normalizeString(row.scene_id) || null,
1430
+ spec_id: normalizeString(row.spec_id) || null,
1431
+ target_library: normalizeString(row.target_library) || null,
1432
+ capability_status: normalizeString(row.capability_status) || null,
1433
+ publish_state: normalizeString(row.publish_state) || null,
1434
+ activation_count: normalizeNonNegativeInteger(row.activation_count, 0),
1435
+ activation_success_count: normalizeNonNegativeInteger(row.activation_success_count, 0),
1436
+ activation_mixed_count: normalizeNonNegativeInteger(row.activation_mixed_count, 0),
1437
+ activation_negative_count: normalizeNonNegativeInteger(row.activation_negative_count, 0),
1438
+ quarantine_count: normalizeNonNegativeInteger(row.quarantine_count, 0),
1439
+ last_activated_at: normalizeIsoTimestamp(row.last_activated_at, '') || null,
1440
+ last_quality_signal: normalizeString(row.last_quality_signal) || null,
1441
+ last_runtime: normalizeString(row.last_runtime) || null,
1442
+ rank_score: Number.isFinite(rankScore) ? Number(rankScore.toFixed(2)) : null,
1443
+ lineage: parseJsonSafe(row.lineage_json, {}) || {},
1444
+ publication: parseJsonSafe(row.publication_json, {}) || {},
1445
+ metrics: parseJsonSafe(row.metrics_json, {}) || {},
1446
+ created_at: normalizeIsoTimestamp(row.created_at) || null,
1447
+ updated_at: normalizeIsoTimestamp(row.updated_at) || null
1448
+ };
1449
+ }
1450
+
1119
1451
  _mapStateMigrationRow(row) {
1120
1452
  if (!row) {
1121
1453
  return null;
@@ -2779,6 +3111,1034 @@ class SceStateStore {
2779
3111
  .filter(Boolean);
2780
3112
  }
2781
3113
 
3114
+ async appendSupremeIntentAssessment(record = {}) {
3115
+ const action = normalizeString(record.action);
3116
+ const sourceKind = normalizeString(record.source_kind || record.sourceKind);
3117
+ if (!action || !sourceKind) {
3118
+ return null;
3119
+ }
3120
+
3121
+ const nowIso = this.now();
3122
+ const assessmentId = normalizeString(record.assessment_id || record.assessmentId)
3123
+ || `supreme-${Date.now()}-${crypto.randomBytes(3).toString('hex')}`;
3124
+ const normalized = {
3125
+ assessment_id: assessmentId,
3126
+ project_id: normalizeString(record.project_id || record.projectId) || null,
3127
+ channel_id: normalizeString(record.channel_id || record.channelId) || null,
3128
+ session_id: normalizeString(record.session_id || record.sessionId) || null,
3129
+ scene_id: normalizeString(record.scene_id || record.sceneId) || null,
3130
+ spec_id: normalizeString(record.spec_id || record.specId) || null,
3131
+ job_id: normalizeString(record.job_id || record.jobId) || null,
3132
+ source_kind: sourceKind,
3133
+ action,
3134
+ planning_allowed: normalizeBooleanValue(record.planning_allowed ?? record.planningAllowed, false),
3135
+ execution_allowed: normalizeBooleanValue(record.execution_allowed ?? record.executionAllowed, false),
3136
+ policy_path: normalizeString(record.policy_path || record.policyPath) || null,
3137
+ policy_loaded_from: normalizeString(record.policy_loaded_from || record.policyLoadedFrom) || null,
3138
+ original_text: normalizeString(record.original_text || record.originalText) || null,
3139
+ effective_text: normalizeString(record.effective_text || record.effectiveText) || null,
3140
+ message: normalizeString(record.message) || null,
3141
+ evidence_path: normalizeString(record.evidence_path || record.evidencePath) || null,
3142
+ worldview: record.worldview && typeof record.worldview === 'object' ? record.worldview : {},
3143
+ lifeview: record.lifeview && typeof record.lifeview === 'object' ? record.lifeview : {},
3144
+ values: record.values && typeof record.values === 'object' ? record.values : {},
3145
+ methodology: record.methodology && typeof record.methodology === 'object' ? record.methodology : {},
3146
+ matched_rules: record.matched_rules && typeof record.matched_rules === 'object' ? record.matched_rules : {},
3147
+ clarification_questions: normalizeStringArray(record.clarification_questions || record.clarificationQuestions, []),
3148
+ metadata: record.metadata && typeof record.metadata === 'object' ? record.metadata : {},
3149
+ created_at: normalizeIsoTimestamp(record.created_at || record.createdAt, nowIso) || nowIso,
3150
+ updated_at: normalizeIsoTimestamp(record.updated_at || record.updatedAt, nowIso) || nowIso
3151
+ };
3152
+
3153
+ if (this._useMemoryBackend()) {
3154
+ this._memory.supreme_intent_assessments[normalized.assessment_id] = { ...normalized };
3155
+ return this._mapSupremeIntentAssessmentRow({
3156
+ ...normalized,
3157
+ worldview_json: JSON.stringify(normalized.worldview || {}),
3158
+ lifeview_json: JSON.stringify(normalized.lifeview || {}),
3159
+ values_json: JSON.stringify(normalized.values || {}),
3160
+ methodology_json: JSON.stringify(normalized.methodology || {}),
3161
+ matched_rules_json: JSON.stringify(normalized.matched_rules || {}),
3162
+ clarification_questions_json: JSON.stringify(normalized.clarification_questions || []),
3163
+ metadata_json: JSON.stringify(normalized.metadata || {})
3164
+ });
3165
+ }
3166
+
3167
+ if (!await this.ensureReady()) {
3168
+ return null;
3169
+ }
3170
+
3171
+ this._db
3172
+ .prepare(`
3173
+ INSERT OR REPLACE INTO supreme_intent_assessment_registry(
3174
+ assessment_id, project_id, channel_id, session_id, scene_id, spec_id, job_id,
3175
+ source_kind, action, planning_allowed, execution_allowed, policy_path, policy_loaded_from,
3176
+ original_text, effective_text, message, evidence_path, worldview_json, lifeview_json,
3177
+ values_json, methodology_json, matched_rules_json, clarification_questions_json, metadata_json,
3178
+ created_at, updated_at
3179
+ )
3180
+ VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
3181
+ `)
3182
+ .run(
3183
+ normalized.assessment_id,
3184
+ normalized.project_id,
3185
+ normalized.channel_id,
3186
+ normalized.session_id,
3187
+ normalized.scene_id,
3188
+ normalized.spec_id,
3189
+ normalized.job_id,
3190
+ normalized.source_kind,
3191
+ normalized.action,
3192
+ normalized.planning_allowed ? 1 : 0,
3193
+ normalized.execution_allowed ? 1 : 0,
3194
+ normalized.policy_path,
3195
+ normalized.policy_loaded_from,
3196
+ normalized.original_text,
3197
+ normalized.effective_text,
3198
+ normalized.message,
3199
+ normalized.evidence_path,
3200
+ JSON.stringify(normalized.worldview || {}),
3201
+ JSON.stringify(normalized.lifeview || {}),
3202
+ JSON.stringify(normalized.values || {}),
3203
+ JSON.stringify(normalized.methodology || {}),
3204
+ JSON.stringify(normalized.matched_rules || {}),
3205
+ JSON.stringify(normalized.clarification_questions || []),
3206
+ JSON.stringify(normalized.metadata || {}),
3207
+ normalized.created_at,
3208
+ normalized.updated_at
3209
+ );
3210
+
3211
+ return this.getSupremeIntentAssessment(normalized.assessment_id);
3212
+ }
3213
+
3214
+ async getSupremeIntentAssessment(assessmentId) {
3215
+ const normalizedAssessmentId = normalizeString(assessmentId);
3216
+ if (!normalizedAssessmentId) {
3217
+ return null;
3218
+ }
3219
+
3220
+ if (this._useMemoryBackend()) {
3221
+ const row = this._memory.supreme_intent_assessments[normalizedAssessmentId];
3222
+ if (!row) {
3223
+ return null;
3224
+ }
3225
+ return this._mapSupremeIntentAssessmentRow({
3226
+ ...row,
3227
+ worldview_json: JSON.stringify(row.worldview || {}),
3228
+ lifeview_json: JSON.stringify(row.lifeview || {}),
3229
+ values_json: JSON.stringify(row.values || {}),
3230
+ methodology_json: JSON.stringify(row.methodology || {}),
3231
+ matched_rules_json: JSON.stringify(row.matched_rules || {}),
3232
+ clarification_questions_json: JSON.stringify(row.clarification_questions || []),
3233
+ metadata_json: JSON.stringify(row.metadata || {})
3234
+ });
3235
+ }
3236
+
3237
+ if (!await this.ensureReady()) {
3238
+ return null;
3239
+ }
3240
+
3241
+ const row = this._db
3242
+ .prepare(`
3243
+ SELECT assessment_id, project_id, channel_id, session_id, scene_id, spec_id, job_id,
3244
+ source_kind, action, planning_allowed, execution_allowed, policy_path, policy_loaded_from,
3245
+ original_text, effective_text, message, evidence_path, worldview_json, lifeview_json,
3246
+ values_json, methodology_json, matched_rules_json, clarification_questions_json, metadata_json,
3247
+ created_at, updated_at
3248
+ FROM supreme_intent_assessment_registry
3249
+ WHERE assessment_id = ?
3250
+ `)
3251
+ .get(normalizedAssessmentId);
3252
+ return this._mapSupremeIntentAssessmentRow(row);
3253
+ }
3254
+
3255
+ async listSupremeIntentAssessments(options = {}) {
3256
+ const limit = normalizeInteger(options.limit, 20);
3257
+ const projectId = normalizeString(options.project_id || options.projectId);
3258
+ const channelId = normalizeString(options.channel_id || options.channelId);
3259
+ const sessionId = normalizeString(options.session_id || options.sessionId);
3260
+ const sceneId = normalizeString(options.scene_id || options.sceneId);
3261
+ const specId = normalizeString(options.spec_id || options.specId);
3262
+ const jobId = normalizeString(options.job_id || options.jobId);
3263
+ const sourceKind = normalizeString(options.source_kind || options.sourceKind);
3264
+ const action = normalizeString(options.action);
3265
+
3266
+ if (this._useMemoryBackend()) {
3267
+ let rows = Object.values(this._memory.supreme_intent_assessments || {}).map((item) => ({ ...item }));
3268
+ if (projectId) rows = rows.filter((item) => normalizeString(item.project_id) === projectId);
3269
+ if (channelId) rows = rows.filter((item) => normalizeString(item.channel_id) === channelId);
3270
+ if (sessionId) rows = rows.filter((item) => normalizeString(item.session_id) === sessionId);
3271
+ if (sceneId) rows = rows.filter((item) => normalizeString(item.scene_id) === sceneId);
3272
+ if (specId) rows = rows.filter((item) => normalizeString(item.spec_id) === specId);
3273
+ if (jobId) rows = rows.filter((item) => normalizeString(item.job_id) === jobId);
3274
+ if (sourceKind) rows = rows.filter((item) => normalizeString(item.source_kind) === sourceKind);
3275
+ if (action) rows = rows.filter((item) => normalizeString(item.action) === action);
3276
+ rows.sort((left, right) => (Date.parse(right.updated_at || '') || 0) - (Date.parse(left.updated_at || '') || 0));
3277
+ if (limit > 0) {
3278
+ rows = rows.slice(0, limit);
3279
+ }
3280
+ return rows.map((row) => this._mapSupremeIntentAssessmentRow({
3281
+ ...row,
3282
+ worldview_json: JSON.stringify(row.worldview || {}),
3283
+ lifeview_json: JSON.stringify(row.lifeview || {}),
3284
+ values_json: JSON.stringify(row.values || {}),
3285
+ methodology_json: JSON.stringify(row.methodology || {}),
3286
+ matched_rules_json: JSON.stringify(row.matched_rules || {}),
3287
+ clarification_questions_json: JSON.stringify(row.clarification_questions || []),
3288
+ metadata_json: JSON.stringify(row.metadata || {})
3289
+ }));
3290
+ }
3291
+
3292
+ if (!await this.ensureReady()) {
3293
+ return null;
3294
+ }
3295
+
3296
+ let query = `
3297
+ SELECT assessment_id, project_id, channel_id, session_id, scene_id, spec_id, job_id,
3298
+ source_kind, action, planning_allowed, execution_allowed, policy_path, policy_loaded_from,
3299
+ original_text, effective_text, message, evidence_path, worldview_json, lifeview_json,
3300
+ values_json, methodology_json, matched_rules_json, clarification_questions_json, metadata_json,
3301
+ created_at, updated_at
3302
+ FROM supreme_intent_assessment_registry
3303
+ `;
3304
+ const params = [];
3305
+ const filters = [];
3306
+ if (projectId) { filters.push('project_id = ?'); params.push(projectId); }
3307
+ if (channelId) { filters.push('channel_id = ?'); params.push(channelId); }
3308
+ if (sessionId) { filters.push('session_id = ?'); params.push(sessionId); }
3309
+ if (sceneId) { filters.push('scene_id = ?'); params.push(sceneId); }
3310
+ if (specId) { filters.push('spec_id = ?'); params.push(specId); }
3311
+ if (jobId) { filters.push('job_id = ?'); params.push(jobId); }
3312
+ if (sourceKind) { filters.push('source_kind = ?'); params.push(sourceKind); }
3313
+ if (action) { filters.push('action = ?'); params.push(action); }
3314
+ if (filters.length > 0) {
3315
+ query += ` WHERE ${filters.join(' AND ')}`;
3316
+ }
3317
+ query += ' ORDER BY updated_at DESC';
3318
+ if (limit > 0) {
3319
+ query += ' LIMIT ?';
3320
+ params.push(limit);
3321
+ }
3322
+
3323
+ const rows = this._db.prepare(query).all(...params);
3324
+ return rows.map((row) => this._mapSupremeIntentAssessmentRow(row)).filter(Boolean);
3325
+ }
3326
+
3327
+ async appendSemanticObservation(record = {}) {
3328
+ const sourceRuntime = normalizeString(record.source_runtime || record.sourceRuntime);
3329
+ const eventKind = normalizeString(record.event_kind || record.eventKind);
3330
+ if (!sourceRuntime || !eventKind) {
3331
+ return null;
3332
+ }
3333
+
3334
+ const nowIso = this.now();
3335
+ const observationId = normalizeString(record.observation_id || record.observationId)
3336
+ || `sem-obs-${Date.now()}-${crypto.randomBytes(3).toString('hex')}`;
3337
+ const normalized = {
3338
+ observation_id: observationId,
3339
+ project_id: normalizeString(record.project_id || record.projectId) || null,
3340
+ channel_id: normalizeString(record.channel_id || record.channelId) || null,
3341
+ session_id: normalizeString(record.session_id || record.sessionId) || null,
3342
+ scene_id: normalizeString(record.scene_id || record.sceneId) || null,
3343
+ spec_id: normalizeString(record.spec_id || record.specId) || null,
3344
+ task_ref: normalizeString(record.task_ref || record.taskRef) || null,
3345
+ source_runtime: sourceRuntime,
3346
+ source_kind: normalizeString(record.source_kind || record.sourceKind) || 'embedded-host',
3347
+ host_session_id: normalizeString(record.host_session_id || record.hostSessionId) || null,
3348
+ event_kind: eventKind,
3349
+ role: normalizeString(record.role) || null,
3350
+ intent: normalizeString(record.intent) || null,
3351
+ summary: normalizeString(record.summary) || null,
3352
+ outcome: normalizeString(record.outcome) || null,
3353
+ quality_signal: normalizeString(record.quality_signal || record.qualitySignal) || null,
3354
+ raw_ref: normalizeString(record.raw_ref || record.rawRef) || null,
3355
+ raw_payload: record.raw_payload && typeof record.raw_payload === 'object'
3356
+ ? record.raw_payload
3357
+ : (record.rawPayload && typeof record.rawPayload === 'object' ? record.rawPayload : {}),
3358
+ normalized_payload: record.normalized_payload && typeof record.normalized_payload === 'object'
3359
+ ? record.normalized_payload
3360
+ : (record.normalizedPayload && typeof record.normalizedPayload === 'object' ? record.normalizedPayload : {}),
3361
+ created_at: normalizeIsoTimestamp(record.created_at || record.createdAt, nowIso) || nowIso,
3362
+ updated_at: normalizeIsoTimestamp(record.updated_at || record.updatedAt, nowIso) || nowIso
3363
+ };
3364
+
3365
+ if (this._useMemoryBackend()) {
3366
+ this._memory.semantic_observations[normalized.observation_id] = { ...normalized };
3367
+ return this._mapSemanticObservationRow({
3368
+ ...normalized,
3369
+ raw_payload_json: JSON.stringify(normalized.raw_payload || {}),
3370
+ normalized_payload_json: JSON.stringify(normalized.normalized_payload || {})
3371
+ });
3372
+ }
3373
+
3374
+ if (!await this.ensureReady()) {
3375
+ return null;
3376
+ }
3377
+
3378
+ this._db
3379
+ .prepare(`
3380
+ INSERT OR REPLACE INTO semantic_observation_registry(
3381
+ observation_id, project_id, channel_id, session_id, scene_id, spec_id, task_ref,
3382
+ source_runtime, source_kind, host_session_id, event_kind, role, intent, summary,
3383
+ outcome, quality_signal, raw_ref, raw_payload_json, normalized_payload_json, created_at, updated_at
3384
+ )
3385
+ VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
3386
+ `)
3387
+ .run(
3388
+ normalized.observation_id,
3389
+ normalized.project_id,
3390
+ normalized.channel_id,
3391
+ normalized.session_id,
3392
+ normalized.scene_id,
3393
+ normalized.spec_id,
3394
+ normalized.task_ref,
3395
+ normalized.source_runtime,
3396
+ normalized.source_kind,
3397
+ normalized.host_session_id,
3398
+ normalized.event_kind,
3399
+ normalized.role,
3400
+ normalized.intent,
3401
+ normalized.summary,
3402
+ normalized.outcome,
3403
+ normalized.quality_signal,
3404
+ normalized.raw_ref,
3405
+ JSON.stringify(normalized.raw_payload || {}),
3406
+ JSON.stringify(normalized.normalized_payload || {}),
3407
+ normalized.created_at,
3408
+ normalized.updated_at
3409
+ );
3410
+
3411
+ return this.getSemanticObservation(normalized.observation_id);
3412
+ }
3413
+
3414
+ async getSemanticObservation(observationId) {
3415
+ const normalizedObservationId = normalizeString(observationId);
3416
+ if (!normalizedObservationId) {
3417
+ return null;
3418
+ }
3419
+
3420
+ if (this._useMemoryBackend()) {
3421
+ const row = this._memory.semantic_observations[normalizedObservationId];
3422
+ if (!row) {
3423
+ return null;
3424
+ }
3425
+ return this._mapSemanticObservationRow({
3426
+ ...row,
3427
+ raw_payload_json: JSON.stringify(row.raw_payload || {}),
3428
+ normalized_payload_json: JSON.stringify(row.normalized_payload || {})
3429
+ });
3430
+ }
3431
+
3432
+ if (!await this.ensureReady()) {
3433
+ return null;
3434
+ }
3435
+
3436
+ const row = this._db
3437
+ .prepare(`
3438
+ SELECT observation_id, project_id, channel_id, session_id, scene_id, spec_id, task_ref,
3439
+ source_runtime, source_kind, host_session_id, event_kind, role, intent, summary,
3440
+ outcome, quality_signal, raw_ref, raw_payload_json, normalized_payload_json, created_at, updated_at
3441
+ FROM semantic_observation_registry
3442
+ WHERE observation_id = ?
3443
+ `)
3444
+ .get(normalizedObservationId);
3445
+ return this._mapSemanticObservationRow(row);
3446
+ }
3447
+
3448
+ async listSemanticObservations(options = {}) {
3449
+ const limit = normalizeInteger(options.limit, 20);
3450
+ const projectId = normalizeString(options.project_id || options.projectId);
3451
+ const sourceRuntime = normalizeString(options.source_runtime || options.sourceRuntime);
3452
+ const sessionId = normalizeString(options.session_id || options.sessionId);
3453
+
3454
+ if (this._useMemoryBackend()) {
3455
+ let rows = Object.values(this._memory.semantic_observations || {}).map((item) => ({ ...item }));
3456
+ if (projectId) {
3457
+ rows = rows.filter((item) => normalizeString(item.project_id) === projectId);
3458
+ }
3459
+ if (sourceRuntime) {
3460
+ rows = rows.filter((item) => normalizeString(item.source_runtime) === sourceRuntime);
3461
+ }
3462
+ if (sessionId) {
3463
+ rows = rows.filter((item) => normalizeString(item.session_id) === sessionId);
3464
+ }
3465
+ rows.sort((left, right) => (Date.parse(right.updated_at || '') || 0) - (Date.parse(left.updated_at || '') || 0));
3466
+ if (limit > 0) {
3467
+ rows = rows.slice(0, limit);
3468
+ }
3469
+ return rows.map((row) => this._mapSemanticObservationRow({
3470
+ ...row,
3471
+ raw_payload_json: JSON.stringify(row.raw_payload || {}),
3472
+ normalized_payload_json: JSON.stringify(row.normalized_payload || {})
3473
+ }));
3474
+ }
3475
+
3476
+ if (!await this.ensureReady()) {
3477
+ return null;
3478
+ }
3479
+
3480
+ let query = `
3481
+ SELECT observation_id, project_id, channel_id, session_id, scene_id, spec_id, task_ref,
3482
+ source_runtime, source_kind, host_session_id, event_kind, role, intent, summary,
3483
+ outcome, quality_signal, raw_ref, raw_payload_json, normalized_payload_json, created_at, updated_at
3484
+ FROM semantic_observation_registry
3485
+ `;
3486
+ const params = [];
3487
+ const filters = [];
3488
+ if (projectId) {
3489
+ filters.push('project_id = ?');
3490
+ params.push(projectId);
3491
+ }
3492
+ if (sourceRuntime) {
3493
+ filters.push('source_runtime = ?');
3494
+ params.push(sourceRuntime);
3495
+ }
3496
+ if (sessionId) {
3497
+ filters.push('session_id = ?');
3498
+ params.push(sessionId);
3499
+ }
3500
+ if (filters.length > 0) {
3501
+ query += ` WHERE ${filters.join(' AND ')}`;
3502
+ }
3503
+ query += ' ORDER BY updated_at DESC';
3504
+ if (limit > 0) {
3505
+ query += ' LIMIT ?';
3506
+ params.push(limit);
3507
+ }
3508
+
3509
+ const rows = this._db.prepare(query).all(...params);
3510
+ return rows.map((row) => this._mapSemanticObservationRow(row)).filter(Boolean);
3511
+ }
3512
+
3513
+ async upsertSemanticLessonCandidate(record = {}) {
3514
+ const lessonType = normalizeString(record.lesson_type || record.lessonType);
3515
+ if (!lessonType) {
3516
+ return null;
3517
+ }
3518
+ const nowIso = this.now();
3519
+ const lessonId = normalizeString(record.lesson_id || record.lessonId)
3520
+ || `sem-lesson-${Date.now()}-${crypto.randomBytes(3).toString('hex')}`;
3521
+ const confidenceValue = Number(record.confidence);
3522
+ const normalized = {
3523
+ lesson_id: lessonId,
3524
+ project_id: normalizeString(record.project_id || record.projectId) || null,
3525
+ scene_id: normalizeString(record.scene_id || record.sceneId) || null,
3526
+ spec_id: normalizeString(record.spec_id || record.specId) || null,
3527
+ source_runtime: normalizeString(record.source_runtime || record.sourceRuntime) || null,
3528
+ fingerprint: normalizeString(record.fingerprint) || null,
3529
+ lesson_type: lessonType,
3530
+ title: normalizeString(record.title) || null,
3531
+ summary: normalizeString(record.summary) || null,
3532
+ heuristic: normalizeString(record.heuristic) || null,
3533
+ confidence: Number.isFinite(confidenceValue) ? confidenceValue : null,
3534
+ status: normalizeString(record.status) || 'candidate',
3535
+ evidence: record.evidence && typeof record.evidence === 'object' ? record.evidence : {},
3536
+ metadata: record.metadata && typeof record.metadata === 'object' ? record.metadata : {},
3537
+ created_at: normalizeIsoTimestamp(record.created_at || record.createdAt, nowIso) || nowIso,
3538
+ updated_at: normalizeIsoTimestamp(record.updated_at || record.updatedAt, nowIso) || nowIso
3539
+ };
3540
+
3541
+ if (this._useMemoryBackend()) {
3542
+ this._memory.semantic_lesson_candidates[normalized.lesson_id] = { ...normalized };
3543
+ return this._mapSemanticLessonCandidateRow({
3544
+ ...normalized,
3545
+ evidence_json: JSON.stringify(normalized.evidence || {}),
3546
+ metadata_json: JSON.stringify(normalized.metadata || {})
3547
+ });
3548
+ }
3549
+
3550
+ if (!await this.ensureReady()) {
3551
+ return null;
3552
+ }
3553
+
3554
+ this._db
3555
+ .prepare(`
3556
+ INSERT OR REPLACE INTO semantic_lesson_candidate_registry(
3557
+ lesson_id, project_id, scene_id, spec_id, source_runtime, fingerprint, lesson_type,
3558
+ title, summary, heuristic, confidence, status, evidence_json, metadata_json, created_at, updated_at
3559
+ )
3560
+ VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
3561
+ `)
3562
+ .run(
3563
+ normalized.lesson_id,
3564
+ normalized.project_id,
3565
+ normalized.scene_id,
3566
+ normalized.spec_id,
3567
+ normalized.source_runtime,
3568
+ normalized.fingerprint,
3569
+ normalized.lesson_type,
3570
+ normalized.title,
3571
+ normalized.summary,
3572
+ normalized.heuristic,
3573
+ normalized.confidence,
3574
+ normalized.status,
3575
+ JSON.stringify(normalized.evidence || {}),
3576
+ JSON.stringify(normalized.metadata || {}),
3577
+ normalized.created_at,
3578
+ normalized.updated_at
3579
+ );
3580
+
3581
+ return this.getSemanticLessonCandidate(normalized.lesson_id);
3582
+ }
3583
+
3584
+ async getSemanticLessonCandidate(lessonId) {
3585
+ const normalizedLessonId = normalizeString(lessonId);
3586
+ if (!normalizedLessonId) {
3587
+ return null;
3588
+ }
3589
+
3590
+ if (this._useMemoryBackend()) {
3591
+ const row = this._memory.semantic_lesson_candidates[normalizedLessonId];
3592
+ if (!row) {
3593
+ return null;
3594
+ }
3595
+ return this._mapSemanticLessonCandidateRow({
3596
+ ...row,
3597
+ evidence_json: JSON.stringify(row.evidence || {}),
3598
+ metadata_json: JSON.stringify(row.metadata || {})
3599
+ });
3600
+ }
3601
+
3602
+ if (!await this.ensureReady()) {
3603
+ return null;
3604
+ }
3605
+
3606
+ const row = this._db
3607
+ .prepare(`
3608
+ SELECT lesson_id, project_id, scene_id, spec_id, source_runtime, fingerprint, lesson_type,
3609
+ title, summary, heuristic, confidence, status, evidence_json, metadata_json, created_at, updated_at
3610
+ FROM semantic_lesson_candidate_registry
3611
+ WHERE lesson_id = ?
3612
+ `)
3613
+ .get(normalizedLessonId);
3614
+ return this._mapSemanticLessonCandidateRow(row);
3615
+ }
3616
+
3617
+ async listSemanticLessonCandidates(options = {}) {
3618
+ const limit = normalizeInteger(options.limit, 20);
3619
+ const projectId = normalizeString(options.project_id || options.projectId);
3620
+ const status = normalizeString(options.status);
3621
+
3622
+ if (this._useMemoryBackend()) {
3623
+ let rows = Object.values(this._memory.semantic_lesson_candidates || {}).map((item) => ({ ...item }));
3624
+ if (projectId) {
3625
+ rows = rows.filter((item) => normalizeString(item.project_id) === projectId);
3626
+ }
3627
+ if (status) {
3628
+ rows = rows.filter((item) => normalizeString(item.status) === status);
3629
+ }
3630
+ rows.sort((left, right) => (Date.parse(right.updated_at || '') || 0) - (Date.parse(left.updated_at || '') || 0));
3631
+ if (limit > 0) {
3632
+ rows = rows.slice(0, limit);
3633
+ }
3634
+ return rows.map((row) => this._mapSemanticLessonCandidateRow({
3635
+ ...row,
3636
+ evidence_json: JSON.stringify(row.evidence || {}),
3637
+ metadata_json: JSON.stringify(row.metadata || {})
3638
+ }));
3639
+ }
3640
+
3641
+ if (!await this.ensureReady()) {
3642
+ return null;
3643
+ }
3644
+
3645
+ let query = `
3646
+ SELECT lesson_id, project_id, scene_id, spec_id, source_runtime, fingerprint, lesson_type,
3647
+ title, summary, heuristic, confidence, status, evidence_json, metadata_json, created_at, updated_at
3648
+ FROM semantic_lesson_candidate_registry
3649
+ `;
3650
+ const params = [];
3651
+ const filters = [];
3652
+ if (projectId) {
3653
+ filters.push('project_id = ?');
3654
+ params.push(projectId);
3655
+ }
3656
+ if (status) {
3657
+ filters.push('status = ?');
3658
+ params.push(status);
3659
+ }
3660
+ if (filters.length > 0) {
3661
+ query += ` WHERE ${filters.join(' AND ')}`;
3662
+ }
3663
+ query += ' ORDER BY updated_at DESC';
3664
+ if (limit > 0) {
3665
+ query += ' LIMIT ?';
3666
+ params.push(limit);
3667
+ }
3668
+
3669
+ const rows = this._db.prepare(query).all(...params);
3670
+ return rows.map((row) => this._mapSemanticLessonCandidateRow(row)).filter(Boolean);
3671
+ }
3672
+
3673
+ async appendSemanticEvaluationRun(record = {}) {
3674
+ const candidateKind = normalizeString(record.candidate_kind || record.candidateKind);
3675
+ if (!candidateKind) {
3676
+ return null;
3677
+ }
3678
+
3679
+ const nowIso = this.now();
3680
+ const evaluationRunId = normalizeString(record.evaluation_run_id || record.evaluationRunId)
3681
+ || `sem-eval-${Date.now()}-${crypto.randomBytes(3).toString('hex')}`;
3682
+ const scoreValue = Number(record.score);
3683
+ const thresholdValue = Number(record.threshold);
3684
+ const normalized = {
3685
+ evaluation_run_id: evaluationRunId,
3686
+ project_id: normalizeString(record.project_id || record.projectId) || null,
3687
+ channel_id: normalizeString(record.channel_id || record.channelId) || null,
3688
+ session_id: normalizeString(record.session_id || record.sessionId) || null,
3689
+ scene_id: normalizeString(record.scene_id || record.sceneId) || null,
3690
+ spec_id: normalizeString(record.spec_id || record.specId) || null,
3691
+ lesson_id: normalizeString(record.lesson_id || record.lessonId) || null,
3692
+ source_runtime: normalizeString(record.source_runtime || record.sourceRuntime) || null,
3693
+ release_gate: normalizeString(record.release_gate || record.releaseGate) || null,
3694
+ baseline_evaluation_run_id: normalizeString(record.baseline_evaluation_run_id || record.baselineEvaluationRunId) || null,
3695
+ candidate_kind: candidateKind,
3696
+ candidate_label: normalizeString(record.candidate_label || record.candidateLabel) || null,
3697
+ candidate_payload: record.candidate_payload && typeof record.candidate_payload === 'object'
3698
+ ? record.candidate_payload
3699
+ : (record.candidatePayload && typeof record.candidatePayload === 'object' ? record.candidatePayload : {}),
3700
+ observation_ids: normalizeStringArray(record.observation_ids || record.observationIds, []),
3701
+ replay_summary: record.replay_summary && typeof record.replay_summary === 'object'
3702
+ ? record.replay_summary
3703
+ : (record.replaySummary && typeof record.replaySummary === 'object' ? record.replaySummary : {}),
3704
+ score: Number.isFinite(scoreValue) ? Number(scoreValue.toFixed(2)) : null,
3705
+ threshold: Number.isFinite(thresholdValue) ? Number(thresholdValue.toFixed(2)) : null,
3706
+ verdict: normalizeString(record.verdict) || null,
3707
+ regression_detected: normalizeBooleanValue(record.regression_detected || record.regressionDetected, false),
3708
+ drift_level: normalizeString(record.drift_level || record.driftLevel) || null,
3709
+ regression_reasons: normalizeStringArray(record.regression_reasons || record.regressionReasons, []),
3710
+ evidence: record.evidence && typeof record.evidence === 'object' ? record.evidence : {},
3711
+ governance: record.governance && typeof record.governance === 'object' ? record.governance : {},
3712
+ created_at: normalizeIsoTimestamp(record.created_at || record.createdAt, nowIso) || nowIso,
3713
+ updated_at: normalizeIsoTimestamp(record.updated_at || record.updatedAt, nowIso) || nowIso
3714
+ };
3715
+
3716
+ if (this._useMemoryBackend()) {
3717
+ this._memory.semantic_evaluation_runs[normalized.evaluation_run_id] = { ...normalized };
3718
+ return this._mapSemanticEvaluationRunRow({
3719
+ ...normalized,
3720
+ candidate_payload_json: JSON.stringify(normalized.candidate_payload || {}),
3721
+ observation_ids_json: JSON.stringify(normalized.observation_ids || []),
3722
+ replay_summary_json: JSON.stringify(normalized.replay_summary || {}),
3723
+ regression_reasons_json: JSON.stringify(normalized.regression_reasons || []),
3724
+ evidence_json: JSON.stringify(normalized.evidence || {}),
3725
+ governance_json: JSON.stringify(normalized.governance || {})
3726
+ });
3727
+ }
3728
+
3729
+ if (!await this.ensureReady()) {
3730
+ return null;
3731
+ }
3732
+
3733
+ this._db
3734
+ .prepare(`
3735
+ INSERT OR REPLACE INTO semantic_evaluation_run_registry(
3736
+ evaluation_run_id, project_id, channel_id, session_id, scene_id, spec_id, lesson_id,
3737
+ source_runtime, release_gate, baseline_evaluation_run_id, candidate_kind, candidate_label,
3738
+ candidate_payload_json, observation_ids_json, replay_summary_json, score, threshold, verdict,
3739
+ regression_detected, drift_level, regression_reasons_json, evidence_json, governance_json,
3740
+ created_at, updated_at
3741
+ )
3742
+ VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
3743
+ `)
3744
+ .run(
3745
+ normalized.evaluation_run_id,
3746
+ normalized.project_id,
3747
+ normalized.channel_id,
3748
+ normalized.session_id,
3749
+ normalized.scene_id,
3750
+ normalized.spec_id,
3751
+ normalized.lesson_id,
3752
+ normalized.source_runtime,
3753
+ normalized.release_gate,
3754
+ normalized.baseline_evaluation_run_id,
3755
+ normalized.candidate_kind,
3756
+ normalized.candidate_label,
3757
+ JSON.stringify(normalized.candidate_payload || {}),
3758
+ JSON.stringify(normalized.observation_ids || []),
3759
+ JSON.stringify(normalized.replay_summary || {}),
3760
+ normalized.score,
3761
+ normalized.threshold,
3762
+ normalized.verdict,
3763
+ normalized.regression_detected ? 1 : 0,
3764
+ normalized.drift_level,
3765
+ JSON.stringify(normalized.regression_reasons || []),
3766
+ JSON.stringify(normalized.evidence || {}),
3767
+ JSON.stringify(normalized.governance || {}),
3768
+ normalized.created_at,
3769
+ normalized.updated_at
3770
+ );
3771
+
3772
+ return this.getSemanticEvaluationRun(normalized.evaluation_run_id);
3773
+ }
3774
+
3775
+ async getSemanticEvaluationRun(evaluationRunId) {
3776
+ const normalizedEvaluationRunId = normalizeString(evaluationRunId);
3777
+ if (!normalizedEvaluationRunId) {
3778
+ return null;
3779
+ }
3780
+
3781
+ if (this._useMemoryBackend()) {
3782
+ const row = this._memory.semantic_evaluation_runs[normalizedEvaluationRunId];
3783
+ if (!row) {
3784
+ return null;
3785
+ }
3786
+ return this._mapSemanticEvaluationRunRow({
3787
+ ...row,
3788
+ candidate_payload_json: JSON.stringify(row.candidate_payload || {}),
3789
+ observation_ids_json: JSON.stringify(row.observation_ids || []),
3790
+ replay_summary_json: JSON.stringify(row.replay_summary || {}),
3791
+ regression_reasons_json: JSON.stringify(row.regression_reasons || []),
3792
+ evidence_json: JSON.stringify(row.evidence || {}),
3793
+ governance_json: JSON.stringify(row.governance || {})
3794
+ });
3795
+ }
3796
+
3797
+ if (!await this.ensureReady()) {
3798
+ return null;
3799
+ }
3800
+
3801
+ const row = this._db
3802
+ .prepare(`
3803
+ SELECT evaluation_run_id, project_id, channel_id, session_id, scene_id, spec_id, lesson_id,
3804
+ source_runtime, release_gate, baseline_evaluation_run_id, candidate_kind, candidate_label,
3805
+ candidate_payload_json, observation_ids_json, replay_summary_json, score, threshold, verdict,
3806
+ regression_detected, drift_level, regression_reasons_json, evidence_json, governance_json,
3807
+ created_at, updated_at
3808
+ FROM semantic_evaluation_run_registry
3809
+ WHERE evaluation_run_id = ?
3810
+ `)
3811
+ .get(normalizedEvaluationRunId);
3812
+ return this._mapSemanticEvaluationRunRow(row);
3813
+ }
3814
+
3815
+ async listSemanticEvaluationRuns(options = {}) {
3816
+ const limit = normalizeInteger(options.limit, 20);
3817
+ const projectId = normalizeString(options.project_id || options.projectId);
3818
+ const sessionId = normalizeString(options.session_id || options.sessionId);
3819
+ const specId = normalizeString(options.spec_id || options.specId);
3820
+ const verdict = normalizeString(options.verdict);
3821
+
3822
+ if (this._useMemoryBackend()) {
3823
+ let rows = Object.values(this._memory.semantic_evaluation_runs || {}).map((item) => ({ ...item }));
3824
+ if (projectId) {
3825
+ rows = rows.filter((item) => normalizeString(item.project_id) === projectId);
3826
+ }
3827
+ if (sessionId) {
3828
+ rows = rows.filter((item) => normalizeString(item.session_id) === sessionId);
3829
+ }
3830
+ if (specId) {
3831
+ rows = rows.filter((item) => normalizeString(item.spec_id) === specId);
3832
+ }
3833
+ if (verdict) {
3834
+ rows = rows.filter((item) => normalizeString(item.verdict) === verdict);
3835
+ }
3836
+ rows.sort((left, right) => (Date.parse(right.updated_at || '') || 0) - (Date.parse(left.updated_at || '') || 0));
3837
+ if (limit > 0) {
3838
+ rows = rows.slice(0, limit);
3839
+ }
3840
+ return rows.map((row) => this._mapSemanticEvaluationRunRow({
3841
+ ...row,
3842
+ candidate_payload_json: JSON.stringify(row.candidate_payload || {}),
3843
+ observation_ids_json: JSON.stringify(row.observation_ids || []),
3844
+ replay_summary_json: JSON.stringify(row.replay_summary || {}),
3845
+ regression_reasons_json: JSON.stringify(row.regression_reasons || []),
3846
+ evidence_json: JSON.stringify(row.evidence || {}),
3847
+ governance_json: JSON.stringify(row.governance || {})
3848
+ }));
3849
+ }
3850
+
3851
+ if (!await this.ensureReady()) {
3852
+ return null;
3853
+ }
3854
+
3855
+ let query = `
3856
+ SELECT evaluation_run_id, project_id, channel_id, session_id, scene_id, spec_id, lesson_id,
3857
+ source_runtime, release_gate, baseline_evaluation_run_id, candidate_kind, candidate_label,
3858
+ candidate_payload_json, observation_ids_json, replay_summary_json, score, threshold, verdict,
3859
+ regression_detected, drift_level, regression_reasons_json, evidence_json, governance_json,
3860
+ created_at, updated_at
3861
+ FROM semantic_evaluation_run_registry
3862
+ `;
3863
+ const params = [];
3864
+ const filters = [];
3865
+ if (projectId) {
3866
+ filters.push('project_id = ?');
3867
+ params.push(projectId);
3868
+ }
3869
+ if (sessionId) {
3870
+ filters.push('session_id = ?');
3871
+ params.push(sessionId);
3872
+ }
3873
+ if (specId) {
3874
+ filters.push('spec_id = ?');
3875
+ params.push(specId);
3876
+ }
3877
+ if (verdict) {
3878
+ filters.push('verdict = ?');
3879
+ params.push(verdict);
3880
+ }
3881
+ if (filters.length > 0) {
3882
+ query += ` WHERE ${filters.join(' AND ')}`;
3883
+ }
3884
+ query += ' ORDER BY updated_at DESC';
3885
+ if (limit > 0) {
3886
+ query += ' LIMIT ?';
3887
+ params.push(limit);
3888
+ }
3889
+
3890
+ const rows = this._db.prepare(query).all(...params);
3891
+ return rows.map((row) => this._mapSemanticEvaluationRunRow(row)).filter(Boolean);
3892
+ }
3893
+
3894
+ async upsertSemanticCapabilityLedger(record = {}) {
3895
+ const capabilityId = normalizeString(record.capability_id || record.capabilityId);
3896
+ if (!capabilityId) {
3897
+ return null;
3898
+ }
3899
+
3900
+ const nowIso = this.now();
3901
+ const metrics = record.metrics && typeof record.metrics === 'object' ? record.metrics : {};
3902
+ const lineage = record.lineage && typeof record.lineage === 'object' ? record.lineage : {};
3903
+ const publication = record.publication && typeof record.publication === 'object' ? record.publication : {};
3904
+ const rankScoreValue = Number(record.rank_score ?? record.rankScore ?? metrics.rank_score);
3905
+
3906
+ const normalized = {
3907
+ capability_id: capabilityId,
3908
+ lesson_id: normalizeString(record.lesson_id || record.lessonId) || null,
3909
+ evaluation_run_id: normalizeString(record.evaluation_run_id || record.evaluationRunId) || null,
3910
+ project_id: normalizeString(record.project_id || record.projectId) || null,
3911
+ channel_id: normalizeString(record.channel_id || record.channelId) || null,
3912
+ session_id: normalizeString(record.session_id || record.sessionId) || null,
3913
+ scene_id: normalizeString(record.scene_id || record.sceneId) || null,
3914
+ spec_id: normalizeString(record.spec_id || record.specId) || null,
3915
+ target_library: normalizeString(record.target_library || record.targetLibrary) || null,
3916
+ capability_status: normalizeString(record.capability_status || record.capabilityStatus) || 'candidate',
3917
+ publish_state: normalizeString(record.publish_state || record.publishState || publication.publish_state) || 'pending',
3918
+ activation_count: normalizeNonNegativeInteger(
3919
+ record.activation_count ?? record.activationCount ?? metrics.activation_count,
3920
+ 0
3921
+ ),
3922
+ activation_success_count: normalizeNonNegativeInteger(
3923
+ record.activation_success_count ?? record.activationSuccessCount ?? metrics.activation_success_count,
3924
+ 0
3925
+ ),
3926
+ activation_mixed_count: normalizeNonNegativeInteger(
3927
+ record.activation_mixed_count ?? record.activationMixedCount ?? metrics.activation_mixed_count,
3928
+ 0
3929
+ ),
3930
+ activation_negative_count: normalizeNonNegativeInteger(
3931
+ record.activation_negative_count ?? record.activationNegativeCount ?? metrics.activation_negative_count,
3932
+ 0
3933
+ ),
3934
+ quarantine_count: normalizeNonNegativeInteger(
3935
+ record.quarantine_count ?? record.quarantineCount ?? metrics.quarantine_count,
3936
+ 0
3937
+ ),
3938
+ last_activated_at: normalizeIsoTimestamp(record.last_activated_at || record.lastActivatedAt, '') || null,
3939
+ last_quality_signal: normalizeString(record.last_quality_signal || record.lastQualitySignal || metrics.last_quality_signal) || null,
3940
+ last_runtime: normalizeString(record.last_runtime || record.lastRuntime || metrics.last_runtime) || null,
3941
+ rank_score: Number.isFinite(rankScoreValue) ? Number(rankScoreValue.toFixed(2)) : null,
3942
+ lineage,
3943
+ publication,
3944
+ metrics,
3945
+ created_at: normalizeIsoTimestamp(record.created_at || record.createdAt, nowIso) || nowIso,
3946
+ updated_at: normalizeIsoTimestamp(record.updated_at || record.updatedAt, nowIso) || nowIso
3947
+ };
3948
+
3949
+ if (this._useMemoryBackend()) {
3950
+ this._memory.semantic_capability_ledgers[normalized.capability_id] = { ...normalized };
3951
+ return this._mapSemanticCapabilityLedgerRow({
3952
+ ...normalized,
3953
+ lineage_json: JSON.stringify(normalized.lineage || {}),
3954
+ publication_json: JSON.stringify(normalized.publication || {}),
3955
+ metrics_json: JSON.stringify(normalized.metrics || {})
3956
+ });
3957
+ }
3958
+
3959
+ if (!await this.ensureReady()) {
3960
+ return null;
3961
+ }
3962
+
3963
+ this._db
3964
+ .prepare(`
3965
+ INSERT OR REPLACE INTO semantic_capability_ledger_registry(
3966
+ capability_id, lesson_id, evaluation_run_id, project_id, channel_id, session_id, scene_id, spec_id,
3967
+ target_library, capability_status, publish_state, activation_count, activation_success_count,
3968
+ activation_mixed_count, activation_negative_count, quarantine_count, last_activated_at,
3969
+ last_quality_signal, last_runtime, rank_score, lineage_json, publication_json, metrics_json,
3970
+ created_at, updated_at
3971
+ )
3972
+ VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
3973
+ `)
3974
+ .run(
3975
+ normalized.capability_id,
3976
+ normalized.lesson_id,
3977
+ normalized.evaluation_run_id,
3978
+ normalized.project_id,
3979
+ normalized.channel_id,
3980
+ normalized.session_id,
3981
+ normalized.scene_id,
3982
+ normalized.spec_id,
3983
+ normalized.target_library,
3984
+ normalized.capability_status,
3985
+ normalized.publish_state,
3986
+ normalized.activation_count,
3987
+ normalized.activation_success_count,
3988
+ normalized.activation_mixed_count,
3989
+ normalized.activation_negative_count,
3990
+ normalized.quarantine_count,
3991
+ normalized.last_activated_at,
3992
+ normalized.last_quality_signal,
3993
+ normalized.last_runtime,
3994
+ normalized.rank_score,
3995
+ JSON.stringify(normalized.lineage || {}),
3996
+ JSON.stringify(normalized.publication || {}),
3997
+ JSON.stringify(normalized.metrics || {}),
3998
+ normalized.created_at,
3999
+ normalized.updated_at
4000
+ );
4001
+
4002
+ return this.getSemanticCapabilityLedger(normalized.capability_id);
4003
+ }
4004
+
4005
+ async getSemanticCapabilityLedger(capabilityId) {
4006
+ const normalizedCapabilityId = normalizeString(capabilityId);
4007
+ if (!normalizedCapabilityId) {
4008
+ return null;
4009
+ }
4010
+
4011
+ if (this._useMemoryBackend()) {
4012
+ const row = this._memory.semantic_capability_ledgers[normalizedCapabilityId];
4013
+ if (!row) {
4014
+ return null;
4015
+ }
4016
+ return this._mapSemanticCapabilityLedgerRow({
4017
+ ...row,
4018
+ lineage_json: JSON.stringify(row.lineage || {}),
4019
+ publication_json: JSON.stringify(row.publication || {}),
4020
+ metrics_json: JSON.stringify(row.metrics || {})
4021
+ });
4022
+ }
4023
+
4024
+ if (!await this.ensureReady()) {
4025
+ return null;
4026
+ }
4027
+
4028
+ const row = this._db
4029
+ .prepare(`
4030
+ SELECT capability_id, lesson_id, evaluation_run_id, project_id, channel_id, session_id, scene_id, spec_id,
4031
+ target_library, capability_status, publish_state, activation_count, activation_success_count,
4032
+ activation_mixed_count, activation_negative_count, quarantine_count, last_activated_at,
4033
+ last_quality_signal, last_runtime, rank_score, lineage_json, publication_json, metrics_json,
4034
+ created_at, updated_at
4035
+ FROM semantic_capability_ledger_registry
4036
+ WHERE capability_id = ?
4037
+ `)
4038
+ .get(normalizedCapabilityId);
4039
+ return this._mapSemanticCapabilityLedgerRow(row);
4040
+ }
4041
+
4042
+ async listSemanticCapabilityLedgers(options = {}) {
4043
+ const limit = normalizeInteger(options.limit, 20);
4044
+ const projectId = normalizeString(options.project_id || options.projectId);
4045
+ const lessonId = normalizeString(options.lesson_id || options.lessonId);
4046
+ const sceneId = normalizeString(options.scene_id || options.sceneId);
4047
+ const specId = normalizeString(options.spec_id || options.specId);
4048
+ const targetLibrary = normalizeString(options.target_library || options.targetLibrary);
4049
+ const capabilityStatus = normalizeString(options.capability_status || options.capabilityStatus);
4050
+ const publishState = normalizeString(options.publish_state || options.publishState);
4051
+
4052
+ if (this._useMemoryBackend()) {
4053
+ let rows = Object.values(this._memory.semantic_capability_ledgers || {}).map((item) => ({ ...item }));
4054
+ if (projectId) {
4055
+ rows = rows.filter((item) => normalizeString(item.project_id) === projectId);
4056
+ }
4057
+ if (lessonId) {
4058
+ rows = rows.filter((item) => normalizeString(item.lesson_id) === lessonId);
4059
+ }
4060
+ if (sceneId) {
4061
+ rows = rows.filter((item) => normalizeString(item.scene_id) === sceneId);
4062
+ }
4063
+ if (specId) {
4064
+ rows = rows.filter((item) => normalizeString(item.spec_id) === specId);
4065
+ }
4066
+ if (targetLibrary) {
4067
+ rows = rows.filter((item) => normalizeString(item.target_library) === targetLibrary);
4068
+ }
4069
+ if (capabilityStatus) {
4070
+ rows = rows.filter((item) => normalizeString(item.capability_status) === capabilityStatus);
4071
+ }
4072
+ if (publishState) {
4073
+ rows = rows.filter((item) => normalizeString(item.publish_state) === publishState);
4074
+ }
4075
+ rows.sort((left, right) => (Date.parse(right.updated_at || '') || 0) - (Date.parse(left.updated_at || '') || 0));
4076
+ if (limit > 0) {
4077
+ rows = rows.slice(0, limit);
4078
+ }
4079
+ return rows.map((row) => this._mapSemanticCapabilityLedgerRow({
4080
+ ...row,
4081
+ lineage_json: JSON.stringify(row.lineage || {}),
4082
+ publication_json: JSON.stringify(row.publication || {}),
4083
+ metrics_json: JSON.stringify(row.metrics || {})
4084
+ }));
4085
+ }
4086
+
4087
+ if (!await this.ensureReady()) {
4088
+ return null;
4089
+ }
4090
+
4091
+ let query = `
4092
+ SELECT capability_id, lesson_id, evaluation_run_id, project_id, channel_id, session_id, scene_id, spec_id,
4093
+ target_library, capability_status, publish_state, activation_count, activation_success_count,
4094
+ activation_mixed_count, activation_negative_count, quarantine_count, last_activated_at,
4095
+ last_quality_signal, last_runtime, rank_score, lineage_json, publication_json, metrics_json,
4096
+ created_at, updated_at
4097
+ FROM semantic_capability_ledger_registry
4098
+ `;
4099
+ const params = [];
4100
+ const filters = [];
4101
+ if (projectId) {
4102
+ filters.push('project_id = ?');
4103
+ params.push(projectId);
4104
+ }
4105
+ if (lessonId) {
4106
+ filters.push('lesson_id = ?');
4107
+ params.push(lessonId);
4108
+ }
4109
+ if (sceneId) {
4110
+ filters.push('scene_id = ?');
4111
+ params.push(sceneId);
4112
+ }
4113
+ if (specId) {
4114
+ filters.push('spec_id = ?');
4115
+ params.push(specId);
4116
+ }
4117
+ if (targetLibrary) {
4118
+ filters.push('target_library = ?');
4119
+ params.push(targetLibrary);
4120
+ }
4121
+ if (capabilityStatus) {
4122
+ filters.push('capability_status = ?');
4123
+ params.push(capabilityStatus);
4124
+ }
4125
+ if (publishState) {
4126
+ filters.push('publish_state = ?');
4127
+ params.push(publishState);
4128
+ }
4129
+ if (filters.length > 0) {
4130
+ query += ` WHERE ${filters.join(' AND ')}`;
4131
+ }
4132
+ query += ' ORDER BY updated_at DESC';
4133
+ if (limit > 0) {
4134
+ query += ' LIMIT ?';
4135
+ params.push(limit);
4136
+ }
4137
+
4138
+ const rows = this._db.prepare(query).all(...params);
4139
+ return rows.map((row) => this._mapSemanticCapabilityLedgerRow(row)).filter(Boolean);
4140
+ }
4141
+
2782
4142
  async appendStateMigrationRecord(record = {}) {
2783
4143
  const componentId = normalizeString(record.component_id || record.componentId);
2784
4144
  if (!componentId) {