Skip to content

T-BR8T-start-task-accepts-base-ref

Status: closed/superseded · Impact: medium · Complexity: small

AUTO-DEFINED: this spec was best-effort machine-authored by /sdlc:task-auto-define on 2026-07-20 because the task is autonomy: autonomous/pr. Review the Goal, Approach, Today, Files-to-touch, and Acceptance-criteria carefully before trusting it.

/sdlc:task-work cannot pick up a task that must sit on top of another task’s branch: start_task.ts hardcodes origin/main as the branch base, so a stacked PR’s base is destroyed at pickup and the operator has to repair the stack by hand. This task makes the base an explicit input.

apps/sdlc/skills/task-work/start_task.ts ends by running git reset --hard origin/main on the new task branch, which destroys the base of a stacked PR. During T-C9RD the task had to sit on task/T-J5DI-remove-clear-duplicate-augmented-packages, so the operator manually rebased the sibling branch, force-pushed its PR, and re-pointed the branch by hand. The fix: start_task.ts should accept a --base <ref> flag defaulting to origin/main, reset/branch from that ref instead of hardcoding origin/main, and /sdlc:task-work Step 3 in apps/sdlc/skills/task-work/SKILL.md should document stacking as a first-class flow. Touchpoints: apps/sdlc/skills/task-work/start_task.ts and apps/sdlc/skills/task-work/SKILL.md.

T-C9RD-consolidate-augmented-into-solutions

LocationRole today
apps/sdlc/skills/task-work/start_task.ts#startTaskLands the start-commit on origin/main via an ephemeral worktree, transitions the lease, then ends with a hardcoded git fetch origin main + git reset --hard origin/main inside the task worktree. That final reset is what destroys a stacked base.
apps/sdlc/skills/task-work/start_task.ts#parseArgsParses --worktree, --branch, --main-repo, --today, --lease-authority. No base flag exists.
apps/sdlc/skills/task-work/start_task.ts#StartTaskOptionsThe typed option bag main() fills and startTask() consumes; carries no base field.
apps/sdlc/skills/task-work/SKILL.mdStep 4 creates the worktree with git worktree add .sdlc/worktrees/<basename> -b task/<basename> main; Step 5b shells out to start_task.ts and documents its exit codes. Neither step mentions stacking on a sibling task branch.
apps/sdlc/skills/task-work/tests/start_task.test.tsIntegration tests over a seeded main repo + bare origin + worktree; asserts the start-commit lands on origin/main and the task branch is reset to that tip.
apps/sdlc/skills/task-work/check_ancestry.tsStep 9’s ancestry classifier, which reasons against origin/main. Untouched by this task (see Out of scope).

