@team-semicolon/semicolony-cli 4.18.51

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 (164) hide show
  1. package/LICENSE +200 -0
  2. package/NOTICE +8 -0
  3. package/README.md +152 -0
  4. package/dist/bundle.js +2887 -0
  5. package/dist/templates/launchd/ai.semicolony.host-signals-sidecar.plist +40 -0
  6. package/migrations/001_initial.sql +280 -0
  7. package/migrations/002_add_indexes.sql +11 -0
  8. package/migrations/003_add_fk.sql +32 -0
  9. package/migrations/004_session_count_trigger.sql +35 -0
  10. package/migrations/005_bot_workspace_audits.sql +16 -0
  11. package/migrations/006_bot_kb_subscriptions.sql +24 -0
  12. package/migrations/007_flatten_skill_names.sql +16 -0
  13. package/migrations/008_bot_workspace_files.sql +14 -0
  14. package/migrations/009_enforce_flat_skill_names.sql +53 -0
  15. package/migrations/010_bot_delegation.sql +27 -0
  16. package/migrations/011_drop_legacy_tables.sql +35 -0
  17. package/migrations/012_drop_bot_knowledge.sql +16 -0
  18. package/migrations/013_kb_workspace_domains.sql +88 -0
  19. package/migrations/014_timestamp_to_timestamptz.sql +33 -0
  20. package/migrations/015_kb_domain_enforcement.sql +83 -0
  21. package/migrations/016_ontology_redesign.sql +108 -0
  22. package/migrations/017_ontology_instance_model.sql +151 -0
  23. package/migrations/018_type_schema.sql +11 -0
  24. package/migrations/019_test_management.sql +69 -0
  25. package/migrations/020_bot_workspace_standard.sql +174 -0
  26. package/migrations/021_drop_dead_tables.sql +8 -0
  27. package/migrations/021_test_declarative.sql +19 -0
  28. package/migrations/022_bot_ontology_type.sql +38 -0
  29. package/migrations/022_kb_schema_enforcement.sql +77 -0
  30. package/migrations/023_decision_key_cleanup.ts +154 -0
  31. package/migrations/024_embedding_backfill.ts +137 -0
  32. package/migrations/025_kb_flat_keys.sql +33 -0
  33. package/migrations/026_drop_session_log.sql +19 -0
  34. package/migrations/027_kb_manager_skill.sql +22 -0
  35. package/migrations/028_skill_definitions_to_semicolony.sql +19 -0
  36. package/migrations/029_agents_citation_max_lines.sql +6 -0
  37. package/migrations/030_team_ontology.sql +54 -0
  38. package/migrations/031_gfp_tables.sql +101 -0
  39. package/migrations/031_kb_manager_domain_register.sql +12 -0
  40. package/migrations/032_gfp_skill_and_callback.sql +40 -0
  41. package/migrations/032_kebab_case_keys.sql +33 -0
  42. package/migrations/033_skill_workspace_rules.sql +10 -0
  43. package/migrations/034_current_to_date_keys.sql +13 -0
  44. package/migrations/034_current_to_date_keys.ts +104 -0
  45. package/migrations/035_bot_budgets.sql +51 -0
  46. package/migrations/036_gfp_stitch_design.sql +35 -0
  47. package/migrations/037_gfp_qa_sections.sql +13 -0
  48. package/migrations/038_gfp_phase_split.sql +26 -0
  49. package/migrations/039_meeting_audio_data.sql +2 -0
  50. package/migrations/040_bot_commitments.sql +68 -0
  51. package/migrations/041_palette_previews.sql +13 -0
  52. package/migrations/042_gfp_parallel_tracks.sql +37 -0
  53. package/migrations/043_blocker_key.sql +13 -0
  54. package/migrations/044_gfp_stitch_screenshots.sql +9 -0
  55. package/migrations/045_service_table_rename_and_projection.sql +150 -0
  56. package/migrations/046_service_ops_tables.sql +75 -0
  57. package/migrations/047_update_gfp_manager_skill.sql +16 -0
  58. package/migrations/048_service_migration_skill.sql +23 -0
  59. package/migrations/049_service_features.sql +39 -0
  60. package/migrations/050_service_kpi_action_items.sql +87 -0
  61. package/migrations/051_update_service_migration_skill_prompt.sql +9 -0
  62. package/migrations/052_feature_iteration_link.sql +11 -0
  63. package/migrations/052_services_table_rename.sql +149 -0
  64. package/migrations/053_feature_discovery.sql +47 -0
  65. package/migrations/054_deploy_verification.sql +17 -0
  66. package/migrations/055_feature_lifecycle.sql +37 -0
  67. package/migrations/056_service_incident_schema.sql +16 -0
  68. package/migrations/057_decision_date_to_metadata.ts +173 -0
  69. package/migrations/058_incubator_kb_schema.sql +8 -0
  70. package/migrations/059_incubator_sessions.sql +29 -0
  71. package/migrations/060_skill_reference_files.sql +8 -0
  72. package/migrations/061_cron_trigger_bridge.sql +7 -0
  73. package/migrations/062_bot_slack_profiles.sql +21 -0
  74. package/migrations/063_rename_gfp_skills.sql +7 -0
  75. package/migrations/064_bot_cost_log.sql +11 -0
  76. package/migrations/065_hub_spoke_orchestration.sql +35 -0
  77. package/migrations/066_cost_log_commitment.sql +9 -0
  78. package/migrations/067_module_ontology_type.sql +44 -0
  79. package/migrations/068_migrate_incubator_data.sql +32 -0
  80. package/migrations/069_action_items_sot.sql +156 -0
  81. package/migrations/069_cost_log_tokens.sql +45 -0
  82. package/migrations/070_services_sot_columns.sql +78 -0
  83. package/migrations/071_cleanup_deprecated_service_kb.sql +38 -0
  84. package/migrations/072_incubator_heartbeat.sql +12 -0
  85. package/migrations/072_service_role_schema.sql +57 -0
  86. package/migrations/073_service_type_and_platform.sql +8 -0
  87. package/migrations/074_schema_ref_type.sql +16 -0
  88. package/migrations/075_routing_delegation.sql +34 -0
  89. package/migrations/076_meeting_service_link.sql +5 -0
  90. package/migrations/077_agents_ontology_type.sql +93 -0
  91. package/migrations/078_incubator_agent.sql +45 -0
  92. package/migrations/079_drop_audio_blob_url.sql +4 -0
  93. package/migrations/080_kb_metadata_indexing.sql +9 -0
  94. package/migrations/081_person_unification.sql +41 -0
  95. package/migrations/082_discord_channel.sql +3 -0
  96. package/migrations/084_deprecate_kpi_metrics_table.sql +5 -0
  97. package/migrations/085_meeting_target_domain.sql +37 -0
  98. package/migrations/086_skill_routing_new_skills.sql +23 -0
  99. package/migrations/087_skill_routing_second_opinion.sql +8 -0
  100. package/migrations/088_meeting_notion_sync.sql +10 -0
  101. package/migrations/089_bot_commitments_dedup.sql +17 -0
  102. package/migrations/090_incubator_discord_guild.sql +8 -0
  103. package/migrations/091_drop_deprecated_gfp_kpi_views.sql +65 -0
  104. package/migrations/092_ontology_channel_mapping.sql +28 -0
  105. package/migrations/093_update_bot_workspace_paths.sql +15 -0
  106. package/migrations/094_cron_run_tracking.sql +28 -0
  107. package/migrations/095_drop_bot_cron_runs.sql +7 -0
  108. package/migrations/096_kb_pipeline_keys.sql +66 -0
  109. package/migrations/097_drop_empty_service_tables.sql +83 -0
  110. package/migrations/098_migrate_features_materials_drop.sql +119 -0
  111. package/migrations/099_migrate_sections_drop.sql +52 -0
  112. package/migrations/099_seed_cron_poller_tick.sql +14 -0
  113. package/migrations/100_migrate_services_drop.sql +57 -0
  114. package/migrations/101_drop_services.sql +5 -0
  115. package/migrations/102_cost_log_session_dedup.sql +13 -0
  116. package/migrations/103_board.sql +57 -0
  117. package/migrations/104_agent_factory.sql +284 -0
  118. package/migrations/105_kb_notify.sql +44 -0
  119. package/migrations/106_office_id_agents_commands.sql +73 -0
  120. package/migrations/107_agent_service_credentials.sql +79 -0
  121. package/migrations/108_drop_l2_ontology_seeds.sql +16 -0
  122. package/migrations/109_generic_ontology_descriptions.sql +21 -0
  123. package/migrations/110_kb_manager_skill_l2_cleanup.sql +34 -0
  124. package/migrations/111_drop_l2_team_ontology_seeds.sql +20 -0
  125. package/migrations/112_fix_pipeline_schema_and_role_trigger.sql +83 -0
  126. package/migrations/113_kb_history.sql +53 -0
  127. package/migrations/114_runtime_target_columns.sql +26 -0
  128. package/migrations/115_runtime_source_columns.sql +52 -0
  129. package/migrations/116_commitment_pattern_health.sql +81 -0
  130. package/migrations/117_commitment_pattern_alert_claims.sql +33 -0
  131. package/migrations/118_retire_semiclaw_semicolonybot_alias.sql +30 -0
  132. package/migrations/119_commitment_events.sql +51 -0
  133. package/migrations/120_host_signals.sql +51 -0
  134. package/migrations/121_agent_spec_derived_runtime_metadata.sql +68 -0
  135. package/migrations/122_agent_spec_derived_fk_policy.sql +18 -0
  136. package/migrations/123_agent_spec_projection_skip_targets.sql +24 -0
  137. package/migrations/124_bot_commitments_notify.sql +26 -0
  138. package/migrations/125_agent_personas.sql +36 -0
  139. package/migrations/128_entity_relations.sql +125 -0
  140. package/migrations/129_kb_multitenant_gateway.sql +86 -0
  141. package/migrations/130_jewelry_relation_types.sql +36 -0
  142. package/migrations/131_concierge_requests.sql +38 -0
  143. package/migrations/132_kb_supersession.sql +27 -0
  144. package/migrations/133_kb_claims.sql +52 -0
  145. package/migrations/134_migration_registry.sql +18 -0
  146. package/migrations/135_sc_roles.sql +102 -0
  147. package/migrations/136_runtime_tenant_columns.sql +71 -0
  148. package/migrations/137_runtime_backfill_team_semicolon.sql +131 -0
  149. package/migrations/138_runtime_constraints_not_valid.sql +56 -0
  150. package/migrations/139_tenant_vms.sql +31 -0
  151. package/migrations/140_fleet_slots.sql +23 -0
  152. package/migrations/141_provisioning_jobs.sql +29 -0
  153. package/migrations/142_rls_enable_semicolony.sql +129 -0
  154. package/migrations/143_rls_enable_public.sql +54 -0
  155. package/migrations/144_worker_device_registry.sql +211 -0
  156. package/migrations/145_workspace_profile_workstation_policy.sql +39 -0
  157. package/migrations/146_worker_profile_repo_scope.sql +24 -0
  158. package/migrations/147_worker_profile_semo_ops_repo_rename.sql +18 -0
  159. package/migrations/148_momo_runtime_convergence.sql +92 -0
  160. package/migrations/README.md +88 -0
  161. package/migrations-sqlite/kb/001_initial.sql +56 -0
  162. package/migrations-sqlite/ops/001_initial.sql +53 -0
  163. package/migrations-sqlite/ops/002_action_items.sql +48 -0
  164. package/package.json +78 -0
