Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ at a throwaway. You stay the only `nightshift → main` gate.

## More

- [`docs/context-guidance.md`](docs/context-guidance.md) — task-relevant briefings, scoped preferences, and how to evaluate context changes
- [`DESIGN.md`](DESIGN.md) — architecture, the TODO queue, and the golden rule (never lose the log)
- [`SECURITY.md`](SECURITY.md) — what's captured, where it's stored, who can see it, how to report a vuln
- [`docs/privacy.md`](docs/privacy.md) — what an entry looks like, redaction gaps, how to delete/disable/audit your data
Expand Down
21 changes: 12 additions & 9 deletions assets/skills/continue/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,9 @@ done
```
Read hits with the **same slug rules as Step 3** (full `<owner>__<repo>/<page>` slug,
`--fuzzy`, never `2>/dev/null`), plus two rules specific to building real context:
- **Read the 3-5 most relevant hits IN FULL** — and follow any `[[links]]` on those
pages to others that clearly bear on the task. A single page is rarely enough.
- Read the relevant source pages, including surrounding decisions and gotchas.
Follow `[[links]]` when they resolve a gap that matters to this task; reuse pages
already read in this session unless their contents or the task have changed.
- **Don't pre-filter the page** with `devbrain brain get … | grep <keyword>` — grep throws away
the surrounding decisions/gotchas that are exactly what a fresh worker is missing.
Synthesize from the full text in Step 8 instead.
Expand All @@ -187,13 +188,15 @@ devbrain todo context "$id" <<'CTX'
CTX
```
`todo context` appends (or replaces, on a re-run) a `## Context (synthesized …)`
section in the task body — multi-line, idempotent. **Aim for ~500-1000 words** — that's
roughly what 3-5 fully-read pages distill down to, and it's the floor for actually
carrying the decisions, constraints, file pointers, and prior work a fresh worker needs,
not a one-line gesture. If your draft is well under ~500 words, you probably under-read
in Step 7 — go back and read more pages rather than padding. The one exception: if the
brain genuinely surfaced little, write the little there is and say so explicitly ("brain
had little on this") rather than inventing filler.
section in the task body — multi-line, idempotent. Include the objective and acceptance
criteria, accepted decisions, relevant constraints, current artifact/code state, failed
approaches that must not be repeated, remaining work, and source page/file pointers
with relevant dates. For time-sensitive facts, retain when they were observed or last
verified; flag stale or conflicting notes instead of silently dropping their qualifications.
State unresolved gaps. Stop reading when these needs are covered; there is no minimum
page count or word count. A small task may need a short brief; a complex task may need
substantial context. If the brain has little relevant information, say so rather than
padding or retrieving unrelated history.

Then **show it to the user** — print the brief back (`devbrain todo show "$id"`, whose body now
includes the `## Context` section, or just paste it) so they see what's framing the build
Expand Down
9 changes: 9 additions & 0 deletions assets/skills/distill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,15 @@ Then:
(plan-before-code, staging-not-prod, verify-before-done, commit+push), cost/infra. A one-off
ask is queue/brain material, not a standing default. You only need the user-prompt blocks
(the `## HH:MM:SS` headers and the text beneath), not the response samples — keeps it cheap.
**Preserve scope when promoting a steer.** Repetition within one project or incident
does not make a rule universal. Keep project-specific rules in that project's section
or brain page, and retain conditions such as "for schema changes" or "before a paid batch".
Do not turn a requested audit, report format, review process, or one model's workaround
into an always-on requirement. Prefer durable goals and constraints; keep model names,
effort levels, provider routes, and compaction thresholds in explicit configuration or
task-specific guidance unless the owner deliberately chooses a standing default.
Record supporting examples, source dates, and detailed rationale in relevant brain pages
instead of copying their full history into the global preferences page.
4. **Converge, don't grow — consolidate-or-add, never append a duplicate.** Append-only is
wrong: it makes the page grow without bound. The page has a **hard cap of 8192 bytes** (8 KB —
the dashboard's Global Preferences meter shows size/cap and turns red over it; the value is
Expand Down
23 changes: 13 additions & 10 deletions assets/skills/work/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ The split is simple: **`/work` reads the brain, but doesn't write it or brief a
human.** `/continue` exists to *resume a human* — it folds last session's log back
into the brain (`/distill`), refreshes the live git/PR world, and hands back a
briefing. In an unattended loop none of the *writing* or *reporting* pays off: N
parallel workers re-folding the same log is wasted work (~15% of turn time for zero
gain on a build turn), and there's no human to brief. But the *reads* — pulling
parallel workers re-folding the same log duplicate memory maintenance,
and there's no human to brief. But the *reads* — pulling
project conventions and the task's prior decisions out of gbrain — are exactly what
keep the MVP correct, so `/work` keeps both.

Expand Down Expand Up @@ -101,10 +101,10 @@ if you change the identity resolver or the stash-safety rule there, mirror it he
devbrain brain "$qmode" "$q" 2>/dev/null | head -8
done
```
Read the **3-5 most relevant hits IN FULL** (same slug rules as Step 2), follow their
`[[links]]`, and **don't pre-`grep`** the page — that throws away the surrounding
decisions/gotchas a fresh worker is missing. Together with Step 2 this is the context
that makes the build correct.
Read the relevant source pages with their surrounding decisions and gotchas (same
slug rules as Step 2). Follow `[[links]]` when they resolve a task-relevant gap;
reuse pages already read unless the task or source has changed. Don't pre-`grep`
away the context needed to interpret a decision.

5. **Synthesize + attach to the TODO.** Distill what you read into a context brief for
*this* task — not a page dump. Write it to the task so it persists and the next
Expand All @@ -118,10 +118,13 @@ if you change the identity resolver or the stash-safety rule there, mirror it he
**Approach implied:** <one or two lines on how this shapes the MVP>
CTX
```
Aim for **~500-1000 words** — roughly what 3-5 fully-read pages distill to, and the
floor for actually carrying the constraints/file-pointers/prior-work a fresh worker
needs. Well under that means you under-read in Step 4 — go back, don't pad. **Attach
and move straight on** — do not print the brief back; the task file is the only reader.
Cover the objective and acceptance criteria, accepted decisions, relevant constraints,
current artifact/code state, failed approaches, remaining work, and source pointers with relevant dates.
For time-sensitive facts, retain when they were observed or last verified; flag stale
or conflicting notes instead of silently dropping their qualifications.
State unresolved gaps. Stop when these needs are covered, without a minimum page or
word count; preserve substantial context when the task needs it. **Attach and move
straight on** — do not print the brief back; the task file is the only reader.

6. **Branch off the base, then build a MINIMAL MVP.** Start clean from the target branch:
```bash
Expand Down
53 changes: 53 additions & 0 deletions docs/context-guidance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Context that follows the task

devbrain should preserve the decisions an agent needs without making every task
replay the same setup. This is a shared workflow contract for Claude and Codex;
model settings belong to the host or project configuration.

At session start, retrieve relevant project context and inspect the queue. The
current user request remains the assignment. Starting a session does not itself
authorize `/continue`, distillation, or work on another queued item. An explicit
`/continue` still runs its existing resume, distill, and task workflow.

## Choose depth by missing information

The continue/work briefing needs the objective, acceptance criteria, accepted
decisions, constraints, current state, failed approaches, remaining work, and source
pointers. Preserve observation or verification dates when freshness matters, and
identify stale evidence, conflicts, and missing information.

Read source pages with enough surrounding context to interpret their decisions.
Reuse relevant pages already read; follow links or search again to resolve a real
gap. There is no minimum page count or word count, and no maximum brief length.
One relevant page can cover a small task. A cross-service change may need many.
Attach the brief to the task so later workers can recover the context and sources.

## Keep preferences scoped

Global preferences contain durable cross-project defaults. A repeated correction
within one incident does not establish a universal rule. Preserve the condition
that makes a preference useful: schema review for schema changes, for example,
rather than a full database review before every edit. Keep project rules scoped
and detailed evidence in the relevant brain page. Existing hand-edit precedence,
deletion history, maintenance gating, and privacy rules still apply.

## Check changes before calling them an optimization

Compare representative tasks against the existing setup using the same model,
effort, tools, and acceptance criteria. Include a small edit, a task with substantial
prior context, and a task involving stale or conflicting notes. Check correctness,
retained decisions and sources, tool calls, latency, and measured token usage. When
available, report cached input separately and count reasoning within output.

Do not equate shorter instruction files with measured usage savings or equal
quality. Do not compare an API-equivalent estimate with a subscription invoice.
Adjust model effort or compaction policy separately, based on the host's actual
behavior and the task's quality requirements; avoid universal token thresholds.

As reviewed on 2026-09-19, both providers recommend revisiting older scaffolding:
[OpenAI's Astra guidance](https://developers.openai.com/blog/rethinking-skills-and-prompts-for-gpt-6-astra)
emphasizes precise skill triggers and reading relevant documentation;
[Anthropic's Fable 5 guidance](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5)
recommends removing overly prescriptive instructions while preserving useful memory
and verification for long runs. Their effort and verification recommendations
differ. Those model-specific choices should not become universal devbrain defaults.
6 changes: 4 additions & 2 deletions internal/hooks/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,10 @@ func SessionStart(e *Event) error {
"The brain is usually faster and more current than re-deriving from the code. " +
"To READ a page a search surfaces, pass its FULL `<project>/<page>` slug from the output to " +
"`devbrain brain get \"<project>/<page>\" --fuzzy` — not the bare page name " +
"(the brain is one namespace, so a bare slug is page_not_found). To resume this project in full " +
"— brief + work the top task — run /continue."
"(the brain is one namespace, so a bare slug is page_not_found). Reuse context already gathered " +
"for the active task; search again for changed scope, missing facts, or stale evidence. " +
"Run /continue only when the user requests the devbrain resume workflow; it also distills " +
"memory and works a queued task. Session startup alone does not authorize that workflow."
if warn != "" {
msg += " ⚠ " + warn
}
Expand Down
9 changes: 9 additions & 0 deletions internal/hooks/hooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,15 @@ func TestSessionStartNudge(t *testing.T) {
if wrap["hookSpecificOutput"]["hookEventName"] != "SessionStart" {
t.Error("hookEventName missing")
}
for _, want := range []string{
"devbrain brain search",
"Run /continue only when the user requests the devbrain resume workflow",
"Session startup alone does not authorize that workflow",
} {
if !strings.Contains(msg, want) {
t.Errorf("startup nudge lost its retrieval/authorization boundary %q", want)
}
}
}

func TestSessionStartStampsRemote(t *testing.T) {
Expand Down
30 changes: 17 additions & 13 deletions internal/install/markers.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,12 @@ func claudeMdBody(dataDisplay string) string {
body := fmt.Sprintf(`## devbrain (cross-project brain)

Every prompt is captured to the private data repo at `+"`%s`"+`
(routing by git remote -> `+"`projects/<project>/`"+`). At the start of a session,
or when the user explicitly asks "where was I" / "continue", run `+"`/continue`"+`
to pull this project's brain and refresh the live world; it includes `+"`/distill`"+`.
(routing by git remote -> `+"`projects/<project>/`"+`). At session start, retrieve
relevant brain context for the current request and inspect `+"`devbrain todo list`"+`.
Run `+"`/continue`"+` when the user requests the devbrain resume workflow; it includes
`+"`/distill`"+` and working a queued task. Continuing an active task does not select
a different queue item. Session startup alone does not authorize memory maintenance
or queue execution.
Never initiate `+"`/distill`"+` proactively. An explicit `+"`/continue`"+` or
`+"`/distill`"+` invocation is already consent: run it immediately without asking again.
Do not infer consent from progress, a final response, a session boundary, a commit,
Expand All @@ -109,8 +112,8 @@ or a PR being created or merged.
last resort.** Before answering a non-trivial question about a project, before
asking the user something the brain may already record, and whenever you pick
up or resume work, run `+"`devbrain brain search \"<terms>\"`"+` (or `+"`devbrain brain query \"<question>\"`"+`
with an OpenAI key) FIRST. The brain is usually faster and more current than
re-deriving from the code or asking — even mid-task, not just on `+"`/continue`"+`.
with an OpenAI key) FIRST. Reuse context already gathered for the active task;
search again when the task changes, a relevant gap remains, or evidence may be stale.
To READ a page a search surfaces, pass its FULL `+"`<project>/<page>`"+` slug from the
output to `+"`devbrain brain get \"<project>/<page>\" --fuzzy`"+` — not the bare page name (the
brain is one namespace, so a bare slug is `+"`page_not_found`"+`), and do not pipe the
Expand Down Expand Up @@ -141,9 +144,12 @@ func agentsMdBody(dataDisplay, prefs string) string {
body := fmt.Sprintf(`## devbrain (cross-project brain)

Every prompt is captured to the private data repo at `+"`%s`"+`
(routing by git remote -> `+"`projects/<project>/`"+`). At the start of a session,
or when the user explicitly asks "where was I" / "continue", run `+"`$continue`"+`
to pull this project's brain and refresh the live world; it includes `+"`$distill`"+`.
(routing by git remote -> `+"`projects/<project>/`"+`). At session start, retrieve
relevant brain context for the current request and inspect `+"`devbrain todo list`"+`.
Run `+"`$continue`"+` when the user requests the devbrain resume workflow; it includes
`+"`$distill`"+` and working a queued task. Continuing an active task does not select
a different queue item. Session startup alone does not authorize memory maintenance
or queue execution.
Never initiate `+"`$distill`"+` proactively. An explicit `+"`$continue`"+` or
`+"`$distill`"+` invocation is already consent: run it immediately without asking again.
Do not infer consent from progress, a final response, a session boundary, a commit,
Expand All @@ -154,13 +160,11 @@ or a PR being created or merged. The devbrain skills are installed at
last resort.** Before answering a non-trivial question about a project, before
asking the user something the brain may already record, and whenever you pick
up or resume work, run `+"`devbrain brain search \"<terms>\"`"+` (or `+"`devbrain brain query \"<question>\"`"+`
with an OpenAI key) FIRST. To read a surfaced page, pass its full
with an OpenAI key) FIRST. Reuse context already gathered for the active task;
search again when the task changes, a relevant gap remains, or evidence may be stale.
To read a surfaced page, pass its full
`+"`<project>/<page>`"+` slug to `+"`devbrain brain get \"<project>/<page>\" --fuzzy`"+`.

**At the start of a session in a repo, brief yourself** — devbrain injects no
context into Codex, so fetch your own: run `+"`devbrain brain search \"<repo topic>\"`"+` and
`+"`devbrain todo list`"+` to see what the brain records and what's queued.

**End your final message of each turn with a one-sentence recap** of what
you actually did or concluded this turn — outcome, not preamble. devbrain
sweeps the last sentence of your final message from the transcript as the
Expand Down
9 changes: 6 additions & 3 deletions internal/install/markers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,17 @@ func TestMarkerBodiesLimitMidSessionDistill(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
body := strings.Join(strings.Fields(tt.body), " ")
for _, forbidden := range []string{"After meaningful progress", "after ordinary turns", "session is clearly ending", "ask for permission"} {
for _, forbidden := range []string{"After meaningful progress", "after ordinary turns", "session is clearly ending", "ask for permission", "At the start of a session, or when the user explicitly asks"} {
if strings.Contains(body, forbidden) {
t.Errorf("marker contains proactive or ambiguous distill trigger %q", forbidden)
}
}
for _, want := range []string{
"At the start of a session, or when the user explicitly asks",
tt.continueCommand + "` to pull this project's brain and refresh the live world; it includes `" + tt.distill,
"At session start, retrieve relevant brain context for the current request",
"inspect `devbrain todo list`",
"Run `" + tt.continueCommand + "` when the user requests the devbrain resume workflow; it includes `" + tt.distill,
"Session startup alone does not authorize memory maintenance or queue execution",
"Continuing an active task does not select a different queue item",
"Never initiate `" + tt.distill + "` proactively",
"An explicit `" + tt.continueCommand + "` or `" + tt.distill + "` invocation is already consent: run it immediately without asking again",
"Do not infer consent from progress, a final response, a session boundary, a commit, or a PR being created or merged",
Expand Down
Loading