Skip to content

Commit d069de2

Browse files
committed
fix(development-system): enforce checkpoint transitions
Validate every successor against the predecessor’s sole next action in addition to standalone schema and lineage checks. This prevents structurally valid records from skipping required edits, reviews, gates, delivery, or CI-monitoring transitions. Make passing-stage tests advance sequentially, add a skipped-gate regression, document the transition guarantee, and bump the plugin patch version. Refs: 20260901-xige
1 parent 11bde9c commit d069de2

6 files changed

Lines changed: 88 additions & 14 deletions

File tree

.agents/plugins/marketplace.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"source": "local",
1111
"path": "./plugins/development-system"
1212
},
13-
"version": "6.2.3",
13+
"version": "6.2.4",
1414
"policy": {
1515
"installation": "AVAILABLE",
1616
"authentication": "ON_INSTALL"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ user-managed MCPs that need compatibility review.
2222

2323
| Plugin | Harness | Description | Version |
2424
| ---------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- | ------- |
25-
| [development-system](plugins/development-system/README.md) | Codex | Advisory repository setup and structured multi-agent review with reusable native services for Tiber. | 6.2.3 |
25+
| [development-system](plugins/development-system/README.md) | Codex | Advisory repository setup and structured multi-agent review with reusable native services for Tiber. | 6.2.4 |
2626

2727
## Using the marketplace (Codex)
2828

plugins/development-system/.codex-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "development-system",
3-
"version": "6.2.3",
3+
"version": "6.2.4",
44
"description": "John's consolidated development workflow, engineering standards, worktree, task, review, and agentic-system tooling.",
55
"author": {
66
"name": "John Wilger",

plugins/development-system/scripts/write-local-checkpoint.sh

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,68 @@ if [[ -e $target ]]; then
168168
[[ $expected_generation -eq $((current_generation + 1)) ]] || { echo "stale checkpoint generation" >&2; exit 3; }
169169
[[ $expected_predecessor == "$current_predecessor" ]] || { echo "stale checkpoint predecessor" >&2; exit 3; }
170170
[[ $proposed_baseline == "$current_baseline" ]] || { echo "checkpoint baseline does not match predecessor" >&2; exit 3; }
171-
current_ci=$(sed -n 's/^checkpoint-v1 //p' "$target" | jq -c '.ci.runs')
172-
proposed_ci=$(tail -c +15 "$candidate" | jq -c '.ci.runs')
171+
current_record=$(sed -n 's/^checkpoint-v1 //p' "$target")
172+
proposed_record=$(tail -c +15 "$candidate")
173+
current_ci=$(jq -c '.ci.runs' <<<"$current_record")
174+
proposed_ci=$(jq -c '.ci.runs' <<<"$proposed_record")
173175
jq -en --argjson current "$current_ci" --argjson proposed "$proposed_ci" \
174176
'$proposed[0:($current | length)] == $current' >/dev/null || {
175177
echo "checkpoint CI observations do not preserve predecessor history" >&2
176178
exit 3
177179
}
180+
jq -en --argjson current "$current_record" --argjson proposed "$proposed_record" '
181+
def passing($action):
182+
$proposed.state == "passing-awaiting-gates-or-review" and
183+
$proposed.next_action == $action;
184+
def remediation_result:
185+
$proposed.state == "failing" or
186+
(passing("lightweight-review") and
187+
$proposed.gates.lightweight_review_receipt == null and
188+
$proposed.gates.fast_gate_receipt == null);
189+
if ($current.next_action | test("^(causal-edit|rewrite-invalid-test): \\S")) then
190+
remediation_result
191+
elif $current.next_action == "lightweight-review" then
192+
passing("fast-gate") and
193+
$proposed.test == $current.test and
194+
($proposed.gates.lightweight_review_receipt | type == "string") and
195+
$proposed.gates.fast_gate_receipt == null
196+
elif $current.next_action == "fast-gate" then
197+
passing("commit-or-record-local-snapshot") and
198+
$proposed.test == $current.test and
199+
$proposed.gates.lightweight_review_receipt == $current.gates.lightweight_review_receipt and
200+
($proposed.gates.fast_gate_receipt | type == "string")
201+
elif $current.next_action == "commit-or-record-local-snapshot" then
202+
$proposed.test == $current.test and
203+
$proposed.gates.lightweight_review_receipt == $current.gates.lightweight_review_receipt and
204+
$proposed.gates.fast_gate_receipt == $current.gates.fast_gate_receipt and
205+
(($proposed.state == "committed" and $proposed.next_action == "verify-exact-commit") or
206+
($proposed.state == "pushed-or-delivery-mode-equivalent" and
207+
$proposed.delivery.mode == "local-only" and $proposed.next_action == "terminal-review"))
208+
elif $current.next_action == "verify-exact-commit" then
209+
$proposed.state == "committed" and
210+
($proposed.next_action | IN("repair-exact-identity-verification", "push", "record-local-delivery"))
211+
elif $current.next_action == "repair-exact-identity-verification" then
212+
$proposed.state == "committed" and $proposed.next_action == "verify-exact-commit"
213+
elif $current.next_action == "push" then
214+
$proposed.state == "pushed-or-delivery-mode-equivalent" and
215+
$proposed.next_action == "register-exact-sha-ci-monitor"
216+
elif $current.next_action == "record-local-delivery" then
217+
$proposed.state == "pushed-or-delivery-mode-equivalent" and
218+
$proposed.delivery.mode == "local-only" and $proposed.next_action == "terminal-review"
219+
elif ($current.next_action | IN("register-exact-sha-ci-monitor", "monitor-exact-sha-ci", "enter-ci-recovery")) then
220+
$proposed.state == "pushed-or-delivery-mode-equivalent" and
221+
($proposed.next_action | IN("register-exact-sha-ci-monitor", "monitor-exact-sha-ci", "enter-ci-recovery", "terminal-review"))
222+
elif $current.next_action == "terminal-review" then
223+
remediation_result
224+
else
225+
($proposed | del(.generation, .predecessor_sha256, .next_action)) ==
226+
($current | del(.generation, .predecessor_sha256, .next_action)) and
227+
($proposed.next_action | test("^(causal-edit|rewrite-invalid-test): \\S"))
228+
end
229+
' >/dev/null || {
230+
echo "successor does not perform predecessor next_action" >&2
231+
exit 3
232+
}
178233
else
179234
[[ $expected_generation -eq 0 && $expected_predecessor == null ]] || { echo "missing checkpoint predecessor" >&2; exit 3; }
180235
fi

plugins/development-system/skills/development-workflow/SKILL.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,12 @@ same-directory candidate, then validates and publishes that exact candidate.
6767
It reads the current complete record and requires the candidate's
6868
`generation` to equal the current generation plus one and its
6969
`predecessor_sha256` to equal SHA-256 of the exact current `checkpoint-v1` line;
70-
the bootstrap record uses generation zero and a null predecessor. Reject a
71-
missing or stale predecessor without replacing the current record. The helper
70+
the bootstrap record uses generation zero and a null predecessor. It also
71+
requires the candidate to perform the predecessor's exact `next_action`, so a
72+
schema-valid record cannot skip or reorder an edit, test, review, gate,
73+
verification, delivery, CI-monitoring, recovery, or terminal-review transition.
74+
Reject a missing, stale, or action-incompatible predecessor without replacing
75+
the current record. The helper
7276
flushes the private candidate,
7377
recomputes the complete worktree identity and rejects publication if it changed
7478
since validation, atomically renames the stable record over the target, flushes

scripts/tests/development-discipline-plugin.bats

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,23 +187,35 @@ setup() {
187187
run bash -c 'cd "$1" && "$2" legacy-upgrade 2 "$3" "$4"' _ "$repo" "$writer" "$legacy_predecessor" "$stale"
188188
[ "$status" -eq 0 ]
189189

190+
run bash -c 'cd "$1" && "$2" passing-sequence 0 null "$3"' _ "$repo" "$writer" "$first"
191+
[ "$status" -eq 0 ]
192+
case_target="$repo/.git/development-system/checkpoints/passing-sequence.latest"
193+
case_predecessor=$(sha256sum "$case_target" | cut -d ' ' -f 1)
194+
passing_generation=1
190195
for passing_case in lightweight fast commit; do
191-
case_id="passing-$passing_case"
192-
run bash -c 'cd "$1" && "$2" "$3" 0 null "$4"' _ "$repo" "$writer" "$case_id" "$first"
193-
[ "$status" -eq 0 ]
194-
case_target="$repo/.git/development-system/checkpoints/$case_id.latest"
195-
case_predecessor=$(sha256sum "$case_target" | cut -d ' ' -f 1)
196196
case "$passing_case" in
197197
lightweight) light=null; fast=null; action=lightweight-review ;;
198198
fast) light='"review"'; fast=null; action=fast-gate ;;
199199
commit) light='"review"'; fast='"gate"'; action=commit-or-record-local-snapshot ;;
200200
esac
201-
passing_json=$(jq -cn --arg predecessor "$case_predecessor" --arg head "$head_oid" --arg empty "$empty_sha" --arg action "$action" --argjson light "$light" --argjson fast "$fast" '{generation:1,predecessor_sha256:$predecessor,baseline_oid:$head,snapshot:{head_oid:$head,tracked_sha256:$empty,untracked_sha256:$empty},state:"passing-awaiting-gates-or-review",test:{command:"test",receipt_ref:"receipt",outcome:"pass",failure_kind:null},gates:{lightweight_review_receipt:$light,fast_gate_receipt:$fast,exact_identity_verification_receipt:null},delivery:null,ci:{runs:[],terminal_success_run_id:null},next_action:$action}')
201+
passing_json=$(jq -cn --argjson generation "$passing_generation" --arg predecessor "$case_predecessor" --arg head "$head_oid" --arg empty "$empty_sha" --arg action "$action" --argjson light "$light" --argjson fast "$fast" '{generation:$generation,predecessor_sha256:$predecessor,baseline_oid:$head,snapshot:{head_oid:$head,tracked_sha256:$empty,untracked_sha256:$empty},state:"passing-awaiting-gates-or-review",test:{command:"test",receipt_ref:"receipt",outcome:"pass",failure_kind:null},gates:{lightweight_review_receipt:$light,fast_gate_receipt:$fast,exact_identity_verification_receipt:null},delivery:null,ci:{runs:[],terminal_success_run_id:null},next_action:$action}')
202202
printf 'checkpoint-v1 %s\n' "$passing_json" >"$stale"
203-
run bash -c 'cd "$1" && "$2" "$3" 1 "$4" "$5"' _ "$repo" "$writer" "$case_id" "$case_predecessor" "$stale"
203+
run bash -c 'cd "$1" && "$2" passing-sequence "$3" "$4" "$5"' _ "$repo" "$writer" "$passing_generation" "$case_predecessor" "$stale"
204204
[ "$status" -eq 0 ]
205+
case_predecessor=$(sha256sum "$case_target" | cut -d ' ' -f 1)
206+
passing_generation=$((passing_generation + 1))
205207
done
206208

