ci(release): make every version tag-driven and fix the dev channel - #485
Conversation
Release-readiness pass ahead of #149. Every component now derives its version from the tag it was built at, so cutting a release is one tag and nothing else -- no bump commit, which the main ruleset forbids pushing anyway. Release path - goreleaser: prerelease: auto (an alpha tag would have shipped as a stable GitHub Release), channel-scoped moving image tag (an rc would have taken :latest from a shipped stable), lowercase project_name, .zip on Windows, no CHANGELOG in archives - both release paths pin the generated-notes anchor to their own tag family; without it two tags on one commit yield empty notes - the SDK release step no longer fails when a release already exists - release.yml verifies its own attestations before finishing Tag naming - sdk-v* -> clients/ts/v*; Go requires clients/go/vX.Y.Z for a subdirectory module (#434), so every client shares that shape - publish-npm stamps package.json from the tag instead of validating it Fixes - #431: retire triage.yml (GitHub Models retired 2026-07-30, 410) - #475: dev versions ordered by a numeric UTC stamp, based at 0.0.1 - -X main.BuildTime never applied (non-constant initializer) - go install builds reported themselves as "dev" - dependabot could not see .github/actions/setup-env Tooling - make release-server / release-sdk-ts / release-sdk-go - CHANGELOG merged from 35 duplicate bands into 5 sections, stamped 0.1.0 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
Round 2 of the pre-push gate. Three [MUST] from the code review and seven from the docs review, all reproduced before fixing. Code - .goreleaser.yaml: changelog.disable templated on WAVEHOUSE_DEV. The changelog pipe is NOT skipped by release.disable (verified), so github-native would have made publish-dev POST generate-notes on every push to main -- contents:write on a contents:read workflow. Snapshot validation could never have caught it. - .goreleaser.yaml: git.ignore_tags ["clients/*"] so GoReleaser's own tag detection is family-aware. Fixes the case the explicit env var missed and makes release.yml's GORELEASER_PREVIOUS_TAG step redundant -- 26 lines removed. - publish-npm.yml: previous SDK tag now selected by walking history from the tag's parent, not by version-sorting. Sorting picked a tag AHEAD of the one being released (releasing v0.1.0 with v0.2.0 present chose v0.2.0) and ranked prereleases above their release. Needs commit history, so fetch-tags becomes fetch-depth: 0. - publish-npm.yml: first-release note no longer links a same-version server release that may not exist. - release.sh: the CI-green preflight silently no-opped. Commits carry 30-46 check runs against a per_page=30 default, so the aggregator was often off-page and the script waved the release through with a message that read like an API hiccup. Now check_name=CI&per_page=100, all runs must be green (a commit has two), in-progress reported as such. - Makefile: git describe --match 'v[0-9]*'. Without it, once clients/ts/v0.1.0 exists every make build stamps the SDK's version into the server binary. Introduced by this release's tag rename. Docs - api.md: /version has three behaviors now, not two -- the doc still said un-ldflagged builds report dev/unknown. - deployment.md: replaced the raw git-tag procedure with make release-server. - development.md: Dependabot is four configs not three; Go SDK marked pending #434; restored the still-true `latest`-points-at-a-dev-snapshot caution; publish list labelled per component; dropped the stale "three tiers" claim; added the Release group to the targets table; noted keep-existing is GoReleaser's default, not our config. - CHANGELOG: this commit's own entries named the sdk-v* family the same commit renamed away; recorded the ruleset change and the date caveat. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
# Conflicts: # CHANGELOG.md
Round 3. No [MUST] from the code review this time; 1 [MUST] from docs.
Licensing
- .goreleaser.yaml: ship NOTICE in the archives. Apache-2.0 4(d) makes
every redistributor inherit an attribution obligation they cannot meet
from a tarball carrying only LICENSE. Never included by goreleaser's
default glob either, but narrowing that glob was the moment to decide.
Correctness
- release.sh: roll back the local tag when the push is rejected. Tag
creation is admin-only, so a non-admin got a rejected push and a stray
tag, and the next attempt then died with "already exists -- pick the
next version" when nothing had been published and the version was free.
- New scripts/ci/release-channel.test.sh, wired into verify-parallel.
Three publishers depend on that rule and it had no test; covers every
tag family, the build-metadata strip (v1.0.0+alpha is NOT a
prerelease), and the fail-closed rejections.
Docs
- api.md: a release binary reports 1.2.3, `make build` reports v1.2.3 --
goreleaser injects {{ .Version }}, which strips the v, while git
describe keeps it. The page showed "v1.2.3" and lumped both paths into
one table row while row 3 already said "without its leading v".
- development.md: provenance bullet was labelled Both but described only
the server; the SDK gets npm provenance and no verify step. Also
PROJECT_BOARD_TOKEN still exists as a repo secret -- reworded to
"unused, worth deleting" rather than claiming it is gone.
- sdk/index.mdx + README.md: the bare CDN URL and :latest do not track a
release today, which is exactly what the restored caution says.
- publish-dev.yml: header predated the channel scheme.
Also merges origin/main (#479, /v1/ops). CHANGELOG conflicted -- this
branch regrouped entries while #479 rewrote them in place -- resolved by
taking main's entry text into this branch's structure, verified: all 326
main entries and all 19 branch entries present, no dupes, none invented.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
Both round-3 reviewers landed on the same finding from opposite sides. #479 merged guidance into this tree stating plainly that `--repo` alone accepts an attestation from ANY workflow in the repo, and this branch then added two verify call sites using exactly that weaker form. - release.yml's self-verification now pins --signer-workflow to itself. Without it the step could pass on provenance minted by some other workflow, which is most of what it was added to prove. - development.md's consumer snippet taught the weaker command; README's example additionally targeted :latest, which does not exist yet and sits five lines under this branch's own note saying so -- switched to :dev with publish-dev.yml as the signer. - deployment.md's Registry section was still the canonical "which tags exist" list and never learned about the channel pointers. - clients/ts/README.md was a third copy of the bare-CDN-URL claim corrected twice already; it is the npm package page, so it is the highest-traffic place for the caveat. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
Round-4 docs review, both [SHOULD]. - clients/ts/README.md: my previous edit spliced badly -- "pin for production" landed twice in consecutive sentences, and "Otherwise" attached to the wrong antecedent, reading as "if you don't pin, it serves the latest release". Rewritten as one before/after pair, the way sdk/index.mdx already folds the two cases. This is the npm package page, so it is the highest-traffic copy of the caveat. - AGENTS.md: claimed PROJECT_BOARD_TOKEN was removed with triage.yml. A branch cannot delete a repo secret and it still exists; development.md already said so correctly. Telling the agent-facing source of truth that a PAT is already gone is how an unused credential survives. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
Round-5 review findings. release.yml categorization was wrong in a way that would have shown up in the very first release's notes. `github_actions` is applied by actions/labeler to anything touching .github/workflows/** or .github/actions/**, so it marks our own CI PRs, not just Dependabot's -- excluding it from the catch-all filed every hand-written CI PR under "Dependencies" (#446 carries github_actions with no dependencies label). Dropping it from the exclude instead is not a fix either: Dependabot's action bumps carry github_actions and NOT dependencies (#480, #412, #341), so that empties the category. Only the author axis separates them. Our CI work now gets its own "CI & build" section, and the Dependabot exclude lists both spellings since the docs use the bare handle while the API reports `dependabot[bot]`. Routing simulated against real PRs: #446 -> CI & build, #480 -> Dependencies, feature/bug/breaking/security unchanged. Docs: `latest` tracks the newest STABLE release, not the newest published one -- my previous wording contradicted this branch's own release-channel.sh, under which a prerelease publishes to alpha/beta/rc/next and never moves `latest`. Corrected in clients/ts/README.md and mirrored into sdk/index.mdx. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
…pies Round-6 findings. release.yml: the author exclude was on the catch-all and CI category but not on Documentation -- and actions/labeler maps docs/** to `documentation`, while the npm Dependabot config points at the workspace root, so every npm bump touches docs/package.json and gets labelled. 13 of the last 30 Dependabot PRs carry it (#482, #439, #426, #423, #420), so Documentation would have rendered as a wall of `deps: bump the npm-deps group` in the first release's notes. My earlier simulation only exercised action bumps, which is why it missed this. Recorded the generalizable invariant in the file: every category keyed on a label actions/labeler applies BY PATH must carry the author exclude, because the final catch-all is what collects Dependabot. `security` deliberately does not, so a hand-labelled Dependabot security fix still sorts to the top. Re-simulated across all three bump populations plus human PRs; nothing drops. Docs: - development.md carried the CANONICAL `latest` caution that both corrected copies deep-link to, and it still said "the first clients/ts/v* release" -- which a prerelease satisfies without moving `latest`. Its own next sentence already said "stable". - The caveat lived only under the CDN headings, while the primary install path (`pnpm add` / `npm install`) had none; Starlight shows one tab at a time and defaults to pnpm, so readers never saw it. Those are the commands that fetch the June 4 bootstrap build today. Hoisted a caution under each Installation heading. - development.md's release-notes bullet gained the outcome (the CI & build section) and dropped `dependencies` from the labels said to drive grouping -- it routes nothing now. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
Round-7 code review. The "CI & build" category added last commit was dead on arrival: Documentation sat above it, first match wins, and our CI PRs carry BOTH labels because AGENTS.md requires a doc update with every change. 7 of the last 9 (#334, #329, #312, #311, #310, #308, #275) carry documentation alongside github_actions -- so the new section would have stayed empty while Documentation filled with `ci:` PRs, which is the same noise the Dependabot exclude exists to prevent, just with the human population. Reordered. Cost is a docs PR that also edits a workflow filing under CI & build: one instance in recent history (#187) against seven the other way. Also widened the invariant. It was scoped to "labels actions/labeler applies by path", but labeler is not the only source of Dependabot labels -- Dependabot applies its own ecosystem labels, and `javascript` (on #439, #416, #342) is not in labeler.yml at all. A future category keyed on it would satisfy the old wording and still intercept every npm bump. Now scoped to any label a Dependabot PR can carry, with both sources enumerated. CHANGELOG and development.md updated to match; both previously claimed the CI section worked, which was only true after the reorder. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
Round-8 review, found independently by both reviewers. The invariant was widened in .github/release.yml last commit but not in CHANGELOG.md or development.md, so the same rule was recorded at two different scopes -- and the previous commit message claimed both were updated when only the ordering sentence was. `javascript` is the case that motivates it: Dependabot applies it (#439, #416, #342), it is absent from labeler.yml, and a future category keyed on it satisfies the narrow "path-applied label" wording while still intercepting every npm bump. Both copies now say "any label a Dependabot PR can carry" and name the two sources. Also corrected the numbers recorded beside the ordering decision, which were wrong in both directions and would have been copied forward. Real data, last 12 human PRs carrying github_actions: 10 also carry documentation, not "7 of the last 9" -- and the cost side listed one instance (#187) when #290 and #277 sit in the same window. Restated as an explicit trade with both sides counted (~7 CI PRs rescued vs ~2-4 docs PRs misfiled) and a note to re-check the balance before copying the decision forward. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
Round-9 review. Both findings are the same defect in different places: a number recorded beside a decision that measures the wrong population. - "13 of the last 30 Dependabot PRs carry documentation" counted PRs regardless of state, but release notes only ever list MERGED PRs, and npm group bumps are routinely superseded before merge. Real figure: 3 of the 23 merged to date (#439, #416, #342). Four of the five PRs I cited as evidence could never appear in any release body -- #482 is open, #426/#423/#420 are closed unmerged. The exclude is still right, but the rationale overstated the impact ~4x. - The ordering statistic corrected in release.yml last commit was left stale in CHANGELOG.md ("7 of the last 9", wrong at any window -- 8 of 9, or 10 of 12). Rather than fix the second copy, the CHANGELOG now carries no count and points at release.yml as the one copy kept current; this number has drifted between copies twice now. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
|
Warning Review limit reached
Next review available in: 34 minutes Limit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits within each organization. For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe change adds release-channel validation and release commands, updates server, SDK, container, and provenance workflows, adds Go build metadata fallback, revises release documentation, and removes automated issue triage and board configuration. ChangesRelease delivery
Repository automation
Estimated code review effort: 4 (Complex) | ~60 minutes Merge Risk: 🟠 High · up to This PR changes release, package, image-channel, and build-version behavior, but unresolved issues could publish incorrect channels or stale development packages, leave excessive write access in a release job, or prevent recovery after a partial release. Those risks can affect consumers and release integrity, so the PR is not ready to merge without fixes or explicit owner acceptance. Sequence Diagram(s)sequenceDiagram
participant Maintainer
participant Makefile
participant ReleaseScript
participant ReleaseChannel
participant GitHubActions
participant GoReleaser
participant Registry
Maintainer->>Makefile: provide VERSION and release target
Makefile->>ReleaseScript: invoke component release
ReleaseScript->>ReleaseChannel: validate version and resolve channel
ReleaseScript->>GitHubActions: create annotated release tag
GitHubActions->>GoReleaser: build with WAVEHOUSE_CHANNEL
GoReleaser->>Registry: publish channel-specific image and archives
GitHubActions->>Registry: verify digests and attestations
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Code Coverage OverviewLanguages: Go GoThe overall line coverage in commit 98d3bca in the Show a line coverage summary of the most impacted files.
Updated |
|
📚 Docs preview is live → https://8e356355-wavehouse-docs.wave-rf.workers.dev
|
There was a problem hiding this comment.
Actionable comments posted: 8
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 90854e7c-53f0-44bc-bd25-fcffee5e96c4
📒 Files selected for processing (23)
.github/actions/setup-env/action.yml.github/board-config.env.github/dependabot.yml.github/release.yml.github/workflows/publish-dev.yml.github/workflows/publish-npm.yml.github/workflows/release.yml.github/workflows/triage.yml.gitignore.goreleaser.yamlAGENTS.mdCHANGELOG.mdMakefileREADME.mdclients/ts/README.mdcmd/wavehouse/main.godocs/src/content/docs/api.mddocs/src/content/docs/deployment.mddocs/src/content/docs/development.mddocs/src/content/docs/sdk/index.mdxscripts/ci/release-channel.shscripts/ci/release-channel.test.shscripts/release.sh
💤 Files with no reviewable changes (3)
- .gitignore
- .github/workflows/triage.yml
- .github/board-config.env
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: Docs build
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
Comment the why, not the what.
Files:
docs/src/content/docs/sdk/index.mdxREADME.mdclients/ts/README.mdAGENTS.mddocs/src/content/docs/deployment.mddocs/src/content/docs/api.mddocs/src/content/docs/development.md
**/*
📄 CodeRabbit inference engine (AGENTS.md)
Every code change should update the corresponding docs in the same PR. A code change without its doc update is incomplete.
Files:
docs/src/content/docs/sdk/index.mdxREADME.mdclients/ts/README.mdscripts/ci/release-channel.shAGENTS.mddocs/src/content/docs/deployment.mdscripts/release.shcmd/wavehouse/main.goscripts/ci/release-channel.test.shdocs/src/content/docs/api.mddocs/src/content/docs/development.mdMakefile
🧠 Learnings (5)
📚 Learning: 2026-08-11T11:20:19.556Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 446
File: .github/workflows/publish-dev.yml:0-0
Timestamp: 2026-08-11T11:20:19.556Z
Learning: When reviewing GitHub Actions workflows that use `actions/cache` or `actions/setup-go` dependency caching, account for exact-key behavior: a cache archive is saved only after an exact-key miss. A cache key based on `go.sum` creates a new archive when dependencies change, while runs with an existing exact key restore that archive and skip the post-job save.
Applied to files:
.github/workflows/publish-dev.yml.github/workflows/release.yml.github/workflows/publish-npm.yml
📚 Learning: 2026-08-13T12:17:52.620Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 470
File: docs/src/content/docs/reverse-proxy.mdx:137-144
Timestamp: 2026-08-13T12:17:52.620Z
Learning: For Wave-RF/WaveHouse documentation, verify claims about implementation control flow against the authoritative implementation source (for example, internal/auth/auth.go) rather than relying solely on docs/** content. Documentation may lag behind or paraphrase behavior, so control-flow claims should be confirmed in source code.
Applied to files:
docs/src/content/docs/sdk/index.mdx
📚 Learning: 2026-06-10T15:01:09.027Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 312
File: docs/src/content/docs/development.md:0-0
Timestamp: 2026-06-10T15:01:09.027Z
Learning: In this repo’s Markdown review (all .md files), do not flag capitalization/style issues for literal paths starting with ".github/" (or any substring that is a path beginning with ".github/"). Treat ".github" as the correct lowercase dotfile directory name, even when it appears inside prose or code spans; automated checks such as LanguageTool’s "(GITHUB)" rule commonly produce false positives for this literal filesystem path.
Applied to files:
README.mdclients/ts/README.mdAGENTS.mddocs/src/content/docs/deployment.mddocs/src/content/docs/api.mddocs/src/content/docs/development.md
📚 Learning: 2026-07-07T12:38:12.052Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 378
File: internal/auth/auth.go:119-132
Timestamp: 2026-07-07T12:38:12.052Z
Learning: In this repo, do not add or recommend logging/tracing client IP addresses using naive or untrusted sources (e.g., `r.RemoteAddr` or directly trusting/deriving `X-Forwarded-For`) anywhere in the Go codebase. `middleware.RealIP` was removed due to IP-spoofing risks, and proper trusted-proxy-aware client-IP handling is intentionally deferred to issue `#333`. During code review, if proposed changes would record client IPs (including in audit paths such as `internal/auth/auth.go`), reject/redirect until `#333` lands with correct trusted-proxy configuration and safeguards.
Applied to files:
cmd/wavehouse/main.go
📚 Learning: 2026-08-11T21:55:53.726Z
Learnt from: jfwoods
Repo: Wave-RF/WaveHouse PR: 434
File: clients/go/stream_test.go:159-176
Timestamp: 2026-08-11T21:55:53.726Z
Learning: For Go files in this repository, do not report direct type assertions solely because the `forcetypeassert` rule is commented out in `.golangci.yml`. Only flag a type assertion when there is an independent correctness, safety, or maintainability issue.
Applied to files:
cmd/wavehouse/main.go
🪛 LanguageTool
clients/ts/README.md
[style] ~47-~47: Consider using a more formal replacement.
Context: ...ouse.dev/development#the-dev-channel)); after that it tracks the newest stable release — a...
(AFTER_THAT)
AGENTS.md
[uncategorized] ~375-~375: The official name of this software platform is spelled with a capital “H”.
Context: ...ge, and add the path → label mapping to .github/labeler.yml so PRs touching the packag...
(GITHUB)
[uncategorized] ~430-~430: The official name of this software platform is spelled with a capital “H”.
Context: ...issue event and was removed, along with .github/board-config.env ([#431](https://githu...
(GITHUB)
docs/src/content/docs/development.md
[uncategorized] ~560-~560: The official name of this software platform is spelled with a capital “H”.
Context: ...Dependabot Dependabot is configured in .github/dependabot.yml to open weekly grouped ...
(GITHUB)
[uncategorized] ~564-~564: The official name of this software platform is spelled with a capital “H”.
Context: ...mmit prefix ci: - GitHub Actions (/.github/actions/setup-env) — the same, for the...
(GITHUB)
[uncategorized] ~567-~567: The official name of this software platform is spelled with a capital “H”.
Context: ...not* mean "the whole repo" — it means .github/workflows/ plus an action.yml in the...
(GITHUB)
[uncategorized] ~567-~567: The official name of this software platform is spelled with a capital “H”.
Context: ...them. Adding a composite action under .github/actions/ means adding an entry here;...
(GITHUB)
[typographical] ~584-~584: To join two clauses or introduce examples, consider using an em dash.
Context: ..., so open a PR renaming that heading to ## [X.Y.Z] - YYYY-MM-DD and adding the matching link...
(DASH_RULE)
[style] ~584-~584: ‘at the foot of’ might be wordy. Consider a shorter alternative.
Context: ... and adding the matching link reference at the foot of the file. Nothing in the release pipeli...
(EN_WORDINESS_PREMIUM_AT_THE_FOOT_OF)
[style] ~612-~612: Consider using the typographical ellipsis character here instead.
Context: ...f the ref name, so v* never matches a clients/... tag — which is what keeps a client rel...
(ELLIPSIS)
[typographical] ~616-~616: Consider using an em dash in dialogues and enumerations.
Context: - Server — a GitHub Release with ...
(DASH_RULE)
[uncategorized] ~616-~616: Do not mix variants of the same word (‘pre-release’ and ‘prerelease’) within a single text.
Context: ...v0.1.0-alpha.1) is marked as a GitHub pre-release, so it never takes the "Latest release"...
(EN_WORD_COHERENCY)
[uncategorized] ~617-~617: The official name of this software platform is spelled with a capital “H”.
Context: ... grouped into the categories defined in [.github/release.yml](https://github.com/Wave-R...
(GITHUB)
[uncategorized] ~617-~617: The official name of this software platform is spelled with a capital “H”.
Context: ...ease.yml). Grouping is by PR label: github_actions / documentation are applied ...
(GITHUB)
[style] ~617-~617: Since ownership is already implied, this phrasing may be redundant.
Context: ...github_actions, documentation` — mark our own PRs too; our CI work gets its own "CI &...
(PRP_OWN)
[uncategorized] ~617-~617: The official name of this software platform is spelled with a capital “H”.
Context: ...lf (dependencies, javascript, go, github_actions; javascript is in neither `l...
(GITHUB)
[style] ~619-~619: Since ownership is already implied, this phrasing may be redundant.
Context: .../beta/rc/next` (prerelease), plus its own GitHub Release. - Server — **build-...
(PRP_OWN)
[style] ~620-~620: Since ownership is already implied, this phrasing may be redundant.
Context: ...de it in GHCR. The release job verifies its own attestations before finishing, so a rel...
(PRP_OWN)
[style] ~638-~638: To elevate your writing, consider using more formal language here.
Context: ...wo things the make targets do for you and the UI does not: none of the preflight ...
(AND_WHEREAS)
[uncategorized] ~730-~730: The official name of this software platform is spelled with a capital “H”.
Context: ...manual*. There is no triage workflow: .github/workflows/triage.yml classified new an...
(GITHUB)
[uncategorized] ~735-~735: The official name of this software platform is spelled with a capital “H”.
Context: ...y hand on the board's Priority field. .github/board-config.env existed only for that...
(GITHUB)
[uncategorized] ~747-~747: The official name of this software platform is spelled with a capital “H”.
Context: ...ion. 2. Add the path → label mapping to .github/labeler.yml so PRs touching the new pa...
(GITHUB)
🪛 zizmor (1.29.0)
.github/workflows/publish-npm.yml
[warning] 162-168: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🔇 Additional comments (14)
cmd/wavehouse/main.go (1)
13-13: LGTM!Also applies to: 33-47
docs/src/content/docs/api.md (1)
159-177: LGTM!Also applies to: 179-181
README.md (1)
95-109: LGTM!docs/src/content/docs/deployment.md (1)
84-86: LGTM!Also applies to: 115-121
docs/src/content/docs/development.md (1)
521-524: LGTM!Also applies to: 560-571, 573-619, 621-656, 660-660, 730-736, 746-749
docs/src/content/docs/sdk/index.mdx (1)
12-14: LGTM!Also applies to: 62-67
clients/ts/README.md (1)
11-12: LGTM!Also applies to: 47-47
.github/workflows/publish-dev.yml (1)
14-18: 🗄️ Data Integrity & IntegrationNo change needed. The comment correctly distinguishes tagged releases from the development workflow, which sets
WAVEHOUSE_DEV=1and publishes:devand:dev-<sha>.> Likely an incorrect or invalid review comment.AGENTS.md (2)
375-375: LGTM!
430-430: LGTM!.github/release.yml (2)
1-51: LGTM!
52-104: 📐 Maintainability & Code QualityNo documentation update is needed. This change updates comments only; the release-note categories and Dependabot routing are unchanged, and the existing documentation covers them.
> Likely an incorrect or invalid review comment..github/actions/setup-env/action.yml (1)
250-250: LGTM!.github/dependabot.yml (1)
16-25: LGTM!Also applies to: 40-50
CodeRabbit review on #485. Six of its eight findings were valid; the seventh is wrong and the eighth is out of scope (see below). - release-channel.sh accepted invalid semver (v01.2.3, v1.2.3-01, v1.2.3-alpha..1) and matched channels by substring, so v1.2.3-alphafoo resolved to `alpha` and v1.2.3-preview-rc.1 to `rc` -- pointing a channel consumers install from at an unrelated release. Now full SemVer 2.0.0 grammar, and the first prerelease identifier matched exactly. Both classes pinned by tests. - publish-npm hashed only dist, so a change to exports/files/bin/engines or the bundled README/LICENSE left the hash identical and suppressed a publish that changed the package. Now hashes what npm pack would ship. - publish-npm could not be retried after a post-publish failure: --allow-same-version covers `npm version`, not `npm publish`. Skips when already published. - publish-npm's release checkout persisted git credentials while holding contents: write, with npm lifecycle scripts running before the release step. persist-credentials: false. - buildInfoFallback was gated on Version alone, so a build stamping only -X main.GitCommit had it overwritten. Each field now gated on its own default. Not applied: - api.md's "go build in a checkout" row is correct as written. CodeRabbit claims Main.Version is "(devel)"; verified twice on Go 1.26.6 that a checkout build reports a real pseudo-version (0.0.0-20260818143712-91ac2be6a98f). "(devel)" appears only without VCS metadata, which the fallback already handles. - pnpm 11.1.3 advisories are real and worse than reported (10 advisories, 8 high, needs >= 11.8.0) but pre-existing and declared in four places plus the lockfile. Filed separately rather than folded into a release-tooling PR. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
Pre-push review of the CodeRabbit fixes. I accepted persist-credentials: false for publish-npm's release job last commit and did not apply the same reasoning to its siblings. release.yml is the more dangerous one: contents+packages+attestations write, running a third-party action, a downloaded goreleaser binary, a full go mod download + 8-target cross-compile, and a Docker build -- any of which could read the token out of .git/config. Audited every checkout in the repo; release.yml, publish-dev.yml, goreleaser-validate.yml and publish-npm's dev job all persisted. None needs authenticated git (goreleaser uses GITHUB_TOKEN, git describe is local, the fetch is done). All four fixed. ci.yml's badge job stays as the one documented exception -- its purpose is to push. Docs sync for the previous commit: widening the dev-channel hash to the full publishable set left every description of it saying "dist", including the workflow's own header, so the docs promised a skip in exactly the case the fix made publish. "dist is the identity" was the misconception that caused the bug, so leaving it in the first paragraph would teach the next reader the broken model. Also documents the channel rule where a maintainer will read it: the pointer comes from the first prerelease identifier matched exactly, so v0.2.0-rc.1 -> :rc but -alpha1 or -preview.1 -> :next. The suffix is typed by hand and the tag is immutable. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
"Every workflow checkout outside ci.yml persisted git credentials" is false -- housekeeping.yml already set persist-credentials: false on main before this branch. The four files listed were right; the headline generalised past them, and the trailing clause implied ci.yml was the only already-compliant workflow. Narrowed to "every release workflow's checkout" and named housekeeping.yml alongside ci.yml as already compliant. This entry's whole subject is the completeness of a security audit, and CHANGELOG.md sits outside the docs-reviewer scope, so it is the record the next auditor reads. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
#490 landed a better fix for the Dependabot composite-action gap than mine, so main's version wins on every shared file: - .github/dependabot.yml: taken wholesale. My two `updates:` entries are two independent Dependabot jobs and a group is scoped to its own job, so they would emit two actions-deps PRs every Monday -- the noise the group comment exists to prevent. main's `directories: [/, ...]` is one job, one PR. main's comment also carries the accuracy fix: actions/cache was uniformly v5.0.5 at every site, a major behind upstream rather than behind a caller. - .github/actions/setup-env/action.yml: taken wholesale. My bumps were a strict subset and stale (cache still v5.0.5, pnpm 11.1.3). - development.md Dependabot section: taken wholesale. My "four update configs" auto-merged silently and is wrong under the directories form -- it is three. main's also documents the typescript major hold (#487). - My CHANGELOG entry describing the two-entry mechanism is dropped; #490's entry on main is the accurate record of the same fix. Kept mine, reconciled by hand: - README's `--signer-workflow` fix -- #490 deliberately avoided it. - persist-credentials: false across the four release workflows. - clients/ts/README.md and sdk/index.mdx: #470 changed streaming from EventSource to fetch. Took its wording, kept my `latest`-is-a-dev- snapshot caveat and the corrected anchor -- main still links #releasing-the-sdk, a section this branch renamed. - CHANGELOG resolved with the same script as the #479 merge: main's entry text into this branch's structure. Verified 331 main entries + 29 branch entries, none lost, none invented, no duplicates. All action pins now match main exactly; no stale pnpm strings remain. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
The README's `gh attestation verify` was the last place still teaching `--repo` alone -- #479 added `--signer-workflow` to SECURITY.md and deployment.md, and 1b2dfc7 fixed the README itself but only reworded the release.yml entry, so the fix shipped without its own changelog line. Kept out of the merge commit deliberately: that commit's message claims the CHANGELOG resolution invented nothing, and hand-writing an entry into it would have made the claim false -- the same overclaim f29dd54 exists to correct, one commit earlier on this branch. The merge now audits as a pure resolution and this rides on top. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
Both stale against what actually ships, found by the pre-push gate. - "Aligned setup-env's action pins" recorded pnpm/action-setup v6.0.8 -> v6.0.9. The merge took main's setup-env wholesale, so the file is now byte-identical to origin/main and carries v6.0.10 -- my entry recorded a state no commit in this release ever produced, and #490's entry immediately below it already covers the same file's same pins with the numbers that shipped. Same reasoning the merge gave for dropping its sibling. - "The SDK release checkout persisted git credentials" was subsumed by the sweep entry two lines above, which even narrates its origin. It still ended "matching ci.yml" -- verbatim the implication f29dd54 was written to remove, and contradicted by the sweep entry now naming housekeeping.yml as also already compliant. A reader also counted two credential incidents where there was one. Its two unique details (the npm-lifecycle threat model, the CodeRabbit attribution) are folded up. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
# Conflicts: # CHANGELOG.md
Three conflicts, all resolved keeping both sides' intent: - Makefile: both branches added a verify leaf -- #489's test-md-rules and this branch's test-release-channel. Kept both. - sdk/index.mdx: #489 relocated the CDN paragraph out of the <Tabs> block and rewrote it, dropping this branch's corrections with it. Took #489's structure and re-applied both: `latest` resolves to a 0.0.0-dev.* snapshot until the first STABLE release (a prerelease publishes to alpha/beta/rc/next and leaves it alone), and the two anchors. #489's prose linked /development#releasing-the-sdk, a section this branch renames -- neither PR's CI could catch that, since the anchor exists on main until this branch lands. Now #cutting-a-release and #the-dev-channel; no reference to the dead anchor survives repo-wide. - CHANGELOG: resolved with the same script as the previous merges (main's entry text into this branch's structure). 336 main entries + 27 branch entries, none lost, none invented, no duplicates. Preamble taken from main, which carries #489's reflow -- its new WH001/no-hard-wrapped-prose rule rejects the old hard-wrapped Keep a Changelog boilerplate. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
Four findings from the pre-push gates, all consequences of the merge. - Makefile: #489 rewrote the verify-parallel comment into an accurate 13-item inventory; adding test-release-channel made it 14 while the comment still said 13 and never named the new leaf. The conflict resolution updated the dependency line and missed the comment three lines above documenting the same list. - CHANGELOG: the restructure entry quoted "35 bands" and "333 top-level entries byte-identical". Both describe a base that has moved twice since. Rather than recount figures that drift on every merge, the entry now states the property qualitatively and says why no number is quoted -- a stale figure beside a "verified" claim is worse than none. This is the fourth stale self-describing count on this branch; the pattern is the number, not the arithmetic. - CHANGELOG: stamp moved to 2026-08-19. #489 merged today and this section covers it, so the 08-18 date was already wrong. - README: `docker pull ...:latest` 404s today and the explanation landed after the code block, so a reader copy-pastes the failure first. Annotated inline. - development.md: the `go install` paragraph describes what a TAGGED release reports, but sat as the last paragraph of "The dev channel", whose subject is what happens between releases. Moved to "What a release publishes", beside the archive and image bullets. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
I had this wrong in the config comment and twice in the PR body: generate-notes accepts configuration_file_path and resolves it from target_commitish, so the routing can be exercised from a branch without the config being on main first. Corrected, with the command that works. Ran it: all 23 merged Dependabot PRs land in Dependencies, zero leak into CI & build (41) or Documentation (54). The author-exclude invariant is now confirmed empirically rather than by reasoning about GitHub's first-match-wins semantics -- and the last open item on the test plan is closed rather than deferred to post-merge. Also: development.md's `make verify` row enumerated the leaves and was one short, still describing the 13-leaf shape after this branch added test-release-channel. Third copy of that list; the Makefile dependency line and its inventory comment were fixed last commit and this one was missed. Since test-classify-paths is named there, the omission read as "the release-channel rule isn't gated" rather than as a shortened list. PR #485's body carried the same drifting figures this branch just removed from the changelog, a superseded stamp date, and a Dependabot bullet describing a fix that arrived via main and is no longer in the delta. Refreshed -- leaving the numbers in the description while removing them from the file would have half-applied the decision. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
cmd/wavehouse/main.go (1)
59-95: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy liftRemove mutable package metadata state.
buildInfoFallbackmutatesVersion,GitCommit, andBuildTimepackage variables. Return aBuildMetadatavalue instead. Pass that value intorunand the version handler explicitly. Keep linker inputs isolated at startup.As per coding guidelines,
**/*.go: “No global state: Dependencies are passed explicitly (constructor injection).”Source: Coding guidelines
README.md (1)
101-109: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick winVerify and deploy the same immutable image digest.
Line 104 verifies the current
:devtarget. A later main-branch build can move:devbefore the user deploys it. Resolve the digest once, verifyoci://...@sha256:..., and deploy that same digest reference. This matches.github/workflows/release.ymlLines 120-177.Proposed documentation change
-gh attestation verify oci://ghcr.io/wave-rf/wavehouse:dev \ +digest="$(docker buildx imagetools inspect ghcr.io/wave-rf/wavehouse:dev --format '{{.Manifest.Digest}}')" +image="ghcr.io/wave-rf/wavehouse@${digest}" +gh attestation verify "oci://${image}" \ --repo Wave-RF/WaveHouse \ --signer-workflow Wave-RF/WaveHouse/.github/workflows/publish-dev.yml +docker pull "${image}"
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 3a2655a4-30c7-43fd-9e71-cf2b61a2572c
📒 Files selected for processing (17)
.github/release.yml.github/workflows/goreleaser-validate.yml.github/workflows/publish-dev.yml.github/workflows/publish-npm.yml.github/workflows/release.ymlAGENTS.mdCHANGELOG.mdMakefileREADME.mdclients/ts/README.mdcmd/wavehouse/main.godocs/src/content/docs/api.mddocs/src/content/docs/deployment.mddocs/src/content/docs/development.mddocs/src/content/docs/sdk/index.mdxscripts/ci/release-channel.shscripts/ci/release-channel.test.sh
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
- GitHub Check: Coverage
- GitHub Check: E2E tests
- GitHub Check: Docs build
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
- Never hard-wrap prose. One paragraph is one line. No wrapping at 72/80 columns, no "semantic linefeeds" splitting a paragraph at sentence boundaries.
Files:
docs/src/content/docs/api.mddocs/src/content/docs/sdk/index.mdxREADME.mdAGENTS.mdclients/ts/README.mddocs/src/content/docs/deployment.mddocs/src/content/docs/development.md
**/*.mdx
📄 CodeRabbit inference engine (AGENTS.md)
- In MDX, leave a blank line between a JSX tag and a code fence.
Files:
docs/src/content/docs/sdk/index.mdx
**/*.go
📄 CodeRabbit inference engine (AGENTS.md)
**/*.go: - Go 1.26, strict formatting (gofumpt, enforced by CI)
- Structured logging with
log/slog(JSON handler)- Error handling: Return errors, don't panic. Wrap with
fmt.Errorf("context: %w", err).- No global state: Dependencies are passed explicitly (constructor injection).
Files:
cmd/wavehouse/main.go
🧠 Learnings (18)
📚 Learning: 2026-08-11T11:20:19.556Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 446
File: .github/workflows/publish-dev.yml:0-0
Timestamp: 2026-08-11T11:20:19.556Z
Learning: When reviewing GitHub Actions workflows that use `actions/cache` or `actions/setup-go` dependency caching, account for exact-key behavior: a cache archive is saved only after an exact-key miss. A cache key based on `go.sum` creates a new archive when dependencies change, while runs with an existing exact key restore that archive and skip the post-job save.
Applied to files:
.github/workflows/goreleaser-validate.yml.github/workflows/publish-dev.yml.github/workflows/release.yml.github/workflows/publish-npm.yml
📚 Learning: 2026-06-10T15:01:09.027Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 312
File: docs/src/content/docs/development.md:0-0
Timestamp: 2026-06-10T15:01:09.027Z
Learning: In this repo’s Markdown review (all .md files), do not flag capitalization/style issues for literal paths starting with ".github/" (or any substring that is a path beginning with ".github/"). Treat ".github" as the correct lowercase dotfile directory name, even when it appears inside prose or code spans; automated checks such as LanguageTool’s "(GITHUB)" rule commonly produce false positives for this literal filesystem path.
Applied to files:
docs/src/content/docs/api.mdREADME.mdAGENTS.mdclients/ts/README.mddocs/src/content/docs/deployment.mddocs/src/content/docs/development.md
📚 Learning: 2026-08-12T15:28:23.992Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 456
File: docs/src/content/docs/sdk/index.mdx:0-0
Timestamp: 2026-08-12T15:28:23.992Z
Learning: For `docs/src/content/docs/sdk/index.mdx`, the documented workaround for the undici idle-event-loop keep-alive stall is to upgrade to undici 8.10.0 or later. If a consumer is pinned to an affected version, `new Agent({ pipelining: 0 })` must be merged as `dispatcher` into the SDK-provided `RequestInit`; this disables keep-alive reuse. Configuring `keepAliveTimeout` does not mitigate this stall because the socket retirement timer is starved by the same idle event loop.
Applied to files:
docs/src/content/docs/sdk/index.mdx
📚 Learning: 2026-08-13T12:17:52.620Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 470
File: docs/src/content/docs/reverse-proxy.mdx:137-144
Timestamp: 2026-08-13T12:17:52.620Z
Learning: For Wave-RF/WaveHouse documentation, verify claims about implementation control flow against the authoritative implementation source (for example, internal/auth/auth.go) rather than relying solely on docs/** content. Documentation may lag behind or paraphrase behavior, so control-flow claims should be confirmed in source code.
Applied to files:
docs/src/content/docs/sdk/index.mdx
📚 Learning: 2026-05-13T15:14:46.366Z
Learnt from: CR
Repo: Wave-RF/WaveHouse PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-13T15:14:46.366Z
Learning: AGENTS.md is the single source of truth for project conventions and AI agent instructions
Applied to files:
README.md
📚 Learning: 2026-05-20T03:17:53.774Z
Learnt from: CR
Repo: Wave-RF/WaveHouse PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-05-20T03:17:53.774Z
Learning: Refer to AGENTS.md for project conventions, architecture notes, and AI agent instructions - it is the single source of truth
Applied to files:
README.md
📚 Learning: 2026-05-13T15:14:46.366Z
Learnt from: CR
Repo: Wave-RF/WaveHouse PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-05-13T15:14:46.366Z
Learning: Refer to AGENTS.md for project conventions, architecture notes, and AI agent instructions
Applied to files:
README.md
📚 Learning: 2026-08-12T05:35:22.804Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 455
File: clients/ts/README.md:11-11
Timestamp: 2026-08-12T05:35:22.804Z
Learning: For Wave-RF/WaveHouse, CI currently tests Node 22 only through `.nvmrc` and `.github/actions/setup-env` using `node-version-file`. Local `make ci` verification on Node 26 is not CI coverage and must not be documented as continuously tested runtime support.
Applied to files:
AGENTS.mdclients/ts/README.md
📚 Learning: 2026-08-19T15:23:52.908Z
Learnt from: CR
Repo: Wave-RF/WaveHouse PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-08-19T15:23:52.908Z
Learning: Applies to docs/src/content/docs/**/*.mdx : - **Never hand-write `utm_*` params or `rel` on a link to `wavehouse.cloud` or `wave-rf.com`.** Use `cloudLink()` / `relFor()` from `docs/src/config/outbound.ts`.
Applied to files:
AGENTS.md
📚 Learning: 2026-08-19T15:23:52.908Z
Learnt from: CR
Repo: Wave-RF/WaveHouse PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-08-19T15:23:52.908Z
Learning: Applies to **/*.{md,mdx} : - **Never hard-wrap prose. One paragraph is one line.** No wrapping at 72/80 columns, no "semantic linefeeds" splitting a paragraph at sentence boundaries.
Applied to files:
AGENTS.md
📚 Learning: 2026-08-19T15:23:52.908Z
Learnt from: CR
Repo: Wave-RF/WaveHouse PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-08-19T15:23:52.908Z
Learning: Applies to docs/src/content/docs/**/*.mdx : - **Never hand-write `®` or `™` in prose.**
Applied to files:
AGENTS.md
📚 Learning: 2026-08-19T15:23:52.908Z
Learnt from: CR
Repo: Wave-RF/WaveHouse PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-08-19T15:23:52.908Z
Learning: Applies to docs/src/content/docs/**/*.mdx : - **Opt a page into the Cloud CTA with `cloudCta` frontmatter**, not by importing the component.
Applied to files:
AGENTS.md
📚 Learning: 2026-08-19T15:23:52.908Z
Learnt from: CR
Repo: Wave-RF/WaveHouse PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-08-19T15:23:52.908Z
Learning: Applies to **/*.mdx : - **In MDX, leave a blank line between a JSX tag and a code fence.**
Applied to files:
AGENTS.md
📚 Learning: 2026-08-13T11:51:23.569Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 470
File: docs/src/content/docs/sdk/reference.md:50-50
Timestamp: 2026-08-13T11:51:23.569Z
Learning: In the TypeScript SDK, `SSE_*` errors are stream-only and reach the subscriber `error` callback; they never appear in `Result.error`. REST and streams expose their own retryable errors at different times: REST exposes `retryable` after `maxRetries` is exhausted, while streams report a retryable failure before the transport re-dials.
Applied to files:
clients/ts/README.md
📚 Learning: 2026-08-11T15:22:23.813Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 448
File: clients/ts/src/types.ts:61-71
Timestamp: 2026-08-11T15:22:23.813Z
Learning: In the TypeScript SDK, `ClientConfig.baseURL` must be an absolute URL with a scheme and host. A relative `baseURL` causes `resolveURL` to throw a `TypeError` on the first request. REST requests reject because `resolveURL` runs outside `request()`'s retry `try` block. In `clients/ts/src/stream/sse.ts`, `SSETransport` catches this failure and reports `SSE_CONNECT_ERROR` through the optional `StreamSubscriber.error` callback, so a subscriber without that callback can observe no error.
Applied to files:
clients/ts/README.md
📚 Learning: 2026-08-18T19:26:46.940Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 485
File: docs/src/content/docs/api.md:178-178
Timestamp: 2026-08-18T19:26:46.940Z
Learning: In WaveHouse `cmd/wavehouse/main.go`, a checkout `go build` with VCS metadata on Go 1.24+ can expose a synthesized module pseudo-version through `debug.ReadBuildInfo().Main.Version`, plus `vcs.revision` and `vcs.time`. `buildInfoFallback` uses `"dev"` and `"unknown"` only when VCS metadata is unavailable, such as with `-buildvcs=false` or outside a repository.
Applied to files:
cmd/wavehouse/main.go
📚 Learning: 2026-07-07T12:38:12.052Z
Learnt from: EricAndrechek
Repo: Wave-RF/WaveHouse PR: 378
File: internal/auth/auth.go:119-132
Timestamp: 2026-07-07T12:38:12.052Z
Learning: In this repo, do not add or recommend logging/tracing client IP addresses using naive or untrusted sources (e.g., `r.RemoteAddr` or directly trusting/deriving `X-Forwarded-For`) anywhere in the Go codebase. `middleware.RealIP` was removed due to IP-spoofing risks, and proper trusted-proxy-aware client-IP handling is intentionally deferred to issue `#333`. During code review, if proposed changes would record client IPs (including in audit paths such as `internal/auth/auth.go`), reject/redirect until `#333` lands with correct trusted-proxy configuration and safeguards.
Applied to files:
cmd/wavehouse/main.go
📚 Learning: 2026-08-11T21:55:53.726Z
Learnt from: jfwoods
Repo: Wave-RF/WaveHouse PR: 434
File: clients/go/stream_test.go:159-176
Timestamp: 2026-08-11T21:55:53.726Z
Learning: For Go files in this repository, do not report direct type assertions solely because the `forcetypeassert` rule is commented out in `.golangci.yml`. Only flag a type assertion when there is an independent correctness, safety, or maintainability issue.
Applied to files:
cmd/wavehouse/main.go
🪛 LanguageTool
docs/src/content/docs/sdk/index.mdx
[style] ~65-~65: Consider using the typographical ellipsis character here instead.
Context: ...sm.sh/@wavehouse/sdk@0.1.0); jsDelivr (.../+esm) and unpkg (?module`) serve the ...
(ELLIPSIS)
[style] ~347-~347: Consider using a more formal/concise alternative here.
Context: ...ix, for a WaveHouse reachable somewhere other than the root of an origin — behind a backen...
(OTHER_THAN)
[style] ~382-~382: Since ownership is already implied, this phrasing may be redundant.
Context: ...he SDK's value stands alone, and two of your own entries differing only in case collapse...
(PRP_OWN)
[style] ~402-~402: Since ownership is already implied, this phrasing may be redundant.
Context: ...row if it is set at all. See Supplying your own fetch for w...
(PRP_OWN)
[style] ~415-~415: Since ownership is already implied, this phrasing may be redundant.
Context: ...h client certificates, wrap requests in your own middleware (logging, tracing, circuit b...
(PRP_OWN)
[style] ~415-~415: Since ownership is already implied, this phrasing may be redundant.
Context: ...racing, circuit breaking), stub HTTP in your own tests without monkey-patching a global,...
(PRP_OWN)
[style] ~433-~433: This word has been used in one of the immediately preceding sentences. Using a synonym could make your text more interesting to read, unless the repetition is intentional.
Context: ...used with .stream() or .liveQuery() needs a different set: .ok, .status, `.ty...
(EN_REPEATEDWORDS_NEED)
[style] ~466-~466: Since ownership is already implied, this phrasing may be redundant.
Context: ... you don't really control, and auditing your own code for fetch calls won't tell you: ...
(PRP_OWN)
[style] ~479-~479: Since ownership is already implied, this phrasing may be redundant.
Context: ... one underlying reason: undici declares its own request/response types, separate from t...
(PRP_OWN)
[style] ~479-~479: Consider using the typographical ellipsis character here instead.
Context: ...the two aren't structurally assignable. { ...init, dispatcher } as never covers the ...
(ELLIPSIS)
[style] ~479-~479: Consider shortening this phrase to just ‘whether’, unless you mean ‘regardless of whether’.
Context: ...ither spelling, so one snippet compiles whether or not your lib includes DOM); and the retur...
(WHETHER)
AGENTS.md
[style] ~326-~326: This word has been used in one of the immediately preceding sentences. Using a synonym could make your text more interesting to read, unless the repetition is intentional.
Context: ...prose makes every later edit rewrap the whole block, so a one-word change lands as a ...
(EN_REPEATEDWORDS_WHOLE)
[style] ~341-~341: This sentence is over 40 words long. Consider splitting it up, as shorter sentences make the text easier to read.
Context: ...nd the agent hook are the MDX path. - These fix themselves as you write. .claude/hooks/markdown-on-save.sh (PostToolUse, sibling of gofumpt-on-save.sh) runs the MDX fence pass on .mdx, markdownlint --fix on .md, and misspell on both, so an agent's output is corrected in the same pass rather than costing a lint failure and a manual cleanup. It only sees Edit/Write/MultiEdit...
(TOO_LONG_SENTENCE)
[uncategorized] ~342-~342: The official name of this software platform is spelled with a capital “H”.
Context: ...fter doing that. - WH001 is off under .github/ and .claude/ (CI docs and agent p...
(GITHUB)
docs/src/content/docs/development.md
[uncategorized] ~570-~570: The official name of this software platform is spelled with a capital “H”.
Context: ...Dependabot Dependabot is configured in .github/dependabot.yml to open weekly grouped ...
(GITHUB)
[uncategorized] ~573-~573: The official name of this software platform is spelled with a capital “H”.
Context: ...ps:- **GitHub Actions** (root **and**/.github/actions/setup-env`) — outdated action v...
(GITHUB)
[uncategorized] ~573-~573: The official name of this software platform is spelled with a capital “H”.
Context: ...ons tracked against the SHA pins across .github/workflows/* and the setup-env compos...
(GITHUB)
[uncategorized] ~578-~578: The official name of this software platform is spelled with a capital “H”.
Context: ...o** directories. directory: / reaches .github/workflows/ but does not descend into `...
(GITHUB)
[uncategorized] ~578-~578: The official name of this software platform is spelled with a capital “H”.
Context: ...b/workflows/but does not descend into.github/actions/*/action.yml, so the setup-en...
(GITHUB)
[uncategorized] ~580-~580: The official name of this software platform is spelled with a capital “H”.
Context: ...de job down at once. See the comment in .github/dependabot.yml for the condition that ...
(GITHUB)
[style] ~630-~630: Since ownership is already implied, this phrasing may be redundant.
Context: .../beta/rc/next` (prerelease), plus its own GitHub Release. - Server — **build-...
(PRP_OWN)
[style] ~631-~631: Since ownership is already implied, this phrasing may be redundant.
Context: ...image in GHCR. The release job verifies its own attestations before finishing, so a rel...
(PRP_OWN)
🪛 zizmor (1.29.0)
.github/workflows/publish-dev.yml
[error] 82-82: runtime artifacts potentially vulnerable to a cache poisoning attack (cache-poisoning): enables caching by default
(cache-poisoning)
🔇 Additional comments (15)
AGENTS.md (1)
63-63: LGTM!Also applies to: 102-102, 114-116, 324-342, 397-403
scripts/ci/release-channel.sh (1)
49-56: LGTM!Also applies to: 65-81
scripts/ci/release-channel.test.sh (1)
63-88: LGTM!Makefile (1)
271-275: LGTM!Also applies to: 382-388, 417-424, 456-475, 489-510, 528-532, 546-546, 674-692
docs/src/content/docs/api.md (1)
26-28: LGTM!Also applies to: 597-600
docs/src/content/docs/deployment.md (1)
4-5: LGTM!Also applies to: 86-94
docs/src/content/docs/development.md (1)
21-32: LGTM!Also applies to: 41-42, 134-141, 154-165, 289-289, 403-439, 498-516, 570-580, 584-667
docs/src/content/docs/sdk/index.mdx (1)
3-63: LGTM!Also applies to: 67-119, 123-481, 501-532
.github/workflows/release.yml (1)
30-36: LGTM!Also applies to: 74-104, 111-177
.github/workflows/goreleaser-validate.yml (1)
40-41: LGTM!.github/workflows/publish-dev.yml (1)
51-53: LGTM!Also applies to: 82-119, 158-162
.github/workflows/publish-npm.yml (1)
8-12: LGTM!Also applies to: 53-54, 87-95, 126-188, 205-214, 230-339
.github/release.yml (1)
48-56: LGTM!README.md (1)
63-63: LGTM!Also applies to: 95-99, 117-117, 129-129, 141-141
clients/ts/README.md (1)
3-3: LGTM!Also applies to: 11-13, 47-47, 49-49, 62-62, 136-136
Summary
Release-readiness pass ahead of #149, plus #431 and #475. The through-line: every component now derives its version from the tag it was built at, so cutting a release is one tag and nothing else. That isn't just convenience — the
mainruleset forbids direct pushes, so a version-bump commit would have needed its own reviewed PR before every SDK release.Two bugs that would have fired on the first tag
release.prereleasedefaults to a flatfalse, so av0.1.0-alpha.1tag would have published as a stable GitHub Release and taken the "Latest release" badge. Nowauto.dockers_v2tagged:latestunconditionally on anyv*tag, so a futurev1.3.0-rc.1would have movedghcr.io/wave-rf/wavehouse:latestoff the shippedv1.2.0. Each build now gets one immutable ref plus one channel pointer (:lateststable,:alpha/:beta/:rc/:nextprerelease,:devon main), resolved byscripts/ci/release-channel.sh— shared with the npm dist-tag selection so:rcand@rccan't drift apart.Release notes could come out empty
Two tag families share this repo, and both release paths asked GitHub to generate notes without saying which tag to diff from. GitHub's default is the previous release, so cutting the SDK tag on the same commit as an already-published server release yields a completely empty changelog. The server side is fixed at the root with
git.ignore_tags: ["clients/*"], so GoReleaser's own detection is family-aware and no workflow has to pass an override; the SDK side passes--notes-start-tag, resolved by walking git history from the tag's parent rather than version-sorting (sorting picked a tag ahead of the one being released). The SDK release step also no longer fails outright when a release already exists — it previously ran a baregh release create, which reddens a run whose npm publish had already succeeded.Release bodies now come from GitHub's own per-PR generator (
changelog.use: github-native) grouped by.github/release.yml, rather than raw commit subjects.Tag naming:
clients/<lang>/vX.Y.Zsdk-v*becomesclients/ts/v*. Not cosmetic — Go resolves a subdirectory module only against a tag carrying that subdirectory as a prefix (go.dev/ref/mod), so the incoming Go SDK (#434, whoseclients/go/go.moddeclaresgithub.com/Wave-RF/WaveHouse/clients/go) must beclients/go/vX.Y.Z. Every client follows that shape rather than leaving Go as the exception. Done now because it was free exactly once: nosdk-v*tag had ever been created. Therelease tag protectionruleset was updated torefs/tags/v*+refs/tags/clients/*/v*.Fixes
triage.ymlretired. GitHub Models was retired 2026-07-30; the endpoint returns410unconditionally and the workflow had failed on every issue event since. The issue's suggestedcontinue-on-error+ fallback was written while it still looked like the announced brownout; with the service gone it would mean always taking the fallback. Triage is manual now..github/board-config.envwent with it (no other consumer), andPROJECT_BOARD_TOKENis now unused.0.0.0-dev.h<hash>to0.0.1-dev.<utc-stamp>.h<hash>. semver compares alphanumeric prerelease identifiers lexically, so a content hash made the channel's order arbitrary with respect to time — and sincenpm i …@devrecords a range, resolution walked backwards to a two-month-old build. A numeric identifier compares numerically; the0.0.1base outranks the permanently-published legacy versions and keeps the channel isolated from any release range.-X main.BuildTimehas never worked — the variable was initialized totime.Now(), and-Xsilently no-ops on a non-constant initializer, so/versionreported process start time as build time.go install …@vX.Y.Zreportedversion=dev— added adebug.ReadBuildInfo()fallback, gated so ldflags always win.Release-notes taxonomy
changelog.use: github-nativehands the release body to GitHub's per-PR generator, grouped by a new.github/release.yml. Getting that grouping right took several passes and the reasoning is recorded in the file, because the failure mode is silent — a wrong-looking changelog, not a red build:github_actionsis path-based (labeler maps.github/workflows/**), so it marks our own CI PRs too — excluding the label filed all our CI work under Dependencies, and dropping it instead empties that category, since Dependabot's action bumps carrygithub_actionsand notdependencies.documentationneeded the same exclude, because the npm Dependabot config points at the workspace root, so every npm bump touchesdocs/package.json.🔧 CI & buildsits above📚 Documentation, or it never matches: AGENTS.md requires a doc update with every change, so 10 of the last 12 humangithub_actionsPRs also carrydocumentation. It's a trade — a few docs PRs that touch a workflow now file under CI — and both sides are counted in the file.The invariant, recorded inline: any category keyed on a label a Dependabot PR can carry needs the author exclude — labeler's path labels and the ecosystem labels Dependabot applies itself (
javascriptis in neitherlabeler.ymlnor our categories).This routing can't be linted locally, but it can be dry-run against real history from the branch —
configuration_file_pathresolves relative totarget_commitish:Run on this config: 23/23 merged Dependabot PRs in 📦 Dependencies, zero leaking into 🔧 CI & build or 📚 Documentation.
Tooling and housekeeping
make release-server/release-sdk-ts/release-sdk-go→scripts/release.sh, which preflights (on main, clean tree, synced with origin, tag free both sides,CIgreen on that exact commit), prints what will publish, and prompts.DRY_RUN=1stops after the plan.release.ymlverifies its own attestations before finishing, so a release publishing unverifiable provenance goes red.wavehouse_linux_amd64.tar.gz),.zipon Windows, archives no longer bundle the 324 KB CHANGELOG.CHANGELOG.mdmerged from dozens of duplicate###bands under one## Unreleasedinto 5 canonical sections and stamped## [0.1.0]. Verified content-preserving — every entry byte-identical, checked by diffing the sorted multiset of non-heading lines. (No count is quoted: the base moves with every merge, and a stale figure beside a "verified" claim is worse than none.)Test plan
make cigreen:v1.2.3+:latest; prerelease →:v0.1.0-alpha.1+:alpha; dev →:dev-<sha>+:dev; env-unset → safe:latestfallback)node-semverusing the ten actually-published versions — old scheme resolves^0.0.0-dev.h04a…to the June 8 build; new scheme resolves forward and is unsatisfiable by^0.1.0.zipgo buildin-VCS,-ldflags, no-VCS, andmake buildscripts/release.shexercised end-to-end in a scratch repo — real tag creation and push, re-run refusal, abort at prompt, dirty tree, wrong branch, bad version, missingVERSIONwavehouse health→ clean exit 1, labels/user/healthcheck correct)pre-push-reviewer+docs-reviewer), bothship_itat zero findingsgenerate-notesacceptsconfiguration_file_pathresolved fromtarget_commitish, so this validates from the branch before mergeNotes for review
## [0.1.0] - 2026-08-19stamp is a judgement call. This branch promotes## Unreleased, which its own new docs prescribe as a separate pre-tag PR. The date is the intended cut date and the[0.1.0]link 404s until the tag exists. If tagging slips, correct the date and move anything merged in between up from## Unreleased— or say the word and I'll split it out.PROJECT_BOARD_TOKENshould be deleted. Retiringtriage.ymlleft it with no consumers — an unused PAT with Projects scope on a public repo. A branch can't remove a repo secret, sogh secret delete PROJECT_BOARD_TOKENplus revoking the PAT is a manual step. The docs now say so rather than claiming it's already gone.:latestand the bare CDN URL don't resolve yet.ghcr.io/wave-rf/wavehouse:latest404s and npm'slateststill points at the June 4 bootstrap0.0.0-dev.0f8826c. Both self-heal the moment a stablev0.1.0/clients/ts/v0.1.0ships — which is why the first release should not be a prerelease, despite release: cut v0.1.0 (first public release) #149's title./wavehouseto.gitignore(the pre-push reviewer'sgo build ./cmd/...drops a binary there that voids themake cimarker), and a post-release smoke test that installs the published SDK against the published image.Related Issues
Closes #431
Closes #475
Advances #149
🤖 Generated with Claude Code
https://claude.ai/code/session_015bVwHtNakQgmnBhMcfW8pe