@@ -0,0 +1,156 @@
1
+ -- 069: action_items — Single Source of Truth 전환
2
+ --
3
+ -- 변경 사항:
4
+ -- A. owner_domain, target_domain 컬럼 추가 (ontology FK)
5
+ -- B. 기존 데이터 마이그레이션 (project_id → target_domain, assignee → owner_domain)
6
+ -- C. NOT NULL + FK 제약조건 설정
7
+ -- D. project_id 컬럼 및 깨진 FK 제거
8
+ -- E. 테이블 리네이밍: service_action_items → action_items
9
+ -- F. 새 인덱스 생성
10
+ -- G. 하위호환 VIEW 생성
11
+ -- H. KB 스키마에서 action-item 키 제거
12
+ --
13
+ -- 배경:
14
+ -- - service_action_items.project_id FK가 migration 052에서 리네이밍 누락되어 깨진 상태
15
+ -- - KB와 DB 이중 구조 → DB를 유일한 SoT로 전환
16
+ -- - 액션 아이템은 반드시 주체(owner_domain: team/person/bot)가 있어야 함
17
+ -- - 대상 서비스/프로젝트(target_domain)는 선택적
18
+ --
19
+ -- 선행 조건: 068_migrate_incubator_data.sql
20
+
21
+ BEGIN;
22
+
23
+ -- ============================================================
24
+ -- 선행 검증: semicolon 도메인 존재 확인 (B5 폴백에 필요)
25
+ -- ============================================================
26
+ DO $$
27
+ BEGIN
28
+ IF NOT EXISTS (SELECT 1 FROM semicolony.ontology WHERE domain = 'semicolon') THEN
29
+ RAISE EXCEPTION 'ontology domain "semicolon" must exist before this migration';
30
+ END IF;
31
+ END $$;
32
+
33
+ -- ============================================================
34
+ -- A. 새 컬럼 추가
35
+ -- ============================================================
36
+
37
+ ALTER TABLE semicolony.service_action_items
38
+ ADD COLUMN IF NOT EXISTS owner_domain VARCHAR(100),
39
+ ADD COLUMN IF NOT EXISTS target_domain VARCHAR(100);
40
+
41
+ -- ============================================================
42
+ -- B. 기존 데이터 마이그레이션
43
+ -- ============================================================
44
+
45
+ -- B1: target_domain ← service_id → services.service_domain
46
+ UPDATE semicolony.service_action_items ai
47
+ SET target_domain = s.service_domain
48
+ FROM semicolony.services s
49
+ WHERE ai.service_id = s.service_id
50
+ AND ai.target_domain IS NULL;
51
+
52
+ -- B2: owner_domain ← assignee가 ontology domain과 직접 매칭 (team 타입)
53
+ UPDATE semicolony.service_action_items ai
54
+ SET owner_domain = o.domain
55
+ FROM semicolony.ontology o
56
+ WHERE o.entity_type = 'team'
57
+ AND LOWER(ai.assignee) = LOWER(o.domain)
58
+ AND ai.owner_domain IS NULL;
59
+
60
+ -- B3: owner_domain ← kb-sync 메타데이터의 kb_domain
61
+ UPDATE semicolony.service_action_items
62
+ SET owner_domain = metadata->>'kb_domain'
63
+ WHERE owner_domain IS NULL
64
+ AND source = 'kb-sync'
65
+ AND metadata->>'kb_domain' IS NOT NULL
66
+ AND EXISTS (
67
+ SELECT 1 FROM semicolony.ontology WHERE domain = metadata->>'kb_domain'
68
+ );
69
+
70
+ -- B4: owner_domain ← assignee가 nickname과 매칭
71
+ UPDATE semicolony.service_action_items ai
72
+ SET owner_domain = kb.domain
73
+ FROM semicolony.knowledge_base kb
74
+ WHERE kb.key = 'nickname'
75
+ AND LOWER(TRIM(kb.content)) = LOWER(ai.assignee)
76
+ AND ai.owner_domain IS NULL;
77
+
78
+ -- B5: owner_domain 남은 NULL → target_domain 폴백, 최종적으로 'semicolon'
79
+ UPDATE semicolony.service_action_items
80
+ SET owner_domain = COALESCE(target_domain, 'semicolon')
81
+ WHERE owner_domain IS NULL;
82
+
83
+ -- ============================================================
84
+ -- C. NOT NULL + FK 제약조건
85
+ -- ============================================================
86
+
87
+ ALTER TABLE semicolony.service_action_items
88
+ ALTER COLUMN owner_domain SET NOT NULL;
89
+
90
+ ALTER TABLE semicolony.service_action_items
91
+ ADD CONSTRAINT action_items_owner_domain_fkey
92
+ FOREIGN KEY (owner_domain) REFERENCES semicolony.ontology(domain);
93
+
94
+ ALTER TABLE semicolony.service_action_items
95
+ ADD CONSTRAINT action_items_target_domain_fkey
96
+ FOREIGN KEY (target_domain) REFERENCES semicolony.ontology(domain);
97
+
98
+ -- ============================================================
99
+ -- D. service_id 컬럼 및 FK 제거 (owner_domain + target_domain으로 대체)
100
+ -- ============================================================
101
+
102
+ ALTER TABLE semicolony.service_action_items
103
+ DROP CONSTRAINT IF EXISTS service_action_items_service_id_fkey;
104
+
105
+ DROP INDEX IF EXISTS semicolony.idx_sai_project_status;
106
+
107
+ ALTER TABLE semicolony.service_action_items
108
+ DROP COLUMN IF EXISTS service_id;
109
+
110
+ -- ============================================================
111
+ -- E. 테이블 리네이밍
112
+ -- ============================================================
113
+
114
+ ALTER TABLE semicolony.service_action_items RENAME TO action_items;
115
+
116
+ DO $$ BEGIN
117
+ ALTER TRIGGER trg_service_action_items_updated ON semicolony.action_items
118
+ RENAME TO trg_action_items_updated;
119
+ EXCEPTION WHEN undefined_object THEN NULL;
120
+ END $$;
121
+
122
+ DO $$ BEGIN
123
+ ALTER INDEX semicolony.idx_sai_assignee
124
+ RENAME TO idx_action_items_assignee;
125
+ EXCEPTION WHEN undefined_object THEN NULL;
126
+ END $$;
127
+
128
+ -- ============================================================
129
+ -- F. 새 인덱스
130
+ -- ============================================================
131
+
132
+ CREATE INDEX idx_action_items_owner_status
133
+ ON semicolony.action_items(owner_domain, status);
134
+
135
+ CREATE INDEX idx_action_items_target_status
136
+ ON semicolony.action_items(target_domain, status)
137
+ WHERE target_domain IS NOT NULL;
138
+
139
+ CREATE INDEX idx_action_items_created
140
+ ON semicolony.action_items(created_at DESC);
141
+
142
+ -- ============================================================
143
+ -- G. 하위호환 VIEW (기존 코드가 service_action_items 참조 시 호환)
144
+ -- ============================================================
145
+
146
+ CREATE VIEW semicolony.service_action_items AS
147
+ SELECT * FROM semicolony.action_items;
148
+
149
+ -- ============================================================
150
+ -- H. KB 스키마에서 action-item 키 제거
151
+ -- ============================================================
152
+
153
+ DELETE FROM semicolony.kb_type_schema
154
+ WHERE scheme_key = 'action-item';
155
+
156
+ COMMIT;
@@ -0,0 +1,45 @@
1
+ -- 069: bot_cost_log에 토큰 추적 컬럼 추가 + 비용 뷰를 bot_cost_log 기반으로 전환
2
+ -- Agent SDK SDKResultMessage.usage.apiUsage에서 토큰 데이터 기록
3
+
4
+ BEGIN;
5
+
6
+ -- 1. 토큰 컬럼 추가
7
+ ALTER TABLE semicolony.bot_cost_log
8
+ ADD COLUMN IF NOT EXISTS input_tokens INT DEFAULT 0,
9
+ ADD COLUMN IF NOT EXISTS output_tokens INT DEFAULT 0,
10
+ ADD COLUMN IF NOT EXISTS cache_read_tokens INT DEFAULT 0,
11
+ ADD COLUMN IF NOT EXISTS cache_creation_tokens INT DEFAULT 0,
12
+ ADD COLUMN IF NOT EXISTS num_turns INT DEFAULT 1,
13
+ ADD COLUMN IF NOT EXISTS duration_ms INT;
14
+
15
+ -- 2. service_id 인덱스 (프로젝트별 비용 집계용)
16
+ CREATE INDEX IF NOT EXISTS idx_cost_log_service
17
+ ON semicolony.bot_cost_log (service_id) WHERE service_id IS NOT NULL;
18
+
19
+ -- 3. 기존 뷰 DROP 후 bot_cost_log 기반으로 재생성 (레거시 bot_query_logs → bot_cost_log)
20
+ -- bot_id 타입이 다를 수 있으므로 CREATE OR REPLACE 대신 DROP + CREATE
21
+ DROP VIEW IF EXISTS semicolony.bot_cost_summary;
22
+ DROP VIEW IF EXISTS semicolony.bot_cost_daily;
23
+
24
+ CREATE VIEW semicolony.bot_cost_summary AS
25
+ SELECT bot_id,
26
+ date_trunc('month', created_at)::date AS month,
27
+ COUNT(*) AS query_count,
28
+ COALESCE(SUM(input_tokens), 0) AS total_input_tokens,
29
+ COALESCE(SUM(output_tokens), 0) AS total_output_tokens,
30
+ COALESCE(SUM(cost_usd), 0) AS total_cost_usd,
31
+ COALESCE(AVG(duration_ms), 0)::int AS avg_latency_ms
32
+ FROM semicolony.bot_cost_log
33
+ GROUP BY bot_id, date_trunc('month', created_at);
34
+
35
+ CREATE VIEW semicolony.bot_cost_daily AS
36
+ SELECT bot_id,
37
+ created_at::date AS day,
38
+ COUNT(*) AS query_count,
39
+ COALESCE(SUM(input_tokens), 0) AS total_input_tokens,
40
+ COALESCE(SUM(output_tokens), 0) AS total_output_tokens,
41
+ COALESCE(SUM(cost_usd), 0) AS total_cost_usd
42
+ FROM semicolony.bot_cost_log
43
+ GROUP BY bot_id, created_at::date;
44
+
45
+ COMMIT;
@@ -0,0 +1,78 @@
1
+ -- 070: services 테이블 SoT 강화 — KB-only 메타데이터를 DB 컬럼으로 이전
2
+ -- KB의 singleton 키(tech-stack, service-url, bm, repo, slack-channel)를 services 컬럼으로 승격.
3
+ -- status, po(owner_name)는 이미 DB에 있으므로 KB 키만 제거 대상.
4
+
5
+ BEGIN;
6
+
7
+ -- 1. 컬럼 추가
8
+ ALTER TABLE semicolony.services
9
+ ADD COLUMN IF NOT EXISTS tech_stack TEXT,
10
+ ADD COLUMN IF NOT EXISTS service_url TEXT,
11
+ ADD COLUMN IF NOT EXISTS bm TEXT,
12
+ ADD COLUMN IF NOT EXISTS repo TEXT,
13
+ ADD COLUMN IF NOT EXISTS slack_channel TEXT;
14
+
15
+ -- 2. KB → DB 데이터 이전 (tech-stack — 원문 그대로 저장, 마크다운/리스트 혼재)
16
+ UPDATE semicolony.services s SET tech_stack = (
17
+ SELECT TRIM(kb.content)
18
+ FROM semicolony.knowledge_base kb
19
+ WHERE kb.domain = s.service_domain
20
+ AND kb.key = 'tech-stack' AND kb.sub_key = ''
21
+ AND kb.content IS NOT NULL AND kb.content != ''
22
+ AND kb.content NOT LIKE '%(미입력)%'
23
+ )
24
+ WHERE s.service_domain IS NOT NULL AND s.tech_stack IS NULL;
25
+
26
+ -- 3. KB → DB 데이터 이전 (service-url)
27
+ UPDATE semicolony.services s SET service_url = (
28
+ SELECT kb.content
29
+ FROM semicolony.knowledge_base kb
30
+ WHERE kb.domain = s.service_domain
31
+ AND kb.key = 'service-url' AND kb.sub_key = ''
32
+ AND kb.content IS NOT NULL AND kb.content != ''
33
+ AND kb.content NOT LIKE '%(미입력)%'
34
+ )
35
+ WHERE s.service_domain IS NOT NULL AND s.service_url IS NULL;
36
+
37
+ -- 4. KB → DB 데이터 이전 (bm)
38
+ UPDATE semicolony.services s SET bm = (
39
+ SELECT kb.content
40
+ FROM semicolony.knowledge_base kb
41
+ WHERE kb.domain = s.service_domain
42
+ AND kb.key = 'bm' AND kb.sub_key = ''
43
+ AND kb.content IS NOT NULL AND kb.content != ''
44
+ AND kb.content NOT LIKE '%(미입력)%'
45
+ )
46
+ WHERE s.service_domain IS NOT NULL AND s.bm IS NULL;
47
+
48
+ -- 5. KB → DB 데이터 이전 (repo)
49
+ UPDATE semicolony.services s SET repo = (
50
+ SELECT kb.content
51
+ FROM semicolony.knowledge_base kb
52
+ WHERE kb.domain = s.service_domain
53
+ AND kb.key = 'repo' AND kb.sub_key = ''
54
+ AND kb.content IS NOT NULL AND kb.content != ''
55
+ AND kb.content NOT LIKE '%(미입력)%'
56
+ )
57
+ WHERE s.service_domain IS NOT NULL AND s.repo IS NULL;
58
+
59
+ -- 6. KB → DB 데이터 이전 (slack-channel)
60
+ UPDATE semicolony.services s SET slack_channel = (
61
+ SELECT kb.content
62
+ FROM semicolony.knowledge_base kb
63
+ WHERE kb.domain = s.service_domain
64
+ AND kb.key = 'slack-channel' AND kb.sub_key = ''
65
+ AND kb.content IS NOT NULL AND kb.content != ''
66
+ AND kb.content NOT LIKE '%(미입력)%'
67
+ )
68
+ WHERE s.service_domain IS NOT NULL AND s.slack_channel IS NULL;
69
+
70
+ -- 7. KB service 타입 스키마에서 이전된 키 제거
71
+ DELETE FROM semicolony.kb_type_schema
72
+ WHERE type_key = 'service'
73
+ AND scheme_key IN ('tech-stack', 'service-url', 'bm', 'repo', 'slack-channel', 'status', 'po');
74
+
75
+ -- 8. 이전된 KB 엔트리는 보존 (향후 정리 시 수동 삭제 가능)
76
+ -- KB 데이터 자체는 삭제하지 않음 — 스키마 키만 제거하여 신규 upsert 차단
77
+
78
+ COMMIT;
@@ -0,0 +1,38 @@
1
+ -- 071: service 타입 deprecated KB 엔트리 정리 + DB 트리거
2
+ -- migration 070에서 services 테이블로 데이터 복사 완료 후 스키마만 제거했으나,
3
+ -- 레거시 KB 엔트리가 남아있고 raw SQL 쓰기 차단이 없었음.
4
+
5
+ BEGIN;
6
+
7
+ -- Part A: service 타입 도메인의 deprecated KB 엔트리 삭제
8
+ -- (migration 070에서 이미 services 테이블로 데이터 복사 완료)
9
+ DELETE FROM semicolony.knowledge_base kb
10
+ USING semicolony.ontology o
11
+ WHERE kb.domain = o.domain
12
+ AND o.entity_type = 'service'
13
+ AND kb.key IN ('status', 'po', 'tech-stack', 'service-url', 'bm', 'repo', 'slack-channel')
14
+ AND kb.sub_key = '';
15
+
16
+ -- Part B: raw SQL 통한 deprecated 키 쓰기 차단 트리거
17
+ CREATE OR REPLACE FUNCTION semicolony.reject_deprecated_service_kb_keys()
18
+ RETURNS TRIGGER AS $$
19
+ BEGIN
20
+ IF NEW.key IN ('status', 'po', 'tech-stack', 'service-url', 'bm', 'repo', 'slack-channel')
21
+ AND NEW.sub_key = ''
22
+ AND EXISTS (
23
+ SELECT 1 FROM semicolony.ontology
24
+ WHERE domain = NEW.domain AND entity_type = 'service'
25
+ )
26
+ THEN
27
+ RAISE EXCEPTION 'KB key "%" is deprecated for service-type domains. Use: semicolony service update --domain %', NEW.key, NEW.domain;
28
+ END IF;
29
+ RETURN NEW;
30
+ END;
31
+ $$ LANGUAGE plpgsql;
32
+
33
+ CREATE TRIGGER trg_reject_deprecated_service_kb
34
+ BEFORE INSERT OR UPDATE ON semicolony.knowledge_base
35
+ FOR EACH ROW
36
+ EXECUTE FUNCTION semicolony.reject_deprecated_service_kb_keys();
37
+
38
+ COMMIT;
@@ -0,0 +1,12 @@
1
+ -- 072: Incubator Sessions Heartbeat
2
+ -- channel-slack이 주기적으로 heartbeat를 전송하여 세션 활성 상태를 증명.
3
+ -- orchestrator는 heartbeat가 stale인 세션을 자동 정리하여 중복 응답 방지.
4
+
5
+ ALTER TABLE semicolony.incubator_sessions
6
+ ADD COLUMN IF NOT EXISTS last_heartbeat TIMESTAMPTZ DEFAULT NULL,
7
+ ADD COLUMN IF NOT EXISTS heartbeat_stale_threshold_sec INTEGER DEFAULT 180,
8
+ ADD COLUMN IF NOT EXISTS stopped_reason TEXT DEFAULT NULL;
9
+
10
+ CREATE INDEX IF NOT EXISTS idx_incubator_heartbeat
11
+ ON semicolony.incubator_sessions(status, last_heartbeat)
12
+ WHERE status = 'active';
@@ -0,0 +1,57 @@
1
+ -- 072: 서비스 Role 시스템 표준화
2
+ --
3
+ -- 변경 사항:
4
+ -- 1. kb_type_schema에 'role' collection 키 추가 (service 타입)
5
+ -- 2. 사용되지 않는 'members' 키 제거
6
+ -- 3. role/po upsert 시 services.owner_name 자동 동기화 trigger
7
+ --
8
+ -- 배경:
9
+ -- 서비스별 역할(PO, 개발, 디자인 등)이 base-information에 자유형으로 섞여있어
10
+ -- 검색/조회 불가. role/{role-name} collection 키로 표준화.
11
+ --
12
+ -- 선행 조건: 071
13
+
14
+ BEGIN;
15
+
16
+ -- ============================================================
17
+ -- 1. role collection 키 추가
18
+ -- ============================================================
19
+
20
+ INSERT INTO semicolony.kb_type_schema (type_key, scheme_key, scheme_description, required, value_hint, sort_order, key_type)
21
+ VALUES ('service', 'role', '서비스 역할 매핑 (PO, 개발, 디자인 등)', false,
22
+ 'role/po, role/lead-dev, role/backend, role/frontend, role/designer, role/ops, role/planner. content는 ontology team 도메인 (소문자). 복수: 쉼표 구분.', 15, 'collection')
23
+ ON CONFLICT DO NOTHING;
24
+
25
+ -- ============================================================
26
+ -- 2. members 키 제거 (dead key — 전체 서비스 KB 엔트리 0건)
27
+ -- ============================================================
28
+
29
+ DELETE FROM semicolony.kb_type_schema
30
+ WHERE type_key = 'service' AND scheme_key = 'members';
31
+
32
+ -- ============================================================
33
+ -- 3. role/po → services.owner_name 동기화 trigger
34
+ -- ============================================================
35
+
36
+ CREATE OR REPLACE FUNCTION semicolony.sync_role_po_to_owner()
37
+ RETURNS TRIGGER AS $$
38
+ BEGIN
39
+ IF NEW.key = 'role' AND NEW.sub_key = 'po' THEN
40
+ UPDATE semicolony.services
41
+ SET owner_name = TRIM(SPLIT_PART(NEW.content, ',', 1))
42
+ WHERE service_domain = NEW.domain;
43
+ END IF;
44
+ RETURN NEW;
45
+ END;
46
+ $$ LANGUAGE plpgsql;
47
+
48
+ -- 기존 trigger가 있으면 교체
49
+ DROP TRIGGER IF EXISTS trg_sync_role_po ON semicolony.knowledge_base;
50
+
51
+ CREATE TRIGGER trg_sync_role_po
52
+ AFTER INSERT OR UPDATE ON semicolony.knowledge_base
53
+ FOR EACH ROW
54
+ WHEN (NEW.key = 'role' AND NEW.sub_key = 'po')
55
+ EXECUTE FUNCTION semicolony.sync_role_po_to_owner();
56
+
57
+ COMMIT;
@@ -0,0 +1,8 @@
1
+ -- 073: service_type_and_platform (공개 배포용 no-op 스텁)
2
+ --
3
+ -- 원본은 세미콜론 tenant 전용 parent-child 서비스 매핑을 포함.
4
+ --
5
+ -- 세미콜론 DB 는 이미 적용됨. 신규 설치자는 이 파일을 건너뛴다 (schema 변경 없음).
6
+ BEGIN;
7
+ -- historical no-op
8
+ COMMIT;
@@ -0,0 +1,16 @@
1
+ -- 074_schema_ref_type.sql
2
+ -- kb_type_schema에 ref_type 컬럼 추가
3
+ -- 특정 키의 값이 다른 온톨로지 도메인을 참조해야 할 때, 참조 대상 타입을 지정
4
+ -- upsert 시 content가 해당 타입의 등록된 도메인인지 자동 검증
5
+
6
+ -- 1. ref_type 컬럼 추가
7
+ ALTER TABLE semicolony.kb_type_schema
8
+ ADD COLUMN IF NOT EXISTS ref_type VARCHAR(100)
9
+ REFERENCES semicolony.ontology_types(type_key);
10
+
11
+ COMMENT ON COLUMN semicolony.kb_type_schema.ref_type IS
12
+ '값이 참조해야 하는 온톨로지 타입. 설정 시 content가 해당 타입의 도메인으로 존재하는지 upsert 시 검증.';
13
+
14
+ -- 2. person.organization은 하이브리드 허용 (도메인명 우선, 자유 텍스트 폴백)
15
+ -- ref_type 강제 검증을 걸지 않고 value_hint로만 가이드한다.
16
+ -- ref_type이 필요한 키가 생기면 여기에 UPDATE 추가.
@@ -0,0 +1,34 @@
1
+ -- 075_routing_delegation.sql
2
+ -- bot_delegation에 KB-driven 라우팅 데이터 추가
3
+ -- orchestrator router.ts의 하드코딩 라우팅을 DB 기반으로 전환
4
+
5
+ BEGIN;
6
+
7
+ -- 1. metadata 컬럼 추가 (스킬 힌트, 정렬 순서 등 확장용)
8
+ ALTER TABLE semicolony.bot_delegation ADD COLUMN IF NOT EXISTS metadata JSONB DEFAULT '{}';
9
+
10
+ -- 2. unique constraint 완화 (같은 봇에 routing 여러 행 허용 — designclaw stitch + 일반)
11
+ ALTER TABLE semicolony.bot_delegation
12
+ DROP CONSTRAINT IF EXISTS bot_delegation_from_bot_id_to_bot_id_delegation_type_key;
13
+
14
+ CREATE UNIQUE INDEX IF NOT EXISTS bot_delegation_unique_v2
15
+ ON semicolony.bot_delegation (from_bot_id, to_bot_id, delegation_type, COALESCE(metadata->>'label', ''));
16
+
17
+ -- 3. 키워드 라우팅 시드 (orchestrator → 봇, metadata.order로 우선순위 관리)
18
+ INSERT INTO semicolony.bot_delegation (from_bot_id, to_bot_id, delegation_type, domains, method, priority, metadata) VALUES
19
+ ('orchestrator', 'designclaw', 'routing', ARRAY['stitch 리뷰 완료','스티치 리뷰 완료','스티치 완료','디자인 승인'], 'keyword', 'high', '{"label":"stitch","order":1}'),
20
+ ('orchestrator', 'infraclaw', 'routing', ARRAY['인프라','배포','cicd','deploy','서버','쿠버','k8s','docker','argocd'], 'keyword', 'medium', '{"label":"infra","order":2}'),
21
+ ('orchestrator', 'designclaw', 'routing', ARRAY['디자인','ui','ux','컬러','폰트','레이아웃','tailwind','css','퍼블리싱'], 'keyword', 'medium', '{"label":"design","order":3}'),
22
+ ('orchestrator', 'reviewclaw', 'routing', ARRAY['리뷰','review','qa','테스트','test','버그','bug','품질'], 'keyword', 'medium', '{"label":"review","order":4}'),
23
+ ('orchestrator', 'growthclaw', 'routing', ARRAY['마케팅','seo','그로스','트래픽','전환율','키워드','콘텐츠','광고','트래킹','커뮤니티 게시','백링크','조회수'], 'keyword', 'medium', '{"label":"growth","order":5}'),
24
+ ('orchestrator', 'workclaw', 'routing', ARRAY['코딩','구현','개발','코드','fix','feature','pr','풀리퀘'], 'keyword', 'medium', '{"label":"work","order":6}'),
25
+ ('orchestrator', 'planclaw', 'routing', ARRAY['기획','스펙','prd','요구사항','epic','유저스토리','플로우'], 'keyword', 'medium', '{"label":"plan","order":7}')
26
+ ON CONFLICT DO NOTHING;
27
+
28
+ -- 4. 스킬 라우팅 시드 (orchestrator → 봇 + 스킬 힌트)
29
+ INSERT INTO semicolony.bot_delegation (from_bot_id, to_bot_id, delegation_type, domains, method, metadata) VALUES
30
+ ('orchestrator', 'semiclaw', 'skill-routing', ARRAY['액션아이템','action item','할일','todo 확인','할일 추적'], 'keyword', '{"skill":"action-item-tracker","label":"action-items"}'),
31
+ ('orchestrator', 'semiclaw', 'skill-routing', ARRAY['서비스 현황','서비스 상태','서비스 조회','서비스 목록','서비스 브리핑','service status','service list'], 'keyword', '{"skill":"service-briefing","label":"service-briefing"}')
32
+ ON CONFLICT DO NOTHING;
33
+
34
+ COMMIT;
@@ -0,0 +1,5 @@
1
+ -- 회의에 서비스/프로젝트 연동 (optional FK)
2
+ ALTER TABLE semicolony.meetings
3
+ ADD COLUMN IF NOT EXISTS service_id UUID REFERENCES semicolony.services(service_id);
4
+
5
+ CREATE INDEX IF NOT EXISTS idx_meetings_service ON semicolony.meetings (service_id);
@@ -0,0 +1,93 @@
1
+ -- 077: agents 온톨로지 타입 + Architecture B 에이전트 KB 시딩
2
+ BEGIN;
3
+
4
+ -- 1. agents 타입 생성
5
+ INSERT INTO semicolony.ontology_types (type_key, description)
6
+ VALUES ('agents', 'Architecture B 에이전트 — 정체성, 위임, 도구, 슬랙 프로필')
7
+ ON CONFLICT (type_key) DO NOTHING;
8
+
9
+ -- 2. 스키마 키 등록
10
+ INSERT INTO semicolony.kb_type_schema (type_key, scheme_key, scheme_description, required, value_hint, sort_order, key_type) VALUES
11
+ ('agents', 'identity', '에이전트 기본 정보 (이름, 이모지, 역할)', true, 'YAML: name, emoji, tagline, role, agent_type (orchestrator|specialist)', 1, 'singleton'),
12
+ ('agents', 'model-config', '모델 설정 (기본 모델, 예산, opus 트리거)', true, 'YAML: base_model, max_turns, max_budget, opus_trigger_keywords[]', 2, 'singleton'),
13
+ ('agents', 'delegation', '담당 도메인 + 위임 규칙', true, '마크다운: 담당 키워드, 에스컬레이션 대상', 3, 'singleton'),
14
+ ('agents', 'tools', '사용 가능한 도구 목록', false, 'YAML: tools[], mcp_servers{}', 4, 'singleton'),
15
+ ('agents', 'skills', '할당된 스킬 목록', false, '스킬 이름 + 트리거 키워드', 5, 'collection'),
16
+ ('agents', 'slack-profile', 'Slack 표시 정체성', true, 'YAML: username, icon_emoji, slack_user_id', 6, 'singleton'),
17
+ ('agents', 'kb-access', 'KB 접근 허용 도메인 목록', false, 'YAML: domains[] (빈 = 전체 허용)', 7, 'singleton'),
18
+ ('agents', 'status', '현재 상태', true, 'online | offline | maintenance', 8, 'singleton'),
19
+ ('agents', 'cron-schedule', '크론 작업 목록', false, '마크다운: 스케줄 + 설명 테이블', 9, 'singleton')
20
+ ON CONFLICT (type_key, scheme_key) DO UPDATE SET
21
+ scheme_description = EXCLUDED.scheme_description,
22
+ required = EXCLUDED.required,
23
+ value_hint = EXCLUDED.value_hint,
24
+ sort_order = EXCLUDED.sort_order;
25
+
26
+ -- 3. 기존 bot 도메인 → agents 타입으로 전환
27
+ UPDATE semicolony.ontology
28
+ SET entity_type = 'agents'
29
+ WHERE entity_type = 'bot'
30
+ AND domain IN (SELECT bot_id FROM semicolony.bot_status WHERE status != 'retired');
31
+
32
+ -- 4. identity 시딩 (bot_status → KB)
33
+ INSERT INTO semicolony.knowledge_base (domain, key, sub_key, content, metadata, created_by)
34
+ SELECT
35
+ bs.bot_id, 'identity', '',
36
+ format(E'name: %s\nemoji: %s\ntagline: %s\nrole: %s\nagent_type: %s',
37
+ COALESCE(bs.name, bs.bot_id),
38
+ COALESCE(bs.emoji, ':robot_face:'),
39
+ COALESCE(bs.role, bs.bot_id || ' 에이전트'),
40
+ COALESCE(bs.role, '-'),
41
+ CASE WHEN bs.bot_id = 'semiclaw' THEN 'orchestrator' ELSE 'specialist' END
42
+ ),
43
+ '{}', 'migration-077'
44
+ FROM semicolony.bot_status bs
45
+ WHERE bs.status != 'retired'
46
+ ON CONFLICT (domain, key, sub_key) DO UPDATE SET
47
+ content = EXCLUDED.content, updated_at = now();
48
+
49
+ -- 5. delegation 시딩 (bot_delegation → KB)
50
+ INSERT INTO semicolony.knowledge_base (domain, key, sub_key, content, metadata, created_by)
51
+ SELECT
52
+ sub.to_bot_id, 'delegation', '',
53
+ format(E'## 수신 키워드\n%s\n\n## 에스컬레이션\n- 담당 밖 요청 → escalate("semiclaw", reason, context)', sub.keyword_list),
54
+ '{}', 'migration-077'
55
+ FROM (
56
+ SELECT
57
+ to_bot_id,
58
+ string_agg('- ' || kw, E'\n' ORDER BY kw) AS keyword_list
59
+ FROM (
60
+ SELECT to_bot_id, unnest(domains) AS kw
61
+ FROM semicolony.bot_delegation
62
+ WHERE is_active = true
63
+ ) expanded
64
+ GROUP BY to_bot_id
65
+ ) sub
66
+ ON CONFLICT (domain, key, sub_key) DO UPDATE SET
67
+ content = EXCLUDED.content, updated_at = now();
68
+
69
+ -- 6. model-config 시딩
70
+ INSERT INTO semicolony.knowledge_base (domain, key, sub_key, content, metadata, created_by) VALUES
71
+ ('semiclaw', 'model-config', '', E'base_model: sonnet\nmax_turns: 50\nmax_budget: 1.5', '{}', 'migration-077'),
72
+ ('planclaw', 'model-config', '', E'base_model: sonnet\nmax_turns: 40\nmax_budget: 1.0', '{}', 'migration-077'),
73
+ ('designclaw', 'model-config', '', E'base_model: sonnet\nmax_turns: 40\nmax_budget: 1.0', '{}', 'migration-077'),
74
+ ('workclaw', 'model-config', '', E'base_model: sonnet\nmax_turns: 40\nmax_budget: 1.5', '{}', 'migration-077'),
75
+ ('reviewclaw', 'model-config', '', E'base_model: sonnet\nmax_turns: 40\nmax_budget: 0.8', '{}', 'migration-077'),
76
+ ('infraclaw', 'model-config', '', E'base_model: sonnet\nmax_turns: 40\nmax_budget: 1.0', '{}', 'migration-077'),
77
+ ('growthclaw', 'model-config', '', E'base_model: sonnet\nmax_turns: 40\nmax_budget: 0.5', '{}', 'migration-077')
78
+ ON CONFLICT (domain, key, sub_key) DO UPDATE SET
79
+ content = EXCLUDED.content, updated_at = now();
80
+
81
+ -- 7. status 시딩
82
+ INSERT INTO semicolony.knowledge_base (domain, key, sub_key, content, metadata, created_by)
83
+ SELECT bot_id, 'status', '', COALESCE(status, 'online'), '{}', 'migration-077'
84
+ FROM semicolony.bot_status WHERE status != 'retired'
85
+ ON CONFLICT (domain, key, sub_key) DO UPDATE SET
86
+ content = EXCLUDED.content, updated_at = now();
87
+
88
+ -- 8. bot 타입 deprecated 마킹
89
+ UPDATE semicolony.ontology_types
90
+ SET description = '[DEPRECATED — agents 타입 사용] OpenClaw 봇 에이전트'
91
+ WHERE type_key = 'bot';
92
+
93
+ COMMIT;
@@ -0,0 +1,45 @@
1
+ -- 078: Incubator Agent 등록
2
+ -- incubator 전용 에이전트: 인큐베이터 파이프라인 오케스트레이션 전담
3
+
4
+ -- 1. bot_status 등록
5
+ INSERT INTO semicolony.bot_status (bot_id, name, emoji, role, status, workspace_path)
6
+ VALUES ('incubator', 'Incubator', ':hatching_chick:', 'Incubator Pipeline Orchestrator', 'online', '~/.semicolony-bot-sessions/incubator')
7
+ ON CONFLICT (bot_id) DO UPDATE SET status = 'online', role = EXCLUDED.role, name = EXCLUDED.name, emoji = EXCLUDED.emoji;
8
+
9
+ -- 2. ontology 도메인 등록 (agents 타입)
10
+ INSERT INTO semicolony.ontology (domain, entity_type, description, parent, schema)
11
+ VALUES ('incubator', 'agents', 'Incubator Pipeline Orchestrator', 'semicolony', '{}'::jsonb)
12
+ ON CONFLICT (domain) DO UPDATE SET entity_type = 'agents', description = EXCLUDED.description;
13
+
14
+ -- 3. orchestrator → incubator 키워드 라우팅
15
+ INSERT INTO semicolony.bot_delegation (from_bot_id, to_bot_id, delegation_type, domains, method, is_active, metadata)
16
+ VALUES ('orchestrator', 'incubator', 'routing',
17
+ ARRAY['인큐베이팅','인큐베이터','incubator','incubating','샌드박스 시작','sandbox create'],
18
+ 'keyword', true, '{"label":"incubator","order":0}')
19
+ ON CONFLICT (from_bot_id, to_bot_id, delegation_type, COALESCE(metadata->>'label', '')) DO NOTHING;
20
+
21
+ -- 4. orchestrator → incubator 스킬 라우팅
22
+ INSERT INTO semicolony.bot_delegation (from_bot_id, to_bot_id, delegation_type, domains, method, is_active, metadata)
23
+ VALUES ('orchestrator', 'incubator', 'skill-routing',
24
+ ARRAY['인큐베이팅 시작','인큐베이팅 진행','인큐베이팅 이어서','인큐베이팅 현황','인큐베이터 시작','sandbox'],
25
+ 'keyword', true, '{"skill":"semicolony-incubator","label":"incubator-skill"}')
26
+ ON CONFLICT (from_bot_id, to_bot_id, delegation_type, COALESCE(metadata->>'label', '')) DO NOTHING;
27
+
28
+ -- 5. incubator → 전문 봇 위임 (CP별)
29
+ INSERT INTO semicolony.bot_delegation (from_bot_id, to_bot_id, delegation_type, domains, method, is_active, metadata) VALUES
30
+ ('incubator', 'planclaw', 'task', ARRAY['planning','requirements','prd','cp-2','cp-3'], 'escalation', true, '{"label":"cp-plan"}'),
31
+ ('incubator', 'designclaw', 'task', ARRAY['design','ui','ux','cp-3'], 'escalation', true, '{"label":"cp-design"}'),
32
+ ('incubator', 'infraclaw', 'task', ARRAY['infra','deploy','cp-4','cp-7','cp-8','cp-9'], 'escalation', true, '{"label":"cp-infra"}'),
33
+ ('incubator', 'workclaw', 'task', ARRAY['implementation','dev','cp-5'], 'escalation', true, '{"label":"cp-work"}'),
34
+ ('incubator', 'reviewclaw', 'task', ARRAY['review','qa','cp-6'], 'escalation', true, '{"label":"cp-review"}'),
35
+ ('incubator', 'growthclaw', 'task', ARRAY['growth','marketing','cp-9'], 'escalation', true, '{"label":"cp-growth"}')
36
+ ON CONFLICT (from_bot_id, to_bot_id, delegation_type, COALESCE(metadata->>'label', '')) DO NOTHING;
37
+
38
+ -- 6. semicolony-incubator 스킬을 incubator 봇으로 이전
39
+ UPDATE semicolony.skill_definitions
40
+ SET metadata = jsonb_set(
41
+ COALESCE(metadata, '{}'::jsonb),
42
+ '{bot_ids}',
43
+ '["incubator"]'::jsonb
44
+ )
45
+ WHERE name = 'semicolony-incubator';
@@ -0,0 +1,4 @@
1
+ -- 079: 미사용 audio_blob_url 컬럼 제거
2
+ -- Vercel Blob 도입 후 철회 (bytea 유지 결정). 077에서 추가된 컬럼 정리.
3
+
4
+ ALTER TABLE semicolony.meetings DROP COLUMN IF EXISTS audio_blob_url;
@@ -0,0 +1,9 @@
1
+ -- 080: GIN index on knowledge_base.metadata for JSONB filtering queries
2
+ -- Enables KB as universal data layer with metadata-based querying
3
+
4
+ CREATE INDEX IF NOT EXISTS idx_kb_metadata_gin
5
+ ON semicolony.knowledge_base USING GIN(metadata jsonb_path_ops);
6
+
7
+ CREATE INDEX IF NOT EXISTS idx_kb_metadata_status
8
+ ON semicolony.knowledge_base((metadata->>'status'))
9
+ WHERE metadata->>'status' IS NOT NULL;