Use the installed Distill CLI at ~/.agents/skills/.autopilot/bin/distill.
If ~/.agents/skills/.autopilot/distill.env exists, read it and use AUTOPILOT_DISTILL_BIN as the executable path. Otherwise use the stable path above.
Current Kimi Session Identity
Distill is session-bound. Before starting, resuming, submitting evidence, inspecting, or taking over a run, obtain one unambiguous runtime-native identity for the current Kimi session and pass it as --session-id "<kimi-session-id>".
Use this order:
- Inspect the current Kimi runtime trace. A Kimi session has a directory under
~/.kimi-code/sessions/.../session_<uuid>/; its global index is~/.kimi-code/session_index.jsonl, with lines shaped like{"sessionId":"...","sessionDir":"...","workDir":"..."}. EachsessionDircontainsstate.jsonwith fields such asworkDir,lastPrompt, andagents.main.homedir. - Match the current invocation to exactly one indexed
sessionDirby runtime-owned trace evidence: thestate.jsonworkDirmust match the current project directory,agents.main.homedirmust be inside thatsessionDir, andlastPromptor another Kimi-owned current trace value must match the current invocation prompt or unique invocation marker. Use that entry'ssessionId. - If the current agent homedir or trace path is directly known, match it to exactly one
sessionDirentry and use that entry'ssessionId. - If no runtime-owned evidence yields exactly one current Kimi session, fail closed. Do not guess from recency, title, current working directory alone, the newest entry in
session_index.jsonl, a user-provided non-runtime identifier, or a caller-injected environment variable.
Do not use a user-supplied KIMI_SESSION_ID, prompt-provided session id, or other custom session token as the Distill --session-id. The session id must be the native session_<uuid> from Kimi's own session_index.jsonl.
Report identity failure as: Distill cannot start because the current Kimi session identity is unavailable or ambiguous.
Start Or Resume
For an explicitly supplied text requirement, start or resume the run from the target project worktree:
"${AUTOPILOT_DISTILL_BIN:-$HOME/.agents/skills/.autopilot/bin/distill}" start --json --runtime kimi --session-id "<kimi-session-id>" --worktree "$PWD" --requirement "<explicit requirement text>"
For runtime-submitted intake, pass the Kimi-captured intake JSON instead of plain text:
"${AUTOPILOT_DISTILL_BIN:-$HOME/.agents/skills/.autopilot/bin/distill}" start --json --runtime kimi --session-id "<kimi-session-id>" --worktree "$PWD" --intake-json '<intake-json>'
When the CLI returns JSON, inspect run_id, stage, revision, next_action, and authorized_action. A same-session resume returns the same unfinished run. A different Kimi session must not advance it; cross-session rejection is enforced by the runner through the shared --session-id contract. A Kimi session may own one unfinished run; if the runner reports more than one unfinished run or a duplicate session binding, stop and report that state without choosing one.
Run To Boundary
Continue until the runner yields a terminal, waiting, blocked, or needs-reconciliation state. Every yield to the user must include run_id, stage, revision, next_action, and the required next command or executor.
Only invoke the executor named in authorized_action. Do not skip stages, reorder stages, or submit evidence for a stage other than the returned stage.
- If
next_actionisterminal, report the completion report paths and session release status. - If the runner state is
blocked, report the blocked reason and required recovery action. After recovery, resume with the same Kimi session identity and the returnedrevision. - If the runner state is
needs-reconciliation, do not retry publication blindly. Follow the runner's reconciliation instruction, verify the external tracker state, then resume with the returnedrevision.
Authorized Executors
If authorized_action.skill is grill-with-docs, invoke the unmodified grill-with-docs skill for the captured requirement. When that stage has enough information, submit completion evidence with the preserved checkpoint:
"${AUTOPILOT_DISTILL_BIN:-$HOME/.agents/skills/.autopilot/bin/distill}" submit-evidence --json --worktree "$PWD" --run-id "<run_id>" --session-id "<kimi-session-id>" --expected-revision "<revision>" --stage clarification --evidence '{"checkpoint":"clarification-complete","summary":"<clarification summary>","clarified_requirement":"<complete clarified requirement>","decisions":[],"accepted_assumptions":[],"material_unknowns":[],"domain_document_artifacts":[]}'
If authorized_action.skill is to-spec, invoke the unmodified to-spec skill. Submit the exact accepted PRD markdown and the testing-seam checkpoint:
"${AUTOPILOT_DISTILL_BIN:-$HOME/.agents/skills/.autopilot/bin/distill}" submit-evidence --json --worktree "$PWD" --run-id "<run_id>" --session-id "<kimi-session-id>" --expected-revision "<revision>" --stage prd --evidence '{"checkpoint":"testing-seam-confirmed","summary":"<PRD summary>","feature_slug":"<stable-lowercase-feature-slug>","prd_markdown":"<exact PRD markdown>"}'
If authorized_action.skill is to-tickets, invoke the unmodified to-tickets skill. Submit the exact accepted implementation issue payloads and approval checkpoint:
"${AUTOPILOT_DISTILL_BIN:-$HOME/.agents/skills/.autopilot/bin/distill}" submit-evidence --json --worktree "$PWD" --run-id "<run_id>" --session-id "<kimi-session-id>" --expected-revision "<revision>" --stage issues --evidence '{"checkpoint":"slice-breakdown-approved","summary":"<issue slicing summary>","issues":[{"title":"<issue title>","body":"<exact issue markdown>"}]}'
LOCAL_ISSUE_HANDOFF_CONTRACT
When docs/agents/issue-tracker.md configures Local Markdown, choose a stable lowercase feature_slug for the PRD evidence, use to-tickets to draft and approve the vertical slices, but stop before its tracker-publication step. The Distill runner is the sole local publisher: it creates the PRD at .scratch/<feature_slug>/PRD.md and each local issue exactly once under .scratch/<feature_slug>/issues/. Do not create a second issue copy elsewhere under .scratch/. The runner rejects a target path that already contains different content; never acknowledge that collision as immaterial drift.
Before submit-evidence, ensure every local issue body begins with agent-ready triage frontmatter:
---
Status: ready-for-agent
---
The exact Markdown including this frontmatter is the frozen issue payload. When the configured tracker is GitHub, keep the external publication and receipt flow below.
After every submit-evidence response, use the returned revision as the next --expected-revision.
Clarification completion is the agent's declaration, not a user checkpoint. Populate every structured field explicitly. Each material unknown must include description, material, resolved, and, when resolved, resolution; do not complete while a material unknown remains unresolved. For every glossary, domain document, or ADR changed by clarification, include its worktree-relative path and SHA-256 in domain_document_artifacts.
When the configured tracker is GitHub, to-spec and to-tickets perform the external creation. Include the confirmed receipt as external_publication on the PRD evidence or each issue object. The receipt must contain tracker: "github", the configured repository, the stable operation_id (<run_id>-r<revision>-prd or <run_id>-r<revision>-issue-<two-digit-index>), the SHA-256 of the exact frozen Markdown payload, status: "confirmed", the positive issue number as artifact_id, and its canonical artifact_url. The runner remains offline, validates this receipt, and never falls back to another tracker. If the response is needs-reconciliation, stop and follow required_next_action; do not invoke another skill or create a duplicate issue.
Takeover And Recovery
Same-session resume is the default. If a previous Kimi session is stranded and the user explicitly authorizes explicit takeover, use the shared runner takeover command:
"${AUTOPILOT_DISTILL_BIN:-$HOME/.agents/skills/.autopilot/bin/distill}" takeover --json --worktree "$PWD" --run-id "<run_id>" --from-session "<old-kimi-session-id>" --to-session "<current-kimi-session-id>" --expected-revision "<revision>" --reason "<user-authorized reason>" --user-authorized
Preserve the returned revision and continue run-to-boundary. Do not use takeover to bypass an ambiguous current Kimi session identity. Do not mutate .distill/ state directly.
Only after an explicit user instruction may the agent call abort, purge, or takeover; pass --user-authorized and the returned expected revision. Never infer that authority from a failure or from the user ending a conversation.
Reporting
Every user-visible yield should include:
run_idstagerevisionnext_actionauthorized_actionor terminal report paths- whether the Kimi session is still bound or released
On completion, report the canonical JSON report path, Markdown report path when rendered, published PRD and issue references, and session release.