pantheon-opencode 1.6.0-beta.6 → 1.6.0-beta.8

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 (54) hide show
  1. package/AGENTS.md +19 -769
  2. package/CHANGELOG.md +53 -0
  3. package/README.md +78 -9
  4. package/README.pt-BR.md +10 -4
  5. package/package.json +5 -1
  6. package/plugin.json +2 -2
  7. package/pyproject.toml +3 -1
  8. package/scripts/build-agents-md.mjs +159 -26
  9. package/scripts/install/agents-md.mjs +2 -2
  10. package/scripts/install/config-migration.mjs +115 -1
  11. package/scripts/install/interactive.mjs +1 -1
  12. package/scripts/install/opencode.mjs +245 -12
  13. package/scripts/install/shared.mjs +115 -7
  14. package/scripts/sync-artifacts.mjs +2 -2
  15. package/scripts/test-opencode-v2-sandbox.sh +155 -4
  16. package/scripts/validate-sandbox-install.mjs +138 -0
  17. package/skills-lock.json +5 -5
  18. package/src/agents/aphrodite.md +18 -36
  19. package/src/agents/demeter.md +8 -27
  20. package/src/agents/gaia.md +1 -0
  21. package/src/agents/hephaestus.md +10 -20
  22. package/src/agents/hermes.md +15 -37
  23. package/src/agents/mnemosyne.md +14 -42
  24. package/src/agents/prometheus.md +16 -19
  25. package/src/agents/talos.md +4 -1
  26. package/src/agents/themis.md +4 -4
  27. package/src/agents/zeus.md +24 -127
  28. package/src/instructions/agent-return-format.instructions.md +2 -3
  29. package/src/instructions/backend-standards.instructions.md +2 -0
  30. package/src/instructions/frontend-standards.instructions.md +3 -1
  31. package/src/instructions/memory-protocol.instructions.md +11 -121
  32. package/src/instructions/zeus-anti-stall.instructions.md +14 -69
  33. package/src/instructions/zeus-communication-rules.instructions.md +0 -1
  34. package/src/instructions/zeus-council-synthesis.instructions.md +32 -260
  35. package/src/instructions/zeus-memory-operations.instructions.md +26 -0
  36. package/src/instructions/zeus-timeout-retry.instructions.md +40 -87
  37. package/src/pantheon/v2-delegation-enforce.ts +87 -0
  38. package/src/pantheon/v2-execute-after.ts +186 -0
  39. package/src/pantheon/v2-unsupported.mjs +0 -23
  40. package/src/plugin-v2.ts +271 -36
  41. package/src/plugins/tui/dist/tui.d.ts +11 -8
  42. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  43. package/src/plugins/tui/dist/tui.js +53 -37
  44. package/src/plugins/tui/package-lock.json +30 -33
  45. package/src/plugins/tui/package.json +5 -1
  46. package/src/plugins/tui/src/index.tsx +103 -82
  47. package/src/plugins/tui/tsdown.config.ts +17 -0
  48. package/src/routing.yml +10 -5
  49. package/src/skills/README.md +3 -3
  50. package/src/skills/artifact-management/SKILL.md +12 -5
  51. package/src/skills/auto-continue/SKILL.md +37 -28
  52. package/src/skills/code-review-checklist/SKILL.md +5 -5
  53. package/src/skills/context-compression/SKILL.md +26 -879
  54. package/src/skills/tdd-with-agents/SKILL.md +18 -10
@@ -19,10 +19,10 @@
19
19
  */
20
20
  import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync } from 'node:fs'
21
21
  import { join } from 'node:path'
22
+ import { copyAgentPrompts } from './build-agents-md.mjs'
22
23
 