209+
run bash -c 'cd "$1" && "$2" skipped-gates 0 null "$3"' _ "$repo" "$writer" "$first"
210+
[ "$status" -eq 0 ]
211+
skipped_target="$repo/.git/development-system/checkpoints/skipped-gates.latest"
212+
skipped_predecessor=$(sha256sum "$skipped_target" | cut -d ' ' -f 1)
213+
skipped_json=$(printf '%s' "$passing_json" | jq -c --arg predecessor "$skipped_predecessor" '.generation = 1 | .predecessor_sha256 = $predecessor')
214+
printf 'checkpoint-v1 %s\n' "$skipped_json" >"$stale"
215+
run bash -c 'cd "$1" && "$2" skipped-gates 1 "$3" "$4"' _ "$repo" "$writer" "$skipped_predecessor" "$stale"
216+
[ "$status" -ne 0 ]
217+
[[ "$output" == *"successor does not perform predecessor next_action"* ]]
218+
207219
invalid_passing_json=$(jq -cn --arg predecessor "$predecessor" --arg head "$head_oid" --arg empty "$empty_sha" '{generation:1,predecessor_sha256:$predecessor,baseline_oid:$head,snapshot:{head_oid:$head,tracked_sha256:$empty,untracked_sha256:$empty},state:"passing-awaiting-gates-or-review",test:{command:"test",receipt_ref:"receipt",outcome:"pass",failure_kind:null},gates:{lightweight_review_receipt:null,fast_gate_receipt:"gate",exact_identity_verification_receipt:null},delivery:null,ci:{runs:[],terminal_success_run_id:null},next_action:"lightweight-review"}')
208220
printf 'checkpoint-v1 %s\n' "$invalid_passing_json" >"$stale"
209221
run bash -c 'cd "$1" && "$2" work-item 1 "$3" "$4"' _ "$repo" "$writer" "$predecessor" "$stale"
@@ -246,6 +258,8 @@ setup() {
246258
run bash -c 'cd "$1" && "$2" remote-ci 0 null "$3"' _ "$repo" "$writer" "$stale"
247259
[ "$status" -eq 0 ]
248260
remote_target="$repo/.git/development-system/checkpoints/remote-ci.latest"
261+
remote_ready_json=$(jq -cn --arg head "$head_oid" --arg empty "$empty_sha" '{generation:0,predecessor_sha256:null,baseline_oid:$head,snapshot:{head_oid:$head,tracked_sha256:$empty,untracked_sha256:$empty},state:"pushed-or-delivery-mode-equivalent",test:{command:"test",receipt_ref:"receipt",outcome:"pass",failure_kind:null},gates:{lightweight_review_receipt:"review",fast_gate_receipt:"gate",exact_identity_verification_receipt:{receipt_ref:"verification",outcome:"pass"}},delivery:{mode:"direct-to-trunk",commit_oid:$head,pushed_oid:$head,local_snapshot:null},ci:{runs:[],terminal_success_run_id:null},next_action:"register-exact-sha-ci-monitor"}')
262+
printf 'checkpoint-v1 %s\n' "$remote_ready_json" >"$remote_target"
249263
remote_predecessor=$(sha256sum "$remote_target" | cut -d ' ' -f 1)
250264
remote_failure_json=$(jq -cn --arg predecessor "$remote_predecessor" --arg head "$head_oid" --arg empty "$empty_sha" '{generation:1,predecessor_sha256:$predecessor,baseline_oid:$head,snapshot:{head_oid:$head,tracked_sha256:$empty,untracked_sha256:$empty},state:"pushed-or-delivery-mode-equivalent",test:{command:"test",receipt_ref:"receipt",outcome:"pass",failure_kind:null},gates:{lightweight_review_receipt:"review",fast_gate_receipt:"gate",exact_identity_verification_receipt:{receipt_ref:"verification",outcome:"pass"}},delivery:{mode:"direct-to-trunk",commit_oid:$head,pushed_oid:$head,local_snapshot:null},ci:{runs:[{provider:"ci",run_id:"failed",commit_oid:$head,status:"failure"}],terminal_success_run_id:null},next_action:"edit"}')
251265
printf 'checkpoint-v1 %s\n' "$remote_failure_json" >"$stale"
@@ -274,6 +288,7 @@ setup() {
274288
run bash -c 'cd "$1" && "$2" cross-commit-ci 0 null "$3"' _ "$repo" "$writer" "$stale"
275289
[ "$status" -eq 0 ]
276290
cross_commit_target="$repo/.git/development-system/checkpoints/cross-commit-ci.latest"
291+
printf 'checkpoint-v1 %s\n' "$remote_ready_json" >"$cross_commit_target"
277292
cross_commit_predecessor=$(sha256sum "$cross_commit_target" | cut -d ' ' -f 1)
278293
retained_older_ci_json=$(jq -cn --arg predecessor "$cross_commit_predecessor" --arg head "$head_oid" --arg empty "$empty_sha" '{generation:1,predecessor_sha256:$predecessor,baseline_oid:$head,snapshot:{head_oid:$head,tracked_sha256:$empty,untracked_sha256:$empty},state:"pushed-or-delivery-mode-equivalent",test:{command:"test",receipt_ref:"receipt",outcome:"pass",failure_kind:null},gates:{lightweight_review_receipt:"review",fast_gate_receipt:"gate",exact_identity_verification_receipt:{receipt_ref:"verification",outcome:"pass"}},delivery:{mode:"direct-to-trunk",commit_oid:$head,pushed_oid:$head,local_snapshot:null},ci:{runs:[{provider:"ci",run_id:"older-success",commit_oid:"1111111111111111111111111111111111111111",status:"success"}],terminal_success_run_id:null},next_action:"register-exact-sha-ci-monitor"}')
279294
printf 'checkpoint-v1 %s\n' "$retained_older_ci_json" >"$stale"

0 commit comments

Comments
 (0)