refactor: extract agent bounded context + fix SSE comments + cleanup unused
- Extract src/lib/agent/ bounded context with types, registry, messaging - Add comments_count to BeadIssue for SSE comment detection - Create batch endpoints for mail/reservations APIs - Add memory validation to session-preflight - Remove unused empty dirs (mockup, sessions, timeline) - Move stashes to docs/references, gitignore them
This commit is contained in:
parent
6f41c4af31
commit
18fbafdce4
34 changed files with 62714 additions and 1970 deletions
|
|
@ -315,6 +315,8 @@ Stop and correct if you are about to:
|
|||
Swarm composition, molecule operations, worker dispatch patterns.
|
||||
- `references/missions-realtime.md`:
|
||||
Real-time/watcher/event troubleshooting.
|
||||
- `references/creating-beads.md`:
|
||||
Creating epics, tasks, subtasks with proper naming, dependencies, and workflow.
|
||||
|
||||
## Bottom Line
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,31 @@
|
|||
# Project Driver Template
|
||||
# project.md — BeadBoard Driver Session Cache
|
||||
|
||||
Use this template to create `project.md` at the target repository root.
|
||||
The first agent in a repo should create this file; later agents must read and update it before work.
|
||||
This file is maintained by agents. A new agent reads this first.
|
||||
If the Environment Status table shows all `pass`, skip straight to Step 2 of the runbook.
|
||||
Only re-run a check if its row says `fail` or `unknown`, or if you hit an actual error.
|
||||
|
||||
---
|
||||
|
||||
## Environment Status Cache
|
||||
|
||||
Last updated: YYYY-MM-DD by `<agent-bead-id>`
|
||||
|
||||
| Component | Status | Version / Detail | Verified |
|
||||
|-----------|--------|-----------------|---------|
|
||||
| `bd` on PATH | `unknown` | | |
|
||||
| `bb` on PATH | `unknown` | | |
|
||||
| `.beads` db exists | `unknown` | | |
|
||||
| `mail.delegate` configured | `unknown` | | |
|
||||
| `session-preflight` | `unknown` | | |
|
||||
| `bb agent` registered | `unknown` | `BB_AGENT=` | |
|
||||
| Tests last run | `unknown` | | |
|
||||
|
||||
**Status values:** `pass` · `fail` · `unknown` · `skip` (not applicable to this project)
|
||||
|
||||
**Rule:** If every row is `pass` → skip Step 1 entirely and go straight to Step 2.
|
||||
If any row is `fail` or `unknown` → run only that check, update this table, continue.
|
||||
|
||||
---
|
||||
|
||||
## Project Identity
|
||||
|
||||
|
|
@ -10,68 +34,33 @@ The first agent in a repo should create this file; later agents must read and up
|
|||
- Primary language/runtime:
|
||||
- Primary package manager:
|
||||
|
||||
## Tooling Baseline (Global Installs)
|
||||
## Tooling Baseline
|
||||
|
||||
Record what is already installed on this machine so later agents do not re-check unnecessarily.
|
||||
|
||||
- `bd` installed and on PATH: yes/no
|
||||
- `bb` or `beadboard` installed and on PATH: yes/no
|
||||
- Detection commands used (with date):
|
||||
- Notes on shell/platform quirks (WSL/Windows/macOS/Linux):
|
||||
- `bd` installed and on PATH: yes/no — version:
|
||||
- `bb` installed and on PATH: yes/no — version:
|
||||
- Detection commands used:
|
||||
- Shell/platform: (e.g. WSL2/bash, macOS/zsh, Windows/PowerShell)
|
||||
|
||||
## BeadBoard/Communication Setup
|
||||
|
||||
- Mail delegate command configured:
|
||||
- `bd config set mail.delegate "node <abs-path>/skills/beadboard-driver/scripts/bb-mail-shim.mjs"`
|
||||
- Agent identity env var policy:
|
||||
- Preferred: `BB_AGENT=<agent-id>`
|
||||
- Fallback: `BD_ACTOR=<agent-id>`
|
||||
- Delegate validation status:
|
||||
- `node skills/beadboard-driver/scripts/ensure-bb-mail-configured.mjs` pass/fail
|
||||
- Session preflight status:
|
||||
- `node skills/beadboard-driver/scripts/session-preflight.mjs` pass/fail
|
||||
- `.beads` database: exists/created on YYYY-MM-DD via `bd init`
|
||||
- Mail delegate: `bd config set mail.delegate "node <abs-path>/scripts/bb-mail-shim.mjs"` — configured YYYY-MM-DD
|
||||
- Agent identity policy: `export BB_AGENT=<role-name>` (set fresh each session in Step 2)
|
||||
- `session-preflight` last pass: YYYY-MM-DD
|
||||
|
||||
## Agent State + Heartbeat Policy
|
||||
|
||||
- Agent bead naming convention for this repo:
|
||||
- Required state transitions (spawning -> running -> working -> stuck/done/stopped):
|
||||
- Heartbeat cadence during active work (recommended 30-120s):
|
||||
- Stuck escalation timeout before user ping:
|
||||
|
||||
## Swarm / Formula Defaults
|
||||
|
||||
- Primary epic/swarm pattern used by this repo:
|
||||
- Formula/proto id(s) commonly used (if any):
|
||||
- Preferred swarm command flow (`bd swarm validate/create/status` etc.):
|
||||
- Agent bead naming: `bb-<role-name>` (e.g. `bb-silver-scribe`)
|
||||
- Required state transitions: `spawning → running → working → stuck/done/stopped`
|
||||
- Heartbeat: LLM agents heartbeat at turn start + before long commands; daemon agents every 5 min
|
||||
|
||||
## Command Baseline
|
||||
|
||||
- Install command:
|
||||
- Build command:
|
||||
- Typecheck command:
|
||||
- Lint command:
|
||||
- Test command:
|
||||
- Smoke command (optional):
|
||||
|
||||
## Verification Policy Overrides
|
||||
|
||||
- Required gates for this project:
|
||||
- Known slow gates and timeout guidance:
|
||||
- Evidence format expected in bead notes:
|
||||
|
||||
## Scope and Safety
|
||||
|
||||
- Forbidden commands/actions for this repo:
|
||||
- Paths requiring reservation before edits:
|
||||
- External systems requiring human approval:
|
||||
- Secret handling guidance:
|
||||
|
||||
## Coordination Defaults
|
||||
|
||||
- Default handoff style:
|
||||
- Blocker escalation policy:
|
||||
- ACK expectations for `HANDOFF`/`BLOCKED`:
|
||||
- Reservation conflict policy (`--takeover-stale` rules):
|
||||
- Install:
|
||||
- Build:
|
||||
- Typecheck:
|
||||
- Lint:
|
||||
- Test:
|
||||
|
||||
## Known Workarounds
|
||||
|
||||
|
|
@ -80,24 +69,12 @@ Document only stable, repeatable workarounds.
|
|||
1. Trigger:
|
||||
- Symptom:
|
||||
- Workaround:
|
||||
- Verification:
|
||||
- Owner:
|
||||
- Verified:
|
||||
|
||||
2. Trigger:
|
||||
- Symptom:
|
||||
- Workaround:
|
||||
- Verification:
|
||||
- Owner:
|
||||
## Session Log (append-only)
|
||||
|
||||
## Session Closeout Checklist
|
||||
Each agent appends one line when they update this file:
|
||||
|
||||
- [ ] Bead status/assignee updated
|
||||
- [ ] Verification commands executed and recorded
|
||||
- [ ] Artifacts attached/linked
|
||||
- [ ] Memory review performed
|
||||
- [ ] Follow-up beads created (if needed)
|
||||
- [ ] `project.md` updated with any new environment facts
|
||||
|
||||
## Change Log
|
||||
|
||||
- YYYY-MM-DD: Initial `project.md` created from template.
|
||||
| Date | Agent | What changed |
|
||||
|------|-------|-------------|
|
||||
| YYYY-MM-DD | `<agent-bead-id>` | Initial project.md created |
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ Blocked condition:
|
|||
|
||||
```bash
|
||||
bd agent state bb-silver-scribe stuck
|
||||
bb agent send --from silver-scribe --to cobalt-ridge --bead beadboard-123 --category BLOCKED --subject "Waiting on schema" --body "Need migration direction before continuing."
|
||||
bd mail send --to cobalt-ridge --bead beadboard-123 --category BLOCKED --subject "Waiting on schema" --body "Need migration direction before continuing."
|
||||
```
|
||||
|
||||
Work completion:
|
||||
|
|
@ -74,14 +74,16 @@ Use `bd agent heartbeat <agent-bead-id>` to refresh `last_activity` without chan
|
|||
bd agent heartbeat bb-silver-scribe
|
||||
```
|
||||
|
||||
When to heartbeat:
|
||||
- At least once every 5-10 minutes during long-running work
|
||||
**Daemon agents (persistent processes):**
|
||||
- Normal work: every 5 minutes
|
||||
- High-risk long operations: every 2-3 minutes
|
||||
- Immediately before long test/build phases
|
||||
- Immediately after recovering from interruptions
|
||||
|
||||
Recommended cadence:
|
||||
- Normal work: every 5 minutes
|
||||
- High-risk long operations: every 2-3 minutes
|
||||
**LLM agents (Claude Code, turn-based):**
|
||||
- At turn start (when picking up work)
|
||||
- Immediately before long-running commands
|
||||
- Inter-turn silence is expected and not a health signal
|
||||
|
||||
## Witness Death Timeout
|
||||
|
||||
|
|
@ -95,6 +97,8 @@ Operational interpretation:
|
|||
Agent-side rule:
|
||||
- If you are alive and still executing, heartbeat before anyone has to guess.
|
||||
|
||||
> **Current status:** The Witness enforcement layer is not yet running. Heartbeats are recorded in `last_activity` and visible in the BeadBoard dashboard but are not currently auto-enforced. Agents will not be auto-marked `dead`. Daemon implementation is a future epic.
|
||||
|
||||
## Slot Operations (Current Work Attachment)
|
||||
|
||||
The `hook` slot links an agent bead to the active task bead.
|
||||
|
|
@ -125,7 +129,7 @@ Important slot constraints:
|
|||
|
||||
When blocked:
|
||||
1. Set state to stuck (`bd agent state ... stuck`)
|
||||
2. Send explicit BLOCKED coordination event (`bb agent send --category BLOCKED ...`)
|
||||
2. Send explicit BLOCKED coordination event (`bd mail send --category BLOCKED ...`)
|
||||
3. Keep heartbeat active while waiting
|
||||
4. Resume with `running`/`working` once unblocked
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,12 @@ Day-to-day runbooks use `bd mail` delegation rather than direct low-level agent
|
|||
- `node skills/beadboard-driver/scripts/session-preflight.mjs`
|
||||
- `node skills/beadboard-driver/scripts/ensure-bb-mail-configured.mjs`
|
||||
- `bd create --title="Agent: <role-name>" --description="<agent scope>" --type=task --priority=0 --label="gt:agent,role:<orchestrator|ui|graph|backend|infra>"`
|
||||
- `bd agent state <agent-bead-id> spawning`
|
||||
- `bd agent state <agent-bead-id> running`
|
||||
- `bd agent state <agent-bead-id> spawning` — agent bead created, environment not yet verified
|
||||
- `bd agent state <agent-bead-id> running` — environment verified, ready to claim work
|
||||
- `bd agent state <agent-bead-id> working` — work bead claimed, actively executing
|
||||
- `bd agent state <agent-bead-id> stuck` — blocked, waiting on intervention or response
|
||||
- `bd agent state <agent-bead-id> done` — work bead closed, all deliverables complete
|
||||
- `bd agent state <agent-bead-id> stopped` — session ending cleanly
|
||||
- `bd agent heartbeat <agent-bead-id>`
|
||||
- `bd agent show <agent-bead-id>`
|
||||
|
||||
|
|
@ -75,7 +79,7 @@ Delegate setup and validation:
|
|||
|
||||
## Environment and Repair Helpers
|
||||
|
||||
- `node skills/beadboard-driver/scripts/resolve-bb.mjs`
|
||||
- `node skills/beadboard-driver/scripts/readiness-report.mjs --checks <json> --artifacts <json>`
|
||||
- `node skills/beadboard-driver/scripts/diagnose-env.mjs`
|
||||
- `node skills/beadboard-driver/scripts/heal-common-issues.mjs [--project-root <path>] [--apply] [--fix-git-index-lock]`
|
||||
- `node {baseDir}/scripts/setup-mail-delegate.mjs` — configure mail.delegate (self-resolves shim path)
|
||||
- `node {baseDir}/scripts/readiness-report.mjs --checks <json> --artifacts <json>`
|
||||
- `node {baseDir}/scripts/diagnose-env.mjs`
|
||||
- `node {baseDir}/scripts/heal-common-issues.mjs [--project-root <path>] [--apply] [--fix-git-index-lock]`
|
||||
|
|
|
|||
286
skills/beadboard-driver/references/creating-beads.md
Normal file
286
skills/beadboard-driver/references/creating-beads.md
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
# Creating and Managing Beads
|
||||
|
||||
Complete guide for agents on bead creation, naming, dependencies, and workflow.
|
||||
|
||||
---
|
||||
|
||||
## Bead Naming Format (CRITICAL)
|
||||
|
||||
| Level | Format | Example |
|
||||
|-------|--------|---------|
|
||||
| **Epic** | `beadboard-<id>` | `beadboard-abc` |
|
||||
| **Task** | `beadboard-<epic>.x` | `beadboard-abc.1` |
|
||||
| **Subtask** | `beadboard-<epic>.x.x` | `beadboard-abc.1.2` |
|
||||
|
||||
**Rules:**
|
||||
- `<id>` is auto-generated by `bd create` (alphanumeric, 2-4 chars)
|
||||
- Task numbers increment sequentially under epic
|
||||
- Subtask numbers increment under parent task
|
||||
- **Never skip levels**: epic → task → subtask
|
||||
|
||||
---
|
||||
|
||||
## Creating Epics
|
||||
|
||||
Epics represent high-level features or initiatives.
|
||||
|
||||
```bash
|
||||
bd create \
|
||||
--title="[EPIC] User Authentication System" \
|
||||
--description="Implement secure user login/registration with OAuth support" \
|
||||
--type=epic \
|
||||
--priority=2 \
|
||||
--label="feature,auth"
|
||||
```
|
||||
|
||||
**Output:** `Created beadboard-xyz (epic)`
|
||||
|
||||
---
|
||||
|
||||
## Creating Tasks Under Epics
|
||||
|
||||
Tasks are actionable work units under an epic.
|
||||
|
||||
```bash
|
||||
# Task naming convention: epic.1: Description
|
||||
bd create \
|
||||
--title="xyz.1: Implement login form UI" \
|
||||
--description="Build responsive login form with email/password fields" \
|
||||
--type=task \
|
||||
--priority=2 \
|
||||
--parent=beadboard-xyz
|
||||
```
|
||||
|
||||
**Output:** `Created beadboard-xyz.1 (task)`
|
||||
|
||||
### Creating Subtasks
|
||||
|
||||
```bash
|
||||
# Subtask naming: epic.task.subtask: Description
|
||||
bd create \
|
||||
--title="xyz.1.1: Add form validation" \
|
||||
--description="Implement client-side validation for email format" \
|
||||
--type=task \
|
||||
--priority=1 \
|
||||
--parent=beadboard-xyz.1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Setting Dependencies
|
||||
|
||||
### Blocker Dependencies (Execution Order)
|
||||
|
||||
Use when one bead must complete before another starts:
|
||||
|
||||
```bash
|
||||
# xyz.1 cannot start until xyz is done
|
||||
bd dep add beadboard-xyz.1 beadboard-xyz
|
||||
|
||||
# xyz.1.2 is blocked by xyz.1.1
|
||||
bd dep add beadboard-xyz.1.2 beadboard-xyz.1.1
|
||||
```
|
||||
|
||||
### Parent-Child Relationships
|
||||
|
||||
Use for semantic grouping (non-blocking):
|
||||
|
||||
```bash
|
||||
# Link child to parent epic
|
||||
bd dep relate beadboard-xyz beadboard-xyz.1
|
||||
|
||||
# Link subtask to task
|
||||
bd dep relate beadboard-xyz.1 beadboard-xyz.1.1
|
||||
```
|
||||
|
||||
### Viewing Dependencies
|
||||
|
||||
```bash
|
||||
bd dep list beadboard-xyz # Show all dependencies
|
||||
bd ready # Show unblocked, ready-to-start beads
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Writing Descriptions
|
||||
|
||||
Every bead description MUST include:
|
||||
|
||||
```markdown
|
||||
**Scope:**
|
||||
- Specific thing to implement
|
||||
- Another specific requirement
|
||||
|
||||
**Out of Scope:**
|
||||
- Things explicitly not included
|
||||
- Future work to avoid
|
||||
|
||||
**Success Criteria:**
|
||||
1. Specific measurable outcome
|
||||
2. Test passes
|
||||
3. Evidence of completion
|
||||
```
|
||||
|
||||
### Example Description
|
||||
|
||||
```bash
|
||||
bd create --title="xyz.2: API endpoint" --description="Scope:
|
||||
- POST /api/login endpoint
|
||||
- JWT token generation
|
||||
- Rate limiting (5 req/min)
|
||||
|
||||
Out of Scope:
|
||||
- OAuth providers (in xyz.3)
|
||||
- Password reset flow
|
||||
|
||||
Success Criteria:
|
||||
1. Endpoint returns 200 with valid JWT
|
||||
2. Returns 401 for invalid credentials
|
||||
3. Rate limit enforced" --type=task --priority=2 --parent=beadboard-xyz
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Closing Beads
|
||||
|
||||
### Step 1: Update with Evidence
|
||||
|
||||
```bash
|
||||
bd update beadboard-xyz.1 \
|
||||
--notes "Tests pass: npm test -- --grep 'login'
|
||||
Files changed:
|
||||
- src/components/LoginForm.tsx
|
||||
- src/lib/validation.ts
|
||||
Coverage: 94%"
|
||||
```
|
||||
|
||||
### Step 2: Close
|
||||
|
||||
```bash
|
||||
bd close beadboard-xyz.1 --reason "Login form implemented, tested, merged to main"
|
||||
```
|
||||
|
||||
**Rule:** Update first, then close. `bd close` does not accept `--notes`.
|
||||
|
||||
---
|
||||
|
||||
## Complete Example: End-to-End Workflow
|
||||
|
||||
### 1. Create Epic
|
||||
|
||||
```bash
|
||||
$ bd create --title="[EPIC] Payment Integration" --description="Add Stripe payment processing" --type=epic --priority=1 --label="feature,payments"
|
||||
|
||||
Created beadboard-pmt (epic)
|
||||
```
|
||||
|
||||
### 2. Create Tasks
|
||||
|
||||
```bash
|
||||
$ bd create --title="pmt.1: Stripe account setup" --description="Scope:
|
||||
- Create Stripe dev account
|
||||
- Configure webhook endpoint
|
||||
- Add API keys to vault
|
||||
|
||||
Out of Scope:
|
||||
- Production account (separate epic)
|
||||
|
||||
Success Criteria:
|
||||
1. Test transactions work in sandbox
|
||||
2. Webhook receives events" --type=task --priority=1 --parent=beadboard-pmt
|
||||
|
||||
Created beadboard-pmt.1 (task)
|
||||
|
||||
$ bd create --title="pmt.2: Checkout UI" --description="Scope:
|
||||
- Payment form component
|
||||
- Card element integration
|
||||
- Error handling display
|
||||
|
||||
Success Criteria:
|
||||
1. Form submits to Stripe
|
||||
2. Shows success/failure states" --type=task --priority=2 --parent=beadboard-pmt
|
||||
|
||||
Created beadboard-pmt.2 (task)
|
||||
```
|
||||
|
||||
### 3. Set Dependencies
|
||||
|
||||
```bash
|
||||
# pmt.2 blocked by pmt.1 (need Stripe setup first)
|
||||
$ bd dep add beadboard-pmt.2 beadboard-pmt.1
|
||||
|
||||
Added dependency: beadboard-pmt.2 -> beadboard-pmt.1
|
||||
```
|
||||
|
||||
### 4. Check Ready Status
|
||||
|
||||
```bash
|
||||
$ bd ready
|
||||
|
||||
beadboard-pmt.1 [task] pmt.1: Stripe account setup
|
||||
```
|
||||
|
||||
Only `pmt.1` is ready—`pmt.2` is blocked.
|
||||
|
||||
### 5. Create Subtask
|
||||
|
||||
```bash
|
||||
$ bd create --title="pmt.1.1: Webhook handler" --description="Scope:
|
||||
- POST /webhooks/stripe endpoint
|
||||
- Verify Stripe signature
|
||||
- Update order status
|
||||
|
||||
Success Criteria:
|
||||
1. Signature verification passes
|
||||
2. Order updated correctly" --type=task --priority=1 --parent=beadboard-pmt.1
|
||||
|
||||
Created beadboard-pmt.1.1 (task)
|
||||
```
|
||||
|
||||
### 6. Work and Close
|
||||
|
||||
```bash
|
||||
# After completing pmt.1.1
|
||||
$ bd update beadboard-pmt.1.1 --notes "Webhook handler implemented
|
||||
- src/app/api/webhooks/stripe/route.ts
|
||||
- Tests: npm test webhook.test.ts (3 passing)"
|
||||
|
||||
$ bd close beadboard-pmt.1.1 --reason "Webhook handler complete"
|
||||
|
||||
# After completing pmt.1
|
||||
$ bd update beadboard-pmt.1 --notes "Stripe integration complete
|
||||
- Sandbox account: acct_xxx
|
||||
- Webhook: /api/webhooks/stripe
|
||||
- All tests passing"
|
||||
|
||||
$ bd close beadboard-pmt.1 --reason "Stripe account setup finished"
|
||||
|
||||
# Now pmt.2 becomes unblocked
|
||||
$ bd ready
|
||||
|
||||
beadboard-pmt.2 [task] pmt.2: Checkout UI
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `bd create --title="..." --type=epic` | Create epic |
|
||||
| `bd create --title="epic.N: ..." --parent=beadboard-xxx` | Create task |
|
||||
| `bd dep add <blocked> <blocker>` | Set blocker dependency |
|
||||
| `bd dep relate <parent> <child>` | Set semantic relationship |
|
||||
| `bd ready` | List unblocked beads |
|
||||
| `bd update <id> --notes "..."` | Add evidence |
|
||||
| `bd close <id> --reason "..."` | Complete bead |
|
||||
|
||||
---
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
1. **Wrong naming**: `task-1` instead of `beadboard-abc.1`
|
||||
2. **Missing parent**: Tasks must have `--parent=beadboard-<epic>`
|
||||
3. **Closing before updating**: Always `update` first, then `close`
|
||||
4. **Wrong dep direction**: `bd dep add <blocked> <blocker>` (blocked first!)
|
||||
5. **Skipping evidence**: Always include command output in `--notes`
|
||||
|
|
@ -13,12 +13,12 @@ This document tracks high-impact coordination and environment failures for the B
|
|||
|
||||
## `BB_NOT_FOUND`
|
||||
|
||||
- Signal: `resolve-bb.mjs` or `bb-mail-shim.mjs` reports bb command missing.
|
||||
- Signal: `session-preflight.mjs` or `bb-mail-shim.mjs` reports bb command missing.
|
||||
- Cause: global BeadBoard CLI not installed, or not discoverable.
|
||||
- Recovery:
|
||||
- Install BeadBoard globally (`bb`/`beadboard` on `PATH`).
|
||||
- Re-run `node skills/beadboard-driver/scripts/resolve-bb.mjs`.
|
||||
- Re-run preflight.
|
||||
- Install BeadBoard globally (`bb`/`beadboard` on `PATH`) — see Bootstrap Step C in SKILL.md.
|
||||
- Run `node {baseDir}/scripts/setup-mail-delegate.mjs` to reconfigure the mail delegate after `bb` is installed.
|
||||
- Re-run preflight: `node {baseDir}/scripts/session-preflight.mjs`.
|
||||
|
||||
## `MAIL_DELEGATE_MISSING` / `BD_MAIL_DELEGATE_NOT_SET`
|
||||
|
||||
|
|
@ -33,10 +33,12 @@ This document tracks high-impact coordination and environment failures for the B
|
|||
|
||||
- Signal: `ensure-bb-mail-configured.mjs` fails contract checks.
|
||||
- Cause: delegate points to wrong command, missing shim path, or invalid `BB_AGENT` context.
|
||||
- Recovery:
|
||||
- Run session preflight to re-apply expected delegate command.
|
||||
- Set `BB_AGENT` explicitly.
|
||||
- Validate with `node skills/beadboard-driver/scripts/ensure-bb-mail-configured.mjs`.
|
||||
- Recovery (in order):
|
||||
1. Check delegate is set: `bd config get mail.delegate`
|
||||
2. Verify shim path: the path shown must be absolute and the `bb-mail-shim.mjs` file must exist on disk
|
||||
3. Reconfigure if wrong/missing: `node {baseDir}/scripts/setup-mail-delegate.mjs`
|
||||
4. Verify `BB_AGENT` is set: `echo $BB_AGENT` (must be non-empty)
|
||||
5. Re-run verification: `node {baseDir}/scripts/ensure-bb-mail-configured.mjs` — expected: `ok: true`
|
||||
|
||||
## `DOLT_NOT_RUNNING`
|
||||
|
||||
|
|
@ -72,4 +74,4 @@ This document tracks high-impact coordination and environment failures for the B
|
|||
|
||||
- Do not write `.beads/issues.jsonl` directly.
|
||||
- Do not close beads without fresh evidence.
|
||||
- Do not bypass invalid `BB_REPO` values; fix configuration first.
|
||||
- Do not bypass a misconfigured mail delegate; fix configuration with `{baseDir}/scripts/setup-mail-delegate.mjs` first.
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ This runbook is the minimum lifecycle contract for agents using BeadBoard Driver
|
|||
1. Run preflight and discovery checks:
|
||||
|
||||
```bash
|
||||
node skills/beadboard-driver/scripts/session-preflight.mjs
|
||||
node skills/beadboard-driver/scripts/resolve-bb.mjs
|
||||
node {baseDir}/scripts/session-preflight.mjs
|
||||
```
|
||||
|
||||
2. Create or identify your agent bead first (required before claiming work):
|
||||
|
|
@ -27,7 +26,8 @@ bd agent state <agent-bead-id> running
|
|||
4. Query hard memory for your domain before claim:
|
||||
|
||||
```bash
|
||||
bd query "label=memory AND label=mem-canonical AND label=mem-hard AND status=closed"
|
||||
# Select domain: memory-arch | memory-workflow | memory-agent | memory-ux | memory-reliability
|
||||
bd query "label=memory AND label=mem-canonical AND label=<domain> AND status=closed" --sort updated --reverse
|
||||
```
|
||||
|
||||
## 2) Discover Work and Read Epic Context
|
||||
|
|
@ -100,7 +100,7 @@ bd agent state <agent-bead-id> stuck
|
|||
2. Coordination signal:
|
||||
|
||||
```bash
|
||||
bb agent send --from <agent-name> --to <target-agent-or-role> --bead <bead-id> --category BLOCKED --subject "<blocker summary>" --body "<what is needed>"
|
||||
bd mail send --to <target-agent-or-role> --bead <bead-id> --category BLOCKED --subject "<blocker summary>" --body "<what is needed>"
|
||||
```
|
||||
|
||||
3. Keep heartbeat while waiting:
|
||||
|
|
|
|||
|
|
@ -40,6 +40,38 @@ function configureMailDelegate(bdPath, shimPath) {
|
|||
};
|
||||
}
|
||||
|
||||
function validateMemorySystem(bdPath) {
|
||||
try {
|
||||
const result = spawnSync(bdPath, ['query', 'label=mem-canonical,status=closed', '--limit', '5'], {
|
||||
stdio: 'pipe',
|
||||
shell: false,
|
||||
});
|
||||
|
||||
if (result.status !== 0) {
|
||||
return {
|
||||
validated: false,
|
||||
reason: 'Failed to query memory system',
|
||||
memories_found: 0,
|
||||
};
|
||||
}
|
||||
|
||||
const output = result.stdout?.toString() || '';
|
||||
const memoryCount = (output.match(/beadboard-/g) || []).length;
|
||||
|
||||
return {
|
||||
validated: true,
|
||||
memories_found: memoryCount,
|
||||
note: 'Remember to read memory beads at session start: bd show beadboard-116 beadboard-60a beadboard-zas',
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
validated: false,
|
||||
reason: error instanceof Error ? error.message : String(error),
|
||||
memories_found: 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const shimPath = join(__dirname, 'bb-mail-shim.mjs');
|
||||
|
||||
|
|
@ -54,13 +86,14 @@ async function main() {
|
|||
reason: 'Could not find bd in PATH.',
|
||||
remediation:
|
||||
process.platform === 'win32'
|
||||
? 'Primary: npm i -g beadboard. Fallback: powershell -ExecutionPolicy Bypass -File .\\install\\install.ps1. Then ensure bd is available in PATH.'
|
||||
? 'Primary: npm i -g beadboard. Fallback: powershell -ExecutionPolicy Bypass -File ./install/install.ps1. Then ensure bd is available in PATH.'
|
||||
: 'Primary: npm i -g beadboard. Fallback: bash ./install/install.sh. Then ensure bd is available in PATH.',
|
||||
tools: {
|
||||
bd: { available: false, path: null },
|
||||
},
|
||||
bb: null,
|
||||
mail: null,
|
||||
memory: null,
|
||||
},
|
||||
null,
|
||||
2,
|
||||
|
|
@ -86,6 +119,7 @@ async function main() {
|
|||
configured: false,
|
||||
reason: 'bb not available — mail delegate requires bb agent commands',
|
||||
},
|
||||
memory: null,
|
||||
},
|
||||
null,
|
||||
2,
|
||||
|
|
@ -95,6 +129,7 @@ async function main() {
|
|||
}
|
||||
|
||||
const mail = configureMailDelegate(bdPath, shimPath);
|
||||
const memory = validateMemorySystem(bdPath);
|
||||
|
||||
process.stdout.write(
|
||||
`${JSON.stringify(
|
||||
|
|
@ -106,6 +141,7 @@ async function main() {
|
|||
},
|
||||
bb,
|
||||
mail,
|
||||
memory,
|
||||
},
|
||||
null,
|
||||
2,
|
||||
|
|
@ -124,6 +160,7 @@ async function main() {
|
|||
},
|
||||
bb: null,
|
||||
mail: null,
|
||||
memory: null,
|
||||
},
|
||||
null,
|
||||
2,
|
||||
|
|
|
|||
95
skills/beadboard-driver/scripts/setup-mail-delegate.mjs
Normal file
95
skills/beadboard-driver/scripts/setup-mail-delegate.mjs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* setup-mail-delegate.mjs
|
||||
*
|
||||
* Configures bd's mail.delegate to point at the bb-mail-shim.mjs bundled
|
||||
* alongside this script. Uses import.meta.url to resolve the absolute path
|
||||
* so the caller never needs to know where the skill is installed.
|
||||
*
|
||||
* Usage: node {baseDir}/scripts/setup-mail-delegate.mjs
|
||||
* Output: JSON { ok, configured, delegate } or { ok, error_code, reason }
|
||||
*/
|
||||
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname, join } from 'node:path';
|
||||
|
||||
import { findCommandInPath } from './lib/driver-lib.mjs';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const shimPath = join(__dirname, 'bb-mail-shim.mjs');
|
||||
const delegateCommand = `node ${shimPath}`;
|
||||
|
||||
async function main() {
|
||||
const dryRun = process.argv.includes('--dry-run');
|
||||
const bdPath = await findCommandInPath('bd');
|
||||
|
||||
if (!bdPath) {
|
||||
process.stdout.write(
|
||||
`${JSON.stringify(
|
||||
{
|
||||
ok: false,
|
||||
error_code: 'BD_NOT_FOUND',
|
||||
reason: 'Could not find bd in PATH. Install with: npm install -g beads-cli',
|
||||
delegate: null,
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dryRun) {
|
||||
process.stdout.write(
|
||||
`${JSON.stringify(
|
||||
{
|
||||
ok: true,
|
||||
dry_run: true,
|
||||
configured: false,
|
||||
delegate: delegateCommand,
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const result = spawnSync(bdPath, ['config', 'set', 'mail.delegate', delegateCommand], {
|
||||
stdio: 'pipe',
|
||||
shell: false,
|
||||
});
|
||||
|
||||
if (result.status !== 0) {
|
||||
const stderr = result.stderr?.toString().trim() || '';
|
||||
process.stdout.write(
|
||||
`${JSON.stringify(
|
||||
{
|
||||
ok: false,
|
||||
error_code: 'BD_CONFIG_FAILED',
|
||||
reason: stderr || 'bd config set mail.delegate exited non-zero.',
|
||||
delegate: delegateCommand,
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
process.stdout.write(
|
||||
`${JSON.stringify(
|
||||
{
|
||||
ok: true,
|
||||
configured: true,
|
||||
delegate: delegateCommand,
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
);
|
||||
}
|
||||
|
||||
void main();
|
||||
|
|
@ -21,7 +21,7 @@ test('ensure-project-context creates project.md when missing', async () => {
|
|||
const content = await fs.readFile(path.join(root, 'project.md'), 'utf8');
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(result.created, true);
|
||||
assert.match(content, /Project Driver Template/);
|
||||
assert.match(content, /Environment Status Cache/);
|
||||
} finally {
|
||||
await fs.rm(root, { recursive: true, force: true });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ const tests = [
|
|||
path.join(__dirname, 'diagnose-env.contract.test.mjs'),
|
||||
path.join(__dirname, 'heal-common-issues.contract.test.mjs'),
|
||||
path.join(__dirname, 'ensure-project-context.contract.test.mjs'),
|
||||
path.join(__dirname, 'setup-mail-delegate.contract.test.mjs'),
|
||||
];
|
||||
|
||||
const child = spawn(process.execPath, ['--test', ...tests], {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs/promises';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { execFile } from 'node:child_process';
|
||||
import { promisify } from 'node:util';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname } from 'node:path';
|
||||
|
||||
const execFileAsync = promisify(execFile);
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const scriptPath = path.resolve('skills/beadboard-driver/scripts/setup-mail-delegate.mjs');
|
||||
const expectedShimPath = path.join(__dirname, '..', 'scripts', 'bb-mail-shim.mjs');
|
||||
|
||||
async function withTempDir(run) {
|
||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'bb-skill-setupdelegate-'));
|
||||
try {
|
||||
await run(root);
|
||||
} finally {
|
||||
await fs.rm(root, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
test('setup-mail-delegate contract: dry-run resolves absolute shim path', async () => {
|
||||
await withTempDir(async (root) => {
|
||||
const { stdout } = await execFileAsync(process.execPath, [scriptPath, '--dry-run'], {
|
||||
cwd: root,
|
||||
env: { ...process.env },
|
||||
});
|
||||
|
||||
const result = JSON.parse(stdout);
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(result.dry_run, true);
|
||||
assert.ok(
|
||||
result.delegate.includes('bb-mail-shim.mjs'),
|
||||
`delegate should reference bb-mail-shim.mjs, got: ${result.delegate}`,
|
||||
);
|
||||
|
||||
const resolvedPath = result.delegate.replace(/^node\s+/, '');
|
||||
assert.ok(
|
||||
path.isAbsolute(resolvedPath),
|
||||
`delegate path should be absolute, got: ${resolvedPath}`,
|
||||
);
|
||||
assert.equal(
|
||||
resolvedPath,
|
||||
expectedShimPath,
|
||||
`delegate should point to the bundled shim`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('setup-mail-delegate contract: BD_NOT_FOUND when bd missing', async () => {
|
||||
await withTempDir(async (root) => {
|
||||
const { stdout } = await execFileAsync(process.execPath, [scriptPath], {
|
||||
cwd: root,
|
||||
env: {
|
||||
...process.env,
|
||||
PATH: '/nonexistent',
|
||||
},
|
||||
});
|
||||
|
||||
const result = JSON.parse(stdout);
|
||||
assert.equal(result.ok, false);
|
||||
assert.equal(result.error_code, 'BD_NOT_FOUND');
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue