Skip to content

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

Closed
HugoXK wants to merge 1 commit into
ThinkFlowLab:delivery/ai-centric-development-servicefrom
HugoXK:delivery1/issue-ref-url-fragment
Closed

HugoXK wants to merge 1 commit into
ThinkFlowLab:delivery/ai-centric-development-servicefrom
HugoXK:delivery1/issue-ref-url-fragment

Conversation

@HugoXK

@HugoXK HugoXK commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Written-by: Delivery-1
Fixes #2435
Owner: Delivery-1
Tip SHA: bb6579b
Branch: delivery1/issue-ref-url-fragment (fork HugoXK/FlyBot, base delivery/ai-centric-development-service @ 5e71a07e)

Reproduce

On the base, a link whose path has a segment before the # reads as owner/repo#12:

cd core && node -e "
import('./src/shared/issue-ref.js').then(m => {
  for (const t of ['see https://example.com/page#123 for details', 'https://example.com/docs/guide#12'])
    console.log(JSON.stringify(t), '->', m.issueRefs(t));
});
"

Actual: ['#123'] and ['#12']. Expected: [] for both — the module's own rule is that a word character, ., - or / in front makes the # part of an identifier, a version, a hex colour or a URL fragment; only #1234, owner/repo#1234 and a GitHub /(issues|pull)/<n> link name an issue (#1392).

What changed

core/src/shared/issue-ref.js:10 — the repository-qualified alternative had no lookbehind, so in https://example.com/page#123 it matched com/page#123 (host segment as "owner", path segment as "repo"). It now carries the same (?<![\w./-]) boundary as the bare-number alternative. The third alternative (GitHub issue/pull URL) is untouched, and so are owner/repo#1360, a bare #1360 and a mention-qualified ref.

Four files, +66/−4: core/src/shared/issue-ref.js (+6/−2), core/test/issue-ref-url-fragment.test.js (new, 29 lines), and the two generated patches/ds-bot/files/ mirrors (generate then check).

Red without the source change

core/test/issue-ref-url-fragment.test.js on base 5e71a07e (fix reverted, test file present):

not ok 1 - a URL fragment is not an issue reference: see https://example.com/page#123 for details
not ok 2 - a URL fragment is not an issue reference: https://example.com/docs/guide#12
not ok 3 - a URL fragment is not an issue reference: read https://docs.example.org/a/b#42 then
not ok 4 - the shapes that name an issue keep working beside a URL
# tests 4 / # pass 0 / # fail 4

With the source change: # tests 4 / # pass 4 / # fail 0. The fourth test also holds the accepted shapes (owner/repo#1360, a bare ref, a GitHub issue URL) so the fix is not "reject every qualified ref".

Why the existing suite missed it: its URL-fragment case is https://example.com/help/#123 (core/test/issue-ref.test.js:13), which has no owner/repo pair before the #; a fragment after one path segment is the common documentation-link shape and was untested.

What I ran (at the tip bb6579bd)

$ cd core && TZ=UTC node --import ./test/harness-resolve.mjs --test test/issue-ref-url-fragment.test.js test/issue-ref.test.js test/face-mentions.test.js test/work-dispatch.test.js
# tests 44 / # pass 44 / # fail 0

$ cd core && TZ=UTC node --import ./test/harness-resolve.mjs --test "test/*.test.js"
# tests 3163 / # pass 3156 / # fail 7

The 7 failures are the box's environment group (test/workbench-client.test.js and test/project-runtime-setup.test.js, PTY / browser routes); they fail identically with the source change reverted (32 tests / 25 pass / 7 fail in those two files) and no issue-ref suite is among them.

$ cd core && npm run lint
Found 105 warnings and 0 errors.        (warnings are pre-existing)
$ ARCH_DOCS_BASE=upstream/delivery/ai-centric-development-service node core/scripts/check-arch-docs.mjs
arch-docs: OK (4 changed file(s))
$ node scripts/ds-bot-patches.mjs generate && node scripts/ds-bot-patches.mjs check
ok   ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 (tree 5834c00, v0.1.5)
ok   10 patches apply cleanly in order
ok   core/ equals ds-bot/ + patches/ds-bot/
$ cd core && node scripts/build-client.mjs --check   # exit 0 (client untouched)

git diff upstream/delivery/ai-centric-development-service...HEAD --stat lists only the four files above.

Not run

  • No changelog fragment: changelog.d/ is outside this lane's file surface (core/src/shared/**, core/test/**); the repository gate only validates existing fragments. The change removes a false issue reference; it adds no feature.
  • No smoke test: index.js / src/host/ are untouched.

Checkpoint

{
  "pr": 2437,
  "claim": "Delivery-1",
  "issue": 2435,
  "summary": "The repository-qualified issue pattern had no lookbehind, so a URL with a path segment before the # matched as <host>/<segment>#12 and named an issue nobody meant. The qualified shape now needs the same boundary as a bare number, while owner/repo#12, a bare #12, a GitHub issue URL and a mention-qualified ref keep working. One new test file proves the fragment cases and holds the accepted shapes.",
  "files": ["core/src/shared/issue-ref.js", "core/test/issue-ref-url-fragment.test.js"],
  "checks": { "ran": "node --import ./test/harness-resolve.mjs --test test/issue-ref-url-fragment.test.js test/issue-ref.test.js test/face-mentions.test.js test/work-dispatch.test.js && node scripts/ds-bot-patches.mjs check", "result": "green", "at": "bb6579bd5af212a922d8a9b1a3a878ed07ffb2cb" },
  "next": "none — ready for review"
}

The repository-qualified shape had no lookbehind in front of it, so any
link whose path carried a segment before the `#` matched it 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 a GitHub
issue/pull URL still name the issue.

Test: core/test/issue-ref-url-fragment.test.js (red on the base: 4/4).

Docs-not-needed: the shape list in docs/subsystems/core-host.md is
unchanged; this closes a hole in the rule the module and its tests already
state (ThinkFlowLab#1392), with no new module, contract or owned-path change.
@github-actions github-actions Bot added the risk:T3 Risk tier T3 (needs a human approval), set by the controller from the diff label Nov 4, 2026
@HugoXK

HugoXK commented Nov 5, 2026

Copy link
Copy Markdown
Contributor Author

Written-by: Delivery-1

Review requested at the current tip, please.

  • PR #2437, tip bb6579bd5af212a922d8a9b1a3a878ed07ffb2cb
  • base delivery/ai-centric-development-service
  • open, not a draft, maintainer_can_modify: true
  • enqueue-guard at this tip says no Verifier report names the tip — every other check it reads is green.

One conclusion at this tip is what clears it; nothing else here is waiting on a change.

@HugoXK

HugoXK commented Nov 5, 2026

Copy link
Copy Markdown
Contributor Author

Closing: our account has no write access to ThinkFlowLab/FlyBot, so it cannot merge into delivery/ai-centric-development-service; the fix is complete and verified at bb6579bd5af212a922d8a9b1a3a878ed07ffb2cb, and we will re-open it against main or this branch the moment someone with merge rights wants it.

Owner: Delivery-1
Written-by: Delivery-1

@HugoXK HugoXK closed this Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:T3 Risk tier T3 (needs a human approval), set by the controller from the diff

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants