Ships the four shell scripts the sweep manifest references plus the R4-L7 contract test that 08-01's threat model deferred (T-08-05). Scripts: - scripts/shipping-gate.sh: invokes the debug-built jarvis-eval all binary; --live requires JARVIS_LIVE_EVAL=1 (D-04 dual-gate). Debug configuration is intentional: MCPCrashRunner consumes #if DEBUG-gated test seams on MCPClient/MCPServerHandle, so a release build of jarvis-eval would not compile. - scripts/promote-replay-session.sh: D-09 operator helper; copies recorded SQLite + writes sidecar JSON with temperature / model / replaySchemaVersion so DriftClassifier knows whether nondeterministicUnderSampling exclusions apply. - scripts/check-corpus-secrets.sh: D-07 pre-commit guard greps Corpora/ for sk-ant-, AKIA, ghp_, sk- patterns. Verified on positive (planted-secret) + negative (clean Corpora) inputs. - scripts/precommit-template.sh: committed template the operator symlinks to .git/hooks/pre-commit; updates flow through automatically. Worktree's pre-commit hook also installed at .git/hooks/pre-commit. ReplaySuppressionIntegrationTests (R4-L7): - 9 tests asserting the TurnSource suppression contract: .replay(sessionId:) and .evaluation(scenarioId:) both have dispatchesToHUD=false / speaks=false; .text and .voice (controls) have both true; .memoryExtraction shares the suppressed policy. - Asserted as a contract test (not a behavioral spy) because CONTEXT 5.1 forbids modifying production AgentOrchestrator/bus/TTS to inject spies. The properties are the architectural seam the first consumer reads; the test locks the policy table. jarvis-eval `all` cross-subcommand dispatch refactored from direct .init()+property assignment to .parse(argv) — the property-wrapper backing storage of @Flag/@Option requires the parser path; direct init trips the "Can't read a value from a parsable argument definition" guard. Shipping-gate.sh end-to-end smoke (recorded for SUMMARY): - checklist: PASS (with manual coverage on 06-voice + 1 on 01-foundations) - corpus-injection: PASS - corpus-sse: PASS - corpus-ndjson: PASS - cap-recovery: PASS - audio-rebuild: PASS (4/4 triggers automated) - wake-corpus: FAIL (empty corpus — operator-recorded WAVs deferred) - mcp-crash: FAIL (MockHelper fixture path resolution; pre-existing 08-03 issue with packages/packages/ duplication) - corpus-ndjson-live: SKIPPED (--live not set) - 8-hardening checklist: PASS (15/15 items) The infrastructure-failure-free run is the success criterion; the two downstream failures (wake-corpus + mcp-crash) trace back to 08-02 and 08-03 respectively and are not Task 3 bugs. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
67 lines
2.4 KiB
Bash
Executable File
67 lines
2.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# promote-replay-session.sh — D-09 operator helper.
|
|
#
|
|
# Copies a recorded session SQLite into Corpora/replay-golden/ + records
|
|
# temperature / model / replaySchemaVersion meta into a sidecar JSON so
|
|
# DriftClassifier knows whether `nondeterministicUnderSampling` exclusions
|
|
# apply to this archetype on replay.
|
|
#
|
|
# Usage:
|
|
# scripts/promote-replay-session.sh <session.sqlite> <archetype-name>
|
|
#
|
|
# Where <archetype-name> is one of (D-08 curated set):
|
|
# short-turn, long-multitool-turn, cap-recovery,
|
|
# confirm-approved, confirm-denied, voice-barge-in,
|
|
# stream-truncation-retry, vision-frame-attach
|
|
#
|
|
# The source SQLite must contain a `meta` table with rows for
|
|
# `temperature`, `model`, and `schema_version` (P4 ReplayLog writes these).
|
|
# Missing keys default to "0.0" / "unknown" / "1" respectively.
|
|
#
|
|
# Variable indirection per S-6:
|
|
# REPO=... override repo root detection
|
|
# DEST_DIR=... override Corpora/replay-golden/ path
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
: "${REPO:=$(cd "$SCRIPT_DIR/.." && pwd)}"
|
|
: "${DEST_DIR:=$REPO/packages/Harness/Corpora/replay-golden}"
|
|
|
|
SRC="${1:?source SQLite path required (arg 1)}"
|
|
NAME="${2:?archetype name required (arg 2)}"
|
|
DEST_SQLITE="${DEST_DIR}/${NAME}.sqlite"
|
|
DEST_META="${DEST_DIR}/${NAME}.meta.json"
|
|
|
|
[[ -f "$SRC" ]] || { echo "promote-replay-session: source SQLite not found: $SRC" >&2; exit 1; }
|
|
mkdir -p "$DEST_DIR"
|
|
|
|
# Read meta from source's `meta` table. Parameter-free SELECT — no SQL
|
|
# injection surface (T-08-22 mitigation).
|
|
TEMPERATURE=$(sqlite3 "$SRC" "SELECT value FROM meta WHERE key='temperature' LIMIT 1;" 2>/dev/null || true)
|
|
MODEL=$(sqlite3 "$SRC" "SELECT value FROM meta WHERE key='model' LIMIT 1;" 2>/dev/null || true)
|
|
SCHEMA=$(sqlite3 "$SRC" "SELECT value FROM meta WHERE key='schema_version' LIMIT 1;" 2>/dev/null || true)
|
|
RECORDED_AT=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
|
|
[[ -z "$TEMPERATURE" ]] && TEMPERATURE="0.0"
|
|
[[ -z "$MODEL" ]] && MODEL="unknown"
|
|
[[ -z "$SCHEMA" ]] && SCHEMA="1"
|
|
|
|
# JSON-escape the model string (it can carry colons and slashes).
|
|
MODEL_ESCAPED=$(printf '%s' "$MODEL" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g')
|
|
|
|
cp -p "$SRC" "$DEST_SQLITE"
|
|
|
|
cat > "$DEST_META" <<JSON_EOF
|
|
{
|
|
"archetype": "${NAME}",
|
|
"temperature": ${TEMPERATURE},
|
|
"model": "${MODEL_ESCAPED}",
|
|
"replaySchemaVersion": ${SCHEMA},
|
|
"recordedAt": "${RECORDED_AT}",
|
|
"source": "${SRC}"
|
|
}
|
|
JSON_EOF
|
|
|
|
echo "Promoted: $DEST_SQLITE"
|
|
echo "Meta: $DEST_META"
|