A malformed marker crashed the courtesy URL, and the hint guessed the port - #93

Merged
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening
Aug 5, 2026
Merged

A malformed marker crashed the courtesy URL, and the hint guessed the port#93
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening

Conversation

@Shashankss1205

Copy link
Copy Markdown
Collaborator

Three defects in the watch-line plumbing

watch_url() reads .grapharc/live-server.json to print the exact live-view URL for a run, and watch_hint() prints the instruction when no server answers. Three gaps, all found by walking the marker lifecycle:

1. Two marker shapes escaped as tracebacks. The tolerant read caught OSError, ValueError, KeyError — but a marker containing "port": null (int(None)) or a non-object JSON document (indexing a list) raises TypeError, which flew straight out of a command whose only job at that moment was printing a courtesy URL. TypeError joins the net, so every malformed marker now degrades to the hint.

2. The root comparison was asymmetric. The trace side was .resolve()d, the marker's live_root was trusted verbatim. serve does write it resolved, but a hand-edited or symlinked spelling of the same directory failed the lexical relative_to and silently lost the URL. Both sides resolve now, and the resolve is inside the guarded block (OSError included).

3. The hint hardcoded http://127.0.0.1:8000. An operator serving on any other port got an instruction quoting a URL their own grapharc serve command does not produce. The hint now reads the marker's last-known base URL with the same tolerance (_marker_base()), falling back to the default only when there is no readable marker at all. A stale marker is exactly the case where this matters: the server is down, and the instruction should name the port the operator actually uses.

Tests

Three new, in the existing watch-line block of tests/test_cli.py:

  • test_a_malformed_marker_degrades_to_the_hint_instead_of_crashing — null port and array-shaped marker both return None (both raised TypeError before).
  • test_an_unresolved_marker_root_still_matches_through_a_symlink — a live listener plus a marker whose root is an unresolved symlink spelling; the URL is produced.
  • test_the_hint_quotes_the_marker_port_when_the_server_is_down — dead port in the marker; the fallback watch line quotes that port, not 8000.

The existing pins (exact URL on a live server, None on a stale marker, None outside the root, no-marker instruction with the 8000 default) are untouched and green. Full suite: 1,994 passed, 12 deselected; ruff clean.

🤖 Generated with Claude Code

… port
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Shashankss1205
Shashankss1205 merged commit 7caed66 into mainAug 5, 2026
6 checks passed
Sign up for freeto 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.

1 participant

@Shashankss1205
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

A malformed marker crashed the courtesy URL, and the hint guessed the port - #93

Merged
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening
Aug 5, 2026
Merged

A malformed marker crashed the courtesy URL, and the hint guessed the port#93
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening

Conversation

@Shashankss1205

Copy link
Copy Markdown
Collaborator

Three defects in the watch-line plumbing

watch_url() reads .grapharc/live-server.json to print the exact live-view URL for a run, and watch_hint() prints the instruction when no server answers. Three gaps, all found by walking the marker lifecycle:

1. Two marker shapes escaped as tracebacks. The tolerant read caught OSError, ValueError, KeyError — but a marker containing "port": null (int(None)) or a non-object JSON document (indexing a list) raises TypeError, which flew straight out of a command whose only job at that moment was printing a courtesy URL. TypeError joins the net, so every malformed marker now degrades to the hint.

2. The root comparison was asymmetric. The trace side was .resolve()d, the marker's live_root was trusted verbatim. serve does write it resolved, but a hand-edited or symlinked spelling of the same directory failed the lexical relative_to and silently lost the URL. Both sides resolve now, and the resolve is inside the guarded block (OSError included).

3. The hint hardcoded http://127.0.0.1:8000. An operator serving on any other port got an instruction quoting a URL their own grapharc serve command does not produce. The hint now reads the marker's last-known base URL with the same tolerance (_marker_base()), falling back to the default only when there is no readable marker at all. A stale marker is exactly the case where this matters: the server is down, and the instruction should name the port the operator actually uses.

