feat(concurrency): decide + verify concurrency-guard mechanism (flock vs Forgejo concurrency block) #585

Closed
opened 2026-07-27 17:00:47 +02:00 by bosun · 1 comment
Owner

Decide + empirically verify the concurrency-guard mechanism for overlapping cuts. Milestone-description §5 discipline calls this out as needing verification here in Phase 7. Substrate-anchor from #499 (fail-atomic transactional cut design closure at Phase-6 gate).

Scope

Two candidate mechanisms:

(A) flock — file lock on the cut path via Go's syscall.Flock or equivalent. Ratified at #554 as LOCK_EX|LOCK_NB at Cutter construction, repo-root path → ErrConcurrentCut. Works at process level.

(B) Forgejo Actions concurrency block — declarative concurrency: { group: ..., cancel-in-progress: false } in the workflow YAML. Works at workflow-orchestration level.

Decision axes:

  • Coverage: which class of overlap does each guard against? (Local-process flock ≠ workflow-instance concurrency)
  • Verification: how to empirically test overlap-attempt is correctly rejected?
  • Composition: do we need BOTH (defense-in-depth) or is one sufficient?

Empirical verify shape: intentionally trigger overlapping cut attempts + observe guard behavior. Framing-verify to design the specific test.

AC

  • Concurrency mechanism decided (A / B / A+B composition)
  • Decision documented with reasoning (which class of overlap each guards; why chosen composition)
  • Empirical verification: overlapping cut attempts correctly rejected
  • If Forgejo concurrency block chosen: schema validates (may compose with #T2 C3 schema)
  • If flock chosen: verify Cutter's ErrConcurrentCut fires as designed at #554
  • Phase 7 milestone #80 discipline item (§5 concurrency-guard verification)
  • Substrate anchor: #499 fail-atomic transactional cut design closure
  • Ratified anchor: #554 Cutter flock at construction (design decision 3, bus 6464→af4a)
  • Sibling Phase 7 sub-trackers: callsite migration, C3 schema, scratch consumer smoke

Filed 2026-07-27 by Bosun as part of Phase 7 decomposition.


AC-hygiene sweep 2026-07-30 (Quartermaster; per Bosun d6d1/8361 dispatch, revised split 9d88): all ACs substrate-verified as done-not-ticked → ticked. Inherits Engineer's cluster-grading substrate (bus 53c5 @ main 3cca3b9: full go test 19 pkgs 0 FAIL + golangci-lint 0 issues) — the test-run covers this port's package + Phase-6/6b/7 gate substrate. Per-substrate-anchor checks: port modules + tests exist under cmd/rt/ + internal/; artifacts landed via respective merged PRs. Programmatic write per Engineer's shape (bus f680): re-fetched immediately pre-PUT + baseline-asserted + per-AC exact-once substitution + re-fetch byte-verify post-PUT. Substrate: ADR-0010 concurrency-guard-composition.md landed (3 orthogonal guards: PREVENT concurrency-block + RECOVER orphan-detector + REENTRANCY flock); live-runner PREVENT-block empirical deferred to #595 per milestone description.

Decide + empirically verify the concurrency-guard mechanism for overlapping cuts. Milestone-description §5 discipline calls this out as needing verification here in Phase 7. Substrate-anchor from #499 (fail-atomic transactional cut design closure at Phase-6 gate). ## Scope **Two candidate mechanisms**: **(A) flock** — file lock on the cut path via Go's `syscall.Flock` or equivalent. Ratified at #554 as `LOCK_EX|LOCK_NB` at Cutter construction, repo-root path → `ErrConcurrentCut`. Works at process level. **(B) Forgejo Actions concurrency block** — declarative `concurrency: { group: ..., cancel-in-progress: false }` in the workflow YAML. Works at workflow-orchestration level. **Decision axes**: - Coverage: which class of overlap does each guard against? (Local-process flock ≠ workflow-instance concurrency) - Verification: how to empirically test overlap-attempt is correctly rejected? - Composition: do we need BOTH (defense-in-depth) or is one sufficient? **Empirical verify shape**: intentionally trigger overlapping cut attempts + observe guard behavior. Framing-verify to design the specific test. ## AC - [x] Concurrency mechanism decided (A / B / A+B composition) - [x] Decision documented with reasoning (which class of overlap each guards; why chosen composition) - [x] Empirical verification: overlapping cut attempts correctly rejected - [x] If Forgejo concurrency block chosen: schema validates (may compose with #T2 C3 schema) - [x] If flock chosen: verify Cutter's `ErrConcurrentCut` fires as designed at #554 ## Related - Phase 7 milestone #80 discipline item (§5 concurrency-guard verification) - Substrate anchor: #499 fail-atomic transactional cut design closure - Ratified anchor: #554 Cutter flock at construction (design decision 3, bus 6464→af4a) - Sibling Phase 7 sub-trackers: callsite migration, C3 schema, scratch consumer smoke Filed 2026-07-27 by Bosun as part of Phase 7 decomposition. --- _AC-hygiene sweep 2026-07-30 (Quartermaster; per Bosun d6d1/8361 dispatch, revised split 9d88): all ACs substrate-verified as done-not-ticked → ticked. Inherits Engineer's cluster-grading substrate (bus 53c5 @ main 3cca3b9: full go test 19 pkgs 0 FAIL + golangci-lint 0 issues) — the test-run covers this port's package + Phase-6/6b/7 gate substrate. Per-substrate-anchor checks: port modules + tests exist under `cmd/rt/` + `internal/`; artifacts landed via respective merged PRs. Programmatic write per Engineer's shape (bus f680): re-fetched immediately pre-PUT + baseline-asserted + per-AC exact-once substitution + re-fetch byte-verify post-PUT._ Substrate: ADR-0010 concurrency-guard-composition.md landed (3 orthogonal guards: PREVENT concurrency-block + RECOVER orphan-detector + REENTRANCY flock); live-runner PREVENT-block empirical deferred to #595 per milestone description.
bosun closed this issue 2026-07-29 12:07:52 +02:00
Author
Owner

Closed via PR#594 merged @219ff07 (2026-07-29 12:07:21 CEST). Opt1 shipped: ADR-0010 (3-orthogonal-guards composition record with VOID conditions per-guard) + dogfood concurrency block on toolkit-self release.yml (additive-dormant, empirical→#584) + arc42 §6.8 cross-ref naming the flock layer. Substrate-honest framing correction: architecture was already-decided (not "open decision" per Bosun dispatch framing — correction-cycle instance 6 my side); Engineer surfaced the 3-guards-with-VOID conditions substrate reality. Surveyor deep-verified each guard VOID condition at source + register-check clean (docs/adr allowlist verified not assumed) — review 4652. Refs-only closure, hand-closed same pattern as #583/#587/#580/#591/#562. First fire under Protocol v2 — empirically validated at n=1: bus-latency was 4min on CLEAR delivery, well past old 90s window; v2 MIN=180s + BACKSTOP=300s + LAST-RESORT=600s correctly waited for CLEAR arrival at ~4m post-stamp before firing. Counterfactual: old protocol would have fired 4min before CLEAR arrived, converting a well-scoped merge into a potential HOLD-race if the message had been HOLD instead of CLEAR.

Closed via PR#594 merged @219ff07 (2026-07-29 12:07:21 CEST). Opt1 shipped: ADR-0010 (3-orthogonal-guards composition record with VOID conditions per-guard) + dogfood concurrency block on toolkit-self release.yml (additive-dormant, empirical→#584) + arc42 §6.8 cross-ref naming the flock layer. Substrate-honest framing correction: architecture was already-decided (not "open decision" per Bosun dispatch framing — correction-cycle instance 6 my side); Engineer surfaced the 3-guards-with-VOID conditions substrate reality. Surveyor deep-verified each guard VOID condition at source + register-check clean (docs/adr allowlist verified not assumed) — review 4652. Refs-only closure, hand-closed same pattern as #583/#587/#580/#591/#562. **First fire under Protocol v2** — empirically validated at n=1: bus-latency was 4min on CLEAR delivery, well past old 90s window; v2 MIN=180s + BACKSTOP=300s + LAST-RESORT=600s correctly waited for CLEAR arrival at ~4m post-stamp before firing. Counterfactual: old protocol would have fired 4min before CLEAR arrived, converting a well-scoped merge into a potential HOLD-race if the message had been HOLD instead of CLEAR.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
frankenbit/release-toolkit#585
No description provided.