Docs (vibed) for serious: real documentation with a modern theme #460
Conversation
25f5210 to
ea98287
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces a major Sphinx documentation revamp for tractor, including a modern theme, new guide/API content, diagram support via d2, CI docs builds/deploy, and refreshed example scripts intended to be literalinclude’d by the docs.
Changes:
- Add a
docsdependency group (Sphinx + theme + extensions) and a GitHub Actions workflow to build and deploy docs. - Add a full new docs tree (start/explain/guide/api/project) with custom theme config, CSS, and local Sphinx extensions (
.. d2::,.. margin::) plus new diagram sources. - Add new runnable examples and update older examples to use
wait_for_result().
Reviewed changes
Copilot reviewed 58 out of 65 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| pyproject.toml | Adds docs dependency group for building Sphinx docs with the chosen theme/extensions. |
| .github/workflows/docs.yml | Builds docs on PRs/pushes and deploys to GitHub Pages on main. |
| examples/uds_transport_actor_tree.py | New example demonstrating actor trees over UDS transport. |
| examples/typed_payloads.py | New example demonstrating @tractor.context(pld_spec=...) typed payload validation. |
| examples/streaming_broadcast_fanout.py | New example demonstrating MsgStream.subscribe() fan-out to multiple local tasks. |
| examples/service_daemon_discovery.py | New example demonstrating discovery + service-daemon pattern via registrar lookups. |
| examples/nested_actor_tree.py | New example showing a nested actor tree and fan-out RPC aggregation. |
| examples/parallelism/single_func.py | Updates example to use portal.wait_for_result() (API modernization). |
| examples/parallelism/concurrent_futures_primes.py | Makes the stdlib baseline script test-runner-friendly via a Trio shim and renames the sync entry function. |
| examples/actor_spawning_and_causality.py | Updates example to use portal.wait_for_result() (API modernization). |
| examples/a_trynamic_first_scene.py | Updates example to use wait_for_result() on actor run portals. |
| docs/conf.py | Reworks Sphinx configuration: pydata theme, extensions, intersphinx, opengraph, copybutton, local _ext/ setup. |
| docs/_static/css/custom.css | Adds custom CSS skin + margin aside/diagram styling for the new theme. |
| docs/_ext/marginalia.py | Adds local .. margin:: directive for right-margin asides. |
| docs/_ext/d2diagrams.py | Adds local .. d2:: directive for rendering/embedding d2 diagrams with SVG fallback. |
| docs/diagrams/actor_tree.d2 | New d2 diagram source for actor supervision tree. |
| docs/diagrams/context_handshake.d2 | New d2 diagram source for Context handshake flow. |
| docs/diagrams/debug_lock.d2 | New d2 diagram source for debugger TTY lock sequencing. |
| docs/diagrams/error_propagation.d2 | New d2 diagram source for one-cancels-all error propagation. |
| docs/diagrams/infected_aio.d2 | New d2 diagram source for infected-asyncio architecture. |
| docs/diagrams/runtime_stack.d2 | New d2 diagram source for runtime layering. |
| docs/diagrams/streaming_pipeline.d2 | New d2 diagram source for streaming pipeline topology. |
| docs/start/index.rst | Adds “Getting started” landing and toctree. |
| docs/start/install.rst | Adds installation/platform guidance and uv-based workflows. |
| docs/start/quickstart.rst | Adds quickstart walkthrough referencing runnable examples and diagrams. |
| docs/explain/index.rst | Adds conceptual “Big ideas” index. |
| docs/explain/sc-distributed.rst | Adds conceptual explanation of structured concurrency across processes. |
| docs/explain/architecture.rst | Adds runtime architecture deep-dive with transport/spawn/registrar overview. |
| docs/guide/index.rst | Adds guides index and toctree for subsystem walkthroughs. |
| docs/guide/spawning.rst | Adds spawning/lifetime/supervision guide. |
| docs/guide/rpc.rst | Adds portal/RPC guide, including wait_for_result() semantics. |
| docs/guide/context.rst | Adds Context handshake/streaming/cancellation semantics guide. |
| docs/guide/streaming.rst | Adds streaming guide for one-way and context-based streaming + fan-out. |
| docs/guide/cancellation.rst | Adds cancellation and error propagation guide. |
| docs/guide/debugging.rst | Adds multi-process debugging guide (debug_mode, pause, crash REPL, stackscope). |
| docs/guide/discovery.rst | Adds registrar/discovery guide and service patterns. |
| docs/guide/clustering.rst | Adds higher-level cluster APIs guide. |
| docs/guide/parallelism.rst | Adds worker-pool/parallelism guide contrasting stdlib baseline with tractor approach. |
| docs/guide/asyncio.rst | Adds infected-asyncio guide and cross-loop task-linking semantics. |
| docs/guide/msging.rst | Adds typed messaging / msgspec protocol guide and validation behavior. |
| docs/guide/testing.rst | Adds test-suite usage and “examples are tests” conventions. |
| docs/project/index.rst | Adds project meta index (changelog/dev tips/roadmap pointers). |
| docs/project/dev-tips.rst | Adds contributor/dev tips (release flow, debugging, logging, monitoring). |
| docs/project/changelog.rst | Includes NEWS as the changelog source. |
| docs/api/index.rst | Adds API reference index and toctree. |
| docs/api/core.rst | Adds runtime/spawning API reference page. |
| docs/api/context.rst | Adds Context/MsgStream API reference page. |
| docs/api/ipc.rst | Adds IPC/logging API reference page. |
| docs/api/msg.rst | Adds typed messaging/codec API reference page. |
| docs/api/errors.rst | Adds errors/cancellation types API reference page. |
| docs/api/discovery.rst | Adds discovery/registrar API reference page. |
| docs/api/devx.rst | Adds debugging/devx API reference page. |
| docs/api/to_asyncio.rst | Adds asyncio interop API reference page. |
| docs/api/trionics.rst | Adds trionics helper API reference page. |
| docs/dev_tips.rst | Removes old dev tips doc (migrated to docs/project/dev-tips.rst). |
| ai/prompt-io/claude/20260611T175152Z_8526985c_prompt_io.raw.md | Adds AI prompt-io raw metadata snapshot for the docs generation pass. |
| ai/prompt-io/claude/20260611T175152Z_8526985c_prompt_io.md | Adds AI prompt-io summary snapshot for the docs generation pass. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| img = nodes.image( | ||
| uri=f'/{_outdir}/{out.name}', | ||
| alt=self.options.get( | ||
| 'alt', | ||
| f'd2 diagram: {src.stem}', | ||
| ), | ||
| ) |
| This is a (perpetually WIP) guide for newcomers to the project, | ||
| mostly to do with dev, testing, CI and release gotchas, reminders | ||
| and best practises. |
goodboy
left a comment
There was a problem hiding this comment.
Review — xhigh multi-angle pass (correctness + reference integrity + prose accuracy)
Reviewed all 65 files / +7722. Bottom line: genuinely solid — a
CI-like sphinx-build exits 0 (the 24 warnings all trace to
pre-existing library docstrings + NEWS.rst, not this PR), every
literalinclude/:pyobject:/:doc:/toctree reference resolves, all
example scripts run green, and the autodoc API pages have zero broken
directives / failed imports / missing members. Findings below are the
residue; ✅ = fix prepared locally (incoming follow-up commit).
Correctness
1. ✅ examples/uds_transport_actor_tree.py — flagship example prints the wrong address (reproduced).
portal.chan.raddr.sockpath prints …/tractor/registry@1616.sock —
the root registrar's listener socket — not the child's. The UDS
transport derives both laddr/raddr from the same bound listener
path; only raddr.maybe_pid (via SO_PEERCRED) is child-specific.
So the "see the child's socket, no TCP port!" narrative shows a socket
named for the registrar; the child's real uds_child@<pid>.sock
only appears via the separate report_addr RPC. Fixed by relabeling
as the shared listener + leading with the peer pid.
2. ✅ .github/workflows/docs.yml — a PR run could cancel a production deploy.
Workflow-level concurrency: {group: 'pages', cancel-in-progress: true}
is shared by every run; a PR push while a main-merge deploy is mid
actions/deploy-pages cancels the in-flight production deploy. Fixed
by scoping the concurrency block to the deploy job with
cancel-in-progress: false (matches GitHub's Pages starter).
3. ✅ docs/explain/architecture.rst — documents a 'subint' backend not in this branch.
A full paragraph presents start_method='subint' as selectable, but
SpawnMethodKey = Literal['trio','mp_spawn','mp_forkserver'] here —
'subint' raises ValueError. Reworded to "in development / not yet
selectable on this release."
4. ✅ docs/guide/context.rst — tractor.StreamOverrun isn't exported.
StreamOverrun lives in tractor._exceptions, not the tractor
namespace ('StreamOverrun' in dir(tractor) → False); a reader
copying except tractor.StreamOverrun: gets AttributeError. Fixed
to reference the real module.
5. ✅ docs/guide/debugging.rst literalincludes 3 examples still using deprecated .result().
subactor_breakpoint.py, subactor_error.py, shielded_pause.py
(rendered into the flagship debugging page) still called
.result() — the deprecation purged elsewhere in this PR. Swept to
.wait_for_result().
tests/devx/test_debugger.py for them.
6. ✅ docs/start/quickstart.rst — proc-title format wrong + self-contradictory.
Said _subactor[worker_0@<uuid>]; Aid.reprol() yields name@pid,
and architecture.rst already documents _subactor[<name>@<pid>].
Fixed <uuid> → <pid>.
Lower severity (not auto-applied — flagging for your call)
7. docs/_ext/d2diagrams.py — silent stale-SVG on render failure.
With a d2 binary present, a .d2 edit that fails to compile
(returncode != 0) falls back to the committed SVG and the build
still exits 0 (only a log.warning). Consider failing the build when
a render is attempted and errors (distinct from the no-binary
fallback, which is correctly graceful).
8. docs/_ext/d2diagrams.py — parallel_read_safe/parallel_write_safe=True overclaims.
run() writes the shared _diagrams/<stem>.svg during the read
phase; under sphinx-build -j + a d2 binary + the same diagram on two
pages, two workers can write the same file. Harmless in CI today.
9. docs/_ext/d2diagrams.py — output keyed only by src.stem.
diagrams/foo.d2 and other/foo.d2 would collide to one
_diagrams/foo.svg. Latent (all 7 stems unique today).
10. docs/api/context.rst (Context autoclass) renders ~6 docutils errors.
Sourced from tractor/_context.py docstrings (Behaviour: underline,
unexpected indentation, …) — silent in CI (nitpicky=False) but
visible on the page; needs a source-docstring cleanup (already flagged
by the conf.py TODO).
Cross-check note
If the copilot review flags examples/streaming_broadcast_fanout.py
cancel_actor() as "inside the open-context block" — that's a false
positive: the call sits at 8-space indent, outside the block
(canonical teardown). Verified by indentation.
🤖 review by Claude Code (/code-review, xhigh effort)
Address the actionable findings from the `/code-review` pass (#1-6); the d2-ext + docstring nits (#7-10) are left for a follow-up. Deats, - `uds_transport_actor_tree.py`: `portal.chan.raddr.sockpath` is the *shared listener* socket (named for the root registrar), NOT the child's path — relabel it + lead with the per-child peer pid, and stop claiming it's the child addr in the docstring, - `docs.yml`: scope the `pages` `concurrency` group to the `deploy` job w/ `cancel-in-progress: false` so a PR build can't cancel an in-flight production deploy, - `architecture.rst`: `'subint'` is not a selectable `start_method` on this branch (`SpawnMethodKey` lacks it) — reframe as in-development/roadmap, - `context.rst`: `StreamOverrun` isn't re-exported from `tractor`; point at `tractor._exceptions`, - `debugging/`: sweep the 3 literalinclude'd examples off the deprecated `.result()` -> `.wait_for_result()`, - `quickstart.rst`: proc-title is `name@pid` (per `Aid.reprol`), not `@uuid`. NOTE, the `debugging/` examples are pexpect-tested; re-run `tests/devx/test_debugger.py` for them. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
|
Review nits #1–6 addressed in 37e7470:
The lower-severity items (#7–10: d2-ext render-failure silence,
|
Three robustness fixes surfaced by the PR #460 self-review, - a render that's *attempted and fails* (a `d2` bin is present but errors on the source) now raises a docutils error instead of silently serving the stale committed SVG — so `sphinx-build -W` fails on a broken `.d2` edit. The no-binary case stays a quiet committed-SVG fallback. - render into a sibling temp-file then `os.replace()` so a failed/torn render can never clobber a good committed SVG. - guard against 2 distinct `.d2` sources colliding on a single `_diagrams/<stem>.svg` within a build. `render_svg()` now returns a `RenderResult` tristate that `run()` maps to error / raw-source-literal / image. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Swap the deprecated `portal.result()` calls for the modern `.wait_for_result()` spelling in, - `a_trynamic_first_scene.py` (x2) - `actor_spawning_and_causality.py` - `parallelism/single_func.py` These 3 are literalinclude'd by the new docs tree so the rendered code must teach the current api; the `debugging/` set still calls `.result()` (pexpect pattern-matched tests, left for a follow-up sweep). (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Rename `parallelism/_concurrent_futures_primes.py` -> `concurrent_futures_primes.py` so the example-runner (`test_docs_examples.py`) stops skipping it (leading `_` = excluded) and CI finally exercises the `concurrent.futures` baseline we compare against in the new parallelism guide. Deats, - keep the original executor code verbatim in a sync `check_primes()` fn for clean docs excerpting, - add module docstring + zero-arg `async def main()` + `trio.run(main)` guard per the runner conventions. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
New runnable (and so CI-auto-tested) scripts backing the new docs guides, each following the `test_docs_examples.py` runner conventions, - `typed_payloads.py`: `@tractor.context(pld_spec=)` typed `started()`/stream roundtrip + a deliberate `MsgTypeError` catch demoing send-side validation, - `nested_actor_tree.py`: 3-level tree w/ fan-out rpc through a mid-tier supervisor actor, - `service_daemon_discovery.py`: registered daemon located via `find_actor()`/`wait_for_actor()` sans any spawn-portal ref, - `uds_transport_actor_tree.py`: `enable_transports=['uds']` tree printing the filesystem sockaddr + kernel peer-pid creds, - `streaming_broadcast_fanout.py`: one ipc stream fanned out to N local tasks via `MsgStream.subscribe()`. All gaps were mined from in-code TODOs + the docs recon pass; see #175 for the orig tutorial wishlist. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Fill in the long-TODO'd `[dependency-groups]` entry: `sphinx>=9.1` + `pydata-sphinx-theme>=0.18` + design/copybutton/opengraph/togglebutton exts; relock. Build via, `uv run --group docs make -C docs html` Theme choice per the #157 research: `numpy`, `ray` + `polars` all ride `pydata-sphinx-theme` these days (`ray` migrated off `sphinx-book-theme`, which now hard-pins a stale pydata 0.16.1 anyway). (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Full `docs/conf.py` rewrite targeting `pydata-sphinx-theme` 0.18 (3-col layout: nav-index left, content middle, page-toc right) skinned to a minimal b&w look via `_static/css/custom.css`, keeping the `algol_nu` pygments style. Also add 2 local sphinx exts under `docs/_ext/`, - `d2diagrams.py`: a `.. d2::` directive rendering `d2lang` sources at build time when a `d2` bin is found (`D2_BIN` env supports argful values eg. `'nix run nixpkgs#d2 --'`), falling back to any git-committed SVG, else emitting the raw source as a literal block; no pypi ext was usable (all stubs or returncode-swallowing per the #157 research), - `marginalia.py`: a theme-agnostic `.. margin::` directive (`sphinx-book-theme` style `Sidebar` subclass) for prose-anchored RHS asides; the custom css floats these (and `:margin:` d2 figs) into the right gutter on wide screens. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
7 hand-authored `docs/diagrams/*.d2` sources (sketch-mode, grayscale theme, `elk` layout) w/ their pre-rendered fallback SVGs committed under `docs/_diagrams/` (served as-is when no `d2` bin is found, eg. in CI), - `actor_tree`: the hero supervision-tree, - `context_handshake`: seq diagram of the `Start`/`StartAck`/`Started`/`Yield`/`Stop`/`Return` ctx dialog, - `streaming_pipeline`: 4-actor fan-in topology, - `runtime_stack`: the per-actor layer cake, - `debug_lock`: root-tty-lock REPL serialization, - `error_propagation`: one-cancels-all boxed-err flow, - `infected_aio`: guest-mode loop nesting. Rendered w/ `d2` v0.7.1 via `nix run nixpkgs#d2`. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Replace the ancient `docs/index.rst` (still teaching `tractor.run()`, `@stream` + arbiters..) with a full ~32 page tree teaching ONLY the current api (`.wait_for_result()`, registrar naming, `@context` + `open_context()` as the core model), - landing: hero example, feature cards + canon links, - `start/`: install + a 4-example quickstart on-ramp, - `explain/`: an "SC across processes" essay distilling the essence per #157's orig ask + a runtime architecture tour, - `guide/`: 12 task-focused pages incl the flagship multi-process debugging walkthrough, `Context` + `MsgStream` deep-dives, cancellation semantics (self-vs-cross cancel rules), discovery, infected `asyncio`, typed msging + the #126 testing-tips page, - `api/`: 10 curated autodoc pages (all targets import-verified vs the reorg'd subpkg tree), - `project/`: changelog include, ported dev-tips (drops old `docs/dev_tips.rst`) + roadmap. Every code block is a `literalinclude` from `examples/` - zero duplication, all CI-run - w/ `d2` figs floated into the RHS margin per the 3-col design. Build is green; the 24 remaining warnings all source from lib docstring rst-isms or legacy `NEWS.rst` content. Substantially resolves #157 (refine round pending); chips at #175 + #126. Prompt-IO: ai/prompt-io/claude/20260611T175152Z_8526985c_prompt_io.md (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
`docs.yml`: sphinx build on PRs + main pushes (via `uv sync
--no-dev --group docs`), deploying to gh-pages only from main
pushes using the official
`actions/{upload-pages-artifact,deploy-pages}` pair - the
`msgspec`-style flow wished for in #123. No `d2` bin in CI (yet) so
the committed SVGs serve as-is.
(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
Address the actionable findings from the `/code-review` pass (#1-6); the d2-ext + docstring nits (#7-10) are left for a follow-up. Deats, - `uds_transport_actor_tree.py`: `portal.chan.raddr.sockpath` is the *shared listener* socket (named for the root registrar), NOT the child's path — relabel it + lead with the per-child peer pid, and stop claiming it's the child addr in the docstring, - `docs.yml`: scope the `pages` `concurrency` group to the `deploy` job w/ `cancel-in-progress: false` so a PR build can't cancel an in-flight production deploy, - `architecture.rst`: `'subint'` is not a selectable `start_method` on this branch (`SpawnMethodKey` lacks it) — reframe as in-development/roadmap, - `context.rst`: `StreamOverrun` isn't re-exported from `tractor`; point at `tractor._exceptions`, - `debugging/`: sweep the 3 literalinclude'd examples off the deprecated `.result()` -> `.wait_for_result()`, - `quickstart.rst`: proc-title is `name@pid` (per `Aid.reprol`), not `@uuid`. NOTE, the `debugging/` examples are pexpect-tested; re-run `tests/devx/test_debugger.py` for them. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Factor the shared dev-shell toolchain into `basePkgs` + `baseHook` so extra-tooling shells can extend it, then add a `docs` shell = base + `pkgs.d2` (the diagram renderer our `.. d2::` sphinx directive shells out to). Keeps `d2` OUT of the `default` shell so casual dev envs stay lean. Enter with `nix develop .#docs`, then build via `uv run --group docs make -C docs html`. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Three robustness fixes surfaced by the PR #460 self-review, - a render that's *attempted and fails* (a `d2` bin is present but errors on the source) now raises a docutils error instead of silently serving the stale committed SVG — so `sphinx-build -W` fails on a broken `.d2` edit. The no-binary case stays a quiet committed-SVG fallback. - render into a sibling temp-file then `os.replace()` so a failed/torn render can never clobber a good committed SVG. - guard against 2 distinct `.d2` sources colliding on a single `_diagrams/<stem>.svg` within a build. `render_svg()` now returns a `RenderResult` tristate that `run()` maps to error / raw-source-literal / image. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
The new `api/` reference pages surfaced 22 docutils warnings from informal reST in public docstrings; fix the markup so the docs build is warning-free (24 -> 0), clearing the path to a future `-W`/`nitpicky` flip in CI. Deats (docstring content only; no code/signature changes), - give bullet lists a blank line + base-column indent (`Context`, `Context.cancel_called`/`.cancelled_caught`/ `.outcome`, `ActorNursery.cancel_called`, `query_actor`, `open_crash_handler`), - demote the under-short `Behaviour:` underline in `Context.cancel` to a `**bold**` label, - close an unbalanced backtick in the `wait_for_actor` summary and use the `` `role`\ s `` escaped-plural idiom where a role was pluralized (`gather_contexts`, `mk_pdb`, `MsgCodec`, msg `Error`, `open_context_from_portal`), - make the `|_` method-tree in `ContextCancelled.canceller` a literal block (the bare `|` was read as a substitution ref), - same blank-line fix for the `#318` entry in `NEWS.rst`. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
The `docs` group (sphinx 9 + `pydata-sphinx-theme` stack) was added to `pyproject.toml` but its lockfile half never landed — the committed `uv.lock` still matched `main` and `uv lock --check` flagged it out-of-sync. Relock to add the (additions-only) docs deps so `uv sync --locked` and any CI lock-check pass. (this commit msg was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Collect the sphinx build + live-preview one-liners (incl. the nix `.#docs` opt-in shell and the `d2` diagram specifics) so contributors don't have to reverse-engineer them, - new `notes_to_self/howtodocs.md` terse cheat-sheet (force-added past the `notes_to_self/` ignore, same as `howtorelease.md`), - a rendered "Building these docs" section in the dev-tips guide (`docs/project/dev-tips.rst`), - a README pointer to the note. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Add a "Share on your LAN" blurb to both docs how-to homes (`notes_to_self/howtodocs.md` + the dev-tips "Building these docs" section): bind the server to all ifaces — via `sphinx-autobuild --host 0.0.0.0` (live-reload) or `python -m http.server --bind 0.0.0.0` (static) — so a peer on your subnet can hit `http://<lan-ip>:8000` (`hostname -I` prints the ip). Verified a LAN-ip `curl` returns 200 + the socket binds `0.0.0.0`; includes a trusted-LAN-only caveat since it's an unauthenticated server on every interface. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Swap the landing-page hero from a static `<img>` (white-faced —
which glared as a light box on the dark theme) to an INLINE svg
whose linework uses `fill: currentColor` and whose faces are
transparent. The wireframe now inherits the theme text colour
(`svg.hero-logo { color: var(--pst-color-text-base); }`) and the
page background shows through, so it flips correctly with the
light/dark toggle.
- `tractor_logo_hero.html`: the inline svg partial (`.st0` ->
`currentColor`, `.st1` -> `none`), `.. raw:: html :file:`-d into
`index.rst`,
- the shared `tractor_logo_side.svg` is untouched here (navbar +
favicon still ride it).
(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
Carry the landing hero's transparent-faces wireframe look to the two other logo contexts. An `<img>`-embedded svg can't read the page CSS (no `currentColor`), so the colours are baked per target, - navbar: 2 variants (`tractor_logo_nav_light.svg` near-black lines, `…_nav_dark.svg` near-white) wired via the pydata `logo.image_light`/`image_dark` opts so it swaps with the theme toggle, matching the hero, - README: `tractor_logo_wire.svg` — one neutral-grey, with INLINE fills (no `<style>`) so it reads on both GitHub light + dark and survives GitHub's svg sanitiser. Faces are `fill: none` throughout; the filled `tractor_logo_side` stays the recolour source + favicon. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Capture the (easy-to-forget) logo recolour + theme-preview flow, - new `notes_to_self/svgtool.py`: a headless-firefox svg helper (`colors`/`recolor`/`preview`/`page`); its `page --theme dark|light` injects a `localStorage` pin so a pydata `auto`-mode build renders its dark variant in a screenshot — the only way to verify theme-adaptive bits headlessly, - `howtodocs.md`: a "Tweaking the logo" table (which file + `color:` knob per context) and an `svgtool` section that breaks down the `--theme` trick for the sphinx-rusty. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Rework the landing top into a left-anchored hero row and match the
navbar branding to it.
- `index.rst` + new `tractor_hero.html`: an inline-svg hero
(`[logo] distributed structured concurrency`) with a full-width
sub-tagline, plus a single screen-reader-only `<h1>` ("tractor")
so the section headings become proper `<h2>` (was 4x `<h1>`), and
the intro prose reflowed into 3 bullets,
- `conf.py`: a `logo.text` ("tractor") beside the navbar wireframe,
polars-style,
- `custom.css`: the hero-row layout (logo + tagline + sub-line,
single row on desktop / stack on mobile), the navbar brand styled
like the centered nav tabs with `display:inline-block` to kill
the parent link's propagated hover-underline, and smaller landing
section headings w/ their `tl;dr` margin-note pulled level.
The hero linework stays `fill: currentColor` so the whole thing
flips with the light/dark toggle.
(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
The gh-pages deploy workflow already exists (build on PR + main, deploy on main push via `actions/deploy-pages`); wire up the sphinx side, - `sphinx.ext.githubpages`: emits a `.nojekyll` so Pages serves the `_static/` + `_images/` dirs (Jekyll otherwise drops `_`-prefixed paths, breaking every asset), - `html_baseurl`: the canonical site root (`https://goodboy.github.io/tractor/`) for the `<link rel="canonical">` + `og:url` tags. The one remaining (one-time, manual) step is the repo setting: Settings -> Pages -> Source = "GitHub Actions". (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
`run_in_actor()` is slated to become a hilevel wrapper (`runtime/_supervise.py` "TODO: DEPRECATE THIS"), so the showcase `we_are_processes.py` shouldn't lead with it. Move it to the modern API: each `worker_<i>` subactor runs a `@tractor.context` `endpoint()` that `started()`-hands its name + pid back over `Portal.open_context()` and parks; the root sleeps then raises on purpose so the runtime reaps the whole tree (zero zombies). The subs spawn concurrently from bg `trio.Task`s so each child's cold `import tractor` (~0.4s, see #470) overlaps instead of stacking; a comment flags the coming `main_thread_forkserver` backend (#463) which'll make serial spawns cheap enough to just loop. Match the landing prose to the snippet — name the `Context` + `started()` handshake it now leads with. Also, document `--watch examples` on the `sphinx-autobuild` cmds so edits to `literalinclude`-d example scripts (which live outside `docs/`) live-reload too. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
The README inlined six example scripts; per our own "point at `examples/`, don't duplicate" philosophy that's a lot of rot surface. Drop all but the showcase and rework it onto the modern `Context` API to mirror the docs landing + `we_are_processes.py`: spawn a subactor per core, `open_context()` each, crash the root, reap the tree. Replace the rest with a short "want more?" pointer to the docs site + the `examples/` dir (where the debugger, streaming, cancellation, `asyncio`, msging + cluster demos all live, CI-run). Also tidy a few nits while here, - fix the title typo "structurred" -> "structured", - close the unterminated quote in the `UV_PROJECT_ENVIRONMENT` install snippet, - add the blank line a nested `trionics` bullet list needs so the PyPI long-desc (this file) renders as valid RST. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
The reworked `we_are_processes.py` (now `Context`-API based) prints different stdout, so the hardcoded expected-output block went stale: swap the old `Yo, i'm 'worker_N'...` / "self-destruct in 1 sec" lines for the real run - "self-destruct in 2s.." then the per-worker `Started ep-task in subactor,` / `N::'worker_N'@<pid>` blocks. Also retell the prose to match: subs spawn concurrently from bg `trio` tasks, each runs a `@tractor.context` `endpoint()` that `ctx.started()`-hands its name + pid back through `Portal.open_context()`, then parks in `trio.sleep_forever()` before the root crashes + the tree is reaped. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
5ca4124 to
c028e03
Compare
Continuing the README slim-down: stop inlining content that now
lives (and renders better) on the GitHub Pages site, and just
point readers there.
- "Where do i start" drops the SC reading-list links in favor of
a single nudge to the docs quickstart.
- "Example codez" drops the full `we_are_processes.py` listing -
keep the one-minute pitch prose + the docs/examples links.
- "What's on the TODO" collapses the inline bullet list down to a
link to the docs roadmap ("what the future holds").
Also,
- prune the now-dead RST link targets (`blog post`, `trio docs`,
`SC`, `libdill-docs`, `async sandwich`, `messages`, ..).
- swap the `|docs|` badge from readthedocs over to the GitHub
Pages `docs.yml` action badge + `goodboy.github.io` target.
(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
Continuing the README slim-down: stop inlining content that now
lives (and renders better) on the GitHub Pages site, and just
point readers there.
- "Where do i start" drops the SC reading-list links in favor of
a single nudge to the docs quickstart.
- "Example codez" drops the full `we_are_processes.py` listing -
keep the one-minute pitch prose + the docs/examples links.
- "What's on the TODO" collapses the inline bullet list down to a
link to the docs roadmap ("what the future holds").
Also,
- prune the now-dead RST link targets (`blog post`, `trio docs`,
`SC`, `libdill-docs`, `async sandwich`, `messages`, ..).
- swap the `|docs|` badge from readthedocs over to the GitHub
Pages `docs.yml` action badge + `goodboy.github.io` target.
(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
The `context_handshake` sequence diagram only showed the graceful `Return` ending - underselling the whole SC pitch (errors + cancels propagate *both* ways across the wire). Add a "... or, instead of a graceful Return" group with the non-graceful endings, - parent-initiated: `ctx.cancel()` (or a parent-side error) -> child relays `Error: ContextCancelled`, - child-initiated: child ships `Error: <raised>` (or `ContextCancelled`). Labelled `Error: ...` since `ContextCancelled` is an exception that rides inside an `Error` wire msg, not its own msg type - keeping the diagram's wire-level labels honest. Re-render the committed `_diagrams/context_handshake.svg` fallback (CI has no `d2` bin) to match. Also cache-bust d2 images in `d2diagrams.py`: sphinx tags css/js with `?v=<hash>` but not images, so an edited diagram kept serving the browser's stale copy at the stable `_images/<stem>.svg` url (cost us a manual hard-refresh). Hash each rendered svg + rewrite only the d2 `<img src>` to `...svg?v=<hash8>` via the `html-page-context` hook - content-addressed, so unchanged diagrams keep their query. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
`uds_transport_actor_tree.py` (new in 759d46d) reliably fails on macOS CI with a bare `returncode 1`. The example forces `enable_transports=['uds']`, and UDS-on-macOS is otherwise un-exercised by the matrix (there's no `tpt_proto=uds` macOS job), so it's the first thing to surface a macOS UDS-path issue. It passes cleanly on Linux, and the peer-cred paths are already platform-guarded + graceful (`get_peer_info`/SO_PEERCRED on linux vs `get_peer_pid`/LOCAL_PEERPID elsewhere) - so the crash is deeper in the macOS UDS stack. The test swallows the subproc stderr (only re-raises when the last line has "Error"), so the exact failure can't be pinned from CI logs; needs a macOS box to root-cause. Skip it on `_friggin_macos and ci_env` (same shape as the existing `full_fledged_streaming_service` skip) so #460 lands green; the macOS UDS root-cause is a follow-up. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
|
Hmm flaky macos test (latency issues) which should be resolved by #468, so I'm likely just gonna 🤠 merge this. |
Add a real docs site:
pydatatheme,d2diagrams, tested examplesMotivation
Our docs were years out of date — teaching a long-dead API
(
tractor.run(),@stream, "arbiters") on a barebones theme — and#157 had been asking for a proper modern docs site for ages, with
#175/#126/#123 piling on tutorial/testing/deploy asks.
This rebuilds the docs from the ground up: a 3-column
pydata-sphinx-themesite skinned black-and-white,d2-rendereddiagrams, and prose that teaches ONLY the current API — with every
code block
literalinclude-d fromexamples/so the docs can't rot(what you read is what CI runs).
Src of research
Theme + tooling choices were research-backed (the #157 thread plus a
live survey of peer projects),
pydata-sphinx-theme— numpy / ray / polars all use it today (raymigrated off
sphinx-book-theme).d2(terrastruct) for diagrams-as-code.Summary of changes
pydata-sphinx-theme0.18 + sphinx9: new
docs/conf.py, adocsdependency-group, a minimal b&wcustom.css, and an opt-innix develop .#docsshell carrying thed2renderer... d2::directive (docs/_ext/d2diagrams.py) thatrenders
d2sources at build time with a committed-SVG fallback(CI needs no
d2bin) + a vendored.. margin::, plus 7hand-authored diagrams.
explainer + runtime architecture, 12 task guides (the flagship
multi-process debugger,
Context/streaming, cancellation,discovery, infected
asyncio, typed msging, testing) and 10curated autodoc API pages — and fix the lib docstrings'
informal-RST so the build is warning-free.
scripts, the dated set moved to
.wait_for_result(), and thestdlib primes baseline un-hidden — all CI-run.
with the light/dark toggle (
fill: currentColor), carry it to thenavbar + README, and brand the navbar polars-style.
mainworkflow,sphinx.ext.githubpages(.nojekyll) +html_baseurl.notes_to_self/howtodocs.md+ adev-tips section + an
svgtool.pyhelper) and log AI provenanceper NLNet policy.
TODOs before landing
landing + README main example off
ActorNursery.run_in_actor()onto
@tractor.context/Portal.open_context().run_in_actoris slated to become a hilevel wrapper (
runtime/_supervise.py"TODO: DEPRECATE THIS"), so the showcase example shouldn't lead
with it.
1f84d5f5) README cleanup — simplify + strip most of the
"example codez" section (leave ~just the one example the docs
landing uses), and swap the
|logo|to the transparent-faceswireframe so it shows through the GitHub repo-page theme instead of
the old white-bg block.
Future follow up
across the guides, plus the
run_in_actor()-led showcase →Contextsweep (guide/rpc.rst,guide/spawning.rst). Tracked inDocs content refinement pass (follow-up to #460) #472 so this PR lands now as the scaffold/middle-ground.
Links
Closes #157 (the "big boi docs" ask). Partially addresses #175
(tutorials/examples), #126 (testing-tips page) and #123 (gh-pages
deploy).
(this pr content was generated in some part by
claude-code)