Commit Graph
20 Commits
Author SHA1 Message Date
Felix FaerberandClaude Opus 4.8 e22a4cf98c publish: qa APPROVE detail goes to the PR — issue gets the terse verdict only
ci / lint (push) Skipped
ci / lint (pull_request) Successful in 11s
Seen on issue #83: qa's approval pasted whitespace-nit detail into the issue
thread. The issue is for the creator/orchestration; review internals belong on
the PR. On APPROVE the full reply (+run report) now posts to the PR and the
issue gets exactly ' Reviewed PR #N — looks good.' (falls back to the issue
only if no PR could be resolved).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 11:10:12 +03:00
ffaerber d0345617d5 Merge pull request '@junior: intern' (#84) from ai/issue-83 into main
ci / lint (push) Successful in 12s
2026-07-06 10:04:59 +02:00
Felix FaerberandClaude Opus 4.8 b40f547740 agents: retro loop — "@pm retro" distills learnings into LEARNINGS.md
ci / lint (push) Skipped
ci / lint (pull_request) Successful in 11s
New learning step: ask @pm for a retrospective on any issue and the system
turns what happened into prompt-visible rules for future runs.

- run-agent.sh: @pm gains a RETRO marker (emit only when the maintainer asks);
  LEARNINGS.md (caller repo root, capped at 4KB) is injected into EVERY agent's
  prompt as "TEAM LEARNINGS" — the feedback loop that makes delegation more
  robust over time.
- publish.sh: on @pm's RETRO marker, open a "retro: issue #N" issue pointing at
  the issue + its PR (state=all resolve, works after merge) and trigger @senior
  on it (has gitea-api to read both threads). The retro produces a LEARNINGS.md
  PR through the NORMAL choreography (senior → pm → qa), so retros are reviewed
  like any change. Strip the RETRO marker from visible replies.
- publish.sh: bounce counter now counts only @qa-authored comments matching the
  exact trigger template — on PR #84 it jumped 1/3 → 3/3 because a qa review
  QUOTED our own "(fix attempt …)" template from the diff, halving the fix
  budget. Template + regex pinned together with a sync note.
- README: document the retro loop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 11:02:19 +03:00
junior c95d52aabb fixup: remove stray leading spaces in run-agent.sh prompts and blank line in publish.sh 2026-07-06 07:41:31 +00:00
junior bf1256ecec agents: add @intern routed to local ollama/ornith:35b
ci / lint (pull_request) Successful in 12s
2026-07-06 07:30:30 +00:00
Felix FaerberandClaude Opus 4.8 305aeb085c publish: trigger comments speak in first person (no agent self-mention)
ci / lint (push) Skipped
ci / lint (pull_request) Successful in 12s
The fixed trigger templates referred to their own author in the third person —
e.g. @qa posting 'please address @qa's review above' (seen on PR #80) or a dev
posting 'the dev has pushed an update'. Reworded to first person ('my review',
'I have pushed', 'per my plan'), which also makes routing order-independent:
each trigger now mentions ONLY its target agent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 10:09:52 +03:00
Felix FaerberandClaude Opus 4.8 6334ebe8c6 agents: report tokens + $ cost on every agent comment
Each run now appends a report to the agent's reply: the tool calls it made plus
input/output token totals and the dollar cost. opencode's --format json emits
per-step `tokens` and `cost` (USD, priced from the model) on step_finish events;
build-activity-log.sh sums them across the run.

- build-activity-log.sh: compute for EVERY agent (not just devs — @pm/@qa also
  call tools and cost money); output a collapsed <details> report (summary line
  shows "N tool calls · in X · out Y · $Z"; body lists the tools + a token/cost
  breakdown). Zero-tool runs get a one-line "$Z · in X · out Y" footer.
- publish.sh: build $activity once (near the top) and append it to every agent's
  reply — @pm plan/finalize, @qa verdict/recommendations, and dev PR comments.
- agent.yml: rename the step accordingly.

Models without pricing (self-hosted ollama) report cost $0.0000.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 09:22:00 +03:00
Felix FaerberandClaude Opus 4.8 84cec444ef agents: PM-orchestrated flow — @pm hub, @qa reviews, human/@pm merges
Rework the delegation/trigger choreography so @pm orchestrates end-to-end from
the issue thread while @qa reviews on the PR and never merges.

Flow: issue → @pm plans (asks creator; autopilot skips) → dev builds PR → dev
pings @pm on the issue → @pm hands to @qa → @qa reviews ON THE PR (recommends /
BOUNCE:@dev, direct qa↔dev loop, 3 max) → @qa APPROVEs → verdict on the ISSUE →
@pm → normal: tells creator "ready to merge" (human merges); autopilot: @pm
MERGE_PR. @pm never reads or comments on the PR (small context); @qa never merges.

- run-agent.sh: @pm prompt = 3 phases (plan / hand PR to @qa / finalize),
  autopilot only drops the approval gate + adds @pm MERGE_PR. @qa prompt =
  reviewer, ends with APPROVE / BOUNCE:@dev / HALT; identical in both flows.
- publish.sh: shared post_to()/trig()/resolve_pr() helpers + ISSN; @qa routes
  reply to PR (bounce) vs issue (approve) and fires @pm/@dev; @pm handles
  DELEGATE:@dev, DELEGATE:@qa (resolves the PR), and autopilot MERGE_PR; dev
  NEW=true fires @pm on the issue, NEW=false fires @qa on the PR. Strip
  APPROVE/HALT markers.

Tokens re-minted to match: TOKEN_PM gains write:repository (it merges now),
TOKEN_QA drops to read:repository (never merges).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 21:06:39 +03:00
Felix FaerberandClaude Opus 4.8 4c05abac63 agents: drop redundant agent-name headers from comments (+ fix self-trigger loop)
Gitea already attributes every comment/PR to its author, so the "🤖 **@name**" /
"🔨 **@name**" header at the top of agent comments was redundant noise. Remove it
everywhere and, in the process, close a self-trigger loop.

- publish.sh: post()/prpost() now append a hidden `<!-- 🤖 … -->` marker instead
  of each message carrying a visible "🤖 **@name**" header. The gate keys on the
  '🤖' char to skip agent replies, so the marker preserves loop-prevention while
  being invisible. All reply/status/autopilot strings drop the name header.
- route.sh: the "building on branch" notice is posted with the agent's PAT and
  previously had NO 🤖 marker + an "@name" mention, so it re-triggered the agent
  (the observed loop on issue #139). Reword without the self-name and add the
  hidden marker so it can't fire a new run.
- publish.sh: broaden the leading self-header stripper to drop any leading line
  referencing the agent's own @handle (e.g. "## 🔨 @senior — …"), not just bare
  "**@name**" lines. Legit headings like "## Summary" are preserved.
- run-agent.sh: tell the model not to begin its reply with its own name/handle.
- Trigger comments (delegation / autopilot / bounce) stay marker-free by design,
  so they still fire the next agent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 18:00:58 +03:00
Felix FaerberandClaude Opus 4.8 3c66220f6d agents: remove shared AGENT_TOKEN fallback — per-agent tokens only
All three consuming repos (gitea/agents, gitea/ops, ffaerber/homelab) now
carry the per-agent TOKEN_* secrets (org-level for gitea/*, user-level for
ffaerber/*), so the shared AGENT_TOKEN fallback is no longer needed.

- agent.yml: SELF_TOKEN ternary ends in '' instead of secrets.AGENT_TOKEN;
  removed AGENT_TOKEN from the publish + rescue step env.
- publish.sh: TTOK is just the agent's own token; if an agent somehow has none
  (TOK fell back to the built-in GT), TTOK is left empty so the trigger/merge
  is skipped rather than silently no-op'ing under the built-in token.
- README: drop the AGENT_TOKEN row; state that every consuming repo must carry
  the per-agent TOKEN_* (no shared fallback).

The AGENT_TOKEN Actions secrets (org + user) and its gitea/secrets/.env entry
are removed separately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 16:51:06 +03:00
Felix FaerberandClaude Opus 4.8 06f1924441 agents: per-agent Gitea identity — each agent uses its own token
Drop the shared AGENT_TOKEN as the primary credential; every agent now acts
as its own Gitea user (TOKEN_PM for @pm, TOKEN_OPS for @ops, …) for API
calls, delegation/autopilot trigger comments, and PR merges.

- agent.yml: Run-agent step injects SELF_TOKEN — a ternary selecting the
  running agent's own token by name, falling back to AGENT_TOKEN for repos
  not yet migrated to per-agent tokens (e.g. homelab). Only that one token
  enters the agent process, so no agent can act as another. The gitea-api /
  gitea-admin skill-setup steps no longer carry a token (they only write docs).
- Gate: trust the agent roster (pm/junior/senior/lead/qa/ops) as comment
  authors so an agent's own delegation/autopilot trigger comment (posted with
  its PAT, no 🤖 prefix) fires the next run. @ops added to the mention set.
- publish.sh: TOK = agent identity (comments/replies); new TTOK = trigger/merge
  token (agent PAT, else AGENT_TOKEN fallback) for delegation, autopilot @qa
  triggers, and PR merges that must fire downstream workflows.
- skill-gitea-api.sh / skill-gitea-admin.sh / run-agent.sh: AGENT_TOKEN/
  TOKEN_OPS → SELF_TOKEN in the emitted skill docs and env contract.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 16:20:29 +03:00
Felix FaerberandClaude Opus 4.8 2f1ae61b06 feat(ops): make @ops routable + post under its own TOKEN_OPS identity
PR #55 added @ops to the registry but route.sh only looped pm/junior/senior/lead/qa, so @ops could
never be triggered, and there was no token case for it. Add 'ops' to the routing loop and the
TOKEN_OPS case in route.sh + publish.sh, and pass TOKEN_OPS in the workflow env next to TOKEN_QA
(route/publish/rescue steps) so route.sh (set -u) doesn't error on an @ops run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 14:53:09 +03:00
Felix FaerberandClaude Opus 4.8 cf1e7178b5 fix(autopilot): merge with AGENT_TOKEN so the merge triggers the deploy
@qa's autopilot merge used the built-in Actions token (TOKEN_QA unset -> fell back to GITEA_TOKEN).
Gitea does not fire new workflow runs for pushes made by the built-in Actions token, so the merge
landed on main but deploy.yml never ran — the change was merged-but-not-deployed. Merge with
AGENT_TOKEN (a PAT, already used for delegation and proven to trigger runs) so the push to main
triggers the deploy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 23:32:12 +03:00
Felix FaerberandClaude Opus 4.8 9840c2a860 autopilot(qa): bounce back to the dev instead of halting; stop after 3 bounces
Per maintainer: @qa must never change code — it only accepts a PR or sends it back to the dev with
precise instructions. Replaces the halt-on-any-problem behavior with a bounce loop:

- QA prompt: emit MERGE_PR (approve), or `BOUNCE: @<dev>` after spelling out exactly what to change.
  HALT_AUTOPILOT is now only for problems a dev can't fix (needs a human decision).
- publish.sh: on BOUNCE, re-trigger the named dev (via AGENT_TOKEN) with "autopilot fix attempt N/3".
  Count prior attempts from the PR thread; at 3 it stops (removes the label) and hands to @ffaerber.
- publish.sh: after a dev pushes a fix (resume), auto-re-trigger @qa to re-verify — closing the loop
  (dev fix -> qa re-check -> merge or bounce again).
- Updated the initial @qa trigger wording (bounce, not halt).

Verified: BOUNCE target parsing and the 3-strike counter (attempts 1/3,2/3,3/3 then HALT).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 23:18:00 +03:00
lead df0f6d6543 @lead: issue #16 — fully-automatic autopilot (label-gated @pm auto-delegate + @qa merge) 2026-07-04 19:23:20 +00:00
Felix FaerberandClaude Opus 4.8 0a89309ff1 fix(activity-log): tool calls only — drop the agent's prose summary
The activity <details> was labelled 'tool calls & reasoning' but included the agent's final prose
summary ('Added the whoami service... Exposed via Traefik... Pushed to branch...'), which is just a
restatement of the PR description and not a tool call. Emit only tool_use events; relabel to
'N tool calls'. The what-changed narrative lives in the PR description; this section is the record of
actions taken.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 14:40:59 +03:00
Felix FaerberandClaude Opus 4.8 81882ee3ec fix(publish): de-dup agent comments (no repeated PR desc, no doubled header)
Batches the remaining comment-noise cleanups on top of the activity-log fix:
- Resume comment no longer re-posts the full PR description (## Summary/## Changes) — the PR body and
  diff already carry it; the comment just links the PR (the reasoning trail shows what the run did).
- Strip a leading self-header the model sometimes emits ("🤖 **@pm**" on its own line, sometimes
  twice) before we prepend our own, so headers aren't doubled.
- Also drop the BEGIN_PR_DESCRIPTION block from the plain reply text, and simplify the activity
  block's summary (it repeated "🤖 **@name** — activity log").

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-04 14:24:37 +03:00
senior 767a3341fd feat(publish): one comment per agent run (issue #38)
Merge the activity-log comment into the main reply comment and merge the
sub-issues-created comment into the pm reply, so each agent run posts
exactly one comment (reply + tool calls & reasoning inline).
2026-07-04 08:42:56 +00:00
lead 423a060816 fix(agent): run step scripts from outside the workspace so agents can't break the run
Stage the shared scripts into $RUNNER_TEMP and point $SCRIPTS there for every
step, so an agent that commits/deletes the in-tree .agents-workflow checkout no
longer destroys the scripts the post-agent steps run (issue #33). Scrub any
in-tree .agents-workflow artifact before publishing, and add a failure-safe
rescue step that opens a PR for pushed work when a run fails.
2026-07-04 07:34:53 +00:00
lead 36ba91cdd8 @lead: externalize agent.yml inline scripts into .gitea/workflows/scripts/*.sh
Rebased onto the per-agent skill-scoping change so PR #25 carries both:
- route.sh keeps the registry 'skills' allow-list and emits skills as a step output
- install-opencode.sh writes the permission.skill block (deny-all + allow listed)

Pure refactor otherwise: each step's shell moves to its own file, called via
bash "$SCRIPTS/<name>.sh". The two extracted SKILL.md bodies are byte-identical to
main; routing/config/publish behavior is unchanged. Because this is a reusable
workflow (workflow_call) the runtime checkout is the caller's repo, so agent.yml now
checks THIS repo out into .agents-workflow/ (pinned @main) and points $SCRIPTS there.
2026-07-04 05:54:27 +00:00