Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# dmux-style cockpit — Phase 2: branded welcome screen

## Why

Phase 1 wired the dmux-style top-bar shortcuts (`[n]ew agent`,
`[t]erminal`, `[l]ogs`, `[p]rojects`). The welcome screen still shows
the original `gx` ASCII robot motif and lists only the legacy `n`/`t`/
`s` next-actions. To match the dmux look users asked for and to
advertise the new shortcuts on first launch, the welcome page needs a
proper gitguardex brand block and an updated next-actions list.

## What changes

- Replace the 5-line `GUARD_MOTIF` (`/ _)`, `/ gx \`) with a 5-line
ASCII `GUARDEX` wordmark plus a single `guarded multi-agent cockpit`
strapline.
- Add `l logs` and `p projects` to the welcome screen's `Next actions`
block so users see all four primary shortcuts immediately.
- Keep the existing box, status rows (Repo / Branch / Safety / Hooks /
Locks / Agents), and shortcut block intact.

## Impact

- New constants `GITGUARDEX_BRAND` and `GITGUARDEX_STRAPLINE` in
`src/cockpit/welcome.js`.
- 2 lines added to the next-actions block.
- Tests:
- `renderWelcomePage snapshots the empty cockpit welcome strings`
extended to assert `l logs`, `p projects`, and the strapline.
- `renderWelcomePage stays width bounded and plain terminal safe`
swaps the obsolete `/ _)` / `/ gx \` motif assertions for the
new strapline + brand-marker checks.
- ASCII-only constraint preserved (no unicode block or box-drawing
chars, so plain terminals stay safe).
- No behavior change to safety model, branches, worktrees, locks, or
PR-only finish flow.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
## ADDED Requirements

### Requirement: Welcome screen renders the gitguardex brand and strapline
The cockpit welcome screen SHALL render a multi-line ASCII gitguardex
brand block followed by a single-line `guarded multi-agent cockpit`
strapline, in place of the previous `gx` ASCII robot motif.

#### Scenario: Brand and strapline appear on the empty welcome
- **WHEN** `renderWelcomePage` is invoked with no active sessions
- **THEN** the rendered output contains the `\____|` marker from the
bottom of the ASCII brand
- **AND** the output contains the substring `guarded multi-agent cockpit`.

### Requirement: Welcome screen advertises all four primary shortcuts
The cockpit welcome screen's `Next actions` block SHALL list `n`, `t`,
`l`, `p`, and `s` so users see all four primary dmux-style shortcuts on
first launch alongside the existing settings hint.

#### Scenario: Next actions list includes l and p
- **WHEN** `renderWelcomePage` is invoked with any state
- **THEN** the rendered output contains the substrings `l logs` and
`p projects` in addition to the existing `n new agent`, `t terminal`,
and `s settings` lines.

### Requirement: Welcome screen stays ASCII-only
The cockpit welcome screen SHALL remain plain-terminal safe: every
character in the rendered output (including the new brand block) MUST
fall within the printable ASCII range so terminals without unicode box
or block glyphs render correctly.

#### Scenario: No characters above U+007F appear in the output
- **WHEN** `renderWelcomePage` is invoked with any state
- **THEN** the rendered output contains no character in the range
`[€-￿]`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Tasks

## 1. Spec
- [x] 1.1 Capture proposal in `proposal.md`
- [x] 1.2 Capture spec delta in `specs/cockpit-welcome/spec.md`

## 2. Tests
- [x] 2.1 Extend the empty-welcome snapshot test to assert `l logs`,
`p projects`, and the `guarded multi-agent cockpit` strapline.
- [x] 2.2 Replace the obsolete `/ _)` / `/ gx \` motif assertions
in the width-bounded test with strapline + brand-marker checks.

## 3. Implementation
- [x] 3.1 Replace `GUARD_MOTIF` with `GITGUARDEX_BRAND` (5-line ASCII
wordmark for `GUARDEX`).
- [x] 3.2 Add `GITGUARDEX_STRAPLINE = 'guarded multi-agent cockpit'`.
- [x] 3.3 Wire the new brand and strapline into `renderWelcomePage`
in place of `GUARD_MOTIF.forEach(...)`.
- [x] 3.4 Add `l logs` and `p projects` rows to the `Next actions`
block.

## 4. Cleanup
- [ ] 4.1 Commit changes on the agent branch.
- [ ] 4.2 Push branch and open a PR.
- [ ] 4.3 Run `gx branch finish ... --via-pr --wait-for-merge --cleanup`.
- [ ] 4.4 Record PR URL and `MERGED` evidence.
23 changes: 15 additions & 8 deletions src/cockpit/welcome.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ const MIN_WIDTH = 48;
const MAX_WIDTH = 88;

const DEFAULT_AGENTS = ['codex', 'claude', 'opencode', 'cursor', 'gemini'];
const GUARD_MOTIF = [
' __',
' / _)',
' .-^^^-/',
'/ gx \\',
'|_|--|_|',
const GITGUARDEX_BRAND = [
' ____ _ _ _ ___ ___ _____ __',
' / ___|| | | | / \\ | _ \\ | _ \\ | ____|\\ \\/ /',
'| | _ | | | |/ _ \\| |_) || | | || _| \\ /',
'| |_| || |_| / ___ \\ _ < | |_| || |___ / \\',
' \\____| \\___/_/ \\_\\_| \\_\\____/ |_____|/_/\\_\\',
];
const GITGUARDEX_STRAPLINE = 'guarded multi-agent cockpit';

function stringValue(value, fallback = '') {
if (typeof value === 'string') {
Expand Down Expand Up @@ -222,9 +223,13 @@ function renderWelcomePage(state = {}, settings = {}) {
emptyLine(width),
];

GUARD_MOTIF.forEach((motifLine) => {
lines.push(themedBoxedLine(motifLine, width, 'accent', theme));
GITGUARDEX_BRAND.forEach((brandLine) => {
lines.push(themedBoxedLine(brandLine, width, 'accent', theme));
});
lines.push(
emptyLine(width),
themedBoxedLine(GITGUARDEX_STRAPLINE, width, 'heading', theme),
);

lines.push(
emptyLine(width),
Expand All @@ -247,6 +252,8 @@ function renderWelcomePage(state = {}, settings = {}) {
themedBoxedLine('Next actions', width, 'heading', theme),
themedBoxedLine(' n new agent - start a guarded agent lane', width, 'secondary', theme),
themedBoxedLine(' t terminal - open a repo terminal', width, 'secondary', theme),
themedBoxedLine(' l logs - tail apps/logs/*.log and lane events', width, 'secondary', theme),
themedBoxedLine(' p projects - switch repo (no lane selected)', width, 'secondary', theme),
themedBoxedLine(' s settings - tune cockpit defaults', width, 'secondary', theme),
colorize(divider(width), 'border', theme),
);
Expand Down
7 changes: 5 additions & 2 deletions test/cockpit-welcome.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@ test('renderWelcomePage snapshots the empty cockpit welcome strings', () => {
assert.match(output, /Agents:\s+codex, claude/);
assert.match(output, /n new agent/);
assert.match(output, /t terminal/);
assert.match(output, /l logs/);
assert.match(output, /p projects/);
assert.match(output, /s settings/);
assert.match(output, /\? shortcuts/);
assert.match(output, /q quit/);
assert.match(output, /Next actions/);
assert.match(output, /guarded multi-agent cockpit/);
assert.equal(output.endsWith('\n'), true);
});

Expand All @@ -54,8 +57,8 @@ test('renderWelcomePage stays width bounded and plain terminal safe', () => {
assert.equal(line.length <= width, true, `line exceeded ${width}: ${line}`);
}

assert.match(output, /\/ _\)/);
assert.match(output, /\/ gx \\/);
assert.match(output, /guarded multi-agent cockpit/);
assert.match(output, /\\____\|/);
assert.match(output, /Locks:\s+5/);
assert.match(output, /Agents:\s+codex, gemini/);
assert.doesNotMatch(output, /[\u0080-\uffff]/);
Expand Down
Loading