@plot-pm/board 0.13.0 → 0.14.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plot-pm/board",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "Local Kanban board for Plot — a glanceable view of plan phases from docs/plans, with sprint and story filters",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -38,6 +38,7 @@
38
38
  "plot-reap.sh",
39
39
  "plot-release-refs.sh",
40
40
  "plot-resolve-artifact.sh",
41
+ "plot-state-receipt.sh",
41
42
  "plot-transcript-quiet.sh",
42
43
  "plot-worker-monitor.sh",
43
44
  "plot-worker-state.sh"
package/plot-approve.sh CHANGED
@@ -99,6 +99,12 @@ set -uo pipefail
99
99
 
100
100
  script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
101
101
 
102
+ # The receipt this script leaves for plot-state-gate.sh, which refuses every
103
+ # other writer of a `State:` line. Sourced rather than run: the gate and the
104
+ # three owning scripts must agree on where a receipt lives, and one file is how.
105
+ # shellcheck source=plot-state-receipt.sh
106
+ . "$script_dir/plot-state-receipt.sh"
107
+
102
108
  dry_run=0
103
109
  who_override=""
104
110
  slug=""
@@ -538,6 +544,10 @@ write_transition() { # $1=file $2=record $3=recorded(yes|no) → sets phase_repo
538
544
  fi
539
545
 
540
546
  phase_report=$([ "$flipped" = 1 ] && echo flipped || echo already)
547
+ # The receipt plot-state-gate.sh clears on. Recorded after the `mv`, so it
548
+ # names a value the file actually carries — a receipt written before a failed
549
+ # write would license a commit of the state that was refused.
550
+ record_state_receipt "$f" "Approved"
541
551
  return 0
542
552
  }
543
553
 
@@ -776,4 +786,12 @@ else
776
786
  fi
777
787
 
778
788
  echo "summary: merged=$merged_report phase=$phase_report record=$record_report holds=$holds_report sprint=$sprint_report push=$push_report"
789
+ # THE RECEIPT IS SPENT HERE, on the action COMPLETING — never at the gate.
790
+ # `plot-controller-gate.sh` clears on a receipt and LEAVES it, so an
791
+ # interrupted run can be repeated on the same licence: this script documents
792
+ # re-running as the repair for any interruption after its irreversible step,
793
+ # and a receipt spent at the gate would refuse that repair in the case it is
794
+ # most needed. One authorisation, one completed action.
795
+ spend_action_receipt "plot-approve.sh"
796
+
779
797
  exit 0
package/plot-config.sh CHANGED
@@ -95,6 +95,23 @@
95
95
  # Hosts plans yes | no (no = refuse plan files)
96
96
  # Tracker plot | jira | github-issues | linear (+ URL)
97
97
  # (plot = plans in this repo ARE the tracker; absent = same)
98
+ # Ticket prefixes the tracker project keys this repository's work lives
99
+ # in, comma-separated (`PROJ-A, PROJ-B`). NOT
100
+ # `Branch prefixes`, which sits next to it and holds
101
+ # `idea/`, `feature/`, `bug/` — that key is structural and
102
+ # names git branches; this one names tracker projects.
103
+ # Read by plot-host.sh's `issue-list` to scope the inbox:
104
+ # the default JQL scopes by person and state, so on a
105
+ # shared instance it is instance-wide and returns other
106
+ # customers' tickets. A LIST, because a repository mapping
107
+ # to several projects is the normal case; adoption seeds
108
+ # ONE prefix and a person adds the rest. Absent = today's
109
+ # unscoped query, byte for byte — a default that filtered
110
+ # on an undeclared key would empty every existing board's
111
+ # inbox on upgrade. `PLOT_JIRA_JQL` overrides both.
112
+ # NEVER WRITTEN EMPTY: an empty list reads as *this
113
+ # repository has no projects* and changes nothing about
114
+ # the query, so adoption omits the key instead.
98
115
  # Git host github | bitbucket (resolves gh vs bb)
99
116
  # CI jenkins | github-actions | none — which CI system this
100
117
  # project uses. Recorded by /plot-board-setup; not yet
package/plot-deliver.sh CHANGED
@@ -49,6 +49,12 @@ set -uo pipefail
49
49
 
50
50
  script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
51
51
 
52
+ # The receipt this script leaves for plot-state-gate.sh, which refuses every
53
+ # other writer of a `State:` line. Sourced rather than run: the gate and the
54
+ # three owning scripts must agree on where a receipt lives, and one file is how.
55
+ # shellcheck source=plot-state-receipt.sh
56
+ . "$script_dir/plot-state-receipt.sh"
57
+
52
58
  dry_run=0
53
59
  who_override=""
54
60
  slug=""
