- name
- kirocrew-worktree-dev
- description
- HARD RULE for developing the Kiro Crew source repo ITSELF (not users' projects): develop, build and verify in a git worktree, never against the live gateway. Covers env setup, main-clone sync, build/dist ordering, flags, previews, cleanup, publish authorization; kirocrew-prepare-pr owns PRs.
- triggers
- kirocrew worktree, kirocrew main clone sync, kirocrew build gate, kirocrew dev, kirocrew source, contribute to kirocrew, kirocrew repo
# Kiro Crew worktree development
This skill applies ONLY to the Kiro Crew source repository or a worktree of it.
Ignore it for other projects. One feature uses one dedicated worktree containing
both `src/kiro_crew/` and `website/`, including backend-only changes.
Never edit the live checkout or start/stop the live gateway from a feature session.
## Worktree and environment
```bash
# From the main clone; skip creation when already in the assigned worktree.
git fetch origin main
git worktree add ../kirocrew-wt-<name> -b feat/<name> origin/main
cd ../kirocrew-wt-<name>
python3 -m venv .venv
.venv/bin/pip install -e ".[voice]" --group dev
cd website && npm ci && cd ..
git worktree list
```
To bring the main clone itself current (the first path `git worktree list`
prints), fast-forward it and nothing else:
```bash
git -C <main clone> symbolic-ref --short HEAD # must print main
git -C <main clone> fetch origin main
git -C <main clone> merge --ff-only --no-autostash --no-overwrite-ignore origin/main
```
It refuses, changing nothing, when local `main` has diverged or a local change
would be overwritten; then stop and report, because that state belongs to whoever
left it. Before any rebase, checkout, switch, merge, pull or reset in a clone,
run `python3 <this skill>/scripts/live_checkout_guard.py <clone>`. Exit 30 (or 2):
a running gateway runs from it, so make a worktree; the operator's dashboard
Update syncs that clone. Never overlay a whole tree with `git checkout <ref> -- .`
or `git restore --source <ref> .`: neither moves HEAD, both overwrite local edits
without asking, and the checkout form keeps every file upstream deleted. Never
`git stash`: every worktree shares one stash list, so a pop can apply another
session's work.
Working from several worktrees? If `uv` resolves in your shell (`command -v uv`
— it is a declared dependency of the package, so any activated Kiro Crew venv
has it on `PATH`; a bare shell may not), build the venv with it instead: same
deps, but site-packages are copy-on-write clones out of one global cache, so on a
reflink filesystem (XFS with reflink, btrfs, APFS) each extra venv costs ~10 MB
of unique disk and ~10 s instead of ~400 MB and ~1 min; without reflink uv copies,
so you keep the speed and lose the disk saving. `kirocrew pod provision` runs
the same two steps (without the `[voice]` extra) when `KIROCREW_PROVISION_USE_UV=1` is set
(opt-in for now; design record: the "Shared Dependency Cache for Worktrees" RFC
under docs/request-for-change):
```bash
uv venv --seed --allow-existing --link-mode clone --python 3.12 .venv
uv pip install --link-mode clone --python .venv/bin/python --project . -e ".[voice]" --group dev
```
`--link-mode clone` must be explicit (uv's Linux default has been seen to copy
on a reflink-capable filesystem), `--project .` makes `--group` read this
worktree's `pyproject.toml` from any cwd, and `--seed` keeps `.venv/bin/pip`
present for `make backend`. Do not use `--link-mode hardlink`: it shares the
inode, so an in-place edit under `.venv/lib/.../site-packages` would land in every
sibling venv and in the cache. A clone is safe to edit; the write copies the block.
`dev` is a PEP 735 dependency group, not an extra. `--group` needs pip >= 25.1;
if unsupported, upgrade the worktree's pip with `.venv/bin/pip install -U pip`.
On Windows use `.venv\Scripts\` in place of `.venv/bin/`.
Making a worktree live swaps code behind the same URL and REAL data home,
including DB and sessions. Only one can be live at a time. This is not preview
isolation: get explicit authorization for a live cutover or migration, and return
to the clean baseline afterwards. The default home is `~/.kiro/crew`;
`KIROCREW_HOME` overrides it. A legacy `~/.kirocrew` does not auto-migrate.
## Verification
Read `.github/workflows/ci.yml` AND `.github/workflows/fast-gate.yml` for the
canonical blocking gates; CI wins over prose. Never weaken or skip a check to
make it green. For test authoring, flakes, isolation or suite speed, load
`writing-tests` and the owning section of
`docs/system-specs/common/testing-conventions.md` before fixing the test.
During iteration, run `python3 scripts/local-gate.py` from the worktree. It
runs the tests RELATED to the diff on both surfaces with a bounded worker count
and never escalates to a full suite -- meta, mixed and large diffs all get a
related set; an unreadable diff exits 2 and runs nothing. The full suite is CI's
job; `--full` exists for a human who asks. `--dry-run` prints the plan,
`--base REF` selects a base. Before publication, MUST load
[kirocrew-prepare-pr](../kirocrew-prepare-pr/SKILL.md) and run its complete resolved `gates[]`
floor from the base-ref profile. That skill alone owns PR preparation, local
reviewers, history, dispositions and push-to-green steps.
Minimum manual checks, not a replacement for that floor:
```bash
python3 scripts/local-gate.py
isort --check-only src/kiro_crew test conftest.py xdist_budget.py
flake8 src/kiro_crew test conftest.py xdist_budget.py
mypy src/kiro_crew/
cd website
npx tsc -p tsconfig.app.json
npx vitest run
cd ..
```
- Rebuild and stage frontend dist BEFORE backend tests that read static assets.
- A bare `python -m pytest` (the full suite, for a human who wants it) uses
`setup.cfg`'s `-n auto --dist loadgroup` and `--max-worker-restart=2`. Keep
grouping for `xdist_group` serialization. The root conftest budgets workers by
free memory and concurrent runs; explicit `-n <N>` bypasses it. Check host
headroom before a full suite. The gate scripts pass their own bounded `-n`.
A scoped subagent may use serial targeted tests; the parent owns aggregate gates.
- Coverage is off by default (`setup.cfg` addopts carries no `--cov`), so no
`--override-ini` is needed to skip it. An override REPLACES the whole addopts
list; if you must use one for a multi-test run, keep `--ignore=build/private
-p no:platformdirs -n auto --dist loadgroup --max-worker-restart=2
--timeout=120`. Never a bare
`--override-ini=addopts=` for the multi-test gate.
- Capture logs under `$KIROCREW_SCRATCH`; check the command's exit code, not a
pipe's last command. A green `tail` does not mean a green test.
- Reproduce a failure on a clean `origin/main` worktree before calling it
pre-existing or flaky. A branch-only failure is yours. Never fix a flake with
a retry, longer sleep, relaxed assertion or skip; use `writing-tests`.
- To rank suspected flakes, start from the flake ledger: the open issues titled
`Flaky: <test name> ...`, labelled `area: tests`
(`gh issue list --state open --search "flaky in:title"`), where a red confirmed as a
flake is recorded before any rerun (`kirocrew-prepare-pr`, *Before you rerun a red
test*). For a test not on it, mine CI rather than guessing from a local pass:
```bash
gh run list --workflow=ci.yml --limit 250 --json databaseId,conclusion \
--jq '.[]|select(.conclusion=="failure")|.databaseId' > "$KIROCREW_SCRATCH/ci-ids"
```
Read candidate runs with `gh run view <id> --log-failed`, rank recurring test
names, then compare each against main. A ratchet failing on feature branches
may be a true positive. Check Windows timing/process causes as well as Linux.
- Match mypy's version to the dev-group pin in `pyproject.toml`; install the same
`.[voice]` plus `--group dev` dependencies as CI. A venv with `faiss-cpu`
makes imports typed where CI sees `Any`, so it is not a CI mirror. On macOS
run `mypy --platform linux src/kiro_crew`.
A reusable mypy-only environment can be provisioned from the repo root:
```bash
python3 -m venv ~/.kiro/crew/venvs/mypy-ci
~/.kiro/crew/venvs/mypy-ci/bin/pip install -e ".[voice]" --group dev
# Never add faiss. Run from the worktree, which supplies mypy's config.
~/.kiro/crew/venvs/mypy-ci/bin/mypy src/kiro_crew/
```
## The served frontend is built dist
The gateway serves `src/kiro_crew/static/dist/`, not source TSX or a Vite server.
After creating a worktree or changing frontend code, build and stage:
```bash
cd website && npm ci && npm run build && cd ..
PYTHONPATH=src python -m kiro_crew.frontend stage .
```
Every Vite build publishes into `website/dist` atomically
(`website/scripts/publish-dist.mjs`). The stager points `static/dist` at it (the
dev link), or for an edition at a fresh private copy, and a running gateway
follows either on its next request. Never `rm -rf` + `cp -R` `static/dist`:
that deletes the tree a running gateway serves. `make build` builds, installs
and stages. Dist is gitignored and does not transfer with a fetch or new
worktree. To inspect a minified bundle, search surviving route,
API or label strings, not React component names.
## Flags and isolated preview
Flags belong in the RUNNING instance's `$KIROCREW_HOME/config.json`, not in code.
The live gateway uses the shared home; `dev-backend.sh` uses `.kirocrew-dev/`;
each pod has its own home. Editing production config cannot enable a preview
flag. Check the right instance's flag before blaming the bundle. Config's live
fingerprint cache picks up edits without a restart, except fields marked
`restart=True` (the schema's `requiresRestart`), which need that instance
restarted; live flags persist across live-worktree switches.
Green gates are the floor. Preview is optional where unit coverage suffices;
when verifying changed UI, load `web-verify` and inspect the rendered change.
Prefer a disposable isolated pod, built first with venv and dist:
```bash
kirocrew pod up <worktree-name> --json
kirocrew pod up <worktree-name> --seed minimal --json
kirocrew pod down <worktree-name>
```
`kirocrew pod --help` is authoritative. `--provision` runs the build on-ramp.
`--seed` names shipped fixtures (`pod scenarios` lists them); an unknown name is
refused, while a path is the sanitized config-only form. Other boot flags:
- `--approval reads|yolo|interactive` persists the pod's mode; omission inherits
`agent.approval_mode`. No approval flag grants permission to publish or touch live.
- `--crons` enables its scheduler; the default is `--no-crons`.
- `--no-embeddings` avoids GGUF download and vectors in this pod only; search uses
keyword fallback, useful for ingestion tests. The real home's model is untouched.
- `--ttl` bounds the dashboard token (default `2h`). Re-up a stopped pod to change
boot flags. `pod token` re-mints a token; `pod url` prints the base URL without it.
Pods need Linux `systemd --user` or macOS `launchd`; run `kirocrew pod install`
once per host. See [pod platform requirements](../../../pod/README.md).
Every verb above talks to that per-user service manager, so an agent session
behind an outer sandbox with its own user namespace gets `Permission denied` from
all of them; `systemctl --user is-system-running` says which case you are in. The
`pod_up` / `pod_down` / `pod_status` / `pod_ls` tools do the same work through the
gateway, which holds the host bus, and `pod_up` returns the `{base_url, token,
port}` handle directly. They need the Dev Fleet app enabled.
`pod ls`, `status`, `logs`, `provision`, `prune`, `exec` and `api` cover inspection,
provisioning, removal of gone worktrees, in-pod commands and HTTP probes.
Without a service manager, or for a foreground debugger, run `./dev-backend.sh`
from the worktree. It uses an isolated port/home and `PYTHONPATH=src`; Ctrl+C
stops it, and rerunning picks up code changes. Reclaim its process and dev home
yourself. Never use the live gateway instead.
A healthy pod proves only boot. For behavior proof, follow
`docs/guides/worktree-verification-recipes.md`: select the owning endpoint from
the feature map, assert seeded state, run the pod-e2e Playwright harness and
preserve screenshots. Treat commands marked forthcoming as absent until help
lists them, and a session-control HTTP 403 as a gap, not successful proof.
### Agent/MCP specs are a separate isolation axis
`KIROCREW_HOME` isolates config, DB and sessions, NOT machine-wide
`~/.kiro/agents/*.json`. An ephemeral gateway refuses to rewrite that shared
agent home so its MCP paths cannot outlive its venv. The warning is protection,
not a failure: preview uses the real install's specs and MCP servers. A preview
therefore does NOT exercise changes to `mcp-core`, `mcp-cron` or `mcp-computer`.
Use unit tests; any temporary change to the real spec requires explicit user
authorization and restoration afterwards.
Do not bypass this with `KIRO_HOME`: it also moves sessions, settings, skills
and steering, while remaining host-path readers can break resume. It is not yet
a complete preview-isolation switch.
## Review repair and publication authorization
For Kiro Crew PR CI AI comments, MUST load
[kirocrew-prepare-pr: Review repair routing](../kirocrew-prepare-pr/SKILL.md#review-repair-routing)
BEFORE any repair. Follow that canonical model-pinned delegation procedure;
parent self-fixing is not a substitute. This pointer does not change the profile's
read-only local-review gate.
Committing, pushing and opening a PR each require explicit user authorization.
Permission to commit is not permission to push, and green gates grant neither.
A fix-and-push monitoring scope must be explicit; absent it, confirm each push.
Never push to a protected base branch. For authorized publication, follow
kirocrew-prepare-pr's SHA-pinned force-with-lease protocol and `single_commit` handling,
and AGENTS.md's at-most-two-commit limit; never use an implicit lease or interactive
git. No direct merge: hand back review-ready work, or let kirocrew-prepare-pr's
Phase 4 arm auto-merge as its Mode table decides. Any hold turns that off,
including "don't merge", "review only", or a conductor's or work brief's hold.
Auto-merge still waits for the required approval and every check.
## Cleanup and comments
Keep scratch, PR bodies, logs and QA media under `$KIROCREW_SCRATCH`, not the
worktree. Capture scripts' gitignored `temp-screenshots/` is also permitted;
evidence is uploaded as attachments, never committed — with write access, which
this agent has. (A fork contributor, whose `--attach` upload GitHub refuses, may
instead `git add -f` the media there; see kirocrew-prepare-pr's *Screenshots*.) A directory
that must survive your own processes so a later run can advance it is not scratch
and not `/tmp`: report that you need one instead of choosing a path. Before
ending:
```bash
git status --porcelain
git diff -- <regenerated-file>
```
Inspect every change. Restore/remove only residue YOU produced, not user changes
or another agent's work. Discarding uncommitted content is unrecoverable: ask if
ownership is unclear. Leave requested uncommitted implementation intact and report
it; cleanup is not permission to commit or discard it. A merged worktree must be
clean, including untracked files, before Dev Fleet's `Prune merged` can reap it.
After merge and cleanup: `git worktree remove ../kirocrew-wt-<name>`.
Add a genuinely needed ignored scratch pattern to `.gitignore` only within scope.
Comments and docstrings state current behavior and the non-obvious why: invariants,
edge cases, units and security constraints. No task log, PR/CR numbers, review-round
markers, incident dates, milestone tags, SHAs or historical narration. Do not
paraphrase adjacent code. Leave `_vendor/` and semantic pragmas (`type: ignore`,
`noqa`, `pragma`, TypeScript/eslint directives) untouched.
在 GitHub 查看