Tests

Three new, in the existing watch-line block of tests/test_cli.py:

  • test_a_malformed_marker_degrades_to_the_hint_instead_of_crashing — null port and array-shaped marker both return None (both raised TypeError before).
  • test_an_unresolved_marker_root_still_matches_through_a_symlink — a live listener plus a marker whose root is an unresolved symlink spelling; the URL is produced.
  • test_the_hint_quotes_the_marker_port_when_the_server_is_down — dead port in the marker; the fallback watch line quotes that port, not 8000.

The existing pins (exact URL on a live server, None on a stale marker, None outside the root, no-marker instruction with the 8000 default) are untouched and green. Full suite: 1,994 passed, 12 deselected; ruff clean.

🤖 Generated with Claude Code

… port
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Shashankss1205
Shashankss1205 merged commit 7caed66 into mainAug 5, 2026
6 checks passed
Sign up for freeto 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.

1 participant

@Shashankss1205
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

A malformed marker crashed the courtesy URL, and the hint guessed the port - #93

Merged
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening
Aug 5, 2026
Merged

A malformed marker crashed the courtesy URL, and the hint guessed the port#93
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening

Conversation

@Shashankss1205

Copy link
Copy Markdown
Collaborator

Three defects in the watch-line plumbing

watch_url() reads .grapharc/live-server.json to print the exact live-view URL for a run, and watch_hint() prints the instruction when no server answers. Three gaps, all found by walking the marker lifecycle:

1. Two marker shapes escaped as tracebacks. The tolerant read caught OSError, ValueError, KeyError — but a marker containing "port": null (int(None)) or a non-object JSON document (indexing a list) raises TypeError, which flew straight out of a command whose only job at that moment was printing a courtesy URL. TypeError joins the net, so every malformed marker now degrades to the hint.

2. The root comparison was asymmetric. The trace side was .resolve()d, the marker's live_root was trusted verbatim. serve does write it resolved, but a hand-edited or symlinked spelling of the same directory failed the lexical relative_to and silently lost the URL. Both sides resolve now, and the resolve is inside the guarded block (OSError included).

3. The hint hardcoded http://127.0.0.1:8000. An operator serving on any other port got an instruction quoting a URL their own grapharc serve command does not produce. The hint now reads the marker's last-known base URL with the same tolerance (_marker_base()), falling back to the default only when there is no readable marker at all. A stale marker is exactly the case where this matters: the server is down, and the instruction should name the port the operator actually uses.

Tests

Three new, in the existing watch-line block of tests/test_cli.py:

  • test_a_malformed_marker_degrades_to_the_hint_instead_of_crashing — null port and array-shaped marker both return None (both raised TypeError before).
  • test_an_unresolved_marker_root_still_matches_through_a_symlink — a live listener plus a marker whose root is an unresolved symlink spelling; the URL is produced.
  • test_the_hint_quotes_the_marker_port_when_the_server_is_down — dead port in the marker; the fallback watch line quotes that port, not 8000.

The existing pins (exact URL on a live server, None on a stale marker, None outside the root, no-marker instruction with the 8000 default) are untouched and green. Full suite: 1,994 passed, 12 deselected; ruff clean.

🤖 Generated with Claude Code

… port
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Shashankss1205
Shashankss1205 merged commit 7caed66 into mainAug 5, 2026
6 checks passed
Sign up for freeto 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.

1 participant

@Shashankss1205
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

A malformed marker crashed the courtesy URL, and the hint guessed the port - #93

Merged
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening
Aug 5, 2026
Merged

A malformed marker crashed the courtesy URL, and the hint guessed the port#93
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening

Conversation

@Shashankss1205

Copy link
Copy Markdown
Collaborator

Three defects in the watch-line plumbing

watch_url() reads .grapharc/live-server.json to print the exact live-view URL for a run, and watch_hint() prints the instruction when no server answers. Three gaps, all found by walking the marker lifecycle:

