Skip to content

Restore the docs signpost and fix the bench lockfile - #116

Merged
kingchenc merged 2 commits into
mainfrom
fix/docs-wayfinder-and-bench-lock
Aug 30, 2026
Merged

Restore the docs signpost and fix the bench lockfile#116
kingchenc merged 2 commits into
mainfrom
fix/docs-wayfinder-and-bench-lock

Conversation

@kingchenc

Copy link
Copy Markdown
Contributor

Two gaps that came out of holding the tree against the blueprint path by path
rather than against the checker, which could see neither of them.

The signpost in docs/

Section 01 lists docs/README.md as a file both repositories carry, and says
what it prevents: someone starting a second documentation tree in the main
repository. That is what happened here. docs/ holds three real documents and
nothing that says where the rest lives, so a reader who opens the directory has
no reason to think a site exists at all.

The blueprint even anticipated it — the row reads "In wickra-backtest liegen
daneben drei echte Dokumente" — and check_blueprint.py still reported the root
inventory complete, because docs/README.md was missing from its ROOT list.
Fixed on the tooling side too, so the next repo cannot hide the same gap.

The new file names both directions. The per-language API reference is on
backtest.wickra.org, one page per language surface; the Rust API is on docs.rs.
What stays here is what a release can change and what this repository owns: the
spec reference beside its JSON schema, the cookbook beside the strategies it
explains, the microstructure guide beside the engine implementing it. It closes
with the rule that keeps it a signpost — a page about calling the library from a
language belongs on the site, a page about what the engine accepts belongs
beside the code.

Site URLs verified against the site's own .vitepress/config.ts (cleanUrls: true, links of the form /api/rust) rather than guessed.

bench.yml has been red for three nights

2026-08-28, -29 and -30, all with the same error, and nobody saw it because the
workflow only runs on a schedule and nothing watches a scheduled workflow:

ERROR: In --require-hashes mode, all requirements must have their versions
pinned with ==. These do not: pexpect>4.6 (from ipython==9.16.1)

The lock was compiled on Windows. ipython requires pexpect only where
sys_platform != "win32", so that branch was never taken and pexpect never
entered the file. On the ubuntu runner pip needs it, finds it unpinned, and
--require-hashes refuses the entire install — so not one benchmark ran on any
of those nights.

--python-platform linux fixes it at the source, and update-lockfiles.sh now
carries the reason, because the next person regenerating this on a laptop would
otherwise undo it silently. bench.yml runs on ubuntu and nothing else, so the
lock is built for ubuntu and nothing else.

The diff is the whole story: +pexpect, +ptyprocess, and the Windows-only
colorama and tzdata drop out of a file that only ever installs on Linux. No
other version moved — uv keeps existing pins as preferences.

The two ci-dev locks are deliberately untouched. They install on all three
runner operating systems, so resolving them for one would be the same mistake in
reverse. Measured rather than assumed: neither carries a platform-conditional
requirement, which is why both have been green on all three all along.

Verification

  • Dependency closure of the new lock is complete — 21 via sources, every one
    pinned — and all 61 packages carry hashes.
  • actionlint (with shellcheck), check_readme_links, check_version_sync,
    check_example_specs, check_license_copies: green.
  • Every relative link in the new file resolves to a path that exists.
  • Blueprint checker after this: 82/82, no finding. The counterpart run
    against wickra stays at 88/88 with every conditional check still firing
    there, so nothing was weakened to reach it.

Not attempted, and named rather than left implied: the R vignette, r/data,
data-raw, the node harness.js / dts-header.d.ts polish, gen_golden_test.py
and the extra example scenarios. All are marked wickra-only in the blueprint,
and §08 says the matrix is filled as needed rather than in full. Writing them
here would be inventing product content, not closing a gap.

The blueprint lists docs/README.md as a file both repositories carry, and
describes exactly what it prevents: someone starting a second documentation
tree in the main repository. That is what happened here. docs/ holds three real
documents and nothing that says where the rest lives, so a reader who opens the
directory has no reason to think there is a site at all.

The file names both directions. The per-language API reference is on
backtest.wickra.org, one page per language surface, and the Rust API is on
docs.rs. What stays here is what a release can change and what the repository
owns: the spec reference beside its JSON schema, the cookbook beside the
strategies it explains, the microstructure guide beside the engine that
implements it.

It also states the rule that keeps it a signpost. A page about calling the
library from a language belongs on the site; a page about what the engine
accepts belongs beside the code. A second tree drifts from the first, and
nobody notices, because both look maintained.
bench.yml has failed for at least three consecutive nights -- 2026-08-28, -29
and -30 -- and nobody saw it, because it only runs on a schedule and nothing
watches a scheduled workflow. The error was the same each time:

  ERROR: In --require-hashes mode, all requirements must have their versions
  pinned with ==. These do not: pexpect>4.6 (from ipython==9.16.1)

