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
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Sixteen top-level commands (run `genie <command> --help` for detail):
| `setup` | Configure Genie; authenticated `setup --codex` owns Codex activation and managed convergence; `setup --orchestration-mode <standalone\|orca>` selects the lifecycle authority |
| `shortcuts` | Manage tmux keyboard shortcuts |
| `task` | Task state (SQLite, zero-daemon) |
| `ui-bridge` | UI-owned stdio MCP bridge into genie.db (reads + roster writes + change-push) |
| `ui-bridge` | Retired — prints the stable non-zero UI-bridge-retirement diagnostic (the Orca integration is the supported UI surface) |
| `uninstall` | Remove Genie CLI and clean up hooks |
| `update` | Update Genie CLI to the latest GitHub Release |
| `help` | `genie help [command]` |
Expand Down Expand Up @@ -182,7 +182,7 @@ Biome's `noExcessiveCognitiveComplexity` is set to `maxAllowedComplexity: 25` (w
- **Codex ships exactly H3/H4/H6, and all remain untrusted after an edit** — H3 is bounded read-only SessionStart context; H4 is deterministic local PreToolUse guarding; H6 is matcher-scoped PermissionRequest approval and is the only retained hook that may write approval-queue state. No Codex lifecycle hook installs, updates, synchronizes, or scaffolds. Run `genie update` to deliver signed bytes, then authenticated `genie setup --codex` to activate them; inspect changed hashes with `/hooks` and start a new task. Codex hook commands run outside the model sandbox, so hard controls still belong in sandbox permissions and server-side branch protection.
- **Hook dispatch is provider-aware and fail-closed** — the plugin-local Codex launcher selects only the canonical `$GENIE_HOME/bin/genie`, preserves stdin/stdout/signals, bounds child time/output, validates event-specific JSON, and converts launch/timeout/schema failures into a reasoned deny. Claude dispatch remains a short-lived in-process `genie hook dispatch` fork. Neither path is a daemon.
- **`AskUserQuestion` is the one PreToolUse carve-out** — it is in `NON_INTERCEPTABLE_PRE_TOOL_USE_TOOLS` and MUST get an EMPTY response, not the neutral `{ decision: 'block' }` block form. Empirically CC consumes any additionalContext as the synthesized answer, so a fail-closed block would corrupt the inline picker. The fail-closed envelope special-cases this tool.
- **The product MCP server and its launchers are retired** — `genie mcp` is a stub that writes a stable diagnostic to stderr and exits 1; no plugin ships an MCP declaration or launcher, and `genie init` only retires proven Genie-owned historical routes (in `.mcp.json` it retires only the dead `genie mcp` entry — a genie binary with args exactly `["mcp"]` — backing the file up first and preserving every other server byte-for-byte; `genie doctor` warns while that entry is still present). The UI-owned `genie ui-bridge` is a separate private stdio bridge and is NOT the retired product integration.
- **The product MCP server and its launchers are retired** — `genie mcp` is a stub that writes a stable diagnostic to stderr and exits 1; no plugin ships an MCP declaration or launcher, and `genie init` only retires proven Genie-owned historical routes (in `.mcp.json` it retires only the dead `genie mcp` entry — a genie binary with args exactly `["mcp"]` — backing the file up first and preserving every other server byte-for-byte; `genie doctor` warns while that entry is still present). The UI-owned `genie ui-bridge` is retired too — there is no Genie UI any more, the Orca integration is the only UI surface — so it is the same shape of stub (stable stderr diagnostic, exit 1), and its private transport (`mcp-server.ts`), tool registry (`mcp-tools.ts`), and change watcher (`bridge-watcher.ts`) are deleted.
- **Lifecycle authority is an explicit mode, never inferred** — `standalone` is the default (including when `orchestration.mode` is absent); installing or opening Orca changes nothing. `genie setup --orchestration-mode orca` probes the shipped plugin payload and a compatible Orca runtime before atomically switching, after which Genie refuses local `genie.db` lifecycle reads/writes and roadmap writes/syncs/exports. Switching back with `--orchestration-mode standalone` imports no Orca state. There is no fallback database in either direction.
- **Two `genie.db` files, never cross-import** — per-repo `.genie/genie.db` (`genie-db.ts`, task/board/wish) and global `~/.genie/genie.db` (`global-db.ts`, omni queue + inbox) are independent databases with their own schemas and `user_version`. `global-db.ts` shares only `sqlite-open.ts` with the per-repo one — do not reach across for path constants.
- **Codex integration health is native state, not OTel** — the old Genie exporter at `127.0.0.1:14318` has no relay and is removed by an exact-match, backup-first migration. Preserve unrelated OTel settings and `disable_paste_burst`.
Expand Down
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ genie --help
| `genie board` | Kanban view of task state, derived live by query |
| `genie idea` | Capture an idea into the roadmap board Idea lane (creates the board if absent) |
| `genie task` | Inspect and drive task state (SQLite, zero-daemon) |
| `genie ui-bridge` | Run the UI-owned stdio MCP bridge into genie.db (reads + roster writes + change-push) |
| `genie ui-bridge` | Return the stable non-zero UI-bridge-retirement diagnostic |
| `genie install` | Finish a verified install and deliver selected integrations; Codex activation is deferred to setup |
| `genie mcp` | Return the stable non-zero MCP-retirement diagnostic |
| `genie omni` | Bridge agents to WhatsApp via Omni — remote approvals + inbound one-shots (`serve`, `status`, `inbox`, `handshake`) |
Expand Down Expand Up @@ -252,9 +252,12 @@ The legacy cross-client MCP server, its write tools, plugin launchers, and Genie
pre-A7 signed release.` to stderr and exits 1 without reading or speaking MCP. `genie init` removes only historical
registrations proven to be Genie-owned; unowned same-name routes and every unrelated config key remain untouched.

The UI-owned `genie ui-bridge` is not the retired product MCP integration. It retains its private stdio transport and
read/roster surface for the Genie UI. Standalone `genie task` and `genie board` retain their existing behavior in
standalone mode; Orca mode continues to use the public `orca orchestration ... --json` adapter as its sole authority.
The UI-owned `genie ui-bridge` is retired on the same terms: there is no separate Genie UI any more, the Orca
integration is the supported UI surface, and the private stdio transport, tool registry, and change watcher behind the
bridge are deleted. `genie ui-bridge` prints `Error: genie ui-bridge has been retired; the Orca integration is the
supported UI surface, or roll back to a pre-retirement signed release.` to stderr and exits 1. Standalone `genie task`
and `genie board` retain their existing behavior in standalone mode; Orca mode continues to use the public
`orca orchestration ... --json` adapter as its sole authority.

## Hermes-native surface

Expand Down
2 changes: 1 addition & 1 deletion knip.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://unpkg.com/knip@6.29.0/schema.json",
"entry": ["src/hooks/dispatch-command.ts"],
"project": ["src/**/*.ts"],
"ignoreBinaries": ["ldd", "omni", "ss"],
"ignoreBinaries": ["ldd", "omni"],
"ignoreExportsUsedInFile": true,
"ignore": ["src/term-commands/hook/trust.ts"]
}
1 change: 0 additions & 1 deletion src/__tests__/claude-md-drift.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ const REQUIRED_V5_COMMANDS: ReadonlyArray<string> = [
'setup',
'shortcuts',
'task',
'ui-bridge',
'uninstall',
'update',
];
Expand Down
7 changes: 4 additions & 3 deletions src/lib/interactivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ const WORKSPACE_EXEMPT = new Set([
// exits 1. It touches no workspace state, so the legacy workspace gate must not
// exit 2 and mask the retirement diagnostic callers are told to expect.
'mcp',
// `ui-bridge` is the UI-owned stdio MCP bridge (reads + roster writes + push).
// It self-resolves the shared genie.db and speaks JSON-RPC on stdio;
// the legacy workspace gate must not exit 2 before the handshake can happen.
// `ui-bridge` is now a retirement stub too: the Orca integration replaced the
// UI-owned stdio bridge, so the command only writes its stable diagnostic to
// stderr and exits 1. It touches no workspace state, so the legacy workspace
// gate must not exit 2 and mask the diagnostic callers are told to expect.
'ui-bridge',
]);

Expand Down
152 changes: 0 additions & 152 deletions src/lib/v5/UI-BRIDGE.md

This file was deleted.

3 changes: 0 additions & 3 deletions src/lib/v5/authority-barriers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { join } from 'node:path';
import { openReadonlyHandle } from '../../term-commands/context.js';
import { InvalidOrchestrationAuthorityError, LocalLifecycleDisabledError } from '../orchestration-mode.js';
import { openDb } from './genie-db.js';
import { openReadonlyDb } from './mcp-tools.js';
import { writeSnapshotFile } from './roadmap-sync.js';

const originalGenieHome = process.env.GENIE_HOME;
Expand Down Expand Up @@ -87,7 +86,6 @@ describe('Orca authority barriers', () => {
const beforeMtime = statSync(dbPath).mtimeMs;

expect(() => openReadonlyHandle(dbPath)).toThrow(LocalLifecycleDisabledError);
expect(() => openReadonlyDb(join(root, 'repo'))).toThrow(LocalLifecycleDisabledError);

expect(readdirSync(directory)).toEqual(beforeNames);
expect(readFileSync(dbPath)).toEqual(beforeBytes);
Expand Down Expand Up @@ -177,7 +175,6 @@ describe('Orca authority barriers', () => {

expect(() => openDb({ path: dbPath })).toThrow(fixtureCase.error);
expect(() => openReadonlyHandle(dbPath)).toThrow(fixtureCase.error);
expect(() => openReadonlyDb(repo)).toThrow(fixtureCase.error);
expect(() => writeSnapshotFile(roadmap, { forbidden: true })).toThrow(fixtureCase.error);

expect(existsSync(dbPath)).toBe(false);
Expand Down
Loading
Loading