1. Two marker shapes escaped as tracebacks. The tolerant read caught OSError, ValueError, KeyError — but a marker containing "port": null (int(None)) or a non-object JSON document (indexing a list) raises TypeError, which flew straight out of a command whose only job at that moment was printing a courtesy URL. TypeError joins the net, so every malformed marker now degrades to the hint.

2. The root comparison was asymmetric. The trace side was .resolve()d, the marker's live_root was trusted verbatim. serve does write it resolved, but a hand-edited or symlinked spelling of the same directory failed the lexical relative_to and silently lost the URL. Both sides resolve now, and the resolve is inside the guarded block (OSError included).

3. The hint hardcoded http://127.0.0.1:8000. An operator serving on any other port got an instruction quoting a URL their own grapharc serve command does not produce. The hint now reads the marker's last-known base URL with the same tolerance (_marker_base()), falling back to the default only when there is no readable marker at all. A stale marker is exactly the case where this matters: the server is down, and the instruction should name the port the operator actually uses.

Tests

Three new, in the existing watch-line block of tests/test_cli.py:

  • test_a_malformed_marker_degrades_to_the_hint_instead_of_crashing — null port and array-shaped marker both return None (both raised TypeError before).
  • test_an_unresolved_marker_root_still_matches_through_a_symlink — a live listener plus a marker whose root is an unresolved symlink spelling; the URL is produced.
  • test_the_hint_quotes_the_marker_port_when_the_server_is_down — dead port in the marker; the fallback watch line quotes that port, not 8000.

The existing pins (exact URL on a live server, None on a stale marker, None outside the root, no-marker instruction with the 8000 default) are untouched and green. Full suite: 1,994 passed, 12 deselected; ruff clean.

🤖 Generated with Claude Code

… port
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Shashankss1205
Shashankss1205 merged commit 7caed66 into mainAug 5, 2026
6 checks passed
Sign up for freeto 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.

1 participant

@Shashankss1205
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

A malformed marker crashed the courtesy URL, and the hint guessed the port - #93

Merged
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening
Aug 5, 2026
Merged

A malformed marker crashed the courtesy URL, and the hint guessed the port#93
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening

Conversation

@Shashankss1205

Copy link
Copy Markdown
Collaborator

Three defects in the watch-line plumbing

watch_url() reads .grapharc/live-server.json to print the exact live-view URL for a run, and watch_hint() prints the instruction when no server answers. Three gaps, all found by walking the marker lifecycle:

1. Two marker shapes escaped as tracebacks. The tolerant read caught OSError, ValueError, KeyError — but a marker containing "port": null (int(None)) or a non-object JSON document (indexing a list) raises TypeError, which flew straight out of a command whose only job at that moment was printing a courtesy URL. TypeError joins the net, so every malformed marker now degrades to the hint.

2. The root comparison was asymmetric. The trace side was .resolve()d, the marker's live_root was trusted verbatim. serve does write it resolved, but a hand-edited or symlinked spelling of the same directory failed the lexical relative_to and silently lost the URL. Both sides resolve now, and the resolve is inside the guarded block (OSError included).

3. The hint hardcoded http://127.0.0.1:8000. An operator serving on any other port got an instruction quoting a URL their own grapharc serve command does not produce. The hint now reads the marker's last-known base URL with the same tolerance (_marker_base()), falling back to the default only when there is no readable marker at all. A stale marker is exactly the case where this matters: the server is down, and the instruction should name the port the operator actually uses.

Tests

Three new, in the existing watch-line block of tests/test_cli.py:

  • test_a_malformed_marker_degrades_to_the_hint_instead_of_crashing — null port and array-shaped marker both return None (both raised TypeError before).
  • test_an_unresolved_marker_root_still_matches_through_a_symlink — a live listener plus a marker whose root is an unresolved symlink spelling; the URL is produced.
  • test_the_hint_quotes_the_marker_port_when_the_server_is_down — dead port in the marker; the fallback watch line quotes that port, not 8000.

