86 Commits
Author SHA1 Message Date
Mike SchwarzandOpenRig contributors 451e373165 fix(cli): replace proof artifacts without writing through links (#314)
* fix(cli): replace proof artifacts without writing through links

`rig proof add --replace` opened the existing artifact name with the "w"
flag. That follows a symlink and truncates a shared inode, so replacing
an artifact name that was a symlink or hard link overwrote the other
path's bytes, including files outside the slice and proof media.

--replace now writes a uniquely named staging file next to the artifact,
created exclusively, and renames it over the name. The old link or inode
is never opened for writing, so other paths keep their bytes. A failed
write or rename leaves the target as it was and removes only the staging
file this call created; the original error is reported. A self-sourced
replace still works because the source is read before the write. The
non-replace path keeps its exclusive-create refusal.

The replaced artifact is a new inode with default permissions. There is
no fsync, so this is a directory-entry swap, not a crash-durability
guarantee.

* fix(cli): keep artifact permissions and the first failure on proof replace

An explicit --replace of an existing regular artifact now carries its
permission bits onto the staging file before the swap, so a replacement
never broadens access (a 0600 artifact stays 0600; a read-only artifact
is replaced and stays read-only). A symlinked or new name still gets
default permissions.

The write and close failures are collected separately: the first one is
reported and a later close failure is a warning. A close failure on its
own still refuses the rename, and the target keeps its bytes either way.

* fix(cli): create the proof replace staging file no wider than the artifact

The exclusive staging open now passes the replaced artifact's permission
bits (or the default 0666 for a symlinked or new name) as its creation
mode, so the staging file is never created wider than the artifact it
replaces. The fchmod still sets the exact bits regardless of umask.

---------

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-10-01 06:23:13 -07:00
Mike Schwarzandv-openrig-build 3fba553a2f docs: describe OpenRig teams as persistent in the npm and Context7 descriptions (#304)
Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
2026-10-01 05:11:25 -07:00
Mike Schwarzandv-openrig-build 29a72ad324 fix(gateway): redact secrets in the Slack file-upload title (#302)
The file title sent with files.completeUploadExternal was the queue summary
(or the file name) as is, while the message text carrying the same summary
already went through redactSecrets. A secret in a row summary was therefore
hidden in the text but shown as the uploaded file's title. The title now
goes through the same redaction. Slack does not parse file titles as mrkdwn,
so the text's control-syntax escaping is not applied to it.

Fixes #300

Claude-Session: https://claude.ai/code/session_01V8RzdrMhGkYLV4rn96kNMN

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
2026-10-01 04:37:17 -07:00
Mike SchwarzandOpenRig contributors d0623e06cb feat(daemon): turn the web UI and its terminal WebSocket off by default (#301)
The daemon no longer serves the web UI's pages, assets and SPA routes, or
registers the web-terminal WebSocket, unless `ui.enabled` is true. Turn them
on with `rig config set ui.enabled true`, then stop and start the daemon.
While the UI is off, a page request answers 404 with those steps, and
`rig ui open` asks the running daemon and prints the same steps instead of
opening the page.

The /api routes, /healthz and the HTTP terminal routes (open, views, preview,
status) answer as before. The guard that ran in front of the HTTP terminal
routes through the WebSocket route still runs when the WebSocket is absent.

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-10-01 04:34:43 -07:00
Mike Schwarzandv-openrig-build 9480978770 docs: describe OpenRig as a network of agents in the README, npm and Context7 (#297)
The README opening now says what OpenRig is in one sentence (open-source
software for building and running your own network of agents) and closes
with the line about the AI civilization experiments. The npm package
description and the Context7 description use the same short summary:
"Build your own network of agents from Claude Code, Codex and Pi:
long-running teams with roles, shared context and owned work."

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
2026-10-01 04:15:12 -07:00
Mike Schwarzanddev-driver bb5d17223a fix(daemon): retain bound Claude auto identity across restore (#294)
Co-authored-by: dev-driver <dev-driver@openrig-build>
2026-10-01 03:01:43 -07:00
Mike Schwarzandv-openrig-build 8c4b30bee8 docs(onboarding): tell both doghouse failures and hand over intent, not instructions (#289)
Onboarding piece 01 told only half of the doghouse story: the build that
over-grows (now a light that needs power, not a lock) and then asked "How
big is the dog?", which belongs to the other half. It now tells both: the
moon base, stopped by "does the thing actually need this?", and the tidy
doghouse whose door the dog can't fit through, stopped by "how big is the
dog?". A short paragraph adds that shared understanding of the goal, not
tighter instructions, is what prevents both.

Piece 02's ending becomes "When you need more": the capability map is read
when needed rather than by every seat, a world pack is for planning and
routing work, and the world template is pointed to for people setting one up.

The delegating-work skill gains "Hand over intent, not instructions".

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
2026-10-01 02:28:22 -07:00
Mike SchwarzandOpenRig contributors 809c338843 fix(cli): report a mutating handover's timeout as an unknown outcome (#198)
A mutating `rig seat handover` (and `rig handover`, which shares it) waits up to
120 s for the daemon (#260). When the client reaches that bound the daemon may
still be working, so the handover's outcome is unknown, but the CLI surfaced only
a raw transport timeout (reported in korallis/agent-stack#32).

The CLI now prints "handover outcome unknown" in text and JSON, exits 1, and
makes no second request. It tells the user to inspect the seat before any new
handover, and that a result shown there may belong to an earlier attempt.
A completed or refused handover, a connection failure, and dry-run behave as
before.

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-10-01 01:26:01 -07:00
Mike Schwarzandv-openrig-build 792ef42e5f docs: add contributor maps and a developing-openrig skill (#282)
* docs: add contributor maps and a developing-openrig skill

Add ARCHITECTURE.md (packages, request path, counts with the commands that
produce them, where to add a command, route, migration, adapter, skill,
context pack or scenario), docs/as-built/arteries.md (high-impact areas,
their dependents and past regressions) and docs/as-built/test-layers.md
(what to run before a pull request and what each layer proves).

Add a repo-local developing-openrig skill for Claude Code (.claude/skills)
and Codex (.agents/skills) that routes to these maps, with narrow .gitignore
exceptions so only that skill is tracked. Point CONTRIBUTING.md at the maps
and correct its skill-mirror instructions. Replace the private-host paragraph
in the shipped openrig-skills router with a pointer to the repository skill.

* docs: correct six factual points from review

Newest as-built markers; skills may have one or several copies; the host
scenario runner drops rather than refuses TMUX and daemon variables;
scenario-10 declares its own normaliser; the managed Claude launch applies
only with an explicit permission mode; Dockerfile.scenarios is layered by
run-pr-scenarios.sh. Also tighten several wordings the review flagged.

---------

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
2026-10-01 00:49:21 -07:00
Mike Schwarzandv-openrig-build 07dab0761d fix(daemon): shipped startup files and resources follow the running install (#261) (#269) (#281)
* fix(daemon): deliver built-in startup files from the running install (#261)

Built-in startup files (CULTURE-default.md, openrig-start.md and the two
onboarding files) are stored per seat as absolute paths inside the install
that created the seat. After an upgrade removes that install (mise and other
versioned managers), every fresh launch rolled back with ENOENT, and restore
blocked on the missing required file. While the old install remained, seats
kept receiving the old version's shipped guidance.

Fresh launch (SeatLifecycleService.readStartupContext) and restore
(pre-validation and replay) now re-anchor a stored file to the running
daemon's assets when it is a recognized built-in: one of the four logical
names, stored at exactly <ownerRoot>/<known relative path>, with ownerRoot a
daemon/assets directory. Custom rig and agent files, including a same-named
CULTURE-default.md, are delivered exactly as stored. Required/appliesOn/
delivery metadata is unchanged, a missing current built-in still fails
honestly, and a same-native resume still replays nothing.

Refs #261

* fix(daemon): project shipped-spec resources from the running install (#261)

Kernel and library agents ship inside the install, so their stored projection
entries (agent guidance, shared runtime settings/MCP fragments) also point
into the install that created the rig. After that install is removed, a fresh
launch still rolled back in projection, before startup-file delivery.

Fresh launch and restore (pre-validation drift checks and replay) now
re-anchor a stored projection entry to the running install's daemon/specs when
both its sourcePath and its resource path lie under the same OpenRig install's
daemon/specs (packaged @openrig/cli/daemon/specs or a packages/daemon/specs
checkout). A resource stored elsewhere, such as the openrig-core plugin under
~/.openrig/plugins, user specs, or a folder merely named daemon/specs, is
projected exactly as stored. Identifiers, category, target, merge behavior and
the existing skill exclusion are unchanged; a resource missing from the
running version keeps the existing failure or warning.

Refs #261

* fix(daemon): own-key built-in lookup; restore-check judges the running paths (#261)

The built-in name lookup used a plain object, so a custom startup file named
constructor, toString or __proto__ matched an inherited key and fresh launch
threw on a valid seat (review finding on be599a64). Use a Map.

RestoreCheckService.checkStartupContext checked and reported the stored
paths directly, so a seat whose old install was removed showed missing
required inputs that replay no longer uses, and named stale paths in its
evidence and remediation. It now applies the same resolvers to the inspected
context and uses the resolved paths in both the predicates and the reported
text. The red/yellow rule, genuinely missing current or custom files, and
missing/malformed/probe-error handling are unchanged. The route's context
reader passes ownerRoot and sourcePath through so the resolvers can apply.

Refs #261

* fix(daemon): shipped-spec startup files follow the running install (#261)

Kernel and library seats also store their rig culture and agent startup files
(culture/CULTURE.md, guidance/role.md, startup/context.md) as absolute paths
inside the install's daemon/specs. With the projection fixed, a kernel created
by a removed install still rolled back on the culture file, and its post-launch
role/context would have followed.

The startup-file resolver now also re-anchors a stored startup file whose
ownerRoot and absolutePath both lie under the same recognized install's
daemon/specs, using the same mapping as projection entries. It applies through
fresh launch (pre- and post-launch delivery), restore replay and
pre-validation, and restore-check. Custom, external and plugin paths, and all
required/applicability/delivery metadata, are unchanged; a file missing from
the running version still fails or warns honestly.

Refs #261

* fix(daemon): re-anchor dev-checkout paths only when missing (#261)

A daemon running from one install remapped every recognized shipped path,
including ones stored from a developer checkout (packages/daemon/...). Those
files can be newer than, or absent from, the running install, so a present
file was remapped to a missing running path and the launch rolled back
(review finding, confirmed by both reviewers).

Packaged installs (@openrig/cli/daemon/...) still re-anchor even while the
stored file exists, so seats never keep an old version's shipped content.
Dev-checkout files re-anchor only when the stored file is missing. Recognition
is limited to those two layouts for built-in assets too. Each consumer passes
its own existence check (restore fsOps, restore-check deps; fresh launch uses
the filesystem).

Refs #261

* fix(daemon): leave legacy persisted startup shapes as stored (#261)

Snapshots and contexts persisted by older versions can lack ownerRoot on
startup files or sourcePath on projection entries. The #261 resolvers called
path.resolve on those fields, which threw, so restore reported restore_error
instead of its real outcome; restore pre-validation walks projection entries
even for an exact resume (CI: restore-honesty-d1-d6 D6a, 4 failures).

Entries without a string root or path are now returned exactly as stored,
which is their pre-#261 behavior.

Refs #261

---------

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
2026-10-01 00:06:13 -07:00
Mike Schwarzanddev-driver d1ba4ee71e fix(cli): honor the recorded daemon endpoint for local commands (#266) (#279)
* fix(cli): use current home daemon endpoint for local clients

* fix(cli): retain recorded endpoint after daemon exit

---------


(cherry picked from commit cdf5fff724)

Co-authored-by: dev-driver <dev-driver@openrig-build>
2026-09-30 23:37:14 -07:00
Mike SchwarzandOpenRig contributors 6963421604 fix: give the managed Claude capability query room before refusing a launch (#278)
A managed Claude launch with an explicit permission mode first runs
`claude --help` to read the supported modes. The query was killed after one
second, so a valid but slow help refused the launch with "capability query
failed". The daemon now allows five seconds; a hung query still ends at that
bound with the same refusal. `rig seat set-permissions` waits up to 10 seconds
and a mutating `rig seat handover` gets the existing 120-second launch window,
so the daemon's answer arrives before the client deadline.

Port of #271 from release/0.6.4 (squash bfa66821). Original author:
dev50-driver; one-line S03 test finisher: dev60-driver.

Refs #260

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-30 23:32:01 -07:00
Mike SchwarzandOpenRig contributors b24ef4f6f6 fix(daemon): keep binary files byte-identical in rig bundles (#276)
Bundle create read every vendored agent-package file, and the declared
culture, docs and startup files, as UTF-8 text and wrote it back as UTF-8.
Any byte sequence that is not valid UTF-8 became U+FFFD, and the integrity
manifest was hashed from the changed copy, so inspect and install verified
the corrupted bytes as intact.

Copy those files as bytes: the pod assembler reads them with readFileBuffer
and writes the same bytes, and the install-side skills and workflow-spec
routers copy with fs.copyFileSync. Rewriting rig.yaml and agent.yaml import
refs stays a text operation.

Port of #257 from release/0.6.4 (squash 2174b11e). The async test change in
that squash is already on main via #268 and is not repeated here.

Fixes #245

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-30 23:31:44 -07:00
Mike SchwarzandOpenRig contributors 15763c46bb fix(daemon): relaunch a sole seat after fresh --stop ends its tmux server (#277)
Stopping the server's last session ends tmux's server, so launchFresh's
later probes saw transport_unavailable and refused with tmux_probe_failed
after the occupant was already stopped. After its own successful stop,
launchFresh now restores an empty server with the existing startServer()
(a no-op while the server is up; no session is invented), so the
classified probes get a positive answer. Transport, permission,
collision, claimed-seat and wrong-pane refusals are unchanged.

Port of #267 from release/0.6.4 (squash fa770114), without its RC-only
CHANGELOG notes.

Refs #265

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-30 23:31:26 -07:00
Mike Schwarzandv-openrig-build 700e6a05be fix(cli): include the repository README in the npm package (#272)
The npm page for @openrig/cli shows "No README data found" because the
published package root has no README.md. The CLI build already copies the
root LICENSE into the package; it now copies the root README.md the same
way, and the generated copy is ignored like LICENSE. The packaging test
now also checks that npm pack carries README.md byte-for-byte.

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
2026-09-30 23:02:03 -07:00
Mike Schwarzanddev-driver 964b904fd2 fix(daemon): prove managed Claude identity through shell wrappers (#264)
* fix(daemon): prove managed Claude identity during restore

* fix(daemon): sample Claude lineage only for shell labels

* test(daemon): distinguish bare shells from unusable Claude panes

* fix(identity): retain unavailable final Claude command observation

---------

Co-authored-by: dev-driver <dev-driver@openrig-build>
2026-09-30 21:28:33 -07:00
Mike SchwarzandOpenRig contributors 030227c5d1 test(daemon): assert async ps samplers stay pending through a microtask drain (#268)
The three anti-sync discriminators in list-processes-async.test.ts raced a
0ms timer against the sampler's result. Timer order is not a valid guarantee
of async execution: in a local probe, a 70ms synchronous stall after spawning
a single-PID `ps eww` let the result settle before the 0ms timer in most
trials. The CI failure of this test is consistent with that race; the CI
timing itself was not measured.

Assert instead that the returned promise is still pending after draining 20
microtask ticks: an async execFile cannot settle without an event-loop turn,
while a synchronous ps inside the call settles within a few ticks. The real
rows and HOME assertions are unchanged.

Refs #245

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-30 21:08:42 -07:00
Mike SchwarzandOpenRig contributors de9ec4f7ee test(cli): accept a pre-release version in the CLI --version check (#255)
client.test.ts expected only MAJOR.MINOR.PATCH, so the 0.6.4-rc.1 candidate failed
Tests run 36798254083. Allow an optional pre-release suffix and keep the anchors and the
optional (commit[, dirty]) stamp. Test-only.

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-30 18:35:57 -07:00
c1ff76635e test: bind scenario seeds and exercise the library baton in CI (#243)
* test: bind scenario seeds and exercise the library baton in CI

* test: run named scenarios through a remote Docker executor

* test: bound and clean up the testbed image-load check

---------

Co-authored-by: dev-driver <dev-driver@openrig-build>
Co-authored-by: dev-qa <dev-qa@openrig-build>
2026-09-30 17:55:20 -07:00
Mike SchwarzandOpenRig contributors afde814f5b fix(daemon): keep a blocked row's park timer through a seat handover (#242)
* fix(daemon): keep a blocked row's park timer through a seat handover

At a seat swap, the occupant invalidator stops every watchdog job the retiring
generation registered. A park timer (rig queue block --wake-after, with or without
--wake-max) is registered by the parking seat, so a handover stopped it too. Nothing
re-armed it, and the row stayed blocked with no timer, which is the strand reported
in korallis/agent-stack#61.

The rig's parked-owner consumer eventually noticed the dead wake and sent one generic
wake once the new occupant was idle. The recorded wake time, message and backoff
cadence were still lost.

A blocked row's current queue-generated timer wakes the seat that owns the row, and
the successor inherits that row, so the swap now keeps it. The queue lists those
timers: each is still the row's current armed wake, is still active, and still
targets the row's destination. The watchdog drop leaves them running.

Every other job the retiring generation registered still stops: operator-attached
watchdogs, superseded or stale timers, timers of rows rerouted to another seat, and
occupant-only jobs. Re-parking still retires the kept timer, so no duplicate is
created. A failed handover never reaches the invalidator, as before.

* fix(daemon): retire a park timer when its row is rerouted

routeToFallback moved a blocked row to a new owner but left the row's park timer
active and aimed at the old owner, so it could fire to the old owner. The
pre-delivery check only refuses timers whose rows are all terminal. That was already
reachable on main (park, reroute, fire), and keeping park timers through a handover
also let it happen after a swap (review-r2).

The reroute now retires the row's current park-generated timer through the existing
retireParkGeneratedTimer path, reason park_rerouted, the same one re-park and exit
use. The new owner has no dedicated wake from a reroute, as before; the retired timer
leaves the row's wake dead, so the parked-owner backstop covers it.

* fix(daemon): leave a repeating queue wait running when its row is rerouted

The previous commit retired every park timer on reroute. A repeating queue wait
already delivers to the row's current owner (evaluateQueueWait sends to view.owner),
so it woke the new owner correctly, and retiring it took that wake away. Only a
periodic park timer is aimed at the old owner, so only that is retired now.

Tests now fire through the engine with resolveQueueWait wired, as startup.ts wires
it. After a periodic reroute the row shows no live park timer, and the new owner's
parked diagnosis sees it as unhealthy, so the backstop covers the new owner. A
repeating wait survives the reroute, with or without swaps, and delivers only to the
new owner.

---------

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-30 17:19:00 -07:00
Mike SchwarzandOpenRig contributors cc2c37dc2f fix(daemon): keep UTF-8 intact across herdr socket chunks (#241)
createHerdrSocketRpc decoded each socket chunk on its own, so a
multi-byte character split across two chunks became U+FFFD while the
JSON line still parsed. Setting the socket encoding to UTF-8 uses Node's
streaming decoder, which carries an incomplete character into the next
chunk. Newline framing, id matching and error, end and timeout handling
are unchanged.

The new test drives the real RPC over a private unix socket and splits
the reply inside 2-, 3- and 4-byte characters, plus a case where
another id's line arrives first.

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-30 16:11:27 -07:00
Mike Schwarzanddev-driver e6bfdce242 fix(transport): distinguish unverified runtime from stopped agent (#240)
Co-authored-by: dev-driver <dev-driver@openrig-build>
2026-09-30 15:24:11 -07:00
d3ad0d1995 fix(daemon): observe native processes independently of the inherited locale (#239)
Both native process listers run `ps` with an `lstart` column and parse it with
an English date pattern. `ps` formats that column through the locale, so a
daemon that inherited a non-English locale (for example LANG=de_DE.UTF-8,
LC_TIME=fr_FR.UTF-8 or LC_ALL=ja_JP.UTF-8) saw every row fail the pattern:
process detection and resume metadata silently came back empty.

Each `ps` call now runs with a child-only `LC_ALL=C`, spread over the existing
environment. The parent environment, the column sets, the parsers and every
identity requirement are unchanged.

On macOS, the C locale also makes `ps` print non-ASCII bytes in the command
column as escapes (for example `\240`) instead of raw UTF-8. Token boundaries
and every ASCII identity token (executable name, session and resume ids) are
unchanged.


Claude-Session: https://claude.ai/code/session_01V8RzdrMhGkYLV4rn96kNMN

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:14:59 -07:00
Mike SchwarzandOpenRig contributors bcc0010de9 fix: replace stopped same-name rig generations on YAML import (#196)
* fix(daemon): rig remove never kills another rig's live seat; seat refs skip archived rigs (#174)

An archived duplicate of a live rig shares its name and its seats'
canonical session names.

- `rig remove <archived-rigId> <node>` killed the tmux session by name,
  so it could end the live rig's seat. Removal now asks whether another
  node owns that session name, using the handover's live-ownership check,
  now shared as session-owner.ts. If another node owns it, removal
  leaves the session running, doesn't block on or reroute the queue
  work addressed to it, and reports the owner as `sessionKeptFor`. The
  node itself is still removed.
- Seat refs (`member@rig`) for seat launch, stop, model and handover
  resolved rigs by name including archived ones, so they failed with
  "matched multiple nodes". They now resolve unarchived rigs only, as
  default reads do since migration 042. Other findRigsByName callers
  are unchanged.

* fix(daemon): archived rigs don't claim a live seat's session or input target (#174)

Review follow-up. Archiving a rig keeps its bindings, so the archived twin
still names the live seat's session:

- Removing the live node found the archived twin as the "other owner",
  kept the session and removed the node's open work. Removal now ignores
  owners in archived rigs, so the live node kills its own session and
  still refuses open work without --fallback. The handover check is
  unchanged.
- The delivery guard needs exactly one match for a target, and the twin's
  binding made it two, so delivery to the live seat failed. Unarchived
  matches now win, and archived ones count only when nothing else
  matches. Exactly one match is still required, so a truly ambiguous
  live target still refuses.
- `rig remove` and `rig shrink` human output now says when a session was
  kept, and for whom.

* fix(daemon): a YAML import archives the stopped same-name rig it replaces (#141)

After the seats' tmux server died, `rig up <same rig.yaml>` created a
second, unarchived rig with the same name. Every seat name then matched
two nodes, so launches and kills were refused.

When an explicit YAML import (PodRigInstantiator.instantiate) finds an
unarchived rig with the same name, it first confirms that rig is stopped:
- no running session rows (the existing running-name guard); and
- for every session name it used, this daemon's tmux reports positive
  absence or "no server running".

It then archives that rig in the same database transaction that creates
the replacement. The earlier rig's records are kept, and the output names
it with `rig unarchive <id>`. If the rig can't be confirmed stopped, the
import creates nothing and says why.

If creating the replacement fails, the service hook refuses it, or every
replacement node fails and the replacement is removed, the earlier rig
is un-archived. An adapter that cannot probe keeps today's behavior.

* fix(daemon): one YAML import per rig name while it may archive a generation (#141)

Review follow-up to the stopped-generation archive.

- Concurrency. The stopped check awaits tmux, and a second same-name
  import could run during that wait. It could replace the same old rig
  too, or archive the first import's in-progress replacement, which has
  no running sessions yet. The YAML import now takes a per-database,
  per-name in-flight claim, and a same-name import arriving meanwhile is
  refused (generation_unconfirmed). Unrelated names are unaffected. The
  create transaction also rechecks that the same-name set is the one it
  checked, and that each archive changed its row, so a rollback restores
  only archives this import made.
- Responses. generation_unconfirmed is now a 409 conflict with its
  message on POST /api/up and POST /api/rigs/import, not a 500. The
  archive notice also rides the attention_required outcome, where the
  replacement is kept.

* fix(cli): print the #141 archive notice on the attention 409 and the generation_unconfirmed message

rig up returned from its status >= 400 block before either warnings loop, so the
archive notice (old rig id and its unarchive command) on an attention 409 reached
--json only. Print the response warnings after the attention nodes; that path returns
early, so nothing prints twice. Render generation_unconfirmed verbatim like
rig_name_running instead of the validate-your-spec fallback. JSON output and exit
codes are unchanged.

* fix(daemon): archived generations don't block the replacement's handover or pod shrink

A YAML re-import archives the stopped earlier generation, which keeps its bindings
to the session names the live replacement now uses.

Handover: a fresh, fork or rebuild successor reuses the seat's own session name,
so the archived binding made finalize return successor_already_managed after the
successor had replaced the process. The owner check skips archived rigs for
composer-launched successors, as removeNode does. A discovered successor is still
blocked by any other owner.

Pod shrink: shrinkPod counted and, with --fallback, rerouted queue work addressed
to member session names that another unarchived node owns. It now applies
removeNode's ownership rule first, so shrinking the archived pod neither stops on
nor moves the replacement's work.

* fix(daemon): keep a shrink target's own shared-name work in the up-front check

C3's shrinkPod ownership filter excluded only the node being checked, so when two
members of the pod being shrunk shared a session name, each counted the other as its
owner. Their open queue work then dropped out of the up-front check. Without
--fallback the shrink removed one member and failed on the last. With --fallback the
work wasn't rerouted.

findOtherSessionOwner gains an optional excludeNodeIds, applied in both the binding
and the session-row lookups before the first match, and its default is unchanged.
shrinkPod passes the whole target, so only an unarchived owner outside the target
takes a name's work out of the check. Before C3, shrinking such a pod refused up front
or rerouted with --fallback, and that behavior is restored.

---------

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-30 14:08:23 -07:00
5177ec8913 fix: provider-aware Codex readiness for non-OpenAI providers (#222)
* fix: provider-aware Codex readiness for non-OpenAI providers (#194)

`rig setup` and the kernel runtime probe treated `codex login status` as the
only Codex authentication check. A user whose Codex selects a custom provider
with `requires_openai_auth = false` and an `env_key` (the reported Amazon
Bedrock bearer-token provider) failed setup and was never offered a Codex
kernel, even with the provider's credential set.

Both checks now read the provider selected in `$CODEX_HOME/config.toml`. For
an explicit provider entry with `requires_openai_auth = false` and an
`env_key`, a nonblank variable counts as local credential availability; the
kernel probe still requires the Codex executable. Every other case keeps the
OpenAI login check, including a missing file, a parse error, a legacy
top-level `profile`, and built-in or undeclared providers, so an unresolved
config never earns readiness. The setup message says this is a local
credential check, not remote authentication or inference.

`AWS_BEARER_TOKEN_BEDROCK` joins the known provider-auth names, so an operator
who names it in `recovery.provider_auth_env_allowlist` can forward it to
managed seats. Nothing is forwarded without that opt-in.

Other Codex config layers (project, system or managed config, requirements,
`-c`, `--profile`) are not resolved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V8RzdrMhGkYLV4rn96kNMN

* docs: narrow the #194 unresolved-config wording

An unresolved Codex config does not take the new env-key shortcut; readiness
still follows the existing login result. The comment and one test title now say
that, instead of implying OpenRig validates every configuration. No behavior
change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V8RzdrMhGkYLV4rn96kNMN

---------

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 13:37:36 -07:00
Mike Schwarzanddev-driver 5b344e0578 fix(claude): preserve unset native config selection (#225)
Co-authored-by: dev-driver <dev-driver@openrig-build>
2026-09-30 12:02:47 -07:00
Mike Schwarzandv-openrig-build b43498d7da docs(contributing): ask security and integration PRs for practical scenarios (#224)
Adds a 'Before a security or integration PR' section to CONTRIBUTING.md, a
security question block to the PR template, and a trust-model bullet to
SECURITY.md's scope notes. Additive only; existing scope text is unchanged.

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
2026-09-30 11:57:13 -07:00
Mike Schwarzanddev-qa 8b5e948807 chore(release): prepare 0.6.3 regression repair notes (#223)
Co-authored-by: dev-qa <dev-qa@openrig-build>
2026-09-30 11:25:15 -07:00
Mike Schwarzanddev-qa 4dc4047cdb fix(ci): serialize script tests sharing build outputs (#221)
Co-authored-by: dev-qa <dev-qa@openrig-build>
2026-09-30 11:03:08 -07:00
Mike SchwarzandOpenRig contributors 3b1b335dbe fix(daemon): rig remove never kills another rig's live seat; seat refs skip archived rigs (#174) (#181)
* fix(daemon): rig remove never kills another rig's live seat; seat refs skip archived rigs (#174)

An archived duplicate of a live rig shares its name and its seats'
canonical session names.

- `rig remove <archived-rigId> <node>` killed the tmux session by name,
  so it could end the live rig's seat. Removal now asks whether another
  node owns that session name, using the handover's live-ownership check,
  now shared as session-owner.ts. If another node owns it, removal
  leaves the session running, doesn't block on or reroute the queue
  work addressed to it, and reports the owner as `sessionKeptFor`. The
  node itself is still removed.
- Seat refs (`member@rig`) for seat launch, stop, model and handover
  resolved rigs by name including archived ones, so they failed with
  "matched multiple nodes". They now resolve unarchived rigs only, as
  default reads do since migration 042. Other findRigsByName callers
  are unchanged.

* fix(daemon): archived rigs don't claim a live seat's session or input target (#174)

Review follow-up. Archiving a rig keeps its bindings, so the archived twin
still names the live seat's session:

- Removing the live node found the archived twin as the "other owner",
  kept the session and removed the node's open work. Removal now ignores
  owners in archived rigs, so the live node kills its own session and
  still refuses open work without --fallback. The handover check is
  unchanged.
- The delivery guard needs exactly one match for a target, and the twin's
  binding made it two, so delivery to the live seat failed. Unarchived
  matches now win, and archived ones count only when nothing else
  matches. Exactly one match is still required, so a truly ambiguous
  live target still refuses.
- `rig remove` and `rig shrink` human output now says when a session was
  kept, and for whom.

---------

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-30 10:23:18 -07:00
Mike SchwarzandOpenRig contributors e3ebd4ac2c fix(daemon): clean up unusable snapshot refresh helpers (#189)
* fix(daemon): a snapshot refresh probe never leaves its tmux session behind (#188)

`rig down` probes Claude resumability in a private `rigged-refresh-*`
tmux session. Two paths left it running, and every retry added another:

- After a seats' tmux server restart, the new server reuses pane ids,
  so a stale seat binding could name the probe's brand-new pane. The
  probe's kill then asked the guard to resolve the helper by name, which
  threw, and the unawaited write let the throw escape: the snapshot
  failed ("Cannot establish managed input target rigged-refresh-...")
  and the helper was never killed.
- When the new pane could not be proven, the probe returned failure
  without removing the session it had just created.

createProbeSession now refuses to use a probe whose new pane is named by
a managed record, or whose pane it cannot prove. It removes that helper
immediately, by the name this call just created. The probe write is
awaited, so a later refusal returns as a result instead of throwing.
Managed or changed targets are still never killed.

* fix(daemon): roll back an unusable probe only by the id its create returned (#188)

Review follow-up. The allocation rollback killed the helper by name after
awaiting creation and pane observation, which could kill a session that a
managed record had adopted meanwhile, or a different session that had taken
the name.

The probe is now created with `new-session -P -F '#{session_id}'`, and the
rollback kills only that session id. It leaves the helper in place, and
says so, when the id is unknown or a managed record now claims the helper's
name. A binding that names only the reused pane id under another session
name is stale and does not block the rollback. A cleanup failure is
reported in the result. The awaited probe write is unchanged.

* fix(daemon): check the helper's identity in the same tmux command that removes it (#188)

Review follow-up. A tmux session id is unique only for one server's
lifetime. If the server restarted between creating the refresh helper and
rolling it back, `kill-session -t $N` could remove an unrelated session
that the new server gave the same id.

The helper's create now returns its id and creation time. The rollback
runs `if-shell -F -t $N` with a check on the session's name and creation
time, and kills only when both match, in the same tmux command. A
mismatch, or an id that no longer resolves, leaves everything in place
and says so in the result.

---------

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-30 09:31:52 -07:00
Mike Schwarzanddev-driver 100be9d646 fix: recognize managed Claude seats behind launch wrappers (#220)
* fix: recognize managed Claude behind shell wrappers

* fix: normalize observed Claude executable name

---------

Co-authored-by: dev-driver <dev-driver@openrig-build>
2026-09-30 09:31:13 -07:00
Mike Schwarzanddev-driver f8f3aff68b fix(transport): recognize proven Codex behind shell wrappers (#171)
Co-authored-by: dev-driver <dev-driver@openrig-build>
2026-09-29 17:03:50 -07:00
Mike Schwarzanddev-driver 1618bab05f fix(daemon): bound overlapping identity and transcript polls (#169)
Co-authored-by: dev-driver <dev-driver@openrig-build>
2026-09-29 15:38:24 -07:00
Mike Schwarzanddev-driver b68571318d fix(codex): project shared skills to the Codex target (#162)
* fix(codex): project shared skills to the Codex target

* test(projection): allow runtime-aware resolver wiring

---------

Co-authored-by: dev-driver <dev-driver@openrig-build>
2026-09-29 15:24:58 -07:00
Mike Schwarzanddev-driver 6ab706d435 chore(release): prepare 0.6.2 (#153)
* chore(release): prepare 0.6.2

* docs(release): clarify the default bundle target directory

---------

Co-authored-by: dev-driver <dev-driver@openrig-build>
2026-09-29 13:04:56 -07:00
Mike Schwarzanddev50-guard a745475b07 fix(daemon): preserve managed launch target across pane reuse (#151)
Co-authored-by: dev50-guard <dev50-guard@openrig-build>
2026-09-29 09:46:38 -07:00
Mike SchwarzandOpenRig contributors 18201ac659 fix(transport): don't type into a bare shell where an agent runtime should run (#142) (#150)
When a seat's agent runtime has failed or exited, its pane shows a bare
shell, and any text typed there runs as shell commands. The
parked-owner watchdog wake was delivered anyway (`zsh: bad pattern:
[OpenRig`).

The transport now refuses a send when the pane's foreground is a shell
and the seat's runtime is an agent runtime, before anything is written.
It uses the shared shell classifier. A terminal node's shell is its
runtime and still receives text. An unknown or unreadable pane stays
advisory, as before.

The watchdog records the refusal as a failed delivery on the open row
and sends no second wake that episode. A running runtime still gets its
wake.

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-29 09:30:28 -07:00
Mike Schwarzanddev-driver aa7bc4407f feat: guide first-project permissions and provider choice (#147)
Co-authored-by: dev-driver <dev-driver@openrig-build>
2026-09-29 09:30:11 -07:00
6b8bee36b1 fix(bundle): install v2 bundles into --target and resolve paths on the client (#146)
* fix(bundle): resolve bundle paths on the client and launch v2 installs from --target

`rig bundle create/inspect/install` sent spec, output, bundle and target paths
unresolved, so the daemon resolved them against its own cwd. The CLI now
resolves them against the operator's cwd (files are still read on the daemon's
host; nothing is uploaded).

A schema-version-2 bundle apply launched from the temp extraction dir, which is
removed right after instantiate, and ignored targetRoot: members with cwd "."
and the spec/agent refs pointed at a deleted directory. Apply with a targetRoot
now copies the verified extraction into the target and launches from there.
A target with different content at any bundle path is refused with
target_conflict and nothing written; identical files are accepted so a
reinstall works. Plan mode, explicit cwdOverride, legacy v1 bundles and
applies without a targetRoot are unchanged.

Docs: rig-bundle.md install/inspect/--plan/--target/path behavior.

* fix(cli): resolve local rig up --target and align its help with the v2 target contract

On the local route, `rig up <bundle> --target <rel>` now resolves the
target against the client's cwd before sending it, matching `rig bundle
install`. The --target help now states the accepted contract: a v2 bundle
is materialized into the target (default: current directory), relative
member cwds resolve against it, and --cwd still overrides the launch cwd.
Remote --host and topology routing are unchanged: --host sends --target
as given, and it must exist on that host.

Docs: drop the "pass an absolute --target" workaround for the local route.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 09:29:33 -07:00
Mike SchwarzandOpenRig contributors 705cda2f0e test(daemon): give successful launch fixtures a startup context and adapter (#148)
#107 refuses to report a fresh pod-aware launch as fresh-primed without the
node's startup context and a runtime adapter. Two fixtures still expected a
successful launch without either, and failed on main:

- launch-node-subset: the single-node launch now seeds the target's startup
  context and passes a ready claude-code adapter, and asserts the harness
  was launched. The non-target assertions are unchanged.
- sessions-routes: the launch-subset success case seeds both nodes' startup
  contexts and opts into route runtime adapters, as startup wires them.

createTestApp gains an opt-in wireRuntimeAdapters option. It is off by
default, so every other route test keeps no route adapters. No production
change.

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-29 09:01:59 -07:00
9523b9de02 test(daemon): pin the #131 sender canonicalizer's edges and scope (#144)
Carries the tests and scope note from #137, which was folded into #135:
- round trip with the stampSelfHostSuffix producer;
- 4-segment names, @local, a near-miss host id, legacy flat names and
  virtual refs pass through unchanged;
- the origin-unknown marker and the P18 wire-over-body rule hold after
  the strip, for both sender helpers.

The comment records that only the sender is canonicalized: the CLI
cannot fix this at the source, and self-suffixed destinations keep the
C4 refusal. No behavior change.

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
Co-authored-by: Yi-111-a <153097222+Yi-111-a@users.noreply.github.com>
2026-09-29 07:48:56 -07:00
Mike Schwarzanddev-qa d83bbebe97 chore(release): prepare 0.6.1 maintenance notes (#129)
Co-authored-by: dev-qa <dev-qa@openrig-build>
2026-09-29 03:03:08 -07:00
Mike Schwarzandv-openrig-build d7fbf88639 docs(readme): link the guide, help, Q&A and updates on X near the top (#127)
* docs(readme): link the guide, help, Q&A and updates on X near the top

OpenRig is on GitHub's daily trending list. A stranger reading the first
screen found no link to the getting-started guide, the help guide, the Q&A
start-here thread or where updates and demos are posted. One line after the
introduction adds all four.

* docs(readme): offer the next walkthrough to visitors not installing today

For trending visitors who can't stop to install now: a secondary call to action
near the top and again after the getting-started steps, pointing to the
existing openrig.dev/follow signup. Nothing about installing the software is
gated.

* docs(readme): show the demo and a Start here link before the install steps

Trending visitors read the install prerequisites before seeing what OpenRig
looks like. Move the existing 'See it running' recording above the install
section, add a Start here link to the guided first-use path, and keep the
follow line after it. The install section, its requirements and the
disclosure of what OpenRig changes are unchanged and in the same order.

---------

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
2026-09-29 03:02:20 -07:00
Mike Schwarzandorch-advisor f87a956dbb fix(codex): pass real git dirs, not a worktree's .git file, to --add-dir (#121) (#126)
In a linked git worktree <cwd>/.git is a file, and passing it to Codex as
--add-dir breaks the Linux sandbox for every command. The fresh launch now
resolves the git metadata directories: an ordinary repository keeps
<cwd>/.git; a .git file resolves through git rev-parse to the worktree git
dir and the common git dir (existing directories only); anything
unresolvable adds nothing. A missing .git keeps the previous argument.
Resume and fork are unchanged.

Reported with a reproduction and the suggested rev-parse approach by
mgall-ibizdigital in #121.

Co-authored-by: orch-advisor <orch-advisor@openrig-build>
2026-09-29 01:57:09 -07:00
Mike SchwarzandOpenRig Contributors 7981bca7a3 fix(daemon): recognize custom Codex status-line model fields (#125)
Reported-by: Hexgunner69 (issue #116, recognition portion). Includes screen-derived regressions contributed by Aummadour in PR #120; the admitted generic recognizer covers these cases without widening the unguarded legacy branch.

Co-authored-by: OpenRig Contributors <contributors@openrig.dev>
2026-09-29 01:53:35 -07:00
Mike Schwarzandorch-advisor a567d9b193 chore: remove the retired TUI drivability spike (#119)
spike/tui-drivability was the Phase-0 agent-drivability harness from
2026-08-02: ten self-contained files importing only each other and Node
built-ins. No test command, config, workflow or published package
reaches it. The Context7 'spike' exclusion stays because
packages/tui/spike still holds a tracked fixture.

Co-authored-by: orch-advisor <orch-advisor@openrig-build>
2026-09-29 01:44:40 -07:00
50e519b399 Run installed queue durability checks alongside PR test suites (#117)
* ci: add installed baton scenario and regression control to PR tests

* ci: retain healthy return after the durability fault control

* Bind seeded failure to queue observation and propagate pack errors

* test: repair hosted fixture drift and bound temporary IPC

* ci: record a bounded self-process probe before package suites

* test: keep hosted process and transport probes confined

---------

Co-authored-by: dev-driver <dev-driver@openrig-build>
Co-authored-by: dev-qa <dev-qa@openrig-build>
2026-09-28 22:10:45 -07:00
Mike Schwarzandv-openrig-build 61f13f64ff docs: one help guide for agents (docs/reference/help.md, rig context get help) (#113)
* docs: point agents to the OpenRig help route when OpenRig misbehaves

Add a short pointer to https://www.openrig.dev/help/agents in the
managed start guidance every seat reads, the openrig-skills index (all
three identical copies, digests regenerated) and the README 'For agents'
line. The route sends a symptom to version-matched docs and known
issues and explains how to reach the team. rig --version and rig doctor
help when available, but a broken install is not a reason to skip the
page. No new command.

* docs: one help guide for agents, served by rig context get help

Agent help now lives in one file, docs/reference/help.md. It ships with every
install, so it matches the installed version, and Context7 indexes it. A new
static context pack, help, serves the same file through `rig context get help`
by symlinking to it. The pack build copies the link's target, so installs get a
real file.

The pack generator accepts a static-pack symlink only when it points to a file
under docs/reference/. Any other link fails the build before anything is
written. Tests cover the help pack's bytes and both symlink cases.

The startup guidance, the openrig-skills index (all three copies), the
onboarding capability map, README and SUPPORT now point to `rig context get
help`, falling back to the installed file or openrig.dev/help/agents (the same
text) when `rig` won't run.

* docs(help): say contact options, not a contact form

The website's help page lists email and public Q&A; it has no contact form.

* docs(help): load linked guides on demand; correct the installed fallback path

F1: `rig context get help` served help.md alone, so its links to
getting-started, instance-layout and rig-spec had nothing to resolve against.
A new static pack, reference, symlinks exactly those three files from
docs/reference/. help.md keeps its source-relative links and adds the
`rig context get reference/<file>[#section]` address beside each, so a guide
loads only when it's needed and a help read stays small.

F2: the broken-rig fallback named docs/reference/help.md "in the installed
package". The package build copies these files to daemon/docs/reference/ in
@openrig/cli. Corrected in help.md, the startup guidance and the openrig-skills
index (all three copies, digests regenerated).

Tests: the reference pack ships real files equal to their sources; every
address help.md teaches resolves through the daemon's address route, section
and whole-file; the help preview contains none of the three manuals; a fixture
proves the address check fails on a missing target; source links and the
installed-path text match build-package.sh.

---------

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
2026-09-28 20:59:08 -07:00
Mike Schwarzandv-openrig-build 95c6c9126c chore: remove the internal .evidence folder from the repository (#118)
.evidence held 23 internal build receipts (test runs, spec drafts, fix-round
notes, 156 KB) committed during 0.5.4 work on 2026-08-26. Nothing in the
product or package uses them. Remove the folder, ignore it at the repo root,
and drop its now-unneeded Context7 exclude.

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
2026-09-28 20:04:36 -07:00
Mike Schwarzandv-openrig-build ea52fa8f83 fix(specs): add frontmatter to the shipped vault-user skill (#115)
* fix(specs): give the vault-user skill the frontmatter every shipped skill needs (OPR.0.6.1.6)

vault-user/SKILL.md was the only shipped SKILL.md without a name/description
frontmatter block, so it failed the daemon's own parseSkillFrontmatter
contract and external skill syncers rejected it. Adds name + description and
leaves the body byte-identical.

Adds a regression check that runs parseSkillFrontmatter over every SKILL.md
under packages/daemon/specs and packages/daemon/assets, the two skill roots
scripts/build-package.sh copies into the npm artifact.

* test(daemon): correct the shipped-skill check's context-packs scope note (OPR.0.6.1.6)

The projection's default source is packages/daemon/specs/agents/shared/skills,
already inside the checked specs root. Manifest validation is not SKILL.md
frontmatter validation. Comment only; test behavior unchanged.

---------

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
2026-09-28 19:21:34 -07:00
Mike Schwarzanddev-qa 57380a250e Release0.6.0: works for strangers (#109)
* chore(release): prepare OpenRig 0.6.0

Add per-seat permission selection and typing protection, rig-wide Herdr entry,
Node 22/24 support with SQLite 13, and first-use improvements. Label the optional
Jev/Rig Stream classifier and Slack manifest setup assistance experimental.

* docs: finalize 0.6.0 verification scope and release references

Record the accepted Node 22 candidate install, retained Node 24 evidence,
and unperformed native permission checks without broadening test claims.

---------

Co-authored-by: dev-qa <dev-qa@openrig.local>
2026-09-28 14:07:36 -07:00
Mike Schwarzandv-openrig-build 5fead45078 docs: recommend Node 22 on Apple silicon and state platform support (#94)
Bring the shipped macOS arm64/Node 24 SQLite caveat (0.5.15 known
compatibility limitation, repeated in the 0.5.17 notes) to the install
line, the Requirements list and Getting Started. State the platform
posture: macOS or Linux; native Windows is not supported yet; WSL2 has
not been tested. The declared Node range is unchanged.

Co-authored-by: v-openrig-build <v-openrig-build@users.noreply.github.com>
2026-09-28 02:48:03 -07:00
Mike SchwarzandOpenRig contributors edc01fe658 fix(codex): launch Codex seats with --no-daemon when supported (#69) (#77)
* fix(codex): launch Codex seats with --no-daemon when supported (#69)

Before each managed Codex launch, run `codex --help` once, asynchronously, in the
seat's cwd with its launch PATH. Codex usage listing --no-daemon: fresh, fork,
pod resume and restore resume start with `codex --no-daemon`. Codex usage
without it: the command is unchanged. Failure, timeout or non-Codex output:
refuse the launch and send nothing. Suggested manual resume commands are
unchanged.

Reported by @reisalbuquerque.

* Bound Codex capability probe decision time (#69)

---------

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-27 18:40:56 -07:00
Mike SchwarzandOpenRig contributors f137f11bef Release 0.5.17: install with Bun (#73)
* release: prepare 0.5.17

Set the version to 0.5.17 and add the changelog entry and release notes for
installing with Bun (#66, #68).

* docs: attribute the Bun verification to the installation fix

---------

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-26 23:23:22 -07:00
Mike SchwarzandOpenRig contributors c9be421b9c fix(package): install with Bun without the unpublished @openrig/daemon (#66) (#68)
* fix(package): install without the unpublished @openrig/daemon (#66)

The CLI package declared the private @openrig/daemon in dependencies and
shipped it as a bundled dependency. npm used the bundle, but package managers
that resolve every dependency from the registry, such as Bun, failed with a
404.

The package already ships the daemon under daemon/. The package build now
rewrites the compiled CLI and TUI imports of @openrig/daemon/<subpath> to that
copy, using the daemon's exports map, and fails on any unmapped or unstaged
subpath or any daemon import left afterwards. The dependency, the bundled
copy and their lockfile entries are removed. Source imports and development
resolution are unchanged.

Reported by @drewpayment.

* fix(package): rewrite daemon imports from the syntax tree, not text

Parse each staged file with the TypeScript compiler and rewrite only real
import/export specifiers and literal import()/require() arguments. Text in
comments, strings and templates is no longer changed, and imports that carry
comments or use template literals are no longer missed. Unparseable files and
non-literal module arguments naming the package now fail the build.

* docs: note Bun installation and its postinstall limit

Bun can install the CLI, but OpenRig still runs on Node.js and Bun may
block the package's postinstall check.

* fix(package): run the daemon import rewrite from any checkout path

The direct-run check compared import.meta.url with a hand-built file:// URL,
which never matched when the path needed percent-encoding (spaces, #) or went
through a symlink. The script then exited 0 without rewriting anything. Compare
the decoded module path with the real path of argv[1] instead.

---------

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-26 22:47:33 -07:00
Mike SchwarzandOpenRig contributors 5c54703035 Release 0.5.16: choose CLAUDE.local.md for Claude managed blocks (#25) (#63)
* feat(daemon): let a rig choose CLAUDE.local.md for Claude managed blocks (#25)

A rig spec can now declare

    managed_blocks:
      claude-code: CLAUDE.local.md

so OpenRig writes its managed instruction blocks for Claude Code members to
CLAUDE.local.md instead of a git-tracked CLAUDE.md. The default stays
CLAUDE.md and Codex members stay on AGENTS.md.

- Validation accepts only the claude-code key with CLAUDE.md or
  CLAUDE.local.md, and rejects anything else before a member launches.
- The selection is stored on the rig (migration 085) and bound once in
  StartupOrchestrator.startNode, so launch, restore replay, relaunch,
  continue and added members all write the same file. Startup
  guidance_merge, profile managed_block projection and the conflict
  target all use it.
- Teardown cleans only the selected file. The other file is never edited,
  moved or deleted; blocks already written to CLAUDE.md stay until the
  user removes them, as the reference docs explain.
- Export and the bundle rig.yaml rewrite round-trip the field.

Reported and proposed by @hvpaiva.

* docs(daemon): say accurately which paths deliver the Claude managed-block file

Handover launches the successor directly and writes no guidance, so the
startNode and migration comments no longer list it among the delivery paths.
Comment-only change.

* release: prepare 0.5.16

Set the version to 0.5.16 and finalize the changelog and release notes for
the Claude instruction-file option (#25), the advisory portability report (#56)
and the README update (#54).

* docs: keep uncommitted edits safe when removing old Claude blocks

Recommend deleting only the managed sections by hand, and warn that
git restore CLAUDE.md discards every unstaged change to the file. Say that
portability findings never fail the check while operational errors still do.

---------

Co-authored-by: OpenRig contributors <noreply@openrig.dev>
2026-09-26 02:05:03 -07:00
Mike Schwarzandorch-advisor bee173902a chore: restore Context7 indexing settings after the claim (#62)
Co-authored-by: orch-advisor <orch-advisor@openrig-build>
2026-09-26 01:06:40 -07:00
Mike Schwarzandorch-advisor a52767c1fa chore: reduce context7.json to the claiming fields until the library is claimed (#61)
Co-authored-by: orch-advisor <orch-advisor@openrig-build>
2026-09-26 01:05:11 -07:00
Mike Schwarzandorch-advisor 0ffbf3df48 chore: drop the $schema field Context7's claim check rejects (#60)
Co-authored-by: orch-advisor <orch-advisor@openrig-build>
2026-09-26 01:02:57 -07:00
Mike Schwarzandorch-advisor fbc30c2b6d ci: list file and line only in the public portability report (#59)
Co-authored-by: orch-advisor <orch-advisor@openrig-build>
2026-09-26 01:00:48 -07:00
Mike Schwarzandorch-advisor 6d27f87586 chore: add and configure context7.json (#58)
* chore: add context7.json to claim the Context7 library listing

* chore: configure Context7 indexing scope and usage rules

---------

Co-authored-by: orch-advisor <orch-advisor@openrig-build>
2026-09-26 00:58:16 -07:00
Mike Schwarzandorch-advisor 3b2fc4e624 ci: add a portability report for pull requests (#56)
* ci: add a portability report for pull requests

* ci: word the empty portability report as a scan result

---------

Co-authored-by: orch-advisor <orch-advisor@openrig-build>
2026-09-26 00:52:05 -07:00
Mike Schwarz 1039f72637 Merge pull request #54 from mvschwarz/community-adoption/readme-badges
README: badges, a short demo of agents working, and star history
2026-09-25 20:18:02 -07:00
Mike Schwarz 49c1c783a3 Merge pull request #50 from mvschwarz/first-users-0515-final-20260925
Prepare 0.5.15 first-use recovery and Pi fixes
2026-09-25 13:19:40 -07:00
Mike Schwarz 91a04d7098 Merge pull request #46 from mvschwarz/docs/readme-first-use-20260925
docs: bring installation and first use to the top of the README
2026-09-25 04:00:46 -07:00
Mike Schwarz 6109431f97 Merge pull request #45 from mvschwarz/community-adoption/repo-hygiene-publication-20260925
docs: add contributor, conduct, security, and support guidance
2026-09-25 02:16:08 -07:00
Mike Schwarz b374dde300 Merge pull request #37 from danielkuykendall23-boop/fm/openrig-pi-reply-mirror
fix(daemon): show Pi replies in the seat pane with Pi 0.84+
2026-09-24 21:59:18 -07:00
Mike Schwarz 0859caa33c Merge pull request #39 from mvschwarz/docs/openrig-software-factory-20260925
Add Software Factory guidance and agent-configured permissions
2026-09-24 20:29:58 -07:00
Mike Schwarz 634b107f13 Merge pull request #38 from mvschwarz/fix/first-users-startup-20260924
fix: improve Codex startup and restore reporting
2026-09-24 18:05:06 -07:00
Mike Schwarz 9c9e518d29 Merge pull request #34 from mvschwarz/docs/first-users-permissions-20260924
docs: explain agent permissions for first use
2026-09-24 11:56:07 -07:00
mvschwarz 209030f047 chore(test): refresh AUTHORITY_SHA256 for standard + yolo policy files
Delta commits 3c24b69a0 ('docs: make shipped references self-contained')
and d83f84d70 ('fix(s12): classify packaged derived artifacts') modified
packages/daemon/policies/builtin/standard.policy.md and yolo.policy.md
content but did not update the corresponding entries in the packing-
policies test's AUTHORITY_SHA256 constant. Aligns the test's expected
hashes with the actual shipped-content hashes so the T7 byte-equal
check reflects the current shipped surface.

No product code change; no policy-content change; only the test's
expectation is being brought forward to match commits already in the
delta.
2026-08-30 01:39:59 -07:00
mvschwarz 4c68a0f1da docs: v0.5.6 release notes (CHANGELOG entry + docs/releases file)
v0.5.6 — world-building as context engineering. Three themes: the context
system (mission install, lore routing, taxonomy, verifiable public world
pack, complete skill index, substance gate); continuity (compaction_strategy
policy, apprentice-handover, managed compaction with honest restores,
usage-threshold watchdog primitive); the human layer (destination resolver,
delivery receipts on the row, notification levels + dials, delivery-rules
engine, Slack files as work). Plus operational honesty fixes and the SDLC
conventions component menu.

Three new migrations: 074_context_usage_watchdog +
075_context_usage_watchdog_generation + 076_owner_notification_levels
(head advances 073 to 076); 41 shipped context packs (up from 39).
2026-08-30 01:39:59 -07:00
mvschwarz 2967124039 chore: bump version to 0.5.6
Bounded version bump across the release-owned files (root package.json,
packages/cli|daemon|ui/package.json, and the matching root+workspace entries
in package-lock.json). packages/tui remains at its independent 0.1.0.
2026-08-30 00:19:43 -07:00
mvschwarz 42700c4be7 docs: v0.5.5 release notes (CHANGELOG entry + docs/releases file)
The 'ambient-attention release': rig parked derives silent-stuck diagnosis;
self-retrying wake ladder + escalations view; standing stuck-sweep runs
without you; queue block --on park-with-wake; rig ps typed ACTIVITY column;
seat handover fork:/rebuild execute; Slack human layer live; fresh installs
onboard themselves; refocus fires only when it should; one-file scope
convention; daemon bind provenance.

Two new migrations: 072_thread_seat_map + 073_queue_transition_wakes
(head advances 071 to 073).
2026-08-27 12:30:32 -07:00
mvschwarz 236c7fff21 chore: bump version to 0.5.5
Bounded version bump across the release-owned files (root package.json,
packages/cli|daemon|ui/package.json, and the matching root+workspace entries
in package-lock.json). packages/tui remains at its independent 0.1.0.
2026-08-27 12:28:54 -07:00
mvschwarz 0a1718c76d docs: v0.5.4 release notes
The honesty release: classified transport resolution, delivery verification by effect, supported single-seat lifecycle controls, and state-preserving truth surfaces.
2026-08-26 11:28:55 -07:00
mvschwarz 4504989f7f chore: bump version to 0.5.4
Bounded version bump across the release-owned files (root package.json,
packages/cli|daemon|ui/package.json, and the matching root+workspace entries
in package-lock.json). packages/tui remains at its independent 0.1.0.
2026-08-26 11:28:55 -07:00
mvschwarz e6add8b86b chore(test): rename rig-policy packaging guard to rig-mode
The slice-09 packaging guard at scripts/check-cli-daemon-freshness.test.mjs
still asserted existence of vendored routes/rig-policy.js and registration
of rigPolicyRoutes + /api/rig-policy after the rig-policy -> rig-mode
rename (verb, API path, identifiers) landed in the 0.5.3 delta. Renames
the assertions to match the shipped route name, so the guard reflects the
current packaging contract.

Companion to the delta's rig-mode rename commit. No product code change.
2026-08-25 19:53:25 -07:00
mvschwarz 2c6e9e509d docs: v0.5.3 release notes (CHANGELOG entry + docs/releases file)
The 'context release': rig context get/list/profile/recap-write. Address
grammar for context, ask-then-ref discovery, durable seat recap, refocus
resolves refs. Composition by reference, not by copy.

No new migrations (head stays at 071). No CLI surface removals or renames.
2026-08-25 18:46:15 -07:00
mvschwarz 7a72f4081f chore: bump version to 0.5.3
Bounded version bump across the release-owned files (root package.json,
packages/cli|daemon|ui/package.json, and the matching root+workspace entries
in package-lock.json). packages/tui remains at its independent 0.1.0.
2026-08-25 18:44:16 -07:00
mvschwarz 029acda80a docs: v0.5.2 release notes (CHANGELOG entry + docs/releases file)
Formal CHANGELOG [0.5.2] entry + docs/releases/v0.5.2.md file, both
authored from the VM-side closing paper (RELEASE-0.5.2-CLOSING-PAPER.md
+ ADDENDUM-1) — not derived from 74 commit subjects. Content structure
matches prior release-notes shape.

Known-limits section carries all 5.3 inheritances the closing paper
lists as user-visible; internal debt items summarized. Migration
wording precise: no migrations added in this release (v0.5.1 shipped
068-071 with 068+071 as a create/drop-if-exists pair; v0.5.2 stays
at 071).

Companion to the Release 0.5.2 version-bump commit below; GH Release
body will use docs/releases/v0.5.2.md via gh release create
--notes-file at ceremony time.
2026-08-22 10:15:31 -07:00
mvschwarz 7b7178dda8 Release 0.5.2
A test system for the product — self-driving scenarios that prove the
product's behaviour through the same commands a person uses. This
release exercises that system for real and ships the reliability fixes
that fell out of doing so.

The headline is B1: the crash-cart fleet-restore conductor. Type bare
`rig` at a dead daemon and reach a truthful cockpit; one Enter restores
the fleet kernel-first with surviving tmux panes adopted (never
clobbered); the triage carries exact per-seat remediation walkable in
one keystroke; cancel is honest; destructive restore is only offered
on positive evidence that adoption cannot succeed. Ten build rounds,
four independent gates.

Alongside: the daemon event-loop no-longer-hangs-under-load fix (with
its measurement); unattended Claude seat handover (outgoing seat writes
a recap and submits its packet automatically, door-proven); `rig
policy` handles adversarial input honestly (three review rounds);
messages carry their machine-of-origin end-to-end; a detector for a
class of Codex model-config drift that caught real cases on landing;
test-integrity work (runner refuses a dirty tree; hermetic test roots;
flaky fixtures isolated); governance-in-code (plan locks are chosen,
not inherited; wake is opt-in); the container tar-file hang cause
eliminated at the seam.

v0.5.2 contains v0.5.1 in full. One lineage, no divergence. No new
migrations in this release (v0.5.1 was 067 → 071 already; v0.5.2 stays
at 071). API surface preserved.

Formal CHANGELOG entry + docs/releases/v0.5.2.md follow in a small
docs commit on top of this release commit.
2026-08-22 10:14:05 -07:00
mvschwarz a4ce0d0dc5 docs: v0.5.1 release notes (CHANGELOG entry + docs/releases file)
Formal CHANGELOG [0.5.1] entry + docs/releases/v0.5.1.md file, both
authored from the intent-vs-delivered trace at
openrig-work/missions/release-0.5.1 (not derived from 362 commit
subjects). Content structure matches prior release-notes shape.

Known-limits wording carried verbatim per the trace: container mode is
scaffolded but not driven (scoped forward); three of the intended
seed scenarios run green, the tenth cannot be built without two
capabilities that do not yet exist (scoped forward).

Companion to the Release 0.5.1 version-bump commit below; GH Release
body will use docs/releases/v0.5.1.md via gh release create
--notes-file at ceremony time.
2026-08-11 23:12:32 -07:00
mvschwarz 68d59acff2 Release 0.5.1
A test system for the product, plus reliability fixes shipped through it.

Scenarios drive the real product through the same commands a person uses,
so it can prove its own behaviour without a human checking by hand. The
reliability fixes of this window ship through the test system — proving
its value on its first cycle.

v0.5.1 contains v0.5.0 in full. One lineage, no divergence, no dual
maintenance. Migrations are additive-only; existing v0.5.0 databases
upgrade by running rig daemon start on the new daemon.

TEST SYSTEM

- Stub runtime for tests: a fake agent runtime that scenarios can drive.
  Lets scenarios exercise the daemon end-to-end without needing a real
  Claude or Codex process.
- Scenario format + runner: a text-based format and an executor that
  runs scenarios against the real product. Includes a real fix that
  surfaced from writing the runner: text-matching against a pane or
  transcript could never match its two intended surfaces; now it does.
- Seed scenarios: three seed scenarios that run green end-to-end against
  the real product. The intended tenth cannot be built without two
  capabilities that do not yet exist in the product (a scenario cannot
  mutate the running system's shape; the terminal interface exposes
  navigation state rather than fleet inventory). Both capabilities are
  scoped forward.

CONTAINER TEST BED — SCAFFOLDING

Scaffolding for container mode ships: argument builders, image-identity
stamping, runbooks, and a unit suite. The runner does not yet execute
in containers — this is scaffolding you will see in the tree but that
no test currently drives. Container-mode execution is scoped forward.

RELIABILITY FIXES SHIPPED THROUGH THE TEST SYSTEM

- Honest render for daemon transport failures: the operator sees the
  actual failure rather than a silent no-op or generic error.
- Queue persistence: two fixes ensuring queue records reflect what
  actually happened after they were written.
- Cross-machine send regression: found and fixed during verification.
  The test system doing its job — proving product behaviour across
  machines and catching a regression before release.

SMALL FEATURES

- Per-agent model from spec: each agent's model comes from its spec
  rather than a fleet-wide default, so different agents can run on
  different providers or models.
- Token usage tracked over time: the daemon records token use so
  operators can see trends and predict when a seat is approaching a
  usage limit.
- Machine-of-origin on messages: messages carry the machine they came
  from, so multi-host coordination is legible.

OTHER

- UI timing hardening: UI tests no longer fail on load-timing flakes.
- Queue records tell the truth after they are written: a class of
  wrote-it-and-it-did-not-stick issues closed.
- Unreached-message visibility: show messages that never reached an
  agent. On landing, this surfaced nine real handoffs that had been
  silently lost since 8 August.

BEHAVIOR + COMPATIBILITY

- Migrations: additive-only.
- API surface preserved: no CLI-command or flag removals or renames
  from v0.5.0.
- v0.5.1 contains v0.5.0 in full.

KNOWN LIMITS (carried into release notes verbatim)

- Container mode is scaffolded but not driven. Scoped forward.
- Seed scenarios: three of the intended set run green; the tenth
  cannot be built without two capabilities that do not yet exist.
  Scoped forward.

Formal CHANGELOG entry + docs/releases/v0.5.1.md follow in a small
docs commit on top of this release commit.
2026-08-11 23:11:06 -07:00
mvschwarz 1920aa315d merge: bring origin/main docs backfill (a310c161 + 9f977da4) into 0.5.1 lineage
Reconciles origin/main forward-only into the 0.5.1 release branch so the
push is a fast-forward and does not drop the two 2026-08-07 docs commits
(CHANGELOG entries + docs/releases/v0.4.7.md, v0.4.8.md, v0.5.0.md).

Zero-conflict merge — the 362 scrubbed VM commits did not touch
CHANGELOG.md or docs/releases/*.md. Tree-identity of those 362 scrubbed
commits is preserved (first-parent reachable, SHAs unchanged).

Per §6a step 2 standing pattern: every release's public tip back-merges
into the working lineage promptly post-release. Doing it here at the
last honest moment; the release-ceremony discipline says next time this
happens right after each ship, not four days later.
2026-08-11 23:08:13 -07:00