Closed-loop automation across semcod/* repositories.
Project description
koru
AI Cost Tracking
- ๐ค LLM usage: $14.5713 (245 commits)
- ๐ค Human dev: ~$7908 (79.1h @ $100/h, 30min dedup)
Generated on 2026-05-21 using openrouter/qwen/qwen3-coder-next
Python package for closed-loop refactor automation across multi-repo
workspaces (validated on semcod/*, maskservice/c2004, and other monorepos).
The name refers to Koru (Mฤori spiral), matching the "spiraling loop" refactor flow: detect โ plan โ execute โ verify โ heal โ repeat.
What koru is
A meta-orchestrator that coordinates LLM-augmented refactor tools with ticket-driven workflow and regression-free verification:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ KORU โ
โโโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโฌโโโโโโโโโโโค
โ DETECT โ PLAN โ EXECUTE โ VERIFY โ HEAL โ LEARN โ
โโโโโโโโโโโโผโโโโโโโโโโโผโโโโโโโโโโโผโโโโโโโโโโโผโโโโโโโโโโผโโโโโโโโโโโค
โ redup โ planfile โ Windsurf โ regix โ healing โ pyqual โ
โ regix โ tickets โ Cursor โ pytest โ webhook โ metrics โ
โ TestQL โ Promet. โ aider โ TestQL โ retry โdashboardsโ
โ Probe โ Alertmgr โ vallm โ vallm โ โ โ
โโโโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโโโดโโโโโโโโโโโ
โ โ
โโโโโโโโโโโโ closed-loop feedback โโโโโโโโโโโโโโโโโโ
Quick start โ start an LLM session in 3 commands
cd /path/to/your/project
pip install koru
koru --init # 1. set up .planfile/ + .koru/ + .gitignore
koru # 2. print the LLM brief (paste into Cascade/Cursor/aider)
koru --queue --loop # 3. drain the queue (the agent works on each ticket)
That is the entire onboarding. koru (no args) is the command an LLM
agent runs at the start of every session โ the markdown brief it
prints contains the active ticket, the policy gates, and the exact
planfile ticket โฆ commands the agent is allowed to use. Nothing
else needs to be memorised.
If the project is not initialised yet, koru (no args) detects this
and prints a โ Setup required section with the exact koru --init
command to run โ the LLM never has to guess.
Fast local startup (existing repo)
python -m venv .venv
. .venv/bin/activate
python -m pip install -U pip
python -m pip install -e ".[dev]"
# verify which build this shell is using
koru --version
which koru
# smoke-run one autonomous cycle (no IDE injection)
koru autonomous up --project . --max-cycles 1 --sleep-seconds 0 --no-autopilot
# start dashboard even if 8765 is already occupied
koru serve --project . --auto-port --no-open
Use explicit up for compatibility (koru autonomous up --project .),
especially when switching between local source checkouts and older PyPI builds.
Installation extras
The base package stays intentionally small (pyyaml plus stdlib-based CLI/API).
Install only the lanes you are working on:
pip install "koru[watch]" # WebSocket queue watcher
pip install "koru[dev]" # tests, lint, typing, local quality tooling
pip install "koru[api]" # FastAPI healing webhook service
pip install "koru[agent]" # LLM / structured-output integrations
pip install "koru[obs]" # tracing, Sentry, structured logging
pip install "koru[queue]" # optional Redis/scheduler queue adapters
pip install "koru[quality]" # deeper refactor quality gates
pip install "koru[all]" # local workstation with every optional lane
koru autopilot and the IDE control-plane socket protocol are part of the
base package; see docs/IDE_PROTOCOL.md for the
formal plugin/daemon wire contract.
Structured stdio (NDJSON / JSON Lines)
koru autonomous up defaults to human-readable logs. For versioned,
pipe-friendly control-plane records (CQRS-style commands/events on
stdout), use:
koru autonomous up --project . --max-cycles 1 --sleep-seconds 0 --emit-events jsonl --no-autopilot \
2>/dev/null | jq -c .
Or set KORU_STDIO_FORMAT=jsonl so the default matches (still overridable
with --emit-events human). In jsonl mode, incidental status lines go to
stderr so stdout stays one JSON object per line. JSON Schema:
schemas/koru-stdio-event.schema.json. Event type values include
SessionStarted, CycleStarted, ScanCompleted, ScanSkipped,
QueueIteration, DiagnosticsCompleted, WupHealthChanged,
PostRunVerifyCompleted, PostRunVerifyIdeCompleted, QueueStaleReleased,
AutopilotDecision, CycleCompleted, and AutonomousStopped.
Post-run verify (closed loop after done)
Projects can declare regression gates in root koru.yaml under
queue.post_run_verify. koru autonomous up runs them after the queue
closes tickets and after the IDE marks tickets done in planfile (status
poll โ not chat readback). See docs/post-run-verify.md.
Quick troubleshooting
| Symptom | Fix |
|---|---|
koru autonomous: ... invalid choice: '.' (choose from 'up') |
Run koru autonomous up --project . |
koru serve: cannot bind 127.0.0.1:8765 |
Run koru serve --auto-port or free the port via ss -ltnp | rg 8765 then kill <pid> |
| CLI seems to ignore freshly installed version | Run koru autopilot manage --ide vscode; compare PATH koru, repo koru, source and package; prefer .venv/bin/koru in project-local workflows |
| VS Code/VSCodium/Cursor/Windsurf plugin is installed but not connected | Run KORU_AUTOPILOT_INSTANCE=vscode koru autopilot manage --ide vscode (or vscodium/cursor/windsurf), then start the daemon/reload the IDE/run koru: Connect autopilot daemon |
| Live plugin keeps reconnecting as an old version | koru auto now rejects stale plugin versions by default. Run koru autopilot manage --ide vscode; if it reports plugin_live_host_stale, reload the IDE window, then run koru: Connect autopilot daemon |
goal -a takes too long to fail |
Keep strategies.python.test fail-fast (--maxfail=1) for quick feedback; run full suite explicitly when needed |
goal -a: No module named 'costs' |
Install dev extras: pip install -e ".[dev]", or set [tool.costs] badge = false in pyproject.toml |
goal -a unstages .code2llm_cache/*.pkl |
Ensure .code2llm_cache/ is in .gitignore (not per-file pickle lines) |
Topology & pipelines โ what is active right now
If you want a live answer to:
- which systems/tools are active (
regix,testql,wup,redup,sumr, โฆ), - which pipelines are enabled (
idle-diagnostics,gate:regix,scan:on-change,autoloop:queue,autopilot:drive), - and how they are connected,
use topology mode:
# terminal view
koru topology
koru topology --format json
# toggle one component or pipeline
koru topology --disable redsl
koru topology --enable-pipeline gate:sumr
# predicate (exit 0/1)
koru topology --is-enabled gate:regix
koru topology --enabled-components-for idle-diagnostics
State is persisted in .koru/topology.yaml.
Dashboard (koru serve) now includes a Topology & pipelines panel with
checkboxes. Toggling a checkbox updates .koru/topology.yaml via
POST /api/topology.
These flags are honored by runtime behavior:
scripts/koru-autoloop.shrespects pipeline toggles for scan/queue/idle-diagnostics/autopilot,- quality tasks (
quality:regix,quality:redup,quality:sumr:*) skip when the matching topology pipeline is disabled.
Diagnostics โ koru --doctor
When something feels off (LLM stuck, queue runner refusing, policy not taking effect), run:
koru --doctor # human-readable PASS/WARN/FAIL list
koru --doctor --format json # machine-readable for the LLM itself
koru --doctor --fix # read-only guided repair commands
The doctor probes project, planfile, policy, topology, autonomous env,
agent-backend, CI, and pytest-collection health. It never writes anything.
Exit code is 1 if any check fails, 0 if only warnings (warnings are
advisory). Use it after koru --init and whenever a session starts
mis-behaving. For the full repair checklist, see
docs/autodiagnostics-auto-repair.md.
Natural-language intake and housekeeping are built in:
koru task "Dodaj feature importu raportรณw"
koru agent --list # show Windsurf/Cursor/Claude Code/aider/OpenRouter lanes
koru agent # print and save the current LLM handoff prompt
koru agent --launch # launch the best available CLI agent when possible
koru scan # auto-generate tickets from repo signals (TODOs, pytest errors)
koru scan --apply # create the proposed tickets in planfile
koru gc # preview stale tickets eligible for cleanup
koru gc --apply # delete old done/failed/blocked tickets
koru gate authorize PLF-070 --mode advisory --reason "..." # record a gate waiver
The no-args koru prompt includes detected project markers
(pyproject.toml, package.json, Taskfile.yml, .windsurf/, .cursor/,
.planfile/), available LLM/IDE lanes, the recommended agent, the active
ticket, and the exact lifecycle commands the agent may use.
Autopilot โ drive your IDE from the terminal
koru autopilot lets a terminal-side koru take over the LLM chat in
Windsurf / VS Code / VSCodium / Cursor / JetBrains / Zed: it types the next ticket
brief directly into the chat panel and presses submit, with zero
clicks. Useful when an in-IDE session ends and you want koru to
continue the loop from a separate terminal (or tmux pane, or SSH).
# 0) make this shell deterministic
koru --version
which koru
# Choose one instance when several IDEs are open.
# Common values: vscode, vscodium, cursor, windsurf, jetbrains, zed.
export KORU_AUTOPILOT_INSTANCE=vscode
# 1) verify host backends, IDE detection and install state
koru autopilot doctor
koru autopilot doctor --fix
koru autopilot ide-list
koru autopilot manage --ide vscode
# VS Code and VSCodium intentionally use separate identities and sockets:
# /run/user/$UID/koru-autopilot-vscode.sock
# /run/user/$UID/koru-autopilot-vscodium.sock
# guided host setup (optional apt auto-install for xdotool/wtype/ydotool)
koru autopilot setup-host
koru autopilot setup-host --install --dry-run
koru autopilot setup-host --install
# install/reassert the VS Code-family plugin and socket setting
koru autopilot manage --ide vscode --fix --dry-run
koru autopilot manage --ide vscode --fix
# 2) run daemon (recommended long-running setup via systemd --user)
koru autopilot install-unit
systemctl --user daemon-reload
systemctl --user enable --now koru-autopilot.service
# fallback: run daemon in a terminal/tmux pane
koru autopilot daemon --project "$(pwd)"
# 3) after IDE reload: connect plugin and verify live runtime
# Command Palette in IDE: "koru: Connect autopilot daemon"
koru autopilot status
koru autopilot manage --ide vscode
# 4) inject into IDE chat through the daemon/plugin path
koru autopilot handoff --project "$(pwd)" --ide vscode --require-plugin
koru autopilot drive --ide vscode --require-plugin 'continue with the next ticket'
koru autopilot tail -n 50
# Strict runtime gate for one-off drive commands:
# block drive if the connected plugin version is stale.
KORU_STRICT_PLUGIN_VERSION=1 KORU_STRICT_PLUGIN_ACK=1 \
koru autopilot drive --ide vscode --require-plugin 'probe strict plugin version'
# Optional: coordinate fallback (global focus+click+type), bypassing daemon.
koru autopilot calibrate --ide vscode
koru autopilot drive --direct --os-profile vscode --prompt 'continue with the next ticket'
koru autopilot drive --direct --os-profile vscode --delay-seconds 5 \
--prompt 'continue with the next ticket'
# Multi-IDE session bootstrap: calibrate each IDE + immediate smoke prompt.
koru autopilot session-start --ides auto --delay-seconds 5
# If PATH points to an older installed koru, run from source checkout:
PYTHONPATH=src python -m koru.cli autopilot calibrate --ide vscode --delay-seconds 8
# Autonomous loop. `koru auto` enables strict plugin version + ACK policy by default
# and skips chat drive until a compatible live plugin is connected.
koru auto
koru autonomous up --project .
# phase-1 tool coverage detection (registry-backed)
koru tools detect
koru tools detect --format json
# phase-2 tool adapter scaffold ticket
koru task "Prepare Gemini adapter" --project . --tool gemini-cli
# phase-3 native lane launchers
koru agent --agent gemini-cli --project . --launch
koru agent --agent cline --project . --launch
koru agent --agent qwen-code --project . --launch
koru agent --agent opencode --project . --launch
# machine-readable agent readiness report
koru agent --project . --list --format json
# non-invasive smoke test (daemon routing + IDE autodetect, no real key injection)
scripts/autopilot-ide-autodetect-smoke.sh --require-running-ide
scripts/autopilot-ide-autodetect-smoke.sh --check-ide jetbrains --check-ide windsurf
Newer autopilot functions you can use directly from CLI:
koru autopilot handoffโ build current koru brief and inject it in one shot.koru autopilot manageโ inventory/repair the active installation:korubinary, daemon socket, installed plugin, connected plugin and expected VSIX version.koru autopilot install-unitโ installsystemd --userunit for persistent daemon.koru autopilot tailโ read persistent autopilot audit log (text or JSON).
koru autopilot manage reports the plugin state as:
connected/versionโ the live plugin currently attached to the daemon,installedโ the extension version reported by the editor CLI,expectedโ the VSIX/package version bundled with the active koru runtime.
If installed=expected but connected=False, installation is healthy and the next
step is runtime handshake: start the daemon, reload the IDE window and run
koru: Connect autopilot daemon. If the daemon recently rejected old live plugin
versions, manage reports plugin_live_host_stale; the extension is installed on
disk, but the editor's live extension host still needs a reload. koru auto
enables strict plugin version and strict submit ACK policy by default, so it skips
chat drive instead of sending prompts through a stale or unverifiable plugin.
Two injection paths, picked automatically:
- IDE plugin โ if
plugins/koru-autopilot-vscode/is loaded in the editor, the daemon forwardschat.sendto it and the extension pastes + submits via the editor's own API. Most reliable; works on Wayland. Runtime version drift is rejected bykoru auto; one-offkoru autopilot drivecan opt into the same behavior withKORU_STRICT_PLUGIN_VERSION=1 KORU_STRICT_PLUGIN_ACK=1. - Keyboard simulation โ fallback for editors without the plugin.
Uses
xdotoolon X11,wtype/ydotoolon Wayland.
- Start here:
docs/autopilot-quickstart.mdโ 30-second setup, full checklist, common pitfalls, security model. - Architecture & wire protocol:
docs/autopilot-design.md. - Formal IDE protocol (normative + operational):
docs/IDE_PROTOCOL.md. - Normative wire contract
v1(API table/spec):docs/specs/kide-002-koruide-api-v1.md. - What is shipped vs. planned:
docs/autopilot-roadmap.md.
Windsurf autonomous mode (hours, unattended)
If you want koru + Windsurf to keep working for hours with minimal human input,
use the built-in autoloop wrapper.
1) Prepare once per machine
# verify keyboard/plugin path
koru autopilot doctor
koru autopilot manage --ide windsurf
# recommended persistent daemon setup
export KORU_AUTOPILOT_INSTANCE=windsurf
koru autopilot install-unit
systemctl --user daemon-reload
systemctl --user enable --now koru-autopilot.service
Install and enable the VS Code/VSCodium/Windsurf/Cursor plugin from
plugins/koru-autopilot-vscode/ for the most
reliable injection path on Wayland. Use koru autopilot manage --ide windsurf --fix
to install or reassert the bundled VSIX and write the socket setting.
2) Start autonomous loop in project root
cd /path/to/project
task queue:autoloop
After pip install koru, you can bootstrap + run autonomy in one command
(no Taskfile required):
cd /path/to/project
KORU_AUTOPILOT_INSTANCE=windsurf koru autonomous up
Useful variants:
# safest diagnostic pass (queue only, one cycle, no IDE drive)
koru autonomous safe-up --project .
# smoke run (single cycle)
KORU_AUTOPILOT_INSTANCE=windsurf koru autonomous up --max-cycles 1 --sleep-seconds 0
# long-running 24/7 mode with explicit actor + queue
KORU_AUTOPILOT_INSTANCE=windsurf koru autonomous up \
--actor koru-bot --queue-name default --sleep-seconds 30
# queue-only mode (no autopilot injection)
koru autonomous up --no-autopilot
What each iteration does:
koru scan --applykoru --queue --loop --max-iterations ...koru autopilot drive --ide "$KORU_AUTOPILOT_INSTANCE" --require-plugin "continue with the next ticket"- sleep (
SLEEP_SECONDS, default120)
This loop is resilient by design: if one step fails, it logs the error and
continues next iteration. Autopilot drive is fail-closed by default: when the
live plugin is missing, stale, or cannot confirm submit with a strict ACK, the
cycle records autopilot=skipped(...) or autopilot=failed instead of using a
Wayland keyboard fallback with the wrong focus.
3) Useful long-run overrides
# faster cadence
task queue:autoloop SLEEP_SECONDS=30 MAX_ITERATIONS=100
# single execution queue only
task queue:autoloop QUEUE_NAME=default
# include interactive handling of human tickets
task queue:autoloop ENABLE_INTERACTIVE=true
# queue-only mode (without autopilot ping)
task queue:autoloop ENABLE_AUTOPILOT_DRIVE=false
4) Monitor while it runs
KORU_AUTOPILOT_INSTANCE=windsurf koru autopilot status
KORU_AUTOPILOT_INSTANCE=windsurf koru autopilot manage --ide windsurf
koru autopilot tail -n 200
journalctl --user -u koru-autopilot -f
Related docs:
docs/autopilot-quickstart.mddocs/cli-examples.mdscripts/koru-autoloop.shdocs/agent-guide.mddocs/ide-router.mdโkoru ide-router, headless vs IDE mergedocs/ide-control-surfaces.mdโ MCP, autopilot, RPC, DAP, profiles
Two operational modes
| Mode | When | What runs |
|---|---|---|
| Default: IDE-native | normal ticket work, no external API | Windsurf/Cursor LLM + task tickets:next + regix/pytest |
| Opt-in: OpenRouter automation lane | infra smoke tests, headless auto-fix, scheduled runs | redsl improve, llx fix, vallm validate --semantic (all use OpenRouter) |
Install (editable)
pip install -e .
Multi-repo loop mode
Run one command across matching repositories and retry failures in a closed loop:
koru \
--workspace /path/to/repos \
--include "semcod/*" \
--command "python -m pytest -q"
Or use Taskfile
task # list all tasks (40+)
task install # pip install -e .
task ci # local CI equivalent: lint + tests
task install:tools # semcod toolchain: planfile, wup, testql, regix, redup, ...
task tickets:next # highest-priority open ticket
task queue:run # execute one runnable planfile queue task
task queue:dry-run # preview the next planfile queue task
task queue:watch # watch planfile WebSocket queue events
task queue:autoloop # unattended scan+queue+autopilot loop
task quality:semcod:planfile # semcod gates -> deduplicated planfile tickets
task quality:regix # regression metrics gate
task quality:redup # duplicate detection
task template:install # bootstrap configs in current dir
task webhook:run # start healing-webhook on :8810
Full examples: docs/cli-examples.md
Planfile queue runner
koru can execute one runnable planfile ticket at a time, or drain
the entire queue in a single call:
# Single tick (legacy, default):
koru --queue --project . --actor koru-shell
# Drain everything:
koru --queue --project . --loop --max-iterations 50
# Drain shell tickets AND answer humans interactively in one shot:
koru --queue --project . --loop --interactive --actor c2004-koru
# Preview without execution:
koru --queue --project . --dry-run
By default koru uses the current Python environment's planfile module when
available, then falls back to the planfile executable in PATH. To pin a
specific command:
KORU_PLANFILE_CMD="python -m planfile.cli" koru --queue --project .
Supported executor kinds:
executor.kind: shellโ claim, start, runinputs.scriptorexecutor.handler, then complete or fail the ticket.executor.kind: apiโ claim, start, callinputs.api_endpoint(orexecutor.handler) withinputs.api_method,inputs.api_headers,inputs.api_body, then complete or fail the ticket.executor.kind: llmโ claim, start, POSTinputs.promptto an OpenAI-compatible chat-completion endpoint (default OpenRouter), capture the assistant's text as the ticket'sstdout, and storellm_model+ tokenusagein the result-json. Configure viaOPENROUTER_API_KEY/OPENAI_API_KEY/KORU_LLM_ENDPOINT. Seedocs/cli-examples.mdfor the full schema.executor.kind: humanโ print the prompt and leave the task for an operator. With--interactive, koru collects the answer on stdin (multi-line, Ctrl-D submits, Ctrl-C cancels) and completes the ticket itself.
The remaining executor kind (mcp) is intentionally reported as
unsupported until its adapter is wired (Phase 5).
Minimal API ticket:
tickets:
PLF-010:
name: "Notify deployment API"
status: open
priority: high
executor:
kind: api
mode: automatic
execution:
queue: default
state: ready
inputs:
api_endpoint: "http://localhost:8810/probe-failure"
api_method: POST
api_headers:
content-type: application/json
api_body:
source: koru
To watch queue changes streamed by the planfile API:
uvicorn planfile.api.server:app --reload --port 8000
koru --watch --ws-url ws://localhost:8000/ws
task queue:watch
For transparent management-layer logs in a dashboard, point koru at the planfile event-ingest endpoint:
export KORU_EVENTS_URL="http://localhost:8000/events/ingest"
koru --queue --project . --dry-run
When configured, koru emits best-effort management.event entries for
koru.bootstrap, koru.queue, koru.watch, and repository loop runs. This is
intended for UI surfaces such as planfile's Live Events panel and does not
change queue execution semantics.
watch support uses the optional websockets package. Install it with:
pip install "koru[watch]"
Queue garbage collection โ koru gc
Over time, completed and failed tickets accumulate in the sprint YAML.
koru gc cleans them up:
koru gc # dry-run: preview what would be removed
koru gc --apply # actually delete stale tickets
koru gc --max-age 7 # only keep tickets younger than 7 days
koru gc --keep-last 5 # always keep the 5 newest done tickets
koru gc --status done,failed # only clean these statuses (default: done,failed,blocked)
koru gc --no-archive # skip JSONL archive before deletion
koru gc --format json # machine-readable output
Before deletion, tickets are archived to
.planfile/.koru/gc/gc-YYYYMMDD-HHMMSS.jsonl (disable with --no-archive).
The --keep-last N flag protects the N most recently finished tickets per
status even when they exceed --max-age.
Filesystem contract
koru never writes outside <project>/.planfile/. This is a hard
rule for the production code path; any deviation is a bug.
<project>/.planfile/
โโโ config.yaml # planfile-owned (project config)
โโโ sprints/
โ โโโ current.yaml # planfile-owned (source of truth)
โโโ .koru/ # koru-owned, opt-in, gitignore-friendly
โโโ runs/ # one log per `koru --queue` invocation
โโโ gc/ # JSONL archives from `koru gc --apply`
โโโ prompts/ # captured `--interactive` answers
โโโ llm-cache/ # opt-in LlmExecutor response cache
โโโ README.md # in-place explainer
The .koru/ subtree is non-authoritative โ planfile sprint YAML is
always the source of truth. Anything in .koru/ can be deleted at any
time without losing ticket state. Recommended .gitignore entry:
.planfile/.koru/
The path helpers exposed by koru.runtime (runtime_dir, runs_dir,
new_run_id, ensure_runs_dir) are pure resolvers โ they only touch
disk via ensure_runs_dir, so a --dry-run invocation leaves zero
trace.
/tmp/ policy. Production code does not use /tmp/. Test
fixtures (tests/ and tests/e2e/*.sh) are the only allowed
/tmp/ users and MUST be PID-scoped (/tmp/koru-*-$$) with
trap cleanup EXIT so a failed run leaves nothing behind. If you find
koru artefacts elsewhere, please open an issue.
LLM agent contract โ koru as the gate
When an LLM agent (Cascade, Cursor, aider, claude-code, local model, โฆ) drives a koru-managed project, it must read its instructions from koru, not from the human chat.
The agent's first command in every session is just koru โ the
markdown brief that comes back is the entire contract. If the project
has never been initialised, the brief leads with โ Setup required
and the exact koru --init command. The contract is delivered by:
koru --context --project . # JSON brief (machine-readable)
koru --context --project . --format markdown # Markdown handoff (paste-to-IDE)
koru --context --project . --ticket PLF-074 # brief for a specific ticket
The brief contains everything an autonomous agent needs to act safely:
- the next runnable ticket (or one named via
--ticket) โ id, name, status, files in scope, prompt, executor kind; - the resolved policy โ explicit booleans for every git operation the agent might attempt;
- environment fingerprint โ git branch, dirty state, remote, whether planfile is initialised in the project;
- imperative rules โ copy-paste-able
DO NOT โฆlines so even a weak model can compare any candidate command to a checklist; - self-service vocabulary โ concrete
planfile ticket {claim,start, complete,fail,input}invocations with the active ticket id pre-filled.
Safe-by-default policy
The policy lives at <project>/.planfile/.koru/policy.yaml. All
gates default to the most restrictive value. A missing or malformed
file falls back to defaults โ corruption can never silently loosen
the policy.
| gate | default | meaning |
|---|---|---|
allow_commit |
false |
the agent does NOT run git commit |
allow_push |
false |
the agent does NOT run git push |
allow_branch_create |
false |
no git checkout -b, git branch X, git switch -c |
allow_branch_switch |
false |
no git checkout <ref>, git switch <branch> |
allow_tag |
false |
no git tag |
allow_destructive_shell |
false |
blocks rm -rf /, dd, mkfs, force-pushes, โฆ |
require_planfile_lifecycle |
true |
every state change goes through planfile ticket * |
require_ci_pass_before_complete |
true |
the agent verifies CI exit 0 before ticket complete |
The agent bounces off CI/CD and koru: it cannot commit, cannot
push, cannot mutate planfile state outside the CLI vocabulary the
brief gave it. To make a change that ships, the agent has exactly two
exits: complete the ticket (humans/CI take it from there) or call
planfile ticket input <id> --prompt "<question>" and stop.
Universal quality gates (built-in)
Every koru --init creates a universal CI command that automatically
detects and runs quality tools when they're available:
# Runs on every ticket completion (if require_ci_pass_before_complete=true)
echo "=== Universal Quality Gates ==="
# 1. Project tests (auto-detects runner)
# - task test (Taskfile)
# - pytest -q (Python)
# - npm test (Node.js)
# - make test (Makefile)
# 2. TestQL E2E scenarios (when *.testql.toon.yaml files exist)
testql suite --pattern "*.testql.toon.yaml" --output console --fail-fast
# 3. WUP dependency analysis (semcod/wup, when wup.yaml exists)
wup status
# 4. Regix quality gates (when regix.yaml exists)
regix gates
Tools are gracefully skipped if not installed or configured โ no manual setup required for basic quality control. The universal gates ensure:
- Consistent quality across all koru projects
- Automatic regression testing with testQL scenarios
- Real-time regression monitoring with
wup watchwhen you want an on-change loop for files and services - Zero configuration for basic validation
- Adaptive detection of project-specific tooling
Docker OS ร IDE smoke matrix
Koru also ships a containerized IDE-routing smoke matrix for environments where real GUI automation is unavailable. It builds one image per Linux base and runs the same autopilot routing/dry-run checks for every supported IDE surface:
task test:docker:ide-matrix
# Narrow the matrix while debugging:
task test:docker:ide-matrix SYSTEMS=ubuntu-noble IDES="vscode cursor"
Default systems: debian-slim, debian-bookworm, ubuntu-noble, fedora,
alpine. Default IDEs: vscode, vscodium, cursor, windsurf, jetbrains, zed.
The GitHub Actions workflow Docker IDE Matrix runs the same 5 ร 6 matrix on
demand. Each container run verifies the headless IDE route, per-IDE submit-key
defaults, isolated autopilot socket names, koru autopilot drive --direct --dry-run,
and koru autopilot manage for plugin-managed IDEs.
VS Code and VSCodium are separate lanes. A VSCodium terminal or explicit
--ide vscodium routes to KORU_AUTOPILOT_INSTANCE=vscodium, VSCodium settings,
and koru-autopilot-vscodium.sock; it should not attach to the VS Code socket.
Native OS ร IDE smoke matrix
Container tests cover popular Linux bases. Native GitHub Actions cover host platform differences that Docker does not model:
ubuntu-latestwindows-latestmacos-latest
The Native IDE Matrix workflow runs the same IDE set:
vscode, vscodium, cursor, windsurf, jetbrains, zed.
It installs koru, adds fake editor CLIs to PATH, runs
tests/test_docker_ide_matrix.py, then smoke-tests koru autopilot drive and
koru autopilot manage where the IDE has a plugin-managed lane.
iOS is intentionally not part of this matrix: koru autopilot targets desktop IDE
CLIs, editor extension hosts, and local socket/process workflows. For Apple
desktop coverage, use the macos-latest lane.
For continuous monitoring, use the semcod/wup package directly:
wup map-deps
wup testql-endpoints testql-scenarios
wup watch . \
--deps deps.json \
--cpu-throttle 0.8 \
--mode testql \
--scenarios-dir testql-scenarios \
--testql-bin scripts/koru-wup-testql \
--track-dir .wup/tracks \
--quick-limit 3
wup watches the paths from wup.yaml, maps changed files to affected
services, runs quick TestQL probes first, and writes live service status to
.wup/service-health.json. Use regix separately for git/metric regressions
against HEAD.
semcod/* control loop โ planfile tickets
Koru also has a single operator command for the full semcod toolchain:
task install:tools
task quality:semcod:planfile
That command is intentionally LLM-free. It:
- runs
koru scan --apply --semcod-artifacts; - detects configured
semcod/*tools (wup,testql,regix,redup,sumr/sumd,doql,redsl, plus the rest surfaced in the Koru brief); - runs only the gates that are both installed and configured in the project;
- uses
scripts/koru-gate-capture.pyto create or update deduplicatedplanfiletickets marked with[gate-finding:<hash>].
Useful variants:
DRY_RUN=1 task quality:semcod:planfile # show what tickets would be created
UPDATE_EXISTING=1 task quality:semcod:planfile # append notes to existing findings
PRIORITY=critical task quality:semcod:planfile # promote new gate findings
The source of truth stays in .planfile/; Koru does not hand-edit sprint YAML.
Agents should consume the resulting work through planfile ticket next or
koru --queue.
Auto-promotion & auto-repair for blocking tickets
Koru automatically manages workflow priorities to prevent deadlocks:
Auto-promotion
- Tickets that block others are automatically promoted to
criticalpriority - This ensures blocking issues are resolved first
- Promotion happens on every
koru --contextcall
Auto-repair mode
- Critical tickets receive special instructions for LLM agents:
- "AUTO-REPAIR MODE: Fix this issue immediately to unblock the workflow"
- "Do NOT ask for human input unless absolutely necessary"
- "Use all available tools and knowledge to resolve the blocking issue"
- "After fixing, immediately call
planfile ticket complete"
Workflow
- Main task โ encounters blocking issue
- Blocking ticket created โ auto-promoted to
critical - LLM agent receives auto-repair instructions
- Issue resolved โ main task unblocked
- Workflow continues without manual intervention
Bug-first priority system
Koru ensures bugs are always fixed before features when priorities are equal:
Automatic bug promotion
- Bugs get priority boost within their category:
lowโnormalnormalโhighhighโcriticalcriticalstayscritical
- Promotion happens automatically on every
koru --contextcall - Only tickets with
buglabel are promoted
Priority hierarchy
critical (blocking tickets + high-priority bugs)
โโโ high bugs (promoted from normal)
โโโ high features
โโโ normal bugs (promoted from low)
โโโ normal features
โโโ low bugs
โโโ low features
Benefits
- Bug-first workflow โ stability issues resolved before new features
- Automatic triage โ no manual priority adjustments needed
- Predictable execution โ bugs always jump ahead of same-priority features
- Quality assurance โ prevents feature development while bugs exist
Integration with planfile
Koru's priority system is fully integrated with planfile:
Shared priority logic
- Same promotion rules applied in both koru and planfile core
- Consistent ticket ordering across all planfile commands
- Unified bug-first workflow throughout the ecosystem
Planfile commands enhanced
planfile ticket nextโ respects bug-first prioritiesplanfile ticket listโ shows promoted prioritiesplanfile queueโ processes bugs before features- All planfile operations use the same priority hierarchy
Seamless workflow
- Koru auto-promotes tickets on
--contextcall - Planfile respects promoted priorities natively
- Consistent execution whether using koru or planfile directly
- No conflicts โ both systems use identical priority logic
Loosening the policy
Editing <project>/.planfile/.koru/policy.yaml is the only way to
relax a default. There is no CLI flag for it โ that is a deliberate
choice so any loosening is reviewable in git history.
# .planfile/.koru/policy.yaml
llm:
allow_commit: false # never (recommended)
allow_push: false # never (recommended)
allow_branch_create: true # opt-in: agent may create feature branches
ci:
command: pytest -q # override universal gates (optional)
timeout_seconds: 300
notes:
- "Always run `task lint` before `ticket complete`."
- "Never edit migrations under alembic/versions/."
Run logs
koru --queue and koru --queue --loop write a JSON-Lines log per run
to <project>/.planfile/.koru/runs/queue-<timestamp>-<pid>.jsonl:
{"type":"run.start","run_id":"queue-โฆ","mode":"loop","actor":"koru","pid":12345,โฆ}
{"type":"iteration","iteration":1,"ticket_id":"PLF-074","status":"completed",โฆ}
{"type":"iteration","iteration":2,"ticket_id":"PLF-075","status":"failed",โฆ}
{"type":"run.end","iterations":2,"completed":["PLF-074"],"failed":["PLF-075"],โฆ}
--dry-run skips the writer (preserves "dry-run leaves zero trace").
--no-log opts out explicitly. Logs are non-authoritative โ planfile
sprint YAML remains the source of truth.
Documentation
The full documentation lives in docs/:
docs/autopilot-quickstart.mdโ production setup forkoru autopilot(doctor, daemon, plugin, systemd user unit, handoff, audit log, troubleshooting).docs/agent-guide.mdโ full LLM agent workflow guide (originally written formaskservice/c2004Windsurf agent, generalized for any koru-driven repo). Covers ticket workflow, validation gates, anti-patterns, troubleshooting.docs/planfile-llm-guide.mdโ ticket-driven development withplanfileCLI.docs/planfile-execution-gateway.mdโ design for turningplanfile.yamlinto the execution gateway for shell, MCP, API, human, and LLM tasks.docs/llm-tools/โ per-tool docs and install scripts:planfile/โ ticket backlogregix/โ Python regression metricsredup/โ duplicate detectionredsl/โ OpenRouter auto-refactor (opt-in)vallm/โ multi-tier patch validatorprefact/โ proactive LLM-aware linterpfix/โ auto-fix importsllx/โ LLM CLI wrappersumd/โ LLM refactor snapshots (SUMR.md)redeploy/โ multi-target deployment (markpact specs)goal/โ automated git push + smart commits + release workflowdoql/โ declarative infrastructure-as-code (.doql files)costs/โ zero-config AI cost tracker per commitop3/โ layered infrastructure observation (multi-layer scan)toonic/โ universal TOON format platform (LLM-friendly compact files)protogate/โ migration tool dla legacy systems (bounded slices)rebuild/โ code evolution intelligence (git history walker)mdflow/โ markdown dependency analyzermetrun/โ execution intelligence + bottleneck detectionaider/โ pair-programming agentclaude-code/โ Anthropic agentcursor/โ Cursor IDE setuptestql/โ declarative HTTP tests
Templates (config snippets)
Reference configurations from the c2004 reference deployment:
templates/pyqual.yaml.templateโ full pipeline orchestratortemplates/redup.toml.templateโ duplicate budgettemplates/redsl.yaml.templateโ refactor lane configtemplates/regix.yaml.templateโ regression metrics
Reference deployment
maskservice/c2004 โ the original
production-grade closed-loop refactor system that koru generalizes.
Real metrics from c2004 (May 2026):
- 88% size reduction in compatibility shim files (14640 โ 1812 bytes)
- 8 stale alerts auto-closed in single workflow run
- 0 errors / 42 improvements via regix gates after refactor
- 58/58 endpoint health probes post-migration
License
Licensed under Apache-2.0.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file koru-0.1.186.tar.gz.
File metadata
- Download URL: koru-0.1.186.tar.gz
- Upload date:
- Size: 500.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1c0c55c42f90075a16ba869dcf55b59e44c91a43ac7fb836b40439ba9c118baf
|
|
| MD5 |
c9d324cb317b7f55727238feb5070ff4
|
|
| BLAKE2b-256 |
4d5c7778f12e54327f206fb821d66a5a2795358855363e6a597d20aec882f07b
|
File details
Details for the file koru-0.1.186-py3-none-any.whl.
File metadata
- Download URL: koru-0.1.186-py3-none-any.whl
- Upload date:
- Size: 401.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a650e175aa6d7db648eb2b87537610b32f12e1e180b55b7232b022864eb283ec
|
|
| MD5 |
d52b5eee71c4101daa973ac441cd65b9
|
|
| BLAKE2b-256 |
b7b92eb360758dddc808315576236dc457892ce657da77bee4a08f34d207e1e2
|