Land (offline-demo)
There is no remote, no GitHub PR, and no CI in this demo. "Land" means:
- Make sure the feature branch is conflict-free against local
main. - Squash-merge the feature branch into local
main. - Mark the local PR record as
MERGEDand move the issue toDone.
Goals
- Branch is conflict-free with
main. - Local validation has been run on this branch (you should have done this during the run that opened the PR; re-run if anything changed).
- The branch is squash-merged into local
main. - The local PR record (
tasks pr-merge) is markedMERGED. - The issue is moved to
Done.
Preconditions
- You are on the feature branch (
symphony/<identifier>) with a clean working tree. - The issue is in
Mergingstate (the human approved it). - The local PR record is
OPEN.
Steps
- Resolve PR context:
branch=$(git branch --show-current) identifier=$(echo "$branch" | sed 's|^symphony/||' | tr '[:lower:]' '[:upper:]') tasks pr-view "$identifier" - Make sure the branch is up to date against
main:
If the branch hasn't ingested recentgit fetch . main:main 2>/dev/null || truemaincommits, run thepullskill first. Thepullskill is configured for this offline mode and merges from localmainrather thanorigin/main. - Address any review feedback. In offline mode, reviewer comments live on
the issue itself (not on the PR), so:
tasks comment-list "$identifier"- For each non-
[claude]comment that's actionable, choose: accept (implement), clarify (ask), or push back (justified disagreement). - Reply by appending a
[claude]-prefixed comment with your decision:cat > /tmp/reply.md <<'EOF' [claude] Re: "<paraphrase of the reviewer's point>" <decision and rationale> EOF tasks comment-create "$identifier" --body-file /tmp/reply.md - For accepted feedback, make the code change, run the
commitskill, and re-run thepushskill to update the PR body before merging.
- For each non-
- Re-run validation if any code changed:
# Whatever the issue's Validation section specifies, e.g.: pytest -q - Squash-merge into local
main. From the feature branch:
Note: this is happening inside the agent's git worktree. The squashed commit lands on the worktree's localpr_title=$(tasks pr-view "$identifier" --json | python3 -c 'import sys,json;print(json.load(sys.stdin)["title"])') pr_body=$(tasks pr-view "$identifier" --json | python3 -c 'import sys,json;print(json.load(sys.stdin)["body"])') # Stash any in-flight uncommitted changes — there should be none at this point. git switch main git -c merge.ff=false merge --squash "$branch" commit_msg=$(printf '%s\n\n%s' "$pr_title" "$pr_body") git commit -m "$commit_msg" merge_sha=$(git rev-parse HEAD)main. The orchestrator'sbefore_removehook will clean up the worktree afterwards. The squashed commit is the deliverable for this issue. - Mark the local PR merged and move the issue to
Done:tasks pr-merge "$identifier" --merge-commit "$merge_sha" tasks update-state "$identifier" --state "Done" - Switch back to the feature branch so any post-skill housekeeping the
orchestrator runs has the expected HEAD:
git switch "$branch"
Failure handling
- Merge conflicts: run the
pullskill, resolve, run thecommitskill, re-run thepushskill, then start this skill from the top. - Validation regressions after a feedback-driven change: fix → commit → push → re-validate before re-attempting the merge.
- Unexpected branch state (you're not on the feature branch, or
maindiverged in unexpected ways): stop and surface the exact state in the workpad. Don't try to recover with destructive commands.
Guardrails
- Never
git push,git fetch origin, orgh .... There is no remote. - Never
--forceanything; nothing forces in offline mode. - Never call
git mergeorgit switch mainoutside this skill flow. - All bot-authored issue/PR comments must start with
[claude]. - Do not yield until the squash-merge has landed and the issue is
Done, unless you hit a true blocker.