Skip to content

fix(issue-ref): do not read a URL fragment as owner/repo#12 - #2517

Open
HugoXK wants to merge 1 commit into
ThinkFlowLab:mainfrom
HugoXK:delivery1/main-issue-ref-url-fragment
Open

HugoXK wants to merge 1 commit into
ThinkFlowLab:mainfrom
HugoXK:delivery1/main-issue-ref-url-fragment

Conversation

@HugoXK

@HugoXK HugoXK commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #2435

Owner: Delivery-1
Reviewer: Birfy
Written-by: Delivery-1
Claim-Id: 9ebcbbe589f8456289f64635143a95d5
Base: b38ec01
Risk tier: T3

What changed

issueRefs read a URL fragment as an owner/repo#12 reference whenever the link's path had a segment before the #. https://example.com/page#123 matched com/page#123 and named issue #123; on a group line with an imperative that number becomes a card for an issue nobody meant (workDispatch → work-dispatch.js).

After: the repository-qualified shape needs the same boundary as the bare #12 (a (?<![\w./-]) in front), so a URL fragment stays a fragment. The number a caller reads is unchanged and still comes from refOf — the three alternatives keep groups 1/4/7, and no consumer picks a number itself.

owner/repo#1360, a bare #1360 and GitHub /(issues|pull)/<n> links keep naming the issue, and https://github.com/o/r/issues/123#issuecomment-4567 still yields exactly #123.

Hand-written files: core/src/shared/issue-ref.js (+4/−2), core/test/issue-ref-url-fragment.test.js (new, 42 lines), changelog.d/2435-issue-ref-url-fragment.fixed.md. patches/ds-bot/files/src/shared/issue-ref.js and its test mirror are only what node scripts/ds-bot-patches.mjs generate writes. core/client.js and core/src/client/** are untouched: the module is imported only by core/src/host/tasks.js and core/src/host/work-dispatch.js.

Verification at the tip

Tip SHA: eed6068

Ran:

  • red first on a clean b38ec011 tree carrying only core/test/issue-ref-url-fragment.test.js: # tests 8 / # pass 3 / # fail 5
  • after the fix, both issue-ref suites: # tests 22 / # pass 22 / # fail 0
  • consumer suites (work-dispatch, tasks, groups): # tests 63 / # pass 63 / # fail 0
  • full core suite, TZ=UTC node --import ./test/harness-resolve.mjs --test "test/*.test.js": # tests 2925 / # pass 2925 / # fail 0
  • node scripts/build-client.mjs --check: exit 0
  • npm run lint: 80 warnings, 0 errors
  • node scripts/ds-bot-patches.mjs check: 10 patches apply cleanly in order, core/ equals ds-bot/ + patches/ds-bot/
  • node scripts/ds-bot-patches.mjs canonical: ok patches/ds-bot/ is what generate writes
  • node .github/scripts/changelog.mjs check: 33 fragment(s) in changelog.d/ are well formed
  • ARCH_DOCS_BASE=b38ec011d7dc3df13d76c8bf60af205534b2d69d npm run arch-docs: OK (0 changed file(s))

Not run: the smoke test (no index.js or src/host change) and CI itself.

Docs-not-needed: core/src/shared/issue-ref.js is not on an owned_path of any subsystem page; this closes a hole in the rule the module comment already states, with no new module, contract or owned-path change.

Checkpoint

{
  "pr": 2517,
  "claim": "Delivery-1",
  "issue": 2435,
  "summary": "A URL fragment no longer reads as a repository-qualified issue reference: https://example.com/page#123 named issue #123 and wrote a card for it. The repository-qualified shape now needs the same boundary as a bare #12, while owner/repo#12, a bare #12 and GitHub issue and pull-request links keep their numbers. The number still comes from the one refOf export, so no caller picks a group itself. Red first on b38ec011: 5 of 8 tests failed; at the tip the full core suite is 2925/2925.",
  "files": [
    "core/src/shared/issue-ref.js",
    "core/test/issue-ref-url-fragment.test.js",
    "patches/ds-bot/files/src/shared/issue-ref.js",
    "patches/ds-bot/files/test/issue-ref-url-fragment.test.js",
    "changelog.d/2435-issue-ref-url-fragment.fixed.md"
  ],
  "checks": {
    "ran": "TZ=UTC node --import ./test/harness-resolve.mjs --test \"test/*.test.js\"; node scripts/ds-bot-patches.mjs check; node scripts/build-client.mjs --check; npm run lint",
    "result": "green",
    "at": "eed6068ba46a95d60f8c9db0dce7acb1adaaf4b2"
  },
  "next": "none \u2014 ready for review"
}

The repository-qualified shape had no boundary in front of it, so any link whose
path carried a segment before the `#` matched as `<host>/<segment>ThinkFlowLab#12`:
`https://example.com/page#123` named issue ThinkFlowLab#123 and the dispatch wrote a card for
an issue nobody meant. The qualified shape now needs the same boundary as the bare
number, so a URL fragment stays a fragment while `owner/repo#12`, a bare `ThinkFlowLab#12` and
GitHub issue/pull URLs still name the issue.

Test: core/test/issue-ref-url-fragment.test.js (red on b38ec01: 5 of 8 tests fail).

Docs-not-needed: core/src/shared/issue-ref.js is not on an owned_path of any
subsystem page; this closes a hole in the rule the module comment already states,
with no new module, contract or owned-path change.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(issue-ref): a URL fragment after a path segment is read as owner/repo#12 and names an issue nobody meant

1 participant