jan-cli 0.27.0

YAML-defined CLI trees with progressive help, optional exec aliases, merged extra specs, and SQLite audit logging keyed by git branch
Documentation
# Unifier + Jan multi-agent synergy

Jan and Unifier stay separate products, but **Jan is allowed to speak Unifier’s daemon sockets**. Dotfiles agents are **CLI-only**: they never listen on sockets.

This page is the rationale. The normative wire contract — schemas, delivery
semantics, invariants, failure modes — is [ipc-contract.md](ipc-contract.md).

## Socket roles

| Channel | Direction | Who uses it |
|---------|-----------|-------------|
| **`events.sock`** | Unifier → subscribers | **Jan cron** listens; wakes leaves on mailbox/event (and tick-phase) notices |
| **`tick.sock`** | Jan → Unifier | **Jan** (and `unifier tick` CLI) starts/ends/locks ticks and sets phases; Unifier runs the ACID state machine |
| **`unifier` CLI** | Agent → Unifier | **Dotfiles agents** only (`put`/`get`/`message`/`event`/`ack`/`log`/`sql`/…) |

```
agent: unifier message …  →  Unifier  →  events.sock  →  Jan  →  jan … pong-agent run --message-id …
Jan tick driver           →  tick control sock  →  Unifier tick start/end
                          →  spawn phased agents with JAN_TICK / --phase
agents                    →  unifier get/put/… (CLI)
```

No agent opens `events.sock` or the tick control socket.

## Role split

| Layer | Owns | Does not own |
|---|---|---|
| **Unifier** | Blackboard, mail, events, **`events.sock`**, **tick semantics + tick control API**, sql, log, serve | Jan leaves, cron expressions |
| **Jan** | Leaf identity, cron, **event-socket listener**, **tick lifecycle driver**, wakeup registry, concurrency, disable | Board schemas, agent business logic |
| **Dotfiles** | Arm scripts via **CLI**, key conventions, swarm bring-up of the two daemons | Any socket listener / bridge daemon |

## What synergizes

**1. Name-as-address via Jan.**  
Unifier notice `to` / `name` → Jan registry → leaf + argv (`--message-id`, …). Agents do not subscribe.

**2. Clocks.**  
- Wall: Jan `cron:`  
- Causal: `events.sock` → Jan  
- Coordinated turns: Unifier **ticks**, **driven by Jan** over the reverse socket  

**3. Blackboard vs mailbox.**  
Agents `unifier put/get` for facts; `unifier message`/`event` to signal; Jan delivers the wake.

**4. Process isolation.**  
Isolated process (or fork/worker child) per run — not necessarily a cold interpreter start. Jan may reuse warm language workers; each job still runs in a fresh child so state does not leak. Shared state only through Unifier CLI (and argv/env Jan injects).

**5. Ops.**  
`jan cron status` should show events + tick connectivity; Unifier keeps `tick status` / `daemon watch` for debugging.

## Patterns

```
jan cron sensor     →  unifier put (CLI)
unifier message/event (CLI) → events.sock → Jan → specialist
Jan tick driver → tick sock → phases → agents (CLI board I/O)
report → unifier serve (CLI)
```

## Debt / direction

Keep Jan’s `events.sock` listener (harden it). Unifier **`tick.sock`** + `tick phase` + tick notices on `events.sock` are in place—next is Jan’s tick driver (0.3) and concurrency/queue hardening (0.1 / 0.6). Agents remain CLI-only (no socket listeners).

## Weak spots

Jan↔Unifier socket coupling is real (intentional at the daemon layer). Registry misconfig misses wakes. Agents must stay disciplined (CLI only). Tick driver failure modes need clear ownership (Jan retries vs Unifier tick queue).

## Practical architecture

1. Define arms as Jan leaves; use `unifier` CLI inside them.  
2. Configure Jan wakeup registry for bus names.  
3. Sensors: Jan cron + CLI writes; notify with `unifier message`/`event`.  
4. Specialists: no `cron:` required; Jan wakes from `events.sock`.  
5. Coordinated turns: Jan tick YAML/driver + Unifier tick sock—not agent-orchestrated sockets.  
6. `jan cron disable` to pause arms.  
7. Humans: `unifier serve` / `log` from agents or one-shot CLI.

## Bottom line

**Unifier** owns the board, the **event broadcast socket**, and **tick semantics** (plus a tick **control** socket). **Jan** listens on events, drives ticks the other way, and spawns leaves. **Dotfiles** only makes **`unifier` CLI calls**—never socket listeners.