Skip to content

task-id-normalize-helper: false-positive advisory on HTML-commented TODO examples; range/slash IDs left half-normalised #34969

Closed

Description

@robstiles

What

task-id-normalize-helper.sh (added by GH#33612) has two defects observed on aidevops v3.39.43:

  1. 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. The task_line regex therefore treats these four example lines as live tasks. aidevops update printed 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-run then proposes rewriting only those four lines. Per reference/task-identity-parser-inventory.md, examples "must not be mechanically rewritten".

  2. Range and slash-separated IDs are skipped, which leaves mixed forms. task_pattern uses (?<![\w./-]) / (?![\w./-]), so tokens next to - or / never match. In todo/PLANS.md the 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/t066 unchanged while neighbouring IDs are rewritten

    The exclusion is presumably there to avoid branch names (feature/t022-x). An explicit tA-tB range form (both ends task tokens) and tA/tB could be handled separately.

How (worker-ready)

  • File: .agents/scripts/task-id-normalize-helper.sh
    • active_lines(): track an html_comment state. 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 --advisory mode, which already goes through active_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: --advisory prints nothing and --dry-run proposes no rewrites.
  • PLANS.md containing t038.24-t038.25, t065/t066, feature/t022-x: dry run gives t38.24-t38.25, t65/t66 and leaves feature/t022-x unchanged.
  • Existing conflict refusal (t039 alongside t39) still exits non-zero.
  • shellcheck .agents/scripts/task-id-normalize-helper.sh reports 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

  1. github-actions commented on Oct 18, 2026

    @github-actions
    Contributor

    This externally authored issue requires maintainer trust review before it can be processed by the pipeline.

    A maintainer can approve it using:

    sudo aidevops approve issue 34969
    

    This posts a cryptographic approval comment and removes the label, allowing the pipeline to process the issue on the next pulse cycle.

  2. marcusquinn commented on Oct 18, 2026

    @marcusquinn
    Owner

    Review: Recommendation: Approve

    Pre-Review Context

    Check Result
    Pre-existing duplicates None (searched task-id-normalize, HTML comment, padded IDs)
    Superseded by recent work None. The helper has a single commit, 2a10aa4bba (GH#33612/#33613); it is unchanged since. Checkout bf5f46a576 equals remote main.
    Framing matches reality Yes. Both defects reproduce on current main (evidence below).
    Current file state matches issue body references Yes. active_lines() is at .agents/scripts/task-id-normalize-helper.sh:45-76 and task_pattern at :34.

    Issue Validation

    Check Status Notes
    Reproducible Yes Defect 2 shows up on this repo's own --dry-run. In TODO.md, t004 (~20h) becomes t4, but t004.1-5, t005.1-6 on the same line stay padded. t012.6 becomes t12.6, but t012.1-t012.5 stays padded. In PLANS.md, t083-t094 stays padded while the table rows become t83…t94.
    Not a pre-existing duplicate Yes —
    Not superseded by recent work Yes —
    Actual bug Yes Defect 1: .agents/templates/todo-template.md:19-26 keeps format examples inside a GH#17804 HTML comment. Older installs had padded t001 examples there. active_lines() does not track <!-- … -->, so task_line (:37) treats those lines as live. The sibling parser issue-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-26 says examples must not be mechanically rewritten. aidevops update/init run --advisory on every managed repo (aidevops-update-lib.sh:145, aidevops-init-lib.sh:1277), so the false positive reaches users.
    In scope Yes Opt-in migration helper owned by GH#33612.

    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 legitimate tA-tB, tA/tB and tA.N-M compounds.

    Resolution plan (one canonical fix in .agents/scripts/task-id-normalize-helper.sh)

    1. HTML comments in active_lines(): add a comment state next to fence/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 of strip_html_comments. Keep the existing TOON close at :74 so it doesn't consume the HTML-comment terminator.
    2. Compound tokens: replace the reporter's separate pair pass with one compound tokenizer, so that chains and shorthand ranges are handled too. Let T = t[0-9]+(?:\.[0-9]+)*. Match (?<![\w./-])T(?:[-/](?:T|[0-9]+))*(?![\w./-]) and unpad each T member inside the match.
      • feature/t022-x stays unchanged (the lookbehind rejects it).
      • t005.1-diag-1 stays unchanged (the lookahead still rejects it).
      • t004.1-5 becomes t4.1-5, and t038.24-t038.25-t038.27 is normalized in full.
    3. Conflict safety (required): ids() (:78) and seed() (:147) must use the same tokenizer. If they don't, range members bypass the t039/t39 ambiguity refusal at :126-145 and the counter-seed invariant.

    Verification

    • A scratch repo whose TODO.md holds only the commented example block: --advisory prints nothing and --dry-run proposes no rewrites.
    • PLANS.md containing t038.24-t038.25, t065/t066, t004.1-5, t005.1-diag-1, feature/t022-x gives t38.24-t38.25, t65/t66, t4.1-5 and leaves the last two unchanged.
    • t039-t040 alongside t39 exits non-zero with CONFLICT.
    • --dry-run on this repo shows no line that is still mixed padded/unpadded after rewrite.
    • shellcheck reports zero violations.
    • No test file exists for this helper. A small focused tests/test-task-id-normalize-helper.sh is justified here, because --apply rewrites planning files.

    Second-Order Effects

    Dimension Finding
    Architectural intent Aligned. This brings the helper in line with the issue-sync parser and the inventory rule on examples.
    Safety gates touched None. It does not touch dispatch, approval or privacy gates. The conflict-refusal invariant must be preserved (step 3).
    Symptom vs root cause Root cause (grammar/context), not an output filter.
    Ripple effects --advisory output during aidevops update/init goes quiet for commented-only repos. --dry-run/--apply rewrite 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 in task-identity-parser-inventory.md:32-38 stay accurate.
    Rollback path Trivial revert of one helper. --apply was always opt-in.

    Scope & Recommendation

    • Scope creep: Low
    • Complexity: Medium (tier:standard). The tokenizer and conflict-set coupling need care.
    • Recommendation: APPROVE
    • PR disposition: NOT APPLICABLE. No PR yet. After approval this goes to the worker pipeline.
    • Labels: bug, tier:standard, auto-dispatch
    • Implementation guidance: the plan above. The reporter's "How" is accepted with two refinements: the compound tokenizer instead of a pair-only pass, and the shared tokenizer for ids()/seed().

    Dispatchability Assessment

    Check Status Notes
    Brief exists No The issue body acts as the brief: file, pattern and verification are present.
    Brief has code blocks Partial Regex given inline; enough for tier:standard.
    TODO entry with ref No —
    Task ID claimed No —

    Tier prerequisite met: Yes for tier:standard.
    What's needed to dispatch: maintainer approval (clears needs-maintainer-review), then the tier and auto-dispatch labels.

    Maintainer approval

    sudo aidevops approve issue 34969 marcusquinn/aidevops

    Thanks for the precise report and repro, @robstiles.


    aidevops.sh v3.39.43 plugin for OpenCode v1.19.3 with claude-opus-5-5

  3. Repository owner locked as resolved and limited conversation to collaborators on Oct 18, 2026
  4. marcusquinn commented on Oct 18, 2026

    @marcusquinn
    Owner

    Maintainer Approval (cryptographically signed)

    {"authority":"development","issue":{"content_digests":{"body":"46f5e8ee01ae9adb3eb81f910bc273ff1f1c0cb6d8a226c9084d0c8b077e3687","frame":"84d40a90105a30931ff3a5a745916eba4372e463a2e884e0af1acb6ec81bf4a1","title":"e397242a4e8b24f31447b04ea9c2d8a846bf4c43cfcf8954acaef8e8084bd92a"},"lifecycle":{"active_lock_reason":"resolved","assignees":[],"labels":[{"id":10384931023,"name":"needs-maintainer-review","node_id":"LA_kwDOQSEXLM8AAAACav14zw"}],"lock_anchor":{"actor":{"id":6428977,"login":"marcusquinn","type":"User"},"created_at":"2026-10-18T13:44:40Z","id":33573938859,"node_id":"LOE_lADOQSEXLM8AAAABYASRw88AAAAH0Smmqw"},"locked":true,"milestone":null,"state":"open","state_reason":null}},"issued_at":"2026-10-18T13:44:40Z","pr":null,"schema":"aidevops-approval/v2","snapshot_sha256":"80c3e91fdb7d50cf8d3e275c3ce9f20f55e7738a5d3afbc263b135bd7766047e","target":{"kind":"issue","number":34969,"repository":"marcusquinn/aidevops"}}
    
    -----BEGIN SSH SIGNATURE-----
    U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgeu2Ii1FVuPun+49v51FONnIskf
    TinwsexuL1MNgCwJ8AAAAQYWlkZXZvcHMtYXBwcm92ZQAAAAAAAAAGc2hhNTEyAAAAUwAA
    AAtzc2gtZWQyNTUxOQAAAEDV/N62tzPPUeeqazINkJeamOlafP9x8Ubzsj27fVmp+Dy1fb
    jVGbnpSpZigVtUa6d9I2HEifYWAe+N6DpG+9sP
    -----END SSH SIGNATURE-----
    

    This approval was signed with a root-protected SSH key. It cannot be forged by automation.

    This issue is now locked. To propose scope changes, open a new issue referencing this one.


    aidevops.sh v3.39.43 automated scan.

  5. added
    auto-dispatchEligible for automated worker dispatch
    and removed
    needs-maintainer-reviewExternal-author gate requiring maintainer approval before work begins
    on Oct 18, 2026
  6. self-assigned this
    on Oct 18, 2026
  7. added
    status:claimedInteractive implementation is actively claimed
    and removed on Oct 18, 2026
  8. marcusquinn commented on Oct 18, 2026

    @marcusquinn
    Owner

    Interactive session claimed by @marcusquinn in aidevops-bugfix-gh34969-gh-34969-task-id-normalize-html-comments on Mac.
    Pulse dispatch blocked via status:claimed + self-assignment.


    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.

  9. added
    status:in-reviewNon-draft PR ready for review/merge
    and removed
    status:claimedInteractive implementation is actively claimed
    on Oct 18, 2026
  10. removed their assignment
    on Oct 18, 2026
  11. added and removed
    status:in-reviewNon-draft PR ready for review/merge
    on Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    auto-dispatchEligible for automated worker dispatchsolved:interactiveTask was solved by an interactive sessionstatus:doneTask is completetier:standardStandard workload: implementation, bug fixes, refactors

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions