# PIPELINES.md

Foreground/Background pipeline contract for OpenClaw operations.

## Purpose
Prevent context drift by separating user interaction from asynchronous processing.

## Pipeline Split

### Foreground Pipeline (FP)
Owns the user conversation.

Responsibilities:
- Track active thread (`thread_id`, `thread_title`, `status`)
- Ask clarifying questions and collect approvals
- Start background jobs with explicit payloads
- Consume background completion summaries
- Present concise results + options to user

Rules:
- FP must not run long jobs inline when BG is appropriate.
- FP must not acknowledge ambiguous confirmations ("done", "fixed") without target resolution.
- After any reminder/cron interrupt, FP must explicitly return to the prior active thread unless user switches.

### Background Pipeline (BP)
Runs jobs, automations, and sub-agent tasks.

Responsibilities:
- Execute deterministic task payloads
- Write structured status/events
- Return compact completion summaries and artifacts

Rules:
- BP must not assume conversational context.
- BP must operate only on provided `job_payload`.
- BP must be idempotent where possible.

## Data Contract

### Job Request (FP -> BP)
```json
{
  "job_id": "uuid-or-stable-id",
  "origin_thread": {
    "thread_id": "string",
    "thread_title": "string"
  },
  "intent": "string",
  "inputs": {
    "...": "..."
  },
  "approval_ref": "message_id-or-confirm-token",
  "priority": "low|normal|high",
  "idempotency_key": "string"
}
```

### Job Event (BP -> FP)
```json
{
  "job_id": "string",
  "event": "started|progress|completed|failed",
  "timestamp": "ISO-8601",
  "summary": "short human-readable status",
  "details": {
    "...": "..."
  }
}
```

### Job Completion (BP -> FP)
```json
{
  "job_id": "string",
  "origin_thread": "string",
  "status": "completed|failed|partial",
  "completion_summary": "2-5 sentence summary",
  "artifacts": [
    {"type": "url|file|id", "value": "string", "label": "string"}
  ],
  "next_action_required": true,
  "next_action_prompt": "optional user-facing question"
}
```

## Thread Guard Rails (Foreground)

1. Maintain a single `active_thread` pointer.
2. On interruption (cron/reminder):
   - mark `active_thread.status = paused`
   - run interrupt task
   - restore previous `active_thread`
3. For ambiguous confirmations:
   - if >1 candidate target exists, ask: "Which thread is this done for: A or B?"
4. Before any state-changing action, bind action to explicit thread + target object.

## Checkpoint Files

- `memory/active-thread.md` (single latest pointer)
- `memory/YYYY-MM-DD.md` (append transition events)

### active-thread.md format
```md
thread_id: tailscale-hardening
thread_title: Tailscale hardening for dashboard access
status: active
updated_at: 2026-03-01T14:59:00-08:00
last_user_intent: "resume hardening and enforce guard rails"
```

### daily checkpoint line format
```md
- [HH:MM] THREAD_SWITCH from=<old_thread> to=<new_thread> reason=<user|reminder|system>
```

## Scheduling and Ownership

- Cron/reminders should trigger BP tasks by default.
- FP should only receive completion summaries unless user asks for full logs.
- For complex work, use isolated sessions/subagents and report via completion payload.

## Failure Handling

When BP fails:
1. Return structured failure with probable cause and safe retry command.
2. FP asks user whether to retry, adjust inputs, or pause.
3. Do not silently switch active thread on failure.

## Verification Checklist

Run this checklist weekly:
- [ ] Ambiguous "done" messages were disambiguated
- [ ] Interruptions returned to prior thread explicitly
- [ ] Every background run emitted `job_id` and completion summary
- [ ] Active thread checkpoint updated on thread switches

## Success Criteria

- Foreground conversation remains coherent across reminders/jobs
- Background work progresses independently
- User confirmations always map to the intended thread
