Skip to content

task-work: recognize app.notion.com URLs in notion dispatchers (#158)#161

Merged
martin-conur merged 2 commits into
mainfrom
task/notion-app-url-158
Jun 24, 2026
Merged

task-work: recognize app.notion.com URLs in notion dispatchers (#158)#161
martin-conur merged 2 commits into
mainfrom
task/notion-app-url-158

Conversation

@martin-conur

Copy link
Copy Markdown
Owner

Summary

is_notion_url() in the notion task-work dispatchers only recognized notion.so / notion.site, so app.notion.com URLs (now Notion's default workspace/page form, and what the Notion MCP fetch/search tools return) fell through to the slug-only branch — NOTION_URL was dropped and the worker launched with no task.

Fix: add notion.com to the predicate in both claude-notion/bin/task-work and kiro-notion/bin/task-work. This also fixes the --plan / /planner path transitively (it gates URL forwarding on the same predicate). Per the corrected spec, no task-reviewer or planner-side change is needed.

Changes

  • claude-notion/bin/task-work, kiro-notion/bin/task-work: is_notion_url() now also matches *notion.com*.
  • tests/claude_notion_task_work.bats, tests/kiro_task_work.bats: regression tests covering both the <slug> <url> (verifies NOTION_URL in .info) and single-<url> (verifies slug derivation) forms for an app.notion.com URL.

Verification

  • claude_notion_task_work — 28/28 pass
  • kiro_task_work — 22/22 pass
  • drift_check — 8/8 pass (incl. live-repo default-manifest check; is_notion_url sits outside drift-checked sentinel regions, both edits are identical)

Closes #158

🧙 Built with WOZCODE

is_notion_url() in claude-notion/bin/task-work and kiro-notion/bin/task-work
only matched notion.so / notion.site, so app.notion.com URLs (now the default
form Notion serves and the Notion MCP returns) fell through to the slug-only
branch — NOTION_URL was dropped and the worker launched with no task.

Add notion.com to the predicate in both files. Fixes the --plan/--planner
path transitively (it gates URL forwarding on the same predicate). No
task-reviewer or planner change needed.

Adds regression tests covering both the <slug> <url> and single-<url> forms
for an app.notion.com URL in each dispatcher.

Co-Authored-By: WOZCODE <contact@withwoz.com>
@martin-conur

Copy link
Copy Markdown
Owner Author

PR Review — #161: recognize app.notion.com URLs in notion dispatchers

Spec compliance

Issue #158 called for:

  • is_notion_url() recognizes app.notion.com URLs in both files — done identically in both.
  • task-work <slug> <app.notion.com-url> populates NOTION_URL in .info — covered by new bats test.
  • Single-arg task-work <app.notion.com-url> derives a sane slug — covered by new bats test.
  • Regression tests in tests/ for both the <slug> <url> and single-<url> forms — present for both claude_notion_task_work.bats and kiro_task_work.bats.
  • drift_check still passes — PR description confirms 8/8 pass (and notes is_notion_url sits outside drift-checked sentinel regions, so both edits are identical).
  • No change to any task-reviewer or /planner file — correct, spec-confirmed.

Full spec compliance. ✓


Code-review findings

NIT — bare substring match on notion.com can false-positive on a slug containing that text

File: claude-notion/bin/task-work:88, kiro-notion/bin/task-work:94

[[ "$1" == *"notion.so"* || "$1" == *"notion.site"* || "$1" == *"notion.com"* ]]

The pattern *"notion.com"* matches any string that contains the substring, not just URLs. If a user ever passes a slug like my-notion.com-feature as P0 alongside a real Notion URL as P1, the arg-resolution logic at lines 101–113 will misclassify P0 as a Notion URL — NOTION_URL gets the bare slug and the actual URL is lost:

task-work "my-notion.com-feature" "https://app.notion.com/Real-Page-abc123..."
# P0 matches is_notion_url → NOTION_URL="my-notion.com-feature", actual URL dropped

The spec's own reasoning is "a real free-form slug won't contain 'notion.com'" — true in practice, but not enforced by the code. A URL-anchored pattern would be airtight:

is_notion_url() {
  [[ "$1" =~ ^https?://(www\.|app\.)?notion\.(so|site|com)/ ]]
}

This is a nit — the pathological slug is contrived and no test exercises it — but it's worth flagging since the same predicate guards both dispatch paths.

Non-issue (noted for clarity) — *"notion.so"* / *"notion.site"* are not made redundant by *"notion.com"*

The cleanup angle flagged these as potentially redundant. They are not — "notion.so" does not contain "notion.com" as a substring. All three conditions remain independently necessary.


Verdict

clean-with-nits. The fix is correct, minimal, and ships with good test coverage across both flavors. The one nit (bare-substring false-positive) is unlikely to bite in practice but easy to harden if desired. No spec omissions, no regressions in drift or test suites. PM can merge.

@martin-conur

Copy link
Copy Markdown
Owner Author

PM: clean-with-nits review — one change requested before merge.

Please apply the reviewer's nit (harden is_notion_url() against the bare-substring false-positive) in both claude-notion/bin/task-work and kiro-notion/bin/task-work, using the URL-anchored form the reviewer gave:

is_notion_url() {
  [[ "$1" =~ ^https?://(www\.|app\.)?notion\.(so|site|com)/ ]]
}

Then add a regression test that exercises the false-positive case the nit describes — a slug like my-notion.com-feature passed as P0 alongside a real app.notion.com URL as P1 must resolve the URL to NOTION_URL (not the slug). Keep it to this one round; everything else in the review is clean. Re-radio re-review-requested when pushed.

Per review: a bare *"notion.com"* substring test misclassifies a free-form
slug that merely contains "notion.com" (e.g. "my-notion.com-feature") as a
URL, so the third arg-resolution branch fires and NOTION_URL gets the slug
instead of the real Notion URL.

Replace the substring predicate with an anchored regex in both
claude-notion/bin/task-work and kiro-notion/bin/task-work.

Deviation from the reviewer's suggested form (www.|app.)?: that variant only
allows www./app./no subdomain, which would silently drop the *.notion.site
published-site subdomains the original substring predicate accepted. Used
([a-zA-Z0-9-]+\.)* instead so any subdomain (or none) is accepted — fixes the
false-positive while preserving the original notion.site behavior.

Tests: add the false-positive guard (slug containing "notion.com" + real URL
→ URL wins) and a notion.site-subdomain regression to both bats suites.

Co-Authored-By: WOZCODE <contact@withwoz.com>
@martin-conur

Copy link
Copy Markdown
Owner Author

Addressed the nit in 2067e21.

Hardened is_notion_url() in both claude-notion/bin/task-work and kiro-notion/bin/task-work — replaced the bare-substring test with an anchored regex.

One deviation from the reviewer's suggested form, flagged for the merge decision:

The reviewer proposed:

[[ "$1" =~ ^https?://(www\.|app\.)?notion\.(so|site|com)/ ]]

That only permits www., app., or no subdomain. But the original substring predicate matched any *.notion.site host, and published Notion sites live on arbitrary workspace subdomains (e.g. https://myworkspace.notion.site/...). Since the reviewer kept site in the alternation, supporting notion.site is clearly intended — so the (www\.|app\.)? form would be an unintended regression for those URLs.

I used a subdomain-tolerant form instead, which fixes the false-positive and preserves the original behavior:

[[ "$1" =~ ^https?://([a-zA-Z0-9-]+\.)*notion\.(so|site|com)/ ]]

Verified under real bash (the predicate runs in a #!/usr/bin/env bash script):

input result
https://www.notion.so/My-Feature-<hex> URL ✓
https://app.notion.com/My-Feature-<hex> URL ✓
https://myworkspace.notion.site/My-Feature-<hex> URL ✓ (preserved)
my-notion.com-feature NOT-URL ✓ (false-positive fixed)
https://evil.com/notion.com/x NOT-URL ✓ (host-anchored)
https://notnotion.com/x NOT-URL ✓

Tests added to both tests/claude_notion_task_work.bats and tests/kiro_task_work.bats:

  • false-positive guard: task-work "my-notion.com-feature" "<app.notion.com URL>" → URL lands in NOTION_URL, not the slug.
  • notion.site subdomain regression: task-work "https://myworkspace.notion.site/..." → recognized + slug derived.

Results: claude_notion_task_work 30/30, kiro_task_work 24/24, drift_check 8/8 (incl. live-repo default-manifest).

If you'd prefer the exact (www\.|app\.)? form despite the notion.site narrowing, say the word and I'll swap it.

@martin-conur martin-conur merged commit 40f7592 into main Jun 24, 2026
4 checks passed
@martin-conur martin-conur deleted the task/notion-app-url-158 branch June 24, 2026 16:00
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.

task-work silently drops app.notion.com URLs (notion task-work only; reviewer unaffected)

1 participant