diff --git a/README.md b/README.md index 2b73225..a4c7bef 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ Any split-pane setup works β€” [Supacode], tmux, or your terminal’s built-in s Two flags opt out of a default: `--no-claude` skips the `CLAUDE.md` note and reconcile hook; `--keep-board` leaves a legacy root `SIDECAR.md` where it is and points `init` at it directly, instead of migrating to `.sidecar/` (a no-op when `.sidecar/sidecar.md` already exists). `--yes`/`-y` skip the section picker described next, and keep `init` non-interactive end to end: from a terminal, a bare `sidecar init` opens the viewer on the board it just created, while `--yes` returns to the shell for scripts and muscle memory that need it to. Creating a brand-new board from an interactive terminal still opens a short picker for choosing its sections; pass a custom path (`sidecar init notes.md`) to place the board somewhere other than `.sidecar/sidecar.md`, which still gets the same automatic exclude, note, and hook. +The note in `CLAUDE.md` is upgraded in place whenever you re-run `sidecar init`, so a repo picks up new entry guidance β€” such as one next action per 🧠 entry β€” only when you run it there again. + Boards are per-directory. `sidecar init` refuses a board that is a symlink β€” the file itself, or the `.sidecar/` home it sits in β€” and writes nothing at all: no board, no `CLAUDE.md` note, no reconcile hook, so a linked board can't be re-inited to pick up a newer note until the link is gone. A link points two checkouts at one queue, and a linked `.sidecar/` shares one `previous.md` besides, so the per-turn `sidecar diff` reports another session's changes as this one's. Reading is unchanged: the viewer still opens a symlinked board that already exists. ## What it does diff --git a/sections.go b/sections.go index 6846244..2707fc9 100644 --- a/sections.go +++ b/sections.go @@ -159,6 +159,7 @@ func entryStyleRules(sections []Section, bullet string) string { b.WriteString(" β€” it belongs in a later section") } b.WriteString(" until it needs a decision, and then the `Next:` line asks for that decision.\n") + b.WriteString("\nEach `" + human.Header() + "` entry is one next action: one physical step, in one place β€” one tool or site, one verb β€” that the human can finish in one sitting. A `Next:` line that says \"and\" or names two places is two entries. Put what they need to act in the entry itself: the direct link, and the exact values to paste, so nothing has to be looked up.\n") } b.WriteString("\nWhen a turn ends, leave its result as an entry and, under it, an indented `Ask:` line with one narrative question β€” \"what did you change on your side?\", \"how did the deploy go?\" β€” never a yes/no. The human sees it as `? …` and answers under it; the answer arrives as an `Answer:` line, and sidecar's hook reports it after your next tool call, so read it, act on it, then clear the `Ask:` and `Answer:` lines or move the entry. The human can also click any entry's bullet, which turns it to `βœ“` (`- [x]`): read that as \"I did this\". The human never moves entries between sections β€” filing them stays yours.\n") return b.String() diff --git a/sections_test.go b/sections_test.go index 2a2431a..980ae05 100644 --- a/sections_test.go +++ b/sections_test.go @@ -178,3 +178,25 @@ func TestEntryStyleExampleDropsQueuePairWithoutAgentSection(t *testing.T) { t.Errorf("queue pair missing or misdirected with πŸ€– present:\n%s", full) } } + +// A Needs-you entry is one physical action in one place, with everything +// needed to act inside it β€” and the rule names the section by its own header, +// so it never points at a heading the board lacks. +func TestEntryStyleRulesTeachOneNextAction(t *testing.T) { + got := entryStyleRules(defaultSections(), "- ") + for _, want := range []string{ + "one next action", + "one tool or site, one verb", + "one sitting", + "is two entries", + "the direct link, and the exact values to paste", + } { + if !strings.Contains(got, want) { + t.Errorf("rules missing %q:\n%s", want, got) + } + } + noHuman := []Section{{"🚧", "In progress", "actively being worked"}} + if got := entryStyleRules(noHuman, "- "); strings.Contains(got, "one next action") { + t.Errorf("the rule names the human section and must vanish without one:\n%s", got) + } +}