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 main Aug 5, 2026
6 checks passed
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.

1 participant