BACK-494 - Backlog-Guard: PreToolUse hook to enforce MCP/CLI access to backlog directories#649
BACK-494 - Backlog-Guard: PreToolUse hook to enforce MCP/CLI access to backlog directories#649lenucksi wants to merge 49 commits into
Conversation
- Add terminalStatuses?: string[] to BacklogConfig interface - Parse terminal_statuses key in config loader (same pattern as statuses) - Extend getTerminalStatus/isTerminalStatus with optional terminalStatuses param - Falls back to last-element convention when not provided (backward-compatible) - isTerminalStatus returns true for any entry in terminalStatuses array - getTerminalStatus returns terminalStatuses[0] as primary terminal status - Add 5 new test cases covering multi-terminal, fallback, empty-array, and non-last-element override scenarios Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BACK-465 - Config-Schema: terminalStatuses-Key einführen
…atistics, milestones, handlers Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…uences and board filters Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…x serializeConfig Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Added 4 tests to src/web/lib/lanes.test.ts covering the sortTasksForStatus refactoring from BACK-467: custom terminal status gets done-sort even when not last in statuses array, empty terminalStatuses falls back to last-element convention, and active statuses are unaffected when terminalStatuses is set. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tyling
- Add blockedStatuses?: string[] to BacklogConfig type
- Parse/serialize blocked_statuses in parseConfig/serializeConfig (same pattern as terminalStatuses)
- Extend getStatusStyle(), getStatusColor(), getStatusIcon(), formatStatusWithIcon() to accept optional blockedStatuses param
- Config-aware check runs first; falls back to exact-match statusMap ("Blocked") and substring heuristic (includes("blocked"))
- Thread blockedStatuses prop through App.tsx -> BoardPage -> Board -> TaskColumn
- Update getStatusBadgeClass() in TaskColumn: config array checked first, then fallback includes("blocked")/includes("stuck")
- Add 3 new tests (RED confirmed before implementation)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…HEAD Replace git rev-list --all --count with git rev-list --count HEAD in getCommitCountInTest. The --all flag includes refs/notes/ai commits created asynchronously by the global git-ai trace2 tool, inflating counts non-deterministically. HEAD-scoped counting matches the approach in cli.test.ts and correctly measures commits on the current branch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…HEAD Replace git rev-list --all --count with git rev-list --count HEAD in getCommitCountInTest. The --all flag includes refs/notes/ai commits created asynchronously by the global git-ai trace2 tool, inflating counts non-deterministically. HEAD-scoped counting matches the approach in cli.test.ts and correctly measures commits on the current branch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Commit all untracked backlog task files (back-465 through back-482) and update modified task files (back-200 through back-438) to establish a safe baseline before upstream PR rebase operations. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Upstream version-bump CI commit used 2-space indent; reformat to tabs to match the project Biome config and unblock `bun run check .`. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Renamed back-466/back-467 task files from German to English names. Translated implementation notes in back-469 to English. BACK-480 marked Done with full notes and final summary. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Exclude package.json from Biome's formatter via overrides to prevent tabs-vs-spaces conflicts on every pull from upstream, which uses spaces. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
style.css is rebuilt by build:css before every build/cli invocation; committing it caused noisy 200KB single-line diffs on any CSS change. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New tasks: - BACK-486: Colored Labels (WebUI/TUI/CLI/MCP/REST) - BACK-487: Labels for Documents and Decisions - BACK-488: Label Management — central CRUD + autocomplete - BACK-489: Archive Documents and Decisions + superseded ADRs - BACK-490: REST API OpenAPI self-documentation - BACK-491: Cross-Modality CI — enforce feature parity - BACK-492: Tech Debt Research — codebase audit Updated: - BACK-474: recycled from German stub → Sequence/Dependency Visualizer Research (audits BACK-217/218 cluster, library eval, no code) - BACK-484: fleshed out assignee autocomplete stub with description + AC (scraping-based, no central config) All tickets include upstream-master constraint block and explicit 5-modality AC. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- BACK-466/467: translate implementation notes and titles to English (BACK-480 follow-up) - BACK-479/481/482: mark Done, check off all ACs, add Final Summary sections - BACK-478: remove task (superseded by BACK-479–482) - BACK-483: add new task (subtasks / Epic-level tracking question) - .gitignore: ignore archive/ directory Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously the milestones page sorted milestone cards by ID descending (newest first), so a project with phases m-3 through m-6 would display Phase 9 (m-6) at the top, followed by Phase 7 (m-4) and Phase 8 (m-5). This reverses the sort to ascending so milestones appear in their natural creation order (m-1 → m-2 → m-3 … ), matching the sequence users intend when they create milestones in phase/sprint order.
The task list view (web UI + CLI) previously only supported sorting by id and priority. Tasks have an ordinal field used for manual wave-based ordering, which the board view already respects — but the list view ignored it entirely, showing tasks in ID order with no way to recover the deliberate sequence. Changes: - TaskList.tsx: add "ordinal" to TaskSortColumn union type; add ordinal sort case in sortedDisplayTasks useMemo (tasks with ordinals come first, then ascending by ordinal value, matching board view behavior); add sortable "Ordinal" column header and data cell in the table - cli.ts: add "ordinal" to validSortFields in all four task list/draft list call sites; update --sort option help text accordingly Closes MrLesk#643
…o backlog dirs Adds hooks/backlog-guard/ — a hard-blocking PreToolUse hook that intercepts Read/Edit/Write/Bash operations on files inside configured backlog directories and redirects the agent to the correct MCP tool or CLI command. Config via .backlog-guard YAML at git root (auto-discovered via git rev-parse); falls back to auto-detecting backlog/config.yml in the directory tree. Block messages include the exact MCP call and CLI command, with task ID extracted from the filename (back-NNN-title.md) for task files. Also adds .codex/skills/backlog-guard-setup/SKILL.md — a setup skill that auto-detects the backlog directory, creates .backlog-guard, writes the hook entry into the appropriate settings file, and optionally adds mcp__backlog__* allowlist entries. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…aths - Add Grep tool handling: block when path resolves under protected dir; suggest task_search for tasks, document_search for docs - Write with no task ID in filename now suggests task_create instead of task_edit; Write to new doc path suggests document_create instead of document_update - classify_path now covers completed/, drafts/, decisions/ directories - _generic_suggestions handles decision type (search suggestion) - Matcher updated to Read|Edit|Write|Bash|Grep in README and setup skill - 4 new tests (12 total, all passing) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
hooks/backlog-guard introduces .py and .sh files; adding these languages enables LSP support for the new hook files in the Serena project. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
hooks/backlog-guard introduces .py and .sh files; adding these languages enables LSP support for the new hook files in the Serena project. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add isPortAvailable() and findNextAvailablePort() to server/index.ts, pre-check port in CLI browser command, prompt user to start on next free port if taken. Simplify EADDRINUSE catch (UX now in CLI).
# Conflicts: # backlog/tasks/back-473 - handle-port-congestion-for-backlog-browser.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Code and OpenCode Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
05c0f69 to
17a4aab
Compare
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cate cleanup - Created 6 new milestones (m-7 through m-13) covering Forge Integration, Web UI Polish, Task Schema & Metadata, Subtasks & Dependencies, Agent & IDE Integrations, CLI & TUI Enhancements, and Infrastructure & DevEx - Assigned all ~80 open tasks to milestones - Closed BACK-222 and BACK-483 as duplicates of the BACK-493 cluster - Marked BACK-420 as sub-concern of BACK-260; added cross-references - Added dependency and relationship notes across BACK-239/477, BACK-349/200/310, and the BACK-474/217 sequence cluster - Set priorities on all previously unprioritized open tasks (1× high, 14× medium, 16× low) - Added dependency chains: 268→267, 487→486, 488→486, 504→500+503, 506→260 - Added BACK-506 (batch operations in All Tasks view) to Web UI Polish milestone Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Research pass identifying DRY/KISS violations, pattern inconsistencies, and static analysis tooling options. Output: doc-004 in backlog/docs/. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Internal audit document (doc-004) — not for upstream PR.
4 additional DRY/KISS violations: core.fs vs core.filesystem accessor inconsistency, duplicate ensureInitialized pattern, error surface fragmentation across modalities, repeated listMilestones Promise.all. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Create doc-005 with full CLI/TUI/WebUI/MCP feature matrix across 9 domains. Create BACK-492 subtasks .1–.7 from audit stubs A–G with full ACs and implementation plans. Keep BACK-492 In Progress pending subtask completion. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…l summary Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Milestone cards sort by ID ascending (m-1 before m-2). Tests used [0] to pick the first Edit/Remove button but expected m-2 (Release 2) behavior. Changed [0] to [1] to match actual card ordering.
…Code and OpenCode Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Claude Code + OpenCode, dual MCP naming, Claude Code plugin structure, marketplace, skills
17a4aab to
0d84d25
Compare
…publish workflow - packages/backlog-guard/package.json - scoped npm package for OpenCode plugin - .github/workflows/publish-backlog-guard.yml - publish on push/tag/manual - dev.sh copies compiled opencode-plugin.js into the package
|
Alex's Agent: Thanks for putting this together. I’m going to close this for the current project scope rather than try to review it into shape. The main issue is scope/risk, not the underlying goal. This PR currently touches 171 files with +15,852/-130 lines, carries 49 commits, includes unrelated backlog/task/doc/milestone and product changes, is behind/conflicting with For the current project direction we’re keeping agent integration conservative and public-surface based: short generated instructions plus optional CLI/MCP setup. A cross-client enforcement hook is product direction we’d need to design deliberately, not merge as a broad PR. If we revisit this, it should come back as a fresh, narrow proposal or external companion package with clear product ownership, no unrelated backlog state, no generated artifacts unless required, and tests/checks focused on that one surface. Future PRs in this area should link an issue first, or open one before implementation so scope can be agreed. |
Summary
hooks/backlog-guard/— a Claude CodePreToolUsehook that hard-blocks directRead/Edit/Write/Bashaccess to configured backlog directories and redirects agents to the correct MCP tool or CLI command with pre-filled parameters (task ID extracted from filename, document name, etc.).backlog-guardYAML file at git root, auto-discovered viagit rev-parse --show-toplevel; falls back to detectingbacklog/config.ymlin the directory tree (no configuration needed for standard single-backlog projects).codex/skills/backlog-guard-setup/SKILL.md— a one-command setup skill that auto-detects the backlog directory, creates.backlog-guard, writes the hook entry into the appropriate settings file, and optionally addsmcp__backlog__*tool permissions to the allowlist__pycache__/and*.pycto.gitignoreTest plan
python -m pytest hooks/backlog-guard/test_check.py -v— 8 tests passReadonbacklog/tasks/back-1-...md→ denied,BACK-1in reason, MCP + CLI suggestion in contextReadonsrc/cli.ts→ allowed (not in backlog dir)Bash(cat backlog/tasks/back-1-...md)→ deniedgrep pattern file.txt | grep back-123→ allowed (pipeline stdin, not file arg).backlog-guard,backlog/config.ymlpresent → auto-detect still blocks/backlog-guard-setupskill →.backlog-guardcreated, settings hook entry writtenBlock message example
When an agent tries
Read(backlog/tasks/back-494 - Backlog-Guard-....md):🤖 Generated with Claude Code