@plot-pm/board 0.8.0-rc.8 → 0.8.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 +147 -102
- package/package.json +1 -1
- package/plot-config.sh +15 -0
- package/plot-plan-meta.sh +40 -2
package/package.json
CHANGED
package/plot-config.sh
CHANGED
|
@@ -27,6 +27,21 @@
|
|
|
27
27
|
# Project board | Branch prefixes | Plan directory | Active index |
|
|
28
28
|
# Delivered index | Sprint directory | Story directory | Story index |
|
|
29
29
|
# Plan template | Main branch | Board command
|
|
30
|
+
# Worker bound seconds a single prompt run may take in the worker loop
|
|
31
|
+
# before it is ended and the worker exits (no hop). Read by
|
|
32
|
+
# plot-worker-loop.sh; default 3600 (~1h), `0` disables it.
|
|
33
|
+
# Non-numeric or empty falls back to the default. It bounds
|
|
34
|
+
# a HUNG agent — one whose CLI crashed without exiting — so
|
|
35
|
+
# one dead worker cannot hold a slot for hours.
|
|
36
|
+
# Agent registry the directory the dispatcher writes agent manifests to,
|
|
37
|
+
# read by the board's registry. Default `.plot/agents`
|
|
38
|
+
# (repo-relative, gitignored, hence per-worktree). A board
|
|
39
|
+
# served from a worktree the dispatcher never wrote to
|
|
40
|
+
# reads an empty directory and synthesizes the whole fleet
|
|
41
|
+
# with no session ids; point this at a shared location so
|
|
42
|
+
# the board finds the registry wherever it was started.
|
|
43
|
+
# Absent = the default, so a single-checkout project is
|
|
44
|
+
# unaffected.
|
|
30
45
|
# Agent-runner keys (optional; Plot hardcodes no agent tooling, Principle 5):
|
|
31
46
|
# Worker command how /plot-dispatch runs an agent headless on a worktree.
|
|
32
47
|
# `none` = asked, and this repo starts workers by hand —
|
package/plot-plan-meta.sh
CHANGED
|
@@ -128,6 +128,18 @@
|
|
|
128
128
|
# is a note to a reviewer rather than a release note. Comment
|
|
129
129
|
# interiors stay non-content, as everywhere else in this parser,
|
|
130
130
|
# so the template's guidance block contributes nothing.
|
|
131
|
+
# long_wave_names wave names too long to be labels — a report, not a refusal.
|
|
132
|
+
# A wave name is a label (`Shaped`, `Gated`, `Offered first`);
|
|
133
|
+
# a sentence-length heading is a plan-authoring mistake the
|
|
134
|
+
# board can only render badly. Names past a threshold judgement
|
|
135
|
+
# (LONG_WAVE_NAME_MAX, set from the estate's longest legitimate
|
|
136
|
+
# name) are listed here in document order, so the reconcile
|
|
137
|
+
# sweep can surface them for a fix. Reads the SAME wave names
|
|
138
|
+
# waves[] carries — never a second scan of the file — so both
|
|
139
|
+
# the ## Branches and ## Waves spellings are covered. [] when
|
|
140
|
+
# every wave name is a label; ALWAYS present, so a consumer
|
|
141
|
+
# never reads undefined. The plan still parses in full: waves[]
|
|
142
|
+
# is unchanged and no name is shortened or dropped.
|
|
131
143
|
# issues tracker issue numbers this plan answers, from the `## Status`
|
|
132
144
|
# `Issue:` line or front matter `issue:` (sorted, unique).
|
|
133
145
|
# A DEDICATED field, never a scan of the body for `#NNN`: a
|
|
@@ -204,7 +216,7 @@ if [ ${#files[@]} -eq 0 ] && [ ${#missing[@]} -eq 0 ]; then
|
|
|
204
216
|
fi
|
|
205
217
|
|
|
206
218
|
for f in ${missing[@]+"${missing[@]}"}; do
|
|
207
|
-
printf '{"file":"%s","format":"none","error":"file not found","phase_raw":"","phase":"NONE","phase_alt_raw":"","phase_alt":"NONE","type":"","title":"","sprint":"","story":"","assignee":"","branches":[],"prs":[],"issues":[],"malformed_prs":[],"changelog":[],"review_raw":"","review":"NONE","impl_raw":"","impl":"NONE","design_raw":"","approved_raw":"","released_raw":"","delivered_raw":"","started_raw":[]}\n' \
|
|
219
|
+
printf '{"file":"%s","format":"none","error":"file not found","phase_raw":"","phase":"NONE","phase_alt_raw":"","phase_alt":"NONE","type":"","title":"","sprint":"","story":"","assignee":"","branches":[],"prs":[],"issues":[],"malformed_prs":[],"changelog":[],"long_wave_names":[],"review_raw":"","review":"NONE","impl_raw":"","impl":"NONE","design_raw":"","approved_raw":"","released_raw":"","delivered_raw":"","started_raw":[]}\n' \
|
|
208
220
|
"$(printf '%s' "$f" | sed 's/\\/\\\\/g; s/"/\\"/g')"
|
|
209
221
|
done
|
|
210
222
|
|
|
@@ -399,6 +411,27 @@ function emit_record( fmt, praw, palt_raw, traw, title, sprint, story, assigne
|
|
|
399
411
|
out = out "]}"
|
|
400
412
|
}
|
|
401
413
|
out = out "]"
|
|
414
|
+
# long_wave_names[]: wave names past LONG_WAVE_NAME_MAX, in document order. A
|
|
415
|
+
# wave name is a label (`Shaped`, `Gated`, `Offered first`); a sentence-length
|
|
416
|
+
# heading is a plan-authoring mistake the board can only render badly. This
|
|
417
|
+
# REPORTS the offenders — a top-level field, never a change to waves[], so the
|
|
418
|
+
# plan still parses and every existing consumer of waves[] is untouched. The
|
|
419
|
+
# threshold is a JUDGEMENT baked into one constant (see LONG_WAVE_NAME_MAX):
|
|
420
|
+
# the longest legitimate name in the estate is `Offered first` at 13, the
|
|
421
|
+
# offender that motivated this is 53. Measured over the whole array so BOTH
|
|
422
|
+
# spellings (## Branches and ## Waves) are covered from one place. length()
|
|
423
|
+
# here is the awk byte length, which can exceed the character count for a name
|
|
424
|
+
# with a multi-byte dash — harmless: the threshold clears every real name by
|
|
425
|
+
# tens of bytes either way, so the verdict never turns on the last byte.
|
|
426
|
+
out = out ",\"long_wave_names\":["
|
|
427
|
+
lwn = 0
|
|
428
|
+
for (w = 1; w <= n_waves; w++) {
|
|
429
|
+
if (length(wave_names[w]) > LONG_WAVE_NAME_MAX) {
|
|
430
|
+
out = out (lwn > 0 ? "," : "") "\"" jesc(wave_names[w]) "\""
|
|
431
|
+
lwn++
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
out = out "]"
|
|
402
435
|
out = out ",\"review_raw\":\"" jesc(review) "\",\"review\":\"" norm_review(review) "\""
|
|
403
436
|
out = out ",\"impl_raw\":\"" jesc(impl) "\",\"impl\":\"" norm_impl(impl) "\""
|
|
404
437
|
out = out ",\"design_raw\":\"" jesc(design) "\""
|
|
@@ -413,7 +446,12 @@ function emit_record( fmt, praw, palt_raw, traw, title, sprint, story, assigne
|
|
|
413
446
|
out = out "}"
|
|
414
447
|
print out
|
|
415
448
|
}
|
|
416
|
-
|
|
449
|
+
# The longest wave name that still reads as a label, not prose. A JUDGEMENT, not
|
|
450
|
+
# a measurement: the longest legitimate name in the estate is `Offered first`
|
|
451
|
+
# (13), and the offender this exists to catch is a 53-character sentence, so the
|
|
452
|
+
# line sits well clear of both. Reported, never enforced — a name past it makes
|
|
453
|
+
# `long_wave_names`, and nothing refuses the plan.
|
|
454
|
+
BEGIN { branch_re = "`(" PREFIXES ")/[^`]+`"; LONG_WAVE_NAME_MAX = 40 }
|
|
417
455
|
FNR == 1 {
|
|
418
456
|
if (NR > 1) emit_record()
|
|
419
457
|
reset_state()
|