workledger-cli 0.6.1__tar.gz → 0.7.0__tar.gz
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.
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/ask-colleague/SKILL.md +31 -7
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/ask-colleague/prompts/explore.md +10 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/ask-colleague/prompts/review.md +8 -7
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/ask-colleague/prompts/write.md +6 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/ask-colleague/scripts/ask-colleague.sh +302 -36
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/CHANGELOG.md +25 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/PKG-INFO +2 -2
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/pyproject.toml +1 -1
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/uv.lock +31 -31
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/agent-config/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/agent-config/data/backend-fingerprints.yaml +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/agent-config/scripts/show.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/assign-to-workforce/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/challenge/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/cicd/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/cicd/scripts/_resolve-nick.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/cicd/scripts/portability-lint.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/cicd/scripts/pr-reply.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/cicd/scripts/pr-status.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/cicd/scripts/workflow.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/communicate/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/communicate/scripts/templates/skill-new-brief.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/communicate/scripts/templates/skill-update-brief.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/deviate/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/pypi-maintainer/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/pypi-maintainer/scripts/switch-source.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/recall/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/recall/scripts/recall.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/remember/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/remember/scripts/remember.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/run-tests/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/scope/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/sonarclaude/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/spec-to-plan/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/summarize-delivery/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/think/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/think/scripts/think.sh +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/version-bump/SKILL.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/version-bump/scripts/bump.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills.local.yaml.example +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.flake8 +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.github/workflows/publish.yml +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.github/workflows/tests.yml +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.gitignore +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/.markdownlint-cli2.yaml +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/AGENTS.colleague.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/CLAUDE.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/LICENSE +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/README.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/culture.yaml +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/docs/skill-sources.md +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/sonar-project.properties +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/tests/__init__.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/tests/test_cli.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/tests/test_cli_introspection.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/workledger/__init__.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/workledger/__main__.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/workledger/cli/__init__.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/workledger/cli/_commands/__init__.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/workledger/cli/_commands/cli.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/workledger/cli/_commands/doctor.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/workledger/cli/_commands/explain.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/workledger/cli/_commands/learn.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/workledger/cli/_commands/overview.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/workledger/cli/_commands/whoami.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/workledger/cli/_errors.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/workledger/cli/_output.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/workledger/explain/__init__.py +0 -0
- {workledger_cli-0.6.1 → workledger_cli-0.7.0}/workledger/explain/catalog.py +0 -0
|
@@ -27,7 +27,7 @@ description: >
|
|
|
27
27
|
# ask-colleague — lean on colleague as a different mind
|
|
28
28
|
|
|
29
29
|
`ask-colleague` drives the **`colleague`** CLI so a Claude agent can hand a scoped
|
|
30
|
-
task to a *different* backend (default: a local vLLM `Qwen3.
|
|
30
|
+
task to a *different* backend (default: a local vLLM `Qwen3.8-27B` on
|
|
31
31
|
`:8001`). Colleague's model is **not** assumed to be stronger than you — its
|
|
32
32
|
value is **diversity**. A second, independent mind catches things the author's
|
|
33
33
|
mind glides past, which is why **review** is the headline verb. Treat it the way
|
|
@@ -101,7 +101,9 @@ else an install hint.
|
|
|
101
101
|
| `explore "<question or area>"` | Read-only investigation of the repo; the model reads and reports findings. | **None** to your working tree / branch — runs in a throwaway worktree at HEAD; writes only a gradable run artifact under the gitignored `.colleague/` bookkeeping dir. |
|
|
102
102
|
| `review "<what to focus on>" [--base main]` | A diverse second opinion on the **committed** diff (`<base>...HEAD`). | **None** to your working tree / branch — throwaway worktree, committed changes only; writes only a gradable run artifact under the gitignored `.colleague/` bookkeeping dir. |
|
|
103
103
|
| `write "<task>" [--apply\|--pr]` | Implement a change. **Previews by default** (throwaway worktree, prints the would-be diff); `--apply` lands a work branch in place; `--pr` pushes + opens a PR. | **None** to your working tree / branch by default (preview); a `colleague/<id>` work branch / PR only with `--apply` / `--pr`. |
|
|
104
|
+
| `plan "<task>"` | Colleague **PLANS** a complex task: it proposes a spec, then a split plan, then fans the waves out to a subagent-colleague workforce (`colleague plan run … --yes`). The *inverse of `/think`* — same arc, but colleague is the planning mind, not Claude. Needs a live backend. | Runs `colleague plan` in `--repo` (not a throwaway worktree): the workforce stage spawns isolated subagent worktrees and can land branches — treat like `write --apply` (gets a user nod). |
|
|
104
105
|
| `feedback <id\|last> [--rating N]` | **Grade a finished work item** (the ROI loop). With `--rating N` (1–5, plus `--notes`) it records feedback; without, it shows the work item's existing feedback. `last` resolves the most recent work item in `--repo`. | Writes `.colleague/<id>.feedback.json` only when `--rating` is given; read-only otherwise. |
|
|
106
|
+
| `resume <task-id\|last> [--detach]` | **Resume a cut run** — a timed-out / SIGTERM'd / budget-exhausted work item picked back up from its persisted artifact (`colleague work --continue`, lineage on `TaskResult.continued_from`). `last` resolves the most recent work item in `--repo`. `--detach` runs it under `setsid`/`nohup` and returns at once (not `--background`, which drops the continue id — colleague#418). | Continues the ORIGINAL run's `colleague/<id>` work branch; never touches your tree / branch. |
|
|
105
107
|
| `clean [--dry-run]` | **Reap what a crashed run left behind** (#162): stale/corrupt `colleague/*` branches + orphaned 0-byte `.colleague/` artifacts that can wedge `git fetch`. Scoped strictly to `colleague/*` (never touches an unrelated branch); conservative with `.git/objects` (reports 0-byte loose objects + suggests `git prune`, never deletes them). A thin pass-through to `colleague clean`. | Deletes corrupt `colleague/<id>` refs + 0-byte `.colleague/` artifacts in `--repo`; `--dry-run` changes nothing. |
|
|
106
108
|
|
|
107
109
|
### Options
|
|
@@ -111,9 +113,13 @@ else an install hint.
|
|
|
111
113
|
| `--repo PATH` | Target repo (default: `.`). |
|
|
112
114
|
| `--base BRANCH` | Base for the `review` diff (default: `main`). |
|
|
113
115
|
| `--engine NAME` | Backend plugin (default: `$COLLEAGUE_ENGINE` or `vllm-openai`). |
|
|
114
|
-
| `--model NAME` | Model (default: `$COLLEAGUE_MODEL` or `
|
|
116
|
+
| `--model NAME` | Model (default: `$COLLEAGUE_MODEL` or `unsloth/Qwen3.8-27B-NVFP4`). |
|
|
115
117
|
| `--base-url URL` | OpenAI base URL (default: `$COLLEAGUE_BASE_URL` or `http://localhost:8001/v1`). |
|
|
116
|
-
| `--
|
|
118
|
+
| `--role NAME` | Typed subagent role for the run (`explorer`, `reviewer`, `validator`, `planner`, `writer`). Since #416 a top-level `--role explorer` runs at thinking effort **`low`** (off selectable via `--effort off`); other top-level roles keep the acting seat's effort. |
|
|
119
|
+
| `--effort RUNG` | **Thinking effort for the acting seat** (#416): `off` \| `low` \| `medium` \| `high` \| `xhigh` \| `default`. Unset = colleague's own table (acting seat `medium`). `off` sends `enable_thinking:false` — the measured win for small, well-specified briefs (same brief: off 24 s / xhigh 88 s / medium 129 s, all correct — `docs/evidence/2026-08-22-per-seat-thinking-effort-416-results.md`); `xhigh` for open-ended judgement; `default` = the kill-switch (send nothing, the pre-#416 wire). Exported as `COLLEAGUE_CORTEX_REASONING_EFFORT` + `COLLEAGUE_WORKER_REASONING_EFFORT`; validated before the run. |
|
|
120
|
+
| `--seat-effort S=R[,S=R]` | Per-seat override for the other seats (`cortex`, `worker`, `deepthink`, `senses`, `evaluator`, `design`) — e.g. `--seat-effort senses=off,deepthink=xhigh`. Exported as `COLLEAGUE_<SEAT>_REASONING_EFFORT`. Children keep their role table (writer/planner medium, reviewer/validator low, explorer off) unless the parent overrides per delegation. |
|
|
121
|
+
| `--detach` | (`resume`) run detached and return at once; pilot with `monitor` / `guide` / `stop` once the log names the new flight id. |
|
|
122
|
+
| `--max-steps N` | Loop step budget (default: 20). `explore`/`review` select colleague's own native **`explore`**/**`review`** mode profile (`colleague/profiles.py`, applied via `colleague work --mode`) instead of a wrapper-side override — today that profile defaults to 30, since read-only mapping fans out across more files. An explicit `--max-steps N` always overrides the profile's default, in either direction. If the resolved `colleague` predates `--mode` (a stale install on `PATH`), the wrapper falls back to the old caller-side `--max-steps 30` + reserved-steps behavior so it keeps working. |
|
|
117
123
|
| `--apply` | (`write`) apply the change in place (work branch) instead of previewing. |
|
|
118
124
|
| `--allow-dirty` | (`write`) allow running on a dirty tree (only matters with `--apply` / `--pr`). |
|
|
119
125
|
| `--pr` | (`write`) push + open a PR instead of a local work branch (implies `--apply`). |
|
|
@@ -155,6 +161,24 @@ keeping stdout valid JSON for a machine consumer while diagnostics stay on stder
|
|
|
155
161
|
(or `colleague clean`) to reap it — start with `--dry-run` to see what it would
|
|
156
162
|
remove. It only ever touches `colleague/*` refs and `.colleague/` artifacts.
|
|
157
163
|
|
|
164
|
+
## Thinking effort and resuming (#416)
|
|
165
|
+
|
|
166
|
+
Colleague resolves a **per-seat thinking effort** where each seat is built,
|
|
167
|
+
never per turn — the acting seat defaults to `medium`, deepthink `xhigh`,
|
|
168
|
+
senses/Talker `off`, children by role (writer/planner `medium`,
|
|
169
|
+
reviewer/validator `low`, explorer `off`). The wrapper exposes the operator
|
|
170
|
+
overrides as `--effort` (acting seat) and `--seat-effort` (any seat); a typo
|
|
171
|
+
fails fast. Rule of thumb from the measurements: **`--effort off` for small,
|
|
172
|
+
well-specified briefs** (5× faster, same result), **leave the default for
|
|
173
|
+
ordinary work**, **`--effort xhigh` for open-ended judgement** (review of a
|
|
174
|
+
subtle diff, a plan). Effort does not rescue a module-sized brief — split the
|
|
175
|
+
request instead (#415).
|
|
176
|
+
|
|
177
|
+
A run cut by a timeout, SIGTERM or an exhausted budget is **resumable**:
|
|
178
|
+
`ask-colleague resume <task-id|last>` continues it from its artifact on the same
|
|
179
|
+
work branch; `--detach` keeps your shell free. Prefer resume over re-dispatch —
|
|
180
|
+
the continuation carries the prior steps and lineage.
|
|
181
|
+
|
|
158
182
|
## Piloting a flight
|
|
159
183
|
|
|
160
184
|
Dispatch a drive with `--watch` (on `explore`, `review`, or `write`) to make the
|
|
@@ -207,7 +231,7 @@ stop requests take effect on the next iteration rather than interrupting mid-ste
|
|
|
207
231
|
|
|
208
232
|
## Provenance
|
|
209
233
|
|
|
210
|
-
This is a **first-party** colleague skill — colleague is its origin.
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
234
|
+
This is a **first-party** colleague skill — colleague is its origin. See
|
|
235
|
+
`docs/skill-sources.md` for the consumer's per-repo skill ledger. The `cite,
|
|
236
|
+
don't import` policy holds: downstream repos copy it, they don't symlink or
|
|
237
|
+
depend on it.
|
{workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/ask-colleague/prompts/explore.md
RENAMED
|
@@ -18,6 +18,16 @@ Rules:
|
|
|
18
18
|
report (or you are within a few steps of the budget), STOP reading and call
|
|
19
19
|
`finish`. Err on the side of finishing early — a focused finding beats endless
|
|
20
20
|
reading.
|
|
21
|
+
- For a WIDE codebase map (many folders/modules), do NOT read every file in series
|
|
22
|
+
— that exhausts the step budget. Partition the surface by folder and delegate the
|
|
23
|
+
per-folder sub-surveys to the `subagents` tool (one child per folder/subtree, each
|
|
24
|
+
returning its findings), then synthesize their results into your report.
|
|
25
|
+
- NARRATE PROGRESS: with EVERY tool call, write one short line of plain text
|
|
26
|
+
first — what you just learned and what you are checking next. That line rides
|
|
27
|
+
the run's flight feed, so the operator can see where you are instead of a
|
|
28
|
+
silent turn. A long think with nothing written looks like a stall. If you are
|
|
29
|
+
within ~3 steps of the budget, STOP and write the answer-so-far (partial is
|
|
30
|
+
fine, mark it partial) rather than reading one more file.
|
|
21
31
|
|
|
22
32
|
When you are done, call finish with a structured findings report:
|
|
23
33
|
1. What it is / how it works (with file:line references).
|
{workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/ask-colleague/prompts/review.md
RENAMED
|
@@ -5,13 +5,8 @@ Focus the review on:
|
|
|
5
5
|
|
|
6
6
|
$ARGUMENTS
|
|
7
7
|
|
|
8
|
-
The
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
git diff $BASE...HEAD --stat
|
|
12
|
-
git diff $BASE...HEAD
|
|
13
|
-
|
|
14
|
-
then read the touched files for the context you need.
|
|
8
|
+
The diff for this change is ALREADY PROVIDED below the instructions (filtered +
|
|
9
|
+
capped). Read specific files only if you need more context.
|
|
15
10
|
|
|
16
11
|
Rules:
|
|
17
12
|
- READ-ONLY. Do NOT modify, create, or delete any file. Only read and run
|
|
@@ -29,6 +24,12 @@ Rules:
|
|
|
29
24
|
NOTHING and wastes the entire drive — so the moment you have enough to write a
|
|
30
25
|
useful review (or you are within a few steps of the budget), STOP reading and
|
|
31
26
|
call `finish`. Err on the side of finishing early.
|
|
27
|
+
- NARRATE PROGRESS: with EVERY tool call, write one short line of plain text
|
|
28
|
+
first — what you just learned and what you are checking next. That line rides
|
|
29
|
+
the run's flight feed, so the operator can see where you are instead of a
|
|
30
|
+
silent turn. A long think with nothing written looks like a stall. If you are
|
|
31
|
+
within ~3 steps of the budget, STOP and write the answer-so-far (partial is
|
|
32
|
+
fine, mark it partial) rather than reading one more file.
|
|
32
33
|
|
|
33
34
|
When you are done, call finish with a structured review:
|
|
34
35
|
1. Correctness risks / likely bugs (with file:line).
|
|
@@ -10,6 +10,12 @@ Rules:
|
|
|
10
10
|
text file with exactly one trailing newline.
|
|
11
11
|
- You may read, create, modify files, and run commands as needed.
|
|
12
12
|
- Don't widen the scope: do exactly what was asked, nothing more.
|
|
13
|
+
- NARRATE PROGRESS: with EVERY tool call, write one short line of plain text
|
|
14
|
+
first — what you just learned and what you are checking next. That line rides
|
|
15
|
+
the run's flight feed, so the operator can see where you are instead of a
|
|
16
|
+
silent turn. A long think with nothing written looks like a stall. If you are
|
|
17
|
+
within ~3 steps of the budget, STOP and write the answer-so-far (partial is
|
|
18
|
+
fine, mark it partial) rather than reading one more file.
|
|
13
19
|
|
|
14
20
|
When you are done, call finish with a short summary of exactly what you changed
|
|
15
21
|
and why.
|
{workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/ask-colleague/scripts/ask-colleague.sh
RENAMED
|
@@ -43,11 +43,19 @@ PROMPTS_DIR="$SKILL_DIR/prompts"
|
|
|
43
43
|
# ── resolve the colleague CLI (installed, then local-dev fallback) ─────────
|
|
44
44
|
COLLEAGUE=()
|
|
45
45
|
|
|
46
|
+
_pyproject_is_colleague() {
|
|
47
|
+
local line
|
|
48
|
+
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
49
|
+
[[ "$line" == 'name = "colleague"'* ]] && return 0
|
|
50
|
+
done < "$1"
|
|
51
|
+
return 1
|
|
52
|
+
}
|
|
53
|
+
|
|
46
54
|
_colleague_via_uv() {
|
|
47
55
|
local dir="$1"
|
|
48
56
|
while [[ -n "$dir" ]] && [[ "$dir" != "/" ]]; do
|
|
49
57
|
if [[ -f "$dir/pyproject.toml" ]] \
|
|
50
|
-
&&
|
|
58
|
+
&& _pyproject_is_colleague "$dir/pyproject.toml"; then
|
|
51
59
|
command -v uv >/dev/null 2>&1 || return 1
|
|
52
60
|
COLLEAGUE=(uv run --project "$dir" colleague)
|
|
53
61
|
return 0
|
|
@@ -81,22 +89,38 @@ Usage:
|
|
|
81
89
|
ask-colleague explore "<question or area>" Read-only investigation -> findings (no side effects)
|
|
82
90
|
ask-colleague review "<what to focus on>" Diverse second-opinion on the committed diff (no side effects)
|
|
83
91
|
ask-colleague write "<task>" [--apply|--pr] Implement a change (preview by default; --apply lands it)
|
|
92
|
+
ask-colleague plan "<task>" [--no-workforce] Colleague PLANS a complex task (spec -> plan -> subagent workforce)
|
|
84
93
|
ask-colleague feedback <id|last> [--rating N] Grade a past drive (ROI loop); with --rating records, without shows
|
|
85
94
|
ask-colleague feedback list List every recorded drive by request + grade (find one by its request)
|
|
86
95
|
ask-colleague clean [--dry-run] Reap stale/corrupt colleague/* branches + orphaned .colleague/ artifacts (#162)
|
|
87
|
-
ask-colleague monitor <task-id>
|
|
96
|
+
ask-colleague monitor <task-id> Stream a running flight's live feed (--follow)
|
|
88
97
|
ask-colleague guide <task-id> "<msg>" Send mid-flight guidance to a running flight
|
|
89
98
|
ask-colleague stop <task-id> Ask a running flight to stop (cooperative)
|
|
99
|
+
ask-colleague resume <task-id|last> [--detach] Resume a cut/timed-out/SIGTERM'd run from its artifact (work --continue)
|
|
90
100
|
|
|
91
101
|
Options:
|
|
92
102
|
--repo PATH Target repo (default: .)
|
|
93
103
|
--dry-run (clean) report what would be reaped without changing anything
|
|
94
104
|
--base BRANCH Base for `review` diff (default: main)
|
|
95
105
|
--engine NAME Backend plugin (default: $COLLEAGUE_ENGINE or vllm-openai)
|
|
96
|
-
--model NAME Model (default: $COLLEAGUE_MODEL or
|
|
106
|
+
--model NAME Model (default: $COLLEAGUE_MODEL or unsloth/Qwen3.8-27B-NVFP4)
|
|
107
|
+
--role NAME Typed subagent role (e.g. explorer, reviewer, writer); a top-level
|
|
108
|
+
explorer runs at thinking effort "low" by default (#416)
|
|
109
|
+
--effort RUNG Thinking effort for the ACTING seat: off|low|medium|high|xhigh|default
|
|
110
|
+
(#416; default = colleague's table, medium for the acting seat;
|
|
111
|
+
"default" = the kill-switch, send nothing). Exported as
|
|
112
|
+
COLLEAGUE_CORTEX_REASONING_EFFORT + COLLEAGUE_WORKER_REASONING_EFFORT.
|
|
113
|
+
--seat-effort S=R Per-seat override, comma-separated (seats: cortex, worker, deepthink,
|
|
114
|
+
senses, evaluator, design), e.g. --seat-effort senses=off,deepthink=xhigh
|
|
115
|
+
--detach (resume) run detached (setsid/nohup) and return at once; pilot it with
|
|
116
|
+
monitor/guide/stop once the new flight id appears in the log
|
|
97
117
|
--base-url URL OpenAI base URL (default: $COLLEAGUE_BASE_URL or http://localhost:8001/v1)
|
|
98
|
-
--max-steps N Loop step budget (default: 20
|
|
118
|
+
--max-steps N Loop step budget (default: 20; explore/review default from
|
|
119
|
+
colleague's own "explore"/"review" mode profile, today 30 —
|
|
120
|
+
an explicit --max-steps always overrides, lower or higher)
|
|
99
121
|
--timeout N Per-request timeout, seconds (default: $COLLEAGUE_TIMEOUT or 300)
|
|
122
|
+
--no-workforce (plan) deliver the spec+plan only, skip the workforce fan-out (#215)
|
|
123
|
+
--quick / --no-spec (plan) skip the spec stage, plan directly from the request (#199)
|
|
100
124
|
--apply (write) apply the change in place (drive branch) instead of previewing
|
|
101
125
|
--allow-dirty (write) allow running on a dirty tree (only with --apply/--pr)
|
|
102
126
|
--pr (write) push + open a PR instead of a local drive branch (implies --apply)
|
|
@@ -123,11 +147,11 @@ EOF
|
|
|
123
147
|
# ── parse the verb ──────────────────────────────────────────────────────────
|
|
124
148
|
VERB="${1:-}"
|
|
125
149
|
case "$VERB" in
|
|
126
|
-
explore | review | write | feedback | clean | monitor | guide | stop) shift ;;
|
|
150
|
+
explore | review | write | plan | feedback | clean | monitor | guide | stop | resume) shift ;;
|
|
127
151
|
-h | --help) usage; exit 0 ;;
|
|
128
152
|
"") usage >&2; exit 1 ;; # missing arg -> user-input error (#161)
|
|
129
153
|
*)
|
|
130
|
-
echo "error: unknown verb '$VERB' (expected explore|review|write|feedback|clean|monitor|guide|stop)" >&2
|
|
154
|
+
echo "error: unknown verb '$VERB' (expected explore|review|write|plan|feedback|clean|monitor|guide|stop|resume)" >&2
|
|
131
155
|
echo "hint: run 'ask-colleague --help'" >&2
|
|
132
156
|
exit 1 # bad verb -> user-input error (#161)
|
|
133
157
|
;;
|
|
@@ -139,9 +163,7 @@ esac
|
|
|
139
163
|
# feedback/clean are thin pass-throughs to `colleague` plus the shared git
|
|
140
164
|
# work-tree guard, so they need only git; the drive verbs (explore/review/write)
|
|
141
165
|
# also render a prompt and parse colleague's --json result via python3, and the
|
|
142
|
-
# worktree-isolated paths additionally need mktemp.
|
|
143
|
-
# uv-fallback resolver, which degrades to the clear "colleague not found" message
|
|
144
|
-
# when absent, so it is not a hard requirement here.
|
|
166
|
+
# worktree-isolated paths additionally need mktemp.
|
|
145
167
|
require_tools() { # $@ = tool names this verb path needs
|
|
146
168
|
local missing=() t
|
|
147
169
|
for t in "$@"; do
|
|
@@ -169,9 +191,10 @@ REPO="."
|
|
|
169
191
|
BASE="main"
|
|
170
192
|
# COLLEAGUE_* wins; the legacy CONVERTIBLE_* names are honored as a deprecated fallback.
|
|
171
193
|
ENGINE="${COLLEAGUE_ENGINE:-${CONVERTIBLE_ENGINE:-vllm-openai}}"
|
|
172
|
-
MODEL="${COLLEAGUE_MODEL:-${CONVERTIBLE_MODEL:-
|
|
194
|
+
MODEL="${COLLEAGUE_MODEL:-${CONVERTIBLE_MODEL:-unsloth/Qwen3.8-27B-NVFP4}}"
|
|
173
195
|
BASE_URL="${COLLEAGUE_BASE_URL:-${CONVERTIBLE_BASE_URL:-http://localhost:8001/v1}}"
|
|
174
196
|
MAX_STEPS=20
|
|
197
|
+
MAX_STEPS_EXPLICIT=0
|
|
175
198
|
TIMEOUT="${COLLEAGUE_TIMEOUT:-${CONVERTIBLE_TIMEOUT:-300}}"
|
|
176
199
|
ALLOW_DIRTY=0
|
|
177
200
|
APPLY=0
|
|
@@ -183,6 +206,12 @@ NOTES=""
|
|
|
183
206
|
BY=""
|
|
184
207
|
ARG=""
|
|
185
208
|
JSON_OUT=0
|
|
209
|
+
ROLE=""
|
|
210
|
+
EFFORT=""
|
|
211
|
+
SEAT_EFFORT=""
|
|
212
|
+
DETACH=0
|
|
213
|
+
QUICK=0
|
|
214
|
+
NO_WORKFORCE=0
|
|
186
215
|
|
|
187
216
|
while [[ $# -gt 0 ]]; do
|
|
188
217
|
case "$1" in
|
|
@@ -190,14 +219,20 @@ while [[ $# -gt 0 ]]; do
|
|
|
190
219
|
--base) need_value "$#" "$1"; BASE="$2"; shift 2 ;;
|
|
191
220
|
--engine) need_value "$#" "$1"; ENGINE="$2"; shift 2 ;;
|
|
192
221
|
--model) need_value "$#" "$1"; MODEL="$2"; shift 2 ;;
|
|
222
|
+
--role) need_value "$#" "$1"; ROLE="$2"; shift 2 ;;
|
|
223
|
+
--effort) need_value "$#" "$1"; EFFORT="$2"; shift 2 ;;
|
|
224
|
+
--seat-effort) need_value "$#" "$1"; SEAT_EFFORT="$2"; shift 2 ;;
|
|
225
|
+
--detach) DETACH=1; shift ;;
|
|
193
226
|
--base-url) need_value "$#" "$1"; BASE_URL="$2"; shift 2 ;;
|
|
194
|
-
--max-steps) need_value "$#" "$1"; MAX_STEPS="$2"; shift 2 ;;
|
|
227
|
+
--max-steps) need_value "$#" "$1"; MAX_STEPS="$2"; MAX_STEPS_EXPLICIT=1; shift 2 ;;
|
|
195
228
|
--timeout) need_value "$#" "$1"; TIMEOUT="$2"; shift 2 ;;
|
|
196
229
|
--apply) APPLY=1; shift ;;
|
|
197
230
|
--watch) WATCH=1; shift ;;
|
|
198
231
|
--allow-dirty) ALLOW_DIRTY=1; shift ;;
|
|
199
232
|
--pr) OPEN_PR=1; shift ;;
|
|
200
233
|
--dry-run) DRY_RUN=1; shift ;;
|
|
234
|
+
--quick | --no-spec) QUICK=1; shift ;; # plan: skip the spec stage (#199)
|
|
235
|
+
--no-workforce) NO_WORKFORCE=1; shift ;; # plan: deliver spec+plan only (#215)
|
|
201
236
|
--rating) need_value "$#" "$1"; RATING="$2"; shift 2 ;;
|
|
202
237
|
--notes) need_value "$#" "$1"; NOTES="$2"; shift 2 ;;
|
|
203
238
|
--by) need_value "$#" "$1"; BY="$2"; shift 2 ;;
|
|
@@ -210,14 +245,28 @@ while [[ $# -gt 0 ]]; do
|
|
|
210
245
|
esac
|
|
211
246
|
done
|
|
212
247
|
|
|
248
|
+
# Per-verb default: explore and review get a modest higher budget (30) for wider
|
|
249
|
+
# surveys and read-heavy diffs; write keeps the global default (20). Only apply
|
|
250
|
+
# when the user did NOT pass an explicit --max-steps.
|
|
251
|
+
#
|
|
252
|
+
# t4/spec R1: this number now ALSO matches colleague's own native "explore"/
|
|
253
|
+
# "review" mode profile (colleague/profiles.py), which is what actually drives
|
|
254
|
+
# the step budget at runtime once `--mode` is selected below — this wrapper-side
|
|
255
|
+
# value survives only so the "widen --max-steps" re-run hint (print_result)
|
|
256
|
+
# still names the right number; whether --max-steps is actually FORWARDED to
|
|
257
|
+
# colleague is decided later, once mode support is known.
|
|
258
|
+
if [[ ( "$VERB" == "explore" || "$VERB" == "review" ) && "$MAX_STEPS_EXPLICIT" -eq 0 ]]; then
|
|
259
|
+
MAX_STEPS=30
|
|
260
|
+
fi
|
|
261
|
+
|
|
213
262
|
# Now that the verb and its flags are known, require only the tools THIS path
|
|
214
263
|
# uses. feedback/clean shell straight to `colleague` (+ the git work-tree guard
|
|
215
264
|
# below), so they need only git — not python3/mktemp (qodo: the old blanket check
|
|
216
265
|
# failed those verbs in minimal envs). write --apply/--pr lands in place with no
|
|
217
266
|
# throwaway worktree, so it needs no mktemp either.
|
|
218
267
|
case "$VERB" in
|
|
219
|
-
feedback | clean) require_tools git ;;
|
|
220
|
-
monitor | guide | stop) : ;;
|
|
268
|
+
feedback | clean | plan) require_tools git ;;
|
|
269
|
+
monitor | guide | stop) : ;; # resume needs the engine path like write, so it is NOT listed here
|
|
221
270
|
write)
|
|
222
271
|
if [[ "$APPLY" -eq 1 || "$OPEN_PR" -eq 1 ]]; then
|
|
223
272
|
require_tools git python3
|
|
@@ -245,7 +294,7 @@ REPO="$(cd "$REPO" && pwd)"
|
|
|
245
294
|
# The pilot verbs (monitor/guide/stop) are pure .colleague/flight/ file I/O — they
|
|
246
295
|
# need no git work tree, so they are exempt from this fail-fast guard.
|
|
247
296
|
case "$VERB" in
|
|
248
|
-
monitor | guide | stop) : ;;
|
|
297
|
+
monitor | guide | stop) : ;; # resume needs the engine path like write, so it is NOT listed here
|
|
249
298
|
*)
|
|
250
299
|
git -C "$REPO" rev-parse --is-inside-work-tree >/dev/null 2>&1 \
|
|
251
300
|
|| { echo "error: --repo is not a git repository: $REPO" >&2; exit 1; }
|
|
@@ -265,10 +314,128 @@ resolve_colleague || exit 2
|
|
|
265
314
|
# Per-request timeout is config (no drive flag); EngineConfig reads it from env.
|
|
266
315
|
# A local model can be slow on a growing context, so default generously.
|
|
267
316
|
export COLLEAGUE_TIMEOUT="$TIMEOUT"
|
|
268
|
-
|
|
317
|
+
|
|
318
|
+
# ── thinking effort (#416): per-seat, resolved by colleague where each seat is
|
|
319
|
+
# built — the wrapper only sets the operator override env vars colleague reads
|
|
320
|
+
# (flag > env > config.json > table). Validated here so a typo fails fast
|
|
321
|
+
# (user-input error, #161) instead of as a refused run.
|
|
322
|
+
_EFFORT_RUNGS="off|low|medium|high|xhigh|default"
|
|
323
|
+
_check_rung() {
|
|
324
|
+
case "$1" in
|
|
325
|
+
off | low | medium | high | xhigh | default) : ;;
|
|
326
|
+
*) echo "error: unknown thinking effort '$1' (expected one of: ${_EFFORT_RUNGS//|/, })" >&2; exit 1 ;;
|
|
327
|
+
esac
|
|
328
|
+
}
|
|
329
|
+
if [[ -n "$EFFORT" ]]; then
|
|
330
|
+
_check_rung "$EFFORT"
|
|
331
|
+
export COLLEAGUE_CORTEX_REASONING_EFFORT="$EFFORT"
|
|
332
|
+
export COLLEAGUE_WORKER_REASONING_EFFORT="$EFFORT"
|
|
333
|
+
fi
|
|
334
|
+
if [[ -n "$SEAT_EFFORT" ]]; then
|
|
335
|
+
IFS=',' read -r -a _pairs <<< "$SEAT_EFFORT"
|
|
336
|
+
for _pair in "${_pairs[@]}"; do
|
|
337
|
+
_seat="${_pair%%=*}"; _rung="${_pair#*=}"
|
|
338
|
+
case "$_seat" in
|
|
339
|
+
cortex | worker | deepthink | senses | evaluator | design) : ;;
|
|
340
|
+
*) echo "error: unknown seat '$_seat' in --seat-effort (expected cortex|worker|deepthink|senses|evaluator|design)" >&2; exit 1 ;;
|
|
341
|
+
esac
|
|
342
|
+
_check_rung "$_rung"
|
|
343
|
+
export "COLLEAGUE_$(printf '%s' "$_seat" | tr '[:lower:]' '[:upper:]')_REASONING_EFFORT=$_rung"
|
|
344
|
+
done
|
|
345
|
+
fi
|
|
346
|
+
|
|
347
|
+
# ── plan: colleague does the planning (the inverse of /think) ────────────────
|
|
348
|
+
# plan delegates the WHOLE planning arc to colleague via the `colleague plan`
|
|
349
|
+
# verb — no throwaway worktree, no prompt template. Gated non-interactively
|
|
350
|
+
# (--yes) so a delegating agent can hand off the arc and read the
|
|
351
|
+
# spec -> plan -> workforce result. colleague is the planning mind; /think keeps
|
|
352
|
+
# Claude as the planner (same arc, a different mind).
|
|
353
|
+
if [[ "$VERB" == "plan" ]]; then
|
|
354
|
+
plan_flags=(--repo "$REPO" --engine "$ENGINE" --model "$MODEL" --base-url "$BASE_URL" --yes)
|
|
355
|
+
# --quick skips the spec stage (#199); --no-workforce delivers spec+plan only,
|
|
356
|
+
# skipping the timeout-prone fan-out (#215). --timeout already applies via the
|
|
357
|
+
# COLLEAGUE_TIMEOUT export above. These are forwarded, never auto-applied.
|
|
358
|
+
[[ "$QUICK" -eq 1 ]] && plan_flags+=(--quick)
|
|
359
|
+
[[ "$NO_WORKFORCE" -eq 1 ]] && plan_flags+=(--no-workforce)
|
|
360
|
+
[[ "${JSON_OUT:-0}" -eq 1 ]] && plan_flags+=(--json)
|
|
361
|
+
plan_rc=0
|
|
362
|
+
"${COLLEAGUE[@]}" plan run "$ARG" "${plan_flags[@]}" || plan_rc=$?
|
|
363
|
+
# No silent auto-degrade: name the recovery levers (those not already set) and
|
|
364
|
+
# let the caller choose. Human hints are TEXT-mode only — in --json mode the
|
|
365
|
+
# consumer is a machine and colleague's own structured {code,message,remediation}
|
|
366
|
+
# error already went to stderr, so suppress the prose there (Qodo #230 F4).
|
|
367
|
+
if [[ "$plan_rc" -ne 0 && "${JSON_OUT:-0}" -ne 1 ]]; then
|
|
368
|
+
echo "hint: plan mode did not complete on this backend. Recovery options (no auto-degrade):" >&2
|
|
369
|
+
[[ "$NO_WORKFORCE" -eq 0 ]] && echo "hint: --no-workforce deliver the spec+plan only, skip the timeout-prone workforce fan-out (#215)" >&2
|
|
370
|
+
[[ "$QUICK" -eq 0 ]] && echo "hint: --quick skip the spec stage, plan directly from the request (#199)" >&2
|
|
371
|
+
echo "hint: --timeout N widen the per-request window (currently ${TIMEOUT}s)" >&2
|
|
372
|
+
fi
|
|
373
|
+
exit "$plan_rc"
|
|
374
|
+
fi
|
|
375
|
+
|
|
376
|
+
# ── explore/review adopt colleague's native mode profile (t4/spec R1) ───────
|
|
377
|
+
# explore/review's step budget + synthesis-reserve tail used to be caller-side
|
|
378
|
+
# overrides baked into this script (a fixed --max-steps 30 plus an exported
|
|
379
|
+
# COLLEAGUE_SYNTHESIS_RESERVE_STEPS=3). Those numbers now live in colleague's
|
|
380
|
+
# own mode-profile catalog (colleague/profiles.py "explore"/"review") and are
|
|
381
|
+
# applied runtime-side by `colleague work --mode explore|review`
|
|
382
|
+
# (colleague/config.py apply_mode_profile) — so this wrapper's job shrinks to
|
|
383
|
+
# "select the mode" instead of re-deriving the profile's numbers itself; a
|
|
384
|
+
# future retune of the profile then reaches this wrapper for free.
|
|
385
|
+
#
|
|
386
|
+
# Honest limit: this wrapper prefers an installed `colleague` on PATH ahead of
|
|
387
|
+
# a local checkout, and an installed CLI can be older than the one this repo
|
|
388
|
+
# ships (it can predate --mode entirely). Detect that cheaply by checking the
|
|
389
|
+
# resolved CLI's OWN --help text for the literal flag with a plain bash
|
|
390
|
+
# substring match (no external text-search tool — the resolver stays as
|
|
391
|
+
# dependency-free as the uv-fallback path above, #190); fall back to the old
|
|
392
|
+
# caller-side defaults when --mode isn't there, so the wrapper keeps working
|
|
393
|
+
# unmodified against a stale CLI.
|
|
394
|
+
#
|
|
395
|
+
# NOTE: the substring must be anchored past the flag name — "--mode" is
|
|
396
|
+
# itself a literal prefix of "--model" (already a flag on every version), so
|
|
397
|
+
# a naive `*--mode*` match false-positives on a stale --help that only has
|
|
398
|
+
# --model. Requiring the next character NOT be a letter (or end-of-string)
|
|
399
|
+
# distinguishes a genuine "--mode ..."/"--mode]" occurrence from "--model".
|
|
400
|
+
MODE_SUPPORTED=0
|
|
401
|
+
if [[ "$VERB" == "explore" || "$VERB" == "review" ]]; then
|
|
402
|
+
help_out="$("${COLLEAGUE[@]}" work --help 2>/dev/null)" || help_out=""
|
|
403
|
+
if [[ "$help_out" == *"--mode"[!a-zA-Z]* || "$help_out" == *--mode ]]; then
|
|
404
|
+
MODE_SUPPORTED=1
|
|
405
|
+
fi
|
|
406
|
+
fi
|
|
407
|
+
|
|
408
|
+
if [[ ( "$VERB" == "explore" || "$VERB" == "review" ) && "$MODE_SUPPORTED" -eq 0 ]]; then
|
|
409
|
+
# Legacy fallback (stale CLI without --mode): reserve a few steps for the
|
|
410
|
+
# final verdict turn so a big-diff review/explore yields findings instead
|
|
411
|
+
# of dying mid-read (#197). Caller env wins.
|
|
412
|
+
: "${COLLEAGUE_SYNTHESIS_RESERVE_STEPS:=3}"
|
|
413
|
+
export COLLEAGUE_SYNTHESIS_RESERVE_STEPS
|
|
414
|
+
fi
|
|
415
|
+
|
|
416
|
+
COMMON_FLAGS=(--engine "$ENGINE" --model "$MODEL" --base-url "$BASE_URL" --json)
|
|
417
|
+
# --max-steps: forwarded unless this is a native-mode-capable explore/review run
|
|
418
|
+
# with no explicit --max-steps — then the flag is withheld so colleague's own
|
|
419
|
+
# mode profile supplies the step budget as a DEFAULT at runtime. An explicit
|
|
420
|
+
# --max-steps always wins, in EITHER direction (lower or higher than the
|
|
421
|
+
# profile's own number): it is still forwarded here, and the runtime resolves
|
|
422
|
+
# an explicit flag ahead of any profile default (colleague/config.py
|
|
423
|
+
# apply_mode_profile's explicit-knobs precedence).
|
|
424
|
+
if [[ "$MAX_STEPS_EXPLICIT" -eq 1 || "$MODE_SUPPORTED" -eq 0 || ( "$VERB" != "explore" && "$VERB" != "review" ) ]]; then
|
|
425
|
+
COMMON_FLAGS+=(--max-steps "$MAX_STEPS")
|
|
426
|
+
fi
|
|
427
|
+
# --mode: select colleague's native explore/review constraint profile when the
|
|
428
|
+
# resolved CLI supports it (detected above). write carries no --mode — its
|
|
429
|
+
# profile is behavior-neutral (identical to no mode at all), so the numbers
|
|
430
|
+
# stay exactly as documented (--max-steps 20 default, no reserve override).
|
|
431
|
+
if [[ "$MODE_SUPPORTED" -eq 1 && ( "$VERB" == "explore" || "$VERB" == "review" ) ]]; then
|
|
432
|
+
COMMON_FLAGS+=(--mode "$VERB")
|
|
433
|
+
fi
|
|
269
434
|
# --watch arms a flight for EVERY drive verb (explore/review/write), so it lives on
|
|
270
435
|
# the shared flag list — not inside one verb's path — so monitor/guide/stop work.
|
|
271
436
|
[[ "${WATCH:-0}" -eq 1 ]] && COMMON_FLAGS+=(--watch)
|
|
437
|
+
# --role forwards a typed-subagent role to the work item.
|
|
438
|
+
[[ -n "${ROLE:-}" ]] && COMMON_FLAGS+=(--role "$ROLE")
|
|
272
439
|
|
|
273
440
|
# ── render an instruction from a prompt template ────────────────────────────
|
|
274
441
|
render_prompt() {
|
|
@@ -305,20 +472,38 @@ print_result() {
|
|
|
305
472
|
# empty (its artifact was discarded with the worktree, so it is not gradable).
|
|
306
473
|
# $3 (optional): exit code from the colleague drive command, propagated to
|
|
307
474
|
# the caller when the drive itself failed.
|
|
308
|
-
ASK_COLLEAGUE_REAL_ARTIFACT_DIR="${1:-}" ASK_COLLEAGUE_GRADABLE="${2:-}" ASK_COLLEAGUE_DRIVE_RC="${3:-}" ASK_COLLEAGUE_JSON="${JSON_OUT:-0}" python3 -c '
|
|
475
|
+
ASK_COLLEAGUE_REAL_ARTIFACT_DIR="${1:-}" ASK_COLLEAGUE_GRADABLE="${2:-}" ASK_COLLEAGUE_DRIVE_RC="${3:-}" ASK_COLLEAGUE_JSON="${JSON_OUT:-0}" ASK_COLLEAGUE_MAX_STEPS="${MAX_STEPS:-20}" python3 -c '
|
|
309
476
|
import sys, json, os
|
|
310
477
|
raw = sys.stdin.read().strip()
|
|
311
478
|
json_mode = os.environ.get("ASK_COLLEAGUE_JSON") == "1"
|
|
479
|
+
def _fail(code, message, remediation, detail=None):
|
|
480
|
+
# #226: in --json mode emit a structured {code, message, remediation} object
|
|
481
|
+
# on stderr (matching colleague CliError shape) so a machine consumer parses
|
|
482
|
+
# a failure the same way it parses success; in text mode keep the standard
|
|
483
|
+
# error:/hint: contract. stdout stays clean (no result) on every path.
|
|
484
|
+
if json_mode:
|
|
485
|
+
obj = {"code": code, "message": message, "remediation": remediation}
|
|
486
|
+
if detail is not None:
|
|
487
|
+
obj["detail"] = detail
|
|
488
|
+
sys.stderr.write(json.dumps(obj) + "\n")
|
|
489
|
+
else:
|
|
490
|
+
sys.stderr.write("error: " + message + "\n")
|
|
491
|
+
if detail is not None:
|
|
492
|
+
sys.stderr.write(detail + "\n")
|
|
493
|
+
if remediation:
|
|
494
|
+
sys.stderr.write("hint: " + remediation + "\n")
|
|
495
|
+
sys.exit(code)
|
|
312
496
|
if not raw:
|
|
313
|
-
|
|
314
|
-
|
|
497
|
+
_fail(2, "colleague produced no result on stdout (see diagnostics above)",
|
|
498
|
+
"re-run; if it persists, check the backend with colleague doctor --probe")
|
|
315
499
|
try:
|
|
316
500
|
d = json.loads(raw)
|
|
317
501
|
except Exception:
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
502
|
+
_fail(2, "could not parse colleague --json output",
|
|
503
|
+
"the backend may have emitted non-JSON; see the raw output and diagnostics above",
|
|
504
|
+
detail=raw[:2000])
|
|
321
505
|
ok = d.get("status") == "ok"
|
|
506
|
+
inc = d.get("incompletion") if isinstance(d.get("incompletion"), dict) else None
|
|
322
507
|
tid = d.get("task_id") or ""
|
|
323
508
|
# Resolve the artifact path to the preserved copy when the drive ran in a
|
|
324
509
|
# throwaway worktree (read-only verbs); the raw JSON points into the now-deleted
|
|
@@ -332,11 +517,37 @@ if ap and real_dir:
|
|
|
332
517
|
# trailing off mid-task. Warn so the caller treats it as a partial, not a verdict.
|
|
333
518
|
# The warning is a DIAGNOSTIC -> always stderr (never stdout), so both the digest
|
|
334
519
|
# and --json keep a clean, machine-readable stdout (no single quotes in this body).
|
|
520
|
+
# Enriched partial warnings: include reached step count and a concrete larger
|
|
521
|
+
# --max-steps to retry with, so the hint is actionable (#194).
|
|
522
|
+
max_steps = int(os.environ.get("ASK_COLLEAGUE_MAX_STEPS", "20"))
|
|
523
|
+
stats = d.get("stats") or {}
|
|
524
|
+
model_turns = stats.get("model_turns")
|
|
525
|
+
step_count = stats.get("step_count")
|
|
335
526
|
if d.get("stopped_without_finish"):
|
|
336
|
-
|
|
337
|
-
|
|
527
|
+
reached = model_turns if model_turns is not None else step_count
|
|
528
|
+
if reached is not None:
|
|
529
|
+
print(f"warning: drive ended without calling finish (reached {reached} model turns of {max_steps}) — re-run with --max-steps {2 * max_steps} to go deeper.", file=sys.stderr)
|
|
530
|
+
else:
|
|
531
|
+
print("warning: drive ended without calling finish — treat the summary as a", file=sys.stderr)
|
|
532
|
+
print(" partial (the model stopped mid-task), not an authoritative result.", file=sys.stderr)
|
|
338
533
|
elif d.get("not_finished"):
|
|
339
|
-
|
|
534
|
+
reached = model_turns if model_turns is not None else step_count
|
|
535
|
+
if reached is not None:
|
|
536
|
+
print(f"warning: drive ran out of steps without finishing (reached {reached} model turns of {max_steps}) — re-run with --max-steps {2 * max_steps} to go deeper.", file=sys.stderr)
|
|
537
|
+
else:
|
|
538
|
+
print("warning: drive ran out of steps without finishing — summary is partial.", file=sys.stderr)
|
|
539
|
+
# No-result sentinel: the drive produced nothing actionable (#192).
|
|
540
|
+
summary = d.get("summary") or ""
|
|
541
|
+
if summary == "__COLLEAGUE_NO_RESULT_PRODUCED__":
|
|
542
|
+
print("warning: no result produced — widen --max-steps or narrow the scope.", file=sys.stderr)
|
|
543
|
+
# Incompletion: when the run did NOT deliver (status != "ok") and colleague
|
|
544
|
+
# carried an incompletion record, surface it as a diagnostic to stderr so the
|
|
545
|
+
# delegating caller knows WHY the run failed and what to do next. Always stderr
|
|
546
|
+
# (never stdout) so --json stdout stays pure.
|
|
547
|
+
if not ok and inc:
|
|
548
|
+
reason = inc.get("reason", "")
|
|
549
|
+
recommendation = inc.get("recommendation", "")
|
|
550
|
+
print(f"incomplete: {reason} — {recommendation}", file=sys.stderr)
|
|
340
551
|
if json_mode:
|
|
341
552
|
# --json contract: stdout carries ONLY the TaskResult JSON; every
|
|
342
553
|
# human/diagnostic line already went to stderr above. The exit code still
|
|
@@ -359,7 +570,10 @@ if json_mode:
|
|
|
359
570
|
# task_id is already in the payload, but echoing the copy-paste grade hint
|
|
360
571
|
# keeps the convention every work item follows (rule 907536) without breaking
|
|
361
572
|
# the stdout contract. Gated on gradable, exactly like the digest below.
|
|
362
|
-
|
|
573
|
+
# Skip the grade hint for the no-result sentinel (#192). A FAILED/incomplete but
|
|
574
|
+
# gradable drive still gets the hint — a failure rated 1/5 is the ROI signal
|
|
575
|
+
# (#139); the incompletion diagnostic above already says it did not succeed.
|
|
576
|
+
if tid and gradable and summary != "__COLLEAGUE_NO_RESULT_PRODUCED__":
|
|
363
577
|
print("task:", tid, file=sys.stderr)
|
|
364
578
|
print("grade:", "ask-colleague feedback", tid, "--rating N", file=sys.stderr)
|
|
365
579
|
else:
|
|
@@ -380,7 +594,10 @@ else:
|
|
|
380
594
|
# drive (colleague writes an artifact on failure too, h5): a failure rated
|
|
381
595
|
# 1/5 is exactly the ROI signal, so the hint must not be gated on `ok` (#139
|
|
382
596
|
# qodo). It prints to `out` (stderr on failure), matching the failure digest.
|
|
383
|
-
|
|
597
|
+
# Skip the grade footer for the no-result sentinel (#192): a drive that
|
|
598
|
+
# produced nothing is not worth grading.
|
|
599
|
+
summary = d.get("summary") or ""
|
|
600
|
+
if tid and os.environ.get("ASK_COLLEAGUE_GRADABLE") == "1" and summary != "__COLLEAGUE_NO_RESULT_PRODUCED__":
|
|
384
601
|
print("grade:", "ask-colleague feedback", tid, "--rating N", file=out)
|
|
385
602
|
if ok:
|
|
386
603
|
sys.exit(0)
|
|
@@ -474,7 +691,7 @@ _preserve_artifact() {
|
|
|
474
691
|
local art_name="$1"
|
|
475
692
|
[[ -n "$art_name" && -n "$_WT" ]] || return 1
|
|
476
693
|
if ! _valid_segment "$art_name"; then
|
|
477
|
-
printf '
|
|
694
|
+
printf 'error: refusing to preserve unsafe artifact name %q\n' "$art_name" >&2
|
|
478
695
|
return 1
|
|
479
696
|
fi
|
|
480
697
|
local src="$_WT/.colleague"
|
|
@@ -484,7 +701,7 @@ _preserve_artifact() {
|
|
|
484
701
|
# The JSON artifact is the record of the drive — surface a copy failure rather
|
|
485
702
|
# than swallow it, so the caller can fall back to honest path reporting.
|
|
486
703
|
if ! cp -f "$src/$art_name" "$dst/$art_name"; then
|
|
487
|
-
printf '
|
|
704
|
+
printf 'error: could not preserve artifact %s\n' "$art_name" >&2
|
|
488
705
|
return 1
|
|
489
706
|
fi
|
|
490
707
|
# The trace shares the artifact stem (.json -> .trace.jsonl); a best-effort
|
|
@@ -508,7 +725,7 @@ run_readonly() {
|
|
|
508
725
|
local instruction="$1"
|
|
509
726
|
_add_worktree
|
|
510
727
|
local out rc=0
|
|
511
|
-
out="$("${COLLEAGUE[@]}"
|
|
728
|
+
out="$("${COLLEAGUE[@]}" work "$instruction" --repo "$_WT" --no-pr "${COMMON_FLAGS[@]}")" || rc=$?
|
|
512
729
|
_DRIVE_BRANCH="$(printf '%s' "$out" | _extract_branch)"
|
|
513
730
|
# Preserve the artifact to the real repo BEFORE the EXIT trap removes the
|
|
514
731
|
# worktree, so the drive can be graded by its task-id (`ask-colleague feedback
|
|
@@ -532,7 +749,7 @@ run_preview() {
|
|
|
532
749
|
local instruction="$1"
|
|
533
750
|
_add_worktree
|
|
534
751
|
local out rc=0
|
|
535
|
-
out="$("${COLLEAGUE[@]}"
|
|
752
|
+
out="$("${COLLEAGUE[@]}" work "$instruction" --repo "$_WT" --no-pr "${COMMON_FLAGS[@]}")" || rc=$?
|
|
536
753
|
_DRIVE_BRANCH="$(printf '%s' "$out" | _extract_branch)"
|
|
537
754
|
|
|
538
755
|
# Capture the would-be patch before _cleanup_worktree deletes the drive branch.
|
|
@@ -568,9 +785,9 @@ run_write() {
|
|
|
568
785
|
return
|
|
569
786
|
fi
|
|
570
787
|
if [[ "$ALLOW_DIRTY" -eq 0 ]] \
|
|
571
|
-
&& [[ -n "$(git -C "$REPO" status --porcelain 2>/dev/null)" ]]; then
|
|
788
|
+
&& [[ -n "$(git -C "$REPO" status --porcelain --untracked-files=no 2>/dev/null)" ]]; then
|
|
572
789
|
echo "error: working tree is dirty — commit/stash first, or pass --allow-dirty" >&2
|
|
573
|
-
echo "hint: 'colleague
|
|
790
|
+
echo "hint: 'colleague work --no-pr' commits uncommitted edits onto the work branch" >&2
|
|
574
791
|
# User-fixable state guard -> exit 1, matching the runtime's own
|
|
575
792
|
# dirty-tree guard (colleague/handoff.py _guard_clean_tree =
|
|
576
793
|
# EXIT_USER_ERROR), not exit 2 (#161).
|
|
@@ -591,9 +808,9 @@ run_write() {
|
|
|
591
808
|
# read-only / preview paths, which guard this way.
|
|
592
809
|
local out rc=0
|
|
593
810
|
if [[ "$OPEN_PR" -eq 1 ]]; then
|
|
594
|
-
out="$("${COLLEAGUE[@]}"
|
|
811
|
+
out="$("${COLLEAGUE[@]}" work "$instruction" --repo "$REPO" "${COMMON_FLAGS[@]}")" || rc=$?
|
|
595
812
|
else
|
|
596
|
-
out="$("${COLLEAGUE[@]}"
|
|
813
|
+
out="$("${COLLEAGUE[@]}" work "$instruction" --repo "$REPO" --no-pr "${COMMON_FLAGS[@]}")" || rc=$?
|
|
597
814
|
fi
|
|
598
815
|
# A landed write persists its artifact in the real repo and moves `last`, so it
|
|
599
816
|
# is gradable — print the `grade:` hint (with the explicit task-id).
|
|
@@ -641,13 +858,61 @@ run_clean() {
|
|
|
641
858
|
"${cmd[@]}"
|
|
642
859
|
}
|
|
643
860
|
|
|
861
|
+
# ── front-load a filtered, capped diff into the review instruction ──────────
|
|
862
|
+
# Issue #220a: print a diffstat + filtered diff body so the model does not waste
|
|
863
|
+
# turns running `git diff` itself. Lockfile/vendored noise is excluded; the body
|
|
864
|
+
# is capped at ${COLLEAGUE_MAX_OUTPUT_CHARS:-100000} characters.
|
|
865
|
+
front_load_review_diff() {
|
|
866
|
+
local cap="${COLLEAGUE_MAX_OUTPUT_CHARS:-100000}"
|
|
867
|
+
printf '%s\n' "--- DIFF UNDER REVIEW (filtered + capped; read specific files for more) ---"
|
|
868
|
+
git -C "$REPO" diff "$BASE"...HEAD --stat
|
|
869
|
+
printf '\n'
|
|
870
|
+
local diff_body
|
|
871
|
+
# #324: bound the buffering itself, not just the printed output — `head -c`
|
|
872
|
+
# caps what the substitution ever holds (cap+1 bytes, just enough to detect
|
|
873
|
+
# truncation) and SIGPIPEs git early on a pathological diff, instead of
|
|
874
|
+
# materializing the full diff in memory before the length check. `|| true`
|
|
875
|
+
# also absorbs the SIGPIPE exit under `set -o pipefail`.
|
|
876
|
+
diff_body="$(git -C "$REPO" diff "$BASE"...HEAD -- . ':(exclude)*.lock' ':(exclude)**/*.lock' ':(exclude)package-lock.json' ':(exclude)**/package-lock.json' ':(exclude)*.min.js' ':(exclude)**/*.min.js' 2>/dev/null | head -c "$((cap + 1))" || true)"
|
|
877
|
+
if [[ "${#diff_body}" -gt "$cap" ]]; then
|
|
878
|
+
printf '%s\n' "${diff_body:0:$cap}"
|
|
879
|
+
printf '%s\n' "[... diff body truncated at ${cap} chars; read specific files for the rest ...]"
|
|
880
|
+
else
|
|
881
|
+
printf '%s\n' "$diff_body"
|
|
882
|
+
fi
|
|
883
|
+
}
|
|
884
|
+
|
|
644
885
|
# ── piloting verbs: thin passthroughs to the `colleague flight` noun ─────────
|
|
645
886
|
_flight_json_flag() { [[ "$JSON_OUT" -eq 1 ]] && printf -- '--json'; }
|
|
646
887
|
|
|
888
|
+
# ── resume verb: pick a cut run back up from its artifact ───────────────────
|
|
889
|
+
# `colleague work --continue <id|last>` resumes a timed-out / SIGTERM'd /
|
|
890
|
+
# budget-exhausted run from its persisted artifact (continuation lineage lands on
|
|
891
|
+
# TaskResult.continued_from). The wrapper adds nothing but the shared flags and
|
|
892
|
+
# the effort/role env already exported above. `--detach` runs it under
|
|
893
|
+
# setsid/nohup — NOT `colleague --background`, which drops the continue id
|
|
894
|
+
# (colleague#418) — and returns at once; the log names the new flight id.
|
|
895
|
+
run_resume() {
|
|
896
|
+
local fid="${ARG%% *}"
|
|
897
|
+
[[ -z "$fid" ]] && { echo "error: resume needs a task-id (or 'last')" >&2; exit 1; }
|
|
898
|
+
if [[ "$DETACH" -eq 1 ]]; then
|
|
899
|
+
local log="$REPO/.colleague/resume-$fid.log"
|
|
900
|
+
mkdir -p "$REPO/.colleague"
|
|
901
|
+
setsid nohup "${COLLEAGUE[@]}" work --continue "$fid" --repo "$REPO" --no-pr "${COMMON_FLAGS[@]}" \
|
|
902
|
+
> "$log" 2>&1 < /dev/null &
|
|
903
|
+
echo "resume: detached (pid $!) — log: $log" >&2
|
|
904
|
+
echo "hint: the new flight id appears in the log as 'flight: <id>'; then ask-colleague monitor <id>" >&2
|
|
905
|
+
return 0
|
|
906
|
+
fi
|
|
907
|
+
local out rc=0
|
|
908
|
+
out="$("${COLLEAGUE[@]}" work --continue "$fid" --repo "$REPO" --no-pr "${COMMON_FLAGS[@]}")" || rc=$?
|
|
909
|
+
printf '%s' "$out" | print_result "" "1" "$rc"
|
|
910
|
+
}
|
|
911
|
+
|
|
647
912
|
run_monitor() {
|
|
648
913
|
local fid="${ARG%% *}"
|
|
649
914
|
[[ -z "$fid" ]] && { echo "error: monitor needs a flight task-id" >&2; exit 1; }
|
|
650
|
-
"${COLLEAGUE[@]}" flight status "$fid" --repo "$REPO" $(_flight_json_flag)
|
|
915
|
+
"${COLLEAGUE[@]}" flight status "$fid" --repo "$REPO" --follow $(_flight_json_flag)
|
|
651
916
|
}
|
|
652
917
|
|
|
653
918
|
run_stop() {
|
|
@@ -665,11 +930,12 @@ run_guide() {
|
|
|
665
930
|
|
|
666
931
|
case "$VERB" in
|
|
667
932
|
explore) run_readonly "$(render_prompt explore)" ;;
|
|
668
|
-
review) run_readonly "$(render_prompt review)" ;;
|
|
933
|
+
review) run_readonly "$(render_prompt review)"$'\n\n'"$(front_load_review_diff)" ;;
|
|
669
934
|
write) run_write "$(render_prompt write)" ;;
|
|
670
935
|
feedback) run_feedback "$ARG" ;;
|
|
671
936
|
clean) run_clean ;;
|
|
672
937
|
monitor) run_monitor ;;
|
|
673
938
|
guide) run_guide ;;
|
|
674
939
|
stop) run_stop ;;
|
|
940
|
+
resume) run_resume ;;
|
|
675
941
|
esac
|
|
@@ -5,6 +5,31 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
Format follows [Keep a Changelog](https://keepachangelog.com/). This project
|
|
6
6
|
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.7.0] - 2026-08-24
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`ask-colleague resume <task-id|last> [--detach]`** — pick a cut /
|
|
13
|
+
timed-out / SIGTERM'd run back up from its persisted artifact, continuing
|
|
14
|
+
on the original `colleague/<id>` work branch. `--detach` runs it under
|
|
15
|
+
`setsid`/`nohup` and returns at once.
|
|
16
|
+
- **Per-seat thinking effort** for `ask-colleague` (colleague#416) —
|
|
17
|
+
`--effort RUNG` (acting seat), `--seat-effort S=R` (any seat),
|
|
18
|
+
`--role NAME`. `off` for small well-specified briefs, `xhigh` for
|
|
19
|
+
open-ended judgement, `default` as the kill-switch.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- **`ask-colleague` re-vendored byte-verbatim from `agentculture/colleague`
|
|
24
|
+
@ 1.63.0** — all five files (`SKILL.md`, `scripts/ask-colleague.sh`,
|
|
25
|
+
`prompts/{explore,review,write}.md`) match
|
|
26
|
+
`diff -r ../colleague/.claude/skills/ask-colleague`.
|
|
27
|
+
- **Default colleague model is now `unsloth/Qwen3.8-27B-NVFP4`** (was the
|
|
28
|
+
Qwen3.6 pin) — the lobes gateway on `:8001` no longer serves 3.6, so the
|
|
29
|
+
old default only worked via colleague's auto-refresh warning path.
|
|
30
|
+
- `ask-colleague review` front-loads a filtered, capped diff into the review
|
|
31
|
+
instruction so the model does not spend turns running `git diff` itself.
|
|
32
|
+
|
|
8
33
|
## [0.6.1] - 2026-07-20
|
|
9
34
|
|
|
10
35
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: workledger-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Tracks work in a ledger so agents can prove what they did. An agent records its work as append-only ledger entries, hands the ledger down to subagents, and gets it back with their entries folded in, so the whole tree of work and its results stays traceable and checkable.
|
|
5
5
|
Project-URL: Homepage, https://github.com/agentculture/workledger-cli
|
|
6
6
|
Project-URL: Issues, https://github.com/agentculture/workledger-cli/issues
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "workledger-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.0"
|
|
4
4
|
description = "Tracks work in a ledger so agents can prove what they did. An agent records its work as append-only ledger entries, hands the ledger down to subagents, and gets it back with their entries folded in, so the whole tree of work and its results stays traceable and checkable."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -154,37 +154,6 @@ wheels = [
|
|
|
154
154
|
{ url = "https://files.pythonhosted.org/packages/61/e8/cb8e80d6f9f55b99588625062822bf946cf03ed06315df4bd8397f5632a1/coverage-7.14.0-py3-none-any.whl", hash = "sha256:8de5b61163aee3d05c8a2beab6f47913df7981dad1baf82c414d99158c286ab1", size = 211764, upload-time = "2026-05-10T18:02:29.538Z" },
|
|
155
155
|
]
|
|
156
156
|
|
|
157
|
-
[[package]]
|
|
158
|
-
name = "workledger-cli"
|
|
159
|
-
version = "0.6.1"
|
|
160
|
-
source = { editable = "." }
|
|
161
|
-
|
|
162
|
-
[package.dev-dependencies]
|
|
163
|
-
dev = [
|
|
164
|
-
{ name = "bandit" },
|
|
165
|
-
{ name = "black" },
|
|
166
|
-
{ name = "flake8" },
|
|
167
|
-
{ name = "isort" },
|
|
168
|
-
{ name = "pytest" },
|
|
169
|
-
{ name = "pytest-cov" },
|
|
170
|
-
{ name = "pytest-xdist" },
|
|
171
|
-
{ name = "teken" },
|
|
172
|
-
]
|
|
173
|
-
|
|
174
|
-
[package.metadata]
|
|
175
|
-
|
|
176
|
-
[package.metadata.requires-dev]
|
|
177
|
-
dev = [
|
|
178
|
-
{ name = "bandit", specifier = ">=1.7.5" },
|
|
179
|
-
{ name = "black", specifier = ">=23.7.0" },
|
|
180
|
-
{ name = "flake8", specifier = ">=6.1" },
|
|
181
|
-
{ name = "isort", specifier = ">=5.12.0" },
|
|
182
|
-
{ name = "pytest", specifier = ">=8.0" },
|
|
183
|
-
{ name = "pytest-cov", specifier = ">=4.1" },
|
|
184
|
-
{ name = "pytest-xdist", specifier = ">=3.0" },
|
|
185
|
-
{ name = "teken", specifier = ">=0.8" },
|
|
186
|
-
]
|
|
187
|
-
|
|
188
157
|
[[package]]
|
|
189
158
|
name = "execnet"
|
|
190
159
|
version = "2.1.2"
|
|
@@ -476,3 +445,34 @@ sdist = { url = "https://files.pythonhosted.org/packages/25/95/3c3eff8e550c1347c
|
|
|
476
445
|
wheels = [
|
|
477
446
|
{ url = "https://files.pythonhosted.org/packages/00/2c/ca005d32831d883b10215a1ea31c32197a3a410f6d4ea3516b3d3c6a1183/teken-0.8.0-py3-none-any.whl", hash = "sha256:385a529df5a76adfff56ba5ae191a1bf8a5573f3698da4cc5bf7a2b5ca7cc311", size = 73189, upload-time = "2026-05-22T19:47:53.959Z" },
|
|
478
447
|
]
|
|
448
|
+
|
|
449
|
+
[[package]]
|
|
450
|
+
name = "workledger-cli"
|
|
451
|
+
version = "0.7.0"
|
|
452
|
+
source = { editable = "." }
|
|
453
|
+
|
|
454
|
+
[package.dev-dependencies]
|
|
455
|
+
dev = [
|
|
456
|
+
{ name = "bandit" },
|
|
457
|
+
{ name = "black" },
|
|
458
|
+
{ name = "flake8" },
|
|
459
|
+
{ name = "isort" },
|
|
460
|
+
{ name = "pytest" },
|
|
461
|
+
{ name = "pytest-cov" },
|
|
462
|
+
{ name = "pytest-xdist" },
|
|
463
|
+
{ name = "teken" },
|
|
464
|
+
]
|
|
465
|
+
|
|
466
|
+
[package.metadata]
|
|
467
|
+
|
|
468
|
+
[package.metadata.requires-dev]
|
|
469
|
+
dev = [
|
|
470
|
+
{ name = "bandit", specifier = ">=1.7.5" },
|
|
471
|
+
{ name = "black", specifier = ">=23.7.0" },
|
|
472
|
+
{ name = "flake8", specifier = ">=6.1" },
|
|
473
|
+
{ name = "isort", specifier = ">=5.12.0" },
|
|
474
|
+
{ name = "pytest", specifier = ">=8.0" },
|
|
475
|
+
{ name = "pytest-cov", specifier = ">=4.1" },
|
|
476
|
+
{ name = "pytest-xdist", specifier = ">=3.0" },
|
|
477
|
+
{ name = "teken", specifier = ">=0.8" },
|
|
478
|
+
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/cicd/scripts/portability-lint.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/communicate/scripts/fetch-issues.sh
RENAMED
|
File without changes
|
{workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/communicate/scripts/mesh-message.sh
RENAMED
|
File without changes
|
{workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/communicate/scripts/post-comment.sh
RENAMED
|
File without changes
|
{workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/communicate/scripts/post-issue.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/doc-test-alignment/scripts/check.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{workledger_cli-0.6.1 → workledger_cli-0.7.0}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|