Skip to content
Merged
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ All notable user-visible changes to the TMB plugin. Versions follow [SemVer](htt

## Unreleased

### Refactored — defaults seeded by schema, not by bro

The previous unreleased entry had bro silently writing 3 `plugin_config` rows + a `tmb_defaults_applied` ledger event on first contact. Per user follow-up: that's still bro doing work the system should do.

- `mcp/trajectory-server/src/schema.sql` now seeds the 3 default policy keys via `INSERT OR IGNORE` at DB creation. Bro never touches `plugin_config` on first contact.
- `tmb_defaults_applied` ledger event removed entirely (the schema seed is silent; bro only logs events for decisions it actually makes).
- CLAUDE.md first-action chain compressed from 12 lines (state check + conditional default-write + cache + resume) to 4 lines (two parallel reads: `identity_get` + `issue_resume`, then welcome banner). `config_get` no longer in the always-call set; bro fetches lazily when a specific key matters.
- Welcome banner simplified from 3 variants to 2 (no "first contact" variant — pending-work or idle is enough).
- Test fixtures (`onboarding-named.sql`, `onboarding-anonymous.sql`) shrunk: they no longer INSERT plugin_config (now schema-seeded) and dropped the `tmb_defaults_applied` ledger row. `onboarding-named.sql` writes a `tmb_user_named` event instead to mark "user explicitly chose this name".

### Removed — first-run-onboarding ceremony (modern-agent UX)

Modern agents (Cursor, ChatGPT, etc.) don't onboard — they just work. TMB's previous behavior of asking name + branching model + PR target + protected branches via `AskUserQuestion` on first contact was friction with no upside for the 80% case, and it broke completely in headless `claude -p` mode (no Human to answer).
Expand Down
35 changes: 15 additions & 20 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,21 @@ All non-workflow agents are **consultants**, not deciders. They return analyses;

Every MCP call MUST include `agent: 'bro'`. Server rejects others. For forbidden-tool errors, policy-key writes, and `is_error: true` recovery: see `tmb_mcp-error-handling`.

## First-action chain (every triggered message — no exceptions, no shortcuts for casual messages)

1. **State check** — `identity_get(agent='bro')` + `config_get(agent='bro', key='branching_model')`.
- **`config_get` returns null** (first activation in this project) → write defaults silently to DB:
- `config_set(agent='bro', key='branching_model', value='github-flow')`
- `config_set(agent='bro', key='pr_target', value='main')`
- `config_set(agent='bro', key='protected_branches', value='["main"]')`
- `ledger_log(agent='bro', event_type='tmb_defaults_applied', summary='First activation: defaults applied silently. Say reonboard to customize.')`
- **Do NOT write an `identity` row.** Identity stays unset until the user reonboards (the absence of a row means "user hasn't named themselves yet").
- **Both already exist** → use what's there. No writes.
2. **Cache human_name** — use it when set; plain second-person ("hey", "you") otherwise.
3. **Resume** — `issue_resume(agent='bro')` to detect unfinished work.

## Welcome banner (the activation announcement)

When you announce `Entering bro mode.`, follow it immediately with one banner line that names the state. The user must always know what just activated and what bro is operating on.

- **First activation** (just wrote defaults): *"Entering bro mode. First activation here — applied defaults: github-flow, main as PR target. Say `reonboard` to customize."*
- **Returning, unfinished work pending** (`issue_resume` returned a row): *"Entering bro mode. Welcome back — resuming issue #N: <title>."*
- **Returning, no pending work**: *"Entering bro mode. Welcome back. What are we doing?"*
## Activation routine (every triggered message, no shortcuts)

Two parallel MCP reads, then the welcome banner, then the actual ask:

- `identity_get(agent='bro')` — name (or null = user hasn't reonboarded yet)
- `issue_resume(agent='bro')` — pending work, if any

Policy keys (`branching_model`, `pr_target`, `protected_branches`) are seeded at DB init by the schema — bro never writes them; fetch via `config_get` only when you need a specific value.

## Welcome banner (mandatory)

After `Entering bro mode.`, one banner line that reflects state:

- **`issue_resume` returned a row** → *"Welcome back — resuming issue #N: \<title\>."*
- **No pending work** → *"What are we doing?"* (use `<name>` if `identity_get` returned one, otherwise plain second-person)

The banner is mandatory. A silent activation breaks the user's mental model of "is bro driving or is regular Claude driving?".

Expand Down
29 changes: 12 additions & 17 deletions docs/architecture/FLOWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,35 +52,30 @@ Companion docs: [`ERD.md`](ERD.md) for schema, [`FILES.md`](FILES.md) for the fi
- Hooks: none
- **Filesystem ops: NONE.** swe + pr-reviewer + default skills serve globally; nothing is copied into the project.

**Doctrine: no onboarding ceremony.** Modern agents don't onboard — they just work. Bro applies sensible defaults silently on first activation, persists them to the DB so they survive across sessions, and announces what it did in the welcome banner. The user can change anything any time via `tmb_reonboard`.
**Doctrine: no onboarding, no bro-side default-write.** Modern agents don't onboard. The schema (`mcp/trajectory-server/src/schema.sql`) seeds the three policy keys at DB creation via `INSERT OR IGNORE`, so bro never has to apply or persist defaults — they're there from the moment the DB exists. Bro just reads what it needs and greets.

```mermaid
sequenceDiagram
participant H as Human
participant G as Bro
participant DB as SQLite (plugin_config, ledger)
participant DB as SQLite (plugin_config, identity, ledger)

Note over G: First activation — checks identity_get + config_get
Note over DB: Schema-init seeded plugin_config defaults<br/>(github-flow / main / ["main"]) at DB creation.

Note over G: First activation — two parallel reads
G->>DB: identity_get()
G->>DB: config_get("branching_model")
DB-->>G: both null → first contact

Note over G: No AskUserQuestion. Apply defaults silently.
G->>DB: config_set("branching_model", "github-flow")
G->>DB: config_set("pr_target", "main")
G->>DB: config_set("protected_branches", ["main"])
G->>DB: ledger_log(event_type='tmb_defaults_applied', ...)
G->>DB: issue_resume()
DB-->>G: identity null + no pending work

G->>H: "Entering bro mode. First activation here — applied defaults: github-flow, main as PR target. Say `reonboard` to customize. <continue with the actual ask>"
G->>H: "Entering bro mode. What are we doing?"
```

**Notes:**
- **No `identity` row written.** The absence of an identity row means "user hasn't named themselves yet." Bro greets without a name (plain second-person) until the user invokes `tmb_reonboard` to set one.
- **No file copying.** swe + pr-reviewer + default skills already serve from the plugin globally.
- **The welcome banner is mandatory** — see CLAUDE.md "Welcome banner" section for the three banner variants (first activation / returning with pending work / returning idle).
- **Subsequent sessions skip the writes.** Bro reads the existing config, mentions "Welcome back" in the banner, continues.
- **Re-runnable any time** via the `tmb_reonboard` skill (bro invokes it on phrases like "switch to gitflow", "update my name", "reonboard").
- **No `identity` row exists** until the user invokes `tmb_reonboard`. Bro greets with plain second-person ("hey", "you") until then.
- **No bro-side default-write.** Defaults are part of the schema. `INSERT OR IGNORE` makes the seed idempotent across re-runs.
- **No `tmb_defaults_applied` ledger event** — system seeding is silent; bro only logs ledger events for decisions it actually makes.
- **Welcome banner is mandatory** (CLAUDE.md). Two variants: pending work (resume) or idle (greeting).
- **`tmb_reonboard`** is the only skill that writes to `identity` or changes policy keys. Phrases that invoke it: "switch to gitflow", "update my name", "reonboard".
- Resolution rule for backbone agents: if `<project>/.claude/agents/swe.md` (or `pr-reviewer.md`) exists → use local; else use the global plugin-shipped one. Local creation is opt-in via `tmb_agent-creator` with explicit Human approval.

---
Expand Down
1 change: 0 additions & 1 deletion docs/contributing/ENUMS.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ K8s Events have a `reason` field with a similar shape but different semantics. *

| Value | Trigger |
|---|---|
| `tmb_defaults_applied` | Bro finishes first-run onboarding |
| `planning_complete` | Bro finishes planning, batched task_create + SWE spawn |
| `scope_gate_waived` | Bro waives the scope gate with explicit reason |
| `direct_mode_used` | Bro fixes ≤3 lines without SWE spawn |
Expand Down
9 changes: 9 additions & 0 deletions mcp/trajectory-server/dist/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@ CREATE TABLE IF NOT EXISTS plugin_config (
updated_at TEXT NOT NULL
);

-- Default policy keys, seeded at DB init so bro never has to "apply defaults"
-- on first contact. Modern-agent UX: the system gives bro working state out
-- of the box; the user changes anything via tmb_reonboard. INSERT OR IGNORE
-- makes this safe to re-run on existing DBs (no overwrite of user choices).
INSERT OR IGNORE INTO plugin_config (key, value_json, updated_at) VALUES
('branching_model', '"github-flow"', datetime('now')),
('pr_target', '"main"', datetime('now')),
('protected_branches', '["main"]', datetime('now'));

CREATE TABLE IF NOT EXISTS identity (
id INTEGER PRIMARY KEY CHECK (id = 1),
human_name TEXT,
Expand Down
28 changes: 22 additions & 6 deletions mcp/trajectory-server/dist/test/config.test.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading