Merge pull request 'agents: discussion mode — devs talk in threads, build only on explicit signal' (#102) from feat/discussion-mode into main
ci / lint (push) Skipped
ci / lint (push) Skipped
This commit was merged in pull request #102.
This commit is contained in:
@@ -198,6 +198,7 @@ jobs:
|
|||||||
MODEL: ${{ steps.prep.outputs.model }}
|
MODEL: ${{ steps.prep.outputs.model }}
|
||||||
VISION: ${{ steps.prep.outputs.vision }}
|
VISION: ${{ steps.prep.outputs.vision }}
|
||||||
MODE: ${{ steps.prep.outputs.mode }}
|
MODE: ${{ steps.prep.outputs.mode }}
|
||||||
|
WORKMODE: ${{ steps.prep.outputs.workmode }} # build | discuss (devs consulted in-thread)
|
||||||
HAS_IMAGES: ${{ steps.imgs.outputs.has_images }}
|
HAS_IMAGES: ${{ steps.imgs.outputs.has_images }}
|
||||||
BRANCH: ${{ steps.prep.outputs.branch }}
|
BRANCH: ${{ steps.prep.outputs.branch }}
|
||||||
AUTOPILOT: ${{ steps.prep.outputs.autopilot }} # 'true' when the issue carries the `autopilot` label
|
AUTOPILOT: ${{ steps.prep.outputs.autopilot }} # 'true' when the issue carries the `autopilot` label
|
||||||
@@ -231,6 +232,7 @@ jobs:
|
|||||||
TOKEN_INTERN: ${{ secrets.TOKEN_INTERN }}
|
TOKEN_INTERN: ${{ secrets.TOKEN_INTERN }}
|
||||||
NAME: ${{ steps.prep.outputs.name }}
|
NAME: ${{ steps.prep.outputs.name }}
|
||||||
MODE: ${{ steps.prep.outputs.mode }}
|
MODE: ${{ steps.prep.outputs.mode }}
|
||||||
|
WORKMODE: ${{ steps.prep.outputs.workmode }}
|
||||||
NUM: ${{ github.event.issue.number }}
|
NUM: ${{ github.event.issue.number }}
|
||||||
TITLE: ${{ github.event.issue.title }}
|
TITLE: ${{ github.event.issue.title }}
|
||||||
BRANCH: ${{ steps.prep.outputs.branch }}
|
BRANCH: ${{ steps.prep.outputs.branch }}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ reply=$(awk '
|
|||||||
/^[[:space:]]*BEGIN_SUBTASKS/{s=1}
|
/^[[:space:]]*BEGIN_SUBTASKS/{s=1}
|
||||||
/^[[:space:]]*BEGIN_PR_DESCRIPTION/{p=1}
|
/^[[:space:]]*BEGIN_PR_DESCRIPTION/{p=1}
|
||||||
/^[[:space:]]*DELEGATE:[[:space:]]*@/{next}
|
/^[[:space:]]*DELEGATE:[[:space:]]*@/{next}
|
||||||
|
/^[[:space:]]*ASK:[[:space:]]*@/{next}
|
||||||
/^[[:space:]]*CLOSE_ISSUE[[:space:]]*$/{next}
|
/^[[:space:]]*CLOSE_ISSUE[[:space:]]*$/{next}
|
||||||
/^[[:space:]]*MERGE_PR[[:space:]]*$/{next}
|
/^[[:space:]]*MERGE_PR[[:space:]]*$/{next}
|
||||||
/^[[:space:]]*RETRO[[:space:]]*$/{next}
|
/^[[:space:]]*RETRO[[:space:]]*$/{next}
|
||||||
@@ -246,6 +247,18 @@ if [ "$MODE" != "pr" ]; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# --- @pm ASK: consult a dev in the thread WITHOUT starting a build ---
|
||||||
|
# 'ASK: @<dev> <question>' fires the dev in DISCUSSION mode (route.sh: the trigger below does not
|
||||||
|
# match any build phrase, so the dev replies in-thread — no branch, no PR). @pm gathers input this
|
||||||
|
# way, then DELEGATEs when enough is known.
|
||||||
|
ask_line=$(grep -oiE '^[[:space:]]*ASK:[[:space:]]*@(junior|senior|lead|intern)[[:space:]]+.*$' /tmp/agent_out.md 2>/dev/null | head -1)
|
||||||
|
if [ "$NAME" = "pm" ] && [ -n "$ask_line" ]; then
|
||||||
|
ask_dev=$(printf '%s' "$ask_line" | grep -oiE '@(junior|senior|lead|intern)' | head -1 | tr -d '@' | tr '[:upper:]' '[:lower:]')
|
||||||
|
ask_q=$(printf '%s' "$ask_line" | sed -E 's/^[[:space:]]*ASK:[[:space:]]*@[A-Za-z]+[[:space:]]+//')
|
||||||
|
trig "$ISSN" "@$ask_dev $ask_q — this is a discussion: reply in this thread with your assessment; do not start any work."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
# --- @pm delegation: hand the build to a dev, or hand the finished PR to @qa for review ---
|
# --- @pm delegation: hand the build to a dev, or hand the finished PR to @qa for review ---
|
||||||
# Only an explicit 'DELEGATE: @<agent>' line acts (never a prose mention). Fires via the PAT (TTOK)
|
# Only an explicit 'DELEGATE: @<agent>' line acts (never a prose mention). Fires via the PAT (TTOK)
|
||||||
# so a new run starts; the built-in token cannot. Everything posts on the ISSUE — @pm never touches
|
# so a new run starts; the built-in token cannot. Everything posts on the ISSUE — @pm never touches
|
||||||
@@ -269,6 +282,15 @@ if [ "$MODE" != "pr" ]; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# --- dev DISCUSSION mode: consulted for expertise, no build (route.sh workmode=discuss) ---
|
||||||
|
# The reply is a comment on the thread — discard any stray file edits, skip ALL git/PR machinery.
|
||||||
|
if [ "${WORKMODE:-build}" = "discuss" ]; then
|
||||||
|
git checkout -- . 2>/dev/null || true
|
||||||
|
git clean -fd 2>/dev/null || true
|
||||||
|
post "$(printf '%s%s' "$reply" "$activity")"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
# Scrub the runtime scripts checkout (.agents-workflow) from the tree so it never lands in a
|
# Scrub the runtime scripts checkout (.agents-workflow) from the tree so it never lands in a
|
||||||
# commit/PR and never confuses the git ops below (issue #33). The scripts we run live outside the
|
# commit/PR and never confuses the git ops below (issue #33). The scripts we run live outside the
|
||||||
# workspace ($SCRIPTS -> runner.temp), so removing this in-tree copy is always safe. Handle every
|
# workspace ($SCRIPTS -> runner.temp), so removing this in-tree copy is always safe. Handle every
|
||||||
|
|||||||
@@ -53,8 +53,25 @@ vision=$(jq -r --arg a "$name" '.[$a].vision' /tmp/agents.json)
|
|||||||
mode=$(jq -r --arg a "$name" '.[$a].mode' /tmp/agents.json)
|
mode=$(jq -r --arg a "$name" '.[$a].mode' /tmp/agents.json)
|
||||||
# Compact JSON array of the skills this agent may load (scopes permission.skill in install-opencode.sh).
|
# Compact JSON array of the skills this agent may load (scopes permission.skill in install-opencode.sh).
|
||||||
skills=$(jq -c --arg a "$name" '.[$a].skills // []' /tmp/agents.json)
|
skills=$(jq -c --arg a "$name" '.[$a].skills // []' /tmp/agents.json)
|
||||||
echo "Routing to @$name (model=$model vision=$vision mode=$mode skills=$skills)"
|
|
||||||
{ echo "name=$name"; echo "model=$model"; echo "vision=$vision"; echo "mode=$mode"; echo "skills=$skills"; } >> "$GITHUB_OUTPUT"
|
# --- WORKMODE for dev (mode=pr) agents: build vs DISCUSS. ---
|
||||||
|
# Mentioning a dev is a CONVERSATION by default — it replies in the thread without creating a
|
||||||
|
# branch or PR. Actual building starts ONLY on the explicit signals:
|
||||||
|
# - a comment on a PR thread (resuming existing work), or
|
||||||
|
# - the pm delegation template ".. please proceed with issue .." (also usable by a human), or
|
||||||
|
# - the qa bounce template ".. please address my review ..".
|
||||||
|
# This lets @pm (via its ASK marker) and the maintainer consult devs to gather information first,
|
||||||
|
# and explicitly start the build later — see publish.sh / run-agent.sh.
|
||||||
|
workmode=build
|
||||||
|
if [ "$mode" = "pr" ] && [ -z "$IS_PR" ]; then
|
||||||
|
if printf '%s' "$scan" | grep -qiE 'please (proceed with issue|address my review)'; then
|
||||||
|
workmode=build
|
||||||
|
else
|
||||||
|
workmode=discuss
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "Routing to @$name (model=$model vision=$vision mode=$mode workmode=$workmode skills=$skills)"
|
||||||
|
{ echo "name=$name"; echo "model=$model"; echo "vision=$vision"; echo "mode=$mode"; echo "workmode=$workmode"; echo "skills=$skills"; } >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
# Act as the agent's own Gitea user when its token is set; else the built-in bot.
|
# Act as the agent's own Gitea user when its token is set; else the built-in bot.
|
||||||
case "$name" in
|
case "$name" in
|
||||||
@@ -67,7 +84,10 @@ git config user.email "$name@ffaerber.duckdns.org"
|
|||||||
API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}"
|
API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}"
|
||||||
hdr=(-H "Authorization: token $TOK" -H "Content-Type: application/json")
|
hdr=(-H "Authorization: token $TOK" -H "Content-Type: application/json")
|
||||||
branch_ref=""
|
branch_ref=""
|
||||||
if [ -n "$IS_PR" ]; then # comment on a PR -> resume its branch
|
if [ "$workmode" = "discuss" ]; then # conversation only — no branch, no PR machinery
|
||||||
|
echo "discussion mode — staying on main, no branch prep"
|
||||||
|
{ echo "branch=main"; echo "new=false"; } >> "$GITHUB_OUTPUT"
|
||||||
|
elif [ -n "$IS_PR" ]; then # comment on a PR -> resume its branch
|
||||||
ref=$(curl -s -H "Authorization: token $GT" "$API/pulls/$NUM" | jq -r .head.ref)
|
ref=$(curl -s -H "Authorization: token $GT" "$API/pulls/$NUM" | jq -r .head.ref)
|
||||||
branch_ref="$ref"
|
branch_ref="$ref"
|
||||||
git fetch origin "$ref" && git checkout "$ref"
|
git fetch origin "$ref" && git checkout "$ref"
|
||||||
|
|||||||
@@ -54,7 +54,11 @@ if [ "$MODE" = "comment" ]; then
|
|||||||
|
|
||||||
If anything is unclear or needs a decision at any phase, START your reply with '@ffaerber', ask
|
If anything is unclear or needs a decision at any phase, START your reply with '@ffaerber', ask
|
||||||
specific questions, and do NOT emit a marker. Mentioning a teammate in prose does NOT act — only a
|
specific questions, and do NOT emit a marker. Mentioning a teammate in prose does NOT act — only a
|
||||||
DELEGATE line does.
|
marker line does.
|
||||||
|
ASK — to CONSULT a dev before (or instead of) planning, end your reply with EXACTLY one line:
|
||||||
|
'ASK: @<dev> <one concrete question>'. The dev replies in this thread WITHOUT starting any work —
|
||||||
|
use it to gather feasibility/effort/approach input, then present your plan (and later DELEGATE)
|
||||||
|
once you know enough. One ASK per reply; never ASK and DELEGATE in the same reply.
|
||||||
RETRO — when the maintainer asks for a retrospective on this issue (e.g. 'run a retro',
|
RETRO — when the maintainer asks for a retrospective on this issue (e.g. 'run a retro',
|
||||||
'@pm retro'), briefly acknowledge and end your reply with EXACTLY one line: 'RETRO'. The
|
'@pm retro'), briefly acknowledge and end your reply with EXACTLY one line: 'RETRO'. The
|
||||||
automation opens a retro issue (read this issue + its PR, distill learnings into LEARNINGS.md)
|
automation opens a retro issue (read this issue + its PR, distill learnings into LEARNINGS.md)
|
||||||
@@ -97,6 +101,15 @@ if [ "$MODE" = "comment" ]; then
|
|||||||
decision). Hands back to @ffaerber.
|
decision). Hands back to @ffaerber.
|
||||||
Emit AT MOST one marker, and only after you have actually verified."
|
Emit AT MOST one marker, and only after you have actually verified."
|
||||||
fi
|
fi
|
||||||
|
elif [ "${WORKMODE:-build}" = "discuss" ]; then
|
||||||
|
# A dev agent consulted for its EXPERTISE — conversation only, no build. Building starts later,
|
||||||
|
# explicitly ('please proceed with issue …'). See route.sh workmode.
|
||||||
|
ACTION="You are being CONSULTED in this thread — this is a DISCUSSION, not a build task. Answer the
|
||||||
|
question you were asked: read whatever files/logs you need (read-only), give your assessment,
|
||||||
|
approach, effort estimate, risks, or answer — concise and concrete. Your reply becomes a comment.
|
||||||
|
Do NOT modify files, do NOT commit or push, do NOT create branches, do NOT open PRs. Do not
|
||||||
|
emit any marker. When the team has enough information, @pm (or the maintainer) will explicitly
|
||||||
|
tell a dev to start building."
|
||||||
else
|
else
|
||||||
ACTION="You start on git branch '${BRANCH}', with git and push credentials already configured.
|
ACTION="You start on git branch '${BRANCH}', with git and push credentials already configured.
|
||||||
FIRST read AGENTS.md at the repo root and FOLLOW IT EXACTLY — it defines the golden rules,
|
FIRST read AGENTS.md at the repo root and FOLLOW IT EXACTLY — it defines the golden rules,
|
||||||
|
|||||||
@@ -36,6 +36,15 @@ deploy-host SSH skill, live in the consuming repo under `.gitea/agent-skills/`
|
|||||||
`@pm` is the only agent that ever merges, and only under the `autopilot` label (its kill switch:
|
`@pm` is the only agent that ever merges, and only under the `autopilot` label (its kill switch:
|
||||||
remove the label mid-flight and the next step reverts to human control).
|
remove the label mid-flight and the next step reverts to human control).
|
||||||
|
|
||||||
|
### Discussion vs building
|
||||||
|
|
||||||
|
Mentioning a dev agent is a **conversation by default**: it reads what it needs and replies in the
|
||||||
|
thread — no branch, no PR. `@pm` can consult devs the same way with an `ASK: @<dev> <question>`
|
||||||
|
marker (gather feasibility/effort input before planning). **Building starts only on the explicit
|
||||||
|
signals**: `@pm`'s delegation (*"please proceed with issue …"* — a human can write the same phrase
|
||||||
|
to start a build directly), a `@qa` bounce (*"please address my review …"*), or any comment on the
|
||||||
|
PR thread itself (resuming existing work).
|
||||||
|
|
||||||
### Retros — the learning loop
|
### Retros — the learning loop
|
||||||
|
|
||||||
Ask `@pm` for a retrospective on any issue (e.g. **"@pm run a retro"**, typically when merging). The
|
Ask `@pm` for a retrospective on any issue (e.g. **"@pm run a retro"**, typically when merging). The
|
||||||
|
|||||||
Reference in New Issue
Block a user