{"id":50472448,"url":"https://github.com/semcod/koru","last_synced_at":"2026-06-01T11:03:36.252Z","repository":{"id":356945011,"uuid":"1234549981","full_name":"semcod/koru","owner":"semcod","description":"KORU - steruje kilkoma IDE na raz tak jak MCP/ACP agentami","archived":false,"fork":false,"pushed_at":"2026-05-24T17:47:20.000Z","size":185684,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-24T18:05:47.312Z","etag":null,"topics":["acp","cursor","ide","jetbrains","mcp","windsurf","zed"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/semcod.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"docs/roadmap-competition.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-10T10:33:42.000Z","updated_at":"2026-05-24T17:47:22.000Z","dependencies_parsed_at":null,"dependency_job_id":"5d19c9cc-5aa9-4f19-b5f0-591de2003de2","html_url":"https://github.com/semcod/koru","commit_stats":null,"previous_names":["semcod/koru"],"tags_count":252,"template":false,"template_full_name":null,"purl":"pkg:github/semcod/koru","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semcod%2Fkoru","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semcod%2Fkoru/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semcod%2Fkoru/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semcod%2Fkoru/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/semcod","download_url":"https://codeload.github.com/semcod/koru/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/semcod%2Fkoru/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33771630,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acp","cursor","ide","jetbrains","mcp","windsurf","zed"],"created_at":"2026-06-01T11:03:36.159Z","updated_at":"2026-06-01T11:03:36.242Z","avatar_url":"https://github.com/semcod.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"![koru.mp4](koru.mp4)\n\n[koru.mp4](koru.mp4)\n# koru\n\n\u003cimg src=\"maori-koru-bold-400w.png\" width=\"200\" alt=\"koru\"\u003e\n\n## AI Cost Tracking\n\n![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.1.300-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)\n![AI Cost](https://img.shields.io/badge/AI%20Cost-$34.66-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-126.2h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)\n\n- 🤖 **LLM usage:** $34.6587 (399 commits)\n- 👤 **Human dev:** ~$12622 (126.2h @ $100/h, 30min dedup)\n\nGenerated on 2026-05-28 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)\n\n---\n\nPython package for **closed-loop refactor automation** across multi-repo\nworkspaces (validated on `semcod/*`, `maskservice/c2004`, and other monorepos).\n\nThe name refers to *Koru* (Māori spiral), matching the \"spiraling loop\"\nrefactor flow: **detect → plan → execute → verify → heal → repeat**.\n\n## What koru is\n\nA meta-orchestrator that coordinates **LLM-augmented refactor tools** with\n**ticket-driven workflow** and **regression-free verification**:\n\n```\n┌────────────────────────────────────────────────────────────────┐\n│                          KORU                                  │\n├──────────┬──────────┬──────────┬──────────┬─────────┬──────────┤\n│ DETECT   │ PLAN     │ EXECUTE  │ VERIFY   │ HEAL    │ LEARN    │\n├──────────┼──────────┼──────────┼──────────┼─────────┼──────────┤\n│ redup    │ planfile │ Windsurf │ regix    │ healing │ pyqual   │\n│ regix    │ tickets  │ Cursor   │ pytest   │ webhook │ metrics  │\n│ TestQL   │ Promet.  │ aider    │ TestQL   │ retry   │dashboards│\n│ Probe    │ Alertmgr │ vallm    │ vallm    │         │          │\n└──────────┴──────────┴──────────┴──────────┴─────────┴──────────┘\n        ↑                                                  │\n        └─────────── closed-loop feedback ─────────────────┘\n```\n\n\n## autonomous cycle chat activity\n![img.png](img.png)\n```\n[10:18:48] koru ▸ KORUAUTONOMOUS: next 1/3 wait 240s; chat cooldown is active for STARTER-217, so Koru will not paste over the IDE chat\n[10:18:48] koru ▸ KORUAUTONOMOUS: next 2/3 rerun planfile queue (max 50) and check whether STARTER-217 moved\n[10:18:48] koru ▸ KORUAUTONOMOUS: next 3/3 if queue becomes idle, run scan/discovery; if still waiting, use chat events/reflection before any redrive\n```\n\n\n\n## Quick start — start an LLM session in 3 commands\n\n```bash\ncd /path/to/your/project\npip install koru\nkoru --init                # 1. set up .planfile/ + .koru/ + .gitignore\nkoru                       # 2. print the LLM brief (paste into Cascade/Cursor/aider)\nkoru --queue --loop        # 3. drain the queue (the agent works on each ticket)\n```\n\n### Brand-new project? Run the wizard first\n\n```bash\npip install koru\nkoru wizard                # interactive: detects your IDE, picks a project,\n                           # walks a strategy decision tree, creates the first ticket\nkoru wizard --quick        # zero prompts — creates a sensible default ticket\n                           # (quality → CC hotspots) immediately\nkoru wizard --bilingual    # show every label as \"Polski · English\" side-by-side\n```\n\n`koru wizard`:\n\n- **Detects IDEs** — both *running* processes (Cursor, VS Code, Windsurf,\n  PyCharm/IntelliJ, Zed, Antigravity, VSCodium) and *installed* ones found\n  in standard locations (`/usr/bin`, `/opt/*`, `/snap/*`, `~/.local/bin`,\n  `/Applications/*`).\n- **Offers to install an IDE** when none is found — runs a guarded\n  `snap`/`apt`/`brew` command for Cursor / VS Code / Windsurf / VSCodium\n  (you confirm before anything mutates the system).\n- **Suggests a project** — the workspace open in the running IDE, the\n  current shell `cwd`, plus JetBrains recent-projects history.\n- **Walks a JSON decision tree** (`koru/wizard/strategies.json`) so you\n  pick a strategy: *architecture refactor*, *frontend/UX*, *backend/API*,\n  *CQRS + Event Sourcing*, *quality (CC, tests, CI gates)*, *performance*,\n  *DevX*. The tree is fully **user-editable** — copy it, edit, and pass\n  `--strategies my-tree.json`.\n- **`[?]` per option** — every choice ships with a 1-2 sentence\n  explanation. Type `?2` to read help for option 2, `?` to list help for\n  every option in the current prompt. You never need to know what \"CQRS\"\n  or \"Hexagonal\" means up front.\n- **Bilingual mode** (`--bilingual` or `--language pl,en`) — shows both\n  Polish and English labels in one prompt so you don't pick a language\n  up front.\n- **Quick mode** (`--quick`) — skips every prompt, follows the\n  `quick_default.path` declared in `strategies.json` (defaults to\n  *quality → CC refactor*), and creates the first ticket immediately.\n  Use `--quick --strategy architecture.cqrs_es` to pick a different path\n  without prompts.\n- **Creates the first planfile ticket** matching the chosen leaf, then\n  prints a *\"Co teraz / What's next\"* panel listing the exact 3 commands\n  to run next (`koru` brief, IDE chat prompt, `koru --queue --loop`).\n- **Optional `--llx`** — calls the [`llx`](https://pypi.org/project/llx/)\n  CLI to *extend* branches dynamically based on the analysed project.\n- **Browser GUI** (`--gui`) — step-by-step UI at `http://127.0.0.1:\u003cport\u003e/wizard`\n  (localhost only, offline CSS/JS). Use `--no-browser` to print the URL only.\n  Requires `pip install 'koru[api]'`.\n- **Strategy templates** (`--template web-app`, `--template ml-research`,\n  `--template cli-tool`, `--template library`) — curated decision trees for\n  common project shapes. Run `koru wizard --list-templates` to see all\n  built-ins. Remote trees: `--strategies https://… --allow-remote` (HTTPS\n  only, 1 MiB max, cached in `~/.cache/koru/wizard/`).\n- **`--detect-only`** — prints the discovered IDEs + project candidates as\n  text or JSON without prompting; useful in scripts.\n\nCalling `koru auto` in a brand-new project (no `.planfile`, TTY attached)\nwill now hint that `koru wizard` is the recommended first step. Skip the\nhint with `KORU_AUTO_SKIP_WIZARD=1`.\n\nThat is the entire onboarding. **`koru` (no args) is the command an LLM\nagent runs at the start of every session** — the markdown brief it\nprints contains the active ticket, the policy gates, and the exact\n`planfile ticket …` commands the agent is allowed to use. Nothing\nelse needs to be memorised.\n\nIf the project is not initialised yet, `koru` (no args) detects this\nand prints a **⚠ Setup required** section with the exact `koru --init`\ncommand to run — the LLM never has to guess.\n\n### Fast local startup (existing repo)\n\n```bash\npython -m venv .venv\n. .venv/bin/activate\npython -m pip install -U pip\npython -m pip install -e \".[dev]\"\n\n# pyenv / ~/.venv often shadow the project CLI — force repo-first PATH:\nexport PATH=\"$(pwd)/.venv/bin:$PATH\"\nhash -r\n# or: source scripts/activate-koru-dev.sh\n# or: scripts/koru-from-repo.sh auto\n\n# verify which build this shell is using\nkoru --version\nwhich koru   # must be …/semcod/koru/.venv/bin/koru\nkoru --doctor --project .   # warns if PATH koru lacks ``koru auto``\n\n# smoke-run one autonomous cycle (no IDE injection)\nkoru autonomous up --project . --max-cycles 1 --sleep-seconds 0 --no-autopilot\n\n# start dashboard even if 8765 is already occupied\nkoru serve --project . --auto-port --no-open\n```\n\nUse explicit `up` for compatibility (`koru autonomous up --project .`),\nespecially when switching between local source checkouts and older PyPI builds.\n\n### Installation extras\n\nThe base package stays intentionally small (`pyyaml` plus stdlib-based CLI/API).\nInstall only the lanes you are working on:\n\n```bash\npip install \"koru[watch]\"    # WebSocket queue watcher\npip install \"koru[vision]\"   # local screen capture for observation mesh\npip install \"koru[mesh]\"     # WebSocket relay/publish transport for observation mesh\npip install \"koru[observe]\"  # full local observation stack (vision + mesh)\npip install \"koru[dev]\"      # tests, lint, typing, local quality tooling\npip install \"koru[api]\"      # FastAPI healing webhook service\npip install \"koru[agent]\"    # LLM / structured-output integrations\npip install \"koru[obs]\"      # tracing, Sentry, structured logging\npip install \"koru[queue]\"    # optional Redis/scheduler queue adapters\npip install \"koru[quality]\"  # deeper refactor quality gates\npip install \"koru[all]\"      # local workstation with every optional lane\n```\n\n`koru autopilot` and the IDE control-plane socket protocol are part of the\nbase package; see [`docs/IDE_PROTOCOL.md`](docs/IDE_PROTOCOL.md) for the\nformal plugin/daemon wire contract.\n\nTo understand the core differences between `koru auto` (active execution) and `koru observe up` (passive telemetry), and to troubleshoot IDE-specific compatibility issues (such as with **Cursor** or custom window environments), please read **[`docs/koru_auto_vs_observe_up.md`](docs/koru_auto_vs_observe_up.md)**.\n\n### Structured stdio (NDJSON / JSON Lines)\n\n`koru autonomous up` defaults to human-readable logs. For **versioned,\npipe-friendly control-plane records** (CQRS-style commands/events on\nstdout), use:\n\n```bash\nkoru autonomous up --project . --max-cycles 1 --sleep-seconds 0 --emit-events jsonl --no-autopilot \\\n  2\u003e/dev/null | jq -c .\n```\n\nOr set `KORU_STDIO_FORMAT=jsonl` so the default matches (still overridable\nwith `--emit-events human`). In `jsonl` mode, incidental status lines go to\n**stderr** so stdout stays one JSON object per line. JSON Schema:\n`schemas/koru-stdio-event.schema.json`. Event `type` values include\n`SessionStarted`, `CycleStarted`, `ScanCompleted`, `ScanSkipped`,\n`QueueIteration`, `DiagnosticsCompleted`, `WupHealthChanged`,\n`PostRunVerifyCompleted`, `PostRunVerifyIdeCompleted`, `QueueStaleReleased`,\n`AutopilotDecision`, `CycleCompleted`, and `AutonomousStopped`.\n\n### Post-run verify (closed loop after `done`)\n\nProjects can declare regression gates in root **`koru.yaml`** under\n`queue.post_run_verify`. `koru autonomous up` runs them after the queue\ncloses tickets and after the IDE marks tickets `done` in planfile (status\npoll — not chat readback). See [docs/post-run-verify.md](docs/post-run-verify.md).\n\n### Autopilot redrive cooldown (chat-aware loop)\n\nBefore this change, `koru autonomous up` would re-paste the same ticket\nprompt into the IDE chat on **every cycle** (default 60 s sleep) as long as\nthe queue stayed `waiting_input` with an `llm-ready` label. That clobbered\nthe IDE-side LLM mid-response and produced spurious \"random task suggestions\"\nthat ignored what the LLM had already written. See `terminal selection` in\nPLF-…/`autonomy-ide-cursor.md` for the original repro (STARTER-184: \"CQRS +\nEvent Sourcing\" driven twice in 60 s while VS Code Copilot was still typing).\n\nThe autonomous loop now reads the daemon-emitted plugin events\n(`message.sent`, `message.received`) from\n`$XDG_RUNTIME_DIR/koru-autopilot-events.ndjson` (see\n[`src/koruide/chat_history.py`](src/koruide/chat_history.py)) and **skips\nthe drive** when the IDE chat has been active within the cooldown window.\n\n| Env var | Default | Effect |\n|---|---|---|\n| `KORU_AUTOPILOT_REDRIVE_COOLDOWN_SECONDS` | `300` | Skip the next drive for the same ticket if any `message.sent` / `message.received` was emitted within this many seconds. Set to `0` to disable and restore the legacy \"redrive every cycle\" behavior. |\n| `KORU_LLM_REFLECT` | unset (off) | When set to `1`/`true` **and** `llx` is on `PATH`, the loop calls `llx chat --free --prompt …` (OpenRouter-backed) with the recent chat events to decide `{done, needs_input}`. If llx replies `done=true`, the loop unblocks even within the cooldown so the queue can move on. Falls back to the plain cooldown if llx is missing, errors, or returns non-JSON. |\n\nThe cycle telemetry records the decision so it's visible in the dashboard:\n\n* `autopilot_skipped_chat_activity=true` — drive was skipped by the cooldown\n* `autopilot_chat_activity_last_event=message.sent|message.received`\n* `autopilot_llx_reflection={\"done\":…,\"needs_input\":…,\"summary\":…}` — only\n  when `KORU_LLM_REFLECT=1`.\n\nIf you want koru to \"react to the IDE chat\" the way the operator described (using OpenRouter / LLM-reflection to inspect the chat context, make autonomous decisions, and drive Cascade/Cursor):\n\n```bash\npip install -U llx                 # OpenRouter-aware router\nexport OPENROUTER_API_KEY=sk-…     # or whatever llx asks for\nexport KORU_LLM_REFLECT=1\nexport KORU_AUTOPILOT_REDRIVE_COOLDOWN_SECONDS=300\nkoru auto\n```\n\nIn this mode:\n- Koru **reads the active IDE chat history** dynamically.\n- Refers to **OpenRouter LLMs** to intelligently reflect on whether the IDE agent successfully completed the task, is stuck, or requires a corrective prompt.\n- Automatically drives the chat with **adaptive prompt escalation** instead of blindly pasting text.\n\n### Live Plugin Console Logs on the Dashboard\n\nYou can now diagnose issues within the Windsurf/Cursor/VS Code extension host dynamically (e.g. chat panels closing unexpectedly) **without opening the IDE Developer Tools**:\n1. Run the local dashboard: `koru serve --project .` (or through `koru observe up`).\n2. Navigate to **`http://127.0.0.1:8765/`** and select the **`Plugin logs`** tab.\n3. Logs are automatically grouped into **collapsible service execution sessions**.\n4. To avoid clutter and optimize bandwidth, logs are strictly **clamped to 10KB per session**.\n5. Use the built-in interactive buttons to:\n   - **Copy to Clipboard** — copies full/session logs with a temporary green \"Copied!\" feedback badge.\n   - **Download .log file** — downloads raw log files (`koru-plugin-console.log`) directly to your machine.\n\nYou can also inspect plugin console logs at any time on the terminal using:\n```bash\nkoru doctor\n```\n\n### Quick troubleshooting\n\n| Symptom | Fix |\n|---|---|\n| `koru: error: unrecognized arguments: auto` | The `koru` on your `PATH` is **not** the editable build you just installed. Common causes: (1) **pyenv shim** — run `type -a koru`; if you see `~/.pyenv/shims/koru`, that Python 3.12 wheel only has `koru autonomous`, not `koru auto`. Fix: `cd /path/to/semcod/koru \u0026\u0026 pip install -e . \u0026\u0026 pyenv rehash`, or use `koru autonomous` / `python -m koru auto`. (2) **Wrong venv active** — `pip install -e .` may have updated `c2004/.venv` while your shell still runs `~/.venv/bin/koru` or pyenv. Fix: `deactivate`, `cd semcod/koru`, `source .venv/bin/activate`, `hash -r`, `which koru` (must be `…/semcod/koru/.venv/bin/koru`), then `pip install -e \".[dev]\"`. (3) **Stale global install** — `pip install -e .` into `~/.venv` or upgrade with `pip install -U -e .` from the koru repo. Current source maps `koru auto` → `autonomous` even on legacy `_SUBCOMMANDS` tables after reinstall. |\n| `koru auto` picks `lane=jetbrains` / `terminal hint → jetbrains` and then prints `autopilot plugin unsupported` | The shell has a stale `KORU_AUTOPILOT_INSTANCE=jetbrains` exported (e.g. from a previous session) and the IDE parent-process walk finds the JetBrains process. JetBrains does not have an installable koru plugin yet, so the loop falls back to the OS injector path — unreliable on Wayland. Fix: `unset KORU_AUTOPILOT_INSTANCE` (auto-pick the focused IDE) **or** export a supported lane: `export KORU_AUTOPILOT_INSTANCE=cursor` (also accepts `vscode`/`vscodium`/`windsurf`). `koru auto` now prints this remedy inline when it detects the stale env. |\n| Autonomous log floods with `client connected: fd5` / `client disconnected: fd5` | Health probes (dashboard `/api/dashboard`, MCP, WUP, status checks) connect to the autopilot daemon every second. These per-fd events are now hidden by default. Set `KORU_AUTOPILOT_VERBOSE=1` to re-enable them for debugging. `send to fdN failed: [Errno 32] Broken pipe` is similarly downgraded (it just means the caller already timed out and disconnected). |\n| `koru: nfo activity log disabled: ModuleNotFoundError: No module named 'nfo'` | `nfo` is an optional dependency for the structured activity log. Install it with `pip install nfo` (or `pip install \"koru[obs]\"`). The autonomous loop runs fine without it; the warning is printed once and then silenced. |\n| `koru autonomous: ... invalid choice: '.' (choose from 'up')` | Run `koru autonomous up --project .` |\n| `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 \u003cpid\u003e` |\n| 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 |\n| 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` |\n| 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` |\n| `goal -a` takes too long to fail | Keep `strategies.python.test` fail-fast (`--maxfail=1`) for quick feedback; run full suite explicitly when needed |\n| `goal -a`: `No module named 'costs'` | Install dev extras: `pip install -e \".[dev]\"`, or set `[tool.costs] badge = false` in `pyproject.toml` |\n| `goal -a` unstages `.code2llm_cache/*.pkl` | Ensure `.code2llm_cache/` is in `.gitignore` (not per-file pickle lines) |\n| Autopilot re-pastes the same ticket prompt every cycle while the IDE chat is still typing | The cooldown is too low or the events file is missing. Default cooldown is 300 s; tune via `KORU_AUTOPILOT_REDRIVE_COOLDOWN_SECONDS=\u003cseconds\u003e`. Verify the plugin actually emits events: `tail -f $XDG_RUNTIME_DIR/koru-autopilot-events.ndjson`. If empty, the plugin is connected but `chat.events` capability is missing — reload the IDE window. To opt into OpenRouter-backed reflection (decide *based on what the LLM wrote* whether to redrive): `pip install llx \u0026\u0026 export KORU_LLM_REFLECT=1`. |\n| **Cursor**: Koru drives the prompt into the chat but the LLM never starts working (log shows `winning_submit=...Return` and `verification=strict`, message stays in input box as a new line, or even ends up in another OS window) | Two stacked bugs combine here. (1) Cursor's chat textarea treats plain `Enter` as a newline; only `Ctrl+Enter` actually submits on Linux. (2) On Wayland-native compositors (GNOME, KDE on Wayland) `xdotool` cannot reach Cursor at all — it exits 0 but routes the synthetic key to whatever XWayland window happens to be active (commonly the terminal running `koru auto` or a sibling VS Code). **Upgrade the plugin to ≥0.1.49**: `cd plugins/koru-autopilot-vscode \u0026\u0026 npm run package \u0026\u0026 /usr/bin/cursor --install-extension koru-autopilot-0.1.49.vsix --force`, then reload the Cursor window and run `koru: Connect autopilot daemon`. The new version (a) prefers `Ctrl+Return` over `Return` for Cursor and (b) prefers `ydotool` (which uses `/dev/uinput` and crosses into the Wayland compositor) over `xdotool` whenever `XDG_SESSION_TYPE=wayland` or `WAYLAND_DISPLAY` is set. Already-poisoned caches from 0.1.47/0.1.48 are auto-discarded on first load. For best results on Wayland: keep Cursor as the focused window during autonomous cycles (uinput events go to whichever surface has compositor focus), make sure the user is in the `input` group, and consider `systemctl --user enable --now ydotool` to start the daemon for lower-latency injection. Override the shortcut with `koruAutopilot.submitHostKey` if your setup differs. |\n\n### CLI subcommand reference\n\n`koru \u003csubcommand\u003e [args…]` dispatches to one of the registered subcommands\nbelow; running `koru` with no args (or just flags like `--ticket`, `--doctor`,\n`--init`) keeps the legacy single-shot behavior (closed-loop runner / context\nbrief / etc.).\n\n| Subcommand | What it does |\n|---|---|\n| `koru auto`, `koru autonomous` | Bootstrap and run the closed loop (init → scan → queue → autopilot daemon → optional WUP watch). `auto` is an alias of `autonomous`. Run `koru auto --help` for `doctor` / `self-heal` / `up`. |\n| `koru autopilot` | Drive an IDE chat session (handoff / drive / manage / setup-host / install-unit / status / tail / calibrate / session-start). See [`docs/IDE_PROTOCOL.md`](docs/IDE_PROTOCOL.md). |\n| `koru autoloop` | Loop a single command across `semcod/*` repositories with retries. |\n| `koru wizard` | Interactive (or `--gui` browser) onboarding: detect IDEs, pick project, scaffold `.planfile/`. |\n| `koru init-ci` / `koru init-ide` | Scaffold CI templates / install IDE plugins + MCP. |\n| `koru serve` / `koru local-serve` | Start the dashboard / HTTP healing webhook (`pip install \"koru[api]\"`). |\n| `koru mesh` | Run / publish to the observation mesh (WebSocket relay). |\n| `koru vision` | Local screen capture providers (`pip install \"koru[vision]\"`). |\n| `koru observe` | Convenience launcher for the full observation stack (vision + mesh + dashboard). |\n| `koru mcp-serve` | Run koru as an MCP server (stdio) for Cursor / VS Code / Claude Desktop. |\n| `koru ide-router` | Route ticket events to specific IDE lanes. |\n| `koru task` / `koru agent` | Planfile task creation and LLM agent management. |\n| `koru tools` | Inspect / dispatch the AI tool registry. |\n| `koru gate` / `koru queue` / `koru scan` | Run individual stages of the closed loop in isolation. |\n| `koru gc` | Garbage-collect old planfile tickets / artifacts (see [Queue GC](#queue-garbage-collection--koru-gc)). |\n| `koru tagi` | Run tagi-backed change analysis / safe commit orchestration. |\n| `koru git` | Git helpers used by the autopilot daemon. |\n| `koru doctor` | Detailed diagnostics catalog (alias for `koru --doctor`). |\n| `koru configure` | Edit `koru.yaml` interactively. |\n| `koru topology` | Print the live topology (active systems / pipelines). |\n| `koru runtime-context` | Print the runtime context the LLM brief is built from. |\n| `koru dsl` / `koru api` | DSL evaluator / dashboard API helpers. |\n| `koru dev` | Internal dev-sync helpers used by the monorepo. |\n\nIf an unknown token is passed where a subcommand is expected, koru now prints\na `Did you mean 'koru …'?` hint based on the closest match (e.g. `koru autox`\n→ `koru auto`), followed by the list of known subcommands. This is the same\nmechanism that disambiguates the **`koru: error: unrecognized arguments: auto`**\ncase in the troubleshooting table above — that error only happens when the\nactive `koru` on `PATH` was installed from an older release that predates the\n`auto` alias; upgrading or activating the project `.venv` resolves it.\n\n## Topology \u0026 pipelines — what is active right now\n\nIf you want a live answer to:\n\n- which systems/tools are active (`regix`, `testql`, `wup`, `redup`, `sumr`, …),\n- which pipelines are enabled (`idle-diagnostics`, `gate:regix`, `scan:on-change`,\n  `autoloop:queue`, `autopilot:drive`),\n- and how they are connected,\n\nuse topology mode:\n\n```bash\n# terminal view\nkoru topology\nkoru topology --format json\n\n# toggle one component or pipeline\nkoru topology --disable redsl\nkoru topology --enable-pipeline gate:sumr\n\n# predicate (exit 0/1)\nkoru topology --is-enabled gate:regix\nkoru topology --enabled-components-for idle-diagnostics\n```\n\nState is persisted in `.koru/topology.yaml`.\n\nDashboard (`koru serve`) now includes a **Topology \u0026 pipelines** panel with\ncheckboxes. Toggling a checkbox updates `.koru/topology.yaml` via\n`POST /api/topology`.\n\nThese flags are honored by runtime behavior:\n\n- `scripts/koru-autoloop.sh` respects pipeline toggles for scan/queue/idle-diagnostics/autopilot,\n- quality tasks (`quality:regix`, `quality:redup`, `quality:sumr:*`) skip when the matching\n  topology pipeline is disabled.\n\n## Diagnostics — `koru --doctor`\n\nWhen something feels off (LLM stuck, queue runner refusing, policy\nnot taking effect), run:\n\n```bash\nkoru --doctor                 # human-readable PASS/WARN/FAIL list\nkoru --doctor --format json   # machine-readable for the LLM itself\nkoru --doctor --fix           # read-only guided repair commands\n```\n\nThe doctor probes project, planfile, policy, topology, autonomous env,\nagent-backend, CI, and pytest-collection health. It never writes anything.\nExit code is `1` if any check fails, `0` if only warnings (warnings are\nadvisory). Use it after `koru --init` and whenever a session starts\nmis-behaving. For the full repair checklist, see\n[`docs/autodiagnostics-auto-repair.md`](docs/autodiagnostics-auto-repair.md).\n\nNatural-language intake and housekeeping are built in:\n\n```bash\nkoru task \"Dodaj feature importu raportów\"\nkoru agent --list          # show Windsurf/Cursor/Claude Code/aider/OpenRouter lanes\nkoru agent                 # print and save the current LLM handoff prompt\nkoru agent --launch        # launch the best available CLI agent when possible\nkoru scan                  # auto-generate tickets from repo signals (TODOs, pytest errors)\nkoru scan --apply          # create the proposed tickets in planfile\nkoru gc                    # preview stale tickets eligible for cleanup\nkoru gc --apply            # delete old done/failed/blocked tickets\nkoru gate authorize PLF-070 --mode advisory --reason \"...\"  # record a gate waiver\n```\n\nThe no-args `koru` prompt includes detected project markers\n(`pyproject.toml`, `package.json`, `Taskfile.yml`, `.windsurf/`, `.cursor/`,\n`.planfile/`), available LLM/IDE lanes, the recommended agent, the active\nticket, and the exact lifecycle commands the agent may use.\n\n## Autopilot — drive your IDE from the terminal\n\n`koru autopilot` lets a terminal-side koru take over the LLM chat in\n**Windsurf / VS Code / VSCodium / Cursor / JetBrains / Zed**: it types the next ticket\nbrief directly into the chat panel and presses submit, with zero\nclicks. Useful when an in-IDE session ends and you want koru to\ncontinue the loop from a separate terminal (or tmux pane, or SSH).\n\n```bash\n# 0) make this shell deterministic\nkoru --version\nwhich koru\n\n# Choose one instance when several IDEs are open.\n# Common values: vscode, vscodium, cursor, windsurf, jetbrains, zed.\nexport KORU_AUTOPILOT_INSTANCE=vscode\n\n# 1) verify host backends, IDE detection and install state\nkoru autopilot doctor\nkoru autopilot doctor --fix\nkoru autopilot ide-list\nkoru autopilot manage --ide vscode\n\n# VS Code and VSCodium intentionally use separate identities and sockets:\n# /run/user/$UID/koru-autopilot-vscode.sock\n# /run/user/$UID/koru-autopilot-vscodium.sock\n\n# guided host setup (optional apt auto-install for xdotool/wtype/ydotool)\nkoru autopilot setup-host\nkoru autopilot setup-host --install --dry-run\nkoru autopilot setup-host --install\n\n# install/reassert the VS Code-family plugin and socket setting\nkoru autopilot manage --ide vscode --fix --dry-run\nkoru autopilot manage --ide vscode --fix\n\n# 2) run daemon (recommended long-running setup via systemd --user)\nkoru autopilot install-unit\nsystemctl --user daemon-reload\nsystemctl --user enable --now koru-autopilot.service\n\n# fallback: run daemon in a terminal/tmux pane\nkoru autopilot daemon --project \"$(pwd)\"\n\n# 3) after IDE reload: connect plugin and verify live runtime\n# Command Palette in IDE: \"koru: Connect autopilot daemon\"\nkoru autopilot status\nkoru autopilot manage --ide vscode\n\n# 4) inject into IDE chat through the daemon/plugin path\nkoru autopilot handoff --project \"$(pwd)\" --ide vscode --require-plugin\nkoru autopilot drive --ide vscode --require-plugin 'continue with the next ticket'\nkoru autopilot tail -n 50\n\n# Strict runtime gate for one-off drive commands:\n# block drive if the connected plugin version is stale.\nKORU_STRICT_PLUGIN_VERSION=1 KORU_STRICT_PLUGIN_ACK=1 \\\n  koru autopilot drive --ide vscode --require-plugin 'probe strict plugin version'\n\n# Optional: coordinate fallback (global focus+click+type), bypassing daemon.\nkoru autopilot calibrate --ide vscode\nkoru autopilot drive --direct --os-profile vscode --prompt 'continue with the next ticket'\nkoru autopilot drive --direct --os-profile vscode --delay-seconds 5 \\\n  --prompt 'continue with the next ticket'\n\n# Multi-IDE session bootstrap: calibrate each IDE + immediate smoke prompt.\nkoru autopilot session-start --ides auto --delay-seconds 5\n\n# If PATH points to an older installed koru, run from source checkout:\nPYTHONPATH=src python -m koru.cli autopilot calibrate --ide vscode --delay-seconds 8\n\n# Autonomous loop. `koru auto` enables strict plugin version + ACK policy by default\n# and skips chat drive until a compatible live plugin is connected.\nkoru auto\nkoru autonomous up --project .\n\n# phase-1 tool coverage detection (registry-backed)\nkoru tools detect\nkoru tools detect --format json\n\n# phase-2 tool adapter scaffold ticket\nkoru task \"Prepare Gemini adapter\" --project . --tool gemini-cli\n\n# phase-3 native lane launchers\nkoru agent --agent gemini-cli --project . --launch\nkoru agent --agent cline --project . --launch\nkoru agent --agent qwen-code --project . --launch\nkoru agent --agent opencode --project . --launch\n\n# machine-readable agent readiness report\nkoru agent --project . --list --format json\n\n# non-invasive smoke test (daemon routing + IDE autodetect, no real key injection)\nscripts/autopilot-ide-autodetect-smoke.sh --require-running-ide\nscripts/autopilot-ide-autodetect-smoke.sh --check-ide jetbrains --check-ide windsurf\n```\n\nNewer autopilot functions you can use directly from CLI:\n\n- `koru autopilot handoff` — build current koru brief and inject it in one shot.\n- `koru autopilot manage` — inventory/repair the active installation: `koru` binary,\n  daemon socket, installed plugin, connected plugin and expected VSIX version.\n- `koru autopilot install-unit` — install `systemd --user` unit for persistent daemon.\n- `koru autopilot tail` — read persistent autopilot audit log (text or JSON).\n\n`koru autopilot manage` reports the plugin state as:\n\n- `connected` / `version` / `buildSha` — the live plugin currently attached to the daemon,\n- `installed` — the extension version reported by the editor CLI,\n- `expected` — the VSIX/package version bundled with the active koru runtime.\n- `expected_build` — the VSIX build hash expected by the active koru runtime.\n\nIf `installed=expected` but `connected=False`, installation is healthy and the next\nstep is runtime handshake: start the daemon, reload the IDE window and run\n`koru: Connect autopilot daemon`. If the daemon recently rejected old live plugin\nversions or build hashes, `manage` reports `plugin_live_host_stale`; the extension\nis installed on disk, but the editor's live extension host still needs a reload.\n`koru auto` enables strict plugin version/build and strict submit ACK policy by default, so it skips\nchat drive instead of sending prompts through a stale or unverifiable plugin.\n\nTwo injection paths, picked automatically:\n\n1. **IDE plugin** — if `plugins/koru-autopilot-vscode/` is loaded in\n   the editor, the daemon forwards `chat.send` to it and the\n   extension pastes + submits via the editor's own API. Most reliable;\n   works on Wayland. Runtime version drift is rejected by `koru auto`;\n   one-off `koru autopilot drive` can opt into the same behavior with\n   `KORU_STRICT_PLUGIN_VERSION=1 KORU_STRICT_PLUGIN_ACK=1`.\n2. **Keyboard simulation** — fallback for editors without the plugin.\n   Uses `xdotool` on X11, `wtype`/`ydotool` on Wayland.\n\n- **Start here:** [`docs/autopilot-quickstart.md`](docs/autopilot-quickstart.md) —\n  30-second setup, full checklist, common pitfalls, security model.\n- **Architecture \u0026 wire protocol:** [`docs/autopilot-design.md`](docs/autopilot-design.md).\n- **Formal IDE protocol (normative + operational):** [`docs/IDE_PROTOCOL.md`](docs/IDE_PROTOCOL.md).\n- **Normative wire contract `v1` (API table/spec):** [`docs/specs/kide-002-koruide-api-v1.md`](docs/specs/kide-002-koruide-api-v1.md).\n- **What is shipped vs. planned:** [`docs/autopilot-roadmap.md`](docs/autopilot-roadmap.md).\n\n## Windsurf autonomous mode (hours, unattended)\n\nIf you want `koru + Windsurf` to keep working for hours with minimal human input,\nuse the built-in autoloop wrapper.\n\n### 1) Prepare once per machine\n\n```bash\n# verify keyboard/plugin path\nkoru autopilot doctor\nkoru autopilot manage --ide windsurf\n\n# recommended persistent daemon setup\nexport KORU_AUTOPILOT_INSTANCE=windsurf\nkoru autopilot install-unit\nsystemctl --user daemon-reload\nsystemctl --user enable --now koru-autopilot.service\n```\n\nInstall and enable the VS Code/VSCodium/Windsurf/Cursor plugin from\n[`plugins/koru-autopilot-vscode/`](plugins/koru-autopilot-vscode/) for the most\nreliable injection path on Wayland. Use `koru autopilot manage --ide windsurf --fix`\nto install or reassert the bundled VSIX and write the socket setting.\n\n### 2) Start autonomous loop in project root\n\n```bash\ncd /path/to/project\ntask queue:autoloop\n```\n\nAfter `pip install koru`, you can bootstrap + run autonomy in one command\n(no Taskfile required):\n\n```bash\ncd /path/to/project\nKORU_AUTOPILOT_INSTANCE=windsurf koru autonomous up\n```\n\nUseful variants:\n\n```bash\n# safest diagnostic pass (queue only, one cycle, no IDE drive)\nkoru autonomous safe-up --project .\n\n# smoke run (single cycle)\nKORU_AUTOPILOT_INSTANCE=windsurf koru autonomous up --max-cycles 1 --sleep-seconds 0\n\n# long-running 24/7 mode with explicit actor + queue\nKORU_AUTOPILOT_INSTANCE=windsurf koru autonomous up \\\n  --actor koru-bot --queue-name default --sleep-seconds 30\n\n# queue-only mode (no autopilot injection)\nkoru autonomous up --no-autopilot\n```\n\nWhat each iteration does:\n\n1. `koru scan --apply`\n2. `koru --queue --loop --max-iterations ...`\n3. `koru autopilot drive --ide \"$KORU_AUTOPILOT_INSTANCE\" --require-plugin \"continue with the next ticket\"`\n4. sleep (`SLEEP_SECONDS`, default `120`)\n\nThis loop is resilient by design: if one step fails, it logs the error and\ncontinues next iteration. Autopilot drive is fail-closed by default: when the\nlive plugin is missing, stale, or cannot confirm submit with a strict ACK, the\ncycle records `autopilot=skipped(...)` or `autopilot=failed` instead of using a\nWayland keyboard fallback with the wrong focus.\n\n### 3) Useful long-run overrides\n\n```bash\n# faster cadence\ntask queue:autoloop SLEEP_SECONDS=30 MAX_ITERATIONS=100\n\n# single execution queue only\ntask queue:autoloop QUEUE_NAME=default\n\n# include interactive handling of human tickets\ntask queue:autoloop ENABLE_INTERACTIVE=true\n\n# queue-only mode (without autopilot ping)\ntask queue:autoloop ENABLE_AUTOPILOT_DRIVE=false\n```\n\n### 4) Monitor while it runs\n\n```bash\nKORU_AUTOPILOT_INSTANCE=windsurf koru autopilot status\nKORU_AUTOPILOT_INSTANCE=windsurf koru autopilot manage --ide windsurf\nkoru autopilot tail -n 200\njournalctl --user -u koru-autopilot -f\n```\n\nRelated docs:\n\n- [`docs/autopilot-quickstart.md`](docs/autopilot-quickstart.md)\n- [`docs/cli-examples.md`](docs/cli-examples.md)\n- [`scripts/koru-autoloop.sh`](scripts/koru-autoloop.sh)\n- [`docs/agent-guide.md`](docs/agent-guide.md)\n- [`docs/ide-router.md`](docs/ide-router.md) — `koru ide-router`, headless vs IDE merge\n- [`docs/ide-control-surfaces.md`](docs/ide-control-surfaces.md) — MCP, autopilot, RPC, DAP, profiles\n\n## Two operational modes\n\n| Mode | When | What runs |\n|---|---|---|\n| **Default: IDE-native** | normal ticket work, no external API | Windsurf/Cursor LLM + `task tickets:next` + regix/pytest |\n| **Opt-in: OpenRouter automation lane** | infra smoke tests, headless auto-fix, scheduled runs | `redsl improve`, `llx fix`, `vallm validate --semantic` (all use OpenRouter) |\n\n## Install (editable)\n\n```bash\npip install -e .\n```\n\n## Multi-repo loop mode\n\nRun one command across matching repositories and retry failures in a closed loop:\n\n```bash\nkoru \\\n  --workspace /path/to/repos \\\n  --include \"semcod/*\" \\\n  --command \"python -m pytest -q\"\n```\n\n### Or use Taskfile\n\n```bash\ntask                          # list all tasks (40+)\ntask install                  # pip install -e .\ntask ci                       # local CI equivalent: lint + tests\ntask install:tools            # semcod toolchain: planfile, wup, testql, regix, redup, ...\ntask tickets:next             # highest-priority open ticket\ntask queue:run                # execute one runnable planfile queue task\ntask queue:dry-run            # preview the next planfile queue task\ntask queue:watch              # watch planfile WebSocket queue events\ntask queue:autoloop           # unattended scan+queue+autopilot loop\ntask quality:semcod:planfile  # semcod gates -\u003e deduplicated planfile tickets\ntask quality:regix            # regression metrics gate\ntask quality:redup            # duplicate detection\ntask template:install         # bootstrap configs in current dir\ntask webhook:run              # start healing-webhook on :8810\n```\n\nFull examples: [`docs/cli-examples.md`](./docs/cli-examples.md)\n\n## Planfile queue runner\n\n`koru` can execute one runnable `planfile` ticket at a time, or drain\nthe entire queue in a single call:\n\n```bash\n# Single tick (legacy, default):\nkoru --queue --project . --actor koru-shell\n\n# Drain everything:\nkoru --queue --project . --loop --max-iterations 50\n\n# Drain shell tickets AND answer humans interactively in one shot:\nkoru --queue --project . --loop --interactive --actor c2004-koru\n\n# Preview without execution:\nkoru --queue --project . --dry-run\n```\n\nBy default koru uses the current Python environment's `planfile` module when\navailable, then falls back to the `planfile` executable in `PATH`. To pin a\nspecific command:\n\n```bash\nKORU_PLANFILE_CMD=\"python -m planfile.cli\" koru --queue --project .\n```\n\nSupported executor kinds:\n\n- `executor.kind: shell` — claim, start, run `inputs.script` or `executor.handler`,\n  then complete or fail the ticket.\n- `executor.kind: api` — claim, start, call `inputs.api_endpoint` (or\n  `executor.handler`) with `inputs.api_method`, `inputs.api_headers`,\n  `inputs.api_body`, then complete or fail the ticket.\n- `executor.kind: llm` — claim, start, POST `inputs.prompt` to an\n  OpenAI-compatible chat-completion endpoint (default OpenRouter),\n  capture the assistant's text as the ticket's `stdout`, and store\n  `llm_model` + token `usage` in the result-json. Configure via\n  `OPENROUTER_API_KEY` / `OPENAI_API_KEY` / `KORU_LLM_ENDPOINT`. See\n  [`docs/cli-examples.md`](docs/cli-examples.md) for the full schema.\n- `executor.kind: human` — print the prompt and leave the task for\n  an operator. With `--interactive`, koru collects the answer on\n  stdin (multi-line, Ctrl-D submits, Ctrl-C cancels) and completes\n  the ticket itself.\n\nThe remaining executor kind (`mcp`) is intentionally reported as\nunsupported until its adapter is wired (Phase 5).\n\nMinimal API ticket:\n\n```yaml\ntickets:\n  PLF-010:\n    name: \"Notify deployment API\"\n    status: open\n    priority: high\n    executor:\n      kind: api\n      mode: automatic\n    execution:\n      queue: default\n      state: ready\n    inputs:\n      api_endpoint: \"http://localhost:8810/probe-failure\"\n      api_method: POST\n      api_headers:\n        content-type: application/json\n      api_body:\n        source: koru\n```\n\nTo watch queue changes streamed by the `planfile` API:\n\n```bash\nuvicorn planfile.api.server:app --reload --port 8000\nkoru --watch --ws-url ws://localhost:8000/ws\ntask queue:watch\n```\n\nFor transparent management-layer logs in a dashboard, point koru at the\nplanfile event-ingest endpoint:\n\n```bash\nexport KORU_EVENTS_URL=\"http://localhost:8000/events/ingest\"\nkoru --queue --project . --dry-run\n```\n\nWhen configured, koru emits best-effort `management.event` entries for\n`koru.bootstrap`, `koru.queue`, `koru.watch`, and repository loop runs. This is\nintended for UI surfaces such as planfile's **Live Events** panel and does not\nchange queue execution semantics.\n\n`watch` support uses the optional `websockets` package. Install it with:\n\n```bash\npip install \"koru[watch]\"\n```\n\n## Queue garbage collection — `koru gc`\n\nOver time, completed and failed tickets accumulate in the sprint YAML.\n`koru gc` cleans them up:\n\n```bash\nkoru gc                              # dry-run: preview what would be removed\nkoru gc --apply                      # actually delete stale tickets\nkoru gc --max-age 7                  # only keep tickets younger than 7 days\nkoru gc --keep-last 5                # always keep the 5 newest done tickets\nkoru gc --status done,failed         # only clean these statuses (default: done,failed,blocked)\nkoru gc --no-archive                 # skip JSONL archive before deletion\nkoru gc --format json                # machine-readable output\n```\n\nBefore deletion, tickets are archived to\n`.planfile/.koru/gc/gc-YYYYMMDD-HHMMSS.jsonl` (disable with `--no-archive`).\nThe `--keep-last N` flag protects the N most recently finished tickets per\nstatus even when they exceed `--max-age`.\n\n## Filesystem contract\n\nThe planfile execution runtime writes under `\u003cproject\u003e/.planfile/`.\nFeature-level local configuration and opt-in observation state can also live\nunder `\u003cproject\u003e/.koru/`; both trees are generated and gitignore-friendly.\n\n```\n\u003cproject\u003e/.planfile/\n├── config.yaml                  # planfile-owned (project config)\n├── sprints/\n│   └── current.yaml             # planfile-owned (source of truth)\n└── .koru/                       # koru-owned, opt-in, gitignore-friendly\n    ├── runs/                    # one log per `koru --queue` invocation\n    ├── gc/                      # JSONL archives from `koru gc --apply`\n    ├── prompts/                 # captured `--interactive` answers\n    ├── llm-cache/               # opt-in LlmExecutor response cache\n    └── README.md                # in-place explainer\n```\n\nThe `.koru/` subtree is **non-authoritative** — planfile sprint YAML is\nalways the source of truth. Anything in `.koru/` can be deleted at any\ntime without losing ticket state. Recommended `.gitignore` entry:\n\n```gitignore\n.koru/\n.planfile/.koru/\n```\n\nThe path helpers exposed by `koru.runtime` (`runtime_dir`, `runs_dir`,\n`new_run_id`, `ensure_runs_dir`) are pure resolvers — they only touch\ndisk via `ensure_runs_dir`, so a `--dry-run` invocation leaves zero\ntrace.\n\n**`/tmp/` policy.** Production code does not use `/tmp/`. Test\nfixtures (`tests/` and `tests/e2e/*.sh`) are the only allowed\n`/tmp/` users and MUST be PID-scoped (`/tmp/koru-*-$$`) with\n`trap cleanup EXIT` so a failed run leaves nothing behind. If you find\nkoru artefacts elsewhere, please open an issue.\n\n## LLM agent contract — koru as the gate\n\nWhen an LLM agent (Cascade, Cursor, aider, claude-code, local model, …)\ndrives a koru-managed project, it must **read its instructions from\nkoru, not from the human chat**.\n\nThe agent's first command in every session is just `koru` — the\nmarkdown brief that comes back is the entire contract. If the project\nhas never been initialised, the brief leads with **⚠ Setup required**\nand the exact `koru --init` command. The contract is delivered by:\n\n```bash\nkoru --context --project .                     # JSON brief (machine-readable)\nkoru --context --project . --format markdown   # Markdown handoff (paste-to-IDE)\nkoru --context --project . --ticket PLF-074    # brief for a specific ticket\n```\n\nThe brief contains everything an autonomous agent needs to act safely:\n\n- **the next runnable ticket** (or one named via `--ticket`) — id,\n  name, status, files in scope, prompt, executor kind;\n- **the resolved policy** — explicit booleans for every git operation\n  the agent might attempt;\n- **environment fingerprint** — git branch, dirty state, remote,\n  whether planfile is initialised in the project;\n- **imperative rules** — copy-paste-able `DO NOT …` lines so even a\n  weak model can compare any candidate command to a checklist;\n- **self-service vocabulary** — concrete `planfile ticket {claim,start,\n  complete,fail,input}` invocations with the active ticket id pre-filled.\n\n### Safe-by-default policy\n\nThe policy lives at `\u003cproject\u003e/.planfile/.koru/policy.yaml`. **All\ngates default to the most restrictive value.** A missing or malformed\nfile falls back to defaults — corruption can never silently loosen\nthe policy.\n\n| gate | default | meaning |\n|---|---|---|\n| `allow_commit` | `false` | the agent does NOT run `git commit` |\n| `allow_push` | `false` | the agent does NOT run `git push` |\n| `allow_branch_create` | `false` | no `git checkout -b`, `git branch X`, `git switch -c` |\n| `allow_branch_switch` | `false` | no `git checkout \u003cref\u003e`, `git switch \u003cbranch\u003e` |\n| `allow_tag` | `false` | no `git tag` |\n| `allow_destructive_shell` | `false` | blocks `rm -rf /`, `dd`, `mkfs`, force-pushes, … |\n| `require_planfile_lifecycle` | `true` | every state change goes through `planfile ticket *` |\n| `require_ci_pass_before_complete` | `true` | the agent verifies CI exit 0 before `ticket complete` |\n\nThe agent **bounces off CI/CD and koru**: it cannot commit, cannot\npush, cannot mutate planfile state outside the CLI vocabulary the\nbrief gave it. To make a change that ships, the agent has exactly two\nexits: complete the ticket (humans/CI take it from there) or call\n`planfile ticket input \u003cid\u003e --prompt \"\u003cquestion\u003e\"` and stop.\n\n### Universal quality gates (built-in)\n\nEvery `koru --init` creates a **universal CI command** that automatically\ndetects and runs quality tools when they're available:\n\n```bash\n# Runs on every ticket completion (if require_ci_pass_before_complete=true)\necho \"=== Universal Quality Gates ===\"\n\n# 1. Project tests (auto-detects runner)\n# - task test (Taskfile)\n# - pytest -q (Python)\n# - npm test (Node.js)\n# - make test (Makefile)\n\n# 2. TestQL E2E scenarios (when *.testql.toon.yaml files exist)\ntestql suite --pattern \"*.testql.toon.yaml\" --output console --fail-fast\n\n# 3. WUP dependency analysis (semcod/wup, when wup.yaml exists)\nwup status\n\n# 4. Regix quality gates (when regix.yaml exists)\nregix gates\n```\n\n**Tools are gracefully skipped** if not installed or configured — no manual\nsetup required for basic quality control. The universal gates ensure:\n\n- **Consistent quality** across all koru projects\n- **Automatic regression testing** with testQL scenarios\n- **Real-time regression monitoring** with `wup watch` when you want an\n  on-change loop for files and services\n- **Zero configuration** for basic validation\n- **Adaptive detection** of project-specific tooling\n\n### Docker OS × IDE smoke matrix\n\nKoru also ships a containerized IDE-routing smoke matrix for environments where\nreal GUI automation is unavailable. It builds one image per Linux base and runs\nthe same autopilot routing/dry-run checks for every supported IDE surface:\n\n```bash\ntask test:docker:ide-matrix\n\n# Narrow the matrix while debugging:\ntask test:docker:ide-matrix SYSTEMS=ubuntu-noble IDES=\"vscode cursor\"\n```\n\nDefault systems: `debian-slim`, `debian-bookworm`, `ubuntu-noble`, `fedora`,\n`alpine`. Default IDEs: `vscode`, `vscodium`, `cursor`, `windsurf`, `jetbrains`, `zed`.\nThe GitHub Actions workflow `Docker IDE Matrix` runs the same 5 × 6 matrix on\ndemand. Each container run verifies the headless IDE route, per-IDE submit-key\ndefaults, isolated autopilot socket names, `koru autopilot drive --direct --dry-run`,\nand `koru autopilot manage` for plugin-managed IDEs.\n\nVS Code and VSCodium are separate lanes. A VSCodium terminal or explicit\n`--ide vscodium` routes to `KORU_AUTOPILOT_INSTANCE=vscodium`, VSCodium settings,\nand `koru-autopilot-vscodium.sock`; it should not attach to the VS Code socket.\n\n### Native OS × IDE smoke matrix\n\nContainer tests cover popular Linux bases. Native GitHub Actions cover host\nplatform differences that Docker does not model:\n\n- `ubuntu-latest`\n- `windows-latest`\n- `macos-latest`\n\nThe `Native IDE Matrix` workflow runs the same IDE set:\n`vscode`, `vscodium`, `cursor`, `windsurf`, `jetbrains`, `zed`.\nIt installs koru, adds fake editor CLIs to `PATH`, runs\n`tests/test_docker_ide_matrix.py`, then smoke-tests `koru autopilot drive` and\n`koru autopilot manage` where the IDE has a plugin-managed lane.\n\niOS is intentionally not part of this matrix: koru autopilot targets desktop IDE\nCLIs, editor extension hosts, and local socket/process workflows. For Apple\ndesktop coverage, use the `macos-latest` lane.\n\nFor continuous monitoring, use the `semcod/wup` package directly:\n\n```bash\nwup map-deps\nwup testql-endpoints testql-scenarios\nwup watch . \\\n  --deps deps.json \\\n  --cpu-throttle 0.8 \\\n  --mode testql \\\n  --scenarios-dir testql-scenarios \\\n  --testql-bin scripts/koru-wup-testql \\\n  --track-dir .wup/tracks \\\n  --quick-limit 3\n```\n\n`wup` watches the paths from `wup.yaml`, maps changed files to affected\nservices, runs quick TestQL probes first, and writes live service status to\n`.wup/service-health.json`. Use `regix` separately for git/metric regressions\nagainst `HEAD`.\n\n### semcod/* control loop → planfile tickets\n\nKoru also has a single operator command for the full semcod toolchain:\n\n```bash\ntask install:tools\ntask quality:semcod:planfile\n```\n\nThat command is intentionally LLM-free. It:\n\n1. runs `koru scan --apply --semcod-artifacts`;\n2. detects configured `semcod/*` tools (`wup`, `testql`, `regix`, `redup`,\n   `sumr/sumd`, `doql`, `redsl`, plus the rest surfaced in the Koru brief);\n3. runs only the gates that are both installed and configured in the project;\n4. uses `scripts/koru-gate-capture.py` to create or update deduplicated\n   `planfile` tickets marked with `[gate-finding:\u003chash\u003e]`.\n\nUseful variants:\n\n```bash\nDRY_RUN=1 task quality:semcod:planfile        # show what tickets would be created\nUPDATE_EXISTING=1 task quality:semcod:planfile # append notes to existing findings\nPRIORITY=critical task quality:semcod:planfile # promote new gate findings\n```\n\nThe source of truth stays in `.planfile/`; Koru does not hand-edit sprint YAML.\nAgents should consume the resulting work through `planfile ticket next` or\n`koru --queue`.\n\n#### Idle queue discovery with code2llm\n\nWhen `koru auto` or `koru autonomous up` drains the queue and reports `idle`,\nKoru can move from local ticket execution back to whole-project discovery. The\nstrategy is active when scan-after-idle is enabled and semcod artifacts are\nincluded. `koru auto` enables scan-after-idle by default so a cycle that moves\nfrom `waiting_input` to `idle` does not wait for the next outer tick before\nrunning intake discovery. Use `--no-scan-after-idle-queue` to disable that\nbehavior. For `koru autonomous up`, pass the knobs explicitly, or let adaptive\nruns (`KORU_AUTO_PIPELINE=1`) enable them for the quality/architecture stages:\n\n```bash\nkoru autonomous up \\\n  --ticket-sources queue \\\n  --scan-after-idle-queue \\\n  --scan-after-idle-min-interval 60 \\\n  --semcod-artifacts\n```\n\nOn an idle cycle Koru first runs a normal intake scan:\n\n```bash\nkoru scan --apply --semcod-artifacts\n```\n\nIf that scan applies no tickets, Koru runs `code2llm` locally first:\n\n```bash\ncode2llm \"$PROJECT\" \\\n  -f all \\\n  -o \"$PROJECT/project\" \\\n  --no-chunk \\\n  --exclude '*.md' \\\n  --planfile-apply \\\n  --planfile-source koru-project-discovery \\\n  --planfile-sprint current \\\n  --planfile-project \"$PROJECT\" \\\n  --planfile-limit 20\n```\n\n`code2llm` refreshes `project/` artifacts such as `analysis.toon.yaml` and\n`planfile-tickets.yaml`, then applies up to 20 high-signal tickets through\n`planfile`. The generated tickets come from whole-project signals such as god\nmodules, duplicated code, cyclomatic complexity, stale architecture pressure,\nand other code2llm findings. Koru records the result as a\n`Code2llmDiscoveryCompleted` event with `applied`, `skipped`, `ran`, and error\nmetadata.\n\nIf scan + code2llm still leave the queue empty, Koru adds a bounded IDE LLM\nfollow-up task:\n\n\u003e \"Co jeszcze zostalo do wykonania? zrob z tego nastepne tickety do planfile.\"\n\nThis follow-up is ticket-oriented by contract: the output should be additional\nplanfile tickets, not broad direct edits.\n\nThe standardized workflow is: auto-create/reuse a project-discovery ticket,\nattach the follow-up question to that ticket context, then close it with the\nnormal planfile handoff (`done` / `input` / `fail`).\n\nThis is the intentional autonomy rhythm: work concrete tickets first; when the\nqueue is empty, inspect the whole project; turn broad findings into planfile\ntickets; then stop discovery and let the normal queue work those tickets one by\none. IDE LLM prompts for generated or existing tickets include a Planfile status\nhandoff, so the agent is expected to run `planfile ticket done \u003cID\u003e` after\nsuccessful checks, `planfile ticket input \u003cID\u003e --prompt ... --note ...` when it\nis blocked, or `planfile ticket fail \u003cID\u003e --error ...` after a real failed\nattempt. The Planfile status is the source of truth for what the IDE LLM\nactually completed.\n\nDiscovery is rate-limited in two places: `--scan-after-idle-min-interval`\nlimits idle scans, and fresh `project/analysis.toon.yaml` artifacts younger\nthan 60 minutes skip a full `code2llm` rerun. If `code2llm` is missing or the\nrun fails, Koru logs a structured skipped/error outcome; install `code2llm` or\nrun the command above manually, then continue through the normal planfile queue.\n\nFull strategy details are in\n[`docs/project-discovery-strategy.md`](./docs/project-discovery-strategy.md).\n\n### Auto-promotion \u0026 auto-repair for blocking tickets\n\nKoru automatically manages workflow priorities to prevent deadlocks:\n\n#### **Auto-promotion**\n- Tickets that block others are **automatically promoted to `critical` priority**\n- This ensures blocking issues are resolved first\n- Promotion happens on every `koru --context` call\n\n#### **Auto-repair mode**\n- Critical tickets receive **special instructions for LLM agents**:\n  - \"AUTO-REPAIR MODE: Fix this issue immediately to unblock the workflow\"\n  - \"Do NOT ask for human input unless absolutely necessary\"\n  - \"Use all available tools and knowledge to resolve the blocking issue\"\n  - \"After fixing, immediately call `planfile ticket complete`\"\n\n#### **Workflow**\n1. **Main task** → encounters blocking issue\n2. **Blocking ticket** created → auto-promoted to `critical`\n3. **LLM agent** receives auto-repair instructions\n4. **Issue resolved** → main task unblocked\n5. **Workflow continues** without manual intervention\n\n### Bug-first priority system\n\nKoru ensures bugs are always fixed before features when priorities are equal:\n\n#### **Automatic bug promotion**\n- Bugs get **priority boost** within their category:\n  - `low` → `normal`\n  - `normal` → `high`\n  - `high` → `critical`\n  - `critical` stays `critical`\n- Promotion happens automatically on every `koru --context` call\n- Only tickets with `bug` label are promoted\n\n#### **Priority hierarchy**\n```\ncritical (blocking tickets + high-priority bugs)\n├── high bugs (promoted from normal)\n├── high features\n├── normal bugs (promoted from low)\n├── normal features\n├── low bugs\n└── low features\n```\n\n#### **Benefits**\n- **Bug-first workflow** — stability issues resolved before new features\n- **Automatic triage** — no manual priority adjustments needed\n- **Predictable execution** — bugs always jump ahead of same-priority features\n- **Quality assurance** — prevents feature development while bugs exist\n\n### Integration with planfile\n\nKoru's priority system is **fully integrated with planfile**:\n\n#### **Shared priority logic**\n- **Same promotion rules** applied in both koru and planfile core\n- **Consistent ticket ordering** across all planfile commands\n- **Unified bug-first workflow** throughout the ecosystem\n\n#### **Planfile commands enhanced**\n- `planfile ticket next` — respects bug-first priorities\n- `planfile ticket list` — shows promoted priorities\n- `planfile queue` — processes bugs before features\n- **All planfile operations** use the same priority hierarchy\n\n#### **Seamless workflow**\n1. **Koru auto-promotes** tickets on `--context` call\n2. **Planfile respects** promoted priorities natively\n3. **Consistent execution** whether using koru or planfile directly\n4. **No conflicts** — both systems use identical priority logic\n\n### Loosening the policy\n\nEditing `\u003cproject\u003e/.planfile/.koru/policy.yaml` is the **only** way to\nrelax a default. There is no CLI flag for it — that is a deliberate\nchoice so any loosening is reviewable in git history.\n\n```yaml\n# .planfile/.koru/policy.yaml\nllm:\n  allow_commit: false       # never (recommended)\n  allow_push: false         # never (recommended)\n  allow_branch_create: true # opt-in: agent may create feature branches\nci:\n  command: pytest -q        # override universal gates (optional)\n  timeout_seconds: 300\nnotes:\n  - \"Always run `task lint` before `ticket complete`.\"\n  - \"Never edit migrations under alembic/versions/.\"\n```\n\n### Run logs\n\n`koru --queue` and `koru --queue --loop` write a JSON-Lines log per run\nto `\u003cproject\u003e/.planfile/.koru/runs/queue-\u003ctimestamp\u003e-\u003cpid\u003e.jsonl`:\n\n```jsonl\n{\"type\":\"run.start\",\"run_id\":\"queue-…\",\"mode\":\"loop\",\"actor\":\"koru\",\"pid\":12345,…}\n{\"type\":\"iteration\",\"iteration\":1,\"ticket_id\":\"PLF-074\",\"status\":\"completed\",…}\n{\"type\":\"iteration\",\"iteration\":2,\"ticket_id\":\"PLF-075\",\"status\":\"failed\",…}\n{\"type\":\"run.end\",\"iterations\":2,\"completed\":[\"PLF-074\"],\"failed\":[\"PLF-075\"],…}\n```\n\n`--dry-run` skips the writer (preserves \"dry-run leaves zero trace\").\n`--no-log` opts out explicitly. Logs are non-authoritative — planfile\nsprint YAML remains the source of truth.\n\n## Documentation\n\nThe full documentation lives in [`docs/`](./docs/):\n\n- **[`docs/autopilot-quickstart.md`](./docs/autopilot-quickstart.md)** —\n  production setup for `koru autopilot` (doctor, daemon, plugin, systemd user unit,\n  handoff, audit log, troubleshooting).\n- **[`docs/agent-guide.md`](./docs/agent-guide.md)** — full LLM agent\n  workflow guide (originally written for `maskservice/c2004` Windsurf\n  agent, generalized for any koru-driven repo). Covers ticket workflow,\n  validation gates, anti-patterns, troubleshooting.\n- **[`docs/planfile-llm-guide.md`](./docs/planfile-llm-guide.md)** —\n  ticket-driven development with `planfile` CLI.\n- **[`docs/planfile-execution-gateway.md`](./docs/planfile-execution-gateway.md)** —\n  design for turning `planfile.yaml` into the execution gateway for shell,\n  MCP, API, human, and LLM tasks.\n- **[`docs/llm-tools/`](./docs/llm-tools/)** — per-tool docs and install\n  scripts:\n  - [`planfile/`](./docs/llm-tools/planfile/) — ticket backlog\n  - [`regix/`](./docs/llm-tools/regix/) — Python regression metrics\n  - [`redup/`](./docs/llm-tools/redup/) — duplicate detection\n  - [`redsl/`](./docs/llm-tools/redsl/) — OpenRouter auto-refactor (opt-in)\n  - [`vallm/`](./docs/llm-tools/vallm/) — multi-tier patch validator\n  - [`prefact/`](./docs/llm-tools/prefact/) — proactive LLM-aware linter\n  - [`pfix/`](./docs/llm-tools/pfix/) — auto-fix imports\n  - [`llx/`](./docs/llm-tools/llx/) — LLM CLI wrapper\n  - [`sumd/`](./docs/llm-tools/sumd/) — LLM refactor snapshots (SUMR.md)\n  - [`redeploy/`](./docs/llm-tools/redeploy/) — multi-target deployment (markpact specs)\n  - [`goal/`](./docs/llm-tools/goal/) — automated git push + smart commits + release workflow\n  - [`doql/`](./docs/llm-tools/doql/) — declarative infrastructure-as-code (.doql files)\n  - [`costs/`](./docs/llm-tools/costs/) — zero-config AI cost tracker per commit\n  - [`op3/`](./docs/llm-tools/op3/) — layered infrastructure observation (multi-layer scan)\n  - [`toonic/`](./docs/llm-tools/toonic/) — universal TOON format platform (LLM-friendly compact files)\n  - [`protogate/`](./docs/llm-tools/protogate/) — migration tool dla legacy systems (bounded slices)\n  - [`rebuild/`](./docs/llm-tools/rebuild/) — code evolution intelligence (git history walker)\n  - [`mdflow/`](./docs/llm-tools/mdflow/) — markdown dependency analyzer\n  - [`metrun/`](./docs/llm-tools/metrun/) — execution intelligence + bottleneck detection\n  - [`aider/`](./docs/llm-tools/aider/) — pair-programming agent\n  - [`claude-code/`](./docs/llm-tools/claude-code/) — Anthropic agent\n  - [`cursor/`](./docs/llm-tools/cursor/) — Cursor IDE setup\n  - [`testql/`](./docs/llm-tools/testql/) — declarative HTTP tests\n\n## Templates (config snippets)\n\nReference configurations from the c2004 reference deployment:\n\n- [`templates/pyqual.yaml.template`](./templates/pyqual.yaml.template) — full pipeline orchestrator\n- [`templates/redup.toml.template`](./templates/redup.toml.template) — duplicate budget\n- [`templates/redsl.yaml.template`](./templates/redsl.yaml.template) — refactor lane config\n- [`templates/regix.yaml.template`](./templates/regix.yaml.template) — regression metrics\n\n## License\n\nLicensed under Apache-2.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsemcod%2Fkoru","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsemcod%2Fkoru","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsemcod%2Fkoru/lists"}