Add a dark-mode star-history chart under the README footer thank-you line (all existing badges kept), and make sync-about also patch the indicator count into wickra-docs .vitepress/config.ts.
## Problem
On every indicator PR the `sync-about` workflow found `docs/README.md` lagging `lib.rs` (the wiring only bumped `README.md`) and pushed a `wickra-bot` *"sync indicator count"* commit onto the PR head. That push uses `GITHUB_TOKEN`, which **triggers no workflows**, so it moved the PR head onto a commit with no CI run — and the **Codecov patch status** (keyed to the PR head sha) stopped surfacing on the PR.
## Fix
- The indicator wiring (`ScriptHelpers/_common.py` `wire_readme_counter`) now bumps **both** `README.md` and `docs/README.md` in the author's code commit, so the counter is already correct when CI runs.
- This workflow's PR flow is reduced to a **read-only check** that fails loud (fork and same-repo PRs alike) if either counter is stale, and **never pushes**.
- The `GITHUB_TOKEN` job permission drops from `contents: write` back to `read` (OpenSSF Scorecard: Token-Permissions). The removed `ctx` step + push steps are gone.
- The `main`/tag outward syncs (About description, docs/webpage/wiki/org) are **unchanged** — they use the `ABOUT_SYNC_TOKEN` PAT, not `GITHUB_TOKEN`.
## Effect
Indicator PRs keep their head on the code commit → the Codecov patch status surfaces again. No functional change to merged-main state (the counts still land, now inside the squash-merged code commit).
* fix: keep docs/README indicator count in sync-about
The docs/README.md pointer prose names the indicator count
("**N indicators**") but was never part of the sync-about counter
pipeline, so it drifted to 214 while the real count (lib.rs) is 249.
Add docs/README.md to the PR-flow gate check, the patch sed, and the
fix-up commit so future count changes keep it in sync, and correct the
current stale value to 249.
* docs: fix stale Wiki reference in CONTRIBUTING layout table
The project-layout table still described docs/ as a "Pointer to the
project Wiki" even though the wiki was retired and the docs moved to
docs.wickra.org (wickra-lib/wickra-docs). Align the row with the
already-correct doc-site section further down the same file.
* ci: fix webpage count sync crashing on removed public/hero.svg
The webpage indicator-count sync sed'd index.md, .vitepress/config.ts and
public/hero.svg, but hero.svg was removed from wickra-lib/webpage (the count is
now baked into og-banner.webp at build time from index.md). Under 'bash -e' the
missing file made sed exit 2 before the commit/push, so the count never reached
the webpage repo and its OG banner stayed stale — masked green by the step's
continue-on-error. Drops public/hero.svg from the sed and git add; index.md and
.vitepress/config.ts (both still carry the count) remain.
* docs: point README banner at the self-updating org profile image
Switches the top README banner from https://wickra.org/og-banner.webp (baked at
webpage deploy time) to the org profile banner that wickra-lib/.github's
banner.yml regenerates from the indicator count on every sync
(raw.githubusercontent.com/wickra-lib/.github/main/profile/wickra-banner.webp).
The ?v=227 query busts GitHub's Camo image cache; the next commit teaches
sync-about to bump it with the count.
* ci: bump README banner cache-buster alongside the indicator count
Extends the PR-head README counter patch to also rewrite wickra-banner.webp?v=N
to the current count. The banner now points at the org profile image, whose
content changes when .github/banner.yml regenerates it; bumping the ?v query
busts GitHub's Camo cache so the README shows the new banner immediately. Rides
in the existing count-sync commit, so no extra commit lands on main.
* docs: changelog entry for self-updating README banner and sync fix
* docs(readme): surface the documentation site (docs.wickra.org)
The README never linked the canonical docs at docs.wickra.org — visitors had
no path from the repo to the per-indicator deep dives, quickstarts, and
guides. Add a docs badge, a Documentation section mirroring the binding
READMEs and docs/README.md, and an Indicators-Overview link in the indicator
section.
* ci(sync-about): keep the wiki pointer page's indicator count in sync
The GitHub wiki was collapsed to a single Home.md that points at
docs.wickra.org but still names the indicator count ('… for all N indicators').
Add a count-sync step mirroring the docs/webpage steps — clone wickra.wiki into
its own dir, sed Home.md, commit as wickra-bot, push — with the same
continue-on-error soft-skip so a missing PAT scope never fails the run.
* ci(sync-about): fix docs version-sync clone collision + webpage npm race
Two real release-time bugs surfaced by the v0.4.0 release, where the docs
"Published versions" table never updated and the marketing-site Cloudflare
build failed:
1. docs version sync never ran. The "Sync docs version (wickra-docs)" step
cloned into a directory literally named `docs`, but on a tag push the job
checks out the wickra repo at the workspace root, which already contains a
top-level `docs/` directory. `git clone … docs` therefore failed with
"destination path 'docs' already exists", silenced by `2>/dev/null` and
misreported as a missing-token warning, so the docs version table stayed at
the previous release. Clone into `docs-ver` instead (mirrors the `docs-count`
dir the count step already uses); it collides with nothing in the repo.
2. webpage build broke on a version race. The "Sync webpage version" step bumps
package.json's `wickra-wasm` pin to the released version and pushes
immediately, but release.yml publishes wickra-wasm to npm in parallel on the
same tag and finishes minutes later. Cloudflare's `npm clean-install` then
hit `ETARGET: No matching version found for wickra-wasm@^0.4.0`. Poll npm for
wickra-wasm@<version> (up to ~15 min) before committing; if it never appears
the step skips with a warning rather than pushing a build-breaking commit.
Both steps were designed to mirror each other across docs/webpage; these fixes
restore that symmetry so every release self-heals both sites.
* ci(sync-about): regenerate webpage package-lock on version bump
Third v0.4.0 release-sync defect: the webpage version step seds package.json's
wickra-wasm pin but never touched package-lock.json, so even after wickra-wasm
went live on npm the Cloudflare build still failed with
`npm ci` EUSAGE: "lock file's wickra-wasm@0.3.1 does not satisfy
wickra-wasm@0.4.0".
After the package.json sed, run `npm install --package-lock-only` so the lockfile
(version + resolved + integrity) matches the new pin; commit package-lock.json
alongside package.json. The earlier npm-wait already guarantees the version is
resolvable. Guarded: if the regen fails the step skips the whole commit rather
than push a package.json/lock mismatch.
The live site was unblocked out-of-band by a matching lockfile commit on the
webpage repo; this makes it self-heal on every future release.
The auto-injected GITHUB_TOKEN defaulted to write-all in ci.yml, bench.yml
and release.yml (no top-level permissions block), and codeql.yml declared
its scopes only at job level. Add a top-level `permissions: contents: read`
to all four so the token starts read-only and only the jobs that genuinely
write through it raise the scope:
- release.yml: github-release keeps contents: write; node-/wasm-publish and
attestations keep their id-token / attestations: write blocks. The
cargo/python/node publish jobs push to crates.io/PyPI/npm via their own
registry secrets, not the GITHUB_TOKEN, so read-only is correct for them.
- codeql.yml: analyze keeps security-events: write (job level).
- ci.yml / bench.yml: no job writes back to the repo (coverage uploads via
CODECOV_TOKEN; bench only uploads an artifact), so no job override is needed.
sync-about.yml already had a top-level block but at contents: write; demote
the top level to read and move contents: write down to the single `sync` job
(the PR-head counter push is the only GITHUB_TOKEN write). The cross-repo
About/docs/webpage/org writes are unaffected — they run through the
fine-grained ABOUT_SYNC_TOKEN, which the permissions key does not govern.
Raises OpenSSF Scorecard Token-Permissions from 0 toward 10.
* ci(sync-about): auto-sync the published version to wickra-docs on release
* ci(sync-about): retarget indicator-count sync from wiki to wickra-docs + point About homepage at docs.wickra.org (P8.3)
* ci(sync-about): self-update the marketing site (webpage) count + version (P12.1)
* ci(sync-about): auto-sync the published version to wickra-docs on release
* ci(sync-about): retarget indicator-count sync from wiki to wickra-docs + point About homepage at docs.wickra.org (P8.3)
Extend the count-sync workflow to drive three more surfaces from the same
single count, so the org page never drifts again:
- Repo About **homepage** URL — enforced unconditionally via
`gh repo edit --homepage` in the existing About step (fixes the stale
kingchenc URL and self-heals). Uses the same Administration-write
permission as --description, so NO extra token scope.
- Org **profile README** count (wickra-lib/.github, profile/README.md) —
clone + sed + bot commit/push, same pattern as the Sync Wiki step.
- Org **description** field ('… N indicators, install-free.') — gh api PATCH.
The two org steps need ABOUT_SYNC_TOKEN scope the main-repo syncs do not
(write on wickra-lib/.github; admin:org for the description PATCH). Both are
written to soft-skip with a ::warning:: and continue-on-error, so the run
stays green until the scope is granted — then they sync with no further
change. Homepage swap-point to a docs domain is a one-line change.
Refs findings P9 / P10.
* chore(sync-about): count public indicator types, not module files
The sync-about workflow counted `mod xxx;` lines in
crates/wickra-core/src/indicators/mod.rs to derive the indicator count
that gets propagated to README, the GitHub About description, and the
wiki. That under-reported by one because `vwap.rs` exports two public
types — `Vwap` (cumulative) and `RollingVwap` (finite window) — from
the same module. The bindings reach both, so users see 214 indicators
even though there are only 213 source files.
Fix the count by parsing the canonical `pub use indicators::{ ... }`
block in lib.rs, dropping the `FAMILIES` constant and any `*Output`
companion structs, and counting the remaining public types. Pure-shell
implementation so the workflow doesn't grow a python dependency.
Sync README to the corrected count (213 -> 214) in the same commit so
the PR validates cleanly through the workflow's PR-flow.
* docs(bindings): sync per-binding READMEs and docs/ pointer to 214 / 16
The bindings/{node,python,wasm}/README.md files (which ship to
npm / PyPI / npm again) and docs/README.md (the pointer to the
wiki) all carried the stale '71 streaming-first indicators across
eight families' header from before the family expansion. Pull the
canonical 16-family table out of the main README into all three
binding READMEs and update docs/README.md to list every family by
name, so a user landing on PyPI / npm sees the current catalogue
shape.
Previously the workflow patched README.md on main after every push,
producing an unsigned 'chore: sync indicator count' commit per merge.
Now the README counter is kept in sync on the PR side instead: on
every pull_request event, the workflow checks out the PR's head ref,
compares grep -c '^mod ' to the README counter, and if they differ,
pushes a fix-up commit back onto the PR branch using the default
GITHUB_TOKEN.
When the PR is squash-merged, that fix-up commit is folded into the
single web-flow-signed merge commit on main — so main's history never
shows a separate bot commit. About description and Wiki sync still
run on push to main / v* tags via the existing PAT, since both reach
outside the main repo (Administration:write and the .wiki repo).
For PRs from forks the workflow cannot push back; it emits a hard
::error:: pointing at README.md so the contributor can fix the
counter manually.
Pushes via GITHUB_TOKEN do not re-trigger downstream workflows
(GitHub's anti-recursion policy), so the fix-up commit costs zero
extra CI minutes — only sync-about itself re-runs on the next
synchronize event and no-ops once the counter matches.
site/ is local-only (listed in .git/info/exclude), so the sed call in
the Patch step aborted the workflow on every push to main with
"sed: can't read site/index.md: No such file or directory". That kept
the README counter from being committed and skipped the wiki sync.
Patches README only now. site/ stays out of CI until the marketing
site is promoted.
Counts `mod xxx;` declarations in crates/wickra-core/src/indicators/mod.rs
on every push to main, every PR, and every v* tag push. On non-PR runs
it syncs the count into:
- GitHub repo About description (via `gh repo edit`)
- README.md + site/index.md (commit with [skip ci] back to main)
- Wiki: Home.md, FAQ.md, Streaming-vs-Batch.md
Requires a `ABOUT_SYNC_TOKEN` secret (classic PAT with `repo` scope, or
fine-grained PAT with Administration+Contents write on the wickra repo).
PR runs are read-only: count is logged but nothing is mutated, so forks
cannot trigger writes.