@oneie/claude 0.6.0 → 0.7.0
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.
- package/agents/w1-recon.md +9 -4
- package/agents/w2-decide.md +51 -28
- package/agents/w3-edit.md +70 -78
- package/agents/w4-verify.md +164 -69
- package/commands/browser.md +98 -35
- package/commands/cc-connect.md +6 -0
- package/commands/chat.md +13 -1
- package/commands/close.md +45 -19
- package/commands/create.md +20 -10
- package/commands/db-sync.md +5 -1
- package/commands/deploy.md +174 -87
- package/commands/do-autonomous.md +31 -20
- package/commands/do-improve.md +4 -4
- package/commands/do-show.md +4 -3
- package/commands/do.md +53 -13
- package/commands/go.md +75 -0
- package/commands/improve.md +4 -2
- package/commands/kill.md +6 -8
- package/commands/notify.md +15 -2
- package/commands/oo-push.md +24 -9
- package/commands/rag.md +6 -0
- package/commands/release.md +46 -25
- package/commands/restart.md +5 -4
- package/commands/see.md +45 -35
- package/commands/skill-create.md +38 -5
- package/commands/sync.md +21 -11
- package/hooks/scripts/auto-continue.sh +70 -0
- package/hooks/scripts/branch-pin.sh +85 -0
- package/hooks/scripts/git-add-guard.sh +16 -5
- package/hooks/scripts/post-edit-check.sh +16 -0
- package/hooks/scripts/session-start.sh +13 -8
- package/hooks/scripts/sync-priority-todo.sh +5 -0
- package/package.json +1 -1
- package/rules/api.md +9 -0
- package/rules/design.md +13 -3
- package/rules/documentation.md +30 -71
- package/rules/engine.md +8 -1
- package/rules/ui.md +5 -1
- package/scripts/__pycache__/do-rank.cpython-313.pyc +0 -0
- package/scripts/browser-check.mjs +44 -103
- package/scripts/cc-events-proof.sh +13 -12
- package/scripts/chrome.mjs +381 -0
- package/scripts/do-analyze.sh +109 -4
- package/scripts/do-auto.sh +350 -43
- package/scripts/do-consumer-sweep.sh +72 -0
- package/scripts/do-derives-check.sh +88 -0
- package/scripts/do-fleet.sh +50 -1
- package/scripts/do-killswitch-audit.py +33 -14
- package/scripts/do-promise-lint.sh +150 -4
- package/scripts/do-promise-settle.sh +131 -9
- package/scripts/do-prove.sh +197 -17
- package/scripts/do-rank.py +606 -20
- package/scripts/do-rubric.py +21 -2
- package/scripts/do-signal.sh +157 -17
- package/scripts/do-smoke.sh +9 -0
- package/scripts/do-substrate-check.sh +49 -0
- package/scripts/do-tasks-wire-check.sh +81 -0
- package/scripts/do-tier.sh +90 -5
- package/scripts/do-ui-gate.sh +332 -0
- package/scripts/do-untracked-gate.sh +231 -0
- package/scripts/do-walk.sh +344 -0
- package/scripts/factory-check.sh +747 -0
- package/scripts/factory-repo.sh +1361 -0
- package/scripts/factory-tasks-check.sh +85 -0
- package/scripts/outcome-pull.ts +279 -0
- package/scripts/promise-manifest.mjs +167 -0
- package/scripts/reconcile-allow.txt +5 -0
- package/scripts/rubric-weights.json +64 -0
- package/scripts/spine-canary.sh +20 -0
- package/scripts/typedb-cluster-status.sh +128 -0
- package/scripts/typedb-env.sh +182 -0
- package/scripts/typedb-flap-recorder.sh +85 -0
- package/scripts/typedb-probes/containment-probe.py +88 -0
- package/scripts/typedb-probes/panic-probe-version.py +92 -0
- package/scripts/typedb-probes/panic-probe.py +77 -0
- package/scripts/typedb-scratch.sh +73 -0
- package/scripts/urls-lint.sh +58 -0
- package/scripts/w4-rubric.ts +96 -12
- package/scripts/wf-check.mjs +75 -0
- package/skills/ai-ui/SKILL.md +1 -1
- package/skills/astro/SKILL.md +177 -132
- package/skills/astro/add-content-collection.md +29 -13
- package/skills/astro/check-build.md +19 -13
- package/skills/astro/create-component.md +36 -9
- package/skills/astro/create-page.md +39 -10
- package/skills/astro/optimize-performance.md +36 -8
- package/skills/cli/SKILL.md +254 -220
- package/skills/dev/SKILL.md +1 -1
- package/skills/directory-autofill/SKILL.md +68 -0
- package/skills/docs/SKILL.md +4 -4
- package/skills/mcp/SKILL.md +186 -156
- package/skills/promise-make/SKILL.md +2 -2
- package/skills/puck/SKILL.md +465 -250
- package/skills/react19/SKILL.md +196 -296
- package/skills/reactflow/SKILL.md +387 -412
- package/skills/sdk/SKILL.md +167 -106
- package/skills/shadcn/SKILL.md +245 -201
- package/skills/signal/SKILL.md +5 -0
- package/skills/sui/SKILL.md +6 -1
- package/skills/tutorial/SKILL.md +15 -0
- package/skills/typedb/SKILL.md +427 -217
- package/skills/typedb/examples/python-patterns.py +11 -4
- package/skills/typedb/examples/query-patterns.tql +8 -3
- package/skills/typedb/examples/schema-patterns.tql +4 -2
- package/skills/typedb/reference/migration-2x-3x.md +19 -1
- package/skills/typedb/reference/python-driver.md +17 -1
- package/skills/voice/SKILL.md +117 -0
- package/skills/writer/SKILL.md +29 -12
- package/templates/template-feature.md +26 -1
- package/templates/template-tests.md +4 -0
- package/templates/template-todo.md +65 -10
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# do-walk.sh — the deterministic verification walk for a shipped /do loop.
|
|
3
|
+
#
|
|
4
|
+
# Reads the walk stops out of text/<slug>-humans.md (guided browser walk for a
|
|
5
|
+
# person) or text/<slug>-agents.md (machine asserts, zero LLM) and executes
|
|
6
|
+
# them in order. Both files carry the same fenced-block format:
|
|
7
|
+
#
|
|
8
|
+
# ```walk
|
|
9
|
+
# stop: 1
|
|
10
|
+
# title: Ads board loads
|
|
11
|
+
# route: /u/one/ads
|
|
12
|
+
# expect_status: ok # ok (default, <500) | exact code e.g. 200
|
|
13
|
+
# expect_text: "New campaign" # optional — substring in the served HTML
|
|
14
|
+
# expect_cmd: test -f one.ie/web/src/pages/api/ads/push.ts # optional bash, exit 0 = pass
|
|
15
|
+
# max_ms: 3000 # optional speed budget for THIS stop's asserts
|
|
16
|
+
# check: The board renders with the New campaign button top-right.
|
|
17
|
+
# ```
|
|
18
|
+
#
|
|
19
|
+
# Usage:
|
|
20
|
+
# do-walk.sh <slug> --agents [--base <url>] # run every stop's asserts; exit 0 iff none failed
|
|
21
|
+
# do-walk.sh <slug> --humans [--base <url>] # open each page in the browser, ask y/n per stop
|
|
22
|
+
# do-walk.sh <slug> --list [--humans|--agents] # print the stops, run nothing
|
|
23
|
+
# do-walk.sh <slug> --agents --strict # also exit 3 if any stop could not be run
|
|
24
|
+
# do-walk.sh --self-test
|
|
25
|
+
#
|
|
26
|
+
# Env:
|
|
27
|
+
# WALK_BASE_URL force the base (else dev http://localhost:4321 if up, else prod)
|
|
28
|
+
# PROVE_PROD_URL prod fallback base (default https://one.ie)
|
|
29
|
+
# PROVE_SESSION_COOKIE optional "name=value" — sent on every request so
|
|
30
|
+
# auth-gated routes (/u/[slug]/*) can be walked signed-in.
|
|
31
|
+
# WALK_STRICT=1 same as --strict
|
|
32
|
+
# WALK_DEPTH set by the script itself; a nested run refuses (see below)
|
|
33
|
+
#
|
|
34
|
+
# ── max_ms — a stop that passes slowly is not a stop that passes ──────────
|
|
35
|
+
# `max_ms: N` budgets THIS stop's own asserts (the curl(s) plus expect_cmd),
|
|
36
|
+
# not the whole walk. Over budget with everything else green fails the stop on
|
|
37
|
+
# SPEED, and says so in the FAIL line so nobody goes hunting for a correctness
|
|
38
|
+
# bug that isn't there.
|
|
39
|
+
#
|
|
40
|
+
# **A stop with no `max_ms` has NO budget.** Absent must never read as zero —
|
|
41
|
+
# every walk doc written before this field existed would fail instantly. Same
|
|
42
|
+
# for an unmeasurable clock: if neither bash 5 nor python3 can stamp the time,
|
|
43
|
+
# budgets are skipped rather than assumed blown. A non-numeric `max_ms` is a
|
|
44
|
+
# doc bug and fails the stop loudly instead of being silently ignored.
|
|
45
|
+
#
|
|
46
|
+
# Put budgets on the deterministic stops (file greps, local commands). A stop
|
|
47
|
+
# whose assert crosses the network is measuring someone else's latency, so
|
|
48
|
+
# either leave it unbudgeted or make the budget wide enough to mean something.
|
|
49
|
+
#
|
|
50
|
+
# ── red vs cannot run ────────────────────────────────────────────────────
|
|
51
|
+
# An `expect_cmd` that exits **3** did not fail — it could not be run, and
|
|
52
|
+
# nothing was proven either way (the convention `.claude/scripts/factory-check.sh`
|
|
53
|
+
# already uses, and text/factory.md § "A note on red vs cannot run"). Exit 1
|
|
54
|
+
# sends someone to fix the build; exit 3 says the environment could not answer.
|
|
55
|
+
#
|
|
56
|
+
# So: the walk's EXIT CODE answers "did anything fail?", and its OUTPUT answers
|
|
57
|
+
# "was everything proven?". Cannot-run stops are printed as CANNOT-RUN, counted
|
|
58
|
+
# separately, and named in the summary — they are never folded into the pass
|
|
59
|
+
# count. `--strict` is for a caller that needs full proof: it exits 3 when
|
|
60
|
+
# nothing failed but something could not be run.
|
|
61
|
+
#
|
|
62
|
+
# The 3 must always ORIGINATE IN THE CHECK. Never wrap a command so that its
|
|
63
|
+
# red becomes a cannot-run; that is how a walk starts lying.
|
|
64
|
+
#
|
|
65
|
+
# ── no nesting ───────────────────────────────────────────────────────────
|
|
66
|
+
# A stop must not re-run do-walk.sh. The obvious way to write the stop for a
|
|
67
|
+
# "the walk passes" deliverable is to paste in an accept: that calls this
|
|
68
|
+
# script, which loops forever. WALK_DEPTH makes a nested run refuse loudly
|
|
69
|
+
# instead. Assert the observable directly (--self-test, a grep) instead.
|
|
70
|
+
#
|
|
71
|
+
# Exit codes: 0 = nothing failed · 1 = a stop failed · 3 = --strict and a stop
|
|
72
|
+
# could not be run.
|
|
73
|
+
set -euo pipefail
|
|
74
|
+
|
|
75
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
76
|
+
PROD_URL="${PROVE_PROD_URL:-https://one.ie}"
|
|
77
|
+
DEV_URL="${PROVE_DEV_URL:-http://localhost:4321}"
|
|
78
|
+
|
|
79
|
+
# ---------- parse helpers ----------
|
|
80
|
+
|
|
81
|
+
# extract_stops <file> → lines "N<TAB>key: value" for every ```walk block
|
|
82
|
+
extract_stops() {
|
|
83
|
+
awk '
|
|
84
|
+
/^```walk[[:space:]]*$/ { inb=1; n++; next }
|
|
85
|
+
/^```[[:space:]]*$/ { inb=0; next }
|
|
86
|
+
inb { print n "\t" $0 }
|
|
87
|
+
' "$1"
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# field <stops> <n> <key> → value, empty if absent. Strips ONE matching pair
|
|
91
|
+
# of wrapping quotes (title: "x") but leaves an unquoted value — e.g. any
|
|
92
|
+
# expect_cmd containing its own internal 'quoted' args — completely untouched.
|
|
93
|
+
field() {
|
|
94
|
+
printf '%s\n' "$1" | awk -F'\t' -v n="$2" -v k="$3" '
|
|
95
|
+
$1 == n {
|
|
96
|
+
line = $2
|
|
97
|
+
prefix = k ": "
|
|
98
|
+
if (index(line, prefix) == 1) {
|
|
99
|
+
v = substr(line, length(prefix) + 1)
|
|
100
|
+
sub(/[ \t]+$/, "", v)
|
|
101
|
+
len = length(v)
|
|
102
|
+
if (len >= 2) {
|
|
103
|
+
first = substr(v, 1, 1); last = substr(v, len, 1)
|
|
104
|
+
if ((first == "\"" && last == "\"") || (first == "'"'"'" && last == "'"'"'")) {
|
|
105
|
+
v = substr(v, 2, len - 2)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
print v
|
|
109
|
+
exit
|
|
110
|
+
}
|
|
111
|
+
}'
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
# now_ms → epoch milliseconds, or EMPTY if this box cannot stamp one.
|
|
115
|
+
# Portability is the whole point: `date +%s%N` is a GNU-ism, and BSD date (what
|
|
116
|
+
# macOS ships) prints a literal N — which then arithmetics into garbage that
|
|
117
|
+
# compares as 0 and fails every budget. bash 5 has EPOCHREALTIME with no
|
|
118
|
+
# subprocess; macOS's stock bash is 3.2, so python3 is the fallback; if neither
|
|
119
|
+
# answers, the caller SKIPS the budget rather than inventing a duration.
|
|
120
|
+
now_ms() {
|
|
121
|
+
local e s f
|
|
122
|
+
if [ "${BASH_VERSINFO[0]:-0}" -ge 5 ]; then
|
|
123
|
+
e="${EPOCHREALTIME:-}"
|
|
124
|
+
case "$e" in
|
|
125
|
+
*[.,]*)
|
|
126
|
+
s="${e%%[.,]*}"; f="${e##*[.,]}"; f="${f}000"; f="${f:0:3}"
|
|
127
|
+
printf '%s' "$(( 10#$s * 1000 + 10#$f ))"; return 0 ;;
|
|
128
|
+
esac
|
|
129
|
+
fi
|
|
130
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
131
|
+
python3 -c 'import time;print(int(time.time()*1000))'; return 0
|
|
132
|
+
fi
|
|
133
|
+
printf ''
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# ---------- self-test ----------
|
|
137
|
+
|
|
138
|
+
if [ "${1:-}" = "--self-test" ]; then
|
|
139
|
+
tmp="$(mktemp)"
|
|
140
|
+
cat > "$tmp" <<'EOF'
|
|
141
|
+
## Stop 1
|
|
142
|
+
```walk
|
|
143
|
+
stop: 1
|
|
144
|
+
title: First
|
|
145
|
+
route: /a
|
|
146
|
+
expect_text: "hello"
|
|
147
|
+
check: first check
|
|
148
|
+
```
|
|
149
|
+
## Stop 2
|
|
150
|
+
```walk
|
|
151
|
+
stop: 2
|
|
152
|
+
title: Second
|
|
153
|
+
route: /b
|
|
154
|
+
expect_cmd: true
|
|
155
|
+
max_ms: 1500
|
|
156
|
+
check: second check
|
|
157
|
+
```
|
|
158
|
+
EOF
|
|
159
|
+
stops="$(extract_stops "$tmp")"
|
|
160
|
+
count="$(printf '%s\n' "$stops" | awk -F'\t' '{print $1}' | sort -u | grep -c . || true)"
|
|
161
|
+
t1="$(field "$stops" 1 title)"; r2="$(field "$stops" 2 route)"
|
|
162
|
+
# The budget arms: stop 2 carries one, stop 1 does not — and "does not" MUST
|
|
163
|
+
# read as empty, never as 0, or every pre-max_ms walk doc fails on speed.
|
|
164
|
+
b2="$(field "$stops" 2 max_ms)"; b1="$(field "$stops" 1 max_ms)"
|
|
165
|
+
# And the clock must actually tick — a stuck clock makes every budget pass.
|
|
166
|
+
c0="$(now_ms)"; sleep 0.05; c1="$(now_ms)"
|
|
167
|
+
clock_ok=0
|
|
168
|
+
if [ -n "$c0" ] && [ -n "$c1" ] && [ "$c1" -ge "$c0" ] && [ "$c0" -gt 1600000000000 ]; then clock_ok=1; fi
|
|
169
|
+
rm -f "$tmp"
|
|
170
|
+
if [ "$count" = "2" ] && [ "$t1" = "First" ] && [ "$r2" = "/b" ] \
|
|
171
|
+
&& [ "$b2" = "1500" ] && [ -z "$b1" ] && [ "$clock_ok" = "1" ]; then
|
|
172
|
+
echo "WALK: self-test pass (parse + max_ms + clock)"; exit 0
|
|
173
|
+
fi
|
|
174
|
+
echo "WALK: self-test FAIL (count=$count t1=$t1 r2=$r2 b2=$b2 b1='$b1' clock_ok=$clock_ok)"; exit 1
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
# ---------- args ----------
|
|
178
|
+
|
|
179
|
+
slug="" mode="" base="" list=0
|
|
180
|
+
strict=0; [ "${WALK_STRICT:-0}" = "1" ] && strict=1
|
|
181
|
+
while [ "$#" -gt 0 ]; do
|
|
182
|
+
case "$1" in
|
|
183
|
+
--agents) mode=agents; shift ;;
|
|
184
|
+
--humans) mode=humans; shift ;;
|
|
185
|
+
--strict) strict=1; shift ;;
|
|
186
|
+
--list) list=1; shift ;;
|
|
187
|
+
--base) [ "$#" -ge 2 ] || { echo "WALK: --base requires a value"; exit 1; }
|
|
188
|
+
base="$2"; shift 2 ;;
|
|
189
|
+
-*) echo "WALK: unknown flag $1"; exit 1 ;;
|
|
190
|
+
*) slug="$1"; shift ;;
|
|
191
|
+
esac
|
|
192
|
+
done
|
|
193
|
+
[ -n "$slug" ] || { echo "WALK: usage: do-walk.sh <slug> --agents|--humans [--base <url>] [--list]"; exit 1; }
|
|
194
|
+
[ -n "$mode" ] || mode=agents
|
|
195
|
+
|
|
196
|
+
file="$ROOT/text/${slug}-${mode}.md"
|
|
197
|
+
[ -f "$file" ] || { echo "WALK: no walk doc at text/${slug}-${mode}.md"; exit 1; }
|
|
198
|
+
|
|
199
|
+
stops="$(extract_stops "$file")"
|
|
200
|
+
[ -n "$stops" ] || { echo "WALK: text/${slug}-${mode}.md has no \`\`\`walk blocks"; exit 1; }
|
|
201
|
+
ids="$(printf '%s\n' "$stops" | awk -F'\t' '{print $1}' | sort -un)"
|
|
202
|
+
|
|
203
|
+
# ---------- base resolution ----------
|
|
204
|
+
|
|
205
|
+
if [ -z "$base" ]; then
|
|
206
|
+
base="${WALK_BASE_URL:-}"
|
|
207
|
+
fi
|
|
208
|
+
if [ -z "$base" ]; then
|
|
209
|
+
if curl -sf -o /dev/null --max-time 4 "$DEV_URL/" 2>/dev/null; then base="$DEV_URL"; else base="$PROD_URL"; fi
|
|
210
|
+
fi
|
|
211
|
+
|
|
212
|
+
cookie_args=()
|
|
213
|
+
[ -n "${PROVE_SESSION_COOKIE:-}" ] && cookie_args=(-H "Cookie: ${PROVE_SESSION_COOKIE}")
|
|
214
|
+
|
|
215
|
+
echo "WALK: $slug · $mode · base=$base · $(printf '%s\n' "$ids" | grep -c .) stop(s)"
|
|
216
|
+
|
|
217
|
+
# ---------- list mode ----------
|
|
218
|
+
|
|
219
|
+
if [ "$list" -eq 1 ]; then
|
|
220
|
+
for n in $ids; do
|
|
221
|
+
t="$(field "$stops" "$n" title)"; r="$(field "$stops" "$n" route)"
|
|
222
|
+
c="$(field "$stops" "$n" check)"
|
|
223
|
+
echo " $n. ${t:-'(untitled)'} ${r:+→ $base$r}"
|
|
224
|
+
[ -n "$c" ] && echo " $c"
|
|
225
|
+
done
|
|
226
|
+
exit 0
|
|
227
|
+
fi
|
|
228
|
+
|
|
229
|
+
# ---------- run ----------
|
|
230
|
+
|
|
231
|
+
# Nesting guard — see the header. A stop that shells back into do-walk.sh (the
|
|
232
|
+
# natural mistake when a deliverable IS "the walk passes") would recurse until
|
|
233
|
+
# the box gives up. Refuse loudly, at the stop, with the fix in the message.
|
|
234
|
+
# Placed after --list/--self-test so those stay usable from inside a walk.
|
|
235
|
+
if [ "${WALK_DEPTH:-0}" -ge 1 ]; then
|
|
236
|
+
echo "WALK: refusing to nest (WALK_DEPTH=${WALK_DEPTH}) — a stop must not re-run do-walk.sh."
|
|
237
|
+
echo "WALK: assert the observable directly (do-walk.sh --self-test, a grep), not by recursion."
|
|
238
|
+
exit 1
|
|
239
|
+
fi
|
|
240
|
+
export WALK_DEPTH=$(( ${WALK_DEPTH:-0} + 1 ))
|
|
241
|
+
|
|
242
|
+
fail=0; passed=0; unknown=0; failed=0
|
|
243
|
+
for n in $ids; do
|
|
244
|
+
t="$(field "$stops" "$n" title)"
|
|
245
|
+
r="$(field "$stops" "$n" route)"
|
|
246
|
+
es="$(field "$stops" "$n" expect_status)"; es="${es:-ok}"
|
|
247
|
+
et="$(field "$stops" "$n" expect_text)"
|
|
248
|
+
ec="$(field "$stops" "$n" expect_cmd)"
|
|
249
|
+
mm="$(field "$stops" "$n" max_ms)"
|
|
250
|
+
ck="$(field "$stops" "$n" check)"
|
|
251
|
+
url=""; [ -n "$r" ] && url="$base$r"
|
|
252
|
+
|
|
253
|
+
if [ "$mode" = "humans" ]; then
|
|
254
|
+
echo ""
|
|
255
|
+
echo "── Stop $n — ${t:-'(untitled)'}"
|
|
256
|
+
[ -n "$url" ] && echo " page: $url"
|
|
257
|
+
[ -n "$ck" ] && echo " check: $ck"
|
|
258
|
+
if [ ! -t 0 ]; then
|
|
259
|
+
continue # non-interactive: print the guide only
|
|
260
|
+
fi
|
|
261
|
+
if [ -n "$url" ] && command -v open >/dev/null 2>&1; then open "$url"; fi
|
|
262
|
+
printf ' verified? [y/n] '
|
|
263
|
+
read -r verdict || verdict=n
|
|
264
|
+
case "$verdict" in
|
|
265
|
+
y|Y|yes) echo " WALK: ok stop $n" ;;
|
|
266
|
+
*) echo " WALK: FAIL stop $n — human rejected"; fail=1 ;;
|
|
267
|
+
esac
|
|
268
|
+
continue
|
|
269
|
+
fi
|
|
270
|
+
|
|
271
|
+
# agents mode — deterministic asserts, zero LLM
|
|
272
|
+
ok=1; why=""; cannot=0; elapsed=""; code=""
|
|
273
|
+
# A malformed budget is a doc bug, and a doc bug that silently disables the
|
|
274
|
+
# budget is worse than no budget at all. Fail the stop and name the value.
|
|
275
|
+
if [ -n "$mm" ]; then
|
|
276
|
+
case "$mm" in
|
|
277
|
+
''|*[!0-9]*) ok=0; why="invalid max_ms '$mm' — want whole milliseconds" ;;
|
|
278
|
+
esac
|
|
279
|
+
fi
|
|
280
|
+
t0="$(now_ms)"
|
|
281
|
+
if [ "$ok" -eq 1 ] && [ -n "$url" ]; then
|
|
282
|
+
code="$(curl -s -o /dev/null --max-time 20 -w '%{http_code}' "${cookie_args[@]+"${cookie_args[@]}"}" "$url" 2>/dev/null || echo 000)"
|
|
283
|
+
if [ "$es" = "ok" ]; then
|
|
284
|
+
{ [ "$code" = "000" ] || [ "$code" -ge 500 ]; } && { ok=0; why="http=$code"; }
|
|
285
|
+
else
|
|
286
|
+
[ "$code" != "$es" ] && { ok=0; why="http=$code (want $es)"; }
|
|
287
|
+
fi
|
|
288
|
+
if [ "$ok" -eq 1 ] && [ -n "$et" ]; then
|
|
289
|
+
if ! curl -s --max-time 20 "${cookie_args[@]+"${cookie_args[@]}"}" "$url" 2>/dev/null | grep -qiF "$et"; then
|
|
290
|
+
ok=0; why="text '$et' not in served HTML"
|
|
291
|
+
fi
|
|
292
|
+
fi
|
|
293
|
+
fi
|
|
294
|
+
if [ "$ok" -eq 1 ] && [ -n "$ec" ]; then
|
|
295
|
+
# rc captured via `|| rc=$?` — NOT `cmd; rc=$?`, which set -e would kill
|
|
296
|
+
# before the assignment ran. 3 = the check could not run; anything else
|
|
297
|
+
# non-zero = it ran and failed.
|
|
298
|
+
rc=0
|
|
299
|
+
(cd "$ROOT" && bash -c "$ec" >/dev/null 2>&1) || rc=$?
|
|
300
|
+
if [ "$rc" -eq 3 ]; then
|
|
301
|
+
cannot=1; why="expect_cmd could not run (exit 3): $ec"
|
|
302
|
+
elif [ "$rc" -ne 0 ]; then
|
|
303
|
+
ok=0; why="expect_cmd failed (exit $rc): $ec"
|
|
304
|
+
fi
|
|
305
|
+
fi
|
|
306
|
+
t1="$(now_ms)"
|
|
307
|
+
if [ -n "$t0" ] && [ -n "$t1" ]; then elapsed=$(( t1 - t0 )); fi
|
|
308
|
+
|
|
309
|
+
# Speed is judged LAST and only on a stop that actually decided itself.
|
|
310
|
+
# A cannot-run stop proved nothing — including nothing about its duration —
|
|
311
|
+
# so timing it would be measuring an outage.
|
|
312
|
+
if [ "$cannot" -eq 0 ] && [ "$ok" -eq 1 ] && [ -n "$mm" ] && [ -n "$elapsed" ] \
|
|
313
|
+
&& [ "$elapsed" -gt "$mm" ]; then
|
|
314
|
+
ok=0; why="SPEED: ${elapsed}ms over budget max_ms=${mm} (correctness passed)"
|
|
315
|
+
fi
|
|
316
|
+
|
|
317
|
+
timing=""; [ -n "$mm" ] && [ -n "$elapsed" ] && timing=" [${elapsed}ms/${mm}ms]"
|
|
318
|
+
if [ "$cannot" -eq 1 ]; then
|
|
319
|
+
echo "WALK: CANNOT-RUN stop $n — ${t:-'(untitled)'} — $why"
|
|
320
|
+
unknown=$(( unknown + 1 ))
|
|
321
|
+
elif [ "$ok" -eq 1 ]; then
|
|
322
|
+
echo "WALK: ok stop $n — ${t:-'(untitled)'}${url:+ ($code)}${timing}"
|
|
323
|
+
passed=$(( passed + 1 ))
|
|
324
|
+
else
|
|
325
|
+
echo "WALK: FAIL stop $n — ${t:-'(untitled)'} — $why"
|
|
326
|
+
fail=1; failed=$(( failed + 1 ))
|
|
327
|
+
fi
|
|
328
|
+
done
|
|
329
|
+
|
|
330
|
+
echo ""
|
|
331
|
+
if [ "$fail" -eq 1 ]; then
|
|
332
|
+
echo "WALK: fail — $failed failed · $passed proven · $unknown could not be run"
|
|
333
|
+
exit 1
|
|
334
|
+
fi
|
|
335
|
+
if [ "$unknown" -gt 0 ]; then
|
|
336
|
+
echo "WALK: pass — $passed proven · $unknown could not be run · 0 failed"
|
|
337
|
+
echo "WALK: nothing failed, but $unknown stop(s) proved nothing either way — re-run when the environment answers."
|
|
338
|
+
if [ "$strict" -eq 1 ]; then
|
|
339
|
+
echo "WALK: strict — a walk that could not run every stop is not a full proof."
|
|
340
|
+
exit 3
|
|
341
|
+
fi
|
|
342
|
+
exit 0
|
|
343
|
+
fi
|
|
344
|
+
echo "WALK: pass — $passed proven"; exit 0
|