@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.
- package/LICENSE +200 -0
- package/NOTICE +8 -0
- package/README.md +152 -0
- package/dist/bundle.js +2887 -0
- package/dist/templates/launchd/ai.semicolony.host-signals-sidecar.plist +40 -0
- package/migrations/001_initial.sql +280 -0
- package/migrations/002_add_indexes.sql +11 -0
- package/migrations/003_add_fk.sql +32 -0
- package/migrations/004_session_count_trigger.sql +35 -0
- package/migrations/005_bot_workspace_audits.sql +16 -0
- package/migrations/006_bot_kb_subscriptions.sql +24 -0
- package/migrations/007_flatten_skill_names.sql +16 -0
- package/migrations/008_bot_workspace_files.sql +14 -0
- package/migrations/009_enforce_flat_skill_names.sql +53 -0
- package/migrations/010_bot_delegation.sql +27 -0
- package/migrations/011_drop_legacy_tables.sql +35 -0
- package/migrations/012_drop_bot_knowledge.sql +16 -0
- package/migrations/013_kb_workspace_domains.sql +88 -0
- package/migrations/014_timestamp_to_timestamptz.sql +33 -0
- package/migrations/015_kb_domain_enforcement.sql +83 -0
- package/migrations/016_ontology_redesign.sql +108 -0
- package/migrations/017_ontology_instance_model.sql +151 -0
- package/migrations/018_type_schema.sql +11 -0
- package/migrations/019_test_management.sql +69 -0
- package/migrations/020_bot_workspace_standard.sql +174 -0
- package/migrations/021_drop_dead_tables.sql +8 -0
- package/migrations/021_test_declarative.sql +19 -0
- package/migrations/022_bot_ontology_type.sql +38 -0
- package/migrations/022_kb_schema_enforcement.sql +77 -0
- package/migrations/023_decision_key_cleanup.ts +154 -0
- package/migrations/024_embedding_backfill.ts +137 -0
- package/migrations/025_kb_flat_keys.sql +33 -0
- package/migrations/026_drop_session_log.sql +19 -0
- package/migrations/027_kb_manager_skill.sql +22 -0
- package/migrations/028_skill_definitions_to_semicolony.sql +19 -0
- package/migrations/029_agents_citation_max_lines.sql +6 -0
- package/migrations/030_team_ontology.sql +54 -0
- package/migrations/031_gfp_tables.sql +101 -0
- package/migrations/031_kb_manager_domain_register.sql +12 -0
- package/migrations/032_gfp_skill_and_callback.sql +40 -0
- package/migrations/032_kebab_case_keys.sql +33 -0
- package/migrations/033_skill_workspace_rules.sql +10 -0
- package/migrations/034_current_to_date_keys.sql +13 -0
- package/migrations/034_current_to_date_keys.ts +104 -0
- package/migrations/035_bot_budgets.sql +51 -0
- package/migrations/036_gfp_stitch_design.sql +35 -0
- package/migrations/037_gfp_qa_sections.sql +13 -0
- package/migrations/038_gfp_phase_split.sql +26 -0
- package/migrations/039_meeting_audio_data.sql +2 -0
- package/migrations/040_bot_commitments.sql +68 -0
- package/migrations/041_palette_previews.sql +13 -0
- package/migrations/042_gfp_parallel_tracks.sql +37 -0
- package/migrations/043_blocker_key.sql +13 -0
- package/migrations/044_gfp_stitch_screenshots.sql +9 -0
- package/migrations/045_service_table_rename_and_projection.sql +150 -0
- package/migrations/046_service_ops_tables.sql +75 -0
- package/migrations/047_update_gfp_manager_skill.sql +16 -0
- package/migrations/048_service_migration_skill.sql +23 -0
- package/migrations/049_service_features.sql +39 -0
- package/migrations/050_service_kpi_action_items.sql +87 -0
- package/migrations/051_update_service_migration_skill_prompt.sql +9 -0
- package/migrations/052_feature_iteration_link.sql +11 -0
- package/migrations/052_services_table_rename.sql +149 -0
- package/migrations/053_feature_discovery.sql +47 -0
- package/migrations/054_deploy_verification.sql +17 -0
- package/migrations/055_feature_lifecycle.sql +37 -0
- package/migrations/056_service_incident_schema.sql +16 -0
- package/migrations/057_decision_date_to_metadata.ts +173 -0
- package/migrations/058_incubator_kb_schema.sql +8 -0
- package/migrations/059_incubator_sessions.sql +29 -0
- package/migrations/060_skill_reference_files.sql +8 -0
- package/migrations/061_cron_trigger_bridge.sql +7 -0
- package/migrations/062_bot_slack_profiles.sql +21 -0
- package/migrations/063_rename_gfp_skills.sql +7 -0
- package/migrations/064_bot_cost_log.sql +11 -0
- package/migrations/065_hub_spoke_orchestration.sql +35 -0
- package/migrations/066_cost_log_commitment.sql +9 -0
- package/migrations/067_module_ontology_type.sql +44 -0
- package/migrations/068_migrate_incubator_data.sql +32 -0
- package/migrations/069_action_items_sot.sql +156 -0
- package/migrations/069_cost_log_tokens.sql +45 -0
- package/migrations/070_services_sot_columns.sql +78 -0
- package/migrations/071_cleanup_deprecated_service_kb.sql +38 -0
- package/migrations/072_incubator_heartbeat.sql +12 -0
- package/migrations/072_service_role_schema.sql +57 -0
- package/migrations/073_service_type_and_platform.sql +8 -0
- package/migrations/074_schema_ref_type.sql +16 -0
- package/migrations/075_routing_delegation.sql +34 -0
- package/migrations/076_meeting_service_link.sql +5 -0
- package/migrations/077_agents_ontology_type.sql +93 -0
- package/migrations/078_incubator_agent.sql +45 -0
- package/migrations/079_drop_audio_blob_url.sql +4 -0
- package/migrations/080_kb_metadata_indexing.sql +9 -0
- package/migrations/081_person_unification.sql +41 -0
- package/migrations/082_discord_channel.sql +3 -0
- package/migrations/084_deprecate_kpi_metrics_table.sql +5 -0
- package/migrations/085_meeting_target_domain.sql +37 -0
- package/migrations/086_skill_routing_new_skills.sql +23 -0
- package/migrations/087_skill_routing_second_opinion.sql +8 -0
- package/migrations/088_meeting_notion_sync.sql +10 -0
- package/migrations/089_bot_commitments_dedup.sql +17 -0
- package/migrations/090_incubator_discord_guild.sql +8 -0
- package/migrations/091_drop_deprecated_gfp_kpi_views.sql +65 -0
- package/migrations/092_ontology_channel_mapping.sql +28 -0
- package/migrations/093_update_bot_workspace_paths.sql +15 -0
- package/migrations/094_cron_run_tracking.sql +28 -0
- package/migrations/095_drop_bot_cron_runs.sql +7 -0
- package/migrations/096_kb_pipeline_keys.sql +66 -0
- package/migrations/097_drop_empty_service_tables.sql +83 -0
- package/migrations/098_migrate_features_materials_drop.sql +119 -0
- package/migrations/099_migrate_sections_drop.sql +52 -0
- package/migrations/099_seed_cron_poller_tick.sql +14 -0
- package/migrations/100_migrate_services_drop.sql +57 -0
- package/migrations/101_drop_services.sql +5 -0
- package/migrations/102_cost_log_session_dedup.sql +13 -0
- package/migrations/103_board.sql +57 -0
- package/migrations/104_agent_factory.sql +284 -0
- package/migrations/105_kb_notify.sql +44 -0
- package/migrations/106_office_id_agents_commands.sql +73 -0
- package/migrations/107_agent_service_credentials.sql +79 -0
- package/migrations/108_drop_l2_ontology_seeds.sql +16 -0
- package/migrations/109_generic_ontology_descriptions.sql +21 -0
- package/migrations/110_kb_manager_skill_l2_cleanup.sql +34 -0
- package/migrations/111_drop_l2_team_ontology_seeds.sql +20 -0
- package/migrations/112_fix_pipeline_schema_and_role_trigger.sql +83 -0
- package/migrations/113_kb_history.sql +53 -0
- package/migrations/114_runtime_target_columns.sql +26 -0
- package/migrations/115_runtime_source_columns.sql +52 -0
- package/migrations/116_commitment_pattern_health.sql +81 -0
- package/migrations/117_commitment_pattern_alert_claims.sql +33 -0
- package/migrations/118_retire_semiclaw_semicolonybot_alias.sql +30 -0
- package/migrations/119_commitment_events.sql +51 -0
- package/migrations/120_host_signals.sql +51 -0
- package/migrations/121_agent_spec_derived_runtime_metadata.sql +68 -0
- package/migrations/122_agent_spec_derived_fk_policy.sql +18 -0
- package/migrations/123_agent_spec_projection_skip_targets.sql +24 -0
- package/migrations/124_bot_commitments_notify.sql +26 -0
- package/migrations/125_agent_personas.sql +36 -0
- package/migrations/128_entity_relations.sql +125 -0
- package/migrations/129_kb_multitenant_gateway.sql +86 -0
- package/migrations/130_jewelry_relation_types.sql +36 -0
- package/migrations/131_concierge_requests.sql +38 -0
- package/migrations/132_kb_supersession.sql +27 -0
- package/migrations/133_kb_claims.sql +52 -0
- package/migrations/134_migration_registry.sql +18 -0
- package/migrations/135_sc_roles.sql +102 -0
- package/migrations/136_runtime_tenant_columns.sql +71 -0
- package/migrations/137_runtime_backfill_team_semicolon.sql +131 -0
- package/migrations/138_runtime_constraints_not_valid.sql +56 -0
- package/migrations/139_tenant_vms.sql +31 -0
- package/migrations/140_fleet_slots.sql +23 -0
- package/migrations/141_provisioning_jobs.sql +29 -0
- package/migrations/142_rls_enable_semicolony.sql +129 -0
- package/migrations/143_rls_enable_public.sql +54 -0
- package/migrations/144_worker_device_registry.sql +211 -0
- package/migrations/145_workspace_profile_workstation_policy.sql +39 -0
- package/migrations/146_worker_profile_repo_scope.sql +24 -0
- package/migrations/147_worker_profile_semo_ops_repo_rename.sql +18 -0
- package/migrations/148_momo_runtime_convergence.sql +92 -0
- package/migrations/README.md +88 -0
- package/migrations-sqlite/kb/001_initial.sql +56 -0
- package/migrations-sqlite/ops/001_initial.sql +53 -0
- package/migrations-sqlite/ops/002_action_items.sql +48 -0
- package/package.json +78 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
-- Migration 013: Add bot-config, spec, skill ontology domains
|
|
2
|
+
-- bot_workspace_files → KB 전환을 위한 새 도메인 추가.
|
|
3
|
+
-- 봇 메타/규격, 문서/스펙, 스킬 정의를 KB로 관리.
|
|
4
|
+
|
|
5
|
+
-- 1. bot-config 도메인: 봇 메타데이터 및 규격 문서
|
|
6
|
+
INSERT INTO semicolony.ontology (domain, schema, description, version)
|
|
7
|
+
VALUES (
|
|
8
|
+
'bot-config',
|
|
9
|
+
'{
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"content": { "type": "string", "description": "문서 본문 (Markdown)" },
|
|
13
|
+
"metadata": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"properties": {
|
|
16
|
+
"bot_id": { "type": "string", "description": "봇 ID (semiclaw, workclaw 등)" },
|
|
17
|
+
"file_type": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"enum": ["identity", "agents", "rules", "tools", "heartbeat", "bootstrap", "claude"],
|
|
20
|
+
"description": "원본 파일 종류"
|
|
21
|
+
},
|
|
22
|
+
"source_path": { "type": "string", "description": "원본 파일 경로" }
|
|
23
|
+
},
|
|
24
|
+
"required": ["bot_id", "file_type"]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}'::jsonb,
|
|
28
|
+
'봇 메타데이터 및 규격 문서 (IDENTITY.md, AGENTS.md, RULES.md, TOOLS.md, HEARTBEAT.md, BOOTSTRAP.md, CLAUDE.md)',
|
|
29
|
+
1
|
|
30
|
+
)
|
|
31
|
+
ON CONFLICT (domain) DO NOTHING;
|
|
32
|
+
|
|
33
|
+
-- 2. spec 도메인: 프로젝트 스펙/설계 문서
|
|
34
|
+
INSERT INTO semicolony.ontology (domain, schema, description, version)
|
|
35
|
+
VALUES (
|
|
36
|
+
'spec',
|
|
37
|
+
'{
|
|
38
|
+
"type": "object",
|
|
39
|
+
"properties": {
|
|
40
|
+
"content": { "type": "string", "description": "스펙 문서 본문 (Markdown)" },
|
|
41
|
+
"metadata": {
|
|
42
|
+
"type": "object",
|
|
43
|
+
"properties": {
|
|
44
|
+
"project": { "type": "string", "description": "관련 프로젝트명" },
|
|
45
|
+
"doc_type": {
|
|
46
|
+
"type": "string",
|
|
47
|
+
"enum": ["prd", "spec", "plan", "design", "epic", "protocol"],
|
|
48
|
+
"description": "문서 유형"
|
|
49
|
+
},
|
|
50
|
+
"author": { "type": "string", "description": "작성자 (봇 ID 또는 사용자)" },
|
|
51
|
+
"source_bot": { "type": "string", "description": "원본이 있던 봇 워크스페이스" }
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}'::jsonb,
|
|
56
|
+
'프로젝트 스펙, PRD, 설계 문서, 구현 계획',
|
|
57
|
+
1
|
|
58
|
+
)
|
|
59
|
+
ON CONFLICT (domain) DO NOTHING;
|
|
60
|
+
|
|
61
|
+
-- 3. skill 도메인: 봇 스킬 정의 및 참조 문서
|
|
62
|
+
INSERT INTO semicolony.ontology (domain, schema, description, version)
|
|
63
|
+
VALUES (
|
|
64
|
+
'skill',
|
|
65
|
+
'{
|
|
66
|
+
"type": "object",
|
|
67
|
+
"properties": {
|
|
68
|
+
"content": { "type": "string", "description": "스킬 정의 또는 참조 문서 (Markdown)" },
|
|
69
|
+
"metadata": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"properties": {
|
|
72
|
+
"bot_id": { "type": "string", "description": "스킬 소유 봇 ID" },
|
|
73
|
+
"skill_name": { "type": "string", "description": "스킬 이름" },
|
|
74
|
+
"content_type": {
|
|
75
|
+
"type": "string",
|
|
76
|
+
"enum": ["definition", "reference"],
|
|
77
|
+
"description": "definition=SKILL.md, reference=references/*.md"
|
|
78
|
+
},
|
|
79
|
+
"ref_name": { "type": "string", "description": "참조 문서 이름 (reference 타입일 때)" }
|
|
80
|
+
},
|
|
81
|
+
"required": ["bot_id", "skill_name", "content_type"]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}'::jsonb,
|
|
85
|
+
'봇 스킬 정의 (SKILL.md) 및 참조 문서 (references/*.md). scripts/는 제외 (로컬 실행 필요)',
|
|
86
|
+
1
|
|
87
|
+
)
|
|
88
|
+
ON CONFLICT (domain) DO NOTHING;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
-- 014_timestamp_to_timestamptz.sql
|
|
2
|
+
-- Fix timezone double-conversion bug: TIMESTAMP → TIMESTAMPTZ
|
|
3
|
+
--
|
|
4
|
+
-- DB session timezone = Asia/Seoul (KST).
|
|
5
|
+
-- Application-provided timestamps (last_active, last_activity, last_run, next_run)
|
|
6
|
+
-- were stored from toISOString() with 'Z' stripped → raw UTC digits.
|
|
7
|
+
-- Database-generated timestamps (synced_at via NOW())
|
|
8
|
+
-- were stored as KST digits.
|
|
9
|
+
|
|
10
|
+
-- bot_status
|
|
11
|
+
ALTER TABLE semicolony.bot_status
|
|
12
|
+
ALTER COLUMN last_active TYPE TIMESTAMPTZ USING last_active AT TIME ZONE 'UTC',
|
|
13
|
+
ALTER COLUMN synced_at TYPE TIMESTAMPTZ USING synced_at AT TIME ZONE 'Asia/Seoul';
|
|
14
|
+
|
|
15
|
+
ALTER TABLE semicolony.bot_status
|
|
16
|
+
ALTER COLUMN synced_at SET DEFAULT NOW();
|
|
17
|
+
|
|
18
|
+
-- bot_sessions
|
|
19
|
+
ALTER TABLE semicolony.bot_sessions
|
|
20
|
+
ALTER COLUMN last_activity TYPE TIMESTAMPTZ USING last_activity AT TIME ZONE 'UTC',
|
|
21
|
+
ALTER COLUMN synced_at TYPE TIMESTAMPTZ USING synced_at AT TIME ZONE 'Asia/Seoul';
|
|
22
|
+
|
|
23
|
+
ALTER TABLE semicolony.bot_sessions
|
|
24
|
+
ALTER COLUMN synced_at SET DEFAULT NOW();
|
|
25
|
+
|
|
26
|
+
-- bot_cron_jobs
|
|
27
|
+
ALTER TABLE semicolony.bot_cron_jobs
|
|
28
|
+
ALTER COLUMN last_run TYPE TIMESTAMPTZ USING last_run AT TIME ZONE 'UTC',
|
|
29
|
+
ALTER COLUMN next_run TYPE TIMESTAMPTZ USING next_run AT TIME ZONE 'UTC',
|
|
30
|
+
ALTER COLUMN synced_at TYPE TIMESTAMPTZ USING synced_at AT TIME ZONE 'Asia/Seoul';
|
|
31
|
+
|
|
32
|
+
ALTER TABLE semicolony.bot_cron_jobs
|
|
33
|
+
ALTER COLUMN synced_at SET DEFAULT NOW();
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
-- Migration 015: KB Domain Enforcement + KPI/Decision Ontology Update
|
|
2
|
+
--
|
|
3
|
+
-- 1. 고아 도메인 자동 등록 (FK 추가 전 안전장치)
|
|
4
|
+
-- 2. FK 제약 추가 (domain → ontology)
|
|
5
|
+
-- 3. KPI/Decision 온톨로지 스키마 업데이트
|
|
6
|
+
-- 4. 임베딩 NULL 인덱스
|
|
7
|
+
|
|
8
|
+
BEGIN;
|
|
9
|
+
|
|
10
|
+
-- ============================================================
|
|
11
|
+
-- 1. 고아 도메인 자동 등록
|
|
12
|
+
-- ============================================================
|
|
13
|
+
INSERT INTO semicolony.ontology (domain, schema, description, version)
|
|
14
|
+
SELECT DISTINCT kb.domain,
|
|
15
|
+
'{"type":"object","properties":{"content":{"type":"string"}}}'::jsonb,
|
|
16
|
+
'Auto-created during FK migration', 1
|
|
17
|
+
FROM semicolony.knowledge_base kb
|
|
18
|
+
WHERE NOT EXISTS (SELECT 1 FROM semicolony.ontology o WHERE o.domain = kb.domain)
|
|
19
|
+
ON CONFLICT (domain) DO NOTHING;
|
|
20
|
+
|
|
21
|
+
-- ============================================================
|
|
22
|
+
-- 2. FK 추가 (ON UPDATE CASCADE, ON DELETE RESTRICT)
|
|
23
|
+
-- ============================================================
|
|
24
|
+
ALTER TABLE semicolony.knowledge_base
|
|
25
|
+
ADD CONSTRAINT fk_kb_domain_ontology
|
|
26
|
+
FOREIGN KEY (domain) REFERENCES semicolony.ontology(domain)
|
|
27
|
+
ON UPDATE CASCADE ON DELETE RESTRICT;
|
|
28
|
+
|
|
29
|
+
-- ============================================================
|
|
30
|
+
-- 3. KPI 온톨로지 스키마 업데이트
|
|
31
|
+
-- ============================================================
|
|
32
|
+
UPDATE semicolony.ontology SET schema = '{
|
|
33
|
+
"type": "object",
|
|
34
|
+
"required": ["content"],
|
|
35
|
+
"properties": {
|
|
36
|
+
"content": {"type": "string"},
|
|
37
|
+
"metadata": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"properties": {
|
|
40
|
+
"project": {"type": "string", "description": "프로젝트 ID (예: my-service)"},
|
|
41
|
+
"record_type": {"type": "string", "enum": ["current", "weekly", "target"], "description": "current=최신 스냅샷, weekly=주간 기록, target=목표"},
|
|
42
|
+
"week": {"type": "string", "description": "YYYY-WNN 형식 (weekly 타입만)"},
|
|
43
|
+
"measured_at": {"type": "string", "description": "측정일 ISO 8601"}
|
|
44
|
+
},
|
|
45
|
+
"required": ["project", "record_type"]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}'::jsonb,
|
|
49
|
+
description = 'KPI 지표. key 형식: {project}/current | {project}/target | {project}/YYYY-WNN',
|
|
50
|
+
version = version + 1
|
|
51
|
+
WHERE domain = 'kpi';
|
|
52
|
+
|
|
53
|
+
-- ============================================================
|
|
54
|
+
-- 4. Decision 온톨로지 스키마 업데이트
|
|
55
|
+
-- ============================================================
|
|
56
|
+
UPDATE semicolony.ontology SET schema = '{
|
|
57
|
+
"type": "object",
|
|
58
|
+
"required": ["content"],
|
|
59
|
+
"properties": {
|
|
60
|
+
"content": {"type": "string"},
|
|
61
|
+
"metadata": {
|
|
62
|
+
"type": "object",
|
|
63
|
+
"properties": {
|
|
64
|
+
"date": {"type": "string", "description": "결정일 YYYY-MM-DD"},
|
|
65
|
+
"participants": {"type": "array", "items": {"type": "string"}, "description": "참여자 목록"},
|
|
66
|
+
"status": {"type": "string", "enum": ["active", "superseded", "revoked"], "description": "결정 상태"},
|
|
67
|
+
"source_meeting": {"type": "string", "description": "관련 회의 링크"}
|
|
68
|
+
},
|
|
69
|
+
"required": ["date"]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}'::jsonb,
|
|
73
|
+
description = '의사결정 기록 (ADR). key: {YYYY-MM-DD}/{slug}. 하나의 엔트리에 전체 결정 포함.',
|
|
74
|
+
version = version + 1
|
|
75
|
+
WHERE domain = 'decision';
|
|
76
|
+
|
|
77
|
+
-- ============================================================
|
|
78
|
+
-- 5. 임베딩 NULL 인덱스 (backfill 쿼리 최적화)
|
|
79
|
+
-- ============================================================
|
|
80
|
+
CREATE INDEX IF NOT EXISTS idx_kb_embedding_null
|
|
81
|
+
ON semicolony.knowledge_base(domain) WHERE embedding IS NULL;
|
|
82
|
+
|
|
83
|
+
COMMIT;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
-- 016_ontology_redesign.sql
|
|
2
|
+
-- 온톨로지 재설계: 서비스(프로젝트) 단위 + 타입 분리
|
|
3
|
+
-- Discussion #235 (2026-03-22) 합의 기반
|
|
4
|
+
|
|
5
|
+
BEGIN;
|
|
6
|
+
|
|
7
|
+
-- ============================================================
|
|
8
|
+
-- 1. ontology_types 테이블 (구조적 템플릿, 서비스와 독립)
|
|
9
|
+
-- ============================================================
|
|
10
|
+
|
|
11
|
+
CREATE TABLE IF NOT EXISTS semicolony.ontology_types (
|
|
12
|
+
id BIGSERIAL PRIMARY KEY,
|
|
13
|
+
type_key VARCHAR(100) NOT NULL UNIQUE,
|
|
14
|
+
schema JSONB NOT NULL DEFAULT '{}',
|
|
15
|
+
description TEXT,
|
|
16
|
+
version INT DEFAULT 1,
|
|
17
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
18
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
-- 시드 타입 등록
|
|
22
|
+
INSERT INTO semicolony.ontology_types (type_key, schema, description) VALUES
|
|
23
|
+
('service', '{"type":"object","properties":{"content":{"type":"string"},"metadata":{"type":"object","properties":{"status":{"type":"string","enum":["active","archived","planned"]},"tech_stack":{"type":"array","items":{"type":"string"}}}}}}', '서비스(프로젝트) 프로필'),
|
|
24
|
+
('person', '{"type":"object","properties":{"content":{"type":"string"},"metadata":{"type":"object","properties":{"role":{"type":"string"},"squad":{"type":"string"}}}}}', '팀원 정보'),
|
|
25
|
+
('decision', '{"type":"object","properties":{"content":{"type":"string"},"metadata":{"type":"object","required":["date","status"],"properties":{"date":{"type":"string","format":"date"},"status":{"type":"string","enum":["proposed","accepted","deprecated"]},"participants":{"type":"array","items":{"type":"string"}}}}}}', '의사결정 기록'),
|
|
26
|
+
('process', '{"type":"object","properties":{"content":{"type":"string"},"metadata":{"type":"object","properties":{"owner":{"type":"string"},"frequency":{"type":"string"}}}}}', '업무 프로세스'),
|
|
27
|
+
('kpi', '{"type":"object","properties":{"content":{"type":"string"},"metadata":{"type":"object","properties":{"project":{"type":"string"},"period":{"type":"string"},"value":{"type":"number"},"target":{"type":"number"}}}}}', 'KPI 지표'),
|
|
28
|
+
('milestone', '{"type":"object","properties":{"content":{"type":"string"},"metadata":{"type":"object","required":["project","title","start_date","end_date","status"],"properties":{"project":{"type":"string"},"title":{"type":"string"},"start_date":{"type":"string","format":"date"},"end_date":{"type":"string","format":"date"},"status":{"type":"string","enum":["planned","in-progress","completed"]},"order":{"type":"integer"}}}}}', '마일스톤'),
|
|
29
|
+
('infra', '{"type":"object","properties":{"content":{"type":"string"},"metadata":{"type":"object","properties":{"provider":{"type":"string"},"region":{"type":"string"}}}}}', '인프라 구성'),
|
|
30
|
+
('spec', '{"type":"object","properties":{"content":{"type":"string"},"metadata":{"type":"object","properties":{"status":{"type":"string","enum":["draft","review","approved","archived"]},"author":{"type":"string"}}}}}', '스펙/설계 문서'),
|
|
31
|
+
('bot-config', '{"type":"object","properties":{"content":{"type":"string"},"metadata":{"type":"object","properties":{"bot_id":{"type":"string"},"file_type":{"type":"string"}}}}}', '봇 설정/규격'),
|
|
32
|
+
('skill', '{"type":"object","properties":{"content":{"type":"string"},"metadata":{"type":"object","properties":{"bot_ids":{"type":"array","items":{"type":"string"}},"category":{"type":"string"}}}}}', '스킬 정의'),
|
|
33
|
+
('glossary', '{"type":"object","properties":{"content":{"type":"string"},"metadata":{"type":"object","properties":{"aliases":{"type":"array","items":{"type":"string"}}}}}}', '용어 사전'),
|
|
34
|
+
('memory', '{"type":"object","properties":{"content":{"type":"string"},"metadata":{"type":"object","required":["source_type","source_id","date"],"properties":{"source_type":{"type":"string","enum":["bot","local-session"]},"source_id":{"type":"string"},"date":{"type":"string","format":"date"},"content_hash":{"type":"string"},"original_size":{"type":"integer"},"synced_at":{"type":"string","format":"date-time"}}}}}', '봇/세션 일일 메모리 (L1→L2 싱크). key: {sourceId}/{YYYY-MM-DD}')
|
|
35
|
+
ON CONFLICT (type_key) DO NOTHING;
|
|
36
|
+
|
|
37
|
+
-- ============================================================
|
|
38
|
+
-- 2. ontology 테이블 컬럼 확장
|
|
39
|
+
-- ============================================================
|
|
40
|
+
|
|
41
|
+
ALTER TABLE semicolony.ontology
|
|
42
|
+
ADD COLUMN IF NOT EXISTS service VARCHAR(100),
|
|
43
|
+
ADD COLUMN IF NOT EXISTS entity_type VARCHAR(100),
|
|
44
|
+
ADD COLUMN IF NOT EXISTS parent VARCHAR(100),
|
|
45
|
+
ADD COLUMN IF NOT EXISTS tags TEXT[] DEFAULT '{}';
|
|
46
|
+
|
|
47
|
+
-- ============================================================
|
|
48
|
+
-- 3. 기존 도메인 backfill (entity_type 매핑)
|
|
49
|
+
-- ============================================================
|
|
50
|
+
|
|
51
|
+
UPDATE semicolony.ontology SET entity_type = 'person' WHERE domain = 'team' AND entity_type IS NULL;
|
|
52
|
+
UPDATE semicolony.ontology SET entity_type = 'service' WHERE domain = 'project' AND entity_type IS NULL;
|
|
53
|
+
UPDATE semicolony.ontology SET entity_type = 'decision' WHERE domain = 'decision' AND entity_type IS NULL;
|
|
54
|
+
UPDATE semicolony.ontology SET entity_type = 'process' WHERE domain = 'process' AND entity_type IS NULL;
|
|
55
|
+
UPDATE semicolony.ontology SET entity_type = 'infra' WHERE domain = 'infra' AND entity_type IS NULL;
|
|
56
|
+
UPDATE semicolony.ontology SET entity_type = 'kpi' WHERE domain = 'kpi' AND entity_type IS NULL;
|
|
57
|
+
UPDATE semicolony.ontology SET entity_type = 'bot-config' WHERE domain = 'bot-config' AND entity_type IS NULL;
|
|
58
|
+
UPDATE semicolony.ontology SET entity_type = 'spec' WHERE domain = 'spec' AND entity_type IS NULL;
|
|
59
|
+
UPDATE semicolony.ontology SET entity_type = 'skill' WHERE domain = 'skill' AND entity_type IS NULL;
|
|
60
|
+
UPDATE semicolony.ontology SET entity_type = 'milestone' WHERE domain = 'milestone' AND entity_type IS NULL;
|
|
61
|
+
|
|
62
|
+
-- ============================================================
|
|
63
|
+
-- 4. memory 도메인 등록 (L1→L2 동기화용)
|
|
64
|
+
-- ============================================================
|
|
65
|
+
|
|
66
|
+
INSERT INTO semicolony.ontology (domain, entity_type, schema, description) VALUES
|
|
67
|
+
('memory', 'memory', '{
|
|
68
|
+
"type": "object",
|
|
69
|
+
"properties": {
|
|
70
|
+
"content": {"type": "string"},
|
|
71
|
+
"metadata": {
|
|
72
|
+
"type": "object",
|
|
73
|
+
"required": ["source_type", "source_id", "date"],
|
|
74
|
+
"properties": {
|
|
75
|
+
"source_type": {"enum": ["bot", "local-session"]},
|
|
76
|
+
"source_id": {"type": "string"},
|
|
77
|
+
"date": {"type": "string", "format": "date"},
|
|
78
|
+
"content_hash": {"type": "string"},
|
|
79
|
+
"original_size": {"type": "integer"},
|
|
80
|
+
"synced_at": {"type": "string", "format": "date-time"}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}', '봇/세션 일일 메모리 (L1→L2 싱크). key: {sourceId}/{YYYY-MM-DD}')
|
|
85
|
+
ON CONFLICT (domain) DO UPDATE SET
|
|
86
|
+
entity_type = EXCLUDED.entity_type,
|
|
87
|
+
schema = EXCLUDED.schema,
|
|
88
|
+
description = EXCLUDED.description;
|
|
89
|
+
|
|
90
|
+
-- ============================================================
|
|
91
|
+
-- 5. knowledge_base — generated column for service extraction
|
|
92
|
+
-- ============================================================
|
|
93
|
+
|
|
94
|
+
ALTER TABLE semicolony.knowledge_base
|
|
95
|
+
ADD COLUMN IF NOT EXISTS service VARCHAR(100)
|
|
96
|
+
GENERATED ALWAYS AS (
|
|
97
|
+
CASE WHEN domain LIKE '%.%' THEN split_part(domain, '.', 1) ELSE NULL END
|
|
98
|
+
) STORED;
|
|
99
|
+
|
|
100
|
+
-- ============================================================
|
|
101
|
+
-- 6. 인덱스
|
|
102
|
+
-- ============================================================
|
|
103
|
+
|
|
104
|
+
CREATE INDEX IF NOT EXISTS idx_ontology_service ON semicolony.ontology (service) WHERE service IS NOT NULL;
|
|
105
|
+
CREATE INDEX IF NOT EXISTS idx_ontology_entity_type ON semicolony.ontology (entity_type) WHERE entity_type IS NOT NULL;
|
|
106
|
+
CREATE INDEX IF NOT EXISTS idx_kb_service ON semicolony.knowledge_base (service) WHERE service IS NOT NULL;
|
|
107
|
+
|
|
108
|
+
COMMIT;
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
-- 017_ontology_instance_model.sql
|
|
2
|
+
-- 온톨로지 인스턴스 모델: 서비스 인스턴스 중심 재구성 + entity_type FK
|
|
3
|
+
-- Discussion #235 (2026-03-22) 합의 기반
|
|
4
|
+
--
|
|
5
|
+
-- 핵심 변경:
|
|
6
|
+
-- 1. ontology.entity_type → FK 참조 ontology_types.type_key
|
|
7
|
+
-- 2. 서비스 인스턴스를 ontology 1등 시민으로 등록
|
|
8
|
+
-- 3. 글로벌 도메인에 service='_global' 태깅
|
|
9
|
+
-- 4. KB 엔트리 도메인을 서비스 인스턴스 스코프(dot-notation)로 전환
|
|
10
|
+
|
|
11
|
+
BEGIN;
|
|
12
|
+
|
|
13
|
+
-- ============================================================
|
|
14
|
+
-- 1. entity_type backfill (NULL → 적절한 타입 매핑)
|
|
15
|
+
-- ============================================================
|
|
16
|
+
|
|
17
|
+
-- 서비스 스코프 도메인 (my-service.kpi → kpi)
|
|
18
|
+
UPDATE semicolony.ontology
|
|
19
|
+
SET entity_type = split_part(domain, '.', 2)
|
|
20
|
+
WHERE entity_type IS NULL AND domain LIKE '%.%'
|
|
21
|
+
AND split_part(domain, '.', 2) IN (
|
|
22
|
+
SELECT type_key FROM semicolony.ontology_types
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
-- 서비스 프로필 도메인 (my-service → service)
|
|
26
|
+
-- NOTE: organization 도메인은 INSERT 시 entity_type='organization' 이 설정되므로
|
|
27
|
+
-- entity_type IS NULL 필터에 걸리지 않아 별도 제외 목록이 불필요하다.
|
|
28
|
+
UPDATE semicolony.ontology
|
|
29
|
+
SET entity_type = 'service'
|
|
30
|
+
WHERE entity_type IS NULL
|
|
31
|
+
AND domain NOT LIKE '%.%'
|
|
32
|
+
AND domain NOT IN (
|
|
33
|
+
'team','project','decision','process','infra','kpi',
|
|
34
|
+
'bot-config','spec','skill','milestone','memory','glossary',
|
|
35
|
+
'session-log'
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
-- 나머지 NULL → glossary (안전망)
|
|
39
|
+
UPDATE semicolony.ontology
|
|
40
|
+
SET entity_type = 'glossary'
|
|
41
|
+
WHERE entity_type IS NULL;
|
|
42
|
+
|
|
43
|
+
-- ============================================================
|
|
44
|
+
-- 2. entity_type FK 제약 추가
|
|
45
|
+
-- ============================================================
|
|
46
|
+
|
|
47
|
+
-- 누락된 entity_type 값이 ontology_types에 없으면 등록
|
|
48
|
+
INSERT INTO semicolony.ontology_types (type_key, schema, description)
|
|
49
|
+
SELECT DISTINCT o.entity_type, '{}'::jsonb, o.entity_type || ' (auto-registered)'
|
|
50
|
+
FROM semicolony.ontology o
|
|
51
|
+
WHERE NOT EXISTS (
|
|
52
|
+
SELECT 1 FROM semicolony.ontology_types t WHERE t.type_key = o.entity_type
|
|
53
|
+
)
|
|
54
|
+
ON CONFLICT (type_key) DO NOTHING;
|
|
55
|
+
|
|
56
|
+
ALTER TABLE semicolony.ontology
|
|
57
|
+
ALTER COLUMN entity_type SET NOT NULL;
|
|
58
|
+
|
|
59
|
+
DO $$
|
|
60
|
+
BEGIN
|
|
61
|
+
IF NOT EXISTS (
|
|
62
|
+
SELECT 1 FROM information_schema.table_constraints
|
|
63
|
+
WHERE constraint_name = 'fk_ontology_entity_type'
|
|
64
|
+
AND table_schema = 'semicolony'
|
|
65
|
+
) THEN
|
|
66
|
+
ALTER TABLE semicolony.ontology
|
|
67
|
+
ADD CONSTRAINT fk_ontology_entity_type
|
|
68
|
+
FOREIGN KEY (entity_type) REFERENCES semicolony.ontology_types(type_key);
|
|
69
|
+
END IF;
|
|
70
|
+
END $$;
|
|
71
|
+
|
|
72
|
+
-- ============================================================
|
|
73
|
+
-- 3. 서비스 인스턴스 등록 (1등 시민)
|
|
74
|
+
-- ============================================================
|
|
75
|
+
|
|
76
|
+
-- organization 타입 등록 (팀/조직)
|
|
77
|
+
INSERT INTO semicolony.ontology_types (type_key, schema, description) VALUES
|
|
78
|
+
('organization', '{}'::jsonb, '팀/조직 (서비스 상위 개체)'),
|
|
79
|
+
('session-log', '{}'::jsonb, '세션 로그')
|
|
80
|
+
ON CONFLICT (type_key) DO NOTHING;
|
|
81
|
+
|
|
82
|
+
-- NOTE: 신규 OSS 인스턴스는 organization/service ontology row 를
|
|
83
|
+
-- `semicolony kb ontology --action register` 로 직접 등록한다.
|
|
84
|
+
-- 과거 세미콜론 인스턴스에 시드되었던 행(`semicolon` org, `jungchipan`/`playland` service)은
|
|
85
|
+
-- migration 108 에서 KB 데이터 0건일 때만 조건부 삭제된다.
|
|
86
|
+
|
|
87
|
+
-- ============================================================
|
|
88
|
+
-- 4. 글로벌 도메인에 service='_global' 태깅
|
|
89
|
+
-- ============================================================
|
|
90
|
+
|
|
91
|
+
UPDATE semicolony.ontology
|
|
92
|
+
SET service = '_global'
|
|
93
|
+
WHERE service IS NULL
|
|
94
|
+
AND entity_type NOT IN ('service', 'organization');
|
|
95
|
+
|
|
96
|
+
-- ============================================================
|
|
97
|
+
-- 5. KB 엔트리 도메인 전환 (flat → service-scoped dot-notation)
|
|
98
|
+
-- team → _global.team, project → _global.project 등
|
|
99
|
+
-- 단, 이미 dot-notation인 도메인(my-service.kpi)은 유지
|
|
100
|
+
-- ============================================================
|
|
101
|
+
|
|
102
|
+
-- 먼저 대상 도메인을 온톨로지에 등록 (dot-notation)
|
|
103
|
+
-- 단, service/organization 인스턴스는 제외 (my-org, my-service 등은 top-level 유지)
|
|
104
|
+
INSERT INTO semicolony.ontology (domain, entity_type, service, schema, description)
|
|
105
|
+
SELECT '_global.' || o.domain, o.entity_type, '_global', o.schema, o.description
|
|
106
|
+
FROM semicolony.ontology o
|
|
107
|
+
WHERE o.service = '_global'
|
|
108
|
+
AND o.domain NOT LIKE '%.%'
|
|
109
|
+
AND o.entity_type NOT IN ('service', 'organization')
|
|
110
|
+
AND NOT EXISTS (
|
|
111
|
+
SELECT 1 FROM semicolony.ontology WHERE domain = '_global.' || o.domain
|
|
112
|
+
)
|
|
113
|
+
ON CONFLICT (domain) DO NOTHING;
|
|
114
|
+
|
|
115
|
+
-- KB 엔트리 도메인 키 전환
|
|
116
|
+
-- 단, service/organization 인스턴스 도메인은 제외
|
|
117
|
+
UPDATE semicolony.knowledge_base
|
|
118
|
+
SET domain = '_global.' || domain
|
|
119
|
+
WHERE domain NOT LIKE '%.%'
|
|
120
|
+
AND domain IN (
|
|
121
|
+
SELECT domain FROM semicolony.ontology
|
|
122
|
+
WHERE service = '_global'
|
|
123
|
+
AND domain NOT LIKE '%.%'
|
|
124
|
+
AND entity_type NOT IN ('service', 'organization')
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
-- 기존 flat 도메인 온톨로지 엔트리 제거 (dot-notation으로 이전됨)
|
|
128
|
+
-- 단, service/organization 인스턴스는 유지
|
|
129
|
+
DELETE FROM semicolony.ontology
|
|
130
|
+
WHERE service = '_global'
|
|
131
|
+
AND domain NOT LIKE '%.%'
|
|
132
|
+
AND entity_type NOT IN ('service', 'organization')
|
|
133
|
+
AND EXISTS (
|
|
134
|
+
SELECT 1 FROM semicolony.ontology o2 WHERE o2.domain = '_global.' || semicolony.ontology.domain
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
-- ============================================================
|
|
138
|
+
-- 6. 인덱스
|
|
139
|
+
-- ============================================================
|
|
140
|
+
|
|
141
|
+
CREATE INDEX IF NOT EXISTS idx_ontology_entity_type_fk
|
|
142
|
+
ON semicolony.ontology (entity_type);
|
|
143
|
+
|
|
144
|
+
-- ============================================================
|
|
145
|
+
-- 7. knowledge_base service generated column 갱신
|
|
146
|
+
-- 기존: service = split_part(domain, '.', 1) WHERE domain LIKE '%.%'
|
|
147
|
+
-- 변경 없음 — _global.team → service='_global', my-service.kpi → service='my-service'
|
|
148
|
+
-- generated column은 ALTER 불가이므로 그대로 유지
|
|
149
|
+
-- ============================================================
|
|
150
|
+
|
|
151
|
+
COMMIT;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
-- 018: type_schema (공개 배포용 no-op 스텁)
|
|
2
|
+
--
|
|
3
|
+
-- 이 번호의 마이그레이션은 세미콜론 내부 DB 에 이미 적용 완료됨.
|
|
4
|
+
-- semicolon tenant 전용 데이터(서비스 도메인 샘플 예시 등)를 포함하므로
|
|
5
|
+
-- 공개 배포 빌드에서는 실행되지 않는다.
|
|
6
|
+
--
|
|
7
|
+
-- 세미콜론 DB 는 schema_migrations 에 018_type_schema 가 이미 기록되어 있어 이 파일을 skip.
|
|
8
|
+
-- 신규(공개) 설치자는 이 파일이 실행되어도 ontology 스키마에 영향 없음.
|
|
9
|
+
BEGIN;
|
|
10
|
+
-- historical no-op
|
|
11
|
+
COMMIT;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
-- 019_test_management.sql
|
|
2
|
+
-- SEMICOLONY 테스트 관리 시스템: 스위트 레지스트리 + 실행 이력 + TC 결과 추적
|
|
3
|
+
|
|
4
|
+
BEGIN;
|
|
5
|
+
|
|
6
|
+
-- 1. test_suites: 테스트 스위트 레지스트리
|
|
7
|
+
CREATE TABLE IF NOT EXISTS semicolony.test_suites (
|
|
8
|
+
suite_id TEXT PRIMARY KEY,
|
|
9
|
+
name TEXT NOT NULL,
|
|
10
|
+
layer TEXT NOT NULL DEFAULT 'integration',
|
|
11
|
+
runner_type TEXT NOT NULL DEFAULT 'tsx',
|
|
12
|
+
runner_path TEXT NOT NULL,
|
|
13
|
+
schedule TEXT,
|
|
14
|
+
enabled BOOLEAN DEFAULT true,
|
|
15
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
16
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
-- 2. test_cases: 개별 TC 정의 (첫 실행 시 자동 등록)
|
|
20
|
+
CREATE TABLE IF NOT EXISTS semicolony.test_cases (
|
|
21
|
+
case_id TEXT NOT NULL,
|
|
22
|
+
suite_id TEXT NOT NULL REFERENCES semicolony.test_suites(suite_id) ON DELETE CASCADE,
|
|
23
|
+
name TEXT NOT NULL,
|
|
24
|
+
category TEXT,
|
|
25
|
+
severity TEXT DEFAULT 'normal',
|
|
26
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
27
|
+
PRIMARY KEY (suite_id, case_id)
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
-- 3. test_runs: 실행 이력
|
|
31
|
+
CREATE TABLE IF NOT EXISTS semicolony.test_runs (
|
|
32
|
+
run_id TEXT PRIMARY KEY,
|
|
33
|
+
suite_id TEXT NOT NULL REFERENCES semicolony.test_suites(suite_id) ON DELETE CASCADE,
|
|
34
|
+
triggered_by TEXT NOT NULL DEFAULT 'manual',
|
|
35
|
+
started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
36
|
+
finished_at TIMESTAMPTZ,
|
|
37
|
+
total_pass INT DEFAULT 0,
|
|
38
|
+
total_fail INT DEFAULT 0,
|
|
39
|
+
total_warn INT DEFAULT 0,
|
|
40
|
+
status TEXT DEFAULT 'running',
|
|
41
|
+
summary TEXT
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
-- 4. test_results: 개별 TC 결과
|
|
45
|
+
CREATE TABLE IF NOT EXISTS semicolony.test_results (
|
|
46
|
+
id BIGSERIAL PRIMARY KEY,
|
|
47
|
+
run_id TEXT NOT NULL REFERENCES semicolony.test_runs(run_id) ON DELETE CASCADE,
|
|
48
|
+
case_id TEXT NOT NULL,
|
|
49
|
+
suite_id TEXT NOT NULL,
|
|
50
|
+
label TEXT NOT NULL,
|
|
51
|
+
status TEXT NOT NULL,
|
|
52
|
+
detail TEXT,
|
|
53
|
+
duration_ms INT,
|
|
54
|
+
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
-- Indexes
|
|
58
|
+
CREATE INDEX IF NOT EXISTS idx_test_runs_suite ON semicolony.test_runs(suite_id, started_at DESC);
|
|
59
|
+
CREATE INDEX IF NOT EXISTS idx_test_results_run ON semicolony.test_results(run_id);
|
|
60
|
+
|
|
61
|
+
-- Seed: 기존 4개 테스트 스위트 등록
|
|
62
|
+
INSERT INTO semicolony.test_suites (suite_id, name, layer, runner_type, runner_path) VALUES
|
|
63
|
+
('017-migration', '017 Migration Validation', 'integration', 'tsx', 'packages/mcp-kb/test-017-migration.ts'),
|
|
64
|
+
('018-transplant', '018 Data Transplant', 'integration', 'tsx', 'packages/mcp-kb/test-018-data-transplant.ts'),
|
|
65
|
+
('018-ai-integration', '018 AI Integration E2E', 'e2e', 'tsx', 'packages/mcp-kb/test-018-ai-integration.ts'),
|
|
66
|
+
('workspace-audit', 'Bot Workspace Compliance', 'compliance', 'shell', '~/.openclaw-shared/workspace-audit/run-audit.sh')
|
|
67
|
+
ON CONFLICT (suite_id) DO NOTHING;
|
|
68
|
+
|
|
69
|
+
COMMIT;
|