From f50561ea7840b93df6c7baab815adb081a4d7c9d Mon Sep 17 00:00:00 2001 From: Paul O'Reilly Date: Fri, 11 Sep 2026 16:27:08 +1200 Subject: [PATCH] =?UTF-8?q?feat(mm-worktree-task):=20run=20from=20any=20pl?= =?UTF-8?q?anner-backed=20repo=20=E2=80=94=20cp=5Fcli=20dir=20+=20context?= =?UTF-8?q?=20resolution=20(--context,=20MM=5FWORKTREE=5FTASK=5FCP=5F*),?= =?UTF-8?q?=20empty-docs=20guard,=20tests=20+=20spec?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cp_cli lives in agent-runtimes; previously every planner call ran 'python3 -m lib.cp_cli' from the current repo with no --context, so the script only worked inside agent-runtimes. The context now resolves from ~/.cpconfig by matching project_id to the repo directory name. Verified live from hatchmate (item + parent + documents fetched via the hatchmate context). Claude-Session: https://claude.ai/code/session_01JgJbWzVJioVznVTFyQFEfx --- .reflection-state.json | 7 +- scripts/__pycache__/idle-draftcpython-312.pyc | Bin 0 -> 76378 bytes scripts/mm-worktree-task | 73 ++++- specs/bg-model-call.spec.md | 158 +++++++++ specs/mm-worktree-task.spec.md | 15 +- specs/wait-for-version.spec.md | 125 +++++++ tests/test-bg-model-call.sh | 268 +++++++++++++++ tests/test-mm-worktree-task.sh | 23 ++ tests/test-wait-for-version.sh | 310 ++++++++++++++++++ 9 files changed, 969 insertions(+), 10 deletions(-) create mode 100644 scripts/__pycache__/idle-draftcpython-312.pyc create mode 100644 specs/bg-model-call.spec.md create mode 100644 specs/wait-for-version.spec.md create mode 100755 tests/test-bg-model-call.sh create mode 100755 tests/test-wait-for-version.sh diff --git a/.reflection-state.json b/.reflection-state.json index 40defce..fdf3d7b 100644 --- a/.reflection-state.json +++ b/.reflection-state.json @@ -1,10 +1,13 @@ { "version": 1, - "last_run": "2026-03-24T10:36:46Z", + "last_run": "2026-05-11T09:48:44Z", "processed": { "log/2026-03-17.095436.md": "253f75f7ae43fb2547cd3377afb8d3b2", "log/2026-03-17.105314.md": "9c81013e9ab545527a363f525eff93e3", "log/2026-03-17.110414.md": "5ad1a211737b604f33e31e9ce754be74", - "log/2026-03-23.123551.md": "6c9560f5348b0625abb5c4e52b1e0464" + "log/2026-03-23.123551.md": "6c9560f5348b0625abb5c4e52b1e0464", + "log/2026-04-12.002212.md": "7bc1c971149fdd04f528e432fd8a1e16", + "log/2026-04-12.003747.md": "17fafffbfc6735c777b2fc71fdd463d2", + "log/2026-04-24.075643.md": "894d58fc7e390bb6af39e71d5219cc3f" } } diff --git a/scripts/__pycache__/idle-draftcpython-312.pyc b/scripts/__pycache__/idle-draftcpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fd3b32267ba19bc1da6d42462780579b4ef7f3d3 GIT binary patch literal 76378 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 bvlTjneIzoKmi?i@{GYZ$F2s<-HiQ2IE+aSX literal 0 HcmV?d00001 diff --git a/scripts/mm-worktree-task b/scripts/mm-worktree-task index 77785ca..e9f061a 100755 --- a/scripts/mm-worktree-task +++ b/scripts/mm-worktree-task @@ -31,11 +31,21 @@ Options: --docs all|recent|none Which item documents to bundle (default: recent) --tools "" Extra --allowedTools entries (comma-separated) --timeout Sub-session timeout (default: 1800) + --context cp-cli planner context (default: the ~/.cpconfig context + whose project_id equals the repo name, else cp-cli's own + current_context) --upload After --collect, upload the report + mark impl-complete --collect Don't launch; print status for an already-run slug --dryrun, -n Assemble everything, print it, create nothing --help, -h Show this help +Environment: + MM_WORKTREE_TASK_CP_CLI_DIR= checkout holding lib/cp_cli (default: the + current repo if it has one, else + ~/dev/claude/projects/agent-runtimes) + MM_WORKTREE_TASK_CP_CONTEXT= same as --context + MM_WORKTREE_TASK_CPCONFIG= cpconfig to resolve the context from + (default: ~/.cpconfig) Env overrides (for testing): MM_WORKTREE_TASK_FAKE_ITEM= fake `planner items get --json` output MM_WORKTREE_TASK_FAKE_DOCS_DIR= fake docs: /list.json + / @@ -52,6 +62,7 @@ TIMEOUT=1800 UPLOAD=0 COLLECT=0 DRYRUN=0 +CP_CONTEXT="${MM_WORKTREE_TASK_CP_CONTEXT:-}" while [[ $# -gt 0 ]]; do case "$1" in @@ -61,6 +72,7 @@ while [[ $# -gt 0 ]]; do --docs) DOCS="$2"; shift 2 ;; --tools) EXTRA_TOOLS="$2"; shift 2 ;; --timeout) TIMEOUT="$2"; shift 2 ;; + --context) CP_CONTEXT="$2"; shift 2 ;; --upload) UPLOAD=1; shift ;; --collect) COLLECT=1; shift ;; --dryrun|-n) DRYRUN=1; shift ;; @@ -97,6 +109,50 @@ if ! REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)"; then fi REPO_NAME="$(basename "$REPO_ROOT")" +# --- planner CLI: where it runs from, and which context it talks to --- +# The script is used from any planner-backed project; cp_cli itself lives in +# agent-runtimes. Resolve the checkout once and the context once, then every +# planner call goes through cp_cli(). +resolve_cp_cli_dir() { + local d + for d in "${MM_WORKTREE_TASK_CP_CLI_DIR:-}" "$REPO_ROOT" "$HOME/dev/claude/projects/agent-runtimes"; do + [[ -n "$d" && ( -f "$d/lib/cp_cli.py" || -d "$d/lib/cp_cli" ) ]] && { echo "$d"; return 0; } + done + return 1 +} +CP_CLI_DIR="$(resolve_cp_cli_dir || true)" + +if [[ -z "$CP_CONTEXT" ]]; then + CPCONFIG="${MM_WORKTREE_TASK_CPCONFIG:-$HOME/.cpconfig}" + if [[ -f "$CPCONFIG" ]]; then + CP_CONTEXT="$(python3 - "$CPCONFIG" "$REPO_NAME" <<'PY' 2>/dev/null || true +import sys +try: + import yaml + cfg = yaml.safe_load(open(sys.argv[1])) or {} +except Exception: + sys.exit(0) +for ctx in cfg.get("contexts") or []: + if ctx.get("project_id") == sys.argv[2]: + print(ctx.get("name", "")) + break +PY +)" + fi +fi + +cp_cli() { + if [[ -z "$CP_CLI_DIR" ]]; then + err "cannot find lib/cp_cli.py (set MM_WORKTREE_TASK_CP_CLI_DIR or check out agent-runtimes)" + return 1 + fi + if [[ -n "$CP_CONTEXT" ]]; then + ( cd "$CP_CLI_DIR" && python3 -m lib.cp_cli --context "$CP_CONTEXT" "$@" ) + else + ( cd "$CP_CLI_DIR" && python3 -m lib.cp_cli "$@" ) + fi +} + REPORT_DIR="${XDG_RUNTIME_DIR:-/tmp}/mm-worktree-task/${REPO_NAME}" WORKTREE="${REPO_ROOT}/.claude/worktrees/mm-${SLUG}" BRANCH="mm/${SLUG}" @@ -140,9 +196,9 @@ if [[ $COLLECT -eq 1 ]]; then DATE="$(date +%Y-%m-%d)" DOC_NAME="mm-${SLUG}-${DATE}.md" info "uploading ${DOC_NAME} to item ${UUID}" - ( cd "$REPO_ROOT" && python3 -m lib.cp_cli planner items documents put "$UUID" "$DOC_NAME" --file "$RESULT_FILE" ) - ( cd "$REPO_ROOT" && python3 -m lib.cp_cli planner items patch "$UUID" --flow-state impl-complete \ - --description "mm-worktree-task: ${SLUG} committed on mm/${SLUG}" ) + cp_cli planner items documents put "$UUID" "$DOC_NAME" --file "$RESULT_FILE" + cp_cli planner items patch "$UUID" --flow-state impl-complete \ + --description "mm-worktree-task: ${SLUG} committed on mm/${SLUG}" ok "uploaded and marked impl-complete" fi exit 0 @@ -160,7 +216,7 @@ fetch_item() { if [[ -n "${MM_WORKTREE_TASK_FAKE_ITEM:-}" ]]; then ITEM_JSON="$(cat "$MM_WORKTREE_TASK_FAKE_ITEM")" else - ITEM_JSON="$(cd "$REPO_ROOT" && python3 -m lib.cp_cli planner items get "$UUID" --json)" + ITEM_JSON="$(cp_cli planner items get "$UUID" --json)" fi TITLE="$(echo "$ITEM_JSON" | python3 -c 'import json,sys;print(json.load(sys.stdin).get("title",""))')" fi @@ -173,7 +229,7 @@ fetch_docs() { [[ -f "${MM_WORKTREE_TASK_FAKE_DOCS_DIR}/list.json" ]] || return list_json="$(cat "${MM_WORKTREE_TASK_FAKE_DOCS_DIR}/list.json")" elif [[ -n "$UUID" ]]; then - list_json="$(cd "$REPO_ROOT" && python3 -m lib.cp_cli planner items documents list "$UUID" --json 2>/dev/null || echo '{"documents":[]}')" + list_json="$(cp_cli planner items documents list "$UUID" --json 2>/dev/null || echo '{"documents":[]}')" else return fi @@ -201,7 +257,7 @@ fetch_docs() { if [[ -n "${MM_WORKTREE_TASK_FAKE_DOCS_DIR:-}" ]]; then DOC_BODY["$name"]="$(cat "${MM_WORKTREE_TASK_FAKE_DOCS_DIR}/${name}" 2>/dev/null || echo "")" else - DOC_BODY["$name"]="$(cd "$REPO_ROOT" && python3 -m lib.cp_cli planner items documents get "$UUID" "$name" 2>/dev/null || echo "")" + DOC_BODY["$name"]="$(cp_cli planner items documents get "$UUID" "$name" 2>/dev/null || echo "")" fi fi done < <(echo "$list_json" | python3 -c ' @@ -223,7 +279,7 @@ if [[ -n "$ITEM_JSON" ]]; then PARENT_ID="$(echo "$ITEM_JSON" | python3 -c 'import json,sys;print(json.load(sys.stdin).get("parent_id") or "")')" fi if [[ -n "$PARENT_ID" && -z "${MM_WORKTREE_TASK_FAKE_ITEM:-}" ]]; then - PARENT_JSON="$(cd "$REPO_ROOT" && python3 -m lib.cp_cli planner items get "$PARENT_ID" --json 2>/dev/null || echo "")" + PARENT_JSON="$(cp_cli planner items get "$PARENT_ID" --json 2>/dev/null || echo "")" fi # --- build bundle content --- @@ -256,6 +312,7 @@ build_bundle() { fi echo for n in "${DOC_BUNDLED[@]:-}"; do + [[ -z "$n" ]] && continue echo "## Document: ${n}" echo '```' echo "${DOC_BODY[$n]:-}" @@ -308,6 +365,8 @@ CMD="cd ${WORKTREE} && setsid nohup timeout ${TIMEOUT} ask-minimax-run --model \ if [[ $DRYRUN -eq 1 ]]; then echo "[dryrun] mm-worktree-task — no changes will be made" echo " Repo: ${REPO_ROOT}" + echo " cp-cli from: ${CP_CLI_DIR:-}" + echo " cp-cli ctx: ${CP_CONTEXT:-}" echo " Slug: ${SLUG}" echo " UUID: ${UUID:-(none, --brief only)}" echo " Worktree: ${WORKTREE}" diff --git a/specs/bg-model-call.spec.md b/specs/bg-model-call.spec.md new file mode 100644 index 0000000..8871379 --- /dev/null +++ b/specs/bg-model-call.spec.md @@ -0,0 +1,158 @@ +# bg-model-call + +## Purpose + +Submit a prompt to a third-party model via the agent-runtimes control plane, wait for completion, and write the result to a file — enabling the `ScheduleWakeup` polling pattern for second-opinion consultations without blocking the main Claude Code session. + +## Usage + +``` +bg-model-call [OPTIONS] +``` + +### Required flags + +| Flag | Description | +|------|-------------| +| `--model ` | Model alias: `minimax`, `sonnet`, `haiku`, `opus` | +| `--prompt ` | Path to a file containing the prompt text | +| `--output ` | Path where the result will be written | + +### Optional flags + +| Flag | Default | Description | +|------|---------|-------------| +| `--template ` | (derived from `--model`) | Override the task template name (without `.yaml`). Takes precedence over the `--model` → template mapping. | +| `--project ` | `bg-model-call` | Project ID sent to the CP, used for task grouping in agent-monitor | +| `--url ` | `$CP_URL`, then `http://localhost:8100` | Control plane base URL | +| `--task-name ` | `bg-model-call-` | Short task name shown in agent-monitor | +| `--timeout ` | `1800` | Max seconds to wait for the task before declaring it failed | +| `--poll-interval ` | `10` | Seconds between CP state polls | +| `--dryrun`, `-n` | — | Resolve all values and print what would be submitted; do not call the CP or write any files | +| `--help`, `-h` | — | Show usage information and exit 0 | + +## Model-to-Template Mapping + +A constant defined at the top of the script: + +| Model alias | Template name | +|-------------|---------------| +| `minimax` | `minimax-planning` | +| `sonnet` | `sonnet-code-repo` | +| `haiku` | `haiku-code-repo` | +| `opus` | `opus-code-repo` | + +The `--template` flag overrides this mapping entirely. + +## Behaviour + +1. Parse and validate all flags. Exit 1 with an error message if required flags are missing or values are invalid. +2. Resolve the CP URL: `--url` flag → `$CP_URL` env var → `http://localhost:8100`. +3. Resolve the template name: `--template` flag if given, otherwise look up `--model` in the mapping table. If the model alias is not in the table, exit 1. +4. Read the prompt text from the `--prompt` file. If the file is not readable, exit 1. +5. Locate the `dispatch-task` CLI: + - Check if `dispatch-task` is on PATH. + - Otherwise try `/../../../projects/agent-runtimes/scripts/dispatch-task` as a fallback (for dev environments). + - If neither is found, fall back to direct `curl` POST to `$CP_URL/tasks`. +6. Submit the task to the CP via the resolved `dispatch-task` (or curl fallback): + - `--name ` + - `--project-id ` + - `--prompt-file ` + - `--template