v0.4.3: cross-env bundle for regression — no direct peer protocol needed
Each Larry is independent. Bryan's question "how will Larry on Windows
talk to Larry on Linux for regression file transfer" answered: they don't.
File transfer is YOUR responsibility (scp / gh release / shared mount /
USB), but nc-regression now produces and consumes portable bundles that
make the split a one-command-on-each-side workflow.
Changes:
lib/nc-regression.sh
+ --phase env-a convenience for phases 1+2+3 (env-A side)
+ --phase env-b convenience for phases 4+5+6 (env-B side + diff)
+ --bundle-out PATH after env-A phases, tar inputs+outputs/env-a +
manifest.json + README.md + inbounds.txt
+ --bundle-in PATH at start, untar a bundle into $OUT; pulls scope
from the manifest so the env-B side just needs
--env-b and --route-test-cmd
MANUAL.md
+ New "Cross-environment Larry — how the boxes communicate" section
+ Bundle transport table (scp, gh release, NFS, USB, etc.)
+ Notes that the lesson loop uses the same local-capture / manual-
transport / central-merge model
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
a0502e2ec6
commit
b141d54847
60
MANUAL.md
60
MANUAL.md
@ -398,6 +398,66 @@ Output: markdown report with cluster overview, per-thread protocol-block diff, p
|
||||
|
||||
---
|
||||
|
||||
## Cross-environment Larry — how the boxes communicate
|
||||
|
||||
**They don't, directly.** Each Larry on each box is independent. For regression
|
||||
testing across two firewalled environments, the workflow is:
|
||||
|
||||
```
|
||||
env-A (Windows) env-B (Linux)
|
||||
nc-regression --phase env-a → nc-regression --phase env-b
|
||||
--bundle-out /tmp/reg.tar.gz --bundle-in /tmp/reg.tar.gz
|
||||
│ │
|
||||
└────── you move the bundle ────────┘
|
||||
(scp, gh release, USB,
|
||||
shared mount, etc.)
|
||||
```
|
||||
|
||||
The `--bundle-out` flag (after env-A phases 1-3) produces a tarball with:
|
||||
- `inputs/*.msgs` — sampled messages from env-A smatdbs
|
||||
- `outputs/env-a/*/*.out` — env-A route_test outputs
|
||||
- `manifest.json` — env-A metadata + hints
|
||||
- `inbounds.txt` — the threads tested
|
||||
- `README.md` — instructions for the env-B side
|
||||
|
||||
Move the bundle however you can (see below). Then on env-B:
|
||||
|
||||
```bash
|
||||
nc-regression.sh \
|
||||
--bundle-in /path/to/reg.tar.gz \
|
||||
--out /tmp/reg \
|
||||
--env-b $HCIROOT --site-b $HCISITE \
|
||||
--route-test-cmd '<env-b route_test command>' \
|
||||
--phase env-b
|
||||
```
|
||||
|
||||
That runs phases 4-6 (route_test on env-B with same inputs, diff each pair,
|
||||
master summary).
|
||||
|
||||
### Bundle transport options (pick whichever your network allows)
|
||||
|
||||
| how | when |
|
||||
|---|---|
|
||||
| `scp` between the boxes | both boxes mutually SSH-reachable |
|
||||
| `scp` to your laptop, `scp` to env-B | you can SSH to each separately |
|
||||
| Private GitHub release / gist | both boxes can reach github.com but not each other |
|
||||
| Shared NFS / SMB mount | the boxes share a filesystem |
|
||||
| Box / SharePoint / S3 | enterprise common-storage |
|
||||
| USB stick / portable drive | nothing else works |
|
||||
| Tarball as email attachment | small bundles, both boxes have email |
|
||||
|
||||
The bundle is plain `tar.gz` — nothing Cloverleaf-specific. Inspect it with
|
||||
`tar -tzf reg.tar.gz` to see what's inside before moving it.
|
||||
|
||||
### Lessons / refinements use the same pattern
|
||||
|
||||
Larry on a client captures lessons locally (`/lesson`, lesson_record tool).
|
||||
You export the lesson bundle with `lib/lessons.sh export` and paste it back
|
||||
to home-Larry (the dev-machine session you have with me). Same model:
|
||||
local capture, manual transport, central merge. No direct peer protocol.
|
||||
|
||||
---
|
||||
|
||||
## Regression testing — end to end (`lib/nc-regression.sh`)
|
||||
|
||||
Full Example 6 orchestrator. Six phases: discover → sample → route-test A → route-test B → diff → summary.
|
||||
|
||||
2
larry.sh
2
larry.sh
@ -32,7 +32,7 @@ set -o pipefail
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Config
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
LARRY_VERSION="0.4.2"
|
||||
LARRY_VERSION="0.4.3"
|
||||
LARRY_HOME="${LARRY_HOME:-$HOME/.larry}"
|
||||
LARRY_UPDATE_URL="${LARRY_UPDATE_URL:-https://raw.githubusercontent.com/bojj27/cloverleaf-larry/main/larry.sh}"
|
||||
LARRY_AGENTS_URL="${LARRY_AGENTS_URL:-https://raw.githubusercontent.com/bojj27/cloverleaf-larry/main/agents}"
|
||||
|
||||
@ -70,6 +70,8 @@ DRY_RUN=0
|
||||
INBOUND_MODE="all"
|
||||
ENV_B_HOST=""
|
||||
ENV_B_USER=""
|
||||
BUNDLE_OUT="" # after env-A phases, tar up the artifacts here
|
||||
BUNDLE_IN="" # at start, untar a bundle here as the env-A artifacts
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
@ -88,6 +90,8 @@ while [ $# -gt 0 ]; do
|
||||
--inbound-mode) shift; INBOUND_MODE="$1" ;;
|
||||
--env-b-host) shift; ENV_B_HOST="$1" ;;
|
||||
--env-b-user) shift; ENV_B_USER="$1" ;;
|
||||
--bundle-out) shift; BUNDLE_OUT="$1" ;;
|
||||
--bundle-in) shift; BUNDLE_IN="$1" ;;
|
||||
-h|--help) sed -n '2,55p' "$NC_SELF"; exit 0 ;;
|
||||
-*) die "unknown flag: $1" ;;
|
||||
*) die "extra arg: $1" ;;
|
||||
@ -95,16 +99,35 @@ while [ $# -gt 0 ]; do
|
||||
shift
|
||||
done
|
||||
|
||||
[ -n "$OUT" ] || die "missing --out DIR"
|
||||
# When --bundle-in is given, we don't need scope/env-a/etc. — the bundle has them.
|
||||
if [ -z "$BUNDLE_IN" ]; then
|
||||
[ -n "$SCOPE" ] || die "missing --scope (thread:NAME | threads:N1,N2 | site | server)"
|
||||
[ -n "$ENV_A" ] || die "missing --env-a HCIROOT_A"
|
||||
[ -n "$ENV_B" ] || die "missing --env-b HCIROOT_B"
|
||||
[ -n "$OUT" ] || die "missing --out DIR"
|
||||
[ -d "$ENV_A" ] || die "env-a is not a directory: $ENV_A"
|
||||
case "$PHASE" in 1|2|3|4|5|6|all) ;; *) die "bad --phase" ;; esac
|
||||
fi
|
||||
case "$PHASE" in 1|2|3|4|5|6|all|env-a|env-b) ;; *) die "bad --phase (use 1|2|3|4|5|6|all|env-a|env-b)" ;; esac
|
||||
[ "$DRY_RUN" = "1" ] || [ -n "$ROUTE_TEST_CMD" ] || say "WARNING: --route-test-cmd is unset; phases 3 and 4 will be skipped (you can run them manually using the generated input files)"
|
||||
|
||||
mkdir -p "$OUT" "$OUT/inputs" "$OUT/outputs/env-a" "$OUT/outputs/env-b" "$OUT/diff" 2>/dev/null
|
||||
|
||||
# If --bundle-in given, untar the bundle into $OUT first. Manifest tells us
|
||||
# what env-A was and (optionally) what route_test command to use.
|
||||
if [ -n "$BUNDLE_IN" ]; then
|
||||
[ -f "$BUNDLE_IN" ] || die "bundle-in file not found: $BUNDLE_IN"
|
||||
say "unpacking bundle $BUNDLE_IN into $OUT/"
|
||||
tar -xzf "$BUNDLE_IN" -C "$OUT" 2>&1 | tail -5
|
||||
if [ -f "$OUT/manifest.json" ]; then
|
||||
say "manifest from env-A:"
|
||||
cat "$OUT/manifest.json" >&2
|
||||
# Pull scope and route-test-cmd hints if not overridden
|
||||
if [ -z "$SCOPE" ] && command -v jq >/dev/null 2>&1; then
|
||||
SCOPE=$(jq -r '.scope // ""' "$OUT/manifest.json")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Phase 1: discover inbound threads in scope
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
@ -328,5 +351,50 @@ case "$PHASE" in
|
||||
5) phase_5 ;;
|
||||
6) phase_6 ;;
|
||||
all) phase_1 && phase_2 && phase_3 && phase_4 && phase_5 && phase_6 ;;
|
||||
env-a) phase_1 && phase_2 && phase_3 ;; # everything that uses env-A
|
||||
env-b) phase_4 && phase_5 && phase_6 ;; # everything that uses env-B + diff
|
||||
esac
|
||||
|
||||
# Optional: produce a portable bundle of the env-A artifacts (inputs + a-outputs)
|
||||
# so the user can move them to the env-B box manually.
|
||||
if [ -n "$BUNDLE_OUT" ]; then
|
||||
say "producing bundle: $BUNDLE_OUT"
|
||||
{
|
||||
printf '{'
|
||||
printf '"generated":"%s",' "$(date -Iseconds 2>/dev/null || date)"
|
||||
printf '"host":"%s",' "$(hostname 2>/dev/null || echo unknown)"
|
||||
printf '"env_a":"%s",' "$ENV_A"
|
||||
printf '"site_a":"%s",' "$SITE_A"
|
||||
printf '"env_b_expected":"%s",' "$ENV_B"
|
||||
printf '"site_b_expected":"%s",' "$SITE_B"
|
||||
printf '"scope":"%s",' "$SCOPE"
|
||||
printf '"count":%s,' "$COUNT"
|
||||
printf '"ignore":"%s",' "$IGNORE"
|
||||
printf '"route_test_cmd_hint":"%s"' "$ROUTE_TEST_CMD"
|
||||
printf '}\n'
|
||||
} > "$OUT/manifest.json"
|
||||
cat > "$OUT/README.md" <<EOF
|
||||
# Regression bundle — env-A artifacts
|
||||
|
||||
Take this bundle to the env-B box and run:
|
||||
|
||||
\`\`\`
|
||||
nc-regression.sh --bundle-in $(basename "$BUNDLE_OUT") --out $OUT \\
|
||||
--env-b /path/to/env-b/integrator --site-b <site> \\
|
||||
--route-test-cmd '<env-b route_test command>' \\
|
||||
--phase env-b
|
||||
\`\`\`
|
||||
|
||||
The bundle contains:
|
||||
- inputs/ — sampled messages from env-A (one .msgs per inbound)
|
||||
- outputs/env-a/ — route_test outputs from env-A
|
||||
- manifest.json — env-A metadata
|
||||
- inbounds.txt — the threads tested
|
||||
|
||||
env-B side will produce outputs/env-b/ and the diff/ tree.
|
||||
EOF
|
||||
tar -czf "$BUNDLE_OUT" -C "$OUT" inputs outputs/env-a inbounds.txt manifest.json README.md 2>/dev/null
|
||||
say "bundle ready: $BUNDLE_OUT ($(du -h "$BUNDLE_OUT" | awk '{print $1}'))"
|
||||
fi
|
||||
|
||||
say "regression run done. Output root: $OUT"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user