Phase 4-1: Hook hardening (sed bug, portability, dynamic fields) #65
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
ldraney/claude-custom#65
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Lineage
plan-2026-03-07-note-hierarchy-conventions→ Phase 4 (Enforcement Hook) → Phase 4-1 (Hook Hardening)Repo
forgejo_admin/claude-customUser Story
As a platform operator
I want hooks to be correct and portable
So that HTML entity decoding doesn't corrupt data and hooks work on non-GNU systems
Context
QA review of PR #64 (check-phase-template.sh) found three issues. Two are cross-cutting bugs affecting all hooks that decode HTML entities, one is specific to the new phase hook.
Bug 1 — sed ampersand backreference (CROSS-CUTTING):
All hooks using
sed 's/</</g'style HTML entity decoding have a latent bug. In sed replacement strings,&is a backreference to the matched pattern. Example: if content contains&literally, the sed chains/&/\&/greplaces&with&(the matched text) rather than&. The fix is to escape&as\&in replacements, or better yet, avoid the ambiguity entirely.Affected files:
hooks/check-issue-template.shhooks/check-note-template.shhooks/check-phase-template.shBug 2 — GNU grep
\|syntax (CROSS-CUTTING):Hooks use
grep 'patternA\|patternB'which is GNU grep BRE syntax. POSIX-portable equivalent isgrep -E 'patternA|patternB'. Works on Arch (GNU grep) but fails silently on Alpine/busybox.Affected files: any hook using
\|in grep patterns. Check all hooks.Improvement 3 — Hardcoded field list in check-phase-template.sh:
The hook hardcodes Goal/Owner/Repo/Depends on checks. Unlike
check-issue-template.sh(which extracts### headingsfrom the markdown template dynamically), the phase template uses HTML<strong>tags which are harder to parse generically. Options: (a) extract from template's Hook Enforcement section, (b) add a comment documenting why it's hardcoded. Option (b) is simpler and honest.File Targets
Files the agent should modify:
hooks/check-issue-template.sh— fix sed ampersand bug, fix grep portabilityhooks/check-note-template.sh— fix sed ampersand bug, fix grep portabilityhooks/check-phase-template.sh— fix sed ampersand bug, fix grep portability, add comment about hardcoded fieldsFiles the agent should check (fix if affected):
hooks/*.shfiles — scan for\|in grep patterns and&in sed replacementsFiles the agent should NOT touch:
settings.json— no registration changes needed.mdfilesAcceptance Criteria
sedHTML entity decoding uses properly escaped replacements (no bare&in replacement strings)greppatterns use-Eflag with|instead of BRE\|check-phase-template.shhas a comment explaining why fields are hardcoded (HTML<strong>tags vs markdown###headings)Test Expectations
Constraints
trap 'exit 0' ERR) in all hooks-Eflag and remove backslash before|Checklist
Related
phase-hierarchy-4-1-hook-hardening— phase notetemplate-phase— the template check-phase-template.sh enforcesai-agency— project