@plot-pm/board 0.10.0 → 0.12.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/dist/board-server.mjs +157 -151
- package/package.json +9 -1
- package/plot-agent-monitor.sh +532 -0
- package/plot-approve.sh +151 -32
- package/plot-budget.sh +439 -0
- package/plot-build-monitor.sh +435 -0
- package/plot-config.sh +17 -1
- package/plot-default-branch.sh +109 -0
- package/plot-deliver.sh +214 -119
- package/plot-dispatch.sh +1327 -188
- package/plot-fleet-scan.sh +1005 -170
- package/plot-host.sh +1438 -61
- package/plot-monitor-subject.sh +194 -0
- package/plot-plan-meta.sh +345 -47
- package/plot-pr-merged.sh +180 -0
- package/plot-reap.sh +719 -61
- package/plot-release-refs.sh +188 -46
- package/plot-resolve-artifact.sh +115 -22
- package/plot-transcript-quiet.sh +142 -0
- package/plot-worker-monitor.sh +644 -0
- package/plot-worker-state.sh +81 -50
package/plot-worker-state.sh
CHANGED
|
@@ -276,6 +276,32 @@ plot_worker_log() { # $1=worktree → path to the worker log, or "" (non-zero)
|
|
|
276
276
|
[ -e "$wt/.plot-worker.log" ] || return 1
|
|
277
277
|
printf '%s' "$wt/.plot-worker.log"
|
|
278
278
|
}
|
|
279
|
+
# Why did the worker in this worktree end?
|
|
280
|
+
#
|
|
281
|
+
# A SEPARATE READING FROM `plot_worker_state`, and deliberately so. That function
|
|
282
|
+
# answers what the PROCESS did and what the desk holds; this answers why the
|
|
283
|
+
# worker stopped, which is a fact only the worker itself could record. The two
|
|
284
|
+
# come apart in the case that matters: a worker ended by the floor and one ended
|
|
285
|
+
# by a monitor finding both leave `.plot-worker.exit` holding `124`, so the exit
|
|
286
|
+
# code cannot tell them apart and the state word does not try to.
|
|
287
|
+
#
|
|
288
|
+
# IT IS NOT FOLDED INTO THE STATE ROW. `plot_worker_state` prints three
|
|
289
|
+
# tab-separated fields that three callers and one domain port parse positionally;
|
|
290
|
+
# a fourth field would change a contract this reading does not need to change.
|
|
291
|
+
# `plot_worker_log` is the precedent — a standalone reader beside the state
|
|
292
|
+
# function, asked by whoever wants it.
|
|
293
|
+
#
|
|
294
|
+
# ABSENT IS ABSENT, and it is load-bearing. No worktree, or no ending file in
|
|
295
|
+
# one, prints nothing and returns non-zero — which is what a SIGKILLed worker
|
|
296
|
+
# leaves behind, and what every worker that ran before this record existed
|
|
297
|
+
# leaves too. The domain's `readEnding` keeps that apart from a file that exists
|
|
298
|
+
# and does not parse; this prints the bytes and decides neither.
|
|
299
|
+
plot_worker_ending() { # $1=worktree → the ending record's JSON, or "" (non-zero)
|
|
300
|
+
local wt="$1"
|
|
301
|
+
[ -n "$wt" ] || return 1
|
|
302
|
+
[ -f "$wt/.plot-worker.ending.json" ] || return 1
|
|
303
|
+
cat "$wt/.plot-worker.ending.json" 2>/dev/null
|
|
304
|
+
}
|
|
279
305
|
|
|
280
306
|
# Is a person being waited on inside this worktree?
|
|
281
307
|
#
|
|
@@ -513,58 +539,63 @@ plot_worker_activity() { # $1=pid → working | idle | "" (empty = nothing to me
|
|
|
513
539
|
|
|
514
540
|
# Refine a clean exit into finished / waiting / stalled.
|
|
515
541
|
#
|
|
516
|
-
# THE
|
|
517
|
-
#
|
|
518
|
-
#
|
|
519
|
-
#
|
|
520
|
-
#
|
|
521
|
-
#
|
|
522
|
-
#
|
|
523
|
-
#
|
|
524
|
-
#
|
|
525
|
-
#
|
|
526
|
-
#
|
|
527
|
-
#
|
|
528
|
-
#
|
|
529
|
-
#
|
|
530
|
-
#
|
|
531
|
-
#
|
|
532
|
-
#
|
|
542
|
+
# THE DECISION IS NOT MADE HERE. `taskState` lives in `@plot-pm/domain` and this
|
|
543
|
+
# function asks it. The four readings and the order they are decided in — a PR
|
|
544
|
+
# outranking everything, `waiting` outranking `stalled`, an unanswerable
|
|
545
|
+
# `unpushed` refusing to become `stalled` — are one implementation now, testable
|
|
546
|
+
# over all 24 combinations of the four readings instead of over the worktrees an
|
|
547
|
+
# estate happens to produce. That is what this script carried in duplicate until
|
|
548
|
+
# 2026-08-18, five of six states in two places, and the copies had drifted.
|
|
549
|
+
#
|
|
550
|
+
# WHAT STAYS HERE IS THE READING. The four world questions below are shell's,
|
|
551
|
+
# and each is asked exactly as it was: the marker is a FILE `plot_worker_blocked`
|
|
552
|
+
# globs for, dirtiness is `plot_worker_dirty`'s filtered answer, and `unpushed`
|
|
553
|
+
# is `@{upstream}` and nothing else.
|
|
554
|
+
#
|
|
555
|
+
# ONLY `@{upstream}` ANSWERS "PUSHED?", and when there is no upstream the
|
|
556
|
+
# question is UNANSWERABLE rather than answered zero — or answered anything
|
|
557
|
+
# else. This went in the wrong direction first and was measured doing it: a
|
|
558
|
+
# fallback that counted against `origin/main` reported EVERY clean branch
|
|
559
|
+
# `stalled` in a repo with no remote, because `rev-list --count "..HEAD"` with
|
|
560
|
+
# an empty left side counts the whole history from the root commit. Nine commits
|
|
561
|
+
# of ordinary history read as nine commits of unpushed work.
|
|
562
|
+
#
|
|
563
|
+
# The fallback was also wrong where it worked. A branch legitimately ahead of
|
|
564
|
+
# `origin/main` is the NORMAL state of every branch under review — it is what
|
|
565
|
+
# having commits means — so counting against the trunk marks finished work
|
|
566
|
+
# `stalled` for as long as it exists. Only the branch's OWN upstream separates
|
|
567
|
+
# "pushed" from "not pushed"; the trunk answers a different question entirely.
|
|
568
|
+
#
|
|
569
|
+
# So an absent upstream travels to the rule as an EMPTY field, which the rule
|
|
570
|
+
# reads as unanswerable and does not turn into `stalled`. A failure to observe
|
|
571
|
+
# is not evidence of something to see — the same principle `local_ahead_of`
|
|
572
|
+
# states in plot-fleet-scan.sh, reached the hard way.
|
|
573
|
+
#
|
|
574
|
+
# A RULE THAT CANNOT BE ASKED REFUSES, and it says so with the rebuild in the
|
|
575
|
+
# message — the shape `plot-fleet-scan.sh` uses at its own bundle call. There is
|
|
576
|
+
# no shell fallback: a second implementation kept "just in case" is the
|
|
577
|
+
# duplication this move removes, and it would be the copy nobody tests. An
|
|
578
|
+
# EMPTY answer is checked separately from a non-zero exit, because a bundle that
|
|
579
|
+
# writes nothing exits 0 and `||` alone cannot see it.
|
|
533
580
|
plot_worker_task_state() { # $1=worktree $2=pr-fact → finished|waiting|stalled
|
|
534
|
-
local wt="$1" has_pr="$2"
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
[
|
|
581
|
+
local wt="$1" has_pr="$2" here ahead has_pr_flag blocked_flag dirty_flag answer
|
|
582
|
+
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
583
|
+
|
|
584
|
+
[ "$has_pr" = "pr" ] && has_pr_flag=1 || has_pr_flag=0
|
|
585
|
+
plot_worker_blocked "$wt" && blocked_flag=1 || blocked_flag=0
|
|
586
|
+
[ -n "$(plot_worker_dirty "$wt")" ] && dirty_flag=1 || dirty_flag=0
|
|
587
|
+
|
|
538
588
|
# UNPUSHED IS A REF QUESTION, asked THROUGH the worktree because that is the
|
|
539
|
-
# checkout whose HEAD is the branch.
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
# The fallback was also wrong where it worked. A branch legitimately ahead of
|
|
550
|
-
# `origin/main` is the NORMAL state of every branch under review — it is what
|
|
551
|
-
# having commits means — so counting against the trunk marks finished work
|
|
552
|
-
# `stalled` for as long as it exists. Only the branch's OWN upstream separates
|
|
553
|
-
# "pushed" from "not pushed"; the trunk answers a different question entirely.
|
|
554
|
-
#
|
|
555
|
-
# So an absent upstream yields no verdict here and falls through to
|
|
556
|
-
# `finished`, which is the answer the branch gave before this state existed.
|
|
557
|
-
# A failure to observe is not evidence of something to see — the same
|
|
558
|
-
# principle `local_ahead_of` states in plot-fleet-scan.sh, reached the hard
|
|
559
|
-
# way.
|
|
560
|
-
local ahead
|
|
561
|
-
if ahead=$(git -C "$wt" rev-list --count '@{upstream}..HEAD' 2>/dev/null); then
|
|
562
|
-
case "$ahead" in
|
|
563
|
-
''|0|*[!0-9]*) ;;
|
|
564
|
-
*) printf 'stalled'; return ;;
|
|
565
|
-
esac
|
|
566
|
-
fi
|
|
567
|
-
printf 'finished'
|
|
589
|
+
# checkout whose HEAD is the branch. An unreadable count stays EMPTY.
|
|
590
|
+
ahead=$(git -C "$wt" rev-list --count '@{upstream}..HEAD' 2>/dev/null) || ahead=""
|
|
591
|
+
|
|
592
|
+
answer=$(printf '%s\t%s\t%s\t%s' \
|
|
593
|
+
"$has_pr_flag" "$blocked_flag" "$dirty_flag" "$ahead" \
|
|
594
|
+
| node "$here/board/plot-task.mjs" 2>/dev/null) \
|
|
595
|
+
|| { echo "error: cannot read the task state — run 'pnpm build:board'." >&2; exit 2; }
|
|
596
|
+
[ -n "$answer" ] \
|
|
597
|
+
|| { echo "error: the task state rule answered nothing — run 'pnpm build:board'." >&2; exit 2; }
|
|
598
|
+
printf '%s' "$answer"
|
|
568
599
|
}
|
|
569
600
|
|
|
570
601
|
# Classify the worker in a worktree.
|