The existing pins (exact URL on a live server, None on a stale marker, None outside the root, no-marker instruction with the 8000 default) are untouched and green. Full suite: 1,994 passed, 12 deselected; ruff clean.

🤖 Generated with Claude Code

… port
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Shashankss1205
Shashankss1205 merged commit 7caed66 into mainAug 5, 2026
6 checks passed
Sign up for freeto 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.

1 participant

@Shashankss1205
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

A malformed marker crashed the courtesy URL, and the hint guessed the port - #93

Merged
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening
Aug 5, 2026
Merged

A malformed marker crashed the courtesy URL, and the hint guessed the port#93
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening

Conversation

@Shashankss1205

Copy link
Copy Markdown
Collaborator

Three defects in the watch-line plumbing

watch_url() reads .grapharc/live-server.json to print the exact live-view URL for a run, and watch_hint() prints the instruction when no server answers. Three gaps, all found by walking the marker lifecycle:

1. Two marker shapes escaped as tracebacks. The tolerant read caught OSError, ValueError, KeyError — but a marker containing "port": null (int(None)) or a non-object JSON document (indexing a list) raises TypeError, which flew straight out of a command whose only job at that moment was printing a courtesy URL. TypeError joins the net, so every malformed marker now degrades to the hint.

2. The root comparison was asymmetric. The trace side was .resolve()d, the marker's live_root was trusted verbatim. serve does write it resolved, but a hand-edited or symlinked spelling of the same directory failed the lexical relative_to and silently lost the URL. Both sides resolve now, and the resolve is inside the guarded block (OSError included).

3. The hint hardcoded http://127.0.0.1:8000. An operator serving on any other port got an instruction quoting a URL their own grapharc serve command does not produce. The hint now reads the marker's last-known base URL with the same tolerance (_marker_base()), falling back to the default only when there is no readable marker at all. A stale marker is exactly the case where this matters: the server is down, and the instruction should name the port the operator actually uses.

Tests

Three new, in the existing watch-line block of tests/test_cli.py:

  • test_a_malformed_marker_degrades_to_the_hint_instead_of_crashing — null port and array-shaped marker both return None (both raised TypeError before).
  • test_an_unresolved_marker_root_still_matches_through_a_symlink — a live listener plus a marker whose root is an unresolved symlink spelling; the URL is produced.
  • test_the_hint_quotes_the_marker_port_when_the_server_is_down — dead port in the marker; the fallback watch line quotes that port, not 8000.

The existing pins (exact URL on a live server, None on a stale marker, None outside the root, no-marker instruction with the 8000 default) are untouched and green. Full suite: 1,994 passed, 12 deselected; ruff clean.

🤖 Generated with Claude Code

… port
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Shashankss1205
Shashankss1205 merged commit 7caed66 into mainAug 5, 2026
6 checks passed
Sign up for freeto 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.

1 participant

@Shashankss1205
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

A malformed marker crashed the courtesy URL, and the hint guessed the port - #93

Merged
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening
Aug 5, 2026
Merged

A malformed marker crashed the courtesy URL, and the hint guessed the port#93
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening

Conversation

@Shashankss1205

Copy link
Copy Markdown
Collaborator

Three defects in the watch-line plumbing

watch_url() reads .grapharc/live-server.json to print the exact live-view URL for a run, and watch_hint() prints the instruction when no server answers. Three gaps, all found by walking the marker lifecycle:

1. Two marker shapes escaped as tracebacks. The tolerant read caught OSError, ValueError, KeyError — but a marker containing "port": null (int(None)) or a non-object JSON document (indexing a list) raises TypeError, which flew straight out of a command whose only job at that moment was printing a courtesy URL. TypeError joins the net, so every malformed marker now degrades to the hint.

2. The root comparison was asymmetric. The trace side was .resolve()d, the marker's live_root was trusted verbatim. serve does write it resolved, but a hand-edited or symlinked spelling of the same directory failed the lexical relative_to and silently lost the URL. Both sides resolve now, and the resolve is inside the guarded block (OSError included).

