pilot-workers 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pilot_workers/__init__.py +1 -0
- pilot_workers/__main__.py +3 -0
- pilot_workers/cli/__init__.py +0 -0
- pilot_workers/cli/dispatch.py +577 -0
- pilot_workers/cli/install.py +259 -0
- pilot_workers/cli/main.py +115 -0
- pilot_workers/cli/run.py +191 -0
- pilot_workers/credentials.py +102 -0
- pilot_workers/data/permissions/README.md +47 -0
- pilot_workers/data/permissions/relaxed.yaml +10 -0
- pilot_workers/data/permissions/strict.yaml +9 -0
- pilot_workers/data/providers/README.md +24 -0
- pilot_workers/data/providers/ds.yaml +11 -0
- pilot_workers/data/providers/glm.yaml +11 -0
- pilot_workers/data/providers/kimi-k3.yaml +11 -0
- pilot_workers/data/templates/code.md +28 -0
- pilot_workers/data/templates/explore.md +17 -0
- pilot_workers/data/templates/review.md +18 -0
- pilot_workers/data/templates/test.md +17 -0
- pilot_workers/fmt_events.py +218 -0
- pilot_workers/integrations/README.md +25 -0
- pilot_workers/integrations/claude-host/agents/ds-coder.md +66 -0
- pilot_workers/integrations/claude-host/agents/ds-explorer.md +56 -0
- pilot_workers/integrations/claude-host/agents/ds-reviewer.md +50 -0
- pilot_workers/integrations/claude-host/agents/ds-tester.md +46 -0
- pilot_workers/integrations/claude-host/agents/glm-coder.md +66 -0
- pilot_workers/integrations/claude-host/agents/glm-explorer.md +56 -0
- pilot_workers/integrations/claude-host/agents/glm-reviewer.md +50 -0
- pilot_workers/integrations/claude-host/agents/glm-tester.md +46 -0
- pilot_workers/integrations/claude-host/agents/kimi-coder.md +66 -0
- pilot_workers/integrations/claude-host/agents/kimi-explorer.md +56 -0
- pilot_workers/integrations/claude-host/agents/kimi-reviewer.md +50 -0
- pilot_workers/integrations/claude-host/agents/kimi-tester.md +50 -0
- pilot_workers/integrations/claude-host/commands/glm/code.md +48 -0
- pilot_workers/integrations/claude-host/commands/glm/explore.md +38 -0
- pilot_workers/integrations/claude-host/commands/glm/review.md +38 -0
- pilot_workers/integrations/claude-host/commands/glm/test.md +30 -0
- pilot_workers/integrations/claude-host/commands/kimi/code.md +47 -0
- pilot_workers/integrations/claude-host/commands/kimi/explore.md +38 -0
- pilot_workers/integrations/claude-host/commands/kimi/review.md +38 -0
- pilot_workers/integrations/claude-host/commands/kimi/test.md +32 -0
- pilot_workers/integrations/codex-host/ds/SKILL.md +15 -0
- pilot_workers/integrations/codex-host/ds/openai.yaml +4 -0
- pilot_workers/integrations/codex-host/glm/SKILL.md +15 -0
- pilot_workers/integrations/codex-host/glm/openai.yaml +4 -0
- pilot_workers/integrations/codex-host/kimi/SKILL.md +15 -0
- pilot_workers/integrations/codex-host/kimi/openai.yaml +4 -0
- pilot_workers/maintain.py +170 -0
- pilot_workers/policy.py +295 -0
- pilot_workers/prompts/code.md +6 -0
- pilot_workers/prompts/common.md +24 -0
- pilot_workers/prompts/explore.md +7 -0
- pilot_workers/prompts/review.md +5 -0
- pilot_workers/prompts/test.md +6 -0
- pilot_workers/providers.py +137 -0
- pilot_workers/runners/__init__.py +28 -0
- pilot_workers/runners/base.py +123 -0
- pilot_workers/runners/opencode_runner.py +377 -0
- pilot_workers/runtime.py +314 -0
- pilot_workers/scripts/install_runtime.sh +51 -0
- pilot_workers-0.2.0.dist-info/METADATA +84 -0
- pilot_workers-0.2.0.dist-info/RECORD +66 -0
- pilot_workers-0.2.0.dist-info/WHEEL +5 -0
- pilot_workers-0.2.0.dist-info/entry_points.txt +2 -0
- pilot_workers-0.2.0.dist-info/licenses/LICENSE +21 -0
- pilot_workers-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Dispatch GLM to review code (read-only, no fixes); fan out across multiple axes in parallel
|
|
3
|
+
argument-hint: [what to review]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The user wants GLM to review code:
|
|
7
|
+
|
|
8
|
+
$ARGUMENTS
|
|
9
|
+
|
|
10
|
+
Do the following:
|
|
11
|
+
|
|
12
|
+
1. **First fix the review axes -- this is judgment work and it is yours.** Split out 2-4 orthogonal axes from the target under review, for example: correctness and boundary conditions, security (injection/privilege escalation/secret leakage), performance (hot paths/N+1/leaks), consistency (deviations from existing codebase conventions). Write each axis as its own self-contained task file: scope, what specifically to look at under this axis. GLM is a separate OpenCode process and cannot see this conversation. Append the output discipline:
|
|
13
|
+
|
|
14
|
+
> Output discipline:
|
|
15
|
+
> 1. Format for each finding: `[high|medium|low] file:line one-sentence problem -- one-sentence why-it-matters`
|
|
16
|
+
> 2. Findings without a `file:line` are invalid; mark uncertain ones "doubtful" rather than skipping them
|
|
17
|
+
> 3. Do not paste large code blocks -- when a quote is needed, cap it at 3 lines
|
|
18
|
+
> 4. No fix proposals, no summary or reflections; no more than 15 findings total -- if you go over, list the severe ones and note how many remain
|
|
19
|
+
|
|
20
|
+
The structure is provided by the `pilot-workers template review` template; just fill in the blanks. When there are many axes, you can mix in kimi (`--provider kimi-k3`) to spread the load across both quotas.
|
|
21
|
+
|
|
22
|
+
2. **Dispatch (the protocol is fixed in the pilot-workers CLI; do not invent your own flow). Each axis is one independent task with one independent background Bash:**
|
|
23
|
+
|
|
24
|
+
1. For each axis: `pilot-workers template review > /tmp/glm-review-<axis-name>-<timestamp>.md`, filling the task requirements into the template (unique naming prevents parallel sessions from clobbering each other). The worker is a separate process and cannot see this conversation, so the content must be self-contained.
|
|
25
|
+
2. Launch multiple background Bash calls (`run_in_background: true`) in the same round, one per axis:
|
|
26
|
+
```bash
|
|
27
|
+
pilot-workers dispatch --provider glm --mode review --workdir "$PWD" --task-file /tmp/glm-review-<axis-name>-<timestamp>.md
|
|
28
|
+
```
|
|
29
|
+
3. Each stream's stdout is exactly two lines of JSON: the first line is `worker_runner.started` (record the run_id and log path); the last line is `worker_runner.verdict`. **The completion signal = that background Bash exiting on its own**; do not poll by process name, do not read the shared log to make any judgment (latest.log is for humans only). Each axis collects its verdict independently, without interference.
|
|
30
|
+
4. Verdict handling: `completed` -> `final_text` is the full worker report; `step_capped_partial` -> partial coverage, report the uncovered scope truthfully; `empty`/`error` -> read `jsonl_path` first to do a post-mortem, then report the cause of death truthfully; never draw a conclusion without reading the evidence.
|
|
31
|
+
|
|
32
|
+
Do not edit a worker's target files while it is running.
|
|
33
|
+
|
|
34
|
+
3. **Aggregation is your job.** Merge and dedupe findings across axes, sort by severity, and **report to the user directly**. Do not spot-check -- findings carry `file:line`, so the user can verify themselves. You decide the fix plan: do small fixes yourself, and route large batches of mechanical fixes through `/glm:code`.
|
|
35
|
+
|
|
36
|
+
4. **Report honestly**: how many findings per axis, which ones are real (with `file:line`), and how you plan to fix them.
|
|
37
|
+
|
|
38
|
+
If the scope of review is unclear (no range at all), ask the user first; do not fire indiscriminately across the whole repo.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Dispatch GLM to run tests and gather failure information (read-only, no fixes)
|
|
3
|
+
argument-hint: [what tests to run]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The user wants GLM to run tests:
|
|
7
|
+
|
|
8
|
+
$ARGUMENTS
|
|
9
|
+
|
|
10
|
+
Do the following:
|
|
11
|
+
|
|
12
|
+
1. **Make clear what to run.** Write the test command, directory, and preconditions as a self-contained task file (GLM is a separate OpenCode process and cannot see this conversation). If nothing is specified, take a quick look at how the project runs its tests, fix the command, then dispatch. General discipline (run, do not fix; reporting format) **does not need to be written** -- dispatch injects `prompts/test.md` automatically; the task only states which command to run and any known pre-existing failures. The structure is provided by the `pilot-workers template test` template; just fill in the blanks.
|
|
13
|
+
|
|
14
|
+
2. **Dispatch (the protocol is fixed in the pilot-workers CLI; do not invent your own flow):**
|
|
15
|
+
|
|
16
|
+
1. `pilot-workers template test > /tmp/glm-test-<task-slug>-<timestamp>.md`, filling the task requirements into the template (unique naming prevents parallel sessions from clobbering each other). The worker is a separate process and cannot see this conversation, so the content must be self-contained.
|
|
17
|
+
2. Run in the background with Bash (`run_in_background: true`):
|
|
18
|
+
```bash
|
|
19
|
+
pilot-workers dispatch --provider glm --mode test --workdir "$PWD" --task-file /tmp/glm-test-<task-slug>-<timestamp>.md
|
|
20
|
+
```
|
|
21
|
+
3. stdout is exactly two lines of JSON: the first line is `worker_runner.started` (record the run_id and log path); the last line is `worker_runner.verdict`. **The completion signal = this background Bash exiting on its own**; do not poll by process name, do not read the shared log to make any judgment (latest.log is for humans only).
|
|
22
|
+
4. Verdict handling: `completed` -> `final_text` is the full worker report; sanity-check it: has counts and raw error text -> trust it; just "all passed" with no counts -> suspicious, read `jsonl_path` to see what command it actually ran, and redispatch if needed; run `git status` to confirm it left no junk changes; `step_capped_partial` -> partial coverage, report the uncovered scope truthfully; `empty`/`error` -> read `jsonl_path` first to do a post-mortem, then report the cause of death truthfully; never draw a conclusion without reading the evidence.
|
|
23
|
+
|
|
24
|
+
Do not edit a worker's target files while it is running.
|
|
25
|
+
|
|
26
|
+
3. **Once you have the failure list, diagnosis and fixes are your job.** Use `file:line` to locate the cause and decide the fix; route large batches of mechanical fixes through `/glm:code`, and do small fixes yourself.
|
|
27
|
+
|
|
28
|
+
4. **Report honestly**: how many passed/failed, your read on the cause of failure, and how you plan to fix it.
|
|
29
|
+
|
|
30
|
+
If what to run is unclear, ask the user first; do not guess the command.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Dispatch a coding task Claude has already planned to Kimi for execution (modifies files directly; dispatch in the background, then harvest by verdict when done)
|
|
3
|
+
argument-hint: [task description]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The user wants to dispatch this coding task to Kimi for execution:
|
|
7
|
+
|
|
8
|
+
$ARGUMENTS
|
|
9
|
+
|
|
10
|
+
Do the following:
|
|
11
|
+
|
|
12
|
+
1. **Planning is your job, not Kimi's.** If the approach is not decided, think it through first; if you need to scope the code first, run `/kimi:explore` -- do not read through it yourself.
|
|
13
|
+
|
|
14
|
+
2. **Before dispatching, self-check whether it is worth it: is the expected change volume far larger than the task description?**
|
|
15
|
+
- Worth it: large batches of mechanical changes (renaming dozens of files, scaffolding boilerplate, backfilling tests in bulk), parallel fan-out, your quota near the cap
|
|
16
|
+
- Not worth it: small tweaks, tasks that need mid-course judgment, self-contained specs about as long as the diff
|
|
17
|
+
- **One worker call should bundle at most 2-3 related fix points; split larger batches into multiple workers (which can run in parallel).**
|
|
18
|
+
|
|
19
|
+
If it is not worth it, just tell the user "this is better done by me" and do it yourself. Do not force a dispatch.
|
|
20
|
+
|
|
21
|
+
3. **Write the task as a self-contained spec.** Kimi is a separate OpenCode process and cannot see this conversation, so the spec must be self-contained: explicit file paths, completion criteria, and the do-not-touch boundaries. **Pick sub-second verification commands** (grep/diff/typecheck); leave the heavyweight `pnpm test` for the main session to run. General discipline **does not need to be written** -- dispatch injects `prompts/*.md` automatically. Copy any out-of-project material into the project root first, then reference it. The structure is provided by the `pilot-workers template code` template; just fill in the blanks.
|
|
22
|
+
|
|
23
|
+
4. **Dispatch (the protocol is fixed in the pilot-workers CLI; do not invent your own flow):**
|
|
24
|
+
|
|
25
|
+
1. `pilot-workers template code > /tmp/kimi-k3-code-<task-slug>-<timestamp>.md`, filling the task requirements into the template (unique naming prevents parallel sessions from clobbering each other). The worker is a separate process and cannot see this conversation, so the content must be self-contained.
|
|
26
|
+
2. Run in the background with Bash (`run_in_background: true`):
|
|
27
|
+
```bash
|
|
28
|
+
pilot-workers dispatch --provider kimi-k3 --mode code --workdir "$PWD" --task-file /tmp/kimi-k3-code-<task-slug>-<timestamp>.md
|
|
29
|
+
```
|
|
30
|
+
3. stdout is exactly two lines of JSON: the first line is `worker_runner.started` (record the run_id and log path); the last line is `worker_runner.verdict`. **The completion signal = this background Bash exiting on its own**; do not poll by process name, do not read the shared log to make any judgment (latest.log is for humans only).
|
|
31
|
+
4. Verdict handling: `completed` -> `final_text` is the full worker report; `step_capped_partial` -> partial coverage, report the uncovered scope truthfully; `empty`/`error` -> read `jsonl_path` first to do a post-mortem, then report the cause of death truthfully; never draw a conclusion without reading the evidence.
|
|
32
|
+
5. If the worker fails or does not converge, prefer resume (it reuses the full prior-session context and saves minute-scale round-trips versus a cold restart):
|
|
33
|
+
```bash
|
|
34
|
+
pilot-workers dispatch --provider kimi-k3 --mode resume --session <session_id from the verdict> --workdir <workdir from started> --task "Previous task incomplete: <what is missing, how to fix>"
|
|
35
|
+
```
|
|
36
|
+
If it hits the same obstacle twice and still does not pass -> the main session takes over and wraps up.
|
|
37
|
+
|
|
38
|
+
For parallel workers, add `--worktree` so each gets an isolated git worktree that will not stomp the others; clean up with `pilot-workers maintain worktrees remove <path>` when done. When you want parallel fan-out without consuming main-session turns, route through the corresponding coder subagent instead (one instance manages one worker). Do not edit a worker's target files while it is running.
|
|
39
|
+
|
|
40
|
+
5. **Verification is the single verification pass -- do not skip it** (only when verdict == `completed` or `step_capped_partial`):
|
|
41
|
+
- Run `git diff --stat` against the spec whitelist to catch out-of-bounds changes (exclude dirty changes that pre-existed before the session started)
|
|
42
|
+
- Spot-check the actual diff with `git diff` to confirm it matches the plan
|
|
43
|
+
- Run tests/lint
|
|
44
|
+
|
|
45
|
+
6. **Report honestly**: what changed, what verification found, and what the user should look at themselves.
|
|
46
|
+
|
|
47
|
+
If the task description is too vague to dispatch, ask the user first; do not force a dispatch.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Dispatch Kimi to explore the codebase (read-only); conclusions must carry file:line
|
|
3
|
+
argument-hint: [what to investigate]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The user wants to dispatch this exploration task to Kimi (reading code is the bulk of token spend, so this kind of work is a top candidate for dispatch):
|
|
7
|
+
|
|
8
|
+
$ARGUMENTS
|
|
9
|
+
|
|
10
|
+
Do the following:
|
|
11
|
+
|
|
12
|
+
1. **Write the user's question straight into a task file; do not read the code yourself first.** The whole point of dispatching explore is to save your tokens -- running grep/read yourself first wastes that saving. You only do two things:
|
|
13
|
+
- Fill in the working directory and scope (if the user did not specify, use `$PWD` and scope to `src/` or the whole project)
|
|
14
|
+
- Append the output discipline below verbatim to the end of the task
|
|
15
|
+
|
|
16
|
+
> Output discipline:
|
|
17
|
+
> 1. Every conclusion must carry a `file:line` reference; conclusions without a reference are invalid
|
|
18
|
+
> 2. Output structured items, one fact per item; be terse; do not write preambles, summaries, or reflections
|
|
19
|
+
> 3. Do not paste large code blocks -- when a quote is needed, cap it at 3 lines; for more, give `file:line` and let the reader look
|
|
20
|
+
> 4. No more than 20 conclusions total (or follow the budget set by the task); going over means the question was too broad -- list the most important ones and note "X more not listed, in these directories"
|
|
21
|
+
|
|
22
|
+
The structure is provided by the `pilot-workers template explore` template; just fill in the blanks.
|
|
23
|
+
|
|
24
|
+
2. **Dispatch (the protocol is fixed in the pilot-workers CLI; do not invent your own flow):**
|
|
25
|
+
|
|
26
|
+
1. `pilot-workers template explore > /tmp/kimi-k3-explore-<task-slug>-<timestamp>.md`, filling the task requirements into the template (unique naming prevents parallel sessions from clobbering each other). The worker is a separate process and cannot see this conversation, so the content must be self-contained.
|
|
27
|
+
2. Run in the background with Bash (`run_in_background: true`):
|
|
28
|
+
```bash
|
|
29
|
+
pilot-workers dispatch --provider kimi-k3 --mode explore --workdir "$PWD" --task-file /tmp/kimi-k3-explore-<task-slug>-<timestamp>.md
|
|
30
|
+
```
|
|
31
|
+
3. stdout is exactly two lines of JSON: the first line is `worker_runner.started` (record the run_id and log path); the last line is `worker_runner.verdict`. **The completion signal = this background Bash exiting on its own**; do not poll by process name, do not read the shared log to make any judgment (latest.log is for humans only).
|
|
32
|
+
4. Verdict handling: `completed` -> `final_text` is the full worker report -- **bring it straight back to the user**, no spot-checking, no parroting, no rewriting; hand the conclusions on as-is with their `file:line`; `step_capped_partial` -> partial coverage, report the uncovered scope truthfully; `empty`/`error` -> read `jsonl_path` first to do a post-mortem, then report the cause of death truthfully; never draw a conclusion without reading the evidence.
|
|
33
|
+
|
|
34
|
+
Do not edit a worker's target files while it is running.
|
|
35
|
+
|
|
36
|
+
3. If the next step is to change code: planning is your job; the mechanical-execution part of the plan goes through `/kimi:code`.
|
|
37
|
+
|
|
38
|
+
If the question is too vague (even the user does not know what to investigate), ask one clarifying question first; do not force a dispatch. But the bar for "vague" is that the user themselves does not know what to look into -- not that you think the question is not structured enough. "Figure out how auth works" is enough; do not require them to list specific files first.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Dispatch Kimi to review code (read-only, no fixes); fan out across multiple axes in parallel
|
|
3
|
+
argument-hint: [what to review]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The user wants Kimi to review code:
|
|
7
|
+
|
|
8
|
+
$ARGUMENTS
|
|
9
|
+
|
|
10
|
+
Do the following:
|
|
11
|
+
|
|
12
|
+
1. **First fix the review axes -- this is judgment work and it is yours.** Split out 2-4 orthogonal axes from the target under review, for example: correctness and boundary conditions, security (injection/privilege escalation/secret leakage), performance (hot paths/N+1/leaks), consistency (deviations from existing codebase conventions). Write each axis as its own self-contained task file: scope, what specifically to look at under this axis. Kimi is a separate OpenCode process and cannot see this conversation. Append the output discipline:
|
|
13
|
+
|
|
14
|
+
> Output discipline:
|
|
15
|
+
> 1. Format for each finding: `[high|medium|low] file:line one-sentence problem -- one-sentence why-it-matters`
|
|
16
|
+
> 2. Findings without a `file:line` are invalid; mark uncertain ones "doubtful" rather than skipping them
|
|
17
|
+
> 3. Do not paste large code blocks -- when a quote is needed, cap it at 3 lines
|
|
18
|
+
> 4. No fix proposals, no summary or reflections; no more than 15 findings total -- if you go over, list the severe ones and note how many remain
|
|
19
|
+
|
|
20
|
+
The structure is provided by the `pilot-workers template review` template; just fill in the blanks. When there are many axes, you can mix in glm (`--provider glm`) to spread the load across both quotas.
|
|
21
|
+
|
|
22
|
+
2. **Dispatch (the protocol is fixed in the pilot-workers CLI; do not invent your own flow). Each axis is one independent task with one independent background Bash:**
|
|
23
|
+
|
|
24
|
+
1. For each axis: `pilot-workers template review > /tmp/kimi-k3-review-<axis-name>-<timestamp>.md`, filling the task requirements into the template (unique naming prevents parallel sessions from clobbering each other). The worker is a separate process and cannot see this conversation, so the content must be self-contained.
|
|
25
|
+
2. Launch multiple background Bash calls (`run_in_background: true`) in the same round, one per axis:
|
|
26
|
+
```bash
|
|
27
|
+
pilot-workers dispatch --provider kimi-k3 --mode review --workdir "$PWD" --task-file /tmp/kimi-k3-review-<axis-name>-<timestamp>.md
|
|
28
|
+
```
|
|
29
|
+
3. Each stream's stdout is exactly two lines of JSON: the first line is `worker_runner.started` (record the run_id and log path); the last line is `worker_runner.verdict`. **The completion signal = that background Bash exiting on its own**; do not poll by process name, do not read the shared log to make any judgment (latest.log is for humans only). Each axis collects its verdict independently, without interference.
|
|
30
|
+
4. Verdict handling: `completed` -> `final_text` is the full worker report; `step_capped_partial` -> partial coverage, report the uncovered scope truthfully; `empty`/`error` -> read `jsonl_path` first to do a post-mortem, then report the cause of death truthfully; never draw a conclusion without reading the evidence.
|
|
31
|
+
|
|
32
|
+
Do not edit a worker's target files while it is running.
|
|
33
|
+
|
|
34
|
+
3. **Aggregation is your job.** Merge and dedupe findings across axes, sort by severity, and **report to the user directly**. Do not spot-check -- findings carry `file:line`, so the user can verify themselves. You decide the fix plan: do small fixes yourself, and route large batches of mechanical fixes through `/kimi:code`.
|
|
35
|
+
|
|
36
|
+
4. **Report honestly**: how many findings per axis, which ones are real (with `file:line`), and how you plan to fix them.
|
|
37
|
+
|
|
38
|
+
If the scope of review is unclear (no range at all), ask the user first; do not fire indiscriminately across the whole repo.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Dispatch Kimi to run tests and gather failure information (read-only, no fixes; dispatch in the background, then harvest by verdict when done)
|
|
3
|
+
argument-hint: [what tests to run]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
The user wants Kimi to run tests:
|
|
7
|
+
|
|
8
|
+
$ARGUMENTS
|
|
9
|
+
|
|
10
|
+
Do the following:
|
|
11
|
+
|
|
12
|
+
1. **First self-check whether it is worth it -- push back on fast suites.** Estimate locally first: if the full suite takes < 1 minute, or the failure output is expected to be short (a few dozen lines) -> just tell the user "I can run this faster myself" and run it yourself. Kimi's value cases are: huge output (hundreds/thousands of lines of failures to sift), repeated reruns to gather data, or your context is near full.
|
|
13
|
+
|
|
14
|
+
2. **Make clear what to run.** Write the test command, directory, and preconditions as a self-contained task file (Kimi is a separate OpenCode process and cannot see this conversation). If nothing is specified, take a quick look at how the project runs its tests, fix the command, then dispatch. General discipline (run, do not fix; reporting format) **does not need to be written** -- dispatch injects `prompts/test.md` automatically; the task only states which command to run and any known pre-existing failures. The structure is provided by the `pilot-workers template test` template; just fill in the blanks.
|
|
15
|
+
|
|
16
|
+
3. **Dispatch (the protocol is fixed in the pilot-workers CLI; do not invent your own flow):**
|
|
17
|
+
|
|
18
|
+
1. `pilot-workers template test > /tmp/kimi-k3-test-<task-slug>-<timestamp>.md`, filling the task requirements into the template (unique naming prevents parallel sessions from clobbering each other). The worker is a separate process and cannot see this conversation, so the content must be self-contained.
|
|
19
|
+
2. Run in the background with Bash (`run_in_background: true`):
|
|
20
|
+
```bash
|
|
21
|
+
pilot-workers dispatch --provider kimi-k3 --mode test --workdir "$PWD" --task-file /tmp/kimi-k3-test-<task-slug>-<timestamp>.md
|
|
22
|
+
```
|
|
23
|
+
3. stdout is exactly two lines of JSON: the first line is `worker_runner.started` (record the run_id and log path); the last line is `worker_runner.verdict`. **The completion signal = this background Bash exiting on its own**; do not poll by process name, do not read the shared log to make any judgment (latest.log is for humans only).
|
|
24
|
+
4. Verdict handling: `completed` -> `final_text` is the full worker report; sanity-check it: has counts and raw error text -> trust it; just "all passed" with no counts -> suspicious, read `jsonl_path` to see what command it actually ran; run `git status` to confirm it left no junk changes; `step_capped_partial` -> partial coverage, report the uncovered scope truthfully; `empty`/`error` -> read `jsonl_path` first to do a post-mortem, then report the cause of death truthfully; never draw a conclusion without reading the evidence.
|
|
25
|
+
|
|
26
|
+
Do not edit a worker's target files while it is running.
|
|
27
|
+
|
|
28
|
+
4. **Once you have the failure list, diagnosis and fixes are your job.** Use `file:line` to locate the cause and decide the fix; route large batches of mechanical fixes through `/kimi:code`, and do small fixes yourself.
|
|
29
|
+
|
|
30
|
+
5. **Report honestly**: how many passed/failed, your read on the cause of failure, and how you plan to fix it.
|
|
31
|
+
|
|
32
|
+
If what to run is unclear, ask the user first; do not guess the command.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ds
|
|
3
|
+
description: Plan with Codex, then run a bounded task through the fixed DeepSeek OpenCode worker and have Codex verify the result. Invoke explicitly as `$ds [code|explore|test|review|resume] [task]`; examples include `$ds code`, `$ds code fix the login bug`, `$ds review current changes`, and `$ds resume ses_xxx continue the fix`. Use whenever the user asks to delegate coding, investigation, testing, review, or session continuation to DeepSeek.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DeepSeek Worker
|
|
7
|
+
|
|
8
|
+
Parse the first word after `$ds` as the mode (`code`/`explore`/`test`/`review`/`resume`); otherwise default to `code` and treat all text as the task. Keep planning, task decomposition, and final verification with Codex; give the worker only settled decisions.
|
|
9
|
+
|
|
10
|
+
1. `pilot-workers template <mode> > /tmp/ds-<mode>-<slug>-<timestamp>.md`, then fill in the template with the task (unique filename — parallel sessions must not collide). The worker is an independent process and cannot see this conversation; the file must be self-contained. No template for `resume` — pass `--task "<what remains, how to fix>"` instead.
|
|
11
|
+
2. Run in a background shell: `pilot-workers dispatch --provider ds --mode <mode> --workdir <absolute-project-path> --task-file <file>`. For `resume` add `--session <session_id>` and use the workdir from the prior `started` event.
|
|
12
|
+
3. stdout is exactly two JSON lines: first `worker_runner.started` (note run_id and log paths), last `worker_runner.verdict`. Completion signal = the background shell exiting. Never poll by process name; never judge from shared logs. Live log for humans: `$PILOT_WORKERS_HOME (default $CODEX_HOME) /opencode-workers/logs/ds/latest.log`.
|
|
13
|
+
4a. If the background shell exits but stdout has fewer than two lines, check its stderr — early failures (missing credentials, runner not installed) produce no JSON.
|
|
14
|
+
4. Act on `verdict`: `completed` → `final_text` is the worker's report; `step_capped_partial` → partial coverage, report honestly; `empty`/`error` → read `jsonl_path` for the post-mortem before concluding anything. Prefer `resume` over cold re-dispatch when a run fails or falls short; after the same obstacle twice, take over yourself.
|
|
15
|
+
5. After `code`/`resume`: inspect the actual diff against the task scope and run the smallest real verification yourself. Never treat the worker's completion claim as proof. Missing credentials → `pilot-workers credentials ds`.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: glm
|
|
3
|
+
description: Plan with Codex, then run a bounded task through the fixed GLM OpenCode worker and have Codex verify the result. Invoke explicitly as `$glm [code|explore|test|review|resume] [task]`; examples include `$glm code`, `$glm code fix the login bug`, `$glm review current changes`, and `$glm resume ses_xxx continue the fix`. Use whenever the user asks to delegate coding, investigation, testing, review, or session continuation to GLM.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GLM Worker
|
|
7
|
+
|
|
8
|
+
Parse the first word after `$glm` as the mode (`code`/`explore`/`test`/`review`/`resume`); otherwise default to `code` and treat all text as the task. Keep planning, task decomposition, and final verification with Codex; give the worker only settled decisions.
|
|
9
|
+
|
|
10
|
+
1. `pilot-workers template <mode> > /tmp/glm-<mode>-<slug>-<timestamp>.md`, then fill in the template with the task (unique filename — parallel sessions must not collide). The worker is an independent process and cannot see this conversation; the file must be self-contained. No template for `resume` — pass `--task "<what remains, how to fix>"` instead.
|
|
11
|
+
2. Run in a background shell: `pilot-workers dispatch --provider glm --mode <mode> --workdir <absolute-project-path> --task-file <file>`. For `resume` add `--session <session_id>` and use the workdir from the prior `started` event.
|
|
12
|
+
3. stdout is exactly two JSON lines: first `worker_runner.started` (note run_id and log paths), last `worker_runner.verdict`. Completion signal = the background shell exiting. Never poll by process name; never judge from shared logs. Live log for humans: `$PILOT_WORKERS_HOME (default $CODEX_HOME) /opencode-workers/logs/glm/latest.log`.
|
|
13
|
+
4a. If the background shell exits but stdout has fewer than two lines, check its stderr — early failures (missing credentials, runner not installed) produce no JSON.
|
|
14
|
+
4. Act on `verdict`: `completed` → `final_text` is the worker's report; `step_capped_partial` → partial coverage, report honestly; `empty`/`error` → read `jsonl_path` for the post-mortem before concluding anything. Prefer `resume` over cold re-dispatch when a run fails or falls short; after the same obstacle twice, take over yourself.
|
|
15
|
+
5. After `code`/`resume`: inspect the actual diff against the task scope and run the smallest real verification yourself. Never treat the worker's completion claim as proof. Missing credentials → `pilot-workers credentials glm`.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kimi
|
|
3
|
+
description: Plan with Codex, then run a bounded task through the fixed Kimi K3 OpenCode worker and have Codex verify the result. Invoke explicitly as `$kimi [code|explore|test|review|resume] [task]`; examples include `$kimi code`, `$kimi code fix the login bug`, `$kimi review current changes`, and `$kimi resume ses_xxx continue the fix`. Use whenever the user asks to delegate coding, investigation, testing, review, or session continuation to Kimi K3.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Kimi K3 Worker
|
|
7
|
+
|
|
8
|
+
Parse the first word after `$kimi` as the mode (`code`/`explore`/`test`/`review`/`resume`); otherwise default to `code` and treat all text as the task. Keep planning, task decomposition, and final verification with Codex; give the worker only settled decisions.
|
|
9
|
+
|
|
10
|
+
1. `pilot-workers template <mode> > /tmp/kimi-<mode>-<slug>-<timestamp>.md`, then fill in the template with the task (unique filename — parallel sessions must not collide). The worker is an independent process and cannot see this conversation; the file must be self-contained. No template for `resume` — pass `--task "<what remains, how to fix>"` instead.
|
|
11
|
+
2. Run in a background shell: `pilot-workers dispatch --provider kimi-k3 --mode <mode> --workdir <absolute-project-path> --task-file <file>`. For `resume` add `--session <session_id>` and use the workdir from the prior `started` event.
|
|
12
|
+
3. stdout is exactly two JSON lines: first `worker_runner.started` (note run_id and log paths), last `worker_runner.verdict`. Completion signal = the background shell exiting. Never poll by process name; never judge from shared logs. Live log for humans: `$PILOT_WORKERS_HOME (default $CODEX_HOME) /opencode-workers/logs/kimi-k3/latest.log`.
|
|
13
|
+
4a. If the background shell exits but stdout has fewer than two lines, check its stderr — early failures (missing credentials, runner not installed) produce no JSON.
|
|
14
|
+
4. Act on `verdict`: `completed` → `final_text` is the worker's report; `step_capped_partial` → partial coverage, report honestly; `empty`/`error` → read `jsonl_path` for the post-mortem before concluding anything. Prefer `resume` over cold re-dispatch when a run fails or falls short; after the same obstacle twice, take over yourself.
|
|
15
|
+
5. After `code`/`resume`: inspect the actual diff against the task scope and run the smallest real verification yourself. Never treat the worker's completion claim as proof. Missing credentials → `pilot-workers credentials kimi-k3`.
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Explicit, auditable lifecycle tools for worker logs and detached worktrees.
|
|
3
|
+
|
|
4
|
+
Never silent: every deletion is printed. Never destructive by surprise:
|
|
5
|
+
- log cleanup keeps each provider's newest run pair regardless of age;
|
|
6
|
+
- worktree removal refuses when the worktree is dirty or holds commits that
|
|
7
|
+
are not reachable from any ref of the main repository (unintegrated work).
|
|
8
|
+
There is no force flag on purpose; unintegrated changes are integrated or
|
|
9
|
+
discarded by a human with plain git, not by this script.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
import json
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
import subprocess
|
|
18
|
+
import time
|
|
19
|
+
|
|
20
|
+
from pilot_workers import providers
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _run_pairs(logs_dir: Path) -> list[list[Path]]:
|
|
24
|
+
"""Group per-run files (jsonl + stderr + rendered archive) by run id, newest first."""
|
|
25
|
+
groups: dict[str, list[Path]] = {}
|
|
26
|
+
for path in logs_dir.iterdir():
|
|
27
|
+
if not path.is_file():
|
|
28
|
+
continue
|
|
29
|
+
name = path.name
|
|
30
|
+
if name == "latest.log":
|
|
31
|
+
continue
|
|
32
|
+
run_id = None
|
|
33
|
+
if name.endswith(".stderr.log"):
|
|
34
|
+
run_id = name[: -len(".stderr.log")]
|
|
35
|
+
elif name.endswith(".jsonl"):
|
|
36
|
+
run_id = name[: -len(".jsonl")]
|
|
37
|
+
elif name.startswith("rendered-") and name.endswith(".log"):
|
|
38
|
+
run_id = name[len("rendered-") : -len(".log")]
|
|
39
|
+
if run_id is None:
|
|
40
|
+
continue
|
|
41
|
+
groups.setdefault(run_id, []).append(path)
|
|
42
|
+
ordered = sorted(
|
|
43
|
+
groups.values(),
|
|
44
|
+
key=lambda paths: max(item.stat().st_mtime for item in paths),
|
|
45
|
+
reverse=True,
|
|
46
|
+
)
|
|
47
|
+
return ordered
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def cleanup_logs(older_than_days: int, provider_keys: list[str]) -> int:
|
|
51
|
+
if older_than_days < 1:
|
|
52
|
+
raise RuntimeError("--older-than-days must be >= 1")
|
|
53
|
+
cutoff = time.time() - older_than_days * 86400
|
|
54
|
+
removed = 0
|
|
55
|
+
for key in provider_keys:
|
|
56
|
+
logs_dir = providers.logs_root(providers.PROVIDERS[key])
|
|
57
|
+
if not logs_dir.is_dir():
|
|
58
|
+
print(f"{key}: no log directory, skipping")
|
|
59
|
+
continue
|
|
60
|
+
pairs = _run_pairs(logs_dir)
|
|
61
|
+
for index, paths in enumerate(pairs):
|
|
62
|
+
newest_mtime = max(item.stat().st_mtime for item in paths)
|
|
63
|
+
if index == 0:
|
|
64
|
+
continue # always keep the newest run for diagnosis
|
|
65
|
+
if newest_mtime >= cutoff:
|
|
66
|
+
continue
|
|
67
|
+
for path in sorted(paths):
|
|
68
|
+
print(f"delete {path}")
|
|
69
|
+
path.unlink()
|
|
70
|
+
removed += 1
|
|
71
|
+
print(f"removed {removed} file(s)")
|
|
72
|
+
return 0
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _git(worktree: Path, *args: str) -> subprocess.CompletedProcess[str]:
|
|
76
|
+
return subprocess.run(
|
|
77
|
+
["git", "-C", str(worktree), *args], text=True, capture_output=True, check=False
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def worktree_status(path: Path) -> dict:
|
|
82
|
+
dirty = None
|
|
83
|
+
unintegrated = None
|
|
84
|
+
head = None
|
|
85
|
+
status = _git(path, "status", "--porcelain")
|
|
86
|
+
if status.returncode == 0:
|
|
87
|
+
dirty = bool(status.stdout.strip())
|
|
88
|
+
head_result = _git(path, "rev-parse", "HEAD")
|
|
89
|
+
if head_result.returncode == 0:
|
|
90
|
+
head = head_result.stdout.strip()
|
|
91
|
+
reachable = _git(path, "rev-list", "HEAD", "--not", "--all")
|
|
92
|
+
if reachable.returncode == 0:
|
|
93
|
+
unintegrated = bool(reachable.stdout.strip())
|
|
94
|
+
return {
|
|
95
|
+
"path": str(path),
|
|
96
|
+
"head": head,
|
|
97
|
+
"dirty": dirty,
|
|
98
|
+
"unintegrated_commits": unintegrated,
|
|
99
|
+
"age_days": round((time.time() - path.stat().st_mtime) / 86400, 1),
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def list_worktrees() -> int:
|
|
104
|
+
root = providers.worktrees_root()
|
|
105
|
+
if not root.is_dir():
|
|
106
|
+
print("[]")
|
|
107
|
+
return 0
|
|
108
|
+
entries = [worktree_status(path) for path in sorted(root.iterdir()) if path.is_dir()]
|
|
109
|
+
print(json.dumps(entries, indent=2))
|
|
110
|
+
return 0
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def remove_worktree(target: str) -> int:
|
|
114
|
+
root = providers.worktrees_root().resolve()
|
|
115
|
+
path = Path(target).expanduser().resolve()
|
|
116
|
+
if not path.is_dir():
|
|
117
|
+
raise RuntimeError(f"worktree does not exist: {path}")
|
|
118
|
+
if root not in path.parents and path != root:
|
|
119
|
+
raise RuntimeError(f"refusing to touch a path outside {root}: {path}")
|
|
120
|
+
info = worktree_status(path)
|
|
121
|
+
if info["dirty"] is not False:
|
|
122
|
+
raise RuntimeError(
|
|
123
|
+
f"refusing removal: worktree is dirty or unreadable ({path}); "
|
|
124
|
+
"integrate or discard changes with git first"
|
|
125
|
+
)
|
|
126
|
+
if info["unintegrated_commits"] is not False:
|
|
127
|
+
raise RuntimeError(
|
|
128
|
+
f"refusing removal: worktree holds commits unreachable from any ref ({path}); "
|
|
129
|
+
"integrate them first"
|
|
130
|
+
)
|
|
131
|
+
result = _git(path, "worktree", "remove", str(path))
|
|
132
|
+
if result.returncode != 0:
|
|
133
|
+
raise RuntimeError(f"git worktree remove failed: {result.stderr.strip()}")
|
|
134
|
+
print(f"removed {path}")
|
|
135
|
+
return 0
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def parse_args() -> argparse.Namespace:
|
|
139
|
+
parser = argparse.ArgumentParser(description="Worker log and worktree lifecycle tools.")
|
|
140
|
+
commands = parser.add_subparsers(dest="command", required=True)
|
|
141
|
+
|
|
142
|
+
logs = commands.add_parser("logs", help="Delete old per-run logs (never the newest run).")
|
|
143
|
+
logs.add_argument("--older-than-days", type=int, required=True)
|
|
144
|
+
logs.add_argument("--provider", choices=sorted(providers.PROVIDERS), default=None)
|
|
145
|
+
|
|
146
|
+
worktrees = commands.add_parser("worktrees", help="List or safely remove detached worktrees.")
|
|
147
|
+
actions = worktrees.add_subparsers(dest="action", required=True)
|
|
148
|
+
actions.add_parser("list", help="Show every worker worktree with dirty/integration state.")
|
|
149
|
+
remove = actions.add_parser("remove", help="Remove one clean, integrated worktree.")
|
|
150
|
+
remove.add_argument("path")
|
|
151
|
+
|
|
152
|
+
return parser.parse_args()
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def main() -> int:
|
|
156
|
+
args = parse_args()
|
|
157
|
+
try:
|
|
158
|
+
if args.command == "logs":
|
|
159
|
+
keys = [args.provider] if args.provider else sorted(providers.PROVIDERS)
|
|
160
|
+
return cleanup_logs(args.older_than_days, keys)
|
|
161
|
+
if args.action == "list":
|
|
162
|
+
return list_worktrees()
|
|
163
|
+
return remove_worktree(args.path)
|
|
164
|
+
except (OSError, RuntimeError) as exc:
|
|
165
|
+
print(f"error: {exc}")
|
|
166
|
+
return 1
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
if __name__ == "__main__":
|
|
170
|
+
raise SystemExit(main())
|