feat(route,board): strike the advisor rule, add board.sh --row <repo>
Order 20260912T202210Z-7588027378-from-.claude, operator decision 2026-09-12 (helhetlig vurdering av arbeidssystemet, cut row 3 and the board.sh --row improvement row). One order, two parts, one version bump. THE ADVISOR RULE IS STRUCK. route.sh and board.sh --dispatch emit no --advisor at all. The rule fired per ROW on a need - always on the Sonnet rows (a capability lift, which is what made the quota fallback safe to take), and on the Opus rows at reversibility=costly|one-way - and it read well. It was killed by a MEASUREMENT, not by taste: of 54 dispatches the PM issued 08.-12.09, ZERO carried the flag, because sessions are started by hand from the model and effort rather than from the whole emitted line. A rule nothing honours is not a policy, and an emitted value nobody acts on is decoration in a field whose only job is to be evidence. The advisor is now what it already was in practice: an operator decision per session, said in one sentence in route.sh --help. The comments that rested on the rule were REWRITTEN, not left standing. board.sh --dispatch still refuses a --model/--effort pair, but the reason is no longer "the advisor is a property of the ROW": it is that the rubric has exactly one copy, and a dispatch taking the model directly would be a second, unscored way to reach the same decision - recording no traits, no rationale and no next-cost, so nothing afterwards could say whether the routing or the scoring was wrong. A comment defending a removed mechanism is how the next session restores it. Both skills carry the correction. Pinned as an ABSENCE over the whole trait space - 81 combinations, every line of output, with a known-positive control proving the sweep's grep can find a planted advisor - rather than on four sampled rows, because the claim is that no path emits it. board.sh --dispatch at reversibility=costly is pinned separately: that is the exact input a reintroduced rule would fire on. The literal string is absent from route.sh entirely, including the paragraph recording what was struck (it says "an opus advisor flag" in words), because a blunt grep cannot tell a description from a specification. Backward compatibility is pinned rather than assumed: a route line carrying a legacy advisor= field still parses and still yields a command - measured, 0 of 48 route lines in ~/repos carry one, but a reader that broke on an unknown field would turn last month's STATE.md into "that repo has no route line". The three CLI gates section 14 carried went with the rule; the suite no longer depends on the installed claude at all. board.sh --row <repo> IS THE SEVENTH RENDERING of the same scan, never a second scan, read-only like every other one. (The order calls it the sixth; by this file's own numbering --inbox-plan is the fourth and --dispatch the fifth. Corrected rather than carried wrong.) It exists because the columns WERE misread: on 11.09 the PM read FLY off the table by eye and got it wrong, while every other rendering a program consumes is already key=value. inn, ordre and fly are three separate fields because they are three separate facts; status is the bare token, never the table's blocked>target display, with blocked-on beside it; neste is last and uncut. An unknown repo exits 2 and writes NOTHING to stdout - an empty block would read as a repo whose every column is blank, which is a real and different state. upushet is the ONE field that is not a rendering of the scan, and it is named rather than blended in: nothing in the scan measures it, so it is read once, for the named repo only, and never enters the table, the plan or the briefing. It reads the remote-TRACKING ref, not the remote, so upushet=N honestly means "the local ref says N"; a repo with no upstream reports ?, never 0. The row fixture's three counts are three DIFFERENT integers (3/2/1), and that is the finding worth recording. Built first with 2/1/1, it was mutation-tested by making fly read the ORDRE field - the exact 11.09 misreading - and the check stayed GREEN, because the two fields held the same digit. A fixture that cannot tell two columns apart is the defect wearing a passing test, inside the section written to prevent it. Suites under /bin/bash 3.2, before -> after: coord 257 -> 257, board 393 -> 427, route 73 -> 73 (13 advisor checks and 3 CLI gates out, 15 absence/legacy checks in, and it no longer varies with claude being on PATH), orders 116 -> 116, state-line-guard 54 -> 54. Sum 893 -> 927, README badge updated to the measured sum. npm test 12/12, fail 0. Verified live against the real tree, not only fixtures: --row repo-mailbox reports fly=1 beside ordre=0 (the distinction that was misread), --row on the nested key from-ai-to-chitta/content-sadhguru resolves, and an unknown repo exits 2. No tag, no push, no catalog change - that is the operator's release-plugin.mjs run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
671e275a97
commit
5e5bc4a66e
13 changed files with 689 additions and 271 deletions
|
|
@ -244,8 +244,8 @@ for n in 1 2 3; do echo "msg" > "$CLAUDE_COORD_DIR/repo-a/inbox/2026-msg$n-from-
|
|||
echo "old" > "$CLAUDE_COORD_DIR/repo-a/archive/2026-old-from-x.md"
|
||||
|
||||
# repo-owes: unhandled inbox AND a route line, so the briefing can derive the
|
||||
# EXACT startup command - advisor flag included - from the repo's own four
|
||||
# traits instead of guessing from next-cost alone. Its NESTE runs deliberately
|
||||
# EXACT startup command from the repo's own four traits instead of guessing
|
||||
# from next-cost alone. Its NESTE runs deliberately
|
||||
# past the table's 38-character column: carrying that line whole is the reason
|
||||
# the briefing exists at all.
|
||||
mkrepo "$ROOT/repo-owes"
|
||||
|
|
@ -581,10 +581,15 @@ printf '%s' "$BRIEF" | grep -q 'check-versions'
|
|||
check "brief prints the full NESTE line, not the 38-char table excerpt" $?
|
||||
|
||||
# Derived by CALLING route.sh with the repo's own four traits - deliberately
|
||||
# not spelled out in board.sh - so the rubric keeps exactly one copy. Row 1
|
||||
# carries the advisor, which is what makes the quota fallback safe to take.
|
||||
printf '%s' "$BRIEF" | grep -q 'claude --model sonnet --effort high --advisor opus'
|
||||
# not spelled out in board.sh - so the rubric keeps exactly one copy.
|
||||
printf '%s' "$BRIEF" | grep -q 'claude --model sonnet --effort high'
|
||||
check "brief derives the exact startup command from the repo's route line" $?
|
||||
# Anchored to end-of-line, because the loose grep above would pass just as
|
||||
# happily on a command that grew a flag back. The rubric emits no advisor
|
||||
# since 2026-09-12 and the briefing is a rendering of the rubric, not a
|
||||
# second policy.
|
||||
printf '%s' "$BRIEF" | grep -q 'claude --model sonnet --effort high$'
|
||||
check "brief's startup command ends at the effort - no advisor is appended" $?
|
||||
|
||||
# The command must start its OWN line. `fold` copies its input's missing
|
||||
# trailing newline, which ran the command onto the tail of the NESTE prose and
|
||||
|
|
@ -900,8 +905,8 @@ n_b="$(printf '%s\n' "$PLAN" | grep -n '^repo=repo-b$' | cut -d: -f1)"
|
|||
check "uavklart repos rank below every repo that declared a status" $?
|
||||
|
||||
# The command comes from route.sh, same single copy of the rubric the briefing
|
||||
# uses - advisor flag included, since that is a property of the ROW.
|
||||
printf '%s' "$PLAN" | grep -q '^command=claude --model sonnet --effort high --advisor opus$'
|
||||
# uses.
|
||||
printf '%s' "$PLAN" | grep -q '^command=claude --model sonnet --effort high$'
|
||||
check "plan derives the exact startup command from the repo's route line" $?
|
||||
|
||||
# Both no-command causes must degrade to a marker. A bare `command=` would be
|
||||
|
|
@ -932,7 +937,7 @@ check "plan prints the full NESTE line, not the 38-char table excerpt" $?
|
|||
# because they answer different questions: a driver cd's the pane itself and
|
||||
# would choke on a compound line, while the operator needs ONE thing to copy.
|
||||
# Assembling it by hand from two fields is where a tab lands in the wrong repo.
|
||||
printf '%s' "$PLAN" | grep -q "^paste=cd $ROOT/repo-owes && claude --model sonnet --effort high --advisor opus\$"
|
||||
printf '%s' "$PLAN" | grep -q "^paste=cd $ROOT/repo-owes && claude --model sonnet --effort high\$"
|
||||
check "paste= is the whole line: cd into the repo, then the startup command" $?
|
||||
|
||||
printf '%s\n' "$PLAN" | grep -A7 '^repo=repo-typo$' | grep -q '^paste='; [ $? -ne 0 ]
|
||||
|
|
@ -1530,7 +1535,7 @@ check "ip-repo-no-state reports 1 owed (no reply-expected: no declared)" $?
|
|||
# class=repo still derives the exact startup command from the repo's own
|
||||
# route line - same single copy of the rubric every other rendering uses.
|
||||
printf '%s\n' "$IPLAN" | grep -A8 '^repo=ip-repo-done-fyi$' \
|
||||
| grep -q '^command=claude --model sonnet --effort high --advisor opus$'
|
||||
| grep -q '^command=claude --model sonnet --effort high$'
|
||||
check "class=repo block derives its command from the repo's own route line" $?
|
||||
|
||||
# class=no-state and class=orphan-mailbox can never fabricate a command - ask
|
||||
|
|
@ -1766,8 +1771,8 @@ d6="$("$BOARD" --roots "$ROOT" --dispatch --repo no-such-repo --prompt-file "$DS
|
|||
[ "$rc" -eq 2 ]; check "dispatch: refuses a repo the scan does not know" $?
|
||||
|
||||
# Invalid traits must refuse, never degrade to a command without them: a
|
||||
# command missing --advisor reads exactly like a row that legitimately has no
|
||||
# advisor.
|
||||
# command built on three scored traits and one silently dropped one reads
|
||||
# exactly like a fully scored decision.
|
||||
d7="$("$BOARD" --roots "$ROOT" --dispatch --repo repo-a --prompt-file "$DSP" --target-pane no \
|
||||
--path bogus --verification strong --reversibility cheap --scope local --rationale t 2>&1)"; rc=$?
|
||||
[ "$rc" -eq 2 ]; check "dispatch: refuses trait values route.sh rejects, rather than emitting a partial command" $?
|
||||
|
|
@ -1789,18 +1794,27 @@ printf '%s\n' "$d8" | grep -q '^paste=cd '; check "dispatch: plan block carries
|
|||
printf '%s\n' "$d8" | grep -q "command=.*\"\$(cat $DSP)\""; check "dispatch: the command carries the prompt in argv, never bare model+effort" $?
|
||||
printf '%s\n' "$d8" | grep -q "^paste=cd $ROOT/repo-a && claude .*\"\$(cat $DSP)\""; check "dispatch: paste= is the complete one-string form, prompt included" $?
|
||||
|
||||
# The cost comes from route.sh's row table and nowhere else, so --advisor is a
|
||||
# property of the ROW. These two differ ONLY in reversibility: both land on
|
||||
# row 3 (Opus 5/high), and only the costly one carries the advisor. A dispatch
|
||||
# that took --model/--effort directly would have no source for that flag at
|
||||
# all, and forwarding it blindly is how a session ends up looking peer-reviewed
|
||||
# without being.
|
||||
# The cost comes from route.sh's row table and nowhere else. These two differ
|
||||
# ONLY in reversibility, and both land on row 3 (Opus 5/high) - so since the
|
||||
# advisor rule was struck (2026-09-12) they must produce the IDENTICAL command.
|
||||
# costly is the case that used to add --advisor opus, which makes it the exact
|
||||
# input a reintroduced rule would fire on: this is the order's named red test,
|
||||
# not a sampled one.
|
||||
d9="$("$BOARD" --roots "$ROOT" --dispatch --repo repo-a --prompt-file "$DSP" --target-pane no \
|
||||
--path known --verification strong --reversibility cheap --scope multi-file --rationale t 2>/dev/null)"
|
||||
printf '%s\n' "$d9" | grep -q '^command=claude --model opus --effort high "'; check "dispatch: model+effort come from the route row (row 3, no advisor at cheap)" $?
|
||||
printf '%s\n' "$d9" | grep -q '^command=claude --model opus --effort high "'; check "dispatch: model+effort come from the route row (row 3)" $?
|
||||
d10="$("$BOARD" --roots "$ROOT" --dispatch --repo repo-a --prompt-file "$DSP" --target-pane no \
|
||||
--path known --verification strong --reversibility costly --scope local --rationale t 2>/dev/null)"
|
||||
printf '%s\n' "$d10" | grep -q '^command=claude --model opus --effort high --advisor opus "'; check "dispatch: the advisor flag follows the ROW (costly -> row 3 with advisor)" $?
|
||||
printf '%s\n' "$d10" | grep -q '^command=claude --model opus --effort high "'; check "dispatch: reversibility=costly emits NO advisor (rule struck 2026-09-12)" $?
|
||||
if printf '%s\n' "$d10" | grep -q -- '--advisor'; then rc=1; else rc=0; fi
|
||||
check "dispatch: no advisor anywhere in the costly dispatch block" "$rc"
|
||||
if printf '%s\n' "$d10 claude --advisor opus" | grep -q -- '--advisor'; then rc=0; else rc=1; fi
|
||||
check "control: that grep does find a planted advisor" "$rc"
|
||||
# The paste line is assembled separately from command=, so it is pinned
|
||||
# separately: a flag reintroduced in only one of the two is the shape that
|
||||
# sends the operator and the driver down different paths.
|
||||
if printf '%s\n' "$d10" | grep '^paste=' | grep -q -- '--advisor'; then rc=1; else rc=0; fi
|
||||
check "dispatch: the paste line carries no advisor either" "$rc"
|
||||
printf '%s\n' "$d8" | grep -q '^next-cost=Sonnet 5/high$'; check "dispatch: the row's next-cost is reported alongside the command" $?
|
||||
|
||||
# --no-go stops the Go MESSAGE, not the work: the startup command - prompt in
|
||||
|
|
@ -2133,7 +2147,7 @@ mkrepo "$RG_ROOT/repo-rationale-overrides"
|
|||
} > "$RG_ROOT/repo-rationale-overrides/STATE.md"
|
||||
|
||||
RG_PLAN="$("$BOARD" --roots "$RG_ROOT" --plan 2>/dev/null)"
|
||||
RG_CMD='^command=claude --model sonnet --effort high --advisor opus$'
|
||||
RG_CMD='^command=claude --model sonnet --effort high$'
|
||||
|
||||
printf '%s\n' "$RG_PLAN" | grep -A6 '^repo=repo-greedy-rationale$' | grep -q "$RG_CMD"
|
||||
check "route line whose rationale names all four traits still yields a command" $?
|
||||
|
|
@ -3252,6 +3266,187 @@ check "denominator: a missing scan root adds nothing to the counts" $?
|
|||
|
||||
/bin/rm -rf "$DEN_ROOT" "$DEN_COORD" 2>/dev/null
|
||||
|
||||
|
||||
# --- 33. --row <repo>: one machine-readable line per column -----------------
|
||||
# Order 20260912T202210Z-7588027378 (.claude, operator decision 2026-09-12).
|
||||
# The motivation is a measured misreading, not a convenience: on 11.09 the PM
|
||||
# read the FLY column off the table BY EYE and got it wrong. Every other
|
||||
# rendering that a program consumes emits `key=value` for exactly that reason -
|
||||
# the table's fixed-width columns are for a human, and a 34-character repo key
|
||||
# already shifts a row two characters right (a stated, unclosed gap). A repo
|
||||
# holding a value nobody can grep is a repo whose state is read by counting
|
||||
# spaces.
|
||||
#
|
||||
# It is a RENDERING of the scan every other view already ran, never a second
|
||||
# scan - the same rule --brief has carried since it shipped. Two numbers under
|
||||
# one name, computed twice, is the defect this file names most often.
|
||||
#
|
||||
# ONE DEPARTURE, stated rather than smuggled: `upushet=` is not a column the
|
||||
# scan computes, and it is measured here, once, for the named repo only. It is
|
||||
# in the order's field list, it is exactly the kind of fact that gets misread
|
||||
# ("nothing unpushed" vs "not measured"), and measuring it for one repo in a
|
||||
# one-repo rendering is not a scan. It never enters the table, the plan or the
|
||||
# briefing.
|
||||
ROW_ROOT="$(mktemp -d)"
|
||||
ROW_COORD="$(mktemp -d)"
|
||||
|
||||
mkrepo "$ROW_ROOT/row-repo"
|
||||
{
|
||||
echo "# STATE - row-repo"
|
||||
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
|
||||
echo "<!-- board: status=blocked; blocked-on=other-repo; next-cost=Opus 5/high -->"
|
||||
echo "<!-- route: path=known; verification=strong; reversibility=cheap; scope=local; rationale=x -->"
|
||||
echo "The whole next step, well past the 38 characters the table column cuts at."
|
||||
} > "$ROW_ROOT/row-repo/STATE.md"
|
||||
|
||||
# Mailbox fixture: 3 pending messages, 2 pending orders, 1 claimed order. The
|
||||
# three counts are deliberately three DIFFERENT integers, and that is the whole
|
||||
# design of this fixture rather than an arbitrary choice. Built first with
|
||||
# 2/1/1, it was mutation-tested by making `fly` read the ORDRE field - the
|
||||
# exact 2026-09-11 misreading this rendering exists to close - and the check
|
||||
# stayed GREEN, because the two fields held the same digit. A fixture that
|
||||
# cannot tell two columns apart is the defect wearing a passing test, in the
|
||||
# section written to prevent it. With 3/2/1 that mutation turns it red.
|
||||
mkdir -p "$ROW_COORD/row-repo/inbox" "$ROW_COORD/row-repo/orders/claimed"
|
||||
echo "m" > "$ROW_COORD/row-repo/inbox/20260901T101010Z-1-from-x.md"
|
||||
echo "m" > "$ROW_COORD/row-repo/inbox/20260901T101011Z-2-from-x.md"
|
||||
echo "m" > "$ROW_COORD/row-repo/inbox/20260901T101014Z-5-from-x.md"
|
||||
echo "o" > "$ROW_COORD/row-repo/orders/20260901T101012Z-3-from-x.md"
|
||||
echo "o" > "$ROW_COORD/row-repo/orders/20260901T101015Z-6-from-x.md"
|
||||
echo "o" > "$ROW_COORD/row-repo/orders/claimed/20260901T101013Z-4-from-x.md"
|
||||
|
||||
ROW_OUT="$(CLAUDE_COORD_DIR="$ROW_COORD" "$BOARD" --roots "$ROW_ROOT" --row row-repo 2>/dev/null)"; rc=$?
|
||||
[ "$rc" -eq 0 ]; check "row: a known repo exits 0" $?
|
||||
|
||||
printf '%s\n' "$ROW_OUT" | grep -q '^repo=row-repo$'; check "row: repo= is the board key" $?
|
||||
printf '%s\n' "$ROW_OUT" | grep -q "^dir=$ROW_ROOT/row-repo\$"; check "row: dir= is the checkout path" $?
|
||||
printf '%s\n' "$ROW_OUT" | grep -q '^status=blocked$'; check "row: status= is the bare token, not the blocked>target display" $?
|
||||
printf '%s\n' "$ROW_OUT" | grep -q '^blocked-on=other-repo$';check "row: blocked-on= is its own field" $?
|
||||
printf '%s\n' "$ROW_OUT" | grep -q '^next-cost=Opus 5/high$';check "row: next-cost= survives the space and the slash" $?
|
||||
printf '%s\n' "$ROW_OUT" | grep -q '^inn=3$'; check "row: inn= counts pending messages" $?
|
||||
printf '%s\n' "$ROW_OUT" | grep -q '^ordre=2$'; check "row: ordre= counts pending orders" $?
|
||||
printf '%s\n' "$ROW_OUT" | grep -q '^fly=1$'; check "row: fly= counts claimed orders" $?
|
||||
printf '%s\n' "$ROW_OUT" | grep -q '^siste='; check "row: siste= reports the last-commit reading" $?
|
||||
printf '%s\n' "$ROW_OUT" | grep -q '^drt='; check "row: drt= reports the working-tree reading" $?
|
||||
printf '%s\n' "$ROW_OUT" | grep -q '^upushet='; check "row: upushet= is present" $?
|
||||
|
||||
# The three counts are the whole point: FLY was misread as ORDRE, so a rendering
|
||||
# that emitted the same digit under two names would reproduce the defect it
|
||||
# exists to close.
|
||||
[ "$(printf '%s\n' "$ROW_OUT" | grep -c '^\(inn\|ordre\|fly\)=')" -eq 3 ]
|
||||
check "row: inn, ordre and fly are three separate fields" $?
|
||||
|
||||
# NESTE uncut, same argument --brief has: the 38-char cut is the TABLE column's
|
||||
# property, and cutting here would make the cut string the only copy.
|
||||
printf '%s\n' "$ROW_OUT" | grep -q '^neste=.*38 characters the table column cuts at'
|
||||
check "row: neste= carries the whole line, not the table excerpt" $?
|
||||
|
||||
# `neste` is free prose and may contain anything the STATE.md author wrote, so
|
||||
# it is LAST - the same rule the RECORDS line itself obeys. A consumer reading
|
||||
# field N from the end depends on it.
|
||||
[ "$(printf '%s\n' "$ROW_OUT" | tail -1 | cut -d= -f1)" = "neste" ]
|
||||
check "row: neste= is the last line" $?
|
||||
|
||||
# One line per field, every line a field: a value that wrapped would be read as
|
||||
# a field name by anything grepping ^name=.
|
||||
ROW_BAD="$(printf '%s\n' "$ROW_OUT" | grep -v '^[a-z][a-z-]*=' || true)"
|
||||
[ -z "$ROW_BAD" ]; check "row: every line is a field=value line:${ROW_BAD:- clean}" $?
|
||||
|
||||
# ASCII, because the row is consumed by awk/sed/grep under bash 3.2 - the same
|
||||
# constraint every other emitted block in this file carries. Asserted on a
|
||||
# fixture whose own prose is ASCII, so this measures the renderer, not the
|
||||
# STATE.md it happened to read.
|
||||
if printf '%s' "$ROW_OUT" | LC_ALL=C grep -q '[^ -~]'; then rc=1; else rc=0; fi
|
||||
check "row: the output is ASCII" "$rc"
|
||||
if printf '%s' "$ROW_OUT" | LC_ALL=C grep -q '[^ -~]x'; then rc=1; else rc=0; fi
|
||||
check "control: that ASCII grep runs at all (no match on a clean string)" "$rc"
|
||||
|
||||
# A repo whose NESTE is NOT ASCII still emits one line per field. The renderer
|
||||
# cannot make the operator's Norwegian prose ASCII and must never try - the
|
||||
# field NAMES are the machine surface, the value is whatever was written.
|
||||
mkrepo "$ROW_ROOT/row-utf8"
|
||||
{
|
||||
echo "# STATE - row-utf8"
|
||||
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
|
||||
echo "<!-- board: status=planned; blocked-on=-; next-cost=Sonnet 5/high -->"
|
||||
printf 'M\xc3\x85LT i dag: ingenting gjenst\xc3\xa5r.\n'
|
||||
} > "$ROW_ROOT/row-utf8/STATE.md"
|
||||
ROW_U="$(CLAUDE_COORD_DIR="$ROW_COORD" "$BOARD" --roots "$ROW_ROOT" --row row-utf8 2>/dev/null)"
|
||||
ROW_UBAD="$(printf '%s\n' "$ROW_U" | grep -v '^[a-z][a-z-]*=' || true)"
|
||||
[ -z "$ROW_UBAD" ]; check "row: non-ASCII NESTE still yields one field per line" $?
|
||||
printf '%s\n' "$ROW_U" | grep -q '^neste=.*ingenting'
|
||||
check "row: non-ASCII NESTE is carried through, never mangled or dropped" $?
|
||||
|
||||
# An unknown repo must REFUSE. Emitting an empty block would be the same defect
|
||||
# as a bare `command=`: a consumer reading ^status= would get nothing back and
|
||||
# read it as a repo with no status, which is a real and different state ("?").
|
||||
ROW_ERR="$(CLAUDE_COORD_DIR="$ROW_COORD" "$BOARD" --roots "$ROW_ROOT" --row no-such-repo 2>&1)"; rc=$?
|
||||
[ "$rc" -eq 2 ]; check "row: an unknown repo exits 2" $?
|
||||
printf '%s\n' "$ROW_ERR" | grep -q 'no-such-repo'
|
||||
check "row: the refusal names the repo it could not find" $?
|
||||
ROW_ERR_OUT="$(CLAUDE_COORD_DIR="$ROW_COORD" "$BOARD" --roots "$ROW_ROOT" --row no-such-repo 2>/dev/null)"
|
||||
[ -z "$ROW_ERR_OUT" ]; check "row: a refusal writes nothing at all to stdout" $?
|
||||
|
||||
# A missing value is a usage error, not a silently empty row.
|
||||
CLAUDE_COORD_DIR="$ROW_COORD" "$BOARD" --roots "$ROW_ROOT" --row >/dev/null 2>&1
|
||||
[ $? -eq 2 ]; check "row: --row with no value exits 2" $?
|
||||
|
||||
# Read-only, asserted rather than assumed: this is the one property every
|
||||
# rendering in this file shares and the one a new rendering is most likely to
|
||||
# break.
|
||||
ROW_BEFORE="$(find "$ROW_ROOT" "$ROW_COORD" -type f | sort | while read -r f; do printf '%s %s\n' "$f" "$(stat -f %m "$f")"; done)"
|
||||
CLAUDE_COORD_DIR="$ROW_COORD" "$BOARD" --roots "$ROW_ROOT" --row row-repo >/dev/null 2>&1
|
||||
ROW_AFTER="$(find "$ROW_ROOT" "$ROW_COORD" -type f | sort | while read -r f; do printf '%s %s\n' "$f" "$(stat -f %m "$f")"; done)"
|
||||
[ "$ROW_BEFORE" = "$ROW_AFTER" ]; check "row: writes nothing - no file added, removed or touched" $?
|
||||
|
||||
# upushet: the three states must stay distinguishable. This fixture has no
|
||||
# upstream at all, so the honest answer is "not measured", never 0 - the same
|
||||
# rule DRT's ? and coord-count's exit 3 carry. A 0 here would say "nothing is
|
||||
# waiting to be pushed" about a repo that has never had a remote.
|
||||
printf '%s\n' "$ROW_OUT" | grep -q '^upushet=?$'
|
||||
check "row: a repo with no upstream reports upushet=?, never 0" $?
|
||||
|
||||
# Known-positive control, and the case the field exists for: a real upstream
|
||||
# with a real unpushed commit must report the count. Without this the ? above
|
||||
# would pass on a field that can only ever say ?.
|
||||
ROW_UP="$ROW_ROOT/row-upstream"
|
||||
mkrepo "$ROW_UP"
|
||||
{
|
||||
echo "# STATE - row-upstream"
|
||||
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
|
||||
echo "<!-- board: status=planned; blocked-on=-; next-cost=Sonnet 5/high -->"
|
||||
echo "Next step."
|
||||
} > "$ROW_UP/STATE.md"
|
||||
git -C "$ROW_UP" add -A >/dev/null 2>&1
|
||||
git -C "$ROW_UP" commit -qm "state" >/dev/null 2>&1
|
||||
ROW_BARE="$(mktemp -d)/origin.git"
|
||||
git init -q --bare "$ROW_BARE" >/dev/null 2>&1
|
||||
git -C "$ROW_UP" remote add origin "$ROW_BARE" >/dev/null 2>&1
|
||||
git -C "$ROW_UP" push -q -u origin HEAD >/dev/null 2>&1
|
||||
ROW_U0="$(CLAUDE_COORD_DIR="$ROW_COORD" "$BOARD" --roots "$ROW_ROOT" --row row-upstream 2>/dev/null)"
|
||||
printf '%s\n' "$ROW_U0" | grep -q '^upushet=0$'
|
||||
check "row: control - an upstream with everything pushed reports upushet=0" $?
|
||||
echo "more" > "$ROW_UP/extra.txt"
|
||||
git -C "$ROW_UP" add -A >/dev/null 2>&1
|
||||
git -C "$ROW_UP" commit -qm "unpushed work" >/dev/null 2>&1
|
||||
ROW_U1="$(CLAUDE_COORD_DIR="$ROW_COORD" "$BOARD" --roots "$ROW_ROOT" --row row-upstream 2>/dev/null)"
|
||||
printf '%s\n' "$ROW_U1" | grep -q '^upushet=1$'
|
||||
check "row: one unpushed commit reports upushet=1" $?
|
||||
|
||||
# The table is UNCHANGED by all of this. --row is a rendering, so a field that
|
||||
# only exists there must not leak into the view a human reads.
|
||||
ROW_TABLE="$(CLAUDE_COORD_DIR="$ROW_COORD" "$BOARD" --roots "$ROW_ROOT" 2>/dev/null)"
|
||||
if printf '%s' "$ROW_TABLE" | grep -qi 'upushet'; then rc=1; else rc=0; fi
|
||||
check "row: upushet does not leak into the table" "$rc"
|
||||
|
||||
# Structural, in the shape this file already uses for "no write path exists":
|
||||
# --row must not run its own repo discovery. A second scan is the defect the
|
||||
# rendering rule exists to prevent, and a behavioural test cannot see it.
|
||||
grep -q -- '--row' "$BOARD"; check "row: board.sh actually carries the --row flag" $?
|
||||
|
||||
/bin/rm -rf "$ROW_ROOT" "$ROW_COORD" 2>/dev/null
|
||||
|
||||
|
||||
echo ""
|
||||
echo "board-selftest: $PASS passed, $FAIL failed"
|
||||
[ "$FAIL" -eq 0 ] || exit 1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue