Skip to content

v1.8.1 — v1.4a multipart staging→worktree pipe fix

Choose a tag to compare

@SeasonTemple SeasonTemple released this 21 May 06:19
· 1 commit to main since this release

Fixes the v1.4a regression where multipart POST /plans/new uploads
landed at the adapter as bare basenames after the handler had already
deleted the staging dir on return — opencode then failed to find the
files. v1.4b JSON-body submission stayed functional throughout; only
the file-upload path was affected. Branch: fix/v1.4a-multipart-staging -pipe. Decision chain: docs/brainstorms/2026-05-21-002-fix-v14a -multipart-staging-pipe-requirements.md, docs/plans/2026-05-21-002 -fix-v14a-multipart-staging-pipe-plan.md. Replay oracle
(legacyFoldQuerySnapshot) body byte-identical vs v1.8.0-ui1.

Fixed

  • Multipart POST /plans/new upload pipe wired end-to-end.
    Handler now stages uploaded files at .arranger/staging/<plan> /<task>/ (additive bootstrap — no schema migration), persists the
    path on tasks.staging_path at submit time, and the executor copies
    each staging file into the per-runtime worktree at dispatch time
    (KD4 copy-not-move so retries land in a fresh worktree without
    staging mutation). The handler's eager os.RemoveAll(stagingDir)
    defer is replaced with an error-only defer; happy-path cleanup is
    now owned by arranger gc. On copy failure the executor publishes
    task.failed{reason: upload_move_failed} against the RID aggregate,
    surfaces the failed file in the error message, and never spawns the
    adapter.
  • Per-worktree commit exclusion for upload bytes. Copied upload
    files are listed in the per-worktree excludes.local (via
    extensions.worktreeConfig + core.excludesFile) so subsequent
    git add -A inside the worktree does not commit user-input bytes
    into per-task commits.

Changed

  • arranger gc covers staging dirs. Both --dry-run and --apply
    now enumerate .arranger/staging/<plan>/<task>/ per terminal plan;
    --apply removes them and nulls tasks.staging_path. An orphan
    sweep after the per-plan loop reaps .arranger/staging/<plan>/ dirs
    whose <plan> is not in the plans table (submission-failed-after-
    mkdir, manual leftovers, pre-fix residue).
  • arranger gc --json shape. Per-plan entries gain
    staging_dirs (paths enumerated) and removed.staging_dirs (count
    removed under --apply). Summary gains staging_dirs_total,
    orphan_staging_dirs, orphan_staging_removed, orphan_errors.
  • workspace.Manager.RemovePlan signature. Now takes
    (planID, workspacePaths, stagingDirs, removePlanBranch) —
    caller-orchestrated staging removal. Only caller is arranger gc.