Skip to content

Independent v0.7.0 validation + fixes for the 8 bugs it found#26

Merged
lonexreb merged 4 commits into
mainfrom
claude/site2cli-validation-testing-f0pym5
Jul 17, 2026
Merged

Independent v0.7.0 validation + fixes for the 8 bugs it found#26
lonexreb merged 4 commits into
mainfrom
claude/site2cli-validation-testing-f0pym5

Conversation

@lonexreb

@lonexreb lonexreb commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Summary

Full end-to-end validation of v0.7.0 (fresh install, whole CLI surface exercised against a local test site with a real headless Chromium), documented in VALIDATION-REPORT.md, plus fixes for all 8 bugs the validation reproduced.

Fixes

  1. client_generator — digit-leading hosts (127.0.0.1, 9gag.com) generated syntactically invalid Python (class 127001Client:); now Site127001Client.
  2. discover — registry stored relative -o spec paths, breaking run/mcp generate from other directories; paths are now stored absolute, with a specs-dir fallback for legacy entries.
  3. Action naming — unified on canonical operationIds (get_api_products) across spec, registry, generated clients, and MCP tools; discover prints the runnable name per endpoint; unknown actions fail fast with the valid names instead of silently launching a browser at https://domain/ (which dropped the port); normalized matching keeps legacy GET_/path registries working.
  4. crawler — robots.txt was fetched without the port (hostname instead of netloc) and failed open, silently ignoring Disallow rules on non-standard ports.
  5. screenshot — every invocation crashed with a TypeError (invalid proxy=/session= kwargs); the context factory gained a proxy override and capture passes session_manager/session_name.
  6. mcp_gen — tool names contained {/} from path params, violating the MCP name charset (^[a-zA-Z0-9_-]+$); query params are now type-inferred (limit=5 → integer) for consistency with body params.
  7. daemon start — now detaches by default (logs to ~/.site2cli/daemon.log), --foreground keeps the old behavior; added __main__.py for python -m site2cli.
  8. health — servers answering 405/501 to HEAD/OPTIONS were marked BROKEN despite working endpoints; probes now fall back to GET.

Behavior change

The router no longer falls back to browser exploration when a known site receives an unknown action name — it returns an error listing the valid actions. Browser fallback for entirely unknown domains is unchanged.

Testing

  • 16 regression tests added; suite grew 553 → 569 passing (plus 1 skipped, 6 live-marked), ruff clean.
  • Every fix re-verified live against a local XHR-backed test site: full discover → spec → clients → MCP pipeline, run from arbitrary cwd, robots-compliant crawl, working screenshot, MCP JSON-RPC probe (initialize/tools/list/tools/call), daemon detach/status/stop, health checks.
  • CLAUDE.md test totals deduplicated (had contradictory 559/500 entries).

🤖 Generated with Claude Code

https://claude.ai/code/session_01T2ZL9mUURihJVhk4Q9zGpN


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Run the CLI with python -m site2cli.
    • Start the daemon in foreground or background mode.
    • Generate safer, more consistent API client and MCP tool names.
    • Improve endpoint discovery with inferred query-parameter types.
    • Support normalized action names and clearer available-action guidance.
  • Bug Fixes

    • Fixed spec and generated-client path handling.
    • Improved robots.txt handling for custom ports.
    • Fixed screenshot capture, health checks, and daemon startup reliability.
    • Prevented invalid generated Python class names.

claude added 2 commits July 17, 2026 01:45
End-to-end validation against a local test site with real browser CDP
capture. Core discover->spec->clients->MCP pipeline confirmed working;
8 reproduced bugs documented with locations; quantified README claims
audited (several are simulations/estimates rather than measurements).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T2ZL9mUURihJVhk4Q9zGpN
1. client_generator: digit-leading hosts (127.0.0.1, 9gag.com) produced
   syntactically invalid Python (class 127001Client) — now Site127001Client.
2. discover: registry stored relative -o spec paths, breaking run/mcp
   generate from other directories — paths now resolved absolute, with a
   specs-dir fallback for legacy entries.
3. Action naming unified on operationIds (get_api_products) across spec,
   registry, clients, and MCP tools; discover prints runnable names;
   unknown actions fail fast with the valid list instead of silently
   launching a browser at https://domain/ (dropping base_url's port);
   normalized matching keeps legacy GET_/path registries working.
4. crawler: robots.txt was fetched without the port (hostname instead of
   netloc), failing open on non-standard ports — Disallow rules were
   silently ignored.
5. screenshot: every invocation crashed (proxy=/session= kwargs the
   context factory rejects) — factory gained a proxy override, capture
   passes session_manager/session_name.
6. mcp_gen: tool names contained { } from path params, violating the MCP
   name charset; query params now type-inferred (limit=5 -> integer) for
   consistency with body params.
7. daemon start now detaches by default (--foreground to keep old
   behavior); added __main__.py for python -m site2cli.
8. health: servers answering 405/501 to HEAD/OPTIONS were marked BROKEN
   despite working endpoints — now falls back to a GET probe.

