Switch from the bespoke 1136-line Python orchestrator to the community agentloop tool (https://github.com/guettli/agentloop). The new tool handles the issue → agent → PR pipeline via a label state machine using loop/plan and loop/code labels, running every 5 minutes via cron. Removes: scripts/agent_loop.py, scripts/test_agent_loop.py Removes: .forgejo/workflows/monitor.yml (no heartbeat concept in agentloop) Updates: AGENTS.md to document the new loop/ label workflow agentloop config lives in ~/agentloop/loop/sharedinbox/ on the host. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3.0 KiB
3.0 KiB
SharedInbox — Development Guide
Codeberg
We use Codeberg: https://codeberg.org/guettli/sharedinbox/
CLI tool fgj is available to query issues/PRs/actions.
Issue Label Workflow
Automation is handled by agentloop running every 5 minutes via cron. Add a label to trigger an agent:
| Label | Trigger | Outcome |
|---|---|---|
loop/plan |
Planning agent reads the issue and writes an implementation plan as a comment | Issue moves to loop/plan-done |
loop/code |
Coding agent implements the change, creates a branch + PR | Issue moves to loop/code-done |
State machine:
loop/plan → loop/plan-in-progress → loop/plan-done
↘ NeedSupervisor (on failure)
loop/code → loop/code-in-progress → loop/code-done
↘ NeedSupervisor (on failure)
Rules:
- Only issues authored by allowed users are picked up (guettli, guettlibot, guettlibot2, forgejo-actions).
- An issue with
NeedSupervisorneeds human attention — investigate, fix, then re-label. - The coding agent opens a PR but does NOT close the issue. A human reviews the PR and closes the issue after merging.
- Planning agents only post a comment — they do NOT write code or open PRs.
loop/*labels are managed by agentloop — do not set them manually while an agent is active.
Typical lifecycle for a new feature:
1. Create issue
2. Add label loop/plan → agent writes plan as comment
3. Review plan, request changes or approve
4. Add label loop/code → agent implements + opens PR
5. Review PR, merge
6. Close issue
Code conventions
- Avoid
else, use "early return".
Drift (DB)
- Schema in
lib/data/db/database.dart. - After any schema change run:
dart run build_runner build --delete-conflicting-outputs - Generated
database.g.dartis committed — do not hand-edit it.
enough_mail
- Standard pub dependency (
enough_mail: ^2.1.7inpubspec.yaml) — not vendored. - IMAP client helpers are in
lib/data/imap/imap_client_factory.dart.
Running
Flutter build dependencies (libgtk-3-dev, libepoxy-dev, libsecret-1-dev, etc.) are installed via apt
— see the Flutter Linux docs. The nix dev shell provides only tools: task, fvm, stalwart-mail.
Enter the nix dev shell first: nix develop
# Code generation (must run after schema changes)
task codegen
# Desktop
task run
# Tests
task test
Adding a screen
- Create
lib/ui/screens/my_screen.dart. - Add a
GoRouteinlib/ui/router.dart. - No separate ViewModel file needed — use
ConsumerWidget/ConsumerStatefulWidgetdirectly with Riverpod providers.
Continuous Integration (CI)
- Strategy: "Thin CI, Heavy Taskfile".
- Execution: CI must only invoke
taskcommands (e.g.,nix develop --command task check). All environment setup is handled by Nix (flake.nix), and all task orchestration is handled byTaskfile.yml. - The cli-tool
fgjis available to query/wait for CI.