From 07eb48830f66f0ee8d212ab6a3e0fa1b93939d5a Mon Sep 17 00:00:00 2001 From: Anushka Kawalkar Date: Fri, 10 Jul 2026 21:00:53 +0530 Subject: [PATCH 1/2] Add Amazon Q Developer CLI appendix to primitives matrix (#227) --- docs/primitives-matrix.md | 59 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/docs/primitives-matrix.md b/docs/primitives-matrix.md index bb6bbaa6..1f7b99d3 100644 --- a/docs/primitives-matrix.md +++ b/docs/primitives-matrix.md @@ -103,7 +103,7 @@ Transfer recipes map the same loop shape onto each host: | 4. Verification | Create a verifier named agent with `opencode agent`; invoke via `opencode run "Verify diff" --agent verifier --file diff.patch` | `.cursor/agents/loop-verifier.md` from `templates/SKILL.md.verifier` | Add review step at end of workflow; human gate on denylist paths | | 5. Connectors | Configure MCP or CLI bridges in `opencode.json` | Enable GitHub MCP read-only for issue/PR discovery | Configure GitHub MCP in Cascade settings | -## Appendix: Aider CLI + ## Appendix: Aider CLI Aider is CLI-first rather than a loop host with native schedulers, so map the same primitives from [Choosing a Tool](#choosing-a-tool) onto shell scripts, cron, and git branches. @@ -205,6 +205,63 @@ A Gemini CLI daily triage loop: 5. Do not edit source files during the first week. 6. Save updated state for the next run. +## Appendix: Amazon Q Developer CLI + +Amazon Q Developer CLI (`q chat`) is a terminal-based agent, AWS-native, with custom agent +profiles and MCP support. Map the same loop primitives onto `q chat`, custom agent configs, +context resources, and external schedulers. + +| Primitive | Amazon Q Developer CLI mapping | +|-----------|--------------------------------| +| Scheduling | No native cron-style scheduler. Use external schedulers (cron, systemd timers, GitHub Actions) to invoke `q chat` non-interactively, or `q chat --resume` to continue a saved per-directory conversation on the next scheduled run. | +| Rules / Context files | Define a custom agent in `.amazonq/agents/.json` (project) or `~/.aws/amazonq/cli-agents/.json` (personal), and list always-on context in its `resources` field (e.g. `file://STATE.md`, `file://.amazonq/rules/**/*.md`). Use `hooks.agentSpawn` to inject fresh context (like `git status`) at session start. | +| State | Keep `STATE.md` at the repo root, referenced in the custom agent's `resources` field so it's loaded every session; each run should read then update only the relevant section. | +| Maker/checker split | No native subagent/reviewer primitive. Workaround: define two custom agents (e.g. `daily-triage.json` with write tools, `loop-verifier.json` restricted to `fs_read`/`@git` only) and run the verifier agent over the diff in a separate `q chat --agent loop-verifier` session. | +| Connectors | Configure MCP servers in `.amazonq/mcp.json` (project) or `~/.aws/amazonq/mcp.json` (global); scope tool trust per agent via `allowedTools`. Treat workspace `.amazonq/mcp.json` files from untrusted repos with caution — review before opening, since auto-loaded MCP configs have been a real attack vector for this class of tool. | +| Honest gaps | No first-class scheduler, no built-in maker/checker separation, no dedicated state-file convention — these are all manual conventions layered on top of `q chat`, same as most terminal agents without a purpose-built loop scheduler. | + +Minimal transfer recipe: + +```bash +mkdir -p .amazonq/agents .amazonq/rules +cp templates/SKILL.md.loop-triage .amazonq/rules/loop-triage.md +cp starters/minimal-loop/STATE.md.example STATE.md +``` + +`.amazonq/agents/daily-triage.json`: + +```json +{ + "name": "daily-triage", + "description": "Report-only daily triage agent", + "prompt": "Run loop-triage. Update STATE.md with High Priority and Watch List only. Do not edit source code in week one.", + "tools": ["fs_read", "fs_write"], + "resources": [ + "file://STATE.md", + "file://.amazonq/rules/loop-triage.md" + ] +} +``` + +### Week-one Daily Triage prompt (report-only, copy-paste) + +```bash +q chat --agent daily-triage --no-interactive \ + "Run loop-triage. Read STATE.md first. Update only High Priority and Watch List sections. Do not edit source code in week one." +``` + +Verifier pass for later L2 work — a separate, read-only-scoped agent: + +```bash +git diff > diff.patch +q chat --agent loop-verifier --no-interactive \ + "Act as loop-verifier. Review diff.patch against STATE.md goals. Report PASS/FAIL and do not edit files." +``` + +After copying: map scheduling to cron/systemd/GitHub Actions until Q has a first-class +loop scheduler. Use `.amazonq/rules/` for always-on repo guidance, separate custom agents +for maker/checker separation, and `.amazonq/mcp.json` for external tools. + ### Official Documentation https://github.com/google-gemini/gemini-cli From 8f12e05159eb49b94ddb6ad8de76c3dd98fca228 Mon Sep 17 00:00:00 2001 From: Anushka Kawalkar Date: Thu, 16 Jul 2026 23:00:42 +0530 Subject: [PATCH 2/2] Add week-two loop-worktree story --- stories/loop-worktree-week-two.md | 83 +++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 stories/loop-worktree-week-two.md diff --git a/stories/loop-worktree-week-two.md b/stories/loop-worktree-week-two.md new file mode 100644 index 00000000..cca63817 --- /dev/null +++ b/stories/loop-worktree-week-two.md @@ -0,0 +1,83 @@ +# Week Two with loop-worktree: PR Babysitter, one fix at a time + +**Pattern:** PR Babysitter +**Tool:** loop-worktree (paired with loop-context) + +## What I was doing + +I was running a small PR Babysitter loop: watch a PR, try a fix in isolation, +verify it, and only escalate to a human if the fix doesn't land. The part I +wanted to get right this week was making retries safe — if attempt #1 fails, +attempt #2 shouldn't be fighting attempt #1 for the same branch. + +## The workflow + +For each fix attempt, I create an isolated worktree keyed to the run: + +``` +npx @cobusgreyling/loop-worktree create --run-id pr-42-fix-1 --pattern pr-babysitter +``` + +That gives me a fresh checkout under `.loop-worktrees/pr-42-fix-1` on its own +branch (`loop/pr-42-fix-1`), tracked in `.loop-worktrees/manifest.json` — so +nothing touches the branch another attempt might still be using. + +Once the verifier rejects an attempt, I mark it rather than deleting it +immediately — that keeps the audit trail intact: + +``` +npx @cobusgreyling/loop-worktree mark --run-id pr-42-fix-1 --status rejected +``` + +`list` gives me a quick read on what's currently tracked: + +``` +npx @cobusgreyling/loop-worktree list +``` + +And periodically I sweep anything rejected or escalated: + +``` +npx @cobusgreyling/loop-worktree cleanup --status rejected --older-than 24h +``` + +## Pairing with loop-context --check + +Before letting the loop retry again, I run the ledger through +`loop-context --check` so a stuck fix doesn't just keep burning attempts: + +``` +npx @cobusgreyling/loop-context --check --ledger run.json --stagnation 3 --json +``` + +With three identical failures in a row it stayed green (`shouldContinue: true`), +but on the fourth repeat of the same error it correctly flipped to +`escalate: true` with exit code 2 — which is the signal I use to stop the loop +and hand the PR back to a human instead of trying a fifth time. + +## The surprise + +The gotcha that cost me the most time: `--check`'s stagnation trigger only +recognizes attempts with `"outcome": "failure"` exactly. I'd first logged +attempts as `"outcome": "fail"` — `--summary` and `--status` happily counted +those as failures and showed the repeated error, so everything *looked* +right, but `--check` never escalated no matter how many times the same error +repeated. Nothing errors out to tell you the value was wrong; the breaker +just quietly stays at "continue." Since the whole point of pairing +loop-worktree with loop-context is to stop a bad retry loop before it wastes +a worktree (and tokens) on a fix that isn't working, a silently-inert circuit +breaker is exactly the failure mode you don't want. + +Separately, a smaller but good surprise: `cleanup --older-than 24h` refused +to remove a worktree I'd just marked rejected seconds earlier — it only acts +once the attempt is actually old enough (or you pass `--force`). That's the +right default; I just didn't expect it on first try and thought the command +had silently no-op'd. + +## What I'd change + +I'd want `--check` to validate the `outcome` field against the documented +enum and fail loudly (or at least warn) on an unrecognized value, instead of +silently treating it as a no-op for the stagnation/no-progress triggers while +`--summary` keeps counting it as a failure. Right now the two commands can +disagree about the same ledger without telling you. \ No newline at end of file