Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7585219
[Spike task-Iptx] Findings: Kimi Code CLI feasible with caveats as bu…
mohidmakhdoomi Jul 18, 2026
af1bc53
[Spike task-Iptx] Addendum: task-delivery readiness barrier + correct…
mohidmakhdoomi Jul 18, 2026
1e22513
[Spike task-Iptx] Thread: post-review addendum logged
mohidmakhdoomi Jul 18, 2026
1e8d3c6
chore(porch): 1201 init pir
mohidmakhdoomi Jul 18, 2026
d49c292
[PIR #1201] Plan draft
mohidmakhdoomi Jul 18, 2026
73774d9
chore(porch): 1201 plan-approval gate-requested
mohidmakhdoomi Jul 18, 2026
fe7114e
chore(porch): 1201 plan-approval gate-approved
mohidmakhdoomi Jul 18, 2026
b26c565
chore(porch): 1201 implement phase-transition
mohidmakhdoomi Jul 18, 2026
2cf424c
[PIR #1201] Kimi harness: detection, seed-session launch script, buil…
mohidmakhdoomi Jul 18, 2026
8e86c41
[PIR #1201] Tower: sentinel-gated BEGIN delivery + per-harness Enter …
mohidmakhdoomi Jul 18, 2026
3d40785
[PIR #1201] doctor: kimi presence, truthful auth heuristic, store smo…
mohidmakhdoomi Jul 18, 2026
f075443
[PIR #1201] Docs: kimi builder harness (arch.md + config examples, sk…
mohidmakhdoomi Jul 18, 2026
b27e2d3
[PIR #1201] Pacing resolution is fully best-effort; widen cron sessio…
mohidmakhdoomi Jul 18, 2026
ea6607c
[PIR #1201] Pin Kimi Enter delay with live bisect evidence
mohidmakhdoomi Jul 18, 2026
6b39ca5
[PIR #1201] Live demo driver + results (all 5 checklist steps pass)
mohidmakhdoomi Jul 18, 2026
671e8dd
chore(porch): 1201 dev-approval gate-requested
mohidmakhdoomi Jul 18, 2026
215cda2
chore(porch): 1201 dev-approval gate-approved
mohidmakhdoomi Jul 19, 2026
fee9015
chore(porch): 1201 review phase-transition
mohidmakhdoomi Jul 19, 2026
e8fe2ef
[PIR #1201] Review + retrospective (lessons routed to cold tier)
mohidmakhdoomi Jul 19, 2026
b80dbb4
chore(porch): 1201 record PR #1203
mohidmakhdoomi Jul 19, 2026
ad19c96
chore(porch): 1201 review build-complete
mohidmakhdoomi Jul 19, 2026
732f04b
[PIR #1201] Fix seed-kick confirmation false-positive (codex consulta…
mohidmakhdoomi Jul 19, 2026
b0ad027
chore(porch): 1201 pr gate-requested
mohidmakhdoomi Jul 19, 2026
3c0b6fc
[PIR #1201] Thread: review phase + CMAP disposition logged
mohidmakhdoomi Jul 19, 2026
53bfea0
chore(porch): 1201 pr gate-approved
mohidmakhdoomi Jul 19, 2026
2f889cf
chore(porch): 1201 protocol complete
mohidmakhdoomi Jul 19, 2026
08d4311
[PIR #1201] Thread: pr gate approved, porch wrapped; PR open for main…
mohidmakhdoomi Jul 19, 2026
47d12ba
[PIR #1201] Record CMAP iter-1 disposition (codex finding accepted+fi…
mohidmakhdoomi Jul 19, 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
21 changes: 21 additions & 0 deletions codev-skeleton/resources/commands/agent-farm.md
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,27 @@ afx workspace start --architect-cmd "claude --model opus"
afx spawn 42 --protocol spir --builder-cmd "claude --model haiku"
```

### Builder harnesses

The builder CLI's role/prompt mechanics are handled by a harness, auto-detected
from the command basename (`claude`, `codex`, `gemini`, `opencode`, `kimi`) or
pinned explicitly via `shell.builderHarness`. Example — Kimi Code CLI as the
builder (builder-only; requires kimi >= 0.27.0):

```json
{
"shell": {
"builder": "kimi"
}
}
```

Kimi builders use a seed-session bootstrap (role + task delivered via a
one-shot `kimi -p` call whose session the interactive TUI then resumes), so
context survives builder restarts. Note: Kimi has no hook seam, so Kimi
builders do NOT get the worktree write-guard Claude builders have.
Architect use of kimi and opencode is unsupported (use claude or codex there).

---

## Files
Expand Down
182 changes: 182 additions & 0 deletions codev/plans/1201-support-kimi-code-cli-as-a-bui.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Iteration 1 — disposition of review feedback (PIR #1201)

Verdicts: gemini APPROVE · claude APPROVE · codex REQUEST_CHANGES.

## Codex finding 1 — seed-kick confirmation false-positive: ACCEPTED, FIXED

**Claim**: `seed-kick.ts` confirmed delivery via `state.lastPrompt.includes(opts.message)`; on a fresh spawn the seed prompt itself contains "BEGIN" (the ack-and-wait wrapper says 'You will receive a message "BEGIN"…' and the briefing header says "do not act until BEGIN"), so the verifier could report success even when the Tower-sent BEGIN never submitted — defeating the swallowed-Enter recovery.

**Assessment**: real defect, confirmed against the spike's observed behavior (after a `kimi -p` seed, `state.json.lastPrompt` = the seed prompt). The live demo had not caught it because its kick genuinely submitted (`lastPrompt` overwritten to exactly `BEGIN`) — the false-positive window only matters on the failure path the verification exists to heal.

**Fix** (commit `732f04b8`): confirmation now requires **whitespace-normalized equality** between `lastPrompt` and the kick message. Normalization matters because submitted multi-line messages land in `lastPrompt` with newlines flattened to spaces (observed, kimi 0.27.0), and it keeps the predicate correct for the pre-planned fallback where the whole task prompt becomes the kick payload.

**Pinning tests** (both fail on the pre-fix code):
1. `seed-kick.test.ts` — "the SEED prompt containing the kick word is NOT confirmation": store state carrying a BEGIN-mentioning seed prompt must not confirm and must escalate to the Enter re-send; confirmation only fires once `lastPrompt` becomes exactly `BEGIN`.
2. "confirmation tolerates the observed newline-flattening": a multi-line kick payload still confirms through the flattening.

**Post-fix validation**: full seed-kick suite 14/14; live demo re-run against real kimi 0.27.0 → 5/5 PASS (no false negative from the stricter predicate).

## Codex finding 2 — test suite missed the case: ACCEPTED, FIXED

Covered by the two pinning tests above; also documented in the review file's "Things to Look At During PR Review" with an explicit note that PIR's single-pass consultation did **not** re-review the fix, flagging `confirmed()` for the human's attention at the `pr` gate.
30 changes: 30 additions & 0 deletions codev/projects/1201-support-kimi-code-cli-as-a-bui/status.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
id: '1201'
title: support-kimi-code-cli-as-a-bui
protocol: pir
phase: verified
plan_phases: []
current_plan_phase: null
gates:
plan-approval:
status: approved
requested_at: '2026-07-18T23:06:14.780Z'
approved_at: '2026-07-18T23:13:52.402Z'
dev-approval:
status: approved
requested_at: '2026-07-18T23:43:32.608Z'
approved_at: '2026-07-19T00:42:00.609Z'
pr:
status: approved
requested_at: '2026-07-19T00:51:39.674Z'
approved_at: '2026-07-19T00:55:09.990Z'
iteration: 1
build_complete: true
history: []
started_at: '2026-07-18T22:59:08.361Z'
updated_at: '2026-07-19T00:55:25.203Z'
pr_history:
- phase: review
pr_number: 1203
branch: builder/pir-1201
created_at: '2026-07-19T00:45:29.121Z'
pr_ready_for_human: false
18 changes: 16 additions & 2 deletions 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. 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
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; kimi has no role flag at all — builder-only, role delivered by the seed-session bootstrap (Issue #1201, see the Kimi subsection below)

**Three architect creation points** where role injection is applied:
- `tower-instances.ts` → `launchInstance()` (new project activation)
Expand All @@ -271,14 +271,28 @@ A `codev doctor` audit (`lib/framework-ref-audit.ts`) flags shell-fetch of frame

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

**Supported architect harnesses** (Issue #929): claude and codex are supported as architects, selected via `.codev/config.json` (`shell.architect` / `shell.architectHarness`) — the same config-driven mechanism builders use, and the *recommended* one. **Gemini is builder-only** — the Gemini CLI is retiring (#778), so it is not offered or affirmed as an architect (its `GEMINI_SYSTEM_MD` builder surface stays); `doctor` warns if `gemini` is configured as an architect. (agy, the gemini successor, is deferred as an architect to #1063 — its only role-injection channel is a visible first user turn.) 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 codex` / `TOWER_ARCHITECT_CMD=codex` / `--builder-cmd gemini` with no matching harness config still resolves the *non-claude* harness, not claude. (Before #929 it auto-detected from the raw config value only — an override launched the non-claude CLI 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). Codex reads project context (`AGENTS.md`) natively, so no architect context-file seam is needed; the `getArchitectFiles` seam #1059 added for gemini was removed with gemini's architect support.
**Supported architect harnesses** (Issue #929): claude and codex are supported as architects, selected via `.codev/config.json` (`shell.architect` / `shell.architectHarness`) — the same config-driven mechanism builders use, and the *recommended* one. **Gemini is builder-only** — the Gemini CLI is retiring (#778), so it is not offered or affirmed as an architect (its `GEMINI_SYSTEM_MD` builder surface stays); `doctor` warns if `gemini` is configured as an architect. (agy, the gemini successor, is deferred as an architect to #1063 — its only role-injection channel is a visible first user turn.) 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 codex` / `TOWER_ARCHITECT_CMD=codex` / `--builder-cmd gemini` with no matching harness config still resolves the *non-claude* harness, not claude. (Before #929 it auto-detected from the raw config value only — an override launched the non-claude CLI 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). **Kimi is builder-only too** (Issue #1201 — no system-prompt surface; seed-session bootstrap; see the dedicated subsection below). Codex reads project context (`AGENTS.md`) natively, so no architect context-file seam is needed; the `getArchitectFiles` seam #1059 added for gemini was removed with gemini's architect support.

> **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 case) and separable. Mitigation today: set an explicit `shell.architectHarness` / `shell.builderHarness` when using an unrecognized launcher command.

**Architect conversation resume is stored-id-only (#832 / #1145).** Every architect launch path (`launchInstance` main spawn, `add-architect` / sibling reconcile, both shellper restart-bake sites) resolves through `resolveArchitectLaunch`: a session id stored on the workspace-scoped architect row (minted at spawn, pinned via the harness's `session.newSessionArgs`) is resumed only after the harness's optional `session.verifyOwnership` confirms the session file still exists for this cwd (Claude: `~/.claude/projects/<encoded-cwd>/<id>.jsonl`, accepted under either the logical or physical form of a symlinked path). Anything else — no row, no stored id, missing file — spawns fresh with role injection and a newly minted, persisted id. `launchInstance`'s mtime-based jsonl-discovery fallback was **removed** by #1145: on a fresh workspace (`codev adopt` / first touch) it resumed whatever Claude conversation the user last held in that directory — hijacking personal sessions, roleless too, since the resume path skips role injection. Do not reintroduce discovery on any architect path; mtime cannot distinguish an architect's session from a newer personal one in the same cwd. Discovery (`HarnessProvider.buildResume`, newest jsonl by mtime) survives for **builder resume only** (`spawn.ts` `discoverResumeSession`), harness-gated to claude — the gating that fixes the 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.

**Architect role injection is centralized in `buildArchitectArgs`** (`tower-utils.ts`), the shared 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 the architect role is injected on **every** launch path, not just first-activation. (No architect context-file seam exists: claude/codex read project context natively; the gemini-only `getArchitectFiles` seam #1059 introduced was removed when gemini's architect support was dropped.)

#### Kimi Builder Harness (Issue #1201 — builder-only, seed-session bootstrap)

**Kimi (`kimi` — the Kimi Code CLI) is a supported BUILDER harness; architect use is unsupported** (stage 2 — `KIMI_HARNESS.buildRoleInjection` throws and `doctor` warns, so misconfiguration fails loudly instead of falling through to claude flags). Select via `shell.builder: "kimi"` / `shell.builderHarness: "kimi"` or `--builder-cmd kimi` (detection is override-aware per #929). Minimum supported version: **kimi 0.27.0**.

Kimi documents **no system-prompt flag and no positional prompt** (both exit 1), so the entire builder launch shape is provider-owned via the optional `HarnessProvider.buildBuilderLaunchScript` capability (only Kimi implements it; flag-shaped harnesses keep the generic scripts in `spawn-worktree.ts`). The generated script runs the **seed-session bootstrap**: (1) `kimi -p "<role + task briefing in an ack-and-wait wrapper>" --output-format stream-json` in the worktree; (2) the session id is captured from the `session.resume_hint` stream-json meta line and persisted to `.builder-kimi-session`; (3) the interactive TUI loops on `kimi -S <id> --yolo`, so role/task context **survives inner restarts** (stronger than the fresh-per-restart Claude loop). Seed failure (auth, network) exits before the loop — surfaced once, never restart-looped. The role rides a **user turn**, not a system prompt — the same weaker-authority tradeoff that deferred agy as an architect (#1063).

**Task delivery is readiness-gated and store-verified** (`servers/seed-kick.ts`): bytes written to the PTY during the ~5–15s seed window have no consumer and are silently lost, so the script prints `__CODEV_KIMI_SEED_DONE__ <id>` between seed and TUI, and Tower (armed via the `seedKick` field on `createTerminal`) waits for that sentinel + a grace period, writes the `BEGIN` kick, then confirms submission against the session store (`state.json.lastPrompt`), re-sending Enter → the kick → a loud warning on failure. Armed kicks are in-memory: a Tower restart during the seed window loses the kick (remediation: `afx send <builder-id> "BEGIN"`).

**Message pacing is per-harness** (`servers/message-pacing.ts` + `message-write.ts` `pacing.enterDelayMs`): Kimi's paste-detection window swallows an Enter sent 80ms after the body (the old default); Kimi targets get a ~1s delayed Enter. Resolution probes the worktree for `.builder-kimi-session` FIRST (override-proof for `--builder-cmd` spawns; survives Tower restarts) before falling back to the config-resolved harness.

**Builder resume is explicit-ID** (`KIMI_HARNESS.buildResume`): the ownership-verified `.builder-kimi-session` id, else the newest store session whose `state.json.workDir` exactly matches the worktree, else null → fresh-with-role re-seed (never a roleless fresh session; cwd-scoped `--continue` is deliberately not used). No `session` block exists — the architect stored-UUID contract requires mint-and-pin `newSessionArgs`, which Kimi cannot satisfy; generalizing that contract (async `seedSession` + async-buildable `CrashLoopFallback` per the task-Iptx spike addendum) is the stage-2 architect work.

**Caveats**: (a) the session store layout (`~/.kimi-code/sessions/wd_*/session_*/state.json`), and the `session.resume_hint` meta line are **undocumented, observed surfaces** — `codev doctor` pins kimi ≥ 0.27.0 and runs a session-store smoke probe that warns on layout drift; all discovery is fail-soft to the fresh path. (b) **No write-guard parity**: Kimi has no documented hook seam, so Kimi builders do NOT get the #1018 PreToolUse worktree write-guard — a Kimi builder can silently write outside its worktree; the documented "static deny rules" hint at a deny-rule surface outside the command reference (follow-up investigation, not a claimable guarantee). (c) Doctor's auth check is a **credential-artifact heuristic** (no documented status probe; no billed call is ever made).

#### 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
21 changes: 21 additions & 0 deletions codev/resources/commands/agent-farm.md
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,27 @@ Customize commands via `.codev/config.json` (project root):
}
```

### Builder harnesses

The builder CLI's role/prompt mechanics are handled by a harness, auto-detected
from the command basename (`claude`, `codex`, `gemini`, `opencode`, `kimi`) or
pinned explicitly via `shell.builderHarness`. Example — Kimi Code CLI as the
builder (builder-only; requires kimi >= 0.27.0, Issue #1201):

```json
{
"shell": {
"builder": "kimi"
}
}
```

Kimi builders use a seed-session bootstrap (role + task delivered via a
one-shot `kimi -p` call whose session the interactive TUI then resumes), so
context survives builder restarts. Note: Kimi has no hook seam, so Kimi
builders do NOT get the worktree write-guard Claude builders have (#1018).
Architect use of kimi and opencode is unsupported (claude or codex there).

### Language-Agnostic Porch Checks

By default, porch protocol checks use `npm run build` and `npm test`. Non-Node.js projects can override these via the `porch.checks` section in `.codev/config.json`:
Expand Down
Loading
Loading