@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,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,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,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);
|