@@ -172,6 +178,27 @@ if [ "$(vfield '.deliverable')" != "true" ]; then
172
178
  die "$(vfield '.refusal')"
173
179
  fi
174
180
 
181
+ # THE FINDING — a slice whose merged PR carried no implementation.
182
+ #
183
+ # IT REPORTS AND DOES NOT REFUSE, which is the harder call and the right one.
184
+ # Measured over the last 60 merged PRs on 2026-09-08, seven carried no work and
185
+ # only TWO were this defect: three were claim PRs whose slice finished under a
186
+ # DIFFERENT PR, and a gate refusing on those would have blocked a delivery whose
187
+ # work was complete — right about the PR and wrong about the plan.
188
+ #
189
+ # So it is worded as a QUESTION and names the next move, because a reader told
190
+ # only "this carried nothing" still has the decision to make.
191
+ empty_slices=$(printf '%s' "$verdict" | jq -r '.emptySlices // [] | .[]' 2>/dev/null)
192
+ if [ -n "$empty_slices" ]; then
193
+ echo "note: this plan's merged PR carried no implementation on:"
194
+ while IFS= read -r b; do
195
+ [ -n "$b" ] || continue
196
+ echo " - $b"
197
+ done <<< "$empty_slices"
198
+ echo " check whether its work landed under another PR, mark it deferred"
199
+ echo " (<!-- deferred: <reason> -->), or re-open it. Delivery continues."
200
+ fi
201
+
175
202
  merged_count=$(vfield '.merged')
176
203
  deferred_count=$(vfield '.deferred')
177
204
  # Empty rather than `0`, so the suffix below stays absent where the old block
@@ -417,6 +444,10 @@ write_transition() { # $1=file $2=record $3=recorded(yes|no) → sets phase_repo
417
444
  fi
418
445
 
419
446
  phase_report=$([ "$flipped" = 1 ] && echo flipped || echo already)
447
+ # The receipt plot-state-gate.sh clears on. Recorded after the `mv`, so it
448
+ # names a value the file actually carries — a receipt written before a failed
449
+ # write would license a commit of the state that was refused.
450
+ record_state_receipt "$f" "Delivered"
420
451
  return 0
421
452
  }
422
453
 
@@ -598,4 +629,12 @@ else
598
629
  fi
599
630
 
600
631
  echo "summary: phase=$phase_report record=$record_report index=$index_report sprint=$sprint_report push=$push_report"
632
+ # THE RECEIPT IS SPENT HERE, on the action COMPLETING — never at the gate.
633
+ # `plot-controller-gate.sh` clears on a receipt and LEAVES it, so an
634
+ # interrupted run can be repeated on the same licence: this script documents
635
+ # re-running as the repair for any interruption after its irreversible step,
636
+ # and a receipt spent at the gate would refuse that repair in the case it is
637
+ # most needed. One authorisation, one completed action.
638
+ spend_action_receipt "plot-deliver.sh"
639
+
601
640
  exit 0
package/plot-dispatch.sh CHANGED
@@ -150,6 +150,12 @@ script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
150
150
  # shellcheck source=plot-worker-state.sh
151
151
  . "$script_dir/plot-worker-state.sh"
152
152
 
153
+ # The controller receipt, for `spend_action_receipt` below. Sourced from the
154
+ # ONE file that holds both receipt kinds, for the reason that file states: the
155
+ # gate and the owners must agree on where a receipt lives.
156
+ # shellcheck source=plot-state-receipt.sh
157
+ . "$script_dir/plot-state-receipt.sh"
158
+
153
159
  # The ONE answer to "did the host merge ANY PR for this branch?" — `pr_merged`,
154
160
  # read by `held_worktree` rather than derived from ancestry. Sourced for the
155
161
  # same reason `plot-reap.sh` and `plot-release-refs.sh` source it: three callers
@@ -3206,3 +3212,13 @@ book_started ${claimed_now[@]+"${claimed_now[@]}"} || true
3206
3212
  check_and_update_cap "$n_started"
3207
3213
 
3208
3214
  print_summary "$n_dispatched" "$n_reused" "$n_skipped" "$n_started"
3215
+
3216
+ # THE RECEIPT IS SPENT HERE, on the fan-out COMPLETING — never at the gate.
3217
+ # `plot-controller-gate.sh` clears on a receipt and LEAVES it, so a run that
3218
+ # died partway can be repeated on the same licence. One authorisation, one
3219
+ # completed action.
3220
+ #
3221
+ # ONLY THE FAN-OUT SPENDS ONE. `--status`, `--dry-run`, `--stop`, `--restart`,
3222
+ # `--start` and `--migrate` all return before this line, and the gate exempts
3223
+ # each of them: they are reads, or writes no endpoint owns.
3224
+ spend_action_receipt "plot-dispatch.sh"