Repository navigation
Expand file tree
/
Copy pathtest.sh
More file actions
executable file
·199 lines (174 loc) · 11.1 KB
/
Copy pathtest.sh
File metadata and controls
executable file
·199 lines (174 loc) · 11.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#!/usr/bin/env bash
# Every invariant here was verified to FAIL when broken. A test that can't go red
# proves nothing.
set -euo pipefail
cd "$(dirname "$0")"
n=0
fail() { echo "FAIL: $*" >&2; exit 1; }
ok() { n=$((n+1)); }
STYLE=output-styles/on-point.md
tmp=$(mktemp -d); trap 'rm -rf "$tmp"' EXIT
# ── the hook ─────────────────────────────────────────────────────────────────
# Plain stdout is CAPPED: past ~10 KB Claude Code spills the payload to a file and
# injects a 2 KB preview instead — silently, with the hook still reported as
# succeeding. Measured on 2.1.234: 10001 B inlines, 10050 B spills. The bodies are
# ~12 KB, so they MUST go out as JSON additionalContext, which has no cap.
bash hooks/inject.sh > "$tmp/hook.txt" || fail "inject.sh exited non-zero"
for section in 'ON POINT ACTIVE' 'Essence first' 'i-have-adhd' 'Say less'; do
grep -q "$section" "$tmp/hook.txt" || fail "inject.sh missing section: $section"; ok
done
# The per-prompt reinforcement must stay one line — the whole reason
# UserPromptSubmit gets --line instead of the full bodies.
[ "$(bash hooks/inject.sh --line | wc -l | tr -d ' ')" = 1 ] || fail "--line must emit exactly one line"; ok
bash hooks/inject.sh --line | grep -q 'ON POINT ACTIVE' || fail "--line emitted no marker"; ok
# A missing body degrades that axis, never the run.
mkdir -p "$tmp/personas"; cp personas/00-doctrine.md "$tmp/personas/"
CLAUDE_PLUGIN_ROOT="$tmp" bash hooks/inject.sh | grep -q 'ON POINT ACTIVE' \
|| fail "a partial personas/ should still emit what it has"; ok
if CLAUDE_PLUGIN_ROOT="$tmp" bash hooks/inject.sh | grep -q 'Say less'; then
fail "an absent body must not appear"
fi; ok
CLAUDE_PLUGIN_ROOT="$tmp/nope" bash hooks/inject.sh >/dev/null \
|| fail "a missing personas dir must still exit 0 — a broken install never breaks a session"; ok
# ── the output style: a role statement, never a second copy ───────────────────
python3 - "$STYLE" <<'PY' || fail "output-style frontmatter is invalid"
import sys
lines = open(sys.argv[1], encoding="utf-8").read().split("\n")
assert lines[0] == "---", "must open with frontmatter"
end = lines.index("---", 1)
keys = dict(l.split(":", 1) for l in lines[1:end] if ":" in l)
assert keys.get("name", "").strip() == "On Point", "name must be On Point"
assert keys.get("description", "").strip(), "description is required for the /config picker"
# Without this, selecting the style DELETES Claude Code's coding instructions.
assert keys.get("keep-coding-instructions", "").strip() == "true", "keep-coding-instructions must be true"
PY
ok
# All three source personas must be NAMED here — the style is the role statement,
# so naming two and leaving one as a description is how a surface drifts.
for behavior in 'Abstract first' 'i-have-adhd' 'Caveman when you talk' 'Never compressed'; do
grep -q "$behavior" "$STYLE" || fail "output-style missing behavior: $behavior"; ok
done
style_b=$(wc -c < "$STYLE" | tr -d ' ')
bodies_b=$(wc -c < "$tmp/hook.txt" | tr -d ' ')
[ "$style_b" -lt $((bodies_b / 2)) ] \
|| fail "output-style is ${style_b}B vs bodies ${bodies_b}B — it became a copy, so the system prompt and the tail now both carry it"; ok
# THE load-bearing invariant. Injected context is capped at ~10 KB: past that Claude
# Code writes the payload to a file and injects a 2 KB preview instead — silently,
# hook still reported as succeeding. Measured on 2.1.234: 10000 B inlines, 10050 B
# spills. JSON additionalContext hits the SAME cap (spill file …-additionalContext.txt).
# The cap is per HOOK, so splitting would raise it — at the cost of ordering, which
# came back reversed when tested. 9800 leaves headroom for the doctrine header.
[ "$bodies_b" -lt 9800 ] \
|| fail "bodies are ${bodies_b}B; past ~10000B the injection is silently truncated to a 2KB preview"; ok
# ── generated agent surfaces are in sync with personas/ ──────────────────────
./build.sh "$tmp/build" >/dev/null
stale=0
while read -r f; do
[ -f "$f" ] || { echo " missing: $f"; stale=1; continue; }
cmp -s "$f" "$tmp/build/$f" || { echo " stale: $f"; stale=1; }
done < <(./build.sh --list)
[ "$stale" = 0 ] || fail "generated surfaces differ from a fresh build — run ./build.sh"; ok
surfaces=$(./build.sh --list | wc -l | tr -d ' ')
# ── manifests and artwork parse ──────────────────────────────────────────────
python3 -c 'import json; [json.load(open(f)) for f in [
"hooks/hooks.json",".claude-plugin/plugin.json",".claude-plugin/marketplace.json",
"gemini-extension.json",".codex/hooks.json",
".codex-plugin/plugin.json",".devin-plugin/plugin.json",".qoder-plugin/plugin.json"]]' \
|| fail "invalid JSON in a manifest"; ok
# Claude Code auto-loads the standard hooks/hooks.json, so naming it in the manifest
# too is a DUPLICATE and the whole hook load fails:
# "Duplicate hooks file detected: ./hooks/hooks.json resolves to already-loaded
# file … manifest.hooks should only reference additional hook files."
# Silent: /plugin shows the plugin enabled, only `claude plugin list --json` errors.
python3 - <<'PY' || fail "a plugin manifest declares hooks wrongly"
import json, os
cc = json.load(open(".claude-plugin/plugin.json"))
assert "hooks" not in cc, (
"'.claude-plugin/plugin.json' must NOT declare hooks — hooks/hooks.json is "
"auto-loaded, and naming it again makes Claude Code drop every hook")
assert os.path.isfile("hooks/hooks.json"), "the auto-loaded hooks file is missing"
# Other hosts have no such auto-load convention, so they still need the pointer.
for m in [".codex-plugin/plugin.json", ".devin-plugin/plugin.json",
".qoder-plugin/plugin.json"]:
h = json.load(open(m)).get("hooks")
assert h, f"{m} has no hooks key — that host would inject nothing"
assert os.path.isfile(h.removeprefix("./")), f"{m} points at a missing {h}"
# Same silent-no-injection class, one layer down: the hook file's own command, and
# Gemini's context file, must exist too. Valid JSON, zero behavior, no error.
for ev in json.load(open("hooks/hooks.json"))["hooks"].values():
for group in ev:
for hook in group["hooks"]:
script = hook["command"].split("/hooks/")[-1].split()[0]
assert os.path.isfile("hooks/" + script), f"hook command missing: {script}"
assert os.path.isfile(json.load(open("gemini-extension.json"))["contextFileName"])
PY
ok
# Both Codex lifecycle hooks must reinforce the same one-line payload, and each
# command has to survive JSON quoting AND shell quoting.
for event in SessionStart UserPromptSubmit; do
codex_cmd=$(EVENT="$event" python3 -c 'import json,os;print(json.load(open(".codex/hooks.json"))["hooks"][os.environ["EVENT"]][0]["hooks"][0]["command"])')
eval "$codex_cmd" | grep -q 'ON POINT ACTIVE' \
|| fail "codex $event hook command does not run in a shell"; ok
done
for svg in assets/on-point.svg assets/banner.svg; do
python3 -c "import xml.dom.minidom; xml.dom.minidom.parse('$svg')" \
|| fail "$svg is not valid XML — GitHub renders nothing, with no error anywhere"; ok
grep -q '@keyframes' "$svg" || fail "$svg lost its animation"; ok
grep -q 'prefers-reduced-motion' "$svg" || fail "$svg must honour reduced-motion"; ok
done
grep -q 'assets/on-point.svg' README.md || fail "README does not reference the diagram"; ok
grep -q 'assets/banner.svg' README.md || fail "README does not reference the banner"; ok
# No operator identifiers anywhere in a public repo — the guard that makes the
# repo safe to publish. The needles are assembled from fragments so that this
# file does not match its own pattern.
needles="$(printf 'mi%s|kha%s|mel%s' 'thra' 'zad' 'lon')"
if grep -rIl -iE "$needles" --exclude-dir=.git . >/dev/null 2>&1; then
echo " leaked in: $(grep -rIl -iE "$needles" --exclude-dir=.git . | tr '\n' ' ')" >&2
fail "operator identifier leaked into the repo"
fi; ok
# LICENSE must hold exactly one license, or GitHub's detector gives up and the repo
# renders "license: not identifiable by github". Upstream texts live elsewhere.
[ "$(grep -c 'MIT License' LICENSE)" = 1 ] \
|| fail "LICENSE contains more than one license — GitHub cannot detect it"; ok
for who in 'Julius Brussee' 'Ayoub Ghriss'; do
grep -q "$who" LICENSES-THIRD-PARTY.md || fail "LICENSES-THIRD-PARTY.md is missing $who"; ok
done
# ── the installer, which writes into someone else's repo ─────────────────────
proj="$tmp/proj"; mkdir -p "$proj/.cursor"
printf 'MY OWN RULES\nnever delete the database.\n' > "$proj/AGENTS.md"
cp "$proj/AGENTS.md" "$tmp/agents.orig"
before=$(cd "$proj" && find . -type f | sort | xargs shasum | shasum)
./install.sh --target "$proj" --dry-run >/dev/null
[ "$before" = "$(cd "$proj" && find . -type f | sort | xargs shasum | shasum)" ] \
|| fail "--dry-run wrote something"; ok
./install.sh --target "$proj" >/dev/null
[ -f "$proj/.cursor/rules/on-point.mdc" ] || fail "detected cursor but installed nothing"; ok
if [ -d "$proj/.windsurf" ]; then fail "installed windsurf with no marker present"; fi; ok
grep -q 'never delete the database' "$proj/AGENTS.md" \
|| fail "DESTROYED the user's own AGENTS.md content"; ok
head -1 "$proj/AGENTS.md" | grep -q 'MY OWN RULES' || fail "moved the user's content"; ok
a=$(shasum < "$proj/AGENTS.md"); ./install.sh --target "$proj" >/dev/null
[ "$a" = "$(shasum < "$proj/AGENTS.md")" ] || fail "re-running the installer is not idempotent"; ok
[ "$(grep -c 'on-point:begin' "$proj/AGENTS.md")" = 1 ] || fail "duplicate spliced blocks"; ok
# The plugin's hook already injects the body; splicing CLAUDE.md too would put the
# same ~12 KB in the cached system prefix as well. A stub `claude` on PATH keeps this
# deterministic instead of depending on what is installed on the machine running it.
stub="$tmp/stub"; mkdir -p "$stub"
printf '#!/bin/sh\necho "[]"\n' > "$stub/claude"; chmod +x "$stub/claude"
dup="$tmp/dup"; mkdir -p "$dup/.claude"; printf 'MY RULES\n' > "$dup/CLAUDE.md"
PATH="$stub:$PATH" HOME="$tmp/nohome" ./install.sh --target "$dup" >/dev/null
grep -q 'on-point:begin' "$dup/CLAUDE.md" \
|| fail "no plugin present, so CLAUDE.md should carry the block"; ok
mkdir -p "$tmp/withhome/.claude/plugins/cache/on-point"
printf 'MY RULES\n' > "$dup/CLAUDE.md"
PATH="$stub:$PATH" HOME="$tmp/withhome" ./install.sh --target "$dup" >/dev/null
if grep -q 'on-point:begin' "$dup/CLAUDE.md"; then
fail "the plugin is installed — splicing CLAUDE.md doubles the same body"
fi; ok
PATH="$stub:$PATH" HOME="$tmp/withhome" ON_POINT_FORCE_CLAUDE=1 ./install.sh --target "$dup" >/dev/null
grep -q 'on-point:begin' "$dup/CLAUDE.md" || fail "the force override must still install it"; ok
./install.sh --target "$proj" --uninstall >/dev/null
cmp -s "$proj/AGENTS.md" "$tmp/agents.orig" \
|| fail "--uninstall did not restore AGENTS.md byte-for-byte"; ok
if [ -f "$proj/.cursor/rules/on-point.mdc" ]; then fail "--uninstall left a dedicated file behind"; fi; ok
echo "OK — $n invariants, $surfaces agent surfaces in sync, style is ${style_b}B vs ${bodies_b}B of rules"