257 lines
8.1 KiB
Markdown
257 lines
8.1 KiB
Markdown
# Operative Protocol v1 (Session Constitution)
|
|
|
|
Date: 2026-02-14
|
|
Status: Approved for implementation (superseded for migration planning by `docs/protocols/2026-02-28-bd-audit-coordination-schema.md`)
|
|
Scope: `bb-u6f.6.1`
|
|
Applies to: `bb-u6f.6.2`, `bb-u6f.6.3`, `bb-u6f.6.4`, `bb-u6f.6.5`
|
|
|
|
## 1. Purpose and Boundaries
|
|
|
|
This protocol defines non-negotiable coordination behavior for multi-agent work in BeadBoard Sessions.
|
|
|
|
Boundaries:
|
|
1. Work lifecycle state remains Beads-native (`bd` commands only).
|
|
2. Agent coordination state lives in `bb agent` surfaces and supporting local stores.
|
|
3. No direct writes to `.beads/issues.jsonl`.
|
|
4. User-facing labels must stay plain language.
|
|
|
|
Migration note:
|
|
1. New work should target the `coord.v1` `bd audit` event model documented in `docs/protocols/2026-02-28-bd-audit-coordination-schema.md`.
|
|
2. `bb` coordination semantics are legacy compatibility behavior pending removal after migration sign-off.
|
|
|
|
## 2. Normative Language
|
|
|
|
1. MUST: required behavior.
|
|
2. SHOULD: recommended unless explicit exception is justified.
|
|
3. MAY: optional behavior.
|
|
|
|
## 3. Identity Trust Model
|
|
|
|
### 3.1 Identity primitives
|
|
|
|
Every active session has:
|
|
1. `session_agent_id`: unique working identity for the current runtime.
|
|
2. `logical_agent_id`: persistent persona name used in coordination records.
|
|
|
|
For v1 implementation, both map to the same field (`agent_id`), but contract keeps room for split in future.
|
|
|
|
### 3.2 Adoption policy (resume prior identity)
|
|
|
|
Identity adoption is allowed only when at least one condition is true:
|
|
1. Uncommitted changes exist in target scope (`git status --porcelain` contains files in claimed scope).
|
|
2. Target identity owns at least one `in_progress` bead relevant to current scope.
|
|
|
|
If neither condition is true, adoption MUST be rejected in non-interactive mode and SHOULD require explicit confirmation in interactive mode.
|
|
|
|
### 3.3 Session uniqueness policy
|
|
|
|
1. Each runtime session MUST start with a unique identity name for that session, unless valid adoption is selected.
|
|
2. Reusing previous identity without adoption checks is forbidden.
|
|
3. Recommended naming style is adjective-noun (for example, `amber-otter`, `cobalt-harbor`).
|
|
|
|
### 3.4 Mandatory resume audit signal
|
|
|
|
Any successful identity adoption MUST emit a `RESUME` protocol event with:
|
|
1. prior owner identity,
|
|
2. adoption reason (`uncommitted_scope` or `in_progress_ownership`),
|
|
3. linked bead id(s) when known.
|
|
|
|
Event must be persisted in coordination history exposed to Sessions APIs.
|
|
|
|
## 4. Heartbeat and Liveness Contract
|
|
|
|
### 4.1 Environment and defaults
|
|
|
|
1. `BB_AGENT_STALE_MINUTES` default: `15`.
|
|
2. Stale threshold: `T_last_seen + stale_minutes`.
|
|
3. Eviction threshold: `T_last_seen + (2 * stale_minutes)`; default `30` minutes.
|
|
|
|
### 4.2 Heartbeat behavior
|
|
|
|
1. `bb agent heartbeat --agent <id>` MUST update `last_seen_at` in UTC ISO-8601.
|
|
2. Heartbeat command MUST be idempotent and safe to run repeatedly.
|
|
3. Heartbeat command MUST support JSON envelope output (`ok`, `command`, `data`, `error`).
|
|
|
|
### 4.3 Liveness states
|
|
|
|
Derived states:
|
|
1. `active`: now < stale threshold.
|
|
2. `stale`: stale threshold <= now < eviction threshold.
|
|
3. `evicted`: now >= eviction threshold.
|
|
|
|
### 4.4 Reservation interaction rules
|
|
|
|
For scope takeover:
|
|
1. If reservation owner is `active`: takeover MUST fail.
|
|
2. If owner is `stale`: takeover MAY succeed only when `--takeover-stale` is supplied.
|
|
3. If owner is `evicted`: takeover SHOULD succeed with `--takeover-stale`; prior reservation must be archived as expired.
|
|
|
|
## 5. Path Overlap Canonicalization Contract
|
|
|
|
### 5.1 Normalization pipeline
|
|
|
|
All scope comparisons MUST use the same normalization pipeline:
|
|
1. Resolve to absolute path (`path.resolve`).
|
|
2. Normalize separators to `/`.
|
|
3. On Windows, lowercase normalized path for comparisons.
|
|
4. Remove trailing slash except root.
|
|
|
|
### 5.2 Scope classes
|
|
|
|
Given normalized `A` and `B`:
|
|
1. `exact`: `A === B`.
|
|
2. `partial`: `A` is parent of `B` or `B` is parent of `A`.
|
|
3. `disjoint`: neither exact nor parent-child.
|
|
|
|
Wildcards:
|
|
1. Prefix wildcard (`src/*`) is treated as directory prefix match for overlap checks.
|
|
2. Glob semantics beyond suffix `*` are out of scope for v1.
|
|
|
|
### 5.3 Required examples
|
|
|
|
1. `src/*` vs `src/lib/parser.ts` => `partial`.
|
|
2. `src/lib` vs `src/lib/parser.ts` => `partial`.
|
|
3. `src/lib/parser.ts` vs `src/lib/parser.ts` => `exact`.
|
|
4. `src/lib` vs `src/components` => `disjoint`.
|
|
|
|
## 6. Protocol Event Schema (Stable JSON Contract)
|
|
|
|
### 6.1 Envelope (all protocol events)
|
|
|
|
```json
|
|
{
|
|
"id": "proto_20260214_001",
|
|
"version": "v1",
|
|
"event_type": "HANDOFF",
|
|
"project_root": "/path/to/project",
|
|
"bead_id": "bb-u6f.6.3",
|
|
"from_agent": "amber-otter",
|
|
"to_agent": "cobalt-harbor",
|
|
"scope": "src/components/sessions/*",
|
|
"created_at": "2026-02-14T18:05:11.000Z",
|
|
"payload": {}
|
|
}
|
|
```
|
|
|
|
Required fields:
|
|
1. `id`
|
|
2. `version` (must be `v1` for this protocol)
|
|
3. `event_type`
|
|
4. `project_root`
|
|
5. `bead_id`
|
|
6. `from_agent` (nullable for system-originated events only)
|
|
7. `to_agent` (nullable for system-originated events only)
|
|
8. `scope` (nullable where not applicable)
|
|
9. `created_at`
|
|
10. `payload`
|
|
|
|
### 6.2 Event-specific payloads
|
|
|
|
`HANDOFF` payload:
|
|
1. `subject` (required)
|
|
2. `summary` (required)
|
|
3. `next_action` (required)
|
|
4. `requires_ack` (required, true by default)
|
|
|
|
`BLOCKED` payload:
|
|
1. `subject` (required)
|
|
2. `blocker` (required)
|
|
3. `requested_action` (required)
|
|
4. `urgency` (required: `low|medium|high`)
|
|
5. `requires_ack` (required, true)
|
|
|
|
`INCURSION` payload:
|
|
1. `incursion_kind` (required: `exact|partial`)
|
|
2. `owner_agent` (required)
|
|
3. `incoming_agent` (required)
|
|
4. `owner_liveness` (required: `active|stale|evicted`)
|
|
5. `resolution_hint` (required)
|
|
|
|
`RESUME` payload:
|
|
1. `resume_reason` (required: `uncommitted_scope|in_progress_ownership`)
|
|
2. `prior_session_agent` (required)
|
|
3. `adopted_agent` (required)
|
|
4. `evidence` (required string summary of why adoption passed)
|
|
|
|
### 6.3 UI mapping requirements
|
|
|
|
Sessions UI mapping contract:
|
|
1. `HANDOFF` label: `Passed to`
|
|
2. `BLOCKED` label: `Needs input`
|
|
3. Read action label: `Seen`
|
|
4. Ack action label: `Accepted`
|
|
|
|
`INCURSION` and `RESUME` MUST render as first-class protocol rows in the conversation timeline, not hidden diagnostics.
|
|
|
|
## 7. CLI Contract Requirements for Implementers
|
|
|
|
Required commands for v1 rollout:
|
|
1. `bb agent heartbeat --agent <id> [--json]`
|
|
2. `node scripts/bb-init.mjs --non-interactive --json`
|
|
3. `node scripts/bb-init.mjs --adopt <agentId> --json`
|
|
4. `node scripts/bb-init.mjs --register <name> --json`
|
|
|
|
Non-interactive requirements:
|
|
1. MUST not prompt.
|
|
2. MUST fail with structured error when decision cannot be made safely.
|
|
3. MUST include deterministic recommendation reason in output.
|
|
|
|
## 8. Mapping to Existing Code Modules
|
|
|
|
### 8.1 Backend
|
|
|
|
1. `src/lib/agent-registry.ts`
|
|
2. `src/lib/agent-reservations.ts`
|
|
3. `src/lib/realtime.ts`
|
|
4. `src/lib/agent-sessions.ts`
|
|
|
|
### 8.2 API
|
|
|
|
1. `src/app/api/sessions/route.ts`
|
|
2. `src/app/api/sessions/[beadId]/conversation/route.ts`
|
|
|
|
### 8.3 UI
|
|
|
|
1. `src/components/sessions/session-feed-card.tsx`
|
|
2. `src/components/sessions/session-task-feed.tsx`
|
|
3. `src/components/sessions/conversation-drawer.tsx`
|
|
4. `src/components/sessions/sessions-page.tsx`
|
|
5. `src/hooks/use-session-feed.ts`
|
|
6. `src/hooks/use-beads-subscription.ts`
|
|
|
|
### 8.4 CLI and skill
|
|
|
|
1. `tools/bb.ts`
|
|
2. `scripts/bb-init.mjs` (new)
|
|
3. `skills/beadboard-driver/SKILL.md`
|
|
|
|
## 9. Acceptance Checklist for Downstream Beads
|
|
|
|
`bb-u6f.6.2` MUST implement:
|
|
1. heartbeat mutation,
|
|
2. stale/evicted derivation,
|
|
3. overlap classification,
|
|
4. protocol event emission.
|
|
|
|
`bb-u6f.6.3` MUST implement:
|
|
1. heartbeat command,
|
|
2. non-interactive `bb-init` contract and flags.
|
|
|
|
`bb-u6f.6.4` MUST implement:
|
|
1. protocol event rendering in Sessions,
|
|
2. incursion/stale visibility,
|
|
3. no-refresh-required update behavior.
|
|
|
|
`bb-u6f.6.5` MUST implement:
|
|
1. updated skill flow matching this protocol exactly.
|
|
|
|
## 10. Rejected Alternatives
|
|
|
|
1. Interactive-only bootstrap prompts.
|
|
Reason: automation sessions require deterministic non-blocking behavior.
|
|
|
|
2. Implicit overlap inference without normalization contract.
|
|
Reason: inconsistent behavior across Windows paths.
|
|
|
|
3. UI-first implementation before protocol schema.
|
|
Reason: high risk of repeated API/UI contract churn.
|