a /invoices workspace screen replicating the parts of the invoiceshelf web ui
that are actually used: dashboard, invoices, estimates, recurring invoices,
payments, expenses, customers, items and reports.
one document editor serves invoices, estimates and recurring invoices — they
share the line-item table, the discounts, the taxes and the totals, and differ
only in a header strip. the arithmetic is a port of upstream's
use-document-calculations, rounding points included, because the server
re-validates the totals it is sent. money is integer minor units throughout and
is converted to major units at the edges only.
selection and editor state live in the url (`/invoices/:section`, `?selected=`,
`?edit=`), so the nav highlight is derived rather than held, back closes an
editor instead of leaving the screen, and a half-written form survives a reload.
sending a document is behind an explicit confirmation — it emails the customer.
built against the running 2.4.2 instance rather than the 3.0 checkout in
_references; the two differ materially. typechecked, not yet exercised in a
browser.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
officer-transmission is a new pm2 peer that owns the transmission rpc
connection and exposes a curated /_officer/* contract instead of proxying
raw rpc. it absorbs the three quirks callers otherwise have to know about:
the 409 x-transmission-session-id handshake, failures returned as
{"result": "..."} inside http 200, and basic auth where an empty username
must send no header at all.
/transmission is the ui, on the workspace/panel framework: a filter nav and
three sections (torrents, stats, settings). the torrent list is virtualised
with 30 available columns, multi-select, and a right-click menu; the detail
pane covers general, files as a real tree, peers and trackers. filters and
the open torrent live in the url, so a filtered view is a link.
phase 1 goal was parity with _references/transmission-web. follow-up work is
recorded in TODO.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
officer-headscale owns the whole Headscale contract: the registered servers and
their admin api keys, the >=0.29 version floor, and every multi-call composition
the ui needs. the platform side is auth+forward only and holds no headscale
credentials, so the existing /api/vpn/enroll route and its HEADSCALE_* env vars
are untouched and unrelated.
officer manages many servers rather than one. the owner registers each with a url
and a key generated on that server and switches between them; exactly one is
active, enforced by a partial unique index rather than by convention. keys are
encrypted at rest and never leave the sidecar — the list projection cannot return
one. registration validates before it saves: an unauthenticated GET /version to
prove something headscale-shaped is there and meets the floor, then an
authenticated call to prove the key works. an edit that moves either half
re-validates.
there is deliberately no transparent /api/v1/* passthrough. headscale serialises
every uint64 as a json string and its rest shape moved repeatedly below 0.29;
proxying raw would push all of that into the browser, which is the mistake the
soulseek panels made with 37 raw upstream calls.
the /headscale workspace is nav + view over the panel system. only the servers
section is implemented — nodes, users and pre-auth keys say so plainly rather
than rendering an empty table that reads as a failed fetch.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Being retired, so it is deleted rather than fixed — it had both defects dashboards just
had (edit dropping ?selected=, an abandoned edit following you onto the next item) and
repairing them was work for something on its way out.
Gone: the two screens and the panel apps, the three routes, the dock item and its entry
in the default dock paths (client and the three server-side copies), the page-title rule,
the app-registry entries, the barrel exports, the `projects` table with its queries and
row types, and the proj-meta/proj-layout/proj-terminals/proj-host-terminals branches in
the dashboards endpoint. The chat context and terminal state-key special cases for
`proj-layout-` went with them.
Deliberately kept: `getUserProjectsDir` in data-path.ts — the apps and dev-server routers
resolve user apps under the same on-disk Projects/ directory and are unrelated to this
feature. Nothing on disk is touched.
Needs `bun db:push` to drop the table; the schema change is the only thing standing
between the code and the database. One row was in it.
tsgo clean, 56/56 tests, no references left in src. Not yet exercised at runtime — the
restart is what will prove it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two panels (search + transfers) via WorkspaceView, coordinating over the
soulseek:refresh channel. Adds the page-title rule and documents the
route conventions in CLAUDE.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
"Activity" (placeholder name — jobs/tasks were taken) = watch background tasks
scroll in parallel with chat. Built DB-free; NOT restarted — deploy + test in
the morning.
- NDJSON progress contract (activity/progress.ts): capabilities append
{job,cap,phase,status,pct,detail,ts,...} lines; tolerant parser treats any
JSON object with phase/status as structured progress, else a raw log line.
- Backend (activity/router.ts, owner-only, path-guarded):
- GET /api/activity/tasks — registry by scanning /tmp/claude-*/<cwd>/tasks/
*.output (harness run_in_background) + announced detached jobs.
- POST /api/activity/announce {name,path} — register a detached (setsid) job's
log so it's followable too (the setsid case is on the critical path, since
the warm worker now makes plain run_in_background the default for heavy jobs).
- GET /api/activity/stream?task=<id>|path=<abs> — SSE tail (poll + offset),
emitting {kind:'line'|'progress'} with NDJSON parsed.
- Frontend /activity screen + Radio nav item: task list (active dot) → live tail
with a phase/pct progress header + raw log, following the /system-monitor pattern.
- Retention: startChatEventRetention() prunes chat_session_events >7d every 6h
(wired in bootstrap) so the durable queue stays bounded.
Verified headlessly (no restart): parseTailLine classification, and the scan
finds 53 real task output files. Endpoints + UI untested until deploy.
Deferred (see handoff): cross-device sync + OpenCode parity (both touch the
now-stable chat path — won't ship un-restart-tested); task:progress into chat.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Backend GET /api/system-monitor/stats: one snapshot — CPU overall + per-core
(two /proc/stat samples), memory + swap (/proc/meminfo), disks (df), load,
uptime, top-20 processes (ps). Owner-only via the account gate.
- Frontend /system-monitor screen: polls every 2s; CPU/Memory/Disks cards with
bars + per-core mini-bars, top-processes table. Nav dock "Monitor" item.
- Register /music and /system-monitor in usePageTitle RULES so the browser tab
and editable header title update on those routes (/music was missing too).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A full-page music browser reusing the app-wide player + dock. Sidebar lists
libraries (1st level of ~/Music); main is a card-grid folder browse with rich
pages: albums show a header + tracklist, and artist folders render their album
cards grouped into discography sections (Studio Albums / Live / Compilation / …)
using /music/discography. Cards have hover-play; everything feeds useMusicPlayer.
Adds a green Music dock item (/music) to the default dock.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Onboarding was dead in three layers:
- The OnboardingAdmin screen was only reachable from a route block in App.tsx
that has been commented out, so it never rendered. Its ServerTypeCard carried
accountMode ('organization' | 'single'), inherited from the codebase this was
based on and meaningless for a single-user platform.
- Two /onboarding-complete endpoints, one public and one protected, that no
frontend code called. Both read a server_config key that was never written, so
both answered false while the app's own path defaulted to true.
- HomeScreen gated on settings.onboarding.complete to show a welcome panel, and
seedHomeDir created an Onboarding folder from DATA_PATH/Onboarding and
/Onboarding_Admin — neither seed directory exists, so it only ever produced an
empty folder.
Also drops the onboarding key from UserSettings and the now-empty home-header
panel from the default home layout.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three unrelated type errors that each pointed at something actually broken:
- Dashboard.CodeEditor was deleted in ab03b17 ("Projects") while the
/code-editor route and the dock's Editor item kept pointing at it, so the
route rendered undefined. Screen restored.
- Appearance.tsx imported 'themes', a workspace deleted in 0746844. Nothing
reads settings.appearance.colorTheme and no theme CSS survives, so the picker
was writing a value with no consumer. Removed it and the setting; colorMode
stays, it is live.
- officerdev exported both a component and a type named AppRegistry, so
`import { AppRegistry }` resolved to the type and <AppRegistry /> failed to
typecheck. Renamed the Record type to AppRegistryMap.
Also declares "*.css" so side-effect stylesheet imports resolve.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Deletes the Automation and NewAutomation screens, their /automation and
/new-automation routes, the Dashboard barrel exports, the dock item (+ default
dock path), and the page-title rule. TaskRunnerModal is kept — the file browser
still uses it to run tasks on files.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Pipeline jobs now persist to DB with progress tracking and cost accumulation
- Jobs survive WebSocket disconnects with in-memory event buffer replay
- New /jobs list page with search, status badges, and cost display
- New /jobs/:id detail page with live WebSocket attachment and REST fallback
- Two-column layout using WorkspaceLayout for resizable steps/output panels
- Streaming messages tagged with stepIndex/iterationLabel for per-step output grouping
- TaskRunnerModal links to job detail page once job is created
- Dock entry added for Jobs page
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>