feat(board): FLY column and free-capacity lines, no process inspection
ORDRE counted pending orders only, so a repo with one order in flight and a repo with no orders at all both printed 0 - the same digit for two opposite facts. Measured 2026-08-23: two panes stood open and idle for 45 hours holding finished orders, with full quota authorised, and no column on the board reported it. FLY counts orders/claimed/ - the same queue in its other state, never summed with ORDRE and never a fourth axis. It does NOT mean a session is alive: nothing un-claims an order when the claiming session dies, and one order on the live mailbox had been claimed for 117 hours. The legend denies the liveness reading in those words, pinned as a check on the legend text. --plan now names free capacity as ledig_antall=N plus one ledig=<repo> (<status>) line per repo with nothing owed, no pending order, nothing in flight, a clean tree, at done or deferred. All four conditions are required: measured on the real tree, 4 of 17 done/deferred repos were not free. Lines, never blocks - the plan's second consumer discards a block with no tab=, so a block would be visible to the operator and invisible to the driver. Process inspection was considered and refused; the selftest asserts the absence of pgrep/pkill/lsof structurally with a known-positive control. The full argument, and the gap left open, are in docs/2026-08-23-free-capacity-investigation.md. board-selftest: 259 -> 281 checks, all green. npm test 11/11. Order 20260823T162951Z-941745020-from-.claude Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hfbfr8ERC63kuAfWeHYHQb
This commit is contained in:
parent
2377735554
commit
3beef2a603
12 changed files with 532 additions and 25 deletions
|
|
@ -2141,6 +2141,148 @@ check "--brief recovers the command too (route_cmd_for has one reader)" $?
|
|||
|
||||
/bin/rm -rf "$RG_ROOT" 2>/dev/null
|
||||
|
||||
|
||||
# --- 24. FLY (claimed orders) and --plan's free-capacity reading ------------
|
||||
# Order 20260823T162951Z (.claude, 2026-08-23): ORDRE counted PENDING orders
|
||||
# only, so a repo with one order IN FLIGHT and a repo with no orders at all
|
||||
# both printed 0 - the same digit for two opposite facts ("work is happening
|
||||
# here" vs "nothing is waiting here"). Measured on the live tree the day the
|
||||
# order was written: two tabs stood open and idle for 45 hours holding
|
||||
# finished orders while no column on the board reported it.
|
||||
#
|
||||
# FLY is NOT a fourth axis and never claims a session is alive. It counts
|
||||
# files in orders/claimed/ - the same order queue ORDRE already reads, in its
|
||||
# other state. Measured counter-example, live mailbox 2026-08-23: wiki-advise
|
||||
# held an order claimed for 117 hours. A claim is evidence that a session took
|
||||
# the order, never proof one is still working it, and the legend says so.
|
||||
FLY_ROOT="$(mktemp -d)"
|
||||
mkfly() { # name status
|
||||
mkrepo "$FLY_ROOT/$1"
|
||||
{
|
||||
echo "# STATE - $1"
|
||||
echo ""
|
||||
printf '## %s NESTE\n' "$HAND"
|
||||
echo "<!-- board: status=$2; blocked-on=-; next-cost=Sonnet 5/high -->"
|
||||
echo "<!-- route: path=known; verification=strong; reversibility=cheap; scope=local; rationale=x -->"
|
||||
echo "Next step for $1."
|
||||
} > "$FLY_ROOT/$1/STATE.md"
|
||||
# COMMITTED, deliberately: `mkrepo` alone leaves STATE.md untracked, so every
|
||||
# fixture repo would read DRT=1 - which silently satisfied the FLY column
|
||||
# assertions below before the column existed (the regex matched DRT's 1 where
|
||||
# it expected FLY's), and would make every repo permanently un-free under the
|
||||
# clean-tree condition. A dirty fixture is created explicitly where one is
|
||||
# wanted, never inherited.
|
||||
git -C "$FLY_ROOT/$1" add -A >/dev/null 2>&1
|
||||
git -C "$FLY_ROOT/$1" -c user.email=t@t -c user.name=t commit -qm init >/dev/null 2>&1
|
||||
}
|
||||
mkorder() { # mailbox state(pending|claimed) id
|
||||
mkdir -p "$CLAUDE_COORD_DIR/$1/orders/claimed"
|
||||
if [ "$2" = claimed ]; then f="$CLAUDE_COORD_DIR/$1/orders/claimed/$3.md"
|
||||
else f="$CLAUDE_COORD_DIR/$1/orders/$3.md"; fi
|
||||
printf -- '---\nfrom: d\nto: %s\norder-id: %s\nsubject: s\n---\nbody\n' "$1" "$3" > "$f"
|
||||
}
|
||||
|
||||
# THE defect, isolated: identical ORDRE, opposite meanings.
|
||||
mkfly fly-inflight planned; mkorder fly-inflight claimed 20260101T000000Z-1-from-d
|
||||
mkfly fly-empty planned
|
||||
# Both states at once, so the two counts are provably read from different dirs.
|
||||
mkfly fly-mixed planned
|
||||
mkorder fly-mixed pending 20260102T000000Z-2-from-d
|
||||
mkorder fly-mixed pending 20260103T000000Z-3-from-d
|
||||
mkorder fly-mixed claimed 20260104T000000Z-4-from-d
|
||||
|
||||
FLY_OUT="$("$BOARD" --roots "$FLY_ROOT" 2>/dev/null)"
|
||||
printf '%s' "$FLY_OUT" | grep -q 'FLY'; check "table header carries a FLY column" $?
|
||||
printf '%s' "$FLY_OUT" | grep -qE '^fly-mixed[[:space:]]+planned[[:space:]]+Sonnet 5/high[[:space:]]+0[[:space:]]+2[[:space:]]+1[[:space:]]'
|
||||
check "ORDRE 2 and FLY 1 print side by side, never summed into 3" $?
|
||||
printf '%s' "$FLY_OUT" | grep -qE '^fly-inflight[[:space:]]+planned[[:space:]]+Sonnet 5/high[[:space:]]+0[[:space:]]+0[[:space:]]+1[[:space:]]'
|
||||
check "an order in flight reads ORDRE 0 / FLY 1, not ORDRE 0 alone" $?
|
||||
printf '%s' "$FLY_OUT" | grep -qE '^fly-empty[[:space:]]+planned[[:space:]]+Sonnet 5/high[[:space:]]+0[[:space:]]+0[[:space:]]+0[[:space:]]'
|
||||
check "known-positive: a repo with no orders at all still reads 0 in both" $?
|
||||
printf '%s' "$FLY_OUT" | grep -q 'Next step for fly-mixed'
|
||||
check "NESTE still renders after the second field insertion" $?
|
||||
# The legend must refuse the liveness reading outright - a column that looked
|
||||
# like "a session is running here" would be the process axis smuggled in as a
|
||||
# file count, and wiki-advise's 117-hour claim is why that reading is false.
|
||||
printf '%s' "$FLY_OUT" | grep -qi 'FLY = '
|
||||
check "the legend defines FLY" $?
|
||||
printf '%s' "$FLY_OUT" | grep -qiE 'FLY.*(ikke|aldri).*(lever|kj[^ ]*r|aktiv)'
|
||||
check "the legend denies that FLY proves a session is alive" $?
|
||||
|
||||
# --- --plan: free capacity is NAMED, never turned into a tab ---------------
|
||||
# The operator's actual question ("which repos are finished and can take more
|
||||
# work") has an answer in fields the scan already reads, and it is not
|
||||
# status=done alone: measured on the real tree 2026-08-23, 4 of 17 done/
|
||||
# deferred repos were NOT free (2 held a pending order, 1 owed a reply, 1 had
|
||||
# an uncommitted tree). All four conditions are required.
|
||||
mkfly fly-free done
|
||||
mkfly fly-busy-order done; mkorder fly-busy-order pending 20260105T000000Z-5-from-d
|
||||
mkfly fly-busy-fly done; mkorder fly-busy-fly claimed 20260106T000000Z-6-from-d
|
||||
mkfly fly-busy-mail done
|
||||
mkdir -p "$CLAUDE_COORD_DIR/fly-busy-mail/inbox"
|
||||
printf -- '---\nfrom: x\nto: fly-busy-mail\nsubject: m\nreply-expected: yes\n---\nbody\n' \
|
||||
> "$CLAUDE_COORD_DIR/fly-busy-mail/inbox/20260107T000000Z-7-from-x.md"
|
||||
mkfly fly-busy-dirty done
|
||||
echo "uncommitted" > "$FLY_ROOT/fly-busy-dirty/scratch.txt"
|
||||
mkfly fly-free-def deferred
|
||||
|
||||
FLY_PLAN="$("$BOARD" --roots "$FLY_ROOT" --plan 2>/dev/null)"
|
||||
printf '%s\n' "$FLY_PLAN" | grep -qE '^ledig=fly-free \(done\)$'
|
||||
check "plan names a genuinely free repo with its status" $?
|
||||
printf '%s\n' "$FLY_PLAN" | grep -qE '^ledig=fly-free-def \(deferred\)$'
|
||||
check "plan names a deferred repo as free, labelled deferred rather than merged into done" $?
|
||||
printf '%s\n' "$FLY_PLAN" | grep -q '^ledig=fly-busy-order'; [ $? -ne 0 ]
|
||||
check "a done repo holding a pending order is not free" $?
|
||||
printf '%s\n' "$FLY_PLAN" | grep -q '^ledig=fly-busy-fly'; [ $? -ne 0 ]
|
||||
check "a done repo with an order in flight is not free" $?
|
||||
printf '%s\n' "$FLY_PLAN" | grep -q '^ledig=fly-busy-mail'; [ $? -ne 0 ]
|
||||
check "a done repo owing a reply is not free" $?
|
||||
printf '%s\n' "$FLY_PLAN" | grep -q '^ledig=fly-busy-dirty'; [ $? -ne 0 ]
|
||||
check "a done repo with an uncommitted tree is not free" $?
|
||||
# A count, so zero is an ANSWER and not an absence - the same rule fokus_utenfor
|
||||
# already follows with its "(ingen)" placeholder.
|
||||
printf '%s\n' "$FLY_PLAN" | grep -qE '^ledig_antall=2$'
|
||||
check "plan states how many free repos it found" $?
|
||||
# The plan's second consumer opens a tab per block; plan_parse discards a block
|
||||
# with no tab=, so a free repo emitted as a BLOCK would be invisible to the
|
||||
# driver. A single key=value line is visible to both and can never be opened.
|
||||
printf '%s\n' "$FLY_PLAN" | grep -A2 '^ledig=fly-free ' | grep -q '^tab='; [ $? -ne 0 ]
|
||||
check "a free repo is never emitted as a tab block" $?
|
||||
printf '%s\n' "$FLY_PLAN" | grep -q '^repo=fly-free$'; [ $? -ne 0 ]
|
||||
check "a free repo does not enter the tab list at all" $?
|
||||
# A repo the plan DOES open a tab for may already hold a claimed order: the
|
||||
# driver must be able to see that before typing into a live pane.
|
||||
printf '%s\n' "$FLY_PLAN" | grep -A6 '^repo=fly-inflight$' | grep -qE '^fly=1$'
|
||||
check "a planned repo with an order in flight carries fly=1 in its block" $?
|
||||
printf '%s\n' "$FLY_PLAN" | grep -A6 '^repo=fly-empty$' | grep -q '^fly='; [ $? -ne 0 ]
|
||||
check "known-positive: a planned repo with nothing in flight carries no fly= line" $?
|
||||
|
||||
# Zero free repos must still print the count line, or "none found" and "not
|
||||
# computed" become the same output - Verifiseringslovens ansikt 4.
|
||||
FLY_ROOT2="$(mktemp -d)"
|
||||
FLY_SAVE="$FLY_ROOT"; FLY_ROOT="$FLY_ROOT2"
|
||||
mkfly fly-only-planned planned
|
||||
FLY_ROOT="$FLY_SAVE"
|
||||
FLY_PLAN2="$("$BOARD" --roots "$FLY_ROOT2" --plan 2>/dev/null)"
|
||||
printf '%s\n' "$FLY_PLAN2" | grep -qE '^ledig_antall=0$'
|
||||
check "a tree with no free repo still states the count (zero is an answer)" $?
|
||||
printf '%s\n' "$FLY_PLAN2" | grep -q '^ledig='; [ $? -ne 0 ]
|
||||
check "a tree with no free repo emits no ledig= line" $?
|
||||
/bin/rm -rf "$FLY_ROOT2" 2>/dev/null
|
||||
|
||||
# board.sh must not have grown a process-inspection path. The three axes are
|
||||
# durable filesystem facts reproducible in this fixture tree; a pgrep/ps/lsof
|
||||
# column would measure the operator's machine at one instant, could not be
|
||||
# pinned here at all, and would make the engine decide a session is dead -
|
||||
# which CLAUDE.md already forbids the order queue from doing.
|
||||
grep -nE '(^|[^-[:alnum:]_])(pgrep|pkill|lsof)([^-[:alnum:]_]|$)' "$DIR/board.sh" | grep -qv '^[0-9]*:#'; [ $? -ne 0 ]
|
||||
check "board.sh inspects no processes (no live pgrep/pkill/lsof)" $?
|
||||
printf 'x\npgrep claude\n' > "$FLY_ROOT/known-positive.txt"
|
||||
grep -qE '(^|[^-[:alnum:]_])pgrep([^-[:alnum:]_]|$)' "$FLY_ROOT/known-positive.txt"
|
||||
check "known-positive: the process-inspection grep can find a planted pgrep call" $?
|
||||
|
||||
/bin/rm -rf "$FLY_ROOT" 2>/dev/null
|
||||
|
||||
echo ""
|
||||
echo "board-selftest: $PASS passed, $FAIL failed"
|
||||
[ "$FAIL" -eq 0 ] || exit 1
|
||||
|
|
|
|||
128
scripts/board.sh
128
scripts/board.sh
|
|
@ -9,6 +9,21 @@
|
|||
# STATE.md board line - optional machine-readable field (see below)
|
||||
# git status --porcelain - uncommitted risk
|
||||
# git log -1 --format=%ct - when anything last landed (the SISTE column)
|
||||
# ~/.claude/coord/<repo>/orders - PENDING orders (the ORDRE column)
|
||||
# ~/.claude/coord/<repo>/orders/claimed - orders IN FLIGHT (the FLY column).
|
||||
# Same queue, other state - not a fourth axis.
|
||||
# It exists because ORDRE alone printed the same
|
||||
# digit for two opposite facts: one order in
|
||||
# flight and no orders at all both read 0. FLY
|
||||
# never claims a session is ALIVE: nothing
|
||||
# un-claims an order when the session that took
|
||||
# it dies (measured 2026-08-23: one order held
|
||||
# claimed for 117 hours). There is deliberately
|
||||
# NO process inspection here - pgrep/ps/lsof
|
||||
# would measure the operator's machine at one
|
||||
# instant, could not be pinned in a fixture tree,
|
||||
# and would make this script decide a session is
|
||||
# dead, which it cannot know.
|
||||
# ~/.claude/coord/<repo>/inbox - UNHANDLED INBOUND: others addressed this
|
||||
# repo and it has not processed them. This is an
|
||||
# obligation the repo owes outward - NOT evidence
|
||||
|
|
@ -81,6 +96,19 @@
|
|||
# Within a group: the quantity that group is about (released, then owed), then a
|
||||
# Sonnet next-cost (cheap to move under quota pressure), then oldest plan first.
|
||||
#
|
||||
# --plan also NAMES free capacity, as `ledig_antall=N` plus one `ledig=<repo>
|
||||
# (<status>)` line per repo, and never as a block. A repo with nothing owed,
|
||||
# nothing queued, nothing in flight and a clean tree, at status done or
|
||||
# deferred, has no next step to open a tab for - it used to just fall out of
|
||||
# the plan, which is where new capacity went unseen. All four conditions are
|
||||
# required: status=done alone is not one of them (measured 2026-08-23, 4 of 17
|
||||
# done/deferred repos were not free). It is a LINE and not a block on purpose:
|
||||
# plan_parse discards a block with no `tab=`, so a block would be visible to
|
||||
# the operator and invisible to the driver, while a line is visible to both and
|
||||
# can never be opened as a tab. The count prints even at 0, so "none found" and
|
||||
# "not computed" cannot render the same. A tab block whose repo holds a claimed
|
||||
# order additionally carries `fly=N` - the driver types into live panes.
|
||||
#
|
||||
# 0.19.0 shipped a weighted score here instead, and 0.20.0 replaced it. The score
|
||||
# expressed one thing this cannot - "owes one message AND releases two others" as
|
||||
# a single quantity - and the operator accepted losing that. What a score could
|
||||
|
|
@ -309,7 +337,7 @@ done
|
|||
[ -n "$(printf '%s' "$REPOS" | tr -d '[:space:]')" ] || exit 0
|
||||
|
||||
# --- Collect one record per repo -------------------------------------------
|
||||
# Record: bucket|sortkey|name|status|cost|inbox|dirty|age|last|dir|blockedon|orders|neste
|
||||
# Record: bucket|sortkey|name|status|cost|inbox|dirty|age|last|dir|blockedon|orders|claimed|neste
|
||||
RECORDS=""
|
||||
MALFORMED=""
|
||||
|
||||
|
|
@ -344,6 +372,30 @@ printf '%s\n' "$REPOS" | while IFS= read -r d; do
|
|||
[ -n "$orders" ] || orders=0
|
||||
fi
|
||||
|
||||
# CLAIMED orders, counted separately and never added to the one above. Same
|
||||
# queue, other state - not a fourth axis, which is why it is a second reading
|
||||
# of orders/ rather than a new source. It exists because ORDRE alone printed
|
||||
# the SAME DIGIT for two opposite facts: a repo with one order in flight and a
|
||||
# repo with no orders at all both read 0, so "work is happening here" and
|
||||
# "nothing is waiting here" were indistinguishable (order 20260823T162951Z,
|
||||
# measured on the live tree: two tabs idle 45 hours holding finished orders,
|
||||
# and no column reported it).
|
||||
#
|
||||
# What this count does NOT mean, and must never be reworded into: that a
|
||||
# session is alive. A claim is a `mv` a session performed once; nothing
|
||||
# un-claims it when that session dies, which is exactly why the order queue's
|
||||
# read path keeps showing claimed orders with their in-flight age. Measured
|
||||
# on the live mailbox the same day: wiki-advise held an order claimed for 117
|
||||
# hours. FLY is evidence that someone took the order, never proof anyone is
|
||||
# still working it - the legend says so in those words, because a column that
|
||||
# read as "a session is running here" would be the process axis smuggled in
|
||||
# as a file count.
|
||||
claimed=0
|
||||
if [ -d "$COORD/$name/orders/claimed" ]; then
|
||||
claimed="$(ls "$COORD/$name/orders/claimed"/*.md 2>/dev/null | wc -l | tr -d ' ')"
|
||||
[ -n "$claimed" ] || claimed=0
|
||||
fi
|
||||
|
||||
# Read for EVERY repo, not just the STATE-less ones: a repo whose plan file
|
||||
# is fresh can still have been silent for a year, and that is precisely the
|
||||
# repo no other column reports. A repo with no commits at all has no reading
|
||||
|
|
@ -359,8 +411,8 @@ printf '%s\n' "$REPOS" | while IFS= read -r d; do
|
|||
# No plan file, so no plan age: ALDER is blank rather than quietly showing
|
||||
# the commit age under a heading that means something else everywhere else
|
||||
# in the table. The sort key keeps using it - order is unchanged.
|
||||
printf '5|%06d|%s|-|-|%s|%s|-|%s|%s|-|%s|(ingen STATE.md)\n' \
|
||||
"$lastd" "$name" "$inbox" "$dirty" "$lastcol" "$d" "$orders"
|
||||
printf '5|%06d|%s|-|-|%s|%s|-|%s|%s|-|%s|%s|(ingen STATE.md)\n' \
|
||||
"$lastd" "$name" "$inbox" "$dirty" "$lastcol" "$d" "$orders" "$claimed"
|
||||
continue
|
||||
fi
|
||||
|
||||
|
|
@ -449,9 +501,9 @@ printf '%s\n' "$REPOS" | while IFS= read -r d; do
|
|||
# `orders` sits between blockedon and neste, never after it: `neste` is free
|
||||
# prose lifted out of a STATE.md and may contain a literal '|', so it has to
|
||||
# stay the last field on the line.
|
||||
printf '%s|%06d|%s|%s|%s|%s|%s|%sd|%s|%s|%s|%s|%s\n' \
|
||||
printf '%s|%06d|%s|%s|%s|%s|%s|%sd|%s|%s|%s|%s|%s|%s\n' \
|
||||
"$bucket" "$age" "$name" "$disp" "$cost" "$inbox" "$dirty" "$age" "$lastcol" "$d" \
|
||||
"${blockedon:--}" "$orders" "$neste"
|
||||
"${blockedon:--}" "$orders" "$claimed" "$neste"
|
||||
done > "${TMPDIR:-/tmp}/board.$$"
|
||||
|
||||
RECORDS="${TMPDIR:-/tmp}/board.$$"
|
||||
|
|
@ -558,15 +610,15 @@ awk -F'|' '$4 ~ /^blocked/ && $11 != "-" && $11 != "" {print $11}' "$RECORDS" \
|
|||
|
||||
hdr() {
|
||||
printf '\n%s\n' "$1"
|
||||
printf '%-32s %-34s %-14s %4s %6s %4s %6s %6s %s\n' \
|
||||
"REPO" "STATUS" "KOST" "INN" "ORDRE" "DRT" "ALDER" "SISTE" "NESTE"
|
||||
printf '%-32s %-34s %-14s %4s %6s %4s %4s %6s %6s %s\n' \
|
||||
"REPO" "STATUS" "KOST" "INN" "ORDRE" "FLY" "DRT" "ALDER" "SISTE" "NESTE"
|
||||
}
|
||||
|
||||
rows() {
|
||||
awk -F'|' -v b="$1" '$1==b' "$RECORDS" | sort -t'|' -k2,2n | \
|
||||
while IFS='|' read -r bucket sortkey name status cost inbox dirty age last dir blockedon orders neste; do
|
||||
printf '%-32s %-34s %-14s %4s %6s %4s %6s %6s %s\n' \
|
||||
"$name" "$status" "$cost" "$inbox" "$orders" "$dirty" "$age" "$last" "$(trunc "$neste" "$NESTE_WIDTH")"
|
||||
while IFS='|' read -r bucket sortkey name status cost inbox dirty age last dir blockedon orders claimed neste; do
|
||||
printf '%-32s %-34s %-14s %4s %6s %4s %4s %6s %6s %s\n' \
|
||||
"$name" "$status" "$cost" "$inbox" "$orders" "$claimed" "$dirty" "$age" "$last" "$(trunc "$neste" "$NESTE_WIDTH")"
|
||||
done
|
||||
}
|
||||
|
||||
|
|
@ -757,7 +809,7 @@ brief() {
|
|||
FILENAME==OWF { ow[$1] = $2 + 0; next }
|
||||
{ name = $3; owed = (name in ow) ? ow[name] : 0; if (owed > 0) print owed, $0 }
|
||||
' "$OWED" "$RECORDS" | sort -t'|' -k1,1nr | \
|
||||
while IFS='|' read -r owed bucket sortkey name status cost inbox dirty age last dir blockedon orders neste; do
|
||||
while IFS='|' read -r owed bucket sortkey name status cost inbox dirty age last dir blockedon orders claimed neste; do
|
||||
printf ' %-32s INN %-4s %s\n' "$name" "$owed" "$status"
|
||||
# Wrapped, not cut - the whole line is the point, but a 500-character one
|
||||
# is unreadable in a file nobody watched being written. Locale is set for
|
||||
|
|
@ -877,7 +929,7 @@ dispatch() {
|
|||
[ -n "$d_rec" ] || { echo "board: no repo named '$D_REPO' in the scanned roots ($ROOTS)" >&2; exit 2; }
|
||||
d_status="$(printf '%s' "$d_rec" | cut -d'|' -f4)"
|
||||
d_dir="$(printf '%s' "$d_rec" | cut -d'|' -f10)"
|
||||
d_neste="$(printf '%s' "$d_rec" | cut -d'|' -f13-)"
|
||||
d_neste="$(printf '%s' "$d_rec" | cut -d'|' -f14-)"
|
||||
[ -d "$d_dir" ] || { echo "board: the directory for $D_REPO does not exist: $d_dir" >&2; exit 2; }
|
||||
|
||||
# Rejected traits REFUSE. Degrading to a command without them is the worst
|
||||
|
|
@ -1287,6 +1339,40 @@ plan() {
|
|||
# decided has a second consumer elsewhere), but the driver must be able to
|
||||
# see that the omission happened rather than read a shorter list as complete.
|
||||
[ "$HAVE_COUNT" -eq 1 ] || printf 'advarsel=coord-count.sh mangler - gjeldsvekting (gruppe 2, inbox:N) er ikke beregnet\n'
|
||||
|
||||
# --- Free capacity: NAMED, never turned into a tab ------------------------
|
||||
# The question the plan could not answer until now, in the operator's own
|
||||
# words: "which repos are finished and can take more work". Until 0.29.0 such
|
||||
# a repo simply fell OUT of the plan - correctly, since it has no next step to
|
||||
# open a tab for, but silently, which is where new capacity was going unseen.
|
||||
#
|
||||
# It is a LOOKUP over fields the scan already read, exactly like every group
|
||||
# term above - no new source, no new axis. All four conditions are required,
|
||||
# and status=done alone is not one of them: measured on the real tree
|
||||
# 2026-08-23, 4 of 17 done/deferred repos were NOT free (two held a pending
|
||||
# order, one owed a reply, one had an uncommitted tree). Debt is OWED, not raw
|
||||
# pending, for the same reason group 2 is - a notice is not an obligation.
|
||||
#
|
||||
# Emitted as single key=value LINES, never as blocks, and that is the whole
|
||||
# design: `plan_parse` discards a block with no `tab=`, so a free repo written
|
||||
# as a block would be visible to the operator and invisible to the driver.
|
||||
# A line is visible to both and can never be opened as a tab by accident.
|
||||
# The count is printed even when it is 0, so "none found" and "not computed"
|
||||
# cannot render as the same output.
|
||||
lf="${TMPDIR:-/tmp}/board-ledig.$$"
|
||||
awk -F'|' -v OWF="$OWED" '
|
||||
FILENAME==OWF { ow[$1] = $2 + 0; next }
|
||||
{
|
||||
name = $3; status = $4; dirty = $7 + 0; orders = $12 + 0; claimed = $13 + 0
|
||||
owed = (name in ow) ? ow[name] : 0
|
||||
if (status != "done" && status != "deferred") next
|
||||
if (owed > 0 || orders > 0 || claimed > 0 || dirty > 0) next
|
||||
print name " (" status ")"
|
||||
}
|
||||
' "$OWED" "$RECORDS" | sort > "$lf"
|
||||
printf 'ledig_antall=%s\n' "$(awk 'END{print NR+0}' "$lf")"
|
||||
sed 's/^/ledig=/' "$lf"
|
||||
/bin/rm -f "$lf" 2>/dev/null
|
||||
if [ -n "$FOCUS" ]; then
|
||||
fp_state="$(awk -F'|' '{print $10}' "$RECORDS" | while read -r fp_sd; do
|
||||
[ -n "$fp_sd" ] && [ -f "$fp_sd/STATE.md" ] && echo x
|
||||
|
|
@ -1322,7 +1408,7 @@ plan() {
|
|||
echo ""
|
||||
|
||||
pn=0
|
||||
while IFS='|' read -r why bucket sortkey name status cost inbox dirty age last dir blockedon orders neste; do
|
||||
while IFS='|' read -r why bucket sortkey name status cost inbox dirty age last dir blockedon orders claimed neste; do
|
||||
[ -n "$name" ] || continue
|
||||
pn=$((pn + 1))
|
||||
printf 'tab=%s\n' "$pn"
|
||||
|
|
@ -1336,6 +1422,12 @@ plan() {
|
|||
fp_ev="$(focus_evidence "$dir")" && printf 'fokus_treff=%s\n' "$fp_ev"
|
||||
fi
|
||||
printf 'status=%s\n' "$status"
|
||||
# Emitted only when there IS one, like fokus_treff= above: a `fly=0` on
|
||||
# every block would be noise, and its absence already says nothing is in
|
||||
# flight. A tab whose repo holds a claimed order may already have a session
|
||||
# in it, and the driver types into live panes - it has to be able to see
|
||||
# this before it does.
|
||||
[ "${claimed:-0}" -gt 0 ] 2>/dev/null && printf 'fly=%s\n' "$claimed"
|
||||
printf 'neste=%s\n' "$neste"
|
||||
plan_cmd "$dir" "$cost"
|
||||
echo ""
|
||||
|
|
@ -1376,7 +1468,7 @@ inbox_plan() {
|
|||
FILENAME==RCF {
|
||||
name = $3
|
||||
rc_bucket[name] = $1; rc_status[name] = $4; rc_cost[name] = $5
|
||||
rc_dir[name] = $10; rc_neste[name] = $13
|
||||
rc_dir[name] = $10; rc_neste[name] = $14
|
||||
next
|
||||
}
|
||||
{
|
||||
|
|
@ -1451,6 +1543,14 @@ echo "INN = uhaandtert innboks (andre venter paa DEG). DRT = ukommiterte filer."
|
|||
# legend states the distinction where they are read - they measure opposite
|
||||
# directions and are never summed.
|
||||
echo "ORDRE = ventende ordrer (arbeid venter paa REPOET). INN og ORDRE summeres ALDRI."
|
||||
# FLY is the SAME queue as ORDRE in its other state, never a fourth axis and
|
||||
# never a liveness reading. The denial is part of the legend, not a footnote:
|
||||
# nothing un-claims an order when the session that claimed it dies (measured
|
||||
# 2026-08-23, wiki-advise: one order claimed 117 hours), so "an order is
|
||||
# claimed here" is the only claim this number can carry.
|
||||
echo "FLY = ordrer i arbeid (claimed). Beviser aldri at en okt lever eller er aktiv."
|
||||
echo " Beviser bare at noen TOK ordren; ingenting frigir den om okten dor."
|
||||
echo " Summeres ALDRI med ORDRE - samme ko, annen tilstand."
|
||||
echo "ALDER = dager siden STATE.md endret. SISTE = dager siden siste commit."
|
||||
|
||||
[ "$(count 1)" -gt 0 ] && { hdr "BLOKKERT (venter paa ekstern avhengighet)"; rows 1; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue