docs: one page for a coding assistant, and a copy-page control on every page - #21
Merged
Merged
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
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, all documentation.
A "Copy page" control above every page. A split button: copy the page as Markdown, view it as plain text, or open it in ChatGPT / Claude / Perplexity. It works because
scripts/emit_markdown.pyruns after the build and writes everydocs/<path>.mdnext to the HTML it built, so each page has a plain-text twin one URL away —/user_guide.mdbeside/user_guide/. A page can opt out withcopy_page: falsein its front matter, and the emit step honours the same key.docs/agents.md— the whole library on one page. The public surface with real signatures and defaults, what is and is not exported from the root, the rules a caller has to obey,# WRONG/# RIGHTpairs for the mistakes a model actually makes with this API, the exception table, and a map of every page of the site with a reason to fetch it. It is written from the source, not from the other pages; the rules section is the point of it. The ones that carry the most weight here: the key is the whole identity and the request body is not part of it, two concurrent callers both run the business logic (the check is aGET, the write isSET NX, and the loser replays the winner's record), the decorator reads the key from keyword arguments only and silently does nothing when it or the coordinator is missing,coordinate()swallows every storage and decode failure, and a TTL in seconds is truncated to whole minutes with a floor of one.The rule that keeps it true.
CONTRIBUTING.mdgains a section saying that page is part of the public API and changes in the same pull request the API does, and the pull request template's documentation line now names it. A stale agents page is worse than none — it teaches a model an API that no longer exists.How to see it. The Docs workflow deploys on merge, with the emit step added after the build; the page lands at https://bedrock-python.github.io/idempotency-kit/agents/ and the control appears at the top of every page. Locally:
make docs-build && uv run python scripts/emit_markdown.py, then servesite/—zensical serverebuilds into the same directory without the twins, so the control answers 404 under it.Verified on this branch:
zensical build --cleansays "No issues found", the emit step writes 8 Markdown pages,make checkpasses (ruff, ruff format, mypy over 31 files),uv.lockis untouched, and every public name the page tells a caller to import was checked against the installed package — nothing missing, and nothing inidempotency_kit.__all__that the page leaves out.A few things I noticed while reading the source, none of them touched here:
RedisAsyncIdempotencyRepositoryraisesImportError: ... pip install idempotency-kit[redis-aio], anddocs/architecture.mdsays[redis-aio]too. The extra isredis.docs/api_reference.mddescribes the repository'sredisargument as an "instance ofredis-client-kitclient". It is anyredis.asyncio.Redis; the instrumented client is one option, not the type.IdempotencyProviderwires — every coordinator-driven get is counted twice.BaseIdempotencySettings.enabledis read by nothing. No shipped provider consults it.BaseIdempotencySettingsdefaults (60 min, floor 1 s, ceiling 30 days) are a different set fromIdempotencyDomainService's own (30 min, floor 60 s, ceiling 24 h), so the effective bounds depend on which way the service was built.PydanticResultAdapter.encodereturnsNonefor a falsy value anddecoderaises on a falsy payload, so an action that may returnNonestoresnulland then fails to decode it for the life of the record — a permanent miss that re-runs the action on every replay. The page says to useVoidResultAdapterorJsonResultAdapterinstead, but the adapter could refuse the shape up front.IdempotencyDomainService.validate_recordandIdempotencyRecordExpiredErrorare unused by the library itself.The four shared files —
docs/assets/stylesheets/copy-page.css,docs/assets/javascripts/copy-page.js,overrides/main.html,scripts/emit_markdown.py— are byte-identical across the organisation on purpose, so they can be updated in one sweep.