Commit Graph

36 Commits

Author SHA1 Message Date
nntrivi2001 11b779479d fix: add missing copyright header to splitViewStorage.test.ts 2026-08-14 11:28:43 +07:00
nntrivi2001 18a1ecb6f9 feat(workspace): add localStorage helper for split-view layout state 2026-08-14 11:25:37 +07:00
nntrivi2001 b0bfc66d65 fix(workspace): auto-set cwd when a lane is selected from the strip
Selecting a lane card only updated selectedLaneId, leaving the run-setup
cwd field on whatever it was before — now selecting a lane also syncs
cwd to that lane's own working directory.
2026-08-13 13:55:51 +07:00
nntrivi2001 78fb82b257 fix(run): decode binary WS frames in TerminalView so pty output actually renders
Server streams PTY output as binary WS frames, but the browser's default
binaryType ("blob") handed onmessage a Blob that never matched the
`typeof === "string"` check — every keystroke response was silently
dropped and the terminal stayed blank despite the backend streaming
correctly (verified via a raw ws client against the live tmux session).
2026-08-13 13:54:19 +07:00
nntrivi2001 d581705eb0 fix(workspace): restore View button functionality and clean up dead props
Fix two issues identified in code review:

1. Critical: onViewFromHistory was a silent no-op. Now navigates to the
   SessionDetail page using the same route pattern as the external link in
   RunHistory, allowing users to view a finished run's transcript.

2. Important: Removed dead slashCommands={[]} prop from RunSetup invocation.
   Made slashCommands optional in RunSetupProps to maintain type safety while
   reflecting that the discovery logic was removed.

All tests pass (396 client, 1152 server).
2026-08-12 16:20:02 +07:00
nntrivi2001 cb8800fa31 fix(client): clean up leftover pre-TerminalView dead code and type errors in Workspace.tsx
`npm run test:client` (Vitest/esbuild) doesn't type-check, so several
tasks' incomplete cleanup of the old RunConsole-era code in
Workspace.tsx (SlashCommand/BUILTIN_SLASH_COMMANDS references, old
RunStatus values, a stray `mode` field, a wrong `prompt` vs
`initialPrompt` key) went unnoticed through every review until `tsc
--noEmit` was run directly. Also fixes a stale `RunStatusPayload.exitCode`
read in Tabby's brain.ts and dangling RunStreamPayload/RunInputAckPayload
references left in types.ts.
2026-08-12 16:09:43 +07:00
nntrivi2001 b951f64321 fix(run): plumb the recorded prompt back into live runs, fix lane routing when the cwd doesn't match the selected lane
- pty-run.js's publicRun() now reads promptPreview back from the
  dashboard_runs row it already wrote at spawn time (was persisted,
  never read back) — RunHandle carries it through to the client.
- Workspace.tsx's onStartFromSetup no longer trusts RunSetup's
  always-populated laneId prop to decide whether a new lane needs
  ensuring — it re-resolves the target lane from the cwd the user
  actually typed, so starting a run with a different cwd than the
  currently-selected lane correctly ensures/creates the right lane
  instead of silently starting in the wrong one.

Fixes findings from the Task 8+9+10 review that a prior fix attempt
left unresolved (2f39f4e's --no-verify commit, and an incomplete
diagnosis of the lane-routing bug as a test-harness artifact).
2026-08-12 13:18:04 +07:00
nntrivi2001 2f39f4ec98 feat(run): wire Workspace to TerminalView, delete the stream-json Run feature
Combines three tasks that couldn't land as separate commits: the
pre-commit hook's full test run crashes on any intermediate state
where Workspace.tsx still imports the files being deleted, so the
deletion (old RunConsole/useRunStream/run-spawner/stream-json-parser),
the RunSetup/RunHistory type adjustments, and this file's own
TerminalView wiring had to be staged together and committed as one
hook-passable unit.

- Delete RunConsole.tsx, useRunStream.ts, server/lib/run-spawner.js,
  server/lib/stream-json-parser.js and their tests (Task 8).
- Adjust RunSetup.tsx/RunHistory.tsx to the tmux-backed RunHandle/
  RunStartArgs/DashboardRunHistoryItem shapes, remove mode selection
  UI (Task 9).
- Swap Workspace.tsx's chat-bubble run console for TerminalView
  (xterm.js over /ws-pty/:runId), drop the stream-json envelope
  plumbing, update Start/Resume to the new RunStartArgs payload.
  Create onStartFromSetup handler to work with RunSetup's new callback
  shape. Remove mode state and related plumbing. Remove send/followUp
  state (no longer using old RunConsole chat interface).
- Add promptPlaceholderTerminal i18n key to support RunSetup's new
  placeholder text (Task 10).
- Update Workspace.test.tsx to mock TerminalView component.
- Regenerate screens.snapshot.test.tsx snapshot (only Workspace run
  panel changes: terminal container instead of chat bubbles).
2026-08-12 11:58:38 +07:00
nntrivi2001 24f13911fe feat(run): replace RunHandle/RunStartArgs types and api.run for the tmux backend 2026-08-12 10:24:45 +07:00
nntrivi2001 9b8d9bbe39 feat(run): add TerminalView xterm.js component for the PTY transport
- TerminalView.tsx: xterm.js component with WebSocket attachment to /ws-pty/:runId
- Test: validates WS connection URL, incoming terminal data, and outgoing keystrokes
- Added ResizeObserver stub to test-setup.ts for jsdom environment
2026-08-12 10:19:10 +07:00
nntrivi2001 d96d552428 chore: add node-pty/xterm deps, tmux in Docker, dashboard_runs.tmux_session column 2026-08-12 09:29:44 +07:00
nntrivi2001 7357070fb9 chore: remove unused desktop app, cloud deployment infra, and monitoring stack
Deletes desktop/ (Electron wrapper), deployments/ (Helm/Kustomize/
Terraform/CI for cloud deploy), and monitoring/ (Prometheus + Grafana
stack) along with DESKTOP.md, DEPLOYMENT.md, docker-compose.full.yml,
their npm scripts, and every dangling reference across README,
ARCHITECTURE, INSTALL, SETUP, docs/, and the repeated per-file
MODULE_GUIDE "Observability" boilerplate comment. The GET /api/metrics
endpoint itself is untouched — it's the dashboard's own route, not
part of the removed monitoring stack.
2026-08-11 12:16:54 +07:00
nntrivi2001 f0ae876472 feat(lanes): add pipeline-template picker to the Workspace lane header
Lets a lane's pipeline template be switched live from the dashboard
(the same PATCH /api/lanes/:id the CLI's `ccam lanes pipeline` uses),
so lanes created before the picker shipped don't need the terminal.
Both ship-feature skills now force their own template before their
first `ccam stage` call, so the human never has to pick correctly at
lane creation.
2026-08-11 12:15:16 +07:00
nntrivi2001 201eae68bb fix(client): repair the TypeScript build
`npm run build` runs `tsc -b` first and it has been failing: `api.ts` used
`NamedLock` without importing it, and four lane test fixtures predate
`Lane.active_feature_id` / the widened `LaneRuntime`, so spreading a
`Partial<Lane>` over them no longer satisfied the required fields.

Nothing shipped could be rebuilt while this was red, which is how a client
change reaches a dashboard running in production mode. The fixture fixes are
casts with a note, not type relaxations — the base literals still list every
required field, so the assertion states what they already prove.
2026-08-07 09:52:13 +07:00
nntrivi2001 8fcef5a10b feat(lanes): let Add Lane choose the pipeline template
Creation is the only point the UI could ever set a lane's template, and it
never offered the choice — so every lane added from "+ Add lane" was born
on `default` and rendered an 8-node map for a 16-node workflow, with no
screen able to change it afterwards. That is the defect that made the
ship-feature template unreachable from the browser.

The modal now shows a *Pipeline template* select fed by
`GET /api/lanes/pipelines`, labelled with each template's node count so the
consequence of the choice is visible. A failed fetch degrades to a `default`
option rather than blocking lane creation.

`pipeline` was already accepted by `POST /api/lanes` but silently dropped by
`/ensure` and `/worktree`, which build their own createLane payloads; both
now pass it through, and both map `EBADPIPELINE` to 400 like `EBADCWD`.
2026-08-07 09:44:48 +07:00
nntrivi2001 87b5e1c3db fix(lanes): make Add Lane mode segments fill their row and read as selected
The two-way segment used a translucent accent wash for the active state,
which at this size read as a hover tint rather than a selection. Solid
accent plus a shadow makes the choice unambiguous, and `flex-1` stops the
two segments from sizing to their label text.
2026-08-07 09:29:59 +07:00
nntrivi2001 bd829ba1c3 fix(lanes): capitalize Vietnamese action-button labels, gitignore .ccam/
action.start/stop/clear/forget/purge/remove/reset in lanes.json (vi)
were lowercase (bắt đầu, dừng...) while every other button label in the
app capitalizes its first letter. Also gitignore /.ccam/ - the local
lane profile that appears in a repo's own working tree only when that
repo is adopted as its own lane (machine-specific runtime config, not
source).
2026-08-06 16:14:55 +07:00
nntrivi2001 78f6e1be8e feat(lanes): Add Lane repo/worktree mode toggle, manual branch, folder browse
- Repo mode adopts a directory as-is via /lanes/ensure (no worktree, no
  branch fields) - the right choice for a main repo you want stage
  detection on. Worktree mode (default) keeps the existing provisioning
  flow but now requires a manually-typed branch name instead of deriving
  one from the title.
- POST /lanes/worktree accepts an optional `branch`, validated via
  `git check-ref-format --branch`; omitting it preserves the CLI's
  existing auto-derived-branch behavior.
- New GET /lanes/browse lists a directory's immediate subdirectories,
  backing a small folder-browse modal on both path fields - browsers
  cannot expose an absolute path from a native picker, so this is
  server-backed instead, consistent with the tool's local-first model.
2026-08-06 16:03:49 +07:00
nntrivi2001 9f13769fb4 feat(lanes): surface child worktrees on a lane card + detect Superpowers skills
Adopting the main repo as its own lane now gets stage detection
(cwd matches, same as any other lane), and its card lists every
managed-worktree lane provisioned from it with a jump-to link.
Also add the two missing Skill-tool detect rules (implement, ship)
so detection covers all four Superpowers workflow phases, not just
plan/review.
2026-08-06 15:33:07 +07:00
nntrivi2001 54299f119e fix(lanes): wait for worktree provisioning before auto-setup
POST /worktree answers with 202 before the background git worktree
add finishes, so profileInit/agentsInstall/mcpSync were racing the
lane's own directory into existence and mostly failing. Poll
GET /api/lanes/:id until provisioning leaves "provisioning" first.
2026-08-06 14:28:21 +07:00
nntrivi2001 e31d261fd7 fix(lanes): don't auto-close Add Lane modal after setup summary
The 3s auto-close timer closed before a user reasonably had time to
look at the setup results, making the feature appear to do nothing.
Require an explicit dismiss (Cancel/X) instead.
2026-08-06 13:55:43 +07:00
nntrivi2001 7fa39687fe feat(lanes): show Add Lane auto-setup summary before closing modal
The three setup calls (profile/agents/mcp) fired after worktree
creation but their outcome was only logged to the console. Keep the
modal open with a ✓/✗ summary for a few seconds (or until dismissed)
so the user actually sees what happened, matching the original F5 design.
2026-08-06 13:31:56 +07:00
nntrivi2001 dd0cb4ad7c feat(lanes): auto-setup (profile/agents/mcp) after Add Lane (F5) 2026-08-06 11:49:11 +07:00
nntrivi2001 14dbfa73e5 test(lanes): cover F4's LaneCard additions + regenerate screens snapshot 2026-08-06 10:30:17 +07:00
nntrivi2001 57dd4ffcb7 feat(lanes): add Lanes section (skills install, housekeeping) to Settings (F4) 2026-08-06 10:22:58 +07:00
nntrivi2001 6d8c5399ea feat(lanes): add agents-install/mcp-sync/integration/sync-check to LaneCard (F4) 2026-08-06 09:59:33 +07:00
nntrivi2001 bc7c5e5431 feat(lanes): add client API methods for F4 lane actions (F4) 2026-08-06 09:47:10 +07:00
nntrivi2001 6cb5fb356c fix(lanes): make proof gallery test assertion actually fail on missing panel 2026-08-04 16:34:44 +07:00
nntrivi2001 fccfa5ad17 feat(lanes): show proof gallery panel in the Workspace page (C) 2026-08-04 16:25:09 +07:00
nntrivi2001 3a83e849cf feat(lanes): add a read-only feature picker to the Workspace page (B) 2026-08-04 15:00:41 +07:00
nntrivi2001 c068f0cac6 style(i18n): restore literal UTF-8 chars in lanes.json locale files
The lock-indicator commit's JSON edit re-serialized both files through
something that escaped every non-ASCII character (—, …, ·, ▶, ■) as
\uXXXX, touching ~180 unrelated lines for a two-key addition. No
functional change (JSON \u escapes are semantically identical) — just
restoring the literal-character convention every other locale file uses.
2026-08-04 11:37:18 +07:00
nntrivi2001 1f3a5ff51d feat(locks): show a lock indicator on the lane card (D) 2026-08-04 11:32:34 +07:00
nntrivi2001 4d9a385c5e feat(lanes): lane runtime UI, docs, and env additions (A1+A2)
Client-side rendering for the per-lane runtime facts (slot, ports,
database, Redis index, service liveness) added in the server-side
A1/A2 work, plus the doc updates (README, CLAUDE.md, docs/API.md,
client/server READMEs) describing the new profile.env keys, hook
environment contract, and REST endpoints.
2026-08-04 10:04:58 +07:00
nntrivi2001 b673363351 feat(theme): dark/light mode with a Radix Colors-based palette
Adds a working Dark/Light toggle (next to the language switcher, same row
as EN/VI) and re-themes the whole dashboard, not just the handful of
components that already used semantic tokens.

- Tailwind darkMode:"class" + CSS-variable color tokens (client/src/index.css,
  tailwind.config.js): surface.0-5, border/border-light, accent/accent-hover,
  fg.primary/secondary/muted, status.success/danger/warning. One class flip
  on <html> re-themes everything — no per-element dark: variant pairs.
- useTheme() hook: localStorage-persisted, defaults to dark, no
  prefers-color-scheme fallback (client/src/hooks/useTheme.ts).
- Mechanical, table-driven migration (scripts/migrate-color-tokens.mjs,
  scripts/tokenize-status-colors.mjs, scripts/darken-status-colors.mjs) of
  every raw neutral/gray/slate + emerald/red/amber Tailwind utility across
  client/src onto the new tokens, so every badge/button/component pulls the
  same shade per status/role instead of each picking its own.
- Palette values are the literal Radix Colors (radix-ui.com/colors) scale
  constants — slate/blue/green/red/amber steps 1-12 — adopted after three
  rounds of hand-picked values that kept overshooting (flat, then too dark,
  then glaring); see docs/superpowers/specs/2026-07-31-color-redesign-
  dark-light-mode-design.md for the full history and role mapping.
- PipelineMap: done/current/failed/passed-no-evidence/detected share one
  visual language (border + text + translucent wash of the same status
  color); `current` alone stays a solid accent fill, the one state that
  gets to look bolder ("you are here").
- LaneCard: removed the stage/kind/auto-stage chips that duplicated the
  Workspace lane-detail header already showing them.

Categorical/decorative hues (violet, indigo, cyan, teal, sky, rose, pink,
orange, yellow, and blue where it plays a role-coloring part e.g. message
bubbles) are deliberately out of scope — collapsing those onto shared
tokens would erase the distinction between different kinds of thing, not
a status.
2026-07-31 10:54:31 +07:00
nntrivi2001 4905d63b97 fix(lanes): clear stale detection on real stage transitions, exclude scratch dirs from implement detect
setStage() left detected_stage/signal/at untouched across a real transition,
so a prior task's leftover inference (e.g. `tests` from earlier work) both
misrepresented a fresh task's progress and — because recordDetection is
forward-only — silently rejected every real detection behind it until the
old one aged past DETECTION_TTL_MS. A real stage change now clears the
detection columns; a same-stage heartbeat leaves a live detection alone.

Also excludes `.superpowers/` from the `implement` node's Write detect rule
- brainstorm-companion scratch files were being counted as implementation
work.

fix(client): disable Node's default --experimental-webstorage in tests

Node 25 enables --experimental-webstorage by default, which defines a
broken global `localStorage` (no backing file configured) ahead of jsdom's
own full polyfill. Every test touching real localStorage failed with
"localStorage.clear/getItem is not a function" — not flaky, not test-specific,
just this one Node default. NODE_OPTIONS=--no-experimental-webstorage on the
test scripts lets jsdom's polyfill take over as before.
2026-07-31 10:53:07 +07:00
nntrivi2001 57dc91585d feat: Claude Code Monitor — lanes, pipelines and a merged workspace
Internal SmartGift build of a Claude Code monitoring dashboard.

Lanes: a durable unit of parallel agent work, one per working directory,
tracked across session restarts. Managed lanes are git worktrees the
dashboard provisions and can reset or remove behind a three-check destroy
guard and a counted preflight; adopted lanes are directories you already
own and are never destroyable.

Pipelines: a lane moves through pipeline stages. A stage the agent declares
with evidence renders green; a stage inferred from the tool-event stream
renders dashed amber and never counts as done. Detection is forward-only
within a 30-minute window, and never writes the declared stage.

Workspace: one page at /run with a lane grid, the selected lane's pipeline,
and a full Claude console behind a disclosure.
2026-07-30 14:39:03 +07:00