You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(orchestrator): per-attempt human notes via suggestions/NNN.md (no cursor)
Rework the suggestions channel from the single-file mailbox of the previous
commit into a per-attempt convention, and move delivery out of the
orchestrator entirely.
suggestions/ is now a directory parallel to attempts/: the Runner of attempt
NNN reads suggestions/NNN.md as part of its Load-context step (alongside
goal.md and attempts/). The manager knows the current attempt from status, so
it writes a note targeting the round that will read it (suggestions/006.md
while 005 runs). The note file stays in place afterward as part of the audit
trail.
- No cursor, no offsets, no diffing — nothing to drift when notes are edited
or deleted (the original bug this PR set out to fix).
- The orchestrator no longer injects or consumes anything: _consume_suggestions
is gone and _build_brief is back to a static brief.
- Delivery is an exact attempt-number match; a note whose round the loop has
already passed sits unread until re-pointed — an accepted, low-odds trade
for the simplicity of "Runner reads its own NNN.md".
Runner prompt (agents/goal-runner.md) gains the read step; manager skill
(goal-run), goal-init/goal-flash skills, README, and design.md updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CHb1FkoMGfDfwmeJR5hBG6
--dangerously-skip-permissions`. The brief carries the workspace path,
446
-
the attempt number, the read-context + terminator instructions, and —
447
-
on a fresh attempt — any NEW `suggestions.md`text since the cursor.
446
+
the attempt number, and the read-context + terminator instructions; the
447
+
Runner itself reads `suggestions/NNN.md`for that attempt as context.
448
448
4.**Parse the terminator** (`{"status": pass|advanced|in_progress|blocked}`)
449
449
and branch: `pass`/`blocked` → exit; `advanced` (and `attempts/NNN.md`
450
450
exists) → pace (or, in copilot mode, wait for approval), then next
@@ -531,27 +531,28 @@ on the user's confirmation** — not to carry the guidance itself.
531
531
This is also why `goal.md` is mutable mid-run: it is the steering wheel, not
532
532
just the starting configuration.
533
533
534
-
**`suggestions.md` — transient / per-attempt.**
534
+
**`suggestions/` — transient / per-attempt.**
535
535
536
536
For a one-off note that does not belong in the goal spec (e.g. something left
537
-
while AFK — "try lock granularity next"), the human appends to
538
-
`<workspace>/suggestions.md`. The file is a **mailbox, not a log**: whatever it
539
-
holds is undelivered. On each FRESH attempt the orchestrator atomically
540
-
*claims* its contents (renaming it aside), injects them into the Runner's brief
541
-
as a "Human guidance (NEW)" section, archives them to
542
-
`.goaloop/suggestions.delivered.md`, and clears the file — so each note reaches
543
-
exactly one attempt. The atomic rename is what makes this race-free: a note
544
-
appended while a claim is in flight lands in either that batch or a fresh file
545
-
the next attempt picks up — never lost, never delivered twice, with no byte
546
-
cursor to drift when the human edits or deletes earlier notes. Use `goal.md`
547
-
for changes that should persist; use `suggestions.md` for transient nudges.
537
+
while AFK — "try lock granularity next"), the manager drops a note file into
538
+
`<workspace>/suggestions/` — a directory parallel to `attempts/`. Delivery is
539
+
**Runner-side, by attempt number**: the Runner of attempt NNN reads
540
+
`suggestions/NNN.md` as part of its Load-context step (just like it reads
541
+
`goal.md` and `attempts/`), so the manager — which knows the current attempt
542
+
from status — names the note for the round that will read it (`suggestions/006.md`
543
+
while 005 runs). The orchestrator never touches it; there is no injection, no
544
+
consumption, no cursor. The file stays in place afterward as part of the audit
545
+
trail. Because delivery is an exact number match, a note whose round the loop
546
+
has already passed simply sits unread until re-pointed — an accepted, low-odds
547
+
trade for the simplicity of "Runner reads its own `suggestions/NNN.md`". Use
548
+
`goal.md` for changes that should persist; `suggestions/` for transient nudges.
548
549
549
550
**The Manager distinguishes messages for itself vs. goal edits.**
550
551
551
552
| User message | Manager's response |
552
553
|---|---|
553
554
| "How is it going?" | Answer directly by reading `.goaloop/status.txt` + latest `attempts/NNN.md`|
554
-
| "Try lock granularity instead next time" | A transient nudge → append to `suggestions.md` (next attempt sees it once); a permanent change → propose editing `goal.md`'s Initial Context |
555
+
| "Try lock granularity instead next time" | A transient nudge → write `suggestions/<next-attempt>.md` (that Runner reads it); a permanent change → propose editing `goal.md`'s Initial Context |
555
556
| "Stop the orchestrator" |`goaloop stop <name>`; confirm it stopped |
556
557
| "Change the target to P99 < 3s" | Propose editing `goal.md`'s Objective; edit on confirmation |
557
558
| "Hmm" / "OK" / chit-chat | Ignore |
@@ -633,8 +634,8 @@ Human pacing during a run is achieved by:
633
634
-**Reading status** via `/goal-run` (or `goaloop status`, or
634
635
`tail -f .goaloop/orchestrator.log`) — the orchestrator writes `status.txt` and
635
636
`attempt_complete.json` each attempt.
636
-
-**Editing `goal.md`** (permanent) or **appending to`suggestions.md`**
637
-
(transient, per-attempt) to steer — the next attempt's Runner picks it up
637
+
-**Editing `goal.md`** (permanent) or **dropping a`suggestions/NNN.md`**
638
+
(transient, per-attempt) to steer — the Runner of that attempt picks it up
638
639
(see Human guidance protocol).
639
640
-**`goaloop continue`** to release the next attempt in copilot mode.
640
641
-**`goaloop stop`** to halt earlier than `pass`.
@@ -683,9 +684,9 @@ The following were considered and deliberately not built. Each appears here
683
684
with the reason so future contributors don't reintroduce them by reflex.
684
685
685
686
> **Implemented after v0.1 (now included).** Two features once listed here as
686
-
> excluded have since been built: `suggestions.md` (a transient per-attempt
687
-
> human → agent channel, NEW-since-cursor injection — see Human guidance
688
-
> protocol) and copilot mode (the `--mode copilot` human-review pause,
687
+
> excluded have since been built: `suggestions/` (a transient per-attempt
688
+
> human → agent channel — the Runner of attempt NNN reads `suggestions/NNN.md`;
689
+
> see Human guidance protocol) and copilot mode (the `--mode copilot` human-review pause,
689
690
> released with `goaloop continue` — see How to run). They are documented
0 commit comments