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:
@@ -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)
|
||||
})
|
||||
})
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user