crewforth 3.2.0-rc.5 → 3.2.0-rc.6
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/CHANGELOG.md +7 -0
- package/VERSION +1 -1
- package/kit/eval/smoke-test.sh +20 -0
- package/kit/hooks/guard-agent-model.sh +10 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -220,6 +220,13 @@ versioning follows [SemVer](https://semver.org/).
|
|
|
220
220
|
|
|
221
221
|
### Fixed
|
|
222
222
|
|
|
223
|
+
- **`change: review` is read as `audit`.** The model table of the working rules names review with audit, and
|
|
224
|
+
`crew-review-agent` cards that said `change: review` were refused. It now takes the audit floor, on a critical path
|
|
225
|
+
too; a kind that is not on the list is still refused.
|
|
226
|
+
- **`above:` is read anywhere among a task card's three lines.** A card with `above: <why>` between `change:` and
|
|
227
|
+
`verify:` was refused ("line 3 of the task is not one of files:, change:, verify:") and the call was sent again
|
|
228
|
+
with the line moved down. It is now read in any position and keeps the model as it does after the three; the three
|
|
229
|
+
are still all required.
|
|
223
230
|
- **A click on the approval question is recorded whatever order its keys come back in.** Claude Code hands the
|
|
224
231
|
answered question back either as it was asked or with its keys sorted, and the answer side matched it byte for
|
|
225
232
|
byte: in real `auto` sessions 30 of 30 answers in the asked order were recorded and 7 of 7 sorted ones refused
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.2.0-rc.
|
|
1
|
+
3.2.0-rc.6
|
package/kit/eval/smoke-test.sh
CHANGED
|
@@ -8598,6 +8598,26 @@ for _pr in 'files: a · change: archi (planning only) · verify: none' 'files: a
|
|
|
8598
8598
|
done
|
|
8599
8599
|
[ -z "$_v2b" ] && pass "a card on one line (· ; | separators, a Card: lead, above: on the line) is read by its labels and held to the three-line rules: a critical path still needs opus; a kind with a note in parentheses is the kind, on one line or three; a bad change, labels out of order, a missing verify or prose first are refused" \
|
|
8600
8600
|
|| fail "the one-line card:$_v2b"
|
|
8601
|
+
# `above:` among the three lines, not only after them (2026-10-19: 2 of 19 line refusals had it between change: and
|
|
8602
|
+
# verify:; the retry moved it down and passed). It keeps the model the same way; the three are still all required.
|
|
8603
|
+
_v2b=""
|
|
8604
|
+
for _pr in 'files: src/ui/a.ts\nchange: feature\nabove: the parser is subtle\nverify: true' 'above: the parser is subtle\nfiles: src/ui/a.ts\nchange: feature\nverify: true'; do
|
|
8605
|
+
_v2one "$_pr" opus; { [ "$_rc" = 0 ] && [ ! -s "$_v2/oneout" ]; } || _v2b="$_v2b [above: among the three did not keep opus: $_pr → $_rc $(head -c 100 "$_v2/oneout")]"
|
|
8606
|
+
done
|
|
8607
|
+
_v2one 'files: src/ui/c.ts\nchange: feature\nverify: true' opus
|
|
8608
|
+
grep -q '"updatedInput":' "$_v2/oneout" || _v2b="$_v2b [without above: opus was not lowered (rc $_rc)]"
|
|
8609
|
+
for _pr in 'files: src/ui/a.ts\nchange: feature\nabove: x\nDo it.' 'files: src/ui/a.ts\nabove: x\nabove: y\nverify: true'; do
|
|
8610
|
+
_v2one "$_pr" sonnet; { [ "$_rc" = 2 ] && grep -q 'opens with its task card' "$_v2/err"; } || _v2b="$_v2b [passed: $_pr → $_rc]"
|
|
8611
|
+
done
|
|
8612
|
+
# `change: review` is an audit (the discipline's table lists it with them): same floor, a near miss still refused.
|
|
8613
|
+
_v2one 'files: src/ui/a.ts\nchange: review\nverify: none' haiku; { [ "$_rc" = 2 ] && grep -q 'runs on sonnet' "$_v2/err"; } || _v2b="$_v2b [review on haiku was not held to sonnet as audit (rc $_rc)]"
|
|
8614
|
+
for _pr in 'files: src/ui/a.ts\nchange: review\nverify: none' 'files: src/ui/a.ts · change: review (the staged diff) · verify: none'; do
|
|
8615
|
+
_v2one "$_pr" sonnet; [ "$_rc" = 0 ] || _v2b="$_v2b [refused: $_pr → $_rc $(head -c 100 "$_v2/err")]"
|
|
8616
|
+
done
|
|
8617
|
+
_v2one 'files: src/payments/p.ts\nchange: review\nverify: none' sonnet; { [ "$_rc" = 2 ] && grep -q 'runs on opus' "$_v2/err"; } || _v2b="$_v2b [review on a critical path was not held to opus (rc $_rc)]"
|
|
8618
|
+
_v2one 'files: src/ui/a.ts\nchange: reviews\nverify: none' sonnet; { [ "$_rc" = 2 ] && grep -q 'opens with its task card' "$_v2/err"; } || _v2b="$_v2b [change: reviews passed (rc $_rc)]"
|
|
8619
|
+
[ -z "$_v2b" ] && pass "above: may stand anywhere among the three card lines and keeps the model; without it the model is lowered; above: does not stand in for files:, change: or verify:; change: review is an audit, held to the same floors, and a near miss is still refused" \
|
|
8620
|
+
|| fail "above: in the card:$_v2b"
|
|
8601
8621
|
|
|
8602
8622
|
# ---- at write time: the card can leave a file out --------------------------------------------------------------
|
|
8603
8623
|
_v2new; _v2b=""
|
|
@@ -459,7 +459,7 @@ _am_card_line(){ # $1 = the first line of the task -> 0 and CARD_* set (uncheck
|
|
|
459
459
|
return 0
|
|
460
460
|
}
|
|
461
461
|
_am_card(){ # $1 = a task text -> 0 and CARD_FILES, CARD_CHANGE, CARD_VERIFY (CARD_ABOVE); 1 and CARD_WHY
|
|
462
|
-
local s="$1" l k v n=0 seen="" one=0
|
|
462
|
+
local s="$1" l k v n=0 ln=0 seen="" one=0
|
|
463
463
|
CARD_FILES=""; CARD_CHANGE=""; CARD_VERIFY=""; CARD_WHY=""; CARD_ABOVE=""
|
|
464
464
|
s="${s//$'\r'/}"
|
|
465
465
|
# One line first: the first line that is not empty, read by its labels; the three-line reading otherwise.
|
|
@@ -472,17 +472,20 @@ _am_card(){ # $1 = a task text -> 0 and CARD_FILES, CARD_CHANGE, CARD_VERIFY (C
|
|
|
472
472
|
l="${s%%$'\n'*}"; if [ "$l" = "$s" ]; then s=""; else s="${s#*$'\n'}"; fi
|
|
473
473
|
while :; do case "$l" in [$' \t']*) l="${l:1}" ;; *) break ;; esac; done
|
|
474
474
|
[ -n "$l" ] || continue
|
|
475
|
-
|
|
476
|
-
case "$l" in *:*) ;; *) CARD_WHY="line $
|
|
475
|
+
ln=$((ln+1))
|
|
476
|
+
case "$l" in *:*) ;; *) CARD_WHY="line $ln of the task is not one of files:, change:, verify:"; return 1 ;; esac
|
|
477
477
|
k="${l%%:*}"; v="${l#*:}"
|
|
478
478
|
while :; do case "$v" in [$' \t']*) v="${v:1}" ;; *) break ;; esac; done
|
|
479
479
|
while :; do case "$v" in *[$' \t']) v="${v%?}" ;; *) break ;; esac; done
|
|
480
|
+
# `above:` may stand anywhere among the three (2 of 19 line refusals, 2026-10-19: between change: and verify:).
|
|
480
481
|
case "$k" in
|
|
482
|
+
above) [ -n "$CARD_ABOVE" ] || CARD_ABOVE="${v:0:200}"; continue ;;
|
|
481
483
|
files) CARD_FILES="$v" ;;
|
|
482
484
|
change) CARD_CHANGE="$v" ;;
|
|
483
485
|
verify) CARD_VERIFY="$v" ;;
|
|
484
|
-
*) CARD_WHY="line $
|
|
486
|
+
*) CARD_WHY="line $ln of the task is not one of files:, change:, verify:"; return 1 ;;
|
|
485
487
|
esac
|
|
488
|
+
n=$((n+1))
|
|
486
489
|
case "$seen" in *" $k "*) CARD_WHY="the card names $k twice"; return 1 ;; esac
|
|
487
490
|
seen="$seen $k "
|
|
488
491
|
done
|
|
@@ -491,6 +494,9 @@ _am_card(){ # $1 = a task text -> 0 and CARD_FILES, CARD_CHANGE, CARD_VERIFY (C
|
|
|
491
494
|
# A note in parentheses after the kind is the session's own comment, as `none (…)` is for verify: `architecture
|
|
492
495
|
# (planning only)` is architecture (4 of the cards refused on this machine, 2026-10-18). Only a kind on the list, and
|
|
493
496
|
# only a note that is the whole rest of the value in parentheses.
|
|
497
|
+
# `review` is an audit: the discipline's model table names it with them, and 4 crew-review-agent cards were refused
|
|
498
|
+
# for it (2026-10-19).
|
|
499
|
+
case "$CARD_CHANGE" in review|'review ('*')') CARD_CHANGE=audit ;; esac
|
|
494
500
|
case "$CARD_CHANGE" in *' ('*')') v="${CARD_CHANGE%% (*}"; case "$_AM_CHANGES" in *" $v "*) CARD_CHANGE="$v" ;; esac ;; esac
|
|
495
501
|
case "$_AM_CHANGES" in *" $CARD_CHANGE "*) ;; *) CARD_WHY="change: is '${CARD_CHANGE:0:40}', not one of:$_AM_CHANGES"; return 1 ;; esac
|
|
496
502
|
[ -n "$CARD_VERIFY" ] || { CARD_WHY="verify: is empty (a command, or none)"; return 1; }
|
package/package.json
CHANGED