Skip to content

Docs (vibed) for serious: real documentation with a modern theme #460

Merged
goodboy merged 28 commits into
mainfrom
docs_vibed_for_serious
Jun 29, 2026
Merged

Docs (vibed) for serious: real documentation with a modern theme #460
goodboy merged 28 commits into
mainfrom
docs_vibed_for_serious

Conversation

@goodboy

@goodboy goodboy commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Add a real docs site: pydata theme, d2 diagrams, tested examples

Motivation

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-theme site skinned black-and-white, d2-rendered
diagrams, and prose that teaches ONLY the current API — with every
code block literalinclude-d from examples/ 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 (ray
    migrated off sphinx-book-theme).
  • d2 (terrastruct) for diagrams-as-code.

Summary of changes

  • Stand up the sphinx project on pydata-sphinx-theme 0.18 + sphinx
    9: new docs/conf.py, a docs dependency-group, a minimal b&w
    custom.css, and an opt-in nix develop .#docs shell carrying the
    d2 renderer.
  • Add a local .. d2:: directive (docs/_ext/d2diagrams.py) that
    renders d2 sources at build time with a committed-SVG fallback
    (CI needs no d2 bin) + a vendored .. margin::, plus 7
    hand-authored diagrams.
  • Write the content tree — landing, an "SC across processes"
    explainer + runtime architecture, 12 task guides (the flagship
    multi-process debugger, Context/streaming, cancellation,
    discovery, infected asyncio, typed msging, testing) and 10
    curated autodoc API pages — and fix the lib docstrings'
    informal-RST so the build is warning-free.
  • Add/modernize the examples backing the guides: 5 new gap-filling
    scripts, the dated set moved to .wait_for_result(), and the
    stdlib primes baseline un-hidden — all CI-run.
  • Redesign the landing hero as an inline-svg wireframe that flips
    with the light/dark toggle (fill: currentColor), carry it to the
    navbar + README, and brand the navbar polars-style.
  • Wire up GitHub Pages: a build-on-PR / deploy-on-main workflow,
    sphinx.ext.githubpages (.nojekyll) + html_baseurl.
  • Document the docs workflow itself (notes_to_self/howtodocs.md + a
    dev-tips section + an svgtool.py helper) and log AI provenance
    per NLNet policy.

TODOs before landing

  • (c3e5ed1b, 274cab94) Rewrite the
    landing + README main example off ActorNursery.run_in_actor()
    onto @tractor.context / Portal.open_context(). run_in_actor
    is slated to become a hilevel wrapper (runtime/_supervise.py
    "TODO: DEPRECATE THIS"), so the showcase example shouldn't lead
    with it.
  • (274cab94, 3753c671,
    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-faces
    wireframe so it shows through the GitHub repo-page theme instead of
    the old white-bg block.

Future follow up

  • Remaining docs content refinements — prose filling/refining
    across the guides, plus the run_in_actor()-led showcase
    Context sweep (guide/rpc.rst, guide/spawning.rst). Tracked in
    Docs 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)

@goodboy goodboy added the docs label Jun 11, 2026
@goodboy
goodboy changed the base branch from main to custom_log_levels June 11, 2026 21:04
@goodboy
goodboy force-pushed the docs_vibed_for_serious branch 2 times, most recently from 25f5210 to ea98287 Compare June 25, 2026 17:01
@goodboy
goodboy changed the base branch from custom_log_levels to main June 25, 2026 17:16
@goodboy
goodboy requested a review from Copilot June 25, 2026 17:16

Copilot AI 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.

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 docs dependency 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.

Comment thread docs/_ext/d2diagrams.py
Comment on lines +184 to +190
img = nodes.image(
uri=f'/{_outdir}/{out.name}',
alt=self.options.get(
'alt',
f'd2 diagram: {src.stem}',
),
)
Comment thread docs/project/dev-tips.rst
Comment on lines +4 to +6
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 goodboy left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

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.rsttractor.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(). ⚠️ these are pexpect-tested — please re-run
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.pyparallel_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)

goodboy added a commit that referenced this pull request Jun 25, 2026
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
@goodboy

goodboy commented Jun 25, 2026

Copy link
Copy Markdown
Owner Author

Review nits #1–6 addressed in 37e7470:

The lower-severity items (#7–10: d2-ext render-failure silence,
parallel_*_safe overclaim, stem-collision keying, and the Context
docstring rST cleanup) are left open for a follow-up.

⚠️ #5 touches the pexpect-driven debugger examples — worth a
tests/devx/test_debugger.py run before merge.

goodboy added a commit that referenced this pull request Jun 25, 2026
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
goodboy added 17 commits June 28, 2026 13:29
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
goodboy added 7 commits June 28, 2026 13:29
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
@goodboy
goodboy force-pushed the docs_vibed_for_serious branch from 5ca4124 to c028e03 Compare June 28, 2026 17:29
goodboy added 3 commits June 28, 2026 14:20
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
@goodboy
goodboy marked this pull request as ready for review June 29, 2026 19:44
@goodboy

goodboy commented Jun 29, 2026

Copy link
Copy Markdown
Owner Author

Hmm flaky macos test (latency issues) which should be resolved by #468, so I'm likely just gonna 🤠 merge this.

@goodboy
goodboy merged commit f8b7233 into main Jun 29, 2026
12 of 14 checks passed
@goodboy
goodboy deleted the docs_vibed_for_serious branch June 29, 2026 20:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Revamp DOCS, fo realz

2 participants