pantheon-opencode 1.5.2 → 1.6.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/.pantheon/code-mode/README.md +4 -2
  2. package/.pantheon/code-mode/checkpoint_session.py +138 -102
  3. package/.pantheon/code-mode/compress-inline.py +102 -57
  4. package/.pantheon/code-mode/manifest.json +2 -8
  5. package/AGENTS.global.md +182 -0
  6. package/AGENTS.md +10 -891
  7. package/CHANGELOG.md +343 -0
  8. package/README.md +577 -79
  9. package/README.pt-BR.md +345 -60
  10. package/bin/pantheon-init.mjs +26 -3
  11. package/commands/pantheon-audit.md +7 -1
  12. package/commands/pantheon-consolidate.md +1 -1
  13. package/commands/pantheon-deepwork.md +14 -3
  14. package/commands/pantheon-focus.md +17 -0
  15. package/commands/pantheon-optimize.md +2 -2
  16. package/commands/pantheon-vision.md +61 -12
  17. package/package.json +30 -11
  18. package/plugin.json +2 -2
  19. package/pyproject.toml +11 -16
  20. package/scripts/build-agents-md.mjs +376 -58
  21. package/scripts/changelog-merge.mjs +161 -0
  22. package/scripts/check-plugin-v2-coverage.mjs +213 -0
  23. package/scripts/ci-validate-yaml.py +7 -5
  24. package/scripts/{code_mode_server.py → code_mode.py} +119 -27
  25. package/scripts/cost.mjs +244 -41
  26. package/scripts/doctor.mjs +236 -29
  27. package/scripts/install/agents-md.mjs +4 -4
  28. package/scripts/install/cli-ui.mjs +1 -1
  29. package/scripts/install/config-migration.mjs +319 -6
  30. package/scripts/install/health-check.mjs +26 -37
  31. package/scripts/install/interactive.mjs +7 -7
  32. package/scripts/install/migrate.mjs +1 -1
  33. package/scripts/install/opencode-version.mjs +246 -4
  34. package/scripts/install/opencode.mjs +627 -179
  35. package/scripts/install/plugin.mjs +43 -9
  36. package/scripts/install/shared.mjs +120 -12
  37. package/scripts/install/vision-prompt.mjs +161 -0
  38. package/scripts/install-mcp.mjs +28 -9
  39. package/scripts/{mcp_persistence_server.py → mcp_persistence.py} +392 -78
  40. package/{src/mcp/mcp_resources_server.py → scripts/mcp_resources.py} +2 -2
  41. package/scripts/{memory_mcp_server.py → memory_mcp.py} +372 -198
  42. package/scripts/postinstall.mjs +0 -7
  43. package/scripts/probe-context-rehydrate.mjs +36 -13
  44. package/scripts/probe-pantheon-cost.mjs +71 -15
  45. package/scripts/prune.mjs +2 -2
  46. package/scripts/run-node-tests.mjs +189 -0
  47. package/scripts/sync-artifacts.mjs +26 -13
  48. package/scripts/sync-tui.mjs +24 -3
  49. package/scripts/test-opencode-v2-sandbox.sh +1913 -0
  50. package/scripts/validate-routing.mjs +43 -3
  51. package/scripts/validate-sandbox-install.mjs +138 -0
  52. package/scripts/versioning.mjs +13 -1
  53. package/scripts/vision-status.mjs +682 -0
  54. package/skills-lock.json +15 -16
  55. package/src/agents/aphrodite.md +20 -37
  56. package/src/agents/apollo.md +7 -3
  57. package/src/agents/athena.md +63 -35
  58. package/src/agents/demeter.md +8 -28
  59. package/src/agents/gaia.md +1 -1
  60. package/src/agents/hephaestus.md +10 -21
  61. package/src/agents/hermes.md +15 -38
  62. package/src/agents/iris.md +1 -1
  63. package/src/agents/mnemosyne.md +23 -60
  64. package/src/agents/nyx.md +1 -1
  65. package/src/agents/prometheus.md +16 -20
  66. package/src/agents/talos.md +10 -2
  67. package/src/agents/themis.md +5 -5
  68. package/src/agents/zeus.md +99 -130
  69. package/src/instructions/agent-return-format.instructions.md +18 -3
  70. package/src/instructions/backend-standards.instructions.md +2 -0
  71. package/src/instructions/frontend-standards.instructions.md +3 -1
  72. package/src/instructions/memory-protocol.instructions.md +11 -110
  73. package/src/instructions/zeus-anti-stall.instructions.md +14 -61
  74. package/src/instructions/zeus-communication-rules.instructions.md +0 -1
  75. package/src/instructions/zeus-council-synthesis.instructions.md +32 -260
  76. package/src/instructions/zeus-memory-operations.instructions.md +26 -0
  77. package/src/instructions/zeus-timeout-retry.instructions.md +40 -87
  78. package/src/mcp/{code_mode_server.py → code_mode.py} +119 -27
  79. package/src/mcp/eval_store.py +2 -2
  80. package/src/mcp/mcp_codemap_module.py +559 -129
  81. package/src/mcp/{mcp_persistence_server.py → mcp_persistence.py} +392 -78
  82. package/{scripts/mcp_resources_server.py → src/mcp/mcp_resources.py} +2 -2
  83. package/src/mcp/{memory_mcp_server.py → memory_mcp.py} +373 -250
  84. package/src/mcp/{pantheon_vision_server.py → pantheon_vision.py} +396 -40
  85. package/src/mcp/requirements-mcp.txt +10 -6
  86. package/src/mcp/requirements-vision.txt +4 -2
  87. package/src/pantheon/cost-command.ts +399 -101
  88. package/src/pantheon/delegation-enforce.ts +10 -1
  89. package/src/pantheon/model-command.ts +18 -7
  90. package/src/pantheon/presets.d.mts +0 -8
  91. package/src/pantheon/presets.mjs +5 -32
  92. package/src/pantheon/todo-enforcer.ts +1 -1
  93. package/src/pantheon/v2-bounded-read.ts +640 -0
  94. package/src/pantheon/v2-delegation-enforce.ts +214 -0
  95. package/src/pantheon/v2-execute-after.ts +186 -0
  96. package/src/pantheon/v2-tools.ts +429 -0
  97. package/src/pantheon/v2-unsupported.d.mts +11 -0
  98. package/src/pantheon/v2-unsupported.mjs +90 -0
  99. package/src/pantheon/v2-vision.ts +622 -0
  100. package/src/pantheon/vision-local.ts +531 -0
  101. package/src/pantheon/vision.ts +1161 -116
  102. package/src/plugin-v2.ts +1244 -288
  103. package/src/plugin.ts +12 -9
  104. package/src/plugins/tui/dist/server.d.ts +1 -2
  105. package/src/plugins/tui/dist/server.d.ts.map +1 -1
  106. package/src/plugins/tui/dist/tui-v2.d.ts +154 -0
  107. package/src/plugins/tui/dist/tui-v2.d.ts.map +1 -0
  108. package/src/plugins/tui/dist/tui-v2.js +659 -0
  109. package/src/plugins/tui/dist/tui-v2.js.map +1 -0
  110. package/src/plugins/tui/dist/tui.d.ts +85 -82
  111. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  112. package/src/plugins/tui/dist/tui.js +72 -59
  113. package/src/plugins/tui/index-v2.ts +6 -0
  114. package/src/plugins/tui/package-lock.json +5504 -1341
  115. package/src/plugins/tui/package.json +25 -15
  116. package/src/plugins/tui/src/index-v2.tsx +734 -0
  117. package/src/plugins/tui/src/index.tsx +106 -85
  118. package/src/plugins/tui/src/opencode-v2.d.ts +13 -0
  119. package/src/plugins/tui/tsconfig.build.json +5 -0
  120. package/src/plugins/tui/tsconfig.typecheck.json +5 -0
  121. package/src/plugins/tui/tsdown.config.ts +22 -2
  122. package/src/plugins/tui/tui-v2.ts +2 -0
  123. package/src/plugins/tui/tui.ts +3 -0
  124. package/src/routing.yml +11 -22
  125. package/src/skills/README.md +34 -39
  126. package/src/skills/agent-coordination/SKILL.md +7 -2
  127. package/src/skills/artifact-management/SKILL.md +12 -5
  128. package/src/skills/auto-continue/SKILL.md +54 -95
  129. package/src/skills/code-review-checklist/SKILL.md +5 -5
  130. package/src/skills/context-compression/SKILL.md +26 -879
  131. package/src/skills/session-goal/SKILL.md +14 -5
  132. package/src/skills/spec-driven-development/SKILL.md +3 -1
  133. package/src/skills/tdd-with-agents/SKILL.md +18 -10
  134. package/.pantheon/code-mode/eval-llm-judge.py +0 -255
  135. package/.pantheon/code-mode/eval-monte-carlo.py +0 -368
  136. package/.pantheon/code-mode/eval-run.py +0 -197
  137. package/.pantheon/code-mode/eval-static.py +0 -321
  138. package/.pantheon/code-mode/session-end-save.py +0 -186
  139. package/.pantheon/code-mode/session-end-save.sh +0 -18
  140. package/opencode.json +0 -58
  141. package/scripts/recover-zenodo-deposition.mjs +0 -146
  142. package/scripts/test-opencode-v1-v2-sandbox.sh +0 -862
  143. package/scripts/validate-zenodo-release.mjs +0 -154
  144. package/scripts/zenodo-artifact.mjs +0 -94
  145. package/scripts/zenodo-release-state.mjs +0 -53
  146. package/src/skills/orchestration-workflow/SKILL.md +0 -311
