docs: one page for a coding assistant, and a copy-page control on every page - #19
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three things ship together, and each is useless without the others.
1. A "Copy page" control above every docs page. It copies the page's Markdown, or
opens it in ChatGPT / Claude / Perplexity. It works because
scripts/emit_markdown.pyruns after the build and writes every
docs/<path>.mdnext to the HTML it built, so eachpage has a plain-text twin one URL away:
/guide/retries/and/guide/retries.md. TheDocs workflow gained that one step.
2.
docs/agents.md— the whole library on one page, written for a coding assistant:the public API with its real defaults, where the boundary between the core engine and an
adapter actually runs, the retry/timeout composition, the rules that break code when they
are broken, the mistakes a model makes with this API, and a map of which of the 33 pages
to fetch for the rest. It is in the nav as "For AI agents" and reachable at
/agents/(with/agents.mdfor a machine).3. The rule that keeps it true.
CONTRIBUTING.mdand the pull request template nowsay the page is part of the public API and goes stale in the same pull request that
changes the surface. A stale agents page is worse than none — it teaches a model an API
that no longer exists.
To see it: the Docs workflow deploys on merge. Locally,
uv sync --no-dev --group docs --frozen cp CHANGELOG.md docs/changelog.md uv run --no-sync zensical build --clean uv run --no-sync python scripts/emit_markdown.py # wrote 35 Markdown pages into site/zensical buildreports no issues,make checkpasses (ruff, mypy, import-linter) anduv.lockis untouched. Every name the page tells a caller to import was checked againstthe installed package; the repository's own
tests/unit/test_docs_snippets.pyalso nowcovers the page's snippets, so a renamed export fails CI rather than the reader.
docs/assets/stylesheets/copy-page.css,docs/assets/javascripts/copy-page.js,overrides/main.htmlandscripts/emit_markdown.pyare byte-identical across theorganisation, so all of them can be updated in one sweep.
One deviation worth knowing: the installer could not patch
.github/workflows/docs.ymlbecause it looks for a bare
uv run zensical build --cleanand this repositorydeliberately runs
uv run --no-dev --group docs …. The emit step was added by hand in thesame style, right after the build.
While reading the source for the page I found three things that are not this PR's job to
fix but should not stay unwritten:
docs/guide/per-call-options.mdsaysidempotent=False"forbids retrying a normally-idempotent method". It does not: the gate is
method not in retry.methods and not info.idempotent, so aGETwithidempotent=Falseis still retried. Either the doc orthe gate should move.
docs/guide/native-options.mdanddocs/guide/capabilities.mdboth promisehandle.report.native_overrideslists the accepted passthrough per slot. No adapterpasses
native_overridesintocompile_plan, so it is always{}.AsyncNormalizer.conn_metrics/SyncNormalizer.conn_metricsare implemented by everyadapter (aiohttp does real work for it via
TraceConfig) but nothing in the engine orthe telemetry emitter ever calls them;
Attempt.connis alwaysNoneeven thoughaiohttp declares
CONN_METRICS: native.