Repository navigation
task-id-normalize-helper: false-positive advisory on HTML-commented TODO examples; range/slash IDs left half-normalised #34969
Description
What
task-id-normalize-helper.sh (added by GH#33612) has two defects observed on aidevops v3.39.43:
-
False-positive advisory from HTML-commented format examples. Repos initialised from the GH#17804-era template wrap the format examples in an HTML comment:
<!-- GH#17804: Format examples wrapped in HTML comment to prevent parsers from extracting them as real tasks during upgrade-planning migrations. - [ ] t001 Task description @owner #tag ~30m risk:low logged:2025-01-15 - [ ] t002 Dependent task blocked-by:t001 ~15m risk:med - [ ] t001.1 Subtask of t001 ~10m - [x] t003 Completed task ~30m actual:25m logged:2025-01-10 completed:2025-01-15 - [-] Declined task -->active_lines()tracks code fences, TOON blocks and archive headings, but not plain<!-- ... -->comments. Thetask_lineregex therefore treats these four example lines as live tasks.aidevops updateprinted the padded-ID advisory for 3 of my 4 managed repos, and in each of those 3 the only matches were these commented examples.--dry-runthen proposes rewriting only those four lines. Perreference/task-identity-parser-inventory.md, examples "must not be mechanically rewritten". -
Range and slash-separated IDs are skipped, which leaves mixed forms.
task_patternuses(?<![\w./-])/(?![\w./-]), so tokens next to-or/never match. Intodo/PLANS.mdthe dry run produces half-normalised prose such as:(t038.24-t038.25, t038.27, t038.29-t038.30)->(t038.24-t038.25, t38.27, t038.29-t038.30)(t049: t050-t056)->(t49: t050-t056)t095-t098 (... t098 blocks t113)->t095-t098 (... t98 blocks t113)t065/t066unchanged while neighbouring IDs are rewritten
The exclusion is presumably there to avoid branch names (
feature/t022-x). An explicittA-tBrange form (both ends task tokens) andtA/tBcould be handled separately.
How (worker-ready)
- File:
.agents/scripts/task-id-normalize-helper.shactive_lines(): track anhtml_commentstate. Enter it on a line containing<!--that is not a single-line comment and not a<!--TOON:marker. Leave it on the line containing-->. Yield those lines as inactive. Apply the same logic in--advisorymode, which already goes throughactive_lines().- Add a range/pair pass: match
(?<![\w./-])(t\d+(?:\.\d+)*)([-/])(t\d+(?:\.\d+)*)(?![\w./-])and unpad both sides. Keep the existing single-token lookarounds so branch names stay untouched.
- Reference pattern: the existing fence/TOON state machine in
active_lines().
Verification
- Temp git repo whose TODO.md contains the HTML-commented block above and nothing else:
--advisoryprints nothing and--dry-runproposes no rewrites. - PLANS.md containing
t038.24-t038.25, t065/t066, feature/t022-x: dry run givest38.24-t38.25, t65/t66and leavesfeature/t022-xunchanged. - Existing conflict refusal (
t039alongsidet39) still exits non-zero. shellcheck .agents/scripts/task-id-normalize-helper.shreports zero violations.
aidevops.sh v3.39.43 plugin for OpenCode v1.19.3 with claude-opus-5-5 spent 1m and 4,005 tokens on this with the user in an interactive session.
Activity
github-actions commentedon Oct 18, 2026
This externally authored issue requires maintainer trust review before it can be processed by the pipeline.
A maintainer can approve it using:
This posts a cryptographic approval comment and removes the label, allowing the pipeline to process the issue on the next pulse cycle.
marcusquinn commentedon Oct 18, 2026
Review: Recommendation: Approve
Pre-Review Context
task-id-normalize, HTML comment, padded IDs)2a10aa4bba(GH#33612/#33613); it is unchanged since. Checkoutbf5f46a576equals remotemain.main(evidence below).active_lines()is at.agents/scripts/task-id-normalize-helper.sh:45-76andtask_patternat:34.Issue Validation
--dry-run. InTODO.md,t004 (~20h)becomest4, butt004.1-5, t005.1-6on the same line stay padded.t012.6becomest12.6, butt012.1-t012.5stays padded. InPLANS.md,t083-t094stays padded while the table rows becomet83…t94..agents/templates/todo-template.md:19-26keeps format examples inside a GH#17804 HTML comment. Older installs had paddedt001examples there.active_lines()does not track<!-- … -->, sotask_line(:37) treats those lines as live. The sibling parserissue-sync-lib-parse.sh(strip_code_fences→strip_html_comments,:54-64) already excludes them, so the normalizer is the one that's out of step.reference/task-identity-parser-inventory.md:24-26says examples must not be mechanically rewritten.aidevops update/initrun--advisoryon every managed repo (aidevops-update-lib.sh:145,aidevops-init-lib.sh:1277), so the false positive reaches users.Root cause: the helper uses one fixed lexical grammar. The context state machine has no HTML-comment state. The token regex's lookarounds
(?<![\w./-])…(?![\w./-])reject branch names, but they also reject legitimatetA-tB,tA/tBandtA.N-Mcompounds.Resolution plan (one canonical fix in
.agents/scripts/task-id-normalize-helper.sh)active_lines(): add acommentstate next tofence/toon. A line that opens<!--without closing-->on the same line enters the state. The line containing-->leaves it. Exclude<!--TOON:and<!--/TOON:markers. Every line inside the state, including the open and close lines, is yielded inactive. Single-line<!-- … -->on a task line leaves the task line active. Match the semantics ofstrip_html_comments. Keep the existing TOON close at:74so it doesn't consume the HTML-comment terminator.T = t[0-9]+(?:\.[0-9]+)*. Match(?<![\w./-])T(?:[-/](?:T|[0-9]+))*(?![\w./-])and unpad eachTmember inside the match.feature/t022-xstays unchanged (the lookbehind rejects it).t005.1-diag-1stays unchanged (the lookahead still rejects it).t004.1-5becomest4.1-5, andt038.24-t038.25-t038.27is normalized in full.ids()(:78) andseed()(:147) must use the same tokenizer. If they don't, range members bypass thet039/t39ambiguity refusal at:126-145and the counter-seed invariant.Verification
TODO.mdholds only the commented example block:--advisoryprints nothing and--dry-runproposes no rewrites.PLANS.mdcontainingt038.24-t038.25, t065/t066, t004.1-5, t005.1-diag-1, feature/t022-xgivest38.24-t38.25, t65/t66, t4.1-5and leaves the last two unchanged.t039-t040alongsidet39exits non-zero withCONFLICT.--dry-runon this repo shows no line that is still mixed padded/unpadded after rewrite.shellcheckreports zero violations.tests/test-task-id-normalize-helper.shis justified here, because--applyrewrites planning files.Second-Order Effects
--advisoryoutput duringaidevops update/initgoes quiet for commented-only repos.--dry-run/--applyrewrite more range IDs, which is intended. The counter seed may count more padded IDs, but only to the extent they already counted as single tokens, so the high-water mark cannot decrease. Docs intask-identity-parser-inventory.md:32-38stay accurate.--applywas always opt-in.Scope & Recommendation
tier:standard). The tokenizer and conflict-set coupling need care.bug,tier:standard,auto-dispatchids()/seed().Dispatchability Assessment
tier:standard.Tier prerequisite met: Yes for
tier:standard.What's needed to dispatch: maintainer approval (clears
needs-maintainer-review), then the tier andauto-dispatchlabels.Maintainer approval
sudo aidevops approve issue 34969 marcusquinn/aidevopsThanks for the precise report and repro, @robstiles.
aidevops.sh v3.39.43 plugin for OpenCode v1.19.3 with claude-opus-5-5
marcusquinn commentedon Oct 18, 2026
Maintainer Approval (cryptographically signed)
This approval was signed with a root-protected SSH key. It cannot be forged by automation.
aidevops.sh v3.39.43 automated scan.
marcusquinn commentedon Oct 18, 2026
aidevops.sh v3.39.43 plugin for OpenCode v1.19.3 with claude-opus-5-5 spent 8m and 13,802 tokens on this with the user in an interactive session.