Repository navigation
Commit 0026f5d
fix(release): make v0.3.0 releasable and every install path truthful (#341)
* chore(release): set VERSION to 0.3.0
The Go module proxy already serves v0.1.0, v0.1.1 and v0.2.0 for
github.com/GrayCodeAI/rho (hawk-era tags), so a VERSION of 0.0.1 made
source builds report a version below the published ones and could never
become @latest. The next rho release is v0.3.0.
- VERSION: 0.0.1 -> 0.3.0
- compatibility matrix "stable": rho 0.3.0 with flux 0.0.1 (the pinned
go.mod dependency) instead of the never-released rho 0.0.1
- testaudit: VERSION must be SemVer without a leading "v" and >= 0.3.0
Refs: F018, F024
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* build(release): build and CI-check windows/arm64
README promises binaries for linux/darwin/windows on amd64/arm64, `make
build-all`, install.sh and the npm scaffolding (rho-win32-arm64) all
handle windows/arm64, but .goreleaser.yml ignored that target and the CI
build matrix excluded it, so no windows_arm64 archive was ever produced.
`GOOS=windows GOARCH=arm64 CGO_ENABLED=0 go build ./cmd/rho` succeeds,
so build the target instead of narrowing the promise:
- .goreleaser.yml: drop the windows/arm64 ignore (six archives)
- ci.yml: drop the matrix exclude so the target is compile-checked
- npm assemble script: drop the comments about the missing target
Refs: F282
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* build(release): drop the Homebrew publisher
The brews stanza pushed a formula to GrayCodeAI/homebrew-tap, a
repository that does not exist, with HOMEBREW_TAP_TOKEN, a secret that
is not set. On the next tag GoReleaser would have created the GitHub
release and then failed in the brew publisher, leaving the run red and
the release unsigned. `brews` is also deprecated in the pinned
GoReleaser v2.17.0, so `goreleaser check` exited 1 on this config.
Per the owner decision the tap is not being created now: remove the
stanza and the unused HOMEBREW_TAP_TOKEN/TAP_GITHUB_TOKEN env wiring.
`goreleaser check` now validates the config. Re-adding Homebrew
(homebrew_casks) is documented as a follow-up in docs/RELEASING.md.
Refs: F021
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ci(release): make a v* tag produce a signed, SBOM'd rho release
The tag-triggered workflow had never completed (10 of 10 runs failed):
- GoReleaser's `sboms:` stanza shells out to syft, which the runner does
not have ("exec: syft: executable file not found"). Install it with
anchore/sbom-action/download-syft pinned by SHA.
- The cosign step ran `gh release download ... -D dist/` into the dist/
directory GoReleaser had just written, so it failed on the existing
dist/checksums.txt before signing anything. Signing now happens inside
GoReleaser (`signs:`, cosign keyless over checksums.txt, emitting the
Sigstore bundle checksums.txt.sigstore.json) so the signature is
uploaded with the release. cosign-installer is bumped to v4.1.2
(cosign v3), whose sign-blob requires --bundle. A final step
re-downloads the published files and verifies them with the exact
certificate identity install.sh uses.
- `packages: write` was unused (no images or packages are published).
- The checkout-flux step cloned sibling repos the build never used
(go.mod pins published flux v0.0.1); the job now sets GOWORK=off and
builds only from go.mod/go.sum, with the local-replace guard.
- New scripts/check-release-tag.sh refuses a tag that is not
"v" + VERSION or whose CHANGELOG.md has no non-empty section for it,
and extracts that section as the release notes (--release-notes), so
published notes match the curated changelog instead of an
auto-generated list of every commit since the root.
- Builds use -trimpath; /dist/ is gitignored.
The shared templates are regenerated from the fixed files.
`goreleaser check` passes and `goreleaser release --snapshot --clean
--skip=publish,sign` builds six rho_* archives, six SPDX SBOMs and
checksums.txt locally (signing needs the Actions OIDC token and was not
exercised). testaudit now pins these invariants.
Refs: F022, F023, F024, F031, F259
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(install): verify releases fail-closed and parse flags strictly
install.sh could not install anything and was weaker than it claimed:
- It fetched rho_<ver>_* from releases/latest (v0.2.0), whose assets
are hawk_*: every install 404ed. Releases before v0.3.0 predate the
rename, so they are now refused with a clear message and no download
(no hawk_* fallback: those archives contain a `hawk` binary).
- Signature: it looked for checksums.txt.sig/.cert, which no release
has, and matched the certificate with an unanchored regexp built from
the unescaped version ("anchor and escape" said the comment). It now
verifies the Sigstore bundle checksums.txt.sigstore.json that the
release workflow uploads, with the exact --certificate-identity
https://github.com/<repo>/.github/workflows/release.yml@refs/tags/v<ver>.
When cosign is present, a missing or invalid signature aborts. When it
is absent the script prints a prominent warning and reports
"signature: NOT verified" in the summary; RHO_REQUIRE_COSIGN=1 makes
cosign mandatory.
- The SHA-256 check always runs (sha256sum, shasum or openssl) and
requires exactly one exact-name entry in checksums.txt.
- Flags are parsed in a loop: --version/--prefix in any order, the
--flag=value forms, --help, and exit 2 on unknown or empty flags
(previously `--version X --prefix Y` silently ignored the prefix).
- The version is validated before use, unsupported OS/arch fail fast,
temp files are cleaned on exit/signals, and RHO_INSTALL_REPO (validated
owner/repo) lets a fork install its own signed releases.
internal/testaudit/install_script_test.go runs the real script end to
end against a fake release served by stub curl/uname/cosign, with PATH
restricted so the host's tools cannot change the outcome.
Refs: F019, F029, F260
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(action): install rho from verified release archives
The composite action downloaded the GitHub "latest" release's source
tarball with `curl -sL | tar` (no -f, no checksum, no signature) and ran
`go build ./cmd/rho` on it. Today that tarball is the hawk-era v0.2.0
tree, which has no cmd/rho, so the action failed for every default
invocation; for pinned versions it prepended a second "v" to inputs
documented as "v1.2.3"; and a `@main` pin tried to download tag "vmain".
The install step now:
- installs cosign (sigstore/cosign-installer, pinned SHA) and runs the
repository's install.sh at the action's own ref with
RHO_REQUIRE_COSIGN=1, so the rho_<ver>_<os>_<arch> archive is checked
against the signed checksums.txt (exact release-workflow identity)
and its SHA-256 before anything runs; Go is no longer required;
- resolves the version as: rho-version input (0.3.0, v0.3.0 or latest),
else the release tag the action is pinned to, else the latest release
via `gh release view` with the github-token input;
- validates rho-repo (owner/repo) and the version before use.
Releases before v0.3.0 are refused with a clear message by install.sh.
Also drops the stale feat/ecosystem-wiring-pr branch mapping in ci.yml.
Checked locally by extracting the step: a @main pin resolves latest
(v0.2.0) and is refused as pre-rename, rho-version 0.3.0 fails with a
clear 404 until that release exists, and malformed rho-version/rho-repo
exit 2.
Refs: F031, F254
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(readme): make the install section truthful
Every documented install path failed for a new user:
- `curl .../main/install.sh | sh` requested rho_0.2.0_* assets from the
latest release, which only has hawk_* assets (404);
- `brew install graycodeai/tap/rho`: GrayCodeAI/homebrew-tap does not exist;
- `npm install -g @graycodeai/rho`: nothing is published (E404);
- `go install .../cmd/rho@latest`: @latest is the hawk-era v0.2.0, which
has no cmd/rho ("does not contain package").
The Install section now says prebuilt installs are available from
v0.3.0 (the first rho-named release) and points to the source build
until then; shows the script from the immutable v0.3.0 tag (tags are
protected) with what it verifies and RHO_REQUIRE_COSIGN=1; lists the
release assets; and states plainly that Homebrew and npm packages do not
exist. The contributor `go install` line uses @main, verified today with
a clean GOBIN against proxy.golang.org, and explains why @latest fails
until v0.3.0 is tagged.
Refs: F002, F019, F025, F262
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* build(npm): gate the unpublished npm packaging and fix its assembly
`npm install -g @graycodeai/rho` is E404: nothing is published, there is
no publish job, and the owner decided not to create the npm org now. The
scaffolding also had defects that would have broken a publish:
- every package.json said "license": "Apache-2.0" while the project is
MIT (LICENSE, goreleaser);
- the assemble script stamped only the sub-packages, leaving the meta
package and its optionalDependencies at 0.0.0-development, so every
install would report "platform package not installed";
- it looked for dist/rho_<os>_arm64/ but GoReleaser v2 writes
dist/rho_<os>_arm64_v8.0/, so the arm64 targets always failed.
Changes: license MIT everywhere; "private": true on all seven packages
so `npm publish` refuses until a real channel exists; the assemble
script takes the version from VERSION (or RHO_NPM_VERSION), validates
it, stamps the meta package and its optionalDependencies, and uses the
real GoReleaser v2 directory names. npm/README.md states the channel is
not available and lists what a publish needs. The README no longer
advertises npm.
Checked on a scratch copy against the local snapshot dist/: all six
targets assembled at 0.3.0 and the meta package pins 0.3.0.
Refs: F020
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* build(nix): remove the flake that cannot evaluate
flake.nix declared inputs for five GitHub repositories that no longer
exist (merlin, kestrel, shrike, swift, harrier), so `nix build` and
`nix develop` failed while fetching inputs. Even with those removed it
would have built with vendorHash = null and GONOSUMCHECK=1 (no
dependency integrity), hardcoded version 0.0.1, and no flake.lock.
Nothing in CI evaluated it and the README does not offer Nix.
Nix is not installed where this change was prepared and CI never ran it,
so a fixed flake (real vendorHash, flake.lock, `nix flake check` in CI)
could not be verified. Rather than ship another unverified install path, remove
flake.nix and the `use flake` .envrc that only loaded it; /.envrc is now
gitignored so a local direnv file (which `make test-live` may read keys
from) is never committed. Re-adding a verified flake is recorded as a
follow-up in docs/RELEASING.md.
Refs: F027, F211, F263
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* ci: fail the build when the release binary exceeds its size budget
The CI "size check" only emitted a ::warning above 98 MB and never
failed; `make size-check` warned at a different threshold (80 MB, "matching
CI"), and both comments claimed the binary was ~95 MB. The stripped
linux/amd64 build of ./cmd/rho is 62,492,834 bytes (59.6 MiB) today, so
any regression short of +38 MB passed silently.
The budget now lives in one place, SIZE_LIMIT_MB := 70 in the Makefile
(~10 MiB headroom), `make size-check` exits 1 above it (and no longer
needs bc or platform-specific stat flags), and the CI build job runs
`make size-check` on linux/amd64 instead of its own copy of the logic.
Verified: `make size-check` passes at 60 MiB and fails with
SIZE_LIMIT_MB=50.
Refs: F030
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(packaging): make the systemd unit's state reachable under its hardening
packaging/systemd/rho-daemon.service could not work as written:
- ProtectHome=true makes /home, /root and /run/user inaccessible, yet
the unit granted ReadWritePaths=%h/.rho/state and ReadOnlyPaths=%h/.rho.
In a system unit %h is always /root (systemd.unit(5)), and rho does not
keep state in ~/.rho anyway (it uses the user config dir).
- The docs said the unit runs as user `rho`, but it had no User=, so it
ran as root.
- `--api-key ${RHO_DAEMON_API_KEY}` put the key on the command line
(visible in ps) although the daemon already reads the variable.
- Documentation= pointed at https://docs.rho.ai, which does not resolve.
The unit now runs as User=rho with StateDirectory=rho/CacheDirectory=rho
and points HOME, RHO_CONFIG_DIR, RHO_STATE_DIR and RHO_CACHE_DIR there,
keeps ProtectSystem=strict/ProtectHome=true/PrivateTmp, loads the API key
from an optional root-owned EnvironmentFile, and links the rho
troubleshooting guide, whose systemd section now documents the user,
paths, log file and how to grant project directories.
internal/testaudit/packaging_test.go parses the unit and fails on paths
hidden by ProtectHome, a missing User=, state outside StateDirectory, an
API key on ExecStart, or non-repository documentation links. The unit was
not started under systemd here (no systemd/systemd-analyze on this
machine); the ProtectHome and %h semantics are from systemd.exec(5) and
systemd.unit(5).
Refs: F032
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* chore: remove the unenforced ast-grep configuration
sgconfig.yaml pointed testDirs at a tests/ directory that does not
exist, and the setup never enforced anything:
- ast-grep (0.39.5, checked locally) only discovers sgconfig.yml, so
`sg scan`/`sg test` in the repo root fail with "No ast-grep project
configuration is found"; with `-c sgconfig.yaml`, `sg test` runs 0
tests;
- the lefthook hook ran `sg scan` only when sg happened to be
installed, piped through `head`, so it could never block a commit;
- CI never ran it;
- its single rule (no fmt.Println outside tests) contradicts the CLI,
which prints user output with fmt.Println in ~178 places; the real
guard for internal/ is testaudit's TestNoRawFmtPrintInInternal.
Delete sgconfig.yaml, rules/ and the lefthook hook rather than imply an
enforcement that does not exist.
Refs: F033
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(release): document the manual, tag-protected release process
CONTRIBUTING.md, README.md, docs/versioning.md, docs/compatibility.md,
the compatibility matrix, cmd/rho/main.go and the shared templates all
said release-please bumps VERSION, writes CHANGELOG.md and tags releases,
and told contributors never to edit either file. No release-please
config, manifest or workflow exists; releases are tags pushed by hand
and CHANGELOG entries are hand-written.
- New docs/RELEASING.md: the release PR checklist (VERSION, CHANGELOG
section, compatibility matrix, README install URL), tagging, what
release.yml does, how to verify a release, the status of every
distribution channel (Homebrew, npm and Nix explicitly not available,
with what each would need), and v0.3.0 specifics (hawk-era tags,
retraction, "Latest" release).
- Documents the existing tag ruleset protect-release-tags (id 24053191):
creation/update/deletion/non-fast-forward of refs/tags/v* restricted,
repository admin role as the only bypass.
- Every release-please claim is replaced with the manual process; the PR
checklist now asks for an [Unreleased] CHANGELOG entry instead of
forbidding CHANGELOG edits.
- `make release` no longer runs `goreleaser release --clean` from a
workstation (an unsigned publish with a personal token, which is how
the hawk-era v0.2.0 assets were produced); it explains the tag-driven
process and exits 1. New `make release-check` (the release.yml guard)
and `make release-snapshot` (goreleaser check + snapshot build, no
publish or signing) replace it for local validation.
Refs: F026, F028, F269
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* docs(changelog): repair the version history and record this release work
CHANGELOG.md listed [0.2.0] (2026-07-13) above [0.4.0] and [0.3.0]
(May 2026), so versions were not monotonic, and it already had a
"## [0.3.0]" heading for hawk-era work although v0.3.0 is the next rho
release (the release guard would have accepted that stale section as the
v0.3.0 notes). [Unreleased] had two "### Changed" lists.
- A short history note explains that tags v0.1.0, v0.1.1 and v0.2.0 were
built from the github.com/GrayCodeAI/hawk module and that v0.3.0 is
the first rho release.
- Historical sections keep their text but are relabelled
"[hawk 0.2.0]" (the v0.2.0 tag) and "[hawk X.Y.Z, untagged]" (earlier
numbering that was never tagged), so no heading can be mistaken for a
rho version.
- "Flux v0.2.1" is annotated as the eyrie version of the time, and the
internal/jsonc, internal/providers and internal/permissions/verdict.go
bullets are marked "(since removed)".
- The two [Unreleased] "### Changed" lists are merged, and this PR's
release, install, packaging and removal changes are recorded.
testaudit's TestChangelogStructure requires a single leading
[Unreleased], release headings of the form "## [X.Y.Z] — YYYY-MM-DD" in
descending order and not above VERSION, "[hawk …]" for historical
entries, and unique subsection headings per section.
The "## [0.3.0] — <date>" section itself is written in the release PR
right before tagging (docs/RELEASING.md); until then
`make release-check` and release.yml refuse the v0.3.0 tag.
Refs: F270
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(version): report the tagged module version for go install builds
`go install github.com/GrayCodeAI/rho/cmd/rho@vX.Y.Z` builds without
ldflags, so main.Version stays "dev". DisplayVersion then fell back to
any VERSION file in the working directory or its parents (so running rho
inside another project could print that project's version) and
otherwise "dev"; `rho update` compared the raw "dev" string, which never
parses, and always reported an update.
DisplayVersion now prefers, after the ldflags version, the main module
version from debug.ReadBuildInfo when it is a clean release (e.g.
v0.3.0 -> "0.3.0"); "(devel)", pseudo-versions (@main, untagged commits)
and +dirty builds still fall back to the VERSION file, then "dev".
`rho update` uses DisplayVersion, so go-install and source builds compare
their real version.
Tests stub the build info for a tagged module, each development form,
and the ldflags precedence.
Refs: F018, F025
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* build(go.mod): retract the hawk-era v0.1.0–v0.2.0 tags
proxy.golang.org serves v0.1.0, v0.1.1 and v0.2.0 for
github.com/GrayCodeAI/rho, but those tags were cut before the rename:
their go.mod declares module github.com/GrayCodeAI/hawk and they contain
no cmd/rho, so `go install .../cmd/rho@latest` fails with "does not
contain package" and tooling (pkg.go.dev, dependabot) lists them as rho
versions. The proxy keeps them forever, so retract the range with a
rationale; retractions take effect from the first release that carries
this go.mod (v0.3.0), after which @latest is v0.3.0 and the old
versions are marked retracted.
`go mod tidy -diff`, `go mod verify` and the replace-directive guard
pass; a testaudit test keeps the range retracted and ensures VERSION is
never inside it.
Refs: F025
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>1 parent 13e05ce commit 0026f5d
48 files changed
Lines changed: 2184 additions & 637 deletions
File tree
- .github
- actions/rho
- workflows
- cmd
- rho
- docs
- internal/testaudit
- npm
- rho-darwin-arm64
- rho-darwin-x64
- rho-linux-arm64
- rho-linux-x64
- rho-win32-arm64
- rho-win32-x64
- rho
- scripts
- packaging/systemd
- rules
- scripts
- testdata
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
96 | | - | |
97 | | - | |
| 96 | + | |
| 97 | + | |
98 | 98 | | |
99 | 99 | | |
100 | 100 | | |
| |||
103 | 103 | | |
104 | 104 | | |
105 | 105 | | |
106 | | - | |
107 | | - | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
108 | 110 | | |
109 | 111 | | |
110 | 112 | | |
111 | | - | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
112 | 116 | | |
113 | 117 | | |
114 | 118 | | |
| |||
126 | 130 | | |
127 | 131 | | |
128 | 132 | | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
129 | 138 | | |
130 | 139 | | |
131 | 140 | | |
| |||
134 | 143 | | |
135 | 144 | | |
136 | 145 | | |
| 146 | + | |
137 | 147 | | |
138 | 148 | | |
139 | 149 | | |
140 | 150 | | |
141 | 151 | | |
142 | 152 | | |
143 | 153 | | |
144 | | - | |
145 | | - | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
146 | 162 | | |
147 | | - | |
| 163 | + | |
148 | 164 | | |
149 | 165 | | |
150 | | - | |
151 | | - | |
152 | | - | |
153 | | - | |
154 | | - | |
155 | | - | |
156 | | - | |
| 166 | + | |
| 167 | + | |
157 | 168 | | |
158 | | - | |
159 | | - | |
160 | | - | |
161 | | - | |
162 | | - | |
163 | | - | |
164 | | - | |
165 | | - | |
166 | | - | |
167 | | - | |
168 | | - | |
169 | | - | |
170 | | - | |
171 | | - | |
172 | | - | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
173 | 172 | | |
174 | | - | |
175 | | - | |
176 | | - | |
177 | | - | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
178 | 183 | | |
179 | 184 | | |
180 | 185 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
96 | 96 | | |
97 | 97 | | |
98 | 98 | | |
99 | | - | |
| 99 | + | |
100 | 100 | | |
101 | 101 | | |
102 | 102 | | |
| |||
487 | 487 | | |
488 | 488 | | |
489 | 489 | | |
490 | | - | |
491 | | - | |
492 | | - | |
493 | 490 | | |
494 | 491 | | |
495 | 492 | | |
| |||
507 | 504 | | |
508 | 505 | | |
509 | 506 | | |
510 | | - | |
| 507 | + | |
511 | 508 | | |
512 | | - | |
513 | | - | |
514 | | - | |
515 | | - | |
516 | | - | |
517 | | - | |
518 | | - | |
519 | | - | |
520 | | - | |
521 | | - | |
522 | | - | |
523 | | - | |
524 | | - | |
525 | | - | |
526 | | - | |
527 | | - | |
528 | | - | |
529 | | - | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
530 | 512 | | |
531 | 513 | | |
532 | 514 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
2 | | - | |
| 1 | + | |
| 2 | + | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| |||
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
12 | | - | |
13 | | - | |
14 | | - | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
15 | 19 | | |
16 | 20 | | |
17 | 21 | | |
18 | 22 | | |
19 | 23 | | |
20 | 24 | | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
21 | 28 | | |
22 | 29 | | |
23 | 30 | | |
24 | 31 | | |
25 | 32 | | |
| 33 | + | |
26 | 34 | | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
31 | 39 | | |
32 | 40 | | |
33 | 41 | | |
34 | 42 | | |
35 | 43 | | |
36 | 44 | | |
37 | 45 | | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
38 | 59 | | |
39 | 60 | | |
40 | 61 | | |
41 | 62 | | |
42 | 63 | | |
43 | 64 | | |
44 | 65 | | |
45 | | - | |
| 66 | + | |
46 | 67 | | |
47 | 68 | | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | 69 | | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
59 | 73 | | |
60 | 74 | | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | | - | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
73 | | - | |
74 | | - | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
| 7 | + | |
6 | 8 | | |
7 | 9 | | |
8 | 10 | | |
| |||
38 | 40 | | |
39 | 41 | | |
40 | 42 | | |
41 | | - | |
42 | | - | |
| 43 | + | |
43 | 44 | | |
44 | 45 | | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
45 | 49 | | |
46 | 50 | | |
47 | 51 | | |
| |||
0 commit comments