3. The hint hardcoded http://127.0.0.1:8000. An operator serving on any other port got an instruction quoting a URL their own grapharc serve command does not produce. The hint now reads the marker's last-known base URL with the same tolerance (_marker_base()), falling back to the default only when there is no readable marker at all. A stale marker is exactly the case where this matters: the server is down, and the instruction should name the port the operator actually uses.

Tests

Three new, in the existing watch-line block of tests/test_cli.py:

  • test_a_malformed_marker_degrades_to_the_hint_instead_of_crashing — null port and array-shaped marker both return None (both raised TypeError before).
  • test_an_unresolved_marker_root_still_matches_through_a_symlink — a live listener plus a marker whose root is an unresolved symlink spelling; the URL is produced.
  • test_the_hint_quotes_the_marker_port_when_the_server_is_down — dead port in the marker; the fallback watch line quotes that port, not 8000.

The existing pins (exact URL on a live server, None on a stale marker, None outside the root, no-marker instruction with the 8000 default) are untouched and green. Full suite: 1,994 passed, 12 deselected; ruff clean.

🤖 Generated with Claude Code

… port
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Shashankss1205
Shashankss1205 merged commit 7caed66 into mainAug 5, 2026
6 checks passed
Sign up for freeto 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.

1 participant

@Shashankss1205
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

A malformed marker crashed the courtesy URL, and the hint guessed the port - #93

Merged
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening
Aug 5, 2026
Merged

A malformed marker crashed the courtesy URL, and the hint guessed the port#93
Shashankss1205 merged 1 commit into
mainfrom
fix/watch-url-hardening

Conversation

@Shashankss1205

Copy link
Copy Markdown
Collaborator

Three defects in the watch-line plumbing

watch_url() reads .grapharc/live-server.json to print the exact live-view URL for a run, and watch_hint() prints the instruction when no server answers. Three gaps, all found by walking the marker lifecycle:

1. Two marker shapes escaped as tracebacks. The tolerant read caught OSError, ValueError, KeyError — but a marker containing "port": null (int(None)) or a non-object JSON document (indexing a list) raises TypeError, which flew straight out of a command whose only job at that moment was printing a courtesy URL. TypeError joins the net, so every malformed marker now degrades to the hint.

2. The root comparison was asymmetric. The trace side was .resolve()d, the marker's live_root was trusted verbatim. serve does write it resolved, but a hand-edited or symlinked spelling of the same directory failed the lexical relative_to and silently lost the URL. Both sides resolve now, and the resolve is inside the guarded block (OSError included).

3. The hint hardcoded http://127.0.0.1:8000. An operator serving on any other port got an instruction quoting a URL their own grapharc serve command does not produce. The hint now reads the marker's last-known base URL with the same tolerance (_marker_base()), falling back to the default only when there is no readable marker at all. A stale marker is exactly the case where this matters: the server is down, and the instruction should name the port the operator actually uses.

Tests

Three new, in the existing watch-line block of tests/test_cli.py:

  • test_a_malformed_marker_degrades_to_the_hint_instead_of_crashing — null port and array-shaped marker both return None (both raised TypeError before).
  • test_an_unresolved_marker_root_still_matches_through_a_symlink — a live listener plus a marker whose root is an unresolved symlink spelling; the URL is produced.
  • test_the_hint_quotes_the_marker_port_when_the_server_is_down — dead port in the marker; the fallback watch line quotes that port, not 8000.

The existing pins (exact URL on a live server, None on a stale marker, None outside the root, no-marker instruction with the 8000 default) are untouched and green. Full suite: 1,994 passed, 12 deselected; ruff clean.

🤖 Generated with Claude Code

… port
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Shashankss1205
Shashankss1205 merged commit 7caed66 into mainAug 5, 2026
6 checks passed
Sign up for freeto 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.

1 participant

@Shashankss1205