rollout-cli 0.5.0__tar.gz → 0.5.1__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.
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/ask-colleague/SKILL.md +13 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/ask-colleague/scripts/ask-colleague.sh +46 -4
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/CHANGELOG.md +11 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/PKG-INFO +1 -1
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/docs/skill-sources.md +1 -1
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/pyproject.toml +1 -1
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/ask-colleague-revendor/README.md +1 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/ask-colleague-revendor/files/SKILL.md.tmpl +13 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/ask-colleague-revendor/files/scripts/ask-colleague.sh +46 -4
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/ask-colleague-revendor/manifest.toml +8 -6
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/cli/_commands/apply.py +5 -1
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/core/bump.py +17 -5
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/sonar-project.properties +11 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_bump.py +13 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/uv.lock +1 -1
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/agent-config/SKILL.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/agent-config/data/backend-fingerprints.yaml +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/agent-config/scripts/show.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/ask-colleague/prompts/explore.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/ask-colleague/prompts/review.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/ask-colleague/prompts/write.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/assign-to-workforce/SKILL.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/cicd/SKILL.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/cicd/scripts/_resolve-nick.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/cicd/scripts/portability-lint.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/cicd/scripts/pr-reply.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/cicd/scripts/pr-status.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/cicd/scripts/workflow.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/communicate/SKILL.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/communicate/scripts/templates/skill-new-brief.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/communicate/scripts/templates/skill-update-brief.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/mass-update/SKILL.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/mass-update/scripts/mass-update.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/pypi-maintainer/SKILL.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/pypi-maintainer/scripts/switch-source.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/run-tests/SKILL.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/sonarclaude/SKILL.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/spec-to-plan/SKILL.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/think/SKILL.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/think/scripts/think.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/version-bump/SKILL.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/version-bump/scripts/bump.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills.local.yaml.example +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.devague/frames/mass-update-now-clones-each-target-repo-into-a-git.json +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.devague/frames/rollout-cli-ships-rollout-define-an-org-wide-chang.json +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.devague/plans/mass-update-now-clones-each-target-repo-into-a-git.json +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.devague/plans/rollout-cli-ships-rollout-define-an-org-wide-chang.json +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.flake8 +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.github/workflows/publish.yml +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.github/workflows/tests.yml +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.gitignore +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/.markdownlint-cli2.yaml +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/AGENTS.colleague.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/CLAUDE.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/LICENSE +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/README.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/culture.yaml +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/docs/plans/2026-06-06-rollout-cli-ships-rollout-define-an-org-wide-chang.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/docs/plans/2026-06-12-mass-update-now-clones-each-target-repo-into-a-git.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/docs/specs/2026-06-06-rollout-cli-ships-rollout-define-an-org-wide-chang.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/docs/specs/2026-06-12-mass-update-now-clones-each-target-repo-into-a-git.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/apache-relicense/apply.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/apache-relicense/check.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/apache-relicense/files/LICENSE +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/apache-relicense/manifest.toml +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/ask-colleague-revendor/apply.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/ask-colleague-revendor/check.sh +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/ask-colleague-revendor/files/prompts/explore.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/ask-colleague-revendor/files/prompts/review.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/ask-colleague-revendor/files/prompts/write.md +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/__init__.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/__main__.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/cli/__init__.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/cli/_commands/__init__.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/cli/_commands/cli.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/cli/_commands/doctor.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/cli/_commands/explain.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/cli/_commands/learn.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/cli/_commands/overview.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/cli/_commands/plan.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/cli/_commands/whoami.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/cli/_errors.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/cli/_output.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/core/__init__.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/core/devex_pr.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/core/gitops.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/core/orchestrate.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/core/preflight.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/core/recipe.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/core/report.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/core/targets.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/explain/__init__.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/rollout/explain/catalog.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/__init__.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_apache_relicense.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_apply_cmd.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_cli.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_cli_introspection.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_cli_wiring.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_devex_pr.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_e2e_apache_relicense.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_explain_catalog.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_gitops.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_mass_update.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_orchestrate.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_plan_cmd.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_preflight.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_recipe.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_report.py +0 -0
- {rollout_cli-0.5.0 → rollout_cli-0.5.1}/tests/test_targets.py +0 -0
|
@@ -10,6 +10,7 @@ description: >
|
|
|
10
10
|
hands off a small implementation, `ask-colleague feedback` grades a finished
|
|
11
11
|
work item (the ROI loop), and `ask-colleague clean` reaps stale/corrupt
|
|
12
12
|
`colleague/*` branches a crashed run left behind (which can break `git fetch`).
|
|
13
|
+
Pilot a running work item with `monitor`/`guide`/`stop`.
|
|
13
14
|
Reach for it REFLEXIVELY, the way you'd lean over to the
|
|
14
15
|
teammate at the next desk — not only when asked: before you present or open a PR
|
|
15
16
|
on a non-trivial committed diff, run `review` for a diverse second opinion; for a
|
|
@@ -154,6 +155,18 @@ keeping stdout valid JSON for a machine consumer while diagnostics stay on stder
|
|
|
154
155
|
(or `colleague clean`) to reap it — start with `--dry-run` to see what it would
|
|
155
156
|
remove. It only ever touches `colleague/*` refs and `.colleague/` artifacts.
|
|
156
157
|
|
|
158
|
+
## Piloting a flight
|
|
159
|
+
|
|
160
|
+
Dispatch a drive with `--watch` (on `explore`, `review`, or `write`) to make the
|
|
161
|
+
work item watchable. While it runs you can:
|
|
162
|
+
|
|
163
|
+
- **`ask-colleague monitor <task-id>`** — watch the flight's live feed
|
|
164
|
+
- **`ask-colleague guide <task-id> "<message>"`** — send mid-flight guidance
|
|
165
|
+
- **`ask-colleague stop <task-id>`** — cooperatively ask the flight to stop
|
|
166
|
+
|
|
167
|
+
Control is applied at the running loop's next turn boundary, so guidance and
|
|
168
|
+
stop requests take effect on the next iteration rather than interrupting mid-step.
|
|
169
|
+
|
|
157
170
|
## Hard rules (do not violate)
|
|
158
171
|
|
|
159
172
|
- **explore and review are read-only.** They run in a throwaway `git worktree`
|
{rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/ask-colleague/scripts/ask-colleague.sh
RENAMED
|
@@ -84,6 +84,9 @@ Usage:
|
|
|
84
84
|
ask-colleague feedback <id|last> [--rating N] Grade a past drive (ROI loop); with --rating records, without shows
|
|
85
85
|
ask-colleague feedback list List every recorded drive by request + grade (find one by its request)
|
|
86
86
|
ask-colleague clean [--dry-run] Reap stale/corrupt colleague/* branches + orphaned .colleague/ artifacts (#162)
|
|
87
|
+
ask-colleague monitor <task-id> Watch a running flight's live feed
|
|
88
|
+
ask-colleague guide <task-id> "<msg>" Send mid-flight guidance to a running flight
|
|
89
|
+
ask-colleague stop <task-id> Ask a running flight to stop (cooperative)
|
|
87
90
|
|
|
88
91
|
Options:
|
|
89
92
|
--repo PATH Target repo (default: .)
|
|
@@ -100,6 +103,7 @@ Options:
|
|
|
100
103
|
--rating N (feedback) record a 1-5 quality rating for the drive
|
|
101
104
|
--notes "..." (feedback) free-text notes to store with the rating
|
|
102
105
|
--by NAME (feedback) who is grading (default: colleague's resolved identity)
|
|
106
|
+
--watch (explore/review/write) arm a flight so you can monitor/guide/stop it
|
|
103
107
|
--json Machine-readable output: stdout carries only the result JSON,
|
|
104
108
|
every diagnostic/digest line goes to stderr (any verb)
|
|
105
109
|
|
|
@@ -119,11 +123,11 @@ EOF
|
|
|
119
123
|
# ── parse the verb ──────────────────────────────────────────────────────────
|
|
120
124
|
VERB="${1:-}"
|
|
121
125
|
case "$VERB" in
|
|
122
|
-
explore | review | write | feedback | clean) shift ;;
|
|
126
|
+
explore | review | write | feedback | clean | monitor | guide | stop) shift ;;
|
|
123
127
|
-h | --help) usage; exit 0 ;;
|
|
124
128
|
"") usage >&2; exit 1 ;; # missing arg -> user-input error (#161)
|
|
125
129
|
*)
|
|
126
|
-
echo "error: unknown verb '$VERB' (expected explore|review|write|feedback|clean)" >&2
|
|
130
|
+
echo "error: unknown verb '$VERB' (expected explore|review|write|feedback|clean|monitor|guide|stop)" >&2
|
|
127
131
|
echo "hint: run 'ask-colleague --help'" >&2
|
|
128
132
|
exit 1 # bad verb -> user-input error (#161)
|
|
129
133
|
;;
|
|
@@ -173,6 +177,7 @@ ALLOW_DIRTY=0
|
|
|
173
177
|
APPLY=0
|
|
174
178
|
OPEN_PR=0
|
|
175
179
|
DRY_RUN=0
|
|
180
|
+
WATCH=0
|
|
176
181
|
RATING=""
|
|
177
182
|
NOTES=""
|
|
178
183
|
BY=""
|
|
@@ -189,6 +194,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
189
194
|
--max-steps) need_value "$#" "$1"; MAX_STEPS="$2"; shift 2 ;;
|
|
190
195
|
--timeout) need_value "$#" "$1"; TIMEOUT="$2"; shift 2 ;;
|
|
191
196
|
--apply) APPLY=1; shift ;;
|
|
197
|
+
--watch) WATCH=1; shift ;;
|
|
192
198
|
--allow-dirty) ALLOW_DIRTY=1; shift ;;
|
|
193
199
|
--pr) OPEN_PR=1; shift ;;
|
|
194
200
|
--dry-run) DRY_RUN=1; shift ;;
|
|
@@ -211,6 +217,7 @@ done
|
|
|
211
217
|
# throwaway worktree, so it needs no mktemp either.
|
|
212
218
|
case "$VERB" in
|
|
213
219
|
feedback | clean) require_tools git ;;
|
|
220
|
+
monitor | guide | stop) : ;;
|
|
214
221
|
write)
|
|
215
222
|
if [[ "$APPLY" -eq 1 || "$OPEN_PR" -eq 1 ]]; then
|
|
216
223
|
require_tools git python3
|
|
@@ -235,8 +242,15 @@ REPO="$(cd "$REPO" && pwd)"
|
|
|
235
242
|
# it must at least be a real git work tree. Fail fast with a clear message instead
|
|
236
243
|
# of an opaque mid-drive error (read-only verbs add a worktree, write commits a
|
|
237
244
|
# drive branch, clean reaps colleague/* refs).
|
|
238
|
-
|
|
239
|
-
|
|
245
|
+
# The pilot verbs (monitor/guide/stop) are pure .colleague/flight/ file I/O — they
|
|
246
|
+
# need no git work tree, so they are exempt from this fail-fast guard.
|
|
247
|
+
case "$VERB" in
|
|
248
|
+
monitor | guide | stop) : ;;
|
|
249
|
+
*)
|
|
250
|
+
git -C "$REPO" rev-parse --is-inside-work-tree >/dev/null 2>&1 \
|
|
251
|
+
|| { echo "error: --repo is not a git repository: $REPO" >&2; exit 1; }
|
|
252
|
+
;;
|
|
253
|
+
esac
|
|
240
254
|
|
|
241
255
|
# review interpolates --base into the LLM instruction ("git diff $BASE...HEAD"),
|
|
242
256
|
# so reject a value that is not a real commit/ref before it is rendered into the
|
|
@@ -252,6 +266,9 @@ resolve_colleague || exit 2
|
|
|
252
266
|
# A local model can be slow on a growing context, so default generously.
|
|
253
267
|
export COLLEAGUE_TIMEOUT="$TIMEOUT"
|
|
254
268
|
COMMON_FLAGS=(--engine "$ENGINE" --model "$MODEL" --base-url "$BASE_URL" --max-steps "$MAX_STEPS" --json)
|
|
269
|
+
# --watch arms a flight for EVERY drive verb (explore/review/write), so it lives on
|
|
270
|
+
# the shared flag list — not inside one verb's path — so monitor/guide/stop work.
|
|
271
|
+
[[ "${WATCH:-0}" -eq 1 ]] && COMMON_FLAGS+=(--watch)
|
|
255
272
|
|
|
256
273
|
# ── render an instruction from a prompt template ────────────────────────────
|
|
257
274
|
render_prompt() {
|
|
@@ -624,10 +641,35 @@ run_clean() {
|
|
|
624
641
|
"${cmd[@]}"
|
|
625
642
|
}
|
|
626
643
|
|
|
644
|
+
# ── piloting verbs: thin passthroughs to the `colleague flight` noun ─────────
|
|
645
|
+
_flight_json_flag() { [[ "$JSON_OUT" -eq 1 ]] && printf -- '--json'; }
|
|
646
|
+
|
|
647
|
+
run_monitor() {
|
|
648
|
+
local fid="${ARG%% *}"
|
|
649
|
+
[[ -z "$fid" ]] && { echo "error: monitor needs a flight task-id" >&2; exit 1; }
|
|
650
|
+
"${COLLEAGUE[@]}" flight status "$fid" --repo "$REPO" $(_flight_json_flag)
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
run_stop() {
|
|
654
|
+
local fid="${ARG%% *}"
|
|
655
|
+
[[ -z "$fid" ]] && { echo "error: stop needs a flight task-id" >&2; exit 1; }
|
|
656
|
+
"${COLLEAGUE[@]}" flight stop "$fid" --repo "$REPO" $(_flight_json_flag)
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
run_guide() {
|
|
660
|
+
local fid="${ARG%% *}"
|
|
661
|
+
local msg="${ARG#* }"
|
|
662
|
+
[[ -z "$fid" || "$msg" == "$fid" ]] && { echo "error: guide needs <task-id> <message>" >&2; exit 1; }
|
|
663
|
+
"${COLLEAGUE[@]}" flight guide "$fid" "$msg" --repo "$REPO" $(_flight_json_flag)
|
|
664
|
+
}
|
|
665
|
+
|
|
627
666
|
case "$VERB" in
|
|
628
667
|
explore) run_readonly "$(render_prompt explore)" ;;
|
|
629
668
|
review) run_readonly "$(render_prompt review)" ;;
|
|
630
669
|
write) run_write "$(render_prompt write)" ;;
|
|
631
670
|
feedback) run_feedback "$ARG" ;;
|
|
632
671
|
clean) run_clean ;;
|
|
672
|
+
monitor) run_monitor ;;
|
|
673
|
+
guide) run_guide ;;
|
|
674
|
+
stop) run_stop ;;
|
|
633
675
|
esac
|
|
@@ -5,6 +5,17 @@ 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.5.1] - 2026-06-18
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- ask-colleague: re-vendor the wrapper + recipe snapshot to the canonical colleague source (colleague 1.7.0) — adds the `colleague flight` pilot verbs `monitor` / `guide` / `stop` plus the `--watch` flag that arms a drive (explore/review/write) so it can be watched, guided mid-flight, and cooperatively stopped. Updates the bundled `SKILL.md`, the recipe `SKILL.md.tmpl` + wrapper snapshot, the manifest changelog text, and the `docs/skill-sources.md` provenance row (sync date → 2026-06-14). Adds discord-bot-cli to the ask-colleague-revendor consumer ledger.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- rollout apply: date the prepended changelog entry the day the change lands (`date.today()`) instead of the frozen `2026-06-06` placeholder the apply CLI never overrode.
|
|
17
|
+
- `rollout/core/bump.py` `prepend_changelog`: no longer emits consecutive blank lines (markdownlint MD012) when inserting before an existing entry — every cross-repo rollout target previously inherited a lint-failing CHANGELOG (caught on discord-bot-cli#6). Controls the blank lines at the insertion seams and guarantees a single trailing newline (MD047).
|
|
18
|
+
|
|
8
19
|
## [0.5.0] - 2026-06-13
|
|
9
20
|
|
|
10
21
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rollout-cli
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: Cross-repo propagation workflow built on refactor-cli — apply a transformation across many repos at once.
|
|
5
5
|
Project-URL: Homepage, https://github.com/agentculture/rollout-cli
|
|
6
6
|
Project-URL: Issues, https://github.com/agentculture/rollout-cli/issues
|
|
@@ -33,7 +33,7 @@ is load-bearing, even where guildmaster's upstream copy omits it.
|
|
|
33
33
|
| `think` | `../guildmaster/.claude/skills/think/` | **devague** (re-broadcast via guildmaster) | idea→spec leg of the devague workflow chain. Verbatim (already carried `type: command` at guildmaster). Origin/broadcast prose left verbatim. | 2026-05-26 (guildmaster 0.6.0) |
|
|
34
34
|
| `spec-to-plan` | `../guildmaster/.claude/skills/spec-to-plan/` | **devague** (re-broadcast via guildmaster) | spec→plan leg of the devague workflow chain. Verbatim (already carried `type: command`). | 2026-05-26 (guildmaster 0.6.0) |
|
|
35
35
|
| `assign-to-workforce` | `../guildmaster/.claude/skills/assign-to-workforce/` | **devague** (re-broadcast via guildmaster) | plan→parallel-implementation leg of the devague workflow chain. Verbatim (already carried `type: command`). | 2026-05-26 (guildmaster 0.6.0) |
|
|
36
|
-
| `ask-colleague` | `../colleague/.claude/skills/ask-colleague/` | **colleague** (renamed from convertible; vendored directly — guildmaster re-broadcast pending) | The first-party front door to the `colleague` CLI: hand a scoped task to a *different* engine/mind via `explore` / `review` / `write`, and grade a finished work item via `feedback` (the ROI loop). `explore`/`review` run isolated in a throwaway `git worktree`; `write` **previews by default** (throwaway worktree, no side effects) and refuses a dirty tree only when applying (`--apply` / `--pr`). Verbatim except one consumer-identifying clause in the Provenance paragraph (`colleague vendors from guildmaster` → `rollout-cli vendors from guildmaster`); already carried `type: command`. Optional runtime dep: **`colleague`** on PATH. | 2026-06-
|
|
36
|
+
| `ask-colleague` | `../colleague/.claude/skills/ask-colleague/` | **colleague** (renamed from convertible; vendored directly — guildmaster re-broadcast pending) | The first-party front door to the `colleague` CLI: hand a scoped task to a *different* engine/mind via `explore` / `review` / `write`, and grade a finished work item via `feedback` (the ROI loop); pilot a running drive with `monitor` / `guide` / `stop` (arm it with `--watch`). `explore`/`review` run isolated in a throwaway `git worktree`; `write` **previews by default** (throwaway worktree, no side effects) and refuses a dirty tree only when applying (`--apply` / `--pr`). Verbatim except one consumer-identifying clause in the Provenance paragraph (`colleague vendors from guildmaster` → `rollout-cli vendors from guildmaster`); already carried `type: command`. Optional runtime dep: **`colleague`** on PATH. | 2026-06-14 (colleague 1.7.0, direct) |
|
|
37
37
|
|
|
38
38
|
## Re-sync procedure
|
|
39
39
|
|
|
@@ -44,6 +44,7 @@ Origin: **colleague** (`agentculture/colleague`,
|
|
|
44
44
|
| rollout-cli | `agentculture/rollout-cli` | re-vendor wrapper | this repo ("self"); carries `which rollout-cli …` token |
|
|
45
45
|
| dgx-spark-cli | `agentculture/dgx-spark-cli` | fresh add | skill was absent |
|
|
46
46
|
| reterminal-cli | `agentculture/reterminal-cli` | re-vendor wrapper | merged at pre-#183 |
|
|
47
|
+
| discord-bot-cli | `agentculture/discord-bot-cli` | fresh add | skill was absent; carries `which discord-bot-cli …` token; landed at flight-verbs snapshot (discord-bot-cli#6) |
|
|
47
48
|
|
|
48
49
|
Keep this table current when a consumer is added or dropped.
|
|
49
50
|
|
|
@@ -10,6 +10,7 @@ description: >
|
|
|
10
10
|
hands off a small implementation, `ask-colleague feedback` grades a finished
|
|
11
11
|
work item (the ROI loop), and `ask-colleague clean` reaps stale/corrupt
|
|
12
12
|
`colleague/*` branches a crashed run left behind (which can break `git fetch`).
|
|
13
|
+
Pilot a running work item with `monitor`/`guide`/`stop`.
|
|
13
14
|
Reach for it REFLEXIVELY, the way you'd lean over to the
|
|
14
15
|
teammate at the next desk — not only when asked: before you present or open a PR
|
|
15
16
|
on a non-trivial committed diff, run `review` for a diverse second opinion; for a
|
|
@@ -154,6 +155,18 @@ keeping stdout valid JSON for a machine consumer while diagnostics stay on stder
|
|
|
154
155
|
(or `colleague clean`) to reap it — start with `--dry-run` to see what it would
|
|
155
156
|
remove. It only ever touches `colleague/*` refs and `.colleague/` artifacts.
|
|
156
157
|
|
|
158
|
+
## Piloting a flight
|
|
159
|
+
|
|
160
|
+
Dispatch a drive with `--watch` (on `explore`, `review`, or `write`) to make the
|
|
161
|
+
work item watchable. While it runs you can:
|
|
162
|
+
|
|
163
|
+
- **`ask-colleague monitor <task-id>`** — watch the flight's live feed
|
|
164
|
+
- **`ask-colleague guide <task-id> "<message>"`** — send mid-flight guidance
|
|
165
|
+
- **`ask-colleague stop <task-id>`** — cooperatively ask the flight to stop
|
|
166
|
+
|
|
167
|
+
Control is applied at the running loop's next turn boundary, so guidance and
|
|
168
|
+
stop requests take effect on the next iteration rather than interrupting mid-step.
|
|
169
|
+
|
|
157
170
|
## Hard rules (do not violate)
|
|
158
171
|
|
|
159
172
|
- **explore and review are read-only.** They run in a throwaway `git worktree`
|
|
@@ -84,6 +84,9 @@ Usage:
|
|
|
84
84
|
ask-colleague feedback <id|last> [--rating N] Grade a past drive (ROI loop); with --rating records, without shows
|
|
85
85
|
ask-colleague feedback list List every recorded drive by request + grade (find one by its request)
|
|
86
86
|
ask-colleague clean [--dry-run] Reap stale/corrupt colleague/* branches + orphaned .colleague/ artifacts (#162)
|
|
87
|
+
ask-colleague monitor <task-id> Watch a running flight's live feed
|
|
88
|
+
ask-colleague guide <task-id> "<msg>" Send mid-flight guidance to a running flight
|
|
89
|
+
ask-colleague stop <task-id> Ask a running flight to stop (cooperative)
|
|
87
90
|
|
|
88
91
|
Options:
|
|
89
92
|
--repo PATH Target repo (default: .)
|
|
@@ -100,6 +103,7 @@ Options:
|
|
|
100
103
|
--rating N (feedback) record a 1-5 quality rating for the drive
|
|
101
104
|
--notes "..." (feedback) free-text notes to store with the rating
|
|
102
105
|
--by NAME (feedback) who is grading (default: colleague's resolved identity)
|
|
106
|
+
--watch (explore/review/write) arm a flight so you can monitor/guide/stop it
|
|
103
107
|
--json Machine-readable output: stdout carries only the result JSON,
|
|
104
108
|
every diagnostic/digest line goes to stderr (any verb)
|
|
105
109
|
|
|
@@ -119,11 +123,11 @@ EOF
|
|
|
119
123
|
# ── parse the verb ──────────────────────────────────────────────────────────
|
|
120
124
|
VERB="${1:-}"
|
|
121
125
|
case "$VERB" in
|
|
122
|
-
explore | review | write | feedback | clean) shift ;;
|
|
126
|
+
explore | review | write | feedback | clean | monitor | guide | stop) shift ;;
|
|
123
127
|
-h | --help) usage; exit 0 ;;
|
|
124
128
|
"") usage >&2; exit 1 ;; # missing arg -> user-input error (#161)
|
|
125
129
|
*)
|
|
126
|
-
echo "error: unknown verb '$VERB' (expected explore|review|write|feedback|clean)" >&2
|
|
130
|
+
echo "error: unknown verb '$VERB' (expected explore|review|write|feedback|clean|monitor|guide|stop)" >&2
|
|
127
131
|
echo "hint: run 'ask-colleague --help'" >&2
|
|
128
132
|
exit 1 # bad verb -> user-input error (#161)
|
|
129
133
|
;;
|
|
@@ -173,6 +177,7 @@ ALLOW_DIRTY=0
|
|
|
173
177
|
APPLY=0
|
|
174
178
|
OPEN_PR=0
|
|
175
179
|
DRY_RUN=0
|
|
180
|
+
WATCH=0
|
|
176
181
|
RATING=""
|
|
177
182
|
NOTES=""
|
|
178
183
|
BY=""
|
|
@@ -189,6 +194,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
189
194
|
--max-steps) need_value "$#" "$1"; MAX_STEPS="$2"; shift 2 ;;
|
|
190
195
|
--timeout) need_value "$#" "$1"; TIMEOUT="$2"; shift 2 ;;
|
|
191
196
|
--apply) APPLY=1; shift ;;
|
|
197
|
+
--watch) WATCH=1; shift ;;
|
|
192
198
|
--allow-dirty) ALLOW_DIRTY=1; shift ;;
|
|
193
199
|
--pr) OPEN_PR=1; shift ;;
|
|
194
200
|
--dry-run) DRY_RUN=1; shift ;;
|
|
@@ -211,6 +217,7 @@ done
|
|
|
211
217
|
# throwaway worktree, so it needs no mktemp either.
|
|
212
218
|
case "$VERB" in
|
|
213
219
|
feedback | clean) require_tools git ;;
|
|
220
|
+
monitor | guide | stop) : ;;
|
|
214
221
|
write)
|
|
215
222
|
if [[ "$APPLY" -eq 1 || "$OPEN_PR" -eq 1 ]]; then
|
|
216
223
|
require_tools git python3
|
|
@@ -235,8 +242,15 @@ REPO="$(cd "$REPO" && pwd)"
|
|
|
235
242
|
# it must at least be a real git work tree. Fail fast with a clear message instead
|
|
236
243
|
# of an opaque mid-drive error (read-only verbs add a worktree, write commits a
|
|
237
244
|
# drive branch, clean reaps colleague/* refs).
|
|
238
|
-
|
|
239
|
-
|
|
245
|
+
# The pilot verbs (monitor/guide/stop) are pure .colleague/flight/ file I/O — they
|
|
246
|
+
# need no git work tree, so they are exempt from this fail-fast guard.
|
|
247
|
+
case "$VERB" in
|
|
248
|
+
monitor | guide | stop) : ;;
|
|
249
|
+
*)
|
|
250
|
+
git -C "$REPO" rev-parse --is-inside-work-tree >/dev/null 2>&1 \
|
|
251
|
+
|| { echo "error: --repo is not a git repository: $REPO" >&2; exit 1; }
|
|
252
|
+
;;
|
|
253
|
+
esac
|
|
240
254
|
|
|
241
255
|
# review interpolates --base into the LLM instruction ("git diff $BASE...HEAD"),
|
|
242
256
|
# so reject a value that is not a real commit/ref before it is rendered into the
|
|
@@ -252,6 +266,9 @@ resolve_colleague || exit 2
|
|
|
252
266
|
# A local model can be slow on a growing context, so default generously.
|
|
253
267
|
export COLLEAGUE_TIMEOUT="$TIMEOUT"
|
|
254
268
|
COMMON_FLAGS=(--engine "$ENGINE" --model "$MODEL" --base-url "$BASE_URL" --max-steps "$MAX_STEPS" --json)
|
|
269
|
+
# --watch arms a flight for EVERY drive verb (explore/review/write), so it lives on
|
|
270
|
+
# the shared flag list — not inside one verb's path — so monitor/guide/stop work.
|
|
271
|
+
[[ "${WATCH:-0}" -eq 1 ]] && COMMON_FLAGS+=(--watch)
|
|
255
272
|
|
|
256
273
|
# ── render an instruction from a prompt template ────────────────────────────
|
|
257
274
|
render_prompt() {
|
|
@@ -624,10 +641,35 @@ run_clean() {
|
|
|
624
641
|
"${cmd[@]}"
|
|
625
642
|
}
|
|
626
643
|
|
|
644
|
+
# ── piloting verbs: thin passthroughs to the `colleague flight` noun ─────────
|
|
645
|
+
_flight_json_flag() { [[ "$JSON_OUT" -eq 1 ]] && printf -- '--json'; }
|
|
646
|
+
|
|
647
|
+
run_monitor() {
|
|
648
|
+
local fid="${ARG%% *}"
|
|
649
|
+
[[ -z "$fid" ]] && { echo "error: monitor needs a flight task-id" >&2; exit 1; }
|
|
650
|
+
"${COLLEAGUE[@]}" flight status "$fid" --repo "$REPO" $(_flight_json_flag)
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
run_stop() {
|
|
654
|
+
local fid="${ARG%% *}"
|
|
655
|
+
[[ -z "$fid" ]] && { echo "error: stop needs a flight task-id" >&2; exit 1; }
|
|
656
|
+
"${COLLEAGUE[@]}" flight stop "$fid" --repo "$REPO" $(_flight_json_flag)
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
run_guide() {
|
|
660
|
+
local fid="${ARG%% *}"
|
|
661
|
+
local msg="${ARG#* }"
|
|
662
|
+
[[ -z "$fid" || "$msg" == "$fid" ]] && { echo "error: guide needs <task-id> <message>" >&2; exit 1; }
|
|
663
|
+
"${COLLEAGUE[@]}" flight guide "$fid" "$msg" --repo "$REPO" $(_flight_json_flag)
|
|
664
|
+
}
|
|
665
|
+
|
|
627
666
|
case "$VERB" in
|
|
628
667
|
explore) run_readonly "$(render_prompt explore)" ;;
|
|
629
668
|
review) run_readonly "$(render_prompt review)" ;;
|
|
630
669
|
write) run_write "$(render_prompt write)" ;;
|
|
631
670
|
feedback) run_feedback "$ARG" ;;
|
|
632
671
|
clean) run_clean ;;
|
|
672
|
+
monitor) run_monitor ;;
|
|
673
|
+
guide) run_guide ;;
|
|
674
|
+
stop) run_stop ;;
|
|
633
675
|
esac
|
|
@@ -15,12 +15,14 @@ changelog_text = """\
|
|
|
15
15
|
|
|
16
16
|
- **Re-vendored the `ask-colleague` skill wrapper from its canonical colleague
|
|
17
17
|
source** (`.claude/skills/ask-colleague/scripts/ask-colleague.sh`): the wrapper
|
|
18
|
-
now
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
now drives the `colleague flight` pilot verbs — `monitor` / `guide` / `stop`
|
|
19
|
+
plus the `--watch` flag that arms a drive (`explore` / `review` / `write`) so it
|
|
20
|
+
can be watched, guided mid-flight, and cooperatively stopped. This supersedes the
|
|
21
|
+
earlier colleague#186 snapshot (which predated flights). It keeps the `--json`
|
|
22
|
+
machine-readable output added then — stdout carries **only** the result JSON (the
|
|
23
|
+
drive verbs emit the normalized `TaskResult`; `feedback` / `clean` forward
|
|
24
|
+
`--json` to colleague) while every diagnostic/digest line goes to stderr. The
|
|
25
|
+
bundled `SKILL.md` template documents the new verbs/flag; an existing downstream
|
|
24
26
|
`SKILL.md` is left untouched (it carries a repo-specific provenance token and
|
|
25
27
|
may diverge). Where the skill was absent, it is added fresh (wrapper +
|
|
26
28
|
`SKILL.md` + prompts).
|
|
@@ -9,6 +9,7 @@ as "needs-attention"). Never force-apply or merge.
|
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
11
|
import argparse
|
|
12
|
+
import datetime
|
|
12
13
|
import pathlib
|
|
13
14
|
|
|
14
15
|
from rollout.cli._output import emit_result
|
|
@@ -53,13 +54,16 @@ def cmd_apply(args: argparse.Namespace) -> int:
|
|
|
53
54
|
return 0
|
|
54
55
|
|
|
55
56
|
# --- classify and apply ----------------------------------------------
|
|
57
|
+
# Date the changelog entry the day the change actually lands (not the
|
|
58
|
+
# apply_one frozen-default placeholder, which is only for hermetic tests).
|
|
59
|
+
today = datetime.date.today().isoformat()
|
|
56
60
|
report = Report()
|
|
57
61
|
for name in targets_list:
|
|
58
62
|
repo_path = pathlib.Path(base) / pathlib.Path(name).name
|
|
59
63
|
try:
|
|
60
64
|
status = preflight.classify(repo_path, recipe)
|
|
61
65
|
if status == preflight.Status.CLEAN:
|
|
62
|
-
row = orchestrate.apply_one(repo_path, recipe, repo_slug=name)
|
|
66
|
+
row = orchestrate.apply_one(repo_path, recipe, repo_slug=name, date=today)
|
|
63
67
|
report.add_row(name, row.status, row.pr_url)
|
|
64
68
|
else:
|
|
65
69
|
report.add_row(name, _STATUS_MAP[status])
|
|
@@ -103,16 +103,28 @@ def prepend_changelog(
|
|
|
103
103
|
if f"## [{version}]" in text:
|
|
104
104
|
return
|
|
105
105
|
|
|
106
|
-
# Build the new
|
|
107
|
-
|
|
106
|
+
# Build the new entry. Normalise the body and control the surrounding
|
|
107
|
+
# blank lines here (exactly one before and after) rather than inheriting
|
|
108
|
+
# the caller's / file's trailing whitespace — otherwise the junction with
|
|
109
|
+
# the intro or an existing entry yields consecutive blank lines, which
|
|
110
|
+
# markdownlint rejects (MD012/no-multiple-blanks).
|
|
111
|
+
body_clean = re.sub(r"\n{3,}", "\n\n", body.strip())
|
|
112
|
+
entry = f"## [{version}] - {date}\n\n{body_clean}\n"
|
|
108
113
|
|
|
109
114
|
# Find the first existing release entry (## [X.Y.Z] ...)
|
|
110
115
|
first_entry = _ENTRY_RE.search(text)
|
|
111
116
|
if first_entry:
|
|
112
|
-
# Insert just before the first existing entry
|
|
113
|
-
|
|
117
|
+
# Insert just before the first existing entry, with exactly one blank
|
|
118
|
+
# line separating the intro from the new entry and the new entry from
|
|
119
|
+
# the existing one.
|
|
120
|
+
prefix = text[: first_entry.start()].rstrip()
|
|
121
|
+
suffix = text[first_entry.start() :].lstrip("\n")
|
|
122
|
+
new_text = f"{prefix}\n\n{entry}\n{suffix}"
|
|
114
123
|
else:
|
|
115
124
|
# No existing entries — append after the intro.
|
|
116
|
-
new_text = text.rstrip()
|
|
125
|
+
new_text = f"{text.rstrip()}\n\n{entry}"
|
|
126
|
+
|
|
127
|
+
# Exactly one trailing newline (MD047).
|
|
128
|
+
new_text = new_text.rstrip("\n") + "\n"
|
|
117
129
|
|
|
118
130
|
path.write_text(new_text, encoding="utf-8")
|
|
@@ -16,6 +16,17 @@ sonar.python.version=3.12
|
|
|
16
16
|
# Don't analyze noise.
|
|
17
17
|
sonar.exclusions=**/__pycache__/**,**/.venv/**,uv.lock,.claude/skills/**
|
|
18
18
|
|
|
19
|
+
# False positive: pythonsecurity:S2083 (path injection) fires on
|
|
20
|
+
# prepend_changelog's `path.write_text` in rollout/core/bump.py because it traces
|
|
21
|
+
# the changelog path back to the `--repos` slug. That slug is sanitized at the
|
|
22
|
+
# boundary — apply.py derives the write dir as `<base>/<pathlib.Path(name).name>`,
|
|
23
|
+
# and `.name` strips any traversal — and the sole caller (orchestrate.apply_one)
|
|
24
|
+
# always passes `<repo_path>/CHANGELOG.md`. This is a local, operator-run devtool
|
|
25
|
+
# writing a CHANGELOG, not an attacker-facing surface. Ignore S2083 in bump.py.
|
|
26
|
+
sonar.issue.ignore.multicriteria=e1
|
|
27
|
+
sonar.issue.ignore.multicriteria.e1.ruleKey=pythonsecurity:S2083
|
|
28
|
+
sonar.issue.ignore.multicriteria.e1.resourceKey=**/bump.py
|
|
29
|
+
|
|
19
30
|
# Block CI on a failing quality gate. The scanner polls SonarCloud and exits
|
|
20
31
|
# non-zero on a red gate (coverage regression, new bugs/vulnerabilities). Only
|
|
21
32
|
# takes effect when the SonarCloud Scan step runs — that step is guarded by
|
|
@@ -152,6 +152,19 @@ def test_prepend_changelog_before_existing_entry(tmp_path: pathlib.Path) -> None
|
|
|
152
152
|
assert new_pos < old_pos
|
|
153
153
|
|
|
154
154
|
|
|
155
|
+
def test_prepend_changelog_no_consecutive_blank_lines(tmp_path: pathlib.Path) -> None:
|
|
156
|
+
"""Inserting never produces MD012 double blanks at the intro/entry junctions."""
|
|
157
|
+
existing = "## [0.1.0] - 2025-01-01\n\n### Added\n\n- old thing\n"
|
|
158
|
+
path = _write_changelog(tmp_path, existing=existing)
|
|
159
|
+
# A body padded with stray blank lines must still normalise cleanly.
|
|
160
|
+
prepend_changelog(path, "0.2.0", "2026-01-01", "\n### Changed\n\n\n- new thing\n\n")
|
|
161
|
+
content = path.read_text()
|
|
162
|
+
assert "\n\n\n" not in content, "markdownlint MD012: consecutive blank lines"
|
|
163
|
+
assert content.endswith("\n") and not content.endswith("\n\n")
|
|
164
|
+
assert content.index("## [0.2.0]") < content.index("## [0.1.0]")
|
|
165
|
+
assert "- new thing" in content
|
|
166
|
+
|
|
167
|
+
|
|
155
168
|
# ---------------------------------------------------------------------------
|
|
156
169
|
# prepend_changelog — idempotency
|
|
157
170
|
# ---------------------------------------------------------------------------
|
|
File without changes
|
{rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/agent-config/data/backend-fingerprints.yaml
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
|
{rollout_cli-0.5.0 → rollout_cli-0.5.1}/.claude/skills/pypi-maintainer/scripts/switch-source.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
|
{rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/ask-colleague-revendor/files/prompts/explore.md
RENAMED
|
File without changes
|
{rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/ask-colleague-revendor/files/prompts/review.md
RENAMED
|
File without changes
|
{rollout_cli-0.5.0 → rollout_cli-0.5.1}/recipes/ask-colleague-revendor/files/prompts/write.md
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|