Files
tutti/services/tuttid/data/workspace/migrations_tutti_mode_execution.go
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

409 lines
16 KiB
Go

package workspace
import (
"context"
"fmt"
"time"
)
func (s *SQLiteStore) applyWorkspaceTuttiModeExecutionV1(ctx context.Context) error {
applied, err := s.hasMigration(ctx, schemaMigrationWorkspaceTuttiModeExecutionV1)
if err != nil || applied {
return err
}
tx, err := s.writeDB.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("begin workspace Tutti mode execution migration: %w", err)
}
defer func() { _ = tx.Rollback() }()
_, err = tx.ExecContext(ctx, `
CREATE TABLE workspace_tutti_executions (
workspace_id TEXT NOT NULL,
execution_id TEXT NOT NULL,
issue_id TEXT NOT NULL,
workflow_id TEXT NOT NULL,
source_session_id TEXT NOT NULL,
status TEXT NOT NULL CHECK (status IN (
'awaiting_schedule', 'running', 'awaiting_main', 'pending_goal_review',
'orphaned_source', 'completed', 'archiving', 'archived'
)),
graph_revision INTEGER NOT NULL CHECK (graph_revision > 0),
last_orchestrator_activity_at_unix_ms INTEGER NOT NULL,
watchdog_due_at_unix_ms INTEGER NOT NULL,
review_mode TEXT NOT NULL CHECK (review_mode IN ('self', 'independent')),
review_agent_target_id TEXT NOT NULL DEFAULT '',
completed_at_unix_ms INTEGER NOT NULL DEFAULT 0,
archived_at_unix_ms INTEGER NOT NULL DEFAULT 0,
archived_by TEXT NOT NULL DEFAULT '',
archive_reason TEXT NOT NULL DEFAULT '',
created_at_unix_ms INTEGER NOT NULL,
updated_at_unix_ms INTEGER NOT NULL,
PRIMARY KEY (workspace_id, execution_id),
UNIQUE (workspace_id, issue_id),
UNIQUE (workspace_id, workflow_id),
FOREIGN KEY (workspace_id, issue_id)
REFERENCES workspace_issues(workspace_id, issue_id) ON DELETE CASCADE,
FOREIGN KEY (workspace_id, workflow_id)
REFERENCES workspace_workflows(workspace_id, workflow_id) ON DELETE CASCADE
);
CREATE INDEX idx_workspace_tutti_executions_source_status
ON workspace_tutti_executions(workspace_id, source_session_id, status, updated_at_unix_ms);
CREATE TABLE workspace_tutti_execution_checkpoints (
workspace_id TEXT NOT NULL,
execution_id TEXT NOT NULL,
checkpoint_id TEXT NOT NULL,
kind TEXT NOT NULL CHECK (kind IN (
'initial_schedule', 'task_settled', 'task_failed', 'task_canceled',
'watchdog', 'all_tasks_terminal', 'migration'
)),
status TEXT NOT NULL CHECK (status IN ('pending', 'active', 'resolved', 'superseded', 'canceled')),
sequence INTEGER NOT NULL CHECK (sequence > 0),
graph_revision INTEGER NOT NULL CHECK (graph_revision > 0),
subject_task_id TEXT NOT NULL DEFAULT '',
subject_run_id TEXT NOT NULL DEFAULT '',
creation_reason TEXT NOT NULL,
requires_goal_review INTEGER NOT NULL DEFAULT 0 CHECK (requires_goal_review IN (0, 1)),
created_at_unix_ms INTEGER NOT NULL,
updated_at_unix_ms INTEGER NOT NULL,
resolved_at_unix_ms INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (workspace_id, execution_id, checkpoint_id),
UNIQUE (workspace_id, execution_id, sequence),
FOREIGN KEY (workspace_id, execution_id)
REFERENCES workspace_tutti_executions(workspace_id, execution_id) ON DELETE CASCADE
);
CREATE UNIQUE INDEX idx_workspace_tutti_execution_checkpoints_one_active
ON workspace_tutti_execution_checkpoints(workspace_id, execution_id)
WHERE status = 'active';
CREATE INDEX idx_workspace_tutti_execution_checkpoints_backlog
ON workspace_tutti_execution_checkpoints(workspace_id, execution_id, status, sequence);
CREATE TABLE workspace_tutti_execution_wakes (
workspace_id TEXT NOT NULL,
execution_id TEXT NOT NULL,
checkpoint_id TEXT NOT NULL,
wake_id TEXT NOT NULL,
target_kind TEXT NOT NULL CHECK (target_kind IN ('main', 'reviewer')),
wake_sequence INTEGER NOT NULL CHECK (wake_sequence > 0),
client_submit_id TEXT NOT NULL,
target_session_id TEXT NOT NULL DEFAULT '',
review_agent_target_id TEXT NOT NULL DEFAULT '',
canonical_session_id TEXT NOT NULL DEFAULT '',
canonical_turn_id TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL CHECK (status IN (
'prepared', 'leased', 'dispatched', 'turn_settled',
'acknowledged', 'failed', 'canceled'
)),
due_at_unix_ms INTEGER NOT NULL,
attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
lease_owner TEXT NOT NULL DEFAULT '',
lease_expires_at_unix_ms INTEGER NOT NULL DEFAULT 0,
dispatched_at_unix_ms INTEGER NOT NULL DEFAULT 0,
turn_settled_at_unix_ms INTEGER NOT NULL DEFAULT 0,
acknowledged_at_unix_ms INTEGER NOT NULL DEFAULT 0,
last_error TEXT NOT NULL DEFAULT '',
created_at_unix_ms INTEGER NOT NULL,
updated_at_unix_ms INTEGER NOT NULL,
PRIMARY KEY (workspace_id, execution_id, wake_id),
UNIQUE (workspace_id, client_submit_id),
UNIQUE (workspace_id, execution_id, checkpoint_id, target_kind, wake_sequence),
FOREIGN KEY (workspace_id, execution_id, checkpoint_id)
REFERENCES workspace_tutti_execution_checkpoints(workspace_id, execution_id, checkpoint_id) ON DELETE CASCADE
);
CREATE INDEX idx_workspace_tutti_execution_wakes_due
ON workspace_tutti_execution_wakes(workspace_id, status, due_at_unix_ms, lease_expires_at_unix_ms);
CREATE TABLE workspace_tutti_goal_reviews (
workspace_id TEXT NOT NULL,
execution_id TEXT NOT NULL,
checkpoint_id TEXT NOT NULL,
review_id TEXT NOT NULL,
review_agent_target_id TEXT NOT NULL DEFAULT '',
review_session_id TEXT NOT NULL DEFAULT '',
review_turn_id TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL CHECK (status IN ('prepared', 'dispatched', 'submitted', 'failed', 'canceled')),
verdict TEXT NOT NULL DEFAULT '' CHECK (verdict IN ('', 'goal_satisfied', 'more_work_required', 'inconclusive')),
summary TEXT NOT NULL DEFAULT '',
failure_reason TEXT NOT NULL DEFAULT '',
created_at_unix_ms INTEGER NOT NULL,
updated_at_unix_ms INTEGER NOT NULL,
submitted_at_unix_ms INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (workspace_id, execution_id, review_id),
UNIQUE (workspace_id, execution_id, checkpoint_id),
FOREIGN KEY (workspace_id, execution_id, checkpoint_id)
REFERENCES workspace_tutti_execution_checkpoints(workspace_id, execution_id, checkpoint_id) ON DELETE CASCADE
);
CREATE TABLE workspace_tutti_archive_operations (
workspace_id TEXT NOT NULL,
execution_id TEXT NOT NULL,
operation_id TEXT NOT NULL,
request_id TEXT NOT NULL,
status TEXT NOT NULL CHECK (status IN ('requested', 'canceling_runs', 'archiving', 'completed', 'failed')),
requested_by TEXT NOT NULL,
reason TEXT NOT NULL DEFAULT '',
attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
lease_owner TEXT NOT NULL DEFAULT '',
lease_expires_at_unix_ms INTEGER NOT NULL DEFAULT 0,
last_error TEXT NOT NULL DEFAULT '',
created_at_unix_ms INTEGER NOT NULL,
updated_at_unix_ms INTEGER NOT NULL,
completed_at_unix_ms INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (workspace_id, execution_id, operation_id),
UNIQUE (workspace_id, execution_id, request_id),
FOREIGN KEY (workspace_id, execution_id)
REFERENCES workspace_tutti_executions(workspace_id, execution_id) ON DELETE CASCADE
);
CREATE TABLE workspace_tutti_execution_mutations (
workspace_id TEXT NOT NULL,
execution_id TEXT NOT NULL,
issue_id TEXT NOT NULL,
source_session_id TEXT NOT NULL,
kind TEXT NOT NULL CHECK (kind IN ('schedule', 'mutate', 'complete', 'acknowledge')),
request_id TEXT NOT NULL,
input_sha256 TEXT NOT NULL CHECK (length(input_sha256) = 64),
checkpoint_id TEXT NOT NULL,
expected_graph_revision INTEGER NOT NULL CHECK (expected_graph_revision > 0),
result_graph_revision INTEGER NOT NULL CHECK (result_graph_revision > 0),
result_json TEXT NOT NULL DEFAULT '',
created_at_unix_ms INTEGER NOT NULL,
PRIMARY KEY (workspace_id, source_session_id, kind, issue_id, request_id),
UNIQUE (workspace_id, execution_id, kind, request_id),
FOREIGN KEY (workspace_id, execution_id, checkpoint_id)
REFERENCES workspace_tutti_execution_checkpoints(workspace_id, execution_id, checkpoint_id) ON DELETE CASCADE,
FOREIGN KEY (workspace_id, issue_id)
REFERENCES workspace_issues(workspace_id, issue_id) ON DELETE CASCADE
);
CREATE TABLE workspace_source_session_deletion_admissions (
workspace_id TEXT NOT NULL,
admission_id TEXT NOT NULL,
closure_sha256 TEXT NOT NULL CHECK (length(closure_sha256) = 64),
closure_json TEXT NOT NULL,
status TEXT NOT NULL CHECK (status IN ('prepared', 'admitted', 'superseded', 'released', 'finalized')),
protected_issue_ids_json TEXT NOT NULL DEFAULT '[]',
lease_owner TEXT NOT NULL DEFAULT '',
lease_expires_at_unix_ms INTEGER NOT NULL DEFAULT 0,
created_at_unix_ms INTEGER NOT NULL,
updated_at_unix_ms INTEGER NOT NULL,
finalized_at_unix_ms INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (workspace_id, admission_id),
UNIQUE (workspace_id, closure_sha256),
FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE
);
CREATE TABLE workspace_issue_run_launch_intents (
workspace_id TEXT NOT NULL,
issue_id TEXT NOT NULL,
task_id TEXT NOT NULL,
run_id TEXT NOT NULL,
launch_intent_id TEXT NOT NULL,
client_submit_id TEXT NOT NULL,
status TEXT NOT NULL CHECK (status IN ('prepared', 'leased', 'dispatched', 'failed', 'canceled')),
attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
lease_owner TEXT NOT NULL DEFAULT '',
lease_expires_at_unix_ms INTEGER NOT NULL DEFAULT 0,
canonical_session_id TEXT NOT NULL DEFAULT '',
canonical_turn_id TEXT NOT NULL DEFAULT '',
last_error TEXT NOT NULL DEFAULT '',
created_at_unix_ms INTEGER NOT NULL,
updated_at_unix_ms INTEGER NOT NULL,
dispatched_at_unix_ms INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (workspace_id, issue_id, task_id, run_id, launch_intent_id),
UNIQUE (workspace_id, client_submit_id),
UNIQUE (workspace_id, issue_id, task_id, run_id),
FOREIGN KEY (workspace_id, issue_id, task_id, run_id)
REFERENCES workspace_issue_runs(workspace_id, issue_id, task_id, run_id) ON DELETE CASCADE
);
CREATE INDEX idx_workspace_issue_run_launch_intents_due
ON workspace_issue_run_launch_intents(workspace_id, status, lease_expires_at_unix_ms);
INSERT INTO tuttid_schema_migrations (id, applied_at_unix_ms)
VALUES (?, ?)
`, schemaMigrationWorkspaceTuttiModeExecutionV1, unixMs(time.Now().UTC()))
if err != nil {
return fmt.Errorf("migrate workspace Tutti mode execution: %w", err)
}
if err := tx.Commit(); err != nil {
return fmt.Errorf("commit workspace Tutti mode execution migration: %w", err)
}
return nil
}
func (s *SQLiteStore) applyWorkspaceTuttiModeRunCancelCompensationV2(ctx context.Context) error {
applied, err := s.hasMigration(ctx, schemaMigrationWorkspaceTuttiModeRunCancelCompensationV2)
if err != nil || applied {
return err
}
tx, err := s.writeDB.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("begin Tutti mode Run cancel compensation migration: %w", err)
}
defer func() { _ = tx.Rollback() }()
if _, err := tx.ExecContext(ctx, `
CREATE TABLE workspace_issue_run_cancel_compensations (
workspace_id TEXT NOT NULL,
issue_id TEXT NOT NULL,
task_id TEXT NOT NULL,
run_id TEXT NOT NULL,
agent_session_id TEXT NOT NULL,
client_submit_id TEXT NOT NULL,
status TEXT NOT NULL CHECK (status IN ('prepared', 'leased', 'completed')),
attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0),
lease_owner TEXT NOT NULL DEFAULT '',
lease_expires_at_unix_ms INTEGER NOT NULL DEFAULT 0,
last_error TEXT NOT NULL DEFAULT '',
created_at_unix_ms INTEGER NOT NULL,
updated_at_unix_ms INTEGER NOT NULL,
completed_at_unix_ms INTEGER NOT NULL DEFAULT 0,
PRIMARY KEY (workspace_id, issue_id, task_id, run_id),
UNIQUE (workspace_id, client_submit_id),
FOREIGN KEY (workspace_id, issue_id, task_id, run_id)
REFERENCES workspace_issue_runs(workspace_id, issue_id, task_id, run_id) ON DELETE CASCADE
);
CREATE INDEX idx_workspace_issue_run_cancel_compensations_due
ON workspace_issue_run_cancel_compensations(
workspace_id, status, lease_expires_at_unix_ms
);
INSERT INTO tuttid_schema_migrations (id, applied_at_unix_ms)
VALUES (?, ?)
`, schemaMigrationWorkspaceTuttiModeRunCancelCompensationV2, unixMs(time.Now().UTC())); err != nil {
return fmt.Errorf("migrate Tutti mode Run cancel compensation: %w", err)
}
if err := tx.Commit(); err != nil {
return fmt.Errorf("commit Tutti mode Run cancel compensation migration: %w", err)
}
return nil
}
func (s *SQLiteStore) applyWorkspaceTuttiModeSourceActivityInboxV3(
ctx context.Context,
) error {
applied, err := s.hasMigration(
ctx, schemaMigrationWorkspaceTuttiModeSourceActivityInboxV3,
)
if err != nil || applied {
return err
}
tx, err := s.writeDB.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("begin Tutti mode source activity inbox migration: %w", err)
}
defer func() { _ = tx.Rollback() }()
if _, err := tx.ExecContext(ctx, `
CREATE TABLE workspace_tutti_source_activity_inbox (
mutation_id TEXT PRIMARY KEY,
transaction_id TEXT NOT NULL,
workspace_id TEXT NOT NULL,
agent_session_id TEXT NOT NULL,
entity_kind TEXT NOT NULL CHECK (entity_kind IN ('message', 'turn')),
entity_id TEXT NOT NULL,
entity_version INTEGER NOT NULL,
FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE CASCADE
);
CREATE INDEX idx_workspace_tutti_source_activity_inbox_scope
ON workspace_tutti_source_activity_inbox(
workspace_id, agent_session_id, entity_kind
);
INSERT INTO tuttid_schema_migrations (id, applied_at_unix_ms)
VALUES (?, ?)
`, schemaMigrationWorkspaceTuttiModeSourceActivityInboxV3,
unixMs(time.Now().UTC())); err != nil {
return fmt.Errorf("migrate Tutti mode source activity inbox: %w", err)
}
if err := tx.Commit(); err != nil {
return fmt.Errorf("commit Tutti mode source activity inbox migration: %w", err)
}
return nil
}
func (s *SQLiteStore) applyWorkspaceTuttiModeGoalReviewV4(ctx context.Context) error {
applied, err := s.hasMigration(ctx, schemaMigrationWorkspaceTuttiModeGoalReviewV4)
if err != nil || applied {
return err
}
tx, err := s.writeDB.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("begin Tutti mode Goal Review migration: %w", err)
}
defer func() { _ = tx.Rollback() }()
if _, err := tx.ExecContext(ctx, `
ALTER TABLE workspace_tutti_goal_reviews
ADD COLUMN client_submit_id TEXT NOT NULL DEFAULT '';
ALTER TABLE workspace_tutti_goal_reviews
ADD COLUMN attempt_count INTEGER NOT NULL DEFAULT 0 CHECK (attempt_count >= 0);
ALTER TABLE workspace_tutti_goal_reviews
ADD COLUMN lease_owner TEXT NOT NULL DEFAULT '';
ALTER TABLE workspace_tutti_goal_reviews
ADD COLUMN lease_expires_at_unix_ms INTEGER NOT NULL DEFAULT 0;
UPDATE workspace_tutti_goal_reviews
SET client_submit_id = 'tutti-goal-review:' || review_id,
review_session_id = CASE
WHEN review_session_id = '' THEN review_id || ':session'
ELSE review_session_id
END;
CREATE UNIQUE INDEX idx_workspace_tutti_goal_reviews_submit
ON workspace_tutti_goal_reviews(workspace_id, client_submit_id);
CREATE INDEX idx_workspace_tutti_goal_reviews_due
ON workspace_tutti_goal_reviews(
workspace_id, status, lease_expires_at_unix_ms
);
CREATE TABLE workspace_tutti_goal_review_audit (
workspace_id TEXT NOT NULL,
execution_id TEXT NOT NULL,
audit_id TEXT NOT NULL,
review_id TEXT NOT NULL DEFAULT '',
kind TEXT NOT NULL,
actor_id TEXT NOT NULL DEFAULT '',
reason TEXT NOT NULL DEFAULT '',
created_at_unix_ms INTEGER NOT NULL,
PRIMARY KEY (workspace_id, execution_id, audit_id),
FOREIGN KEY (workspace_id, execution_id)
REFERENCES workspace_tutti_executions(workspace_id, execution_id) ON DELETE CASCADE
);
CREATE TABLE workspace_tutti_goal_review_mutations (
workspace_id TEXT NOT NULL,
execution_id TEXT NOT NULL,
issue_id TEXT NOT NULL,
actor_id TEXT NOT NULL,
kind TEXT NOT NULL CHECK (kind IN ('complete', 'verdict', 'switch_to_self')),
request_id TEXT NOT NULL,
input_sha256 TEXT NOT NULL CHECK (length(input_sha256) = 64),
checkpoint_id TEXT NOT NULL,
expected_graph_revision INTEGER NOT NULL CHECK (expected_graph_revision > 0),
result_json TEXT NOT NULL,
created_at_unix_ms INTEGER NOT NULL,
PRIMARY KEY (workspace_id, actor_id, kind, issue_id, request_id),
UNIQUE (workspace_id, execution_id, kind, request_id),
FOREIGN KEY (workspace_id, execution_id, checkpoint_id)
REFERENCES workspace_tutti_execution_checkpoints(
workspace_id, execution_id, checkpoint_id
) ON DELETE CASCADE
);
INSERT INTO tuttid_schema_migrations (id, applied_at_unix_ms)
VALUES (?, ?)
`, schemaMigrationWorkspaceTuttiModeGoalReviewV4, unixMs(time.Now().UTC())); err != nil {
return fmt.Errorf("migrate Tutti mode Goal Review: %w", err)
}
if err := tx.Commit(); err != nil {
return fmt.Errorf("commit Tutti mode Goal Review migration: %w", err)
}
return nil
}