{"version":3,"file":"task-space.cli.mjs","names":[],"sources":["../../../../../../../../src/extensions/workspaces/sessions/(frontend)/overlay/_lib/task-space.cli.ts"],"sourcesContent":["/**\n * Task Space: the `SPC t l` overlay.\n *\n * The task list and detail pane render from plain values so the whole surface\n * can be asserted as text without a live terminal.\n *\n * The overlay reads the store on every render rather than caching rows, so an\n * external write by a delegated child shows up without closing the overlay.\n *\n * Every commit it makes is a single-entry `upsert` that carries the selected\n * task's id. That id is what keeps creating a task a tool-only path: an entry\n * without one would create rather than be rejected.\n */\n\nimport { homedir } from 'node:os';\n\nimport {\n  DOOM_FULLSCREEN_UI_OPTIONS,\n  DOOM_OVERLAY_ACCENT,\n  DoomOverlay,\n  type DoomOverlayChrome,\n  type DoomOverlayTui,\n} from '@agimon-ai/doompi-ui/doom-overlay';\nimport { fitStyledLine } from '@agimon-ai/doompi-ui/rendering';\nimport type { ExtensionContext, Theme } from '@earendil-works/pi-coding-agent';\nimport { matchesKey, truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nimport type { Task, TaskItemMutation } from '../../../../../../models/task';\nimport { isBlocked } from '../../../../../../models/taskGraph';\nimport { MSG_NO_TASKS, TASK_STATUSES } from '../../../../../../schemas/task';\nimport { applyTaskMutation, isCommittingOp, type Op, singleItemOutcome } from '../../../../../../services/reducer';\nimport type { TaskStore } from '../../../../../../services/taskStore';\nimport { overlayStatusGlyph, STATUS_LABEL } from '../../_shared/format.cli';\nimport { countTasks, visibleTasks } from '.././_lib/selectors';\n\nexport const TASK_SPACE_OVERLAY_OPTIONS = DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions;\n\nexport interface TaskSpaceOptions {\n  store: TaskStore;\n}\n\ntype EditMode = 'browse' | 'status' | 'subject';\n\nconst KEY_BACKSPACE = '\\x7f';\nconst KEY_ENTER = '\\r';\nconst KEY_NEWLINE = '\\n';\nconst FIRST_PRINTABLE_CODE_POINT = 0x20;\nconst DELETE_CODE_POINT = 0x7f;\n\n/**\n * Keystrokes that carry no text: escape sequences, control keys, delete.\n * Indexed rather than iterated so surrogate pairs stay intact; both halves sit\n * far above the control range, so no emoji is ever mistaken for one.\n */\nfunction isControlInput(data: string): boolean {\n  for (let index = 0; index < data.length; index++) {\n    const code = data.charCodeAt(index);\n    if (code < FIRST_PRINTABLE_CODE_POINT || code === DELETE_CODE_POINT) return true;\n  }\n  return false;\n}\n\n/**\n * Store path for the list heading: home collapses to `~`, and an over-long path\n * loses leading segments rather than its tail, because the file name identifies\n * the store while `/var/folders/...` does not.\n */\nfunction storeLabel(storePath: string, width: number): string {\n  const home = homedir();\n  const abbreviated = home && storePath.startsWith(home) ? `~${storePath.slice(home.length)}` : storePath;\n  if (visibleWidth(abbreviated) <= width) return abbreviated;\n\n  const segments = abbreviated.split('/');\n  let tail = segments.pop() ?? abbreviated;\n  while (segments.length > 0) {\n    const candidate = `${segments[segments.length - 1]}/${tail}`;\n    if (visibleWidth(`…/${candidate}`) > width) break;\n    tail = candidate;\n    segments.pop();\n  }\n  return truncateToWidth(`…/${tail}`, width, '');\n}\n\n/** Neither palette name is exported, so take both from the theme's methods. */\ntype ThemeBg = Parameters<Theme['bg']>[0];\ntype ThemeColor = Parameters<Theme['fg']>[0];\n\n/** Each task occupies a heading row and a metadata row beneath it. */\nconst ROWS_PER_TASK = 2;\n/** Hanging indent for the metadata row: clears marker, glyph and id. */\nconst META_INDENT = 6;\n\nconst MIN_WIDTH = 48;\n/** A third for the list, two thirds for the task being read or edited. */\nconst LIST_PANE_RATIO = 1 / 3;\n/** One blank column each side of the pane divider so neither column touches it. */\nconst PANE_GUTTER = 1;\nconst MIN_PANE_WIDTH = 18;\nconst SELECTION_MARKER = '›';\nconst CURRENT_MARKER = '▸';\nconst CURSOR_BLOCK = '█';\nconst ELLIPSIS = '…';\nconst NO_VALUE = 'none';\n\nconst TITLE = 'TASK SPACE';\nconst BREADCRUMB = 'SPC › t › t / tasks';\n/** Key/label pairs rendered as capped keys, matching the mockup's footer. */\nconst LIST_HINTS: readonly (readonly [string, string])[] = [\n  ['↑↓', 'select'],\n  ['enter', 'edit subject'],\n  ['s', 'status'],\n  ['esc', 'close'],\n];\nconst LIST_HEADER_RIGHT = 'esc close';\nconst STATUS_HINT = 'STATUS   s cycles · enter commits';\nconst SUBJECT_HINT = 'SUBJECT  enter commits · esc cancels';\nfunction fitRow(text: string, width: number): string {\n  return fitStyledLine(text, width, ELLIPSIS);\n}\n\nfunction rightAligned(left: string, right: string, width: number): string {\n  const rightWidth = visibleWidth(right);\n  const leftWidth = Math.max(0, width - rightWidth - 1);\n  return fitRow(left, leftWidth) + ' '.repeat(Math.max(1, width - leftWidth - rightWidth)) + fitRow(right, rightWidth);\n}\n\nfunction wrap(text: string, width: number): string[] {\n  if (width <= 0) return [];\n  const lines: string[] = [];\n  let current = '';\n  for (const word of text.split(/\\s+/).filter(Boolean)) {\n    if (current.length === 0) current = word;\n    else if (current.length + 1 + word.length <= width) current += ` ${word}`;\n    else {\n      lines.push(current);\n      current = word;\n    }\n  }\n  if (current.length > 0) lines.push(current);\n  return lines;\n}\n\n/**\n * Task Space overlay component.\n *\n * Rendering is pure: `render(width)` reads the live store and returns lines with\n * no side effects, so the fidelity job can capture it and unit tests can assert on it.\n */\nexport class TaskSpaceComponent extends DoomOverlay {\n  private readonly options: TaskSpaceOptions;\n  private readonly done: (result: undefined) => void;\n  private readonly unwatch: () => void;\n\n  private mode: EditMode = 'browse';\n  private selected = 0;\n  private statusIndex = 0;\n  private draft = '';\n  private notice: string | undefined;\n  private bodyHeight = 1;\n\n  constructor(tui: DoomOverlayTui, theme: Theme, options: TaskSpaceOptions, done: (result: undefined) => void) {\n    super(tui, theme);\n    this.options = options;\n    this.done = done;\n    this.unwatch = options.store.onExternalChange(() => this.tui.requestRender());\n  }\n\n  private tasks(): Task[] {\n    return visibleTasks(this.options.store.snapshot.tasks);\n  }\n\n  private selectedTask(): Task | undefined {\n    const tasks = this.tasks();\n    if (tasks.length === 0) return undefined;\n    return tasks[Math.min(this.selected, tasks.length - 1)];\n  }\n\n  private move(delta: number): void {\n    const tasks = this.tasks();\n    if (tasks.length === 0) return;\n    this.selected = Math.max(0, Math.min(tasks.length - 1, this.selected + delta));\n    this.tui.requestRender();\n  }\n\n  /** Commits through the same reducer the task tool uses, so both paths share every invariant. */\n  private commit(item: TaskItemMutation): void {\n    this.options.store\n      .mutate<Op>((document) => {\n        const result = applyTaskMutation(document, 'upsert', { tasks: [item] });\n        // A rejected mutation must not reach the writer: committing it would\n        // bump `rev` for an edit that never happened.\n        if (!isCommittingOp(result.op)) return { value: result.op };\n        return { document: result.document, value: result.op };\n      })\n      .then((outcome) => {\n        // The reducer's message is unprefixed, so the notice reads\n        // \"subject must not be blank\" rather than \"item[0] failed: ...\".\n        const single = singleItemOutcome(outcome.value);\n        this.notice = single?.kind === 'failed' ? single.message : undefined;\n        this.tui.requestRender();\n      })\n      .catch((error: unknown) => {\n        // Shown in the overlay rather than swallowed: a rejected write means the\n        // edit the operator just made never landed.\n        this.notice = error instanceof Error ? error.message : String(error);\n        this.tui.requestRender();\n      });\n  }\n\n  private handleStatusInput(data: string): void {\n    const task = this.selectedTask();\n    if (matchesKey(data, 'up')) this.statusIndex = Math.max(0, this.statusIndex - 1);\n    else if (matchesKey(data, 'down')) this.statusIndex = Math.min(TASK_STATUSES.length - 1, this.statusIndex + 1);\n    else if (data === 's') this.statusIndex = (this.statusIndex + 1) % TASK_STATUSES.length;\n    else if (data === KEY_ENTER || data === KEY_NEWLINE) {\n      this.mode = 'browse';\n      if (task) this.commit({ id: task.id, status: TASK_STATUSES[this.statusIndex] });\n    } else if (matchesKey(data, 'escape')) this.mode = 'browse';\n    this.tui.requestRender();\n  }\n\n  private handleSubjectInput(data: string): void {\n    const task = this.selectedTask();\n    if (data === KEY_ENTER || data === KEY_NEWLINE) {\n      this.mode = 'browse';\n      if (task) this.commit({ id: task.id, subject: this.draft });\n    } else if (matchesKey(data, 'escape')) this.mode = 'browse';\n    else if (data === KEY_BACKSPACE) this.draft = this.draft.slice(0, -1);\n    else if (!isControlInput(data)) this.draft += data;\n    this.tui.requestRender();\n  }\n\n  handleInput(data: string): void {\n    if (this.mode === 'status') {\n      this.handleStatusInput(data);\n      return;\n    }\n    if (this.mode === 'subject') {\n      this.handleSubjectInput(data);\n      return;\n    }\n\n    if (matchesKey(data, 'escape') || matchesKey(data, 'ctrl+c')) {\n      this.done(undefined);\n      return;\n    }\n    if (matchesKey(data, 'up')) {\n      this.move(-1);\n      return;\n    }\n    if (matchesKey(data, 'down')) {\n      this.move(1);\n      return;\n    }\n\n    const task = this.selectedTask();\n    if (!task) return;\n    if (data === 's') {\n      this.mode = 'status';\n      this.statusIndex = Math.max(0, TASK_STATUSES.indexOf(task.status));\n      this.tui.requestRender();\n      return;\n    }\n    if (data === KEY_ENTER || data === KEY_NEWLINE) {\n      this.mode = 'subject';\n      this.draft = task.subject;\n      this.tui.requestRender();\n    }\n  }\n\n  /**\n   * A padded, background-filled chip. Foreground is applied inside the fill so\n   * the colour closes with it, rather than a reset stripping the background\n   * partway through the label.\n   */\n  private badge(text: string, background: ThemeBg, colour: ThemeColor = 'text'): string {\n    return this.theme.bg(background, this.theme.fg(colour, ` ${text} `));\n  }\n\n  /** Footer hints as capped keys: `[ enter ] edit subject`, per the mockup. */\n  private hintLine(hints: readonly (readonly [string, string])[]): string {\n    return hints\n      .map(([key, label]) => `${this.badge(key, 'selectedBg')}${this.theme.fg('dim', ` ${label}`)}`)\n      .join(this.theme.fg('dim', '   '));\n  }\n\n  private listLines(width: number): string[] {\n    const tasks = this.tasks();\n    const label = this.theme.bold('TASKS');\n    const pathWidth = Math.max(0, width - visibleWidth('TASKS') - 2);\n    const lines = [`${label}  ${this.theme.fg('dim', storeLabel(this.options.store.storePath, pathWidth))}`, ''];\n    if (tasks.length === 0) {\n      lines.push(this.theme.fg('dim', MSG_NO_TASKS));\n      return lines;\n    }\n\n    // Two rows per task: at a third of the width a single row left the subject\n    // with a handful of columns once owner and state took their share.\n    const budget = Math.max(1, Math.floor((this.bodyHeight - lines.length) / ROWS_PER_TASK));\n    const start = Math.max(0, Math.min(this.selected - budget + 1, Math.max(0, tasks.length - budget)));\n    for (const [offset, task] of tasks.slice(start, start + budget).entries()) {\n      const index = start + offset;\n      const active = index === Math.min(this.selected, tasks.length - 1);\n      const marker = active ? this.theme.fg('accent', SELECTION_MARKER) : ' ';\n      const subject = active ? this.theme.bold(task.subject) : task.subject;\n      const glyph = overlayStatusGlyph(task.status, this.theme);\n      const owner = task.owner ?? task.delegation?.agent ?? NO_VALUE;\n      const blocked = task.status === 'pending' && isBlocked(this.options.store.snapshot.tasks, task);\n      const state = blocked\n        ? this.theme.fg('warning', `blocked by ${(task.blockedBy ?? []).map((id) => `#${id}`).join(', ')}`)\n        : this.theme.fg('dim', STATUS_LABEL[task.status]);\n      // Subject owns the first row outright; the metadata hangs under it.\n      const heading = `${marker} ${glyph} ${this.theme.fg('dim', `#${task.id}`)} ${subject}`;\n      const meta = `${' '.repeat(META_INDENT)}${this.badge(owner, 'userMessageBg', 'muted')} ${state}`;\n      // Every task sits on a band, the selected one a shade lighter, as in the\n      // mockup; the marker stays so selection survives themes with no background.\n      const background: ThemeBg = active ? 'selectedBg' : 'userMessageBg';\n      for (const row of [heading, meta]) {\n        lines.push(this.theme.bg(background, fitRow(row, width)));\n      }\n    }\n    return lines;\n  }\n\n  private statusLines(task: Task, width: number): string[] {\n    if (this.mode !== 'status') {\n      const glyph = overlayStatusGlyph(task.status, this.theme);\n      return [this.theme.fg('dim', 'STATUS'), `${glyph} ${STATUS_LABEL[task.status]}`];\n    }\n    // Editing draws the picker as a filled panel, so the whole option list reads\n    // as one surface rather than five loose rows.\n    const lines = [this.theme.fg('dim', STATUS_HINT)];\n    for (const [index, status] of TASK_STATUSES.entries()) {\n      const selected = index === this.statusIndex;\n      const marker = selected ? this.theme.fg('accent', CURRENT_MARKER) : ' ';\n      const label = selected ? this.theme.bold(this.theme.fg('accent', status)) : this.theme.fg('muted', status);\n      const current = status === task.status ? this.theme.fg('dim', 'current') : '';\n      const row = rightAligned(`  ${marker} ${label}`, current, width);\n      lines.push(this.theme.bg(selected ? 'selectedBg' : 'userMessageBg', row));\n    }\n    return lines;\n  }\n\n  /** The subject as an input: a filled field with a caret, as in the mockup. */\n  private subjectField(task: Task, width: number): string[] {\n    const editing = this.mode === 'subject';\n    const value = editing ? `${this.draft}${CURSOR_BLOCK}` : task.subject;\n    return [\n      this.theme.fg('dim', editing ? SUBJECT_HINT : 'SUBJECT'),\n      this.theme.bg(editing ? 'selectedBg' : 'userMessageBg', fitRow(` ${value}`, width)),\n    ];\n  }\n\n  private detailLines(width: number): string[] {\n    const task = this.selectedTask();\n    if (!task) return [this.theme.fg('dim', 'No task selected')];\n\n    const editing = this.mode === 'subject' || this.mode === 'status';\n    const badge = editing ? this.badge('EDIT', 'toolSuccessBg', 'warning') : '';\n    const lines = [rightAligned(this.theme.bold(this.theme.fg('accent', `TASK #${task.id}`)), badge, width), ''];\n    lines.push(...this.subjectField(task, width));\n    lines.push('', ...this.statusLines(task, width), '');\n\n    if (task.activeForm) lines.push(this.theme.fg('dim', 'ACTIVE FORM'), task.activeForm, '');\n    const owner = task.owner ?? task.delegation?.agent ?? NO_VALUE;\n    const delegated = task.delegation?.runId ? this.theme.fg('success', `delegated run ${task.delegation.runId}`) : '';\n    lines.push(\n      this.theme.fg('dim', 'OWNER'),\n      delegated ? `${owner}   ${this.theme.fg('dim', '·')}   ${delegated}` : owner,\n      '',\n    );\n    lines.push(\n      this.theme.fg('dim', 'BLOCKED BY'),\n      task.blockedBy?.length ? task.blockedBy.map((id) => `#${id}`).join(' · ') : NO_VALUE,\n    );\n    if (task.description) lines.push('', this.theme.fg('dim', 'DESCRIPTION'), ...wrap(task.description, width));\n    if (this.notice) lines.push('', this.theme.fg('error', this.notice));\n    return lines;\n  }\n\n  private headerSummary(): string {\n    const counts = countTasks(this.options.store.snapshot.tasks);\n    const summary = [`${counts.completed}/${counts.total} completed`];\n    if (counts.inProgress > 0) summary.push(`${counts.inProgress} in progress`);\n    if (counts.blocked > 0) summary.push(`${counts.blocked} blocked`);\n    if (counts.failed > 0) summary.push(`${counts.failed} failed`);\n    return summary.join(' · ');\n  }\n\n  protected getChrome(): DoomOverlayChrome {\n    return {\n      title: TITLE,\n      accent: DOOM_OVERLAY_ACCENT,\n      breadcrumb: BREADCRUMB,\n      headerRight: `${this.headerSummary()} · ${LIST_HEADER_RIGHT}`,\n      footer: this.hintLine(LIST_HINTS),\n    };\n  }\n\n  protected renderBody(width: number, height: number): string[] {\n    this.bodyHeight = height;\n    if (width < MIN_WIDTH) return this.renderStacked(width, height);\n\n    const leftWidth = Math.max(MIN_PANE_WIDTH, Math.floor((width - 1) * LIST_PANE_RATIO));\n    const rightWidth = Math.max(1, width - leftWidth - 1);\n    // Each column gives up one column to the gutter, so content never abuts the\n    // divider: a long store path used to run straight into the detail heading.\n    const leftContent = Math.max(1, leftWidth - PANE_GUTTER);\n    const rightContent = Math.max(1, rightWidth - PANE_GUTTER);\n    const left = this.listLines(leftContent);\n    const right = this.detailLines(rightContent);\n\n    const divider = this.theme.fg('borderMuted', '│');\n    return Array.from({ length: height }, (_, index) => {\n      const row = `${fitRow(left[index] ?? '', leftContent)} ${divider} ${fitRow(right[index] ?? '', rightContent)}`;\n      return truncateToWidth(row, width, ELLIPSIS);\n    });\n  }\n\n  private renderStacked(width: number, height: number): string[] {\n    const topHeight = Math.max(1, Math.floor((height - 1) / 2));\n    const bottomHeight = Math.max(0, height - topHeight - 1);\n    this.bodyHeight = topHeight;\n    const top = this.listLines(width);\n    const bottom = this.detailLines(width);\n    return [\n      ...top.slice(0, topHeight),\n      ...Array.from({ length: Math.max(0, topHeight - top.length) }, () => ''),\n      this.theme.fg('borderMuted', '─'.repeat(width)),\n      ...bottom.slice(0, bottomHeight),\n    ];\n  }\n\n  dispose(): void {\n    this.unwatch();\n  }\n}\n\nexport async function openTaskSpace(ctx: ExtensionContext, options: TaskSpaceOptions): Promise<void> {\n  await ctx.ui.custom<undefined>(\n    (tui, theme, _keybindings, done) => new TaskSpaceComponent(tui, theme, options, done),\n    DOOM_FULLSCREEN_UI_OPTIONS,\n  );\n}\n\nexport default openTaskSpace;\n"],"mappings":"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"}