start_task.ts gains an optional --base <ref> argument that defaults to origin/main. Only the trailing branch-reset block consults it; the start-commit still lands on origin/main, because task lifecycle state lives on main regardless of where the feature branch is rooted. SKILL.md grows a stacked-pickup path in Step 4 (branch the worktree from the sibling ref) and threads the same ref through Step 5b’s invocation.

  1. In apps/sdlc/skills/task-work/start_task.ts#parseArgs, add a base: string | null field to ParsedArgs (defaulting to null) and parse --base <ref> alongside the existing flags.
  2. Add base: string | null to StartTaskOptions and thread the parsed value through main() into startTask().
  3. Inside startTask(), resolve the effective ref once near the top: const baseRef = opts.base ?? "origin/main". Leave the commitToMainViaWorktree call and the readTask(..., { at: "origin/main" }) source-of-truth read untouched — the start-commit and the eligibility read stay pinned to origin/main by design.
  4. Refresh the base before resetting. Keep the existing git fetch origin main --quiet (the start-commit push must be visible). Additionally, when baseRef has the shape origin/<branch> and <branch> is not main, run git fetch origin <branch> --quiet in the worktree; when baseRef is a local ref (e.g. task/<other-basename>) skip the extra fetch.
  5. Verify the ref resolves before mutating the branch: run git -C <worktree> rev-parse --verify <baseRef>^{commit} and, on a non-zero exit, throw StartTaskError with exit code 2 naming the unresolvable ref. This runs after the lease transition and before the reset, so a typo’d base cannot leave the branch pointing anywhere new.
  6. Replace the hardcoded git reset --hard origin/main with git reset --hard <baseRef>, and rewrite the failure message to interpolate baseRef instead of the literal origin/main.
  7. Update the file’s header docblock — the Usage: line gains [--base <ref>], the prose describing the final reset names the base ref, and the exit-code table records that 2 now also covers an unresolvable base.
  8. Extend apps/sdlc/skills/task-work/tests/start_task.test.ts with three cases: (a) the base flag omitted still resets onto origin/main (assert against the existing seeded fixture); (b) with the flag naming a second local branch seeded off an earlier commit, the worktree HEAD equals that branch’s tip while the start-commit is still on origin/main; (c) an unresolvable base exits 2 and leaves the worktree HEAD unchanged.
  9. In apps/sdlc/skills/task-work/SKILL.md Step 4, add a short “Stacked pickup” subsection: when the task must sit on another task’s branch, run git worktree add .sdlc/worktrees/<basename> -b task/<basename> <base-ref> with <base-ref> defaulting to main, and carry that same ref forward to Step 5b.
  10. In SKILL.md Step 5b, add --base <ref> to the invocation block with a one-line note that it must match the ref Step 4 branched from, state that the start-commit still lands on origin/main either way, and add the unresolvable-base case to the exit-2 bullet.
  11. Refresh the per-skill doc by running /sdlc:update-skill-doc task-work so docs/skills/task-work.md reflects the new Step 4/5b prose.
LocationKindChange
apps/sdlc/skills/task-work/start_task.tsmodifyParse and thread --base; resolve baseRef; conditional base fetch; rev-parse --verify gate; reset onto baseRef; docblock refresh.
apps/sdlc/skills/task-work/tests/start_task.test.tsmodifyAdd default-base, stacked-base, and unresolvable-base cases.
apps/sdlc/skills/task-work/SKILL.mdmodifyStep 4 stacked-pickup subsection; Step 5b invocation gains the base flag; exit-2 bullet covers an unresolvable base.
docs/skills/task-work.mdmodifyRegenerate via /sdlc:update-skill-doc task-work to match the new SKILL.md steps.
  • AC-1: Invoked without the base flag, start_task.ts resets the task branch onto origin/main exactly as today — the pre-existing happy-path case in apps/sdlc/skills/task-work/tests/start_task.test.ts passes with its assertions unmodified.
  • AC-2: Invoked with --base <ref> naming a resolvable local branch, git -C <worktree> rev-parse HEAD equals git rev-parse <ref> after the run, and git log <ref>..task/<basename> is empty.
  • AC-3: With --base <ref> set to a non-main ref, the start-commit still lands on origin/main: git log origin/main -1 --format=%s is chore(tasks): start <basename>.
  • AC-4: Invoked with a base ref that does not resolve, the process exits 2, stderr names the offending ref, and the worktree’s HEAD SHA is byte-identical to its pre-invocation value.
  • AC-5: bun test run over apps/sdlc/skills/task-work/tests/start_task.test.ts exits 0.
  • AC-6: apps/sdlc/skills/task-work/SKILL.md Step 4 documents branching the worktree from a non-main base, and Step 5b’s invocation block shows the base flag; command grep -c -- '--base' apps/sdlc/skills/task-work/SKILL.md returns at least 2.
  • Teaching Step 9’s apps/sdlc/skills/task-work/check_ancestry.ts about a non-main base; its origin/main classification is unchanged.
  • Auto-deriving the base from the task’s related: / depends_on: frontmatter — the base stays an explicit operator-supplied argument.
  • Relocating where the start-commit lands: task lifecycle state still commits and pushes to origin/main regardless of the base.
  • Restacking, rebasing, or force-pushing sibling branches when the base moves after pickup.
  • Passing the base automatically from /sdlc:orchestrate’s dispatch of /sdlc:task-work.
  • none

Spawned by /sdlc:spawn-task-pr on 2026-07-20 UTC from T-C9RD-consolidate-augmented-into-solutions in https://github.com/sksizer/dev.


← Back to Tasks