| name | implementing-fdb-features |
| description | Implements features, functionalities, and improvements to fdb and its packages. Use when creating new features, adding new commands, or improving existing functionality in fdb or fdb_helper. |
| metadata | {"internal":true} |
Workflow checklist
Copy this into mcp_Todowrite at the start of every feature session and tick off each item as you go:
Capture:
- [ ] Read issue in full and claim it (bd update <id> --claim)
Setup:
- [ ] Create worktree (mcp_Git-worktree create <name> main)
- [ ] Run task setup in the worktree
Implementation:
- [ ] Core models: lib/core/commands/<name>/<name>_models.dart
- [ ] Core verb: lib/core/commands/<name>/<name>.dart
- [ ] CLI adapter: lib/cli/adapters/<name>_cli.dart
- [ ] Register case + usage string in bin/fdb.dart
- [ ] fdb_helper handler (if needed): packages/fdb_helper/lib/src/handlers/<name>_handler.dart
- [ ] Register in fdb_binding.dart (if handler added)
- [ ] Test app changes in example/test_app/lib/main.dart (if needed)
Taskfile tests:
- [ ] test:<command> task added following existing pattern
- [ ] Task added to smoke sequence
- [ ] task analyze passes (dart analyze + dart format + flutter analyze)
Docs:
- [ ] README.md — commands table
- [ ] .agents/skills/testing-fdb/SKILL.md — individual test list
- [ ] lib/skill/SKILL.md — usage examples (load creating-opencode-skills skill first)
- [ ] doc/agent-scenarios.md — add scenario for the new/changed command
Agent scenarios (delegated):
- [ ] Spawn scenarios agent with worktree path + scenario IDs to run
- [ ] Triage every failure: scenario doc fix, pre-existing bug, or regression
- [ ] User approves triage findings before any bug issues are filed
- [ ] All failures resolved (fixed, scenario corrected, or filed as separate bugs)
Review loop (delegated):
- [ ] Spawn reviewing-fixing-loop agent
- [ ] All findings resolved or triaged
Checks (delegated):
- [ ] Spawn checks agent (dart analyze + flutter analyze + dart format)
- [ ] All clean
Platform tests (ALL mandatory before PR):
- [ ] macOS — task test:<command> passes
- [ ] Android physical — task test:<command> passes
- [ ] iOS simulator — task test:<command> passes
- [ ] Full smoke suite: task smoke (Android)
PR:
- [ ] Load humanizing-ai-text skill before writing PR body
- [ ] Load managing-pr-descriptions-global skill
- [ ] Push branch
- [ ] Open PR (gh pr create)
- [ ] CI green (gh pr checks --watch)
Merge:
- [ ] bd close <id> + copy issues.jsonl into worktree + commit + push
- [ ] gh pr merge --squash --delete-branch
- [ ] Remove worktree (mcp_Git-worktree remove <name>)
Step 1 — Capture the feature
1a — Starting from a chat pitch (no issue yet)
Create the GitHub issue before touching any code:
gh issue create \
--title "feat: fdb <command> — <short description>" \
--body "..." \
--repo andrzejchm/fdb
Issue must include: problem statement, exact CLI interface + flags, stdout output tokens (THING=value), stderr error format, implementation notes, test app widget changes (if any), acceptance criteria checkboxes.
Only proceed to Step 2 after the issue is created.
1b — Starting from an existing issue
gh issue view <number> --repo andrzejchm/fdb
bd update <id> --claim
Do not deviate from the specified output tokens or CLI flags without updating the issue first.
Step 2 — Create a worktree
mcp_Git-worktree action=create name=<feature-name> ref=main
Run setup inside the worktree:
task setup
Step 3 — Implement
Read these files before writing any code:
AGENTS.md — project overview and directory layout
CODE-STYLE.md — Dart style rules
packages/fdb_helper/AGENTS.md — handler architecture rules
lib/core/commands/scroll_to/scroll_to.dart — canonical core verb
lib/cli/adapters/scroll_to_cli.dart — canonical CLI adapter
packages/fdb_helper/lib/src/handlers/scroll_to_handler.dart — canonical handler
Do not implement or refactor fdb code before reading CODE-STYLE.md. It defines the architecture boundaries, output contracts, import rules, controller command layout, and file-size rules agents must preserve.
Core models (lib/core/commands/<name>/<name>_models.dart):
<Name>Input typedef (named record)
- Sealed
<Name>Result hierarchy — one variant per outcome
Core verb (lib/core/commands/<name>/<name>.dart):
- One public function:
Future<<Name>Result> verbName(<Name>Input input)
- Never throws — catch everything, return a sealed result variant
- Re-export models:
export 'package:fdb/core/commands/<name>/<name>_models.dart';
- VM calls:
vmServiceCall('ext.fdb.yourExt', params: params)
CLI adapter (lib/cli/adapters/<name>_cli.dart):
- One public function:
Future<int> runXxxCli(List<String> args)
- Use
runCliAdapter(parser, args, _execute) from lib/cli/args_helpers.dart
package:args ArgParser — no manual for-loop parsing
- Required option check:
if (results.option('x') == null) { stderr.writeln('ERROR: ...'); return 1; }
- Success tokens → stdout
UPPER_SNAKE_CASE; errors → stderr ERROR:
- Register in
bin/fdb.dart: case 'your-command': return runXxxCli(args); + usage string
fdb_helper handler (packages/fdb_helper/lib/src/handlers/<name>_handler.dart) — only if the command needs the Flutter app side:
- One public function:
Future<developer.ServiceExtensionResponse> handleXxx(String method, Map<String, String> params)
- No classes — top-level functions only; helpers are private
- Register in
fdb_binding.dart: one _registerExtension('ext.fdb.xxx', handleXxx) line
Docs to update:
README.md — commands table
.agents/skills/testing-fdb/SKILL.md — add task test:<command> to individual test list
lib/skill/SKILL.md — add usage examples with output tokens; load creating-opencode-skills skill before editing to follow spec-sheet style rules
Step 4 — Add Taskfile tests
test:your-command:
desc: <short description>
dir: '{{.TEST_APP}}'
cmds:
- |
echo "==> <scenario>"
OUTPUT=$({{.FDB}} your-command --flag value 2>&1)
EXIT_CODE=$?
echo "$OUTPUT"
if [ $EXIT_CODE -ne 0 ]; then
echo "FAIL: fdb your-command exited with code $EXIT_CODE" >&2
exit 1
fi
if echo "$OUTPUT" | grep -q "YOUR_TOKEN="; then
echo "PASS: fdb your-command"
else
echo "FAIL: fdb your-command - YOUR_TOKEN= not found" >&2
exit 1
fi
- Add to
smoke task sequence in the right position
- Cover all acceptance criteria from the issue
- Use
mktemp -d for temp files (macOS + Linux compatible — never mktemp path/XXXXXX.ext)
Verify:
task test:launch DEVICE=<id>
task test:your-command
task analyze
Step 4b — Spawn agent scenarios runner (DELEGATE)
Taskfile tests grep for output tokens — binary pass/fail. They cannot catch
semantic regressions (wrong screen scope, elements leaking from other routes,
incorrect visible text, etc.). The scenarios in doc/agent-scenarios.md fill
this gap: the subagent runs fdb commands against the live test app and evaluates
the actual output against a semantic checklist.
Decide which scenarios to run:
- Always include
S1 (home screen baseline) as a sanity check.
- Include every scenario that covers the command you added or changed.
- If you added a new command, add its scenario to
doc/agent-scenarios.md
first, then include it in the delegation.
Spawn a general subagent with this prompt:
Read doc/agent-scenarios.md, then run scenarios <S1, S2, ...> against the
app running in `.worktrees/<feature-name>/example/test_app`.
Rules — NO EXCEPTIONS:
- Run every step EXACTLY as written. Do NOT modify commands or add flags.
- Do NOT retry with different selectors or workarounds.
- Do NOT fix code, app state, or test setup.
- If a step errors or output doesn't match "What to verify", mark FAIL and stop that scenario.
- Your only job is to execute and report.
Return PASS or FAIL for each scenario with the exact output and the specific
checks that failed.
When the subagent returns, triage every failure before proceeding:
For each failing scenario, ask:
- Is the "What to verify" assertion itself wrong (bad token, wrong type name,
missing setup step)? → Update the scenario in
doc/agent-scenarios.md.
Do NOT open a bug. Explain the correction to the user.
- Is the failure caused by pre-existing broken behavior unrelated to this
feature? → Investigate the root cause. Report findings to the user with a
clear description of expected vs actual behavior, then propose a new bug
issue. Wait for user approval before filing.
- Is the failure a regression introduced by this feature? → Fix it before
proceeding. This is a blocker.
Do not proceed to Step 5 until all failures are triaged and either fixed,
corrected in the scenario doc, or approved as separate bug issues by the user.
Step 5 — Spawn review-fix loop agent (DELEGATE)
Spawn a coding subagent with this prompt:
Run a review-fixing loop on the <feature-name> implementation in the git
worktree at `.worktrees/<feature-name>`.
Review against:
1. GitHub issue acceptance criteria
2. CODE-STYLE.md and packages/fdb_helper/AGENTS.md
3. Edge cases and error handling
4. Output token format
5. Taskfile test coverage
6. Doc completeness (README, testing-fdb/SKILL.md, lib/skill/SKILL.md)
Fix all real findings. Commit and push when the loop converges.
Step 6 — Spawn checks agent (DELEGATE)
Spawn a coding subagent with this prompt:
Run all static analysis and format checks on the fdb worktree at
`.worktrees/<feature-name>`.
1. dart pub get
2. dart analyze lib/ bin/ test/
3. dart format --page-width 120 --trailing-commas preserve --set-exit-if-changed lib/ bin/ test/
4. cd packages/fdb_helper && flutter analyze --suppress-analytics
Fix ALL issues. Commit and push. Return exact output of each check.
Step 7 — Manual platform testing (MANDATORY)
All three platforms must pass before opening a PR. No exceptions.
Devices:
- macOS:
DEVICE_ID=macos
- Android physical:
DEVICE_ID=b433094a
- iOS simulator:
DEVICE_ID=C1DE4562-CFBF-45D8-B79E-740A11E86171
For each platform:
cd .worktrees/<feature-name>/example/test_app
dart run ../../bin/fdb.dart kill 2>/dev/null || true
dart run ../../bin/fdb.dart launch --device <DEVICE_ID>
task test:<command>
dart run bin/fdb.dart kill
Platform notes:
- macOS:
fdb restart (SIGUSR2) is unreliable — use kill + launch between scenarios
- Android: first build is slow (3-5 min);
adb must be on PATH
- iOS simulator:
xcrun must be on PATH
Full smoke suite (after all three platforms pass):
task smoke
Step 8 — Open PR
Load humanizing-ai-text and managing-pr-descriptions-global skills before writing the PR body.
gh pr create \
--title "feat: <short summary>" \
--body "..." \
--repo andrzejchm/fdb
PR body: 1-2 sentences explaining why this exists and what it enables. No file lists. No counts. Closes #<number>.
Wait for CI:
gh pr checks <pr-number> --repo andrzejchm/fdb --watch
Do not merge until CI is green.
Step 9 — Merge and clean up
bd close <issue-id>
cp <repo-root>/.beads/issues.jsonl .beads/issues.jsonl
git add .beads/issues.jsonl
git commit -m "chore(bd): close <issue-id>"
git push
gh pr merge <number> --squash --delete-branch --repo andrzejchm/fdb
mcp_Git-worktree action=remove name=<feature-name>
Key invariants
fdb_binding.dart is registration-only — no handler logic
- Each handler = one file, one public
handleXxx function, no classes
- CLI adapters use
package:args via runCliAdapter — no manual for-loop parsing
fdb_helper production dependencies: must not grow without explicit approval
- All three platforms must pass before PR — no exceptions
- Review-fix loop and checks are always delegated to subagents
bd close must run on the feature branch before merging
Reference files
| File | Purpose |
|---|
AGENTS.md | Project overview, directory layout |
CODE-STYLE.md | Dart style, architecture rules |
packages/fdb_helper/AGENTS.md | Handler file layout, binding rules |
TESTING.md | Test commands and conventions |
doc/agent-scenarios.md | Semantic scenarios for agent-driven regression testing |
Taskfile.yml | All test tasks and smoke sequence |
lib/core/commands/scroll_to/scroll_to.dart | Canonical core verb |
lib/cli/adapters/scroll_to_cli.dart | Canonical CLI adapter |
packages/fdb_helper/lib/src/handlers/scroll_to_handler.dart | Canonical handler |
packages/fdb_helper/lib/src/gesture_dispatcher.dart | Gesture dispatch primitives |
packages/fdb_helper/lib/src/element_tree_finder.dart | Widget tree search utilities |
packages/fdb_helper/lib/src/widget_matcher.dart | Selector parsing |