Issues labelled State/ToPlan are now picked up by a dedicated planning agent before any implementation happens. The agent posts a plan as an issue comment, then the loop transitions the label to State/Planned and leaves a resume command in a follow-up comment. A human reviews the plan and manually promotes the issue to State/Ready to trigger implementation. Planning agents run at higher priority than Ready issues. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3.3 KiB
3.3 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
We use issues, follow this label state machine:
- State/ToPlan — Issue needs a plan written by an agent before implementation
- State/Planned — Plan has been posted as a comment; awaiting human review
- State/Ready — Issue is approved and ready for implementation
- State/InProgress — Set while an agent (or human) is actively working
- State/Question — Agent hit a blocker or needs clarification
Full lifecycle:
State/ToPlan → State/Planned (automated: agent_loop.py runs a planning agent)
State/Planned → State/Ready (manual: human reviews the plan and approves)
State/Ready → State/InProgress (automated: agent_loop.py before starting implementation)
State/InProgress → closed (automated: after PR is merged and CI passes)
any state → State/Question (automated or manual: when blocked)
List open issues ready to pick up:
fgj issue list --json --state open | jq '[.[] | select(.labels[].name == "State/Ready")] | .[] | {number, title, html_url}'
Rules:
- Never start implementation on an issue without
State/Ready - Planning agents only post a plan comment — they do NOT write code or open PRs
- After
State/Planned, a human must review the plan and manually addState/Ready - When working via the agent loop: label transitions are set automatically
by
agent_loop.py— do not set them yourself. - When working manually: switch to
State/InProgressas your first action:fgj issue edit <NUMBER> --remove-label "State/Ready" --add-label "State/InProgress" - If blocked, replace current state label with
State/Questionand leave a comment explaining the blocker - When done and CI is green, close the issue:
fgj issue close <NUMBER>
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.