Goal
Add a builtin processor that injects beads memories/workflow context (via bd prime)
at the beginning of a conversation, so agents start with persistent beads memories
loaded automatically.
Reference: https://gastownhall.github.io/beads/cli-reference/prime
bd prime --memories-only outputs only persistent memories (compact) — the best match
for "beads memories at the start of a conversation". .beads/PRIME.md can override the
content. Output is raw markdown (NOT JSON).
Key engine constraints discovered
- Command-mode stdout MUST be valid JSON (
executor.parseOutput does json.Unmarshal
into ProcessorOutput{message,text,...}). Raw bd prime markdown fails to parse →
processor skipped under on_error:skip. So command: bd, args:[prime] does NOT work
as-is.
- TWO divergent command-mode paths:
ApplyProcessors (standalone): honors output: prepend/append/transform.
Manager.applyWithRerun (used whenever any prompt-mode processor is loaded — almost
always, since builtins like memorize-preferences are prompt-mode — AND on every
rerun): IGNORES output: type, always does result.Message = output.Message. With
output:transform this REPLACES the user message with prime text (data loss). This is
effectively a bug.
- Companion scripts don't work cleanly for builtins: embed glob is
//go:embed processors/builtin/*.yaml (YAML only) and builtins deploy at 0644.
- No builtin currently uses command-mode → safe to enhance command-mode output handling.
- Working dir defaults to
session → bd prime runs where .beads/ lives. Good.
Recommended approach (Option B): native raw-text command output + pure-YAML builtin
Dependency-free (no jq, no companion script), works as a builtin, improves command-mode
generally.
Go changes in internal/processors:
- types.go: add
OutputFormat field (outputFormat: raw|json, default json) +
GetOutputFormat().
- executor.go: when outputFormat:raw, skip json.Unmarshal; set BOTH output.Message and
output.Text to trimmed stdout (works in either code path).
- apply.go
applyWithRerun command branch (~L701-730): honor output: type
(transform/prepend/append/discard) mirroring ApplyProcessors, and chain
input.Message = result.Message. REQUIRED bug fix — otherwise output:prepend silently
degrades to transform and drops the user message.
- loader.go: validate outputFormat in {raw,json}; only meaningful for command-mode.
Builtin config/processors/builtin/beads-prime.yaml:
name: beads-prime
enabledWhen: 'commandExists("bd") && dirExists(".beads")'
when: { on: userPrompt, match: first, rerun: { afterTime: 30m, afterSentMsgs: 20, afterTokens: 80000 } }
command: bd
args: [prime, --memories-only]
input: none
output: prepend
outputFormat: raw
priority: 92
timeout: 10s
Docs/tests: update docs/config/processors.md (new outputFormat field + command-mode
example) and .augment/rules/05-msghooks.md (builtin table + field). Add executor
raw-output test, apply rerun-path prepend test, loader validation test, and the
builtin-validity test.
Alternative (Option A): workspace companion script (no Go changes)
Ship as a workspace processor (.mitto/processors/, where ./script.sh resolves on disk),
output: transform, script reads stdin .message, runs bd prime, emits
{"message": "<prime>\n\n---\n\n<original>"}. Requires jq, only works per-workspace
(not a builtin), leans on the transform path. More fragile; not recommended for a shipped
feature.
Acceptance criteria
- A builtin beads-prime processor injects
bd prime --memories-only output at the start
of a conversation when bd exists AND .beads/ exists.
- The user's original message is preserved (prepended, not replaced) in BOTH the
standalone and rerun code paths.
- No new runtime dependency (no jq) for the builtin.
- Tests cover raw-output execution, rerun-path prepend, and loader validation.
- Docs and .augment/rules updated.
Goal
Add a builtin processor that injects beads memories/workflow context (via
bd prime)at the beginning of a conversation, so agents start with persistent beads memories
loaded automatically.
Reference: https://gastownhall.github.io/beads/cli-reference/prime
bd prime --memories-onlyoutputs only persistent memories (compact) — the best matchfor "beads memories at the start of a conversation".
.beads/PRIME.mdcan override thecontent. Output is raw markdown (NOT JSON).
Key engine constraints discovered
executor.parseOutputdoes json.Unmarshalinto ProcessorOutput{message,text,...}). Raw
bd primemarkdown fails to parse →processor skipped under on_error:skip. So
command: bd, args:[prime]does NOT workas-is.
ApplyProcessors(standalone): honors output: prepend/append/transform.Manager.applyWithRerun(used whenever any prompt-mode processor is loaded — almostalways, since builtins like memorize-preferences are prompt-mode — AND on every
rerun): IGNORES output: type, always does
result.Message = output.Message. Withoutput:transform this REPLACES the user message with prime text (data loss). This is
effectively a bug.
//go:embed processors/builtin/*.yaml(YAML only) and builtins deploy at 0644.session→bd primeruns where.beads/lives. Good.Recommended approach (Option B): native raw-text command output + pure-YAML builtin
Dependency-free (no jq, no companion script), works as a builtin, improves command-mode
generally.
Go changes in
internal/processors:OutputFormatfield (outputFormat: raw|json, default json) +GetOutputFormat().output.Text to trimmed stdout (works in either code path).
applyWithReruncommand branch (~L701-730): honor output: type(transform/prepend/append/discard) mirroring ApplyProcessors, and chain
input.Message = result.Message. REQUIRED bug fix — otherwise output:prepend silentlydegrades to transform and drops the user message.
Builtin
config/processors/builtin/beads-prime.yaml:Docs/tests: update docs/config/processors.md (new outputFormat field + command-mode
example) and .augment/rules/05-msghooks.md (builtin table + field). Add executor
raw-output test, apply rerun-path prepend test, loader validation test, and the
builtin-validity test.
Alternative (Option A): workspace companion script (no Go changes)
Ship as a workspace processor (.mitto/processors/, where ./script.sh resolves on disk),
output: transform, script reads stdin .message, runs
bd prime, emits{"message": "<prime>\n\n---\n\n<original>"}. Requires jq, only works per-workspace(not a builtin), leans on the transform path. More fragile; not recommended for a shipped
feature.
Acceptance criteria
bd prime --memories-onlyoutput at the startof a conversation when
bdexists AND.beads/exists.standalone and rerun code paths.