@@ -1,862 +0,0 @@
1
- #!/usr/bin/env bash
2
- # test-opencode-v1-v2-sandbox.sh — Pantheon global-install sandbox validator
3
- # for OpenCode V1 (`opencode`) and V2 (`opencode2`) side-by-side.
4
- #
5
- # Validates the installed pantheon-opencode package AS A REAL USER inside an
6
- # isolated sandbox (own HOME, npm prefix and venv), never the dev environment.
7
- #
8
- # Modes (combinable):
9
- # --prepare Build tarball, install pantheon-opencode + OpenCode V1/V2
10
- # binaries in the sandbox prefix, headless init, and generate
11
- # the per-version project configs and sandbox run-test.sh.
12
- # --run v1|v2 Base validation for one version: opencode mcp list + doctor
13
- # (config is regenerated for that version first).
14
- # --prompts Prompt battery via `opencode run --format json` for every
15
- # requested version (with --run vX) or both versions alone.
16
- # --cost Offline pantheon_cost probe for the requested
17
- # version (with --run vX) or both versions alone.
18
- # The probe's synthetic checks run in explicit --fixture mode.
19
- # --rehydrate Offline context_rehydrate + context_session_summary
20
- # probe for the requested version (with --run vX) or both.
21
- # --reset Wipe the sandbox root.
22
- # --help Usage.
23
- #
24
- # Env overrides:
25
- # PANTHEON_SANDBOX_ROOT Sandbox root (default: ~/pantheon-sandbox)
26
- # OPENCODE_V1_SPEC npm spec providing the `opencode` binary
27
- # (default: opencode-ai@1.18.18)
28
- # OPENCODE_V2_SPEC npm spec providing the `opencode2` binary
29
- # (default: @opencode-ai/cli@beta)
30
- # PANTHEON_SANDBOX_MODEL Model used by init/prompts
31
- # (default: opencode-go/mimo-v2.5)
32
- # PANTHEON_PROMPT_TIMEOUT Per-prompt timeout in seconds (default: 300)
33
- # Exit codes: 0 = every required check returned explicit PASS,
34
- # 1 = any failure or untested check (see reports in the sandbox root),
35
- # 2 = usage error, 3 = sandbox not prepared.
36
- set -euo pipefail
37
-
38
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
39
- REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
40
-
41
- SANDBOX_ROOT="${PANTHEON_SANDBOX_ROOT:-$HOME/pantheon-sandbox}"
42
- SANDBOX_HOME="$SANDBOX_ROOT/home"
43
- NPM_PREFIX="$SANDBOX_HOME/.npm-global"
44
-
45
- OPENCODE_V1_SPEC="${OPENCODE_V1_SPEC:-opencode-ai@1.18.18}"
46
- OPENCODE_V2_SPEC="${OPENCODE_V2_SPEC:-@opencode-ai/cli@beta}"
47
- PANTHEON_SANDBOX_MODEL="${PANTHEON_SANDBOX_MODEL:-opencode-go/mimo-v2.5}"
48
- PANTHEON_PROMPT_TIMEOUT="${PANTHEON_PROMPT_TIMEOUT:-300}"
49
-
50
- V1_BIN="${OPENCODE_V1_BIN:-opencode}"
51
- V2_BIN="${OPENCODE_V2_BIN:-opencode2}"
52
-
53
- REPORT_FILE="$SANDBOX_ROOT/prompts-report.md"
54
- COST_REPORT_FILE="$SANDBOX_ROOT/pantheon-cost-report.md"
55
- REHYDRATE_REPORT_FILE="$SANDBOX_ROOT/context-rehydrate-report.md"
56
- EXTRACT_PY="$SANDBOX_ROOT/.prompt-extract-json.py"
57
-
58
- MODE_PREPARE=0
59
- MODE_RESET=0
60
- MODE_PROMPTS=0
61
- MODE_COST=0
62
- MODE_REHYDRATE=0
63
- RUN_VERSION=""
64
-
65
- usage() {
66
- sed -n '2,40p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
67
- exit 2
68
- }
69
-
70
- log() { printf '%s\n' "$*"; }
71
- warn() { printf 'WARN: %s\n' "$*" >&2; }
72
- die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; }
73
-
74
- bin_for() {
75
- case "$1" in
76
- v1) printf '%s' "$V1_BIN" ;;
77
- v2) printf '%s' "$V2_BIN" ;;
78
- *) return 1 ;;
79
- esac
80
- }
81
-
82
- project_for() { printf '%s/project-%s' "$SANDBOX_ROOT" "$1"; }
83
-
84
- # Resolve a binary STRICTLY inside the sandbox npm prefix — never fall back to
85
- # the dev PATH, otherwise a non-prepared sandbox would silently test the host
86
- # installation.
87
- sandbox_bin_for() { # name → prints path; rc 1 if not inside sandbox prefix
88
- local p
89
- p="$(command -v "$1" 2>/dev/null || true)"
90
- case "$p" in
91
- "$NPM_PREFIX"/*) printf '%s' "$p" ;;
92
- *) return 1 ;;
93
- esac
94
- }
95
-
96
- sandbox_bin_v() { # v → echoes path; rc 1 if missing
97
- sandbox_bin_for "$(bin_for "$1")"
98
- }
99
-
100
- # ── Sandbox environment isolation ─────────────────────────────────────────────
101
-
102
- sandbox_env() {
103
- export HOME="$SANDBOX_HOME"
104
- export PATH="$NPM_PREFIX/bin:$HOME/.config/opencode/.venv/bin:$PATH"
105
- export npm_config_prefix="$NPM_PREFIX"
106
- }
107
-
108
- # ── Gate (b): sandbox run-test.sh with pantheon://agents content validation ──
109
-
110
- write_run_test_sh() {
111
- cat > "$SANDBOX_ROOT/run-test.sh" <<'RUNTEST'
112
- #!/usr/bin/env bash
113
- # Generated by pantheon-opencode scripts/test-opencode-v1-v2-sandbox.sh --prepare
114
- # Validates the global install: binaries, exactly 5 connected MCPs per version,
115
- # doctor 0 errors, AND the CONTENT of pantheon://agents (zeus/hermes present).
116
- set -euo pipefail
117
-
118
- SANDBOX_DIR="$(cd "$(dirname "$0")" && pwd)"
119
- SANDBOX_HOME="$SANDBOX_DIR/home"
120
- NPM_PREFIX="$SANDBOX_HOME/.npm-global"
121
- PANTHEON_GLOBAL="$SANDBOX_HOME/.config/opencode"
122
- SANDBOX_VENV="$PANTHEON_GLOBAL/.venv"
123
- REPO_DIR="${PANTHEON_REPO:-$(cd "$SANDBOX_DIR/../pantheon" && pwd)}"
124
-
125
- echo "=== Pantheon Sandbox Test ==="
126
- echo "Sandbox: $SANDBOX_DIR"
127
- echo "Repo: $REPO_DIR"
128
-
129
- export HOME="$SANDBOX_HOME"
130
- export PATH="$NPM_PREFIX/bin:$SANDBOX_VENV/bin:$PATH"
131
- export npm_config_prefix="$NPM_PREFIX"
132
-
133
- STATUS_FAIL=0
134
- STATUS_PASS=0
135
-
136
- record_status() { # label status detail
137
- local label="$1" status="$2" detail="$3"
138
- case "$status" in
139
- PASS) STATUS_PASS=$((STATUS_PASS + 1)) ;;
140
- FAIL) STATUS_FAIL=$((STATUS_FAIL + 1)) ;;
141
- *) STATUS_FAIL=$((STATUS_FAIL + 1)); status="FAIL" ;;
142
- esac
143
- printf '%s: %s — %s\n' "$status" "$label" "$detail"
144
- }
145
-
146
- check_binary() { # label binary
147
- local label="$1" bin="$2" out rc=0
148
- if ! command -v "$bin" >/dev/null 2>&1; then
149
- record_status "$label" "FAIL" "binary '$bin' is not installed in the sandbox prefix"
150
- return 0
151
- fi
152
- set +e
153
- out="$("$bin" --version 2>&1)"
154
- rc=$?
155
- set -e
156
- if [ "$rc" -eq 0 ]; then
157
- record_status "$label" "PASS" "${out:-version command exited 0}"
158
- else
159
- record_status "$label" "FAIL" "version check exited $rc"
160
- fi
161
- }
162
-
163
- check_mcp() { # label binary project
164
- local label="$1" bin="$2" project="$3" out connected_count rc=0
165
- if ! command -v "$bin" >/dev/null 2>&1; then
166
- record_status "$label MCP" "FAIL" "binary '$bin' is not installed in the sandbox prefix"
167
- return 0
168
- fi
169
- if [ ! -d "$project" ]; then
170
- record_status "$label MCP" "FAIL" "project directory is missing: $project"
171
- return 0
172
- fi
173
- set +e
174
- out="$(cd "$project" && "$bin" mcp list 2>&1)"
175
- rc=$?
176
- set -e
177
- out="$(printf '%s' "$out" | sed -E $'s/\x1B\\[[0-?]*[ -/]*[@-~]//g')"
178
- printf '%s\n' "$out"
179
- if [ "$rc" -ne 0 ]; then
180
- record_status "$label MCP" "FAIL" "mcp list exited $rc"
181
- return 0
182
- fi
183
- connected_count="$(printf '%s' "$out" | grep -Eic '(^|[^[:alnum:]_])connected([^[:alnum:]_]|$)')" || connected_count=0
184
- if [ "$connected_count" -eq 5 ] \
185
- && ! printf '%s' "$out" | grep -Eiq 'failed|✘'; then
186
- record_status "$label MCP" "PASS" "exactly 5 connected MCPs"
187
- else
188
- record_status "$label MCP" "FAIL" "expected exactly 5 connected MCPs; found $connected_count or failures reported"
189
- fi
190
- }
191
-
192
- echo "--- Binaries ---"
193
- check_binary "V1 binary" opencode
194
- check_binary "V2 binary" opencode2
195
-
196
- echo "--- Building tarball ---"
197
- cd "$REPO_DIR"
198
- npm pack 2>/dev/null || { echo "ERROR: npm pack failed"; exit 1; }
199
- TGZ=$(ls -t pantheon-opencode-*.tgz | head -1)
200
- npm rm -g pantheon-opencode 2>/dev/null || true
201
- npm install -g "$TGZ"
202
- if ! git -C "$REPO_DIR" ls-files --error-unmatch -- "$TGZ" >/dev/null 2>&1; then rm -f -- "$TGZ"; fi
203
-
204
- echo "--- Init (headless) ---"
205
- pantheon-opencode init --headless -y
206
-
207
- echo "--- MCP Validation ---"
208
- check_mcp "V1" opencode "$SANDBOX_DIR/project-v1"
209
- check_mcp "V2" opencode2 "$SANDBOX_DIR/project-v2"
210
-
211
- echo "--- Doctor ---"
212
- if command -v pantheon-opencode >/dev/null 2>&1; then
213
- set +e
214
- DOCTOR_OUTPUT="$(pantheon-opencode doctor --target "$SANDBOX_DIR" 2>&1)"
215
- DOCTOR_RC=$?
216
- set -e
217
- if [ "$DOCTOR_RC" -eq 0 ]; then
218
- record_status "doctor" "PASS" "exit 0"
219
- else
220
- record_status "doctor" "FAIL" "doctor exited $DOCTOR_RC"
221
- fi
222
- else
223
- record_status "doctor" "FAIL" "pantheon-opencode is not installed in the sandbox prefix"
224
- fi
225
-
226
- echo "--- Gate (b): pantheon://agents CONTENT check ---"
227
- RESOURCES_SRV="$PANTHEON_GLOBAL/scripts/mcp_resources_server.py"
228
- if [ ! -f "$RESOURCES_SRV" ]; then
229
- record_status "pantheon://agents resource" "FAIL" "resources server not found at $RESOURCES_SRV"
230
- else
231
- set +e
232
- AGENTS_CONTENT="$("$SANDBOX_VENV/bin/python" - "$RESOURCES_SRV" <<'PYEOF'
233
- import asyncio, importlib.util, sys
234
- from pathlib import Path
235
- resource_path = Path(sys.argv[1]).resolve()
236
- sys.path.insert(0, str(resource_path.parent))
237
- spec = importlib.util.spec_from_file_location("mrs", sys.argv[1])
238
- mod = importlib.util.module_from_spec(spec)
239
- spec.loader.exec_module(mod)
240
- print(asyncio.run(mod.list_agents()))
241
- PYEOF
242
- )"
243
- AGENTS_RC=$?
244
- set -e
245
- printf '%s\n' "$AGENTS_CONTENT" | head -8
246
- if [ "$AGENTS_RC" -ne 0 ]; then
247
- record_status "pantheon://agents resource" "FAIL" "resource probe exited $AGENTS_RC"
248
- elif printf '%s\n' "$AGENTS_CONTENT" | grep -qi 'zeus' \
249
- && printf '%s\n' "$AGENTS_CONTENT" | grep -qi 'hermes'; then
250
- record_status "pantheon://agents resource" "PASS" "pantheon://agents content includes zeus and hermes"
251
- else
252
- record_status "pantheon://agents resource" "FAIL" "content missing zeus/hermes (connectivity alone is not enough)"
253
- fi
254
- fi
255
- echo ""
256
- echo "=== VALIDATION COMPLETE ==="
257
- if [ "$STATUS_FAIL" -gt 0 ] || [ "$STATUS_PASS" -eq 0 ]; then
258
- FINAL_VERDICT="FAIL"
259
- else
260
- FINAL_VERDICT="PASS"
261
- fi
262
- printf 'Final verdict: %s\n' "$FINAL_VERDICT"
263
- if [ "$FINAL_VERDICT" != "PASS" ]; then
264
- exit 1
265
- fi
266
- echo "Next: open the isolated TUI with: $SANDBOX_DIR/start-pantheon.sh"
267
- RUNTEST
268
- chmod +x "$SANDBOX_ROOT/run-test.sh"
269
- }
270
-
271
- # ── Reset / Prepare ───────────────────────────────────────────────────────────
272
-
273
- cmd_reset() {
274
- case "$SANDBOX_ROOT" in
275
- "/" | "$HOME" | "$REPO_DIR" | "$REPO_DIR"/*)
276
- die "refusing to reset unsafe sandbox root: $SANDBOX_ROOT" ;;
277
- esac
278
- log "Resetting sandbox: $SANDBOX_ROOT"
279
- rm -rf "$SANDBOX_ROOT"
280
- log "Sandbox removed."
281
- }
282
-
283
- install_binaries() {
284
- log "--- Installing pantheon-opencode (from repo tarball) ---"
285
- cd "$REPO_DIR"
286
- npm pack 2>/dev/null || die "npm pack failed"
287
- local tgz
288
- tgz=$(ls -t pantheon-opencode-*.tgz | head -1)
289
- npm rm -g pantheon-opencode 2>/dev/null || true
290
- npm install -g "$REPO_DIR/$tgz" || die "install of $tgz failed"
291
- if ! git -C "$REPO_DIR" ls-files --error-unmatch -- "$tgz" >/dev/null 2>&1; then rm -f -- "$tgz"; fi
292
- log "--- Installing OpenCode V1 ($OPENCODE_V1_SPEC) ---"
293
- npm install -g "$OPENCODE_V1_SPEC" || die "install of $OPENCODE_V1_SPEC failed"
294
- log "--- Installing OpenCode V2 ($OPENCODE_V2_SPEC) ---"
295
- npm install -g "$OPENCODE_V2_SPEC" || die "install of $OPENCODE_V2_SPEC failed"
296
- }
297
-
298
- prepare_project() {
299
- local v="$1" dir pan
300
- dir="$(project_for "$v")"
301
- mkdir -p "$dir"
302
- pan="$(sandbox_bin_for "pantheon-opencode")" \
303
- || die "pantheon-opencode not installed in sandbox prefix — run $0 --prepare first"
304
- log "--- Regenerating config for $v in $dir ---"
305
- (cd "$dir" && "$pan" init --project --version "$v" --model "$PANTHEON_SANDBOX_MODEL" -y) \
306
- || die "init --project --version $v failed in $dir"
307
- }
308
-
309
- cmd_prepare() {
310
- mkdir -p "$SANDBOX_HOME" "$NPM_PREFIX"
311
- write_run_test_sh
312
- sandbox_env
313
- install_binaries
314
- local pan
315
- pan="$(sandbox_bin_for "pantheon-opencode")" \
316
- || die "pantheon-opencode not found in sandbox prefix after install"
317
- log "--- Headless init (global venv + runtime) ---"
318
- "$pan" init --headless -y --model "$PANTHEON_SANDBOX_MODEL" \
319
- || die "pantheon-opencode init --headless failed"
320
- prepare_project v1
321
- prepare_project v2
322
- write_extract_py
323
- log "Prepare complete. Sandbox: $SANDBOX_ROOT"
324
- log "Next: $0 --run v1 --prompts | $0 --run v2 --prompts"
325
- }
326
-
327
- # ── JSON text extraction (schema-agnostic) ────────────────────────────────────
328
-
329
- write_extract_py() {
330
- cat > "$EXTRACT_PY" <<'PYEOF'
331
- """Collect every string value from opencode run --format json output."""
332
- import json
333
- import sys
334
-
335
-
336
- def walk(obj, out):
337
- if isinstance(obj, str):
338
- out.append(obj)
339
- elif isinstance(obj, dict):
340
- for value in obj.values():
341
- walk(value, out)
342
- elif isinstance(obj, list):
343
- for value in obj:
344
- walk(value, out)
345
-
346
-
347
- raw = sys.stdin.read()
348
- chunks = []
349
- try:
350
- walk(json.loads(raw), chunks)
351
- except Exception:
352
- for line in raw.splitlines():
353
- line = line.strip()
354
- if not line:
355
- continue
356
- try:
357
- walk(json.loads(line), chunks)
358
- except Exception:
359
- chunks.append(line)
360
- print("\n".join(chunks))
361
- PYEOF
362
- }
363
-
364
- # ── Prompt battery ────────────────────────────────────────────────────────────
365
-
366
- PROMPT_IDS=()
367
- PROMPT_TEXTS=()
368
- PROMPT_MARKERS=()
369
- PROMPT_VERIFY=()
370
-
371
- add_prompt() { # id marker ignored verify text
372
- PROMPT_IDS+=("$1")
373
- PROMPT_MARKERS+=("$2")
374
- PROMPT_VERIFY+=("$4")
375
- PROMPT_TEXTS+=("$5")
376
- }
377
-
378
- build_battery() {
379
- local v="$1"
380
- PROMPT_IDS=()
381
- PROMPT_TEXTS=()
382
- PROMPT_MARKERS=()
383
- PROMPT_VERIFY=()
384
- add_prompt "agents-resource" "AGENTS-OK" "" "" \
385
- "List your MCP resources and read the resource pantheon://agents. If the returned agent list includes an agent named 'zeus' and one named 'hermes', reply with exactly: AGENTS-OK. Otherwise reply with exactly: AGENTS-MISSING."
386
- add_prompt "memory-store" "MEMORY-STORE-OK" "" "" \
387
- "Use the pantheon-memory memory_store tool to store this exact entry: namespace 'default', key 'pantheon-sandbox-probe-$v', value 'alive'. Then reply with exactly: MEMORY-STORE-OK"
388
- add_prompt "memory-recall" "MEMORY-RECALL-OK" "" "" \
389
- "Use the pantheon-memory memory_recall tool (or memory_search) to look up key 'pantheon-sandbox-probe-$v' in namespace 'default'. If the stored value is 'alive', reply with exactly: MEMORY-RECALL-OK"
390
- add_prompt "tmp-write-read" "TMP-OK" "" \
391
- "${TMPDIR:-/tmp}/pantheon-sandbox-probe-$v.txt::TMP-OK" \
392
- "Using the bash tool, run a python3 -c command that writes the text TMP-OK to the file ${TMPDIR:-/tmp}/pantheon-sandbox-probe-$v.txt (overwrite it), then run another python3 -c command to read that file back. Do not use any other tool or command to write or read the file — only python3 -c. If what you read back is exactly TMP-OK, reply with exactly: TMP-OK"
393
- add_prompt "delegation" "DELEGATION-OK" "" "" \
394
- "Delegate a tiny task to the @talos agent via the task tool: ask it to reply with the single word PONG. If the delegated response contains PONG, reply with exactly: DELEGATION-OK. If you cannot delegate to agents in this context, reply with exactly: DELEGATION-UNAVAILABLE"
395
- }
396
-
397
- declare -A RESULTS
398
- declare -A DETAILS
399
-
400
- record() { # v id result detail
401
- RESULTS["$1:$2"]="$3"
402
- DETAILS["$1:$2"]="$4"
403
- }
404
-
405
- extract_text() { "$HOME/.config/opencode/.venv/bin/python" "$EXTRACT_PY" < "$1"; }
406
-
407
- ATTEMPT_RESULT=""
408
- ATTEMPT_DETAIL=""
409
-
410
- run_prompt_attempt() { # v idx current_bin — sets ATTEMPT_RESULT / ATTEMPT_DETAIL
411
- local v="$1" idx="$2" bin="$3" id marker verify text
412
- id="${PROMPT_IDS[$idx]}"
413
- marker="${PROMPT_MARKERS[$idx]}"
414
- verify="${PROMPT_VERIFY[$idx]}"
415
- text="${PROMPT_TEXTS[$idx]}"
416
-
417
- # Remove the probe file first so post-run verification reflects THIS run.
418
- if [ -n "$verify" ]; then
419
- rm -f "${verify%%::*}"
420
- fi
421
-
422
- local out_file err_file rc=0
423
- out_file="$(mktemp)"
424
- err_file="$(mktemp)"
425
-
426
- set +e
427
- (cd "$(project_for "$v")" \
428
- && timeout "$PANTHEON_PROMPT_TIMEOUT" "$bin" run --auto --format json "$text") \
429
- > "$out_file" 2> "$err_file"
430
- rc=$?
431
- set -e
432
-
433
- local extracted
434
- extracted="$(extract_text "$out_file" || true)"
435
- local raw
436
- raw="$( { tr '\n' ' ' < "$out_file"; tr '\n' ' ' < "$err_file"; } | cut -c1-400)"
437
- rm -f "$out_file" "$err_file"
438
-
439
- if [ "$rc" -eq 124 ]; then
440
- ATTEMPT_RESULT="FAIL"
441
- ATTEMPT_DETAIL="timeout after ${PANTHEON_PROMPT_TIMEOUT}s"
442
- elif [ "$rc" -ne 0 ]; then
443
- ATTEMPT_RESULT="FAIL"
444
- ATTEMPT_DETAIL="marker $marker absent; exit $rc; snippet: $(printf '%s' "$raw" | cut -c1-160)"
445
- elif printf '%s' "$extracted" | grep -q "$marker"; then
446
- ATTEMPT_RESULT="PASS"
447
- ATTEMPT_DETAIL="marker $marker found"
448
- elif [ -n "$verify" ] \
449
- && [ "$(cat "${verify%%::*}" 2>/dev/null)" = "${verify##*::}" ]; then
450
- ATTEMPT_RESULT="PASS"
451
- ATTEMPT_DETAIL="probe file verified: ${verify%%::*} contains ${verify##*::}"
452
- else
453
- ATTEMPT_RESULT="FAIL"
454
- ATTEMPT_DETAIL="marker $marker absent; rc=$rc; snippet: $(printf '%s' "$raw" | cut -c1-160)"
455
- fi
456
- }
457
-
458
- run_prompt() { # v idx current_bin — exactly one attempt
459
- local v="$1" idx="$2" bin="$3" id
460
- id="${PROMPT_IDS[$idx]}"
461
- run_prompt_attempt "$v" "$idx" "$bin"
462
- record "$v" "$id" "$ATTEMPT_RESULT" "$ATTEMPT_DETAIL"
463
- }
464
-
465
- check_mcp_list() { # v
466
- local v="$1" bin out connected_count rc=0
467
- if ! bin="$(sandbox_bin_v "$v")"; then
468
- record "$v" "mcp-list" "FAIL" "binary not installed in sandbox prefix"
469
- return 0
470
- fi
471
- set +e
472
- out="$(cd "$(project_for "$v")" && "$bin" mcp list 2>&1)"
473
- rc=$?
474
- set -e
475
- out="$(printf '%s' "$out" | sed -E $'s/\x1B\\[[0-?]*[ -/]*[@-~]//g')"
476
- if [ "$rc" -ne 0 ]; then
477
- record "$v" "mcp-list" "FAIL" "opencode mcp list exited $rc"
478
- return 0
479
- fi
480
- connected_count="$(printf '%s' "$out" | grep -Eic '(^|[^[:alnum:]_])connected([^[:alnum:]_]|$)')" || connected_count=0
481
- if [ "$connected_count" -eq 5 ] \
482
- && ! printf '%s' "$out" | grep -Eiq "failed|✘"; then
483
- record "$v" "mcp-list" "PASS" "$connected_count connected (expected exactly 5)"
484
- else
485
- record "$v" "mcp-list" "FAIL" "expected exactly 5 connected MCPs; found $connected_count or failures reported"
486
- fi
487
- }
488
-
489
- check_doctor() { # v
490
- local v="$1" pan rc=0
491
- if ! pan="$(sandbox_bin_for "pantheon-opencode")"; then
492
- record "$v" "doctor" "FAIL" "pantheon-opencode not installed in sandbox prefix"
493
- return 0
494
- fi
495
- set +e
496
- (cd "$(project_for "$v")" && "$pan" doctor --target "$(project_for "$v")") > /dev/null 2>&1
497
- rc=$?
498
- set -e
499
- if [ "$rc" -eq 0 ]; then
500
- record "$v" "doctor" "PASS" "exit 0"
501
- else
502
- record "$v" "doctor" "FAIL" "doctor exited $rc (blocking errors)"
503
- fi
504
- }
505
-
506
- installed_package_root() {
507
- local pan resolved
508
- if ! pan="$(sandbox_bin_for "pantheon-opencode")"; then
509
- return 1
510
- fi
511
- resolved="$(readlink -f "$pan" 2>/dev/null || true)"
512
- [ -n "$resolved" ] || return 1
513
- dirname "$(dirname "$resolved")"
514
- }
515
-
516
- run_cost_probe() { # v
517
- local v="$1" package_root probe raw status detail
518
- if ! package_root="$(installed_package_root)"; then
519
- record "$v" "pantheon-cost" "FAIL" "sandbox package is not installed"
520
- return 0
521
- fi
522
- probe="$package_root/scripts/probe-pantheon-cost.mjs"
523
- if [ ! -f "$probe" ]; then
524
- record "$v" "pantheon-cost" "FAIL" "installed package has no offline cost probe"
525
- return 0
526
- fi
527
- if ! command -v node >/dev/null 2>&1; then
528
- record "$v" "pantheon-cost" "FAIL" "node runtime is not available"
529
- return 0
530
- fi
531
- set +e
532
- raw="$(node "$probe" --version "$v" --fixture --json 2>&1)"
533
- local rc=$?
534
- set -e
535
- case "$raw" in
536
- *'"status":"PASS"'*) status="PASS" ;;
537
- *'"status":"NOT_TESTED"'*) status="FAIL" ;;
538
- *'"status":"AMBIENTAL"'*) status="FAIL" ;;
539
- *) status="FAIL" ;;
540
- esac
541
- detail="$(printf '%s' "$raw" | tr '\n' ' ' | cut -c1-400)"
542
- if [ "$rc" -ne 0 ] && [ "$status" = "PASS" ]; then
543
- status="FAIL"
544
- detail="$detail (probe exit $rc)"
545
- elif [ "$rc" -ne 0 ] && [ "$status" != "FAIL" ]; then
546
- detail="$detail (probe exit $rc)"
547
- fi
548
- record "$v" "pantheon-cost" "$status" "$detail"
549
- }
550
-
551
- run_rehydrate_probe() { # v
552
- local v="$1" package_root probe raw status detail
553
- if ! package_root="$(installed_package_root)"; then
554
- record "$v" "context-rehydrate" "FAIL" "sandbox package is not installed"
555
- return 0
556
- fi
557
- probe="$package_root/scripts/probe-context-rehydrate.mjs"
558
- if [ ! -f "$probe" ]; then
559
- record "$v" "context-rehydrate" "FAIL" "installed package has no offline context probe"
560
- return 0
561
- fi
562
- if ! command -v node >/dev/null 2>&1; then
563
- record "$v" "context-rehydrate" "FAIL" "node runtime is not available"
564
- return 0
565
- fi
566
- set +e
567
- raw="$(timeout 30 node "$probe" --version "$v" --json 2>&1)"
568
- local rc=$?
569
- set -e
570
- case "$raw" in
571
- *'"status":"PASS"'*) status="PASS" ;;
572
- *'"status":"NOT_TESTED"'*) status="FAIL" ;;
573
- *'"status":"AMBIENTAL"'*) status="FAIL" ;;
574
- *) status="FAIL" ;;
575
- esac
576
- detail="$(printf '%s' "$raw" | tr '\n' ' ' | cut -c1-400)"
577
- if [ "$rc" -eq 124 ]; then
578
- status="FAIL"
579
- detail="context probe timed out after 30s"
580
- elif [ "$rc" -ne 0 ] && [ "$status" = "PASS" ]; then
581
- # A non-zero probe exit must never be reported as PASS.
582
- status="FAIL"
583
- detail="$detail (probe exit $rc)"
584
- elif [ "$rc" -ne 0 ] && [ "$status" != "FAIL" ]; then
585
- detail="$detail (probe exit $rc)"
586
- fi
587
- record "$v" "context-rehydrate" "$status" "$detail"
588
- }
589
-
590
- run_version_prompts() { # v
591
- local v="$1" bin
592
- if ! bin="$(sandbox_bin_v "$v")"; then
593
- log "Binary '$(bin_for "$v")' not in sandbox prefix — failing all $v checks."
594
- build_battery "$v"
595
- local i
596
- for i in "${!PROMPT_IDS[@]}"; do
597
- record "$v" "${PROMPT_IDS[$i]}" "FAIL" "binary $(bin_for "$v") not installed in sandbox"
598
- done
599
- record "$v" "mcp-list" "FAIL" "binary $(bin_for "$v") not installed in sandbox"
600
- record "$v" "doctor" "FAIL" "binary $(bin_for "$v") not installed in sandbox"
601
- return 0
602
- fi
603
- prepare_project "$v"
604
- build_battery "$v"
605
- local i
606
- for i in "${!PROMPT_IDS[@]}"; do
607
- log "[$v] prompt ${PROMPT_IDS[$i]} ..."
608
- run_prompt "$v" "$i" "$bin"
609
- log "[$v] prompt ${PROMPT_IDS[$i]} → ${RESULTS["$v:${PROMPT_IDS[$i]}"]}"
610
- done
611
- check_mcp_list "$v"
612
- check_doctor "$v"
613
- }
614
-
615
- probe_verdict() { # pass total → PASS when every required check was explicitly PASS
616
- local pass="$1" total="$2"
617
- if [ "$pass" -eq "$total" ] && [ "$pass" -gt 0 ]; then
618
- printf 'PASS'
619
- else
620
- printf 'FAIL'
621
- fi
622
- }
623
-
624
- write_report() { # versions...
625
- local versions=("$@") total_fail=0 total_pass=0
626
- {
627
- printf '# Pantheon Sandbox Prompts Report\n\n'
628
- printf -- '- **Date:** %s\n' "$(date -u '+%Y-%m-%d %H:%M UTC')"
629
- printf -- '- **Model:** %s\n' "$PANTHEON_SANDBOX_MODEL"
630
- printf -- '- **Sandbox:** %s\n' "$SANDBOX_ROOT"
631
- printf -- '- **V1 binary:** %s (%s) | **V2 binary:** %s (%s)\n\n' \
632
- "$V1_BIN" "$OPENCODE_V1_SPEC" "$V2_BIN" "$OPENCODE_V2_SPEC"
633
- local v id res
634
- for v in "${versions[@]}"; do
635
- printf '## Version %s (`%s`)\n\n' "$v" "$(bin_for "$v")"
636
- printf '| Prompt | Result | Detail |\n|---|---|---|\n'
637
- for id in "${PROMPT_IDS[@]}" mcp-list doctor; do
638
- res="${RESULTS["$v:$id"]:-SKIP}"
639
- case "$res" in
640
- PASS) total_pass=$((total_pass + 1)) ;;
641
- *) total_fail=$((total_fail + 1)) ;;
642
- esac
643
- printf '| %s | %s | %s |\n' "$id" "$res" "${DETAILS["$v:$id"]:-—}"
644
- done
645
- printf '\n'
646
- done
647
- printf '## Summary\n\n'
648
- printf -- '- PASS: %d\n- Not PASS (blocking): %d\n\n' \
649
- "$total_pass" "$total_fail"
650
- printf '**Verdict: %s**\n' "$(probe_verdict "$total_pass" "$((total_pass + total_fail))")"
651
- } > "$REPORT_FILE"
652
- log "Report written to $REPORT_FILE"
653
- }
654
-
655
- write_cost_report() { # versions...
656
- local versions=("$@") total_fail=0 total_pass=0
657
- {
658
- printf '# Pantheon Cost Probe Report\n\n'
659
- printf -- '- **Date:** %s\n' "$(date -u '+%Y-%m-%d %H:%M UTC')"
660
- printf -- '- **Sandbox:** %s\n\n' "$SANDBOX_ROOT"
661
- printf '| Version | Result | Detail |\n|---|---|---|\n'
662
- local v result
663
- for v in "${versions[@]}"; do
664
- result="${RESULTS["$v:pantheon-cost"]:-NOT_TESTED}"
665
- case "$result" in
666
- PASS) total_pass=$((total_pass + 1)) ;;
667
- *) total_fail=$((total_fail + 1)) ;;
668
- esac
669
- printf '| %s | %s | %s |\n' "$v" "$result" "${DETAILS["$v:pantheon-cost"]:-—}"
670
- done
671
- printf '\n## Summary\n\n'
672
- printf -- '- PASS: %d\n- Not PASS (blocking): %d\n\n' \
673
- "$total_pass" "$total_fail"
674
- printf '**Verdict: %s**\n' "$(probe_verdict "$total_pass" "$((total_pass + total_fail))")"
675
- } > "$COST_REPORT_FILE"
676
- log "Cost probe report written to $COST_REPORT_FILE"
677
- }
678
-
679
- write_rehydrate_report() { # versions...
680
- local versions=("$@") total_fail=0 total_pass=0
681
- {
682
- printf '# Pantheon Context Rehydration Probe Report\n\n'
683
- printf -- '- **Date:** %s\n' "$(date -u '+%Y-%m-%d %H:%M UTC')"
684
- printf -- '- **Sandbox:** %s\n\n' "$SANDBOX_ROOT"
685
- printf '| Version | Probe | Result | Detail |\n|---|---|---|---|\n'
686
- local v result
687
- for v in "${versions[@]}"; do
688
- result="${RESULTS["$v:context-rehydrate"]:-NOT_TESTED}"
689
- case "$result" in
690
- PASS) total_pass=$((total_pass + 1)) ;;
691
- *) total_fail=$((total_fail + 1)) ;;
692
- esac
693
- printf '| %s | context_rehydrate + context_session_summary | %s | %s |\n' \
694
- "$v" "$result" "${DETAILS["$v:context-rehydrate"]:-—}"
695
- done
696
- printf '\n## Summary\n\n'
697
- printf -- '- PASS: %d\n- Not PASS (blocking): %d\n\n' \
698
- "$total_pass" "$total_fail"
699
- printf '**Verdict: %s**\n' "$(probe_verdict "$total_pass" "$((total_pass + total_fail))")"
700
- } > "$REHYDRATE_REPORT_FILE"
701
- log "Context probe report written to $REHYDRATE_REPORT_FILE"
702
- }
703
-
704
- run_cost() { # versions...
705
- local versions=("$@") v fail=0
706
- mkdir -p "$SANDBOX_ROOT"
707
- for v in "${versions[@]}"; do
708
- log "[$v] pantheon_cost offline probe ..."
709
- run_cost_probe "$v"
710
- log "[$v] pantheon-cost → ${RESULTS["$v:pantheon-cost"]}"
711
- done
712
- write_cost_report "${versions[@]}"
713
- for v in "${versions[@]}"; do
714
- [ "${RESULTS["$v:pantheon-cost"]:-}" = "PASS" ] || fail=$((fail + 1))
715
- done
716
- if [ "$fail" -gt 0 ]; then
717
- log "Cost probe: $fail check(s) without explicit PASS."
718
- exit 1
719
- fi
720
- log "Cost probe: PASS."
721
- }
722
-
723
- run_rehydrate() { # versions...
724
- local versions=("$@") v fail=0
725
- mkdir -p "$SANDBOX_ROOT"
726
- for v in "${versions[@]}"; do
727
- log "[$v] context_rehydrate/session_summary offline probe ..."
728
- run_rehydrate_probe "$v"
729
- log "[$v] context probe → ${RESULTS["$v:context-rehydrate"]}"
730
- done
731
- write_rehydrate_report "${versions[@]}"
732
- for v in "${versions[@]}"; do
733
- [ "${RESULTS["$v:context-rehydrate"]:-}" = "PASS" ] || fail=$((fail + 1))
734
- done
735
- if [ "$fail" -gt 0 ]; then
736
- log "Context probe: $fail check(s) without explicit PASS."
737
- exit 1
738
- fi
739
- log "Context probe: PASS."
740
- }
741
-
742
- run_battery() { # versions...
743
- local versions=("$@")
744
- mkdir -p "$SANDBOX_ROOT"
745
- write_extract_py
746
- local v
747
- for v in "${versions[@]}"; do
748
- run_version_prompts "$v"
749
- done
750
- write_report "${versions[@]}"
751
- local v fail=0 id
752
- for v in "${versions[@]}"; do
753
- for id in "${PROMPT_IDS[@]}" mcp-list doctor; do
754
- [ "${RESULTS["$v:$id"]:-}" = "PASS" ] || fail=$((fail + 1))
755
- done
756
- done
757
- if [ "$fail" -gt 0 ]; then
758
- log "Prompts battery: $fail check(s) without explicit PASS."
759
- exit 1
760
- fi
761
- log "Prompts battery: PASS."
762
- }
763
-
764
- # ── Base validation (no prompts) ──────────────────────────────────────────────
765
-
766
- run_base() { # v
767
- local v="$1" bin
768
- if ! bin="$(sandbox_bin_v "$v")"; then
769
- printf 'ERROR: sandbox not prepared for %s (binary '\''%s'\'' missing from sandbox prefix) — run %s --prepare first\n' \
770
- "$v" "$(bin_for "$v")" "$0" >&2
771
- exit 3
772
- fi
773
- prepare_project "$v"
774
- build_battery "$v"
775
- log "[$v] opencode mcp list"
776
- check_mcp_list "$v"
777
- log "[$v] mcp-list → ${RESULTS["$v:mcp-list"]}"
778
- log "[$v] doctor"
779
- check_doctor "$v"
780
- log "[$v] doctor → ${RESULTS["$v:doctor"]}"
781
- local fail=0
782
- [ "${RESULTS["$v:mcp-list"]}" = "PASS" ] || fail=$((fail + 1))
783
- [ "${RESULTS["$v:doctor"]}" = "PASS" ] || fail=$((fail + 1))
784
- if [ "$fail" -gt 0 ]; then
785
- log "Base validation $v: $fail check(s) without explicit PASS."
786
- exit 1
787
- fi
788
- log "Base validation $v: PASS."
789
- }
790
-
791
- # ── CLI ───────────────────────────────────────────────────────────────────────
792
-
793
- while [ $# -gt 0 ]; do
794
- case "$1" in
795
- --prepare) MODE_PREPARE=1 ;;
796
- --reset) MODE_RESET=1 ;;
797
- --prompts) MODE_PROMPTS=1 ;;
798
- --cost) MODE_COST=1 ;;
799
- --rehydrate) MODE_REHYDRATE=1 ;;
800
- --run)
801
- shift
802
- case "${1:-}" in
803
- v1 | v2) RUN_VERSION="$1" ;;
804
- *) usage ;;
805
- esac
806
- ;;
807
- --help | -h) usage ;;
808
- *) usage ;;
809
- esac
810
- shift
811
- done
812
-
813
- if [ "$MODE_RESET" -eq 1 ]; then
814
- cmd_reset
815
- exit 0
816
- fi
817
-
818
- if [ "$MODE_PREPARE" -eq 0 ] && [ -z "$RUN_VERSION" ] \
819
- && [ "$MODE_PROMPTS" -eq 0 ] && [ "$MODE_COST" -eq 0 ] \
820
- && [ "$MODE_REHYDRATE" -eq 0 ]; then
821
- usage
822
- fi
823
-
824
- if [ "$MODE_PREPARE" -eq 1 ]; then
825
- cmd_prepare
826
- fi
827
-
828
- if [ -n "$RUN_VERSION" ]; then
829
- if [ "$MODE_PROMPTS" -eq 1 ]; then
830
- sandbox_env
831
- run_battery "$RUN_VERSION"
832
- else
833
- sandbox_env
834
- run_base "$RUN_VERSION"
835
- fi
836
- if [ "$MODE_COST" -eq 1 ]; then
837
- sandbox_env
838
- run_cost "$RUN_VERSION"
839
- fi
840
- if [ "$MODE_REHYDRATE" -eq 1 ]; then
841
- sandbox_env
842
- run_rehydrate "$RUN_VERSION"
843
- fi
844
- elif [ "$MODE_PROMPTS" -eq 1 ]; then
845
- sandbox_env
846
- run_battery v1 v2
847
- if [ "$MODE_COST" -eq 1 ]; then
848
- run_cost v1 v2
849
- fi
850
- if [ "$MODE_REHYDRATE" -eq 1 ]; then
851
- run_rehydrate v1 v2
852
- fi
853
- elif [ "$MODE_COST" -eq 1 ]; then
854
- sandbox_env
855
- run_cost v1 v2
856
- if [ "$MODE_REHYDRATE" -eq 1 ]; then
857
- run_rehydrate v1 v2
858
- fi
859
- elif [ "$MODE_REHYDRATE" -eq 1 ]; then
860
- sandbox_env
861
- run_rehydrate v1 v2
862
- fi