Skip to content

Commit ac8b0b0

Browse files
feat(docs): update docs
Statistics: 11 files changed, 420 insertions, 160 deletions Summary: - Dirs: src=6, .=2, tests=2, docs=1 - Exts: .py=8, .md=2, .lock=1 - A/M/D: 1/10/0 - Added: tests/test_autopilot_socket_path.py - Symbols: _queue_lock_wanted, planfile_runner, _autopilot_socket_basename, _planfile_command, test_ticket_claim_failure_returns_claim_failed Added files: - tests/test_autopilot_socket_path.py (+28/-0) Modified files: - README.md (+4/-4) - docs/autopilot-quickstart.md (+12/-0) - src/koru/agents.py (+13/-0) - src/koru/autonomous.py (+4/-1) - src/koru/autopilot/__init__.py (+34/-5) - src/koru/autopilot/cli_command.py (+4/-1) - src/koru/context.py (+10/-0) - src/koru/planfile_queue.py (+234/-142) - tests/test_planfile_queue.py (+76/-6) - uv.lock (+1/-1) Implementation notes (heuristics): - Type inferred from file paths + diff keywords + add/delete ratio - Scope prefers 'goal' when goal/* is touched; otherwise based on top-level dirs - For <=6 files: generate short per-file notes from added lines (defs/classes/click options/headings) - A/M/D derived from git name-status; per-file +X/-X from git numstat
1 parent d7765a8 commit ac8b0b0

14 files changed

Lines changed: 435 additions & 162 deletions

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6060
`quality:regix``gate:regix`, `quality:redup*``gate:redup`,
6161
`quality:sumr:*``gate:sumr`.
6262

63+
## [0.1.37] - 2026-05-12
64+
65+
### Docs
66+
- Update README.md
67+
- Update docs/autopilot-quickstart.md
68+
69+
### Test
70+
- Update tests/test_autopilot_socket_path.py
71+
- Update tests/test_planfile_queue.py
72+
73+
### Other
74+
- Update uv.lock
75+
6376
## [0.1.36] - 2026-05-12
6477

6578
### Docs

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
## AI Cost Tracking
66

7-
![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.1.36-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
8-
![AI Cost](https://img.shields.io/badge/AI%20Cost-$3.16-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-20.8h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
7+
![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.1.37-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
8+
![AI Cost](https://img.shields.io/badge/AI%20Cost-$3.19-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-20.9h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
99

10-
- 🤖 **LLM usage:** $3.1592 (59 commits)
11-
- 👤 **Human dev:** ~$2077 (20.8h @ $100/h, 30min dedup)
10+
- 🤖 **LLM usage:** $3.1882 (60 commits)
11+
- 👤 **Human dev:** ~$2093 (20.9h @ $100/h, 30min dedup)
1212

1313
Generated on 2026-05-12 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
1414

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.1.36
1+
0.1.37

docs/autopilot-quickstart.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ automatically. If your IDE has the koru-autopilot extension installed,
2424
the daemon will also type the next ticket brief back into the chat the
2525
moment Cascade/Copilot signals it has finished its turn.
2626

27+
## Multiple IDE windows on one machine
28+
29+
Several editors can run koru against the **same** git checkout. Use
30+
**different** automation endpoints so daemons and chat injection do not
31+
fight each other:
32+
33+
| Concern | Mitigation |
34+
|--------|------------|
35+
| **Autopilot Unix socket** | Default is one socket per login (`$XDG_RUNTIME_DIR/koru-autopilot.sock`). Set **`KORU_AUTOPILOT_INSTANCE`** to a unique label per IDE window (e.g. `cursor-main`, `windsurf-2`); the socket becomes `koru-autopilot-<label>.sock`. Or set **`KORU_AUTOPILOT_SOCKET`** to an absolute path per instance. |
36+
| **Planfile queue** | Koru takes an exclusive **`flock`** on `.planfile/.koru/queue-runner.lock` while running `run_next_planfile_task` (POSIX). A second drain **waits** instead of stealing the same ticket. Set **`KORU_QUEUE_RUNNER_LOCK=0`** only if you accept duplicate work. |
37+
| **Ticket ownership** | Before `ticket start`, koru runs **`planfile ticket claim --assigned-to <actor> --lease-seconds …`**. Give each lane a distinct **`--actor`** name so ownership is visible. Tune lease with **`KORU_TICKET_LEASE_SECONDS`** (default 3600, clamped). |
38+
2739
## What gets installed where
2840

2941
| Piece | Lives in | Purpose |

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "koru"
7-
version = "0.1.36"
7+
version = "0.1.37"
88
description = "Closed-loop automation across semcod/* repositories."
99
readme = "README.md"
1010
requires-python = ">=3.12"

src/koru/agents.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,21 @@ def detect_agent_options(project: Path) -> list[AgentOption]:
5454
aider_cmd = _which("aider")
5555
codex_cmd = _which("codex")
5656
openrouter_ready = bool(os.getenv("OPENROUTER_API_KEY"))
57+
antigravity_ready = bool(os.getenv("ANTIGRAVITY_AGENT"))
5758

5859
return [
60+
AgentOption(
61+
id="antigravity",
62+
label="Antigravity Agent",
63+
available=antigravity_ready,
64+
launchable=False,
65+
command=None,
66+
reason=(
67+
"Antigravity runtime detected; operating natively within context."
68+
if antigravity_ready
69+
else "Antigravity environment not found."
70+
),
71+
),
5972
AgentOption(
6073
id="claude-code",
6174
label="Claude Code",

src/koru/autonomous.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ def _build_parser() -> argparse.ArgumentParser:
3232
"--socket",
3333
type=Path,
3434
default=None,
35-
help=f"Autopilot daemon socket path (default: {default_socket_path()}).",
35+
help=(
36+
"Autopilot daemon socket path (default: $XDG_RUNTIME_DIR/koru-autopilot.sock; "
37+
"override with KORU_AUTOPILOT_SOCKET or KORU_AUTOPILOT_INSTANCE — see docs)."
38+
),
3639
)
3740
sub = parser.add_subparsers(dest="action", required=True)
3841

src/koru/autopilot/__init__.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,51 @@
1717
from pathlib import Path
1818

1919

20+
def _autopilot_socket_basename() -> str:
21+
"""File name (with ``.sock``) under ``$XDG_RUNTIME_DIR`` or ``/tmp``."""
22+
instance = os.environ.get("KORU_AUTOPILOT_INSTANCE", "").strip()
23+
if not instance:
24+
return "koru-autopilot.sock"
25+
slug_chars: list[str] = []
26+
for ch in instance[:64]:
27+
if ch.isalnum() or ch in "-_":
28+
slug_chars.append(ch)
29+
else:
30+
slug_chars.append("-")
31+
slug = "".join(slug_chars).strip("-") or "instance"
32+
return f"koru-autopilot-{slug}.sock"
33+
34+
2035
def default_socket_path() -> Path:
2136
"""Return the canonical unix-socket location for the autopilot daemon.
2237
23-
Uses ``$XDG_RUNTIME_DIR/koru-autopilot.sock`` when available
24-
(it is per-user and auto-cleaned by systemd-logind); otherwise
25-
falls back to ``/tmp/koru-autopilot-<uid>.sock``.
38+
Resolution order:
39+
40+
1. ``KORU_AUTOPILOT_SOCKET`` — absolute path (each IDE/plugin should set a
41+
distinct path when several instances share one login session).
42+
2. Otherwise ``$XDG_RUNTIME_DIR/<name>`` where ``<name>`` is
43+
``koru-autopilot.sock`` (legacy) or ``koru-autopilot-<slug>.sock`` when
44+
``KORU_AUTOPILOT_INSTANCE`` is set (e.g. ``cursor-main``, ``windsurf-2``).
45+
3. Fallback under ``/tmp`` — distinct file per uid; instance sockets
46+
include the slug in the file name.
2647
"""
48+
explicit = os.environ.get("KORU_AUTOPILOT_SOCKET", "").strip()
49+
if explicit:
50+
return Path(explicit).expanduser().resolve()
51+
52+
name = _autopilot_socket_basename()
2753
runtime = os.environ.get("XDG_RUNTIME_DIR")
2854
if runtime:
29-
path = Path(runtime) / "koru-autopilot.sock"
55+
path = Path(runtime) / name
3056
try:
3157
path.parent.mkdir(parents=True, exist_ok=True)
3258
except OSError:
3359
pass
3460
return path
35-
return Path(f"/tmp/koru-autopilot-{os.getuid()}.sock")
61+
if name == "koru-autopilot.sock":
62+
return Path(f"/tmp/koru-autopilot-{os.getuid()}.sock")
63+
stem = name.removesuffix(".sock")
64+
return Path(f"/tmp/{stem}-{os.getuid()}.sock")
3665

3766

3867
__all__ = ["default_socket_path"]

src/koru/autopilot/cli_command.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ def _build_parser() -> argparse.ArgumentParser:
3737
"--socket",
3838
type=Path,
3939
default=None,
40-
help=f"Unix-socket path (default: {default_socket_path()}).",
40+
help=(
41+
"Unix-socket path (default from KORU_AUTOPILOT_SOCKET / "
42+
"KORU_AUTOPILOT_INSTANCE / XDG_RUNTIME_DIR — see koru autopilot docs)."
43+
),
4144
)
4245
sub = parser.add_subparsers(dest="action", required=True)
4346

src/koru/context.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,16 @@ def _render_autonomous_mode(*, planfile_initialised: bool) -> list[str]:
750750
"- `--no-autopilot` for queue/scan only",
751751
"- `--autopilot-ide auto|windsurf|jetbrains|cursor|vscode|zed`",
752752
"",
753+
"Multi-IDE / several chat panes on one machine:",
754+
"- Set a **distinct** `KORU_AUTOPILOT_INSTANCE` per IDE window (e.g. `cursor-a`,",
755+
" `windsurf-b`) so each autopilot daemon gets its own Unix socket; or set",
756+
" `KORU_AUTOPILOT_SOCKET` to an absolute path.",
757+
"- Queue drains for the same repo are **serialized** via "
758+
"`.planfile/.koru/queue-runner.lock` (POSIX); disable only if you accept races:",
759+
" `KORU_QUEUE_RUNNER_LOCK=0`.",
760+
"- Use a **unique** `--actor` / `ACTOR` per automated lane so `ticket claim`",
761+
" ownership is visible in planfile.",
762+
"",
753763
]
754764
)
755765
return lines

0 commit comments

Comments
 (0)