feat: enforce backlog-first column on create_board_item hook #212

Merged
forgejo_admin merged 1 commit from 211-backlog-first-enforcement into main 2026-03-28 16:25:18 +00:00
Contributor

Summary

Adds column validation to check-board-item.sh so new board items must land in backlog. Only incidents (type:incident label) may skip directly to in_progress. All other columns are blocked with a clear error message.

Changes

  • hooks/check-board-item.sh — Extract column field from tool input, add case-based column validation (backlog allowed, in_progress requires type:incident, everything else blocked), update header comment

Test Plan

All 4 acceptance criteria verified via piped JSON input:

  • column: backlog — succeeds (exit 0, no output)
  • column: todo — blocked (deny JSON with clear message)
  • column: in_progress + type:incident — succeeds (exit 0, no output)
  • column: in_progress without incident label — blocked (deny JSON with clear message)
  • Edge cases: no column specified (passes through), next_up and done also blocked

Review Checklist

  • Column validation added for backlog-first enforcement
  • Incident bypass works (type:incident to in_progress)
  • All 4 acceptance criteria tested and passing
  • Edge cases covered (no column, next_up, done)
  • Error messages reference sop-board-workflow
  • Header comment updated to document new validation
  • sop-board-workflow (column semantics)
  • template-ticket (board item conventions)

Closes #211

  • Parent: #210 (validation-gate hook)
  • SOP: sop-board-workflow column semantics
## Summary Adds column validation to `check-board-item.sh` so new board items must land in `backlog`. Only incidents (`type:incident` label) may skip directly to `in_progress`. All other columns are blocked with a clear error message. ## Changes - `hooks/check-board-item.sh` — Extract `column` field from tool input, add case-based column validation (backlog allowed, in_progress requires type:incident, everything else blocked), update header comment ## Test Plan All 4 acceptance criteria verified via piped JSON input: - `column: backlog` — succeeds (exit 0, no output) - `column: todo` — blocked (deny JSON with clear message) - `column: in_progress` + `type:incident` — succeeds (exit 0, no output) - `column: in_progress` without incident label — blocked (deny JSON with clear message) - Edge cases: no column specified (passes through), `next_up` and `done` also blocked ## Review Checklist - [x] Column validation added for backlog-first enforcement - [x] Incident bypass works (type:incident to in_progress) - [x] All 4 acceptance criteria tested and passing - [x] Edge cases covered (no column, next_up, done) - [x] Error messages reference sop-board-workflow - [x] Header comment updated to document new validation ## Related Notes - sop-board-workflow (column semantics) - template-ticket (board item conventions) ## Related Closes #211 - Parent: #210 (validation-gate hook) - SOP: sop-board-workflow column semantics
After the existing fast-forward logic, extract the merged branch name
and remove any matching worktree. gh path uses `gh pr view` for the
branch name; MCP path uses the Forgejo API. Best-effort: silent exit
if no matching worktree exists.

Closes #194

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address 2 QA blockers and 4 nits from PR #199 review:

Blockers:
- Extract ~30-line worktree walk-and-remove logic into
  remove_worktree_for_branch() in forgejo-helper.sh, sourced by both hooks
- Replace token auth (Authorization: token) with existing _load_forgejo_creds
  basic auth pattern in post-mcp-merge-rebase.sh

Nits:
- Initialize MERGED_BRANCH="" in post-merge-rebase.sh
- Add comment about gh pr merge without explicit PR number silently skipping
- Add --connect-timeout 5 --max-time 10 to the Forgejo API curl call
- Differentiate log tags: [post-merge-cleanup:gh] and [post-merge-cleanup:mcp]

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New items must land in backlog. Only incidents (type:incident label)
may go directly to in_progress. All other columns are blocked with
a clear error message pointing to sop-board-workflow.

Closes #211

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
forgejo_admin force-pushed 211-backlog-first-enforcement from 7f12b6ae48 to 68a3d18482 2026-03-28 16:15:35 +00:00 Compare
Author
Contributor

QA Review

Scope Verification

PR changes only hooks/check-board-item.sh (1 file, 21 additions). Correctly scoped to issue #211. Note: rebased to remove 2 unrelated commits from branch 194 that leaked in during clone.

Acceptance Criteria

  • column: backlog succeeds (exit 0, no output)
  • column: todo blocked (deny JSON)
  • column: in_progress + type:incident succeeds
  • column: in_progress without incident label blocked
  • Edge: no column specified passes through (fail-open)
  • Edge: next_up, done also blocked

Code Quality

  • Column extraction follows existing jq pattern with // empty
  • Case statement is idiomatic, covers all three paths (backlog/in_progress/wildcard)
  • Null/empty guard consistent with existing checks
  • Error messages are clear, actionable, reference sop-board-workflow
  • Fail-open preserved (no column = no enforcement)
  • Header comment updated
  • No regressions to existing label/type validations

Edge Case: empty labels + in_progress

When labels is empty and column is in_progress, grep -q "type:incident" correctly fails on empty input, blocking the item. Correct behavior.

VERDICT: APPROVE

## QA Review ### Scope Verification PR changes only `hooks/check-board-item.sh` (1 file, 21 additions). Correctly scoped to issue #211. Note: rebased to remove 2 unrelated commits from branch 194 that leaked in during clone. ### Acceptance Criteria - [x] `column: backlog` succeeds (exit 0, no output) - [x] `column: todo` blocked (deny JSON) - [x] `column: in_progress` + `type:incident` succeeds - [x] `column: in_progress` without incident label blocked - [x] Edge: no column specified passes through (fail-open) - [x] Edge: `next_up`, `done` also blocked ### Code Quality - Column extraction follows existing jq pattern with `// empty` - Case statement is idiomatic, covers all three paths (backlog/in_progress/wildcard) - Null/empty guard consistent with existing checks - Error messages are clear, actionable, reference sop-board-workflow - Fail-open preserved (no column = no enforcement) - Header comment updated - No regressions to existing label/type validations ### Edge Case: empty labels + in_progress When labels is empty and column is `in_progress`, `grep -q "type:incident"` correctly fails on empty input, blocking the item. Correct behavior. ### VERDICT: APPROVE
forgejo_admin deleted branch 211-backlog-first-enforcement 2026-03-28 16:25:18 +00:00
Sign in to join this conversation.
No description provided.