import type { Database } from "bun:sqlite"; import type { CreateWorkspaceInput, EventSource, JsonObject, Root, Workspace, WorkspaceIntegrations, WorkspaceKind, WorkspaceLock } from "../types/workspace.js"; import { type ConversationsChannelRunner, type ProjectChannelEnsureResult } from "./project-channel.js"; import { type WorkspaceRuntimeAction, type WorkspaceTmuxResult, type WorkspaceTmuxWindowSpec } from "./workspace-runtime.js"; export interface WorkspaceCreationPlanInput extends CreateWorkspaceInput { createDirectory?: boolean; requireAbsentDirectory?: boolean; gitInit?: boolean; writeMarker?: boolean; tmux?: { session?: string; windows?: WorkspaceTmuxWindowSpec[]; }; tmux_profile?: string; } export interface WorkspaceCreationPlanAction { type: "db" | "file" | "command" | "tmux" | "github" | "verification" | "rollback"; action: string; target: string; status: "planned"; metadata?: JsonObject; } export interface WorkspaceCreationCleanupAction extends Omit { status: "planned" | "completed" | "skipped" | "failed"; message?: string; } export interface WorkspaceCreationPlan { kind: "project_creation"; created_at: string; can_execute: boolean; warnings: string[]; workspace: Omit & { created_at: null; updated_at: null; last_opened_at: null; synced_at: null; }; workspace_input: CreateWorkspaceInput; locks: Array<{ key: string; reason: string; }>; db_writes: WorkspaceCreationPlanAction[]; runtime_actions: WorkspaceRuntimeAction[]; tmux: WorkspaceTmuxResult | null; commands: WorkspaceCreationPlanAction[]; github_operations: WorkspaceCreationPlanAction[]; verification_steps: WorkspaceCreationPlanAction[]; rollback_actions: WorkspaceCreationPlanAction[]; } export interface WorkspaceCreationExecution { dry_run: boolean; runtime_dry_run: boolean; success: boolean; plan: WorkspaceCreationPlan; workspace: Workspace | null; prepare: WorkspaceRuntimeAction[]; tmux: WorkspaceTmuxResult | null; channel: ProjectChannelEnsureResult | null; locks: WorkspaceLock[]; released_locks: string[]; rollback_actions: WorkspaceCreationPlanAction[]; } export interface WorkspaceCreationCleanupTarget { workspace_slug: string; primary_path?: string | null; rollback_actions: WorkspaceCreationPlanAction[]; } export interface WorkspaceCreationCleanup { dry_run: boolean; success: boolean; workspace_slug: string; primary_path: string | null; actions: WorkspaceCreationCleanupAction[]; errors: string[]; } export interface ExecuteWorkspaceCreationOptions { db?: Database; dryRun?: boolean; runtimeDryRun?: boolean; lockTtlSeconds?: number; /** Ensure the project's conversations channel exists after creation; defaults to shouldEnsureProjectChannel(). */ ensureChannel?: boolean; /** Conversations CLI runner override (used by tests). */ channelRunner?: ConversationsChannelRunner; /** * Store seam for the workspace-row insert. Callers route this through the * active ProjectStore so local creation touches the same seam as every other * command (never a direct sqlite write hoisted into the caller). Defaults to * the on-box `createWorkspace`. Machine-local runtime side effects * (directory/git/tmux/channel) below are intentionally NOT part of the seam. */ createProject?: (input: CreateWorkspaceInput) => Promise; /** Preserve the legacy creation_failed event by default; registration owns a separate immutable failure ledger. */ recordFailureEvent?: boolean; /** Preserve the legacy creation_executed event by default. */ recordExecutionEvent?: boolean; } export interface CleanupWorkspaceCreationOptions { db?: Database; dryRun?: boolean; agentId?: string; source?: EventSource; prompt?: string; command?: string; /** Preserve the legacy hard-delete event by default. */ recordDeletionEvent?: boolean; /** Preserve the legacy creation_cleanup_applied event by default. */ recordCleanupEvent?: boolean; } /** * Registry-level defaults for a new project: the canonical workspace path and * the slug-derived conversations channel. * * Extracted so local planning and the hosted backend PostgreSQL store compute them * identically. The server calls this only after allocating the exact persisted * slug; clients must not precompute slug-dependent values that the server would * then mistake for explicit operator choices. * * Both derivations are pure with respect to the registry: the path is a * function of the project id under `$HASNA_PROJECTS_HOME` (plus the root's * template when a root is given), and the channel is a function of slug and * kind. Neither needs the local database, which is what lets the api transport * call this too. */ export declare function deriveWorkspaceRegistryFields(input: Pick, context: { root: Root | null; slug: string; id: string; kind: WorkspaceKind; }): { primary_path: string | null; integrations: WorkspaceIntegrations; }; export declare function planWorkspaceCreation(input: WorkspaceCreationPlanInput, options?: { db?: Database; }): WorkspaceCreationPlan; export declare function cleanupWorkspaceCreationTarget(target: WorkspaceCreationCleanupTarget, options?: CleanupWorkspaceCreationOptions): WorkspaceCreationCleanup; export declare function cleanupWorkspaceCreation(plan: WorkspaceCreationPlan, options?: CleanupWorkspaceCreationOptions): WorkspaceCreationCleanup; export declare function executeWorkspaceCreation(input: WorkspaceCreationPlanInput, options?: ExecuteWorkspaceCreationOptions): Promise; //# sourceMappingURL=workspace-plan.d.ts.map