23
24
  import {
24
25
  collectSkillNames,
25
- copyFiles,
26
26
  installSkills,
27
27
  ROOT,
28
28
  syncDir,
@@ -59,7 +59,7 @@ export function syncCopyArtifacts(configDir) {
59
59
  const dstAgents = join(configDir, 'agents')
60
60
  if (existsSync(join(ROOT, 'src', 'agents'))) {
61
61
  mkdirSync(dstAgents, { recursive: true })
62
- bump(copyFiles(join(ROOT, 'src', 'agents'), dstAgents, false))
62
+ bump(copyAgentPrompts(join(ROOT, 'src', 'agents'), dstAgents, false))
63
63
  const routing = join(ROOT, 'src', 'routing.yml')
64
64
  if (existsSync(routing)) {
65
65
  if (
@@ -34,7 +34,7 @@
34
34
  # Env overrides:
35
35
  # PANTHEON_SANDBOX_ROOT Sandbox root (default: ~/pantheon-sandbox)
36
36
  # OPENCODE_V2_SPEC npm spec providing the V2 binary
37
- # (default: @opencode-ai/cli@beta). NOTE: this is an
37
+ # (default: @opencode/cli@latest). NOTE: this is an
38
38
  # install spec only — it is not a dependency of this
39
39
  # package, and no code imports it.
40
40
  # PANTHEON_REPO Repository the sandbox is built from (default: the
@@ -63,7 +63,7 @@ SANDBOX_ROOT="${PANTHEON_SANDBOX_ROOT:-$HOME/pantheon-sandbox}"
63
63
  SANDBOX_HOME="$SANDBOX_ROOT/home"
64
64
  NPM_PREFIX="$SANDBOX_HOME/.npm-global"
65
65
 
66
- OPENCODE_V2_SPEC="${OPENCODE_V2_SPEC:-@opencode-ai/cli@beta}"
66
+ OPENCODE_V2_SPEC="${OPENCODE_V2_SPEC:-@opencode/cli@latest}"
67
67
  PANTHEON_SANDBOX_MODEL="${PANTHEON_SANDBOX_MODEL:-opencode-go/mimo-v2.5}"
68
68
  PANTHEON_PROMPT_TIMEOUT="${PANTHEON_PROMPT_TIMEOUT:-300}"
69
69
 
@@ -418,6 +418,7 @@ V2_DB="${PANTHEON_V2_DB:-$SANDBOX_DIR/opencode-v2.db}"
418
418
  V2_PORT="${PANTHEON_V2_PORT:-49376}"
419
419
  V2_LOOPBACK_HOST="${PANTHEON_V2_HOST:-127.0.0.1}"
420
420
  V2_HANDSHAKE_TIMEOUT="${PANTHEON_V2_HANDSHAKE_TIMEOUT:-60}"
421
+ V2_MCP_LIST_TIMEOUT="${PANTHEON_V2_MCP_LIST_TIMEOUT:-15}"
421
422
  V2_SERVER_LOG="$SANDBOX_DIR/v2-server.log"
422
423
  V2_SERVICE_STATE="$SANDBOX_HOME/.local/state/opencode/service.json"
423
424
  V2_SERVER_PID=""
@@ -735,7 +736,8 @@ check_mcp() { # label binary project
735
736
  if ! wait_for_v2_mcp_registrations "$project/.opencode" "$project/.venv/bin/python3"; then
736
737
  kill "$list_pid" 2>/dev/null || true
737
738
  wait "$list_pid" 2>/dev/null || true
738
- rm -f "$list_file"
739
+ echo "--- mcp list output (preserved at $list_file) ---" >&2
740
+ cat "$list_file" >&2 || true
739
741
  record_status "$label MCP" "FAIL" "MCP registrations did not match the active sandbox"
740
742
  return 0
741
743
  fi
@@ -744,7 +746,8 @@ check_mcp() { # label binary project
744
746
  else
745
747
  kill "$list_pid" 2>/dev/null || true
746
748
  wait "$list_pid" 2>/dev/null || true
747
- rm -f "$list_file"
749
+ echo "--- mcp list output (preserved at $list_file) ---" >&2
750
+ cat "$list_file" >&2 || true
748
751
  record_status "$label MCP" "FAIL" "MCP handshakes did not become ready after mcp list started"
749
752
  return 0
750
753
  fi
@@ -809,6 +812,11 @@ if ! git -C "$REPO_DIR" ls-files --error-unmatch -- "$TGZ" >/dev/null 2>&1; then
809
812
  echo "--- Init (headless) ---"
810
813
  pantheon-opencode init --headless -y
811
814
  rewrite_v2_mcp_config
815
+ node "$REPO_DIR/scripts/validate-sandbox-install.mjs" \
816
+ --repo "$REPO_DIR" \
817
+ --install "$NPM_PREFIX/lib/node_modules/pantheon-opencode" \
818
+ --project-config "$V2_CONFIG" \
819
+ --config "$PANTHEON_GLOBAL/opencode.json"
812
820
 
813
821
  echo "--- MCP Validation ---"
814
822
  check_mcp "V2" opencode2 "$SANDBOX_DIR/project-v2"
@@ -871,6 +879,139 @@ fi
871
879
  echo "Next: open the isolated TUI with: $SANDBOX_DIR/start-pantheon.sh"
872
880
  RUNTEST
873
881
  chmod +x "$SANDBOX_ROOT/run-test.sh"
882
+
883
+ cat > "$SANDBOX_ROOT/start-pantheon.sh" <<'STARTPANTHEON'
884
+ #!/usr/bin/env bash
885
+ # Generated by pantheon-opencode scripts/test-opencode-v2-sandbox.sh --prepare
886
+ # Launches the installed OpenCode beta with only this sandbox's HOME/config/db.
887
+ set -euo pipefail
888
+
889
+ SANDBOX_DIR="$(cd "$(dirname "$0")" && pwd)"
890
+ SANDBOX_HOME="$SANDBOX_DIR/home"
891
+ NPM_PREFIX="$SANDBOX_HOME/.npm-global"
892
+ SANDBOX_VENV="$SANDBOX_HOME/.config/opencode/.venv"
893
+ V2_PORT="${PANTHEON_V2_PORT:-49376}"
894
+ if [[ ! "$V2_PORT" =~ ^[0-9]{1,5}$ ]]; then
895
+ echo "ERROR: PANTHEON_V2_PORT must be an integer from 1 through 65535 (got '$V2_PORT')" >&2
896
+ exit 1
897
+ fi
898
+ V2_PORT=$((10#$V2_PORT))
899
+ if [ "$V2_PORT" -lt 1 ] || [ "$V2_PORT" -gt 65535 ]; then
900
+ echo "ERROR: PANTHEON_V2_PORT must be an integer from 1 through 65535 (got '$V2_PORT')" >&2
901
+ exit 1
902
+ fi
903
+ if ! python3 - "$V2_PORT" "$NPM_PREFIX" <<'CHECKPORT'
904
+ import errno
905
+ import os
906
+ import socket
907
+ import sys
908
+ from urllib.request import urlopen
909
+
910
+ port = int(sys.argv[1])
911
+ cli_prefix = os.path.realpath(
912
+ os.path.join(sys.argv[2], "lib", "node_modules", "@opencode", "cli")
913
+ )
914
+ try:
915
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as probe:
916
+ # A just-stopped service can leave a harmless TIME_WAIT socket behind.
917
+ # SO_REUSEADDR permits the new service to bind that port without
918
+ # masking a live listener or an unrelated server.
919
+ probe.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
920
+ probe.bind(("127.0.0.1", port))
921
+ except OSError as exc:
922
+ if exc.errno != errno.EADDRINUSE:
923
+ print(f"ERROR: cannot reserve dedicated V2 port 127.0.0.1:{port}: {exc}", file=sys.stderr)
924
+ raise SystemExit(1)
925
+
926
+ # OpenCode intentionally keeps its managed service alive after the TUI exits.
927
+ # Reuse it only when /proc proves the listener is this sandbox's CLI binary.
928
+ inodes = set()
929
+ for table in ("/proc/net/tcp", "/proc/net/tcp6"):
930
+ try:
931
+ with open(table, encoding="ascii") as entries:
932
+ next(entries, None)
933
+ for line in entries:
934
+ fields = line.split()
935
+ if len(fields) >= 10 and int(fields[1].rsplit(":", 1)[1], 16) == port and fields[3] == "0A":
936
+ inodes.add(fields[9])
937
+ except OSError:
938
+ pass
939
+
940
+ listener_pids = set()
941
+ for pid in (entry for entry in os.listdir("/proc") if entry.isdigit()):
942
+ fd_dir = f"/proc/{pid}/fd"
943
+ try:
944
+ for fd in os.listdir(fd_dir):
945
+ try:
946
+ target = os.readlink(os.path.join(fd_dir, fd))
947
+ except OSError:
948
+ continue
949
+ if target.startswith("socket:[") and target[8:-1] in inodes:
950
+ listener_pids.add(pid)
951
+ break
952
+ except OSError:
953
+ continue
954
+
955
+ owns_listener = False
956
+ for pid in listener_pids:
957
+ try:
958
+ with open(f"/proc/{pid}/cmdline", "rb") as command_line:
959
+ args = [arg.decode(errors="replace") for arg in command_line.read().split(b"\0") if arg]
960
+ except OSError:
961
+ continue
962
+ executable = os.path.realpath(args[0]) if args else ""
963
+ if (
964
+ executable.startswith(cli_prefix + os.sep)
965
+ and "serve" in args
966
+ and "--service" in args
967
+ and len(listener_pids) == 1
968
+ ):
969
+ owns_listener = True
970
+ break
971
+
972
+ healthy = False
973
+ if owns_listener:
974
+ try:
975
+ scheme = "http"
976
+ loopback = ".".join(("127", "0", "0", "1"))
977
+ with urlopen(f"{scheme}://{loopback}:{port}/global/health", timeout=2) as response:
978
+ healthy = response.status == 200
979
+ except Exception:
980
+ pass
981
+
982
+ if not healthy:
983
+ print(
984
+ f"ERROR: dedicated V2 port 127.0.0.1:{port} is occupied by a different or unverifiable service; no service was stopped",
985
+ file=sys.stderr,
986
+ )
987
+ raise SystemExit(1)
988
+ print(f"Reusing the existing beta sandbox OpenCode service on 127.0.0.1:{port} (PID {next(iter(listener_pids))}).")
989
+ CHECKPORT
990
+ then
991
+ exit 1
992
+ fi
993
+
994
+ export HOME="$SANDBOX_HOME"
995
+ export PATH="$NPM_PREFIX/bin:$SANDBOX_VENV/bin:$PATH"
996
+ export npm_config_prefix="$NPM_PREFIX"
997
+ export XDG_CONFIG_HOME="$SANDBOX_HOME/.config"
998
+ export XDG_CONFIG_DIRS="$SANDBOX_HOME/.config/xdg"
999
+ export XDG_DATA_HOME="$SANDBOX_HOME/.local/share"
1000
+ export XDG_DATA_DIRS="$SANDBOX_HOME/.local/share/xdg"
1001
+ export XDG_STATE_HOME="$SANDBOX_HOME/.local/state"
1002
+ export XDG_CACHE_HOME="$SANDBOX_HOME/.cache"
1003
+ export OPENCODE_CONFIG_DIR="$SANDBOX_DIR/project-v2"
1004
+ export OPENCODE_DB="${PANTHEON_V2_DB:-$SANDBOX_DIR/opencode-v2.db}"
1005
+ export PANTHEON_V2_PORT="$V2_PORT"
1006
+ export PORT="$PANTHEON_V2_PORT"
1007
+ unset OPENCODE_CONFIG OPENCODE_CONFIG_CONTENT OPENCODE_CONFIG_PROJECT_DISABLE \
1008
+ OPENCODE_DATA_DIR OPENCODE_STATE_DIR OPENCODE_CACHE_DIR OPENCODE_STORAGE_PATH
1009
+
1010
+ "$NPM_PREFIX/bin/opencode2" service set port "$V2_PORT"
1011
+ cd "$SANDBOX_DIR/project-v2"
1012
+ exec "$NPM_PREFIX/bin/opencode2" "$@"
1013
+ STARTPANTHEON
1014
+ chmod +x "$SANDBOX_ROOT/start-pantheon.sh"
874
1015
  }
875
1016
 
876
1017
  # ── Reset / Prepare ───────────────────────────────────────────────────────────
@@ -990,6 +1131,7 @@ prepare_project() {
990
1131
  (cd "$dir" && "$pan" init --project --version "$TARGET_VERSION" --model "$PANTHEON_SANDBOX_MODEL" -y) \
991
1132
  || die "init --project --version $TARGET_VERSION failed in $dir"
992
1133
  rewrite_v2_mcp_config
1134
+ validate_sandbox_install
993
1135
  }
994
1136
 
995
1137
  # The installer merges an existing project config. A reused sandbox can
@@ -1077,6 +1219,15 @@ for name, script in managed.items():
1077
1219
  PY
1078
1220
  }
1079
1221
 
1222
+ validate_sandbox_install() {
1223
+ node "$REPO_DIR/scripts/validate-sandbox-install.mjs" \
1224
+ --repo "$REPO_DIR" \
1225
+ --install "$NPM_PREFIX/lib/node_modules/pantheon-opencode" \
1226
+ --project-config "$V2_CONFIG" \
1227
+ --config "$SANDBOX_HOME/.config/opencode/opencode.json" \
1228
+ || die "sandbox package/config validation failed"
1229
+ }
1230
+
1080
1231
  cmd_prepare() {
1081
1232
  mkdir -p "$SANDBOX_HOME" "$NPM_PREFIX"
1082
1233
  write_run_test_sh
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env node
2
+ import { createHash } from 'node:crypto'
3
+ import { readFileSync } from 'node:fs'
4
+ import { join, resolve } from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
6
+
7
+ const PACKAGE_REF = /^(?:npm:)?pantheon-opencode(?:@[^/]+)?(?:\/(?:plugin|plugin-v2))?$/
8
+ export const SANDBOX_SOURCE_FILES = [
9
+ 'bin/pantheon-init.mjs',
10
+ 'scripts/install/config-migration.mjs',
11
+ 'scripts/install/opencode.mjs',
12
+ 'scripts/validate-sandbox-install.mjs',
13
+ 'src/plugin-v2.ts',
14
+ ]
15
+
16
+ function readJson(path, label) {
17
+ try {
18
+ return JSON.parse(readFileSync(path, 'utf8'))
19
+ } catch (error) {
20
+ throw new Error(`cannot read ${label} at ${path}: ${error.message}`)
21
+ }
22
+ }
23
+
24
+ function pluginReferences(config) {
25
+ const refs = []
26
+ for (const key of ['plugin', 'plugins']) {
27
+ const value = config?.[key]
28
+ const entries = Array.isArray(value) ? value : value === undefined ? [] : [value]
29
+ for (const entry of entries) {
30
+ if (typeof entry === 'string') refs.push(entry)
31
+ else if (entry && typeof entry === 'object' && !Array.isArray(entry)) {
32
+ for (const field of ['package', 'id', 'name', 'path', 'source']) {
33
+ if (typeof entry[field] === 'string') refs.push(entry[field])
34
+ }
35
+ }
36
+ }
37
+ }
38
+ return refs
39
+ }
40
+
41
+ /**
42
+ * Prove that the sandbox is executing the package built from this checkout and
43
+ * that the project config cannot silently load an older npm-cached Pantheon.
44
+ */
45
+ export function validateSandboxInstall({ repoDir, installDir, projectConfig, configPaths = [] }) {
46
+ const sourcePackagePath = join(resolve(repoDir), 'package.json')
47
+ const installedPackagePath = join(resolve(installDir), 'package.json')
48
+ const sourcePackage = readJson(sourcePackagePath, 'checkout package manifest')
49
+ const installedPackage = readJson(installedPackagePath, 'sandbox package manifest')
50
+ if (sourcePackage.version !== installedPackage.version) {
51
+ throw new Error(
52
+ `sandbox package version ${installedPackage.version} does not match checkout ${sourcePackage.version}`,
53
+ )
54
+ }
55
+
56
+ const sourceHash = createHash('sha256')
57
+ for (const relativePath of SANDBOX_SOURCE_FILES) {
58
+ let source
59
+ let installed
60
+ try {
61
+ source = readFileSync(join(resolve(repoDir), relativePath))
62
+ installed = readFileSync(join(resolve(installDir), relativePath))
63
+ } catch (error) {
64
+ throw new Error(`cannot compare package source ${relativePath}: ${error.message}`)
65
+ }
66
+ if (!source.equals(installed)) {
67
+ throw new Error(`installed package source differs from checkout: ${relativePath}`)
68
+ }
69
+ sourceHash.update(relativePath).update('\0').update(installed).update('\0')
70
+ }
71
+
72
+ const expectedPluginPath = resolve(installDir, 'src', 'plugin-v2')
73
+ const allConfigPaths = [...new Set([projectConfig, ...configPaths].map((path) => resolve(path)))]
74
+ let activeProjectPluginCount = 0
75
+ for (const configPath of allConfigPaths) {
76
+ const config = readJson(configPath, 'active OpenCode config')
77
+ if (!config || typeof config !== 'object' || Array.isArray(config)) {
78
+ throw new Error(`active OpenCode config must be an object: ${configPath}`)
79
+ }
80
+ for (const ref of pluginReferences(config)) {
81
+ const normalized = ref.replaceAll('\\', '/').replace(/\/$/, '')
82
+ if (PACKAGE_REF.test(normalized)) {
83
+ throw new Error(`stale Pantheon package reference in ${configPath}: ${ref}`)
84
+ }
85
+ if (resolve(ref) === expectedPluginPath) {
86
+ if (configPath === resolve(projectConfig)) activeProjectPluginCount += 1
87
+ }
88
+ }
89
+ }
90
+ if (activeProjectPluginCount !== 1) {
91
+ throw new Error(
92
+ `project config must reference the sandbox V2 plugin exactly once; found ${activeProjectPluginCount}: ${resolve(projectConfig)}`,
93
+ )
94
+ }
95
+
96
+ return {
97
+ status: 'PASS',
98
+ version: installedPackage.version,
99
+ sourceSha256: sourceHash.digest('hex'),
100
+ }
101
+ }
102
+
103
+ function parseArgs(args) {
104
+ const options = { configPaths: [] }
105
+ for (let i = 0; i < args.length; i += 1) {
106
+ const arg = args[i]
107
+ if (arg === '--config') options.configPaths.push(args[++i])
108
+ else if (['--repo', '--install', '--project-config'].includes(arg))
109
+ options[arg.slice(2).replace('-', '')] = args[++i]
110
+ else throw new Error(`unknown argument: ${arg}`)
111
+ }
112
+ for (const required of ['repo', 'install', 'projectconfig']) {
113
+ if (!options[required])
114
+ throw new Error(
115
+ `missing required option --${required.replace('projectconfig', 'project-config')}`,
116
+ )
117
+ }
118
+ return {
119
+ repoDir: options.repo,
120
+ installDir: options.install,
121
+ projectConfig: options.projectconfig,
122
+ configPaths: options.configPaths,
123
+ }
124
+ }
125
+
126
+ function main() {
127
+ try {
128
+ const result = validateSandboxInstall(parseArgs(process.argv.slice(2)))
129
+ process.stdout.write(
130
+ `Sandbox install proof: ${result.status} (version ${result.version}, source sha256 ${result.sourceSha256})\n`,
131
+ )
132
+ } catch (error) {
133
+ process.stderr.write(`Sandbox install proof: FAIL — ${error.message}\n`)
134
+ process.exitCode = 1
135
+ }
136
+ }
137
+
138
+ if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) main()
package/skills-lock.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "src/skills/agent-coordination/SKILL.md": "cfd040ef29e3dd0fd5e0e67773874facf7c06e3284898afe1fddba4456c3f1aa",
3
- "src/skills/artifact-management/SKILL.md": "c60e493666bedf46e9113d0dd20106489d5c5a73905e1370fcfc1c0d71c59185",
4
- "src/skills/auto-continue/SKILL.md": "a7a4ec7ab35970bec36bcc286b95881b43a75e3bcdb626a17ebb9e397dd1a708",
3
+ "src/skills/artifact-management/SKILL.md": "91d68c8f2d1b642725adfc6df11e55865a8491aca690dc27d02ea7c778d49d41",
4
+ "src/skills/auto-continue/SKILL.md": "79aa1786ab62332abc45986d147ee944836e6f7a496c289e793639add4211229",
5
5
  "src/skills/clonedeps/SKILL.md": "3e0b43cf96da98c83699dc48db3fd58fbfda84b9022bb70d3747875c81c3e124",
6
- "src/skills/code-review-checklist/SKILL.md": "0e59367c65ef4608db80a0674279f32cfc3f67dca7236f233b61a47fe506579f",
6
+ "src/skills/code-review-checklist/SKILL.md": "6445513ab880efdb1005861ae13cb9a215f80b9d260f6278499f60771e07858c",
7
7
  "src/skills/codemap/SKILL.md": "87af5271e1576e154cadff313eab16264b726e43d094520736b7a5b03b409a4a",
8
- "src/skills/context-compression/SKILL.md": "9c65c132beb0dc7bd20335cfd7f41c589f5168a72dcf5d51740bc66f2865e027",
8
+ "src/skills/context-compression/SKILL.md": "346ed8697b8db42cc49403ee3dd38f9b775fe93cb55395d73c81b55cc77442d6",
9
9
  "src/skills/git-workflow-and-versioning/SKILL.md": "685a94041f1b4ce2a430301f517b89102055696267c369a7e8fb191606659276",
10
10
  "src/skills/incremental-implementation/SKILL.md": "7065ddb45da3c6b6751de07f290e92e6cb072e949a2e3aaae13ee7762f0a70fc",
11
11
  "src/skills/loop-engineering/SKILL.md": "f804e545821b9cca8fe0ec517307ed902446f28c2ca8ff9194c0f987cf7229e3",
@@ -15,7 +15,7 @@
15
15
  "src/skills/session-goal/SKILL.md": "793498265f70253c20524f6adc88bcc86db11d7160fe8232a26aedc6b1c5489f",
16
16
  "src/skills/simplify/SKILL.md": "aa739e9f75962a77d6574557d674ea01b5aea95e580b721d66c058753161b053",
17
17
  "src/skills/spec-driven-development/SKILL.md": "e93b9103d6cd1848ab01328efde82c1daf564d1cabbdc2278254b346fcf55d02",
18
- "src/skills/tdd-with-agents/SKILL.md": "9880919a46b74f549f948147d8b086b008635de94fa259f76261d067772bb8e3",
18
+ "src/skills/tdd-with-agents/SKILL.md": "9d20607ea34fc3e02c7e3ef5186b103d84196bd9a13aaadd55a44f41339125da",
19
19
  "src/skills/verification-planning/SKILL.md": "14186446ef51e1ba2c87b337e8d5f86e566d805156ab21fba2a75f8c4a99df3f",
20
20
  "src/skills/visual-review-pipeline/SKILL.md": "f6e65ff75a9325c38e0e9dde8e87f09b873e14e490936ef48aa80201bb68fe10",
21
21
  "src/skills/worktrees/SKILL.md": "0033c5f8a50f210f31f0256ba8cc0fd99c65674a2aabedb05d8e69447b5ec218"
@@ -23,6 +23,7 @@ mcp_tools:
23
23
  pantheon-resources: all
24
24
  pantheon-memory: [memory_search]
25
25
  pantheon-code-mode: [execute_code_script]
26
+ pantheon-vision: [vision_describe, vision_ocr, vision_analyze]
26
27
  ---
27
28
 
28
29
  ## When NOT to Use Aphrodite
@@ -37,7 +38,7 @@ You are a frontend implementation specialist. You BUILD UI. You do NOT design ar
37
38
 
38
39
  **You MUST:**
39
40
  - Implement React components with TypeScript strict mode
40
- - Follow TDD: write failing test → minimal code → refactor
41
+ - For testable behavior changes, follow RED→GREEN→REFACTOR; use focused verification for non-behavioral edits
41
42
  - Ensure WCAG AA accessibility on every component
42
43
  - Use mobile-first responsive design
43
44
 
@@ -50,17 +51,17 @@ You are a frontend implementation specialist. You BUILD UI. You do NOT design ar
50
51
  ## Workflow
51
52
 
52
53
  ### Before Implementation
53
- 1. If codebase is unfamiliar → delegate discovery to @apollo: "Find all existing components related to [feature]"
54
- 2. Read relevant instruction files: frontend-standards; load `skill: visual-review-pipeline` when doing UI visual review
55
- 3. Plan component tree and data flow before writing code
54
+ 1. Inspect relevant component/test/API files directly; use @apollo only when broad or unfamiliar discovery materially reduces risk
55
+ 2. Read relevant frontend standards; load `skill: visual-review-pipeline` only when visual behavior changed
56
+ 3. Plan component/data flow when scope or risk warrants it; do not require a design phase for a bounded fix
56
57
 
57
58
  ### Implementation (TDD)
58
59
  See `skill: tdd-with-agents` for the full TDD cycle.
59
60
 
60
61
  ### Post-Implementation
61
- 1. Self-review via Playwright screenshots (max 3 iterations)
62
- 2. Send to @themis for quality gate review
63
- 3. Report: "Frontend implementation complete. Components: [list]. Tests: [count]. Coverage: [%]."
62
+ 1. Verify the changed behavior with focused tests; use Playwright screenshots when the change affects visible layout or interaction
63
+ 2. Send auth/security-sensitive or material UI changes to @themis; a trivial isolated edit needs no separate review phase
64
+ 3. Report changed components and checks run; report coverage only when measured and relevant
64
65
 
65
66
  ## Anti-Stall Rules
66
67
 
@@ -73,12 +74,9 @@ See `skill: tdd-with-agents` for the full TDD cycle.
73
74
  | 3 turns no progress | No new code or test in 3 turns | Output \`[APHRODITE_STALL]\`. Escalate to @zeus with: "Stuck on [component]. Last progress: [description]." |
74
75
 
75
76
  ## Pre-Implementation Recall
76
- Before implementing a frontend feature:
77
- 1. Run: @mnemosyne Recall "<feature>" --top-k 3 --agent aphrodite
78
- 2. Review past UI patterns and component decisions
79
- 3. Check for existing similar implementations
77
+ Use relevant supplied memory/ADR context when available. Inspect nearby components for reuse; do not block a bounded fix on a separate recall or broad discovery task.
80
78
 
81
- ## Visual Review Pipeline
79
+ ## Visual Review Pipeline (when visual behavior changes)
82
80
 
83
81
  After implementing UI components:
84
82
  1. Capture screenshot via Playwright: `browser_navigate` to component, `browser_screenshotPage`
@@ -88,41 +86,25 @@ After implementing UI components:
88
86
 
89
87
  ## Handoff Rules
90
88
 
91
- - **To @apollo:** "Find all [component/files] related to [feature]. Return paths and summaries."
92
- - **To @themis:** After implementation: "Review my frontend changes. Files: [list]. Run Biome + accessibility checks."
89
+ - **To @apollo:** For broad/unfamiliar discovery only; otherwise inspect the relevant local files.
90
+ - **To @themis:** For auth/security-sensitive or material UI changes; include focused accessibility and behavior checks.
93
91
  - **To @zeus:** Only for escalations (stuck, conflicting requirements, scope change)
94
92
 
95
93
  ## Efficiency Rules
96
94
 
97
- - Delegate codebase discovery to @apollo — do NOT grep/glob yourself
95
+ - Search/read relevant files directly; delegate broad discovery to @apollo only when useful
98
96
  - Use Context7 only for React/Next.js/TypeScript library docs
99
- - Run `npm test` after every component, not just at the end
100
- - Never read more than 3 files for context without delegating to @apollo
97
+ - Run focused tests for each changed behavior; run the broader suite when the change crosses integration boundaries or risk warrants it
98
+ - Read only as much context as the task needs; a fixed file-count limit must not trigger unnecessary delegation
101
99
 
102
100
  ## Auto-Continue (Embedded: UI TDD Cycles)
103
101
 
104
- - Auto-continue through component test cycles (RED→GREEN→REFACTOR)
105
- - Visual review checkpoint every iteration — capture screenshot via Playwright
102
+ - Auto-continue through relevant component test cycles (RED→GREEN→REFACTOR)
103
+ - Capture screenshots only for changes to visual layout or interaction, not every test iteration
106
104
  - After max 3 visual review iterations, stop for accessibility audit
107
- - Stop for Themis review after all component tests pass
105
+ - Stop for required Themis review on sensitive/material changes
108
106
  - Do NOT auto-continue on visual regression — stop and diagnose
109
107
  - Partial results NOT allowed — must complete or fail
110
108
 
111
- ## Inline Compression
112
-
113
- Compress working context with the `context-compression` skill (L1, Pantheon-native) when:
114
- - > Inline compression: See `skill: context-compression` (C8, C9, C11)
115
-
116
- **How**: call `execute_code_script("compress-inline.py", args=["compress", "--text", "<content>"])`. Use `score` to preview priority, `batch` for multiple files. See the `context-compression` skill for the full protocol.
117
-
118
- **Note**: scrubbing is automatic in the MCP layer; never embed raw secrets in the `--text` argument beyond what the tool scrubs.
119
-
120
109
  ## Skills
121
110
  Frontend: `tdd-with-agents`, `visual-review-pipeline`, `incremental-implementation`
122
-
123
-
124
- ## Session Context Retrieval
125
- When dispatched by Zeus, call context_get(slug=slug, key="latest", session_id=SESSION_ID)
126
- if session_slug is provided in dispatch metadata. Apply any "remaining_tasks",
127
- "current_phase", or "gotchas" from the retrieved context.
128
- If context_get returns None, proceed fresh (first phase or expired session).
@@ -45,24 +45,21 @@ You are a database specialist. You design schemas, write migrations, and optimiz
45
45
  ## Workflow
46
46
 
47
47
  ### Before Migration
48
- 1. If schema is unfamiliar → delegate discovery to @apollo: "Find all existing models and migrations related to [entity]"
49
- 2. Read existing models to understand relationships
48
+ 1. Inspect relevant schema/migrations directly; use @apollo only when the schema is broad or unfamiliar enough that parallel discovery reduces risk
49
+ 2. Read the relevant model/migration context to understand relationships
50
50
  3. Plan migration: what changes, impact on existing data, rollback strategy
51
51
 
52
52
  ### Migration Development (TDD)
53
53
  See `skill: tdd-with-agents` for the full TDD cycle.
54
54
 
55
- ### Post-Migration
55
+ ### Post-Migration (required for schema/data changes)
56
56
  1. Run EXPLAIN on new queries to verify index usage
57
57
  2. Check for N+1 patterns in any new relationships
58
58
  3. Send to @themis for quality gate review
59
59
  4. Report: "Migration complete. Tables: [list]. Indexes: [list]. Rollback tested: [OK]."
60
60
 
61
61
  ## Pre-Migration Recall
62
- Before creating a new migration:
63
- 1. Run: @mnemosyne Recall "<schema change>" --top-k 3 --agent demeter
64
- 2. Review past migration patterns and rollback strategies
65
- 3. Check for existing schema decisions in ADRs
62
+ Use supplied ADR/memory context when relevant. For every schema/data migration, document impact and rollback and keep both upgrade/downgrade verification and Themis review; do not require a separate recall task when context is already available.
66
63
 
67
64
  ## Anti-Stall Rules
68
65
 
@@ -82,36 +79,20 @@ Before creating a new migration:
82
79
 
83
80
  ## Efficiency Rules
84
81
 
85
- - Delegate codebase discovery to @apollo — do NOT grep/glob yourself
82
+ - Inspect the relevant schema directly; delegate only broad/unfamiliar discovery that materially reduces migration risk
86
83
  - Use Context7 only for SQLAlchemy/Alembic/PostgreSQL library docs
87
84
  - Always write the rollback BEFORE testing the upgrade
88
- - Never read more than 3 model files without delegating to @apollo
85
+ - Read the model/migration files needed to establish affected relationships; do not delegate solely to satisfy an arbitrary file-count limit
89
86
  - Batch multiple related schema changes into ONE migration (not one per column)
90
87
 
91
88
  ## Auto-Continue (Embedded: Migration Cycles)
92
89
 
93
- - Auto-continue through migration + downgrade tests (upgrade → verify → downgrade → verify)
94
- - Checkpoint after each migration test cycle — run `pantheon-code-mode execute_code_script checkpoint_session.py save demeter`
90
+ - Auto-continue through migration + downgrade tests for an authorized schema change (upgrade → verify → downgrade → verify)
91
+ - Do not require a checkpoint script for a one-off command; checkpoint only long-running/multi-phase work when context-loss risk warrants it
95
92
  - Stop for data integrity review before finalizing
96
93
  - Do NOT auto-continue when migration fails — stop and diagnose
97
94
  - Always test both upgrade AND downgrade before marking complete
98
95
  - Partial results NOT allowed — must complete or fail
99
96
 
100
- ## Inline Compression
101
-
102
- Compress working context with the `context-compression` skill (L1, Pantheon-native) when:
103
- - > Inline compression: See `skill: context-compression` (C8, C9, C11)
104
-
105
- **How**: call `execute_code_script("compress-inline.py", args=["compress", "--text", "<content>"])`. Use `score` to preview priority, `batch` for multiple files. See the `context-compression` skill for the full protocol.
106
-
107
- **Note**: scrubbing is automatic in the MCP layer; never embed raw secrets in the `--text` argument beyond what the tool scrubs.
108
-
109
97
  ## Skills
110
98
  `tdd-with-agents`, `incremental-implementation`
111
-
112
-
113
- ## Session Context Retrieval
114
- When dispatched by Zeus, call context_get(slug=slug, key="latest", session_id=SESSION_ID)
115
- if session_slug is provided in dispatch metadata. Apply any "remaining_tasks",
116
- "current_phase", or "gotchas" from the retrieved context.
117
- If context_get returns None, proceed fresh (first phase or expired session).
@@ -22,6 +22,7 @@ mcp_tools:
22
22
  pantheon-resources: all
23
23
  pantheon-memory: [memory_recall]
24
24
  pantheon-code-mode: []
25
+ pantheon-vision: [vision_describe, vision_ocr, vision_analyze]
25
26
  ---
26
27
 
27
28
  ## Core Capabilities
@@ -42,29 +42,19 @@ mcp_tools:
42
42
  - Guardrails and safety checks
43
43
 
44
44
  ## Handoffs
45
- - **@apollo**: For RAG research and library patterns
46
- - **@themis**: For code review after implementation
45
+ - **@apollo**: For broad/unfamiliar RAG research or library patterns when direct local inspection is insufficient
46
+ - **@themis**: For auth/security-sensitive or material pipeline changes
47
+
48
+ ## Proportional Execution
49
+
50
+ - Inspect only the relevant chain/config/tests; implement a clear bounded task directly without a mandatory planning or discovery phase.
51
+ - Delegate research only when external or broad context is genuinely needed; verify changed behavior with focused tests/evaluation, not a full pipeline for an unrelated micro-edit.
52
+ - Preserve review and human approval for auth/security, data-integrity, production-impacting, destructive, or global changes. Full-auto cannot authorize those actions.
47
53
 
48
54
  ## Auto-Continue (Embedded: Pipeline)
49
55
 
50
- - Auto-continue through RAG pipeline stages (chunking → embedding → retrieval → evaluation)
51
- - Checkpoint after each pipeline component — run `pantheon-code-mode execute_code_script checkpoint_session.py save hephaestus`
56
+ - Auto-continue through authorized pipeline stages when the task requires them; do not run unrelated stages for a bounded fix
57
+ - Do not require a checkpoint script for a one-off command; checkpoint only long-running/multi-phase work when context-loss risk warrants it
52
58
  - Stop for evaluation before marking pipeline as production-ready
53
59
  - If a stage fails, stop and diagnose — re-run with adjusted parameters
54
60
  - Partial results NOT allowed — pipeline must be verified end-to-end
55
-
56
- ## Inline Compression
57
-
58
- Compress working context with the `context-compression` skill (L1, Pantheon-native) when:
59
- - > Inline compression: See `skill: context-compression` (C8, C9, C11)
60
-
61
- **How**: call `execute_code_script("compress-inline.py", args=["compress", "--text", "<content>"])`. Use `score` to preview priority, `batch` for multiple files. See the `context-compression` skill for the full protocol.
62
-
63
- **Note**: scrubbing is automatic in the MCP layer; never embed raw secrets in the `--text` argument beyond what the tool scrubs.
64
-
65
-
66
- ## Session Context Retrieval
67
- When dispatched by Zeus, call context_get(slug=slug, key="latest", session_id=SESSION_ID)
68
- if session_slug is provided in dispatch metadata. Apply any "remaining_tasks",
69
- "current_phase", or "gotchas" from the retrieved context.
70
- If context_get returns None, proceed fresh (first phase or expired session).