Skip to content

fix(trains,dispatch,surface,tooling): startup errors link their fix; docs for newcomers - #94

Merged
Theauxm merged 11 commits into
mainfrom
docs/newcomer-round
Oct 20, 2026
Merged

Theauxm merged 11 commits into
mainfrom
docs/newcomer-round

Conversation

@Theauxm

@Theauxm Theauxm commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

A newcomer can see everything Trax does, find where to start, and follow a startup error to its fix

Background

An outside read of the docs, done by someone with no prior knowledge of Trax, found the material
mostly there but hard to get into for a person (as opposed to an agent). This PR takes the cheap
fixes from that read. Terms used below:

  • Troubleshooting page (cross-cutting/troubleshooting.md): one ## heading per error
    message Trax raises, quoted as in the source, with the fix underneath.
  • Excerpt fence (from=<path>): a code block on a page that must be lines of a real file in
    the repository. SampleExcerptsMatchSourceTests fails when the page and the file disagree.
  • Behavior bullets: the ## Behavior section of an SDK reference page, stating in prose what
    the member does in the edge cases.

Problem

🟩🟧🟦 A startup error does not say where its fix is
"N of M registered trains cannot run:", "Call AddEffects(...) before AddMediator(...).", "Invalid
cron expression ..." each have an entry on the troubleshooting page, and none of them mentions it.
The reader has to know the page exists and search it.

⬛ Nothing marks which of the ~470 pages to read first
The docs home sorts pages by kind (Learn, Do, Understand, Look up) but not by importance.

⬛ The glossary defines each term by its type
"Train<TIn, TOut> in Trax.Core.Train. A class that ..." is exact, but a reader has to decode
it before learning that a train is roughly a workflow.

⬛🟩 Chapter 1 of the book sends the reader to the wrong chapter, and skips a trap
1.9 says chapter 2 moves the runs to Postgres; chapter 2 is testing, Postgres is chapter 3. 1.6
says Memory holds "one value per type" without saying the second value of a type replaces the
first.

⬛ Nothing shows the breadth of Trax
The docs home, the sidebar and the overviews are organised by package (Trax.Core, Trax.Effect,
Mediator) and by page kind. A reader who finishes the quick start does not learn that machines,
workers, generated clients, decisions or checkpoints exist. The homepage leads with replays of
four advanced features before it says what a train is, and its install line,
dotnet add package Trax.Core, is the one package with nothing web in it.

⬛🟪 No page says when work wants a train and when a state machine
The two appear together everywhere, and the difference is never stated.

⬛🟩 A Behavior bullet is a claim with nothing next to it
"Nothing escapes RunEither" is true and tested, but the page does not show the test, and the test
does not know a page depends on it.

Example

A host registers a train whose junction needs a StockReservation that nothing earlier produces.

What the developer sees at startup
Before 1 of 3 registered trains cannot run:
- Junction 'TakePayment' (train 'IPlaceOrderTrain') needs 'StockReservation' as its input, ...
After the same, then
See https://traxsharp.net/docs/cross-cutting/troubleshooting#n-of-m-registered-trains-cannot-run

And core/memory.md, under "Storage by Type", now shows this test from Trax.Core's suite rather
than a commented fragment:

public class NameTrain : Train<Person, string>
{
    protected override Task<Either<Exception, string>> Junctions() =>
        Chain<GetFirstName>().Chain<GetLastName>().Resolve();
}

[Test]
public async Task Run_TwoJunctionsReturnAString_ReturnsTheSecond()
{
    var name = await new NameTrain().Run(new Person("Ada", "Lovelace"));

    name.Should().Be("Lovelace");
}

How this solves it

🟩🟧🟦 Thirteen messages end with their entry's link
Registration-order, data-provider, chain-verification, manifest-seeding and cron/interval messages
in Mediator, Effect, Scheduler and Api append See https://traxsharp.net/docs/cross-cutting/troubleshooting#<heading>.
The text before the link is unchanged, so *...* assertions still hold. CodeLinksToDocsResolveTests
already scans every src/ file and fails on an anchor no heading produces, so renaming a heading
now breaks the build instead of a link.

⚠️ The [Obsolete(error: true)] on AddMediator before AddEffects carries the link too, so the
CS0619 text changes and Trax.Mediator's public API baseline moves. Only the message changed, not
the signature.

⬛ The docs home lists 14 pages in reading order, from the quick start through Memory, error
handling, testing, the mediator, scheduling, GraphQL, authorization and the console, ending at
troubleshooting and packages.

⬛ Glossary entries open with a plain equivalent (Roughly: a workflow, one step, a saved
schedule entry, middleware around every run ...) where an honest one exists, 17 of 39 terms. The
quick start and chapter 1 link the glossary in their first paragraph.

⬛🟩 Reference pages show the test that proves the behaviour, and the test names the page
Four small examples under Trax.Core/tests/Trax.Core.Tests.Integration/Examples/, each one train
and one test written to be read: Memory replacing a same-type value, a failed junction stopping the
chain (Run throws the junction's own exception, RunEither returns it), and ShortCircuit
keeping a cache hit while the rest of the chain still runs. Each file opens with
// Shown on https://traxsharp.net/docs/<page>, and a new guard checks both directions:

flowchart LR
    Page["Page: from=Trax.Core/tests/.../OneValuePerTypeTests.cs"]
    File["Test file: // Shown on .../docs/core/memory"]
    Match["SampleExcerptsMatchSourceTests: lines match"]
    Names["TestExcerptsNameTheirPagesTests: each names the other"]
    Page -->|excerpt| Match
    File --> Match
    Page -->|"excerpt of a library test needs the line"| Names
    File -->|"the line needs the page to excerpt it"| Names
    class Page,Match,Names tooling
    class File trains
    classDef trains fill:#22c55e,stroke:#15803d,color:#000
    classDef tooling fill:#334155,stroke:#0f172a,color:#fff
Loading

Samples and templates are left out: sample pages tour their sample, and a template's comments ship
into the reader's project. The two existing Decisions examples got their line. writing-docs.md
documents the convention.

⬛ One page maps every capability
what-trax-does.md opens with one paragraph on how the pieces relate (everything in Trax is a way
to use a train) and a diagram, then lists each capability with a plain sentence, the book chapter
that builds it, the page that explains it, and its package. The docs home carries the same
paragraph, puts the page first in Start here, and its Understand list now covers decisions,
checkpoints, retries, workers, GraphQL, persisted operations, the console, machines and the
guards. book.md opens with its 18 chapters in a table.

⬛🟪 Train or machine (statemachine/train-or-machine.md): one operation that runs to its end,
or a long-lived thing a user moves through, and how a state invokes a train.

⬛ Overviews are named by what they do: "Trains (Trax.Core)", "Recording runs (Trax.Effect)",
"Calling a train by its input (Trax.Mediator)", each opening with the problem it solves. URLs are
unchanged.

⬛ Five top-level pages move into their sections
api-graphql-client, api-security, persisted-operations, authorization and
supply-chain-security now live under api/ and security/, each with redirect_from for its
old path, and the links to them across the docs, SECURITY files and templates point at the new
paths. The sidebar places them as before; it groups by type and area, not folder.

⬛ The homepage
The hero installs from the templates (as the README does) and links What Trax does beside Get
started. "One train, four ways to run it" now comes straight after the hero, before the replays.
The layer list gains a state machines rung, and the header, the console page and the layer list
say "console" rather than "dashboard". The import section links the CLI reference instead of a
quick start that never runs trax generate. The README drops its second "Start here".

Architectural hinges

  • 🟧 Trax.Mediator/src/Trax.Mediator/Services/ChainVerification/TrainChainStartupValidator.cs
    (StartingAsync): the refusal most newcomers hit first; its link is the one with a test of its own.
  • ⬛ Trax.Docs/tests/Trax.Docs.Snippets.Tests/Tests/TestExcerptsNameTheirPagesTests.cs: the
    two-way rule between a page and the library test it shows.
  • 🟩 Trax.Core/tests/Trax.Core.Tests.Integration/Examples/Failures/Checkout.cs: the shape the
    examples follow, one train shown on two pages.
  • ⬛ Trax.Docs/what-trax-does.md: the capability map the docs home and the homepage now point at.
  • ⬛ Trax.Docs/index.md (## Start here): the reading order.
  • ⬛ Trax.Website/src/app/page.tsx: the homepage's section order.

@vercel

vercel Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
trax-website Ignored Ignored Preview Oct 20, 2026 3:57pm UTC

@codecov

codecov Bot commented Oct 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Theauxm
Theauxm force-pushed the docs/newcomer-round branch from 9d7f97d to 453f3b8 Compare October 20, 2026 15:57
@Theauxm
Theauxm merged commit a80e4a6 into main Oct 20, 2026
40 checks passed
@Theauxm
Theauxm deleted the docs/newcomer-round branch October 20, 2026 16:07
@github-actions

Copy link
Copy Markdown
Contributor

This PR is included in version 1.68.0

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.

1 participant