Support Kimi Code CLI as a builder (PIR #1201)#1203
Conversation
…ilder and architect Seed-session bootstrap (kimi -p role seed -> capture session id from stream-json -> TUI resume via -S) validated end-to-end; solves role injection, initial prompt delivery, and the stored-ID session contract. Includes reproducible POC script and full impact map / test matrix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cluesmith#1149 parity requirement Two new observations: Kimi TUI never enters the alternate screen (no escape-based readiness signal), and PTY input during the seed window has no defined consumer (silently lost). Barrier design: sentinel + grace + store-verified delivery with retry; seed carries role+task, kick is a single BEGIN line. Architect parity correction: stored-ID resume without an async-buildable CrashLoopFallback is cap-exhaustion outage, not cluesmith#1149 safety — ship Codex-like (stage 1) or stored-ID + async fallback (stage 2), no middle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ipt, builder resume
- KIMI_HARNESS in harness.ts + detectHarnessFromCommand('kimi') — kills the
cluesmith#1062 false-Claude fallthrough; buildRoleInjection throws (builder-only)
- New optional HarnessProvider.buildBuilderLaunchScript capability; Kimi
generates the seed-session bootstrap script (idempotent seed via kimi -p
stream-json, session.resume_hint capture, sentinel, pinned -S --yolo loop)
- kimi-session-discovery.ts: store scan / ownership verify / state reader
(undocumented store layout, observed on kimi 0.27.0; fail-soft)
- buildResume: .builder-kimi-session precedence (ownership-verified) → store
scan → null → fresh-with-role fallback
- spawn-worktree branches on the capability; writes .builder-seed.txt and
passes the seedKick request through createPtySession
- Tests incl. the cluesmith#929-class regression: kimi + stale Claude jsonl never
yields --resume <claude-uuid> or --append-system-prompt
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ss Enter pacing - seed-kick.ts: readiness barrier — waits for the launch script's __CODEV_KIMI_SEED_DONE__ sentinel (writes during the seed window are silently lost), grace, then a store-verified BEGIN kick with an Enter-resend → kick-resend → loud-warn retry ladder - createTerminal grows an optional seedKick field (core SeedKickRequest); handleTerminalCreate validates and arms it (malformed → ignored) - message-write.ts: optional pacing.enterDelayMs overriding both default Enter delays (Kimi swallows an 80ms Enter; defaults unchanged otherwise) - message-pacing.ts: resolves pacing per target — worktree marker probe first (override-proof for --builder-cmd spawns, survives Tower restarts), then config-resolved harness by terminal role - Wired at all delivery paths: send direct + buffered, cron Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…store smoke probe - Kimi in AI_DEPENDENCIES: kimi --version presence with minVersion 0.27.0 (pins the version the undocumented surfaces were observed against) - verifyKimi(): credential-artifact heuristic (no billed probe — Kimi documents no auth status command), kimi login guidance; supplementary 'kimi doctor' config check (documented exit codes, not an auth check) - Session-store layout smoke probe warns loudly on drift - Architect-shell branch: kimi configured as architect → builder-only warning Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mples, skeleton mirror) - arch.md: dedicated Kimi subsection (builder-only, seed-session bootstrap, sentinel-gated store-verified BEGIN, per-harness pacing, explicit-ID resume, undocumented-surface caveats + 0.27.0 pin, NO write-guard parity) - agent-farm.md (instance + skeleton): builder-harness config examples Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on session type - resolvePacingForSession wraps its whole body in try/catch: pacing is advisory and must never break message delivery (a missing DB in the tower-routes test env surfaced this as 500s on /api/send) - CronDeps session shape carries id/cwd (the real PtySession provides both) - tower-routes test mock gains getTerminalSessionById Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bisected on kimi 0.27.0: 80ms and 100ms swallowed; 120/250/500/1000ms submit. Threshold ~100-120ms; shipped value stays 1000ms (~9x margin). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s pass) codev/spikes/pir-1201-kimi-builder-demo.mjs runs the real dist modules (script generator, armSeedKick, writeMessageToSession, buildResume) against a real kimi PTY: seed bootstrap, sentinel-gated store-verified BEGIN, multiline delivery at the pinned Enter delay, inner-restart context retention, and -S resume. Executed against kimi 0.27.0 — 5/5 PASS; the ack-and-wait-with-task seed discipline held (no fallback needed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ier) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… consultation finding) The delivery check used lastPrompt.includes(kickMessage) — but on a fresh spawn lastPrompt initially holds the SEED prompt, whose ack-and-wait wrapper itself mentions BEGIN, so the verifier reported success before the kick ever submitted (silently defeating the swallowed-Enter recovery; the live demo's happy path masked it). Confirmation now requires whitespace-normalized EQUALITY (submitted messages land in lastPrompt with newlines flattened to spaces — observed on kimi 0.27.0). Two pinning regression tests added; live demo re-run post-fix: 5/5 PASS. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Architect Integration ReviewContributor-side review summary for maintainers (this PR was developed under the PIR protocol on our fork; we do not merge — that call is yours). Process: Plan and dev-approval were human-gated pre-PR. The dev-approval gate included a full-path live demo through a locally installed build — a real Consultation (CMAP, single advisory pass): gemini APPROVE, claude APPROVE, codex REQUEST_CHANGES. The codex finding was real and was accepted + fixed in 732f04b: seed-kick delivery confirmation was a substring match on Architect verification of the post-CMAP fix (since PIR's single-pass consultation does not re-review fixes): I reviewed Scope: verified against issue #1201's builder-MVI checklist — no architect-parity changes ( Architect integration review |
… for maintainers Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cepted+fixed) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
PIR Review: Support Kimi Code CLI as a builder
Fixes #1201
Summary
Adds the Kimi Code CLI (
kimi, ≥ 0.27.0) as a supported builder harness —shell.builder: "kimi"/builderHarness: "kimi"/--builder-cmd kiminow produce a working builder instead of the #1062 false-Claude fallthrough (which appended--append-system-promptand a positional prompt, both rejected by kimi, and could route a stale Claude--resume <uuid>into it). Because Kimi documents no system-prompt flag and no positional prompt, the launch shape is provider-owned: a seed-session bootstrap (validated by spike task-Iptx) delivers role + task via a one-shotkimi -pwhose captured session id pins akimi -S <id> --yoloTUI loop, with a Tower-side readiness barrier (sentinel-gated, store-verifiedBEGINkick) and a per-harness delayed-Enter pacing knob soafx sendactually submits. Kimi as an architect is explicitly out of scope (stage 2).Files Changed
git diff --stat $(git merge-base main HEAD)(excluding porch state commits):packages/codev/src/agent-farm/utils/harness.ts(+263) —KIMI_HARNESS, detection,buildBuilderLaunchScript/seedDelivery/messagePacinginterface capabilities,buildResumepackages/codev/src/agent-farm/utils/kimi-session-discovery.ts(+197, new) — store scan / ownership verify / state reader (fail-soft;KIMI_CODE_HOME-aware)packages/codev/src/agent-farm/commands/spawn-worktree.ts(+111/−9) — provider-owned script branch,.builder-seed.txt,seedKickpass-throughpackages/codev/src/agent-farm/servers/seed-kick.ts(+194, new) — sentinel watcher + grace + store-verified kick retry ladderpackages/codev/src/agent-farm/servers/message-pacing.ts(+55, new) — per-target pacing resolution (worktree-marker probe first, config-resolved harness fallback)packages/codev/src/agent-farm/servers/message-write.ts(+16/−2) — optionalpacing.enterDelayMsoverridepackages/codev/src/agent-farm/servers/tower-routes.ts(+20/−2) —seedKickon terminal create; pacing at both send pathspackages/codev/src/agent-farm/servers/tower-cron.ts(+6/−2) — pacing at cron deliverypackages/core/src/tower-client.ts(+24) —SeedKickRequestwire type oncreateTerminalpackages/codev/src/agent-farm/lib/tower-client.ts(+1) — re-exportpackages/codev/src/commands/doctor.ts(+110/−2) — kimi presence/minVersion, auth heuristic,kimi doctorconfig check, store smoke probe, architect-kimi warningkimi-session-discovery.test.ts,seed-kick.test.ts,message-pacing.test.ts; extendedharness.test.ts,spawn-worktree.test.ts,config.test.ts,discover-resume-session.test.ts,bugfix-584-send-multiline-pacing.test.tscodev/resources/arch.md(+16/−2, dedicated Kimi subsection),codev/resources/commands/agent-farm.md+codev-skeleton/resources/commands/agent-farm.md(builder-harness config examples — skeleton mirrored)codev/spikes/pir-1201-kimi-builder-demo.mjs(+193, new) — runnable live-demo driver (real kimi, real dist modules)codev/plans/1201-…md,codev/state/pir-1201_thread.mdTotal: 27 files, +2378/−23.
Commits
2cf424c1[PIR Support Kimi Code CLI as a builder #1201] Kimi harness: detection, seed-session launch script, builder resume8e86c411[PIR Support Kimi Code CLI as a builder #1201] Tower: sentinel-gated BEGIN delivery + per-harness Enter pacing3d407856[PIR Support Kimi Code CLI as a builder #1201] doctor: kimi presence, truthful auth heuristic, store smoke probef0754430[PIR Support Kimi Code CLI as a builder #1201] Docs: kimi builder harness (arch.md + config examples, skeleton mirror)b27e2d38[PIR Support Kimi Code CLI as a builder #1201] Pacing resolution is fully best-effort; widen cron session typeea6607c6[PIR Support Kimi Code CLI as a builder #1201] Pin Kimi Enter delay with live bisect evidence6b39ca5c[PIR Support Kimi Code CLI as a builder #1201] Live demo driver + results (all 5 checklist steps pass)d49c292bplan draft and porch state commits)Test Results
pnpm build: ✓ pass (types → core → codev, incl. dashboard + skeleton copy)pnpm test(vitest): ✓ pass — 3592 passed, 48 skipped (~75 new tests). Porch's build/tests checks green at both the dev-approval and review transitions.codexas an architect #929-class regression covered from four angles:kimi+ a stale Claude.jsonlcan never yield--resume <claude-uuid>or--append-system-prompt(harnessbuildResume,discoverResumeSession, config/override resolution, generated-script assertions).KIMI_ENTER_DELAY_MS = 1000(~9x margin; latency-only cost).node codev/spikes/pir-1201-kimi-builder-demo.mjs): 5/5 PASS — seed bootstrap + id capture; sentinel-gated store-verified BEGIN (lastPrompt="BEGIN"); multiline delivery at pinned delay; inner-restart context retention (role token + task recalled verbatim after killing the TUI);buildResumereturns the pinned id. The spike addendum's open question — does ack-and-wait hold with a task attached? — held; the pre-planned role-only-seed fallback was not needed.afx spawnthrough Tower (branch build via local-install); all 4 checklist items passed live.Architecture Updates
Routed to the COLD tier (
codev/resources/arch.md, updated in commitf0754430): a dedicated "Kimi Builder Harness (Issue #1201)" subsection under Agent Farm Internals — builder-only status, the seed-session bootstrap, the sentinel + store-verified BEGIN barrier, per-harness pacing with the marker-probe resolution order, explicit-ID resume, and the caveats (undocumented store surfaces + 0.27.0 pin + doctor smoke probe; no write-guard parity — Kimi has no documented hook seam; in-memory kick lost on Tower restart during the seed window). The harness enumeration lines in the same section were extended.No HOT tier (
arch-critical.md) change: kimi support is subsystem detail, not a top-10 always-on system-shape fact; the existing hot facts (runtime resolution, dual-tree mirroring, porch/state invariants) already cover the decision surface this touches.Lessons Learned Updates
Routed to the COLD tier (
codev/resources/lessons-learned.md, Architecture section, this commit):/api/sendin the test env; the whole body now degrades to defaults..builder-kimi-sessionmakes pacing correct for--builder-cmdoverride spawns across Tower restarts with zero schema migration.No HOT tier (
lessons-critical.md) change: both lessons are architecture-pattern reference material, not behavior-changing cross-cutting rules of the always-on caliber (the cap is full of broader rules that would each beat these on displacement).Things to Look At During PR Review
lastPrompt.includes(kickMessage). Real defect: on a fresh spawnlastPromptinitially holds the seed prompt, whose ack-and-wait wrapper itself says "wait for BEGIN" — so the substring check reported success before the kick ever submitted, silently defeating the swallowed-Enter recovery (the live demo's happy path masked it: the kick genuinely landed, so the false-positive window was never observed). Fixed inseed-kick.tsby requiring whitespace-normalized equality (submitted messages land inlastPromptwith newlines flattened to spaces — observed), with two pinning regression tests (seed-prompt-containing-BEGIN must NOT confirm and must escalate to the Enter re-send; a multi-line kick payload must still confirm through the flattening). Gemini and Claude both returned APPROVE; PIR's consultation is single-pass, so this fix was not independently re-reviewed — please eyeballconfirmed()inseed-kick.tsat theprgate. The live demo was re-run after the fix: still 5/5 PASS (no false negative).seed-kick.tsretry ladder semantics:updatedAtmovement is deliberately NOT trusted as confirmation (the TUI touches the store on open, which would false-positive and suppress the Enter re-send). A false negative only costs a duplicate BEGIN + loud warn.message-pacing.tsresolution order: marker probe before config, by design (override robustness — see plan-review note). The probe stats one file per message send; sends are rare, so no perf concern.sessions/*/*/state.json(notsession_index.jsonl— one undocumented surface instead of two); every reader is fail-soft to the fresh-with-role path; doctor carries the drift probe.kimiTuiCmdappends--yolounless the user already passed it;--autois deliberately never used (documented conflict with--yolo; suppresses agent→user questions the gate workflow needs).-pdocs is flagged as follow-up investigation, not a claimed guarantee.kimiStoreLayoutLooksDrifted, discovery readers) are unit-tested in the discovery suite.How to Test Locally
pir-1201→ View Diff (orgh pr diff).pnpm buildthennode codev/spikes/pir-1201-kimi-builder-demo.mjs— requires an authenticatedkimi≥ 0.27.0; prints PASS/FAIL for all five checklist steps.pnpm -w run local-install(restarts Tower), then from the main workspace root:afx spawn --task "any small task" --builder-cmd kimi→ watch seed →__CODEV_KIMI_SEED_DONE__→ BEGIN in the builder pane;afx send <builder-id>with a >3-line message → submits as one message; kill the TUI (Ctrl+Conce) → restart resumes with context;afx spawn --resumeafter killing the terminal.codev doctorwith kimi installed → presence + version gate, heuristic auth line, smoke probe; withshell.architect: "kimi"→ builder-only warning.Maintainer note: please add the
area/towerlabel to issue #1201 (we can't set labels cross-fork).