The lock was compiled on Windows. ipython requires pexpect only where
sys_platform != "win32", so that branch was never taken and pexpect never
entered the file. On the ubuntu runner pip needs it, finds it unpinned, and
--require-hashes refuses the whole install -- so not one benchmark ran.

--python-platform linux fixes it at the source, and update-lockfiles.sh now
says why, because the next person to regenerate this on a laptop would
otherwise undo it. bench.yml runs on ubuntu and nothing else, so the lock is
built for ubuntu and nothing else.

The diff is the whole story: +pexpect, +ptyprocess, and the Windows-only
colorama and tzdata drop out of a file that only ever installs on Linux. No
other version moved -- uv keeps the existing pins as preferences.

The two ci-dev locks are deliberately left alone. They install on all three
runner operating systems, so resolving them for one would be the same mistake
in reverse; measured rather than assumed -- they carry no platform-conditional
requirement, which is why they have been green on all three all along.

Verified: the dependency closure is complete (21 via-sources, all pinned) and
all 61 packages carry hashes.
@kingchenc
kingchenc merged commit 59a589b into main Aug 30, 2026
60 checks passed
@kingchenc
kingchenc deleted the fix/docs-wayfinder-and-bench-lock branch August 30, 2026 22:42
@codecov

codecov Bot commented Aug 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

kingchenc added a commit that referenced this pull request Aug 30, 2026
Version-strings only, which is the point: a bump that carries nothing else has
a CI run that is unambiguous, and a failure in it can only come from the bump.

**Do not merge this yet** — merging it is the last reversible step. The tag that
follows publishes to six registries and cannot be taken back.

## What moved

Produced by `bump_version.py`, not by hand — 20 touchpoints across eight
languages, each with an expected hit count, so a manifest that quietly stops
matching is a failure rather than a silent skip:

| | |
|---|---|
| `Cargo.toml` | 3 |
| `bindings/node/package.json` | 7 (version + six `optionalDependencies`) |
| `bindings/node/npm/<rid>/package.json` | 6 × 1 |
| `bindings/node/index.js` | 52 (the napi loader's version literal) |
| `bindings/node/package-lock.json` | 19, one third-party entry left alone |
| `bindings/python/pyproject.toml`, `bindings/java/pom.xml`, `Wickra.Backtest.csproj`, `bindings/r/DESCRIPTION` | 1 each |
| `examples/java/pom.xml` | 2 (its own version and the dependency) |
| `SECURITY.md` | 3 |
| `CITATION.cff` | version **and** `date-released` |
| `Cargo.lock` | refreshed by `cargo build`, never edited |

`CITATION.cff` is new to that list. It became a version touchpoint in #115 when
it grew `version:` and `date-released:`, and the bump tool had not followed — so
this bump would have left the citation naming 0.1.0 while every manifest said
0.1.1, with nothing downstream to catch it, since GitHub's citation box and
Zenodo read that file and no build does. Fixed in the tooling repo, along with
`date-released`, which no replacement finds because it is not a version: left
alone it names the day of the previous release beside the new version, and a
reader cannot tell which of the two is stale.

## Changelog

`[0.1.1]` collects what #115 landed — the publish gate, the ref guard, the split
`wasm-build`, CodeQL over the four compiled bindings, actionlint, CodSpeed,
semver, the container smoke job, the C golden test, the schema check — and two
entries that #116 should have written and did not:

- the `docs/` signpost under **Added**
- the cross-library benchmark under a new **Fixed** section, which had been red
  for three consecutive nights without anyone noticing

## Verification

`cargo fmt`, `cargo test --workspace --all-features` (21 suites), `cargo clippy
-D warnings`, `cargo deny`, `actionlint` with shellcheck, and all six check
scripts: green. `check_version_sync.py` agrees across 18 declarations at 0.1.1.

The diff outside `CHANGELOG.md` and the two lockfiles contains no line that is
not a version string — checked, not assumed.

Line endings are unchanged: `git ls-files --eol` reports 285 index entries as
`i/lf` and none as CRLF.

## What is still unproven, and will be until the tag

`release.yml` runs on `push: tags: ["v*"]` and nothing else, so five things
land in it for the first time on this release: the `gate` job, its ref guard,
the split `wasm-build`, the `go build`/`go test` inside `go-mirror`, and
provenance extended to the nupkg, the jar and the C ABI archives.

Each is built so that failing **blocks** rather than half-publishes — the gate
sits before the first irreversible step rather than after it, and refuses to
open unless this exact commit has a green `ci.yml` and nothing red. That is the
argument for merging it, not against; but it is worth naming before the tag
rather than after.

## After merge

Note the merge SHA. The tag is set on that SHA explicitly —
`git tag -s v0.1.1 <merge-sha>` — because `git tag` without a ref captures the
local `HEAD`, which is not necessarily the merge commit. **Only after explicit
go-ahead.**
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant