summaryrefslogtreecommitdiffstats
path: root/debug/risc-v-gsp-rm-vm/rmharness/harness.sh
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-02 10:58:21 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-02 10:58:21 -0400
commit002e3d7d13c414ea874abbee8d82803dd3a72fe5 (patch)
tree6627c12fa07f6a1cf73e5aaeb7390e698dd3a896 /debug/risc-v-gsp-rm-vm/rmharness/harness.sh
parent2f249817df327f5dcccf0464ad517fa60d6071d3 (diff)
downloadopen-iov-002e3d7d13c414ea874abbee8d82803dd3a72fe5.tar.gz
open-iov-002e3d7d13c414ea874abbee8d82803dd3a72fe5.zip
debug: green-eye wave 3 - RM harness, local simulator, device map, MCP plugin, value-validation demos, CI pipeline, toolchain docs; add host RM tools rmtool/rmtop
Diffstat (limited to 'debug/risc-v-gsp-rm-vm/rmharness/harness.sh')
-rwxr-xr-xdebug/risc-v-gsp-rm-vm/rmharness/harness.sh147
1 files changed, 147 insertions, 0 deletions
diff --git a/debug/risc-v-gsp-rm-vm/rmharness/harness.sh b/debug/risc-v-gsp-rm-vm/rmharness/harness.sh
new file mode 100755
index 0000000..60fce8a
--- /dev/null
+++ b/debug/risc-v-gsp-rm-vm/rmharness/harness.sh
@@ -0,0 +1,147 @@
+#!/usr/bin/env bash
+# harness.sh - run a read-only RM tool, capture stdout/stderr, and record the
+# run into a green-eye session directory (blob + events.jsonl line).
+#
+# usage: harness.sh [--session DIR] [--name LABEL] -- TOOL [ARGS...]
+# TOOL is one of: rmtool rmtop rmq
+#
+# When --session is given the harness appends a "rm_harness_run" event and
+# writes the captured streams under <session>/blobs/. Existing session files
+# are never rewritten; recording is additive. Without --session the tool runs
+# and streams pass through unchanged.
+set -euo pipefail
+HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ALLOWED="rmtool rmtop rmq"
+
+usage() {
+ cat <<'EOF'
+usage: harness.sh [--session DIR] [--name LABEL] -- TOOL [ARGS...]
+
+TOOL is one of: rmtool rmtop rmq (wrapper scripts in this directory).
+Everything after -- is passed to the tool unchanged.
+EOF
+}
+
+session=""
+label=""
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --session)
+ session="${2:?--session needs a directory}"
+ shift 2
+ ;;
+ --name)
+ label="${2:?--name needs a label}"
+ shift 2
+ ;;
+ -h | --help)
+ usage
+ exit 0
+ ;;
+ --)
+ shift
+ break
+ ;;
+ -*)
+ echo "harness.sh: unknown option '$1'" >&2
+ usage >&2
+ exit 2
+ ;;
+ *)
+ break
+ ;;
+ esac
+done
+
+tool="${1:-}"
+if [[ -z "$tool" ]]; then
+ usage >&2
+ exit 2
+fi
+shift
+tool="${tool%.sh}"
+case " $ALLOWED " in
+*" $tool "*) ;;
+*)
+ echo "harness.sh: tool '$tool' is not on the read-only allowlist" \
+ "($ALLOWED)" >&2
+ exit 2
+ ;;
+esac
+
+wrapper="$HERE/$tool.sh"
+if [[ ! -x "$wrapper" ]]; then
+ echo "harness.sh: wrapper not found: $wrapper" >&2
+ exit 2
+fi
+
+argv_json="$(python3 -c 'import json,sys; print(json.dumps(sys.argv[1:]))' \
+ "$tool" "$@")"
+out_file="$(mktemp)"
+err_file="$(mktemp)"
+trap 'rm -f "$out_file" "$err_file"' EXIT
+
+start="$(python3 -c 'import time; print(time.time())')"
+rc=0
+"$wrapper" "$@" >"$out_file" 2>"$err_file" || rc=$?
+end="$(python3 -c 'import time; print(time.time())')"
+
+cat "$out_file"
+cat "$err_file" >&2
+
+if [[ -n "$session" ]]; then
+ mkdir -p "$session/blobs"
+ stamp="$(date -u +%Y%m%dT%H%M%SZ)"
+ out_rel="blobs/rmharness-${stamp}-${tool}-stdout.txt"
+ err_rel="blobs/rmharness-${stamp}-${tool}-stderr.txt"
+ cp "$out_file" "$session/$out_rel"
+ cp "$err_file" "$session/$err_rel"
+ SESSION="$session" TOOL="$tool" ARGV_JSON="$argv_json" \
+ RC="$rc" START="$start" END="$end" LABEL="$label" \
+ OUT_REL="$out_rel" ERR_REL="$err_rel" \
+ python3 - <<'PY'
+import hashlib
+import json
+import os
+import time
+
+session = os.environ["SESSION"]
+
+
+def blob_info(rel):
+ path = os.path.join(session, rel)
+ with open(path, "rb") as fh:
+ data = fh.read()
+ return {"path": rel, "size": len(data),
+ "sha256": hashlib.sha256(data).hexdigest()}
+
+
+event = {
+ "t": 0.0,
+ "type": "rm_harness_run",
+ "tool": os.environ["TOOL"],
+ "label": os.environ["LABEL"] or None,
+ "argv": json.loads(os.environ["ARGV_JSON"]),
+ "exit": int(os.environ["RC"]),
+ "start": float(os.environ["START"]),
+ "end": float(os.environ["END"]),
+ "duration_s": round(float(os.environ["END"]) - float(os.environ["START"]), 6),
+ "stdout": blob_info(os.environ["OUT_REL"]),
+ "stderr": blob_info(os.environ["ERR_REL"]),
+ "readonly": True,
+}
+meta = os.path.join(session, "session.json")
+if not os.path.exists(meta):
+ with open(meta, "w", encoding="utf-8") as fh:
+ json.dump({"format": "greeneye-session/1", "name": "rmharness",
+ "created": time.time(),
+ "greeneye": "external-rmharness/1"}, fh, indent=1,
+ sort_keys=True)
+with open(os.path.join(session, "events.jsonl"), "a", encoding="utf-8") as fh:
+ fh.write(json.dumps(event, sort_keys=True) + "\n")
+print(f"[rmharness] recorded {os.environ['TOOL']} -> {session} "
+ f"({os.environ['OUT_REL']})")
+PY
+fi
+
+exit "$rc"