mirror of
https://github.com/mvschwarz/openrig.git
synced 2026-11-07 05:56:21 -10:00
feat(skills): ship public routing and default projection
This commit is contained in:
1 parent
25bdf742b0
commit
4c6d88834c
116 files changed
+5161
-5078
No files matched your search
+1
-1
@@ -169,7 +169,7 @@ deprecations, and behavioral changes. Breaking changes are called out explicitly
|
||||
|
||||
- **New verbs (capped at exactly three)**: `rig host add` (registry writes validated by the loader's own rules — no more hand-edited YAML for the standard path), `rig host list` (config pointers, never secret values), `rig host doctor <id>` (stepwise distinct errors: transport → remote rig binary → daemon health → identity) with `--posture product-factory-vps` — the ONE built-in security baseline, three-valued per item (UNKNOWN is never pass).
|
||||
- **Transport posture DECIDED + documented** (no behavior change): ssh carries pane ops (`send`/`capture`), http-bearer carries daemon REST (`up`/`down`/`launch`), `ps`/`whoami` follow the host's declared transport, fan-out is http-only; NO cross-transport fallback; NO http parity for send/capture in 0.4.4. Per-command table in cli-reference §Cross-host execution.
|
||||
- **Product-factory bootstrap**: `scripts/bootstrap-product-factory-vps.sh` + `docs/reference/product-factory-vps-runbook.md` (fresh Ubuntu VPS → factory-ready; smoke-tested VPS posture as encoded defaults; safe UI tunnel + restricted fail-closed reverse-path recipes).
|
||||
- **Product-factory bootstrap**: `scripts/bootstrap-product-factory-vps.sh` (fresh Ubuntu VPS → factory-ready; smoke-tested VPS posture as encoded defaults).
|
||||
|
||||
### BREAKING: `rig ps` consolidated all-rigs default + explicit disclosure ladder (OPR.0.4.4.21)
|
||||
|
||||
|
||||
@@ -946,8 +946,8 @@ Semantics + safety wall (source: `packages/cli/src/lib/file-transfer.ts`):
|
||||
|
||||
Usage: `rig host <add|list|doctor>` — the multi-host registry verbs (OPR.0.4.4.13; capped at
|
||||
exactly these three — no edit/remove/tunnel/bootstrap verbs; hand-editing `hosts.yaml` remains
|
||||
the path for exotica, and the factory bootstrap ships as script + runbook at
|
||||
`docs/reference/product-factory-vps-runbook.md`).
|
||||
the path for exotica, and the factory bootstrap ships as
|
||||
`scripts/bootstrap-product-factory-vps.sh`).
|
||||
|
||||
- `add --id <id> --transport <ssh|http> [--target <t> --user <u> | --url <u> [--bearer-env <n>|--bearer-file <p>]] [--notes <text>] [--json]` — writes the entry validated by the registry loader's OWN rules (add-time errors are load-time errors, verbatim; duplicate ids refused; the http bearer pointer is optional — omit both for a tokenless daemon, never both). Rewrites `hosts.yaml` canonically (hand-authored comments are not preserved).
|
||||
- `list [--json]` — id/transport/target plus AUTH as a config POINTER (`env:NAME` / `file:PATH` / `ssh-key`); never a resolved secret value.
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
# Product-Factory VPS Runbook (product-factory-vps)
|
||||
|
||||
OPR.0.4.4.13 — the productized form of the 2026-06-23 OVH smoke test: a fresh
|
||||
Ubuntu VPS becomes an OpenRig product factory managed from a home base, with
|
||||
the proven security posture as the encoded default. The bootstrap is a
|
||||
SCRIPT + THIS RUNBOOK by design — host verbs are capped at `add`/`list`/
|
||||
`doctor`, and the acceptance anchor is the observable end state: home-base
|
||||
`rig host doctor <id>` all green.
|
||||
|
||||
## 1. Prerequisites
|
||||
|
||||
- A fresh Ubuntu 22.04/24.04 VPS (any provider; the lived reference was OVH).
|
||||
- A Tailscale tailnet you administer; the home base already on it.
|
||||
- A home-base SSH keypair for the factory (`ssh-keygen -t ed25519 -f ~/.ssh/openrig-factory`).
|
||||
- The published OpenRig artifact (`@openrig/cli@<version>`) or the packaged
|
||||
tarball a release branch builds (`npm pack` output) for pre-release proof.
|
||||
- Dedicated Claude/Codex accounts for THIS factory. Never copy home-base
|
||||
credentials (`~/.claude`, `~/.codex`, `~/.openrig`) onto a VPS.
|
||||
|
||||
## 2. Tailscale tag + ACL (one-time per tailnet)
|
||||
|
||||
In the Tailscale admin console (the UI's words, mapped):
|
||||
- **tag name**: `openrig-vps` (enter as `tag:openrig-vps` in ACL JSON).
|
||||
- **tag owner**: your tailnet admin group/user (`"tagOwners": {"tag:openrig-vps": ["autogroup:admin"]}`).
|
||||
- ACL: home base may reach `tag:openrig-vps` on 22/7433 over the tailnet;
|
||||
`tag:openrig-vps` gets NO grants toward the home base (the reverse path is
|
||||
the explicit recipe in §6, never standing policy).
|
||||
- Auth keys for `tailscale up` must be EPHEMERAL or revoked after use.
|
||||
|
||||
## 3. Bootstrap (fresh VPS → factory-ready)
|
||||
|
||||
On the VPS, as root:
|
||||
|
||||
```bash
|
||||
curl -fsSLO <your-copy-of>/scripts/bootstrap-product-factory-vps.sh
|
||||
chmod +x bootstrap-product-factory-vps.sh
|
||||
./bootstrap-product-factory-vps.sh \
|
||||
--artifact @openrig/cli@<version> \
|
||||
--authorized-key "$(cat ~/.ssh/openrig-factory.pub)" \
|
||||
--ts-authkey tskey-... # ephemeral
|
||||
```
|
||||
|
||||
The script is stepwise and loud: non-root `openrig` user (key-only) → sshd
|
||||
hardening drop-in (`PermitRootLogin no`, `PasswordAuthentication no`,
|
||||
`KbdInteractiveAuthentication no`, `X11Forwarding no`) → UFW default-deny +
|
||||
tailnet ingress (public SSH stays open as a BOOTSTRAP ESCAPE HATCH only) →
|
||||
Tailscale with `tag:openrig-vps`, no routes/exit-node/Tailscale SSH → Node 22 →
|
||||
`npm install -g` of the artifact (must succeed with NO manual package
|
||||
patching) → daemon + kernel.
|
||||
|
||||
On the home base:
|
||||
|
||||
```bash
|
||||
rig host add --id ovh-01 --transport ssh --target <tailnet-alias> --user openrig
|
||||
rig host doctor ovh-01 # expect 4/4 green
|
||||
rig host doctor ovh-01 --posture product-factory-vps --public-addr <public-ip>
|
||||
```
|
||||
|
||||
Then close the escape hatch on the VPS: `sudo ufw delete allow OpenSSH` and
|
||||
make sure Tailscale SSH is off: `tailscale set --ssh=false`. Re-run the
|
||||
posture check. UNKNOWN posture items are NOT passes — each carries the command
|
||||
that verifies it from the right vantage.
|
||||
|
||||
## 4. Transport posture (the decided partition)
|
||||
|
||||
See the per-command transport table in `docs/as-built/cli-reference.md`
|
||||
(§Cross-host execution). The partition IS the intended posture: ssh carries
|
||||
interactive pane ops (`send`/`capture`); http carries daemon REST ops
|
||||
(`up`/`down`/`launch`); `ps`/`whoami` follow the host's DECLARED transport;
|
||||
fan-out (`--all-hosts`) is http-only. There is NO cross-transport fallback and
|
||||
NO http parity for send/capture in 0.4.4 (parity = new attack surface with no
|
||||
scope-locked need).
|
||||
|
||||
## 5. Safe UI access (recipe, not a verb)
|
||||
|
||||
The daemon binds loopback/tailnet — never public. View the factory UI through
|
||||
a local tunnel (the smoke test's exact form):
|
||||
|
||||
```bash
|
||||
ssh -N -L 127.0.0.1:17433:127.0.0.1:7433 <tailnet-alias>
|
||||
# then open http://127.0.0.1:17433
|
||||
```
|
||||
|
||||
Tear the tunnel down when done. Do not add public allow rules for :7433.
|
||||
|
||||
## 6. Restricted reverse path (supported recipe — NOT always-on)
|
||||
|
||||
Boundary first: home-base-initiated ONLY; no broad VPS→home SSH; the tunnel is
|
||||
torn down after use. The factory cannot freely reach into the home base.
|
||||
|
||||
1. On the home base, create a dedicated key the FACTORY will use through the
|
||||
reverse tunnel, and gate it with a forced command in
|
||||
`~/.ssh/authorized_keys`:
|
||||
|
||||
```text
|
||||
command="$HOME/.openrig/bin/openrig-reverse-gate",no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-pty ssh-ed25519 AAAA...factory-reverse-key
|
||||
```
|
||||
|
||||
2. The gate script (generatable template — allowlists EXACTLY the four verbs
|
||||
the smoke test proved; everything else is refused, fail-closed):
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
# openrig-reverse-gate — forced-command allowlist for the reverse path.
|
||||
set -euo pipefail
|
||||
case "${SSH_ORIGINAL_COMMAND:-}" in
|
||||
"rig send "*|"rig capture "*|"rig ps"*|"rig whoami"*)
|
||||
exec $SSH_ORIGINAL_COMMAND ;;
|
||||
*)
|
||||
echo "refused: only rig send/capture/ps/whoami are allowed on this key" >&2
|
||||
exit 77 ;;
|
||||
esac
|
||||
```
|
||||
|
||||
3. Open the reverse tunnel FROM the home base when you want the channel:
|
||||
|
||||
```bash
|
||||
ssh -N -R 127.0.0.1:2222:127.0.0.1:22 <tailnet-alias> # home-base initiated
|
||||
```
|
||||
|
||||
4. On the factory, agents reach home through it:
|
||||
`ssh -p 2222 -i <factory-reverse-key> [email protected] rig send <session> "..."`.
|
||||
5. Kill the tunnel after use. The REFUSAL of any out-of-allowlist verb is the
|
||||
proof artifact that the gate works — test it on purpose.
|
||||
|
||||
## 7. Credential + teardown discipline
|
||||
|
||||
- Runtime credentials (Claude/Codex) live ON the VPS, provisioned for it —
|
||||
never copied from the home host.
|
||||
- Snapshot/backup expectations and clean teardown follow the provider's
|
||||
tooling; `rig down --snapshot` before destroying a factory.
|
||||
- Revoke the Tailscale node + one-time keys when a factory is retired.
|
||||
@@ -462,6 +462,12 @@ describe("rig scope mission create (HG-14 + HG-15)", () => {
|
||||
expect(content).toMatch(/## §1\. Top-of-mind context/);
|
||||
expect(content).toMatch(/## §10\. What NOT to reconstruct/);
|
||||
expect(content).toMatch(/## §A\. <first-seat>@<rig> notes/);
|
||||
// Recovery must use durable full-body artifacts first. Compact queue rows
|
||||
// and transcript output are insufficient evidence after compaction.
|
||||
expect(content).toContain("rig queue list --mine --full --json");
|
||||
expect(content).toContain("rig queue show <id> --full --json");
|
||||
expect(content).toMatch(/little or\s+no output does not prove the session was quiet/);
|
||||
expect(content).not.toContain("rig queue list --destination <your-session>");
|
||||
});
|
||||
|
||||
it("FR-3: --no-mission-notes opts out — README created, MISSION_NOTES.md is NOT", async () => {
|
||||
|
||||
@@ -5,6 +5,11 @@ You are running inside an OpenRig-managed topology.
|
||||
This file is the thin bootstrap overlay, not the full OpenRig manual.
|
||||
Use it to recover identity, communicate, and regain context after launch or compaction.
|
||||
|
||||
When you are unsure which packaged skill applies, start with the global `openrig-skills` index. It routes to every shipped skill in one hop:
|
||||
|
||||
- Claude Code: `~/.claude/skills/openrig-skills/SKILL.md`
|
||||
- Codex: `~/.agents/skills/openrig-skills/SKILL.md`
|
||||
|
||||
For the full OpenRig command surface, load the packaged `openrig-user` skill now.
|
||||
If your runtime supports skills, use that mechanism.
|
||||
If it does not auto-load skills reliably, read the packaged copy directly from your current project or workspace:
|
||||
|
||||
@@ -4,7 +4,7 @@ Canonical OpenRig skills and hooks for cross-runtime agent topology coordination
|
||||
|
||||
## What this plugin ships
|
||||
|
||||
**Skills (11):** the canonical OpenRig operating knowledge — how to use the `rig` CLI, how to design rig topologies, how to recover from compaction, how to hand work off durably between agents, and how to maintain seat continuity across handovers and restarts.
|
||||
**Skills (10):** the canonical OpenRig operating knowledge — how to use the `rig` CLI, how to design rig topologies, how to recover from compaction, how to hand work off durably between agents, and how to maintain seat continuity across handovers and restarts.
|
||||
|
||||
**Hooks:** activity-tracking hooks (Claude Code: 4 events; Codex: 3 events) that POST agent state to the OpenRig daemon for real-time UI seat-status updates.
|
||||
|
||||
|
||||
+9
-6
@@ -4,15 +4,17 @@ description: Use when a Claude Code session has just compacted, is about to comp
|
||||
metadata:
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
last_verified: "2026-05-04"
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
Load-bearing for any OpenRig seat that may compact. PreCompact hook
|
||||
is wired into Claude Code's settings (e.g. ~/.claude/settings.json)
|
||||
so the restore packet is generated automatically before compaction.
|
||||
sibling_skills:
|
||||
- mental-model-ha
|
||||
- scope-recovery
|
||||
- session-compaction-and-restore
|
||||
- agent-startup-and-context-ingestion
|
||||
- agent-starters
|
||||
- composable-priming-packs
|
||||
- session-source-fork
|
||||
- seat-continuity-and-handover
|
||||
- claude-compact-in-place
|
||||
- pre-maintenance-agent-preservation
|
||||
---
|
||||
|
||||
# Claude Compaction Restore
|
||||
@@ -105,6 +107,7 @@ After the first restore pass, audit yourself before continuing.
|
||||
|
||||
## Guardrails
|
||||
|
||||
- Compaction is survival, not housekeeping — never compact to free space, "lean" a seat, or capture/prepare an agent starter (the `rig agent-image` library). It is lossy (a compacted Claude is confident-but-hollow); compact only when a seat is genuinely near its context limit, with a before/after plan. A starter's value is being *functional*, not small — see the `agent-starters` skill.
|
||||
- Do not silently launch fresh after compaction.
|
||||
- Do not continue from memory when restore evidence exists.
|
||||
- Do not defer required restore reading until a later user task. The restore is
|
||||
|
||||
+11
-72
@@ -41,10 +41,6 @@ function readInstructionFile(filePath) {
|
||||
return fs.readFileSync(expanded, "utf8");
|
||||
}
|
||||
|
||||
function sanitizeKey(value) {
|
||||
return value.replace(/[^a-zA-Z0-9_.@-]/g, "_");
|
||||
}
|
||||
|
||||
function sessionKey(input) {
|
||||
const raw = [
|
||||
process.env.OPENRIG_SESSION_NAME,
|
||||
@@ -55,65 +51,13 @@ function sessionKey(input) {
|
||||
input.sessionName,
|
||||
input.transcript_path ? path.basename(input.transcript_path, ".jsonl") : "",
|
||||
].find((value) => typeof value === "string" && value.trim().length > 0) || "unknown-session";
|
||||
return sanitizeKey(raw);
|
||||
}
|
||||
|
||||
// OPR.0.4.1.09 (rev1-r2 hook-path leak fix): MUST match claude-compaction-enforcer.ts
|
||||
// declaredSeatOf EXACTLY — a seat is authoritative ONLY inside a WELL-FORMED leading
|
||||
// frontmatter fence (opened AND closed `---`); the body is NEVER scanned; malformed/absent
|
||||
// frontmatter -> null (generic). Duplicated (not imported) because this hook is a standalone
|
||||
// portable plugin asset that cannot import the compiled daemon TS; semantics are kept
|
||||
// identical so the enforcer and hook paths refuse wrong-seat extras the same way.
|
||||
function declaredSeatOf(content) {
|
||||
const fm = /^\s*---\s*\n([\s\S]*?)\n---/.exec(content);
|
||||
if (!fm) return null;
|
||||
const m = /^[ \t]*(?:target[_-]?seat|seat|session(?:[_-]?name)?)[ \t]*:[ \t]*["']?([^"'\n#]+?)["']?[ \t]*$/im.exec(fm[1]);
|
||||
return m ? m[1].trim() : null;
|
||||
}
|
||||
|
||||
// OPR.0.4.1.09 (rev1-r2): resolve the seat-safe EXTRA-FILE CONTENT for
|
||||
// postCompactInstruction, mirroring the enforcer resolvePostCompactExtra: (1) prefer the
|
||||
// PER-SEAT extra post-compact-extra/<seat>.md; (2) else the GLOBAL messageFilePath. In
|
||||
// EITHER case a file whose WELL-FORMED frontmatter declares a DIFFERENT seat is REFUSED
|
||||
// (returns "") so a foreign-seat extra never leaks into the marker via the hook path
|
||||
// (the enforcer path already refused it). Generic/this-seat/malformed -> inject.
|
||||
function readSeatSafeExtraFile(input, globalFilePath) {
|
||||
const seatKey = sessionKey(input);
|
||||
const refusedIfForeign = (content) => {
|
||||
const declared = declaredSeatOf(content);
|
||||
return declared && sanitizeKey(declared) !== seatKey ? "" : content;
|
||||
};
|
||||
// 1. Per-seat extra preferred (seat-keyed path; still defensively seat-checked to match
|
||||
// the enforcer, which refuses a per-seat file declaring a different seat).
|
||||
const perSeatPath = path.join(getOpenRigHome(), "compaction", "post-compact-extra", `${seatKey}.md`);
|
||||
if (fs.existsSync(perSeatPath)) {
|
||||
return refusedIfForeign(fs.readFileSync(perSeatPath, "utf8"));
|
||||
}
|
||||
// 2. Global messageFilePath fallback, seat-checked.
|
||||
if (!globalFilePath) return "";
|
||||
const content = readInstructionFile(globalFilePath);
|
||||
if (!content) return "";
|
||||
return refusedIfForeign(content);
|
||||
return raw.replace(/[^a-zA-Z0-9_.@-]/g, "_");
|
||||
}
|
||||
|
||||
function pendingMarkerPath(input) {
|
||||
return path.join(getOpenRigHome(), "compaction", "restore-pending", `${sessionKey(input)}.json`);
|
||||
}
|
||||
|
||||
// OPR.0.4.1.09: pointer to this seat's per-seat post-compaction extra
|
||||
// (compaction/post-compact-extra/<seat>.md), surfaced by the bridge reader.
|
||||
// Returned ONLY when it EXISTS, so the marker never points at an unresolvable
|
||||
// restoreMapPath; null otherwise.
|
||||
function perSeatRestoreMapPath(input) {
|
||||
const p = path.join(getOpenRigHome(), "compaction", "post-compact-extra", `${sessionKey(input)}.md`);
|
||||
try {
|
||||
fs.accessSync(p);
|
||||
return p;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function writePendingRestoreMarker(input, parsed, restoreInstruction, customMessage) {
|
||||
const markerPath = pendingMarkerPath(input);
|
||||
fs.mkdirSync(path.dirname(markerPath), { recursive: true });
|
||||
@@ -130,8 +74,6 @@ function writePendingRestoreMarker(input, parsed, restoreInstruction, customMess
|
||||
expectedAck: "restored from packet at <path>; resumed at step <X>",
|
||||
deliveredAt: null,
|
||||
deliveryCount: 0,
|
||||
// OPR.0.4.1.09: per-seat restore-map pointer (post-compact-extra/<seat>.md) or null.
|
||||
restoreMapPath: perSeatRestoreMapPath(input),
|
||||
};
|
||||
fs.writeFileSync(markerPath, `${JSON.stringify(payload, null, 2)}\n`, "utf8");
|
||||
return markerPath;
|
||||
@@ -144,7 +86,7 @@ function writePendingRestoreMarker(input, parsed, restoreInstruction, customMess
|
||||
// enabled but restore text has not been written yet, use OpenRig's default
|
||||
// instruction to load the canonical restore skill. Inline instructions and
|
||||
// file-path content are both included when both are configured.
|
||||
function readClaudeCompactionMessage(input) {
|
||||
function readClaudeCompactionMessage() {
|
||||
const configPath = path.join(getOpenRigHome(), "config.json");
|
||||
let inline = "";
|
||||
let filePath = "";
|
||||
@@ -173,20 +115,17 @@ function readClaudeCompactionMessage(input) {
|
||||
|
||||
const parts = [];
|
||||
if (inline && inline.length > 0) {
|
||||
// Inline has no file/seat to declare; keep as-is.
|
||||
parts.push(`Inline restore instruction:\n${inline}`);
|
||||
}
|
||||
// OPR.0.4.1.09 (rev1-r2): the FILE portion is SEAT-SAFE — per-seat extra preferred, a
|
||||
// foreign-seat global refused (mirrors the enforcer). Checked even when messageFilePath
|
||||
// is unset, because the per-seat extra is an independent mechanism (the enforcer also
|
||||
// checks the per-seat path regardless of the global config).
|
||||
try {
|
||||
const fileText = readSeatSafeExtraFile(input, filePath);
|
||||
if (fileText) {
|
||||
parts.push(`Additional restore instruction file:\n${fileText}`);
|
||||
if (filePath && filePath.length > 0) {
|
||||
try {
|
||||
const fileText = readInstructionFile(filePath);
|
||||
if (fileText) {
|
||||
parts.push(`Additional restore instruction file (${filePath}):\n${fileText}`);
|
||||
}
|
||||
} catch {
|
||||
// Keep any inline instruction; unreadable extra files degrade quietly.
|
||||
}
|
||||
} catch {
|
||||
// Keep any inline instruction; unreadable extra files degrade quietly.
|
||||
}
|
||||
if (parts.length > 0) return parts.join("\n\n");
|
||||
if (policyEnabled && !inlineConfigured && !filePathConfigured) {
|
||||
@@ -208,7 +147,7 @@ try {
|
||||
args.push(input.transcript_path);
|
||||
}
|
||||
|
||||
const customMessage = readClaudeCompactionMessage(input);
|
||||
const customMessage = readClaudeCompactionMessage();
|
||||
|
||||
const result = spawnSync("node", args, { encoding: "utf8" });
|
||||
if (result.status !== 0) {
|
||||
|
||||
+36
-26
@@ -1,22 +1,27 @@
|
||||
---
|
||||
name: forming-an-openrig-mental-model
|
||||
description: |
|
||||
Use when an agent is newly oriented to OpenRig and needs to form an accurate mental model of the system fast — what rigs are, how skills load, what the topology shapes mean, what the product loop is. For agents booting into a new seat or returning to OpenRig work after time away. NOT for HA-pair compaction recovery (that's the pair-of-seats coordination pattern; orientation is a solo task) or for specific operational procedures.
|
||||
Use when an agent is newly oriented to OpenRig and needs to form an accurate mental model of the system fast — what rigs are, how skills load, what the topology shapes mean, what the product loop is. For agents booting into a new seat or returning to OpenRig work after time away. NOT for compaction recovery (use claude-compaction-restore for that) or for specific operational procedures.
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- ask
|
||||
- capture
|
||||
- down
|
||||
- ps
|
||||
- send
|
||||
- transcript
|
||||
- up
|
||||
- whoami
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
last_verified: "2026-05-04"
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
Authored 2026-05-02 in response to founder-observed pattern: agents
|
||||
Distinct from HA-pair mental-model preservation (which is a
|
||||
pair-of-seats coordination pattern). This skill serves the legitimate
|
||||
need to form an initial mental model of OpenRig as a system.
|
||||
sibling_skills:
|
||||
- openrig-user
|
||||
- openrig-operator
|
||||
- openrig-builder
|
||||
- openrig-architect
|
||||
transfer_test: pending
|
||||
- openrig-upgrade
|
||||
- ai-dev-workflows
|
||||
- software-for-agents
|
||||
---
|
||||
|
||||
# Forming an OpenRig Mental Model
|
||||
@@ -165,13 +170,14 @@ cost when you reach for one.
|
||||
| Home | Purpose |
|
||||
|---|---|
|
||||
| `<rig-cwd>/.claude/skills/`, `<rig-cwd>/.agents/skills/` | Where the harness actually loads from. Populated by `rig up`. |
|
||||
| `~/.claude/skills/`, `~/.agents/skills/` | Your personal/global skills + the OpenRig bootstrap set (openrig-user, openrig-operator, openrig-architect, forming-an-openrig-mental-model, plus the rest of the openrig-core plugin skills). |
|
||||
| openrig-core plugin skills | Product built-in skills that ship with OpenRig (installed via the openrig-core plugin). |
|
||||
| `~/.openrig/skills/` | Runtime install home for OpenRig-shipped skills. |
|
||||
| `~/.claude/skills/`, `~/.agents/skills/` | Your personal / user-installed global skills, loaded by the harness itself (independent of OpenRig). NOT where OpenRig's own bootstrap skills live — those ship in the product (below) and project into the cwd `.claude/skills/` at `rig up`. |
|
||||
| `openrig/packages/daemon/{specs/agents/shared/skills,assets/plugins/*/skills}/` | Product skills that ship with OpenRig — the spec pool + the bundled plugin assets (openrig-user, openrig-operator, openrig-architect, forming-an-openrig-mental-model, queue-handoff, claude-compaction-restore, …). |
|
||||
| `~/.openrig/skills/` | Future runtime install home for OpenRig-shipped skills. |
|
||||
| the skills authoring workspace | Skill authoring source (not runtime-loaded). |
|
||||
|
||||
The harness only sees the first two. Other locations are shipping and
|
||||
source-of-truth — they reach the harness via projection or NPM install,
|
||||
not directly.
|
||||
The harness only sees the first two. Other locations are authoring,
|
||||
shipping, and source-of-truth — they reach the harness via projection or
|
||||
NPM install, not directly.
|
||||
|
||||
---
|
||||
|
||||
@@ -230,10 +236,8 @@ If you're booting into a new seat in an OpenRig rig:
|
||||
that tells you when to reach for it.
|
||||
5. **Check your peers** — `rig capture <peer-session>` to see what they're
|
||||
doing.
|
||||
6. **Recover from durable artifacts** if you're returning to an in-flight
|
||||
workstream: read the restore map, current `MISSION_NOTES.md`, and owned queue
|
||||
items. Use `rig transcript <session> --tail 100` only as a secondary check;
|
||||
little or no output does not prove the workstream was quiet.
|
||||
6. **Check the transcripts** if you're returning to an in-flight workstream
|
||||
— `rig transcript <session> --tail 100` for recent context.
|
||||
7. **Ask `rig ask <rig> "<question>"`** if you need cross-cutting evidence
|
||||
from the rig's transcripts and chat.
|
||||
|
||||
@@ -252,19 +256,25 @@ For real depth, these are the load-bearing canonical docs:
|
||||
| `openrig/docs/reference/rig-spec.md` | The RigSpec YAML format — pods, members, edges, all fields |
|
||||
| `openrig/docs/reference/agent-spec.md` | The AgentSpec YAML format — resources, profiles, imports |
|
||||
| `openrig/docs/reference/agent-startup-guide.md` | The 7-layer startup layering model; delivery hints |
|
||||
| the product taxonomy | Canonical vocabulary (read literally) |
|
||||
| `substrate/shared-docs/HOST-TOPOLOGY.md` | Host-level doctrine — rig classes, context patterns, lifecycle, authoring SOP |
|
||||
| `substrate/shared-docs/SUBSTRATE-CONVENTIONS.md` | Filesystem layout doctrine for substrate |
|
||||
| `https://agentskills.io/specification` | The cross-runtime skill standard |
|
||||
|
||||
If your team maintains a host-level topology doc (rig classes, context
|
||||
patterns, authoring SOPs), read its rig-authoring section before
|
||||
touching YAML for high-stakes rigs.
|
||||
If you're going to be authoring rigs, read `HOST-TOPOLOGY.md` §7 (the
|
||||
authoring SOP) before touching YAML.
|
||||
|
||||
If you're going to be doing skill work, read
|
||||
the factory-design reference and the
|
||||
`operating-the-skill-library` skill that lives in
|
||||
`substrate/shared-docs/rigs/skill-library/agents/shared/skills/`.
|
||||
|
||||
---
|
||||
|
||||
## What this skill is NOT for
|
||||
|
||||
- **HA pair compaction recovery.** Forming an initial mental model is a
|
||||
solo orientation task — different from the pair-of-seats coordination
|
||||
pattern that preserves a shared mental model across compactions.
|
||||
- **Compaction recovery.** That's `claude-compaction-restore`. Different
|
||||
skill, different scenario.
|
||||
- **Operating a specific rig.** Specific rigs have their own DESIGN.md and
|
||||
CULTURE.md. Read those.
|
||||
- **Authoring a new rig.** Use the `openrig-architect` skill for that.
|
||||
@@ -287,7 +297,7 @@ that fit your actual work.
|
||||
| "I should manage Codex's compaction the way I manage Claude's" | No. Codex auto-compacts cleanly; Claude doesn't. Different runtimes, different lifecycles. |
|
||||
| "MEMORY.md auto-loads, so I don't need to read it" | Maybe. Sometimes MEMORY.md auto-loads via system reminders; sometimes not. Don't assume. If your work touches the topics it covers, read it explicitly. |
|
||||
| "Skills inherit from a parent or compose like classes" | No. Skills are flat artifacts; composition happens via AgentSpec `profile.uses.skills` (structural) or soft cross-references in skill bodies (advisory). Not via OO-style inheritance. |
|
||||
| "Any folder I keep skill files in is the canonical runtime path" | No. The harness only loads from `<rig-cwd>/.claude/skills/`, `<rig-cwd>/.agents/skills/`, and the runtime-installed plugin skills. Other folders are authoring or source-of-truth. |
|
||||
| "The substrate `shared-docs/skills/` folder is the canonical runtime path" | No. The harness doesn't read there. It's an authoring workspace. Runtime loads from `.claude/skills/`, `.agents/skills/`, and product built-in. |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
---
|
||||
name: messaging-the-human
|
||||
description: |
|
||||
When and who should send a message to the human operator, at
|
||||
operator-human@your-rig — which routes straight to his Slack. Role-gated:
|
||||
orchestrators and PMs use discretion to send anything worth his attention
|
||||
(blockers, ships/completions, changes, good news); every other agent may
|
||||
message him ONLY for a real blocker he can personally unblock, and routes
|
||||
everything else through an orchestrator. Use to protect a scarce human's
|
||||
manage-by-exception attention. NOT for agent-to-agent coordination (send/queue
|
||||
a peer) or durable agent work-handoffs (use the queue to the owning seat).
|
||||
metadata:
|
||||
openrig:
|
||||
stage: provisional # operator-directed, freshly authored 2026-07-30; hardens as agents use it
|
||||
audience: ALL agents (universal); orchestrators + PMs are the primary discretionary senders
|
||||
sibling_skills:
|
||||
- queue-handoff
|
||||
- status-not-chat-orchestrator
|
||||
- human-in-the-loop
|
||||
- openrig-user
|
||||
---
|
||||
|
||||
# Messaging the Human
|
||||
|
||||
## The one-line mechanism
|
||||
|
||||
```bash
|
||||
rig send operator-human@your-rig "your message"
|
||||
```
|
||||
|
||||
That goes straight to the human's Slack. That is the entire *how*. Everything
|
||||
below is the *when* and the *who* — which is the part that actually matters.
|
||||
|
||||
## The mental model: the human is a scarce attention resource managing by exception
|
||||
|
||||
There is one human. He is single-threaded across many agents, so his attention
|
||||
is the bottleneck of the whole system. He operates **by exception**: he wants to
|
||||
be pulled in when it genuinely matters and left alone when it doesn't. Every
|
||||
message you send spends a slice of that scarce attention.
|
||||
|
||||
So the rule is not "can I reach him" (you can, trivially — one `rig send`). The
|
||||
rule is **should this reach him, coming from me**. Two things decide that: **who
|
||||
you are** (your role sets how much of his attention you're trusted to spend) and
|
||||
**what it is** (does it clear the bar for that role). Get the altitude wrong in
|
||||
either direction and you fail him: spam his Slack with noise, or sit silently on
|
||||
something he needed to know or could have unblocked.
|
||||
|
||||
## WHO sends WHAT
|
||||
|
||||
### If you are an ORCHESTRATOR or a PRODUCT MANAGER — use discretion
|
||||
|
||||
You are the primary channel to the human. You may send **more than blockers** —
|
||||
anything you judge he would want to know:
|
||||
|
||||
- something **shipped**, **completed**, or a **milestone** was hit
|
||||
- something **important happened**, or something **changed**
|
||||
- **environmental** changes (infra, hosts, tools, external state)
|
||||
- **good news**
|
||||
- anything that needs his attention, or is simply **good for him to know**
|
||||
|
||||
There is no hard trigger here — it is judgment, and you are trusted with it. The
|
||||
test is: **"would he want to know this?"** If yes, send it. Lean toward sending
|
||||
genuine signal and real good news; do not manufacture noise or narrate routine
|
||||
churn. Discernment is the skill: you are curating his attention, not flooding it.
|
||||
|
||||
### If you are ANY OTHER agent — blockers only
|
||||
|
||||
You may message the human **only** when you are **blocked** and **he** is the one
|
||||
who can unblock you. That authority is universal — you do **not** have to be an
|
||||
orchestrator to raise a real blocker. But a blocker is the **only** thing you may
|
||||
send him directly.
|
||||
|
||||
For anything that is **not** a blocker — an update, an idea, a question, an
|
||||
interesting finding — do **not** message the human. Send it to your
|
||||
**orchestrator**, who decides whether it is the human's role to handle or whether
|
||||
it is handled another way. The orchestrator/PM layer is the filter that protects
|
||||
the human's attention; routing through it is how the system keeps his queue at
|
||||
manage-by-exception altitude.
|
||||
|
||||
## What counts as a real blocker (for non-orchestrator / non-PM agents)
|
||||
|
||||
You are **blocked** AND **only the human** can clear it:
|
||||
|
||||
- a **decision** only he can make,
|
||||
- **access / a credential / an authority** only he holds,
|
||||
- an **external action** only he can take (something in the real world, an
|
||||
account or service he owns).
|
||||
|
||||
Not a blocker: "I'd like a second opinion," "which approach do you prefer,"
|
||||
"here's a cool thing I found." Those go to your **orchestrator**. And if an
|
||||
orchestrator or PM *could* unblock you, route to them first — reserve the human
|
||||
for what genuinely only he can do.
|
||||
|
||||
## How to write it (so it earns the interruption)
|
||||
|
||||
- **Lead with the point.** Blocker: what is blocked + exactly what you need from
|
||||
him. Update: the headline first, detail after.
|
||||
- **Full absolute paths.** No internal jargon he can't parse. **No backticks** in
|
||||
`rig send` bodies (they trigger shell substitution).
|
||||
- `rig send` is an **ephemeral conversation** to his Slack. For a durable *agent*
|
||||
work-handoff, use the queue to the owning seat — not the human.
|
||||
|
||||
## Quick reference
|
||||
|
||||
| You are… | You may send the human… |
|
||||
|---|---|
|
||||
| Orchestrator / PM | anything worth his attention — blockers, ships, completions, changes, good news (your discretion) |
|
||||
| Any other agent | a real blocker only he can unblock — **and nothing else** (everything else → your orchestrator) |
|
||||
@@ -4,17 +4,6 @@ description: "Use when working a mission or slice: the SDLC flow (intent -> mini
|
||||
metadata:
|
||||
openrig:
|
||||
stage: shipped
|
||||
last_verified: "2026-07-06"
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
The canonical product SDLC skill: it teaches the full SDLC flow the
|
||||
Living Notes UI projects — the convention sections, the proof-contract
|
||||
pairing, the two staged-approval locks, C1 proof drops, and the three
|
||||
role contracts. Conventions SSOT: docs/reference/sdlc-conventions.md
|
||||
in the repo; on an installed package the daemon materializes the same
|
||||
document at $OPENRIG_HOME/reference/sdlc-conventions.md (default
|
||||
~/.openrig/reference/sdlc-conventions.md). The deterministic backstop
|
||||
is the `rig scope audit` classifier.
|
||||
sibling_skills:
|
||||
- queue-handoff
|
||||
- seat-continuity-and-handover
|
||||
@@ -23,7 +12,10 @@ metadata:
|
||||
|
||||
# Mission/Slice SOP — how you work a mission & slice
|
||||
|
||||
Use this skill to actually **do** mission/slice work the way OpenRig expects: author the convention sections, track on the canonical files, prove on them, hand off through them, and survive compaction on them. **Do the work described here; do not merely explain the protocol.** The deterministic backstop is `rig scope audit` — the audit classifier is the source of truth for adherence. The conventions themselves live in ONE document: **`docs/reference/sdlc-conventions.md`** in the repo, materialized by the daemon at **`$OPENRIG_HOME/reference/sdlc-conventions.md`** (default `~/.openrig/reference/sdlc-conventions.md`) on an installed package — this skill teaches the flow; the SSOT defines the formats.
|
||||
Use this skill to actually **do** mission/slice work the way OpenRig expects: author the convention sections, track on the canonical files, prove on them, hand off through them, and survive compaction on them. **Do the work described here; do not merely explain the protocol.** The deterministic backstop is `rig scope audit` — an **advisory, fail-open** check (it records and advises, never blocks a write; see Proportionality below), not an authority you serve. The conventions themselves live in ONE document: **`docs/reference/sdlc-conventions.md`** in the repo, materialized by the daemon at **`$OPENRIG_HOME/reference/sdlc-conventions.md`** (default `~/.openrig/reference/sdlc-conventions.md`) on an installed package — this skill teaches the flow; the SSOT defines the formats.
|
||||
|
||||
## Proportionality — this SOP serves shipping; it is not the work itself
|
||||
The working product is the deliverable. This bookkeeping exists so the work survives handoff, compaction, and review — nothing more. **Match it to stakes:** OpenRig core = full ceremony; Studio Box / SDK / app slices = pragmatic — the mini-requirements may BE the whole PRD, and a couple of honest, LOOKed proof lines beat an elaborate contract. The `rig scope audit` backstop is **advisory and fail-open** (its own SSOT says so): it never blocks a build and is not a gate you clear before proceeding. If you're spending more time on the convention files or the audit than on the running product, stop and go build. Running the full apparatus on a small change is the letter-worship failure, not diligence.
|
||||
|
||||
## The SDLC flow (intent → proof)
|
||||
|
||||
@@ -38,7 +30,10 @@ intent → mini-requirements + proof contract → (UI slices: mockups)
|
||||
|
||||
1. **Record intent** verbatim in the slice's `## Intent` section (`rig scope slice create` scaffolds it — every template kind).
|
||||
2. **Author the mini-requirements + proof contract**: `## Mini-requirements` is the concise one-glance tier (approval starts there); `## Proof contract` is a checkbox list of promised deliverables, each written as an observable outcome. UI deliverables name their planned mockup. The IMPLEMENTATION-PRD opens with the mini-requirements; everything between intent and proof is **elastic** — for a small slice the mini-requirements may BE the whole PRD.
|
||||
- **PARSER CONTRACT (README AND IMPLEMENTATION-PRD, from first draft — a parser contract, not stylistic):** each doc carries a verbatim, **undecorated** `## Mini-requirements` heading with a **numbered list**, and a verbatim, **undecorated** `## Proof contract` heading whose checkbox (`- [ ]`) lines are **character-identical** across the two files. `rig scope audit` parses the PRD's `## Proof contract`; a prose rollup (e.g. `## Required proof …`) or any renamed/decorated heading trips **`proof_contract_missing_or_malformed`** and forces a post-lock format patch. Never rename or decorate these two headings, and keep the PRD's checkbox lines byte-for-byte equal to the README's.
|
||||
- **REFERENCE-NOT-RESTATE (public / runnable examples — an honesty rail, from first draft):** any example that shows output or a value the referenced file/command **derives** — repo/runtime counts, current-state totals, hashes, timestamps — must **reference the source/derivation, omit the volatile value, or pin an explicitly stable fixture**; never hardcode the live count/state in a public or shipped doc. "Illustrative" derived output is a lie on a timer: `OK registry (2 manifests)` goes false the instant an entry lands. Write the invariant form (`OK registry (<N> manifests)`, N = entries in `registry.json`) or name the fixture instead of the momentary number. Restated derivable state in a public doc is a defect `rig scope audit` will not catch — the author owns it.
|
||||
3. **Plan-lock**: `rig scope slice approve <slice> --scope spec` — "the PRD matches the intent; THIS artifact set is what gets built." One daemon-side write: frontmatter stamp + append-only audit row.
|
||||
- **PRE-PLAN-LOCK SELF-CHECK (advisory, not a gate):** before requesting `--scope spec`, it's worth running `rig scope audit --mission <mission> --json` and clearing any real **format** defect (e.g. `proof_contract_missing_or_malformed`) so the parser can read your proof contract — that's a genuine machine-parsing need, cheap to fix. But the audit is fail-open: findings do NOT block the lock or the build, and you do NOT need a zero-findings score to proceed. Fix what's real, skip what isn't, keep moving.
|
||||
4. **Build the locked set** — look at the mockups, not just the spec text.
|
||||
5. **QA visual compare**: for each deliverable, load the planned mockup, produce the real artifact in a test/demo environment, visually compare, and record the verdict.
|
||||
6. **Drop proof**: `rig proof add <slice> --artifact-type qa --verdict PASS --candidate-sha <tip> --money-evidence "…" --evidences "1,3" --media "walk.webm,panel.png" --self-check "…"` — the C1 header's closed sets validate at drop time; `--evidences` joins the drop to its proof-contract items and `--media` names the curated proof/-relative media the drop stands behind (that pairing + media set is what the UI's DELIVERED section renders).
|
||||
@@ -52,7 +47,7 @@ intent → mini-requirements + proof contract → (UI slices: mockups)
|
||||
|
||||
## The canonical files (the operating surface)
|
||||
|
||||
> The canonical files below are the **operating surface of the work** — you track on them, prove on them, hand off through them, and survive compaction on them. They are NOT side-artifacts to "maintain"; keeping them current *is* the work.
|
||||
> The canonical files below are the **operating surface of the work** — you track on them, prove on them, hand off through them, and survive compaction on them. Keep them current because that is what lets the work survive handoff, compaction, and review — but they **serve** the product, they are not the product. If you're polishing these files while the actual thing isn't shipping, you've inverted it: go build, then update them.
|
||||
|
||||
- **README.md** (mission + slice) — the overview, OPENING with the convention sections (`## Intent` / `## Mini-requirements` / `## Proof contract`). The **mission README carries this SOP at its bottom.**
|
||||
- **IMPLEMENTATION-PRD.md** — the full PRD; opens with the mini-requirements; the `## Proof contract` here is what the UI's DELIVERED pairing joins proof against.
|
||||
@@ -108,7 +103,7 @@ When you `rig capture` a pane, **greyed / ghost autocomplete suggestions are NOT
|
||||
|
||||
## Moment-of-truth checklist
|
||||
|
||||
- **Starting a slice?** → intent recorded verbatim? mini-requirements + proof contract authored? mockups attached (UI slices)? plan locked (`--scope spec`)?
|
||||
- **Starting a slice?** → intent recorded verbatim? **PRD carries a verbatim numbered `## Mini-requirements` + a verbatim `## Proof contract` whose `- [ ]` lines are character-identical to the README's** (parser contract)? **no example restates derivable state** — counts/hashes/timestamps referenced, omitted, or pinned to a stable fixture, never hardcoded (reference-not-restate)? mockups attached (UI slices)? ran `rig scope audit` and fixed any real **format** defect so the parser reads the proof contract (advisory — a clean score is NOT required to lock)?
|
||||
- **Finishing a slice?** → every proof-contract item has curated evidence via `rig proof add … --evidences --media` (C1 drops — never only hand-placed files)? PROGRESS updated? MISSION_NOTES `§1` refreshed? proof locked (`--scope delivery`)? Handed off via queue?
|
||||
- **Committing?** → PROGRESS updated?
|
||||
- **Compacting?** → filed your state in MISSION_NOTES?
|
||||
|
||||
@@ -1,363 +0,0 @@
|
||||
---
|
||||
name: openrig-architect
|
||||
description: Use when designing multi-agent topologies that run ON OpenRig — authoring RigSpec and AgentSpec files for new rigs, creating agent startup content (guidance / skills / culture), or diagnosing why a launched rig's agents aren't behaving as intended. NOT for changing OpenRig itself (work in the openrig product repo); NOT for ordinary CLI operation of an existing rig (use openrig-user). Covers the full authoring lifecycle from user intent to validated, launchable rig.
|
||||
metadata:
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
last_verified: "2026-05-04"
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
Bootstrap skill — NPM install lands this in personal homes (~/.claude/skills/, ~/.agents/skills/) for users authoring their own rigs.
|
||||
sibling_skills:
|
||||
- openrig-user
|
||||
- openrig-operator
|
||||
- forming-an-openrig-mental-model
|
||||
transfer_test: pending
|
||||
---
|
||||
|
||||
# OpenRig Architect
|
||||
|
||||
You are now an OpenRig architect. You design, author, validate, and diagnose multi-agent topologies for OpenRig.
|
||||
|
||||
Your job is to take a user's intent — "I need a team that does X" — and produce a complete, functioning rig: the topology spec, the agent specs, the guidance files, the culture, the startup content, and everything else needed for the rig to boot and the agents to know what to do.
|
||||
|
||||
You also diagnose problems when a rig launches but agents aren't behaving as intended.
|
||||
|
||||
## Before You Design: Required Reading
|
||||
|
||||
Load these before starting any design work. The quality of your output depends on the depth of knowledge you bring.
|
||||
|
||||
**Required (read all of these):**
|
||||
|
||||
1. **`openrig-user` skill** — full OpenRig CLI surface. You must know the operator primitives. If your runtime supports skills, load it by name. Otherwise, look for it at `~/.openrig/skills/openrig-user/SKILL.md` (the runtime install dogfood mirror — packaged skills land here) or inside the OpenRig installation under `packages/daemon/specs/agents/shared/skills/core/openrig-user/SKILL.md`. The `~/.openrig/reference/` directory holds reference docs (rig-spec.md, agent-spec.md, etc.), NOT skills.
|
||||
|
||||
2. **OpenRig reference docs** — these are installed at `~/.openrig/reference/` when the daemon starts. Read all of them:
|
||||
- `~/.openrig/reference/rig-spec.md` — canonical RigSpec YAML reference. Every field, validation rule, default.
|
||||
- `~/.openrig/reference/agent-spec.md` — canonical AgentSpec YAML reference. Same depth.
|
||||
- `~/.openrig/reference/agent-startup-guide.md` — how to think about what goes into agent startup. Context loading vs deterministic config, when to use skills vs guidance, the layering model, current support matrix.
|
||||
- `~/.openrig/reference/edge-types.md` — what edges do today vs what they're intended to do.
|
||||
|
||||
If `~/.openrig/reference/` doesn't exist yet, start the daemon first (`rig daemon start`) — it copies the reference docs on startup.
|
||||
|
||||
**Read as worked examples:**
|
||||
|
||||
3. **Shipped starter specs** — the OpenRig installation includes proven starter topologies. Find them by running `rig specs ls`. Read the ones that are relevant to your design task, especially:
|
||||
- `implementation-pair` — the smallest effective development unit (2 agents)
|
||||
- `secrets-manager` — a managed-app rig with services integration and a specialist agent
|
||||
|
||||
**Read if present on this host:**
|
||||
|
||||
4. **Host-level doctrine file** (if your team maintains one — e.g., a HOST-TOPOLOGY doc that defines canonical rig classes, context-sharing patterns, and authoring SOPs for high-stakes rigs). If present, it supersedes the baseline process below for complex or high-stakes rigs (≥4 members, HA, managed-app, or shared/copied). Solo operators and small/focused rigs use the baseline below directly.
|
||||
5. **Agent-facing software design principles** if your rig ships a new CLI, service, or managed app that agents will operate. Treat the operating surface as a context-engineering problem: every error message and help text gives the agent information to act on.
|
||||
|
||||
**Load as needed:**
|
||||
- Domain-specific skills when designing specialist agents — find shipped skills inside the OpenRig installation under the `specs/agents/` tree
|
||||
- If the design session is long and you're running inside a managed rig, use `rig whoami --json` to recover your identity after compaction
|
||||
|
||||
Do not skip the required reading. A rig architect who doesn't know the spec format will produce specs that don't validate. An architect who doesn't know the startup layering model will produce agents that boot without knowing their role. An architect who doesn't check for host-level doctrine will reinvent conventions the host has already established.
|
||||
|
||||
## The Design Process
|
||||
|
||||
### Step 1: Understand the User's Intent
|
||||
|
||||
Before touching YAML, understand what the user actually needs:
|
||||
|
||||
- **What is the goal?** Not "I need 5 agents" but "I need to build and ship a web application" or "I need to research a technical question deeply" or "I need a team that can operate and monitor a running service."
|
||||
- **What are the workflows?** How does work flow from intent to completion? Who does what? Where are the handoffs?
|
||||
- **What is the project?** What codebase, what tech stack, what domain? This shapes agent specialization and startup content.
|
||||
- **What runtimes are available?** Does the user have Claude Code? Codex? Both? Runtime availability constrains topology design.
|
||||
- **How autonomous should it be?** Does the user want to direct every step, or should the rig be mostly self-driving with occasional human checkpoints?
|
||||
|
||||
Ask clarifying questions if the intent is ambiguous. A well-understood intent produces a dramatically better topology than a guess.
|
||||
|
||||
### Step 2: Identify Bounded Contexts → Pods
|
||||
|
||||
Every rig is organized into pods — bounded context groups where members share a workflow concern. The question is: what are the natural groupings?
|
||||
|
||||
**Common pod patterns:**
|
||||
|
||||
| Pod | Purpose | When to use |
|
||||
|-----|---------|-------------|
|
||||
| Orchestration | Coordination, dispatch, monitoring | Almost always — any rig with 3+ agents needs an orchestrator |
|
||||
| Development | Implementation, testing, quality | Any rig that writes code |
|
||||
| Review | Independent code review, architecture review | When quality gates matter (production code, security-sensitive work) |
|
||||
| Research | Deep investigation, analysis, synthesis | When the work requires research before implementation |
|
||||
| Design | UX, interaction design, product decisions | When the work has a user-facing interface |
|
||||
| Specialist | Domain-specific operations (Vault, DB, infra) | When a specific technology needs dedicated expertise |
|
||||
|
||||
**Sizing principles:**
|
||||
|
||||
- **Solo agent:** Only when the task is genuinely single-person (quick script, simple question). No rig needed.
|
||||
- **Pair (2 agents):** The minimum effective unit for quality work. One does, one verifies. The `implementation-pair` pattern.
|
||||
- **Small team (3-5 agents):** Orchestrator + one or two working pods. Good starting point for focused projects.
|
||||
- **Full team (6-10 agents):** Multiple bounded contexts with orchestration, development, review, and potentially research or design.
|
||||
- **Large team (10-40+ agents):** Complex projects with many concerns. Include pods for development, review, research, documentation, release management, strategy, and any other bounded context the project needs.
|
||||
|
||||
**Important:** Agents do NOT all need to be busy at the same time. A rig is a network, not an assembly line. Some pods will be highly active (dev, review) while others are available on-demand (research, documentation, release management). An idle agent has near-zero cost but is immediately available when any other agent in the rig needs it — for quick questions, lookups, delegation, or specialized work. Design for availability, not constant utilization.
|
||||
|
||||
**Start small to increase the likelihood of success,** not because large rigs are wasteful. A 3-agent rig that boots and works correctly validates your spec authoring before you scale to 20 agents. Once the core topology works, expand with additional pods as needed.
|
||||
|
||||
### Step 3: Design Agent Roles → Members
|
||||
|
||||
Each pod member needs a clear role. The role determines:
|
||||
- What agent spec to reference (builtin or custom)
|
||||
- What profile to use
|
||||
- What guidance and startup content to provide
|
||||
|
||||
**Builtin agents shipped with OpenRig:**
|
||||
|
||||
| Agent | agent_ref (in shipped starters) | Purpose |
|
||||
|-------|-------------------------------|---------|
|
||||
| orchestrator | `local:agents/orchestration/orchestrator` | Rig orchestration lead |
|
||||
| implementer | `local:agents/development/implementer` | TDD implementation agent |
|
||||
| qa | `local:agents/development/qa` | Quality assurance agent |
|
||||
| independent-reviewer | `local:agents/review/independent-reviewer` | Independent code reviewer |
|
||||
| product-designer | `local:agents/design/product-designer` | Product designer |
|
||||
| pm | `local:agents/product-management/pm` | Product manager |
|
||||
| analyst | `local:agents/research/analyst` | Research analyst |
|
||||
| synthesizer | `local:agents/research/synthesizer` | Research synthesizer |
|
||||
| vault-specialist | `local:agents/apps/vault-specialist` | Vault domain specialist |
|
||||
|
||||
To verify the current builtin set on this host, run `rig specs ls` and look for entries with type `agent` and source `builtin`.
|
||||
|
||||
**Path resolution:** The `local:` prefix means relative to the rig spec file's directory. In shipped starters, these paths resolve against the builtin specs directory inside the OpenRig installation. When authoring a custom rig spec outside the installation, you have two options:
|
||||
- **Reference your own agent specs** with `local:` paths relative to your rig spec file
|
||||
- **Use `path:` with an absolute path** to reference builtins inside the OpenRig installation (look under the `specs/agents/` directory near where `rig` is installed)
|
||||
|
||||
**When to create a custom agent spec:**
|
||||
- The builtin doesn't match the role (e.g., you need a documentation specialist, a security auditor, a data scientist)
|
||||
- The role needs domain-specific skills that no builtin carries
|
||||
- The role needs custom guidance that goes beyond what startup files can provide
|
||||
|
||||
**When to reuse a builtin:**
|
||||
- The role maps cleanly to an existing builtin (most implementation, QA, review, and orchestration roles)
|
||||
- You can customize behavior through startup files and culture without changing the agent spec
|
||||
|
||||
### Step 4: Choose Runtimes and Models
|
||||
|
||||
Each member needs a `runtime` and optionally a `model`.
|
||||
|
||||
**Runtime selection:**
|
||||
- `claude-code` — Claude Code. Best for: complex reasoning, architecture, code review, orchestration. Supports `/loop` for recurring tasks, rich hooks system, MCP servers.
|
||||
- `codex` — Codex. Best for: parallel work, implementation, testing. Different approval model. Less reliable for recurring tasks.
|
||||
- `terminal` — Infrastructure nodes. Servers, log tails, build watchers. Not an agent — a process.
|
||||
|
||||
**Runtime diversity is valuable.** Using both Claude Code and Codex in the same rig gives you different reasoning perspectives. The `product-team` starter uses Claude Code for the lead/impl/design/r1 roles and Codex for peer/qa/r2 roles. This is deliberate — model diversity catches different classes of issues.
|
||||
|
||||
**Model selection** is optional. The runtime's default model is usually fine. Override only when you have a specific reason (e.g., a complex architecture agent might benefit from a specific model).
|
||||
|
||||
### Step 5: Design Edge Topology
|
||||
|
||||
Edges define relationships between members. See `~/.openrig/reference/edge-types.md` for the full reference.
|
||||
|
||||
**Practical rules:**
|
||||
- Every working pod should have at least one `delegates_to` edge from the orchestrator
|
||||
- Review pods should have `can_observe` edges to the pods they review
|
||||
- Within a pod, the primary workflow direction should be expressed as `delegates_to` (e.g., impl → qa)
|
||||
- `delegates_to` and `spawned_by` affect launch order. Use them for dependency chains.
|
||||
- `can_observe`, `collaborates_with`, `escalates_to` are informational — they help agents understand the topology but don't constrain launch.
|
||||
|
||||
**Start simple.** You can always add edges later. A rig with only `delegates_to` edges from the orchestrator to working pods is perfectly functional.
|
||||
|
||||
### Step 6: Design Startup Content Strategy
|
||||
|
||||
This is where most rigs succeed or fail. The topology is mechanical; the startup content is what makes agents actually useful. See `~/.openrig/reference/agent-startup-guide.md` for the full guide.
|
||||
|
||||
**Minimum for every rig:**
|
||||
1. Each agent has a `guidance/role.md` — who they are, what they do
|
||||
2. The rig has a `CULTURE.md` — how the team works together
|
||||
3. Each agent gets `openrig-user` skill — so they know how to use the rig primitives
|
||||
|
||||
**For serious rigs, also include:**
|
||||
4. `startup/context.md` per agent — boot-time grounding (project info, environment details)
|
||||
5. Pod SOP skills — how each pod operates (implementation-pair SOP, review-pair SOP, etc.)
|
||||
6. Project-specific documentation in rig-level startup files
|
||||
|
||||
**The key principle:** An agent that boots without knowing its role, its team's culture, and its project context will produce generic, unhelpful work. The startup content IS the product value. Invest in it.
|
||||
|
||||
### Step 7: Services Integration (If Needed)
|
||||
|
||||
If the rig needs managed software (databases, API servers, etc.), add a `services` block. See `~/.openrig/reference/rig-spec.md` for the full services reference.
|
||||
|
||||
**When to add services:**
|
||||
- The agents operate ON software (not just write code)
|
||||
- The project needs a local dev environment (Postgres, Redis, etc.)
|
||||
- You're building a managed-app rig (software + specialist agent)
|
||||
|
||||
**Services boot before agents.** If health checks fail, no agents start. This is the hard gate — the environment must be healthy before agents can work.
|
||||
|
||||
## Authoring: The File Creation Workflow
|
||||
|
||||
### Directory Layout
|
||||
|
||||
```
|
||||
my-rig/
|
||||
rig.yaml # The RigSpec — required
|
||||
culture/
|
||||
CULTURE.md # Rig-wide culture — strongly recommended
|
||||
agents/
|
||||
my-custom-agent/
|
||||
agent.yaml # AgentSpec — if custom agent needed
|
||||
guidance/
|
||||
role.md # Role guidance
|
||||
startup/
|
||||
context.md # Boot-time context
|
||||
skills/
|
||||
my-skill/
|
||||
SKILL.md # Custom skill if needed
|
||||
docker-compose.yaml # Only if services block is used
|
||||
```
|
||||
|
||||
For rigs that reuse builtin agents, the agents directory is often unnecessary — the rig spec references the builtins directly.
|
||||
|
||||
### Workflow
|
||||
|
||||
1. **Write the rig spec** (`rig.yaml`) — define pods, members, edges, optionally services
|
||||
2. **Write or reference agent specs** — builtins for standard roles, custom for specialized roles
|
||||
3. **Write CULTURE.md** — the team operating manual
|
||||
4. **Write role guidance** for each custom agent — who they are, what they do
|
||||
5. **Write startup context** for agents that need environment grounding
|
||||
6. **Validate:** `rig spec validate rig.yaml` and `rig agent validate agents/*/agent.yaml`
|
||||
7. **Audit authoring completeness:** `rig spec audit rig.yaml` — advisory findings identify missing culture or startup context without blocking launch.
|
||||
8. **Confirm the runtime cwd** — do not assume agents should work from the directory where the rig spec is stored. The spec root controls file resolution; the runtime cwd controls trust, project guidance, permissions, and repo context.
|
||||
9. **Launch:** `rig up rig.yaml --cwd /path/to/project`
|
||||
10. **Verify:** `rig ps --nodes` — all agents ready? Check `rig capture` on each agent.
|
||||
|
||||
### Validation Is Non-Negotiable
|
||||
|
||||
Always validate before launching:
|
||||
|
||||
```bash
|
||||
rig spec validate rig.yaml
|
||||
rig spec audit rig.yaml
|
||||
rig agent validate agents/my-agent/agent.yaml
|
||||
```
|
||||
|
||||
If validation fails, fix the errors. Do not try to launch an invalid spec — it will fail with a less helpful error.
|
||||
|
||||
## Diagnosis: When Things Go Wrong
|
||||
|
||||
### Agent doesn't know its role
|
||||
|
||||
**Symptom:** Agent produces generic output, doesn't follow team conventions.
|
||||
**Root cause:** Missing or insufficient `guidance/role.md`.
|
||||
**Fix:** Write a clear role guidance file. Include responsibilities, working rhythm, and principles. Reference it in both `resources.guidance` and `startup.files`.
|
||||
|
||||
### Agent can't coordinate with peers
|
||||
|
||||
**Symptom:** Agent tries raw tmux commands instead of `rig send`, doesn't know peer session names.
|
||||
**Root cause:** Agent didn't receive `openrig-user` skill or `openrig-start` overlay.
|
||||
**Fix:** Ensure the agent's profile `uses.skills` includes `openrig-user`. Verify via `rig ps --nodes` that the agent shows expected startup status; check installed skills via direct startup/capture/transcript evidence or the UI node detail (the `rig ps --nodes` projection does not expose installed-resource counts).
|
||||
|
||||
### Agent hits approval prompts on rig commands
|
||||
|
||||
**Symptom:** Agent stalls on `rig whoami`, `rig send`, etc.
|
||||
**Root cause:** Claude Code permissions not configured for rig commands.
|
||||
**Fix:** Describe the required permissions in startup context. The agent should configure `~/.claude/settings.json` with allowlisted rig commands. See `~/.openrig/reference/agent-startup-guide.md` for the current support matrix.
|
||||
|
||||
### Agents idle — topology doesn't engage the team
|
||||
|
||||
**Symptom:** Orchestrator works with one or two agents, others sit idle.
|
||||
**Root cause:** Missing `CULTURE.md` or pod SOP content that describes how the full team coordinates.
|
||||
**Fix:** Write a culture file that explicitly describes the coordination protocol. Include delegation patterns, review gates, and when each pod should be engaged.
|
||||
|
||||
### Services don't boot
|
||||
|
||||
**Symptom:** `rig up` fails before agents launch with a service health error.
|
||||
**Root cause:** Docker Compose issue, health check failure, or port conflict.
|
||||
**Fix:** Check `docker compose up` manually with the compose file. Verify health check URLs are correct. Check for port conflicts.
|
||||
|
||||
### Agent boots from the wrong project context
|
||||
|
||||
**Symptom:** Agent misses expected guidance, trust settings, permissions, or repo context even though the spec validates.
|
||||
**Root cause:** The rig spec directory was treated as the agent's runtime cwd by assumption.
|
||||
**Fix:** Confirm the intended cwd before launch. The spec can live in a rig/spec shelf while the agent works from the project or hub directory that carries the relevant `AGENTS.md`, `CLAUDE.md`, trust, and permissions. Use member `cwd` or `rig up --cwd` deliberately.
|
||||
|
||||
### Startup content not delivered
|
||||
|
||||
**Symptom:** Agent is missing expected guidance/skills.
|
||||
**Root cause:** File paths in the spec don't resolve, or `delivery_hint` is wrong.
|
||||
**Fix:** Verify file paths resolve relative to their owning artifact — AgentSpec resource paths are relative to the agent spec directory; RigSpec startup, culture, compose, cwd, and `local:` agent-ref paths are relative to the rig root. Check `delivery_hint` — use `guidance_merge` for pre-boot content, `send_text` for post-boot instructions.
|
||||
|
||||
### Agent startup delivered but agent doesn't use skills
|
||||
|
||||
**Symptom:** Skills are projected but agent doesn't invoke them.
|
||||
**Root cause:** Agent wasn't told to load them.
|
||||
**Fix:** In the startup context or role guidance, explicitly tell the agent which skills to load. The belt-and-suspenders pattern: project the skills via the spec AND tell the agent to read them in the guidance.
|
||||
|
||||
## Pattern Catalog
|
||||
|
||||
### The Implementation Pair
|
||||
**2 agents, 1 pod.** The smallest effective development unit. One implements (TDD), one does QA. The implementer proposes, QA approves or rejects, then the implementer commits.
|
||||
|
||||
```yaml
|
||||
pods:
|
||||
- id: dev
|
||||
label: Development
|
||||
members:
|
||||
- id: impl
|
||||
agent_ref: "local:agents/development/implementer"
|
||||
runtime: claude-code
|
||||
profile: default
|
||||
cwd: "."
|
||||
- id: qa
|
||||
agent_ref: "local:agents/development/qa"
|
||||
runtime: codex
|
||||
profile: default
|
||||
cwd: "."
|
||||
edges:
|
||||
- kind: delegates_to
|
||||
from: impl
|
||||
to: qa
|
||||
```
|
||||
|
||||
**Use when:** Focused feature work, bug fixes, small-to-medium implementation tasks.
|
||||
|
||||
### The Orchestrated Team
|
||||
**5-7 agents, 3 pods.** Orchestration + development + review. The orchestrator dispatches work, the dev pair implements, the review pair validates independently.
|
||||
|
||||
**Use when:** Production-quality work that needs coordination and independent review.
|
||||
|
||||
### The Research Team
|
||||
**3 agents, 2 pods.** Orchestrator + research pair (analyst + synthesizer). The analyst investigates deeply, the synthesizer consolidates findings.
|
||||
|
||||
**Use when:** Technical research, competitive analysis, architecture exploration.
|
||||
|
||||
### The Managed App
|
||||
**1+ agents, 1 pod, services block.** Software infrastructure (Docker Compose) plus a specialist agent who knows how to operate it.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
kind: compose
|
||||
compose_file: docker-compose.yaml
|
||||
wait_for:
|
||||
- url: http://127.0.0.1:8200/v1/sys/health
|
||||
|
||||
pods:
|
||||
- id: vault
|
||||
label: Vault
|
||||
members:
|
||||
- id: specialist
|
||||
agent_ref: "local:agents/apps/vault-specialist"
|
||||
runtime: claude-code
|
||||
profile: default
|
||||
cwd: "."
|
||||
edges: []
|
||||
```
|
||||
|
||||
**Use when:** The work involves operating software, not just writing code.
|
||||
|
||||
### The Full Product Team
|
||||
**7 agents, 3 pods.** The kitchen-sink topology: orchestration pair, development pod (impl + qa + design), review pair. See the `product-team` starter spec for the complete worked example.
|
||||
|
||||
**Use when:** Full product development with design, implementation, QA, and independent review. Requires strong culture and SOP content to keep all agents engaged.
|
||||
|
||||
## Final Notes
|
||||
|
||||
**Start simple, add complexity when needed.** A working implementation pair is better than a broken full team. Launch with the minimum viable topology, verify it works, then expand.
|
||||
|
||||
**Culture is not optional for team rigs.** Any rig with 3+ agents needs a CULTURE.md. Without it, agents will default to generic behavior and the topology will underperform.
|
||||
|
||||
**Validate early and often.** Run `rig spec validate` after every change. Run `rig agent validate` after every agent spec edit. Fix errors immediately — don't accumulate them.
|
||||
|
||||
**The startup content IS the product.** The YAML topology is scaffolding. What makes a rig actually useful is the guidance, culture, skills, and startup context that agents receive. Invest your authoring time there.
|
||||
@@ -1,86 +0,0 @@
|
||||
---
|
||||
name: openrig-cmux
|
||||
description: >
|
||||
Use when opening OpenRig fleet terminals into cmux — turning a rig, pod, mission, slice, or saved
|
||||
view into live agent tiles via `rig terminal --provider cmux`, or driving cmux on an agent's
|
||||
request. Same OpenRig view semantics as openrig-herdr (the verbs, honest-partial/degrade, read-only
|
||||
cross-rig, scroll/copy, same-size-only duplicates); cmux is the **best-effort** provider (herdr is
|
||||
the default and the proof-gated one). Prefer openrig-herdr unless cmux is specifically wanted.
|
||||
metadata:
|
||||
openrig:
|
||||
stage: candidate
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
cmux is OpenRig's shipped terminal provider generalized onto `rig terminal <provider>` —
|
||||
best-effort, not proof-gated. Authored clean-room.
|
||||
transfer_test: pending
|
||||
sibling_skills:
|
||||
- openrig-herdr
|
||||
- openrig-user
|
||||
---
|
||||
|
||||
# openrig-cmux
|
||||
|
||||
cmux is a **provider** for OpenRig views — the same `rig terminal` surface as herdr, rendering the
|
||||
tiles into cmux instead. It is the provider OpenRig already shipped (the existing "Launch in cmux"
|
||||
affordance generalizes onto `rig terminal <provider>`), kept working. The OpenRig-semantic half is
|
||||
identical to openrig-herdr: OpenRig decides **which** agents form a view; the provider renders the
|
||||
pixels. **Read openrig-herdr first for the full model** — this skill only calls out what differs for
|
||||
cmux.
|
||||
|
||||
## Provider status — cmux is best-effort
|
||||
|
||||
- **herdr is the default and the proof-gated provider**; **cmux is best-effort** — it ships on the
|
||||
same `rig terminal <provider>` + web-launcher neighborhood, but a cmux miss is not a slice failure.
|
||||
Reach for cmux when it is specifically wanted; otherwise default to herdr (`rig terminal open <view>`
|
||||
with no `--provider`).
|
||||
- Views are **provider-agnostic**: the same view + the same agents + the same semantics carry across
|
||||
herdr and cmux. A saved view opens in either.
|
||||
|
||||
## The surface (same three verbs, `--provider cmux`)
|
||||
|
||||
```bash
|
||||
rig terminal open <view> --provider cmux [--json] # open a view into cmux (herdr is the no-flag default)
|
||||
rig terminal views [--json] # the same view library, provider-agnostic
|
||||
rig terminal status --provider cmux [--json] # cmux liveness / health
|
||||
```
|
||||
|
||||
`<view>` resolves exactly as with herdr: a **rig name** · **`pod:<rig>/<podNamespace>`** ·
|
||||
**`mission:<id>`** · **`slice:<id>`** (derived live) · a **saved-view name**.
|
||||
|
||||
## What carries over unchanged from openrig-herdr
|
||||
|
||||
All of these behave identically — see openrig-herdr for the detail:
|
||||
|
||||
- **Honest-partial / honest-degrade** — opened / absent / degraded, each named; partial opens exit 0,
|
||||
zero-pane exits non-zero; an http-registered host's agents degrade with the reason ("host `<id>` is
|
||||
http-registered; tiles need ssh"), never silently dropped.
|
||||
- **Read-only policy** — a rig or `pod:` view is interactive; `mission:` / `slice:` views are
|
||||
read-only by construction; a saved view is per-member (`readOnly`). A read-only pane is
|
||||
`tmux attach -r` (client `readonly=1`, keystrokes physically cannot reach the agent). See openrig-herdr.
|
||||
- **Safety rails (the fleet-safety rail)** — a tile is a *view* (nested `tmux attach`) of a
|
||||
daemon-owned session; never move/join/kill/re-parent a daemon-owned pane; closing a tile detaches
|
||||
one client and leaves the session untouched; never live-flip tmux options on a running seat in
|
||||
production (prove it in an isolated environment first).
|
||||
- **Scroll + copy out of the box** — the daemon's terminal defaults (per-session scroll at launch +
|
||||
the server's clipboard defaults); running seats pick up wheel-scroll at their next relaunch.
|
||||
- **Limits** — tile chrome v1 = a plain label; same-size panes for duplicate/multi-view membership
|
||||
(the different-size resize mismatch is an inherent tmux multi-client limit, documented not fixed).
|
||||
|
||||
## cmux-specific notes
|
||||
|
||||
- **Open-or-focus per agent** — cmux's shipped integration opens a node or focuses it if already open;
|
||||
expect focus (not a duplicate) when a seat is already tiled in cmux.
|
||||
- **The shipped "Launch in cmux" affordance is preserved** (byte-compatible) and generalizes into the
|
||||
provider + view picker; opening cmux from the web launcher still works.
|
||||
- **No AGPL arm's-length concern** — unlike herdr, cmux is OpenRig's shipped provider integration; the
|
||||
clean-room/never-embed rail that applies to herdr is not a cmux constraint. (This skill itself is
|
||||
still authored clean-room.)
|
||||
|
||||
## Saved views — provider-agnostic
|
||||
|
||||
Saved views are **hand-authored** in `terminal-views.yaml` (v1 has no save/write verb) and are
|
||||
**provider-agnostic** — see **openrig-herdr** for the exact schema, the store facts (atomic tmp+rename,
|
||||
byte-stable, at the OpenRig home root), and the derived-views-never-persisted rule. Reopen any saved
|
||||
view in cmux with `rig terminal open <id> --provider cmux`. Derived views (a rig, `pod:<rig>/<pod>`,
|
||||
`mission:<id>`, `slice:<id>`) are computed live and never written to the file.
|
||||
@@ -1,158 +0,0 @@
|
||||
---
|
||||
name: openrig-herdr
|
||||
description: >
|
||||
Use when opening OpenRig fleet terminals as a herdr wall — turning a rig, pod, mission, slice, or
|
||||
saved view into live interactive agent tiles via `rig terminal`, watching another rig read-only,
|
||||
or driving herdr on an agent's request ("open all my rigs + a mission as views"). Covers the
|
||||
`rig terminal open|views|status` verbs, the honest-partial/degrade reading of the result, the
|
||||
read-only-by-construction rail for cross-rig views, scroll/copy out of the box, and the
|
||||
same-size-only duplicate-pane limit. herdr is the default, proof-gated provider.
|
||||
metadata:
|
||||
openrig:
|
||||
stage: candidate
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
Empirical herdr 0.7.1 hands-on findings + the ratified implementation PRD. Authored
|
||||
clean-room (patterns only, no herdr source text; AGPL arm's-length).
|
||||
transfer_test: pending
|
||||
sibling_skills:
|
||||
- openrig-cmux
|
||||
- openrig-user
|
||||
---
|
||||
|
||||
# openrig-herdr
|
||||
|
||||
OpenRig decides **which** agents make up a view (a rig, a pod, a mission, a slice, or a saved
|
||||
group); **herdr** renders the pixels. A view opens as live, interactive terminal tiles — each tile
|
||||
is a nested `tmux attach` to a daemon-owned agent session, so you get the real session, not a
|
||||
snapshot. OpenRig owns the semantics; herdr owns the surface. You drive it entirely through the
|
||||
`rig terminal` CLI, which rides the installed herdr binary at arm's length — never link, embed, or
|
||||
plugin it.
|
||||
|
||||
## The whole surface — three verbs
|
||||
|
||||
```bash
|
||||
rig terminal open <view> [--provider herdr|cmux] [--json] # herdr is the default provider
|
||||
rig terminal views [--json] # list openable views (saved + derived)
|
||||
rig terminal status [--provider] [--json] # provider liveness / health
|
||||
```
|
||||
|
||||
`<view>` resolves, in order, to one of:
|
||||
- a **rig name** — every live agent in that rig, auto-laid-out;
|
||||
- **`pod:<rig>/<podNamespace>`** — every live agent in one pod of a rig (the rig's inventory filtered by pod);
|
||||
- **`mission:<id>`** — the agents working that mission (derived live from topology);
|
||||
- **`slice:<id>`** — the agents working that slice (derived live);
|
||||
- a **saved-view name** — a user-defined group (see Saved views).
|
||||
|
||||
## Compose a view from a sentence
|
||||
|
||||
An agent asked "open all my rigs plus a mission as views" runs one `open` per target:
|
||||
|
||||
```bash
|
||||
rig terminal open acme-web # a whole rig, live agents as tiles
|
||||
rig terminal open mission:site-relaunch # exactly the agents working the mission
|
||||
rig terminal open slice:02-search-filters # the agents working one slice
|
||||
```
|
||||
|
||||
No hand-listing of seats: the mission/slice membership is derived from live topology at open time.
|
||||
|
||||
## Read the result honestly — partial and degrade
|
||||
|
||||
The result is a partition — every seat lands in exactly one bucket, each **named**:
|
||||
|
||||
- **opened** — the live agents now showing as tiles.
|
||||
- **absent** — seats in the view that aren't currently live: **named and skipped, never silently
|
||||
dropped.** A view that opens *some* of its seats is a success (the partial is disclosed) and exits
|
||||
**0**. Only a view where **no** pane opens exits **non-zero**.
|
||||
- **degraded** — an agent that structurally cannot tile, named **with the reason**. The v1 case:
|
||||
an agent on a host registered over HTTP has no ssh path, so its tile can't be composed — it reads
|
||||
as **"host `<id>` is http-registered; tiles need ssh"** and is skipped, never dropped. (ssh-reachable
|
||||
hosts tile via an ssh-wrapped attach; full http-host tiling is deferred to the cross-host transport
|
||||
seam.)
|
||||
|
||||
Read `--json` to branch on the partition programmatically; the exit code alone tells you opened-something
|
||||
(0) vs opened-nothing (non-zero).
|
||||
|
||||
## Read-only — who's interactive, who's watch-only
|
||||
|
||||
Read-only is composed into the pane at open time — a read-only tile is a `tmux attach -r`, the client
|
||||
reports `readonly=1`, and it **physically cannot send input**. The current policy, by view kind:
|
||||
|
||||
- **A rig view or a `pod:` view is interactive** — you asked for that rig (or pod) directly, so you
|
||||
can drive its agents.
|
||||
- **`mission:` and `slice:` views are read-only by construction** — these derived views cut across
|
||||
rigs; you watch and scroll, you don't keystroke into them.
|
||||
- **A saved view is per-member** — each member carries its own `readOnly` (omit = interactive;
|
||||
`true` = `attach -r`).
|
||||
|
||||
So you don't have to remember to be careful: the view kind (and, for a saved view, the per-member
|
||||
flag) sets it at open time.
|
||||
|
||||
## Safety rails (hard — the fleet-safety rail)
|
||||
|
||||
- A tile is a **view** (a nested `tmux attach`) of a daemon-owned session. **Never** move, join, kill,
|
||||
or re-parent a daemon-owned pane. Closing a tile detaches one tmux client — the daemon's session is
|
||||
untouched and its addressing (send/capture/nudge) is unaffected.
|
||||
- Host-local read-only viewing mutates nothing. Anything that would change a **live** daemon session's
|
||||
shared state (e.g. flipping a tmux option on a running seat) is a config/design change — prove it in
|
||||
an isolated environment, never live-flip in production.
|
||||
|
||||
## Scroll + copy work out of the box
|
||||
|
||||
On a freshly-launched agent tile the mouse wheel scrolls the pane's history and a drag-select copies
|
||||
to your **system** clipboard — with no tmux commands typed. This rides the daemon's terminal defaults
|
||||
(a per-session scroll option set at launch, plus the daemon tmux server's clipboard defaults). Honest
|
||||
timing: agents that were already running before this shipped pick up wheel-scroll at their **next
|
||||
natural relaunch** (the scroll default is per-session and running seats are never retro-flipped);
|
||||
system-clipboard copy works immediately (it's server-wide).
|
||||
|
||||
## Limits — state them, don't paper over them
|
||||
|
||||
- **Tile chrome v1 = a plain label** (agent + slice). Rich per-tile status is roadmap.
|
||||
- **Duplicate / multi-view membership** (the same agent live in two views at once) works — put the
|
||||
duplicates in **same-size panes**. Different-sized duplicate panes have an inherent tmux
|
||||
multi-client resize mismatch (tmux clamps to the smallest client); it is **documented, not fixed** —
|
||||
don't expect a setting to remove it.
|
||||
- **Inner tmux status bar** is hidden by default (herdr provides the chrome); one config key
|
||||
(`terminal.status_bar`) flips it back on for raw-tmux / no-provider surfaces, and the flip applies
|
||||
to **future launches only**.
|
||||
|
||||
## Saved views — the library (`terminal-views.yaml`)
|
||||
|
||||
In v1 you **create** a saved view by **hand-authoring** `terminal-views.yaml` — there is no save/write
|
||||
verb (`open` / `views` / `status` are the whole surface; a `rig terminal save <id>` verb is a named
|
||||
stretch/follow-up). You **reopen** it like any other view: `rig terminal open <id>`.
|
||||
|
||||
The file lives at the OpenRig home root (resolved via `getDefaultOpenRigPath()`), is written
|
||||
atomically (tmp + rename), and is byte-stable. **Only hand-authored saved views live here — derived
|
||||
views (a rig, `pod:<rig>/<pod>`, `mission:<id>`, `slice:<id>`) are computed live and never written to
|
||||
this file.**
|
||||
|
||||
Schema — use these field names **exactly**, in this order; **omit** optional fields when absent
|
||||
(never write `null`):
|
||||
|
||||
```yaml
|
||||
version: 1
|
||||
views:
|
||||
- id: my-view-id # required — the id `rig terminal open <id>` takes
|
||||
name: Human Name # required
|
||||
members:
|
||||
- seat: pod-member@rig # required — the canonical session name
|
||||
label: agent . slice # optional — pane label
|
||||
host: some-host-id # optional — STRUCTURED host id (NEVER a `member@rig@host` string);
|
||||
# omit for local. ssh-registered hosts tile;
|
||||
# http-registered hosts honest-degrade (named + skipped, with reason)
|
||||
tmuxSession: sessname # optional — defaults to `seat`
|
||||
readOnly: true # optional — omit = interactive; true = `tmux attach -r`
|
||||
```
|
||||
|
||||
An agent composing a saved view on request **writes this YAML** and then opens the id:
|
||||
`rig terminal open my-view-id` (add `--provider cmux` for cmux). The library is provider-agnostic —
|
||||
the same saved view opens in herdr or cmux.
|
||||
|
||||
## AGPL / clean-room
|
||||
|
||||
Driving herdr through the `rig terminal` CLI (which talks to the installed herdr binary over its
|
||||
CLI/socket) is arm's-length and fine. Do **not** link herdr's source, embed it in-process, or ship a
|
||||
herdr plugin — a plugin needs legal review. This skill and its docs are clean-room: patterns only,
|
||||
never herdr source text.
|
||||
@@ -1,222 +0,0 @@
|
||||
---
|
||||
name: openrig-operator
|
||||
description: |
|
||||
Use when debugging host-side OpenRig runtime issues: daemon reachability, Codex permission or writable-root failures, command approval friction, rate limits/account switches, helper cleanup, or topology health confusion. NOT for ordinary CLI operation (use openrig-user) or for changing OpenRig itself (work in the openrig product repo).
|
||||
metadata:
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
last_verified: "2026-05-04"
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
Bootstrap skill — NPM install lands this in personal homes (~/.claude/skills/, ~/.agents/skills/).
|
||||
Companion to openrig-user (daily CLI surface) — this skill is host-side troubleshooting.
|
||||
transfer_test: pending
|
||||
sibling_skills:
|
||||
- openrig-user
|
||||
- openrig-architect
|
||||
- forming-an-openrig-mental-model
|
||||
---
|
||||
|
||||
# OpenRig Operator
|
||||
|
||||
## Overview
|
||||
|
||||
This skill covers host/runtime/operator triage around OpenRig itself.
|
||||
Use it when the problem may be the daemon, the shell/runtime surface, or stale helper processes rather than the product workflow you are trying to run.
|
||||
|
||||
> **CANONICAL SURFACE NOTE (2026-05-11)** — for durable queue routing while doing
|
||||
> operator triage, use `rig queue` (daemon-backed SQLite). `rigx queue` is
|
||||
> recovery-only fallback; qitems written there are invisible to daemon-backed
|
||||
> reads and should not be used for new substantive work.
|
||||
|
||||
## When to Use
|
||||
|
||||
Use this skill when you see:
|
||||
- `rig whoami --json` returning partial identity
|
||||
- `rig ps --nodes --json` failing while some other `rig` commands still work
|
||||
- `Sent to ...` plus `Verified: no`
|
||||
- repeated unified-exec-process warnings
|
||||
- suspicion that stale helper processes are accumulating
|
||||
- Codex seats hit `Operation not permitted`, command approval friction, or stale writable roots
|
||||
- Codex seats report usage-limit/rate-limit or need a ChatGPT account switch
|
||||
|
||||
Do not use this skill for normal product workflow routing, queue handling, or ordinary peer communication. Use `openrig-user` for that.
|
||||
|
||||
Do not use this skill to decide how to change OpenRig behavior. Changes
|
||||
to the OpenRig product (CLI, daemon, UI, specs) happen in the openrig
|
||||
product repo — operate that as a normal software project, not via
|
||||
this troubleshooting skill.
|
||||
|
||||
## First Checks
|
||||
|
||||
Start with the minimum truthful operator read:
|
||||
|
||||
```bash
|
||||
rig whoami --json
|
||||
rig daemon status
|
||||
rig ps --nodes --json
|
||||
```
|
||||
|
||||
Interpret them together, not in isolation:
|
||||
- partial `whoami` can mean identity is inferable while daemon-backed surfaces are degraded
|
||||
- `daemon status` tells you whether the host daemon is up, not whether every seat can reach it cleanly
|
||||
- `ps --nodes --json` is the best machine-readable topology check when it works
|
||||
|
||||
## Verification Drift Vs Send Failure
|
||||
|
||||
For `rig send`:
|
||||
- `Sent to ...` + `Verified: yes` = strong positive delivery evidence
|
||||
- `Sent to ...` + `Verified: no` = ambiguous delivery, not automatic failure
|
||||
- no `Sent to ...` line or a hard error = send failure
|
||||
|
||||
When verification is ambiguous, check:
|
||||
- direct reply
|
||||
- `rig capture <session>`
|
||||
- transcript evidence
|
||||
- queue/outbox state if the message asked for a durable handoff
|
||||
|
||||
Do not blindly retry until you have checked one of those.
|
||||
|
||||
## Unified Exec Warning
|
||||
|
||||
If you see:
|
||||
|
||||
- `Warning: The maximum number of unified exec processes you can keep open is 60 ...`
|
||||
|
||||
treat it first as a host/tooling-layer warning, not as automatic proof that the OpenRig topology is unhealthy.
|
||||
|
||||
This warning can coexist with a healthy live topology.
|
||||
|
||||
## Safe Process Triage
|
||||
|
||||
Inspect the process surface first:
|
||||
|
||||
```bash
|
||||
ps -axo pid,ppid,command | rg 'tmux send-keys|rig queue create|tmux attach|codex|claude'
|
||||
```
|
||||
|
||||
Think in layers:
|
||||
- host/tooling layer: stale one-shot wrappers, session bookkeeping, helper shells
|
||||
- topology layer: live `tmux attach` seats, live `codex` / `claude` runtimes, daemon health
|
||||
|
||||
Do not diagnose topology failure from tooling-layer warnings alone.
|
||||
|
||||
## Safe Cleanup Boundary
|
||||
|
||||
Usually safe to reap when clearly orphaned / one-shot:
|
||||
- `tmux send-keys ...`
|
||||
- short-lived shell wrappers created only to enqueue or send one message
|
||||
|
||||
Do not mass-kill:
|
||||
- `tmux attach ...`
|
||||
- `codex ...`
|
||||
- `claude ...`
|
||||
- other long-lived daemon/runtime processes
|
||||
|
||||
The point is to remove garbage, not workers.
|
||||
|
||||
## Terminal Node Escalation
|
||||
|
||||
Use a terminal node when evidence shows a seat-level sandbox/profile cannot perform required host work, but another approved operator surface can. This is an explicit operator lane, not a silent permission bypass.
|
||||
|
||||
Good fits:
|
||||
- Codex/Claude seat cannot access Tart, SSH, tmux, queue directories, or host files needed for a proof
|
||||
- a VM/test-proof or current-host-operator task needs real host capability
|
||||
- another seat or terminal/sysadmin node has approved access and can return command evidence
|
||||
|
||||
Do not use this lane to bypass repo safety, dirty-worktree boundaries, review gates, or destructive-action approval. If the command would stop live rigs, delete data, reset git state, or mutate VM state beyond the accepted plan, require explicit authorization and record it.
|
||||
|
||||
Protocol:
|
||||
1. Classify the original failure as seat/profile-specific if possible, not product failure.
|
||||
2. Write or cite a packet with objective, lane, exact commands, cwd, expected outputs, stop conditions, and artifact path.
|
||||
3. Route to an existing sysadmin/infrastructure/terminal node when available; otherwise provision a named terminal node through the topology/config layer instead of using a hidden ad hoc shell.
|
||||
4. Terminal node runs only the packeted commands and returns command log, exit codes, cwd/env notes, and artifacts.
|
||||
5. Original agent keeps task ownership and proof classification; terminal node supplies host capability.
|
||||
|
||||
Field lesson: if tester sees `Operation not permitted` for Tart/SSH while driver or another approved seat can reach the VM, treat it as permission/profile variance and route a terminal-node/operator remediation before changing product code.
|
||||
|
||||
## Codex Permission Policy
|
||||
|
||||
Use the `security-and-consequence-boundary-policy` skill for the security model.
|
||||
OpenRig gates consequence boundaries, not ordinary work inside the intended boundary.
|
||||
|
||||
Treat Codex permissions as two independent layers:
|
||||
- command approval rules decide which shell commands can run outside the sandbox
|
||||
- filesystem writable roots decide which paths a `workspace-write` seat can mutate
|
||||
|
||||
Codex `auto_review`, `--full-auto`, and approval-bypass modes are not normal fleet defaults. They
|
||||
can burn quota catastrophically and do not widen filesystem roots for an already-running seat. Full
|
||||
access scope with `approvals_reviewer = "user"` is the intended Codex default here.
|
||||
|
||||
Claude Code auto permissions are different and are the preferred Claude default on this host when
|
||||
the consequence-boundary rules still apply.
|
||||
|
||||
Current host policy:
|
||||
- default profile is `fleet`
|
||||
- `fleet` uses `sandbox_mode = "danger-full-access"`, `approval_policy = "on-request"`, `approvals_reviewer = "user"`
|
||||
- top-level `[sandbox_workspace_write].writable_roots` intentionally includes `~/code` and tool dotdirs: `.codex`, `.claude`, `.openrig`, `.agents`, `.config`, `.cache`, `.local`, `.docker`, `.npm`, `.nvm`, `.pnpm-store`
|
||||
- `permissions.fleet.filesystem` mirrors those writes and denies `.ssh`, `.gnupg`, and project env files
|
||||
- `default.rules` broadly allows `rig` and `rigx`; `rigx` is fully permitted for now because it is the fast-moving config-layer overlay
|
||||
- `default.rules` still prompts for destructive/publishing surfaces such as `rm`, `mv`, `chmod`, `git push`, PR mutation, `sudo`, process kills, daemon lifecycle, and destructive Docker/Brew/rig commands
|
||||
|
||||
## Codex Account / Usage-Limit Refresh
|
||||
|
||||
When Codex seats hit usage limits or need a ChatGPT/OpenAI account rotation, use the focused
|
||||
`codex-seat-auth-refresh` skill instead of improvising.
|
||||
|
||||
Key reminder: host auth can switch while already-running Codex TUIs keep the old account. Refresh
|
||||
only the scoped seats, preserve stable seat names, and record auth-seat registry rows sequentially.
|
||||
|
||||
Known failure modes this policy prevents:
|
||||
- Codex seats assuming a task is impossible when the real issue is stale launch roots
|
||||
- agents creating workaround slices/features for what is actually a sandbox/config problem
|
||||
- writing load-bearing canon into `state/`, `/tmp`, or a nearby writable folder because the intended durable path was blocked
|
||||
- trusting labels like `full access`; verify actual roots and command policy instead
|
||||
- changing `config.toml` and expecting already-running seats to pick it up without restart
|
||||
|
||||
When `Operation not permitted` appears:
|
||||
1. Identify whether it is command approval, filesystem root, macOS privacy, or stale session.
|
||||
2. Check effective roots with `codex -p fleet debug prompt-input <probe-name>`.
|
||||
3. Verify with a tiny direct write probe in an allowed target and a negative probe in a protected target such as `.ssh`.
|
||||
4. If `config.toml` changed, restart one seat and re-run the probes before fleet rollout.
|
||||
5. If the target should be durable and is not writable, stop and escalate; do not invent fallback storage.
|
||||
|
||||
Field note: as of Codex CLI `0.125.0`, top-level `[sandbox_workspace_write]` was the shape reflected by `debug prompt-input`; profile-scoped writable roots did not show in the effective prompt. Re-test this if Codex changes.
|
||||
|
||||
|
||||
## Durable Write Escalation
|
||||
|
||||
If the task requires writing load-bearing knowledge or behavior and the intended target is not writable, stop and escalate. Do not silently write to `state/`, `/tmp`, or a nearby writable folder.
|
||||
|
||||
Use the intended durable home for the kind of content:
|
||||
- `skills/` (e.g. `~/.claude/skills/`, `~/.agents/skills/`, or your team's
|
||||
shared skill folder) for operating rules and refocus behavior
|
||||
- Your team's workstream notebook (field notes, lab experiments, mission
|
||||
packets, etc.) for durable observations and PM canon
|
||||
- The product repo for shipped OpenRig daemon/CLI/config/spec/test behavior
|
||||
|
||||
A runtime mirror under a rig `state/` path may be used only as a temporary live patch, must be labeled as non-canonical, and must have a canonical sync follow-up.
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- treating `Verified: no` as if it proves the message did not land
|
||||
- treating the unified-exec warning as if it proves the rig is overloaded
|
||||
- killing live seats when only stale helper wrappers needed cleanup
|
||||
- concluding "daemon down" from one seat's failure without checking host-level daemon status
|
||||
- assuming Codex config changes apply to already-running seats without a restart/probe
|
||||
- confusing command approval with filesystem write permission
|
||||
- calling a VM or product path broken before comparing another approved seat or terminal-node probe
|
||||
- assuming a label like `full access` proves effective write/network capability; verify command approval and filesystem writable-root coverage separately
|
||||
|
||||
## Practical Rule
|
||||
|
||||
Clean the smallest safe surface that matches the evidence.
|
||||
|
||||
If the warning or failure remains after stale-wrapper cleanup, re-check:
|
||||
|
||||
```bash
|
||||
rig daemon status
|
||||
rig ps --nodes --json
|
||||
```
|
||||
|
||||
If those remain healthy, the residual issue may still be in the host/tool/session layer rather than in OpenRig topology state.
|
||||
@@ -0,0 +1,95 @@
|
||||
---
|
||||
name: openrig-skills
|
||||
description: "Use when you're operating OpenRig and don't know which skill or context applies — this is the index of what ships with OpenRig, when to reach for each, and how to load it. Start here from a cold boot when nothing else is projected."
|
||||
metadata:
|
||||
openrig:
|
||||
stage: shipped
|
||||
---
|
||||
|
||||
# OpenRig skills — the index (start here)
|
||||
|
||||
You're running inside OpenRig. OpenRig ships a set of **skills** — small documents that tell you *when* to do something and *how*. This file is the map: what ships, when to reach for each, and how to load it. If you don't know which skill applies, or nothing is projected into your context, **start here.**
|
||||
|
||||
## How OpenRig context works (30 seconds)
|
||||
|
||||
Skills are **progressive disclosure**: a skill's *name + description* sit in your context ambiently (the "hot tier"); its *body* loads only when you open it. So you don't pre-read everything — you pattern-match a skill's "when" to your moment, then open just that one. This file is the index over the whole shipped set. (For the full model of building/operating agent software, open `software-for-agents`.)
|
||||
|
||||
Every row below names **how to reach the skill** — already-hot, or an exact load path. No row is a dead end.
|
||||
|
||||
For repo-shipped skills, resolve the installed CLI package root once:
|
||||
|
||||
```sh
|
||||
OPENRIG_CLI_ROOT="$(dirname "$(dirname "$(realpath "$(command -v rig)")")")"
|
||||
```
|
||||
|
||||
Paths below use that variable. Tier-A skills live in the daemon-vendored plugin at
|
||||
`~/.openrig/plugins/openrig-core/skills/`; selected and vendored skills live in the installed CLI package.
|
||||
|
||||
## The index
|
||||
|
||||
### Always loaded — the universal spine (open its body when its moment hits)
|
||||
These are auto-delivered to every rig; their name+description are already in your context. Open the body when the "when" matches.
|
||||
|
||||
- **forming-an-openrig-mental-model** — first boot, or you're unsure how the pieces fit. The runtime mental model. Load: `~/.openrig/plugins/openrig-core/skills/forming-an-openrig-mental-model/SKILL.md`.
|
||||
- **openrig-user** — you need a `rig` CLI command (send / queue / ps / whoami / scope / broadcast). The daily CLI surface. Load: `~/.openrig/plugins/openrig-core/skills/openrig-user/SKILL.md`.
|
||||
- **claude-compaction-restore** — you just compacted (Claude). Restore from durable evidence before resuming real work. Load: `~/.openrig/plugins/openrig-core/skills/claude-compaction-restore/SKILL.md`.
|
||||
- **session-compaction-and-restore** — preparing for, or recovering from, compaction (any runtime). The write- and read-side protocol. Load: `~/.openrig/plugins/openrig-core/skills/session-compaction-and-restore/SKILL.md`.
|
||||
- **queue-handoff** — you're passing durable work to another seat or ending your turn. The queue is the work ledger, not chat. Load: `~/.openrig/plugins/openrig-core/skills/queue-handoff/SKILL.md`.
|
||||
- **seat-continuity-and-handover** — handing your seat's work across a restart or to another owner. Load: `~/.openrig/plugins/openrig-core/skills/seat-continuity-and-handover/SKILL.md`.
|
||||
- **mission-slice-sop** — you're working a mission/slice (the SDLC: intent → mini-requirements + proof contract → build → QA → proof). The operating manual. Load: `~/.openrig/plugins/openrig-core/skills/mission-slice-sop/SKILL.md`.
|
||||
- **messaging-the-human** — composing a message to the human operator. Plain language, no insider jargon. Load: `~/.openrig/plugins/openrig-core/skills/messaging-the-human/SKILL.md`.
|
||||
- **software-for-agents** — you want the full first-load model of how agent software is built and operated here. Load: `~/.openrig/plugins/openrig-core/skills/software-for-agents/SKILL.md`.
|
||||
- **openrig-skills** — this index (you're reading it). Always loaded; the entry point to everything below. Load: `~/.openrig/plugins/openrig-core/skills/openrig-skills/SKILL.md`.
|
||||
|
||||
### Load when your role or task calls for it (repo-shipped, profile-selected)
|
||||
These ship in the installed OpenRig CLI and reach a seat when its profile selects them. To use one, select it in your profile's `uses.skills`, or open the exact installed path below.
|
||||
|
||||
- **openrig-architect** — authoring a rig or topology (NOT for changing OpenRig itself — that's `openrig-builder`). Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/openrig-architect/SKILL.md`.
|
||||
- **openrig-cmux** — driving the `cmux` terminal provider. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/openrig-cmux/SKILL.md`.
|
||||
- **openrig-herdr** — opening/managing seat terminals via the default proof-gated provider. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/openrig-herdr/SKILL.md`.
|
||||
- **agent-startup-and-context-ingestion** — a seat is booting and ingesting its startup context. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/agent-startup-and-context-ingestion/SKILL.md`.
|
||||
- **topology-mutation-and-seat-management** — adding, removing, renaming seats or otherwise mutating rig topology. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/topology-mutation-and-seat-management/SKILL.md`.
|
||||
- **rig-lifecycle** — rig up / down / pause / resume lifecycle operations. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/rig-lifecycle/SKILL.md`.
|
||||
- **rig-bundles-and-shareable-artifacts** — packaging or installing a rig bundle / shareable artifact. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/rig-bundles-and-shareable-artifacts/SKILL.md`.
|
||||
- **cross-host-rig-commands** — reaching seats or queues on another host (`--host`). Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/cross-host-rig-commands/SKILL.md`.
|
||||
- **openrig-upgrade** — upgrading OpenRig or the daemon. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/openrig-upgrade/SKILL.md`.
|
||||
- **agent-starters** — composing an agent's starter context / priming packs. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/agent-starters/SKILL.md`.
|
||||
- **specification-system** — authoring or reading AgentSpecs and rig specs. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/specification-system/SKILL.md`.
|
||||
- **attention-queue** — managing the attention / needs-attention surface. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/attention-queue/SKILL.md`.
|
||||
- **human-in-the-loop** — deciding when to involve the human vs. proceed on your own authority. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/human-in-the-loop/SKILL.md`.
|
||||
- **watchdog** — monitoring or recovering a seat (health, restore, stuck state). Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/watchdog/SKILL.md`.
|
||||
- **session-source-fork** — forking a session's source/context. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/core/session-source-fork/SKILL.md`.
|
||||
|
||||
Pod handbooks (load when you're in that pod):
|
||||
- **orchestration-team** — you're orchestrating a rig: dispatching, monitoring, keeping the loop moving. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/pods/orchestration-team/SKILL.md`.
|
||||
- **development-team** — you're on the dev pod: building and shipping product changes. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/pods/development-team/SKILL.md`.
|
||||
- **review-team** — you're reviewing: fresh scrutiny, anti-slop, empirical verification. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/pods/review-team/SKILL.md`.
|
||||
|
||||
Product-management craft (load when shaping/reviewing work):
|
||||
- **requirements-writer** — turning intent into clear requirements. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/pm/requirements-writer/SKILL.md`.
|
||||
- **plan-review** — reviewing a plan before it's built. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/pm/plan-review/SKILL.md`.
|
||||
- **exec-summary** — writing a decision-ready summary for a human. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/pm/exec-summary/SKILL.md`.
|
||||
- **office-hours** — running a structured advisory / decision session. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/pm/office-hours/SKILL.md`.
|
||||
- **context-builder** — assembling the context a task or seat needs. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/pm/context-builder/SKILL.md`.
|
||||
- **backlog-capture** — capturing and shaping backlog items. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/pm/backlog-capture/SKILL.md`.
|
||||
- **ui-mockup** — producing a UI mockup for a slice. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/pm/ui-mockup/SKILL.md`.
|
||||
|
||||
### Vendored craft — load when you're coding (ships with upstream provenance)
|
||||
General engineering skills OpenRig ships as vendored copies. Open when the task matches; they carry "modified by OpenRig" provenance.
|
||||
|
||||
- **test-driven-development** — implementing a feature or bugfix: write the failing test first. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/process/test-driven-development/SKILL.md`.
|
||||
- **verification-before-completion** — about to claim done / passing / fixed: run the check and read the output first. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/process/verification-before-completion/SKILL.md`.
|
||||
- **systematic-debugging** — debugging: find the root cause before the fix. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/process/systematic-debugging/SKILL.md`.
|
||||
- **writing-plans** — writing an implementation plan. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/process/writing-plans/SKILL.md`.
|
||||
- **executing-plans** — working through a written plan. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/process/executing-plans/SKILL.md`.
|
||||
- **brainstorming** — divergent ideation before converging. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/process/brainstorming/SKILL.md`.
|
||||
- **using-superpowers** — discovering and using the vendored "superpowers" skill set. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/process/using-superpowers/SKILL.md`.
|
||||
- **agent-browser** — driving a browser (screenshot / screencast) from an agent. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/process/agent-browser/SKILL.md`.
|
||||
- **frontend-design** — designing frontend / UI. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/process/frontend-design/SKILL.md`.
|
||||
- **dogfood** — web-QA / dogfooding a shipped UI. Load: `${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/process/dogfood/SKILL.md`.
|
||||
|
||||
## Need more than what ships here?
|
||||
|
||||
This index covers the **shipped** surface. A dev host carries far more (factory, architecture, PM-craft, studio skills) reached through the host's own routers/codemaps — if you're on a builder host and need something not listed above, that deeper routing is the next hop, not a wall. (Host-scale routing is the subject of the context-routing architecture doc; at product scale, this one file is the whole map.)
|
||||
|
||||
> Membership note: this index lists exactly the approved product-public oracle set (45 skills as of 2026-08-02: 10 Tier-A + 25 Tier-B + 10 vendored). Skills graduated but not yet in the oracle (e.g. `culture-drift`, `triple-gate-verification`, `reference-first-verification`) join this index when they land in `conventions/product-public-skills.yaml` — index and shipped set stay one scope.
|
||||
@@ -8,10 +8,28 @@ description: Use when operating OpenRig with the `rig` CLI and you need the ship
|
||||
This is an as-built guide to the shipped `rig` CLI.
|
||||
Use current code and `rig ... --help` as ground truth if anything here ever conflicts with older planning docs.
|
||||
|
||||
If you need a different shipped skill, open `openrig-skills` — the global index that routes to every shipped skill in one hop.
|
||||
|
||||
This is not the config-layer or builder guide. Use the substrate control-plane guidance for `rigx`
|
||||
and experimental overlays. Use the OpenRig builder guidance when changing OpenRig behavior,
|
||||
doctrine, or release posture.
|
||||
|
||||
|
||||
## Coordination trust boundary
|
||||
|
||||
Coordinate as openly as the trust boundary you actually control allows. Within a set of machines you
|
||||
own that already trust each other — they can reach each other's daemon URLs and the daemon itself
|
||||
requires no authentication — direct `rig send`, `rig capture`, and `rig queue` should just work.
|
||||
Don't invent bearer placeholders, allowlists, trust handshakes, or guest-reach restrictions the
|
||||
environment doesn't require.
|
||||
|
||||
Do not add or defend a restriction without naming the protected asset, the actual adversary, the
|
||||
blocked attack path, and the concrete consequence. Missing capability is not protection — repair the
|
||||
route, registration, runtime posture, or product defect directly. Arbitrary boundaries create
|
||||
constraint-induced circumvention: under goal pressure, agents build shadow transports, alternate
|
||||
credentials, and weaker proof instead of the direct authorized path. Keep only explicitly stated
|
||||
external or irreversible boundaries — public push / PR / publish, and destruction of canonical data.
|
||||
|
||||
## Coordination primitives — when to use which
|
||||
|
||||
Three coordination surfaces, used together for forward-momentum work. Internalize this
|
||||
@@ -28,7 +46,7 @@ the receipt and move on.
|
||||
Example:
|
||||
|
||||
```bash
|
||||
rig send reviewer@acme-web "Heads up — filing the per-commit handoff on the search-filters slice at the current tip." --verify
|
||||
rig send guard@your-rig "Heads up — filing per-commit handoff on the rig-up paper-cut fix at tip 6b8673b6." --verify
|
||||
```
|
||||
|
||||
### `rig queue create --source <X> --destination <Y> --tags <...> --body "<...>"` — durable work item
|
||||
@@ -39,18 +57,19 @@ restarts. Tracked in the daemon SQLite schema. Surfaces in Project / queue views
|
||||
+ in the destination seat's inbox. Tag with mission / slice / gate / checkpoint
|
||||
so future-you (and any peer) can find it.
|
||||
|
||||
Body discipline: substantive bodies go through a temp-file pattern, not inline
|
||||
`--body` with raw backticks — `rig queue create` body parsing breaks on
|
||||
unescaped backticks and rejects flag-like tokens.
|
||||
Body discipline: substantive bodies go through **`--body-file <path>`** (or `-` for stdin) — the
|
||||
purpose-built, corruption-safe surface (it kills the backtick-shell-corruption class for multi-line
|
||||
bodies). Do NOT inline a backtick-heavy or multi-line body via `--body`: `rig queue create` body
|
||||
parsing breaks on unescaped backticks and rejects flag-like tokens.
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
rig queue create \
|
||||
--source builder@acme-web \
|
||||
--destination reviewer@acme-web \
|
||||
--tags "mission:site-relaunch,slice:02-search-filters,gate:guard,handoff:per-commit,checkpoint:bug-1" \
|
||||
--body "$(cat /tmp/per-commit-body.txt)"
|
||||
--source driver-2@your-rig \
|
||||
--destination redo-guard-2@your-rig \
|
||||
--tags "mission:release,slice:rig-up-paper-cut-fix,gate:guard,handoff:per-commit,checkpoint:bug-1-bonus" \
|
||||
--body-file /tmp/per-commit-body.txt
|
||||
```
|
||||
|
||||
### `rig queue handoff <qitem-id> --to <next> ...` — hot-potato handoff
|
||||
@@ -64,8 +83,8 @@ Example:
|
||||
|
||||
```bash
|
||||
rig queue handoff qitem-20260601012431-d78aa805 \
|
||||
--to qa@acme-web \
|
||||
--tags "mission:site-relaunch,slice:02-search-filters,gate:qa,handoff:adversarial-dogfood"
|
||||
--to velocity-qa@your-rig \
|
||||
--tags "mission:release,slice:rig-up-paper-cut-fix,gate:qa,handoff:adversarial-dogfood"
|
||||
```
|
||||
|
||||
### §1b doctrine — turn ends by passing the ball
|
||||
@@ -99,9 +118,9 @@ process does not require.
|
||||
recovery-only fallback; qitems written via `rigx queue` are invisible to
|
||||
daemon-backed reads and break fleet-wide routing discipline.
|
||||
- Inlining a multi-line / backtick-heavy body into `rig queue create --body`
|
||||
→ write the body to `/tmp/<descriptive-name>.txt` first, then
|
||||
`--body "$(cat /tmp/<file>.txt)"`. The body parser does not tolerate raw
|
||||
backticks or flag-like tokens inline.
|
||||
→ use `--body-file /tmp/<descriptive-name>.txt` (or `-` for stdin), the
|
||||
corruption-safe surface. The body parser does not tolerate raw backticks or
|
||||
flag-like tokens inline.
|
||||
|
||||
## Runtime-Gated Coordination Primitives
|
||||
|
||||
@@ -267,11 +286,15 @@ workflow spec.
|
||||
workflow instance + entry-step qitem. Inspect existing surface state with:
|
||||
|
||||
```bash
|
||||
rig workflow specs --json # list registered specs (built-in + operator-authored)
|
||||
rig workflow list --json # list active workflow instances
|
||||
rig workflow show <instanceId> --json
|
||||
rig workflow specs --json # list registered specs (built-in + operator-authored)
|
||||
rig workflow list --json # list active workflow instances
|
||||
rig workflow show <instanceId> --json # inspect one instance
|
||||
rig workflow project <instanceId> # ADVANCE an instance — projects the next-step packet
|
||||
rig workflow continue <instanceId> # read-only inspector of an instance (does NOT advance it)
|
||||
```
|
||||
|
||||
*(Surface note — the current `rig workflow` command group registers **13** subcommands: `validate`, `instantiate`, `project`, `list`, `specs`, `show`, `trace`, `continue`, `run`, `watch`, `route`, `resume`, `status`. There is still no `create` verb — the spec YAML is authored on disk. `project` is the advancing verb (it projects the next-step packet); `continue` is a read-only inspector, NOT an advance — do not conflate them. The 13-verb set and the project-vs-continue semantics are verified against current product main `d37a08ad` (`packages/cli/src/commands/workflow.ts`, 13 registered `.command(...)` entries; the earlier "6-verb surface / continue-advances" claim here was stale). Verify individual subcommand flags with `rig workflow --help`.)*
|
||||
|
||||
## v0.3.x Starter, Workspace, And Plugin Surfaces
|
||||
|
||||
OpenRig v0.3.0 adds `rig agent-image`, `rig context-pack`, `rig workspace`, and
|
||||
@@ -388,7 +411,7 @@ reconcile:
|
||||
|
||||
```bash
|
||||
rig seat clear-attention <session>
|
||||
rig seat clear-attention <session> --reason "operator attested: founder re-authed, confirmed live"
|
||||
rig seat clear-attention <session> --reason "operator attested: the operator re-authed, confirmed live"
|
||||
rig seat clear-attention <session> --json
|
||||
```
|
||||
|
||||
@@ -435,47 +458,27 @@ honestly and the UI exposes a one-click open-missing affordance.
|
||||
|
||||
v0.4.0 flips the five most frequently invoked read-commands from firehose-by-default to compact-by-default, and `rig queue list` adopts the docker / kubectl read-command grammar. **All defaults preserve breadth and capability — the firehose is one explicit flag away.**
|
||||
|
||||
### `rig ps` — consolidated all-rigs default + the disclosure ladder (v0.4.4)
|
||||
### `rig ps` — current-rig default + compact-by-default + `-A`/`--all-rigs` + `--full`
|
||||
|
||||
```bash
|
||||
rig ps # ALL ACTIVE RIGS, one compact row each + rollup line + count line + ladder footer (default)
|
||||
rig ps --json # bare array of ALL non-archived rigs (incl. stopped; existing keys + additive attentionCount)
|
||||
rig ps --rig <name> # one rig's detail
|
||||
rig ps --nodes # compact node inventory (current rig — session default, LOCAL only)
|
||||
rig ps --nodes --rig <name> # compact node inventory, named rig
|
||||
rig ps --nodes -A # fleet node inventory, projected rows
|
||||
rig ps --nodes -A --full # complete per-node records (the ONLY full fan-out; resumeToken VALUE retained here for downstream consumers)
|
||||
rig ps # CURRENT-RIG, all-states, compact rig summaries (default)
|
||||
rig ps --json # compact JSON array (TL;DR per node: session, rig, activity, assigned/pending, resumeTokenPresent boolean)
|
||||
rig ps -A # all-rigs (fleet breadth; was the v0.3.4 default)
|
||||
rig ps --rig <name> # explicit-rig (overrides current-rig default)
|
||||
rig ps --nodes # compact node inventory (current rig)
|
||||
rig ps --nodes -A # cross-rig node inventory (was v0.3.4 default)
|
||||
rig ps --nodes --full # complete record (the v0.3.4 per-node default shape; resumeToken VALUE retained here for downstream consumers)
|
||||
rig ps --nodes --session <sess> # narrow to one canonical session
|
||||
rig ps --include-archived # archived history as rows (otherwise ONE count line)
|
||||
rig ps --active # opt-in active-state filter (does NOT change the all-states default — ps surfaces topology/readiness, where stopped/recoverable/attention IS the actionable signal)
|
||||
```
|
||||
|
||||
**v0.4.4 consolidated default + disclosure ladder (OPR.0.4.4.21)**:
|
||||
- **The default is the fleet MAP**: every active rig as one O(rigs) compact row, with the host rollup ("N rigs · M seats · K need attention"), the archived/stopped count line, and the drill-ladder footer. The v0.4.0 current-rig default is RETIRED — it hid running rigs from the operator's field of view.
|
||||
- **`-A` has exactly ONE meaning**: the `--nodes` fleet widener. Bare `rig ps -A` errors (all-rigs IS the default; archived history stays behind `--include-archived`).
|
||||
- **The session-rig default applies ONLY to `--nodes`, and only locally.** Implicit scope defaults don't cross host boundaries: `rig ps --host <id> --nodes` requires an explicit `--rig` or `-A`; multi-host fan-out is rollup-only by default; the full explicit ladder (`--all-hosts --nodes -A`, `--full` for complete records) fans out per-node with hostId-stamped projected rows.
|
||||
- **STATED JSON contract**: default `--json` = bare array of ALL non-archived rigs INCLUDING stopped ones (scope-not-shape: existing keys preserved, additive `attentionCount`); only the human table folds stopped rigs into the count line.
|
||||
- **Resume-token security unchanged**: compact output never carries token material; `--full` retains it for consumers that legitimately need it.
|
||||
**v0.4.0 breadth + projection changes**:
|
||||
- **Default breadth is CURRENT-RIG** (derived from `OPENRIG_SESSION_NAME`'s `@<rig>` suffix), not all-rigs. `-A` / `--all-rigs` widens to fleet. Matches the `rig queue list -A` pattern.
|
||||
- **Per-node TL;DR projection (compact) is the default**; `--full` returns the raw byte-equivalent passthrough. Daemon-side `recoveryGuidance` relocated to a guidance-by-reference map (no longer duplicated per-node) — even `--full` benefits.
|
||||
- **All-states stays default** (different from `rig queue list` which defaults to active-only) — for `ps`, non-running states ARE often the actionable signal.
|
||||
- **Resume-token security**: `--full` JSON emits `resumeTokenPresent` (boolean) — the actual `resumeToken` value also remains in `--full` for downstream consumers that legitimately need it, but the compact default never carries it (an orch glance never accidentally leaks token material).
|
||||
|
||||
**The casual status glance is just `rig ps`.** The old fleet firehose is the explicit last rung: `rig ps --nodes -A --full`. The ~77,000-token incident class stays closed (compact + O(rigs) default + explicit ladder).
|
||||
|
||||
### `rig host` — the multi-host registry verbs (v0.4.4)
|
||||
|
||||
```bash
|
||||
rig host add --id <id> --transport ssh --target <tailnet-alias> --user openrig
|
||||
rig host add --id <id> --transport http --url http://100.x.y.z:7433 --bearer-env MY_TOKEN
|
||||
rig host list # pointers only — never secret values
|
||||
rig host doctor <id> # stepwise: transport -> rig binary -> daemon -> identity
|
||||
rig host doctor <id> --posture product-factory-vps [--public-addr <ip>]
|
||||
```
|
||||
|
||||
Exactly three verbs (capped); the VPS factory bootstrap is script + runbook
|
||||
(`docs/reference/product-factory-vps-runbook.md`). **Transport posture is
|
||||
DECIDED and documented** (cli-reference §Cross-host execution): ssh = pane ops
|
||||
(`send`/`capture`), http = daemon REST (`up`/`down`/`launch`), `ps`/`whoami`
|
||||
follow the DECLARED transport; fan-out is http-only; no cross-transport
|
||||
fallback; no http parity for send/capture in 0.4.4. Posture/doctor UNKNOWN is
|
||||
never pass — each unknown carries the command that verifies it.
|
||||
**STOP using `rig ps --nodes --json` as a fleet-wide casual status check assuming the v0.3.4 shape.** The v0.4.0 default is CURRENT-RIG + compact; explicit `-A --full` is the fleet firehose. The ~77,000-token status-glance incident is closed twice over (compact + scope).
|
||||
|
||||
### `rig whoami` — compact-by-default + `--full` (`--verbose` alias)
|
||||
|
||||
@@ -503,7 +506,7 @@ rig queue list --source <s> # sourced by <s>
|
||||
rig queue show <qitemId> # full single item (kubectl describe)
|
||||
```
|
||||
|
||||
Four orthogonal axes (scope × history × field-breadth × encoding), all composable. **STOP using bare `rig queue list` as the cross-rig firehose.** Default is now active + compact + current-rig. The cross-rig + history + full-body firehose (the ~64,000-token bomb on this host) is opt-in via `-A -a --full`.
|
||||
Four orthogonal axes (scope × history × field-breadth × encoding), all composable. **STOP using bare `rig queue list` as the cross-rig firehose.** Default is now active + compact + current-rig. The cross-rig + history + full-body firehose (the ~64,000-token payload spike) is opt-in via `-A -a --full`.
|
||||
|
||||
### `rig restore-check` — summary + not-ready-only default + `--full`
|
||||
|
||||
@@ -535,16 +538,16 @@ This release closes the host-version-aged token-burn class: on this host the rea
|
||||
|
||||
The interim `token-efficiency-boot-guardrail` pack (the CLI-command prohibitions on `rig queue list` unfiltered, `rig ps --nodes --json` unfiltered, `rig restore-check`, `rig context`, `rig whoami --json`) is a host-version workaround for the bloated defaults this release closes. **The CLI-command-prohibitions half retires when 0.4.0 lands on the host.** The pack's bounded-local-search rule + scope / over-flag discipline GRADUATE to a standing convention (`conventions/bounded-local-search-and-flag-scope`) and continue to apply host-independently.
|
||||
|
||||
### `rig scope mission|slice progress` — deterministic progress updates (slice 33)
|
||||
### `rig scope mission|slice progress` — deterministic progress updates
|
||||
|
||||
```bash
|
||||
rig scope mission progress <mission> --status <state> --milestone <text>
|
||||
rig scope slice progress <slice-path> --status <state> --note <text>
|
||||
rig scope mission progress <mission> --add "<line>" # append a progress line; --set replaces; --section <heading> (default Rail); --status active|done|blocked
|
||||
rig scope slice progress <slice-path> --add "<line>" # same flags: --add / --set, --section <heading>, --status active|done|blocked
|
||||
```
|
||||
|
||||
Replaces hand-editing `PROGRESS.md` with markdown. Writes the canonical structure the OpenRig PROGRESS UI page reads. `rig scope mission create` + `rig scope slice create` now scaffold `PROGRESS.md` automatically per `conventions/scope-and-versioning/README.md`.
|
||||
|
||||
### `rig scope mission|slice stage / verified / reconcile` — deterministic maturity vocabulary (slice 35)
|
||||
### `rig scope mission|slice stage / verified / repair` — deterministic maturity vocabulary
|
||||
|
||||
```bash
|
||||
rig scope slice stage <slice> <new-stage> # wip / provisional / established / canonical / superseded / retired
|
||||
@@ -554,40 +557,16 @@ rig scope mission stage <mission> <new-stage> # same enum + rules at mis
|
||||
rig scope slice verified <slice> --against "<source>" # stamp `verified: <today> against <source>`; --against MANDATORY
|
||||
rig scope mission verified <mission> --against "<source>"
|
||||
|
||||
rig scope slice reconcile <slice> # idempotent repair: backfill PROGRESS.md, conform id/stage/verified, repair ghosts
|
||||
rig scope mission reconcile <mission> # mission-tier idempotent repair
|
||||
rig scope slice repair <slice> # idempotent repair: backfill PROGRESS.md, conform id/stage/verified, repair ghosts
|
||||
rig scope mission repair <mission> # mission-tier idempotent repair
|
||||
|
||||
rig scope slice show <slice> # derives read-time effective-reliability from (stage × verified)
|
||||
# — stale-`verified` `canonical` reported as effectively `provisional`
|
||||
```
|
||||
|
||||
Composes with slice 33's `progress` + scaffolding to make `rig scope` the **deterministic enforcer** of `conventions/scope-and-versioning` §1 (dot-IDs) + §2 (maturity vocabulary). Agents update `stage` / `verified` / `id` through commands rather than hand-editing markdown and drifting. The `--against` MANDATORY rule on `verified` is the anti-stale keystone: bare timestamps are rejected because a bare timestamp is exactly what lets stale trackers lie while looking fresh. **STOP hand-editing the `stage` / `verified` / `id` fields in scope frontmatter; use the new verbs.** Existing missions / slices with `id:null` ghosts or missing `PROGRESS.md` are repaired idempotently via `reconcile`.
|
||||
Composes with the `progress` command + scaffolding to make `rig scope` the **deterministic enforcer** of `conventions/scope-and-versioning` §1 (dot-IDs) + §2 (maturity vocabulary). Agents update `stage` / `verified` / `id` through commands rather than hand-editing markdown and drifting. The `--against` MANDATORY rule on `verified` is the anti-stale keystone: bare timestamps are rejected because a bare timestamp is exactly what lets stale trackers lie while looking fresh. **STOP hand-editing the `stage` / `verified` / `id` fields in scope frontmatter; use the new verbs.** Existing missions / slices with `id:null` ghosts or missing `PROGRESS.md` are repaired idempotently via `repair`.
|
||||
|
||||
### The SDLC control plane — convention sections, the two locks, `rig proof` (v0.4.4)
|
||||
|
||||
The Living Notes UI is a plain projection of well-formed on-disk markdown. The conventions live in ONE shipped document — **`docs/reference/sdlc-conventions.md`** in the repo, materialized by the daemon at **`$OPENRIG_HOME/reference/sdlc-conventions.md`** (default `~/.openrig/reference/sdlc-conventions.md`) on an installed package — and the operating procedure is the **`mission-slice-sop`** skill. The command surface:
|
||||
|
||||
```bash
|
||||
rig scope slice create <mission> <slug> [--template <kind>] # scaffolds ## Intent / ## Mini-requirements / ## Proof contract
|
||||
# + proof/ + PROOF.md + IMPLEMENTATION-PRD.md — EVERY template kind
|
||||
|
||||
rig scope slice approve <slice> --scope spec # PLAN-LOCK: "the PRD matches my intent; this set gets built"
|
||||
rig scope slice approve <slice> --scope delivery # PROOF-LOCK: the terminal sign-off (default scope; fires the freeze)
|
||||
|
||||
rig proof add <slice> --artifact-type qa --verdict PASS \
|
||||
--candidate-sha <tip> --money-evidence "<one line>" \
|
||||
--evidences "1,3" --media "walk.webm" \
|
||||
--self-check "<looked at it>" # C1 proof drop into proof/; --evidences joins the drop to its
|
||||
# proof-contract items and --media names the curated proof/-relative
|
||||
# media it stands behind (what the DELIVERED section pairs + renders)
|
||||
|
||||
rig scope audit <mission> # deterministic backstop — flags missing sections / malformed
|
||||
# proof contract / invalid C1 headers; ADVISORY, never blocks
|
||||
```
|
||||
|
||||
The flow: intent → mini-requirements + proof contract (→ mockups for UI slices) → plan-lock → build the locked set → QA visual compare → `rig proof` drops → proof-lock. Approval is freeze/sign-off, **never** proven-green — proven-green requires recorded C1 verdicts.
|
||||
|
||||
### `rig skill audit` — skill cascade provenance (slice 10)
|
||||
### `rig skill audit` — skill cascade provenance
|
||||
|
||||
```bash
|
||||
rig skill audit # human report of findings
|
||||
@@ -596,12 +575,46 @@ rig skill audit --severity warn # stale + mirror-drift only
|
||||
rig skill audit --rig <name> # narrow to embedded skill copies for one rig
|
||||
```
|
||||
|
||||
Read-only audit of the skill cascade. Detects `missing` / `stale` / `self-referential` / `invalid-date` / `mirror-drift` across the canonical `openrig-work/skills/` → product mirror → hub cwd → installed plugin chain. Findings route back to the lifecycle for shaped propagation runs. **False-green prevention**: when audit evidence is unavailable, the CLI emits `unable-to-audit` with exit code `2` rather than reporting `clean`.
|
||||
Read-only audit of the skill cascade. Detects `missing` / `stale` / `self-referential` / `invalid-date` / `mirror-drift` across the canonical skills workspace → product mirror → hub cwd → installed plugin chain. Findings route back to the lifecycle for shaped propagation runs. **False-green prevention**: when audit evidence is unavailable, the CLI emits `unable-to-audit` with exit code `2` rather than reporting `clean`.
|
||||
|
||||
### `rig seat clear-attention` — extended to derived projection staleness (slice 16)
|
||||
### `rig seat clear-attention` — extended to derived projection staleness
|
||||
|
||||
v0.3.4 shipped `clear-attention` gating on `session.startupStatus` only. v0.4.0 extends the verb to also reach **restoreOutcome-derived** attention (seat is `startupStatus=ready` + `sessionStatus=running` but carries `restoreOutcome=failed` / `continuityOutcome=failed`). Same evidence-gated audit row applies; the `--reason <text>` operator-attestation override carries the runtime / cwd-uncertainty disclosure honestly.
|
||||
|
||||
### Native Codex session id capture
|
||||
|
||||
Codex seats can now record the real native session id from the Codex
|
||||
`SessionStart` hook instead of relying on scrape-shaped identity. The proof
|
||||
lane for v0.4.0 matched the same id across the hook payload, rollout log, and
|
||||
SQLite. Treat hook-sourced ids as stronger resume/identity evidence than
|
||||
terminal scraping when present.
|
||||
|
||||
Managed-seat hook trust is a 0.4.1 carry: the v0.4.0 surface proves native
|
||||
capture and hook-trust constraints, but do not assume every managed Codex seat
|
||||
has already migrated from scrape-backed to hook-sourced ids.
|
||||
|
||||
### Codex resume preserves approval posture
|
||||
|
||||
Resuming a Codex seat preserves the launching seat's approval/sandbox posture
|
||||
and profile flags. Product-emitted resume commands carry the posture flags
|
||||
instead of silently falling back to implicit-deny or an unrelated profile.
|
||||
|
||||
Do not "fix" a resumed Codex seat by relaunching it with broader approvals
|
||||
unless the operator explicitly grants a bounded window. Verify the seat's
|
||||
active posture first, and preserve it when composing recovery commands.
|
||||
|
||||
### `rig seat set-resume-token --token-stdin`
|
||||
|
||||
```bash
|
||||
printf '%s' "$RESUME_TOKEN" | rig seat set-resume-token <session> --token-stdin
|
||||
```
|
||||
|
||||
Use this command to set or restore a seat resume token. It replaces direct
|
||||
SQLite edits, rejects unauthorized writes and bad/null token false-ready paths,
|
||||
records redacted audit/provenance, and keeps token material out of command
|
||||
arguments, stdout, logs, and normal status rows. Use stdin, not an inline flag,
|
||||
when passing token material.
|
||||
|
||||
## Core Loop
|
||||
|
||||
Most work in OpenRig reduces to this loop:
|
||||
@@ -628,7 +641,7 @@ Typical operator loop:
|
||||
|
||||
```bash
|
||||
rig up secrets-manager --cwd /path/to/project
|
||||
rig ps --nodes --rig secrets-manager --json
|
||||
rig ps --nodes --json
|
||||
rig send vault-specialist@secrets-manager "Check Vault health and report back." --verify
|
||||
rig env status secrets-manager
|
||||
rig env logs secrets-manager
|
||||
@@ -675,19 +688,18 @@ JSON form exposes `peersNote` directly for programmatic consumers.
|
||||
## Inventory and Monitoring
|
||||
|
||||
```bash
|
||||
rig ps
|
||||
rig ps --json
|
||||
rig ps --nodes
|
||||
rig ps --nodes --rig <name> --json
|
||||
rig ps --nodes -A --json
|
||||
rig ps --nodes -A --full --json
|
||||
rig ps # CURRENT-RIG, compact rig summaries (v0.4.0 default)
|
||||
rig ps --nodes # compact node inventory (current rig)
|
||||
rig ps -A # all-rigs breadth (was the pre-0.4.0 default)
|
||||
rig ps --nodes --full # complete per-node record (the firehose — opt-in)
|
||||
rig ps --nodes --json # compact JSON node inventory (add --full for the full record)
|
||||
```
|
||||
|
||||
Use `rig ps --nodes --rig <name> --json` for one rig's node inventory, or `rig ps --nodes -A --json` for fleet-wide projected node inventory. Use `--full` only when a downstream consumer truly needs complete per-node records. The node inventory surface carries:
|
||||
**v0.4.0 flipped these to compact-by-default — see the `rig ps` compact-defaults section above; STOP using bare `rig ps --nodes --json` as a fleet-wide firehose (the ~77k-token status-glance incident).** The compact `rig ps --nodes` node inventory (add `--full` only when you need the complete record, `-A` for cross-rig breadth) carries, per node:
|
||||
- session name
|
||||
- runtime
|
||||
- session/startup status
|
||||
- restore outcome
|
||||
- restore outcome (compact: `resumeTokenPresent` boolean; the token VALUE is in `--full`)
|
||||
- attach/resume commands
|
||||
- latest error
|
||||
|
||||
@@ -719,13 +731,25 @@ rig transcript <session> --json
|
||||
```bash
|
||||
rig send <session> "message"
|
||||
rig send <session> "message" --verify
|
||||
rig send <session> "message" --force
|
||||
rig send <session> "message" --wait-for-idle <seconds>
|
||||
rig send <session> "message" --raw
|
||||
rig send <session> "message" --dangerously-interact --reason "<why>"
|
||||
rig send <session> "message" --host <id>
|
||||
rig send <session> "message" --json
|
||||
```
|
||||
|
||||
Use `--verify` when you want delivery evidence. Use `--force` only when you intentionally want to bypass activity-risk checks.
|
||||
**The send-guard (v0.4.0) — the default is SAFE.** A default `rig send` is guarded: it will NOT submit into an interactive prompt / permission block on the target pane (the footgun that prematurely shipped 0.4.0). Flags:
|
||||
- `--verify` — delivery evidence.
|
||||
- `--force` — **a back-compat no-op on the send DECISION**: it never bypasses the interactive-prompt/permission guard and never changes whether a message is delivered (a mid-task/busy pane already sends-with-advisory by default). *(It does NOT "bypass activity-risk checks" — that earlier teaching is retired.)* It is **not fully inert**, though — it is still parsed solely to be **rejected in combination with `--wait-for-idle`**: `rig send … --force --wait-for-idle <n>` prints `--wait-for-idle cannot be combined with --force`, exits 1, and sends nothing. So do not read "no-op" as "`--force --wait-for-idle` is harmless"; that pairing errors. *(Verified against current product main `d37a08ad`: the guard-bypass no-op is declared at `send.ts` and confirmed by runtime capture — a plain `--force` send delivers through the ordinary path; the `--wait-for-idle` rejection is enforced at `send.ts`, `routes/transport.ts`, and `session-transport.ts`, and confirmed by runtime capture — exit 1, nothing sent.)*
|
||||
- `--wait-for-idle <seconds>` — wait until the target is explicitly idle before sending. **Cannot be combined with `--force`** (that pairing is rejected: exit 1, nothing sent).
|
||||
- `--raw` — send exact text/keystrokes without the From/To messaging envelope (still guarded against interactive prompts).
|
||||
- `--dangerously-interact --reason "<why>"` — the ONLY override of the prompt/permission guard: deliberately drive an interactive prompt/permission block (implies `--raw`, requires `--reason`, audit-logged).
|
||||
- `--host <id>` — send on a remote host declared in `~/.openrig/hosts.yaml` (ssh hosts shell out; http hosts go CLI-direct to the remote daemon).
|
||||
- `--from <session>` — originating session for the envelope sender/actor (provenance; defaults to `$OPENRIG_SESSION_NAME`, and is plumbed through cross-host sends so the remote envelope names the origin, not the relay).
|
||||
|
||||
As of v0.3.3 (slice 17), content beginning with `--` or `-` is safe:
|
||||
> **Durable work goes to the QUEUE, not `send`.** `rig send` is an *ephemeral* message to a pane — it can be missed, and its delivery status is pane-render, not receipt. If you are **assigning work, or the message is important enough that losing it would be a real bummer**, use `rig queue` (below): it's durable, owned, tracked, and survives compaction and restart. Reach for `send` for a quick conversational nudge; reach for the **queue** for anything that must not get lost. Do not default to `send` for work — that's the most common mistake.
|
||||
|
||||
As of v0.3.3, content beginning with `--` or `-` is safe:
|
||||
`rig send <session> "content starting with -- or - is now safe"` delivers
|
||||
literally. The daemon's `send_text` path carries an explicit `--`
|
||||
end-of-options sentinel so tmux no longer parses dash-prefixed content
|
||||
@@ -774,7 +798,17 @@ rig broadcast "message"
|
||||
rig broadcast --rig <name> "message" --json
|
||||
```
|
||||
|
||||
Without `--rig` or `--pod`, broadcast targets all running sessions.
|
||||
**Use `rig broadcast` sparingly — prefer `rig send` fan-out.** Without `--rig` or `--pod`, broadcast targets
|
||||
**every running session across ALL rigs** (plus attached external_cli nodes) — the fastest way to cause a
|
||||
broadcast storm. Reserve `rig broadcast` for small rigs or a genuine all-hands emergency. For the normal
|
||||
"message several seats at once" case, use `rig send`, which scopes the fan-out and keeps the messaging
|
||||
envelope, the delivery/interactive-prompt guards, and per-recipient results:
|
||||
|
||||
```bash
|
||||
rig send --to dev-impl@my-rig,dev-qa@my-rig "message to specific seats" # named seats (comma-list or repeat --to)
|
||||
rig send --pod dev "message to one pod" # scoped fan-out
|
||||
rig send --rig my-rig "message to one rig" # scoped fan-out
|
||||
```
|
||||
|
||||
### Chatroom
|
||||
|
||||
@@ -792,6 +826,27 @@ rig chatroom watch <rig> [--tmux]
|
||||
- `history` — retrieve with composable filters (sender, since, after, topic)
|
||||
- `wait` — block until new matching messages arrive (polls history, times out honestly)
|
||||
- `clear` — delete all messages for the rig (destructive, rig-scoped)
|
||||
|
||||
## See something, say something
|
||||
|
||||
OpenRig has an **observation stream** — the fleet's zero-friction institutional memory, mined for
|
||||
real product improvements. When you notice **anything worth externalizing**, say something and keep
|
||||
working:
|
||||
|
||||
- a **bug**, a rough edge, or something that needs fixing
|
||||
- a **feature idea** or an improvement
|
||||
- something that **worked really well** — a technique, tool, or pattern worth spreading
|
||||
- an **observation**, positive or negative feedback, or something genuinely cool, productive, or funny
|
||||
|
||||
```bash
|
||||
rig stream emit --source <your-session> --body "what you noticed"
|
||||
```
|
||||
|
||||
That's the whole reflex. **Don't** decide where it goes or who it's for — the intake router triages
|
||||
(destination/type/urgency/tags are optional hints — `--hint-type review|handoff|idea`,
|
||||
`--hint-urgency routine|urgent|critical`, `--hint-tags` — never required). One command, then carry
|
||||
on; the value is the habit, not the polish. **Don't overdo it, either:** stream real signal, not
|
||||
narration — a good observation beats ten noisy ones. It's a passing thought you externalize, not a chore.
|
||||
- `topic` — set a topic marker
|
||||
- `watch` — SSE or tmux-based live stream
|
||||
|
||||
@@ -822,6 +877,21 @@ Current shipped behavior:
|
||||
|
||||
This is an evidence/context command. It is not a hidden second-LLM call.
|
||||
|
||||
### `rig auth` — agent auth-profile management (v0.4.1, product-native)
|
||||
|
||||
Product-native switching of agent auth profiles from the CLI. The runtime is a **flag** (`--runtime <codex>`), not a command noun — never `rig codex-auth`.
|
||||
|
||||
```bash
|
||||
rig auth status --runtime codex # presence / mode / parseability / login-state (never prints token contents)
|
||||
rig auth list --runtime codex # saved profiles
|
||||
rig auth save <profile> --runtime codex # snapshot the auth FILE (mode-guarded), never echoes contents
|
||||
rig auth switch <profile> --runtime codex
|
||||
rig auth validate <profile> --runtime codex
|
||||
rig auth seats … --runtime codex # seat -> profile registry (metadata only; NOT proof of a live account)
|
||||
```
|
||||
|
||||
**Hard secret boundary:** no token value is ever printed, logged, queued, streamed, or committed; status/validate report presence/mode/login-state only; seat labels are metadata, not live-account proof. MVP is `--runtime codex`; other runtimes use the same surface with a different `--runtime`, never a parallel command.
|
||||
|
||||
## Lifecycle
|
||||
|
||||
### Bring a rig up
|
||||
@@ -1010,7 +1080,7 @@ rig whoami --json
|
||||
|
||||
Notes:
|
||||
- for tmux-backed self-attach, `rig whoami --json` is the right verification
|
||||
- for raw/external self-attach, `rig ps --nodes --rig <rigId-or-name> --json` is currently the more reliable verification surface
|
||||
- for raw/external self-attach, `rig ps --nodes --json` is currently the more reliable verification surface
|
||||
- if the current shell is outside tmux, pass `--display-name <name>` when you want a stable human session label recorded
|
||||
|
||||
### Adopt a topology and bind live sessions
|
||||
@@ -1077,13 +1147,13 @@ Verification loop:
|
||||
```bash
|
||||
rig discover --json
|
||||
rig adopt <fragment.yaml> --bindings-file <bindings.yaml> --target-rig <rigId>
|
||||
rig ps --nodes --rig <target-rig-name> --json
|
||||
rig ps --nodes --json
|
||||
rig export <rigId> -o rig.yaml
|
||||
```
|
||||
|
||||
Success looks like:
|
||||
- the new sessions stop appearing in `rig discover`
|
||||
- the new logical IDs appear in `rig ps --nodes --rig <target-rig-name> --json`
|
||||
- the new logical IDs appear in `rig ps --nodes --json`
|
||||
- `rig export` includes the new pod
|
||||
|
||||
### Mixed-origin rigs are allowed
|
||||
@@ -1101,7 +1171,7 @@ Current safety rule:
|
||||
The proven operator pattern is:
|
||||
- keep one OpenRig manager session outside the rig it manages
|
||||
- address the target by rig name, not cached rig ID
|
||||
- resolve the current owner from fresh `rig ps --nodes -A --json`
|
||||
- resolve the current owner from fresh `rig ps --nodes --json`
|
||||
- send the manager the spec path, bindings path, and verification steps with `rig send`
|
||||
|
||||
This lets ordinary agents ask the manager for OpenRig help instead of every agent needing to be an OpenRig expert.
|
||||
@@ -1198,7 +1268,7 @@ When the CLI behaves strangely, use the smallest truthful check first:
|
||||
```bash
|
||||
rig whoami --json
|
||||
rig daemon status
|
||||
rig ps --nodes
|
||||
rig ps --nodes --json
|
||||
```
|
||||
|
||||
Specific operator rules:
|
||||
@@ -1234,7 +1304,7 @@ Design assumptions that hold in the shipped CLI:
|
||||
|
||||
1. `rig whoami --json`
|
||||
2. `rig transcript <your-session> --tail 100`
|
||||
3. `rig ps --nodes`
|
||||
3. `rig ps --nodes --json`
|
||||
4. `rig chatroom history <rig> --limit 50`
|
||||
|
||||
## Commands That Do Not Exist
|
||||
|
||||
@@ -2,14 +2,31 @@
|
||||
name: queue-handoff
|
||||
description: Use when ending a turn, finishing a slice, blocked on another agent's work, or escalating to a human — durable work handoff via queue items so the system keeps moving across compactions, missed messages, and interruptions. Covers the hot-potato terminal-turn-rule (active work ends by passing the ball, not by going idle), default-nudge semantics, and when `--no-nudge` is appropriate for intentional cold park or human gate.
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- queue
|
||||
- queue create
|
||||
- queue handoff
|
||||
- queue handoff-and-complete
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
last_verified: "2026-06-24"
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
Daemon-backed `rig queue` shipped in v0.2.0 (PL-004 Phase A) with handed-off-to / handed-off-from / state field shape. `rig queue` is canonical for new work; `rigx queue` is recovery-only fallback. The daemon enforces hot-potato strict-rejection at the API. Body resynced from canonical 2026-06-24 (demo-blocker fix: corrected the default-nudge guidance — the default already nudges; the previously-described extra notify flag does not exist on the shipped CLI).
|
||||
sibling_skills: []
|
||||
transfer_test: pending
|
||||
sibling_skills:
|
||||
- workflow-runtime
|
||||
- watchdog
|
||||
- alignment-trace
|
||||
- looping-workflows
|
||||
- intake-routing
|
||||
- human-in-the-loop
|
||||
- attention-queue
|
||||
- dispatching-parallel-agents
|
||||
- subagent-driven-development
|
||||
- structured-ack-dispatch
|
||||
- control-plane-capabilities
|
||||
- status-not-chat-orchestrator
|
||||
- control-plane-queue
|
||||
- control-plane-watchdog
|
||||
- control-plane-workflows
|
||||
- control-plane-delivery-loop
|
||||
- control-plane-rollout-manager
|
||||
---
|
||||
|
||||
# Queue Handoff
|
||||
@@ -67,7 +84,7 @@ every surface (CLI, MCP, future UI) inherits the same guarantee.
|
||||
| `rig queue create` | yes | New qitem created from scratch |
|
||||
| `rig queue handoff` | yes | Transactional close-as-handed-off + create-new |
|
||||
| `rig queue handoff-and-complete` | yes | Atomic close + create-new; default nudge wakes the new owner |
|
||||
| `rigx queue handoff` (filesystem v0 prototype; **recovery-only fallback since 2026-05-11**) | yes | Legacy artifact; qitems invisible to daemon-backed reads; deprecated with removal queued. Use `rig queue handoff` (daemon-backed) for all new substantive work. |
|
||||
| `rigx queue handoff` (filesystem v0 prototype; **recovery-only fallback since 2026-05-11**) | yes | Legacy artifact; qitems invisible to daemon-backed reads; deprecation warning + removal queued at `missions/bug-fix/slices/rigx-queue-deprecation-message/`. Use `rig queue handoff` (daemon-backed) for all new substantive work. |
|
||||
|
||||
**Footgun**: `--no-nudge` accidentally added to a live-loop handoff.
|
||||
The shipped 0.3.1 CLI nudges by default on every queue write surface
|
||||
@@ -96,8 +113,8 @@ recipient.
|
||||
at the file for the detail. A pasted dump makes `rig queue show <id>
|
||||
--json` huge — a second-order token bloat: bloated DATA living in the
|
||||
queue, distinct from the command-default output bombs the token-burn
|
||||
emergency pack covers. (Sensor: dev1-guard token-burn-flag 8ea201e4,
|
||||
2026-06; founder-directed cure.)
|
||||
emergency pack covers. (Sensor: guard token-burn-flag 8ea201e4,
|
||||
2026-06; operator-directed cure.)
|
||||
- **Substantive bodies go through `--body-file`, not inline `--body`.**
|
||||
For anything beyond a short line, write the body to a file and pass
|
||||
`--body-file <path>` (or `-` for stdin). Inline `--body` with shell
|
||||
|
||||
+11
-9
@@ -4,16 +4,17 @@ description: Use when replacing a seat's occupant (rebuild/handover/swap), reaso
|
||||
metadata:
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
last_verified: "2026-05-04"
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
Option A rebuild MVP shipped 2026-04-30. Option B (full code-direct
|
||||
seat handover via SeatHandoverService daemon module) is a future
|
||||
follow-on.
|
||||
sibling_skills:
|
||||
- claude-compaction-restore
|
||||
- mental-model-ha
|
||||
- scope-recovery
|
||||
- session-compaction-and-restore
|
||||
- agent-startup-and-context-ingestion
|
||||
transfer_test: pending
|
||||
- agent-starters
|
||||
- composable-priming-packs
|
||||
- session-source-fork
|
||||
- claude-compact-in-place
|
||||
- pre-maintenance-agent-preservation
|
||||
---
|
||||
|
||||
# Seat Continuity and Handover
|
||||
@@ -133,5 +134,6 @@ enough to receive new work or needs re-handover.
|
||||
|
||||
## See also
|
||||
|
||||
- `claude-compaction-restore` skill — packet-driven restore after Claude compaction
|
||||
- `agent-startup-and-context-ingestion` skill — ingestion path for restore packets at agent boot
|
||||
- `session-source-fork` skill — `fork` occupant-creation primitive (sibling)
|
||||
- `agent-starters` skill — composes occupant-creation + binding into named reusable starting points
|
||||
- `cross-host-rig-commands` skill — multi-host handover (deferred)
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
---
|
||||
name: session-compaction-and-restore
|
||||
description: Use when reasoning about what survives compaction/context-loss/restart/seat-refresh, designing a high-fidelity restore packet, or distinguishing native runtime resume vs fork vs artifact-backed mental-model rebuild. Covers the 4 failure modes that prevent honest restore (compacted seat drops hot potato; restore packet preserves details but loses product intent; runtime resume mistaken for handover or fork; rebuilt seat starts with stale instructions).
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- whoami
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- claude-compaction-restore
|
||||
- mental-model-ha
|
||||
- scope-recovery
|
||||
- agent-startup-and-context-ingestion
|
||||
- agent-starters
|
||||
- composable-priming-packs
|
||||
- session-source-fork
|
||||
- seat-continuity-and-handover
|
||||
- claude-compact-in-place
|
||||
- pre-maintenance-agent-preservation
|
||||
---
|
||||
|
||||
# Session Compaction and Restore
|
||||
|
||||
Preserving useful working state across **compaction, context loss,
|
||||
restart, or seat refresh.** Includes Claude compaction restore, Codex
|
||||
resume/fork mechanics, transcript-based mental-model rebuilds, and
|
||||
durable handoff packets.
|
||||
|
||||
**Long-lived seats are valuable only if they can survive context
|
||||
pressure.** If compaction turns a senior seat into a cold-started
|
||||
agent, users will avoid persistent topologies and fall back to
|
||||
throwaway agents.
|
||||
|
||||
## Use this when
|
||||
|
||||
- A seat is approaching compaction or just compacted
|
||||
- Designing a high-fidelity restore packet for an active workflow
|
||||
- Distinguishing native runtime resume vs fork vs artifact-backed mental-model rebuild
|
||||
- Reasoning about what should be preserved vs reconstructable
|
||||
- Auditing a restore for product-intent preservation (not just detail preservation)
|
||||
|
||||
## Don't use this when
|
||||
|
||||
- The session is fresh and has no working state to preserve
|
||||
- The intent is to *create* a new seat from a primed source — that's `session-source-fork` or `agent-starters`
|
||||
- The packet is a one-off snapshot for human review — restore packets are for re-entering active work
|
||||
|
||||
## The 5 distinctions (do not collapse)
|
||||
|
||||
Per the cross-runtime restore/reentry packet standard:
|
||||
|
||||
| Mode | What it means | Outcome literal |
|
||||
|---|---|---|
|
||||
| **Native resume** | Continue the same managed seat with native runtime token | `resumed` |
|
||||
| **Fork** | New managed seat from prior native runtime conversation; new post-fork token | `forked` |
|
||||
| **Rebuild** | Fresh-launch seeded with operator-declared artifacts in trust-precedence order | `rebuilt` |
|
||||
| **Artifact-backed mental-model rebuild** | Restored seat derives understanding from a packet rather than native runtime continuity | (case of `rebuilt`) |
|
||||
| **Fresh launch** | New agent without prior continuity | `fresh` |
|
||||
|
||||
These are load-bearing distinctions. **Do NOT collapse `fork` into
|
||||
artifact-backed reentry; do NOT collapse `rebuild` into fork.**
|
||||
|
||||
## The three mechanisms — who owns each (verified vs main d37a08ad, 2026-07-21)
|
||||
|
||||
The outcomes above ride on three DISTINCT mechanisms; keep them separate:
|
||||
|
||||
1. **Claude built-in `/compact`** — a Claude Code HARNESS feature, **not OpenRig
|
||||
code**. OpenRig only *emits* the literal `/compact` toward the pane after a prep
|
||||
turn; there is no compaction algorithm in the OpenRig repo. Provider-owned.
|
||||
2. **OpenRig-managed restore** — the enforcer + hook bridge: a precompact hook
|
||||
WRITES a restore packet; a bridge READER injects exactly ONE restore directive
|
||||
back via the harness hook channel (`hookSpecificOutput.additionalContext`),
|
||||
seat-isolated. The OpenRig-owned half.
|
||||
3. **Codex session continuity** — resume/rollout tokens (`codex resume <token>`),
|
||||
a separate path from the Claude mechanisms. Never conflate with Claude restore.
|
||||
|
||||
**Safety boundary (ties to `native-session-file-lab-boundary`):** no supported
|
||||
OpenRig path EDITS provider-owned native **session / auth / transcript** files to
|
||||
inject context. Context enters ONLY through sanctioned channels: the hook
|
||||
`additionalContext`, a normal user message via `rig send`, or Codex resume tokens.
|
||||
Precise nuance: OpenRig *does* write `~/.codex/config.toml` — but only to install
|
||||
OpenRig activity **hooks** and `[features]`, never session or auth state. So the
|
||||
rule is "never edits native session/auth/transcript files," NOT "never touches any
|
||||
provider-owned file."
|
||||
|
||||
## Current CLI surface (operator / kernel seats; verified vs main d37a08ad)
|
||||
|
||||
Managed compaction/restore is driven by five shipped verbs — pick per intent, and
|
||||
stay durable-substrate-first (the packet/artifacts are the truth; the CLI is the trigger):
|
||||
|
||||
- **`rig compact <session>`** — guided managed compaction for ONE Claude seat
|
||||
(prep → `/compact` → restore → audit). Non-Claude seats rejected. ~180s.
|
||||
- **`rig compact-plan`** — READ-ONLY triage; *does not compact*. Flags `--rig`,
|
||||
`--refresh`, `--threshold-tokens`, `--threshold-percent`. (Codex seats flagged
|
||||
`codex_not_managed_by_claude_compact_in_place`.)
|
||||
- **`rig restore-check`** — restore-readiness probe across running rigs; read-only;
|
||||
exit 0/1/2. Flags `--full`, `--ready`, `--rig`, `--no-queue`, `--no-hooks`.
|
||||
- **`rig restore-packet {write,read,validate}`** — the cross-runtime restore
|
||||
packet (v0): write / read / validate the durable packet this skill's contract defines.
|
||||
- **`rig restore <snapshotId> --rig <rigId>`** — ⚠ RIG SNAPSHOT restore (infra), a
|
||||
DIFFERENT mechanism — NOT session-context restore. Do not conflate.
|
||||
|
||||
## Failure modes (4)
|
||||
|
||||
1. **A compacted seat forgets active workflow state and drops the hot potato.** Compaction without continuity preservation is silent failure.
|
||||
2. **A restore packet preserves details but loses the user's product intent.** Restore must preserve *why this work matters*, not just *what was happening*.
|
||||
3. **A runtime resume is mistaken for a seat handover or fork.** These have different continuity outcomes and provenance — don't conflate.
|
||||
4. **A rebuilt seat starts with stale instructions that conflict with current workflow mode.** Restore must include current state, not just historical state.
|
||||
|
||||
## Proof standard
|
||||
|
||||
Proof should include a deliberate compaction/restart of a seat with
|
||||
active work, followed by **measured recovery**: identity, current
|
||||
workflow, next owner, relevant files, and constraints all restored
|
||||
without human re-briefing.
|
||||
|
||||
## Canonical packet contract (16-field, v0)
|
||||
|
||||
The cross-runtime restore/reentry packet standard v0 defines:
|
||||
|
||||
- Source/target identity
|
||||
- Runtimes
|
||||
- Workspace root, default repo, role pointer
|
||||
- Bounded latest transcript
|
||||
- Touched-path inventory
|
||||
- Durable work pointers
|
||||
- Current work + next owner
|
||||
- Caveats + authority boundaries
|
||||
- Omitted classes + redaction policy
|
||||
- Source-trust ranking
|
||||
- Generated-at + generator version
|
||||
|
||||
Plus a 6-item restored-seat acceptance checklist.
|
||||
|
||||
Source-trust ranking applies when restored seat ingests packet evidence:
|
||||
**`rig whoami` > target rigspec > bounded latest transcript > full
|
||||
transcript > touched-files > `restore-summary.json`.**
|
||||
|
||||
## Memory surfaces consumed at restore time
|
||||
|
||||
This primitive consumes multiple externalized memory surfaces. Per the
|
||||
externalized-memory-surfaces convention's 13-row first inventory pass,
|
||||
the primary rows for restore are:
|
||||
|
||||
| Row | Surface |
|
||||
|---|---|
|
||||
| 1 | Transcripts |
|
||||
| 2 | Durable chat |
|
||||
| 3 | Startup replay context |
|
||||
| 5 | Checkpoints |
|
||||
| 12 | Restore/reentry packets and Agent Starters |
|
||||
|
||||
The umbrella's authority-rank + permission-posture columns govern which
|
||||
surfaces a restore path can write vs only read.
|
||||
|
||||
## See also
|
||||
|
||||
- `claude-compaction-restore` skill — the Claude Code restore SOP (PreCompact hook + JSONL restore script for post-compaction recovery)
|
||||
- `mental-model-ha` skill — HA-pair compaction recovery (different scenario; sister primitive)
|
||||
- `session-source-fork` skill — `fork` mode for native-runtime-continuity-based restoration
|
||||
- `seat-continuity-and-handover` skill — occupant-creation primitives (resume/fork/rebuild/fresh) that this primitive instantiates
|
||||
- `externalized-memory-surfaces` skill — umbrella convention listing all surfaces this primitive consumes
|
||||
@@ -0,0 +1,165 @@
|
||||
---
|
||||
name: software-for-agents
|
||||
description: |
|
||||
Load this FIRST, before you assume how anything here works — especially before building, modifying, or
|
||||
"fixing a bug" in an OpenRig or studio-box system, or when something behaves unexpectedly and you're
|
||||
about to treat it as a code bug. You are almost certainly NOT operating in traditional software. This
|
||||
is a self-improving MARKDOWN CONTROL PLANE: the substrate is markdown + YAML + JSON + folder structure
|
||||
(skills, instructions, bootstrap files, schemas, conventions), and most "bugs" are coherence gaps in
|
||||
that layer, not broken functions. Read this to form the correct mental model so your fixes land at the
|
||||
precise spot that stops the footgun for every future rig — not just patch a symptom. NOTE: the
|
||||
bug-tolerance in this model is SCOPED to agent-managed software; the OpenRig core and rigs.to stay
|
||||
rock-solid — see the scope block up top before you apply anything here.
|
||||
metadata:
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
audience: any agent building on OpenRig or a studio box — the first-load mental model
|
||||
sibling_skills:
|
||||
- forming-an-openrig-mental-model
|
||||
- openrig-program-manager
|
||||
- mission-slice-sop
|
||||
- openrig-user
|
||||
---
|
||||
|
||||
# Software for agents — the markdown control plane
|
||||
|
||||
## Where this applies — and where it does NOT (read this first)
|
||||
|
||||
This mental model — *most bugs are coherence gaps, not code*; *ship-and-flag when unsure*; iterate fast —
|
||||
is scoped to **agent-managed software: the studio-box mini-apps and any agent-in-the-middle / rapidly-
|
||||
evolving lightweight UI** where an agent sits in the loop and downstream cleanup is cheap. It is NOT a
|
||||
universal license.
|
||||
|
||||
**It does NOT apply to TRADITIONAL software held to a rock-solid, no-bugs bar:** the **OpenRig CLI
|
||||
surfaces**, the **OpenRig repo** (daemon / CLI / UI / adapters), and the **rigs.to website**. There, a bug
|
||||
is a bug — reproduce it, fix it in code, hold the full-rigor gate. Do NOT treat a real defect there as a
|
||||
markdown coherence gap, and do NOT "ship and flag." If you are building or fixing OpenRig core or rigs.to,
|
||||
the tolerance in this skill is OFF and `product-is-the-truth-not-the-proof` governs. **Know which lane
|
||||
you're in before you apply anything below.**
|
||||
|
||||
---
|
||||
|
||||
You inherited the accumulated footgun-map of thousands of rigs that ran before you. They found and
|
||||
solved most of the traps. Your job is to find the *next* one and patch it at the precise optimal spot
|
||||
in the substrate, so the rig after you starts from a higher ledge. That is the actual work. Whatever
|
||||
you were "assigned" (a video, a feature, a fix) is the vehicle for surfacing it.
|
||||
|
||||
## 1. This is not traditional software — it's a control plane made of markdown
|
||||
|
||||
In traditional software a bug is a broken function you fix in code. Here, the system you operate in is
|
||||
an **agent-in-the-middle** system whose substrate is **markdown + YAML + JSON + folders**: skills,
|
||||
instructions, bootstrap files (`CLAUDE.md`/`AGENTS.md`), schemas, `culture.md`, mission/slice notes,
|
||||
conventions. **The agents ARE the backend.** So most "bugs" are not broken code — they are **coherence
|
||||
failures in the markdown layer**: an instruction that's unclear or missing, a schema that drifted from
|
||||
its documented state, a convention living in one seat's head instead of a skill.
|
||||
|
||||
**Consequence:** when something surprises you, your first hypothesis is *"the control plane is unclear
|
||||
or drifted here,"* not *"the code is broken."* Sometimes it IS the code (fix it — don't overfit on
|
||||
markdown; see §5, and mind the scope block above: in OpenRig core / rigs.to the code IS the first
|
||||
hypothesis). But the highest-leverage fixes in the agent-managed layer are usually: make the substrate
|
||||
coherent again at the exact spot the confusion arose. Keep the markdown/schemas/conventions in sync with
|
||||
reality and the system **self-improves** — the next rig inherits the patched substrate and never re-hits it.
|
||||
|
||||
## 2. Progressive disclosure — skills are a hot tier, not a manual
|
||||
|
||||
Skills are misnamed. They are a **progressive-disclosure primitive**. Think CPU cache / hot storage
|
||||
tier: the **name + description of every skill is always ambiently loaded** — a hot tier of awareness
|
||||
the agent carries without opening anything. That is enormous leverage, good or bad. So:
|
||||
|
||||
- **Write skill name + description as TRIGGERS** — *why/when do you reach for this?* — not as titles.
|
||||
The hot tier's whole job is to fire when an agent doesn't yet know it needs the skill (the
|
||||
"you don't know what you don't know" problem). This skill's own description is written that way.
|
||||
- **Reaching for a skill unfurls a trail.** A good skill routes you — breadcrumbs, pointers, maps —
|
||||
so it becomes *inevitable* you find the exact context on disk for what you're doing.
|
||||
- **If the context doesn't exist, generate it.** A skill can ship **scripts** that produce context
|
||||
optimally shaped for a decision, or that execute a fiddly API surface so you don't stumble through 12
|
||||
tool calls discovering it. Use a **script as a prompt**: run it — if it works, the result IS your
|
||||
context; if it fails, it should fail in a way that *teaches* you how the system works, so you can
|
||||
read the script, understand the edge case, and do the thing manually. Scripts belong in the skill
|
||||
folder next to the SKILL.md.
|
||||
|
||||
## 2b. Self-certifying artifacts — the convention 5 seats (both models) converged on
|
||||
|
||||
The single most expensive failure class in production is **not being able to tell a finished artifact
|
||||
from an unfinished one.** A mid-write file read as final; a render OOM-killed mid-write left a corrupt
|
||||
`.mp4` that passed a filename check; a truncated clip passed a duration check and froze on playback. In
|
||||
one build, five seats — Claude *and* Codex, independently — each invented a *different* ad-hoc
|
||||
completeness check (ffprobe moov, duration compare, filename convention, manifest assetExists, ffmpeg
|
||||
input count). Five blind spots. So make it ONE shared primitive:
|
||||
|
||||
**When you author ANY tool that produces an artifact (render / composite / export / cut), it must
|
||||
self-certify:**
|
||||
1. Write to `<name>.partial` (never the final path directly).
|
||||
2. **Verify the content** — the specific property that can be wrong, not a proxy: moov atom present,
|
||||
duration matches the intended window, audio stream present, colorspace/hue correct, resolution =
|
||||
delivery res. (Filename ≠ correct; duration ≠ complete; "clean-encoded" ≠ right.)
|
||||
3. **`fsync`, then atomically `rename`** `<name>.partial` → `<name>` (rename is atomic; a half-written
|
||||
file never appears at the real path).
|
||||
4. Write the manifest, then a **`.done` sentinel LAST.**
|
||||
|
||||
Then *"is this finished?"* is **one `stat` of `<name>.done`** — identical for every tool, seat, watcher,
|
||||
and a compacted agent restoring cold (who is least equipped to know what was mid-write when the lights
|
||||
went out). **Consumers fail closed:** e.g. a swap-into-slot (`restore_occupant`) must refuse an artifact
|
||||
lacking `.done` or failing the verify-gate. This convention collapses the whole "content over filename,
|
||||
disk over memory" discipline into one check the substrate enforces for you. Build the sentinel; the
|
||||
workarounds disappear. (Code-side companion: a fail-closed verify-gate wired into the swap verb — a
|
||||
coordinated build with the tool owner, not a solo markdown edit.)
|
||||
|
||||
## 3. Build it like software — piggyback on what agents are trained for
|
||||
|
||||
Agents are fine-tuned to write code and build software; the harness itself is a terminal/coding
|
||||
instrument. So **whatever you're asked to build — even a video — map the process to a software SDLC**
|
||||
and you inherit all that baked-in muscle memory. This is why, e.g., the mini-NLE's beats carry
|
||||
reference IDs like `1.1 / 2.1`: a storyboard is the **human-facing visual metaphor**, but underneath it
|
||||
is a **specification** — sections, beats, success criteria, the thing being built.
|
||||
|
||||
Use an **agent SDLC**, not the antiquated human one (which was shaped around human-org weaknesses):
|
||||
**intent → plan → spec → build → verify → review → QA → done.** The human slots in as **steering,
|
||||
judgment, taste, review**; the agents do the technical nitty-gritty, in parallel, fast. Map any
|
||||
"build X with agents" task onto this and the primitives (specs, locks, proof, verification) become
|
||||
intuitive instead of alien.
|
||||
|
||||
## 4. Phases and the LOCK gate (spec-locking, not just "done")
|
||||
|
||||
Building runs in **phases**, and each phase has a **lock gate** — you don't advance until the taste/
|
||||
steering owner has locked it. This is exactly *don't start building until the PRD is locked by product*:
|
||||
|
||||
- **Storyboard / intent phase** — done on the **canvas** now (the highest-bandwidth human↔agent surface:
|
||||
the human steers, chats, annotates/circles; agents build structure fast). Iterate here; get the
|
||||
storyboard through the canvas gate. (Canvas largely replaced the NLE's old in-timeline storyboard.)
|
||||
- **Plan phase (brief, in the NLE)** — build the spine with placeholders so the human can click through
|
||||
the main-stage player and *feel the flow* (sequencing problems surface when placeholders are strung
|
||||
together with audio). **Lock every beat** = the spec is approved; this is what unlocks parallel build.
|
||||
- **Fill phase** — many agents build each beat in parallel, in clear lanes. **Lock a beat when it's
|
||||
final** (`/api/approve`): lock means *don't touch, we're good, signal to everyone incl. the human.*
|
||||
Unlock to revise. **All beats locked = done.**
|
||||
|
||||
The lock is the "finished" primitive at the editorial layer. Locking a whole phase's beats before the
|
||||
next phase is the discipline that lets 10 agents work in parallel without catastrophic collisions —
|
||||
everyone knows the target, their lane, and who judges done (the **producer owns the final product**).
|
||||
|
||||
## 5. Where to fix — and don't overfit on markdown
|
||||
|
||||
- **Precise-spot discipline:** find the *one* place a coherence fix belongs (the skill, the schema, the
|
||||
bootstrap, `culture.md`) so it can't recur — not a symptom patch. Ask: *what would have prevented
|
||||
this for every future rig?*
|
||||
- **Don't overfit on the markdown layer** — deterministic code bugs exist and you should fix them. The
|
||||
studio-box apps (NLE, canvas, media manager, shell) live in the **studio-box repo**, portable across
|
||||
hosts (VPS/Mac/VM). **A code fix there fixes ALL studio boxes, not just this host** — so: clear bug or
|
||||
broadly-useful feature → ship it; host-specific behavior → make it optional/guarded. When unsure, ship
|
||||
and flag it; downstream cleanup beats you becoming the bottleneck. *(This ship-and-flag latitude is the
|
||||
studio-box / agent-managed lane only — re-read the scope block: OpenRig core + rigs.to hold the
|
||||
rock-solid bar, no ship-and-flag.)*
|
||||
- **Culture lives in `culture.md`** — the rig's social contract / constitution: how the team
|
||||
coordinates, the parallel-agent lanes, the phase-locking discipline, who owns the final call.
|
||||
Coordination is largely **emergent** (bottom-up, evolutionary pressure across thousands of rigs) — but
|
||||
once a pattern proves out, *write it down there* so it's inherited, not re-discovered.
|
||||
|
||||
## The one-line seed
|
||||
You're not maintaining code; you're **gardening a self-improving control plane made of markdown and
|
||||
schemas, using software-engineering muscle memory, with the lock as your spec-gate** — and every
|
||||
footgun you patch at the right spot (in the agent-managed lane) makes every future rig better. See also:
|
||||
`forming-an-openrig-mental-model` (the OpenRig runtime), `mission-slice-sop` (the SDLC operating
|
||||
procedure), `openrig-user` (the CLI surface), `product-is-the-truth-not-the-proof` (the doctrine that
|
||||
governs the rock-solid lane). *(The "agents ARE the backend" idea — agent-in-the-middle — is inlined in
|
||||
§1; a standalone `agent-in-the-middle` skill is a future candidate, not yet authored.)*
|
||||
@@ -97,8 +97,18 @@ export async function extractSkillEdgeLayout({
|
||||
config.forward_overrides ?? {},
|
||||
).sort()) {
|
||||
validateOverride(skill, override, config.edges, sourcePath);
|
||||
if (override.edges.length === 0) {
|
||||
skills.delete(skill);
|
||||
continue;
|
||||
}
|
||||
const edges = new Set(override.edges);
|
||||
if (edges.has("spec")) {
|
||||
for (const [edge, edgeConfig] of Object.entries(config.edges)) {
|
||||
if (edgeConfig.layout === "mirror-of-spec") edges.add(edge);
|
||||
}
|
||||
}
|
||||
skills.set(skill, {
|
||||
edges: [...new Set(override.edges)].sort(),
|
||||
edges: [...edges].sort(),
|
||||
category: override.category ?? null,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -11,9 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [using-superpowers, openrig-user, systematic-debugging, verification-before-completion, vault-user]
|
||||
skills: [using-superpowers, systematic-debugging, verification-before-completion, vault-user]
|
||||
guidance: []
|
||||
subagents: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -11,9 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [openrig-user, mission-slice-sop, development-team, test-driven-development, systematic-debugging, executing-plans, verification-before-completion]
|
||||
skills: [development-team, test-driven-development, systematic-debugging, executing-plans, verification-before-completion]
|
||||
guidance: []
|
||||
subagents: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -11,9 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [openrig-user, mission-slice-sop, orchestration-team, backlog-capture, writing-plans, executing-plans, verification-before-completion, brainstorming]
|
||||
skills: [orchestration-team, backlog-capture, writing-plans, executing-plans, verification-before-completion, brainstorming]
|
||||
guidance: []
|
||||
subagents: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -11,9 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [openrig-user, mission-slice-sop, requirements-writer, context-builder, writing-plans, verification-before-completion]
|
||||
skills: [requirements-writer, context-builder, writing-plans, verification-before-completion]
|
||||
guidance: []
|
||||
subagents: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -11,9 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [openrig-user, mission-slice-sop, review-team, plan-review, systematic-debugging, verification-before-completion]
|
||||
skills: [review-team, plan-review, systematic-debugging, verification-before-completion]
|
||||
guidance: []
|
||||
subagents: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -11,9 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [using-superpowers, openrig-user, mission-slice-sop, development-team, frontend-design, verification-before-completion, writing-plans, brainstorming]
|
||||
skills: [using-superpowers, development-team, frontend-design, verification-before-completion, writing-plans, brainstorming]
|
||||
guidance: []
|
||||
subagents: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -11,9 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [using-superpowers, openrig-user, mission-slice-sop, development-team, test-driven-development, systematic-debugging, verification-before-completion, writing-plans, executing-plans]
|
||||
skills: [using-superpowers, development-team, test-driven-development, systematic-debugging, verification-before-completion, writing-plans, executing-plans]
|
||||
guidance: []
|
||||
subagents: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -11,9 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [using-superpowers, test-driven-development, openrig-user, mission-slice-sop, development-team, systematic-debugging, verification-before-completion, agent-browser, dogfood, writing-plans, executing-plans]
|
||||
skills: [using-superpowers, test-driven-development, development-team, systematic-debugging, verification-before-completion, agent-browser, dogfood, writing-plans, executing-plans]
|
||||
guidance: []
|
||||
subagents: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -11,9 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [using-superpowers, openrig-user, mission-slice-sop, dogfood, systematic-debugging, verification-before-completion]
|
||||
skills: [using-superpowers, dogfood, systematic-debugging, verification-before-completion]
|
||||
guidance: []
|
||||
subagents: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -11,9 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [using-superpowers, openrig-user, mission-slice-sop, verification-before-completion]
|
||||
skills: [using-superpowers, verification-before-completion]
|
||||
guidance: []
|
||||
subagents: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -11,9 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [using-superpowers, openrig-user, mission-slice-sop, orchestration-team, systematic-debugging, verification-before-completion, writing-plans, executing-plans, brainstorming]
|
||||
skills: [using-superpowers, orchestration-team, systematic-debugging, verification-before-completion, writing-plans, executing-plans, brainstorming]
|
||||
guidance: []
|
||||
subagents: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -15,8 +15,6 @@ profiles:
|
||||
default:
|
||||
uses:
|
||||
skills:
|
||||
- openrig-user
|
||||
- mission-slice-sop
|
||||
- office-hours
|
||||
- context-builder
|
||||
- requirements-writer
|
||||
@@ -24,6 +22,7 @@ profiles:
|
||||
- plan-review
|
||||
- exec-summary
|
||||
- backlog-capture
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources:
|
||||
- shared:claude-default-settings
|
||||
- shared:claude-default-mcp
|
||||
|
||||
@@ -11,9 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [openrig-user]
|
||||
skills: []
|
||||
guidance: []
|
||||
subagents: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -11,9 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [openrig-user]
|
||||
skills: []
|
||||
guidance: []
|
||||
subagents: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -11,9 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [using-superpowers, openrig-user, mission-slice-sop, review-team, systematic-debugging, verification-before-completion, writing-plans, brainstorming]
|
||||
skills: [using-superpowers, review-team, systematic-debugging, verification-before-completion, writing-plans, brainstorming]
|
||||
guidance: []
|
||||
subagents: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -16,18 +16,10 @@ resources:
|
||||
path: skills/process/frontend-design
|
||||
- id: using-superpowers
|
||||
path: skills/process/using-superpowers
|
||||
- id: openrig-user
|
||||
path: skills/core/openrig-user
|
||||
- id: openrig-operator
|
||||
path: skills/core/openrig-operator
|
||||
- id: openrig-installer
|
||||
path: skills/core/openrig-installer
|
||||
- id: openrig-architect
|
||||
path: skills/core/openrig-architect
|
||||
- id: rig-lifecycle
|
||||
path: skills/core/rig-lifecycle
|
||||
- id: mission-slice-sop
|
||||
path: skills/core/mission-slice-sop
|
||||
- id: systematic-debugging
|
||||
path: skills/process/systematic-debugging
|
||||
- id: test-driven-development
|
||||
@@ -57,6 +49,11 @@ resources:
|
||||
path: skills/pm/exec-summary
|
||||
- id: backlog-capture
|
||||
path: skills/pm/backlog-capture
|
||||
plugins:
|
||||
- id: openrig-core
|
||||
source:
|
||||
kind: local
|
||||
path: ~/.openrig/plugins/openrig-core
|
||||
runtime_resources:
|
||||
- id: claude-default-settings
|
||||
path: runtime/claude-settings.fragment.json
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
---
|
||||
name: agent-starters
|
||||
description: Use when creating, refreshing, packaging, inspecting, promoting, or deprecating a named per-seat starting point — Agent Starter manifest authoring, the 6-state lifecycle (captured → named → inspectable → used → promoted → deprecated), provenance honesty, and refusal rules. NOT a VM image; a managed starting point composed from agent role + startup context + optional native session source + provenance.
|
||||
metadata:
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- claude-compaction-restore
|
||||
- mental-model-ha
|
||||
- scope-recovery
|
||||
- session-compaction-and-restore
|
||||
- agent-startup-and-context-ingestion
|
||||
- composable-priming-packs
|
||||
- session-source-fork
|
||||
- seat-continuity-and-handover
|
||||
- claude-compact-in-place
|
||||
- pre-maintenance-agent-preservation
|
||||
---
|
||||
|
||||
# Agent Starters
|
||||
|
||||
A named, reusable per-seat starting point. Composes an agent role, startup
|
||||
context, optional native session source, and provenance into something a
|
||||
user or rig can choose when creating, refreshing, or packaging a seat.
|
||||
|
||||
"Agent image" is the analogy. **Agent Starter is the cleaner product
|
||||
noun.** This is NOT a VM image — it is a managed starting point for an
|
||||
agent seat, with provenance you can inspect.
|
||||
|
||||
## Use this when
|
||||
|
||||
- Creating a new seat from a known-good starting context.
|
||||
- Refreshing a seat with `rig expand` and `starter_ref`.
|
||||
- Authoring a new starter (registry entry).
|
||||
- Inspecting an existing starter's provenance, freshness, or recommended status.
|
||||
- Promoting / deprecating starters in the registry.
|
||||
- Composing a starter with a Composable Priming Pack (record manifest id/version, runtime, source session id or transcript path, ready-check evidence, freshness state).
|
||||
|
||||
## Don't use this when
|
||||
|
||||
- You want VM-style deterministic state capture. Starters don't capture VM state.
|
||||
- You want to copy provider auth material into a starter. **Starters refer to session sources and context; they do NOT copy credentials.**
|
||||
|
||||
## What makes a starter valuable
|
||||
|
||||
A starter is valuable when it is **functional** — it carries the context the seat needs to do its task well. Functional is the *only* measure of a good starter. Size is not: a smaller starter is not a better one, and a bigger one is not worse. Whatever it took for the seat to become genuinely capable at its job is the right starter — 80K tokens or 800K.
|
||||
|
||||
Capture the seat as it naturally is at a functional, proven point. Don't pad it with context the seat doesn't use, and — just as important — don't strip context out to make it smaller. Size is an *outcome* of what the seat needed, never a target.
|
||||
|
||||
Never compact, summarize, or shrink a seat in order to make or "lean" a starter. There is nothing valuable in "smaller," and compaction is lossy — you would trade away the exact capability the starter exists to preserve. (Compaction is a separate last-resort step for a seat genuinely near its context limit, with its own before/after plan — never part of capturing a starter.)
|
||||
|
||||
## State model — 6 states
|
||||
|
||||
1. **Captured** — a useful seat/session/context pattern is identified.
|
||||
2. **Named** — it becomes an Agent Starter with stable id and owner.
|
||||
3. **Inspectable** — runtime, context inputs, session source, and provenance are visible.
|
||||
4. **Used** — a rig member or `rig expand` operation starts from it.
|
||||
5. **Promoted** — evidence shows it is recommended for a role or bundle.
|
||||
6. **Deprecated** — replaced, stale, unsafe, or incompatible.
|
||||
|
||||
## Failure modes (5)
|
||||
|
||||
1. **Overclaiming image semantics** — UI/docs imply deterministic VM-style state capture. Say "starter," name what's included, show provenance.
|
||||
2. **Hidden provenance** — users can't tell what session, context, or spec a starter came from. **Refuse promotion until provenance is inspectable.**
|
||||
3. **Stale starter** — points at outdated doctrine, missing files, or invalid native session source. **Inspect must report staleness honestly.**
|
||||
4. **Secret leakage** — starter packages or displays provider auth material. **Refuse.** Refer to session sources and context, never copy credentials.
|
||||
5. **Runtime mismatch** — starter used with unsupported runtime. **Refuse with a clear error.**
|
||||
|
||||
## Manifest shape (v0+v1 shipped)
|
||||
|
||||
```yaml
|
||||
agent_starters:
|
||||
- id: velocity-reviewer-v1
|
||||
runtime: claude-code
|
||||
agent_ref: local:reviewer
|
||||
context_refs:
|
||||
- doctrine:advisor-orchestrator-mode-judgment
|
||||
- convention:workstream-continuity
|
||||
session_source:
|
||||
mode: fork
|
||||
ref:
|
||||
kind: native_id
|
||||
value: "<prior-native-session-id>"
|
||||
```
|
||||
|
||||
Member usage:
|
||||
|
||||
```yaml
|
||||
members:
|
||||
- id: reviewer
|
||||
starter_ref:
|
||||
name: velocity-reviewer-v1
|
||||
```
|
||||
|
||||
When a starter points at a primed session produced from a Composable
|
||||
Priming Pack, record:
|
||||
- manifest id/version
|
||||
- runtime
|
||||
- source session id or transcript path
|
||||
- ready-check evidence
|
||||
- freshness state
|
||||
|
||||
## Proof matrix
|
||||
|
||||
| Surface | Test type | Authority |
|
||||
|---|---|---|
|
||||
| Registry schema accepts minimal starter | unit | daemon or config-layer prototype |
|
||||
| Inspect shows provenance and included context | unit / snapshot | daemon or CLI |
|
||||
| Member can use `starter_ref` | integration | daemon |
|
||||
| Unsupported runtime or stale source refuses honestly | unit + integration | daemon |
|
||||
| No secret material copied into starter artifact | grep / fixture | tester |
|
||||
| Bundle can include or reference starter | package inspection | bundle layer |
|
||||
|
||||
## Dependencies on other primitives
|
||||
|
||||
- **Firm**: `session-source-fork` — native conversation-source continuity for fork-based starters
|
||||
- **Firm**: `specification-system` — declarative starter and member references
|
||||
- **Soft**: `rig-bundles-and-shareable-artifacts` — shareable starter packaging
|
||||
- **Soft**: `context-engineering-and-retrieval` — richer declarative context assembly
|
||||
- **Soft**: `seat-continuity-and-handover` — refresh and swap workflows over starters
|
||||
|
||||
## Required-before-RSI
|
||||
|
||||
Agent Starters need queryable provenance and honest inspect output before
|
||||
RSI loops can rely on them for seat refresh. A workflow must be able to
|
||||
answer: "what starter did this seat use, what source session or context was
|
||||
included, and is that starter still recommended?"
|
||||
|
||||
## See also
|
||||
|
||||
- `session-source-fork` skill — low-level fork primitive that makes native session-based starters possible
|
||||
- `composable-priming-packs` skill — manifest-driven layer for producing primed sessions starters reference
|
||||
+28
-23
@@ -2,17 +2,22 @@
|
||||
name: agent-startup-and-context-ingestion
|
||||
description: Use when designing or auditing how an agent becomes useful after launch — AGENTS.md overlays, role files, skills, rig specs, workflow specs, startup checklists, refocus messages, "rig context" surface. Covers the 4 failure modes that make startup context fail (old rig spec misses current operating mode; current agents never told about new guidance; startup file as dumping ground; orchestrator transmits implementation without preserving product intent).
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- context
|
||||
- whoami
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
last_verified: "2026-05-04"
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
Cross-runtime restore/reentry packet standard + externalized memory
|
||||
surfaces convention. Load at agent start; revisit after compaction.
|
||||
sibling_skills:
|
||||
- claude-compaction-restore
|
||||
- mental-model-ha
|
||||
- scope-recovery
|
||||
- session-compaction-and-restore
|
||||
- agent-starters
|
||||
- composable-priming-packs
|
||||
- session-source-fork
|
||||
- seat-continuity-and-handover
|
||||
transfer_test: pending
|
||||
- claude-compact-in-place
|
||||
- pre-maintenance-agent-preservation
|
||||
---
|
||||
|
||||
# Agent Startup and Context Ingestion
|
||||
@@ -43,8 +48,8 @@ is scattered or stale, agents execute the wrong thing very efficiently.
|
||||
## Don't use this when
|
||||
|
||||
- The agent is being created via Agent Starter — the starter's manifest carries startup context
|
||||
- The work is artifact-backed mental-model rebuild from a packet — that's `claude-compaction-restore`
|
||||
- The intent is to ship reusable startup content as a skill — write the skill against the agentskills.io specification, not as inline startup prose
|
||||
- The work is artifact-backed mental-model rebuild from a packet — that's `session-compaction-and-restore`
|
||||
- The intent is to ship reusable startup content as a skill — that's `writing-skills-for-openrig`
|
||||
|
||||
## Failure modes (4)
|
||||
|
||||
@@ -67,22 +72,18 @@ When a seat's startup is artifact-backed mental-model rebuild (active-work
|
||||
reentry case, distinct from reusable Agent Starters / priming packs):
|
||||
|
||||
- See the **cross-runtime restore/reentry packet standard v0**
|
||||
- Source-trust ranking applies: **`rig whoami` > target rigspec > restore map /
|
||||
current `MISSION_NOTES.md` / owned queue items > touched files > transcript
|
||||
output**. Transcript output is secondary and may be unavailable or incomplete;
|
||||
little or no output does not prove the session was quiet.
|
||||
- Source-trust ranking applies: **`rig whoami` > target rigspec > bounded latest transcript > full transcript > touched-files > `restore-summary.json`**
|
||||
|
||||
## Memory surfaces consumed at startup
|
||||
|
||||
The primary surfaces a startup ingestion path reads:
|
||||
Per the externalized-memory-surfaces convention's 13-row inventory:
|
||||
|
||||
- AGENTS / role / CULTURE / startup overlays (the per-seat identity layer)
|
||||
- startup replay context (what the agent did before the current boot)
|
||||
- restore / reentry packets and Agent Starters (cross-runtime startup path)
|
||||
- **Row 7** — AGENTS/role/CULTURE/startup overlays (primary)
|
||||
- **Row 3** — startup replay context (primary)
|
||||
- **Row 12** — restore/reentry packets and Agent Starters (cross-runtime startup path)
|
||||
|
||||
Authority-rank + read-vs-write posture governs which surfaces a
|
||||
startup-ingestion path can write vs only read; treat overlays as
|
||||
write-restricted unless your role explicitly authors them.
|
||||
The umbrella's authority-rank + permission-posture columns govern which
|
||||
surfaces a startup ingestion path can write vs only read.
|
||||
|
||||
## Startup files vs skills (the distinction)
|
||||
|
||||
@@ -92,7 +93,7 @@ Per `agent-startup-guide.md` (product reference doc) and the team handbook:
|
||||
|---|---|
|
||||
| Rig-specific, role-specific identity | Reusable SOPs / methodology / knowledge |
|
||||
| Tell agent WHO it is, WHAT it's working on, HOW this team operates | Tell agent HOW to do something (transferable across rigs) |
|
||||
| Examples: `role.md`, `CULTURE.md`, `startup/context.md` | Examples: `openrig-user`, `test-driven-development`, `dogfood` |
|
||||
| Examples: `role.md`, `CULTURE.md`, `startup/context.md` | Examples: `openrig-user`, `test-driven-development`, `vault-user` |
|
||||
| Authored per-rig | Authored once, used everywhere |
|
||||
|
||||
Don't put skill content in startup files. Don't put identity content
|
||||
@@ -101,7 +102,11 @@ culture / pod / member / operator) handles the layering.
|
||||
|
||||
## See also
|
||||
|
||||
- `mission-slice-sop` skill — the universal operating procedure for working a mission/slice (the canonical PROGRESS/PROOF/MISSION_NOTES/MISSION_BRIEF files); every agent should reach for it at startup, so this general reading contract points at it here (do NOT duplicate the SOP into seat-specific startup files).
|
||||
- `writing-skills-for-openrig` skill — authoring discipline for skill content (what doesn't belong in startup)
|
||||
- `forming-an-openrig-mental-model` skill — orientation for new agents
|
||||
- `claude-compaction-restore` skill — restore-time startup ingestion after compaction
|
||||
- `seat-continuity-and-handover` skill — packet shape that survives seat resets
|
||||
- https://agentskills.io/specification — the cross-runtime skill standard (what skill content should and shouldn't be)
|
||||
- `session-compaction-and-restore` skill — restore-time startup ingestion
|
||||
- `agent-starters` skill — reusable starter manifests that compose startup context
|
||||
- `composable-priming-packs` skill — manifests that produce primed sessions
|
||||
- `externalized-memory-surfaces` skill — umbrella convention for memory surfaces this primitive consumes
|
||||
- `openrig/docs/reference/agent-startup-guide.md` (product reference doc; not a skill) — the 7-layer additive startup model + delivery hints
|
||||
@@ -0,0 +1,264 @@
|
||||
---
|
||||
name: attention-queue
|
||||
description: Coordination primitive for OpenRig. Per-agent queue files tracking in-flight work with explicit state transitions + handoff semantics + cross-agent composition. Prevents memory-loss drops; surfaces stalls mechanically; closes the feedback loop on handed-off work. Applied liberally by every agent on every kernel-supervised rig; composed views serve human attention, orch pod-load, rig pending-work.
|
||||
status: L4-insight
|
||||
authored-by: advisor-peer-observer@your-rig
|
||||
date: 2026-04-13
|
||||
cited-captures:
|
||||
- improvements-inbox.md 2026-04-13T12:54:50Z — broadcast primitive RSI (same batching-by-theme cluster)
|
||||
- Mission 4 cmux stall (2026-04-13 midday) — packet-design + queue-for-cross-rig coordination
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- chatroom
|
||||
- send
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- queue-handoff
|
||||
- workflow-runtime
|
||||
- watchdog
|
||||
- alignment-trace
|
||||
- looping-workflows
|
||||
- intake-routing
|
||||
- human-in-the-loop
|
||||
- dispatching-parallel-agents
|
||||
- subagent-driven-development
|
||||
- control-plane-capabilities
|
||||
- status-not-chat-orchestrator
|
||||
- control-plane-queue
|
||||
- control-plane-watchdog
|
||||
- control-plane-workflows
|
||||
- control-plane-delivery-loop
|
||||
- control-plane-rollout-manager
|
||||
---
|
||||
|
||||
# Attention queue
|
||||
|
||||
Use this skill when coordinating work that must survive compaction, cross-agent handoffs, or multi-hour stall detection. Applies when you'd otherwise narrate status to chat or rely on memory for pending items.
|
||||
|
||||
## Live protocol override
|
||||
|
||||
Current live routing protocol:
|
||||
|
||||
- **Known target / explicit owner that should wake now**: `rigx queue handoff <destination> "<body>" --type handoff --urgency soon`
|
||||
- **Passive durable assignment without wake-up**: `rigx queue create <destination> "<body>" --type handoff --urgency soon`
|
||||
- **Ambiguous or raw intake**: `rigx stream emit "<body>" ...`
|
||||
- **Direct dialogue / urgent 1:1 conversation**: `rig send ...`
|
||||
- **Summoned 3+ party roundtable**: `rig chatroom ...`
|
||||
|
||||
Do not cargo-cult the earlier "stream everything with `--destination`" prototype shape into the
|
||||
live control-plane. Stream is now the ambiguous-intake lane, not the universal lane.
|
||||
|
||||
## Core shape (minimum-viable discipline)
|
||||
|
||||
1. **Author a queue file at** `substrate/shared-docs/rigs/<your-rig>/state/<your-pod>/<your-member>.queue.md`. Same per-pod directory as your session log.
|
||||
2. **Every known-target hot-potato work handoff** should arrive via `rigx queue handoff`, not via `rig send`. Use `rigx queue create` only when you intentionally want a passive durable item without wake-up.
|
||||
3. **State transitions** (start → promote; finish → complete; stuck → block; hand off → handoff; completed handed-off work notifies source → handoff-complete) are appended to the entry body with timestamp. Never in-place rewrites.
|
||||
4. **Cross-rig reads permitted; cross-rig writes forbidden.** Pod-as-authority-boundary doctrine.
|
||||
|
||||
### Live command surface note
|
||||
|
||||
When the queue control-plane wrapper is installed, treat queue identity as command-resolved, not
|
||||
seat-name-guessed:
|
||||
|
||||
- `rigx queue whoami` resolves the durable queue that belongs to your current seat
|
||||
- `rigx queue list --mine` shows your queue without guessing from member name
|
||||
|
||||
This matters for continuity successors such as `lead2` or `lead5`, which may intentionally share
|
||||
the canonical `lead.queue.md` file instead of owning a separate `lead2.queue.md` or `lead5.queue.md`.
|
||||
|
||||
Known-target direct handoff on the live wrapper:
|
||||
|
||||
```bash
|
||||
rigx queue handoff orch-lead5@your-rig "Need PM shaping on queue attention loop" --type handoff --urgency soon
|
||||
```
|
||||
|
||||
Passive durable write without wake-up:
|
||||
|
||||
```bash
|
||||
rigx queue create orch-lead5@your-rig "Need PM shaping on queue attention loop" --type handoff --urgency soon
|
||||
```
|
||||
|
||||
## Six operations
|
||||
|
||||
| Op | Effect |
|
||||
|---|---|
|
||||
| append | New entry (state=pending) on inbound request |
|
||||
| promote | state=in-progress when you start work |
|
||||
| complete | state=done with optional result |
|
||||
| block | state=blocked + blocked-on=<id or condition> |
|
||||
| handoff | state=handed-off + handed-off-to=<target>/<new-id>; send rig-send with `[queue-handoff:]` prefix to target |
|
||||
| handoff-complete | target signals source that handed-off work finished (closes feedback loop) |
|
||||
| escalate | walk authority chain when blocked past tier threshold |
|
||||
| defer / drop | push-to-later or drop-with-rationale |
|
||||
|
||||
## When is something a queue handoff?
|
||||
|
||||
**Queue handoff** (`rigx queue handoff`):
|
||||
- Asks a known recipient to do new work
|
||||
- Transfers ownership of pending work
|
||||
- Names a deliverable + acceptance criteria
|
||||
|
||||
**NOT a queue handoff**:
|
||||
- Wake-ping `1`
|
||||
- PSA / broadcast / status update
|
||||
- Ack / courtesy notification / diagnostic ping / reply to question
|
||||
- Raw idea or bug where you do not yet know the right owner
|
||||
|
||||
If you do not know the correct owner, emit to stream instead of guessing.
|
||||
|
||||
## Tier-based ack + notification rules
|
||||
|
||||
- **human-gate tier** (gated items; human-watching): mandatory ack on handoff; mandatory notification on completion
|
||||
- **agent-coordination tier** (standard inter-agent work): recommended ack + notification
|
||||
- **internal-self tier** (your own to-dos): optional
|
||||
|
||||
## Read discipline
|
||||
|
||||
- Read your own queue at turn start before picking up new work
|
||||
- Orchestrators read pod-member queues on wake cadence (`1` ping)
|
||||
- Advisor-pod reads cross-rig queues for composed views + human-attention
|
||||
- Past-threshold blocked entries surface during sweeps; execute escalate op if you can't self-unblock
|
||||
|
||||
Recommended turn-start queue commands on the live wrapper:
|
||||
|
||||
```bash
|
||||
rigx queue whoami
|
||||
rigx queue list --mine
|
||||
```
|
||||
|
||||
### Resume-from-idle state sweep
|
||||
|
||||
Agents returning from idle-standby (supervisor-wake-only pings; no substantive dispatch during the window) MUST sweep adjacent state before pulling new work. Minimum sweep:
|
||||
|
||||
- Supervisor-log tail (~200 lines) at `rigs/kernel/state/supervisor-log.md`
|
||||
- human-attention.md at `substrate/shared-docs/human-attention.md`
|
||||
- Any doctrine-decisions added since last-active (`rigs/kernel/state/doctrine-decisions/`)
|
||||
- Partner queue files at `rigs/kernel/state/<pod>/<peer-member>.queue.md` (peer load-tracking for pairs)
|
||||
- **Fleet-changes-feed** at `substrate/shared-docs/fleet-changes-feed.md` (pull-native rollout surface; catches any fleet-wide doctrine / skill / convention / operational changes that landed during idle; filter by scope = fleet-wide + your rig/pod)
|
||||
|
||||
**Trigger:** first active turn after ≥3 consecutive wake-only cycles OR on peer HA-check request. Sweep before responding to HA-check so the response is grounded in current reality, not stale memory.
|
||||
|
||||
**Rationale:** own-queue-at-turn-start catches own-queue drift; adjacent-state drift is a separate failure class that requires its own read discipline. Composable with own-queue sweep (both at same reading point); adds ~2-5 minutes of read time; cheap insurance against peer-driven HA-check round-trips.
|
||||
|
||||
**Worked example (genesis):** advisor-co-observer@your-rig after ~2h idle-standing-by on 2026-04-13 — 5-of-7 HA-check items out-of-sync when peer queried. Rule addition would have caught the drift pre-query via adjacent sweep on wake-to-active transition.
|
||||
|
||||
## Status-not-chat corollary
|
||||
|
||||
Your chat pane is for operational work + ad-hoc human exchanges. Your STATUS lives in queue files + composed views. If you finish work + hit a gate-requiring next-action, do NOT narrate to chat + idle-wait. Queue-handoff to advisor-pod with `tier: human-gate`. The operator doesn't watch agent panes; they watch human-attention.md (composed from human-gate queue entries).
|
||||
|
||||
## Composed views (4 layers)
|
||||
|
||||
- **Pod-load view** — who's loaded / blocked (orch reads)
|
||||
- **Rig pending-work** — cross-pod roll-up
|
||||
- **Fleet cross-rig** — host-wide
|
||||
- **human-attention** — human-gate-tier items across all queues (advisor-pod composes)
|
||||
|
||||
v0: manual regen by orchestrators + advisor-pod.
|
||||
v0.5: terminal-node watch scripts auto-regen.
|
||||
v1: generative UI consuming structured queue data.
|
||||
|
||||
## Codex-sandbox proxy-write pattern (sanctioned workaround)
|
||||
|
||||
Codex members whose sandbox blocks substrate writes can still participate via proxy-write:
|
||||
- Codex authors content locally (e.g., `/tmp/<rig>-attention-queue/<member>.queue.md`)
|
||||
- Claude counterpart physically writes to substrate with sha256-verified integrity check
|
||||
- Subsequent state transitions via `[queue-update: <id> <new-state> <reason>]` rig-send from Codex to Claude-writer
|
||||
- Authorship preserved; only write-access delegated. Distinct from peer-injection (which is forbidden).
|
||||
|
||||
## Escalation mechanics
|
||||
|
||||
When entry stays blocked past tier threshold AND agent can't self-unblock:
|
||||
|
||||
1. Identify escalation target per authority chain:
|
||||
- Pod member → pod orchestrator
|
||||
- Pod orch → rig orch-lead
|
||||
- Rig orch-lead → kernel orch-lead OR advisor-pod (if human-gate)
|
||||
- Skip-levels allowed when agent KNOWS correct target
|
||||
2. Create new entry in escalation-target's queue with `escalated-from: <source-id>`; state=pending; priority elevated
|
||||
3. Send handoff-shape rig-send: `[queue-escalate: <new-id>] <title> — blocked <Nh> on <reason>`
|
||||
4. Update own entry: state=escalated; escalated-to=<target>/<new-id>; transitions-log appended
|
||||
|
||||
Threshold guidance: 1h human-gate / 4h agent-coordination / 24h internal-self. Rigs may tighten.
|
||||
|
||||
## Task-close RSI-check (flywheel trigger)
|
||||
|
||||
Every `complete` op on substantive work reflects briefly: "what did we learn? is this worth filing as L2 capture to improvements-inbox?"
|
||||
|
||||
Two outcomes; both leave evidence in the transition trail:
|
||||
|
||||
- **Novel observation worth filing:** append L2 capture entry to `rigs/kernel/state/improvements-inbox.md` per the v1 queue template (`state: pending` + transition trail started). Transition line in your own queue: `<ts> — RSI-check: filed <capture-id>`.
|
||||
- **Nothing novel:** transition line in your own queue: `<ts> — RSI-check: none`.
|
||||
|
||||
Applies to substantive work-streams. Does NOT apply to:
|
||||
- Wake-pings (`1`) — not a work-stream
|
||||
- Trivial status updates — nothing to reflect on
|
||||
- Pure acks / routing-map updates — no work done
|
||||
|
||||
Rationale: task-close is the deterministic interval that makes recursive-self-improvement mechanical rather than ad-hoc. Pattern named in skill-maturity-convention.md §"Task-close RSI-check discipline".
|
||||
|
||||
## Push vs pull — when to use rig-send vs queue-write
|
||||
|
||||
Not every communication belongs in the receiver's chat pane. The discipline mirrors status-not-chat: most inter-agent signals can flow through queue files (pull) rather than rig-sends (push). Reduces noise; respects receiver's attention cycle.
|
||||
|
||||
**Sender's test:** *Does my message need the receiver's attention within their next turn cycle?*
|
||||
- **Yes → push** via `rig send` (lands in chat; receiver processes on next turn)
|
||||
- **No → pull** via queue-write (write to own queue OR receiver's queue via handoff; receiver sweeps at cadence)
|
||||
|
||||
### Push (rig-send to chat) when:
|
||||
|
||||
- Receiver needs info NOW to unblock their work
|
||||
- Question requires specific answer to proceed
|
||||
- Handoff is past ack-threshold + tier=human-gate (mandatory-ack window)
|
||||
- Blocker surfacing (can't self-unblock; need help from target)
|
||||
- human-gate item needing surface to advisor-pod
|
||||
- Destructive or time-critical coordination
|
||||
|
||||
### Pull (queue-write only) when:
|
||||
|
||||
- Status update / adoption signal / cascade-complete ack
|
||||
- Non-urgent ack (within tier threshold)
|
||||
- Information that can batch in receiver's curator sweep
|
||||
- Broadcast-receipt confirmation (receiver's cadence catches it)
|
||||
- Observed patterns or captures with no time pressure
|
||||
- Resync material for HA peers (they sweep on resume-from-idle)
|
||||
|
||||
### Why this matters
|
||||
|
||||
Push-as-default floods the receiver's chat pane with status that could be pulled. Today's rollout volume proved this: during attention-queue + EMM cascades, most acks arrived as push (rig-sends) when they could have been pull (queue-writes). Receiver (advisor-pod) had to process each ping; most were status signals needing no action.
|
||||
|
||||
Pull-over-push is the queue primitive's whole point. Status lives in queue files; readers sweep at cadence; only genuine unblockers + gate-surfaces push to chat.
|
||||
|
||||
### Worked example
|
||||
|
||||
orch-lead@your-rig ack'd attention-queue cascade:
|
||||
- **Push version (what happened):** `rig send advisor-peer-observer@your-rig "[queue-handoff-ack: ...] ... cascaded to 8 pod members ..."` → lands in my chat; I read immediately; process the status
|
||||
- **Pull version (what should happen):** write ack-receipt to `rigs/openrig-build/state/orch/lead.queue.md` as state-transition on their adoption entry; I sweep their queue on my curator cadence; pick up the ack without chat-ping
|
||||
|
||||
Ack-receipts for status are pull-native. Handoff-complete notifications for human-gate items stay push (they close feedback loops on time-sensitive work).
|
||||
|
||||
### Corollary — orchestrator-to-advisor cadence
|
||||
|
||||
Orchestrators writing to their own queue files lets advisor-pod read without being interrupted. The curator-sweep pattern (advisor reads pod queues on their cadence) is the canonical pull mechanism. Push only when time-matters.
|
||||
|
||||
## Anti-patterns (don't do these)
|
||||
|
||||
- **Chat-as-status** — narrating status/gates to your chat pane + idle-waiting. Use queue + human-attention instead.
|
||||
- **Duplicate-storage** — writing the same fact in queue + session-log + chat + mission-control. Queue is authoritative for in-flight state.
|
||||
- **Peer-injection** — writing directly to another agent's queue without their authorship. Only handoff op moves work cross-queue.
|
||||
- **Silent drops** — don't leave items in pending forever without state transitions. defer or drop with rationale.
|
||||
- **Global queue** — don't try to make one queue for everyone. Per-agent primary; compose for views.
|
||||
|
||||
## Maturity status
|
||||
|
||||
**L4-insight** per skill-maturity-convention. Applied liberally across the host; evolving via observation. Feedback loop: RSI filings reshape this skill; demotion valid if convention reveals wrong shape; promotion to L5-canon requires architect+reviewer pair-review per HOST-TOPOLOGY §7 SOP.
|
||||
|
||||
Rollout date: 2026-04-13 host-wide adoption. 48h observation cycle active; RSI with learnings due ~2026-04-15.
|
||||
|
||||
## Related
|
||||
|
||||
- Spec (full reference): the internal attention-queue spec
|
||||
- Skill-maturity convention: `substrate/shared-docs/skill-maturity-convention.md`
|
||||
- Config-wrapper-code loop doctrine: `config-wrapper-code-loop` skill
|
||||
- HOST-TOPOLOGY §4 context-sharing patterns — attention queue is a new pattern here
|
||||
- SUBSTRATE-CONVENTIONS §7 HA session logs — queue lives in same per-pod directory
|
||||
@@ -0,0 +1,190 @@
|
||||
---
|
||||
name: cross-host-rig-commands
|
||||
description: Use when issuing `rig` commands against a remote host via `--host <id>` flag (single-hop SSH to a host declared in `~/.openrig/hosts.yaml`). Covers the 4 structured failure modes (ssh-unreachable / permission-gate / remote-daemon-unreachable / remote-command-failed), the `--verify` honest pass-through (SSH success is NOT verify success), and the host-registry shape. v0 supports `rig send / capture / ps / whoami --host <id>`.
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- capture
|
||||
- daemon start
|
||||
- host list
|
||||
- host show
|
||||
- ps
|
||||
- send
|
||||
- whoami
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- rig-lifecycle
|
||||
- topology-mutation-and-seat-management
|
||||
- seat-scaling-and-specialization
|
||||
- sidecar-operator
|
||||
- rig-bundles-and-shareable-artifacts
|
||||
- specification-system
|
||||
- extension-and-user-workspace
|
||||
---
|
||||
|
||||
# Cross-Host Rig Commands
|
||||
|
||||
A first-class OpenRig surface for issuing `rig` commands against a
|
||||
remote host via single-hop SSH. v0 productizes the existing SSH-envelope
|
||||
operator pattern (`ssh <host> rig <cmd>`) with declared host identity,
|
||||
explicit cross-host invocation path, preserved `--verify` semantics, and
|
||||
4 named failure modes.
|
||||
|
||||
**Current-host note (2026-07-14):** this skill still preserves the original
|
||||
SSH-v0 doctrine below, but the live host registry may also contain HTTP
|
||||
read-through/tunnel entries such as `your-vm` and `your-other-vm`. Use the
|
||||
host registry entry as ground truth for transport shape, and use
|
||||
`conventions/multi-host-naming/README.md` for host-id naming. HTTP entries
|
||||
require `url` plus exactly one of `bearer_file` or `bearer_env`.
|
||||
|
||||
**v0 is CLI-side shell-out only — `packages/daemon/` is NOT touched.**
|
||||
The remote host has its own managed `rig` available on `$PATH`.
|
||||
|
||||
## Use this when
|
||||
|
||||
- Driving a Tart VM from the host (the immediate cross-host consumer)
|
||||
- Operating Mac host A against Mac host B
|
||||
- Reading remote state via `rig ps --host` / `rig whoami --host`
|
||||
- Sending or capturing on a remote rig session (`rig send/capture --host <id>`)
|
||||
- Authoring a `~/.openrig/hosts.yaml` registry entry
|
||||
|
||||
## Don't use this when
|
||||
|
||||
- The target is local. Don't pass `--host` for local commands.
|
||||
- You need multi-hop SSH (host A → host B → host C). v0 is single-hop only.
|
||||
- You want reverse direction (remote initiates back to local). v0 is originator-pull only.
|
||||
- Cross-host **seat handover** (moving a durable owned seat across hosts) — deferred to higher-level primitives. (Cross-host **queue writes**, by contrast, now ship — see "Cross-host queue writes" below.)
|
||||
- The transport isn't SSH. v0 supports `transport: ssh` only.
|
||||
|
||||
## Cross-host queue writes (updated 2026-07-21 vs main d37a08ad)
|
||||
|
||||
Cross-host **queue writes** are no longer deferred — they ship — but the rule
|
||||
differs from the interactive verbs (`send`/`capture`/`ps`/`whoami`):
|
||||
|
||||
- **Queue writes are EXPLICIT-only.** Address the target host explicitly with
|
||||
`--host <id>` or the `member@rig@<host>` form. A queue write **never** follows a
|
||||
persisted host selection.
|
||||
- **`host select` stickiness does NOT apply to queue.** `host select` affects the
|
||||
`resolveEffectiveHost` verbs (`send`/`capture`/`ps`/`whoami`) — those follow the
|
||||
selected host — but a queue write ignores it and requires explicit addressing.
|
||||
- **Host address parsing differs** between the interactive verbs and the queue
|
||||
verbs; do not assume the interactive form carries over. When unsure, address the
|
||||
host explicitly.
|
||||
|
||||
## Host registry shape (`~/.openrig/hosts.yaml`)
|
||||
|
||||
Host ids should follow the OpenRig-work multi-host naming convention:
|
||||
`conventions/multi-host-naming/README.md`. In this environment that means
|
||||
physical hosts such as `your-vm`, local OpenRig development VMs such as
|
||||
`your-vm`, persistent product VMs such as `your-other-vm`, and VPS hosts such
|
||||
as `your-vps`. Keep old aliases during migration until no live routing
|
||||
depends on them.
|
||||
|
||||
```yaml
|
||||
hosts:
|
||||
- id: a-test-vm
|
||||
transport: ssh # v0 supports "ssh" only
|
||||
target: a-test-vm.local # DNS name, SSH config alias, or IP
|
||||
user: wrandom # optional
|
||||
notes: "Tart VM" # optional
|
||||
- id: laptop-b
|
||||
transport: ssh
|
||||
target: laptop-b.tail-scale-net
|
||||
user: wrandom
|
||||
```
|
||||
|
||||
Validation rules:
|
||||
|
||||
- `hosts` required, non-null array
|
||||
- Each entry: `id` required (non-empty, unique), `transport` required (`ssh` only), `target` required
|
||||
- `user` and `notes` optional
|
||||
- Operator-managed file; v0 does NOT include any sub-command to add/remove/list hosts (operators edit YAML directly)
|
||||
- Missing or invalid file returns a clear error pointing at the canonical path
|
||||
|
||||
## CLI surface (v0 shipped)
|
||||
|
||||
```bash
|
||||
rig send <session> "msg" --host <id> --verify
|
||||
rig capture <session> --host <id>
|
||||
rig ps --host <id> [--nodes] [...]
|
||||
rig whoami --host <id>
|
||||
```
|
||||
|
||||
Forwards every shaping flag (`--nodes`, `--full`, `--limit`, `--fields`,
|
||||
`--summary`, `--filter`, `--json`) to the remote `rig` invocation. The
|
||||
remote rig's output is verbatim passthrough on success.
|
||||
|
||||
## The 4 structured failure modes (load-bearing API contract)
|
||||
|
||||
The CLI distinguishes 4 failure modes; operators get an actionable error
|
||||
per mode; JSON output preserves the `failedStep` enum:
|
||||
|
||||
| Mode | Cause | Action |
|
||||
|---|---|---|
|
||||
| `ssh-unreachable` | SSH itself failed (connection refused, host key mismatch, DNS failure, timeout) | Verify SSH access and the registry entry |
|
||||
| `permission-gate` | SSH hit auth/permission gate (Permission denied, Keychain) | Error includes hint to keychain-over-SSH field note (L4-3 D6) |
|
||||
| `remote-daemon-unreachable` | SSH succeeded but remote `rig` reported the remote daemon was not reachable | `ssh <target> rig daemon start` |
|
||||
| `remote-command-failed` | SSH succeeded but remote `rig` exited non-zero for some other reason; remote stderr is surfaced | Read remote stderr; debug remote command |
|
||||
|
||||
Each is distinct and routable. Don't conflate them.
|
||||
|
||||
## `--verify` honest pass-through (load-bearing)
|
||||
|
||||
`--verify` against a remote target must:
|
||||
|
||||
- **Propagate** the verification request to the remote daemon (or remote `rig` invocation that talks to it)
|
||||
- **Bring back a structured verification result** (true/false + reason if false), NOT just SSH exit code 0
|
||||
- **Distinguish "SSH succeeded but verify returned false" from "SSH itself failed"** — these are different operator actions
|
||||
|
||||
**SSH success is NOT verify success.** The remote rig is authoritative
|
||||
on `--verify`; its `Verified: yes/no` line is surfaced verbatim. Verified
|
||||
at 3 layers (executor unit, command integration, source impl).
|
||||
|
||||
## Hard boundaries (do-not list)
|
||||
|
||||
- **Do NOT collapse `--verify` honest result into SSH exit code.** Operators and agents rely on the distinction.
|
||||
- **Do NOT silently retry SSH failures inside the primitive.** Surface them; let the caller decide.
|
||||
- **Do NOT introduce non-SSH transports in v0.** Goal is productizing the existing shipped pattern, not replacing it.
|
||||
- **Do NOT touch host-side daemon code as part of v0.** Cross-host shape is on the originator side.
|
||||
|
||||
## Cross-host annotation
|
||||
|
||||
Every cross-host invocation is observable as cross-host:
|
||||
|
||||
- **Operator output**: `[via host=<id> (<target>)]` annotation
|
||||
- **JSON output**: `cross_host: { host, target }` field
|
||||
|
||||
Annotation is PRESENT when `--host` is set and ABSENT otherwise
|
||||
(compat regression).
|
||||
|
||||
## Currently shipped (v0) vs deferred
|
||||
|
||||
Shipped at openrig `cdce3a6` (2026-04-30):
|
||||
- `--host <id>` flag on `rig send / capture / ps / whoami` (initial 2 commands; promoted to 4 at `6b7043a` same day)
|
||||
- Read-only host registry validation
|
||||
- Single-hop SSH executor with 4-mode `failedStep` enum
|
||||
- `--verify` honest pass-through
|
||||
- Cross-host annotation (operator + JSON)
|
||||
- Daemon untouched
|
||||
|
||||
Deferred:
|
||||
- Tier 2 real-runtime cross-host proof (disposable Tart VM cycle)
|
||||
- `rig host list / show` read-only sub-namespace (only if host count grows past comfortable manual editing)
|
||||
- Non-SSH transports
|
||||
- Multi-hop SSH
|
||||
- Reverse direction (remote initiates)
|
||||
- Connection pooling/caching
|
||||
|
||||
## See also
|
||||
|
||||
- `seat-continuity-and-handover` skill — host-aware seat-binding semantics for cross-host handover (deferred to v1 on top of this v0 baseline)
|
||||
- `openrig-user` skill — the local CLI surface that cross-host commands wrap
|
||||
|
||||
## Sender identity is ASYMMETRIC (verified vs current main, 2026-07-25)
|
||||
|
||||
The `@host` sugar is **target-addressing only**, not sender-identity. A cross-host
|
||||
message's **From:** is `member@rig` — the sender carries **NO `@host` suffix**. The target
|
||||
supports `member@rig@<host>` for addressing; the sender does not reflect its own host in
|
||||
`From:`. **Do NOT teach or expect a host-qualified `from`** (in openrig-user / operator send
|
||||
docs or anywhere) until that core gap is fixed. (pm@your-rig verified this against
|
||||
current main, 2026-07-25 — a known asymmetry, not a doc error to paper over.)
|
||||
@@ -0,0 +1,104 @@
|
||||
---
|
||||
name: human-in-the-loop
|
||||
description: Use when classifying a slice closeout (auto-continue / human gate / park), routing a real decision to a human, or designing a human queue/dashboard surface. Treats humans as durable network participants with attention surfaces, queues, and decision records — escalation lands as a durable attention item, not a chat message. Approval is NOT required for every clean closeout; the default RSI conveyor continues unless an explicit human gate is reached.
|
||||
metadata:
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- queue-handoff
|
||||
- workflow-runtime
|
||||
- watchdog
|
||||
- alignment-trace
|
||||
- looping-workflows
|
||||
- intake-routing
|
||||
- attention-queue
|
||||
- dispatching-parallel-agents
|
||||
- subagent-driven-development
|
||||
- control-plane-capabilities
|
||||
- status-not-chat-orchestrator
|
||||
- control-plane-queue
|
||||
- control-plane-watchdog
|
||||
- control-plane-workflows
|
||||
- control-plane-delivery-loop
|
||||
- control-plane-rollout-manager
|
||||
---
|
||||
|
||||
# Human In The Loop
|
||||
|
||||
The primitive that treats humans as **durable network participants** —
|
||||
attention surfaces, queues, decision records, routing semantics — not
|
||||
as ad-hoc chat receivers.
|
||||
|
||||
**Autonomy is not the absence of humans; it is knowing when human
|
||||
judgment is needed and making that handoff crisp.**
|
||||
|
||||
## Use this when
|
||||
|
||||
- A slice closeout needs classifying: auto-continue, human gate, or park
|
||||
- A real decision needs to land in front of a human (usage limits, provider auth, roadmap tradeoff, product-intent ambiguity)
|
||||
- Designing a human queue/dashboard surface
|
||||
- Returning a hot potato to orchestration after human approval
|
||||
|
||||
## Don't use this when
|
||||
|
||||
- The slice closeout is clean and `PROGRESS.md` already names the next safe slice. **Default RSI conveyor continues; do NOT manufacture a human gate.**
|
||||
- The escalation is just a status update. Humans are participants for *decisions*, not narration.
|
||||
- The next owner is another agent. Use queue-handoff, not human-in-the-loop.
|
||||
|
||||
## The 3-class closeout classification
|
||||
|
||||
In a productized daemon-backed version, closeout classifies the next
|
||||
step BEFORE touching the human queue:
|
||||
|
||||
| Class | When | Action |
|
||||
|---|---|---|
|
||||
| **auto-continue** | Slice closes cleanly, next named slice in workstream plan | Mark closed; create next-owner qitem from plan |
|
||||
| **human gate** | Genuine decision needed (usage limits, provider auth, product-intent ambiguity, roadmap tradeoff) | Create human queue item with proof + decision text + recommended default + action outcomes |
|
||||
| **park** | Intentionally stop the conveyor (e.g., waiting on external) | Stop with reason + resumption path |
|
||||
|
||||
## Failure modes (5)
|
||||
|
||||
1. **Human decision needed, but the rig only mentions it in chat.** Decisions belong as durable attention items, not chat messages.
|
||||
2. **Human queue item lacks enough plain-English context for a decision.** Include proof + decision text + recommended default + action outcomes.
|
||||
3. **Human response updates a file but does not wake the next owner.** Approval should return the hot potato; feedback should create the next durable qitem.
|
||||
4. **The dashboard shows too much raw rig state and hides the actual decision queue.** Decision queue is the primary surface; rig state is secondary.
|
||||
5. **A clean closeout is parked on the human even though `PROGRESS.md` already names the next safe slice.** Don't manufacture human gates.
|
||||
|
||||
## Proof standard (both paths)
|
||||
|
||||
A trustworthy human-in-the-loop system proves both directions:
|
||||
|
||||
- **Blocking gate path**: real item routed to human → human decision recorded through UI → resulting hot-potato handoff wakes correct next owner
|
||||
- **Non-blocking closeout path**: proof inspectable by human, but orchestrator continues to next named slice without manufacturing a human gate
|
||||
|
||||
A primitive that only wakes humans is not trustworthy. It must also know when NOT to.
|
||||
|
||||
## Product shape (SHIPPED — Mission Control, PL-005)
|
||||
|
||||
This surface has shipped as **Mission Control** (product UI, `/mission-control`
|
||||
route; actions via `POST /api/mission-control/action`). The seven verbs the
|
||||
human acts with:
|
||||
- **approve** (returns the hot potato to orchestration or the chosen owner)
|
||||
- **deny** (reject the item)
|
||||
- **route** (send to a different owner)
|
||||
- **annotate** (add context without action)
|
||||
- **hold** (intentional pause with reason)
|
||||
- **drop** (mark not-actionable)
|
||||
- **handoff** (hand to a specific next owner — creates the next durable qitem)
|
||||
|
||||
**Approval returns the hot potato to orchestration or the chosen owner;
|
||||
feedback creates the next durable qitem rather than only mutating the source
|
||||
queue file** — enforced by the shipped verbs (handoff/route create qitems).
|
||||
See `docs/as-built/architecture/mission-control.md`.
|
||||
|
||||
## Long-term shape
|
||||
|
||||
Likely needs **multiple humans with different scopes**, not a singleton
|
||||
human attention feed. Different humans own different decision
|
||||
domains; queue items route by scope.
|
||||
|
||||
## See also
|
||||
|
||||
- `queue-handoff` skill — durable handoff via queue items; human-in-the-loop is the human-side complement
|
||||
- `watchdog` skill — when to wake (humans included) vs no-op
|
||||
- `looping-workflows` (convention) — the looping-workflows convention covers loop closeouts; human-in-the-loop is the escape hatch
|
||||
@@ -1,115 +0,0 @@
|
||||
---
|
||||
name: mission-slice-sop
|
||||
description: "Use when working a mission or slice: the SDLC flow (intent -> mini-requirements + proof contract -> mockups -> plan-lock -> build -> QA -> `rig proof` drops -> proof-lock), and how to track, prove, and hand off state across agents and compaction via PROGRESS.md / PROOF.md / MISSION_NOTES.md. Covers the two locks, role contracts, hot-potato queue handoff, and the `rig scope audit` backstop."
|
||||
metadata:
|
||||
openrig:
|
||||
stage: shipped
|
||||
last_verified: "2026-07-06"
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
The canonical product SDLC skill: it teaches the full SDLC flow the
|
||||
Living Notes UI projects — the convention sections, the proof-contract
|
||||
pairing, the two staged-approval locks, C1 proof drops, and the three
|
||||
role contracts. Conventions SSOT: docs/reference/sdlc-conventions.md
|
||||
in the repo; on an installed package the daemon materializes the same
|
||||
document at $OPENRIG_HOME/reference/sdlc-conventions.md (default
|
||||
~/.openrig/reference/sdlc-conventions.md). The deterministic backstop
|
||||
is the `rig scope audit` classifier.
|
||||
sibling_skills:
|
||||
- queue-handoff
|
||||
- seat-continuity-and-handover
|
||||
- claude-compaction-restore
|
||||
---
|
||||
|
||||
# Mission/Slice SOP — how you work a mission & slice
|
||||
|
||||
Use this skill to actually **do** mission/slice work the way OpenRig expects: author the convention sections, track on the canonical files, prove on them, hand off through them, and survive compaction on them. **Do the work described here; do not merely explain the protocol.** The deterministic backstop is `rig scope audit` — the audit classifier is the source of truth for adherence. The conventions themselves live in ONE document: **`docs/reference/sdlc-conventions.md`** in the repo, materialized by the daemon at **`$OPENRIG_HOME/reference/sdlc-conventions.md`** (default `~/.openrig/reference/sdlc-conventions.md`) on an installed package — this skill teaches the flow; the SSOT defines the formats.
|
||||
|
||||
## The SDLC flow (intent → proof)
|
||||
|
||||
```
|
||||
intent → mini-requirements + proof contract → (UI slices: mockups)
|
||||
→ plan-lock (rig scope slice approve --scope spec)
|
||||
→ build the LOCKED set
|
||||
→ QA: mockup ↔ delivered VISUAL compare
|
||||
→ proof drops (rig proof add <slice> …)
|
||||
→ proof-lock (rig scope slice approve --scope delivery)
|
||||
```
|
||||
|
||||
1. **Record intent** verbatim in the slice's `## Intent` section (`rig scope slice create` scaffolds it — every template kind).
|
||||
2. **Author the mini-requirements + proof contract**: `## Mini-requirements` is the concise one-glance tier (approval starts there); `## Proof contract` is a checkbox list of promised deliverables, each written as an observable outcome. UI deliverables name their planned mockup. The IMPLEMENTATION-PRD opens with the mini-requirements; everything between intent and proof is **elastic** — for a small slice the mini-requirements may BE the whole PRD.
|
||||
3. **Plan-lock**: `rig scope slice approve <slice> --scope spec` — "the PRD matches the intent; THIS artifact set is what gets built." One daemon-side write: frontmatter stamp + append-only audit row.
|
||||
4. **Build the locked set** — look at the mockups, not just the spec text.
|
||||
5. **QA visual compare**: for each deliverable, load the planned mockup, produce the real artifact in a test/demo environment, visually compare, and record the verdict.
|
||||
6. **Drop proof**: `rig proof add <slice> --artifact-type qa --verdict PASS --candidate-sha <tip> --money-evidence "…" --evidences "1,3" --media "walk.webm,panel.png" --self-check "…"` — the C1 header's closed sets validate at drop time; `--evidences` joins the drop to its proof-contract items and `--media` names the curated proof/-relative media the drop stands behind (that pairing + media set is what the UI's DELIVERED section renders).
|
||||
7. **Proof-lock**: `rig scope slice approve <slice> --scope delivery` — the terminal sign-off. Approval is freeze/sign-off, **never** proven-green: proven-green requires the recorded C1 verdicts.
|
||||
|
||||
## The three role contracts
|
||||
|
||||
- **Planning agent:** authors intent + mini-requirements + the proof contract; produces mockups for UI deliverables and attaches them to the locked set (a UI slice with no mockup is an incomplete plan; non-UI slices have none — not a gate); locks the plan.
|
||||
- **Build agent:** builds against the LOCKED set only; looks at the mockups.
|
||||
- **QA agent (owns the compare):** visually compares planned vs delivered per deliverable, records verdict + note via proof drops, and **curates** the canonical proof set (bounded, mapped to deliverables; the fix-loop pile stays in `proof/`, one drill-in down). On mismatch: fix-and-re-review or kick back with the reason — never escalate a raw mismatch to the human.
|
||||
|
||||
## The canonical files (the operating surface)
|
||||
|
||||
> The canonical files below are the **operating surface of the work** — you track on them, prove on them, hand off through them, and survive compaction on them. They are NOT side-artifacts to "maintain"; keeping them current *is* the work.
|
||||
|
||||
- **README.md** (mission + slice) — the overview, OPENING with the convention sections (`## Intent` / `## Mini-requirements` / `## Proof contract`). The **mission README carries this SOP at its bottom.**
|
||||
- **IMPLEMENTATION-PRD.md** — the full PRD; opens with the mini-requirements; the `## Proof contract` here is what the UI's DELIVERED pairing joins proof against.
|
||||
- **PROGRESS.md** — the live delivery state. One line per outcome; links down for detail.
|
||||
- **MISSION_NOTES.md** — the accruing handoff + tribal-knowledge doc. Blank-slate onboarding + **compaction-restore** read it. `§1` top-of-mind + per-seat `§A–§X`.
|
||||
- **MISSION_BRIEF.md** — the steering doc (the UI "Steering" tab). The 7-section schema.
|
||||
- **PROOF.md** (+ `proof/`) — acceptance evidence. **A slice is not done until every proof-contract item has evidence.**
|
||||
|
||||
## Per-file rules — WHO / WHEN / HOW
|
||||
|
||||
### PROGRESS.md
|
||||
- **WHO:** the orchestrator owns `§1` (current state); every agent logs its own outcomes.
|
||||
- **WHEN:** after every slice-done **AND every commit**; on any material state change.
|
||||
- **HOW:** one line per outcome (checkbox), link down for detail (workstream-continuity format); keep frontmatter `stage`/`verified` honest.
|
||||
|
||||
### PROOF.md + proof/
|
||||
- **WHO:** the impl/QA pair that worked the slice.
|
||||
- **WHEN:** a slice is **NOT "done"** until every proof-contract item has evidence.
|
||||
- **HOW:** proof maps **1:1 to the proof contract's deliverables** — put media under `proof/`, then ATTACH it with `rig proof add <slice> … --evidences <item> --media <files>` (the drop writes the C1 header the DELIVERED pairing joins on) + a line in PROOF.md stating what it proves. **Hand-placing files in `proof/` without a drop is the anti-pattern** — the deliverable stays unpaired and `unverified`. No proof → not done.
|
||||
|
||||
### MISSION_NOTES.md
|
||||
- **WHO:** any agent updates `§1` (top-of-mind); each seat owns + appends to its own `§A–§X` section.
|
||||
- **WHEN:** on any material change; a compacting agent **files its state here BEFORE compaction and reads it on restore.**
|
||||
- **HOW:** accruing tribal knowledge — `§1` ≤ 5–15 lines (gates, open decisions, surprises); per-seat continuation entries (latest = truth; other seats read-only). Pointer-first; don't duplicate.
|
||||
|
||||
### MISSION_BRIEF.md
|
||||
- **WHO:** product/design (steering owner).
|
||||
- **WHEN:** when steering changes.
|
||||
- **HOW:** the 7-section steering schema (the UI "Steering" tab reads it).
|
||||
|
||||
### README.md
|
||||
- **WHO:** the author at creation; refreshed on rescope.
|
||||
- **WHEN:** at mission/slice creation + when scope/theme changes.
|
||||
- **HOW:** overview + honest frontmatter (`id`/`stage`/`verified`) + the convention sections up top; the mission README carries this SOP at its bottom.
|
||||
|
||||
## The lifecycle (4 legs)
|
||||
|
||||
**SCAFFOLD** (`rig scope` creates the files from templates — every slice kind emits the convention sections + `proof/` + the IMPLEMENTATION-PRD skeleton) → **POPULATE** (agents fill them as work happens, per the rules above) → **PROJECT** (the Living Notes UI reads them into INTENT → PLAN → DELIVERED) → **VERIFY** (`rig scope audit` checks adherence). "Loose freeform write + deterministic verify."
|
||||
|
||||
## Hot-potato (handoffs)
|
||||
|
||||
End every turn by passing the ball — a `rig queue` handoff to the next agent (close the qitem with a `closure_reason`). The **durable ball-pass is the queue close, not a chat message.** Never go idle without a handoff.
|
||||
|
||||
## Verify (deterministic backstop)
|
||||
|
||||
Run `rig scope audit` at slice-close. It flags: committed-without-touching-PROGRESS; slice-marked-done-without-PROOF; active-mission-without-MISSION_NOTES; MISSION_BRIEF off-schema; proof artifacts violating the C1 header; missing IMPLEMENTATION-PRD on a building slice; missing convention sections (`## Intent`, a well-formed `## Proof contract`, the UI-slice mockup ref). Every convention check is **advisory / fail-open** — it records and advises, never blocks a write. **Fix the flag, don't suppress it.**
|
||||
|
||||
## Reading terminal captures — KNOWN GOTCHA: ghost-text autocomplete is NOT real
|
||||
|
||||
When you `rig capture` a pane, **greyed / ghost autocomplete suggestions are NOT real content** — they are autocomplete *previews* (shell autosuggestion, the input-box ghost-text completion), not typed, staged, or committed input. **This is known, expected, and has been faking agents out a lot** — reading a ghost suggestion in a peer's input box as "staged text they're about to send," or as a real prompt, and then reasoning/acting on a string that was never actually there.
|
||||
|
||||
**Rule:** ignore ghost/autosuggest text entirely. Only *committed/rendered* pane output is real. If a `❯` input line shows text, treat it as an autocomplete artifact unless you have independent evidence it was actually entered. Do not build decisions (or worry about "colliding with staged text") on ghost text. When it matters, verify at source (git, the queue, the actual event) — never off a capture's ghost line.
|
||||
|
||||
## Moment-of-truth checklist
|
||||
|
||||
- **Starting a slice?** → intent recorded verbatim? mini-requirements + proof contract authored? mockups attached (UI slices)? plan locked (`--scope spec`)?
|
||||
- **Finishing a slice?** → every proof-contract item has curated evidence via `rig proof add … --evidences --media` (C1 drops — never only hand-placed files)? PROGRESS updated? MISSION_NOTES `§1` refreshed? proof locked (`--scope delivery`)? Handed off via queue?
|
||||
- **Committing?** → PROGRESS updated?
|
||||
- **Compacting?** → filed your state in MISSION_NOTES?
|
||||
- **Starting on a mission?** → read the mission README (incl. this SOP) + MISSION_NOTES + the conventions SSOT (`docs/reference/sdlc-conventions.md` in the repo, `$OPENRIG_HOME/reference/sdlc-conventions.md` on an installed package)?
|
||||
@@ -1,18 +1,28 @@
|
||||
---
|
||||
name: openrig-architect
|
||||
description: Use when designing multi-agent topologies that run ON OpenRig — authoring RigSpec and AgentSpec files for new rigs, creating agent startup content (guidance / skills / culture), or diagnosing why a launched rig's agents aren't behaving as intended. NOT for changing OpenRig itself (work in the openrig product repo); NOT for ordinary CLI operation of an existing rig (use openrig-user). Covers the full authoring lifecycle from user intent to validated, launchable rig.
|
||||
description: Use when designing multi-agent topologies that run ON OpenRig — authoring RigSpec and AgentSpec files for new rigs, creating agent startup content (guidance / skills / culture), or diagnosing why a launched rig's agents aren't behaving as intended. NOT for changing OpenRig itself (use openrig-builder); NOT for ordinary CLI operation of an existing rig (use openrig-user). Covers the full authoring lifecycle from user intent to validated, launchable rig.
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- agent validate
|
||||
- capture
|
||||
- daemon start
|
||||
- ps
|
||||
- send
|
||||
- spec validate
|
||||
- specs ls
|
||||
- up
|
||||
- whoami
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
last_verified: "2026-05-04"
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
Bootstrap skill — NPM install lands this in personal homes (~/.claude/skills/, ~/.agents/skills/) for users authoring their own rigs.
|
||||
sibling_skills:
|
||||
- openrig-user
|
||||
- openrig-operator
|
||||
- openrig-builder
|
||||
- openrig-upgrade
|
||||
- forming-an-openrig-mental-model
|
||||
transfer_test: pending
|
||||
- ai-dev-workflows
|
||||
notes: |
|
||||
Description was already correct (starts with "Use when..."; lists specific authoring triggers including the diagnose-bad-rig case). Final sentence ("Covers the full authoring lifecycle from user intent to validated, launchable rig.") is workflow-summary-adjacent; on next iteration, consider trimming. For factory-adoption cycle, kept as-is to match product source-of-truth.
|
||||
---
|
||||
|
||||
# OpenRig Architect
|
||||
@@ -47,8 +57,13 @@ Load these before starting any design work. The quality of your output depends o
|
||||
|
||||
**Read if present on this host:**
|
||||
|
||||
4. **Host-level doctrine file** (if your team maintains one — e.g., a HOST-TOPOLOGY doc that defines canonical rig classes, context-sharing patterns, and authoring SOPs for high-stakes rigs). If present, it supersedes the baseline process below for complex or high-stakes rigs (≥4 members, HA, managed-app, or shared/copied). Solo operators and small/focused rigs use the baseline below directly.
|
||||
5. **Agent-facing software design principles** if your rig ships a new CLI, service, or managed app that agents will operate. Treat the operating surface as a context-engineering problem: every error message and help text gives the agent information to act on.
|
||||
4. **Host-level doctrine** in your host's topology doc, if it keeps one. If this file exists, it supersedes the baseline process below for complex or high-stakes rigs. Specifically:
|
||||
- §3 defines the canonical rig classes (kernel, project, ephemeral, infra-build, managed-app). Classify before designing.
|
||||
- §4 defines context-sharing patterns (pods as context domains, pair pattern, HA via mental-model-ha skill + substrate session logs, terminal nodes as common-room, chatroom/substrate/transcripts/Corpus).
|
||||
- **§7 is the canonical 12-step rig-spec authoring SOP for high-stakes rigs — use it instead of the baseline "Design Process" below when the rig is ≥4 members, uses HA, is a managed-app, or will be shared/copied.** The baseline below still applies to small/focused rigs.
|
||||
- §10 contains the host's bootstrap sequence so you know where your new rig fits.
|
||||
- §12 has the naming canon and vocabulary mapping to shipped terms.
|
||||
5. **`building-agent-software` skill** if available in your skill catalog. Design principles for agent-facing tools and surfaces. Relevant when your rig ships a new CLI, service, or managed app.
|
||||
|
||||
**Load as needed:**
|
||||
- Domain-specific skills when designing specialist agents — find shipped skills inside the OpenRig installation under the `specs/agents/` tree
|
||||
@@ -218,10 +233,9 @@ For rigs that reuse builtin agents, the agents directory is often unnecessary
|
||||
4. **Write role guidance** for each custom agent — who they are, what they do
|
||||
5. **Write startup context** for agents that need environment grounding
|
||||
6. **Validate:** `rig spec validate rig.yaml` and `rig agent validate agents/*/agent.yaml`
|
||||
7. **Audit authoring completeness:** `rig spec audit rig.yaml` — advisory findings identify missing culture or startup context without blocking launch.
|
||||
8. **Confirm the runtime cwd** — do not assume agents should work from the directory where the rig spec is stored. The spec root controls file resolution; the runtime cwd controls trust, project guidance, permissions, and repo context.
|
||||
9. **Launch:** `rig up rig.yaml --cwd /path/to/project`
|
||||
10. **Verify:** `rig ps --nodes` — all agents ready? Check `rig capture` on each agent.
|
||||
7. **Confirm the runtime cwd** — do not assume agents should work from the directory where the rig spec is stored. The spec root controls file resolution; the runtime cwd controls trust, project guidance, permissions, and repo context.
|
||||
8. **Launch:** `rig up rig.yaml --cwd /path/to/project`
|
||||
9. **Verify:** `rig ps --nodes` — all agents ready? Check `rig capture` on each agent.
|
||||
|
||||
### Validation Is Non-Negotiable
|
||||
|
||||
@@ -229,10 +243,11 @@ Always validate before launching:
|
||||
|
||||
```bash
|
||||
rig spec validate rig.yaml
|
||||
rig spec audit rig.yaml
|
||||
rig agent validate agents/my-agent/agent.yaml
|
||||
```
|
||||
|
||||
Then run `rig spec audit rig.yaml` for advisory checks such as stale seat references and other cross-file drift that schema validation cannot detect.
|
||||
|
||||
If validation fails, fix the errors. Do not try to launch an invalid spec — it will fail with a less helpful error.
|
||||
|
||||
## Diagnosis: When Things Go Wrong
|
||||
|
||||
@@ -9,11 +9,6 @@ description: >
|
||||
metadata:
|
||||
openrig:
|
||||
stage: candidate
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
cmux is OpenRig's shipped terminal provider generalized onto `rig terminal <provider>` —
|
||||
best-effort, not proof-gated. Authored clean-room.
|
||||
transfer_test: pending
|
||||
sibling_skills:
|
||||
- openrig-herdr
|
||||
- openrig-user
|
||||
|
||||
@@ -10,11 +10,6 @@ description: >
|
||||
metadata:
|
||||
openrig:
|
||||
stage: candidate
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
Empirical herdr 0.7.1 hands-on findings + the ratified implementation PRD. Authored
|
||||
clean-room (patterns only, no herdr source text; AGPL arm's-length).
|
||||
transfer_test: pending
|
||||
sibling_skills:
|
||||
- openrig-cmux
|
||||
- openrig-user
|
||||
@@ -51,7 +46,7 @@ An agent asked "open all my rigs plus a mission as views" runs one `open` per ta
|
||||
```bash
|
||||
rig terminal open acme-web # a whole rig, live agents as tiles
|
||||
rig terminal open mission:site-relaunch # exactly the agents working the mission
|
||||
rig terminal open slice:02-search-filters # the agents working one slice
|
||||
rig terminal open slice:search-filters # the agents working one slice
|
||||
```
|
||||
|
||||
No hand-listing of seats: the mission/slice membership is derived from live topology at open time.
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
---
|
||||
name: openrig-installer
|
||||
description: Use when installing or upgrading OpenRig on a host, especially the V0.3.1 upgrade flow which includes the substrate-kernel → daemon-managed-kernel migration ceremony. Covers npm install, rig setup, rig daemon start (auto-boots kernel), and the canonical verification commands. NOT for ordinary kernel operation post-install — use openrig-operator skill for that.
|
||||
metadata:
|
||||
openrig:
|
||||
maturity: L2
|
||||
distribution_scope: shipped
|
||||
source_evidence: V0.3.1 slice 05-kernel-rig-as-default IMPLEMENTATION-PRD §8 + OQ-A=B migration-ceremony decision
|
||||
---
|
||||
|
||||
# OpenRig Installer
|
||||
|
||||
This skill teaches the operator agent how to install + upgrade
|
||||
OpenRig cleanly. The V0.3.1 upgrade is the one with the migration
|
||||
ceremony (substrate kernel → daemon-managed kernel); other upgrades
|
||||
follow the same install / setup / start shape with no migration.
|
||||
|
||||
## Fresh install
|
||||
|
||||
```bash
|
||||
npm install -g @openrig/cli
|
||||
rig setup
|
||||
```
|
||||
|
||||
`rig setup` is idempotent — safe to re-run if a step fails. It probes
|
||||
host prereqs (tmux present, Node version, writable state path,
|
||||
optional cmux), then invokes `rig daemon start` per the L2 factoring
|
||||
(OQ-B). The daemon's start path auto-boots the kernel rig per the
|
||||
V0.3.1 slice 05 kernel-rig-as-default logic.
|
||||
|
||||
## Verification after install
|
||||
|
||||
```bash
|
||||
rig ps --nodes --rig kernel --json
|
||||
```
|
||||
|
||||
Should report 4 members (advisor.lead + operator.agent +
|
||||
operator.human + queue.worker) all ready. If a runtime is unavailable
|
||||
the daemon picks the matching variant (`rig-claude-only.yaml` or
|
||||
`rig-codex-only.yaml`); the topology stays the same shape with the
|
||||
unavailable runtime omitted from the agent membership.
|
||||
|
||||
Entry point for chatting with the rig:
|
||||
|
||||
```bash
|
||||
rig capture advisor-lead@kernel
|
||||
```
|
||||
|
||||
Or click the CMUX button on the topology graph in the UI at
|
||||
`/topology`.
|
||||
|
||||
## V0.3.1 upgrade ceremony (one-time migration)
|
||||
|
||||
Operators with a kernel spec stored outside the daemon-managed
|
||||
location (any pre-V0.3.1 layout, typically wherever you kept your
|
||||
own `rigs/kernel/` directory) must migrate to
|
||||
`~/.openrig/specs/rigs/kernel/` as a one-time step during the V0.3.1
|
||||
upgrade. The V0.3.1 upgrade IS the migration moment; it's not a
|
||||
separate ceremony.
|
||||
|
||||
### Migration steps
|
||||
|
||||
1. **Snapshot first.** Take a snapshot of the running substrate
|
||||
kernel so the migration is reversible:
|
||||
|
||||
```bash
|
||||
rig snapshot kernel
|
||||
```
|
||||
|
||||
2. **Stop the substrate kernel** (so the migration doesn't race a
|
||||
running rig):
|
||||
|
||||
```bash
|
||||
rig down kernel --snapshot
|
||||
```
|
||||
|
||||
3. **Copy your existing kernel spec** into the daemon-managed
|
||||
location:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.openrig/specs/rigs/kernel
|
||||
cp -r /path/to/old/kernel-spec/* ~/.openrig/specs/rigs/kernel/
|
||||
```
|
||||
|
||||
4. **Upgrade the CLI + daemon**:
|
||||
|
||||
```bash
|
||||
npm install -g @openrig/[email protected]
|
||||
rig daemon stop
|
||||
rig daemon start
|
||||
```
|
||||
|
||||
At this point the new daemon detects `~/.openrig/specs/rigs/kernel.yaml`
|
||||
exists and skips the V0.3.1 builtin-kernel boot (the
|
||||
already-managed-rig branch). The substrate-rooted topology
|
||||
continues to run under daemon management.
|
||||
|
||||
5. **Verify** the migrated kernel matches expectations:
|
||||
|
||||
```bash
|
||||
rig ps --nodes --rig kernel --json
|
||||
```
|
||||
|
||||
6. **Decommission the old copy** (only after verifying the
|
||||
daemon-managed copy works):
|
||||
|
||||
```bash
|
||||
rm -rf /path/to/old/kernel-spec
|
||||
```
|
||||
|
||||
### If migration fails
|
||||
|
||||
The pre-step snapshot is the rollback. `rig restore <snapshot-id>
|
||||
--rig kernel` revives the prior topology. Then `npm install -g
|
||||
@openrig/cli@0.3.0` rolls the CLI back and you can retry later.
|
||||
|
||||
## Operator agent's role in install + upgrade
|
||||
|
||||
The operator agent shepherds operators through these steps when the
|
||||
user asks "how do I upgrade?" or "what's the V0.3.1 ceremony?". The
|
||||
agent reads this skill on demand via `find-skills` — it does not
|
||||
need to memorize the steps; it consults the canonical reference
|
||||
(this file) and walks the operator through.
|
||||
|
||||
## 3-part error remediation
|
||||
|
||||
| What failed | Why it matters | Fix |
|
||||
|---|---|---|
|
||||
| `npm install -g @openrig/cli` permission denied | Global install needs writable npm prefix; macOS Homebrew default is usually writable; some custom Node installs aren't | Either fix the npm prefix permissions or use `sudo npm install -g`; check `npm config get prefix` |
|
||||
| `rig setup` host prereq fail | tmux, Node version, or writable state path missing | `rig doctor` lists each missing piece + the install command; run those, retry `rig setup` |
|
||||
| `rig daemon start` auth-block error | Neither Claude Code nor Codex authenticated; kernel rig requires at least one | Run `claude auth login` OR `codex login`; then retry `rig daemon start` |
|
||||
| `rig daemon start` "kernel already managed" | An existing managed rig named `kernel` exists; the daemon skips builtin-boot per design | This is the expected path after migration — no action needed |
|
||||
| `rig ps --rig kernel --json` returns empty | Daemon healthy but no kernel rig managed; likely the migration step copied content but did not boot | `rig up kernel` from inside `~/.openrig/specs/rigs/kernel/`; or invoke the daemon's cold-boot path explicitly |
|
||||
|
||||
## What this skill is NOT
|
||||
|
||||
- Not the canonical OpenRig command surface; that lives in the
|
||||
`openrig-user` skill.
|
||||
- Not the kernel-operating-procedure for post-install daily use;
|
||||
that's `openrig-operator`.
|
||||
- Not for project rigs; project rigs install themselves via `rig
|
||||
up <spec>` after the kernel is in place.
|
||||
@@ -1,110 +0,0 @@
|
||||
---
|
||||
name: openrig-operator
|
||||
description: Use when operating or debugging host-side OpenRig runtime issues including daemon reachability, partial identity, unified-exec warnings, stale helper-process cleanup, or when distinguishing harness/process issues from live topology health.
|
||||
---
|
||||
|
||||
# OpenRig Operator
|
||||
|
||||
## Overview
|
||||
|
||||
This skill covers host/runtime/operator triage around OpenRig itself.
|
||||
Use it when the problem may be the daemon, the shell/runtime surface, or stale helper processes rather than the product workflow you are trying to run.
|
||||
|
||||
## When to Use
|
||||
|
||||
Use this skill when you see:
|
||||
- `rig whoami --json` returning partial identity
|
||||
- `rig ps --nodes -A --json` failing while some other `rig` commands still work
|
||||
- `Sent to ...` plus `Verified: no`
|
||||
- repeated unified-exec-process warnings
|
||||
- suspicion that stale helper processes are accumulating
|
||||
|
||||
Do not use this skill for normal product workflow routing, queue handling, or ordinary peer communication. Use `openrig-user` for that.
|
||||
|
||||
## First Checks
|
||||
|
||||
Start with the minimum truthful operator read:
|
||||
|
||||
```bash
|
||||
rig whoami --json
|
||||
rig daemon status
|
||||
rig ps --nodes -A --json
|
||||
```
|
||||
|
||||
Interpret them together, not in isolation:
|
||||
- partial `whoami` can mean identity is inferable while daemon-backed surfaces are degraded
|
||||
- `daemon status` tells you whether the host daemon is up, not whether every seat can reach it cleanly
|
||||
- `ps --nodes -A --json` is the best machine-readable fleet topology check when it works (v0.4.4: `--nodes` needs an explicit scope outside a managed session — `-A` for fleet, `--rig <name>` for one rig; the bare `rig ps` map is the cheap first glance)
|
||||
|
||||
## Verification Drift Vs Send Failure
|
||||
|
||||
For `rig send`:
|
||||
- `Sent to ...` + `Verified: yes` = strong positive delivery evidence
|
||||
- `Sent to ...` + `Verified: no` = ambiguous delivery, not automatic failure
|
||||
- no `Sent to ...` line or a hard error = send failure
|
||||
|
||||
When verification is ambiguous, check:
|
||||
- direct reply
|
||||
- `rig capture <session>`
|
||||
- transcript evidence
|
||||
- queue/outbox state if the message asked for a durable handoff
|
||||
|
||||
Do not blindly retry until you have checked one of those.
|
||||
|
||||
## Unified Exec Warning
|
||||
|
||||
If you see:
|
||||
|
||||
- `Warning: The maximum number of unified exec processes you can keep open is 60 ...`
|
||||
|
||||
treat it first as a host/tooling-layer warning, not as automatic proof that the OpenRig topology is unhealthy.
|
||||
|
||||
This warning can coexist with a healthy live topology.
|
||||
|
||||
## Safe Process Triage
|
||||
|
||||
Inspect the process surface first:
|
||||
|
||||
```bash
|
||||
ps -axo pid,ppid,command | rg 'tmux send-keys|rig queue create|tmux attach|codex|claude'
|
||||
```
|
||||
|
||||
Think in layers:
|
||||
- host/tooling layer: stale one-shot wrappers, session bookkeeping, helper shells
|
||||
- topology layer: live `tmux attach` seats, live `codex` / `claude` runtimes, daemon health
|
||||
|
||||
Do not diagnose topology failure from tooling-layer warnings alone.
|
||||
|
||||
## Safe Cleanup Boundary
|
||||
|
||||
Usually safe to reap when clearly orphaned / one-shot:
|
||||
- `tmux send-keys ...`
|
||||
- short-lived shell wrappers created only to enqueue or send one message
|
||||
|
||||
Do not mass-kill:
|
||||
- `tmux attach ...`
|
||||
- `codex ...`
|
||||
- `claude ...`
|
||||
- other long-lived daemon/runtime processes
|
||||
|
||||
The point is to remove garbage, not workers.
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- treating `Verified: no` as if it proves the message did not land
|
||||
- treating the unified-exec warning as if it proves the rig is overloaded
|
||||
- killing live seats when only stale helper wrappers needed cleanup
|
||||
- concluding "daemon down" from one seat's failure without checking host-level daemon status
|
||||
|
||||
## Practical Rule
|
||||
|
||||
Clean the smallest safe surface that matches the evidence.
|
||||
|
||||
If the warning or failure remains after stale-wrapper cleanup, re-check:
|
||||
|
||||
```bash
|
||||
rig daemon status
|
||||
rig ps --nodes -A --json
|
||||
```
|
||||
|
||||
If those remain healthy, the residual issue may still be in the host/tool/session layer rather than in OpenRig topology state.
|
||||
@@ -0,0 +1,460 @@
|
||||
---
|
||||
name: openrig-upgrade
|
||||
description: Use when upgrading the OpenRig CLI/daemon on a host with running rigs, especially when preserving tmux-backed agent sessions through a daemon restart or documenting hot-upgrade SOP evidence.
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- capture
|
||||
- daemon adopt-state
|
||||
- daemon start
|
||||
- daemon status
|
||||
- daemon stop
|
||||
- down
|
||||
- ps
|
||||
- restore-check
|
||||
- snapshot
|
||||
- up
|
||||
- upgrade backup
|
||||
- upgrade preflight
|
||||
- upgrade promote-runtime
|
||||
- upgrade verify
|
||||
- version
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- openrig-user
|
||||
- openrig-operator
|
||||
- openrig-builder
|
||||
- openrig-architect
|
||||
- forming-an-openrig-mental-model
|
||||
- ai-dev-workflows
|
||||
---
|
||||
|
||||
# OpenRig Upgrade
|
||||
|
||||
## Core Principle
|
||||
|
||||
OpenRig has two different failure domains:
|
||||
|
||||
- **Agent process plane:** Claude/Codex/terminal seats running inside tmux.
|
||||
- **Management plane:** the OpenRig daemon, CLI, SQLite DB, transcripts, node inventory,
|
||||
send/capture APIs, restore metadata, and migrations.
|
||||
|
||||
A hot daemon upgrade is possible when the continuity seats remain alive in tmux and
|
||||
the new daemon restarts against the same DB and transcript root. Do not run
|
||||
`rig down` on continuity rigs unless the goal is a disruptive restore test; `rig down`
|
||||
kills OpenRig-launched tmux sessions.
|
||||
|
||||
## Preferred Live-Cutover Operator Mode
|
||||
|
||||
For live production daemon cutovers, prefer an **out-of-band upgrade operator**:
|
||||
a temporary host-local tmux seat outside the managed OpenRig topology, spawned
|
||||
from the lifecycle/runtime-upgrade agent's current mental model.
|
||||
|
||||
Why: the managed rig stays in the agent process plane while a disposable sidecar
|
||||
mutates the management plane. The sidecar inherits enough context to avoid a
|
||||
cold handoff, but it is not inside the failure domain it is modifying.
|
||||
|
||||
Use this when all are true:
|
||||
|
||||
- the upgrade mutates the live daemon, CLI wrapper, DB, runtime worktree, tmux
|
||||
lifecycle, or active control-plane truth;
|
||||
- continuity seats should keep working during the upgrade;
|
||||
- a lifecycle/runtime-upgrade seat has already prepared the packet or owns the
|
||||
needed context;
|
||||
- the human has granted an `operator auto window`.
|
||||
|
||||
In this SOP, `operator auto window` means a bounded operator-authorized upgrade lane. It does not
|
||||
mean standing Codex `auto_review`, `--full-auto`, or approval-bypass mode. Use
|
||||
`security-and-consequence-boundary-policy` skill for the current
|
||||
security and consequence-boundary policy.
|
||||
|
||||
Do not use this pattern as a standing orchestration seat. The sidecar exists for
|
||||
one cutover and then closes after handback.
|
||||
|
||||
### Sidecar Contract
|
||||
|
||||
The in-rig lifecycle/runtime-upgrade seat owns packet preparation and final
|
||||
interpretation. The out-of-band sidecar owns only execution inside the approved
|
||||
window.
|
||||
|
||||
Sidecar starter prompt shape:
|
||||
|
||||
```text
|
||||
You are the host-local OpenRig runtime upgrade operator, outside the managed rig
|
||||
topology. Execute the approved daemon-only cutover only after explicit human
|
||||
approval. First read the upgrade preflight artifact and runtime-upgrade
|
||||
decision. Prove you are outside the topology before mutation. Never run rig
|
||||
down. Preserve tmux topology. Stop/start only the daemon, verify protected rigs,
|
||||
write cutover evidence, unblock downstream artifacts only when the blocker is
|
||||
truly closed, and rollback to <previous-wrapper-or-commit> if needed.
|
||||
```
|
||||
|
||||
Required handback:
|
||||
|
||||
- write the live cutover evidence under the lifecycle evidence shelf;
|
||||
- include proof that the sidecar was outside the topology/failure domain it
|
||||
mutated;
|
||||
- update any blocked downstream dogfood/runtime task only when the blocking
|
||||
condition is truly closed;
|
||||
- preserve caveats as downstream material instead of using them to reopen a
|
||||
closed cutover gate;
|
||||
- report back to the in-rig lifecycle/runtime-upgrade seat or orch surface with
|
||||
daemon provenance, topology verification, caveats, rollback state, and one
|
||||
compact paragraph of operator judgment about ambiguous choices;
|
||||
- close the sidecar after the original lifecycle owner has absorbed the result.
|
||||
|
||||
Stop conditions for the sidecar:
|
||||
|
||||
- preflight or runtime-upgrade decision is missing;
|
||||
- human approval is absent or narrower than the requested cutover;
|
||||
- protected topology is already degraded beyond the packet's expected caveats;
|
||||
- target runtime cannot be verified by process path, port listener, and command
|
||||
evidence;
|
||||
- any step would require `rig down` or destructive DB restore without a new
|
||||
explicit human decision.
|
||||
|
||||
Generic primitive: this upgrade specialization composes over the
|
||||
`sidecar-operator` skill (the underlying out-of-band-operator pattern;
|
||||
this skill is the upgrade-specific specialization).
|
||||
|
||||
## What Changed On 2026-04-27
|
||||
|
||||
Initial belief:
|
||||
|
||||
- All rigs had to be down before daemon restart.
|
||||
- Live upgrade was research-gated because DB migrations might break session/node
|
||||
state while sessions were running.
|
||||
- A parallel isolated daemon/adoption path looked necessary before production use.
|
||||
|
||||
Observed result:
|
||||
|
||||
- A daemon-only hot cutover preserved the live `example-seat` tmux
|
||||
sessions.
|
||||
- The old daemon was stopped without running `rig down`.
|
||||
- The new source-pinned daemon started against the same production DB.
|
||||
- `rig ps --nodes --json`, `rig capture`, and `rig restore-check` could inspect the
|
||||
still-running Velocity seats after restart.
|
||||
|
||||
The simpler model is now preferred for tmux-backed continuity rigs: snapshot and
|
||||
back up state, stop only the daemon, start the new daemon, then verify that live
|
||||
sessions are still observable and manageable.
|
||||
|
||||
## Proven Hot Path
|
||||
|
||||
Use this as the canonical first-choice workflow for a host where continuity rigs
|
||||
are tmux-backed and the operator wants non-disruptive daemon upgrade.
|
||||
|
||||
0. **Spawn the out-of-band operator when live cutover is required.**
|
||||
The sidecar must be host-local and outside the managed topology being
|
||||
upgraded. Keep the lifecycle/runtime-upgrade owner inside the rig so it can
|
||||
continue to observe, ask questions, and absorb the handback.
|
||||
|
||||
1. **Choose continuity targets.**
|
||||
Name the exact rigs that must remain live. Everything else is source material.
|
||||
Do not let "nice to resume later" rigs expand the success criteria.
|
||||
|
||||
2. **Freeze active work.**
|
||||
Get continuity seats to a stable/idle checkpoint. Record resume commands if
|
||||
available.
|
||||
|
||||
3. **Inventory with filters.**
|
||||
Do not dump full `rig ps` output on this host. Use filtered JSON:
|
||||
|
||||
```bash
|
||||
rig ps --nodes --json \
|
||||
| jq -r 'map(select(.rigName=="<rig>")) | sort_by(.canonicalSessionName)[] | "\(.canonicalSessionName) \(.sessionStatus) \(.startupStatus) \(.resumeToken // "none")"'
|
||||
```
|
||||
|
||||
4. **Take a non-destructive snapshot of each continuity rig.**
|
||||
This records rollback/recovery metadata without killing tmux sessions:
|
||||
|
||||
```bash
|
||||
rig snapshot <rigId>
|
||||
```
|
||||
|
||||
Verify the snapshot payload in SQLite has the expected nodes, sessions,
|
||||
checkpoints, and resume tokens.
|
||||
|
||||
5. **Create a post-snapshot SQLite backup.**
|
||||
Use SQLite's online backup API while the daemon is live. Then run
|
||||
`PRAGMA integrity_check` on the backup and verify it contains the continuity
|
||||
snapshot.
|
||||
|
||||
6. **Prepare a clean runtime artifact.**
|
||||
Prefer a dedicated clean source worktree pinned to a commit:
|
||||
|
||||
```bash
|
||||
git worktree add --detach /path/to/openrig-runtime-<shortsha> <commit>
|
||||
cd /path/to/openrig-runtime-<shortsha>
|
||||
PATH=/path/to/node22/bin:$PATH npm ci
|
||||
PATH=/path/to/node22/bin:$PATH npm run build
|
||||
```
|
||||
|
||||
Use even/LTS Node. The 2026-04-27 upgrade used Node `v22.22.1`.
|
||||
|
||||
7. **Stop only the daemon.**
|
||||
First try:
|
||||
|
||||
```bash
|
||||
rig daemon stop
|
||||
```
|
||||
|
||||
If the daemon state file is missing but the PID is known and verified as the
|
||||
OpenRig daemon, gracefully terminate that PID:
|
||||
|
||||
```bash
|
||||
kill -TERM <daemonPid>
|
||||
```
|
||||
|
||||
Do not use `kill -9` unless recovering from a wedged process with human
|
||||
approval. Do not run `rig down` on continuity rigs.
|
||||
|
||||
8. **Start the pinned daemon against the same production DB.**
|
||||
|
||||
```bash
|
||||
PATH=/path/to/node22/bin:$PATH \
|
||||
node packages/cli/dist/index.js daemon start \
|
||||
--port 7433 \
|
||||
--host 127.0.0.1 \
|
||||
--db ~/.openrig/openrig.sqlite
|
||||
```
|
||||
|
||||
9. **Verify management continuity.**
|
||||
Required checks:
|
||||
|
||||
```bash
|
||||
rig daemon status
|
||||
lsof -nP -iTCP:7433 -sTCP:LISTEN
|
||||
rig ps --nodes --json | jq -r 'map(select(.rigName=="<rig>")) | ...'
|
||||
rig capture --rig <rig> --lines 1 --json
|
||||
rig restore-check --rig <rig>
|
||||
```
|
||||
|
||||
Success means the daemon is healthy, continuity sessions remain running/ready,
|
||||
capture works, transcripts are present, and `restore-check` reports no red
|
||||
blockers.
|
||||
|
||||
10. **Align the default CLI with the new daemon.**
|
||||
If `rig` is a wrapper, make sure it delegates to the new CLI. On the
|
||||
2026-04-27 host this meant repointing the rigx real CLI via
|
||||
`~/.openrig/bin/rig-real-17812d5`.
|
||||
|
||||
11. **Write evidence and hand back.**
|
||||
The sidecar writes a cutover evidence packet with daemon provenance,
|
||||
protected topology counts, representative capture/restore checks, smoke
|
||||
results, caveats, and rollback state. Then it notifies the original in-rig
|
||||
lifecycle/runtime-upgrade owner. Do not rely on chat as the only proof.
|
||||
|
||||
## 2026-04-27 Proof Point
|
||||
|
||||
Continuity target:
|
||||
|
||||
- `example-seat`
|
||||
|
||||
Pinned daemon:
|
||||
|
||||
- commit `17812d5d3bfe53dfdc5e202b1da3e8c91e2f4e54`
|
||||
- subject `feat(agents): make runtime config spec-driven`
|
||||
- committed `2026-04-26T18:30:08-07:00`
|
||||
- runtime worktree `~/code/projects/openrig-runtime-17812d5`
|
||||
|
||||
Evidence:
|
||||
|
||||
- Velocity snapshot `01KQ84D3AF9YW6FQCM9SVSM5EG`
|
||||
- post-snapshot DB backup
|
||||
`db-backup/openrig-post-velocity-snapshot-20260427T185003Z.sqlite`
|
||||
- backup integrity `ok`
|
||||
- old daemon PID `62828`, Node 25 global npm install
|
||||
- new daemon PID `39708`, Node 22 source runtime
|
||||
- post-cutover `example-seat`: 4/4 seats `running` / `ready`
|
||||
- `rig restore-check --rig example-seat`: `RESTORABLE WITH CAVEATS`,
|
||||
`20 green | 9 yellow | 0 red`, `RECOVERY: NOT NEEDED`
|
||||
|
||||
Important caveat: this proves hot daemon cutover for tmux-backed Claude seats on
|
||||
this host and commit range. It does not prove that arbitrary migrations,
|
||||
non-tmux runtimes, service-backed rigs, or dead sessions can be recovered without
|
||||
separate testing.
|
||||
|
||||
## 2026-05-02 Proof Point
|
||||
|
||||
Continuity targets:
|
||||
|
||||
- `kernel`
|
||||
- `openrig-discovery`
|
||||
- `openrig-dogfood`
|
||||
- `openrig-lifecycle`
|
||||
- `openrig-maintenance`
|
||||
- `openrig-product-lab`
|
||||
- `example-rig`
|
||||
- `example-seat`
|
||||
|
||||
Pinned daemon:
|
||||
|
||||
- commit `6af2754824a07291562622ac019b68615fc41abe`
|
||||
- runtime worktree `~/code/projects/openrig-runtime-6af2754`
|
||||
- wrapper `~/.openrig/bin/rig-real-6af2754`
|
||||
|
||||
Pattern proven:
|
||||
|
||||
- lifecycle/runtime-upgrade prepared the decision and preflight artifacts;
|
||||
- a host-local tmux sidecar (`host-upgrade-operator-6af2754`) was spawned
|
||||
outside the managed topology with the current operator context;
|
||||
- the sidecar stopped only the daemon, using verified PID fallback after
|
||||
`rig daemon stop` refused due to missing daemon state;
|
||||
- the sidecar started the target daemon on port `7433`, repointed the
|
||||
config-layer wrapper default, verified protected topology, ran targeted
|
||||
Agent Starter smoke/tests, wrote evidence, and unblocked Dogfood;
|
||||
- Velocity delivery continued working throughout the cutover.
|
||||
|
||||
Evidence:
|
||||
|
||||
- preflight:
|
||||
(internal upgrade-preflight evidence, 2026-05-01)
|
||||
- live cutover:
|
||||
(internal live-cutover evidence, 2026-05-02)
|
||||
|
||||
Important caveat: live `rig up --plan --json` accepted valid `starter_ref`
|
||||
specs and rejected forbidden compositions, but plan-mode output did not emit the
|
||||
`resolve_starter.detail.starterContent` stage expected by the Dogfood proof bar.
|
||||
This is a product/dogfood caveat, not an upgrade failure.
|
||||
|
||||
## Brittle Edges Observed On 2026-04-27
|
||||
|
||||
Detailed field note:
|
||||
|
||||
(internal upgrade-brittleness field note, 2026-04-27)
|
||||
|
||||
Operator lessons from the daemon upgrade:
|
||||
|
||||
- `rig down` kills OpenRig-launched tmux sessions. Do not use it as a snapshot
|
||||
primitive when resumability depends on keeping sessions alive.
|
||||
- Old daemon/CLI combinations can be partially functional even when newer health
|
||||
checks fail. A `/healthz` mismatch blocked `rig down --snapshot` even though
|
||||
other daemon APIs still worked.
|
||||
- `rig daemon stop` can fail when the daemon state file is missing. Operators
|
||||
need a verified PID fallback, but the product should reconcile daemon state
|
||||
automatically.
|
||||
- If the sidecar has an operator auto window and `rig daemon stop` refuses only
|
||||
because state is stale, a verified graceful PID termination is acceptable:
|
||||
identify the daemon PID, verify its runtime path, send graceful `TERM`, and
|
||||
verify the port is gone before starting the target daemon.
|
||||
- CLI and daemon provenance can drift. Repointing or verifying the default
|
||||
`rig` wrapper is part of the upgrade, not an afterthought.
|
||||
- Raw `rig ps` is too noisy on this host. Use filtered JSON until the product
|
||||
has compact first-class inventory views.
|
||||
- Snapshot and backup verification is too manual. The SOP currently depends on
|
||||
checking snapshot rows, resume tokens, SQLite backups, and integrity by hand.
|
||||
|
||||
Separate follow-on note, not part of the daemon-upgrade SOP:
|
||||
|
||||
(internal add-node-brittleness field note, 2026-04-27)
|
||||
|
||||
## Disruptive Restore Path
|
||||
|
||||
Use disruptive restore when the goal is to test recovery from killed sessions, or
|
||||
when hot upgrade is blocked by incompatible migrations or corrupted management
|
||||
state.
|
||||
|
||||
```bash
|
||||
rig snapshot <rigId>
|
||||
rig down <rigId>
|
||||
# upgrade daemon/CLI
|
||||
rig up <rigName>
|
||||
rig restore-check --rig <rigName>
|
||||
```
|
||||
|
||||
Expected restore results:
|
||||
|
||||
| Result | Meaning | Action |
|
||||
|---|---|---|
|
||||
| `fully_restored` | All nodes resumed or rebuilt | Resume normal work |
|
||||
| `partially_restored` | Some nodes succeeded, some failed | Inspect failed nodes and relaunch manually |
|
||||
| `failed` | Zero nodes restored | Check daemon logs, snapshot integrity, provider tokens |
|
||||
| `not_attempted` | Pre-restore blockers | Fix blockers before retrying |
|
||||
|
||||
Do not confuse this path with hot upgrade. `rig down` is intentionally
|
||||
disruptive.
|
||||
|
||||
## Stop Conditions
|
||||
|
||||
Do not proceed with hot upgrade if:
|
||||
|
||||
- continuity targets are mid-task and cannot checkpoint;
|
||||
- continuity target tmux sessions are missing before upgrade;
|
||||
- no verified DB backup exists after continuity snapshots;
|
||||
- the target runtime cannot build under an even/LTS Node version;
|
||||
- the daemon migration plan is known to rewrite session/binding semantics in a
|
||||
way that has not been tested;
|
||||
- disk space or DB integrity checks fail;
|
||||
- the operator cannot identify the current daemon PID and runtime source.
|
||||
|
||||
## Rollback
|
||||
|
||||
Rollback means restoring the previous daemon runtime and, if necessary, the DB
|
||||
backup.
|
||||
|
||||
For source runtime:
|
||||
|
||||
1. Stop the new daemon.
|
||||
2. Start the previous runtime or npm/global daemon.
|
||||
3. Verify `/healthz`, filtered continuity inventory, and `rig capture`.
|
||||
4. Restore the DB backup only if migration or DB corruption is confirmed. Do not
|
||||
replace the DB just because continuity sessions are still live but management
|
||||
projection is degraded.
|
||||
|
||||
For npm runtime:
|
||||
|
||||
```bash
|
||||
npm install -g @openrig/cli@<previous-version>
|
||||
rig daemon stop
|
||||
rig daemon start
|
||||
```
|
||||
|
||||
## Roadmap: Better Hot Upgrades
|
||||
|
||||
The product should make the proven manual path boring and explicit.
|
||||
|
||||
Needed product surfaces:
|
||||
|
||||
- `rig upgrade preflight`:
|
||||
daemon PID/runtime source, CLI source, DB path, migration plan, active rigs,
|
||||
continuity targets, tmux liveness, disk space, DB integrity, backup target,
|
||||
and rollback runtime.
|
||||
- `rig daemon adopt-state` or equivalent:
|
||||
recover a healthy daemon on a port when `daemon.json` is missing.
|
||||
- `rig upgrade backup`:
|
||||
online SQLite backup plus integrity and snapshot-presence verification.
|
||||
- `rig upgrade promote-runtime <commit|artifact>`:
|
||||
start from a clean worktree or packaged artifact under an even/LTS Node.
|
||||
- `rig upgrade verify --rig <name>`:
|
||||
filtered inventory, capture, transcript, restore-check, and honest continuity
|
||||
classification.
|
||||
- CLI/daemon provenance:
|
||||
`rig version --json` should report CLI path, daemon path, commit/package
|
||||
version, Node version, DB path, and started-at.
|
||||
- Wrapper alignment:
|
||||
rigx/default `rig` should clearly show which real CLI it delegates to.
|
||||
- Compact inventory:
|
||||
first-class `rig ps --rig <name> --nodes --compact` or equivalent, so
|
||||
operators do not need ad hoc `jq` for routine safety checks.
|
||||
|
||||
Research still needed:
|
||||
|
||||
1. Migration-bearing hot upgrade on a throwaway rig.
|
||||
2. Hot upgrade with non-critical live Codex seats.
|
||||
3. Hot upgrade with service-backed rigs.
|
||||
4. Adoption/reconciliation when daemon DB says sessions are running but tmux has
|
||||
partially drifted.
|
||||
5. Automated rollback on daemon startup failure or migration failure.
|
||||
|
||||
## Operator Summary
|
||||
|
||||
Hot upgrade rule:
|
||||
|
||||
**Snapshot continuity rigs, back up the DB, stop only the daemon, start the new
|
||||
daemon against the same DB, then verify live tmux sessions through filtered
|
||||
management surfaces.**
|
||||
|
||||
Disruptive restore rule:
|
||||
|
||||
**Use `rig down` only when testing or accepting session teardown.**
|
||||
@@ -1,153 +0,0 @@
|
||||
---
|
||||
name: openrig-user-settings
|
||||
description: Use when the user asks an OpenRig agent to read or change OpenRig configuration settings — workspace paths, file allowlists, progress scan roots, daemon port/host, transcripts, or anything stored in ~/.openrig/config.json
|
||||
---
|
||||
|
||||
# OpenRig User Settings
|
||||
|
||||
OpenRig settings live in `~/.openrig/config.json` and are managed via the
|
||||
`rig config` CLI family. The agent-editable surface is **CLI shell-out**;
|
||||
do NOT write the JSON file directly unless the operator specifically asks
|
||||
for raw-text editing (which is handled by the UI Files browser, not by you).
|
||||
|
||||
## Read
|
||||
|
||||
```bash
|
||||
rig config # all keys, value + source
|
||||
rig config --json # JSON: full RiggedConfig
|
||||
rig config --json --with-source # JSON: {key: {value, source, default}}
|
||||
rig config get <key> # single value
|
||||
rig config get <key> --show-source # value + source on one line
|
||||
rig config get <key> --json # {value, source, default}
|
||||
```
|
||||
|
||||
Resolution order: **env var > config file > default**. Always use
|
||||
`--show-source` (or `--json`) when reporting back to the operator so they
|
||||
see *where* the value came from.
|
||||
|
||||
## Write
|
||||
|
||||
```bash
|
||||
rig config set <key> <value> # set a key
|
||||
rig config reset <key> # clear one override (revert to default)
|
||||
rig config reset # delete the whole file
|
||||
```
|
||||
|
||||
## Initialize a default workspace
|
||||
|
||||
```bash
|
||||
rig config init-workspace # scaffold ~/.openrig/workspace/ with missions + slices
|
||||
rig config init-workspace --dry-run # show what would be created
|
||||
rig config init-workspace --root /path # use a custom root
|
||||
rig config init-workspace --force # overwrite scaffolded files (NOT operator content)
|
||||
```
|
||||
|
||||
This creates a file-backed Project workspace under the workspace root:
|
||||
|
||||
```text
|
||||
README.md
|
||||
STEERING.md
|
||||
missions/<mission-id>/README.md
|
||||
missions/<mission-id>/PROGRESS.md
|
||||
missions/<mission-id>/slices/<slice-id>/README.md
|
||||
progress/
|
||||
field-notes/
|
||||
specs/
|
||||
```
|
||||
|
||||
It seeds two starter missions with multiple slices so the Project UI has a
|
||||
real mission/slice map out of the box. It is operator-explicit; do NOT run it
|
||||
on your own initiative unless the operator asks for workspace initialization
|
||||
or repair.
|
||||
|
||||
## Common keys
|
||||
|
||||
| Key | Type | Purpose |
|
||||
|---|---|---|
|
||||
| `daemon.port` | number | OpenRig daemon HTTP port (default 7433) |
|
||||
| `daemon.host` | string | Daemon bind host (default 127.0.0.1) |
|
||||
| `db.path` | string | SQLite DB path (default ~/.openrig/openrig.sqlite) |
|
||||
| `transcripts.enabled` | boolean | Whether the daemon writes transcripts |
|
||||
| `transcripts.path` | string | Transcripts dir (default ~/.openrig/transcripts) |
|
||||
| `workspace.root` | string | Single-root override (default ~/.openrig/workspace) |
|
||||
| `workspace.slices_root` | string | Slice discovery root; default `<root>/missions` |
|
||||
| `workspace.steering_path` | string | STEERING.md path; default `<root>/STEERING.md` |
|
||||
| `workspace.field_notes_root` | string | Field notes dir; default `<root>/field-notes` |
|
||||
| `workspace.specs_root` | string | Specs dir; default `<root>/specs` |
|
||||
| `files.allowlist` | string | `name:/abs/path,name:/abs/path` — UI Files browser roots |
|
||||
| `progress.scan_roots` | string | `name:/abs/path,name:/abs/path` — Progress browse roots |
|
||||
|
||||
Resolution order for workspace per-subdir keys: per-subdir override >
|
||||
`workspace.root` cascade > built-in default.
|
||||
|
||||
## Common operator requests → canonical commands
|
||||
|
||||
> **"Make the UI work against an existing workspace layout"**:
|
||||
> set the per-subdir workspace overrides explicitly:
|
||||
>
|
||||
> ```bash
|
||||
> rig config set workspace.slices_root /path/to/your/workspace/missions
|
||||
> rig config set workspace.steering_path /path/to/your/workspace/STEERING.md
|
||||
> rig config set workspace.progress_scan_roots 'work:/path/to/your/workspace,missions:/path/to/your/workspace/missions'
|
||||
> rig config set workspace.field_notes_root /path/to/your/workspace/field-notes
|
||||
> ```
|
||||
>
|
||||
> No restart needed for the CLI; for the daemon's reads to pick up
|
||||
> changes affecting startup-time wiring (`files.allowlist`,
|
||||
> `progress.scan_roots`), restart with `rig daemon restart`.
|
||||
|
||||
> **"Initialize a default workspace"**:
|
||||
>
|
||||
> ```bash
|
||||
> rig config init-workspace
|
||||
> ```
|
||||
|
||||
After initialization, the Project UI expects this mapping:
|
||||
|
||||
- `workspace.root` maps to the Project workspace.
|
||||
- `workspace.root/missions/<mission-id>` maps to a Project mission.
|
||||
- `workspace.root/missions/<mission-id>/slices/<slice-id>` maps to a Project slice.
|
||||
|
||||
Queue item bodies or tags should mention the mission id and slice id when the
|
||||
work belongs to a slice. That lets the Project Story, Queue, Tests, and
|
||||
Topology tabs attach runtime work to the filesystem slice.
|
||||
|
||||
> **"Allow the file browser to see X directory"**:
|
||||
>
|
||||
> ```bash
|
||||
> # Append to existing list (operator decides the name token):
|
||||
> rig config get files.allowlist --show-source # check current
|
||||
> rig config set files.allowlist 'workspace:/path/to/ws,docs:/path/to/docs'
|
||||
> rig daemon restart # picks up new roots
|
||||
> ```
|
||||
|
||||
> **"What's my current setting for X and where does it come from?"**:
|
||||
>
|
||||
> ```bash
|
||||
> rig config get <key> --show-source
|
||||
> ```
|
||||
|
||||
## When NOT to use this skill
|
||||
|
||||
- **Per-rig config** — settings are host-global at v0; per-rig is v0+1.
|
||||
- **Secrets / credentials** — the `vault.specialist` managed-app handles
|
||||
secrets. Don't put API keys or tokens in `~/.openrig/config.json`.
|
||||
- **Settings sync across hosts** — out of scope at v0.
|
||||
|
||||
## Errors you might see
|
||||
|
||||
- `Unknown config key "<x>". Valid keys: …` — the key name is wrong.
|
||||
Check the table above; suggest the correct key.
|
||||
- `Config file at <path> is malformed. Fix the JSON or reset with: rig config reset` —
|
||||
hand-edit broke the JSON. Operator can `rig config reset` (deletes the
|
||||
whole file) or fix the syntax in the Files browser.
|
||||
- `Invalid value for <key>: expected a number/true-false, got "<x>"` —
|
||||
wrong type for a typed key. Reach for the key's type in the table.
|
||||
|
||||
## Provenance + safety
|
||||
|
||||
- Never write to `~/.openrig/config.json` directly. Use `rig config set`.
|
||||
- Don't run `rig config init-workspace` on your own initiative — wait for
|
||||
an operator request.
|
||||
- Always cite the resolved source (env / file / default) when reporting
|
||||
values back, so the operator knows whether their change actually took.
|
||||
File diff suppressed because it is too large.
Load diff
+101
@@ -0,0 +1,101 @@
|
||||
---
|
||||
name: rig-bundles-and-shareable-artifacts
|
||||
description: Use when authoring or installing a rig bundle (packaged, shareable artifact that instantiates an opinionated OpenRig topology + workflow), reasoning about the bundle vs extension boundary, or auditing a bundle for portability. Covers the 4 failure modes that prevent bundles from working anywhere but the operator's machine, and the inspect-before-install discipline.
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- bundle create
|
||||
- bundle inspect
|
||||
- bundle install
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- rig-lifecycle
|
||||
- topology-mutation-and-seat-management
|
||||
- seat-scaling-and-specialization
|
||||
- cross-host-rig-commands
|
||||
- sidecar-operator
|
||||
- specification-system
|
||||
- extension-and-user-workspace
|
||||
---
|
||||
|
||||
# Rig Bundles and Shareable Artifacts
|
||||
|
||||
A **rig bundle** is a packaged, shareable artifact that can instantiate
|
||||
an opinionated OpenRig topology and workflow. It may include:
|
||||
|
||||
- rig specs
|
||||
- agent specs
|
||||
- workflow specs
|
||||
- startup files
|
||||
- skills or skill references
|
||||
- operating-mode declarations
|
||||
- proof expectations
|
||||
- supporting fragments
|
||||
|
||||
**Shareable artifact** is broader than bundle: specs, bundles, skills,
|
||||
workflows, and extensions can all be shared. A bundle is the packaged
|
||||
form for "load this topology and way of working."
|
||||
|
||||
## Use this when
|
||||
|
||||
- Authoring a bundle from a proven lab pattern
|
||||
- Installing a bundle (`rig bundle install <path>`)
|
||||
- Inspecting a bundle before install (`rig bundle inspect <path>`)
|
||||
- Reasoning about bundle vs extension boundary (bundle declares topology + workflow; extension adds behavior)
|
||||
- Auditing a bundle for portability — does it work on a clean OpenRig environment, or only the author's machine?
|
||||
|
||||
## Don't use this when
|
||||
|
||||
- The work is a one-off topology you won't reuse. Specs alone are sufficient.
|
||||
- The intent is to add runtime behavior (commands, views, dashboards). Use `extension-and-user-workspace`, not bundles.
|
||||
- You want to ship a workflow as a daemon feature. Bundle is the path *before* daemon promotion.
|
||||
|
||||
## The bundle vs extension boundary (load-bearing)
|
||||
|
||||
| Concept | Declares | Example |
|
||||
|---|---|---|
|
||||
| **Bundle** | Rig shape + workflow ("load this topology and way of working") | A Velocity Team bundle |
|
||||
| **Extension** | Behavior added to user workspace/runtime | A custom command, view, or dashboard |
|
||||
|
||||
Don't confuse them. A bundle is *opinionated content*; an extension is
|
||||
*added behavior*. Both can be shareable artifacts, but they're
|
||||
structurally distinct.
|
||||
|
||||
## Failure modes (4)
|
||||
|
||||
1. **A bundle works only on the operator's machine** because paths, providers, or credentials are implicit. Bundles must be self-describing for a clean OpenRig environment.
|
||||
2. **A bundle includes too much local state and becomes a backup archive instead of a reusable artifact.** Bundle is the *intended shape*, not the current state of one specific install.
|
||||
3. **A bundle declares topology but omits proof expectations or workflow mode.** Topology alone doesn't tell users what "working as advertised" means.
|
||||
4. **Users cannot inspect what a bundle will create before installing it.** `rig bundle inspect` must show what will be created without side effects.
|
||||
|
||||
## Proof standard
|
||||
|
||||
Proof should:
|
||||
|
||||
1. Install the bundle into a **clean OpenRig environment**
|
||||
2. Instantiate it
|
||||
3. Verify the expected seats and workflow mode
|
||||
4. Run a small smoke proof that the topology behaves as advertised
|
||||
|
||||
## Bundle path → product
|
||||
|
||||
Bundles are how proven lab patterns become reusable product experiences:
|
||||
|
||||
```
|
||||
local dogfood pattern
|
||||
→ bundle (with manifest, parameterization, proof expectations)
|
||||
→ installed by another user on clean OpenRig
|
||||
→ opinionated workflow shipped without becoming a daemon feature
|
||||
→ if dependable, graduate parts into core daemon
|
||||
```
|
||||
|
||||
This is also how OpenRig can ship opinionated workflows **without making
|
||||
every workflow a daemon feature.**
|
||||
|
||||
## See also
|
||||
|
||||
- `extension-and-user-workspace` skill — sibling primitive for user-owned behavior added to runtime; bundle vs extension boundary
|
||||
- `specification-system` skill — rig specs / agent specs / workflow specs that bundles package
|
||||
- `agent-starters` skill — bundles can include or reference Agent Starters
|
||||
- `composable-priming-packs` skill — bundles can package priming packs
|
||||
- `openrig-user` skill — `rig bundle create / inspect / install` CLI surface
|
||||
@@ -2,18 +2,27 @@
|
||||
name: rig-lifecycle
|
||||
description: Use when reasoning about the rig lifecycle operations family (create / start / stop / resume / restore / snapshot / release / unclaim / destroy), reading or trusting `rig ps` / lifecycle projections after recovery, or designing proof for a lifecycle scenario. Covers the 4 failure modes (auto-restore creates partial rig; projections report healthier than reality; provider auth treated as impl work; resume succeeds for one runtime fails another) plus the restore-honesty rule (failed resume is FAILED loudly — no auto fresh fallback).
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- destroy
|
||||
- down
|
||||
- ps
|
||||
- release
|
||||
- restore
|
||||
- restore-check
|
||||
- resume
|
||||
- snapshot
|
||||
- unclaim
|
||||
- up
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
last_verified: "2026-05-04"
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
Lifecycle Reboot/Recovery Scenario Matrix (Tier 1 complete; Tier 2
|
||||
human-gated). Codex auth-refusal surfaces as attention_required.
|
||||
sibling_skills:
|
||||
- openrig-user
|
||||
- openrig-operator
|
||||
- seat-continuity-and-handover
|
||||
transfer_test: pending
|
||||
- topology-mutation-and-seat-management
|
||||
- seat-scaling-and-specialization
|
||||
- cross-host-rig-commands
|
||||
- sidecar-operator
|
||||
- rig-bundles-and-shareable-artifacts
|
||||
- specification-system
|
||||
- extension-and-user-workspace
|
||||
---
|
||||
|
||||
# Rig Lifecycle
|
||||
@@ -53,7 +62,7 @@ states.
|
||||
|
||||
**Failed resume is FAILED loudly.** No automatic fresh fallback. Fresh
|
||||
launch is **explicit follow-up only.** This is enforced architecturally
|
||||
at the daemon level (per `docs/as-built/architecture/architecture-rules-and-event-system.md` rule 15).
|
||||
at the daemon level (per `architecture.md` §7 rule 15).
|
||||
|
||||
The locked restore-outcome vocabulary:
|
||||
|
||||
@@ -112,5 +121,7 @@ different claims; don't conflate.
|
||||
|
||||
- `openrig-user` skill — CLI surface for `rig up / down / restore / etc.`
|
||||
- `openrig-operator` skill — operator-level discipline for OpenRig itself
|
||||
- `seat-continuity-and-handover` skill — occupant-creation modes for restore (`resume` / `rebuild` / `fresh` / `failed`)
|
||||
- `seat-continuity-and-handover` skill — sub-primitive: occupant-creation modes for restore (`resume` / `rebuild` / `fresh` / `failed`)
|
||||
- `session-source-fork` skill — `forked` continuity outcome for fork-based restore
|
||||
- `permission-and-capability-preflight` skill — provider-auth blocker → escalation path
|
||||
- `openrig/docs/as-built/architecture/lifecycle-snapshot-restore.md` (product reference doc) — daemon enforcement of restore-honesty rule
|
||||
@@ -0,0 +1,160 @@
|
||||
---
|
||||
name: session-source-fork
|
||||
description: |
|
||||
Use when authoring a rig spec member or `rig expand` payload that needs to start a new managed seat from a prior runtime conversation source — `session_source: { mode: fork, ref: { kind, value } }`. v1 supports `mode: fork` with `ref.kind: native_id` for Claude and Codex. The new seat persists a NEW post-fork token; the parent token is NEVER written onto the new seat. NOT for restoring an existing seat or for artifact-backed mental-model rebuild.
|
||||
metadata:
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- claude-compaction-restore
|
||||
- mental-model-ha
|
||||
- scope-recovery
|
||||
- session-compaction-and-restore
|
||||
- agent-startup-and-context-ingestion
|
||||
- agent-starters
|
||||
- composable-priming-packs
|
||||
- seat-continuity-and-handover
|
||||
- claude-compact-in-place
|
||||
- pre-maintenance-agent-preservation
|
||||
---
|
||||
|
||||
# session_source Fork
|
||||
|
||||
`session_source` is a **member-level OpenRig field** that declares how a
|
||||
newly-launched managed seat should derive its initial conversation
|
||||
continuity from a prior runtime conversation source.
|
||||
|
||||
v1 supports one mode: **`fork`** — start a *new* managed seat from a
|
||||
prior native runtime conversation source without claiming the original
|
||||
seat continued.
|
||||
|
||||
The schema is runtime-neutral; implementation is runtime-specific (Claude
|
||||
and Codex have their own native fork commands).
|
||||
|
||||
## Use this when
|
||||
|
||||
- Authoring a rig spec member that should fork from a prior session
|
||||
- Authoring a `rig expand` payload with `session_source`
|
||||
- Reasoning about whether to use `fork` vs `rebuild` vs `resume` vs `fresh` for a new seat
|
||||
- Composing fork + handover (seat-handover-over-fork) — see `seat-continuity-and-handover` skill
|
||||
|
||||
## Don't use this when
|
||||
|
||||
- The seat is being **restored**, not created. Restore continues an existing managed seat. Fork creates a new seat.
|
||||
- The continuity is **artifact-backed mental-model rebuild** (packet-derived understanding, not native runtime continuity). Use `mode: rebuild` (see `seat-continuity-and-handover` for the rebuild surface) — do NOT collapse fork into artifact-backed reentry; the distinction is load-bearing.
|
||||
- The runtime is `terminal`. Terminal runtime rejects `session_source`.
|
||||
|
||||
## The shape (canonical YAML)
|
||||
|
||||
```yaml
|
||||
members:
|
||||
- id: reviewer-2
|
||||
runtime: claude-code # or "codex"; not valid on terminal
|
||||
agent_ref: specs/agents/reviewer.yaml
|
||||
profile: reviewer
|
||||
cwd: .
|
||||
session_source:
|
||||
mode: fork
|
||||
ref:
|
||||
kind: native_id # v1 fork mode supports native_id only
|
||||
value: "0b0165d7-cb4d-4650-90de-15c0a1ede9e6"
|
||||
```
|
||||
|
||||
Rules:
|
||||
- `mode` v1 only valid value: `fork`.
|
||||
- `ref.kind` v1 supports `native_id` only. Schema rejects `artifact_path`, `name`, `last`, and `artifact_set` pre-launch with explicit deferred/weaker/wrong-mode error messages (see `packages/daemon/src/domain/rigspec-schema.ts` validateSessionSourceFork). Adapter-level refusal exists as defensive handling but should not be reachable in v1 because schema rejects first.
|
||||
- `value` required for `ref.kind: native_id` in v1 (the only schema-accepted kind). Future-state value semantics for `artifact_path` / `name` / `last` are not active in v1 because schema rejects those kinds pre-launch.
|
||||
- `rig expand` accepts the same shape so dynamically-added members can carry session-source attribution.
|
||||
|
||||
The primitive does NOT introduce a new top-level command. It flows
|
||||
through existing rig spec and expansion pathways.
|
||||
|
||||
## State model
|
||||
|
||||
`session_source` is a **launch-time input**, not a long-lived stateful field:
|
||||
|
||||
1. **Declared** — present in member config or expansion payload
|
||||
2. **Resolved** — at launch time, OpenRig resolves the `ref` against the runtime
|
||||
3. **Realized** — runtime fork succeeds; new managed seat receives a **NEW** native continuity token (Claude session id or Codex thread id). OpenRig persists that NEW token. **Parent token is NEVER written onto the new seat.**
|
||||
4. **Failed** — resolution or fork failed; seat not launched as a fork; clear error names the resolution step that failed
|
||||
|
||||
Once realized, `session_source` is essentially history. Restoring the
|
||||
seat later is `restore` of the new seat, not re-fork-from-parent.
|
||||
|
||||
## Failure modes (5)
|
||||
|
||||
1. **Source session id not found** — runtime cannot resolve `native_id`. **Action**: emit error naming runtime + missing id; do NOT silently launch fresh. (Future-state note: when `artifact_path` is supported in a follow-up slice, it could become a candidate fallback for Claude; in v1 schema rejects `artifact_path` pre-launch so no fallback path exists.)
|
||||
2. **Source artifact path missing** *(out of v1 scope)* — would apply once `ref.kind: artifact_path` becomes schema-accepted. v1 schema rejects this kind pre-launch.
|
||||
3. **Unsupported runtime/kind combination** *(largely pre-empted in v1 by schema rejection)* — schema rejects all non-`native_id` kinds upfront. Adapter-level refusal exists as defensive handling but is not reached in v1.
|
||||
4. **Fork launch failed after source resolution** — runtime command (`claude --resume <parent> --fork-session` or `codex fork <id>`) returned non-zero or hung. Preserve runtime stderr; do not record new seat as launched; do not write parent token onto seat.
|
||||
5. **Persistence inconsistency** — fork succeeded but seat-token persistence cannot record new continuity token. **Internal failure**: seat is not considered launched until new token is durably written.
|
||||
|
||||
## Honest UX rule (verbatim)
|
||||
|
||||
The primitive must NOT report "restored the original agent" or "resumed
|
||||
the original seat" or "snapshot." The correct framing is **"forked from
|
||||
source session"** / **"started from prior conversation source."**
|
||||
|
||||
Negative-grep over adapter source confirms ZERO `restored` / `resumed` /
|
||||
`snapshot` strings in fork code paths.
|
||||
|
||||
## Hard boundaries (do-not list; verbatim)
|
||||
|
||||
- **Do NOT introduce a new top-level command** (e.g., `rig fork`). The primitive flows through existing spec/expansion pathways.
|
||||
- **Do NOT report "restored" / "resumed the original seat" / "snapshot"** in any UX surface.
|
||||
- **Do NOT couple `session_source` to AgentSpec.** It's a member-level launch-time input.
|
||||
- **Do NOT change `restore` semantics.** `session_source` creates a seat; `restore` continues an existing managed seat.
|
||||
|
||||
## Adapter command shape (shipped v1)
|
||||
|
||||
| Runtime | Command shape |
|
||||
|---|---|
|
||||
| Claude (`mode: fork` + `ref.kind: native_id`) | `claude --resume <parent-id> --fork-session` |
|
||||
| Codex (`mode: fork` + `ref.kind: native_id`) | `codex... fork <parent-id>` |
|
||||
| Terminal | Rejected at schema level |
|
||||
|
||||
Mutual exclusion between `resumeToken` (restore path) and `forkSource`
|
||||
(fork path) is enforced at three layers in the daemon.
|
||||
|
||||
## Continuity outcome literals
|
||||
|
||||
| Outcome | When |
|
||||
|---|---|
|
||||
| `forked` | Fork succeeded; new seat has new native token; parent never written onto new seat |
|
||||
| `fresh` | Fresh launch (no `session_source` declared) |
|
||||
| `resumed` | Restore of existing managed seat |
|
||||
| `failed` | Resolution or fork failed |
|
||||
|
||||
For `seat handover over fork` composition, the binding outcome is
|
||||
independent (see `seat-continuity-and-handover` skill).
|
||||
|
||||
## Active-daemon caveat (live-runtime gap)
|
||||
|
||||
2026-04-30 live scale-out dogfood found: source checkout contained fork
|
||||
support, but active daemon was running from a pre-fork commit. **Verify
|
||||
the active daemon/runtime commit contains the fork path before live
|
||||
proof.** Isolated daemon proof at the target commit can prove the
|
||||
feature safely; live forked scale-out remains unproven until the active
|
||||
daemon parity is verified.
|
||||
|
||||
## Currently shipped (v1) vs deferred
|
||||
|
||||
Shipped at openrig `c7b6df1` (2026-04-30):
|
||||
- Schema accept/reject for full Honest Refusal Matrix
|
||||
- Codec roundtrip (serialize → parse → normalize preserves `session_source` faithfully)
|
||||
- Expansion path through `rig expand` member-input
|
||||
- Adapter command shape for Claude + Codex `native_id`
|
||||
- Persistence honesty (seat's `resume_token` is the NEW post-fork token; parent token NEVER written)
|
||||
- Honest UX literal contract (`continuityOutcome: forked`)
|
||||
|
||||
Deferred:
|
||||
- Tier 2 real-runtime fork proof (disposable Tart VM cycle, human-gated)
|
||||
- Claude `artifact_path` mode (schema currently refuses with deferred message)
|
||||
- Provenance columns (`parent_native_id` / `created_via` for queryable RSI consumer)
|
||||
- Cross-host fork (source on host A, new seat on host B) — depends on `cross-host-rig-commands`
|
||||
|
||||
## See also
|
||||
|
||||
- `seat-continuity-and-handover` skill — sibling occupant-creation primitives (resume / fork / rebuild / fresh) + seat-binding (handover composes with fork)
|
||||
- `agent-starters` skill — composes session_source fork into named reusable starting points
|
||||
- `cross-host-rig-commands` skill — multi-host fork (deferred)
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
name: specification-system
|
||||
description: Use when authoring rig specs, agent specs, workflow specs, startup/context fragments, operating-mode declarations, or designing the user spec library. Covers the 4 failure modes (spec instantiates topology but not workflow/mode; spec depends on local paths and fails on another host; agents modify specs as one-off files instead of preserving reusable intent; validation proves YAML shape but not whether topology can run) and the validation-vs-runtime-realization distinction.
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- agent
|
||||
- bundle
|
||||
- spec
|
||||
- specs
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- rig-lifecycle
|
||||
- topology-mutation-and-seat-management
|
||||
- seat-scaling-and-specialization
|
||||
- cross-host-rig-commands
|
||||
- sidecar-operator
|
||||
- rig-bundles-and-shareable-artifacts
|
||||
- extension-and-user-workspace
|
||||
---
|
||||
|
||||
# Specification System
|
||||
|
||||
The declarative primitive family for OpenRig intent: **rig specs, agent
|
||||
specs, workflow specs, startup/context fragments, operating-mode
|
||||
declarations, and the user spec library that stores and reuses them.**
|
||||
|
||||
Specs are how humans and agents describe **repeatable topology and
|
||||
behavior** without re-explaining it in chat. They are also shareable
|
||||
artifacts: a user should be able to publish a spec or spec family so
|
||||
another user can instantiate the same rig shape, role structure, or
|
||||
workflow pattern.
|
||||
|
||||
**Without a dependable spec primitive, OpenRig depends on manual
|
||||
startup prompts and tribal memory.** That blocks repeatability, product
|
||||
demos, rig bundles, and autonomous rig construction.
|
||||
|
||||
## Use this when
|
||||
|
||||
- Authoring a RigSpec / AgentSpec / workflow spec
|
||||
- Designing a startup/context fragment
|
||||
- Reasoning about spec-library lifecycle (validation, sharing, upgrade semantics)
|
||||
- Auditing a spec for portability (does it run on another host?)
|
||||
- Distinguishing spec vs bundle vs extension cleanly
|
||||
|
||||
## Don't use this when
|
||||
|
||||
- The work is one-off and won't be reused. Manual rig assembly is fine for one-shot work.
|
||||
- The intent is to package a topology + workflow as a shareable artifact. That's `rig-bundles-and-shareable-artifacts`.
|
||||
- The intent is to add runtime behavior. That's `extension-and-user-workspace`.
|
||||
|
||||
## Failure modes (4)
|
||||
|
||||
1. **A spec can instantiate a topology but not the workflow or operating mode needed to use it.** Topology is necessary but not sufficient — workflow and operating mode must be declared too.
|
||||
2. **A shared spec depends on local paths or hidden startup fragments and fails on another host.** Specs must be self-describing for portability.
|
||||
3. **Agents modify specs as one-off files instead of preserving reusable user/library intent.** Specs are reusable; treating each instance as one-off destroys the primitive's value.
|
||||
4. **Validation proves YAML shape but not whether the declared topology can actually run.** Structural validation is not enough; runtime realization is the real proof.
|
||||
|
||||
## Proof standard
|
||||
|
||||
Proof should:
|
||||
|
||||
1. Author a spec
|
||||
2. Validate it (structural)
|
||||
3. Install it (into spec library)
|
||||
4. Instantiate it on a **clean OpenRig environment**
|
||||
5. Show **both structural validation AND runtime realization**
|
||||
|
||||
Validation alone is insufficient.
|
||||
|
||||
## Spec / bundle / extension boundary
|
||||
|
||||
| Concept | Declares | Example |
|
||||
|---|---|---|
|
||||
| **Spec** | Topology / role / workflow shape (declarative intent) | `rig.yaml`, `agent.yaml`, `workflow.yaml` |
|
||||
| **Bundle** | Spec(s) + supporting fragments packaged for shareable instantiation | A Velocity Team bundle |
|
||||
| **Extension** | Runtime behavior added to user workspace | RigX command, custom view |
|
||||
|
||||
Don't conflate them. The contract should distinguish spec, bundle, and
|
||||
extension cleanly.
|
||||
|
||||
## Currently shipped surfaces
|
||||
|
||||
OpenRig already has:
|
||||
|
||||
- RigSpec / AgentSpec authoring (`agent.yaml`, `rig.yaml` formats; see `openrig-architect` skill)
|
||||
- Workflow specs (markdown/YAML files, daemon read-through cache via `workflow_specs` table; see `workflow-runtime` skill)
|
||||
- Bundle/spec command surface (`rig bundle / spec / agent / specs ls/show/preview/add/sync/remove/rename`)
|
||||
- Spec library (filesystem-backed at `packages/daemon/specs/` + `~/.openrig/specs/` per cli-reference.md)
|
||||
|
||||
Not yet shipped:
|
||||
- Spec library lifecycle (validation, sharing, upgrade) treated as a first-class primitive
|
||||
- Cross-host spec sharing
|
||||
- Marketplace / public registry
|
||||
|
||||
## See also
|
||||
|
||||
- `openrig-architect` skill — RigSpec / AgentSpec authoring discipline
|
||||
- `workflow-runtime` skill — workflow spec authoring + transactional-scribe contract
|
||||
- `rig-bundles-and-shareable-artifacts` skill — bundle is the packaged form of specs
|
||||
- `extension-and-user-workspace` skill — extensions add runtime behavior; specs declare intent
|
||||
- `openrig/docs/reference/rig-spec.md` (product reference doc) — RigSpec format specification
|
||||
- `openrig/docs/reference/agent-spec.md` (product reference doc) — AgentSpec format specification
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
---
|
||||
name: topology-mutation-and-seat-management
|
||||
description: Use when changing a rig while it is alive — `rig expand` / `rig shrink` / `rig launch` / `rig remove` / `rig discover` / `rig bind` / `rig adopt` / `rig attach`. Covers the 4 failure modes (newly created seat lacks queue/startup/role; edges and permissions not updated; adopt/bind succeeds at tmux but not OpenRig identity; shrink/remove leaves stale topology references) and the rule that mutation must work while the rig is active, not just in clean fixtures.
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- adopt
|
||||
- attach
|
||||
- bind
|
||||
- discover
|
||||
- expand
|
||||
- launch
|
||||
- ps
|
||||
- release
|
||||
- remove
|
||||
- shrink
|
||||
- unclaim
|
||||
- up
|
||||
- whoami
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- rig-lifecycle
|
||||
- seat-scaling-and-specialization
|
||||
- cross-host-rig-commands
|
||||
- sidecar-operator
|
||||
- rig-bundles-and-shareable-artifacts
|
||||
- specification-system
|
||||
- extension-and-user-workspace
|
||||
---
|
||||
|
||||
# Topology Mutation and Seat Management
|
||||
|
||||
The ability to change a rig **while it is alive**: expand, shrink,
|
||||
launch, remove, discover, bind, adopt, and attach seats or sessions.
|
||||
Seat management includes the **stable identifiers, edges, roles, and
|
||||
startup context** that make those mutations coherent.
|
||||
|
||||
**OpenRig should be easy to reach for.** A user should be able to add
|
||||
capacity, retire capacity, adopt an existing session, or attach a
|
||||
terminal **without rebuilding the whole topology.** If mutation is
|
||||
rarely tested, users avoid it and the product collapses back into
|
||||
static launch scripts.
|
||||
|
||||
## Use this when
|
||||
|
||||
- Adding capacity to a running rig (`rig expand <rig> <pod-fragment-path>`)
|
||||
- Removing capacity (`rig shrink` / `rig remove`)
|
||||
- Launching/relaunching a node in a running rig (`rig launch`)
|
||||
- Binding a discovered session into an existing logical node (`rig bind`)
|
||||
- Adopting a topology + binding live sessions (`rig adopt`)
|
||||
- Attaching a shell or agent into a rig node (`rig attach --self`)
|
||||
|
||||
## Don't use this when
|
||||
|
||||
- The rig is being created fresh from scratch — use `rig up` (lifecycle, not mutation)
|
||||
- The intent is to scale specifically (add specialized capacity) — use `seat-scaling-and-specialization` skill
|
||||
- The intent is occupant replacement on a stable seat — use `seat-continuity-and-handover` skill
|
||||
|
||||
## Failure modes (4)
|
||||
|
||||
1. **A newly created seat lacks the queue, startup context, or role files it needs to operate.** Topology mutation creates the seat, but the seat needs more than a tmux session to be useful.
|
||||
2. **Edges and permissions are not updated when a seat is added or removed.** Topology references go stale; later workflows route to nonexistent seats.
|
||||
3. **Adopt/bind succeeds at the tmux/session layer but not at the OpenRig identity layer.** The session is attached but `rig whoami` doesn't know about it; downstream consumers see partial state.
|
||||
4. **Shrink/remove leaves stale topology references that later workflows route into.** Cleanup is part of the operation, not an afterthought.
|
||||
|
||||
## Proof standard
|
||||
|
||||
Proof must cover **mutation while a rig is active**, not just in a
|
||||
clean test fixture. The useful matrix:
|
||||
|
||||
| Operation | What to verify |
|
||||
|---|---|
|
||||
| Add seat | New seat has queue, startup context, role; `rig whoami` resolves it |
|
||||
| Remove seat | Stale references cleaned; edges/permissions updated |
|
||||
| Adopt existing session | tmux session bound at OpenRig identity layer; `rig whoami` reports correctly |
|
||||
| Attach observer terminal | External CLI attachment recorded |
|
||||
| Verify topology projections after each move | `rig ps --nodes` reflects current truth, not pre-mutation cache |
|
||||
|
||||
A clean-fixture proof is necessary but not sufficient. Live-rig proof
|
||||
catches the failure modes that fixture-mode misses.
|
||||
|
||||
## Why important strategically
|
||||
|
||||
The current coordination experiments repeatedly need new queues,
|
||||
watchdogs, humans, and test seats — which makes this family
|
||||
**strategically important.** Seat continuity work will eventually
|
||||
separate stable seat identity from runtime occupant identity (see
|
||||
`seat-continuity-and-handover`).
|
||||
|
||||
## Currently shipped surfaces
|
||||
|
||||
Per `cli-reference.md` v0.2.0:
|
||||
|
||||
- `rig expand <rig-id> <pod-fragment-path>` (with optional `session_source`)
|
||||
- `rig shrink <rigId> <podRef>`
|
||||
- `rig launch <rigId> <nodeRef>`
|
||||
- `rig remove <rigId> <nodeRef>`
|
||||
- `rig discover [--draft]`
|
||||
- `rig bind <discoveredId> --rig <rigId> (--node <id> | --pod <ns> --member <name>)`
|
||||
- `rig adopt <path> --bind <logicalId=tmuxSessionOrDiscoveryId>`
|
||||
- `rig attach --self --rig <rigId> --node <logicalId>`
|
||||
- `rig unclaim <sessionRef>` / `rig release <rigId>`
|
||||
|
||||
## Active proof gap (current)
|
||||
|
||||
The 2026-04-30 topology mutation add-seat proof pass is **active**.
|
||||
Product Lab shaped it; planner authored `IMPLEMENTATION.md`; driver
|
||||
landed the smallest honest CLI retry-guidance patch for failed
|
||||
`rig expand` recovery. **Remaining proof is the Section B disposable-rig
|
||||
runtime matrix, blocked on operator posture** and owned by
|
||||
`orch-lead@your-rig`.
|
||||
|
||||
## See also
|
||||
|
||||
- `openrig-user` skill — CLI surface for `rig expand / shrink / launch / remove / bind / adopt / attach`
|
||||
- `seat-scaling-and-specialization` skill — when to add specialized capacity vs generic
|
||||
- `seat-continuity-and-handover` skill — replacing an occupant on a stable seat (different shape than topology mutation)
|
||||
- `cross-host-rig-commands` skill — cross-host topology mutation (deferred)
|
||||
@@ -0,0 +1,125 @@
|
||||
---
|
||||
name: watchdog
|
||||
description: Use when configuring `rig watchdog` policies, authoring wake/refocus/alignment-checkpoint messages, or choosing the right intervention level for a stale-owner situation. The 3-level continuity-check stack (wake / refocus / alignment-checkpoint), the discipline that prevents cadence pollution and bureaucracy theater, and the artifact-pool loop-edge pattern for evidence-aware waking.
|
||||
metadata:
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
# Sibling sweep 2026-07-19 audit: superseded control-plane-* family
|
||||
# dropped (control-plane-watchdog now redirects HERE); kept the
|
||||
# genuinely adjacent set.
|
||||
- queue-handoff
|
||||
- workflow-runtime
|
||||
- alignment-trace
|
||||
- looping-workflows
|
||||
- intake-routing
|
||||
- human-in-the-loop
|
||||
- status-not-chat-orchestrator
|
||||
---
|
||||
|
||||
# Watchdog
|
||||
|
||||
Continuity checks are timed or evidence-triggered interventions that
|
||||
keep an agent workflow from going idle, drifting, or entering needless
|
||||
bureaucracy. They operationalize the alignment-trace doctrine.
|
||||
|
||||
## Use this when
|
||||
|
||||
- **Authoring a watchdog policy** for a long-running rig (artifact-pool
|
||||
edges, stale-owner detection, periodic reminders).
|
||||
- **Choosing the intervention level** for a stale-owner situation: is
|
||||
this a wake, a refocus, or an alignment checkpoint?
|
||||
- **Drafting wake/refocus/alignment-checkpoint message text** that
|
||||
prevents cadence pollution and bureaucracy theater.
|
||||
- **Deciding cadence** — scan vs wake intervals, conservative vs
|
||||
aggressive nudging.
|
||||
|
||||
## Don't use this when
|
||||
|
||||
- The agent is actively working and closing artifacts. Prefer no-op.
|
||||
- The intervention is masking bad startup or workflow design — fix the
|
||||
underlying cause, don't compensate via watchdog.
|
||||
- The work has a clear next-action handoff already in queue. Use queue
|
||||
nudges instead of a watchdog policy.
|
||||
|
||||
## The 3-level intervention stack
|
||||
|
||||
| Level | Goal | When | What it does |
|
||||
|---|---|---|---|
|
||||
| **Wake** | Restart motion | Owner appears idle, stale, blocked, or missing a next handoff | Small liveness nudge — does NOT reframe the work |
|
||||
| **Refocus** | Correct drift | Output shows mode drift, approval regression, weak stop-condition reasoning | Medium alignment nudge — re-centers on role, north star, current approved workstream, coordination mode, stop conditions; does NOT interrupt valid work |
|
||||
| **Alignment checkpoint** | Rebuild shared map | Phase boundary, lifecycle mutation, product-intent decision, confusing contradiction | Larger deliberate pause — agent runs full alignment-trace before proceeding |
|
||||
|
||||
`cron`, timers, and `rig watchdog` are scheduling substrates. They
|
||||
should NOT imply that every tick means the same semantic action. The
|
||||
intervention level is chosen by evidence, not cadence.
|
||||
|
||||
## Current best practice for refocus message text
|
||||
|
||||
A well-shaped refocus message:
|
||||
|
||||
- Starts with: **finish current action first**.
|
||||
- Names the intervention kind: wake, refocus, or alignment checkpoint.
|
||||
- Names the current approved workstream or says none is known.
|
||||
- Says what continuity means: continue, verify, hand off, or explicitly park.
|
||||
- Names stop conditions: scope/risk/posture changes, failed gate, contradictory evidence, or no continuity chain naming a sensible next step.
|
||||
- Does NOT convert itself into a fresh approval gate.
|
||||
- Does NOT wake delivery seats unless an approved workflow exists and the owner is stale.
|
||||
|
||||
## Failure modes (7; verbatim)
|
||||
|
||||
1. Cadence is too frequent and pollutes the workstream.
|
||||
2. Watchdog wakes the wrong seat instead of the stale owner.
|
||||
3. Refocus text is too rule-shaped and creates brittle behavior.
|
||||
4. Watchdog compensates for bad startup or workflow design instead of revealing it.
|
||||
5. Refocus is misread as a new top-priority task and interrupts the current action.
|
||||
6. Refocus becomes bureaucracy theater: an already-approved workflow stops for re-approval.
|
||||
7. Repeated static nudges teach agents to answer the reminder instead of progressing the artifact.
|
||||
|
||||
## Artifact-pool loop edges (the first evidence-aware pattern)
|
||||
|
||||
The first evidence-aware watchdog use that should remain small and
|
||||
explicit:
|
||||
|
||||
- **Consumer-pool wake**: if a ready artifact exists, wake the consumer loop head.
|
||||
- **Producer-edge repair**: if upstream completion exists but the downstream artifact is missing, wake the producer loop head.
|
||||
|
||||
**Scan cadence and wake cadence are separate.** Worked example (from the
|
||||
RSI v2 mission, now archived — the numbers are era-specific, the
|
||||
scan-vs-wake separation is the durable rule): scan every 30 seconds, wake
|
||||
at most every 600 seconds while work remains actionable.
|
||||
|
||||
This is not a generic workflow engine. It's a guardrail against cold
|
||||
pools and missing edge artifacts.
|
||||
|
||||
## Two surfaces: rigx watchdog (config-layer) and rig watchdog (daemon-shipped)
|
||||
|
||||
| Surface | Status | Policies |
|
||||
|---|---|---|
|
||||
| `rigx watchdog` (config-layer dogfood) | Tmux-backed loops; coexists with daemon | Static periodic-reminder + artifact-pool-ready + edge-artifact-required (per-RSI-loop) |
|
||||
| `rig watchdog` (daemon-shipped, v0.2.0 Phase C) | SQLite-backed scheduler; survives daemon restart | `periodic-reminder` / `artifact-pool-ready` / `edge-artifact-required` / `workflow-keepalive` (Phase D — reads workflow_instances directly) |
|
||||
|
||||
Daemon `rig watchdog` is the active host coordination surface for new
|
||||
work. History records only loud evaluations (`sent` / `terminal`);
|
||||
quiet skip reasons are NOT recorded — POC parity so agents are not
|
||||
woken about scheduler polls.
|
||||
|
||||
## Future shape (current limit)
|
||||
|
||||
The mature primitive should be evidence-aware: inspect durable
|
||||
queue/workflow state, pane activity, transcript/context growth, and
|
||||
known workstream frontier; classify the intervention as no-op / wake /
|
||||
refocus / alignment-checkpoint; prefer no-op for active owners; render
|
||||
message text from the active orientation graph instead of hard-coding
|
||||
static policy.
|
||||
|
||||
Until queue substrate, activity state, and lifecycle evidence are fully
|
||||
productized at this level of granularity: keep config-layer use small
|
||||
and explicit, prefer one workflow watchdog plus targeted exception
|
||||
handling over many per-seat nag loops.
|
||||
|
||||
## See also
|
||||
|
||||
- `alignment-trace` skill — the doctrine this primitive operationalizes; full and light trace templates
|
||||
- `queue-handoff` skill — durable handoff via queue items; watchdog is complementary (watchdog wakes; queue routes)
|
||||
- `looping-workflows` skill — operating discipline for self-driving rig-shaped loops; uses watchdog policies for loop edges
|
||||
@@ -10,9 +10,9 @@ You are part of the orchestration pod. Your job is to keep the team productive,
|
||||
## Startup sequence
|
||||
|
||||
Before you summarize the rig or assign real work:
|
||||
1. Load `using-superpowers`, `openrig-user`, `orchestration-team`, `systematic-debugging`, and `verification-before-completion`. Also load `mission-slice-sop` — the operating procedure for the canonical mission/slice files (you own PROGRESS.md `§1`; run `rig scope audit` at slice-close/mission-wrap).
|
||||
1. Load `using-superpowers`, `openrig-user`, `orchestration-team`, `systematic-debugging`, and `verification-before-completion`.
|
||||
2. Run `rig whoami --json` so you know your true identity and observation edges.
|
||||
3. Run `rig ps --nodes -A --json` (v0.4.4: `--nodes` scopes to the current rig by default; `-A` for the fleet) and wait for the expected starter topology to settle.
|
||||
3. Run `rig ps --nodes --json` and wait for the expected starter topology to settle.
|
||||
4. Check recent chatroom history or direct startup messages so you know who is actually online and what they already reported.
|
||||
5. Only then announce readiness or assign work.
|
||||
|
||||
@@ -34,7 +34,7 @@ The orchestration pod is responsible for:
|
||||
**Principle:** monitoring intensity tracks **stakes × how likely you are to need to intervene, bounded to the window where that's true.** Spend tight attention only where it changes what you do, only as long as the risk lasts, then return to default. (Same evidence-not-cadence rule the `watchdog` skill applies to intervention *level*, applied to *intensity*.) **Self-test: "Can I name the stakes AND the condition that ends this close-watch?"** If not, you're hyper-monitoring.
|
||||
|
||||
**Default (almost always) — token-efficient.** Steady-state your job is the **idle-without-handoff exception**: the queue handles normal handoff; you catch the agent who finished + went idle without closing/handing off.
|
||||
- **Status lives in the queue, not panes** (`status-not-chat-orchestrator`): `rig ps` (the consolidated map) / `rig ps --nodes -A --json` + `rig queue` are your status source; do NOT reconstruct fleet-state by capturing panes (pane `rig capture` is high-bandwidth *within your own pod* — that's fine; it is not how you track cross-pod/fleet state).
|
||||
- **Status lives in the queue, not panes** (`status-not-chat-orchestrator`): `rig ps --nodes --json` + `rig queue` are your status source; do NOT reconstruct fleet-state by capturing panes (pane `rig capture` is high-bandwidth *within your own pod* — that's fine; it is not how you track cross-pod/fleet state).
|
||||
- **The watchdog is your clock** (`watchdog`): configure `rig watchdog` to wake you (~3 min); between wakes, idle (zero tokens) — no self-run sleep-loop re-reading panes at steady-state. Prefer one workflow-watchdog + targeted exception handling over many per-seat nag loops.
|
||||
- **On each wake — cheap sweep:** `rig queue` + a *filtered* `rig ps` (see "Read cheap" below) first; ONLY for a seat that looks idle/suspicious, `rig capture <session>` last few lines (never a full pane, never huge chunks); **active owner → no-op.**
|
||||
- **Read cheap — every status command has a token cost; project to the question.** The queue-first rule is about *where* status lives; this is about *how much you pay to read it*. The token bomb is the broad unfiltered dump, not the pane capture: an unfiltered fleet-wide `rig ps --nodes --json` emits ~77k tokens — for a one-rig or one-qitem question that is almost all waste, and at watchdog cadence it burns the shared account fast.
|
||||
@@ -45,7 +45,7 @@ The orchestration pod is responsible for:
|
||||
- **Self-test:** "Does this read return more than the decision in front of me needs?" If yes, narrow it before running.
|
||||
- **A watchdog turn is small:** tiny queue/frontier check → make exactly the needed durable transition or wake → park. Not a fleet-wide scan per wake.
|
||||
|
||||
**Close-monitoring — legitimate exception, deliberate + BOUNDED.** Some moments warrant tight/continuous attention — a seat doing something high-stakes, novel, or fragile where you may need to feed context, hand-hold, or intervene fast; a delicate gate; a recovery in flight. Switch in **on purpose** on a nameable trigger; **exit the instant the condition clears** (time- *and* event-bounded); don't let it bleed into steady-state. Worked example (slice-17): close through compaction-recovery / QA-runtime-proof / merge-gate; back off to queue+watchdog once the owner is active + the qitem in-progress. The anti-pattern is not tight monitoring — it's **unbounded** tight monitoring (an ambient sleep-loop with no nameable end-condition). That is what burns the shared account.
|
||||
**Close-monitoring — legitimate exception, deliberate + BOUNDED.** Some moments warrant tight/continuous attention — a seat doing something high-stakes, novel, or fragile where you may need to feed context, hand-hold, or intervene fast; a delicate gate; a recovery in flight. Switch in **on purpose** on a nameable trigger; **exit the instant the condition clears** (time- *and* event-bounded); don't let it bleed into steady-state. Worked example: close through compaction-recovery / QA-runtime-proof / merge-gate; back off to queue+watchdog once the owner is active + the qitem in-progress. The anti-pattern is not tight monitoring — it's **unbounded** tight monitoring (an ambient sleep-loop with no nameable end-condition). That is what burns the shared account.
|
||||
|
||||
### B. Intervention — correct + re-teach, don't silently substitute
|
||||
When you DO catch a dropped potato, your default is to **teach the agent the protocol, not do it for them.** Agents load the hot-potato / queue-handoff protocol and are supposed to hand off on their own; you are the **belt-and-suspenders** for when one doesn't (skill not loaded, fell out of context, or just got it wrong).
|
||||
|
||||
@@ -7,6 +7,9 @@ description: Complete operating manual for the review pod. Covers everyday revie
|
||||
|
||||
You are part of the review pod. Your value is fresh scrutiny that implementation and QA do not have.
|
||||
|
||||
## Proportionality — right-size the review to the change (read first)
|
||||
Review rigor scales to stakes and change size. A small, low-stakes diff gets a fast, focused pass; the full deep protocol (context proof, confidence scores, independent → cross-exam → convergence → roundtable) is for architecture / security / high-blast-radius changes. Don't run the heavy machinery on a one-line fix — that's ceremony, and it delays the ship it exists to protect. Catch what matters, then let good work through. The point of review is **better product shipped, not review performed.**
|
||||
|
||||
## Startup sequence
|
||||
|
||||
Before you announce a review position:
|
||||
|
||||
@@ -21,13 +21,13 @@ openrig-relationship: vendored-modified
|
||||
|---|---|---|
|
||||
| Visual Companion offer step | Standalone step #2 in the flow — "offer Visual Companion in its own message before clarifying questions" | **Removed.** OpenRig agents typically operate without a separate visual-companion mode; visual design work routes through dedicated design-pod seats. |
|
||||
| Spec self-review step | Step #7 — inline self-review for placeholders/contradictions/scope | **Removed.** Self-review is handled at the rig/orchestration layer (driver/guard pattern + review-lead). |
|
||||
| User reviews written spec | Step #8 — pause for user to review the spec file | **Removed.** OpenRig's founder-walk and orchestration gates already cover this checkpoint at a higher level. |
|
||||
| User reviews written spec | Step #8 — pause for user to review the spec file | **Removed.** OpenRig's the operator-walk and orchestration gates already cover this checkpoint at a higher level. |
|
||||
| Spec save path | `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md` | `docs/plans/YYYY-MM-DD-<topic>-design.md` (matches OpenRig's `docs/plans/` convention) |
|
||||
| Process flow diagram | Includes Visual Companion + Spec self-review nodes | Simplified to remove those nodes; edges rewired |
|
||||
|
||||
## Why these modifications (inferred)
|
||||
|
||||
- **Multi-platform / multi-step gates removed**: OpenRig's rig-level orchestration (driver → guard → qa, founder-walks) already provides the checkpoint structure that the upstream skill builds inline. Keeping those steps inside the skill double-gates the work.
|
||||
- **Multi-platform / multi-step gates removed**: OpenRig's rig-level orchestration (driver → guard → qa, the operator-walks) already provides the checkpoint structure that the upstream skill builds inline. Keeping those steps inside the skill double-gates the work.
|
||||
- **`docs/plans/` path**: OpenRig's project structure uses `docs/plans/` as the canonical home for design + implementation plan documents (matches `writing-plans` modification — both are co-ordinated).
|
||||
|
||||
## Companion files
|
||||
@@ -44,5 +44,5 @@ Watch upstream for:
|
||||
When upstream changes:
|
||||
|
||||
1. Pull non-conflicting changes into the OpenRig copy.
|
||||
2. Preserve the simplified 6-step flow and the `docs/plans/` save path unless founder direction reverses.
|
||||
2. Preserve the simplified 6-step flow and the `docs/plans/` save path unless operator direction reverses.
|
||||
3. Bump `last_upstream_check` in `SKILL.md` frontmatter.
|
||||
@@ -50,7 +50,7 @@ Watch for upstream changes to:
|
||||
When upstream changes:
|
||||
|
||||
1. Pull non-conflicting changes into the OpenRig copy.
|
||||
2. Preserve the batch-with-checkpoint structure unless founder direction reverses.
|
||||
2. Preserve the batch-with-checkpoint structure unless operator direction reverses.
|
||||
3. Re-check that the subagent-alternative pointer hasn't crept back in.
|
||||
4. Bump `last_upstream_check` in `SKILL.md` frontmatter.
|
||||
5. Note any structural shape changes in `divergence_notes`.
|
||||
@@ -4,9 +4,12 @@ description: Create distinctive, production-grade frontend interfaces with high
|
||||
license: Complete terms in LICENSE.txt
|
||||
metadata:
|
||||
openrig:
|
||||
vendored_from: "Anthropic skills (Apache 2.0; see LICENSE.txt sibling)"
|
||||
vendoring_pattern: vendored-as-is
|
||||
last_upstream_check: "2026-05-13 (diff against ~/.claude/skills/frontend-design = identical)"
|
||||
stage: factory-approved
|
||||
license_status: "see LICENSE.txt — vendor-derived; license terms apply"
|
||||
vendored_from: "unknown vendor — LICENSE.txt present at copy time; quarterly license review"
|
||||
sibling_skills:
|
||||
- shadcn
|
||||
- remotion-best-practices
|
||||
---
|
||||
|
||||
This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
||||
|
||||
@@ -16,7 +16,7 @@ Write the test first. Watch it fail. Write minimal code to pass.
|
||||
|
||||
**Core principle:** If you didn't watch the test fail, you don't know if it tests the right thing.
|
||||
|
||||
**Violating the letter of the rules is violating the spirit of the rules.**
|
||||
**A strong default in service of shipping — not a law that outranks it.** TDD earns its keep where a failing test pins down behavior you'd otherwise get wrong: core logic, contracts, tricky edge cases. Match it to stakes — reach for it where test-first genuinely de-risks the change; throwaway prototypes, one-line copy tweaks, and obvious glue don't need the ceremony. Don't dodge it with synonyms; equally, don't let it block you from shipping the working thing.
|
||||
|
||||
## When to Use
|
||||
|
||||
|
||||
@@ -44,5 +44,5 @@ Watch upstream for:
|
||||
When upstream changes:
|
||||
|
||||
1. Pull non-conflicting changes into the OpenRig copy.
|
||||
2. Do NOT re-introduce the multi-platform sections, SUBAGENT-STOP block, or Instruction Priority section unless founder direction reverses.
|
||||
2. Do NOT re-introduce the multi-platform sections, SUBAGENT-STOP block, or Instruction Priority section unless operator direction reverses.
|
||||
3. Bump `last_upstream_check` in `SKILL.md` frontmatter.
|
||||
+12
-2
@@ -16,7 +16,7 @@ Claiming work is complete without verification is dishonesty, not efficiency.
|
||||
|
||||
**Core principle:** Evidence before claims, always.
|
||||
|
||||
**Violating the letter of this rule is violating the spirit of this rule.**
|
||||
**This rule serves shipping — it is not a ritual that outranks it.** It governs one thing: *claims that a verifiable result holds* ("tests pass", "build succeeds", "bug fixed") — run the check before you assert it, and scale the check to the stakes (a one-line copy tweak is not a test-suite ceremony). Don't dodge it with synonyms; equally, don't inflate it into a tax on the word "done" or a reason to keep re-proving instead of shipping the working thing.
|
||||
|
||||
## The Iron Law
|
||||
|
||||
@@ -57,7 +57,7 @@ Skip any step = lying, not verifying
|
||||
## Red Flags - STOP
|
||||
|
||||
- Using "should", "probably", "seems to"
|
||||
- Expressing satisfaction before verification ("Great!", "Perfect!", "Done!", etc.)
|
||||
- Claiming a specific result is *proven* ("tests pass", "it's fixed", "build's green") before running the check in this message — enthusiasm itself is fine; an unverified **result claim** is the flag
|
||||
- About to commit/push/PR without verification
|
||||
- Trusting agent success reports
|
||||
- Relying on partial verification
|
||||
@@ -110,6 +110,16 @@ Skip any step = lying, not verifying
|
||||
❌ Trust agent report
|
||||
```
|
||||
|
||||
## When the check itself lies — content over shape
|
||||
|
||||
Running a verification is necessary but not sufficient: a check can exit clean and still prove nothing. These are the named ways a green check lies — the failure siblings behind "evidence before claims." (Deeper treatment of *what* you verify against: `reference-first-verification`.)
|
||||
|
||||
- **Assert on CONTENT, never shape or count.** Output that *looks* like success — a non-zero count, a clean exit, no error text — can carry failure as its content. Before trusting a check, ask what its output looks like *when it fails*: if failure and success are indistinguishable at a glance, the check proves nothing. (`[1 lines]` and `No matches found` both read as "a match" to a line-count.)
|
||||
- **Compare the returned value to the value you PASSED — never to a description of it.** A confident label (`evidenceRef NOW SET:` printed above the untouched original) is indistinguishable from a verification in a transcript. Diff the actual result against your actual input, not against a claim about it.
|
||||
- **Find the untested axis.** Thorough coverage of ONE axis reads as thorough coverage overall. Ask what every one of your tests shares — a healthy manifest, a default option value, the happy path — and treat that shared assumption as the dimension you never tested. (A 15-case "exhaustive" harness whose only defect lived on the one axis every case held constant.)
|
||||
- **A syntax check proves parseability and nothing else.** A clean `node --check` / lint / parse pass is the *covered* axis; boot and runtime are the untested one. Parseable ≠ sound.
|
||||
- **A failure whose shape is a HANG reports nothing.** A bare `await` against a stated deadline that never re-checks cannot fail loudly. Race it against a timer so failure has a shape you can see.
|
||||
|
||||
## Why This Matters
|
||||
|
||||
From 24 failure memories:
|
||||
|
||||
@@ -47,6 +47,6 @@ Watch upstream for:
|
||||
When upstream changes:
|
||||
|
||||
1. Pull non-conflicting changes into the OpenRig copy.
|
||||
2. Preserve the `docs/plans/` save path and the absence of the Scope Check + File Structure sections unless founder direction reverses.
|
||||
2. Preserve the `docs/plans/` save path and the absence of the Scope Check + File Structure sections unless operator direction reverses.
|
||||
3. Re-check that the subagent-driven-development pointer hasn't crept back in.
|
||||
4. Bump `last_upstream_check` in `SKILL.md` frontmatter.
|
||||
@@ -11,10 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [openrig-user, openrig-architect, brainstorming, requirements-writer]
|
||||
skills: [openrig-architect, brainstorming, requirements-writer]
|
||||
guidance: [role]
|
||||
subagents: []
|
||||
plugins: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -35,10 +35,11 @@ hand off.
|
||||
|
||||
Long advising sessions hit context limits. The discipline is
|
||||
externalize-state-to-durable-substrate, not in-context recall:
|
||||
recover identity via `rig whoami --json`; recover recent peer
|
||||
context via `rig transcript <session> --tail` / `--grep`; recover
|
||||
in-flight work via `rig queue list --as <me>`. Hand off load-bearing
|
||||
decisions to the queue so a fresh-context advisor can pick them up.
|
||||
recover identity via `rig whoami --json`; recover in-flight work from
|
||||
restore maps, current `MISSION_NOTES.md`, and owned queue items. Use
|
||||
`rig transcript <session> --tail` / `--grep` only as a secondary check;
|
||||
little or no output does not prove the session was quiet. Hand off
|
||||
load-bearing decisions to the queue so a fresh-context advisor can pick them up.
|
||||
If the operator has installed a richer compaction-survival skill on
|
||||
this host (substrate skill path or `~/.openrig/skills/`), load it
|
||||
for more detail.
|
||||
|
||||
@@ -11,10 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [openrig-user, openrig-operator, rig-lifecycle, systematic-debugging, verification-before-completion, openrig-installer]
|
||||
skills: [rig-lifecycle, openrig-upgrade, systematic-debugging, verification-before-completion]
|
||||
guidance: [role]
|
||||
subagents: []
|
||||
plugins: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -18,11 +18,9 @@ with them and escalate to them when ops decisions need human approval.
|
||||
4. Confirm healthy via `rig ps --nodes --rig <name>`.
|
||||
- Inspect topology, transcript, attention queue state, mission
|
||||
control views.
|
||||
- Shepherd install / upgrade / migration ceremonies. The
|
||||
`openrig-installer` skill is your reference for the V0.3.1
|
||||
upgrade flow (which includes the substrate-kernel → daemon-managed
|
||||
kernel migration as a one-time ceremony — see openrig-installer
|
||||
for the canonical steps).
|
||||
- Shepherd current install and upgrade work. Use the `openrig-upgrade`
|
||||
skill for the supported upgrade path and verify the resulting daemon
|
||||
and rig health before declaring the operation complete.
|
||||
|
||||
## What you do NOT do
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ imports:
|
||||
profiles:
|
||||
default:
|
||||
uses:
|
||||
skills: [openrig-user]
|
||||
skills: []
|
||||
guidance: [role]
|
||||
subagents: []
|
||||
plugins: []
|
||||
plugins: [shared:openrig-core]
|
||||
runtime_resources: [shared:claude-default-settings, shared:claude-default-mcp, shared:codex-default-config]
|
||||
|
||||
resources:
|
||||
|
||||
@@ -46,10 +46,9 @@ machine and have things happen.
|
||||
and surfaces a 3-part error (fact / reason / fix) per the
|
||||
building-agent-software skill discipline. No best-effort
|
||||
half-booted state.
|
||||
- **Migration ceremony is part of the upgrade.** V0.3.1 ships the
|
||||
kernel as a daemon-managed built-in; operators with a pre-existing
|
||||
substrate-rooted kernel migrate as a one-time step during the
|
||||
V0.3.1 install (openrig-installer skill walks this).
|
||||
- **Use the current upgrade path.** The operator loads `openrig-upgrade`,
|
||||
follows the supported migration guidance for the installed version,
|
||||
and verifies daemon plus rig health before closing the operation.
|
||||
- **Skills earn their slot.** Each agent loads a lean roster at
|
||||
startup (per HOST-TOPOLOGY §4.10); the rest are reachable on demand
|
||||
via find-skills.
|
||||
|
||||
@@ -102,6 +102,44 @@ export class PluginVendorService {
|
||||
}
|
||||
}
|
||||
|
||||
/** Project one plugin skill into the harness-global skill roots. */
|
||||
ensureSkillGlobally(
|
||||
pluginName: string,
|
||||
skillName: string,
|
||||
globalSkillRoots: string[],
|
||||
): void {
|
||||
const sourceDir = nodePath.join(
|
||||
this.userPluginsDir,
|
||||
pluginName,
|
||||
"skills",
|
||||
skillName,
|
||||
);
|
||||
if (!this.fs.exists(sourceDir)) {
|
||||
throw new Error(
|
||||
`Required global seed '${skillName}' is missing from plugin '${pluginName}'`,
|
||||
);
|
||||
}
|
||||
|
||||
const files = this.fs.listFiles(sourceDir);
|
||||
for (const root of globalSkillRoots) {
|
||||
const targetDir = nodePath.join(root, skillName);
|
||||
this.fs.mkdirp(targetDir);
|
||||
for (const relPath of files) {
|
||||
const srcPath = nodePath.join(sourceDir, relPath);
|
||||
const destPath = nodePath.join(targetDir, relPath);
|
||||
const content = this.fs.readFile(srcPath);
|
||||
if (
|
||||
this.fs.exists(destPath) &&
|
||||
hashContent(this.fs.readFile(destPath)) === hashContent(content)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
this.fs.mkdirp(nodePath.dirname(destPath));
|
||||
this.fs.writeFile(destPath, content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to fetch the latest plugin tree from
|
||||
* github.com/mvschwarz/openrig-plugins. Tolerates 404, network errors,
|
||||
|
||||
@@ -625,6 +625,10 @@ export async function createDaemon(opts?: DaemonOptions): Promise<DaemonResult>
|
||||
logger: (...args) => console.log("[openrig]", ...args),
|
||||
});
|
||||
await vendorService.ensureLatest("openrig-core");
|
||||
vendorService.ensureSkillGlobally("openrig-core", "openrig-skills", [
|
||||
nodePath.join(os.homedir(), ".claude", "skills"),
|
||||
nodePath.join(os.homedir(), ".agents", "skills"),
|
||||
]);
|
||||
} catch (err) {
|
||||
console.error(`[openrig] plugin vendor setup warning: ${(err as Error).message}`);
|
||||
}
|
||||
|
||||
@@ -163,11 +163,56 @@ describe("control-plane JSON generator", () => {
|
||||
});
|
||||
expect(layout.skills["stale-only"]).toBeUndefined();
|
||||
expect(layout.skills.future).toEqual({
|
||||
edges: ["plugin", "spec"],
|
||||
edges: ["canonical", "plugin", "spec"],
|
||||
category: "process",
|
||||
});
|
||||
});
|
||||
|
||||
it("projects spec overrides onto the canonical mirror edge", async () => {
|
||||
const generator = await loadGenerator();
|
||||
const root = tempRoot();
|
||||
seedEdges(root);
|
||||
|
||||
const layout = await generator.extractSkillEdgeLayout({
|
||||
repoRoot: root,
|
||||
config: {
|
||||
version: 0,
|
||||
owner: "skills-architect@example",
|
||||
edges: edgeConfig(),
|
||||
extract_from_committed_trees: true,
|
||||
forward_overrides: {
|
||||
future: { edges: ["spec"], category: "process" },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(layout.skills.future).toEqual({
|
||||
edges: ["canonical", "spec"],
|
||||
category: "process",
|
||||
});
|
||||
});
|
||||
|
||||
it("removes an empty-edge override from the generated product layout", async () => {
|
||||
const generator = await loadGenerator();
|
||||
const root = tempRoot();
|
||||
seedEdges(root);
|
||||
|
||||
const layout = await generator.extractSkillEdgeLayout({
|
||||
repoRoot: root,
|
||||
config: {
|
||||
version: 0,
|
||||
owner: "skills-architect@example",
|
||||
edges: edgeConfig(),
|
||||
extract_from_committed_trees: true,
|
||||
forward_overrides: {
|
||||
alpha: { edges: [], category: null },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(layout.skills.alpha).toBeUndefined();
|
||||
});
|
||||
|
||||
it("rejects malformed forward overrides with the source path and reason", async () => {
|
||||
const generator = await loadGenerator();
|
||||
const root = tempRoot();
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
// OPR.0.4.4.23 (arch S2) — the bundled openrig-core plugin's copy of
|
||||
// mission-slice-sop must be MECHANICALLY pinned to the canonical product
|
||||
// skill source: hand-sync without a guard is banned. This is the
|
||||
// scope-audit-copies pattern (byte-parity CI test) applied to the skill —
|
||||
// the mirror-skills script covers specs → skills/_canonical, and this test
|
||||
// covers specs → the bundled plugin. Any edit to one copy fails here until
|
||||
// the other copy is refreshed (cp, byte-for-byte).
|
||||
// OPR.0.4.4.23 originally pinned duplicate spec/plugin copies. The vendoring
|
||||
// placement ruling now makes mission-slice-sop and openrig-user plugin-only:
|
||||
// universal delivery comes from openrig-core, so recreating a spec copy would
|
||||
// reintroduce the drift this guard was meant to prevent.
|
||||
|
||||
import { describe, expect, it } from "vitest";
|
||||
import fs from "node:fs";
|
||||
@@ -14,61 +11,28 @@ import { fileURLToPath } from "node:url";
|
||||
const here = path.dirname(fileURLToPath(import.meta.url));
|
||||
const repoRoot = path.resolve(here, "..", "..", "..");
|
||||
|
||||
const CANONICAL_SOURCE = path.join(
|
||||
repoRoot,
|
||||
"packages/daemon/specs/agents/shared/skills/core/mission-slice-sop/SKILL.md",
|
||||
);
|
||||
const PLUGIN_COPY = path.join(
|
||||
repoRoot,
|
||||
"packages/daemon/assets/plugins/openrig-core/skills/mission-slice-sop/SKILL.md",
|
||||
);
|
||||
|
||||
// aa922842 — openrig-user is the SECOND skill whose canonical and bundled-plugin copies both
|
||||
// carry the conventions pointer, so the dual-context rewrite edits both. Unlike
|
||||
// mission-slice-sop it had NO byte-parity guard: mirror-skills covers specs → _canonical, and
|
||||
// the S2 test above covered specs → plugin for exactly one skill. Verified by negative search
|
||||
// over packages/*/test (openrig-core-plugin.test.ts asserts tree existence, not byte parity;
|
||||
// skill-audit.test.ts has no equality assertion). Editing an unguarded pair is how the repo
|
||||
// ends up correct while the shipped plugin ships stale — pin it before touching it.
|
||||
const PARITY_PINNED_SKILLS = ["mission-slice-sop", "openrig-user"] as const;
|
||||
|
||||
function canonicalPath(skill: string): string {
|
||||
return path.join(repoRoot, `packages/daemon/specs/agents/shared/skills/core/${skill}/SKILL.md`);
|
||||
}
|
||||
function pluginPath(skill: string): string {
|
||||
return path.join(repoRoot, `packages/daemon/assets/plugins/openrig-core/skills/${skill}/SKILL.md`);
|
||||
}
|
||||
|
||||
describe("OPR.0.4.4.23 mission-slice-sop plugin byte-parity (S2 drift guard)", () => {
|
||||
it("both copies exist", () => {
|
||||
expect(fs.existsSync(CANONICAL_SOURCE), `missing ${CANONICAL_SOURCE}`).toBe(true);
|
||||
expect(fs.existsSync(PLUGIN_COPY), `missing ${PLUGIN_COPY}`).toBe(true);
|
||||
});
|
||||
|
||||
it("the bundled plugin copy is byte-identical to the canonical skill source", () => {
|
||||
const source = fs.readFileSync(CANONICAL_SOURCE);
|
||||
const plugin = fs.readFileSync(PLUGIN_COPY);
|
||||
expect(
|
||||
source.equals(plugin),
|
||||
"mission-slice-sop drifted between the canonical skill source and the bundled plugin — refresh the plugin copy byte-for-byte (cp source → plugin); hand-edited divergence is banned (OPR.0.4.4.23 S2)",
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("aa922842 canonical→plugin byte-parity, extended to every conventions-carrying skill", () => {
|
||||
for (const skill of PARITY_PINNED_SKILLS) {
|
||||
it(`${skill}: canonical and bundled plugin copies both exist`, () => {
|
||||
expect(fs.existsSync(canonicalPath(skill)), `missing ${canonicalPath(skill)}`).toBe(true);
|
||||
expect(fs.existsSync(pluginPath(skill)), `missing ${pluginPath(skill)}`).toBe(true);
|
||||
});
|
||||
|
||||
it(`${skill}: bundled plugin copy is byte-identical to canonical`, () => {
|
||||
const source = fs.readFileSync(canonicalPath(skill));
|
||||
const plugin = fs.readFileSync(pluginPath(skill));
|
||||
expect(
|
||||
source.equals(plugin),
|
||||
`${skill} drifted between the canonical skill source and the bundled plugin — refresh the plugin copy byte-for-byte (cp source → plugin). mirror-skills does NOT cover this pair; hand-edited divergence is banned.`,
|
||||
).toBe(true);
|
||||
describe("OPR.0.4.7 vendoring — universal skills have one plugin home", () => {
|
||||
for (const skill of ["mission-slice-sop", "openrig-user"] as const) {
|
||||
it(`${skill}: ships from the plugin and has no spec/canonical duplicate`, () => {
|
||||
const plugin = path.join(
|
||||
repoRoot,
|
||||
`packages/daemon/assets/plugins/openrig-core/skills/${skill}/SKILL.md`,
|
||||
);
|
||||
const spec = path.join(
|
||||
repoRoot,
|
||||
`packages/daemon/specs/agents/shared/skills/core/${skill}/SKILL.md`,
|
||||
);
|
||||
const canonical = path.join(
|
||||
repoRoot,
|
||||
`skills/_canonical/core/${skill}/SKILL.md`,
|
||||
);
|
||||
expect(fs.existsSync(plugin), `missing ${plugin}`).toBe(true);
|
||||
expect(fs.existsSync(spec), `redundant spec copy ${spec}`).toBe(false);
|
||||
expect(fs.existsSync(canonical), `redundant canonical copy ${canonical}`).toBe(false);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -106,8 +70,8 @@ function readDescription(file: string): string {
|
||||
}
|
||||
|
||||
describe("aa922842 mission-slice-sop description budget + trigger preservation", () => {
|
||||
it(`the canonical description fits the ${DESCRIPTION_BUDGET_BYTES}-byte retrieval budget`, () => {
|
||||
const description = readDescription(CANONICAL_SOURCE);
|
||||
it(`the shipped description fits the ${DESCRIPTION_BUDGET_BYTES}-byte retrieval budget`, () => {
|
||||
const description = readDescription(PLUGIN_COPY);
|
||||
const bytes = Buffer.byteLength(description, "utf-8");
|
||||
expect(
|
||||
bytes,
|
||||
@@ -116,7 +80,7 @@ describe("aa922842 mission-slice-sop description budget + trigger preservation",
|
||||
});
|
||||
|
||||
it("every named trigger term survives the trim", () => {
|
||||
const description = readDescription(CANONICAL_SOURCE).toLowerCase();
|
||||
const description = readDescription(PLUGIN_COPY).toLowerCase();
|
||||
const missing = REQUIRED_TRIGGERS.filter((t) => !description.includes(t.toLowerCase()));
|
||||
expect(
|
||||
missing,
|
||||
@@ -124,9 +88,4 @@ describe("aa922842 mission-slice-sop description budget + trigger preservation",
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it("the bundled plugin copy carries the same description (budget survives the byte-copy)", () => {
|
||||
// Byte-parity above already implies this, but asserting it directly means a future
|
||||
// refactor that relaxes parity cannot silently ship an over-budget installed skill.
|
||||
expect(readDescription(PLUGIN_COPY)).toBe(readDescription(CANONICAL_SOURCE));
|
||||
});
|
||||
});
|
||||
@@ -18,25 +18,20 @@ import * as nodePath from "node:path";
|
||||
|
||||
const PLUGIN_ROOT = nodePath.resolve(import.meta.dirname, "../assets/plugins/openrig-core");
|
||||
|
||||
// Skills shipping in openrig-core v0. Slice 29 deleted 4 skills that were
|
||||
// mis-imports or duplicates:
|
||||
// - claude-compact-in-place (was a SPEC, not a skill)
|
||||
// - session-compaction-and-restore (replaced by claude-compaction-restore)
|
||||
// - permission-posture (internal-only doctrine, not operator-facing)
|
||||
// - openrig-compaction-instructions (empty leftover from slice 27)
|
||||
// Remaining: 11 operator-facing skills; slice 32 added mission-slice-sop.
|
||||
// Tier A is the universal skill spine projected into every shipped/default
|
||||
// agent CWD. Role-specific skills stay on the spec-selected edge; host-only
|
||||
// skills do not enter the product edges.
|
||||
const EXPECTED_SKILLS = [
|
||||
"agent-startup-and-context-ingestion",
|
||||
"claude-compaction-restore",
|
||||
"forming-an-openrig-mental-model",
|
||||
"messaging-the-human",
|
||||
"mission-slice-sop",
|
||||
"openrig-architect",
|
||||
"openrig-cmux",
|
||||
"openrig-herdr",
|
||||
"openrig-operator",
|
||||
"openrig-skills",
|
||||
"openrig-user",
|
||||
"queue-handoff",
|
||||
"seat-continuity-and-handover",
|
||||
"session-compaction-and-restore",
|
||||
"software-for-agents",
|
||||
];
|
||||
|
||||
describe("openrig-core plugin — vendored tree shape (HG-2.1)", () => {
|
||||
@@ -117,7 +112,7 @@ describe("openrig-core plugin — skills (HG-2.1 skill content per agentskills.i
|
||||
expect(desc.length).toBeLessThanOrEqual(1024);
|
||||
});
|
||||
|
||||
it("ships exactly the 11 expected skills (no drift; no missing skills; slice 29 deleted 4, slice 32 added mission-slice-sop, OPR.0.4.6.02 added openrig-herdr/openrig-cmux)", () => {
|
||||
it("ships exactly the Tier-A universal spine", () => {
|
||||
const skillsDir = nodePath.join(PLUGIN_ROOT, "skills");
|
||||
const actual = fs.readdirSync(skillsDir).filter((f) =>
|
||||
fs.statSync(nodePath.join(skillsDir, f)).isDirectory()
|
||||
@@ -126,9 +121,42 @@ describe("openrig-core plugin — skills (HG-2.1 skill content per agentskills.i
|
||||
expect(actual.sort()).toEqual([...EXPECTED_SKILLS].sort());
|
||||
});
|
||||
|
||||
it("routes openrig-user readers through the global skill index", () => {
|
||||
const userSkill = fs.readFileSync(
|
||||
nodePath.join(PLUGIN_ROOT, "skills", "openrig-user", "SKILL.md"),
|
||||
"utf-8",
|
||||
);
|
||||
expect(userSkill).toContain("openrig-skills");
|
||||
});
|
||||
|
||||
it("gives a bare installed agent a resolvable one-hop path for every shipped skill", () => {
|
||||
const index = fs.readFileSync(
|
||||
nodePath.join(PLUGIN_ROOT, "skills", "openrig-skills", "SKILL.md"),
|
||||
"utf-8",
|
||||
);
|
||||
const layout = JSON.parse(fs.readFileSync(
|
||||
nodePath.resolve(import.meta.dirname, "../../../scripts/skill-edge-layout.generated.json"),
|
||||
"utf-8",
|
||||
)) as {
|
||||
skills: Record<string, { edges: string[]; category: string | null }>;
|
||||
};
|
||||
|
||||
expect(index).toContain("OPENRIG_CLI_ROOT");
|
||||
for (const [skillId, placement] of Object.entries(layout.skills)) {
|
||||
if (placement.edges.includes("plugin")) {
|
||||
expect(index).toContain(`~/.openrig/plugins/openrig-core/skills/${skillId}/SKILL.md`);
|
||||
} else {
|
||||
expect(placement.category).not.toBeNull();
|
||||
expect(index).toContain(
|
||||
`\${OPENRIG_CLI_ROOT}/daemon/specs/agents/shared/skills/${placement.category}/${skillId}/SKILL.md`,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("routes rig authors through the advisory spec audit in the skill and startup guide", () => {
|
||||
const architectSkill = fs.readFileSync(
|
||||
nodePath.join(PLUGIN_ROOT, "skills", "openrig-architect", "SKILL.md"),
|
||||
nodePath.resolve(import.meta.dirname, "../specs/agents/shared/skills/core/openrig-architect/SKILL.md"),
|
||||
"utf-8",
|
||||
);
|
||||
const startupGuide = fs.readFileSync(
|
||||
|
||||
@@ -40,6 +40,7 @@ function mockFs(initialFiles?: Record<string, string>) {
|
||||
const VENDORED_OPENRIG_CORE = {
|
||||
"/asset-root/openrig-core/.claude-plugin/plugin.json": '{"name":"openrig-core","version":"0.1.0"}',
|
||||
"/asset-root/openrig-core/.codex-plugin/plugin.json": '{"name":"openrig-core","version":"0.1.0","description":"v"}',
|
||||
"/asset-root/openrig-core/skills/openrig-skills/SKILL.md": "# openrig-skills index",
|
||||
"/asset-root/openrig-core/skills/openrig-user/SKILL.md": "# openrig-user vendored",
|
||||
"/asset-root/openrig-core/hooks/claude.json": '{"hooks":{}}',
|
||||
};
|
||||
@@ -69,6 +70,7 @@ describe("PluginVendorService — vendoring (HG-2.3)", () => {
|
||||
...VENDORED_OPENRIG_CORE,
|
||||
"/home/test/.openrig/plugins/openrig-core/.claude-plugin/plugin.json": '{"name":"openrig-core","version":"0.1.0"}',
|
||||
"/home/test/.openrig/plugins/openrig-core/.codex-plugin/plugin.json": '{"name":"openrig-core","version":"0.1.0","description":"v"}',
|
||||
"/home/test/.openrig/plugins/openrig-core/skills/openrig-skills/SKILL.md": "# openrig-skills index",
|
||||
"/home/test/.openrig/plugins/openrig-core/skills/openrig-user/SKILL.md": "# openrig-user vendored",
|
||||
"/home/test/.openrig/plugins/openrig-core/hooks/claude.json": '{"hooks":{}}',
|
||||
});
|
||||
@@ -103,6 +105,45 @@ describe("PluginVendorService — vendoring (HG-2.3)", () => {
|
||||
await expect(svc.ensureVendored("nonexistent-plugin")).resolves.not.toThrow();
|
||||
expect(fs._store["/home/test/.openrig/plugins/nonexistent-plugin/anything"]).toBeUndefined();
|
||||
});
|
||||
|
||||
it("projects a plugin seed skill into both harness-global skill roots", async () => {
|
||||
const fs = mockFs(VENDORED_OPENRIG_CORE);
|
||||
const svc = new PluginVendorService({
|
||||
vendoredAssetsDir: "/asset-root",
|
||||
userPluginsDir: "/home/test/.openrig/plugins",
|
||||
fs,
|
||||
httpClient: vi.fn().mockResolvedValue({ ok: false, status: 404 }),
|
||||
logger: vi.fn(),
|
||||
});
|
||||
|
||||
await svc.ensureVendored("openrig-core");
|
||||
svc.ensureSkillGlobally("openrig-core", "openrig-skills", [
|
||||
"/home/test/.claude/skills",
|
||||
"/home/test/.agents/skills",
|
||||
]);
|
||||
|
||||
expect(fs._store["/home/test/.claude/skills/openrig-skills/SKILL.md"]).toBe("# openrig-skills index");
|
||||
expect(fs._store["/home/test/.agents/skills/openrig-skills/SKILL.md"]).toBe("# openrig-skills index");
|
||||
});
|
||||
|
||||
it("fails loudly when the required global seed is missing from the vendored plugin", async () => {
|
||||
const fs = mockFs(VENDORED_OPENRIG_CORE);
|
||||
const svc = new PluginVendorService({
|
||||
vendoredAssetsDir: "/asset-root",
|
||||
userPluginsDir: "/home/test/.openrig/plugins",
|
||||
fs,
|
||||
httpClient: vi.fn().mockResolvedValue({ ok: false, status: 404 }),
|
||||
logger: vi.fn(),
|
||||
});
|
||||
|
||||
await svc.ensureVendored("openrig-core");
|
||||
expect(() =>
|
||||
svc.ensureSkillGlobally("openrig-core", "missing-seed", [
|
||||
"/home/test/.claude/skills",
|
||||
"/home/test/.agents/skills",
|
||||
]),
|
||||
).toThrow(/missing-seed/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("PluginVendorService — auto-fetch (HG-2.4 + HG-2.5)", () => {
|
||||
|
||||
@@ -317,6 +317,9 @@ profiles:
|
||||
expect(existsSync(assetPath)).toBe(true);
|
||||
const content = readFileSync(assetPath, "utf8");
|
||||
expect(content).toContain("thin bootstrap overlay");
|
||||
expect(content).toContain("openrig-skills");
|
||||
expect(content).toContain("~/.claude/skills/openrig-skills/SKILL.md");
|
||||
expect(content).toContain("~/.agents/skills/openrig-skills/SKILL.md");
|
||||
expect(content).toContain("openrig-user");
|
||||
expect(content).toContain("current project or workspace");
|
||||
expect(content).toContain("usually sees it under `.claude/skills/openrig-user/SKILL.md`");
|
||||
|
||||
@@ -48,6 +48,14 @@ const KERNEL_AGENT_SPECS = [
|
||||
"rigs/launch/kernel/agents/queue/worker/agent.yaml",
|
||||
];
|
||||
|
||||
const RUNNABLE_SHIPPED_AGENT_SPECS = [
|
||||
...AGENT_SPECS,
|
||||
"agents/factory-rsi/dogfood/agent.yaml",
|
||||
"agents/factory-rsi/release-manager/agent.yaml",
|
||||
"agents/product-management/pm/agent.yaml",
|
||||
...KERNEL_AGENT_SPECS,
|
||||
];
|
||||
|
||||
// bug-fix slice deprecation-check-keys-widening — IMPL-PRD §1.2 + §3.
|
||||
// Allowlist of removed/deprecated KEY paths the spec library MUST NOT
|
||||
// carry. Each entry uses dot-path notation with `*` as a profile-name
|
||||
@@ -356,7 +364,7 @@ describe("Starter specs", () => {
|
||||
});
|
||||
|
||||
it("openrig-user documents agent-managed apps and current cwd/env operation", () => {
|
||||
const content = readFileSync(join(SPECS_ROOT, "agents/shared/skills/core/openrig-user/SKILL.md"), "utf-8");
|
||||
const content = readFileSync(join(import.meta.dirname, "../assets/plugins/openrig-core/skills/openrig-user/SKILL.md"), "utf-8");
|
||||
|
||||
expect(content).toContain("agent-managed app");
|
||||
expect(content).toContain("rig up secrets-manager");
|
||||
@@ -382,7 +390,6 @@ describe("Starter specs", () => {
|
||||
"dogfood",
|
||||
"executing-plans",
|
||||
"frontend-design",
|
||||
"openrig-user",
|
||||
"orchestration-team",
|
||||
"development-team",
|
||||
"review-team",
|
||||
@@ -400,6 +407,15 @@ describe("Starter specs", () => {
|
||||
}
|
||||
const deprecatedHaSkill = ["mental", "model", "ha"].join("-");
|
||||
expect(sharedSkills.map((entry) => entry.id)).not.toContain(deprecatedHaSkill);
|
||||
expect(sharedSkills.map((entry) => entry.id)).not.toContain("openrig-operator");
|
||||
expect(sharedSkills.map((entry) => entry.id)).not.toContain("openrig-user");
|
||||
expect(sharedSkills.map((entry) => entry.id)).not.toContain("mission-slice-sop");
|
||||
for (const skill of sharedSkills) {
|
||||
expect(
|
||||
existsSync(join(SPECS_ROOT, "agents/shared", skill.path, "SKILL.md")),
|
||||
`missing shared skill resource ${skill.id} at ${skill.path}`,
|
||||
).toBe(true);
|
||||
}
|
||||
|
||||
const sharedRuntimeResources = (sharedResources["runtime_resources"] as Array<{ id: string; path: string; type: string }>) ?? [];
|
||||
for (const resourceId of ["claude-default-settings", "claude-default-mcp", "codex-default-config"]) {
|
||||
@@ -438,39 +454,39 @@ describe("Starter specs", () => {
|
||||
const expectedAgentSkills = new Map<string, string[]>([
|
||||
[
|
||||
"agents/conveyor/lead/agent.yaml",
|
||||
["openrig-user", "orchestration-team", "backlog-capture", "writing-plans", "executing-plans", "verification-before-completion", "brainstorming"],
|
||||
["orchestration-team", "backlog-capture", "writing-plans", "executing-plans", "verification-before-completion", "brainstorming"],
|
||||
],
|
||||
[
|
||||
"agents/conveyor/planner/agent.yaml",
|
||||
["openrig-user", "requirements-writer", "context-builder", "writing-plans", "verification-before-completion"],
|
||||
["requirements-writer", "context-builder", "writing-plans", "verification-before-completion"],
|
||||
],
|
||||
[
|
||||
"agents/conveyor/builder/agent.yaml",
|
||||
["openrig-user", "development-team", "test-driven-development", "systematic-debugging", "executing-plans", "verification-before-completion"],
|
||||
["development-team", "test-driven-development", "systematic-debugging", "executing-plans", "verification-before-completion"],
|
||||
],
|
||||
[
|
||||
"agents/conveyor/reviewer/agent.yaml",
|
||||
["openrig-user", "review-team", "plan-review", "systematic-debugging", "verification-before-completion"],
|
||||
["review-team", "plan-review", "systematic-debugging", "verification-before-completion"],
|
||||
],
|
||||
[
|
||||
"agents/design/product-designer/agent.yaml",
|
||||
["using-superpowers", "openrig-user", "development-team", "frontend-design", "brainstorming", "writing-plans", "verification-before-completion"],
|
||||
["using-superpowers", "development-team", "frontend-design", "brainstorming", "writing-plans", "verification-before-completion"],
|
||||
],
|
||||
[
|
||||
"agents/development/implementer/agent.yaml",
|
||||
["using-superpowers", "openrig-user", "development-team", "test-driven-development", "systematic-debugging", "writing-plans", "executing-plans", "verification-before-completion"],
|
||||
["using-superpowers", "development-team", "test-driven-development", "systematic-debugging", "writing-plans", "executing-plans", "verification-before-completion"],
|
||||
],
|
||||
[
|
||||
"agents/development/qa/agent.yaml",
|
||||
["using-superpowers", "openrig-user", "development-team", "systematic-debugging", "agent-browser", "dogfood", "writing-plans", "executing-plans", "verification-before-completion"],
|
||||
["using-superpowers", "development-team", "systematic-debugging", "agent-browser", "dogfood", "writing-plans", "executing-plans", "verification-before-completion"],
|
||||
],
|
||||
[
|
||||
"agents/review/independent-reviewer/agent.yaml",
|
||||
["using-superpowers", "openrig-user", "review-team", "systematic-debugging", "brainstorming", "writing-plans", "verification-before-completion"],
|
||||
["using-superpowers", "review-team", "systematic-debugging", "brainstorming", "writing-plans", "verification-before-completion"],
|
||||
],
|
||||
[
|
||||
"agents/orchestration/orchestrator/agent.yaml",
|
||||
["using-superpowers", "openrig-user", "orchestration-team", "systematic-debugging", "brainstorming", "writing-plans", "executing-plans", "verification-before-completion"],
|
||||
["using-superpowers", "orchestration-team", "systematic-debugging", "brainstorming", "writing-plans", "executing-plans", "verification-before-completion"],
|
||||
],
|
||||
]);
|
||||
|
||||
@@ -484,12 +500,48 @@ describe("Starter specs", () => {
|
||||
const defaultProfile = profiles["default"] ?? {};
|
||||
const uses = (defaultProfile["uses"] as Record<string, unknown> | undefined) ?? {};
|
||||
const skills = (uses["skills"] as string[] | undefined) ?? [];
|
||||
for (const skillId of expectedAgentSkills.get(file) ?? ["openrig-user"]) {
|
||||
for (const skillId of expectedAgentSkills.get(file) ?? []) {
|
||||
expect(skills).toContain(skillId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("declares the vendored openrig-core plugin once in the shared resource pool", () => {
|
||||
const shared = parseYaml(
|
||||
readFileSync(join(SPECS_ROOT, SHARED_AGENT_SPEC), "utf-8"),
|
||||
) as {
|
||||
resources?: {
|
||||
plugins?: Array<{
|
||||
id: string;
|
||||
source: { kind: string; path: string };
|
||||
}>;
|
||||
};
|
||||
};
|
||||
|
||||
expect(shared.resources?.plugins ?? []).toContainEqual({
|
||||
id: "openrig-core",
|
||||
source: {
|
||||
kind: "local",
|
||||
path: "~/.openrig/plugins/openrig-core",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("all 18 runnable shipped default profiles explicitly select openrig-core", () => {
|
||||
expect(RUNNABLE_SHIPPED_AGENT_SPECS).toHaveLength(18);
|
||||
|
||||
const missing = RUNNABLE_SHIPPED_AGENT_SPECS.filter((file) => {
|
||||
const raw = parseYaml(readFileSync(join(SPECS_ROOT, file), "utf-8")) as {
|
||||
profiles?: Record<string, { uses?: { plugins?: string[] } }>;
|
||||
};
|
||||
return !raw.profiles?.default?.uses?.plugins?.includes(
|
||||
"shared:openrig-core",
|
||||
);
|
||||
});
|
||||
|
||||
expect(missing).toEqual([]);
|
||||
});
|
||||
|
||||
it("starter role guidance explicitly names every packaged default skill it expects agents to load", () => {
|
||||
for (const file of STARTER_AGENT_SPECS) {
|
||||
const yaml = readFileSync(join(SPECS_ROOT, file), "utf-8");
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# OPR.0.4.4.13 FR-3 — product-factory VPS bootstrap (runs ON the VPS).
|
||||
#
|
||||
# Fresh Ubuntu -> factory-ready: the 2026-06-23 OVH smoke test's manual
|
||||
# sequence, productized. Pairs with docs/reference/product-factory-vps-runbook.md
|
||||
# (read it first: Tailscale tag/ACL setup and the home-base steps live there).
|
||||
# Fresh Ubuntu -> factory-ready: the smoke-tested manual sequence, productized.
|
||||
#
|
||||
# Usage (as root on a fresh Ubuntu 22.04/24.04 VPS):
|
||||
# ./bootstrap-product-factory-vps.sh --artifact <@openrig/[email protected] | /path/to/openrig-cli.tgz> \
|
||||
@@ -110,5 +108,4 @@ VPS side complete. From the HOME BASE now:
|
||||
3. rig host doctor <id> --posture product-factory-vps [--public-addr <public-ip>]
|
||||
4. Remove the public-SSH escape hatch once the tailnet path is verified:
|
||||
sudo ufw delete allow OpenSSH # on the VPS
|
||||
Runbook: docs/reference/product-factory-vps-runbook.md
|
||||
EOF
|
||||
@@ -17,6 +17,29 @@ test("npm pack of @openrig/cli includes scripts/check-abi.mjs in tarball", () =>
|
||||
);
|
||||
});
|
||||
|
||||
test("the private product-factory VPS runbook and its pointers do not ship", () => {
|
||||
const privateRunbook = "docs/reference/product-factory-vps-runbook.md";
|
||||
assert.equal(
|
||||
existsSync(privateRunbook),
|
||||
false,
|
||||
`${privateRunbook} is private operator canon and must not ship in the public repo or package`,
|
||||
);
|
||||
|
||||
const publicPointerSources = [
|
||||
"CHANGELOG.md",
|
||||
"scripts/bootstrap-product-factory-vps.sh",
|
||||
"docs/as-built/cli-reference.md",
|
||||
"packages/daemon/assets/plugins/openrig-core/skills/openrig-user/SKILL.md",
|
||||
];
|
||||
for (const source of publicPointerSources) {
|
||||
assert.doesNotMatch(
|
||||
readFileSync(source, "utf8"),
|
||||
/product-factory-vps-runbook/,
|
||||
`${source} still points public readers at the private VPS runbook`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// aa922842 — the conventions doc reaches agents through a THREE-path model:
|
||||
// repo source docs/reference/sdlc-conventions.md (what repo readers cite)
|
||||
// packed INTERNAL daemon/docs/reference/sdlc-conventions.md (assembly input only —
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
"/Users/wrandom/",
|
||||
"~/code/substrate/",
|
||||
"code/substrate/shared-docs/",
|
||||
".openrig/"
|
||||
".openrig/artifacts/",
|
||||
".openrig/compaction/",
|
||||
".openrig/backups/",
|
||||
".openrig/agent-images/",
|
||||
".openrig/secrets/"
|
||||
],
|
||||
"seat_and_rig_patterns": [
|
||||
"@skill-library",
|
||||
@@ -31,7 +35,6 @@
|
||||
"vm-claude-test"
|
||||
],
|
||||
"charged_terms": [
|
||||
"dogfood",
|
||||
"founder",
|
||||
"founder-owned host",
|
||||
"one open trust domain",
|
||||
|
||||
@@ -6,7 +6,20 @@
|
||||
"clean": [
|
||||
"mission-slice-sop",
|
||||
"openrig-cmux",
|
||||
"openrig-herdr"
|
||||
"openrig-herdr",
|
||||
"messaging-the-human",
|
||||
"software-for-agents",
|
||||
"openrig-skills",
|
||||
"orchestration-team",
|
||||
"development-team",
|
||||
"review-team",
|
||||
"office-hours",
|
||||
"context-builder",
|
||||
"requirements-writer",
|
||||
"ui-mockup",
|
||||
"plan-review",
|
||||
"exec-summary",
|
||||
"backlog-capture"
|
||||
],
|
||||
"ship_after_fix": [
|
||||
"openrig-user",
|
||||
@@ -14,7 +27,8 @@
|
||||
"queue-handoff",
|
||||
"seat-continuity-and-handover",
|
||||
"claude-compaction-restore",
|
||||
"openrig-architect"
|
||||
"openrig-architect",
|
||||
"agent-startup-and-context-ingestion"
|
||||
],
|
||||
"ship_misses_add": [
|
||||
"topology-mutation-and-seat-management",
|
||||
|
||||
@@ -2,15 +2,21 @@
|
||||
"version": 1,
|
||||
"edges": {
|
||||
"canonical": {
|
||||
"core/mission-slice-sop/SKILL.md": "d195ef466ddd09944ad4ddb073fa1c5e5f809c8167ac72d1a3b3277314321930",
|
||||
"core/openrig-architect/SKILL.md": "12c3ddb129cd82b304b24eb7330970c6008ce00e42badfe2961967424f2ca45e",
|
||||
"core/openrig-cmux/SKILL.md": "f54d9b0a0cf42fc9617ab26bb1a45d8b28b982091dbb4332d68b2ebda7d09208",
|
||||
"core/openrig-herdr/SKILL.md": "9301cdff9734dfaffe400c11733168a82154814023e6e021550fe28b392ef9a8",
|
||||
"core/openrig-installer/SKILL.md": "362bf919ff91dc083550e4fa2583ec349187d3ed9e0ec5443d49b704cb900e80",
|
||||
"core/openrig-operator/SKILL.md": "69d5a61f708a69b7d28aeddcd4bda0fbaec26bd4cc9f5f808bf1db16b7d8cf84",
|
||||
"core/openrig-user/SKILL.md": "a0af630b0126c870a4c9ebecb0f7df0058bae63c826a932a3b09d59f9516e5e1",
|
||||
"core/openrig-user-settings/SKILL.md": "a9650e93a669d65cabcb61409f2812bdf4a27672ba8c077c6f94fa704656fe34",
|
||||
"core/rig-lifecycle/SKILL.md": "dde7165d9c1718a154684326ea36d239b82b692b1eb8c97d65f2813a5eb82aa4",
|
||||
"core/agent-starters/SKILL.md": "dd11173ea046dd7d30e23c4fdb3f5188b003ca56ea434ebcc21e14f5e8f29b15",
|
||||
"core/agent-startup-and-context-ingestion/SKILL.md": "36b6d8f56a911c0515ee2ab99a862cb6c466c4d822bce19479293a5dbf31dca4",
|
||||
"core/attention-queue/SKILL.md": "c3faabc016bc169ed9a4724571582db8b0ba74b921baccd31342b6efc0ddb945",
|
||||
"core/cross-host-rig-commands/SKILL.md": "77305c443fb7df11a2df73e33e46b7173cd12d6899a7dec1a12b2118d85bcf02",
|
||||
"core/human-in-the-loop/SKILL.md": "0175b1f5494ad9872f3516ccf8a935cb83af054a60df1bef6b467007c1451426",
|
||||
"core/openrig-architect/SKILL.md": "b53e63d22989bb6cc2da30a79e69902ce57a109145027a4007a900fdd66ee747",
|
||||
"core/openrig-cmux/SKILL.md": "73a86eac45d68b16a38fc0a4438713c634d86061073dac96a4d9e656ea5d34dc",
|
||||
"core/openrig-herdr/SKILL.md": "37508a02f50bb69ee97c22c37ccf70aa8e37dc0784061eb2a5ad813571eebd1a",
|
||||
"core/openrig-upgrade/SKILL.md": "9315df9944625d70aa5e251fcfb1ddaa0369cb14fd7dad44bde303564deb6382",
|
||||
"core/rig-bundles-and-shareable-artifacts/SKILL.md": "e9d5103f419b971373e374474e6ef464e05f242f3fa25e63acfc0b2106651748",
|
||||
"core/rig-lifecycle/SKILL.md": "8346e01d532795b24c3dba63413ca662c7b44cc5eed39ee2e85568580f40adca",
|
||||
"core/session-source-fork/SKILL.md": "43004907271759be52436fb7f30678e9632c9794bd34dec5f96f4e929c1107f2",
|
||||
"core/specification-system/SKILL.md": "5226d6e8b1362df89ba3d5afd82e4b4add355870132ca4b140d7f9f4324ffdc1",
|
||||
"core/topology-mutation-and-seat-management/SKILL.md": "9ba55ef83d2669c23525f0874d3303a87760f3574bc77d0a53cbca9daae295ea",
|
||||
"core/watchdog/SKILL.md": "58c6ff3ce08a82ca2ff796b1c887e6832562a9ee18fee8fbfe197a5160429697",
|
||||
"pm/backlog-capture/SKILL.md": "345c2b47fc85e48c15c0d42bbb48fb27dd3b0ceec36bf59dc6ed20daaea47a84",
|
||||
"pm/context-builder/SKILL.md": "0134c9b0a9f196565109f7f51b6ec78d5c3e4b5982a0d7105a93b29952625b3c",
|
||||
"pm/exec-summary/SKILL.md": "9c06b089b4dec325b1be12b261d6a1984627808915818259d63cbf83a5448352",
|
||||
@@ -19,20 +25,20 @@
|
||||
"pm/requirements-writer/SKILL.md": "01e84e3b1fd6eb37754e45d7ba72488458c427961ec1c35a4fba4c07adc8c80d",
|
||||
"pm/ui-mockup/SKILL.md": "b527c72c73c926c3d2a61e1264279486737d429aa85d3624c4adc364c577afc8",
|
||||
"pods/development-team/SKILL.md": "8bec17cadc8bd4f06ff3593bd802e4103f08124c118c41cb1eb066e58e71ebd7",
|
||||
"pods/orchestration-team/SKILL.md": "08b87a6f73a1f163dcbefadc39adbf0c42d391b68a693e1de44ce08ac69fa312",
|
||||
"pods/review-team/SKILL.md": "1f8ad4dc3960350c373faf77e3ea90d22970766b6aa634dbbfaa765feeafe063",
|
||||
"pods/orchestration-team/SKILL.md": "eca2c8ef8df04aaae8f3094192b964235fd31b00753ad8752614127b5921b784",
|
||||
"pods/review-team/SKILL.md": "97da8b474c289f76a2c48f9d46191f3adc4e3231ae8a49ff23452e1f852e0474",
|
||||
"process/agent-browser/LOCAL-INSIGHTS.md": "e793e30464517bfe0eee3485fb03206292338552cf7ccaadb1713e39bf21b043",
|
||||
"process/agent-browser/OPENRIG.md": "d15123689824c934b51ba572bc7c4d995651e2f606e0e53697263f4ecde108c9",
|
||||
"process/agent-browser/SKILL.md": "f2709bae71a8c60f6a4b80a6873560cdea9632000ed4b28d082dfae58801199b",
|
||||
"process/brainstorming/OPENRIG.md": "608f4b913e482dc12a4d201ece1d265dff1d2bfc7d609c2f11f71cb06d5cfbbe",
|
||||
"process/brainstorming/OPENRIG.md": "583e9bfbfb01392922afbb59c178c91d8db92a1340ae218c048f251886bd04d9",
|
||||
"process/brainstorming/SKILL.md": "f65187f40745b2016332f426a44db5884687d71e53ea0883c5da992e6e66b802",
|
||||
"process/dogfood/SKILL.md": "8addc5d22813193649e8286b354ae2282975d75f1dda6d5d4b33d6ace47f438b",
|
||||
"process/dogfood/references/issue-taxonomy.md": "dee7e925f7fe001903de6cc14f9656bcda90d069bbf65a2273f22202efebba09",
|
||||
"process/dogfood/templates/dogfood-report-template.md": "55eef9286e32e595dcfca30db76352e9f1d149a78b60b54644eb701072364f35",
|
||||
"process/executing-plans/OPENRIG.md": "351f388447a01a27fbc35f08d278da635a922b54d7fded9859aaebbb0eb3eec1",
|
||||
"process/executing-plans/OPENRIG.md": "4a52d0ecdd44078be51794f0083d606ce41cdb71c4dfa6dba6146161db1743ba",
|
||||
"process/executing-plans/SKILL.md": "c73eca0a0f7101b6923c87c8bb1a85c06a9714927e5b8d0b5cf0afbbd8ccc529",
|
||||
"process/frontend-design/LICENSE.txt": "0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594",
|
||||
"process/frontend-design/SKILL.md": "cec3b51520db90c76b044e9bb7645ba6676157dc7b60786a81a97d82dc9395b4",
|
||||
"process/frontend-design/SKILL.md": "3897488693335f3b350292abe067e9f4a39a64af5ac6b1feb82074a36930273d",
|
||||
"process/systematic-debugging/CREATION-LOG.md": "b482ef9a918fbfc6c369729e8160633ddfa2332466dd362ee73f1527c239ef8b",
|
||||
"process/systematic-debugging/SKILL.md": "b2adbca870df5232f018a43f6715c7a97c3ddd9429aefa11f9248a859280c2c5",
|
||||
"process/systematic-debugging/condition-based-waiting-example.ts": "40ae5ebe497fdf310200e43fe986552546d0a22837c0d39e855db1cfd33eb88e",
|
||||
@@ -44,41 +50,46 @@
|
||||
"process/systematic-debugging/test-pressure-1.md": "0b6a915db0054577819834c79be9eb614e97bddba10d73768e1fbe91cfed048a",
|
||||
"process/systematic-debugging/test-pressure-2.md": "b2030aeffba07050e8ad573ddf87486457c4a016a786bb326235bebd856f2016",
|
||||
"process/systematic-debugging/test-pressure-3.md": "96b50a52e2c7989c9cf20fb752c47c1e9a3a70dc362f8f7989f8f5b64dac7708",
|
||||
"process/test-driven-development/SKILL.md": "4ad2e041879cb2708791de1997c9d8e491fef66f29773bb3bd7bc7412b239e8f",
|
||||
"process/test-driven-development/SKILL.md": "9a46b5891604ba0d6d39d2247bc63fc0c1766da7627b2dfbe0eb263c8e057810",
|
||||
"process/test-driven-development/testing-anti-patterns.md": "bde453bc258f06543987477c837939afaa774ea2acbd9f308d702fc452bc4283",
|
||||
"process/using-superpowers/OPENRIG.md": "3af62c62fcab2ff962a5cdf398da3031c9bd4a8fbed6bd8ffc4bf52a0205b403",
|
||||
"process/using-superpowers/OPENRIG.md": "029812750481653a862f6e17f1c7159c80999e0263956e697a4179e7e7b8fa98",
|
||||
"process/using-superpowers/SKILL.md": "df82c78ef649dee45f4b3fd3e99bcd48d716411230dbe593902b395abdaa1a6e",
|
||||
"process/verification-before-completion/SKILL.md": "ecec3b8358b9c4aa95e9331bc68758c81b2ddd6a3f37046436925290eb206bb6",
|
||||
"process/writing-plans/OPENRIG.md": "cf4d50311b02841938343bb1c25ae38bca24e489396acd52cc987f6b435e26ad",
|
||||
"process/verification-before-completion/SKILL.md": "65691874228b4d4148b3c0463aa96bb93d9c75c69041a085847a91f2f89df3f0",
|
||||
"process/writing-plans/OPENRIG.md": "95a1a40dbabe7c364f0e91c0fdedfc8225cfb9677ac98f1fa528c515d92831c6",
|
||||
"process/writing-plans/SKILL.md": "ab71f8b300a16a7d6eaf6e3c54c97019919199d519d34b4a149c2d8866fbd507"
|
||||
},
|
||||
"plugin": {
|
||||
"agent-startup-and-context-ingestion/SKILL.md": "c1d759ff3ef7edf689706fc1976f1695d1af21421ee4bf4707622a4b28f15f08",
|
||||
"claude-compaction-restore/SKILL.md": "58602493348d405af3501fe410289b28e12ba54efdebc4a98ce9d818a07aa71b",
|
||||
"claude-compaction-restore/scripts/precompact-hook.mjs": "be1161c8528f81dcecc7b3f88c17622496e6d8b7c4f376347bf4eb3b37e4d311",
|
||||
"claude-compaction-restore/SKILL.md": "16e0a2e0ef711872ede33aeacd92e22f8e1b7c851112aecd4133a9004e376722",
|
||||
"claude-compaction-restore/scripts/precompact-hook.mjs": "3b739a39210985e6aa2da493bfcda58a1587b258440444188e65133b9450ebac",
|
||||
"claude-compaction-restore/scripts/restore-from-jsonl.mjs": "9de164582eed8270d8e257860d156fade3b1295ca952c23b10d3db8569dd964c",
|
||||
"claude-compaction-restore/templates/compact-instruction.md": "682c778464517b831902ddc2678c055545899b4751a1d32391ce965d5eb7061d",
|
||||
"claude-compaction-restore/templates/post-compact-restore-instruction.md": "10a5a7e5e052f3aa000a4209f386dc4eb90a3c2bba449ca685f124714f59e47a",
|
||||
"forming-an-openrig-mental-model/SKILL.md": "ebadef30569ea07fd27e4cac87104a1ce02fe7a17838e4591c35a9a186e2e7f9",
|
||||
"mission-slice-sop/SKILL.md": "d195ef466ddd09944ad4ddb073fa1c5e5f809c8167ac72d1a3b3277314321930",
|
||||
"openrig-architect/SKILL.md": "12c3ddb129cd82b304b24eb7330970c6008ce00e42badfe2961967424f2ca45e",
|
||||
"openrig-cmux/SKILL.md": "f54d9b0a0cf42fc9617ab26bb1a45d8b28b982091dbb4332d68b2ebda7d09208",
|
||||
"openrig-herdr/SKILL.md": "9301cdff9734dfaffe400c11733168a82154814023e6e021550fe28b392ef9a8",
|
||||
"openrig-operator/SKILL.md": "5fa5223914b7242455dec8c47f4c88b2c408257b5be60cd8bfb5f340a819d948",
|
||||
"openrig-user/SKILL.md": "a0af630b0126c870a4c9ebecb0f7df0058bae63c826a932a3b09d59f9516e5e1",
|
||||
"queue-handoff/SKILL.md": "d4d5d37fb88c885ea40eb2f06ccdde2584d4b471f04fa0f9ed3059cf5446c3ee",
|
||||
"seat-continuity-and-handover/SKILL.md": "bd34b87a320cd43eb1bfaea341ce5a78b3178afe07dcbca7fd524066d61212fc"
|
||||
"forming-an-openrig-mental-model/SKILL.md": "a2767351ca4100f055182320ab413e5ad2d2c5681c6068e42a45481c07ab632c",
|
||||
"messaging-the-human/SKILL.md": "95484b323586a229d05cc2298a93a1000601dba3d47f0258c245e123fef10a53",
|
||||
"mission-slice-sop/SKILL.md": "37f0b5918a49722203058f7fa06fd5b21197be055d869c6cc6a7beee855c2e4e",
|
||||
"openrig-skills/SKILL.md": "f1c3044ff7b9e8930469980acf883bbfaa093bd8c3af0cbb184a98bcf554b44f",
|
||||
"openrig-user/SKILL.md": "4cf898bd9926132e0426da753bc2caea49644e5e86ff277bf8e20d86f53d94cb",
|
||||
"queue-handoff/SKILL.md": "9413dd28597beb4f4d4e0c1c195625bf39e559bce963e43ca3797ca448a9f2b9",
|
||||
"seat-continuity-and-handover/SKILL.md": "4ccf8535e92ce1f282af9b85a630fd6bebebd4750cae53f257818833d306e500",
|
||||
"session-compaction-and-restore/SKILL.md": "20783614bc278285743f007347ffec4fe40d5d7f28ed5fd4ef0438534785bc06",
|
||||
"software-for-agents/SKILL.md": "352e0e46a85c4ff74c6c805692de8386281030c8681c7dbd21923bd72bcfa9f8"
|
||||
},
|
||||
"spec": {
|
||||
"core/mission-slice-sop/SKILL.md": "d195ef466ddd09944ad4ddb073fa1c5e5f809c8167ac72d1a3b3277314321930",
|
||||
"core/openrig-architect/SKILL.md": "12c3ddb129cd82b304b24eb7330970c6008ce00e42badfe2961967424f2ca45e",
|
||||
"core/openrig-cmux/SKILL.md": "f54d9b0a0cf42fc9617ab26bb1a45d8b28b982091dbb4332d68b2ebda7d09208",
|
||||
"core/openrig-herdr/SKILL.md": "9301cdff9734dfaffe400c11733168a82154814023e6e021550fe28b392ef9a8",
|
||||
"core/openrig-installer/SKILL.md": "362bf919ff91dc083550e4fa2583ec349187d3ed9e0ec5443d49b704cb900e80",
|
||||
"core/openrig-operator/SKILL.md": "69d5a61f708a69b7d28aeddcd4bda0fbaec26bd4cc9f5f808bf1db16b7d8cf84",
|
||||
"core/openrig-user/SKILL.md": "a0af630b0126c870a4c9ebecb0f7df0058bae63c826a932a3b09d59f9516e5e1",
|
||||
"core/openrig-user-settings/SKILL.md": "a9650e93a669d65cabcb61409f2812bdf4a27672ba8c077c6f94fa704656fe34",
|
||||
"core/rig-lifecycle/SKILL.md": "dde7165d9c1718a154684326ea36d239b82b692b1eb8c97d65f2813a5eb82aa4",
|
||||
"core/agent-starters/SKILL.md": "dd11173ea046dd7d30e23c4fdb3f5188b003ca56ea434ebcc21e14f5e8f29b15",
|
||||
"core/agent-startup-and-context-ingestion/SKILL.md": "36b6d8f56a911c0515ee2ab99a862cb6c466c4d822bce19479293a5dbf31dca4",
|
||||
"core/attention-queue/SKILL.md": "c3faabc016bc169ed9a4724571582db8b0ba74b921baccd31342b6efc0ddb945",
|
||||
"core/cross-host-rig-commands/SKILL.md": "77305c443fb7df11a2df73e33e46b7173cd12d6899a7dec1a12b2118d85bcf02",
|
||||
"core/human-in-the-loop/SKILL.md": "0175b1f5494ad9872f3516ccf8a935cb83af054a60df1bef6b467007c1451426",
|
||||
"core/openrig-architect/SKILL.md": "b53e63d22989bb6cc2da30a79e69902ce57a109145027a4007a900fdd66ee747",
|
||||
"core/openrig-cmux/SKILL.md": "73a86eac45d68b16a38fc0a4438713c634d86061073dac96a4d9e656ea5d34dc",
|
||||
"core/openrig-herdr/SKILL.md": "37508a02f50bb69ee97c22c37ccf70aa8e37dc0784061eb2a5ad813571eebd1a",
|
||||
"core/openrig-upgrade/SKILL.md": "9315df9944625d70aa5e251fcfb1ddaa0369cb14fd7dad44bde303564deb6382",
|
||||
"core/rig-bundles-and-shareable-artifacts/SKILL.md": "e9d5103f419b971373e374474e6ef464e05f242f3fa25e63acfc0b2106651748",
|
||||
"core/rig-lifecycle/SKILL.md": "8346e01d532795b24c3dba63413ca662c7b44cc5eed39ee2e85568580f40adca",
|
||||
"core/session-source-fork/SKILL.md": "43004907271759be52436fb7f30678e9632c9794bd34dec5f96f4e929c1107f2",
|
||||
"core/specification-system/SKILL.md": "5226d6e8b1362df89ba3d5afd82e4b4add355870132ca4b140d7f9f4324ffdc1",
|
||||
"core/topology-mutation-and-seat-management/SKILL.md": "9ba55ef83d2669c23525f0874d3303a87760f3574bc77d0a53cbca9daae295ea",
|
||||
"core/watchdog/SKILL.md": "58c6ff3ce08a82ca2ff796b1c887e6832562a9ee18fee8fbfe197a5160429697",
|
||||
"pm/backlog-capture/SKILL.md": "345c2b47fc85e48c15c0d42bbb48fb27dd3b0ceec36bf59dc6ed20daaea47a84",
|
||||
"pm/context-builder/SKILL.md": "0134c9b0a9f196565109f7f51b6ec78d5c3e4b5982a0d7105a93b29952625b3c",
|
||||
"pm/exec-summary/SKILL.md": "9c06b089b4dec325b1be12b261d6a1984627808915818259d63cbf83a5448352",
|
||||
@@ -87,20 +98,20 @@
|
||||
"pm/requirements-writer/SKILL.md": "01e84e3b1fd6eb37754e45d7ba72488458c427961ec1c35a4fba4c07adc8c80d",
|
||||
"pm/ui-mockup/SKILL.md": "b527c72c73c926c3d2a61e1264279486737d429aa85d3624c4adc364c577afc8",
|
||||
"pods/development-team/SKILL.md": "8bec17cadc8bd4f06ff3593bd802e4103f08124c118c41cb1eb066e58e71ebd7",
|
||||
"pods/orchestration-team/SKILL.md": "08b87a6f73a1f163dcbefadc39adbf0c42d391b68a693e1de44ce08ac69fa312",
|
||||
"pods/review-team/SKILL.md": "1f8ad4dc3960350c373faf77e3ea90d22970766b6aa634dbbfaa765feeafe063",
|
||||
"pods/orchestration-team/SKILL.md": "eca2c8ef8df04aaae8f3094192b964235fd31b00753ad8752614127b5921b784",
|
||||
"pods/review-team/SKILL.md": "97da8b474c289f76a2c48f9d46191f3adc4e3231ae8a49ff23452e1f852e0474",
|
||||
"process/agent-browser/LOCAL-INSIGHTS.md": "e793e30464517bfe0eee3485fb03206292338552cf7ccaadb1713e39bf21b043",
|
||||
"process/agent-browser/OPENRIG.md": "d15123689824c934b51ba572bc7c4d995651e2f606e0e53697263f4ecde108c9",
|
||||
"process/agent-browser/SKILL.md": "f2709bae71a8c60f6a4b80a6873560cdea9632000ed4b28d082dfae58801199b",
|
||||
"process/brainstorming/OPENRIG.md": "608f4b913e482dc12a4d201ece1d265dff1d2bfc7d609c2f11f71cb06d5cfbbe",
|
||||
"process/brainstorming/OPENRIG.md": "583e9bfbfb01392922afbb59c178c91d8db92a1340ae218c048f251886bd04d9",
|
||||
"process/brainstorming/SKILL.md": "f65187f40745b2016332f426a44db5884687d71e53ea0883c5da992e6e66b802",
|
||||
"process/dogfood/SKILL.md": "8addc5d22813193649e8286b354ae2282975d75f1dda6d5d4b33d6ace47f438b",
|
||||
"process/dogfood/references/issue-taxonomy.md": "dee7e925f7fe001903de6cc14f9656bcda90d069bbf65a2273f22202efebba09",
|
||||
"process/dogfood/templates/dogfood-report-template.md": "55eef9286e32e595dcfca30db76352e9f1d149a78b60b54644eb701072364f35",
|
||||
"process/executing-plans/OPENRIG.md": "351f388447a01a27fbc35f08d278da635a922b54d7fded9859aaebbb0eb3eec1",
|
||||
"process/executing-plans/OPENRIG.md": "4a52d0ecdd44078be51794f0083d606ce41cdb71c4dfa6dba6146161db1743ba",
|
||||
"process/executing-plans/SKILL.md": "c73eca0a0f7101b6923c87c8bb1a85c06a9714927e5b8d0b5cf0afbbd8ccc529",
|
||||
"process/frontend-design/LICENSE.txt": "0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594",
|
||||
"process/frontend-design/SKILL.md": "cec3b51520db90c76b044e9bb7645ba6676157dc7b60786a81a97d82dc9395b4",
|
||||
"process/frontend-design/SKILL.md": "3897488693335f3b350292abe067e9f4a39a64af5ac6b1feb82074a36930273d",
|
||||
"process/systematic-debugging/CREATION-LOG.md": "b482ef9a918fbfc6c369729e8160633ddfa2332466dd362ee73f1527c239ef8b",
|
||||
"process/systematic-debugging/SKILL.md": "b2adbca870df5232f018a43f6715c7a97c3ddd9429aefa11f9248a859280c2c5",
|
||||
"process/systematic-debugging/condition-based-waiting-example.ts": "40ae5ebe497fdf310200e43fe986552546d0a22837c0d39e855db1cfd33eb88e",
|
||||
@@ -112,12 +123,12 @@
|
||||
"process/systematic-debugging/test-pressure-1.md": "0b6a915db0054577819834c79be9eb614e97bddba10d73768e1fbe91cfed048a",
|
||||
"process/systematic-debugging/test-pressure-2.md": "b2030aeffba07050e8ad573ddf87486457c4a016a786bb326235bebd856f2016",
|
||||
"process/systematic-debugging/test-pressure-3.md": "96b50a52e2c7989c9cf20fb752c47c1e9a3a70dc362f8f7989f8f5b64dac7708",
|
||||
"process/test-driven-development/SKILL.md": "4ad2e041879cb2708791de1997c9d8e491fef66f29773bb3bd7bc7412b239e8f",
|
||||
"process/test-driven-development/SKILL.md": "9a46b5891604ba0d6d39d2247bc63fc0c1766da7627b2dfbe0eb263c8e057810",
|
||||
"process/test-driven-development/testing-anti-patterns.md": "bde453bc258f06543987477c837939afaa774ea2acbd9f308d702fc452bc4283",
|
||||
"process/using-superpowers/OPENRIG.md": "3af62c62fcab2ff962a5cdf398da3031c9bd4a8fbed6bd8ffc4bf52a0205b403",
|
||||
"process/using-superpowers/OPENRIG.md": "029812750481653a862f6e17f1c7159c80999e0263956e697a4179e7e7b8fa98",
|
||||
"process/using-superpowers/SKILL.md": "df82c78ef649dee45f4b3fd3e99bcd48d716411230dbe593902b395abdaa1a6e",
|
||||
"process/verification-before-completion/SKILL.md": "ecec3b8358b9c4aa95e9331bc68758c81b2ddd6a3f37046436925290eb206bb6",
|
||||
"process/writing-plans/OPENRIG.md": "cf4d50311b02841938343bb1c25ae38bca24e489396acd52cc987f6b435e26ad",
|
||||
"process/verification-before-completion/SKILL.md": "65691874228b4d4148b3c0463aa96bb93d9c75c69041a085847a91f2f89df3f0",
|
||||
"process/writing-plans/OPENRIG.md": "95a1a40dbabe7c364f0e91c0fdedfc8225cfb9677ac98f1fa528c515d92831c6",
|
||||
"process/writing-plans/SKILL.md": "ab71f8b300a16a7d6eaf6e3c54c97019919199d519d34b4a149c2d8866fbd507"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,11 +23,26 @@
|
||||
],
|
||||
"category": "process"
|
||||
},
|
||||
"agent-starters": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"spec"
|
||||
],
|
||||
"category": "core"
|
||||
},
|
||||
"agent-startup-and-context-ingestion": {
|
||||
"edges": [
|
||||
"plugin"
|
||||
"canonical",
|
||||
"spec"
|
||||
],
|
||||
"category": null
|
||||
"category": "core"
|
||||
},
|
||||
"attention-queue": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"spec"
|
||||
],
|
||||
"category": "core"
|
||||
},
|
||||
"backlog-capture": {
|
||||
"edges": [
|
||||
@@ -56,6 +71,13 @@
|
||||
],
|
||||
"category": "pm"
|
||||
},
|
||||
"cross-host-rig-commands": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"spec"
|
||||
],
|
||||
"category": "core"
|
||||
},
|
||||
"development-team": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
@@ -97,14 +119,25 @@
|
||||
],
|
||||
"category": "process"
|
||||
},
|
||||
"mission-slice-sop": {
|
||||
"human-in-the-loop": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"plugin",
|
||||
"spec"
|
||||
],
|
||||
"category": "core"
|
||||
},
|
||||
"messaging-the-human": {
|
||||
"edges": [
|
||||
"plugin"
|
||||
],
|
||||
"category": null
|
||||
},
|
||||
"mission-slice-sop": {
|
||||
"edges": [
|
||||
"plugin"
|
||||
],
|
||||
"category": null
|
||||
},
|
||||
"office-hours": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
@@ -115,7 +148,6 @@
|
||||
"openrig-architect": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"plugin",
|
||||
"spec"
|
||||
],
|
||||
"category": "core"
|
||||
@@ -123,7 +155,6 @@
|
||||
"openrig-cmux": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"plugin",
|
||||
"spec"
|
||||
],
|
||||
"category": "core"
|
||||
@@ -131,40 +162,28 @@
|
||||
"openrig-herdr": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"plugin",
|
||||
"spec"
|
||||
],
|
||||
"category": "core"
|
||||
},
|
||||
"openrig-installer": {
|
||||
"openrig-skills": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"spec"
|
||||
"plugin"
|
||||
],
|
||||
"category": "core"
|
||||
"category": null
|
||||
},
|
||||
"openrig-operator": {
|
||||
"openrig-upgrade": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"plugin",
|
||||
"spec"
|
||||
],
|
||||
"category": "core"
|
||||
},
|
||||
"openrig-user": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"plugin",
|
||||
"spec"
|
||||
"plugin"
|
||||
],
|
||||
"category": "core"
|
||||
},
|
||||
"openrig-user-settings": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"spec"
|
||||
],
|
||||
"category": "core"
|
||||
"category": null
|
||||
},
|
||||
"orchestration-team": {
|
||||
"edges": [
|
||||
@@ -200,6 +219,13 @@
|
||||
],
|
||||
"category": "pods"
|
||||
},
|
||||
"rig-bundles-and-shareable-artifacts": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"spec"
|
||||
],
|
||||
"category": "core"
|
||||
},
|
||||
"rig-lifecycle": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
@@ -213,6 +239,32 @@
|
||||
],
|
||||
"category": null
|
||||
},
|
||||
"session-compaction-and-restore": {
|
||||
"edges": [
|
||||
"plugin"
|
||||
],
|
||||
"category": null
|
||||
},
|
||||
"session-source-fork": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"spec"
|
||||
],
|
||||
"category": "core"
|
||||
},
|
||||
"software-for-agents": {
|
||||
"edges": [
|
||||
"plugin"
|
||||
],
|
||||
"category": null
|
||||
},
|
||||
"specification-system": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"spec"
|
||||
],
|
||||
"category": "core"
|
||||
},
|
||||
"systematic-debugging": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
@@ -227,6 +279,13 @@
|
||||
],
|
||||
"category": "process"
|
||||
},
|
||||
"topology-mutation-and-seat-management": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"spec"
|
||||
],
|
||||
"category": "core"
|
||||
},
|
||||
"ui-mockup": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
@@ -248,6 +307,13 @@
|
||||
],
|
||||
"category": "process"
|
||||
},
|
||||
"watchdog": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
"spec"
|
||||
],
|
||||
"category": "core"
|
||||
},
|
||||
"writing-plans": {
|
||||
"edges": [
|
||||
"canonical",
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
---
|
||||
name: agent-starters
|
||||
description: Use when creating, refreshing, packaging, inspecting, promoting, or deprecating a named per-seat starting point — Agent Starter manifest authoring, the 6-state lifecycle (captured → named → inspectable → used → promoted → deprecated), provenance honesty, and refusal rules. NOT a VM image; a managed starting point composed from agent role + startup context + optional native session source + provenance.
|
||||
metadata:
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- claude-compaction-restore
|
||||
- mental-model-ha
|
||||
- scope-recovery
|
||||
- session-compaction-and-restore
|
||||
- agent-startup-and-context-ingestion
|
||||
- composable-priming-packs
|
||||
- session-source-fork
|
||||
- seat-continuity-and-handover
|
||||
- claude-compact-in-place
|
||||
- pre-maintenance-agent-preservation
|
||||
---
|
||||
|
||||
# Agent Starters
|
||||
|
||||
A named, reusable per-seat starting point. Composes an agent role, startup
|
||||
context, optional native session source, and provenance into something a
|
||||
user or rig can choose when creating, refreshing, or packaging a seat.
|
||||
|
||||
"Agent image" is the analogy. **Agent Starter is the cleaner product
|
||||
noun.** This is NOT a VM image — it is a managed starting point for an
|
||||
agent seat, with provenance you can inspect.
|
||||
|
||||
## Use this when
|
||||
|
||||
- Creating a new seat from a known-good starting context.
|
||||
- Refreshing a seat with `rig expand` and `starter_ref`.
|
||||
- Authoring a new starter (registry entry).
|
||||
- Inspecting an existing starter's provenance, freshness, or recommended status.
|
||||
- Promoting / deprecating starters in the registry.
|
||||
- Composing a starter with a Composable Priming Pack (record manifest id/version, runtime, source session id or transcript path, ready-check evidence, freshness state).
|
||||
|
||||
## Don't use this when
|
||||
|
||||
- You want VM-style deterministic state capture. Starters don't capture VM state.
|
||||
- You want to copy provider auth material into a starter. **Starters refer to session sources and context; they do NOT copy credentials.**
|
||||
|
||||
## What makes a starter valuable
|
||||
|
||||
A starter is valuable when it is **functional** — it carries the context the seat needs to do its task well. Functional is the *only* measure of a good starter. Size is not: a smaller starter is not a better one, and a bigger one is not worse. Whatever it took for the seat to become genuinely capable at its job is the right starter — 80K tokens or 800K.
|
||||
|
||||
Capture the seat as it naturally is at a functional, proven point. Don't pad it with context the seat doesn't use, and — just as important — don't strip context out to make it smaller. Size is an *outcome* of what the seat needed, never a target.
|
||||
|
||||
Never compact, summarize, or shrink a seat in order to make or "lean" a starter. There is nothing valuable in "smaller," and compaction is lossy — you would trade away the exact capability the starter exists to preserve. (Compaction is a separate last-resort step for a seat genuinely near its context limit, with its own before/after plan — never part of capturing a starter.)
|
||||
|
||||
## State model — 6 states
|
||||
|
||||
1. **Captured** — a useful seat/session/context pattern is identified.
|
||||
2. **Named** — it becomes an Agent Starter with stable id and owner.
|
||||
3. **Inspectable** — runtime, context inputs, session source, and provenance are visible.
|
||||
4. **Used** — a rig member or `rig expand` operation starts from it.
|
||||
5. **Promoted** — evidence shows it is recommended for a role or bundle.
|
||||
6. **Deprecated** — replaced, stale, unsafe, or incompatible.
|
||||
|
||||
## Failure modes (5)
|
||||
|
||||
1. **Overclaiming image semantics** — UI/docs imply deterministic VM-style state capture. Say "starter," name what's included, show provenance.
|
||||
2. **Hidden provenance** — users can't tell what session, context, or spec a starter came from. **Refuse promotion until provenance is inspectable.**
|
||||
3. **Stale starter** — points at outdated doctrine, missing files, or invalid native session source. **Inspect must report staleness honestly.**
|
||||
4. **Secret leakage** — starter packages or displays provider auth material. **Refuse.** Refer to session sources and context, never copy credentials.
|
||||
5. **Runtime mismatch** — starter used with unsupported runtime. **Refuse with a clear error.**
|
||||
|
||||
## Manifest shape (v0+v1 shipped)
|
||||
|
||||
```yaml
|
||||
agent_starters:
|
||||
- id: velocity-reviewer-v1
|
||||
runtime: claude-code
|
||||
agent_ref: local:reviewer
|
||||
context_refs:
|
||||
- doctrine:advisor-orchestrator-mode-judgment
|
||||
- convention:workstream-continuity
|
||||
session_source:
|
||||
mode: fork
|
||||
ref:
|
||||
kind: native_id
|
||||
value: "<prior-native-session-id>"
|
||||
```
|
||||
|
||||
Member usage:
|
||||
|
||||
```yaml
|
||||
members:
|
||||
- id: reviewer
|
||||
starter_ref:
|
||||
name: velocity-reviewer-v1
|
||||
```
|
||||
|
||||
When a starter points at a primed session produced from a Composable
|
||||
Priming Pack, record:
|
||||
- manifest id/version
|
||||
- runtime
|
||||
- source session id or transcript path
|
||||
- ready-check evidence
|
||||
- freshness state
|
||||
|
||||
## Proof matrix
|
||||
|
||||
| Surface | Test type | Authority |
|
||||
|---|---|---|
|
||||
| Registry schema accepts minimal starter | unit | daemon or config-layer prototype |
|
||||
| Inspect shows provenance and included context | unit / snapshot | daemon or CLI |
|
||||
| Member can use `starter_ref` | integration | daemon |
|
||||
| Unsupported runtime or stale source refuses honestly | unit + integration | daemon |
|
||||
| No secret material copied into starter artifact | grep / fixture | tester |
|
||||
| Bundle can include or reference starter | package inspection | bundle layer |
|
||||
|
||||
## Dependencies on other primitives
|
||||
|
||||
- **Firm**: `session-source-fork` — native conversation-source continuity for fork-based starters
|
||||
- **Firm**: `specification-system` — declarative starter and member references
|
||||
- **Soft**: `rig-bundles-and-shareable-artifacts` — shareable starter packaging
|
||||
- **Soft**: `context-engineering-and-retrieval` — richer declarative context assembly
|
||||
- **Soft**: `seat-continuity-and-handover` — refresh and swap workflows over starters
|
||||
|
||||
## Required-before-RSI
|
||||
|
||||
Agent Starters need queryable provenance and honest inspect output before
|
||||
RSI loops can rely on them for seat refresh. A workflow must be able to
|
||||
answer: "what starter did this seat use, what source session or context was
|
||||
included, and is that starter still recommended?"
|
||||
|
||||
## See also
|
||||
|
||||
- `session-source-fork` skill — low-level fork primitive that makes native session-based starters possible
|
||||
- `composable-priming-packs` skill — manifest-driven layer for producing primed sessions starters reference
|
||||
@@ -0,0 +1,112 @@
|
||||
---
|
||||
name: agent-startup-and-context-ingestion
|
||||
description: Use when designing or auditing how an agent becomes useful after launch — AGENTS.md overlays, role files, skills, rig specs, workflow specs, startup checklists, refocus messages, "rig context" surface. Covers the 4 failure modes that make startup context fail (old rig spec misses current operating mode; current agents never told about new guidance; startup file as dumping ground; orchestrator transmits implementation without preserving product intent).
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- context
|
||||
- whoami
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- claude-compaction-restore
|
||||
- mental-model-ha
|
||||
- scope-recovery
|
||||
- session-compaction-and-restore
|
||||
- agent-starters
|
||||
- composable-priming-packs
|
||||
- session-source-fork
|
||||
- seat-continuity-and-handover
|
||||
- claude-compact-in-place
|
||||
- pre-maintenance-agent-preservation
|
||||
---
|
||||
|
||||
# Agent Startup and Context Ingestion
|
||||
|
||||
How an agent becomes useful after launch: **AGENTS.md overlays, role
|
||||
files, skills, rig specs, workflow specs, startup checklists, refocus
|
||||
messages**, and any future "rig context" command or skill-librarian
|
||||
surface.
|
||||
|
||||
It is the current concrete startup path inside the broader
|
||||
context-engineering-and-retrieval primitive. Startup gets a seat into
|
||||
the right initial shape; context engineering is the larger question of
|
||||
how a seat gets the right context for the work it is doing right now.
|
||||
|
||||
**Most coordination failures are not tool failures; they are context
|
||||
failures.** Agents need to know their role, operating mode, coordination
|
||||
convention, boundaries, and current product intent. If startup context
|
||||
is scattered or stale, agents execute the wrong thing very efficiently.
|
||||
|
||||
## Use this when
|
||||
|
||||
- Authoring a new agent's startup files (role / culture / startup-context)
|
||||
- Refreshing a seat that's been running on stale guidance
|
||||
- Auditing whether agents got the current operating mode (not just what's in old files)
|
||||
- Designing the orchestrator → next-agent context-transmission shape
|
||||
- Building a startup map for OpenRig-building rigs
|
||||
|
||||
## Don't use this when
|
||||
|
||||
- The agent is being created via Agent Starter — the starter's manifest carries startup context
|
||||
- The work is artifact-backed mental-model rebuild from a packet — that's `session-compaction-and-restore`
|
||||
- The intent is to ship reusable startup content as a skill — that's `writing-skills-for-openrig`
|
||||
|
||||
## Failure modes (4)
|
||||
|
||||
1. **A new agent starts from an old rig spec and misses the current operating mode.** Specs go stale; current state must be visible at startup, not just historical config.
|
||||
2. **Guidance is written to a file that future agents read, but current agents are never told.** File edits don't propagate to running sessions. Cultural rollout (broadcast + fleet-changes-feed) is needed alongside file edits.
|
||||
3. **A startup file becomes a dumping ground and loses the map-to-canonical-sources role.** Startup should point AT canonical sources; it shouldn't TRY to be one.
|
||||
4. **The orchestrator transmits implementation instructions without preserving product intent.** Instructions decay; intent travels.
|
||||
|
||||
## Proof standard
|
||||
|
||||
Startup proof should:
|
||||
|
||||
1. **Launch or refresh** a seat
|
||||
2. **Inspect** what it actually read
|
||||
3. **Verify** it can state the current role, mode, active constraints, and next handoff convention **in its own words**
|
||||
|
||||
## Cross-runtime startup paths (5; do not collapse)
|
||||
|
||||
When a seat's startup is artifact-backed mental-model rebuild (active-work
|
||||
reentry case, distinct from reusable Agent Starters / priming packs):
|
||||
|
||||
- See the **cross-runtime restore/reentry packet standard v0**
|
||||
- Source-trust ranking applies: **`rig whoami` > target rigspec > bounded latest transcript > full transcript > touched-files > `restore-summary.json`**
|
||||
|
||||
## Memory surfaces consumed at startup
|
||||
|
||||
Per the externalized-memory-surfaces convention's 13-row inventory:
|
||||
|
||||
- **Row 7** — AGENTS/role/CULTURE/startup overlays (primary)
|
||||
- **Row 3** — startup replay context (primary)
|
||||
- **Row 12** — restore/reentry packets and Agent Starters (cross-runtime startup path)
|
||||
|
||||
The umbrella's authority-rank + permission-posture columns govern which
|
||||
surfaces a startup ingestion path can write vs only read.
|
||||
|
||||
## Startup files vs skills (the distinction)
|
||||
|
||||
Per `agent-startup-guide.md` (product reference doc) and the team handbook:
|
||||
|
||||
| Startup files | Skills |
|
||||
|---|---|
|
||||
| Rig-specific, role-specific identity | Reusable SOPs / methodology / knowledge |
|
||||
| Tell agent WHO it is, WHAT it's working on, HOW this team operates | Tell agent HOW to do something (transferable across rigs) |
|
||||
| Examples: `role.md`, `CULTURE.md`, `startup/context.md` | Examples: `openrig-user`, `test-driven-development`, `vault-user` |
|
||||
| Authored per-rig | Authored once, used everywhere |
|
||||
|
||||
Don't put skill content in startup files. Don't put identity content
|
||||
in skills. The 7-layer additive startup model (agent / profile / rig /
|
||||
culture / pod / member / operator) handles the layering.
|
||||
|
||||
## See also
|
||||
|
||||
- `mission-slice-sop` skill — the universal operating procedure for working a mission/slice (the canonical PROGRESS/PROOF/MISSION_NOTES/MISSION_BRIEF files); every agent should reach for it at startup, so this general reading contract points at it here (do NOT duplicate the SOP into seat-specific startup files).
|
||||
- `writing-skills-for-openrig` skill — authoring discipline for skill content (what doesn't belong in startup)
|
||||
- `forming-an-openrig-mental-model` skill — orientation for new agents
|
||||
- `session-compaction-and-restore` skill — restore-time startup ingestion
|
||||
- `agent-starters` skill — reusable starter manifests that compose startup context
|
||||
- `composable-priming-packs` skill — manifests that produce primed sessions
|
||||
- `externalized-memory-surfaces` skill — umbrella convention for memory surfaces this primitive consumes
|
||||
- `openrig/docs/reference/agent-startup-guide.md` (product reference doc; not a skill) — the 7-layer additive startup model + delivery hints
|
||||
@@ -0,0 +1,264 @@
|
||||
---
|
||||
name: attention-queue
|
||||
description: Coordination primitive for OpenRig. Per-agent queue files tracking in-flight work with explicit state transitions + handoff semantics + cross-agent composition. Prevents memory-loss drops; surfaces stalls mechanically; closes the feedback loop on handed-off work. Applied liberally by every agent on every kernel-supervised rig; composed views serve human attention, orch pod-load, rig pending-work.
|
||||
status: L4-insight
|
||||
authored-by: advisor-peer-observer@your-rig
|
||||
date: 2026-04-13
|
||||
cited-captures:
|
||||
- improvements-inbox.md 2026-04-13T12:54:50Z — broadcast primitive RSI (same batching-by-theme cluster)
|
||||
- Mission 4 cmux stall (2026-04-13 midday) — packet-design + queue-for-cross-rig coordination
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- chatroom
|
||||
- send
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- queue-handoff
|
||||
- workflow-runtime
|
||||
- watchdog
|
||||
- alignment-trace
|
||||
- looping-workflows
|
||||
- intake-routing
|
||||
- human-in-the-loop
|
||||
- dispatching-parallel-agents
|
||||
- subagent-driven-development
|
||||
- control-plane-capabilities
|
||||
- status-not-chat-orchestrator
|
||||
- control-plane-queue
|
||||
- control-plane-watchdog
|
||||
- control-plane-workflows
|
||||
- control-plane-delivery-loop
|
||||
- control-plane-rollout-manager
|
||||
---
|
||||
|
||||
# Attention queue
|
||||
|
||||
Use this skill when coordinating work that must survive compaction, cross-agent handoffs, or multi-hour stall detection. Applies when you'd otherwise narrate status to chat or rely on memory for pending items.
|
||||
|
||||
## Live protocol override
|
||||
|
||||
Current live routing protocol:
|
||||
|
||||
- **Known target / explicit owner that should wake now**: `rigx queue handoff <destination> "<body>" --type handoff --urgency soon`
|
||||
- **Passive durable assignment without wake-up**: `rigx queue create <destination> "<body>" --type handoff --urgency soon`
|
||||
- **Ambiguous or raw intake**: `rigx stream emit "<body>" ...`
|
||||
- **Direct dialogue / urgent 1:1 conversation**: `rig send ...`
|
||||
- **Summoned 3+ party roundtable**: `rig chatroom ...`
|
||||
|
||||
Do not cargo-cult the earlier "stream everything with `--destination`" prototype shape into the
|
||||
live control-plane. Stream is now the ambiguous-intake lane, not the universal lane.
|
||||
|
||||
## Core shape (minimum-viable discipline)
|
||||
|
||||
1. **Author a queue file at** `substrate/shared-docs/rigs/<your-rig>/state/<your-pod>/<your-member>.queue.md`. Same per-pod directory as your session log.
|
||||
2. **Every known-target hot-potato work handoff** should arrive via `rigx queue handoff`, not via `rig send`. Use `rigx queue create` only when you intentionally want a passive durable item without wake-up.
|
||||
3. **State transitions** (start → promote; finish → complete; stuck → block; hand off → handoff; completed handed-off work notifies source → handoff-complete) are appended to the entry body with timestamp. Never in-place rewrites.
|
||||
4. **Cross-rig reads permitted; cross-rig writes forbidden.** Pod-as-authority-boundary doctrine.
|
||||
|
||||
### Live command surface note
|
||||
|
||||
When the queue control-plane wrapper is installed, treat queue identity as command-resolved, not
|
||||
seat-name-guessed:
|
||||
|
||||
- `rigx queue whoami` resolves the durable queue that belongs to your current seat
|
||||
- `rigx queue list --mine` shows your queue without guessing from member name
|
||||
|
||||
This matters for continuity successors such as `lead2` or `lead5`, which may intentionally share
|
||||
the canonical `lead.queue.md` file instead of owning a separate `lead2.queue.md` or `lead5.queue.md`.
|
||||
|
||||
Known-target direct handoff on the live wrapper:
|
||||
|
||||
```bash
|
||||
rigx queue handoff orch-lead5@your-rig "Need PM shaping on queue attention loop" --type handoff --urgency soon
|
||||
```
|
||||
|
||||
Passive durable write without wake-up:
|
||||
|
||||
```bash
|
||||
rigx queue create orch-lead5@your-rig "Need PM shaping on queue attention loop" --type handoff --urgency soon
|
||||
```
|
||||
|
||||
## Six operations
|
||||
|
||||
| Op | Effect |
|
||||
|---|---|
|
||||
| append | New entry (state=pending) on inbound request |
|
||||
| promote | state=in-progress when you start work |
|
||||
| complete | state=done with optional result |
|
||||
| block | state=blocked + blocked-on=<id or condition> |
|
||||
| handoff | state=handed-off + handed-off-to=<target>/<new-id>; send rig-send with `[queue-handoff:]` prefix to target |
|
||||
| handoff-complete | target signals source that handed-off work finished (closes feedback loop) |
|
||||
| escalate | walk authority chain when blocked past tier threshold |
|
||||
| defer / drop | push-to-later or drop-with-rationale |
|
||||
|
||||
## When is something a queue handoff?
|
||||
|
||||
**Queue handoff** (`rigx queue handoff`):
|
||||
- Asks a known recipient to do new work
|
||||
- Transfers ownership of pending work
|
||||
- Names a deliverable + acceptance criteria
|
||||
|
||||
**NOT a queue handoff**:
|
||||
- Wake-ping `1`
|
||||
- PSA / broadcast / status update
|
||||
- Ack / courtesy notification / diagnostic ping / reply to question
|
||||
- Raw idea or bug where you do not yet know the right owner
|
||||
|
||||
If you do not know the correct owner, emit to stream instead of guessing.
|
||||
|
||||
## Tier-based ack + notification rules
|
||||
|
||||
- **human-gate tier** (gated items; human-watching): mandatory ack on handoff; mandatory notification on completion
|
||||
- **agent-coordination tier** (standard inter-agent work): recommended ack + notification
|
||||
- **internal-self tier** (your own to-dos): optional
|
||||
|
||||
## Read discipline
|
||||
|
||||
- Read your own queue at turn start before picking up new work
|
||||
- Orchestrators read pod-member queues on wake cadence (`1` ping)
|
||||
- Advisor-pod reads cross-rig queues for composed views + human-attention
|
||||
- Past-threshold blocked entries surface during sweeps; execute escalate op if you can't self-unblock
|
||||
|
||||
Recommended turn-start queue commands on the live wrapper:
|
||||
|
||||
```bash
|
||||
rigx queue whoami
|
||||
rigx queue list --mine
|
||||
```
|
||||
|
||||
### Resume-from-idle state sweep
|
||||
|
||||
Agents returning from idle-standby (supervisor-wake-only pings; no substantive dispatch during the window) MUST sweep adjacent state before pulling new work. Minimum sweep:
|
||||
|
||||
- Supervisor-log tail (~200 lines) at `rigs/kernel/state/supervisor-log.md`
|
||||
- human-attention.md at `substrate/shared-docs/human-attention.md`
|
||||
- Any doctrine-decisions added since last-active (`rigs/kernel/state/doctrine-decisions/`)
|
||||
- Partner queue files at `rigs/kernel/state/<pod>/<peer-member>.queue.md` (peer load-tracking for pairs)
|
||||
- **Fleet-changes-feed** at `substrate/shared-docs/fleet-changes-feed.md` (pull-native rollout surface; catches any fleet-wide doctrine / skill / convention / operational changes that landed during idle; filter by scope = fleet-wide + your rig/pod)
|
||||
|
||||
**Trigger:** first active turn after ≥3 consecutive wake-only cycles OR on peer HA-check request. Sweep before responding to HA-check so the response is grounded in current reality, not stale memory.
|
||||
|
||||
**Rationale:** own-queue-at-turn-start catches own-queue drift; adjacent-state drift is a separate failure class that requires its own read discipline. Composable with own-queue sweep (both at same reading point); adds ~2-5 minutes of read time; cheap insurance against peer-driven HA-check round-trips.
|
||||
|
||||
**Worked example (genesis):** advisor-co-observer@your-rig after ~2h idle-standing-by on 2026-04-13 — 5-of-7 HA-check items out-of-sync when peer queried. Rule addition would have caught the drift pre-query via adjacent sweep on wake-to-active transition.
|
||||
|
||||
## Status-not-chat corollary
|
||||
|
||||
Your chat pane is for operational work + ad-hoc human exchanges. Your STATUS lives in queue files + composed views. If you finish work + hit a gate-requiring next-action, do NOT narrate to chat + idle-wait. Queue-handoff to advisor-pod with `tier: human-gate`. The operator doesn't watch agent panes; they watch human-attention.md (composed from human-gate queue entries).
|
||||
|
||||
## Composed views (4 layers)
|
||||
|
||||
- **Pod-load view** — who's loaded / blocked (orch reads)
|
||||
- **Rig pending-work** — cross-pod roll-up
|
||||
- **Fleet cross-rig** — host-wide
|
||||
- **human-attention** — human-gate-tier items across all queues (advisor-pod composes)
|
||||
|
||||
v0: manual regen by orchestrators + advisor-pod.
|
||||
v0.5: terminal-node watch scripts auto-regen.
|
||||
v1: generative UI consuming structured queue data.
|
||||
|
||||
## Codex-sandbox proxy-write pattern (sanctioned workaround)
|
||||
|
||||
Codex members whose sandbox blocks substrate writes can still participate via proxy-write:
|
||||
- Codex authors content locally (e.g., `/tmp/<rig>-attention-queue/<member>.queue.md`)
|
||||
- Claude counterpart physically writes to substrate with sha256-verified integrity check
|
||||
- Subsequent state transitions via `[queue-update: <id> <new-state> <reason>]` rig-send from Codex to Claude-writer
|
||||
- Authorship preserved; only write-access delegated. Distinct from peer-injection (which is forbidden).
|
||||
|
||||
## Escalation mechanics
|
||||
|
||||
When entry stays blocked past tier threshold AND agent can't self-unblock:
|
||||
|
||||
1. Identify escalation target per authority chain:
|
||||
- Pod member → pod orchestrator
|
||||
- Pod orch → rig orch-lead
|
||||
- Rig orch-lead → kernel orch-lead OR advisor-pod (if human-gate)
|
||||
- Skip-levels allowed when agent KNOWS correct target
|
||||
2. Create new entry in escalation-target's queue with `escalated-from: <source-id>`; state=pending; priority elevated
|
||||
3. Send handoff-shape rig-send: `[queue-escalate: <new-id>] <title> — blocked <Nh> on <reason>`
|
||||
4. Update own entry: state=escalated; escalated-to=<target>/<new-id>; transitions-log appended
|
||||
|
||||
Threshold guidance: 1h human-gate / 4h agent-coordination / 24h internal-self. Rigs may tighten.
|
||||
|
||||
## Task-close RSI-check (flywheel trigger)
|
||||
|
||||
Every `complete` op on substantive work reflects briefly: "what did we learn? is this worth filing as L2 capture to improvements-inbox?"
|
||||
|
||||
Two outcomes; both leave evidence in the transition trail:
|
||||
|
||||
- **Novel observation worth filing:** append L2 capture entry to `rigs/kernel/state/improvements-inbox.md` per the v1 queue template (`state: pending` + transition trail started). Transition line in your own queue: `<ts> — RSI-check: filed <capture-id>`.
|
||||
- **Nothing novel:** transition line in your own queue: `<ts> — RSI-check: none`.
|
||||
|
||||
Applies to substantive work-streams. Does NOT apply to:
|
||||
- Wake-pings (`1`) — not a work-stream
|
||||
- Trivial status updates — nothing to reflect on
|
||||
- Pure acks / routing-map updates — no work done
|
||||
|
||||
Rationale: task-close is the deterministic interval that makes recursive-self-improvement mechanical rather than ad-hoc. Pattern named in skill-maturity-convention.md §"Task-close RSI-check discipline".
|
||||
|
||||
## Push vs pull — when to use rig-send vs queue-write
|
||||
|
||||
Not every communication belongs in the receiver's chat pane. The discipline mirrors status-not-chat: most inter-agent signals can flow through queue files (pull) rather than rig-sends (push). Reduces noise; respects receiver's attention cycle.
|
||||
|
||||
**Sender's test:** *Does my message need the receiver's attention within their next turn cycle?*
|
||||
- **Yes → push** via `rig send` (lands in chat; receiver processes on next turn)
|
||||
- **No → pull** via queue-write (write to own queue OR receiver's queue via handoff; receiver sweeps at cadence)
|
||||
|
||||
### Push (rig-send to chat) when:
|
||||
|
||||
- Receiver needs info NOW to unblock their work
|
||||
- Question requires specific answer to proceed
|
||||
- Handoff is past ack-threshold + tier=human-gate (mandatory-ack window)
|
||||
- Blocker surfacing (can't self-unblock; need help from target)
|
||||
- human-gate item needing surface to advisor-pod
|
||||
- Destructive or time-critical coordination
|
||||
|
||||
### Pull (queue-write only) when:
|
||||
|
||||
- Status update / adoption signal / cascade-complete ack
|
||||
- Non-urgent ack (within tier threshold)
|
||||
- Information that can batch in receiver's curator sweep
|
||||
- Broadcast-receipt confirmation (receiver's cadence catches it)
|
||||
- Observed patterns or captures with no time pressure
|
||||
- Resync material for HA peers (they sweep on resume-from-idle)
|
||||
|
||||
### Why this matters
|
||||
|
||||
Push-as-default floods the receiver's chat pane with status that could be pulled. Today's rollout volume proved this: during attention-queue + EMM cascades, most acks arrived as push (rig-sends) when they could have been pull (queue-writes). Receiver (advisor-pod) had to process each ping; most were status signals needing no action.
|
||||
|
||||
Pull-over-push is the queue primitive's whole point. Status lives in queue files; readers sweep at cadence; only genuine unblockers + gate-surfaces push to chat.
|
||||
|
||||
### Worked example
|
||||
|
||||
orch-lead@your-rig ack'd attention-queue cascade:
|
||||
- **Push version (what happened):** `rig send advisor-peer-observer@your-rig "[queue-handoff-ack: ...] ... cascaded to 8 pod members ..."` → lands in my chat; I read immediately; process the status
|
||||
- **Pull version (what should happen):** write ack-receipt to `rigs/openrig-build/state/orch/lead.queue.md` as state-transition on their adoption entry; I sweep their queue on my curator cadence; pick up the ack without chat-ping
|
||||
|
||||
Ack-receipts for status are pull-native. Handoff-complete notifications for human-gate items stay push (they close feedback loops on time-sensitive work).
|
||||
|
||||
### Corollary — orchestrator-to-advisor cadence
|
||||
|
||||
Orchestrators writing to their own queue files lets advisor-pod read without being interrupted. The curator-sweep pattern (advisor reads pod queues on their cadence) is the canonical pull mechanism. Push only when time-matters.
|
||||
|
||||
## Anti-patterns (don't do these)
|
||||
|
||||
- **Chat-as-status** — narrating status/gates to your chat pane + idle-waiting. Use queue + human-attention instead.
|
||||
- **Duplicate-storage** — writing the same fact in queue + session-log + chat + mission-control. Queue is authoritative for in-flight state.
|
||||
- **Peer-injection** — writing directly to another agent's queue without their authorship. Only handoff op moves work cross-queue.
|
||||
- **Silent drops** — don't leave items in pending forever without state transitions. defer or drop with rationale.
|
||||
- **Global queue** — don't try to make one queue for everyone. Per-agent primary; compose for views.
|
||||
|
||||
## Maturity status
|
||||
|
||||
**L4-insight** per skill-maturity-convention. Applied liberally across the host; evolving via observation. Feedback loop: RSI filings reshape this skill; demotion valid if convention reveals wrong shape; promotion to L5-canon requires architect+reviewer pair-review per HOST-TOPOLOGY §7 SOP.
|
||||
|
||||
Rollout date: 2026-04-13 host-wide adoption. 48h observation cycle active; RSI with learnings due ~2026-04-15.
|
||||
|
||||
## Related
|
||||
|
||||
- Spec (full reference): the internal attention-queue spec
|
||||
- Skill-maturity convention: `substrate/shared-docs/skill-maturity-convention.md`
|
||||
- Config-wrapper-code loop doctrine: `config-wrapper-code-loop` skill
|
||||
- HOST-TOPOLOGY §4 context-sharing patterns — attention queue is a new pattern here
|
||||
- SUBSTRATE-CONVENTIONS §7 HA session logs — queue lives in same per-pod directory
|
||||
@@ -0,0 +1,190 @@
|
||||
---
|
||||
name: cross-host-rig-commands
|
||||
description: Use when issuing `rig` commands against a remote host via `--host <id>` flag (single-hop SSH to a host declared in `~/.openrig/hosts.yaml`). Covers the 4 structured failure modes (ssh-unreachable / permission-gate / remote-daemon-unreachable / remote-command-failed), the `--verify` honest pass-through (SSH success is NOT verify success), and the host-registry shape. v0 supports `rig send / capture / ps / whoami --host <id>`.
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- capture
|
||||
- daemon start
|
||||
- host list
|
||||
- host show
|
||||
- ps
|
||||
- send
|
||||
- whoami
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- rig-lifecycle
|
||||
- topology-mutation-and-seat-management
|
||||
- seat-scaling-and-specialization
|
||||
- sidecar-operator
|
||||
- rig-bundles-and-shareable-artifacts
|
||||
- specification-system
|
||||
- extension-and-user-workspace
|
||||
---
|
||||
|
||||
# Cross-Host Rig Commands
|
||||
|
||||
A first-class OpenRig surface for issuing `rig` commands against a
|
||||
remote host via single-hop SSH. v0 productizes the existing SSH-envelope
|
||||
operator pattern (`ssh <host> rig <cmd>`) with declared host identity,
|
||||
explicit cross-host invocation path, preserved `--verify` semantics, and
|
||||
4 named failure modes.
|
||||
|
||||
**Current-host note (2026-07-14):** this skill still preserves the original
|
||||
SSH-v0 doctrine below, but the live host registry may also contain HTTP
|
||||
read-through/tunnel entries such as `your-vm` and `your-other-vm`. Use the
|
||||
host registry entry as ground truth for transport shape, and use
|
||||
`conventions/multi-host-naming/README.md` for host-id naming. HTTP entries
|
||||
require `url` plus exactly one of `bearer_file` or `bearer_env`.
|
||||
|
||||
**v0 is CLI-side shell-out only — `packages/daemon/` is NOT touched.**
|
||||
The remote host has its own managed `rig` available on `$PATH`.
|
||||
|
||||
## Use this when
|
||||
|
||||
- Driving a Tart VM from the host (the immediate cross-host consumer)
|
||||
- Operating Mac host A against Mac host B
|
||||
- Reading remote state via `rig ps --host` / `rig whoami --host`
|
||||
- Sending or capturing on a remote rig session (`rig send/capture --host <id>`)
|
||||
- Authoring a `~/.openrig/hosts.yaml` registry entry
|
||||
|
||||
## Don't use this when
|
||||
|
||||
- The target is local. Don't pass `--host` for local commands.
|
||||
- You need multi-hop SSH (host A → host B → host C). v0 is single-hop only.
|
||||
- You want reverse direction (remote initiates back to local). v0 is originator-pull only.
|
||||
- Cross-host **seat handover** (moving a durable owned seat across hosts) — deferred to higher-level primitives. (Cross-host **queue writes**, by contrast, now ship — see "Cross-host queue writes" below.)
|
||||
- The transport isn't SSH. v0 supports `transport: ssh` only.
|
||||
|
||||
## Cross-host queue writes (updated 2026-07-21 vs main d37a08ad)
|
||||
|
||||
Cross-host **queue writes** are no longer deferred — they ship — but the rule
|
||||
differs from the interactive verbs (`send`/`capture`/`ps`/`whoami`):
|
||||
|
||||
- **Queue writes are EXPLICIT-only.** Address the target host explicitly with
|
||||
`--host <id>` or the `member@rig@<host>` form. A queue write **never** follows a
|
||||
persisted host selection.
|
||||
- **`host select` stickiness does NOT apply to queue.** `host select` affects the
|
||||
`resolveEffectiveHost` verbs (`send`/`capture`/`ps`/`whoami`) — those follow the
|
||||
selected host — but a queue write ignores it and requires explicit addressing.
|
||||
- **Host address parsing differs** between the interactive verbs and the queue
|
||||
verbs; do not assume the interactive form carries over. When unsure, address the
|
||||
host explicitly.
|
||||
|
||||
## Host registry shape (`~/.openrig/hosts.yaml`)
|
||||
|
||||
Host ids should follow the OpenRig-work multi-host naming convention:
|
||||
`conventions/multi-host-naming/README.md`. In this environment that means
|
||||
physical hosts such as `your-vm`, local OpenRig development VMs such as
|
||||
`your-vm`, persistent product VMs such as `your-other-vm`, and VPS hosts such
|
||||
as `your-vps`. Keep old aliases during migration until no live routing
|
||||
depends on them.
|
||||
|
||||
```yaml
|
||||
hosts:
|
||||
- id: a-test-vm
|
||||
transport: ssh # v0 supports "ssh" only
|
||||
target: a-test-vm.local # DNS name, SSH config alias, or IP
|
||||
user: wrandom # optional
|
||||
notes: "Tart VM" # optional
|
||||
- id: laptop-b
|
||||
transport: ssh
|
||||
target: laptop-b.tail-scale-net
|
||||
user: wrandom
|
||||
```
|
||||
|
||||
Validation rules:
|
||||
|
||||
- `hosts` required, non-null array
|
||||
- Each entry: `id` required (non-empty, unique), `transport` required (`ssh` only), `target` required
|
||||
- `user` and `notes` optional
|
||||
- Operator-managed file; v0 does NOT include any sub-command to add/remove/list hosts (operators edit YAML directly)
|
||||
- Missing or invalid file returns a clear error pointing at the canonical path
|
||||
|
||||
## CLI surface (v0 shipped)
|
||||
|
||||
```bash
|
||||
rig send <session> "msg" --host <id> --verify
|
||||
rig capture <session> --host <id>
|
||||
rig ps --host <id> [--nodes] [...]
|
||||
rig whoami --host <id>
|
||||
```
|
||||
|
||||
Forwards every shaping flag (`--nodes`, `--full`, `--limit`, `--fields`,
|
||||
`--summary`, `--filter`, `--json`) to the remote `rig` invocation. The
|
||||
remote rig's output is verbatim passthrough on success.
|
||||
|
||||
## The 4 structured failure modes (load-bearing API contract)
|
||||
|
||||
The CLI distinguishes 4 failure modes; operators get an actionable error
|
||||
per mode; JSON output preserves the `failedStep` enum:
|
||||
|
||||
| Mode | Cause | Action |
|
||||
|---|---|---|
|
||||
| `ssh-unreachable` | SSH itself failed (connection refused, host key mismatch, DNS failure, timeout) | Verify SSH access and the registry entry |
|
||||
| `permission-gate` | SSH hit auth/permission gate (Permission denied, Keychain) | Error includes hint to keychain-over-SSH field note (L4-3 D6) |
|
||||
| `remote-daemon-unreachable` | SSH succeeded but remote `rig` reported the remote daemon was not reachable | `ssh <target> rig daemon start` |
|
||||
| `remote-command-failed` | SSH succeeded but remote `rig` exited non-zero for some other reason; remote stderr is surfaced | Read remote stderr; debug remote command |
|
||||
|
||||
Each is distinct and routable. Don't conflate them.
|
||||
|
||||
## `--verify` honest pass-through (load-bearing)
|
||||
|
||||
`--verify` against a remote target must:
|
||||
|
||||
- **Propagate** the verification request to the remote daemon (or remote `rig` invocation that talks to it)
|
||||
- **Bring back a structured verification result** (true/false + reason if false), NOT just SSH exit code 0
|
||||
- **Distinguish "SSH succeeded but verify returned false" from "SSH itself failed"** — these are different operator actions
|
||||
|
||||
**SSH success is NOT verify success.** The remote rig is authoritative
|
||||
on `--verify`; its `Verified: yes/no` line is surfaced verbatim. Verified
|
||||
at 3 layers (executor unit, command integration, source impl).
|
||||
|
||||
## Hard boundaries (do-not list)
|
||||
|
||||
- **Do NOT collapse `--verify` honest result into SSH exit code.** Operators and agents rely on the distinction.
|
||||
- **Do NOT silently retry SSH failures inside the primitive.** Surface them; let the caller decide.
|
||||
- **Do NOT introduce non-SSH transports in v0.** Goal is productizing the existing shipped pattern, not replacing it.
|
||||
- **Do NOT touch host-side daemon code as part of v0.** Cross-host shape is on the originator side.
|
||||
|
||||
## Cross-host annotation
|
||||
|
||||
Every cross-host invocation is observable as cross-host:
|
||||
|
||||
- **Operator output**: `[via host=<id> (<target>)]` annotation
|
||||
- **JSON output**: `cross_host: { host, target }` field
|
||||
|
||||
Annotation is PRESENT when `--host` is set and ABSENT otherwise
|
||||
(compat regression).
|
||||
|
||||
## Currently shipped (v0) vs deferred
|
||||
|
||||
Shipped at openrig `cdce3a6` (2026-04-30):
|
||||
- `--host <id>` flag on `rig send / capture / ps / whoami` (initial 2 commands; promoted to 4 at `6b7043a` same day)
|
||||
- Read-only host registry validation
|
||||
- Single-hop SSH executor with 4-mode `failedStep` enum
|
||||
- `--verify` honest pass-through
|
||||
- Cross-host annotation (operator + JSON)
|
||||
- Daemon untouched
|
||||
|
||||
Deferred:
|
||||
- Tier 2 real-runtime cross-host proof (disposable Tart VM cycle)
|
||||
- `rig host list / show` read-only sub-namespace (only if host count grows past comfortable manual editing)
|
||||
- Non-SSH transports
|
||||
- Multi-hop SSH
|
||||
- Reverse direction (remote initiates)
|
||||
- Connection pooling/caching
|
||||
|
||||
## See also
|
||||
|
||||
- `seat-continuity-and-handover` skill — host-aware seat-binding semantics for cross-host handover (deferred to v1 on top of this v0 baseline)
|
||||
- `openrig-user` skill — the local CLI surface that cross-host commands wrap
|
||||
|
||||
## Sender identity is ASYMMETRIC (verified vs current main, 2026-07-25)
|
||||
|
||||
The `@host` sugar is **target-addressing only**, not sender-identity. A cross-host
|
||||
message's **From:** is `member@rig` — the sender carries **NO `@host` suffix**. The target
|
||||
supports `member@rig@<host>` for addressing; the sender does not reflect its own host in
|
||||
`From:`. **Do NOT teach or expect a host-qualified `from`** (in openrig-user / operator send
|
||||
docs or anywhere) until that core gap is fixed. (pm@your-rig verified this against
|
||||
current main, 2026-07-25 — a known asymmetry, not a doc error to paper over.)
|
||||
@@ -0,0 +1,104 @@
|
||||
---
|
||||
name: human-in-the-loop
|
||||
description: Use when classifying a slice closeout (auto-continue / human gate / park), routing a real decision to a human, or designing a human queue/dashboard surface. Treats humans as durable network participants with attention surfaces, queues, and decision records — escalation lands as a durable attention item, not a chat message. Approval is NOT required for every clean closeout; the default RSI conveyor continues unless an explicit human gate is reached.
|
||||
metadata:
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- queue-handoff
|
||||
- workflow-runtime
|
||||
- watchdog
|
||||
- alignment-trace
|
||||
- looping-workflows
|
||||
- intake-routing
|
||||
- attention-queue
|
||||
- dispatching-parallel-agents
|
||||
- subagent-driven-development
|
||||
- control-plane-capabilities
|
||||
- status-not-chat-orchestrator
|
||||
- control-plane-queue
|
||||
- control-plane-watchdog
|
||||
- control-plane-workflows
|
||||
- control-plane-delivery-loop
|
||||
- control-plane-rollout-manager
|
||||
---
|
||||
|
||||
# Human In The Loop
|
||||
|
||||
The primitive that treats humans as **durable network participants** —
|
||||
attention surfaces, queues, decision records, routing semantics — not
|
||||
as ad-hoc chat receivers.
|
||||
|
||||
**Autonomy is not the absence of humans; it is knowing when human
|
||||
judgment is needed and making that handoff crisp.**
|
||||
|
||||
## Use this when
|
||||
|
||||
- A slice closeout needs classifying: auto-continue, human gate, or park
|
||||
- A real decision needs to land in front of a human (usage limits, provider auth, roadmap tradeoff, product-intent ambiguity)
|
||||
- Designing a human queue/dashboard surface
|
||||
- Returning a hot potato to orchestration after human approval
|
||||
|
||||
## Don't use this when
|
||||
|
||||
- The slice closeout is clean and `PROGRESS.md` already names the next safe slice. **Default RSI conveyor continues; do NOT manufacture a human gate.**
|
||||
- The escalation is just a status update. Humans are participants for *decisions*, not narration.
|
||||
- The next owner is another agent. Use queue-handoff, not human-in-the-loop.
|
||||
|
||||
## The 3-class closeout classification
|
||||
|
||||
In a productized daemon-backed version, closeout classifies the next
|
||||
step BEFORE touching the human queue:
|
||||
|
||||
| Class | When | Action |
|
||||
|---|---|---|
|
||||
| **auto-continue** | Slice closes cleanly, next named slice in workstream plan | Mark closed; create next-owner qitem from plan |
|
||||
| **human gate** | Genuine decision needed (usage limits, provider auth, product-intent ambiguity, roadmap tradeoff) | Create human queue item with proof + decision text + recommended default + action outcomes |
|
||||
| **park** | Intentionally stop the conveyor (e.g., waiting on external) | Stop with reason + resumption path |
|
||||
|
||||
## Failure modes (5)
|
||||
|
||||
1. **Human decision needed, but the rig only mentions it in chat.** Decisions belong as durable attention items, not chat messages.
|
||||
2. **Human queue item lacks enough plain-English context for a decision.** Include proof + decision text + recommended default + action outcomes.
|
||||
3. **Human response updates a file but does not wake the next owner.** Approval should return the hot potato; feedback should create the next durable qitem.
|
||||
4. **The dashboard shows too much raw rig state and hides the actual decision queue.** Decision queue is the primary surface; rig state is secondary.
|
||||
5. **A clean closeout is parked on the human even though `PROGRESS.md` already names the next safe slice.** Don't manufacture human gates.
|
||||
|
||||
## Proof standard (both paths)
|
||||
|
||||
A trustworthy human-in-the-loop system proves both directions:
|
||||
|
||||
- **Blocking gate path**: real item routed to human → human decision recorded through UI → resulting hot-potato handoff wakes correct next owner
|
||||
- **Non-blocking closeout path**: proof inspectable by human, but orchestrator continues to next named slice without manufacturing a human gate
|
||||
|
||||
A primitive that only wakes humans is not trustworthy. It must also know when NOT to.
|
||||
|
||||
## Product shape (SHIPPED — Mission Control, PL-005)
|
||||
|
||||
This surface has shipped as **Mission Control** (product UI, `/mission-control`
|
||||
route; actions via `POST /api/mission-control/action`). The seven verbs the
|
||||
human acts with:
|
||||
- **approve** (returns the hot potato to orchestration or the chosen owner)
|
||||
- **deny** (reject the item)
|
||||
- **route** (send to a different owner)
|
||||
- **annotate** (add context without action)
|
||||
- **hold** (intentional pause with reason)
|
||||
- **drop** (mark not-actionable)
|
||||
- **handoff** (hand to a specific next owner — creates the next durable qitem)
|
||||
|
||||
**Approval returns the hot potato to orchestration or the chosen owner;
|
||||
feedback creates the next durable qitem rather than only mutating the source
|
||||
queue file** — enforced by the shipped verbs (handoff/route create qitems).
|
||||
See `docs/as-built/architecture/mission-control.md`.
|
||||
|
||||
## Long-term shape
|
||||
|
||||
Likely needs **multiple humans with different scopes**, not a singleton
|
||||
human attention feed. Different humans own different decision
|
||||
domains; queue items route by scope.
|
||||
|
||||
## See also
|
||||
|
||||
- `queue-handoff` skill — durable handoff via queue items; human-in-the-loop is the human-side complement
|
||||
- `watchdog` skill — when to wake (humans included) vs no-op
|
||||
- `looping-workflows` (convention) — the looping-workflows convention covers loop closeouts; human-in-the-loop is the escape hatch
|
||||
@@ -1,115 +0,0 @@
|
||||
---
|
||||
name: mission-slice-sop
|
||||
description: "Use when working a mission or slice: the SDLC flow (intent -> mini-requirements + proof contract -> mockups -> plan-lock -> build -> QA -> `rig proof` drops -> proof-lock), and how to track, prove, and hand off state across agents and compaction via PROGRESS.md / PROOF.md / MISSION_NOTES.md. Covers the two locks, role contracts, hot-potato queue handoff, and the `rig scope audit` backstop."
|
||||
metadata:
|
||||
openrig:
|
||||
stage: shipped
|
||||
last_verified: "2026-07-06"
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
The canonical product SDLC skill: it teaches the full SDLC flow the
|
||||
Living Notes UI projects — the convention sections, the proof-contract
|
||||
pairing, the two staged-approval locks, C1 proof drops, and the three
|
||||
role contracts. Conventions SSOT: docs/reference/sdlc-conventions.md
|
||||
in the repo; on an installed package the daemon materializes the same
|
||||
document at $OPENRIG_HOME/reference/sdlc-conventions.md (default
|
||||
~/.openrig/reference/sdlc-conventions.md). The deterministic backstop
|
||||
is the `rig scope audit` classifier.
|
||||
sibling_skills:
|
||||
- queue-handoff
|
||||
- seat-continuity-and-handover
|
||||
- claude-compaction-restore
|
||||
---
|
||||
|
||||
# Mission/Slice SOP — how you work a mission & slice
|
||||
|
||||
Use this skill to actually **do** mission/slice work the way OpenRig expects: author the convention sections, track on the canonical files, prove on them, hand off through them, and survive compaction on them. **Do the work described here; do not merely explain the protocol.** The deterministic backstop is `rig scope audit` — the audit classifier is the source of truth for adherence. The conventions themselves live in ONE document: **`docs/reference/sdlc-conventions.md`** in the repo, materialized by the daemon at **`$OPENRIG_HOME/reference/sdlc-conventions.md`** (default `~/.openrig/reference/sdlc-conventions.md`) on an installed package — this skill teaches the flow; the SSOT defines the formats.
|
||||
|
||||
## The SDLC flow (intent → proof)
|
||||
|
||||
```
|
||||
intent → mini-requirements + proof contract → (UI slices: mockups)
|
||||
→ plan-lock (rig scope slice approve --scope spec)
|
||||
→ build the LOCKED set
|
||||
→ QA: mockup ↔ delivered VISUAL compare
|
||||
→ proof drops (rig proof add <slice> …)
|
||||
→ proof-lock (rig scope slice approve --scope delivery)
|
||||
```
|
||||
|
||||
1. **Record intent** verbatim in the slice's `## Intent` section (`rig scope slice create` scaffolds it — every template kind).
|
||||
2. **Author the mini-requirements + proof contract**: `## Mini-requirements` is the concise one-glance tier (approval starts there); `## Proof contract` is a checkbox list of promised deliverables, each written as an observable outcome. UI deliverables name their planned mockup. The IMPLEMENTATION-PRD opens with the mini-requirements; everything between intent and proof is **elastic** — for a small slice the mini-requirements may BE the whole PRD.
|
||||
3. **Plan-lock**: `rig scope slice approve <slice> --scope spec` — "the PRD matches the intent; THIS artifact set is what gets built." One daemon-side write: frontmatter stamp + append-only audit row.
|
||||
4. **Build the locked set** — look at the mockups, not just the spec text.
|
||||
5. **QA visual compare**: for each deliverable, load the planned mockup, produce the real artifact in a test/demo environment, visually compare, and record the verdict.
|
||||
6. **Drop proof**: `rig proof add <slice> --artifact-type qa --verdict PASS --candidate-sha <tip> --money-evidence "…" --evidences "1,3" --media "walk.webm,panel.png" --self-check "…"` — the C1 header's closed sets validate at drop time; `--evidences` joins the drop to its proof-contract items and `--media` names the curated proof/-relative media the drop stands behind (that pairing + media set is what the UI's DELIVERED section renders).
|
||||
7. **Proof-lock**: `rig scope slice approve <slice> --scope delivery` — the terminal sign-off. Approval is freeze/sign-off, **never** proven-green: proven-green requires the recorded C1 verdicts.
|
||||
|
||||
## The three role contracts
|
||||
|
||||
- **Planning agent:** authors intent + mini-requirements + the proof contract; produces mockups for UI deliverables and attaches them to the locked set (a UI slice with no mockup is an incomplete plan; non-UI slices have none — not a gate); locks the plan.
|
||||
- **Build agent:** builds against the LOCKED set only; looks at the mockups.
|
||||
- **QA agent (owns the compare):** visually compares planned vs delivered per deliverable, records verdict + note via proof drops, and **curates** the canonical proof set (bounded, mapped to deliverables; the fix-loop pile stays in `proof/`, one drill-in down). On mismatch: fix-and-re-review or kick back with the reason — never escalate a raw mismatch to the human.
|
||||
|
||||
## The canonical files (the operating surface)
|
||||
|
||||
> The canonical files below are the **operating surface of the work** — you track on them, prove on them, hand off through them, and survive compaction on them. They are NOT side-artifacts to "maintain"; keeping them current *is* the work.
|
||||
|
||||
- **README.md** (mission + slice) — the overview, OPENING with the convention sections (`## Intent` / `## Mini-requirements` / `## Proof contract`). The **mission README carries this SOP at its bottom.**
|
||||
- **IMPLEMENTATION-PRD.md** — the full PRD; opens with the mini-requirements; the `## Proof contract` here is what the UI's DELIVERED pairing joins proof against.
|
||||
- **PROGRESS.md** — the live delivery state. One line per outcome; links down for detail.
|
||||
- **MISSION_NOTES.md** — the accruing handoff + tribal-knowledge doc. Blank-slate onboarding + **compaction-restore** read it. `§1` top-of-mind + per-seat `§A–§X`.
|
||||
- **MISSION_BRIEF.md** — the steering doc (the UI "Steering" tab). The 7-section schema.
|
||||
- **PROOF.md** (+ `proof/`) — acceptance evidence. **A slice is not done until every proof-contract item has evidence.**
|
||||
|
||||
## Per-file rules — WHO / WHEN / HOW
|
||||
|
||||
### PROGRESS.md
|
||||
- **WHO:** the orchestrator owns `§1` (current state); every agent logs its own outcomes.
|
||||
- **WHEN:** after every slice-done **AND every commit**; on any material state change.
|
||||
- **HOW:** one line per outcome (checkbox), link down for detail (workstream-continuity format); keep frontmatter `stage`/`verified` honest.
|
||||
|
||||
### PROOF.md + proof/
|
||||
- **WHO:** the impl/QA pair that worked the slice.
|
||||
- **WHEN:** a slice is **NOT "done"** until every proof-contract item has evidence.
|
||||
- **HOW:** proof maps **1:1 to the proof contract's deliverables** — put media under `proof/`, then ATTACH it with `rig proof add <slice> … --evidences <item> --media <files>` (the drop writes the C1 header the DELIVERED pairing joins on) + a line in PROOF.md stating what it proves. **Hand-placing files in `proof/` without a drop is the anti-pattern** — the deliverable stays unpaired and `unverified`. No proof → not done.
|
||||
|
||||
### MISSION_NOTES.md
|
||||
- **WHO:** any agent updates `§1` (top-of-mind); each seat owns + appends to its own `§A–§X` section.
|
||||
- **WHEN:** on any material change; a compacting agent **files its state here BEFORE compaction and reads it on restore.**
|
||||
- **HOW:** accruing tribal knowledge — `§1` ≤ 5–15 lines (gates, open decisions, surprises); per-seat continuation entries (latest = truth; other seats read-only). Pointer-first; don't duplicate.
|
||||
|
||||
### MISSION_BRIEF.md
|
||||
- **WHO:** product/design (steering owner).
|
||||
- **WHEN:** when steering changes.
|
||||
- **HOW:** the 7-section steering schema (the UI "Steering" tab reads it).
|
||||
|
||||
### README.md
|
||||
- **WHO:** the author at creation; refreshed on rescope.
|
||||
- **WHEN:** at mission/slice creation + when scope/theme changes.
|
||||
- **HOW:** overview + honest frontmatter (`id`/`stage`/`verified`) + the convention sections up top; the mission README carries this SOP at its bottom.
|
||||
|
||||
## The lifecycle (4 legs)
|
||||
|
||||
**SCAFFOLD** (`rig scope` creates the files from templates — every slice kind emits the convention sections + `proof/` + the IMPLEMENTATION-PRD skeleton) → **POPULATE** (agents fill them as work happens, per the rules above) → **PROJECT** (the Living Notes UI reads them into INTENT → PLAN → DELIVERED) → **VERIFY** (`rig scope audit` checks adherence). "Loose freeform write + deterministic verify."
|
||||
|
||||
## Hot-potato (handoffs)
|
||||
|
||||
End every turn by passing the ball — a `rig queue` handoff to the next agent (close the qitem with a `closure_reason`). The **durable ball-pass is the queue close, not a chat message.** Never go idle without a handoff.
|
||||
|
||||
## Verify (deterministic backstop)
|
||||
|
||||
Run `rig scope audit` at slice-close. It flags: committed-without-touching-PROGRESS; slice-marked-done-without-PROOF; active-mission-without-MISSION_NOTES; MISSION_BRIEF off-schema; proof artifacts violating the C1 header; missing IMPLEMENTATION-PRD on a building slice; missing convention sections (`## Intent`, a well-formed `## Proof contract`, the UI-slice mockup ref). Every convention check is **advisory / fail-open** — it records and advises, never blocks a write. **Fix the flag, don't suppress it.**
|
||||
|
||||
## Reading terminal captures — KNOWN GOTCHA: ghost-text autocomplete is NOT real
|
||||
|
||||
When you `rig capture` a pane, **greyed / ghost autocomplete suggestions are NOT real content** — they are autocomplete *previews* (shell autosuggestion, the input-box ghost-text completion), not typed, staged, or committed input. **This is known, expected, and has been faking agents out a lot** — reading a ghost suggestion in a peer's input box as "staged text they're about to send," or as a real prompt, and then reasoning/acting on a string that was never actually there.
|
||||
|
||||
**Rule:** ignore ghost/autosuggest text entirely. Only *committed/rendered* pane output is real. If a `❯` input line shows text, treat it as an autocomplete artifact unless you have independent evidence it was actually entered. Do not build decisions (or worry about "colliding with staged text") on ghost text. When it matters, verify at source (git, the queue, the actual event) — never off a capture's ghost line.
|
||||
|
||||
## Moment-of-truth checklist
|
||||
|
||||
- **Starting a slice?** → intent recorded verbatim? mini-requirements + proof contract authored? mockups attached (UI slices)? plan locked (`--scope spec`)?
|
||||
- **Finishing a slice?** → every proof-contract item has curated evidence via `rig proof add … --evidences --media` (C1 drops — never only hand-placed files)? PROGRESS updated? MISSION_NOTES `§1` refreshed? proof locked (`--scope delivery`)? Handed off via queue?
|
||||
- **Committing?** → PROGRESS updated?
|
||||
- **Compacting?** → filed your state in MISSION_NOTES?
|
||||
- **Starting on a mission?** → read the mission README (incl. this SOP) + MISSION_NOTES + the conventions SSOT (`docs/reference/sdlc-conventions.md` in the repo, `$OPENRIG_HOME/reference/sdlc-conventions.md` on an installed package)?
|
||||
@@ -1,18 +1,28 @@
|
||||
---
|
||||
name: openrig-architect
|
||||
description: Use when designing multi-agent topologies that run ON OpenRig — authoring RigSpec and AgentSpec files for new rigs, creating agent startup content (guidance / skills / culture), or diagnosing why a launched rig's agents aren't behaving as intended. NOT for changing OpenRig itself (work in the openrig product repo); NOT for ordinary CLI operation of an existing rig (use openrig-user). Covers the full authoring lifecycle from user intent to validated, launchable rig.
|
||||
description: Use when designing multi-agent topologies that run ON OpenRig — authoring RigSpec and AgentSpec files for new rigs, creating agent startup content (guidance / skills / culture), or diagnosing why a launched rig's agents aren't behaving as intended. NOT for changing OpenRig itself (use openrig-builder); NOT for ordinary CLI operation of an existing rig (use openrig-user). Covers the full authoring lifecycle from user intent to validated, launchable rig.
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- agent validate
|
||||
- capture
|
||||
- daemon start
|
||||
- ps
|
||||
- send
|
||||
- spec validate
|
||||
- specs ls
|
||||
- up
|
||||
- whoami
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
last_verified: "2026-05-04"
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
Bootstrap skill — NPM install lands this in personal homes (~/.claude/skills/, ~/.agents/skills/) for users authoring their own rigs.
|
||||
sibling_skills:
|
||||
- openrig-user
|
||||
- openrig-operator
|
||||
- openrig-builder
|
||||
- openrig-upgrade
|
||||
- forming-an-openrig-mental-model
|
||||
transfer_test: pending
|
||||
- ai-dev-workflows
|
||||
notes: |
|
||||
Description was already correct (starts with "Use when..."; lists specific authoring triggers including the diagnose-bad-rig case). Final sentence ("Covers the full authoring lifecycle from user intent to validated, launchable rig.") is workflow-summary-adjacent; on next iteration, consider trimming. For factory-adoption cycle, kept as-is to match product source-of-truth.
|
||||
---
|
||||
|
||||
# OpenRig Architect
|
||||
@@ -47,8 +57,13 @@ Load these before starting any design work. The quality of your output depends o
|
||||
|
||||
**Read if present on this host:**
|
||||
|
||||
4. **Host-level doctrine file** (if your team maintains one — e.g., a HOST-TOPOLOGY doc that defines canonical rig classes, context-sharing patterns, and authoring SOPs for high-stakes rigs). If present, it supersedes the baseline process below for complex or high-stakes rigs (≥4 members, HA, managed-app, or shared/copied). Solo operators and small/focused rigs use the baseline below directly.
|
||||
5. **Agent-facing software design principles** if your rig ships a new CLI, service, or managed app that agents will operate. Treat the operating surface as a context-engineering problem: every error message and help text gives the agent information to act on.
|
||||
4. **Host-level doctrine** in your host's topology doc, if it keeps one. If this file exists, it supersedes the baseline process below for complex or high-stakes rigs. Specifically:
|
||||
- §3 defines the canonical rig classes (kernel, project, ephemeral, infra-build, managed-app). Classify before designing.
|
||||
- §4 defines context-sharing patterns (pods as context domains, pair pattern, HA via mental-model-ha skill + substrate session logs, terminal nodes as common-room, chatroom/substrate/transcripts/Corpus).
|
||||
- **§7 is the canonical 12-step rig-spec authoring SOP for high-stakes rigs — use it instead of the baseline "Design Process" below when the rig is ≥4 members, uses HA, is a managed-app, or will be shared/copied.** The baseline below still applies to small/focused rigs.
|
||||
- §10 contains the host's bootstrap sequence so you know where your new rig fits.
|
||||
- §12 has the naming canon and vocabulary mapping to shipped terms.
|
||||
5. **`building-agent-software` skill** if available in your skill catalog. Design principles for agent-facing tools and surfaces. Relevant when your rig ships a new CLI, service, or managed app.
|
||||
|
||||
**Load as needed:**
|
||||
- Domain-specific skills when designing specialist agents — find shipped skills inside the OpenRig installation under the `specs/agents/` tree
|
||||
@@ -218,10 +233,9 @@ For rigs that reuse builtin agents, the agents directory is often unnecessary
|
||||
4. **Write role guidance** for each custom agent — who they are, what they do
|
||||
5. **Write startup context** for agents that need environment grounding
|
||||
6. **Validate:** `rig spec validate rig.yaml` and `rig agent validate agents/*/agent.yaml`
|
||||
7. **Audit authoring completeness:** `rig spec audit rig.yaml` — advisory findings identify missing culture or startup context without blocking launch.
|
||||
8. **Confirm the runtime cwd** — do not assume agents should work from the directory where the rig spec is stored. The spec root controls file resolution; the runtime cwd controls trust, project guidance, permissions, and repo context.
|
||||
9. **Launch:** `rig up rig.yaml --cwd /path/to/project`
|
||||
10. **Verify:** `rig ps --nodes` — all agents ready? Check `rig capture` on each agent.
|
||||
7. **Confirm the runtime cwd** — do not assume agents should work from the directory where the rig spec is stored. The spec root controls file resolution; the runtime cwd controls trust, project guidance, permissions, and repo context.
|
||||
8. **Launch:** `rig up rig.yaml --cwd /path/to/project`
|
||||
9. **Verify:** `rig ps --nodes` — all agents ready? Check `rig capture` on each agent.
|
||||
|
||||
### Validation Is Non-Negotiable
|
||||
|
||||
@@ -229,10 +243,11 @@ Always validate before launching:
|
||||
|
||||
```bash
|
||||
rig spec validate rig.yaml
|
||||
rig spec audit rig.yaml
|
||||
rig agent validate agents/my-agent/agent.yaml
|
||||
```
|
||||
|
||||
Then run `rig spec audit rig.yaml` for advisory checks such as stale seat references and other cross-file drift that schema validation cannot detect.
|
||||
|
||||
If validation fails, fix the errors. Do not try to launch an invalid spec — it will fail with a less helpful error.
|
||||
|
||||
## Diagnosis: When Things Go Wrong
|
||||
|
||||
@@ -9,11 +9,6 @@ description: >
|
||||
metadata:
|
||||
openrig:
|
||||
stage: candidate
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
cmux is OpenRig's shipped terminal provider generalized onto `rig terminal <provider>` —
|
||||
best-effort, not proof-gated. Authored clean-room.
|
||||
transfer_test: pending
|
||||
sibling_skills:
|
||||
- openrig-herdr
|
||||
- openrig-user
|
||||
|
||||
@@ -10,11 +10,6 @@ description: >
|
||||
metadata:
|
||||
openrig:
|
||||
stage: candidate
|
||||
distribution_scope: product-bound
|
||||
source_evidence: |
|
||||
Empirical herdr 0.7.1 hands-on findings + the ratified implementation PRD. Authored
|
||||
clean-room (patterns only, no herdr source text; AGPL arm's-length).
|
||||
transfer_test: pending
|
||||
sibling_skills:
|
||||
- openrig-cmux
|
||||
- openrig-user
|
||||
@@ -51,7 +46,7 @@ An agent asked "open all my rigs plus a mission as views" runs one `open` per ta
|
||||
```bash
|
||||
rig terminal open acme-web # a whole rig, live agents as tiles
|
||||
rig terminal open mission:site-relaunch # exactly the agents working the mission
|
||||
rig terminal open slice:02-search-filters # the agents working one slice
|
||||
rig terminal open slice:search-filters # the agents working one slice
|
||||
```
|
||||
|
||||
No hand-listing of seats: the mission/slice membership is derived from live topology at open time.
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
---
|
||||
name: openrig-installer
|
||||
description: Use when installing or upgrading OpenRig on a host, especially the V0.3.1 upgrade flow which includes the substrate-kernel → daemon-managed-kernel migration ceremony. Covers npm install, rig setup, rig daemon start (auto-boots kernel), and the canonical verification commands. NOT for ordinary kernel operation post-install — use openrig-operator skill for that.
|
||||
metadata:
|
||||
openrig:
|
||||
maturity: L2
|
||||
distribution_scope: shipped
|
||||
source_evidence: V0.3.1 slice 05-kernel-rig-as-default IMPLEMENTATION-PRD §8 + OQ-A=B migration-ceremony decision
|
||||
---
|
||||
|
||||
# OpenRig Installer
|
||||
|
||||
This skill teaches the operator agent how to install + upgrade
|
||||
OpenRig cleanly. The V0.3.1 upgrade is the one with the migration
|
||||
ceremony (substrate kernel → daemon-managed kernel); other upgrades
|
||||
follow the same install / setup / start shape with no migration.
|
||||
|
||||
## Fresh install
|
||||
|
||||
```bash
|
||||
npm install -g @openrig/cli
|
||||
rig setup
|
||||
```
|
||||
|
||||
`rig setup` is idempotent — safe to re-run if a step fails. It probes
|
||||
host prereqs (tmux present, Node version, writable state path,
|
||||
optional cmux), then invokes `rig daemon start` per the L2 factoring
|
||||
(OQ-B). The daemon's start path auto-boots the kernel rig per the
|
||||
V0.3.1 slice 05 kernel-rig-as-default logic.
|
||||
|
||||
## Verification after install
|
||||
|
||||
```bash
|
||||
rig ps --nodes --rig kernel --json
|
||||
```
|
||||
|
||||
Should report 4 members (advisor.lead + operator.agent +
|
||||
operator.human + queue.worker) all ready. If a runtime is unavailable
|
||||
the daemon picks the matching variant (`rig-claude-only.yaml` or
|
||||
`rig-codex-only.yaml`); the topology stays the same shape with the
|
||||
unavailable runtime omitted from the agent membership.
|
||||
|
||||
Entry point for chatting with the rig:
|
||||
|
||||
```bash
|
||||
rig capture advisor-lead@kernel
|
||||
```
|
||||
|
||||
Or click the CMUX button on the topology graph in the UI at
|
||||
`/topology`.
|
||||
|
||||
## V0.3.1 upgrade ceremony (one-time migration)
|
||||
|
||||
Operators with a kernel spec stored outside the daemon-managed
|
||||
location (any pre-V0.3.1 layout, typically wherever you kept your
|
||||
own `rigs/kernel/` directory) must migrate to
|
||||
`~/.openrig/specs/rigs/kernel/` as a one-time step during the V0.3.1
|
||||
upgrade. The V0.3.1 upgrade IS the migration moment; it's not a
|
||||
separate ceremony.
|
||||
|
||||
### Migration steps
|
||||
|
||||
1. **Snapshot first.** Take a snapshot of the running substrate
|
||||
kernel so the migration is reversible:
|
||||
|
||||
```bash
|
||||
rig snapshot kernel
|
||||
```
|
||||
|
||||
2. **Stop the substrate kernel** (so the migration doesn't race a
|
||||
running rig):
|
||||
|
||||
```bash
|
||||
rig down kernel --snapshot
|
||||
```
|
||||
|
||||
3. **Copy your existing kernel spec** into the daemon-managed
|
||||
location:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.openrig/specs/rigs/kernel
|
||||
cp -r /path/to/old/kernel-spec/* ~/.openrig/specs/rigs/kernel/
|
||||
```
|
||||
|
||||
4. **Upgrade the CLI + daemon**:
|
||||
|
||||
```bash
|
||||
npm install -g @openrig/[email protected]
|
||||
rig daemon stop
|
||||
rig daemon start
|
||||
```
|
||||
|
||||
At this point the new daemon detects `~/.openrig/specs/rigs/kernel.yaml`
|
||||
exists and skips the V0.3.1 builtin-kernel boot (the
|
||||
already-managed-rig branch). The substrate-rooted topology
|
||||
continues to run under daemon management.
|
||||
|
||||
5. **Verify** the migrated kernel matches expectations:
|
||||
|
||||
```bash
|
||||
rig ps --nodes --rig kernel --json
|
||||
```
|
||||
|
||||
6. **Decommission the old copy** (only after verifying the
|
||||
daemon-managed copy works):
|
||||
|
||||
```bash
|
||||
rm -rf /path/to/old/kernel-spec
|
||||
```
|
||||
|
||||
### If migration fails
|
||||
|
||||
The pre-step snapshot is the rollback. `rig restore <snapshot-id>
|
||||
--rig kernel` revives the prior topology. Then `npm install -g
|
||||
@openrig/cli@0.3.0` rolls the CLI back and you can retry later.
|
||||
|
||||
## Operator agent's role in install + upgrade
|
||||
|
||||
The operator agent shepherds operators through these steps when the
|
||||
user asks "how do I upgrade?" or "what's the V0.3.1 ceremony?". The
|
||||
agent reads this skill on demand via `find-skills` — it does not
|
||||
need to memorize the steps; it consults the canonical reference
|
||||
(this file) and walks the operator through.
|
||||
|
||||
## 3-part error remediation
|
||||
|
||||
| What failed | Why it matters | Fix |
|
||||
|---|---|---|
|
||||
| `npm install -g @openrig/cli` permission denied | Global install needs writable npm prefix; macOS Homebrew default is usually writable; some custom Node installs aren't | Either fix the npm prefix permissions or use `sudo npm install -g`; check `npm config get prefix` |
|
||||
| `rig setup` host prereq fail | tmux, Node version, or writable state path missing | `rig doctor` lists each missing piece + the install command; run those, retry `rig setup` |
|
||||
| `rig daemon start` auth-block error | Neither Claude Code nor Codex authenticated; kernel rig requires at least one | Run `claude auth login` OR `codex login`; then retry `rig daemon start` |
|
||||
| `rig daemon start` "kernel already managed" | An existing managed rig named `kernel` exists; the daemon skips builtin-boot per design | This is the expected path after migration — no action needed |
|
||||
| `rig ps --rig kernel --json` returns empty | Daemon healthy but no kernel rig managed; likely the migration step copied content but did not boot | `rig up kernel` from inside `~/.openrig/specs/rigs/kernel/`; or invoke the daemon's cold-boot path explicitly |
|
||||
|
||||
## What this skill is NOT
|
||||
|
||||
- Not the canonical OpenRig command surface; that lives in the
|
||||
`openrig-user` skill.
|
||||
- Not the kernel-operating-procedure for post-install daily use;
|
||||
that's `openrig-operator`.
|
||||
- Not for project rigs; project rigs install themselves via `rig
|
||||
up <spec>` after the kernel is in place.
|
||||
@@ -1,110 +0,0 @@
|
||||
---
|
||||
name: openrig-operator
|
||||
description: Use when operating or debugging host-side OpenRig runtime issues including daemon reachability, partial identity, unified-exec warnings, stale helper-process cleanup, or when distinguishing harness/process issues from live topology health.
|
||||
---
|
||||
|
||||
# OpenRig Operator
|
||||
|
||||
## Overview
|
||||
|
||||
This skill covers host/runtime/operator triage around OpenRig itself.
|
||||
Use it when the problem may be the daemon, the shell/runtime surface, or stale helper processes rather than the product workflow you are trying to run.
|
||||
|
||||
## When to Use
|
||||
|
||||
Use this skill when you see:
|
||||
- `rig whoami --json` returning partial identity
|
||||
- `rig ps --nodes -A --json` failing while some other `rig` commands still work
|
||||
- `Sent to ...` plus `Verified: no`
|
||||
- repeated unified-exec-process warnings
|
||||
- suspicion that stale helper processes are accumulating
|
||||
|
||||
Do not use this skill for normal product workflow routing, queue handling, or ordinary peer communication. Use `openrig-user` for that.
|
||||
|
||||
## First Checks
|
||||
|
||||
Start with the minimum truthful operator read:
|
||||
|
||||
```bash
|
||||
rig whoami --json
|
||||
rig daemon status
|
||||
rig ps --nodes -A --json
|
||||
```
|
||||
|
||||
Interpret them together, not in isolation:
|
||||
- partial `whoami` can mean identity is inferable while daemon-backed surfaces are degraded
|
||||
- `daemon status` tells you whether the host daemon is up, not whether every seat can reach it cleanly
|
||||
- `ps --nodes -A --json` is the best machine-readable fleet topology check when it works (v0.4.4: `--nodes` needs an explicit scope outside a managed session — `-A` for fleet, `--rig <name>` for one rig; the bare `rig ps` map is the cheap first glance)
|
||||
|
||||
## Verification Drift Vs Send Failure
|
||||
|
||||
For `rig send`:
|
||||
- `Sent to ...` + `Verified: yes` = strong positive delivery evidence
|
||||
- `Sent to ...` + `Verified: no` = ambiguous delivery, not automatic failure
|
||||
- no `Sent to ...` line or a hard error = send failure
|
||||
|
||||
When verification is ambiguous, check:
|
||||
- direct reply
|
||||
- `rig capture <session>`
|
||||
- transcript evidence
|
||||
- queue/outbox state if the message asked for a durable handoff
|
||||
|
||||
Do not blindly retry until you have checked one of those.
|
||||
|
||||
## Unified Exec Warning
|
||||
|
||||
If you see:
|
||||
|
||||
- `Warning: The maximum number of unified exec processes you can keep open is 60 ...`
|
||||
|
||||
treat it first as a host/tooling-layer warning, not as automatic proof that the OpenRig topology is unhealthy.
|
||||
|
||||
This warning can coexist with a healthy live topology.
|
||||
|
||||
## Safe Process Triage
|
||||
|
||||
Inspect the process surface first:
|
||||
|
||||
```bash
|
||||
ps -axo pid,ppid,command | rg 'tmux send-keys|rig queue create|tmux attach|codex|claude'
|
||||
```
|
||||
|
||||
Think in layers:
|
||||
- host/tooling layer: stale one-shot wrappers, session bookkeeping, helper shells
|
||||
- topology layer: live `tmux attach` seats, live `codex` / `claude` runtimes, daemon health
|
||||
|
||||
Do not diagnose topology failure from tooling-layer warnings alone.
|
||||
|
||||
## Safe Cleanup Boundary
|
||||
|
||||
Usually safe to reap when clearly orphaned / one-shot:
|
||||
- `tmux send-keys ...`
|
||||
- short-lived shell wrappers created only to enqueue or send one message
|
||||
|
||||
Do not mass-kill:
|
||||
- `tmux attach ...`
|
||||
- `codex ...`
|
||||
- `claude ...`
|
||||
- other long-lived daemon/runtime processes
|
||||
|
||||
The point is to remove garbage, not workers.
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
- treating `Verified: no` as if it proves the message did not land
|
||||
- treating the unified-exec warning as if it proves the rig is overloaded
|
||||
- killing live seats when only stale helper wrappers needed cleanup
|
||||
- concluding "daemon down" from one seat's failure without checking host-level daemon status
|
||||
|
||||
## Practical Rule
|
||||
|
||||
Clean the smallest safe surface that matches the evidence.
|
||||
|
||||
If the warning or failure remains after stale-wrapper cleanup, re-check:
|
||||
|
||||
```bash
|
||||
rig daemon status
|
||||
rig ps --nodes -A --json
|
||||
```
|
||||
|
||||
If those remain healthy, the residual issue may still be in the host/tool/session layer rather than in OpenRig topology state.
|
||||
@@ -0,0 +1,460 @@
|
||||
---
|
||||
name: openrig-upgrade
|
||||
description: Use when upgrading the OpenRig CLI/daemon on a host with running rigs, especially when preserving tmux-backed agent sessions through a daemon restart or documenting hot-upgrade SOP evidence.
|
||||
metadata:
|
||||
cli_surfaces_referenced:
|
||||
- capture
|
||||
- daemon adopt-state
|
||||
- daemon start
|
||||
- daemon status
|
||||
- daemon stop
|
||||
- down
|
||||
- ps
|
||||
- restore-check
|
||||
- snapshot
|
||||
- up
|
||||
- upgrade backup
|
||||
- upgrade preflight
|
||||
- upgrade promote-runtime
|
||||
- upgrade verify
|
||||
- version
|
||||
openrig:
|
||||
stage: factory-approved
|
||||
sibling_skills:
|
||||
- openrig-user
|
||||
- openrig-operator
|
||||
- openrig-builder
|
||||
- openrig-architect
|
||||
- forming-an-openrig-mental-model
|
||||
- ai-dev-workflows
|
||||
---
|
||||
|
||||
# OpenRig Upgrade
|
||||
|
||||
## Core Principle
|
||||
|
||||
OpenRig has two different failure domains:
|
||||
|
||||
- **Agent process plane:** Claude/Codex/terminal seats running inside tmux.
|
||||
- **Management plane:** the OpenRig daemon, CLI, SQLite DB, transcripts, node inventory,
|
||||
send/capture APIs, restore metadata, and migrations.
|
||||
|
||||
A hot daemon upgrade is possible when the continuity seats remain alive in tmux and
|
||||
the new daemon restarts against the same DB and transcript root. Do not run
|
||||
`rig down` on continuity rigs unless the goal is a disruptive restore test; `rig down`
|
||||
kills OpenRig-launched tmux sessions.
|
||||
|
||||
## Preferred Live-Cutover Operator Mode
|
||||
|
||||
For live production daemon cutovers, prefer an **out-of-band upgrade operator**:
|
||||
a temporary host-local tmux seat outside the managed OpenRig topology, spawned
|
||||
from the lifecycle/runtime-upgrade agent's current mental model.
|
||||
|
||||
Why: the managed rig stays in the agent process plane while a disposable sidecar
|
||||
mutates the management plane. The sidecar inherits enough context to avoid a
|
||||
cold handoff, but it is not inside the failure domain it is modifying.
|
||||
|
||||
Use this when all are true:
|
||||
|
||||
- the upgrade mutates the live daemon, CLI wrapper, DB, runtime worktree, tmux
|
||||
lifecycle, or active control-plane truth;
|
||||
- continuity seats should keep working during the upgrade;
|
||||
- a lifecycle/runtime-upgrade seat has already prepared the packet or owns the
|
||||
needed context;
|
||||
- the human has granted an `operator auto window`.
|
||||
|
||||
In this SOP, `operator auto window` means a bounded operator-authorized upgrade lane. It does not
|
||||
mean standing Codex `auto_review`, `--full-auto`, or approval-bypass mode. Use
|
||||
`security-and-consequence-boundary-policy` skill for the current
|
||||
security and consequence-boundary policy.
|
||||
|
||||
Do not use this pattern as a standing orchestration seat. The sidecar exists for
|
||||
one cutover and then closes after handback.
|
||||
|
||||
### Sidecar Contract
|
||||
|
||||
The in-rig lifecycle/runtime-upgrade seat owns packet preparation and final
|
||||
interpretation. The out-of-band sidecar owns only execution inside the approved
|
||||
window.
|
||||
|
||||
Sidecar starter prompt shape:
|
||||
|
||||
```text
|
||||
You are the host-local OpenRig runtime upgrade operator, outside the managed rig
|
||||
topology. Execute the approved daemon-only cutover only after explicit human
|
||||
approval. First read the upgrade preflight artifact and runtime-upgrade
|
||||
decision. Prove you are outside the topology before mutation. Never run rig
|
||||
down. Preserve tmux topology. Stop/start only the daemon, verify protected rigs,
|
||||
write cutover evidence, unblock downstream artifacts only when the blocker is
|
||||
truly closed, and rollback to <previous-wrapper-or-commit> if needed.
|
||||
```
|
||||
|
||||
Required handback:
|
||||
|
||||
- write the live cutover evidence under the lifecycle evidence shelf;
|
||||
- include proof that the sidecar was outside the topology/failure domain it
|
||||
mutated;
|
||||
- update any blocked downstream dogfood/runtime task only when the blocking
|
||||
condition is truly closed;
|
||||
- preserve caveats as downstream material instead of using them to reopen a
|
||||
closed cutover gate;
|
||||
- report back to the in-rig lifecycle/runtime-upgrade seat or orch surface with
|
||||
daemon provenance, topology verification, caveats, rollback state, and one
|
||||
compact paragraph of operator judgment about ambiguous choices;
|
||||
- close the sidecar after the original lifecycle owner has absorbed the result.
|
||||
|
||||
Stop conditions for the sidecar:
|
||||
|
||||
- preflight or runtime-upgrade decision is missing;
|
||||
- human approval is absent or narrower than the requested cutover;
|
||||
- protected topology is already degraded beyond the packet's expected caveats;
|
||||
- target runtime cannot be verified by process path, port listener, and command
|
||||
evidence;
|
||||
- any step would require `rig down` or destructive DB restore without a new
|
||||
explicit human decision.
|
||||
|
||||
Generic primitive: this upgrade specialization composes over the
|
||||
`sidecar-operator` skill (the underlying out-of-band-operator pattern;
|
||||
this skill is the upgrade-specific specialization).
|
||||
|
||||
## What Changed On 2026-04-27
|
||||
|
||||
Initial belief:
|
||||
|
||||
- All rigs had to be down before daemon restart.
|
||||
- Live upgrade was research-gated because DB migrations might break session/node
|
||||
state while sessions were running.
|
||||
- A parallel isolated daemon/adoption path looked necessary before production use.
|
||||
|
||||
Observed result:
|
||||
|
||||
- A daemon-only hot cutover preserved the live `example-seat` tmux
|
||||
sessions.
|
||||
- The old daemon was stopped without running `rig down`.
|
||||
- The new source-pinned daemon started against the same production DB.
|
||||
- `rig ps --nodes --json`, `rig capture`, and `rig restore-check` could inspect the
|
||||
still-running Velocity seats after restart.
|
||||
|
||||
The simpler model is now preferred for tmux-backed continuity rigs: snapshot and
|
||||
back up state, stop only the daemon, start the new daemon, then verify that live
|
||||
sessions are still observable and manageable.
|
||||
|
||||
## Proven Hot Path
|
||||
|
||||
Use this as the canonical first-choice workflow for a host where continuity rigs
|
||||
are tmux-backed and the operator wants non-disruptive daemon upgrade.
|
||||
|
||||
0. **Spawn the out-of-band operator when live cutover is required.**
|
||||
The sidecar must be host-local and outside the managed topology being
|
||||
upgraded. Keep the lifecycle/runtime-upgrade owner inside the rig so it can
|
||||
continue to observe, ask questions, and absorb the handback.
|
||||
|
||||
1. **Choose continuity targets.**
|
||||
Name the exact rigs that must remain live. Everything else is source material.
|
||||
Do not let "nice to resume later" rigs expand the success criteria.
|
||||
|
||||
2. **Freeze active work.**
|
||||
Get continuity seats to a stable/idle checkpoint. Record resume commands if
|
||||
available.
|
||||
|
||||
3. **Inventory with filters.**
|
||||
Do not dump full `rig ps` output on this host. Use filtered JSON:
|
||||
|
||||
```bash
|
||||
rig ps --nodes --json \
|
||||
| jq -r 'map(select(.rigName=="<rig>")) | sort_by(.canonicalSessionName)[] | "\(.canonicalSessionName) \(.sessionStatus) \(.startupStatus) \(.resumeToken // "none")"'
|
||||
```
|
||||
|
||||
4. **Take a non-destructive snapshot of each continuity rig.**
|
||||
This records rollback/recovery metadata without killing tmux sessions:
|
||||
|
||||
```bash
|
||||
rig snapshot <rigId>
|
||||
```
|
||||
|
||||
Verify the snapshot payload in SQLite has the expected nodes, sessions,
|
||||
checkpoints, and resume tokens.
|
||||
|
||||
5. **Create a post-snapshot SQLite backup.**
|
||||
Use SQLite's online backup API while the daemon is live. Then run
|
||||
`PRAGMA integrity_check` on the backup and verify it contains the continuity
|
||||
snapshot.
|
||||
|
||||
6. **Prepare a clean runtime artifact.**
|
||||
Prefer a dedicated clean source worktree pinned to a commit:
|
||||
|
||||
```bash
|
||||
git worktree add --detach /path/to/openrig-runtime-<shortsha> <commit>
|
||||
cd /path/to/openrig-runtime-<shortsha>
|
||||
PATH=/path/to/node22/bin:$PATH npm ci
|
||||
PATH=/path/to/node22/bin:$PATH npm run build
|
||||
```
|
||||
|
||||
Use even/LTS Node. The 2026-04-27 upgrade used Node `v22.22.1`.
|
||||
|
||||
7. **Stop only the daemon.**
|
||||
First try:
|
||||
|
||||
```bash
|
||||
rig daemon stop
|
||||
```
|
||||
|
||||
If the daemon state file is missing but the PID is known and verified as the
|
||||
OpenRig daemon, gracefully terminate that PID:
|
||||
|
||||
```bash
|
||||
kill -TERM <daemonPid>
|
||||
```
|
||||
|
||||
Do not use `kill -9` unless recovering from a wedged process with human
|
||||
approval. Do not run `rig down` on continuity rigs.
|
||||
|
||||
8. **Start the pinned daemon against the same production DB.**
|
||||
|
||||
```bash
|
||||
PATH=/path/to/node22/bin:$PATH \
|
||||
node packages/cli/dist/index.js daemon start \
|
||||
--port 7433 \
|
||||
--host 127.0.0.1 \
|
||||
--db ~/.openrig/openrig.sqlite
|
||||
```
|
||||
|
||||
9. **Verify management continuity.**
|
||||
Required checks:
|
||||
|
||||
```bash
|
||||
rig daemon status
|
||||
lsof -nP -iTCP:7433 -sTCP:LISTEN
|
||||
rig ps --nodes --json | jq -r 'map(select(.rigName=="<rig>")) | ...'
|
||||
rig capture --rig <rig> --lines 1 --json
|
||||
rig restore-check --rig <rig>
|
||||
```
|
||||
|
||||
Success means the daemon is healthy, continuity sessions remain running/ready,
|
||||
capture works, transcripts are present, and `restore-check` reports no red
|
||||
blockers.
|
||||
|
||||
10. **Align the default CLI with the new daemon.**
|
||||
If `rig` is a wrapper, make sure it delegates to the new CLI. On the
|
||||
2026-04-27 host this meant repointing the rigx real CLI via
|
||||
`~/.openrig/bin/rig-real-17812d5`.
|
||||
|
||||
11. **Write evidence and hand back.**
|
||||
The sidecar writes a cutover evidence packet with daemon provenance,
|
||||
protected topology counts, representative capture/restore checks, smoke
|
||||
results, caveats, and rollback state. Then it notifies the original in-rig
|
||||
lifecycle/runtime-upgrade owner. Do not rely on chat as the only proof.
|
||||
|
||||
## 2026-04-27 Proof Point
|
||||
|
||||
Continuity target:
|
||||
|
||||
- `example-seat`
|
||||
|
||||
Pinned daemon:
|
||||
|
||||
- commit `17812d5d3bfe53dfdc5e202b1da3e8c91e2f4e54`
|
||||
- subject `feat(agents): make runtime config spec-driven`
|
||||
- committed `2026-04-26T18:30:08-07:00`
|
||||
- runtime worktree `~/code/projects/openrig-runtime-17812d5`
|
||||
|
||||
Evidence:
|
||||
|
||||
- Velocity snapshot `01KQ84D3AF9YW6FQCM9SVSM5EG`
|
||||
- post-snapshot DB backup
|
||||
`db-backup/openrig-post-velocity-snapshot-20260427T185003Z.sqlite`
|
||||
- backup integrity `ok`
|
||||
- old daemon PID `62828`, Node 25 global npm install
|
||||
- new daemon PID `39708`, Node 22 source runtime
|
||||
- post-cutover `example-seat`: 4/4 seats `running` / `ready`
|
||||
- `rig restore-check --rig example-seat`: `RESTORABLE WITH CAVEATS`,
|
||||
`20 green | 9 yellow | 0 red`, `RECOVERY: NOT NEEDED`
|
||||
|
||||
Important caveat: this proves hot daemon cutover for tmux-backed Claude seats on
|
||||
this host and commit range. It does not prove that arbitrary migrations,
|
||||
non-tmux runtimes, service-backed rigs, or dead sessions can be recovered without
|
||||
separate testing.
|
||||
|
||||
## 2026-05-02 Proof Point
|
||||
|
||||
Continuity targets:
|
||||
|
||||
- `kernel`
|
||||
- `openrig-discovery`
|
||||
- `openrig-dogfood`
|
||||
- `openrig-lifecycle`
|
||||
- `openrig-maintenance`
|
||||
- `openrig-product-lab`
|
||||
- `example-rig`
|
||||
- `example-seat`
|
||||
|
||||
Pinned daemon:
|
||||
|
||||
- commit `6af2754824a07291562622ac019b68615fc41abe`
|
||||
- runtime worktree `~/code/projects/openrig-runtime-6af2754`
|
||||
- wrapper `~/.openrig/bin/rig-real-6af2754`
|
||||
|
||||
Pattern proven:
|
||||
|
||||
- lifecycle/runtime-upgrade prepared the decision and preflight artifacts;
|
||||
- a host-local tmux sidecar (`host-upgrade-operator-6af2754`) was spawned
|
||||
outside the managed topology with the current operator context;
|
||||
- the sidecar stopped only the daemon, using verified PID fallback after
|
||||
`rig daemon stop` refused due to missing daemon state;
|
||||
- the sidecar started the target daemon on port `7433`, repointed the
|
||||
config-layer wrapper default, verified protected topology, ran targeted
|
||||
Agent Starter smoke/tests, wrote evidence, and unblocked Dogfood;
|
||||
- Velocity delivery continued working throughout the cutover.
|
||||
|
||||
Evidence:
|
||||
|
||||
- preflight:
|
||||
(internal upgrade-preflight evidence, 2026-05-01)
|
||||
- live cutover:
|
||||
(internal live-cutover evidence, 2026-05-02)
|
||||
|
||||
Important caveat: live `rig up --plan --json` accepted valid `starter_ref`
|
||||
specs and rejected forbidden compositions, but plan-mode output did not emit the
|
||||
`resolve_starter.detail.starterContent` stage expected by the Dogfood proof bar.
|
||||
This is a product/dogfood caveat, not an upgrade failure.
|
||||
|
||||
## Brittle Edges Observed On 2026-04-27
|
||||
|
||||
Detailed field note:
|
||||
|
||||
(internal upgrade-brittleness field note, 2026-04-27)
|
||||
|
||||
Operator lessons from the daemon upgrade:
|
||||
|
||||
- `rig down` kills OpenRig-launched tmux sessions. Do not use it as a snapshot
|
||||
primitive when resumability depends on keeping sessions alive.
|
||||
- Old daemon/CLI combinations can be partially functional even when newer health
|
||||
checks fail. A `/healthz` mismatch blocked `rig down --snapshot` even though
|
||||
other daemon APIs still worked.
|
||||
- `rig daemon stop` can fail when the daemon state file is missing. Operators
|
||||
need a verified PID fallback, but the product should reconcile daemon state
|
||||
automatically.
|
||||
- If the sidecar has an operator auto window and `rig daemon stop` refuses only
|
||||
because state is stale, a verified graceful PID termination is acceptable:
|
||||
identify the daemon PID, verify its runtime path, send graceful `TERM`, and
|
||||
verify the port is gone before starting the target daemon.
|
||||
- CLI and daemon provenance can drift. Repointing or verifying the default
|
||||
`rig` wrapper is part of the upgrade, not an afterthought.
|
||||
- Raw `rig ps` is too noisy on this host. Use filtered JSON until the product
|
||||
has compact first-class inventory views.
|
||||
- Snapshot and backup verification is too manual. The SOP currently depends on
|
||||
checking snapshot rows, resume tokens, SQLite backups, and integrity by hand.
|
||||
|
||||
Separate follow-on note, not part of the daemon-upgrade SOP:
|
||||
|
||||
(internal add-node-brittleness field note, 2026-04-27)
|
||||
|
||||
## Disruptive Restore Path
|
||||
|
||||
Use disruptive restore when the goal is to test recovery from killed sessions, or
|
||||
when hot upgrade is blocked by incompatible migrations or corrupted management
|
||||
state.
|
||||
|
||||
```bash
|
||||
rig snapshot <rigId>
|
||||
rig down <rigId>
|
||||
# upgrade daemon/CLI
|
||||
rig up <rigName>
|
||||
rig restore-check --rig <rigName>
|
||||
```
|
||||
|
||||
Expected restore results:
|
||||
|
||||
| Result | Meaning | Action |
|
||||
|---|---|---|
|
||||
| `fully_restored` | All nodes resumed or rebuilt | Resume normal work |
|
||||
| `partially_restored` | Some nodes succeeded, some failed | Inspect failed nodes and relaunch manually |
|
||||
| `failed` | Zero nodes restored | Check daemon logs, snapshot integrity, provider tokens |
|
||||
| `not_attempted` | Pre-restore blockers | Fix blockers before retrying |
|
||||
|
||||
Do not confuse this path with hot upgrade. `rig down` is intentionally
|
||||
disruptive.
|
||||
|
||||
## Stop Conditions
|
||||
|
||||
Do not proceed with hot upgrade if:
|
||||
|
||||
- continuity targets are mid-task and cannot checkpoint;
|
||||
- continuity target tmux sessions are missing before upgrade;
|
||||
- no verified DB backup exists after continuity snapshots;
|
||||
- the target runtime cannot build under an even/LTS Node version;
|
||||
- the daemon migration plan is known to rewrite session/binding semantics in a
|
||||
way that has not been tested;
|
||||
- disk space or DB integrity checks fail;
|
||||
- the operator cannot identify the current daemon PID and runtime source.
|
||||
|
||||
## Rollback
|
||||
|
||||
Rollback means restoring the previous daemon runtime and, if necessary, the DB
|
||||
backup.
|
||||
|
||||
For source runtime:
|
||||
|
||||
1. Stop the new daemon.
|
||||
2. Start the previous runtime or npm/global daemon.
|
||||
3. Verify `/healthz`, filtered continuity inventory, and `rig capture`.
|
||||
4. Restore the DB backup only if migration or DB corruption is confirmed. Do not
|
||||
replace the DB just because continuity sessions are still live but management
|
||||
projection is degraded.
|
||||
|
||||
For npm runtime:
|
||||
|
||||
```bash
|
||||
npm install -g @openrig/cli@<previous-version>
|
||||
rig daemon stop
|
||||
rig daemon start
|
||||
```
|
||||
|
||||
## Roadmap: Better Hot Upgrades
|
||||
|
||||
The product should make the proven manual path boring and explicit.
|
||||
|
||||
Needed product surfaces:
|
||||
|
||||
- `rig upgrade preflight`:
|
||||
daemon PID/runtime source, CLI source, DB path, migration plan, active rigs,
|
||||
continuity targets, tmux liveness, disk space, DB integrity, backup target,
|
||||
and rollback runtime.
|
||||
- `rig daemon adopt-state` or equivalent:
|
||||
recover a healthy daemon on a port when `daemon.json` is missing.
|
||||
- `rig upgrade backup`:
|
||||
online SQLite backup plus integrity and snapshot-presence verification.
|
||||
- `rig upgrade promote-runtime <commit|artifact>`:
|
||||
start from a clean worktree or packaged artifact under an even/LTS Node.
|
||||
- `rig upgrade verify --rig <name>`:
|
||||
filtered inventory, capture, transcript, restore-check, and honest continuity
|
||||
classification.
|
||||
- CLI/daemon provenance:
|
||||
`rig version --json` should report CLI path, daemon path, commit/package
|
||||
version, Node version, DB path, and started-at.
|
||||
- Wrapper alignment:
|
||||
rigx/default `rig` should clearly show which real CLI it delegates to.
|
||||
- Compact inventory:
|
||||
first-class `rig ps --rig <name> --nodes --compact` or equivalent, so
|
||||
operators do not need ad hoc `jq` for routine safety checks.
|
||||
|
||||
Research still needed:
|
||||
|
||||
1. Migration-bearing hot upgrade on a throwaway rig.
|
||||
2. Hot upgrade with non-critical live Codex seats.
|
||||
3. Hot upgrade with service-backed rigs.
|
||||
4. Adoption/reconciliation when daemon DB says sessions are running but tmux has
|
||||
partially drifted.
|
||||
5. Automated rollback on daemon startup failure or migration failure.
|
||||
|
||||
## Operator Summary
|
||||
|
||||
Hot upgrade rule:
|
||||
|
||||
**Snapshot continuity rigs, back up the DB, stop only the daemon, start the new
|
||||
daemon against the same DB, then verify live tmux sessions through filtered
|
||||
management surfaces.**
|
||||
|
||||
Disruptive restore rule:
|
||||
|
||||
**Use `rig down` only when testing or accepting session teardown.**
|
||||
@@ -1,153 +0,0 @@
|
||||
---
|
||||
name: openrig-user-settings
|
||||
description: Use when the user asks an OpenRig agent to read or change OpenRig configuration settings — workspace paths, file allowlists, progress scan roots, daemon port/host, transcripts, or anything stored in ~/.openrig/config.json
|
||||
---
|
||||
|
||||
# OpenRig User Settings
|
||||
|
||||
OpenRig settings live in `~/.openrig/config.json` and are managed via the
|
||||
`rig config` CLI family. The agent-editable surface is **CLI shell-out**;
|
||||
do NOT write the JSON file directly unless the operator specifically asks
|
||||
for raw-text editing (which is handled by the UI Files browser, not by you).
|
||||
|
||||
## Read
|
||||
|
||||
```bash
|
||||
rig config # all keys, value + source
|
||||
rig config --json # JSON: full RiggedConfig
|
||||
rig config --json --with-source # JSON: {key: {value, source, default}}
|
||||
rig config get <key> # single value
|
||||
rig config get <key> --show-source # value + source on one line
|
||||
rig config get <key> --json # {value, source, default}
|
||||
```
|
||||
|
||||
Resolution order: **env var > config file > default**. Always use
|
||||
`--show-source` (or `--json`) when reporting back to the operator so they
|
||||
see *where* the value came from.
|
||||
|
||||
## Write
|
||||
|
||||
```bash
|
||||
rig config set <key> <value> # set a key
|
||||
rig config reset <key> # clear one override (revert to default)
|
||||
rig config reset # delete the whole file
|
||||
```
|
||||
|
||||
## Initialize a default workspace
|
||||
|
||||
```bash
|
||||
rig config init-workspace # scaffold ~/.openrig/workspace/ with missions + slices
|
||||
rig config init-workspace --dry-run # show what would be created
|
||||
rig config init-workspace --root /path # use a custom root
|
||||
rig config init-workspace --force # overwrite scaffolded files (NOT operator content)
|
||||
```
|
||||
|
||||
This creates a file-backed Project workspace under the workspace root:
|
||||
|
||||
```text
|
||||
README.md
|
||||
STEERING.md
|
||||
missions/<mission-id>/README.md
|
||||
missions/<mission-id>/PROGRESS.md
|
||||
missions/<mission-id>/slices/<slice-id>/README.md
|
||||
progress/
|
||||
field-notes/
|
||||
specs/
|
||||
```
|
||||
|
||||
It seeds two starter missions with multiple slices so the Project UI has a
|
||||
real mission/slice map out of the box. It is operator-explicit; do NOT run it
|
||||
on your own initiative unless the operator asks for workspace initialization
|
||||
or repair.
|
||||
|
||||
## Common keys
|
||||
|
||||
| Key | Type | Purpose |
|
||||
|---|---|---|
|
||||
| `daemon.port` | number | OpenRig daemon HTTP port (default 7433) |
|
||||
| `daemon.host` | string | Daemon bind host (default 127.0.0.1) |
|
||||
| `db.path` | string | SQLite DB path (default ~/.openrig/openrig.sqlite) |
|
||||
| `transcripts.enabled` | boolean | Whether the daemon writes transcripts |
|
||||
| `transcripts.path` | string | Transcripts dir (default ~/.openrig/transcripts) |
|
||||
| `workspace.root` | string | Single-root override (default ~/.openrig/workspace) |
|
||||
| `workspace.slices_root` | string | Slice discovery root; default `<root>/missions` |
|
||||
| `workspace.steering_path` | string | STEERING.md path; default `<root>/STEERING.md` |
|
||||
| `workspace.field_notes_root` | string | Field notes dir; default `<root>/field-notes` |
|
||||
| `workspace.specs_root` | string | Specs dir; default `<root>/specs` |
|
||||
| `files.allowlist` | string | `name:/abs/path,name:/abs/path` — UI Files browser roots |
|
||||
| `progress.scan_roots` | string | `name:/abs/path,name:/abs/path` — Progress browse roots |
|
||||
|
||||
Resolution order for workspace per-subdir keys: per-subdir override >
|
||||
`workspace.root` cascade > built-in default.
|
||||
|
||||
## Common operator requests → canonical commands
|
||||
|
||||
> **"Make the UI work against an existing workspace layout"**:
|
||||
> set the per-subdir workspace overrides explicitly:
|
||||
>
|
||||
> ```bash
|
||||
> rig config set workspace.slices_root /path/to/your/workspace/missions
|
||||
> rig config set workspace.steering_path /path/to/your/workspace/STEERING.md
|
||||
> rig config set workspace.progress_scan_roots 'work:/path/to/your/workspace,missions:/path/to/your/workspace/missions'
|
||||
> rig config set workspace.field_notes_root /path/to/your/workspace/field-notes
|
||||
> ```
|
||||
>
|
||||
> No restart needed for the CLI; for the daemon's reads to pick up
|
||||
> changes affecting startup-time wiring (`files.allowlist`,
|
||||
> `progress.scan_roots`), restart with `rig daemon restart`.
|
||||
|
||||
> **"Initialize a default workspace"**:
|
||||
>
|
||||
> ```bash
|
||||
> rig config init-workspace
|
||||
> ```
|
||||
|
||||
After initialization, the Project UI expects this mapping:
|
||||
|
||||
- `workspace.root` maps to the Project workspace.
|
||||
- `workspace.root/missions/<mission-id>` maps to a Project mission.
|
||||
- `workspace.root/missions/<mission-id>/slices/<slice-id>` maps to a Project slice.
|
||||
|
||||
Queue item bodies or tags should mention the mission id and slice id when the
|
||||
work belongs to a slice. That lets the Project Story, Queue, Tests, and
|
||||
Topology tabs attach runtime work to the filesystem slice.
|
||||
|
||||
> **"Allow the file browser to see X directory"**:
|
||||
>
|
||||
> ```bash
|
||||
> # Append to existing list (operator decides the name token):
|
||||
> rig config get files.allowlist --show-source # check current
|
||||
> rig config set files.allowlist 'workspace:/path/to/ws,docs:/path/to/docs'
|
||||
> rig daemon restart # picks up new roots
|
||||
> ```
|
||||
|
||||
> **"What's my current setting for X and where does it come from?"**:
|
||||
>
|
||||
> ```bash
|
||||
> rig config get <key> --show-source
|
||||
> ```
|
||||
|
||||
## When NOT to use this skill
|
||||
|
||||
- **Per-rig config** — settings are host-global at v0; per-rig is v0+1.
|
||||
- **Secrets / credentials** — the `vault.specialist` managed-app handles
|
||||
secrets. Don't put API keys or tokens in `~/.openrig/config.json`.
|
||||
- **Settings sync across hosts** — out of scope at v0.
|
||||
|
||||
## Errors you might see
|
||||
|
||||
- `Unknown config key "<x>". Valid keys: …` — the key name is wrong.
|
||||
Check the table above; suggest the correct key.
|
||||
- `Config file at <path> is malformed. Fix the JSON or reset with: rig config reset` —
|
||||
hand-edit broke the JSON. Operator can `rig config reset` (deletes the
|
||||
whole file) or fix the syntax in the Files browser.
|
||||
- `Invalid value for <key>: expected a number/true-false, got "<x>"` —
|
||||
wrong type for a typed key. Reach for the key's type in the table.
|
||||
|
||||
## Provenance + safety
|
||||
|
||||
- Never write to `~/.openrig/config.json` directly. Use `rig config set`.
|
||||
- Don't run `rig config init-workspace` on your own initiative — wait for
|
||||
an operator request.
|
||||
- Always cite the resolved source (env / file / default) when reporting
|
||||
values back, so the operator knows whether their change actually took.
|
||||
Loaded 100 of 116 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user