ohwow 0.6.9 → 0.9.0
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/dist/index.js +3112 -1534
- package/dist/mcp-server/index.js +12 -12
- package/dist/migrations/091-skills-sop-columns.sql +18 -0
- package/dist/migrations/092-operational-pillars.sql +55 -0
- package/dist/migrations/093-seed-operational-pillars.sql +176 -0
- package/dist/migrations/094-person-models.sql +58 -0
- package/dist/migrations/095-transition-engine.sql +52 -0
- package/dist/migrations/096-work-router.sql +95 -0
- package/dist/migrations/097-human-growth.sql +58 -0
- package/dist/migrations/098-observation-layer.sql +5 -0
- package/dist/migrations/099-collective-intelligence.sql +5 -0
- package/dist/migrations/100-agent-model-policy.sql +32 -0
- package/dist/migrations/101-llm-calls.sql +36 -0
- package/dist/migrations/102-team-member-guide.sql +14 -0
- package/dist/migrations/103-fix-person-models-fk.sql +89 -0
- package/dist/migrations/104-fix-person-observations-fk.sql +48 -0
- package/dist/migrations/105-onboarding-plans.sql +56 -0
- package/dist/migrations/106-deliverable-actor-link.sql +29 -0
- package/dist/migrations/107-code-skills.sql +20 -0
- package/dist/migrations/108-archive-procedure-skills.sql +29 -0
- package/dist/migrations/109-workspace-default-fs-paths.sql +19 -0
- package/dist/migrations/110-task-state-ttl.sql +28 -0
- package/dist/migrations/111-conversation-status.sql +25 -0
- package/dist/migrations/112-deliverables-created-at-iso.sql +40 -0
- package/dist/migrations/113-permission-requests.sql +36 -0
- package/dist/migrations/114-llm-calls-tool-telemetry.sql +32 -0
- package/dist/migrations/115-trigger-watchdog.sql +46 -0
- package/dist/migrations/116-self-findings.sql +46 -0
- package/dist/migrations/117-experiment-validations.sql +64 -0
- package/dist/migrations/118-validation-rollback.sql +33 -0
- package/dist/migrations/119-runtime-config-overrides.sql +44 -0
- package/dist/migrations/120-business-vitals.sql +44 -0
- package/dist/migrations/121-x-contact-events.sql +42 -0
- package/dist/migrations/122-video-jobs.sql +52 -0
- package/dist/migrations/123-insight-distiller.sql +68 -0
- package/dist/migrations/124-x-dm-messages.sql +55 -0
- package/dist/migrations/125-x-dm-messages-bodies.sql +40 -0
- package/dist/migrations/126-x-dm-signals.sql +52 -0
- package/dist/migrations/127-x-dm-contact-linking.sql +36 -0
- package/dist/migrations/128-attribution-view.sql +59 -0
- package/dist/migrations/129-x-posted-log.sql +36 -0
- package/dist/migrations/130-patches-attempted-log.sql +44 -0
- package/dist/scrapling-server/requirements.txt +3 -0
- package/dist/scrapling-server/server.py +224 -0
- package/dist/web/assets/index-Bp9CoQ8c.css +1 -0
- package/dist/web/assets/index-C5xtuLcg.js +102 -0
- package/dist/web/index.html +2 -2
- package/package.json +9 -4
- package/dist/web/assets/index-B2PzvKIq.js +0 -100
- package/dist/web/assets/index-DZAi92e-.css +0 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
-- Transition Engine: task patterns + task transitions (SQLite)
|
|
2
|
+
|
|
3
|
+
CREATE TABLE IF NOT EXISTS task_patterns (
|
|
4
|
+
id TEXT PRIMARY KEY,
|
|
5
|
+
workspace_id TEXT NOT NULL,
|
|
6
|
+
person_model_id TEXT,
|
|
7
|
+
name TEXT NOT NULL,
|
|
8
|
+
description TEXT,
|
|
9
|
+
category TEXT NOT NULL DEFAULT 'general' CHECK (category IN (
|
|
10
|
+
'email', 'content', 'research', 'data', 'social',
|
|
11
|
+
'scheduling', 'crm', 'support', 'ops', 'general'
|
|
12
|
+
)),
|
|
13
|
+
detection_method TEXT NOT NULL DEFAULT 'auto_detected' CHECK (detection_method IN ('manual', 'auto_detected', 'pillar_derived')),
|
|
14
|
+
frequency TEXT CHECK (frequency IN ('daily', 'weekly', 'biweekly', 'monthly', 'irregular')),
|
|
15
|
+
avg_human_duration_minutes INTEGER,
|
|
16
|
+
avg_agent_duration_minutes INTEGER,
|
|
17
|
+
title_keywords TEXT DEFAULT '[]',
|
|
18
|
+
tool_fingerprint TEXT DEFAULT '[]',
|
|
19
|
+
department_id TEXT,
|
|
20
|
+
preferred_agent_id TEXT,
|
|
21
|
+
instance_count INTEGER DEFAULT 0,
|
|
22
|
+
first_observed_at TEXT DEFAULT (datetime('now')),
|
|
23
|
+
last_observed_at TEXT DEFAULT (datetime('now')),
|
|
24
|
+
archived_at TEXT,
|
|
25
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
26
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE TABLE IF NOT EXISTS task_transitions (
|
|
30
|
+
id TEXT PRIMARY KEY,
|
|
31
|
+
workspace_id TEXT NOT NULL,
|
|
32
|
+
pattern_id TEXT NOT NULL,
|
|
33
|
+
person_model_id TEXT,
|
|
34
|
+
current_stage INTEGER NOT NULL DEFAULT 1 CHECK (current_stage BETWEEN 1 AND 5),
|
|
35
|
+
stage_history TEXT DEFAULT '[]',
|
|
36
|
+
confidence_score REAL DEFAULT 0.0,
|
|
37
|
+
correction_count INTEGER DEFAULT 0,
|
|
38
|
+
total_instances INTEGER DEFAULT 0,
|
|
39
|
+
successful_instances INTEGER DEFAULT 0,
|
|
40
|
+
human_edit_rate REAL DEFAULT 1.0,
|
|
41
|
+
last_promoted_at TEXT,
|
|
42
|
+
last_demoted_at TEXT,
|
|
43
|
+
time_saved_minutes INTEGER DEFAULT 0,
|
|
44
|
+
active INTEGER NOT NULL DEFAULT 1,
|
|
45
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
46
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_task_patterns_workspace ON task_patterns(workspace_id);
|
|
50
|
+
CREATE INDEX IF NOT EXISTS idx_task_patterns_person ON task_patterns(workspace_id, person_model_id);
|
|
51
|
+
CREATE INDEX IF NOT EXISTS idx_task_transitions_pattern ON task_transitions(pattern_id);
|
|
52
|
+
CREATE INDEX IF NOT EXISTS idx_task_transitions_workspace ON task_transitions(workspace_id);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
-- Work Router: intelligent task routing + work augmentation + notification prefs
|
|
2
|
+
-- Phase 3 of Center of Operations
|
|
3
|
+
|
|
4
|
+
-- Routing decisions: tracks how tasks are assigned and why
|
|
5
|
+
CREATE TABLE IF NOT EXISTS work_routing_decisions (
|
|
6
|
+
id TEXT PRIMARY KEY,
|
|
7
|
+
workspace_id TEXT NOT NULL,
|
|
8
|
+
task_id TEXT,
|
|
9
|
+
task_title TEXT NOT NULL,
|
|
10
|
+
task_urgency TEXT DEFAULT 'normal' CHECK (task_urgency IN ('low', 'normal', 'high', 'critical')),
|
|
11
|
+
required_skills TEXT DEFAULT '[]',
|
|
12
|
+
estimated_effort_minutes INTEGER,
|
|
13
|
+
|
|
14
|
+
-- Assignment
|
|
15
|
+
assigned_to_type TEXT NOT NULL CHECK (assigned_to_type IN ('person', 'agent')),
|
|
16
|
+
assigned_to_id TEXT NOT NULL,
|
|
17
|
+
assignment_method TEXT NOT NULL DEFAULT 'recommended' CHECK (assignment_method IN ('auto', 'recommended', 'manual', 'fallback')),
|
|
18
|
+
confidence_score REAL DEFAULT 0.0 CHECK (confidence_score >= 0 AND confidence_score <= 1),
|
|
19
|
+
|
|
20
|
+
-- Scoring breakdown (JSON: { skill: 0.9, capacity: 0.7, energy: 0.8, ... })
|
|
21
|
+
score_breakdown TEXT DEFAULT '{}',
|
|
22
|
+
runner_up_id TEXT,
|
|
23
|
+
runner_up_type TEXT CHECK (runner_up_type IN ('person', 'agent')),
|
|
24
|
+
runner_up_score REAL,
|
|
25
|
+
|
|
26
|
+
-- Outcome tracking
|
|
27
|
+
outcome TEXT CHECK (outcome IN ('completed', 'reassigned', 'rejected', 'timed_out')),
|
|
28
|
+
outcome_quality_score REAL CHECK (outcome_quality_score >= 0 AND outcome_quality_score <= 1),
|
|
29
|
+
actual_effort_minutes INTEGER,
|
|
30
|
+
completed_at TEXT,
|
|
31
|
+
|
|
32
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
33
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
-- Work augmentation: pre/co/post work for human-assigned tasks
|
|
37
|
+
CREATE TABLE IF NOT EXISTS work_augmentations (
|
|
38
|
+
id TEXT PRIMARY KEY,
|
|
39
|
+
workspace_id TEXT NOT NULL,
|
|
40
|
+
routing_decision_id TEXT REFERENCES work_routing_decisions(id) ON DELETE CASCADE,
|
|
41
|
+
task_id TEXT,
|
|
42
|
+
person_model_id TEXT,
|
|
43
|
+
|
|
44
|
+
-- Phase
|
|
45
|
+
phase TEXT NOT NULL CHECK (phase IN ('pre', 'co', 'post')),
|
|
46
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'running', 'completed', 'skipped', 'failed')),
|
|
47
|
+
|
|
48
|
+
-- What the augmentation does
|
|
49
|
+
augmentation_type TEXT NOT NULL,
|
|
50
|
+
description TEXT,
|
|
51
|
+
agent_id TEXT,
|
|
52
|
+
|
|
53
|
+
-- Output
|
|
54
|
+
output TEXT DEFAULT '{}',
|
|
55
|
+
was_useful INTEGER,
|
|
56
|
+
|
|
57
|
+
started_at TEXT,
|
|
58
|
+
completed_at TEXT,
|
|
59
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
-- Notification preferences per person (extends person model)
|
|
63
|
+
CREATE TABLE IF NOT EXISTS notification_preferences (
|
|
64
|
+
id TEXT PRIMARY KEY,
|
|
65
|
+
workspace_id TEXT NOT NULL,
|
|
66
|
+
person_model_id TEXT NOT NULL,
|
|
67
|
+
|
|
68
|
+
-- Channel preferences
|
|
69
|
+
preferred_channel TEXT DEFAULT 'in_app' CHECK (preferred_channel IN ('in_app', 'email', 'slack', 'telegram', 'whatsapp')),
|
|
70
|
+
fallback_channel TEXT DEFAULT 'email' CHECK (fallback_channel IN ('in_app', 'email', 'slack', 'telegram', 'whatsapp')),
|
|
71
|
+
|
|
72
|
+
-- Deep work protection
|
|
73
|
+
deep_work_start TEXT,
|
|
74
|
+
deep_work_end TEXT,
|
|
75
|
+
deep_work_days TEXT DEFAULT '[]',
|
|
76
|
+
buffer_during_deep_work INTEGER NOT NULL DEFAULT 1,
|
|
77
|
+
|
|
78
|
+
-- Energy-aware filtering
|
|
79
|
+
low_energy_start TEXT,
|
|
80
|
+
low_energy_end TEXT,
|
|
81
|
+
suppress_complex_during_low_energy INTEGER NOT NULL DEFAULT 1,
|
|
82
|
+
|
|
83
|
+
-- Urgency thresholds
|
|
84
|
+
min_urgency_for_interrupt TEXT DEFAULT 'high' CHECK (min_urgency_for_interrupt IN ('low', 'normal', 'high', 'critical')),
|
|
85
|
+
|
|
86
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
87
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
CREATE INDEX IF NOT EXISTS idx_routing_decisions_workspace ON work_routing_decisions(workspace_id);
|
|
91
|
+
CREATE INDEX IF NOT EXISTS idx_routing_decisions_assignee ON work_routing_decisions(assigned_to_type, assigned_to_id);
|
|
92
|
+
CREATE INDEX IF NOT EXISTS idx_routing_decisions_task ON work_routing_decisions(task_id);
|
|
93
|
+
CREATE INDEX IF NOT EXISTS idx_augmentations_routing ON work_augmentations(routing_decision_id);
|
|
94
|
+
CREATE INDEX IF NOT EXISTS idx_augmentations_workspace ON work_augmentations(workspace_id);
|
|
95
|
+
CREATE INDEX IF NOT EXISTS idx_notification_prefs_person ON notification_preferences(person_model_id);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
-- Human Growth Engine: skill progression, growth milestones, delegation tracking
|
|
2
|
+
-- Phase 4 of Center of Operations
|
|
3
|
+
|
|
4
|
+
-- Skill progression: tracks skill level changes over time per person
|
|
5
|
+
CREATE TABLE IF NOT EXISTS skill_progression (
|
|
6
|
+
id TEXT PRIMARY KEY,
|
|
7
|
+
workspace_id TEXT NOT NULL,
|
|
8
|
+
person_model_id TEXT NOT NULL REFERENCES agent_workforce_person_models(id) ON DELETE CASCADE,
|
|
9
|
+
skill_name TEXT NOT NULL,
|
|
10
|
+
previous_level REAL DEFAULT 0.0,
|
|
11
|
+
new_level REAL NOT NULL,
|
|
12
|
+
source TEXT NOT NULL DEFAULT 'task_outcome' CHECK (source IN (
|
|
13
|
+
'task_outcome', 'self_assessment', 'peer_observation', 'training', 'routing_feedback'
|
|
14
|
+
)),
|
|
15
|
+
task_id TEXT,
|
|
16
|
+
notes TEXT,
|
|
17
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
-- Growth milestones: target achievements on skill development paths
|
|
21
|
+
CREATE TABLE IF NOT EXISTS growth_milestones (
|
|
22
|
+
id TEXT PRIMARY KEY,
|
|
23
|
+
workspace_id TEXT NOT NULL,
|
|
24
|
+
person_model_id TEXT NOT NULL REFERENCES agent_workforce_person_models(id) ON DELETE CASCADE,
|
|
25
|
+
skill_name TEXT NOT NULL,
|
|
26
|
+
target_level REAL NOT NULL DEFAULT 0.7,
|
|
27
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'achieved', 'abandoned')),
|
|
28
|
+
difficulty TEXT NOT NULL DEFAULT 'intermediate' CHECK (difficulty IN ('beginner', 'intermediate', 'advanced', 'expert')),
|
|
29
|
+
suggested_tasks TEXT DEFAULT '[]',
|
|
30
|
+
scaffolding_level TEXT NOT NULL DEFAULT 'high' CHECK (scaffolding_level IN ('high', 'medium', 'low', 'none')),
|
|
31
|
+
path_order INTEGER DEFAULT 0,
|
|
32
|
+
achieved_at TEXT,
|
|
33
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
34
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
-- Delegation decisions: founder-specific tracking of what gets delegated
|
|
38
|
+
CREATE TABLE IF NOT EXISTS delegation_decisions (
|
|
39
|
+
id TEXT PRIMARY KEY,
|
|
40
|
+
workspace_id TEXT NOT NULL,
|
|
41
|
+
person_model_id TEXT NOT NULL REFERENCES agent_workforce_person_models(id) ON DELETE CASCADE,
|
|
42
|
+
decision_type TEXT NOT NULL,
|
|
43
|
+
description TEXT,
|
|
44
|
+
delegated_to_type TEXT CHECK (delegated_to_type IN ('agent', 'person')),
|
|
45
|
+
delegated_to_id TEXT,
|
|
46
|
+
outcome TEXT DEFAULT 'pending' CHECK (outcome IN ('successful', 'reverted', 'pending')),
|
|
47
|
+
founder_review_needed INTEGER NOT NULL DEFAULT 1,
|
|
48
|
+
routing_decision_id TEXT,
|
|
49
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
50
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
CREATE INDEX IF NOT EXISTS idx_skill_progression_person ON skill_progression(person_model_id);
|
|
54
|
+
CREATE INDEX IF NOT EXISTS idx_skill_progression_skill ON skill_progression(person_model_id, skill_name);
|
|
55
|
+
CREATE INDEX IF NOT EXISTS idx_growth_milestones_person ON growth_milestones(person_model_id);
|
|
56
|
+
CREATE INDEX IF NOT EXISTS idx_growth_milestones_status ON growth_milestones(person_model_id, status);
|
|
57
|
+
CREATE INDEX IF NOT EXISTS idx_delegation_decisions_person ON delegation_decisions(person_model_id);
|
|
58
|
+
CREATE INDEX IF NOT EXISTS idx_delegation_decisions_workspace ON delegation_decisions(workspace_id);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
-- Shape C: agents are sub-orchestrators, not single-model wrappers.
|
|
2
|
+
--
|
|
3
|
+
-- Moves any existing `config.model` string on agent rows into
|
|
4
|
+
-- `config.model_policy.default`, then removes the legacy `config.model` key
|
|
5
|
+
-- so downstream code never reads it again. Agents that already carry a
|
|
6
|
+
-- `model_policy` are left alone. Agents without a model at all are also
|
|
7
|
+
-- untouched.
|
|
8
|
+
--
|
|
9
|
+
-- Idempotent and safe to re-run: the WHERE clause narrows to rows that
|
|
10
|
+
-- both (a) still have `config.model` and (b) do not yet have
|
|
11
|
+
-- `config.model_policy.default`.
|
|
12
|
+
|
|
13
|
+
UPDATE agent_workforce_agents
|
|
14
|
+
SET config = json_remove(
|
|
15
|
+
json_set(
|
|
16
|
+
config,
|
|
17
|
+
'$.model_policy.default',
|
|
18
|
+
json_extract(config, '$.model')
|
|
19
|
+
),
|
|
20
|
+
'$.model'
|
|
21
|
+
)
|
|
22
|
+
WHERE json_extract(config, '$.model') IS NOT NULL
|
|
23
|
+
AND json_extract(config, '$.model_policy.default') IS NULL;
|
|
24
|
+
|
|
25
|
+
-- For rows that had `config.model` AND already had a `model_policy` but
|
|
26
|
+
-- no default set: the previous UPDATE handled the "no default" case. For
|
|
27
|
+
-- rows with both a legacy `config.model` AND an existing
|
|
28
|
+
-- `model_policy.default`, we drop the legacy key without overwriting the
|
|
29
|
+
-- policy — the policy wins.
|
|
30
|
+
UPDATE agent_workforce_agents
|
|
31
|
+
SET config = json_remove(config, '$.model')
|
|
32
|
+
WHERE json_extract(config, '$.model') IS NOT NULL;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
-- Shape C telemetry: per-call record of every llm organ invocation.
|
|
2
|
+
--
|
|
3
|
+
-- Every runLlmCall writes a row here, success or failure, with the
|
|
4
|
+
-- resolved provider, model, token counts, cost, and latency. Feeds
|
|
5
|
+
-- future adaptive routing (routingHistory, bandit model selection) and
|
|
6
|
+
-- lets operators see cost per agent per purpose over time.
|
|
7
|
+
--
|
|
8
|
+
-- Nullable agent_id: llm calls can come from orchestrator chat (no
|
|
9
|
+
-- specific agent) or from external callers via /api/llm.
|
|
10
|
+
-- Nullable task_id: llm calls may be ad-hoc outside any task.
|
|
11
|
+
|
|
12
|
+
CREATE TABLE IF NOT EXISTS llm_calls (
|
|
13
|
+
id TEXT PRIMARY KEY,
|
|
14
|
+
workspace_id TEXT NOT NULL,
|
|
15
|
+
agent_id TEXT,
|
|
16
|
+
task_id TEXT,
|
|
17
|
+
purpose TEXT NOT NULL,
|
|
18
|
+
provider TEXT NOT NULL,
|
|
19
|
+
model TEXT NOT NULL,
|
|
20
|
+
input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
21
|
+
output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
22
|
+
cost_cents INTEGER NOT NULL DEFAULT 0,
|
|
23
|
+
latency_ms INTEGER NOT NULL DEFAULT 0,
|
|
24
|
+
success INTEGER NOT NULL DEFAULT 1,
|
|
25
|
+
error_message TEXT,
|
|
26
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE INDEX IF NOT EXISTS llm_calls_workspace_created_idx
|
|
30
|
+
ON llm_calls(workspace_id, created_at DESC);
|
|
31
|
+
|
|
32
|
+
CREATE INDEX IF NOT EXISTS llm_calls_agent_idx
|
|
33
|
+
ON llm_calls(agent_id, created_at DESC);
|
|
34
|
+
|
|
35
|
+
CREATE INDEX IF NOT EXISTS llm_calls_purpose_idx
|
|
36
|
+
ON llm_calls(purpose, created_at DESC);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
-- 102-team-member-guide.sql
|
|
2
|
+
-- Link a team member to their dedicated "chief of staff" guide agent.
|
|
3
|
+
-- Also adds timezone, cloud_invite_token (for pending invites), and
|
|
4
|
+
-- onboarding_status so the orchestrator can track whether person
|
|
5
|
+
-- ingestion has been kicked off / completed.
|
|
6
|
+
|
|
7
|
+
ALTER TABLE agent_workforce_team_members ADD COLUMN assigned_guide_agent_id TEXT DEFAULT NULL;
|
|
8
|
+
ALTER TABLE agent_workforce_team_members ADD COLUMN timezone TEXT DEFAULT NULL;
|
|
9
|
+
ALTER TABLE agent_workforce_team_members ADD COLUMN cloud_invite_token TEXT DEFAULT NULL;
|
|
10
|
+
ALTER TABLE agent_workforce_team_members ADD COLUMN cloud_invite_status TEXT DEFAULT NULL;
|
|
11
|
+
ALTER TABLE agent_workforce_team_members ADD COLUMN onboarding_status TEXT DEFAULT 'not_started';
|
|
12
|
+
|
|
13
|
+
CREATE INDEX IF NOT EXISTS idx_team_members_guide
|
|
14
|
+
ON agent_workforce_team_members(assigned_guide_agent_id);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
-- 103-fix-person-models-fk.sql
|
|
2
|
+
-- Migration 094 declared team_member_id as REFERENCES team_members(id) but
|
|
3
|
+
-- the real table is agent_workforce_team_members. With foreign_keys = ON
|
|
4
|
+
-- (set in db/init.ts) any INSERT/UPDATE on agent_workforce_person_models
|
|
5
|
+
-- fails with "no such table: main.team_members" because SQLite resolves
|
|
6
|
+
-- the FK target lazily, and the target does not exist.
|
|
7
|
+
--
|
|
8
|
+
-- SQLite has no ALTER TABLE DROP CONSTRAINT, so we rebuild the table:
|
|
9
|
+
-- rename the old one, CREATE the new shape with the correct FK, copy rows,
|
|
10
|
+
-- drop the rename. Wrapped in a transaction so either everything lands or
|
|
11
|
+
-- nothing does.
|
|
12
|
+
--
|
|
13
|
+
-- The new FK points at agent_workforce_team_members(id) with ON DELETE
|
|
14
|
+
-- SET NULL matching the original intent.
|
|
15
|
+
|
|
16
|
+
-- The migration runner already wraps each file in a transaction, so we
|
|
17
|
+
-- do not BEGIN/COMMIT ourselves. foreign_keys is set at init time; the
|
|
18
|
+
-- rebuild-via-rename pattern works here because we copy rows between
|
|
19
|
+
-- two tables in the same workspace and the only broken FK is the one
|
|
20
|
+
-- we are fixing.
|
|
21
|
+
|
|
22
|
+
ALTER TABLE agent_workforce_person_models RENAME TO agent_workforce_person_models_old;
|
|
23
|
+
|
|
24
|
+
CREATE TABLE agent_workforce_person_models (
|
|
25
|
+
id TEXT PRIMARY KEY,
|
|
26
|
+
workspace_id TEXT NOT NULL REFERENCES agent_workforce_workspaces(id) ON DELETE CASCADE,
|
|
27
|
+
team_member_id TEXT REFERENCES agent_workforce_team_members(id) ON DELETE SET NULL,
|
|
28
|
+
name TEXT NOT NULL,
|
|
29
|
+
email TEXT,
|
|
30
|
+
avatar_url TEXT,
|
|
31
|
+
role_title TEXT,
|
|
32
|
+
variant TEXT NOT NULL DEFAULT 'team_member' CHECK (variant IN ('founder', 'team_member', 'new_hire')),
|
|
33
|
+
work_history TEXT DEFAULT '[]',
|
|
34
|
+
skills_map TEXT DEFAULT '{}',
|
|
35
|
+
domain_expertise TEXT DEFAULT '{}',
|
|
36
|
+
blind_spots TEXT DEFAULT '[]',
|
|
37
|
+
tool_proficiency TEXT DEFAULT '{}',
|
|
38
|
+
communication_style TEXT DEFAULT '{}',
|
|
39
|
+
energy_patterns TEXT DEFAULT '{}',
|
|
40
|
+
learning_style TEXT,
|
|
41
|
+
collaboration_preferences TEXT DEFAULT '{}',
|
|
42
|
+
ambitions TEXT DEFAULT '{}',
|
|
43
|
+
values_and_motivations TEXT DEFAULT '[]',
|
|
44
|
+
friction_points TEXT DEFAULT '[]',
|
|
45
|
+
flow_triggers TEXT DEFAULT '[]',
|
|
46
|
+
skill_gaps_to_close TEXT DEFAULT '[]',
|
|
47
|
+
external_context TEXT DEFAULT '{}',
|
|
48
|
+
growth_arc TEXT DEFAULT '{}',
|
|
49
|
+
growth_velocity REAL DEFAULT 0,
|
|
50
|
+
growth_direction TEXT DEFAULT 'ascending' CHECK (growth_direction IN ('ascending', 'plateau', 'declining', 'transforming')),
|
|
51
|
+
growth_snapshots TEXT DEFAULT '[]',
|
|
52
|
+
ingestion_status TEXT DEFAULT 'not_started' CHECK (ingestion_status IN ('not_started', 'in_progress', 'initial_complete', 'mature')),
|
|
53
|
+
ingestion_variant TEXT,
|
|
54
|
+
last_ingestion_at TEXT,
|
|
55
|
+
observation_count INTEGER DEFAULT 0,
|
|
56
|
+
refinement_count INTEGER DEFAULT 0,
|
|
57
|
+
work_pattern_map TEXT DEFAULT '{}',
|
|
58
|
+
collective_briefing TEXT DEFAULT '{}',
|
|
59
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
60
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
INSERT INTO agent_workforce_person_models (
|
|
64
|
+
id, workspace_id, team_member_id, name, email, avatar_url, role_title,
|
|
65
|
+
variant, work_history, skills_map, domain_expertise, blind_spots,
|
|
66
|
+
tool_proficiency, communication_style, energy_patterns, learning_style,
|
|
67
|
+
collaboration_preferences, ambitions, values_and_motivations,
|
|
68
|
+
friction_points, flow_triggers, skill_gaps_to_close, external_context,
|
|
69
|
+
growth_arc, growth_velocity, growth_direction, growth_snapshots,
|
|
70
|
+
ingestion_status, ingestion_variant, last_ingestion_at,
|
|
71
|
+
observation_count, refinement_count, work_pattern_map, collective_briefing,
|
|
72
|
+
created_at, updated_at
|
|
73
|
+
)
|
|
74
|
+
SELECT
|
|
75
|
+
id, workspace_id, team_member_id, name, email, avatar_url, role_title,
|
|
76
|
+
variant, work_history, skills_map, domain_expertise, blind_spots,
|
|
77
|
+
tool_proficiency, communication_style, energy_patterns, learning_style,
|
|
78
|
+
collaboration_preferences, ambitions, values_and_motivations,
|
|
79
|
+
friction_points, flow_triggers, skill_gaps_to_close, external_context,
|
|
80
|
+
growth_arc, growth_velocity, growth_direction, growth_snapshots,
|
|
81
|
+
ingestion_status, ingestion_variant, last_ingestion_at,
|
|
82
|
+
observation_count, refinement_count, work_pattern_map, collective_briefing,
|
|
83
|
+
created_at, updated_at
|
|
84
|
+
FROM agent_workforce_person_models_old;
|
|
85
|
+
|
|
86
|
+
DROP TABLE agent_workforce_person_models_old;
|
|
87
|
+
|
|
88
|
+
CREATE INDEX IF NOT EXISTS idx_person_models_workspace
|
|
89
|
+
ON agent_workforce_person_models(workspace_id);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
-- 104-fix-person-observations-fk.sql
|
|
2
|
+
--
|
|
3
|
+
-- Migration 103 rebuilt agent_workforce_person_models with the correct FK
|
|
4
|
+
-- target (agent_workforce_team_members), via the RENAME + CREATE + INSERT +
|
|
5
|
+
-- DROP dance. But the child table agent_workforce_person_observations
|
|
6
|
+
-- declares its FK as:
|
|
7
|
+
-- person_model_id TEXT NOT NULL REFERENCES "agent_workforce_person_models_old"(id) ON DELETE CASCADE
|
|
8
|
+
-- SQLite baked the rename target into the observations FK at the moment of
|
|
9
|
+
-- RENAME, and now observations point at a dropped table. Any insert fails
|
|
10
|
+
-- with "no such table: main.agent_workforce_person_models_old" because
|
|
11
|
+
-- foreign_keys is on in db/init.ts.
|
|
12
|
+
--
|
|
13
|
+
-- Rebuild the observations table too so the FK points back at
|
|
14
|
+
-- agent_workforce_person_models(id). Same copy-via-rename pattern as 103.
|
|
15
|
+
-- The CHECK and indexes are recreated to match.
|
|
16
|
+
|
|
17
|
+
ALTER TABLE agent_workforce_person_observations RENAME TO agent_workforce_person_observations_old;
|
|
18
|
+
|
|
19
|
+
CREATE TABLE agent_workforce_person_observations (
|
|
20
|
+
id TEXT PRIMARY KEY,
|
|
21
|
+
person_model_id TEXT NOT NULL REFERENCES agent_workforce_person_models(id) ON DELETE CASCADE,
|
|
22
|
+
workspace_id TEXT NOT NULL REFERENCES agent_workforce_workspaces(id) ON DELETE CASCADE,
|
|
23
|
+
dimension TEXT NOT NULL,
|
|
24
|
+
observation_type TEXT NOT NULL CHECK (observation_type IN (
|
|
25
|
+
'task_outcome', 'communication', 'feedback', 'self_report', 'behavioral', 'peer_observation', 'correction'
|
|
26
|
+
)),
|
|
27
|
+
content TEXT NOT NULL,
|
|
28
|
+
data TEXT DEFAULT '{}',
|
|
29
|
+
confidence REAL DEFAULT 0.5 CHECK (confidence >= 0 AND confidence <= 1),
|
|
30
|
+
processed INTEGER DEFAULT 0,
|
|
31
|
+
source_type TEXT,
|
|
32
|
+
source_id TEXT,
|
|
33
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
INSERT INTO agent_workforce_person_observations (
|
|
37
|
+
id, person_model_id, workspace_id, dimension, observation_type, content,
|
|
38
|
+
data, confidence, processed, source_type, source_id, created_at
|
|
39
|
+
)
|
|
40
|
+
SELECT
|
|
41
|
+
id, person_model_id, workspace_id, dimension, observation_type, content,
|
|
42
|
+
data, confidence, processed, source_type, source_id, created_at
|
|
43
|
+
FROM agent_workforce_person_observations_old;
|
|
44
|
+
|
|
45
|
+
DROP TABLE agent_workforce_person_observations_old;
|
|
46
|
+
|
|
47
|
+
CREATE INDEX IF NOT EXISTS idx_person_observations_model
|
|
48
|
+
ON agent_workforce_person_observations(person_model_id);
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
-- 105-onboarding-plans.sql
|
|
2
|
+
--
|
|
3
|
+
-- First-class onboarding plan artifact per team member. The COS agent
|
|
4
|
+
-- generates a 4-week ramp plan during person-model ingestion via
|
|
5
|
+
-- propose_first_month_plan, and that draft lives here until the member
|
|
6
|
+
-- (via the chat) accepts it — at which point accept_onboarding_plan
|
|
7
|
+
-- materializes it into real agent_workforce_tasks + agent_workforce_goals
|
|
8
|
+
-- rows and flips status to 'accepted'.
|
|
9
|
+
--
|
|
10
|
+
-- Shape:
|
|
11
|
+
--
|
|
12
|
+
-- weeks: JSON array, one entry per week:
|
|
13
|
+
-- [
|
|
14
|
+
-- {
|
|
15
|
+
-- "week": 1,
|
|
16
|
+
-- "theme": "Land + observe",
|
|
17
|
+
-- "tasks": [
|
|
18
|
+
-- { "title": ..., "description": ..., "owner": "member|guide|<agent-id>",
|
|
19
|
+
-- "success_criteria": ..., "materialized_task_id": null }
|
|
20
|
+
-- ]
|
|
21
|
+
-- },
|
|
22
|
+
-- ...
|
|
23
|
+
-- ]
|
|
24
|
+
--
|
|
25
|
+
-- status:
|
|
26
|
+
-- 'draft' — freshly proposed, member hasn't reviewed yet
|
|
27
|
+
-- 'accepted' — member accepted, tasks + goals created
|
|
28
|
+
-- 'in_progress' — at least one materialized task has been started
|
|
29
|
+
-- 'completed' — all materialized tasks are done
|
|
30
|
+
-- 'archived' — superseded or canceled
|
|
31
|
+
|
|
32
|
+
CREATE TABLE IF NOT EXISTS agent_workforce_onboarding_plans (
|
|
33
|
+
id TEXT PRIMARY KEY,
|
|
34
|
+
workspace_id TEXT NOT NULL REFERENCES agent_workforce_workspaces(id) ON DELETE CASCADE,
|
|
35
|
+
team_member_id TEXT NOT NULL REFERENCES agent_workforce_team_members(id) ON DELETE CASCADE,
|
|
36
|
+
person_model_id TEXT REFERENCES agent_workforce_person_models(id) ON DELETE SET NULL,
|
|
37
|
+
created_by_agent_id TEXT REFERENCES agent_workforce_agents(id) ON DELETE SET NULL,
|
|
38
|
+
status TEXT NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'accepted', 'in_progress', 'completed', 'archived')),
|
|
39
|
+
rationale TEXT,
|
|
40
|
+
closing_question TEXT,
|
|
41
|
+
weeks TEXT NOT NULL DEFAULT '[]',
|
|
42
|
+
model_used TEXT,
|
|
43
|
+
provider TEXT,
|
|
44
|
+
input_tokens INTEGER DEFAULT 0,
|
|
45
|
+
output_tokens INTEGER DEFAULT 0,
|
|
46
|
+
accepted_at TEXT,
|
|
47
|
+
completed_at TEXT,
|
|
48
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
49
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
CREATE INDEX IF NOT EXISTS idx_onboarding_plans_member
|
|
53
|
+
ON agent_workforce_onboarding_plans(team_member_id, created_at DESC);
|
|
54
|
+
|
|
55
|
+
CREATE INDEX IF NOT EXISTS idx_onboarding_plans_workspace_status
|
|
56
|
+
ON agent_workforce_onboarding_plans(workspace_id, status);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
-- 106-deliverable-actor-link.sql
|
|
2
|
+
--
|
|
3
|
+
-- Add three columns to agent_workforce_deliverables so we can attribute
|
|
4
|
+
-- every produced artifact to who made it AND who it was made for.
|
|
5
|
+
--
|
|
6
|
+
-- produced_by_type 'agent' | 'member' | 'guide' | 'system'
|
|
7
|
+
-- produced_by_id agent_id, team_member_id, or null
|
|
8
|
+
-- for_team_member_id the team_member this deliverable belongs to,
|
|
9
|
+
-- e.g. when the COS runs a research task on
|
|
10
|
+
-- Mario's behalf the resulting cheat sheet is
|
|
11
|
+
-- produced_by_type='guide', produced_by_id=COS,
|
|
12
|
+
-- for_team_member_id=Mario.
|
|
13
|
+
--
|
|
14
|
+
-- The cloud activity timeline + per-person work tracking dashboards
|
|
15
|
+
-- query these columns to render "what did agent X produce" and
|
|
16
|
+
-- "what did member Y produce / receive on their behalf".
|
|
17
|
+
|
|
18
|
+
ALTER TABLE agent_workforce_deliverables ADD COLUMN produced_by_type TEXT;
|
|
19
|
+
-- @statement
|
|
20
|
+
ALTER TABLE agent_workforce_deliverables ADD COLUMN produced_by_id TEXT;
|
|
21
|
+
-- @statement
|
|
22
|
+
ALTER TABLE agent_workforce_deliverables ADD COLUMN for_team_member_id TEXT;
|
|
23
|
+
-- @statement
|
|
24
|
+
CREATE INDEX IF NOT EXISTS idx_deliverables_for_team_member
|
|
25
|
+
ON agent_workforce_deliverables(for_team_member_id)
|
|
26
|
+
WHERE for_team_member_id IS NOT NULL;
|
|
27
|
+
-- @statement
|
|
28
|
+
CREATE INDEX IF NOT EXISTS idx_deliverables_produced_by
|
|
29
|
+
ON agent_workforce_deliverables(produced_by_type, produced_by_id);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-- Code skills: add columns that let the synthesis pipeline store
|
|
2
|
+
-- deterministic TypeScript-backed skills alongside the existing
|
|
3
|
+
-- procedure/judgement/extraction/verification skill_types.
|
|
4
|
+
--
|
|
5
|
+
-- Local SQLite has no CHECK constraint on skill_type, so adding a new
|
|
6
|
+
-- value ('code') is a no-op at the schema level. The new columns are
|
|
7
|
+
-- all nullable or default-initialized so existing rows remain valid.
|
|
8
|
+
--
|
|
9
|
+
-- Mirror migration lives at ohwow.fun/sql/359-code-skills.sql.
|
|
10
|
+
|
|
11
|
+
ALTER TABLE agent_workforce_skills ADD COLUMN script_path TEXT;
|
|
12
|
+
ALTER TABLE agent_workforce_skills ADD COLUMN selectors TEXT DEFAULT '{}';
|
|
13
|
+
ALTER TABLE agent_workforce_skills ADD COLUMN origin_trace_id TEXT;
|
|
14
|
+
ALTER TABLE agent_workforce_skills ADD COLUMN success_count INTEGER NOT NULL DEFAULT 0;
|
|
15
|
+
ALTER TABLE agent_workforce_skills ADD COLUMN fail_count INTEGER NOT NULL DEFAULT 0;
|
|
16
|
+
ALTER TABLE agent_workforce_skills ADD COLUMN promoted_at TEXT;
|
|
17
|
+
|
|
18
|
+
CREATE INDEX IF NOT EXISTS idx_skills_script_path
|
|
19
|
+
ON agent_workforce_skills(script_path)
|
|
20
|
+
WHERE script_path IS NOT NULL;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
-- Archive all active procedure skills.
|
|
2
|
+
--
|
|
3
|
+
-- Context: the runtime's three keyword matchers (runAgent SOP loop,
|
|
4
|
+
-- engine compileSkills, prompt-builder triggerMatched) were removed
|
|
5
|
+
-- in the unified-skill-synthesis refactor. Procedure rows no longer
|
|
6
|
+
-- have any discovery path at runtime. Setting is_active=0 archives
|
|
7
|
+
-- them without losing the audit trail. Rows remain queryable for
|
|
8
|
+
-- historical analysis but stop appearing in the skill loader's
|
|
9
|
+
-- boot scan and the now-deleted matchers.
|
|
10
|
+
--
|
|
11
|
+
-- The three active rows on launch eve were all degenerate single-
|
|
12
|
+
-- tool wrappers:
|
|
13
|
+
-- - "Post a Tweet" → tool_sequence ["x_compose_tweet"]
|
|
14
|
+
-- - "Write X Article" → tool_sequence ["x_compose_article"]
|
|
15
|
+
-- - "Check X Messages" → tool_sequence ["x_list_dms"]
|
|
16
|
+
-- The LLM already has x_compose_tweet, x_compose_article, and
|
|
17
|
+
-- x_list_dms directly in its static tool list. No capability is lost.
|
|
18
|
+
--
|
|
19
|
+
-- The single inactive desktop SOP ("Check X Notifications") is
|
|
20
|
+
-- already is_active=0 and is unaffected.
|
|
21
|
+
--
|
|
22
|
+
-- Idempotent: safe to re-run. The `updated_at` stamp moves on each
|
|
23
|
+
-- run but no functional state changes after the first application.
|
|
24
|
+
|
|
25
|
+
UPDATE agent_workforce_skills
|
|
26
|
+
SET is_active = 0,
|
|
27
|
+
updated_at = datetime('now')
|
|
28
|
+
WHERE skill_type = 'procedure'
|
|
29
|
+
AND is_active = 1;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-- Workspace-level default filesystem paths.
|
|
2
|
+
--
|
|
3
|
+
-- Without this, every agent that doesn't have an explicit row in
|
|
4
|
+
-- agent_file_access_paths fails every local_read_file/local_write_file call
|
|
5
|
+
-- with "No directories are configured for file access". The orchestrator
|
|
6
|
+
-- pseudo-agent has a hardcoded /tmp baseline (filesystem.ts) but real agents
|
|
7
|
+
-- inherit nothing, so SOP-delegated work that touches the disk silently fails.
|
|
8
|
+
--
|
|
9
|
+
-- engine.ts unions this column with per-agent paths when constructing the
|
|
10
|
+
-- FileAccessGuard, so workspace defaults flow to every task execution.
|
|
11
|
+
-- filesystem.ts reads the same column so orchestrator chat and agent task
|
|
12
|
+
-- execution share a single source of truth for "what /tmp-like paths are
|
|
13
|
+
-- always allowed."
|
|
14
|
+
--
|
|
15
|
+
-- Default value gives every existing workspace /tmp out of the box, matching
|
|
16
|
+
-- the prior orchestrator-only baseline.
|
|
17
|
+
|
|
18
|
+
ALTER TABLE agent_workforce_workspaces
|
|
19
|
+
ADD COLUMN default_filesystem_paths TEXT NOT NULL DEFAULT '["/tmp"]';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
-- TTL + lazy cleanup for agent_workforce_task_state.
|
|
2
|
+
--
|
|
3
|
+
-- The state table had no expiration mechanism, so once an agent wrote a key
|
|
4
|
+
-- (incident flag, health check, scratch value, etc.) it lived forever. Stale
|
|
5
|
+
-- rows from old sessions polluted reasoning: agents would get_state on a key
|
|
6
|
+
-- that was set during a long-dead incident, see RED, and refuse the unrelated
|
|
7
|
+
-- task in front of them.
|
|
8
|
+
--
|
|
9
|
+
-- expires_at is NULL for persistent state (the default for keys that don't
|
|
10
|
+
-- match the heuristic prefixes in state.ts). For ephemeral keys (incident_*,
|
|
11
|
+
-- *_health_*, temp_*, scratch_*) state.ts now writes a 24h default expiry.
|
|
12
|
+
-- getAgentState filters expired rows on read and lazy-deletes them so the
|
|
13
|
+
-- next reader doesn't trip the same poisoning.
|
|
14
|
+
--
|
|
15
|
+
-- The DELETE at the bottom is a one-shot purge of the two known-poisoning
|
|
16
|
+
-- keys observed in production today. They are not written by any current
|
|
17
|
+
-- code path (verified) so deleting them is a clean fix; they cannot grow
|
|
18
|
+
-- back through normal use.
|
|
19
|
+
|
|
20
|
+
ALTER TABLE agent_workforce_task_state
|
|
21
|
+
ADD COLUMN expires_at TEXT;
|
|
22
|
+
|
|
23
|
+
CREATE INDEX IF NOT EXISTS idx_task_state_expires
|
|
24
|
+
ON agent_workforce_task_state(expires_at)
|
|
25
|
+
WHERE expires_at IS NOT NULL;
|
|
26
|
+
|
|
27
|
+
DELETE FROM agent_workforce_task_state
|
|
28
|
+
WHERE key IN ('last_health_check', 'incident_scrapling_down');
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
-- Async chat: status tracking on orchestrator_conversations.
|
|
2
|
+
--
|
|
3
|
+
-- The MCP ohwow_chat tool now creates a conversation row, returns its id
|
|
4
|
+
-- immediately, and dispatches the orchestrator turn in the background so
|
|
5
|
+
-- long turns survive client disconnects. Clients poll GET /api/chat/:id
|
|
6
|
+
-- until status flips out of 'running'.
|
|
7
|
+
--
|
|
8
|
+
-- Status values:
|
|
9
|
+
-- idle — conversation exists, no turn currently executing (manual create)
|
|
10
|
+
-- running — orchestrator turn dispatched, in flight
|
|
11
|
+
-- done — turn finished, latest assistant message is the final answer
|
|
12
|
+
-- error — turn failed, last_error has the message
|
|
13
|
+
--
|
|
14
|
+
-- The partial index on status='running' keeps "find in-flight turns" cheap
|
|
15
|
+
-- without bloating the index for the 99% steady-state case.
|
|
16
|
+
|
|
17
|
+
ALTER TABLE orchestrator_conversations
|
|
18
|
+
ADD COLUMN status TEXT NOT NULL DEFAULT 'idle';
|
|
19
|
+
|
|
20
|
+
ALTER TABLE orchestrator_conversations
|
|
21
|
+
ADD COLUMN last_error TEXT;
|
|
22
|
+
|
|
23
|
+
CREATE INDEX IF NOT EXISTS idx_conv_status_running
|
|
24
|
+
ON orchestrator_conversations(workspace_id, status)
|
|
25
|
+
WHERE status = 'running';
|