feat(boulder-state): add BoulderWorkState and timing fields to types

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
YeonGyu-Kim
2026-05-11 13:24:28 +09:00
parent 726c82e131
commit 246e0dca80
2 changed files with 124 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
import { describe, expect, test } from "bun:test"
import type {
BoulderSessionOrigin,
BoulderState,
BoulderTaskStatus,
BoulderWorkResumeOption,
BoulderWorkState,
BoulderWorkStatus,
PlanProgress,
TaskSessionState,
} from "./types"
describe("boulder-state types", () => {
test("keeps legacy BoulderState assignable while allowing v2 fields", () => {
// given
const legacyState: BoulderState = {
active_plan: "/tmp/plan.md",
started_at: "2026-01-01T00:00:00.000Z",
session_ids: ["ses_1"],
plan_name: "plan",
}
// when
const hasLegacyShape = legacyState.active_plan.length > 0
// then
expect(hasLegacyShape).toBe(true)
})
test("supports multi-work and timer fields", () => {
// given
const taskStatus: BoulderTaskStatus = "running"
const workStatus: BoulderWorkStatus = "active"
const origin: BoulderSessionOrigin = "direct"
const taskSession: TaskSessionState = {
task_key: "todo:1",
task_label: "1",
task_title: "Do work",
session_id: "ses_task",
started_at: "2026-01-01T00:00:00.000Z",
ended_at: "2026-01-01T00:00:01.000Z",
elapsed_ms: 1000,
status: taskStatus,
updated_at: "2026-01-01T00:00:01.000Z",
}
const work: BoulderWorkState = {
work_id: "plan-abc12345",
active_plan: "/tmp/plan.md",
plan_name: "plan",
status: workStatus,
started_at: "2026-01-01T00:00:00.000Z",
session_ids: ["ses_1"],
session_origins: { ses_1: origin },
task_sessions: { "todo:1": taskSession },
}
const progress: PlanProgress = { total: 2, completed: 1, isComplete: false }
const resumeOption: BoulderWorkResumeOption = {
work_id: work.work_id,
plan_name: work.plan_name,
active_plan: work.active_plan,
status: "paused",
started_at: work.started_at,
updated_at: "2026-01-01T00:00:02.000Z",
session_count: 1,
progress,
is_current_mirror: false,
}
// when
const combined = { taskSession, work, resumeOption }
// then
expect(combined.resumeOption.progress.total).toBe(2)
})
})
+46
View File
@@ -6,10 +6,17 @@
*/
export interface BoulderState {
schema_version?: 2
active_work_id?: string
works?: Record<string, BoulderWorkState>
/** Absolute path to the active plan file */
active_plan: string
/** ISO timestamp when work started */
started_at: string
ended_at?: string
elapsed_ms?: number
status?: BoulderWorkStatus
updated_at?: string
/** Session IDs that have worked on this plan */
session_ids: string[]
session_origins?: Record<string, "direct" | "appended">
@@ -23,6 +30,26 @@ export interface BoulderState {
task_sessions?: Record<string, TaskSessionState>
}
export type BoulderSessionOrigin = "direct" | "appended"
export type BoulderWorkStatus = "active" | "completed" | "paused" | "abandoned"
export type BoulderTaskStatus = "running" | "completed" | "cancelled"
export interface BoulderWorkState {
work_id: string
active_plan: string
plan_name: string
status?: BoulderWorkStatus
started_at: string
ended_at?: string
elapsed_ms?: number
updated_at?: string
session_ids: string[]
session_origins?: Record<string, BoulderSessionOrigin>
agent?: string
worktree_path?: string
task_sessions?: Record<string, TaskSessionState>
}
export interface PlanProgress {
/** Total number of checkboxes */
total: number
@@ -45,10 +72,29 @@ export interface TaskSessionState {
agent?: string
/** Category associated with the task session, when known */
category?: string
started_at?: string
ended_at?: string
elapsed_ms?: number
status?: BoulderTaskStatus
/** Last update timestamp */
updated_at: string
}
export interface BoulderWorkResumeOption {
work_id: string
plan_name: string
active_plan: string
worktree_path?: string
status: BoulderWorkStatus
started_at: string
updated_at: string
ended_at?: string
elapsed_ms?: number
session_count: number
progress: PlanProgress
is_current_mirror: boolean
}
export interface TopLevelTaskRef {
/** Stable identifier for the current top-level plan task */
key: string