@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,22 @@
1
+ -- 027_kb_manager_skill.sql
2
+ -- KB Manager 스킬을 skill_definitions에 등록
3
+ -- 모든 봇이 semicolony CLI를 통해 KB에 접근할 수 있도록 함
4
+
5
+ INSERT INTO skill_definitions (name, display_name, description, prompt, package, is_active, metadata, version)
6
+ VALUES (
7
+ 'kb-manager',
8
+ 'KB Manager',
9
+ 'SEMICOLONY KB 조회/검색/수정. semicolony CLI를 통해 팀 Knowledge Base에 접근.',
10
+ E'---\nname: kb-manager\ndescription: SEMICOLONY KB 조회/검색/수정. semicolony CLI를 통해 팀 Knowledge Base에 접근.\n---\n\n# KB Manager\n\n## 환경 설정\n```bash\nsource ~/.semicolony.env\n```\n\n## 명령어\n\n| 작업 | 명령어 |\n|------|--------|\n| 검색 | `semicolony kb search \"검색어\" --domain <domain> --format json` |\n| 정확 조회 | `semicolony kb get <domain> <key> [sub_key] --format json` |\n| 목록 | `semicolony kb list --domain <domain> --format json` |\n| 쓰기 | `semicolony kb upsert <domain> <key> [sub_key] --content \"내용\"` |\n| 온톨로지 | `semicolony kb ontology --action <action> --format json` |\n\n## 예시\n```bash\n# 팀원 조회\nsemicolony kb get <org> team alice\n\n# 서비스 PO 조회\nsemicolony kb get my-service po\n\n# 검색\nsemicolony kb search \"PO\" --service my-service\n\n# 의사결정 기록\nsemicolony kb upsert <org> decision 2026-03-24/example --content \"의사결정 내용\"\n\n# 라우팅 테이블 (저장 위치 판단용)\nsemicolony kb ontology --action routing-table --format json\n\n# 타입 스키마 조회\nsemicolony kb ontology --action schema --type service --format json\n\n# 서비스 인스턴스 목록\nsemicolony kb ontology --action instances --format json\n```\n\n## 규칙\n- psql 직접 쿼리 금지 — 반드시 이 명령어 사용 (임베딩 자동 생성, 스키마 검증)\n- 세션 인사이트 저장 시: ontology routing-table 먼저 확인 → 적절한 domain+key로 upsert\n- 도메인 구조가 불확실하면: ontology --action list 또는 ontology --action instances로 확인\n',
11
+ 'core',
12
+ true,
13
+ '{"bot_ids": []}',
14
+ '2.0'
15
+ )
16
+ ON CONFLICT (name, office_id) DO UPDATE SET
17
+ prompt = EXCLUDED.prompt,
18
+ display_name = EXCLUDED.display_name,
19
+ description = EXCLUDED.description,
20
+ version = EXCLUDED.version,
21
+ metadata = EXCLUDED.metadata,
22
+ is_active = true;
@@ -0,0 +1,19 @@
1
+ -- 028: skill_definitions를 semicolony 스키마로 이식 + KB skill 엔트리 제거
2
+ --
3
+ -- 목적: semicolony.skill_definitions를 유일한 SoT로 확립
4
+ -- 영향: CLI, 대시보드의 skill_definitions 참조를 semicolony 스키마로 전환
5
+ -- KB에서 skill 키 엔트리 완전 제거 (56 rows)
6
+
7
+ BEGIN;
8
+
9
+ -- 1. public → semicolony 스키마 이동 (atomic, 인덱스/제약조건 보존)
10
+ ALTER TABLE public.skill_definitions SET SCHEMA semicolony;
11
+
12
+ -- 2. KB skill 엔트리 삭제 (56 rows)
13
+ DELETE FROM semicolony.knowledge_base WHERE key = 'skill';
14
+
15
+ -- 3. kb_type_schema에서 skill 스킴 제거
16
+ DELETE FROM semicolony.kb_type_schema
17
+ WHERE type_key = 'organization' AND scheme_key = 'skill';
18
+
19
+ COMMIT;
@@ -0,0 +1,6 @@
1
+ -- 029: AGENTS.md max_lines 150 → 155 (citation + 쓰기 고지 규칙 추가로 줄 수 증가)
2
+ UPDATE semicolony.bot_workspace_standard
3
+ SET content_rules = jsonb_set(content_rules, '{max_lines}', '155'),
4
+ updated_at = NOW()
5
+ WHERE path_pattern = 'AGENTS.md'
6
+ AND spec_version = '2.0';
@@ -0,0 +1,54 @@
1
+ -- 030_team_ontology.sql
2
+ -- team scheme_type 추가 + 팀원 10명 도메인 등록
3
+ -- 액션아이템 추적용 KB 구조 기반
4
+ --
5
+ -- 변경 내용:
6
+ -- 1. ontology_types에 'team' 타입 추가
7
+ -- 2. kb_type_schema에 team 타입 허용 키 등록 (action-item, profile, preference)
8
+ -- 3. 팀원 10명 ontology 도메인 등록
9
+ --
10
+ -- 선행 조건: 022_kb_schema_enforcement.sql 적용 완료
11
+
12
+ BEGIN;
13
+
14
+ -- ============================================================
15
+ -- 1. team 엔티티 타입 등록
16
+ -- ============================================================
17
+
18
+ INSERT INTO semicolony.ontology_types (type_key, schema, description) VALUES
19
+ ('team', '{
20
+ "type": "object",
21
+ "properties": {
22
+ "content": {"type": "string"},
23
+ "metadata": {
24
+ "type": "object",
25
+ "properties": {
26
+ "name": {"type": "string"},
27
+ "role": {"type": "string"},
28
+ "slack_id": {"type": "string"}
29
+ }
30
+ }
31
+ }
32
+ }', '팀원 개인 도메인 — 액션아이템, 프로필, 선호 등')
33
+ ON CONFLICT (type_key) DO NOTHING;
34
+
35
+ -- ============================================================
36
+ -- 2. team 타입 허용 키 등록 (kb_type_schema)
37
+ -- ============================================================
38
+
39
+ INSERT INTO semicolony.kb_type_schema (type_key, scheme_key, scheme_description, required, value_hint, sort_order, key_type)
40
+ VALUES
41
+ ('team', 'action-item', '액션 아이템 추적', false, 'action-item/current, action-item/2026-W13', 1, 'collection'),
42
+ ('team', 'profile', '팀원 프로필', false, '역할, 연락처, 선호 등', 2, 'singleton'),
43
+ ('team', 'preference', '팀원 업무 선호/스타일', false, '소통 선호, 업무 시간대 등', 3, 'singleton')
44
+ ON CONFLICT (type_key, scheme_key) DO NOTHING;
45
+
46
+ -- ============================================================
47
+ -- 3. 팀원 ontology 도메인 — 인스턴스별 수동 등록
48
+ -- ============================================================
49
+ -- 이 migration 은 'team' (이후 'person' 으로 통합 — 081 참조) 타입 스키마만 등록한다.
50
+ -- 팀원 도메인 자체는 인스턴스별로 다르므로 `semicolony kb ontology --action register` 또는
51
+ -- `semicolony onto register <name> --type person` 으로 직접 등록할 것.
52
+ -- (이전 버전은 세미콜론 내부 팀원 10명 시드를 포함했으나 OSS 누출 방지를 위해 제거됨.)
53
+
54
+ COMMIT;
@@ -0,0 +1,101 @@
1
+ -- 031_gfp_tables.sql
2
+ -- GFP (Greenfield Project Pipeline) v2 — Visual Planning Pipeline
3
+ -- 4 tables: gfp_projects, gfp_phase_sections, gfp_materials, gfp_research_tasks
4
+ --
5
+ -- 선행 조건: semicolony schema 존재
6
+
7
+ BEGIN;
8
+
9
+ -- ============================================================
10
+ -- 1. gfp_projects — 프로젝트 메타
11
+ -- ============================================================
12
+
13
+ CREATE TABLE IF NOT EXISTS semicolony.gfp_projects (
14
+ gfp_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
15
+ project_name VARCHAR(200) NOT NULL,
16
+ service_domain VARCHAR(100),
17
+ owner_name VARCHAR(100) NOT NULL,
18
+ owner_contact VARCHAR(200),
19
+ current_phase SMALLINT NOT NULL DEFAULT 0,
20
+ status VARCHAR(20) NOT NULL DEFAULT 'active',
21
+ metadata JSONB DEFAULT '{}',
22
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
23
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
24
+ );
25
+
26
+ -- ============================================================
27
+ -- 2. gfp_phase_sections — 페이즈별 섹션 (핵심 테이블)
28
+ -- ============================================================
29
+
30
+ CREATE TABLE IF NOT EXISTS semicolony.gfp_phase_sections (
31
+ section_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
32
+ gfp_id UUID NOT NULL REFERENCES semicolony.gfp_projects(gfp_id) ON DELETE CASCADE,
33
+ phase SMALLINT NOT NULL,
34
+ section_key VARCHAR(100) NOT NULL,
35
+ title VARCHAR(200) NOT NULL,
36
+ content TEXT NOT NULL DEFAULT '',
37
+ ordinal SMALLINT NOT NULL DEFAULT 0,
38
+ status VARCHAR(20) NOT NULL DEFAULT 'draft',
39
+ reviewer_note TEXT,
40
+ source VARCHAR(50) NOT NULL DEFAULT 'manual',
41
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
42
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
43
+ UNIQUE(gfp_id, phase, section_key)
44
+ );
45
+
46
+ CREATE INDEX IF NOT EXISTS idx_gfp_sections_project
47
+ ON semicolony.gfp_phase_sections(gfp_id, phase, ordinal);
48
+
49
+ -- ============================================================
50
+ -- 3. gfp_materials — 사전 기획안 업로드
51
+ -- ============================================================
52
+
53
+ CREATE TABLE IF NOT EXISTS semicolony.gfp_materials (
54
+ material_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
55
+ gfp_id UUID NOT NULL REFERENCES semicolony.gfp_projects(gfp_id) ON DELETE CASCADE,
56
+ content TEXT NOT NULL,
57
+ phase_mapping JSONB,
58
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
59
+ );
60
+
61
+ -- ============================================================
62
+ -- 4. gfp_research_tasks — GrowthClaw 리서치
63
+ -- ============================================================
64
+
65
+ CREATE TABLE IF NOT EXISTS semicolony.gfp_research_tasks (
66
+ task_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
67
+ gfp_id UUID NOT NULL REFERENCES semicolony.gfp_projects(gfp_id) ON DELETE CASCADE,
68
+ task_type VARCHAR(50) NOT NULL,
69
+ reference_urls TEXT[] DEFAULT '{}',
70
+ input_prompt TEXT NOT NULL,
71
+ status VARCHAR(20) NOT NULL DEFAULT 'queued',
72
+ result TEXT,
73
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
74
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
75
+ );
76
+
77
+ -- ============================================================
78
+ -- 5. updated_at 트리거
79
+ -- ============================================================
80
+
81
+ CREATE OR REPLACE FUNCTION semicolony.gfp_set_updated_at()
82
+ RETURNS TRIGGER AS $$
83
+ BEGIN
84
+ NEW.updated_at = NOW();
85
+ RETURN NEW;
86
+ END;
87
+ $$ LANGUAGE plpgsql;
88
+
89
+ CREATE TRIGGER trg_gfp_projects_updated
90
+ BEFORE UPDATE ON semicolony.gfp_projects
91
+ FOR EACH ROW EXECUTE FUNCTION semicolony.gfp_set_updated_at();
92
+
93
+ CREATE TRIGGER trg_gfp_sections_updated
94
+ BEFORE UPDATE ON semicolony.gfp_phase_sections
95
+ FOR EACH ROW EXECUTE FUNCTION semicolony.gfp_set_updated_at();
96
+
97
+ CREATE TRIGGER trg_gfp_research_updated
98
+ BEFORE UPDATE ON semicolony.gfp_research_tasks
99
+ FOR EACH ROW EXECUTE FUNCTION semicolony.gfp_set_updated_at();
100
+
101
+ COMMIT;
@@ -0,0 +1,12 @@
1
+ -- 031_kb_manager_domain_register.sql
2
+ -- kb-manager 스킬에 도메인 등록 프로토콜 추가
3
+ -- CLI에 semicolony kb ontology --action register 명령어 추가에 맞춰 스킬 prompt 갱신
4
+ --
5
+ -- 변경 내용:
6
+ -- 1. skill_definitions의 kb-manager prompt 업데이트 (도메인 등록 섹션 추가)
7
+
8
+ UPDATE semicolony.skill_definitions
9
+ SET prompt = E'---\nname: kb-manager\ndescription: SEMICOLONY KB 조회/검색/수정. semicolony CLI를 통해 팀 Knowledge Base에 접근.\n---\n\n# KB Manager\n\n## 환경 설정\n```bash\nsource ~/.semicolony.env\n```\n\n## 명령어\n\n| 작업 | 명령어 |\n|------|--------|\n| 검색 | `semicolony kb search \"검색어\" --domain <domain>` |\n| 정확 조회 | `semicolony kb get <domain> <key> [sub_key]` |\n| 목록 | `semicolony kb list --domain <domain>` |\n| 쓰기 | `semicolony kb upsert <domain> <key> [sub_key] --content \"내용\"` |\n| 온톨로지 | `semicolony kb ontology --action <action>` |\n| 도메인 등록 | `semicolony kb ontology --action register --domain <name> --type <type>` |\n\n## 예시\n```bash\n# 팀원 조회\nsemicolony kb get <org> team alice\n\n# 서비스 PO 조회\nsemicolony kb get my-service po\n\n# 검색\nsemicolony kb search \"PO\" --service my-service\n\n# 의사결정 기록\nsemicolony kb upsert <org> decision 2026-03-24/example --content \"의사결정 내용\"\n\n# 라우팅 테이블 (저장 위치 판단용)\nsemicolony kb ontology --action routing-table\n\n# 타입 스키마 조회\nsemicolony kb ontology --action schema --type service\n\n# 서비스 인스턴스 목록\nsemicolony kb ontology --action instances\n```\n\n## 조회 프로토콜 (읽기)\n\n정확한 domain/key 경로를 모를 때:\n1. `semicolony kb search \"검색어\"` — 결과에서 `[domain] key/sub_key` 확인\n2. 결과의 full key 경로로 `semicolony kb get <domain> <key> <sub_key>` 실행\n\n도메인 자체를 모를 때:\n- `semicolony kb ontology --action instances` — 서비스 도메인 목록\n- `semicolony kb ontology --action routing-table` — 전체 domain→key 매핑\n\n## 저장 프로토콜 (쓰기)\n\n1. `semicolony kb ontology --action routing-table` — 저장 위치 확인\n2. `semicolony kb upsert <domain> <key> [sub_key] --content \"내용\"`\n\n## 도메인 등록 프로토콜\n\n새 도메인(서비스, 팀원, 봇 등)이 필요할 때:\n\n### Step 1: 타입 확인\n```bash\nsemicolony kb ontology --action types\n```\n사용 가능한 타입: service, team, person, bot, organization, decision, process 등\n\n### Step 2: 타입 스키마 확인 (필수 키 파악)\n```bash\nsemicolony kb ontology --action schema --type <type>\n```\n`*` 표시가 required 키 — 등록 시 자동으로 placeholder entry 생성됨\n\n### Step 3: 도메인 등록\n```bash\n# 기본 (필수 KB entry 자동 생성)\nsemicolony kb ontology --action register --domain <name> --type <type> --description \"설명\"\n\n# 서비스 그룹 지정\nsemicolony kb ontology --action register --domain <name> --type <type> --service <service> --description \"설명\"\n\n# 또는 onto 서브커맨드\nsemicolony onto register <name> --type <type> --description \"설명\"\n```\n\n### Step 4: 필수 데이터 입력\n등록 후 placeholder로 생성된 필수 키에 실제 데이터 입력:\n```bash\nsemicolony kb upsert <domain> <key> --content \"실제 내용\"\n```\n\n### 예시: 팀원 도메인 등록\n```bash\n# 1. team 타입 스키마 확인\nsemicolony kb ontology --action schema --type team\n\n# 2. 도메인 등록\nsemicolony kb ontology --action register --domain alice --type team --description \"Alice — 팀원\"\n\n# 3. 필수 데이터 입력\nsemicolony kb upsert alice profile --content \"역할: 프론트엔드 개발자\"\n```\n\n## 규칙\n- psql 직접 쿼리 금지 — 반드시 이 명령어 사용 (임베딩 자동 생성, 스키마 검증)\n- search 결과의 key/sub_key 경로를 그대로 get에 사용할 것\n- 도메인/키를 추측하지 말고 ontology 또는 search로 확인\n- 새 도메인 필요 시 반드시 ontology register로 등록 (직접 DB INSERT 금지)\n',
10
+ version = '3.0',
11
+ updated_at = NOW()
12
+ WHERE name = 'kb-manager' AND office_id IS NULL;
@@ -0,0 +1,40 @@
1
+ -- 032_gfp_skill_and_callback.sql
2
+ -- GFP 스킬 등록 + 봇 콜백을 위한 인프라
3
+ --
4
+ -- 1. gfp-manager 스킬 등록 (봇이 GFP 프로젝트/섹션 조회·수정 가능)
5
+ -- 2. gfp_projects.service_domain → ontology 자동 등록을 위한 트리거
6
+ -- 3. KB write-back 출처 추적을 위한 gfp_phase_sections.kb_written_at 컬럼
7
+
8
+ BEGIN;
9
+
10
+ -- ============================================================
11
+ -- 1. gfp-manager 스킬 등록
12
+ -- ============================================================
13
+
14
+ INSERT INTO semicolony.skill_definitions (name, display_name, description, prompt, package, is_active, metadata, version)
15
+ VALUES (
16
+ 'gfp-manager',
17
+ 'GFP Pipeline Manager',
18
+ 'GFP(Greenfield Project Pipeline) 프로젝트 조회/섹션 수정/리서치 결과 반영. 봇이 GFP DB에 접근.',
19
+ E'---\nname: gfp-manager\ndescription: GFP(Greenfield Project Pipeline) 프로젝트 조회/섹션 수정/리서치 결과 반영.\n---\n\n# GFP Pipeline Manager\n\nGFP 프로젝트의 섹션 생성/수정, 리서치 결과 반영, 상태 변경을 위한 스킬.\n봇(PlanClaw, GrowthClaw 등)이 대시보드 API를 통해 GFP DB에 접근한다.\n\n## API Endpoints\n\nBase URL: `${SEMICOLONY_DASHBOARD_URL}` (default: http://localhost:3000)\n\n### 프로젝트 조회\n```bash\n# 프로젝트 목록\ncurl -s ${SEMICOLONY_DASHBOARD_URL}/api/gfp | jq\n\n# 프로젝트 상세 (progress 포함)\ncurl -s ${SEMICOLONY_DASHBOARD_URL}/api/gfp/{gfp_id} | jq\n```\n\n### 섹션 조회/수정\n```bash\n# 섹션 목록 (페이즈별)\ncurl -s \"${SEMICOLONY_DASHBOARD_URL}/api/gfp/{gfp_id}/sections?phase=1\" | jq\n\n# 섹션 생성/수정 (upsert)\ncurl -X POST ${SEMICOLONY_DASHBOARD_URL}/api/gfp/{gfp_id}/sections \\\n -H \"Content-Type: application/json\" \\\n -d ''{ \"phase\": 1, \"section_key\": \"overview\", \"title\": \"Overview\", \"content\": \"...\", \"status\": \"pending-review\", \"source\": \"planclaw\" }''\n\n# 섹션 내용 업데이트 (재생성 결과 반영)\ncurl -X PATCH ${SEMICOLONY_DASHBOARD_URL}/api/gfp/{gfp_id}/sections \\\n -H \"Content-Type: application/json\" \\\n -d ''{ \"section_id\": \"...\", \"action\": \"update-content\", \"content\": \"수정된 내용\", \"status\": \"pending-review\" }''\n```\n\n### 봇 콜백 (결과 반영)\n```bash\n# PlanClaw: 재생성 결과 반영\ncurl -X POST ${SEMICOLONY_DASHBOARD_URL}/api/gfp/callback \\\n -H \"Content-Type: application/json\" \\\n -d ''{ \"type\": \"section-regeneration\", \"section_id\": \"...\", \"content\": \"재생성된 내용\", \"bot_id\": \"planclaw\" }''\n\n# GrowthClaw: 리서치 결과 반영\ncurl -X POST ${SEMICOLONY_DASHBOARD_URL}/api/gfp/callback \\\n -H \"Content-Type: application/json\" \\\n -d ''{ \"type\": \"research-result\", \"task_id\": \"...\", \"result\": \"리서치 결과 마크다운\", \"bot_id\": \"growthclaw\" }''\n```\n\n### 리서치 작업\n```bash\n# 리서치 목록\ncurl -s ${SEMICOLONY_DASHBOARD_URL}/api/gfp/{gfp_id}/research | jq\n\n# 리서치 결과 업데이트\ncurl -X PATCH ${SEMICOLONY_DASHBOARD_URL}/api/gfp/{gfp_id}/research \\\n -H \"Content-Type: application/json\" \\\n -d ''{ \"task_id\": \"...\", \"status\": \"completed\", \"result\": \"리서치 결과\" }''\n```\n\n## 규칙\n- 섹션 수정 시 status를 반드시 \"pending-review\"로 설정 (PO 재검토 필요)\n- source 필드로 출처 명시: planclaw / growthclaw / imported / manual\n- 콜백 API 사용 시 bot_id 필수\n',
20
+ 'core',
21
+ true,
22
+ '{"bot_ids": ["planclaw", "growthclaw"]}',
23
+ '1.0'
24
+ )
25
+ ON CONFLICT (name, office_id) DO UPDATE SET
26
+ prompt = EXCLUDED.prompt,
27
+ display_name = EXCLUDED.display_name,
28
+ description = EXCLUDED.description,
29
+ version = EXCLUDED.version,
30
+ metadata = EXCLUDED.metadata,
31
+ is_active = true;
32
+
33
+ -- ============================================================
34
+ -- 2. kb_written_at 컬럼 추가 (KB write-back 추적)
35
+ -- ============================================================
36
+
37
+ ALTER TABLE semicolony.gfp_phase_sections
38
+ ADD COLUMN IF NOT EXISTS kb_written_at TIMESTAMPTZ;
39
+
40
+ COMMIT;
@@ -0,0 +1,33 @@
1
+ -- 032_kebab_case_keys.sql
2
+ -- KB 스키마 키 네이밍 컨벤션 통일: snake_case → kebab-case
3
+ -- 영향: kb_type_schema (스키마 정의) + knowledge_base (실제 엔트리)
4
+
5
+ BEGIN;
6
+
7
+ -- ============================================================
8
+ -- 1. kb_type_schema: 스키마 키 이름 변환
9
+ -- ============================================================
10
+
11
+ UPDATE semicolony.kb_type_schema SET scheme_key = 'base-information' WHERE scheme_key = 'base_information';
12
+ UPDATE semicolony.kb_type_schema SET scheme_key = 'current-situation' WHERE scheme_key = 'current_situation';
13
+ UPDATE semicolony.kb_type_schema SET scheme_key = 'service-url' WHERE scheme_key = 'service_url';
14
+ UPDATE semicolony.kb_type_schema SET scheme_key = 'tech-stack' WHERE scheme_key = 'tech_stack';
15
+ UPDATE semicolony.kb_type_schema SET scheme_key = 'slack-channel' WHERE scheme_key = 'slack_channel';
16
+ UPDATE semicolony.kb_type_schema SET scheme_key = 'gateway-config' WHERE scheme_key = 'gateway_config';
17
+ UPDATE semicolony.kb_type_schema SET scheme_key = 'cron-schedule' WHERE scheme_key = 'cron_schedule';
18
+ UPDATE semicolony.kb_type_schema SET scheme_key = 'slack-config' WHERE scheme_key = 'slack_config';
19
+
20
+ -- ============================================================
21
+ -- 2. knowledge_base: 실제 엔트리 key 변환
22
+ -- ============================================================
23
+
24
+ UPDATE semicolony.knowledge_base SET key = 'base-information' WHERE key = 'base_information';
25
+ UPDATE semicolony.knowledge_base SET key = 'current-situation' WHERE key = 'current_situation';
26
+ UPDATE semicolony.knowledge_base SET key = 'service-url' WHERE key = 'service_url';
27
+ UPDATE semicolony.knowledge_base SET key = 'tech-stack' WHERE key = 'tech_stack';
28
+ UPDATE semicolony.knowledge_base SET key = 'slack-channel' WHERE key = 'slack_channel';
29
+ UPDATE semicolony.knowledge_base SET key = 'gateway-config' WHERE key = 'gateway_config';
30
+ UPDATE semicolony.knowledge_base SET key = 'cron-schedule' WHERE key = 'cron_schedule';
31
+ UPDATE semicolony.knowledge_base SET key = 'slack-config' WHERE key = 'slack_config';
32
+
33
+ COMMIT;
@@ -0,0 +1,10 @@
1
+ -- 033_skill_workspace_rules.sql
2
+ -- 스킬 디렉토리 SKILL.md 검증 규칙을 bot_workspace_standard에 추가
3
+
4
+ INSERT INTO semicolony.bot_workspace_standard
5
+ (path_pattern, entry_type, level, severity, category, bot_scope, content_rules, description, spec_version)
6
+ VALUES
7
+ ('skills/*/SKILL.md', 'glob', 'required', 'warn', 'structure', 'all',
8
+ '{"max_lines": 500, "required_patterns": ["^---"]}',
9
+ '각 스킬에 SKILL.md 필수 (frontmatter + 500줄 이하)', '2.0')
10
+ ON CONFLICT DO NOTHING;
@@ -0,0 +1,13 @@
1
+ -- 034_current_to_date_keys.sql
2
+ -- action-item, kpi: current 서브키 → 날짜 기반({YYYY-MM-DD}) 컨벤션으로 변경
3
+ -- 기존 current 서브키를 폐기하고 날짜 기반 서브키로 통일
4
+
5
+ -- action-item: value_hint 업데이트
6
+ UPDATE semicolony.kb_type_schema
7
+ SET value_hint = '날짜 기반 서브키 사용. 예: action-item/2026-03-29. 최신은 가장 큰 날짜로 조회.'
8
+ WHERE scheme_key = 'action-item';
9
+
10
+ -- kpi: value_hint 업데이트
11
+ UPDATE semicolony.kb_type_schema
12
+ SET value_hint = '날짜 기반 서브키 사용. 예: kpi/2026-03-29. 최신은 가장 큰 날짜로 조회.'
13
+ WHERE scheme_key = 'kpi';
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * 034_current_to_date_keys.ts
4
+ *
5
+ * KB 데이터 마이그레이션: action-item/current, kpi/current → 날짜 기반 서브키
6
+ * - action-item/current → action-item/{YYYY-MM-DD} (updated_at 기준)
7
+ * - kpi/current → kpi/{YYYY-MM-DD} (updated_at 기준)
8
+ *
9
+ * 사용법:
10
+ * npx tsx packages/cli/migrations/034_current_to_date_keys.ts [--dry-run]
11
+ */
12
+
13
+ import pg from "pg";
14
+
15
+ const DATABASE_URL = process.env.DATABASE_URL;
16
+
17
+ if (!DATABASE_URL) {
18
+ console.error("DATABASE_URL 환경변수가 필요합니다");
19
+ process.exit(1);
20
+ }
21
+
22
+ const DRY_RUN = process.argv.includes("--dry-run");
23
+
24
+ async function main() {
25
+ const pool = new pg.Pool({ connectionString: DATABASE_URL });
26
+
27
+ try {
28
+ // 1. action-item/current 엔트리 조회
29
+ const actionItems = await pool.query(`
30
+ SELECT kb_id, domain, key, sub_key, content, embedding, updated_at
31
+ FROM semicolony.knowledge_base
32
+ WHERE key = 'action-item' AND sub_key = 'current'
33
+ `);
34
+
35
+ console.log(`action-item/current 엔트리: ${actionItems.rows.length}건`);
36
+
37
+ // 2. kpi/current 엔트리 조회
38
+ const kpiItems = await pool.query(`
39
+ SELECT kb_id, domain, key, sub_key, content, embedding, updated_at
40
+ FROM semicolony.knowledge_base
41
+ WHERE key = 'kpi' AND sub_key = 'current'
42
+ `);
43
+
44
+ console.log(`kpi/current 엔트리: ${kpiItems.rows.length}건`);
45
+
46
+ const allItems = [...actionItems.rows, ...kpiItems.rows];
47
+
48
+ if (allItems.length === 0) {
49
+ console.log("마이그레이션 대상 없음");
50
+ return;
51
+ }
52
+
53
+ for (const row of allItems) {
54
+ const dateStr = new Date(row.updated_at).toISOString().split("T")[0]; // YYYY-MM-DD
55
+ const newSubKey = dateStr;
56
+
57
+ console.log(` ${row.domain}/${row.key}/current → ${row.domain}/${row.key}/${newSubKey}`);
58
+
59
+ if (DRY_RUN) continue;
60
+
61
+ // 동일 날짜 서브키가 이미 존재하는지 확인
62
+ const existing = await pool.query(
63
+ `SELECT kb_id FROM semicolony.knowledge_base WHERE domain = $1 AND key = $2 AND sub_key = $3`,
64
+ [row.domain, row.key, newSubKey]
65
+ );
66
+
67
+ if (existing.rows.length > 0) {
68
+ // 이미 존재하면 current 엔트리만 삭제
69
+ console.log(` (이미 ${newSubKey} 존재 — current만 삭제)`);
70
+ } else {
71
+ // 새 날짜 키로 INSERT
72
+ await pool.query(
73
+ `INSERT INTO semicolony.knowledge_base (domain, key, sub_key, content, embedding, metadata, version, created_by, updated_at)
74
+ SELECT domain, key, $1, content, embedding, metadata, version, created_by, updated_at
75
+ FROM semicolony.knowledge_base WHERE kb_id = $2`,
76
+ [newSubKey, row.kb_id]
77
+ );
78
+ }
79
+
80
+ // current 엔트리 삭제
81
+ await pool.query(
82
+ `DELETE FROM semicolony.knowledge_base WHERE kb_id = $1`,
83
+ [row.kb_id]
84
+ );
85
+ }
86
+
87
+ if (!DRY_RUN) {
88
+ // 검증
89
+ const remaining = await pool.query(
90
+ `SELECT COUNT(*)::int as cnt FROM semicolony.knowledge_base WHERE sub_key = 'current' AND key IN ('action-item', 'kpi')`
91
+ );
92
+ console.log(`\n남은 current 서브키: ${remaining.rows[0].cnt}건`);
93
+ }
94
+
95
+ console.log("\n마이그레이션 완료");
96
+ } finally {
97
+ await pool.end();
98
+ }
99
+ }
100
+
101
+ main().catch((err) => {
102
+ console.error("에러:", err);
103
+ process.exit(1);
104
+ });
@@ -0,0 +1,51 @@
1
+ -- 035_bot_budgets.sql
2
+ -- 봇 예산 관리 + 비용 집계 뷰
3
+ -- Paperclip 컨셉 통합: 에이전트별 월간 예산 + 자동 정지
4
+
5
+ BEGIN;
6
+
7
+ -- ============================================================
8
+ -- 1. bot_budgets — 봇별 월간 예산 설정
9
+ -- ============================================================
10
+
11
+ CREATE TABLE IF NOT EXISTS semicolony.bot_budgets (
12
+ bot_id TEXT PRIMARY KEY REFERENCES semicolony.bot_status(bot_id),
13
+ monthly_budget_usd NUMERIC(10,2),
14
+ alert_threshold_pct INT NOT NULL DEFAULT 80,
15
+ auto_pause BOOLEAN NOT NULL DEFAULT false,
16
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
17
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
18
+ );
19
+
20
+ -- ============================================================
21
+ -- 2. bot_cost_summary — 월별 비용 집계 뷰
22
+ -- ============================================================
23
+
24
+ CREATE OR REPLACE VIEW semicolony.bot_cost_summary AS
25
+ SELECT
26
+ bot_id,
27
+ date_trunc('month', created_at)::date AS month,
28
+ COUNT(*) AS query_count,
29
+ COALESCE(SUM(token_input), 0) AS total_input_tokens,
30
+ COALESCE(SUM(token_output), 0) AS total_output_tokens,
31
+ COALESCE(SUM((metadata->>'cost_usd')::numeric), 0) AS total_cost_usd,
32
+ COALESCE(AVG(latency_ms), 0)::int AS avg_latency_ms
33
+ FROM semicolony.bot_query_logs
34
+ GROUP BY bot_id, date_trunc('month', created_at);
35
+
36
+ -- ============================================================
37
+ -- 3. bot_cost_daily — 일별 비용 집계 뷰 (트렌드용)
38
+ -- ============================================================
39
+
40
+ CREATE OR REPLACE VIEW semicolony.bot_cost_daily AS
41
+ SELECT
42
+ bot_id,
43
+ created_at::date AS day,
44
+ COUNT(*) AS query_count,
45
+ COALESCE(SUM(token_input), 0) AS total_input_tokens,
46
+ COALESCE(SUM(token_output), 0) AS total_output_tokens,
47
+ COALESCE(SUM((metadata->>'cost_usd')::numeric), 0) AS total_cost_usd
48
+ FROM semicolony.bot_query_logs
49
+ GROUP BY bot_id, created_at::date;
50
+
51
+ COMMIT;
@@ -0,0 +1,35 @@
1
+ -- 036_gfp_stitch_design.sql
2
+ -- GFP Phase 3 (Design System) + Stitch 브릿지 지원
3
+ --
4
+ -- 1. gfp_materials에 material_type 컬럼 추가 (planning-doc | stitch-export)
5
+ -- 2. DesignClaw를 gfp-manager 스킬 사용 봇에 추가
6
+
7
+ BEGIN;
8
+
9
+ -- ============================================================
10
+ -- 1. gfp_materials.material_type 컬럼
11
+ -- ============================================================
12
+ ALTER TABLE semicolony.gfp_materials
13
+ ADD COLUMN IF NOT EXISTS material_type VARCHAR(50) DEFAULT 'planning-doc';
14
+
15
+ COMMENT ON COLUMN semicolony.gfp_materials.material_type IS
16
+ 'Material type: planning-doc (기존 기획안), stitch-export (Stitch CSS export)';
17
+
18
+ -- ============================================================
19
+ -- 2. gfp-manager 스킬에 designclaw 봇 추가
20
+ -- ============================================================
21
+ UPDATE semicolony.skill_definitions
22
+ SET metadata = jsonb_set(
23
+ metadata,
24
+ '{bot_ids}',
25
+ (metadata->'bot_ids') || '["designclaw"]'::jsonb
26
+ )
27
+ WHERE name = 'gfp-manager'
28
+ AND NOT (metadata->'bot_ids' @> '"designclaw"'::jsonb);
29
+
30
+ -- ============================================================
31
+ -- 3. GfpSectionSource에 'designclaw' 허용 (CHECK 제약이 없으면 무시)
32
+ -- ============================================================
33
+ -- gfp_phase_sections.source는 VARCHAR이므로 별도 제약 없이 'designclaw' 값 사용 가능
34
+
35
+ COMMIT;
@@ -0,0 +1,13 @@
1
+ -- GFP Phase 3 Q&A support: structured clarification questions
2
+ -- qa_items stores Q&A items as JSONB array
3
+ -- slack_thread_ts tracks Slack thread for answer collection
4
+
5
+ ALTER TABLE semicolony.gfp_phase_sections
6
+ ADD COLUMN IF NOT EXISTS qa_items JSONB,
7
+ ADD COLUMN IF NOT EXISTS slack_thread_ts VARCHAR(50);
8
+
9
+ COMMENT ON COLUMN semicolony.gfp_phase_sections.qa_items IS
10
+ 'Structured Q&A items for clarification sections. Array of {id, question, sub_bullets[], answer, answered_at, answered_via}';
11
+
12
+ COMMENT ON COLUMN semicolony.gfp_phase_sections.slack_thread_ts IS
13
+ 'Slack thread timestamp for Q&A answer collection via threaded replies';
@@ -0,0 +1,26 @@
1
+ BEGIN;
2
+
3
+ -- GFP Phase 3 분리: Clarification(Q&A) + Design System(디자인)
4
+ -- Phase 3 → Clarification(3) + Design System(4), 이후 Phase +1 shift → 10단계(0-9)
5
+
6
+ -- 1. Shift phases 8→9, 7→8, 6→7, 5→6, 4→5 (descending to avoid UNIQUE violation)
7
+ UPDATE semicolony.gfp_phase_sections SET phase = 9 WHERE phase = 8;
8
+ UPDATE semicolony.gfp_phase_sections SET phase = 8 WHERE phase = 7;
9
+ UPDATE semicolony.gfp_phase_sections SET phase = 7 WHERE phase = 6;
10
+ UPDATE semicolony.gfp_phase_sections SET phase = 6 WHERE phase = 5;
11
+ UPDATE semicolony.gfp_phase_sections SET phase = 5 WHERE phase = 4;
12
+
13
+ -- 2. Move phase 3 design-prefixed sections → phase 4
14
+ UPDATE semicolony.gfp_phase_sections SET phase = 4
15
+ WHERE phase = 3
16
+ AND (section_key LIKE 'ref-%' OR section_key LIKE 'ds-%'
17
+ OR section_key LIKE 'impl-%' OR section_key LIKE 'review-%'
18
+ OR section_key LIKE 'handoff-%' OR section_key LIKE 'stitch-%'
19
+ OR section_key = 'design-system' OR section_key LIKE 'design-%');
20
+
21
+ -- 3. Phase 3 non-design sections (Q&A) stay at 3
22
+
23
+ -- 4. Shift gfp_projects.current_phase for existing projects
24
+ UPDATE semicolony.gfp_projects SET current_phase = current_phase + 1 WHERE current_phase >= 4;
25
+
26
+ COMMIT;
@@ -0,0 +1,2 @@
1
+ -- 회의 오디오를 DB에 저장 (컨테이너 /tmp 휘발 문제 해결)
2
+ ALTER TABLE semicolony.meetings ADD COLUMN IF NOT EXISTS audio_data bytea;
@@ -0,0 +1,68 @@
1
+ BEGIN;
2
+
3
+ CREATE TABLE IF NOT EXISTS semicolony.bot_commitments (
4
+ id TEXT PRIMARY KEY, -- "cmt-{botId}-{timestamp}-{rand4}"
5
+ bot_id TEXT NOT NULL, -- FK 논리적: semicolony.bot_status.bot_id
6
+ status VARCHAR(20) NOT NULL DEFAULT 'pending',
7
+ -- pending → active → done | failed | expired
8
+ title TEXT NOT NULL, -- "Typography+Layout+Imagery+Motion 섹션 생성"
9
+ description TEXT,
10
+ source_type VARCHAR(30), -- 'github-issue' | 'slack' | 'cron' | 'manual'
11
+ source_ref TEXT, -- "{org}/{repo}#42" or channel:thread
12
+ deadline_at TIMESTAMPTZ,
13
+ steps JSONB DEFAULT '[]'::jsonb, -- [{"label":"Typography","done":false}]
14
+ metadata JSONB DEFAULT '{}'::jsonb, -- 확장용 (session_key, fail_reason, notes 등)
15
+ last_heartbeat_at TIMESTAMPTZ,
16
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
17
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
18
+ completed_at TIMESTAMPTZ
19
+ );
20
+
21
+ -- 활성 커밋먼트 조회 인덱스 (watchdog 최적화)
22
+ CREATE INDEX IF NOT EXISTS idx_commitments_active
23
+ ON semicolony.bot_commitments (status, deadline_at)
24
+ WHERE status IN ('pending', 'active');
25
+
26
+ CREATE INDEX IF NOT EXISTS idx_commitments_bot
27
+ ON semicolony.bot_commitments (bot_id, status);
28
+
29
+ -- updated_at 자동 갱신 트리거
30
+ CREATE OR REPLACE FUNCTION semicolony.trg_commitments_updated()
31
+ RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ LANGUAGE plpgsql;
32
+
33
+ CREATE TRIGGER trg_commitments_updated
34
+ BEFORE UPDATE ON semicolony.bot_commitments
35
+ FOR EACH ROW EXECUTE FUNCTION semicolony.trg_commitments_updated();
36
+
37
+ -- 완료 시 completed_at 자동 채움
38
+ CREATE OR REPLACE FUNCTION semicolony.trg_commitments_completed()
39
+ RETURNS TRIGGER AS $$
40
+ BEGIN
41
+ IF NEW.status IN ('done','failed','expired') AND OLD.status NOT IN ('done','failed','expired') THEN
42
+ NEW.completed_at = NOW();
43
+ END IF;
44
+ RETURN NEW;
45
+ END;
46
+ $$ LANGUAGE plpgsql;
47
+
48
+ CREATE TRIGGER trg_commitments_completed
49
+ BEFORE UPDATE ON semicolony.bot_commitments
50
+ FOR EACH ROW EXECUTE FUNCTION semicolony.trg_commitments_completed();
51
+
52
+ -- 워치독용 뷰
53
+ CREATE OR REPLACE VIEW semicolony.v_active_commitments AS
54
+ SELECT c.*,
55
+ CASE
56
+ WHEN c.deadline_at IS NOT NULL AND c.deadline_at < NOW() THEN 'overdue'
57
+ WHEN c.last_heartbeat_at IS NOT NULL
58
+ AND c.last_heartbeat_at < NOW() - INTERVAL '30 minutes' THEN 'stale'
59
+ ELSE 'on-track'
60
+ END AS health,
61
+ EXTRACT(EPOCH FROM (NOW() - COALESCE(c.last_heartbeat_at, c.created_at))) / 60.0
62
+ AS minutes_since_heartbeat,
63
+ EXTRACT(EPOCH FROM (NOW() - c.deadline_at)) / 60.0
64
+ AS minutes_overdue
65
+ FROM semicolony.bot_commitments c
66
+ WHERE c.status IN ('pending', 'active');
67
+
68
+ COMMIT;
@@ -0,0 +1,13 @@
1
+ -- 041: Standalone palette preview storage (DesignClaw 독립 색상 상담용)
2
+
3
+ CREATE TABLE IF NOT EXISTS semicolony.palette_previews (
4
+ preview_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
5
+ title TEXT,
6
+ colors_json JSONB NOT NULL, -- ColorGroup[]
7
+ bot_id TEXT NOT NULL DEFAULT 'designclaw',
8
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
9
+ expires_at TIMESTAMPTZ NOT NULL DEFAULT now() + INTERVAL '30 days'
10
+ );
11
+
12
+ CREATE INDEX IF NOT EXISTS idx_palette_previews_created
13
+ ON semicolony.palette_previews (created_at DESC);