Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d8d0daf
chore(porch): 929 init pir
mohidmakhdoomi May 31, 2026
fdddc7e
[PIR #929] Plan draft
mohidmakhdoomi May 31, 2026
0ff5420
chore(porch): 929 plan-approval gate-requested
mohidmakhdoomi May 31, 2026
53374f3
[PIR #929] Plan revised — address architect feedback (5 issues)
mohidmakhdoomi May 31, 2026
dccfbf8
chore(porch): 929 plan-approval gate-approved
mohidmakhdoomi May 31, 2026
1393781
chore(porch): 929 implement phase-transition
mohidmakhdoomi May 31, 2026
69cf20d
[PIR 929][Phase: implement] feat: harness-gated session resume for co…
mohidmakhdoomi May 31, 2026
24bed9d
chore(porch): 929 dev-approval gate-requested
mohidmakhdoomi Jun 16, 2026
4c8d846
chore(porch): 929 dev-approval gate-approved
mohidmakhdoomi Jun 16, 2026
c7961b0
chore(porch): 929 review phase-transition
mohidmakhdoomi Jun 16, 2026
562637e
[PIR #929] Review + retrospective
mohidmakhdoomi Jun 16, 2026
158671b
chore(porch): 929 record PR #1
mohidmakhdoomi Jun 16, 2026
8ee31b4
chore(porch): 929 review build-complete
mohidmakhdoomi Jun 16, 2026
7ae3e4d
chore(porch): 929 pr gate-requested
mohidmakhdoomi Jun 16, 2026
9b615cd
[PIR #929] Address architect integration review: override-aware harne…
mohidmakhdoomi Jun 16, 2026
455c433
chore(porch): 929 review build-complete
mohidmakhdoomi Jun 16, 2026
dbe9ed0
[PIR #929] Review: document iter2 CMAP verdicts + codex frontmatter r…
mohidmakhdoomi Jun 16, 2026
b785178
chore(porch): 929 record PR #1059
mohidmakhdoomi Jun 16, 2026
07fe3f7
[PIR #929] Thread: architect APPROVE + PR retargeted upstream (cluesm…
mohidmakhdoomi Jun 16, 2026
1f4bfd3
[PIR #929] Doc: caveat — unrecognized override commands default to cl…
mohidmakhdoomi Jun 17, 2026
0fd70b7
Merge branch 'main' into builder/pir-929
mohidmakhdoomi Jun 17, 2026
f337b61
chore(porch): 929 pr gate-approved
mohidmakhdoomi Jun 17, 2026
10d739e
chore(porch): 929 protocol complete
mohidmakhdoomi Jun 17, 2026
f9c28ce
[PIR #929] Thread: pr gate approved, protocol complete, not self-merg…
mohidmakhdoomi Jun 17, 2026
780fcdc
chore(porch): 929 rollback verified → plan
mohidmakhdoomi Jun 17, 2026
3082c18
[PIR #929] Plan revised: agy (Antigravity CLI) replaces gemini for ar…
mohidmakhdoomi Jun 17, 2026
a7934bd
chore(porch): 929 plan-approval gate-requested
mohidmakhdoomi Jun 17, 2026
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ worktrees/
.env
.update-hashes.json
.architect-role.md
.gemini/settings.json
.codev/config.json

# OS files
Expand Down
235 changes: 235 additions & 0 deletions codev/plans/929-support-codex-and-gemini-clis-.md

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions codev/projects/929-support-codex-and-gemini-clis-/status.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
id: '929'
title: support-codex-and-gemini-clis-
protocol: pir
phase: plan
plan_phases: []
current_plan_phase: null
gates:
plan-approval:
status: pending
requested_at: '2026-06-17T02:45:09.085Z'
dev-approval:
status: pending
pr:
status: pending
iteration: 1
build_complete: false
history: []
started_at: '2026-05-31T19:04:30.567Z'
updated_at: '2026-06-17T02:45:09.086Z'
pr_history:
- phase: review
pr_number: 1
branch: builder/pir-929
created_at: '2026-06-16T19:10:45.900Z'
- phase: review
pr_number: 1059
branch: builder/pir-929
created_at: '2026-06-16T19:49:59.539Z'
pr_ready_for_human: false
12 changes: 11 additions & 1 deletion codev/resources/arch.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ All architect sessions (at all 3 creation points) receive a role prompt injected

1. Loads the architect role from `codev/roles/architect.md` (local) or `skeleton/roles/architect.md` (bundled fallback) via `loadRolePrompt()`
2. Writes the role content to `.architect-role.md` in the project directory
3. Appends `--append-system-prompt <content>` to the architect command args
3. Delegates the CLI-specific injection to the configured `HarnessProvider` (`agent-farm/utils/harness.ts`, Spec 591): claude `--append-system-prompt`, codex `-c model_instructions_file=`, gemini `GEMINI_SYSTEM_MD` env var

**Three architect creation points** where role injection is applied:
- `tower-instances.ts` → `launchInstance()` (new project activation)
Expand All @@ -269,6 +269,16 @@ Framework files (protocol docs, templates) live in the package skeleton (resolve

A `codev doctor` audit (`lib/framework-ref-audit.ts`) flags shell-fetch of framework files in a project's local `codev/` overrides; the shipped skeleton is guarded by a CI unit test.

#### Supported Architect Harnesses & Conversation Resume (#929)

**Supported architect harnesses** (Issue #929): claude, codex, and gemini are all supported as architects, selected via `.codev/config.json` (`shell.architect` / `shell.architectHarness`) — the same config-driven mechanism builders use, and the *recommended* one. Harness auto-detection is **override-aware**: `getArchitectHarness` / `getBuilderHarness` resolve the harness from the override-aware command (`getResolvedCommands` → `cliOverrides` / `TOWER_ARCHITECT_CMD` / config), so a `--architect-cmd gemini` / `TOWER_ARCHITECT_CMD=gemini` / `--builder-cmd gemini` with no matching harness config still resolves the *gemini* harness, not claude. (Before #929 it auto-detected from the raw config value only — an override launched gemini but resolved the claude harness, re-arming the resume crash-loop below.) An explicit `shell.architectHarness` / `shell.builderHarness` still wins over auto-detection. OpenCode remains builder-only (file-based injection needs an ephemeral worktree). Gemini additionally gets a `.gemini/settings.json` (`context.fileName` → `AGENTS.md`) written if-absent at launch via the harness's `getArchitectFiles`, so it reads project context the way codex reads `AGENTS.md` natively.

> **Caveat — unrecognized override commands still default to the claude harness (tracked in cluesmith/codev#1062).** `#929`'s override-awareness only covers *recognized* harness commands (claude/codex/gemini/opencode, matched by `detectHarnessFromCommand`). An override command the detector does **not** recognize — e.g. `TOWER_ARCHITECT_CMD=bash`, a wrapper script, or any custom launcher — with **no** explicit `shell.architectHarness` / `shell.builderHarness` falls through `resolveHarness` to the **claude** harness (`harness.ts`, the final `return CLAUDE_HARNESS`). With a stale Claude `.jsonl` present, that can still build `<cmd> --resume <uuid>` for the unrecognized command. This is **pre-existing and narrow** (not a #929 regression — #929 strictly *improved* the recognized codex/gemini cases) and separable. Mitigation today: set an explicit `shell.architectHarness` / `shell.builderHarness` when using an unrecognized launcher command.

**Conversation resume is Claude-main-only.** `launchInstance` resumes a prior session only when the configured harness implements `HarnessProvider.buildResume` — currently just claude (its sessions live at `~/.claude/projects/<encoded-cwd>/*.jsonl`). Codex/gemini architects (and resumed codex/gemini builders, via `spawn.ts` `discoverResumeSession`) return `null` from `buildResume` and relaunch fresh with role injection. This gating fixes a latent crash-loop where a non-Claude harness + a stale Claude `.jsonl` built an invalid `<cmd> --resume <claude-uuid>` invocation and shellper restart-looped to death.

**`getArchitectFiles` is centralized in `buildArchitectArgs`** (`tower-utils.ts`), the shared role-injection helper every architect-launch path routes through — `launchInstance` (fresh), `add-architect` (sibling), shellper reconnect (×2), and the no-Tower `afx architect` (refactored in #929 to call `buildArchitectArgs` instead of duplicating injection). So Gemini's context manifest is written on **every** launch path, not just first-activation.

#### Multi-Architect Support (Spec 755 / Spec 786)

A workspace can host more than one architect terminal. Each architect has a stable name (`main` for the workspace's default; siblings via `afx workspace add-architect`). The primary use case is letting a sibling architect drive a focused workflow without monopolising `main`.
Expand Down
1 change: 1 addition & 0 deletions codev/resources/lessons-learned.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Generalizable wisdom extracted from review documents, ordered by impact. Updated

## Architecture

- [From #929] When abstracting per-CLI (or per-provider) behavior behind a provider interface, audit **every** call site that builds a CLI invocation — including resume/restart paths, not just the obvious fresh-launch path. Spec 591's harness abstraction routed fresh-launch role injection through the provider but left the `--resume` seam reading Claude's session store unconditionally; a codex/gemini architect (or resumed builder) with any stale Claude `.jsonl` then built `<cmd> --resume <claude-uuid>` and shellper restart-looped to death. The bug only fires on the resume branch (fresh launches were already correct), which is exactly why "builders already prove the path" didn't cover it — resume is a *different* call site. Fix: an optional capability (`buildResume`) that returns the resume invocation in both Node-argv and shell-escaped-fragment forms (mirroring `buildRoleInjection`/`buildScriptRoleInjection`), so no CLI-specific string survives at the call site and only the harness that has a cwd-keyed session store opts in (others return null → fresh launch).
- [From 1052] Shared *shape* is not shared *substance* — resist extracting on resemblance. The VSCode replay buffer-and-flush and the web client's `flushInitialBuffer` do the same conceptual thing (hold replay → paint once at the settled size), but their triggers and bodies diverge: web uses a fixed 500ms delay entangled with `FitAddon`/`ScrollController`; VSCode uses a `setDimensions` debounce + PTY-resize + paced `writeChunked`. The only common part is a ~10-line "accumulate then emit once" skeleton; the valuable logic (trigger policy, flush body) differs. Extracting would couple two independently-evolving strategies behind one leaky name — a net negative at two call sites. Contrast the primitives that *are* genuinely identical and correctly centralized in core: `reconnect-policy` and `escape-buffer` (the dashboard's `escapeBuffer.ts` is a 5-line re-export of core's, not a copy). Corollary, painfully relearned here: a claim of "duplication" from an *import path* (`../lib/escapeBuffer.js`) is not evidence — read the file before filing a dedup; it was a re-export shim all along.
- [From #907] A workspace package consumed as *source* by one toolchain and as *built output* by another resolves through different `exports` conditions: tsc and vite read `exports.types` (`./src/index.ts`), while esbuild (the VS Code extension bundler) reads the runtime `exports.default` (`./dist/index.js`). `@cluesmith/codev-types` had no `dist` in a fresh worktree, so `tsc --noEmit`, the codev build, and the full test suite all passed while only the extension's esbuild bundle failed with `Could not resolve "@cluesmith/codev-types"`. A green type-check/test run does **not** prove every bundler can resolve a package — if a workspace package ships a `default → ./dist` condition, it must be built before any esbuild consumer. Root `pnpm build` now builds `types` first (types → core → codev).
- [From #907] Derived projection fields need a fallback when their source is transiently unreadable. `OverviewBuilder.area` is re-resolved every refresh from the open-only `gh issue list`; once an issue closes (merge), is torn down mid-cleanup, or the fetch fails, the lookup misses and the field snapped back to its `Uncategorized` default while the builder was still listed — a visible mis-render once #818 made `area` control tree placement. Fix: cache the last *resolved* value (`ResolvedEnrichmentCache`), gated on **source reachability, not value emptiness**, so a reachable-but-unlabeled issue still records a genuine `Uncategorized` and a stale entry can't mask a live label change. The value is a stable per-item fact, so this is a cache bridging a read gap, not history of a changing value — which is why it lives on the process-lifetime cache singleton, not the per-refresh builder DTO.
Expand Down
Loading
Loading