16 regression tests added (suite: 553 -> 569). CLAUDE.md test totals
deduplicated and updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T2ZL9mUURihJVhk4Q9zGpN
@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@lonexreb, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6c5c536c-79d4-4a0a-b3cb-6d7e4a9d66f3

📥 Commits

Reviewing files that changed from the base of the PR and between a5f04b1 and f21fc94.

📒 Files selected for processing (12)
  • CLAUDE.md
  • src/site2cli/__main__.py
  • src/site2cli/browser/context.py
  • src/site2cli/cli.py
  • src/site2cli/discovery/spec_generator.py
  • src/site2cli/generators/mcp_gen.py
  • src/site2cli/router.py
  • tests/test_cli.py
  • tests/test_generated_code.py
  • tests/test_router.py
  • tests/test_search.py
  • tests/test_spec_generator.py
📝 Walkthrough

Walkthrough

The changes normalize generated identifiers and action routing, fix artifact path and browser/session handling, add port-aware robots and health probes, support detached daemon startup, add python -m site2cli, and document validation results with expanded regression tests.

Changes

CLI validation and runtime fixes

Layer / File(s) Summary
Discovery identifiers and generated artifacts
src/site2cli/discovery/*, src/site2cli/cli.py, tests/test_analyzer.py, tests/test_client_generator.py, tests/test_spec_generator.py
Query parameters receive inferred primitive types, operation IDs are normalized, digit-leading client classes are corrected, and discovered artifact paths are resolved.
Action routing and MCP names
src/site2cli/router.py, src/site2cli/generators/mcp_gen.py, src/site2cli/cli.py, tests/test_router.py, tests/test_generated_code.py, tests/test_cli.py
Unknown actions return structured errors, legacy and normalized names resolve interchangeably, and MCP tool names are sanitized.
Browser context, screenshots, and daemon execution
src/site2cli/browser/context.py, src/site2cli/screenshot/capture.py, src/site2cli/cli.py, src/site2cli/__main__.py, tests/test_screenshot.py
Proxy overrides and session-manager forwarding are corrected; module execution and foreground/background daemon modes are added.
Port-aware robots and health probes
src/site2cli/crawl/*, src/site2cli/health/monitor.py, tests/test_crawl_robots.py, tests/test_health.py
Robots requests preserve explicit ports, while health checks fall back to GET after unsupported HEAD or OPTIONS probes.
Validation documentation and test totals
VALIDATION-REPORT.md, CLAUDE.md
Validation findings, fixes, claims auditing, and updated test totals are documented.

Estimated code review effort: 4 (Complex) | ~45 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.24% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the PR’s main changes: independent v0.7.0 validation and fixes for the bugs it uncovered.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/site2cli-validation-testing-f0pym5

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Typer forces colored output when GITHUB_ACTIONS is set, splitting option
names with escape codes (e.g. --foreground) so plain substring asserts
fail on CI while passing locally. Affected the new daemon flag test and
the pre-existing search help test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T2ZL9mUURihJVhk4Q9zGpN

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
src/site2cli/browser/context.py (1)

61-62: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use an explicit is not None check for the optional proxy argument.

Since proxy is typed as dict | None, evaluating it for truthiness (proxy or ...) means an explicitly passed empty dictionary ({}) would evaluate to false and fall back to the config instead of overriding it. Using is not None correctly handles the distinction between "not provided" and "provided but empty".

♻️ Proposed refactor
-        # Resolve proxy settings (explicit argument wins over config)
-        proxy_config = proxy or config.proxy.get_playwright_proxy()
+        # Resolve proxy settings (explicit argument wins over config)
+        proxy_config = proxy if proxy is not None else config.proxy.get_playwright_proxy()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/site2cli/browser/context.py` around lines 61 - 62, Update the proxy
selection in the context initialization flow to use an explicit None check for
the optional proxy argument, so a provided empty dictionary is preserved instead
of falling back to config.proxy.get_playwright_proxy(). Keep the configuration
fallback only for proxy values that are actually None.
src/site2cli/__main__.py (1)

5-6: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Set prog_name explicitly to improve CLI help output.

When invoking a Typer/Click application via python -m site2cli, the CLI help text will often default to displaying Usage: __main__.py [OPTIONS] instead of the module name. Passing prog_name="site2cli" ensures consistent and user-friendly usage instructions.

♻️ Proposed refactor
 if __name__ == "__main__":
-    app()
+    app(prog_name="site2cli")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/site2cli/__main__.py` around lines 5 - 6, Update the __main__ entry-point
invocation of app to pass prog_name explicitly as "site2cli", ensuring help
output uses the module name instead of __main__.py.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CLAUDE.md`:
- Line 110: Update the test-summary statement in CLAUDE.md to explicitly
distinguish the 569 offline tests from the 6 network-dependent live tests, state
that live tests require network access, and avoid implying that all live tests
are always passing. Preserve the separate reporting of offline tests and live
external-API validation.

In `@src/site2cli/discovery/spec_generator.py`:
- Around line 19-21: Make normalized identifiers collision-safe across all three
sites: in src/site2cli/discovery/spec_generator.py lines 19-21, update the
operation-ID generation to assign deterministic unique IDs and persist those
assignments for registry actions; in src/site2cli/router.py lines 128-131,
detect multiple normalized lookup matches and reject them instead of selecting
the first; in src/site2cli/generators/mcp_gen.py lines 32-33, detect sanitized
tool-name collisions and deterministically suffix or reject duplicate names.

In `@tests/test_cli.py`:
- Around line 150-180: Update test_run_unknown_action_lists_available to call
reset_config() after runner.invoke completes, using a fixture or try/finally so
cleanup always runs even if assertions fail. Preserve the existing test setup
and assertions while ensuring the global cached configuration does not leak into
subsequent tests.

---

Nitpick comments:
In `@src/site2cli/__main__.py`:
- Around line 5-6: Update the __main__ entry-point invocation of app to pass
prog_name explicitly as "site2cli", ensuring help output uses the module name
instead of __main__.py.

In `@src/site2cli/browser/context.py`:
- Around line 61-62: Update the proxy selection in the context initialization
flow to use an explicit None check for the optional proxy argument, so a
provided empty dictionary is preserved instead of falling back to
config.proxy.get_playwright_proxy(). Keep the configuration fallback only for
proxy values that are actually None.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 64ab3dbb-2b26-4ee5-91a9-74d05a7438a3

📥 Commits

Reviewing files that changed from the base of the PR and between fc19f10 and a5f04b1.

📒 Files selected for processing (23)
  • CLAUDE.md
  • VALIDATION-REPORT.md
  • src/site2cli/__main__.py
  • src/site2cli/browser/context.py
  • src/site2cli/cli.py
  • src/site2cli/crawl/crawler.py
  • src/site2cli/crawl/robots.py
  • src/site2cli/discovery/analyzer.py
  • src/site2cli/discovery/client_generator.py
  • src/site2cli/discovery/spec_generator.py
  • src/site2cli/generators/mcp_gen.py
  • src/site2cli/health/monitor.py
  • src/site2cli/router.py
  • src/site2cli/screenshot/capture.py
  • tests/test_analyzer.py
  • tests/test_cli.py
  • tests/test_client_generator.py
  • tests/test_crawl_robots.py
  • tests/test_generated_code.py
  • tests/test_health.py
  • tests/test_router.py
  • tests/test_screenshot.py
  • tests/test_spec_generator.py

Comment thread CLAUDE.md Outdated
Comment on lines +19 to +21
raw = endpoint.description or f"{endpoint.method} {endpoint.path_pattern}"
op_id = re.sub(r"[^a-zA-Z0-9]+", "_", raw.lower()).strip("_")
return op_id or "operation"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Make normalized identifiers collision-safe across discovery, routing, and MCP generation.

Lossy normalization currently permits distinct endpoints/actions to share one identifier, causing ambiguous routing or shadowed MCP handlers.

  • src/site2cli/discovery/spec_generator.py#L19-L21: assign deterministic unique operation IDs and persist that assignment for registry actions.
  • src/site2cli/router.py#L128-L131: reject normalized lookups with multiple matches instead of selecting the first.
  • src/site2cli/generators/mcp_gen.py#L32-L33: detect sanitized tool-name collisions and suffix or reject duplicates.
📍 Affects 3 files
  • src/site2cli/discovery/spec_generator.py#L19-L21 (this comment)
  • src/site2cli/router.py#L128-L131
  • src/site2cli/generators/mcp_gen.py#L32-L33
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/site2cli/discovery/spec_generator.py` around lines 19 - 21, Make
normalized identifiers collision-safe across all three sites: in
src/site2cli/discovery/spec_generator.py lines 19-21, update the operation-ID
generation to assign deterministic unique IDs and persist those assignments for
registry actions; in src/site2cli/router.py lines 128-131, detect multiple
normalized lookup matches and reject them instead of selecting the first; in
src/site2cli/generators/mcp_gen.py lines 32-33, detect sanitized tool-name
collisions and deterministically suffix or reject duplicate names.

Comment thread tests/test_cli.py Outdated
…leanups

- Operation IDs / action names / MCP tool names are now collision-safe:
  normalization is lossy (/a-b and /a_b collapse to the same ID), so
  duplicates get deterministic _2/_3 suffixes shared between the spec
  and registry (make_unique_operation_ids), and the router rejects
  ambiguous normalized lookups instead of picking the first match.
- CLAUDE.md: clarify offline vs network-dependent live test split.
- test_cli: reset cached config in finally so tmp_path doesn't leak.
- browser context: explicit 'is not None' for the proxy override.
- __main__: pass prog_name='site2cli' for correct help text.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T2ZL9mUURihJVhk4Q9zGpN
@lonexreb
lonexreb merged commit c14733a into main Jul 17, 2026
5 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.

2 participants