# pi-orchestrator: interactive_protection — skip_owners + grace window (Patch #10063)

## Summary

**Symptom:** John's H/M tasks added via `mc.js add` were being auto-paused by pi-orchestrator within seconds, before manual orchestration (prompt-forge → mehanik → dispatch pipeline) could begin.  
**Root cause:** The daemon's `getNextTask()` loop claimed any open H/M task with no owner-based exclusion, colliding with John's interactive workflow where tasks are created as `open` before the human pipeline starts.  
**Fix:** Added `interactive_protection` config block (skip\_owners + grace\_seconds) and updated the SQL WHERE clause in pi-orchestrator.js (lines 3412–3471) to respect both guards.  
**Date:** 2026-04-29 | **Patch:** MC #10063 | **Proveo verdict:** 8/8 PASS

---

## Root Cause Detail

Prior to this patch, `getNextTask()` in `~/system/kernel/pi-orchestrator.js` selected tasks with a WHERE clause limited to status and priority, with no consideration for task owner. This meant:

- John runs `node ~/system/tools/mc.js add "TASK" --priority H --owner john`
- Task is inserted as `status=open, owner=john`
- Within one daemon poll cycle (~30s), the daemon claimed and auto-paused the task
- John's manual /prompt-forge → /mehanik → dispatch pipeline never had the chance to operate on it

The collision was systematic: `mc.js add` happens *before* manual orchestration begins by design (ZAKON #25). The daemon treated all open tasks as automation targets.

---

## New Config Keys

File: `~/system/config/pi-orchestrator-config.json` (block added at patch time):

```json
"interactive_protection": {
  "skip_owners": ["john"],
  "grace_seconds": 300
}
```

- **skip\_owners**: Array of owner names whose tasks are *never* picked up by the daemon, regardless of age or priority.
- **grace\_seconds**: Unowned tasks (NULL owner) created within this window are also protected — prevents premature pickup of tasks that have not yet been assigned to an owner.
- **Backwards safe:** If the config block is absent, both defaults activate automatically (`skip_owners=['john']`, `grace=300s`). No existing deployments are broken by a missing block.

---

## Pickup Logic Table

<table id="bkmrk-owneragepicked-up%3Fre"> <thead> <tr><th>Owner</th><th>Age</th><th>Picked up?</th><th>Reason</th></tr> </thead> <tbody> <tr><td>`john`</td><td>any</td><td>**NO**</td><td>Interactive owner — skip\_owners guard</td></tr> <tr><td>NULL (unowned)</td><td>&lt; 300s</td><td>**NO**</td><td>Grace window — task may still be in orchestration queue</td></tr> <tr><td>NULL (unowned)</td><td>≥ 300s</td><td>**YES**</td><td>True unassigned automation task</td></tr> <tr><td>`pi-orchestrator` / `autowork` / `agent-worker`</td><td>any</td><td>**YES**</td><td>Explicit automation owners — allowlist passthrough</td></tr> <tr><td>`edita` / other non-protected</td><td>any</td><td>**YES**</td><td>Existing behavior unchanged</td></tr> </tbody></table>

---

## Verification Commands

```bash
# Confirm daemon is running with new code
launchctl list | grep pi-orchestrator   # should return active PID (e.g. 31020)

# Confirm config has interactive_protection block
cat ~/system/config/pi-orchestrator-config.json | jq .interactive_protection

# Live test: create H task as john, verify NOT auto-paused after 90s
ID=$(node ~/system/tools/mc.js add "VERIFY-protection" --priority H --owner john --category system | grep -oE '#[0-9]+' | tr -d '#')
sleep 90
node ~/system/tools/mc.js show $ID | grep -E "Status|Owner"
# Expected: Status = open  |  Owner = john
```

---

## Daemon Reload Procedure

Run this after any change to `pi-orchestrator-config.json` or `pi-orchestrator.js`:

```bash
launchctl unload ~/system/daemons/launchagents/com.john.pi-orchestrator.plist
launchctl load  ~/system/daemons/launchagents/com.john.pi-orchestrator.plist
sleep 5 && launchctl list | grep pi-orchestrator   # PID should be present
```

**Note:** The daemon reads config at startup. Changes to `interactive_protection` are *not* hot-reloaded; a full unload/load cycle is required.

---

## Tuning Guide

### Adding another interactive owner (e.g. alem)

Edit `~/system/config/pi-orchestrator-config.json`: add the owner name to the `skip_owners` array, save, then reload the daemon (procedure above).

### Extending the grace window for slower workflows

Edit `~/system/config/pi-orchestrator-config.json`: increase `grace_seconds` (e.g. 600 for 10-minute window), save, then reload the daemon.

### Verifying config was picked up after reload

```bash
grep -i "interactive_protection|skip_owners|grace" ~/system/logs/pi-orchestrator.log | tail -5
```

---

## Evidence &amp; Cross-References

- **MC #10063:** Task record — `node ~/system/tools/mc.js show 10063`
- **Proveo report (8/8 PASS):** `/tmp/postflight-10063/proveo-report.md`
- **Evidence bundle:** `/tmp/10063-evidence/` (config before/after, diff, reload log, scenario results)
- **Backups:** `~/system/kernel/pi-orchestrator.js.bak-10063` and `~/system/config/pi-orchestrator-config.json.bak-10063`
- **Related runbook — MC #10036:** [MC Quality Trail Validator — agent output write semantics (Patch #10036)](https://docs.alai.no/books/runbooks/page/mc-quality-trail-validator-agent-agent-output-write-semantics-patch-10036)