Initial import: 10 Radix skills across 3 categories
Kategoriserer danske regnskabs-/ERP-skills, ERP-data-afstemnings-
skill og to devops-workflows (gitea-issue-agent, kanban-workflows)
som Radix-medlemmers AI-agenter kan dele.
Struktur:
skills/<kategori>/<skill-navn>/SKILL.md
skills/<kategori>/<skill-navn>/{references,templates,scripts}/
Indekseret af index.json (genereret af scripts/rebuild_index.py).
Kør `python3 scripts/rebuild_index.py --check` i CI for at fange
synkroniseringsfejl.
This commit is contained in:
@@ -0,0 +1,248 @@
|
||||
---
|
||||
name: gitea-issue-agent
|
||||
description: Build a Hermes-managed autonomous issue handler for a self-hosted Gitea instance — scan issues, analyze text + screenshot attachments, post a proposal for human approval, implement, test, push a branch, and open a Gitea PR. Use when the user wants Hermes to act on Gitea issues end-to-end with a human-in-the-loop approval gate, especially with image/visual context in the issue text.
|
||||
version: 0.1.0
|
||||
author: Hermes Agent
|
||||
license: MIT
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [gitea, issues, automation, hermes-plugin, pr-workflow, agent-loop, approval-gate]
|
||||
related_skills: [gitea-tea-macos-setup, software-engineering-workflows]
|
||||
---
|
||||
|
||||
# Gitea Issue Agent
|
||||
|
||||
End-to-end workflow for an autonomous Gitea issue handler that lives inside
|
||||
Hermes. Combines:
|
||||
|
||||
- A **Hermes plugin** exposing Gitea REST API tools (status, scan, get, fetch
|
||||
images, comment, create PR).
|
||||
- A **skill** that orchestrates the human-in-the-loop loop: propose → wait
|
||||
for approval → implement → test → push → open PR.
|
||||
- An optional **cron job** that triggers the loop on a schedule.
|
||||
|
||||
## When to use
|
||||
|
||||
- User wants Hermes to monitor issues across one or more Gitea repos and
|
||||
propose fixes autonomously.
|
||||
- Issue text often includes screenshots or design mock-ups (image support
|
||||
is a first-class requirement).
|
||||
- A human (the user) must approve each fix before code is written.
|
||||
- Push and PR creation should target a working branch the user can review
|
||||
and merge manually.
|
||||
|
||||
Do **not** use for: GitHub (use the `gitea`-equivalent catalog MCP for that),
|
||||
issues that are just questions/discussions (no code work expected), or
|
||||
workflows where the user wants fully autonomous implementation with no
|
||||
human gate.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────┐
|
||||
│ ~/.hermes/plugins/gitea-issue-agent/ │
|
||||
Cron tick → │ ├ plugin.yaml │
|
||||
│ ├ __init__.py (registers 7 tools) │
|
||||
│ └ README.md │
|
||||
└─────────────┬──────────────────────────┘
|
||||
│ exposes
|
||||
▼
|
||||
gitea_agent_status gitea_issue_agent_scan
|
||||
gitea_list_repositories gitea_get_issue
|
||||
gitea_fetch_issue_images gitea_comment_issue
|
||||
gitea_create_pull_request
|
||||
│ consumed by
|
||||
▼
|
||||
┌────────────────────────────────────────┐
|
||||
│ Hermes skill gitea-issue-agent-loop │
|
||||
│ (orchestrates: scan → propose → wait │
|
||||
│ → implement → test → push → PR) │
|
||||
└─────────────┬──────────────────────────┘
|
||||
│ triggers
|
||||
▼
|
||||
┌────────────────────────────────────────┐
|
||||
│ Cron job (optional) "every 30m" │
|
||||
│ "Scan Gitea issues, propose solutions │
|
||||
│ for new ones, implement approved." │
|
||||
└────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
The plugin does **not** implement the loop — it only exposes the API
|
||||
surface. The loop lives in the skill and the cron prompt. This separation
|
||||
keeps the plugin small and lets the loop evolve without code changes to
|
||||
the plugin.
|
||||
|
||||
## Required environment variables
|
||||
|
||||
Add to `~/.hermes/.env` and restart the gateway:
|
||||
|
||||
```bash
|
||||
GITEA_BASE_URL=https://git.example.dk
|
||||
GITEA_TOKEN=*** service-bruger PAT, scope: read+write issues/PRs/attachments>
|
||||
GITEA_APPROVER_LOGIN=<the user's Gitea login, e.g. "dennis">
|
||||
GITEA_DEFAULT_BASE_BRANCH=main
|
||||
# Optional: comma-separated allowlist. If empty, /user/repos is scanned.
|
||||
GITEA_REPOS=owner/repo1,owner/repo2
|
||||
GITEA_AGENT_REPO_LIMIT=200
|
||||
GITEA_AGENT_ISSUE_LIMIT_PER_REPO=50
|
||||
```
|
||||
|
||||
Two Gitea identities, kept separate:
|
||||
|
||||
- `GITEA_TOKEN` → service-bruger account (e.g. `hermes-issues`). Posts
|
||||
comments and PRs as a bot.
|
||||
- `tea` CLI → the **user's personal** token, e.g. `dennis`. Used for
|
||||
local git push of branches the user owns.
|
||||
|
||||
Mixing them causes comments to look like they came from the human
|
||||
personally. See `references/identity-and-safety.md`.
|
||||
|
||||
## Tool set (the plugin registers these)
|
||||
|
||||
| Tool | Purpose |
|
||||
| --- | --- |
|
||||
| `gitea_agent_status` | Verify config + API connectivity; reports `authenticated_user`. |
|
||||
| `gitea_list_repositories` | List repos visible to the token (or `GITEA_REPOS` allowlist). |
|
||||
| `gitea_issue_agent_scan` | Scan open issues, classify each as `new` / `awaiting_approval` / `approved` / `pr_ready`. Returns short summary + image count. |
|
||||
| `gitea_get_issue` | Fetch one issue + comments + image links + classification status. |
|
||||
| `gitea_fetch_issue_images` | Download all screenshots/attachments from the issue + comments to a local cache, so `vision_analyze` can inspect them. |
|
||||
| `gitea_comment_issue` | Post a comment; optional `marker` arg (`proposal` or `pr_ready`) prepends an HTML marker the scanner uses to track state. |
|
||||
| `gitea_create_pull_request` | Open a PR from an already-pushed branch. The branch must be created and pushed by the agent via `git`/`terminal` first. |
|
||||
|
||||
Every tool returns JSON of the shape `{"success": true, ...}` or
|
||||
`{"success": false, "error": "..."}`. JSON is the only contract; the
|
||||
agent's loop should branch on `success` and surface `error` verbatim.
|
||||
|
||||
## The workflow (the loop the skill/cron implements)
|
||||
|
||||
1. **Scan**: `gitea_issue_agent_scan` to find `status == "new"` issues.
|
||||
2. **For each new issue**:
|
||||
1. `gitea_get_issue` for full text + comments.
|
||||
2. `gitea_fetch_issue_images` to download any screenshots to
|
||||
`~/.hermes/cache/gitea-issue-agent/<owner>/<repo>/<index>/`.
|
||||
3. `vision_analyze` on each image (loaded into context) so the
|
||||
proposal is grounded in what the screenshot actually shows.
|
||||
4. Draft a proposal (in Danish if the user is Danish-speaking) covering:
|
||||
- summary of the bug/feature
|
||||
- root-cause hypothesis
|
||||
- proposed change (files, tests, branch name)
|
||||
- explicit approval request
|
||||
5. `gitea_comment_issue` with `marker="proposal"`. The plugin
|
||||
prepends the `<!-- hermes:gitea-issue-agent v1 status=proposal -->`
|
||||
marker so the next scan classifies this issue as `awaiting_approval`.
|
||||
3. **Stop and wait for approval.** Do not implement. The skill exits
|
||||
cleanly; the cron re-scans later and the human will have either:
|
||||
- Posted an approval comment (matched by `APPROVAL_RE` against
|
||||
`GITEA_APPROVER_LOGIN`), or
|
||||
- Applied one of the approval labels (`hermes-approved`,
|
||||
`approved-by-dennis`, `dennis-approved`).
|
||||
4. **On the next scan**, issues that satisfy the approval rule are
|
||||
classified as `approved`. The skill then:
|
||||
1. `cd` into the local clone of the repo (clone it first via
|
||||
`git clone` if not present — `tea clone` will fail on non-standard
|
||||
SSH ports, see `gitea-tea-macos-setup`).
|
||||
2. Create a branch `hermes/issue-<n>-<slug>`.
|
||||
3. Implement, run tests, commit, push (with token in URL or via
|
||||
`~/.netrc`).
|
||||
4. `gitea_create_pull_request` with `head=hermes/issue-<n>-<slug>`,
|
||||
`base=main`, `body` linking to the issue, `draft=true`.
|
||||
5. `gitea_comment_issue` with `marker="pr_ready"` and the PR URL.
|
||||
5. **Stop.** The user reviews the PR in Gitea and merges by hand.
|
||||
|
||||
The two state markers (`proposal`, `pr_ready`) are the only state
|
||||
machine. They survive Gitea restarts, plugin reloads, and Hermes
|
||||
restarts, because they live in the issue's comment history.
|
||||
|
||||
## Approval semantics (default)
|
||||
|
||||
- A comment from `GITEA_APPROVER_LOGIN` matching
|
||||
`(?is)(@?hermes|agent|bot).{0,80}(godkend|approved|ok|go)` counts as
|
||||
approval. Danish is first-class because the user is Danish-speaking.
|
||||
- Any of these labels applied by a maintainer also counts:
|
||||
`hermes-approved`, `approved-by-dennis`, `dennis-approved`.
|
||||
- Approval is only counted if it is **after** the latest `proposal`
|
||||
comment. Re-approving an old proposal does nothing.
|
||||
- If `GITEA_APPROVER_LOGIN` is not set, free-form approval comments are
|
||||
ignored — only labels count. This is the safe default until the user
|
||||
has decided which login should be allowed to approve.
|
||||
|
||||
For a longer rationale, see `references/identity-and-safety.md`.
|
||||
|
||||
## Install checklist (do these in order)
|
||||
|
||||
1. Decide on a service-bruger name (e.g. `hermes-issues`) and create a
|
||||
Gitea PAT for it with `repository` (read+write) + `issue` (write) scope.
|
||||
2. Tell the user the env vars they need to set in `~/.hermes/.env` (see
|
||||
above). The agent **cannot** edit `.env` itself — Hermes blocks it
|
||||
at the tool layer. See `references/identity-and-safety.md` for why.
|
||||
3. Drop the plugin files into `~/.hermes/plugins/gitea-issue-agent/`
|
||||
(`plugin.yaml` + `__init__.py` + `README.md`).
|
||||
4. Tell the user to add `- gitea-issue-agent` under `plugins.enabled`
|
||||
in `~/.hermes/config.yaml`. The agent **cannot** edit `config.yaml`
|
||||
either — same reason.
|
||||
5. Restart the gateway: `hermes gateway restart`.
|
||||
6. Verify with `hermes chat -q "Kald gitea_agent_status" -t gitea_issue_agent`
|
||||
— `api_ok: true`, `authenticated_user: hermes-issues` (or whatever the
|
||||
service-bruger is named).
|
||||
7. Verify the local CLI path: `tea login add --name <user> --url ...`,
|
||||
`tea whoami`, then `git clone` any visible repo (don't rely on
|
||||
`tea clone` — see `gitea-tea-macos-setup` for the SSH-port-2224 trap).
|
||||
8. Only then create the cron job, and only after the user has
|
||||
approved running it unattended.
|
||||
|
||||
## Verification
|
||||
|
||||
Use the bundled script `scripts/verify-plugin-and-gitea.sh` to confirm
|
||||
the plugin is loaded, the API is reachable, and at least one repo is
|
||||
visible. It should print `OK` lines and exit 0.
|
||||
|
||||
## Pitfalls (learned)
|
||||
|
||||
- **Hermes blocks the agent from writing to `~/.hermes/config.yaml` and
|
||||
`~/.hermes/.env`.** The right move when blocked is to give the user
|
||||
the exact one-line edit and stop. Do not try `execute_code`, `patch`,
|
||||
or `write_file` a different way — the guard fires on all of them.
|
||||
See `references/identity-and-safety.md`.
|
||||
- **`tea clone` fails opaquely when SSH is on a non-standard port
|
||||
(e.g. 2224).** Use `git clone` with the HTTPS `clone_url` from the
|
||||
Gitea API. Strip the token from `origin` immediately.
|
||||
- **Stale `osxkeychain` credentials can sabotage `git push` even when
|
||||
the token is correct.** Switch to `~/.netrc` with `chmod 600`. See
|
||||
the troubleshooting reference in `gitea-tea-macos-setup`.
|
||||
- **Service-bruger identity matters.** The plugin's `authenticated_user`
|
||||
field should NOT be your personal login. If it is, create a separate
|
||||
service-bruger or you'll get bot comments attributed to you.
|
||||
- **Free-form approval comments must be gated by a known login** (or
|
||||
by maintainer-applied labels) — otherwise a co-worker saying "looks
|
||||
good!" could trigger an autonomous push.
|
||||
- **First run: verify, don't cron.** Always run a manual scan + a
|
||||
manually-approved test issue before scheduling cron. A cron job
|
||||
firing off PRs in the user's name is the failure mode to avoid.
|
||||
- **Image analysis is mandatory for screenshot issues.** The plugin
|
||||
extracts image URLs and downloads them locally; the skill MUST call
|
||||
`vision_analyze` on each before writing the proposal, otherwise the
|
||||
proposal will be blind to what the screenshot shows.
|
||||
- **Plugin state is in issue comments, not in plugin memory.** The
|
||||
proposal/PR markers make the workflow restart-safe.
|
||||
|
||||
## Related skills
|
||||
|
||||
- `gitea-tea-macos-setup` — the local `tea` + `git` + `osxkeychain`
|
||||
setup that the agent relies on. Includes the SSH-port-2224 trap and
|
||||
the `getlogin(2)` gotcha.
|
||||
- `software-engineering-workflows` — the plan / spike / TDD / debugging
|
||||
patterns the implement-and-test phase of the loop should follow.
|
||||
- `software-development/simplify-code` — useful to invoke on the
|
||||
agent's own code changes before opening the PR.
|
||||
|
||||
## Files in this skill
|
||||
|
||||
- `scripts/verify-plugin-and-gitea.sh` — one-shot verification of the
|
||||
full setup (plugin loaded + API reachable + repos visible + clone
|
||||
works). Run it after every change to the env or plugin.
|
||||
- `references/identity-and-safety.md` — service-bruger vs personal
|
||||
identity split, Hermes safety-guard reality, approval-gate design
|
||||
rationale.
|
||||
- `templates/proposal-comment.md` — starter template for the
|
||||
`gitea_comment_issue` body when posting a proposal. Copy, fill in
|
||||
the issue-specific bits, send.
|
||||
@@ -0,0 +1,101 @@
|
||||
# Identity and safety in the Gitea issue agent
|
||||
|
||||
## Two identities, one Gitea server
|
||||
|
||||
The setup has two Gitea users that should remain separate:
|
||||
|
||||
| Identity | Token stored in | Used for | What it posts |
|
||||
| --- | --- | --- | --- |
|
||||
| **Service-bruger** (e.g. `hermes-issues`) | `GITEA_TOKEN` in `~/.hermes/.env` | All plugin tool calls: scan, comment, create PR | Comments and PRs attributed to the bot |
|
||||
| **Personal user** (e.g. `dennis`) | `tea` login + `~/.netrc` | Local `git push` of branches the agent created | Commits and merges attributed to you |
|
||||
|
||||
The plugin's `gitea_agent_status` reports `authenticated_user`. If it
|
||||
reports your personal login, the bot will post comments as you — fix
|
||||
the `GITEA_TOKEN` before scheduling any cron job.
|
||||
|
||||
## Why the Hermes safety-guards exist (and why the agent can't bypass them)
|
||||
|
||||
Hermes has three layers of "agent cannot edit" protection, all by
|
||||
design:
|
||||
|
||||
1. **`~/.hermes/config.yaml`** — gates plugin load, model selection,
|
||||
toolsets, gateway config. An agent that could rewrite this could
|
||||
give itself new tools, change providers, or open outbound network
|
||||
channels. The `patch` tool explicitly refuses:
|
||||
`Refusing to write to Hermes config file: ... Agent cannot modify
|
||||
security-sensitive configuration.`
|
||||
|
||||
2. **`~/.hermes/.env`** — contains API keys, tokens, passwords. The
|
||||
`write_file`, `patch`, and `execute_code` tools all refuse to
|
||||
modify it.
|
||||
|
||||
3. **`execute_code` with file writes** — when a script is going to
|
||||
write files under `~/.hermes/`, the safety guard blocks it
|
||||
unconditionally: `BLOCKED: execute_code script timed out without
|
||||
user response.`
|
||||
|
||||
**The right move when blocked:** give the user the exact one-line
|
||||
edit (or `cat > file <<EOF ... EOF` block) and stop. Do not try
|
||||
alternative tools, do not retry, do not work around it. The user
|
||||
must run the edit themselves.
|
||||
|
||||
This is not a bug. It is the threat model.
|
||||
|
||||
## Approval-gate design rationale
|
||||
|
||||
The agent should never implement, push, or open a PR for an issue
|
||||
that hasn't been approved. This protects against three classes of
|
||||
mistake:
|
||||
|
||||
1. **Misread issue** — the user wanted "fix the X button", the agent
|
||||
rewrote `X()` in 14 files. Approval forces a human to look at the
|
||||
proposal first.
|
||||
2. **Out-of-scope issue** — the user wanted to push back, not fix.
|
||||
Approval makes "no" cheap (just don't reply).
|
||||
3. **Bad agent day** — the LLM hallucinated, the issue got a wrong
|
||||
proposal, the agent is in a weird state. Approval makes the loop
|
||||
recoverable without reverting commits.
|
||||
|
||||
The two state markers (`proposal`, `pr_ready`) survive Hermes
|
||||
restarts, plugin reloads, and Gitea restarts, because they live in
|
||||
the issue's comment history. The agent never has to remember
|
||||
anything to resume — it can re-scan and pick up where it left off.
|
||||
|
||||
## Approval matching — why it requires a known login by default
|
||||
|
||||
The default approval regex is permissive enough to handle Danish
|
||||
("godkend", "godkender") and English ("approve", "approved", "ok",
|
||||
"go") in either order with the agent mention. But without a
|
||||
known-login check, **any user** with write access to the repo could
|
||||
say "looks good, agent" in a comment and trigger a push. That's a
|
||||
prompt-injection vector — a malicious screenshot, or a co-worker
|
||||
joking, could authorize code execution.
|
||||
|
||||
Two safe modes:
|
||||
|
||||
- **Label-only mode** (the default until `GITEA_APPROVER_LOGIN` is
|
||||
set): a maintainer applies one of three labels. Labels can only
|
||||
be applied by users with write access, so the trust surface is
|
||||
the maintainer set, not "anyone who can comment".
|
||||
- **Login-gated mode** (once `GITEA_APPROVER_LOGIN` is set): a
|
||||
comment from that specific user, matching the regex, AND
|
||||
after the latest proposal comment. This is the strict mode.
|
||||
|
||||
If the user wants both, both work — labels OR login-comment. If they
|
||||
want neither (auto-implement everything), they should set both
|
||||
`GITEA_APPROVER_LOGIN` and approve a *meta-issue* saying "always
|
||||
implement" — but that's not the default and not recommended.
|
||||
|
||||
## The first run is always manual
|
||||
|
||||
Before scheduling a cron, the user must:
|
||||
|
||||
1. Run a manual `gitea_issue_agent_scan` and confirm issues show up.
|
||||
2. Pick a real issue and walk it through: scan → fetch images →
|
||||
analyze → propose → wait → approve → implement → test → push →
|
||||
PR.
|
||||
3. Confirm the PR body links to the issue, the commit message is
|
||||
reasonable, and `git log` shows the expected author/email.
|
||||
4. **Then** schedule a cron. The cron prompt itself should be
|
||||
minimal — "scan, propose for new issues, implement approved" —
|
||||
with a clear hand-off to the skill for the details.
|
||||
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env bash
|
||||
# Verify the Gitea issue agent is wired up end to end.
|
||||
#
|
||||
# Exits 0 on success. Prints OK / FAIL lines for each step.
|
||||
# Run after every env or plugin change.
|
||||
#
|
||||
# Does NOT need a real token in the script — reads from ~/.hermes/.env.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
ok() { echo " OK $*"; }
|
||||
bad() { echo " FAIL $*"; exit 1; }
|
||||
|
||||
echo "=== 1. Plugin files present ==="
|
||||
PLUGIN_DIR="$HOME/.hermes/plugins/gitea-issue-agent"
|
||||
for f in plugin.yaml __init__.py README.md; do
|
||||
[ -f "$PLUGIN_DIR/$f" ] && ok "$f" || bad "$PLUGIN_DIR/$f missing"
|
||||
done
|
||||
|
||||
echo
|
||||
echo "=== 2. Plugin listed in config.yaml ==="
|
||||
grep -q "gitea-issue-agent" "$HOME/.hermes/config.yaml" \
|
||||
&& ok "config.yaml references gitea-issue-agent" \
|
||||
|| bad "gitea-issue-agent not in plugins.enabled — add it under plugins.enabled in ~/.hermes/config.yaml"
|
||||
|
||||
echo
|
||||
echo "=== 3. Plugin imports without error ==="
|
||||
python3 - <<'PY' && ok "import gitea-issue-agent OK" || bad "import failed"
|
||||
import importlib.util, sys
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
"gitea_issue_agent",
|
||||
f"{__import__('os').path.expanduser('~')}/.hermes/plugins/gitea-issue-agent/__init__.py",
|
||||
)
|
||||
mod = importlib.util.module_from_spec(spec)
|
||||
sys.modules["gitea_issue_agent"] = mod
|
||||
spec.loader.exec_module(mod)
|
||||
assert len(mod.SCHEMAS) >= 5, f"expected at least 5 tools, got {len(mod.SCHEMAS)}"
|
||||
PY
|
||||
|
||||
echo
|
||||
echo "=== 4. Env vars present ==="
|
||||
set +e
|
||||
. "$HOME/.hermes/.env" 2>/dev/null
|
||||
set -e
|
||||
[ -n "${GITEA_BASE_URL:-}" ] && ok "GITEA_BASE_URL=$GITEA_BASE_URL" || bad "GITEA_BASE_URL missing in ~/.hermes/.env"
|
||||
[ -n "${GITEA_TOKEN:-}" ] && ok "GITEA_TOKEN set (${#GITEA_TOKEN} chars)" || bad "GITEA_TOKEN missing in ~/.hermes/.env"
|
||||
|
||||
echo
|
||||
echo "=== 5. API connectivity ==="
|
||||
HTTP=$(curl -4 -s -o /dev/null -m 10 -w "%{http_code}" \
|
||||
-H "Authorization: token $GITEA_TOKEN" \
|
||||
"$GITEA_BASE_URL/api/v1/user")
|
||||
if [ "$HTTP" = "200" ]; then
|
||||
USER=$(curl -4 -s -m 10 -H "Authorization: token $GITEA_TOKEN" \
|
||||
"$GITEA_BASE_URL/api/v1/user" | python3 -c "import sys,json; print(json.load(sys.stdin).get('login','?'))")
|
||||
ok "API reachable, authenticated as: $USER"
|
||||
else
|
||||
bad "API $GITEA_BASE_URL/api/v1/user returned HTTP $HTTP"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "=== 6. At least one repo visible ==="
|
||||
N=$(curl -4 -s -m 10 -H "Authorization: token $GITEA_TOKEN" \
|
||||
"$GITEA_BASE_URL/api/v1/user/repos?limit=100" | python3 -c "import sys,json; print(len(json.load(sys.stdin)))")
|
||||
[ "$N" -gt 0 ] && ok "$N repos visible to token" || bad "no repos visible — token scope may be too narrow"
|
||||
|
||||
echo
|
||||
echo "=== 7. local tea login (optional but recommended) ==="
|
||||
if command -v tea >/dev/null 2>&1; then
|
||||
TUSER=$(tea whoami 2>/dev/null | grep -E "^[a-zA-Z0-9_-]+$" | head -1)
|
||||
[ -n "$TUSER" ] && ok "tea whoami -> $TUSER" || echo " INFO tea installed but no login yet"
|
||||
else
|
||||
echo " INFO tea not on PATH — see gitea-tea-macos-setup"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "=== 8. ~/.netrc (optional but recommended) ==="
|
||||
if [ -f "$HOME/.netrc" ] && grep -q "git.radixadm.dk\|$GITEA_BASE_URL" "$HOME/.netrc"; then
|
||||
ok "~/.netrc has an entry for $GITEA_BASE_URL"
|
||||
else
|
||||
echo " INFO ~/.netrc missing — git push will use osxkeychain (may be stale)"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "All checks passed. The agent is ready to use."
|
||||
@@ -0,0 +1,40 @@
|
||||
<!-- hermes:gitea-issue-agent v1 status=proposal -->
|
||||
|
||||
## Analyse
|
||||
|
||||
<kort resumé af hvad issuet beder om — i dansk hvis brugeren er dansk>
|
||||
|
||||
## Screenshots / visuelle referencer
|
||||
|
||||
<bullet-liste over hvad hver screenshot viser og hvad vi har udledt af den>
|
||||
|
||||
## Rod-hypotese
|
||||
|
||||
<1-3 bullets der peger på den underliggende årsag, ikke symptomet>
|
||||
|
||||
## Foreslået ændring
|
||||
|
||||
- **Repo:** `<owner>/<repo>`
|
||||
- **Branch:** `hermes/issue-<index>-<kort-slug>`
|
||||
- **Filer der forventes ændret:**
|
||||
- `<sti/til/fil.py>` — <hvad og hvorfor>
|
||||
- `<sti/til/test_x.py>` — ny test der dækker regressionen
|
||||
- **Risiko:** lav / medium / høj — <begrundelse>
|
||||
|
||||
## Test-plan
|
||||
|
||||
- `docker compose exec web python manage.py test <app>` skal køre grønt
|
||||
- Manuel verify: <trin brugeren kan tjekke i UI>
|
||||
- Hvis relevant: <evt. playwright/screenshot-verifikation>
|
||||
|
||||
## Spørgsmål til Dennis
|
||||
|
||||
- <evt. valg brugeren skal tage før implementering — f.eks. "skal eksisterende data migreres, eller kun nye records?">
|
||||
|
||||
## Godkend
|
||||
|
||||
Hvis du vil have mig til at implementere det her, så svar med:
|
||||
|
||||
> @hermes godkend
|
||||
|
||||
(eller sæt label `hermes-approved` på issuet)
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
name: kanban-workflows
|
||||
description: "Use when operating Hermes Kanban workflows: decomposing work as an orchestrator, executing as a worker, managing lanes, status, blockers, and reconciliation."
|
||||
version: 1.0.0
|
||||
author: Hermes Agent
|
||||
license: MIT
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [kanban, orchestration, workers, task-management, hermes]
|
||||
related_skills: [autonomous-coding-agents]
|
||||
---
|
||||
|
||||
# Kanban Workflows Umbrella
|
||||
|
||||
## Overview
|
||||
|
||||
Kanban work has two sides: orchestrators decompose and route work without doing it themselves; workers execute a scoped card, keep status current, and return verifiable evidence. Use this umbrella for both roles.
|
||||
|
||||
## When to Use
|
||||
|
||||
- Acting as a Hermes Kanban orchestrator.
|
||||
- Acting as a Hermes Kanban worker.
|
||||
- Deciding whether to split, assign, block, or reconcile cards.
|
||||
- Handling worker pitfalls, examples, and edge cases.
|
||||
|
||||
## Role Playbooks
|
||||
|
||||
### Orchestrator
|
||||
|
||||
Decompose outcomes into cards small enough for one worker, include acceptance criteria, and avoid the temptation to implement the work directly. Route work, unblock workers, and reconcile results.
|
||||
|
||||
### Worker
|
||||
|
||||
Own exactly the assigned card. Update status when starting, blocked, or done. Run the requested checks and return concise evidence: files changed, commands run, output, and remaining risks.
|
||||
|
||||
### Lanes and external agents
|
||||
|
||||
If a worker uses an external coding agent lane, keep Kanban as the source of truth and verify the lane's output before closing the card.
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
1. Orchestrators doing implementation work themselves.
|
||||
2. Workers broadening scope beyond the card.
|
||||
3. Closing cards from self-reports without independent verification.
|
||||
4. Losing blocker state instead of surfacing it promptly.
|
||||
|
||||
## Package Notes
|
||||
|
||||
Archived source skills retain the deeper role-specific text: `kanban-orchestrator` and `kanban-worker`.
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
- [ ] Card scope and acceptance criteria are explicit.
|
||||
- [ ] Exactly one owner is responsible for each action.
|
||||
- [ ] Status reflects reality: pending, in progress, blocked, done.
|
||||
- [ ] Completion includes verifiable evidence.
|
||||
Reference in New Issue
Block a user