feat(board)!: rank --plan on five ordered groups, planned above in-progress
Replaces the weighted score shipped in 0.19.0 with five lookups: chain-root credit, unhandled inbox, planned, in-progress, undeclared status. Within a group: that group's own quantity, then a Sonnet next-cost, then oldest plan. The score's objection is accepted, not forgotten, and is written into board.sh and CLAUDE.md so a later session reads it as decided rather than as an unfixed defect: a group order cannot express "owes one message AND releases two others" as one quantity. What the score could not do was hold still for the format's second consumer - re-tuning one weight against another silently reorders a parser in another repo, and no test here can catch that. planned now ranks above in-progress, inverted by the same decision: converting a decision into motion is the slow step; live work is already moving. Debt stays uncapped and never excluded. One group below chain-root credit is not the cap declined at 0.19.0 - the debtor keeps its tab, its most-owed-first position, and its why=inbox:N. Pinned by a discriminating fixture the score would fail: a root releasing one repo outranks a repo owing four. board-selftest 134 -> 138. Suite 183 + 138 + 73 = 394. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y6ULuFCPMNYAPNN3pAjsXQ
This commit is contained in:
parent
e5e9cbe847
commit
d0a5ffe515
10 changed files with 287 additions and 118 deletions
|
|
@ -591,10 +591,18 @@ check "a BLOCKED repo that owes mail is still planned (debt is the other axis)"
|
|||
printf '%s\n' "$PLAN" | grep -A4 '^repo=repo-blocked-owes$' | grep -q '^why=inbox:2$'
|
||||
check "a blocked repo in the plan says debt, not status, is why it is there" $?
|
||||
|
||||
# Debt before live work: repo-h is in-progress and owes nothing.
|
||||
# Debt before live work: repo-h is in-progress and owes nothing. Stated as
|
||||
# group 2 over group 4, NOT as "before any that owes none" - since 0.20.0 the
|
||||
# chain-root group sits above debt, so a repo owing nothing CAN outrank one that
|
||||
# does. Section 12 pins that half on the fixture that shows it cleanly.
|
||||
n_h="$(printf '%s\n' "$PLAN" | grep -n '^repo=repo-h$' | cut -d: -f1)"
|
||||
[ -n "$n_h" ] && [ "$n_ow" -lt "$n_h" ]
|
||||
check "every repo owing mail is planned before any that owes none" $?
|
||||
check "a repo owing mail is planned before live work that owes and releases nothing" $?
|
||||
|
||||
# Group 2 over group 3: repo-g is planned and owes nothing.
|
||||
n_g="$(printf '%s\n' "$PLAN" | grep -n '^repo=repo-g$' | cut -d: -f1)"
|
||||
[ -n "$n_g" ] && [ "$n_ow" -lt "$n_g" ]
|
||||
check "a repo owing mail is planned before a repo that merely has a plan" $?
|
||||
|
||||
# repo-a is BOTH in-progress and owing. It must appear exactly once - a repo
|
||||
# listed twice is two tabs for one repo, which is the plan failing at its job.
|
||||
|
|
@ -602,17 +610,28 @@ check "every repo owing mail is planned before any that owes none" $?
|
|||
check "a repo qualifying under two rules is planned exactly once" $?
|
||||
|
||||
# repo-a owes 3 messages AND is the blocker plug-x and repo-blocked-owes both
|
||||
# name. why= reports the DOMINANT term, so it says what a session there would
|
||||
# release rather than what it owes - the whole reason this field was changed.
|
||||
# Before chain-root credit existed this read `inbox:3`, and that was the line
|
||||
# eleven blocks repeated verbatim.
|
||||
# name. Under the group form why= names the GROUP that put the repo in the plan,
|
||||
# and the chain-root group is the first one tested - so it reports what a session
|
||||
# there would release rather than what it owes. Between 0.19.0 and 0.20.0 the
|
||||
# same assertion held for a different reason (the dominant term of a score);
|
||||
# the reason is written down because the check passes either way and only the
|
||||
# reason says which form is running.
|
||||
printf '%s\n' "$PLAN" | grep -A3 '^repo=repo-a$' | grep -q '^why=unblocks:2$'
|
||||
check "why= names the dominant reason, releasing over owing when it dominates" $?
|
||||
check "why= names the group that planned the repo, releasing over owing" $?
|
||||
|
||||
# in-progress outranks planned among the repos owing nothing.
|
||||
n_g="$(printf '%s\n' "$PLAN" | grep -n '^repo=repo-g$' | cut -d: -f1)"
|
||||
[ -n "$n_g" ] && [ "$n_h" -lt "$n_g" ]
|
||||
check "live work (in-progress) is planned before merely planned work" $?
|
||||
# planned outranks in-progress among the repos that neither owe nor release.
|
||||
# INVERTED at 0.20.0 by operator decision: a decided-but-unstarted next step is
|
||||
# the step that converts a decision into motion, and live work is already moving.
|
||||
# This is a policy call, not a preference - it is recorded here and in board.sh
|
||||
# so a later session cannot read it as a sort that drifted.
|
||||
[ -n "$n_g" ] && [ "$n_g" -lt "$n_h" ]
|
||||
check "planned work is planned before live in-progress work (operator inversion)" $?
|
||||
|
||||
# Group 4 over group 5: repo-e declares an out-of-set status token and lands in
|
||||
# the undeclared group, which is planned LAST and never dropped.
|
||||
n_e="$(printf '%s\n' "$PLAN" | grep -n '^repo=repo-e$' | cut -d: -f1)"
|
||||
[ -n "$n_e" ] && [ "$n_h" -lt "$n_e" ]
|
||||
check "a repo with no declared status is planned after live work, not dropped" $?
|
||||
|
||||
# Excluded classes. A tab for a done or deferred repo is noise; a tab for a
|
||||
# blocked repo that owes nothing cannot be moved at all.
|
||||
|
|
@ -896,9 +915,9 @@ mkrepo "$ROOT/chain-root"
|
|||
{
|
||||
echo "# STATE - chain-root"
|
||||
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
|
||||
# Deliberately `planned`, not `in-progress`: under the old four-bucket order
|
||||
# that puts the root BELOW every live repo, so the ranking check below fails
|
||||
# for the right reason instead of passing on fixture order.
|
||||
# Deliberately `planned`, not `in-progress`: the root must earn its position
|
||||
# from the chain-root group alone, never from the status group, so the ranking
|
||||
# checks below fail for the right reason instead of passing on fixture order.
|
||||
echo "<!-- board: status=planned; blocked-on=-; next-cost=Opus 5/high -->"
|
||||
printf 'Roten %s ingen gjeld, men holder to repo oppe.\n' "$EMDASH"
|
||||
} > "$ROOT/chain-root/STATE.md"
|
||||
|
|
@ -948,6 +967,43 @@ mkrepo "$ROOT/dangle"
|
|||
echo "Venter paa noe som ikke finnes."
|
||||
} > "$ROOT/dangle/STATE.md"
|
||||
|
||||
# THE DISCRIMINATING PAIR for the 0.20.0 group form. Every other ordering check
|
||||
# in this section passes under BOTH the 0.19.0 score and the group form, because
|
||||
# chain-root releases two repos and 40*2 beats any debt in this tree - it would
|
||||
# have gone green while the operator's decision quietly failed to ship.
|
||||
#
|
||||
# These two are built so the forms DISAGREE. solo-root releases exactly one repo
|
||||
# and owes nothing (score: 40 + 5 planned = 45). heavy-debtor owes four (score:
|
||||
# 60 + 10 in-progress = 70). The score ranks the debtor first; the group form
|
||||
# ranks the root first, because releasing is group 1 and debt is group 2.
|
||||
mkrepo "$ROOT/solo-root"
|
||||
{
|
||||
echo "# STATE - solo-root"
|
||||
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
|
||||
echo "<!-- board: status=planned; blocked-on=-; next-cost=Opus 5/high -->"
|
||||
printf 'Losner ett repo, skylder ingenting.\n'
|
||||
} > "$ROOT/solo-root/STATE.md"
|
||||
|
||||
mkrepo "$ROOT/solo-leaf"
|
||||
{
|
||||
echo "# STATE - solo-leaf"
|
||||
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
|
||||
echo "<!-- board: status=blocked; blocked-on=solo-root; next-cost=Opus 5/high -->"
|
||||
printf 'Venter p%s solo-root.\n' "$EMDASH"
|
||||
} > "$ROOT/solo-leaf/STATE.md"
|
||||
|
||||
mkrepo "$ROOT/heavy-debtor"
|
||||
{
|
||||
echo "# STATE - heavy-debtor"
|
||||
printf '## %s NESTE %s START HER\n' "$HAND" "$EMDASH"
|
||||
echo "<!-- board: status=in-progress; blocked-on=-; next-cost=Opus 5/high -->"
|
||||
printf 'Skylder fire svar, losner ingen.\n'
|
||||
} > "$ROOT/heavy-debtor/STATE.md"
|
||||
mkdir -p "$CLAUDE_COORD_DIR/heavy-debtor/inbox"
|
||||
for n in 1 2 3 4; do
|
||||
echo "msg" > "$CLAUDE_COORD_DIR/heavy-debtor/inbox/2026-msg$n-from-v.md"
|
||||
done
|
||||
|
||||
P2="$("$BOARD" --roots "$ROOT" --plan 2>/dev/null)"; rc=$?
|
||||
check "--plan still exits 0 with chain, cycle and dangling fixtures present" "$rc"
|
||||
|
||||
|
|
@ -973,6 +1029,22 @@ n2_h="$(printf '%s\n' "$P2" | grep -n '^repo=repo-h$' | cut -d: -f1)"
|
|||
[ -n "$n2_cr" ] && [ -n "$n2_h" ] && [ "$n2_cr" -lt "$n2_h" ]
|
||||
check "a chain root ranks above live work that releases nothing" $?
|
||||
|
||||
# THE decisive check for the 0.20.0 group form - the discriminating pair built
|
||||
# above. solo-root releases ONE and owes nothing; heavy-debtor owes FOUR. This is
|
||||
# the only ordering assertion in the file that the 0.19.0 score would fail, so it
|
||||
# is the one that proves which form is actually running. Debt is still neither
|
||||
# capped nor excluded here - it is one group lower, not down-weighted.
|
||||
n2_sr="$(printf '%s\n' "$P2" | grep -n '^repo=solo-root$' | cut -d: -f1)"
|
||||
n2_hd="$(printf '%s\n' "$P2" | grep -n '^repo=heavy-debtor$' | cut -d: -f1)"
|
||||
[ -n "$n2_sr" ] && [ -n "$n2_hd" ] && [ "$n2_sr" -lt "$n2_hd" ]
|
||||
check "releasing ONE repo outranks owing FOUR (group form, not the score)" $?
|
||||
|
||||
# The other half of the same rule: the debtor is still IN the plan, and still
|
||||
# says debt is why. A group form that ranked debt lower by dropping it would be
|
||||
# the excluded-debt defect wearing the operator's decision as a disguise.
|
||||
printf '%s\n' "$P2" | grep -A3 '^repo=heavy-debtor$' | grep -q '^why=inbox:4$'
|
||||
check "a repo outranked by a chain root still keeps its tab and its why=" $?
|
||||
|
||||
# A cycle terminates and credits nobody. Both halves matter: hanging is the
|
||||
# failure everyone imagines, but silently inventing a root is the one that would
|
||||
# ship - it looks like a working plan.
|
||||
|
|
@ -989,9 +1061,9 @@ check "a dangling blocked-on target is never planned into existence" $?
|
|||
printf '%s' "$P2" | grep -q '^repo=dangle$'; [ $? -ne 0 ]
|
||||
check "the repo carrying a dangling blocked-on is itself still excluded" $?
|
||||
|
||||
# The format is the API. Adding a scoring rule must not move, rename or drop a
|
||||
# single field - the driver parses these keys positionally-independently, but it
|
||||
# parses THESE keys.
|
||||
# The format is the API. Changing the ranking form must not move, rename or drop
|
||||
# a single field - the driver parses these keys positionally-independently, but
|
||||
# it parses THESE keys.
|
||||
n2_tab="$(printf '%s\n' "$P2" | grep -c '^tab=')"
|
||||
n2_rep="$(printf '%s\n' "$P2" | grep -c '^repo=')"
|
||||
n2_dir="$(printf '%s\n' "$P2" | grep -c '^dir=')"
|
||||
|
|
@ -1003,10 +1075,10 @@ n2_cms="$(printf '%s\n' "$P2" | grep -c '^command_missing=')"
|
|||
[ "$n2_tab" -gt 0 ] && [ "$n2_rep" -eq "$n2_tab" ] && [ "$n2_dir" -eq "$n2_tab" ] \
|
||||
&& [ "$n2_why" -eq "$n2_tab" ] && [ "$n2_sta" -eq "$n2_tab" ] \
|
||||
&& [ "$n2_nes" -eq "$n2_tab" ] && [ $(( n2_cmd + n2_cms )) -eq "$n2_tab" ]
|
||||
check "scored plan still carries every documented field exactly once per block" $?
|
||||
check "ranked plan still carries every documented field exactly once per block" $?
|
||||
|
||||
printf '%s' "$P2" | grep -q '^command=$'; [ $? -ne 0 ]
|
||||
check "scored plan never emits an empty command= line" $?
|
||||
check "ranked plan never emits an empty command= line" $?
|
||||
|
||||
# Debt still puts a repo in the plan and still names itself when it is the
|
||||
# dominant reason. Rejecting the proposed cap on debt was a deliberate call:
|
||||
|
|
@ -1016,12 +1088,12 @@ check "debt still names itself in why= when it is the dominant reason" $?
|
|||
|
||||
# --brief is a second RENDERING of the same scan and must survive the change.
|
||||
"$BOARD" --roots "$ROOT" --brief >/dev/null 2>&1
|
||||
check "--brief still exits 0 after the scoring change" $?
|
||||
check "--brief still exits 0 after the ranking change" $?
|
||||
|
||||
# The plan must still print the scan whole. There is no cutoff by design, so a
|
||||
# consumer's own tab cap is the only thing that ever hides a repo.
|
||||
[ "$n2_tab" -ge "$n_tab" ]
|
||||
check "the scored plan hides nothing the bucketed plan showed" $?
|
||||
check "the grouped plan hides nothing an earlier ordering showed" $?
|
||||
|
||||
echo ""
|
||||
echo "board-selftest: $PASS passed, $FAIL failed"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue