chore(v0.6): checkpoint foundation — Amber theme, P1 types, P3 config, design docs

Prior-session prep for the v0.6 Project Manager, checkpointed on the
v0.6-projects branch as a clean base for the parallel builders:

- P1 (src/types.ts): ProjectInfo + ProjectSessionRef contracts; Config
  gains projectRoots/projectScanDepth/projectScanTtlMs/projectDirtyCheck.
- P3 (src/config.ts): parseBool + parseProjectRoots helpers; parse the
  4 PROJECT_* env vars with defaults ([homeDir]/4/10000/true).
- UI: public/style.css indigo -> Amber (#e3a64a) accent theme.
- Docs: FEATURE_PROJECT_MANAGER.md (1:N session design), THEME.md,
  docs/mockups/ (final-amber.png is the locked visual).

Typecheck (backend + web) green. No behavior change to runtime code yet;
P2/P4/P5/P6 implement the feature on top of this.
This commit is contained in:
Yaojia Wang
2026-06-30 10:05:40 +02:00
parent f9964a517d
commit dc5d073374
16 changed files with 1073 additions and 23 deletions

View File

@@ -34,6 +34,11 @@ export interface Config {
readonly previewBytes: number; // manage-page preview: bytes of scrollback tail rendered
readonly useTmux: boolean; // H1: spawn the shell inside tmux so it survives a server restart
readonly allowedOrigins: readonly string[]; // derived from NIC IPs, NOT bindHost (M1)
// v0.6 Project Manager — project discovery (impl: src/config.ts T-PM3)
readonly projectRoots: readonly string[]; // PROJECT_ROOTS, default [homeDir]
readonly projectScanDepth: number; // PROJECT_SCAN_DEPTH, default 4
readonly projectScanTtlMs: number; // PROJECT_SCAN_TTL, default 10000 (discovery cache)
readonly projectDirtyCheck: boolean; // PROJECT_DIRTY_CHECK, default true (git status per repo)
}
/** process.env is structurally assignable to this; keeps the file free of `NodeJS.*`. */
@@ -192,6 +197,31 @@ export interface LiveSessionInfo {
rows: number;
}
/* ───────────────── project manager (v0.6, §4.3 FEATURE doc) ──────────────── */
/** One running session belonging to a project (live-sessions归并 by cwd).
* Mirrors LiveSessionInfo fields so buildProjects can map directly. */
export interface ProjectSessionRef {
id: string;
title?: string; // tab title / derived label (e.g. 'claude', 'shell'); optional
status: ClaudeStatus; // reuse hook status (working|waiting|idle|unknown)
clientCount: number; // mirror devices currently attached
createdAt: number;
exited: boolean;
}
/** A discovered project (git repo or recently-used cwd) for the Projects panel.
* impl: src/http/projects.ts buildProjects(cfg, liveSessions) — T-PM2. */
export interface ProjectInfo {
name: string; // repo directory name
path: string; // absolute path
isGit: boolean;
branch?: string; // current branch (git repos only)
dirty?: boolean; // uncommitted changes (when projectDirtyCheck)
lastActiveMs?: number; // newest ~/.claude/projects mtime for this cwd; sort key
sessions: ProjectSessionRef[]; // running sessions in this project (1:N; may be empty)
}
export interface SessionManager {
handleAttach(
ws: WebSocketLike,