diff --git a/swarmforge/constitution/articles/handoffs.prompt b/swarmforge/constitution/articles/handoffs.prompt index da16b9ae..82c9fba2 100644 --- a/swarmforge/constitution/articles/handoffs.prompt +++ b/swarmforge/constitution/articles/handoffs.prompt @@ -26,7 +26,7 @@ commit: <10-character-commit-abbrev> generated metadata, and other non-functional churn still require a forward down the chain. - When your role sends the end-of-chain handoff to multiple recipients, those - recipients merge only (`merge_and_process`). They do not forward that handoff + recipients merge the received commit only. They do not forward that handoff further. Only this terminal broadcast is merge-only without re-forwarding. - Preserve the received task name when forwarding work for the same task. If the handoff starts new work, invent a short stable task name. diff --git a/swarmforge/handoff-protocol.md b/swarmforge/handoff-protocol.md index 16fe1cc9..f12161d1 100644 --- a/swarmforge/handoff-protocol.md +++ b/swarmforge/handoff-protocol.md @@ -118,7 +118,7 @@ enqueued_at: 2026-06-15T14:05:32Z Re-read your role and constitution. -merge_and_process coder a1b2c3d9 +Merge commit a1b2c3d9 from role coder into your current branch. Then process the merged state according to your role and constitution. ``` For broadcast handoffs, `to` preserves the full recipient list and `recipient` @@ -147,7 +147,7 @@ Generated body: ```text Re-read your role and constitution. -merge_and_process coder a1b2c3d9 +Merge commit a1b2c3d9 from role coder into your current branch. Then process the merged state according to your role and constitution. ``` The script validates the task name and canonicalizes the commit abbreviation @@ -175,7 +175,7 @@ Examples: #### Terminal broadcast Only the end-of-chain handoff sent to multiple recipients is not forwarded -further. Each recipient merges that commit (`merge_and_process`) and stops; +further. Each recipient merges that commit and stops; recipients do not re-forward that handoff down the chain. Examples: @@ -388,7 +388,7 @@ TASK_NAME: task-1-cave-setup PAYLOAD: Re-read your role and constitution. -merge_and_process architect a1b2c3d9 +Merge commit a1b2c3d9 from role architect into your current branch. Then process the merged state according to your role and constitution. ``` ### `done_with_current_task.sh` diff --git a/swarmforge/scripts/swarm_handoff.bb b/swarmforge/scripts/swarm_handoff.bb index e96da88d..808143cc 100755 --- a/swarmforge/scripts/swarm_handoff.bb +++ b/swarmforge/scripts/swarm_handoff.bb @@ -264,7 +264,9 @@ (defn body [type sender canonical-commit note-message] (case type - "git_handoff" (str "Re-read your role and constitution.\n\nmerge_and_process " sender " " canonical-commit) + "git_handoff" (str "Re-read your role and constitution.\n\nMerge commit " canonical-commit + " from role " sender + " into your current branch. Then process the merged state according to your role and constitution.") "note" (str "Re-read your role and constitution.\n\n" note-message))) (defn write-handoff! [{:keys [headers recipients canonical-commit sender]}] diff --git a/test/swarmforge/handoff_test.clj b/test/swarmforge/handoff_test.clj index 9d8d0469..1d9b77d3 100644 --- a/test/swarmforge/handoff_test.clj +++ b/test/swarmforge/handoff_test.clj @@ -111,7 +111,8 @@ :type "git_handoff" :task "task-one" :commit "0123456789" - :body "merge_and_process sender 0123456789"} + :body (str "Merge commit 0123456789 from role sender into your current branch. " + "Then process the merged state according to your role and constitution.")} attrs)))) (deftest swarm-handoff-validates-and-queues-git-handoffs @@ -135,7 +136,10 @@ content (read-file queued)] (is (str/includes? content "task: task-1-cave-setup\n")) (is (str/includes? content (str "commit: " commit "\n"))) - (is (str/includes? content (str "merge_and_process sender " commit))) + (is (str/includes? content + (str "Merge commit " commit " from role sender into your current branch. " + "Then process the merged state according to your role and constitution."))) + (is (not (str/includes? content "merge_and_process"))) (is (fs/exists? queued)) (is (not (fs/exists? draft)))))))) diff --git a/test/swarmforge/script_test.clj b/test/swarmforge/script_test.clj index c7ed1e34..3c991d9d 100644 --- a/test/swarmforge/script_test.clj +++ b/test/swarmforge/script_test.clj @@ -48,12 +48,13 @@ "type: git_handoff\n" "task: task-alpha\n" "\n" - "merge_and_process coder abcdef1234\n")) + "Merge commit abcdef1234 from role coder into your current branch. " + "Then process the merged state according to your role and constitution.\n")) (let [header (run {:dir root} (script "handoff_lib.bb") "header-field" "task.handoff" "task") body (run {:dir root} (script "handoff_lib.bb") "body" "task.handoff") task (run {:dir root} (script "handoff_lib.bb") "print-task" "task.handoff")] (is (str/includes? (:out header) "task-alpha")) - (is (str/includes? (:out body) "merge_and_process coder abcdef1234")) + (is (str/includes? (:out body) "Merge commit abcdef1234 from role coder into your current branch.")) (is (str/includes? (:out task) "TASK: task.handoff")) (is (str/includes? (:out task) "FROM: coder")) (is (str/includes? (:out task) "TASK_NAME: task-alpha")))