mirror of
https://github.com/mvschwarz/openrig.git
synced 2026-11-10 03:31:40 -10:00
feat(slice-22): two-daemon VM-preview bootstrap + sample fixture
release-0.3.1 Slice 22 founder-walk-vm-populated-env Phase D + E
(merged) — ships the operational artifacts for running two daemons
side-by-side in a Tart preview VM with fully isolated state.
OQ resolutions (per qitem-20260511113113-9fea3ab4):
OQ-1 (UI switcher): (a) multi-port + operator-picks-URL — zero UI change
OQ-2 (fixture source): (b) static YAML + idempotent loader (scope-cut to
bootstrap script as the loader for v0)
OQ-3 (bootstrap loc): (c) both — scripts in repo + conventions in substrate
OQ-4 (HOME isolation): (a) fully isolated per daemon
Adds:
- scripts/vm-bootstrap/two-daemon-start.sh — idempotent two-daemon
spawn (refuses to clobber an existing daemon.json; operator must
cleanly reset state dirs to retry). Each daemon gets its own
--openrig-home / --port / --db so they share only the host's
network namespace, not state. Defaults: blank → 7433 at
$HOME/.openrig-blank; populated → 7434 at $HOME/.openrig-populated.
Env-overridable: BLANK_HOME, POPULATED_HOME, BLANK_PORT,
POPULATED_PORT, FIXTURE_DIR.
- packages/daemon/assets/vm-preview-fixtures/ — fixture-source
directory with README documenting the canonical layout, scope, and
placeholder conventions (/Users/example/, <substrate-<internal-docs>>/
per banked feedback_test_fixture_example_path_placeholder). Ships
one sample workflow fixture (renamed from the basic-loop starter to
vm-preview-basic-loop so it does not collide with the bundled
built-in when dropped into a populated daemon's workspace/
specs_root). Slice 11 folder-discovery auto-discovers it.
Scope cuts (explicit, called out in IMPL-PRD §13):
- Phase C structured fixture-loader module: not needed for v0; the
bootstrap script is the loader. Operator runs `rig up product-team`
for sample rigs, drops workflow YAMLs into the populated daemon's
specs_root for workflow specs. No new daemon module.
- Rich populated content (~13-node openrig-velocity rig, ~20 qitems,
getting-started narrative): deferred to follow-up content slices.
Convention doc added in substrate at
<work-tree>/conventions/vm-preview/README.md
with operator workflow, OQ resolutions, future-evolution ideas, and
cross-links to slice 11 (folder-discovery) and auth-bearer-tailscale
-trust (bind model).
No SC-29 EXCEPTIONS: --openrig-home is pure ergonomics on the
pre-existing OPENRIG_HOME env contract; no allowlist additions.
Tests unchanged from Phase B (56/56 daemon-lifecycle; full sweep
4270/4272; one pre-existing env-only fail). tsc clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This commit is contained in:
1 parent
3d9a6f6190
commit
5a14029739
3 files changed
+204
No files matched your search
@@ -0,0 +1,44 @@
|
||||
# VM Preview Fixtures
|
||||
|
||||
Sample data the Tart preview VM uses to populate the "populated" daemon with
|
||||
a representative "lived-in" environment. See
|
||||
`<substrate-shared-docs>/openrig-work/conventions/vm-preview/README.md` for the
|
||||
operator workflow and the rationale behind the two-daemon model.
|
||||
|
||||
## Contents
|
||||
|
||||
- `workflows/` — workflow_spec YAML files. The operator copies these into the
|
||||
populated daemon's `<workspace.specs_root>/workflows/` directory; slice 11's
|
||||
folder-discovery scanner auto-discovers them on the next
|
||||
`GET /api/specs/library` call.
|
||||
|
||||
- `queue-items/` — placeholder for future qitem fixture content (TODO; slice
|
||||
follow-up will add).
|
||||
|
||||
- `rigs/` — placeholder for future rig-instance fixtures (TODO; slice
|
||||
follow-up will add). For v0, the operator manually instantiates a sample
|
||||
rig via `rig up product-team` against the populated daemon (see bootstrap
|
||||
script).
|
||||
|
||||
## Conventions
|
||||
|
||||
Fixture YAML files use the canonical placeholder paths per banked
|
||||
`feedback_test_fixture_example_path_placeholder.md`:
|
||||
|
||||
- Username-bearing paths: `/Users/example/...` (never `wrandom` or other
|
||||
contributor usernames)
|
||||
- Substrate-relative refs: `<substrate-shared-docs>/...`
|
||||
|
||||
## v0 scope
|
||||
|
||||
Slice 22 (release-0.3.1) ships the INFRASTRUCTURE for the two-daemon model:
|
||||
|
||||
- `--openrig-home` CLI flag on `rig daemon start` and `rig up`
|
||||
- Bootstrap script (`scripts/vm-bootstrap/two-daemon-start.sh`)
|
||||
- This fixtures directory + a sample workflow YAML
|
||||
- Convention doc in substrate
|
||||
|
||||
Authoring rich populated content (~13-node openrig-velocity rig + 20 qitems
|
||||
+ getting-started mission narrative) is deferred to follow-up content slices
|
||||
that have clearer ownership (slice 21 onboarding-conveyor will likely
|
||||
contribute getting-started mission content).
|
||||
@@ -0,0 +1,79 @@
|
||||
# VM-preview fixture for slice 22 founder-walk-vm-populated-env.
|
||||
# Derived from the 0.3.0 basic-loop starter; renamed to avoid colliding
|
||||
# with the built-in spec when this fixture file is dropped into a
|
||||
# populated daemon's workspace.specs_root/workflows/ directory.
|
||||
# Slice 11's folder-discovery scanner auto-discovers it on next list.
|
||||
workflow:
|
||||
id: vm-preview-basic-loop
|
||||
version: 1
|
||||
objective: >
|
||||
Walk one work packet through the conveyor rig slowly enough for a new user
|
||||
to inspect each handoff.
|
||||
target:
|
||||
rig: conveyor
|
||||
entry:
|
||||
role: intake
|
||||
coordination_terminal_turn_rule: hot_potato
|
||||
roles:
|
||||
intake:
|
||||
skill_refs: [openrig-user, backlog-capture]
|
||||
preferred_targets: [intake-lead@conveyor]
|
||||
planner:
|
||||
skill_refs: [openrig-user, writing-plans]
|
||||
preferred_targets: [plan-planner@conveyor]
|
||||
builder:
|
||||
skill_refs: [openrig-user, executing-plans]
|
||||
preferred_targets: [build-builder@conveyor]
|
||||
reviewer:
|
||||
skill_refs: [openrig-user, review-team]
|
||||
preferred_targets: [review-reviewer@conveyor]
|
||||
closer:
|
||||
skill_refs: [openrig-user, verification-before-completion]
|
||||
preferred_targets: [intake-lead@conveyor]
|
||||
steps:
|
||||
- id: intake
|
||||
actor_role: intake
|
||||
objective: Restate the objective and hand off one packet.
|
||||
allowed_exits: [handoff, waiting, failed]
|
||||
next_hop:
|
||||
mode: require
|
||||
suggested_roles: [planner]
|
||||
- id: plan
|
||||
actor_role: planner
|
||||
objective: Produce a short plan for one build turn.
|
||||
allowed_exits: [handoff, waiting, failed]
|
||||
next_hop:
|
||||
mode: require
|
||||
suggested_roles: [builder]
|
||||
- id: build
|
||||
actor_role: builder
|
||||
objective: Build or draft the planned output.
|
||||
allowed_exits: [handoff, waiting, failed]
|
||||
next_hop:
|
||||
mode: require
|
||||
suggested_roles: [reviewer]
|
||||
- id: review
|
||||
actor_role: reviewer
|
||||
objective: Check the output and clear it for close.
|
||||
allowed_exits: [handoff, waiting, failed]
|
||||
next_hop:
|
||||
mode: require
|
||||
suggested_roles: [closer]
|
||||
- id: close
|
||||
actor_role: closer
|
||||
objective: Close the walkthrough packet.
|
||||
allowed_exits: [done, failed]
|
||||
next_hop:
|
||||
mode: forbid
|
||||
invariants:
|
||||
continuation_required: true
|
||||
preserve_lineage: true
|
||||
closure_required: true
|
||||
allowed_exits: [handoff, waiting, done, failed]
|
||||
loop_guards:
|
||||
max_hops: 10
|
||||
spawn_budget: 0
|
||||
closure:
|
||||
success: Walkthrough packet closed.
|
||||
degraded: Walkthrough stopped with a named blocker.
|
||||
failed: Walkthrough failed with evidence.
|
||||
Executable
+81
@@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env bash
|
||||
# Slice 22 (release-0.3.1) — VM preview two-daemon bootstrap.
|
||||
#
|
||||
# Starts two OpenRig daemons in the same VM with fully isolated state
|
||||
# (separate OPENRIG_HOME dirs, distinct ports, distinct SQLite paths)
|
||||
# so a founder can compare a blank-slate "first install" UI to a
|
||||
# pre-populated "lived-in" UI side-by-side.
|
||||
#
|
||||
# Operator workflow (per <substrate-shared-docs>/openrig-work/conventions/vm-preview/README.md):
|
||||
# 1. Provision a Tart VM with OpenRig CLI installed.
|
||||
# 2. Run this script.
|
||||
# 3. Open two browser tabs:
|
||||
# http://<vm-ip>:7433 → blank-slate (default, fresh install UX)
|
||||
# http://<vm-ip>:7434 → populated (sample rig + qitems for "lived-in" UX)
|
||||
# 4. To reset: kill both daemons + rm both OPENRIG_HOME dirs + re-run.
|
||||
#
|
||||
# Pre-conditions (operator install before running this):
|
||||
# - `rig` CLI on PATH
|
||||
# - Tailscale daemon active OR explicit LAN bind via OPENRIG_HOST (see
|
||||
# auth-bearer-tailscale-trust slice for the bind rules)
|
||||
#
|
||||
# Idempotency: the script refuses to clobber existing daemons; operator
|
||||
# must clean state dirs to fully reset.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
BLANK_HOME="${BLANK_HOME:-$HOME/.openrig-blank}"
|
||||
POPULATED_HOME="${POPULATED_HOME:-$HOME/.openrig-populated}"
|
||||
BLANK_PORT="${BLANK_PORT:-7433}"
|
||||
POPULATED_PORT="${POPULATED_PORT:-7434}"
|
||||
FIXTURE_DIR="${FIXTURE_DIR:-$(dirname "$0")/../../packages/daemon/assets/vm-preview-fixtures}"
|
||||
|
||||
echo "==> VM preview two-daemon bootstrap"
|
||||
echo " BLANK_HOME=$BLANK_HOME (port $BLANK_PORT)"
|
||||
echo " POPULATED_HOME=$POPULATED_HOME (port $POPULATED_PORT)"
|
||||
echo " FIXTURE_DIR=$FIXTURE_DIR"
|
||||
|
||||
# Refuse to overwrite existing daemons — operator action required to reset.
|
||||
if [ -f "$BLANK_HOME/daemon.json" ]; then
|
||||
echo "ERROR: blank daemon already running per $BLANK_HOME/daemon.json"
|
||||
echo " Run: rig daemon stop --openrig-home $BLANK_HOME"
|
||||
echo " Then: rm -rf $BLANK_HOME && rerun this script."
|
||||
exit 1
|
||||
fi
|
||||
if [ -f "$POPULATED_HOME/daemon.json" ]; then
|
||||
echo "ERROR: populated daemon already running per $POPULATED_HOME/daemon.json"
|
||||
echo " Run: rig daemon stop --openrig-home $POPULATED_HOME"
|
||||
echo " Then: rm -rf $POPULATED_HOME && rerun this script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$BLANK_HOME" "$POPULATED_HOME"
|
||||
|
||||
# Start the blank-slate daemon — pristine first-launch UX.
|
||||
echo "==> Starting blank-slate daemon (port $BLANK_PORT)"
|
||||
rig daemon start \
|
||||
--openrig-home "$BLANK_HOME" \
|
||||
--port "$BLANK_PORT" \
|
||||
--db "$BLANK_HOME/openrig.sqlite"
|
||||
|
||||
# Start the populated daemon — runs alongside the blank one with its own state.
|
||||
echo "==> Starting populated daemon (port $POPULATED_PORT)"
|
||||
rig daemon start \
|
||||
--openrig-home "$POPULATED_HOME" \
|
||||
--port "$POPULATED_PORT" \
|
||||
--db "$POPULATED_HOME/openrig.sqlite"
|
||||
|
||||
echo
|
||||
echo "==> Both daemons up. Seed the populated daemon with sample data:"
|
||||
echo " OPENRIG_HOME=$POPULATED_HOME OPENRIG_PORT=$POPULATED_PORT \\"
|
||||
echo " rig up product-team # instantiate a sample rig"
|
||||
echo
|
||||
echo " Copy workflow fixtures to operator workspace specs dir:"
|
||||
echo " cp $FIXTURE_DIR/workflows/*.yaml \$OPENRIG_WORKSPACE_SPECS_ROOT/workflows/"
|
||||
echo " (slice 11 auto-discovers them on GET /api/specs/library)"
|
||||
echo
|
||||
echo "==> Operator UI access:"
|
||||
echo " Blank-slate: http://127.0.0.1:$BLANK_PORT"
|
||||
echo " Populated: http://127.0.0.1:$POPULATED_PORT"
|
||||
echo
|
||||
echo "==> See conventions/vm-preview/README.md for the full workflow + how to extend."
|
||||
Reference in new issue
Block a user