mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-02 21:49:42 +02:00
Make the branch genuinely master-mergeable and fix several review findings: - Defaults are now prod-safe: CODEMAN_INSTANCE defaults to '' (→ ~/.codeman, -L codeman) and the web port back to 3000, so an existing install upgrades cleanly. Port also honors a new CODEMAN_PORT env var. Run the beta isolated alongside prod with scripts/run-beta.sh (CODEMAN_INSTANCE=beta + PORT 5000). - .gitignore: anchor the root `public` symlink rule to `/public` (a bare `public` also swallowed src/web/public, silently un-staging new web assets); ignore the gesture wasm/model binaries explicitly instead. - span-displays: add a macOS-only guard (400 elsewhere instead of spawning a bash that fails invisibly); extract resolveSpanUrl() for unit testing. - server.ts: memoize asset-version stat() calls (~1s TTL) so each index render doesn't re-stat every script/link tag. - styles.css: hide the multi-monitor button in solo (detached) windows. - app.js: require two consecutive unanswered roll-calls before redocking, so a timer-throttled background popup isn't wrongly un-marked. - index.html: make the "skip to terminal" link base-href-safe (onclick scroll) so it doesn't navigate to the dashboard from a /session/:id window. - Tests: test/config/instance.test.ts, test/routes/system-span-displays.test.ts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
67 lines
2.8 KiB
TypeScript
67 lines
2.8 KiB
TypeScript
/**
|
|
* @fileoverview Per-instance isolation: data directory + tmux socket.
|
|
*
|
|
* Codeman keeps all runtime state under `~/.codeman` and runs its tmux sessions
|
|
* on a dedicated socket (`tmux -L codeman`). Both are PROCESS-WIDE and SHARED by
|
|
* every Codeman instance on the machine — so a second instance pointed at the
|
|
* same socket will discover and attach to the first instance's live sessions,
|
|
* and two instances sharing `~/.codeman/state.json` will clobber each other.
|
|
*
|
|
* To let a beta build coexist with a production one, this module derives both
|
|
* the data dir and the tmux socket from a single "instance" name:
|
|
* - default (unset/empty) → `~/.codeman` + `tmux -L codeman` (prod layout)
|
|
* - `CODEMAN_INSTANCE=beta` → `~/.codeman-beta` + `tmux -L codeman-beta`
|
|
* - `CODEMAN_INSTANCE=foo` → `~/.codeman-foo` + `tmux -L codeman-foo`
|
|
*
|
|
* The DEFAULT is the production layout so this is safe to ship to master: an
|
|
* existing install keeps reading `~/.codeman`. To run a beta ALONGSIDE prod,
|
|
* launch it with `CODEMAN_INSTANCE=beta` (and a distinct port, see below) —
|
|
* `scripts/run-beta.sh` does both. The port is unrelated to the instance and is
|
|
* set separately via `--port` / `CODEMAN_PORT` (see `src/cli.ts`).
|
|
*
|
|
* Individual overrides still win: `CODEMAN_DATA_DIR` (absolute data dir) and
|
|
* `CODEMAN_TMUX_SOCKET` (socket name, validated in tmux-manager).
|
|
*/
|
|
|
|
import { homedir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import { mkdirSync } from 'node:fs';
|
|
|
|
/**
|
|
* Instance name. Empty string (the default) = production layout (`~/.codeman`,
|
|
* `-L codeman`), so this is safe on master and existing installs are untouched.
|
|
* Set `CODEMAN_INSTANCE=beta` (e.g. via `scripts/run-beta.sh`) to run an
|
|
* isolated beta alongside prod.
|
|
*/
|
|
export const CODEMAN_INSTANCE = process.env.CODEMAN_INSTANCE ?? '';
|
|
|
|
const INSTANCE_SUFFIX = CODEMAN_INSTANCE ? `-${CODEMAN_INSTANCE}` : '';
|
|
|
|
/** Default tmux socket for this instance. `CODEMAN_TMUX_SOCKET` still overrides. */
|
|
export const DEFAULT_TMUX_SOCKET = `codeman${INSTANCE_SUFFIX}`;
|
|
|
|
let _ensured = false;
|
|
|
|
/**
|
|
* Absolute path to this instance's data directory (created on first use). All
|
|
* persisted state (`state.json`, `mux-sessions.json`, settings, push keys,
|
|
* lifecycle log, screenshots, certs, …) lives here.
|
|
*/
|
|
export function getDataDir(): string {
|
|
const dir = process.env.CODEMAN_DATA_DIR || join(homedir(), `.codeman${INSTANCE_SUFFIX}`);
|
|
if (!_ensured) {
|
|
try {
|
|
mkdirSync(dir, { recursive: true });
|
|
_ensured = true;
|
|
} catch {
|
|
/* best-effort; individual writers also mkdir as needed */
|
|
}
|
|
}
|
|
return dir;
|
|
}
|
|
|
|
/** Join one or more segments onto this instance's data directory. */
|
|
export function dataPath(...segments: string[]): string {
|
|
return join(getDataDir(), ...segments);
|
|
}
|