Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a926383827 | |||
| 557f5a3acc | |||
| 17e6195aeb | |||
| 14f2725452 | |||
| 353b8f5a16 |
@@ -54,8 +54,15 @@ carries `-count=1` and sets `MAVEN_ONNX_LIB`. Without that variable the four
|
|||||||
make build # all 11 binaries. make build-web for one (web/waked/poll/caldav skip CGO)
|
make build # all 11 binaries. make build-web for one (web/waked/poll/caldav skip CGO)
|
||||||
make test # go test -race across ./internal/... ./cmd/... with CGO env set
|
make test # go test -race across ./internal/... ./cmd/... with CGO env set
|
||||||
make t PKG=./internal/router/eval/ RUN='TestONNX' V=1 # V=1 for -v, RACE=0 to drop -race
|
make t PKG=./internal/router/eval/ RUN='TestONNX' V=1 # V=1 for -v, RACE=0 to drop -race
|
||||||
|
make analyze # staticcheck, deadcode and govulncheck. Not in `test`: all three need the network
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**The static gates pass against a baseline, not against zero**
|
||||||
|
(`scripts/analyzers/*.baseline`, reasoning in `docs/workflow.md`). A fix must
|
||||||
|
delete its baseline entry, because the gate also fails on an entry whose finding
|
||||||
|
is gone. **`make audit` is a git-grep inventory, not analysis.** Do not cite it
|
||||||
|
as a reachability check.
|
||||||
|
|
||||||
## The daemons
|
## The daemons
|
||||||
|
|
||||||
Eleven binaries under `cmd/`, wired socket-to-socket over `internal/ipc`, not
|
Eleven binaries under `cmd/`, wired socket-to-socket over `internal/ipc`, not
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
# `test` below fail on the two packages that have no test files. deps-go builds
|
# `test` below fail on the two packages that have no test files. deps-go builds
|
||||||
# the missing tools in, so the vendored tree is self-sufficient. Keep the version
|
# the missing tools in, so the vendored tree is self-sufficient. Keep the version
|
||||||
# here in step with the `go` directive in go.mod.
|
# here in step with the `go` directive in go.mod.
|
||||||
GO_VERSION := 1.25.5
|
GO_VERSION := 1.25.12
|
||||||
GO := $(shell pwd)/deps/go/go/bin/go
|
GO := $(shell pwd)/deps/go/go/bin/go
|
||||||
export GOTOOLCHAIN := local
|
export GOTOOLCHAIN := local
|
||||||
GOFLAGS :=
|
GOFLAGS :=
|
||||||
@@ -16,7 +16,7 @@ PIPER_BIN := $(shell pwd)/deps/piper/piper
|
|||||||
PIPER_MODEL := $(shell pwd)/models/tts/ru_RU-irina-medium.onnx
|
PIPER_MODEL := $(shell pwd)/models/tts/ru_RU-irina-medium.onnx
|
||||||
PIPER_ESPEAK := $(shell pwd)/deps/piper/espeak-ng-data
|
PIPER_ESPEAK := $(shell pwd)/deps/piper/espeak-ng-data
|
||||||
|
|
||||||
.PHONY: t audit simulate stt-fixtures test-stt-golden all build build-stt build-tts build-daemon build-client build-waked build-web build-poll build-caldav clean test fmt-check vet run-stt run-tts run-web download-embedder deps-go deps-sentinel tidy eval-router eval-reach eval-recall eval-phrasing eval-models build-gpud
|
.PHONY: t audit simulate stt-fixtures test-stt-golden all build build-stt build-tts build-daemon build-client build-waked build-web build-poll build-caldav clean test fmt-check vet run-stt run-tts run-web download-embedder deps-go deps-sentinel deps-vuln vuln deps-lint lint deadcode analyze tidy eval-router eval-reach eval-recall eval-phrasing eval-models build-gpud
|
||||||
|
|
||||||
all: build
|
all: build
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ run-web: build-web
|
|||||||
# builds them on demand, but `go test -coverprofile` calls covdata through
|
# builds them on demand, but `go test -coverprofile` calls covdata through
|
||||||
# base.Tool(), which only stats pkg/tool and exits. So build them in once here.
|
# base.Tool(), which only stats pkg/tool and exits. So build them in once here.
|
||||||
GO_TARBALL := go$(GO_VERSION).linux-amd64.tar.gz
|
GO_TARBALL := go$(GO_VERSION).linux-amd64.tar.gz
|
||||||
GO_SHA256 := 9e9b755d63b36acf30c12a9a3fc379243714c1c6d3dd72861da637f336ebb35b
|
GO_SHA256 := 234828b7a89e0e303d2556310ee549fbcf253d28de937bac3da13d6294262ac1
|
||||||
deps-go: deps-sentinel
|
deps-go: deps-sentinel
|
||||||
@mkdir -p deps/go
|
@mkdir -p deps/go
|
||||||
cd deps/go && curl -fLO 'https://go.dev/dl/$(GO_TARBALL)'
|
cd deps/go && curl -fLO 'https://go.dev/dl/$(GO_TARBALL)'
|
||||||
@@ -95,6 +95,70 @@ deps-sentinel:
|
|||||||
@mkdir -p deps
|
@mkdir -p deps
|
||||||
@printf 'module github.com/kami/maven/deps\n\ngo 1.21\n' > deps/go.mod
|
@printf 'module github.com/kami/maven/deps\n\ngo 1.21\n' > deps/go.mod
|
||||||
|
|
||||||
|
# vuln — the advisory gate the 2026-08-10 audit found missing (V-682). It reads
|
||||||
|
# the published database over the network, so it is not part of `test`, which
|
||||||
|
# has to pass on a box with no route out. Run it before a toolchain or
|
||||||
|
# dependency bump lands, because that is what it grades: on 2026-08-11 the
|
||||||
|
# pinned Go 1.25.5 and x/text 0.14.0 carried 20 reachable advisories and the
|
||||||
|
# bumped pair carries none.
|
||||||
|
#
|
||||||
|
# govulncheck is a tool and not a dependency, so it is installed into deps/ like
|
||||||
|
# the toolchain rather than added to go.mod. The version is pinned here for the
|
||||||
|
# same reason GO_VERSION is: a gate that moves on its own is not a gate.
|
||||||
|
GOVULNCHECK_VERSION := v1.6.0
|
||||||
|
GOVULNCHECK := $(shell pwd)/deps/bin/govulncheck
|
||||||
|
|
||||||
|
deps-vuln: deps-sentinel
|
||||||
|
@mkdir -p deps/bin
|
||||||
|
GOTOOLCHAIN=local GOBIN=$(shell pwd)/deps/bin \
|
||||||
|
$(GO) install golang.org/x/vuln/cmd/govulncheck@$(GOVULNCHECK_VERSION)
|
||||||
|
|
||||||
|
# The CGO env is the same one `test` carries: govulncheck loads the packages,
|
||||||
|
# and the four CGO daemons do not load without it.
|
||||||
|
vuln: deps-vuln
|
||||||
|
CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" LD_LIBRARY_PATH="$(shell pwd)/deps/lib" \
|
||||||
|
PATH="$(shell pwd)/deps/go/go/bin:$$PATH" GOTOOLCHAIN=local $(GOVULNCHECK) ./...
|
||||||
|
|
||||||
|
# lint and deadcode — the other two analyzers the 2026-08-10 audit asked for
|
||||||
|
# (V-694). They are not part of `test` for the same reason `vuln` is not: they
|
||||||
|
# install over the network, and they are slow enough that a change to one Go
|
||||||
|
# file should not pay for them.
|
||||||
|
#
|
||||||
|
# Neither reports zero, so neither fails on its own output. The accepted set
|
||||||
|
# lives in scripts/analyzers/*.baseline and scripts/analyzer-gate.sh decides.
|
||||||
|
# What is new fails, and so does a baseline entry whose finding is gone.
|
||||||
|
#
|
||||||
|
# deadcode runs with -test, so a test file is a root. Without it the report is
|
||||||
|
# 172 lines, most of internal/router/eval, and none of it is a mistake.
|
||||||
|
STATICCHECK_VERSION := v0.7.0
|
||||||
|
DEADCODE_VERSION := v0.48.0
|
||||||
|
STATICCHECK := $(shell pwd)/deps/bin/staticcheck
|
||||||
|
DEADCODE := $(shell pwd)/deps/bin/deadcode
|
||||||
|
|
||||||
|
deps-lint: deps-sentinel
|
||||||
|
@mkdir -p deps/bin
|
||||||
|
GOTOOLCHAIN=local GOBIN=$(shell pwd)/deps/bin \
|
||||||
|
$(GO) install honnef.co/go/tools/cmd/staticcheck@$(STATICCHECK_VERSION)
|
||||||
|
GOTOOLCHAIN=local GOBIN=$(shell pwd)/deps/bin \
|
||||||
|
$(GO) install golang.org/x/tools/cmd/deadcode@$(DEADCODE_VERSION)
|
||||||
|
|
||||||
|
# Both load the packages, so both carry the CGO env `test` carries. Without it
|
||||||
|
# the four CGO daemons do not load and the analyzer reports a build error
|
||||||
|
# instead of a finding -- which analyzer-gate.sh fails on rather than filters.
|
||||||
|
ANALYZER_ENV = CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" \
|
||||||
|
LD_LIBRARY_PATH="$(shell pwd)/deps/lib" \
|
||||||
|
PATH="$(shell pwd)/deps/go/go/bin:$$PATH" GOTOOLCHAIN=local
|
||||||
|
|
||||||
|
lint: deps-lint
|
||||||
|
@$(ANALYZER_ENV) $(STATICCHECK) ./... | scripts/analyzer-gate.sh staticcheck
|
||||||
|
|
||||||
|
deadcode: deps-lint
|
||||||
|
@$(ANALYZER_ENV) $(DEADCODE) -test ./... | scripts/analyzer-gate.sh deadcode
|
||||||
|
|
||||||
|
# Every static gate in one command. Not `check`, because it is not the thing to
|
||||||
|
# run before a commit: vuln reads the network and all three are slow.
|
||||||
|
analyze: lint deadcode vuln
|
||||||
|
|
||||||
# Run the tidy the sentinel makes possible. Not part of `test`: it rewrites
|
# Run the tidy the sentinel makes possible. Not part of `test`: it rewrites
|
||||||
# go.mod, and a build target that edits the module file is a surprise.
|
# go.mod, and a build target that edits the module file is a surprise.
|
||||||
# vendor/ is committed, so a tidy that drops a requirement must be followed by
|
# vendor/ is committed, so a tidy that drops a requirement must be followed by
|
||||||
|
|||||||
@@ -21,12 +21,14 @@ caveat is the pointer between them plus the trigger.
|
|||||||
## Index
|
## Index
|
||||||
|
|
||||||
Every entry below came from the 2026-08-10 deep audit
|
Every entry below came from the 2026-08-10 deep audit
|
||||||
(`docs/evals/2026-08-10-repo-audit.md`). One of the twenty findings, the
|
(`docs/evals/2026-08-10-repo-audit.md`), except the last, which came from wiring
|
||||||
unauthenticated mavgpud proxy, was fixed as V-673 and has no entry.
|
the gate the audit asked for. Three of the twenty findings are fixed and have no
|
||||||
|
entry. The unauthenticated mavgpud proxy was V-673. The 20 reachable advisories
|
||||||
|
in the toolchain and `x/text` were V-682. The missing analyzers were V-694, and
|
||||||
|
what they now report is the baseline entry under V-701.
|
||||||
|
|
||||||
| limit | severity |
|
| limit | severity |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| [Go 1.25.5 and x/text 0.14.0 carry 20 reachable advisories](dependencies.md#toolchain) | high |
|
|
||||||
| [Anyone past the proxy can enroll a passkey](security.md#enrollment) | high |
|
| [Anyone past the proxy can enroll a passkey](security.md#enrollment) | high |
|
||||||
| [Passkey credentials are rewritten in place](security.md#credentials) | medium |
|
| [Passkey credentials are rewritten in place](security.md#credentials) | medium |
|
||||||
| [An empty STT transcript reads as a successful one](external-inputs.md#stt) | medium |
|
| [An empty STT transcript reads as a successful one](external-inputs.md#stt) | medium |
|
||||||
@@ -43,5 +45,6 @@ unauthenticated mavgpud proxy, was fixed as V-673 and has no entry.
|
|||||||
| [baselineGrammars is mirrored by hand](invariants.md#grammars) | medium |
|
| [baselineGrammars is mirrored by hand](invariants.md#grammars) | medium |
|
||||||
| [Committed absolute paths pin the build to this box](config.md#paths) | medium |
|
| [Committed absolute paths pin the build to this box](config.md#paths) | medium |
|
||||||
| [The env example omits deployed variables](config.md#secrets) | medium |
|
| [The env example omits deployed variables](config.md#secrets) | medium |
|
||||||
|
| [The analyzers pass against a baseline, not zero](dependencies.md#baseline) | medium |
|
||||||
| [Domain packages depend on store and IPC types](layering.md#dtos) | low |
|
| [Domain packages depend on store and IPC types](layering.md#dtos) | low |
|
||||||
| [Eleven symbols are unreachable](layering.md#deadcode) | low |
|
| [Eleven symbols are unreachable](layering.md#deadcode) | low |
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
# Dependencies
|
# Dependencies
|
||||||
|
|
||||||
## Go 1.25.5 and x/text 0.14.0 carry 20 reachable advisories [#682] {#toolchain}
|
## The analyzers pass against a baseline, not against zero [#701] {#baseline}
|
||||||
|
|
||||||
Costs: `govulncheck` found 20 reachable advisories, one in `x/text` and 19 in
|
Costs: `make lint` and `make deadcode` are wired and green (V-694), but green
|
||||||
the standard library. They include template XSS, parser denial of service and
|
means "nothing new since 2026-08-11". The accepted set is 19 staticcheck
|
||||||
TLS issues. Reachable traces run through the ONNX embedder's normalization,
|
findings and 13 unreachable symbols, listed with a reason each in
|
||||||
mavweb's HTML rendering, email header decoding and the mavgpud proxy. The
|
`scripts/analyzers/*.baseline`. Three of the unreachable symbols must stay:
|
||||||
vendored toolchain was built 2025-11-26.
|
[layering.md](layering.md#deadcode). One accepted staticcheck finding is V-687.
|
||||||
Revisit when: now. This is the highest-severity open entry and the fix is
|
Revisit when: V-701 sweeps the baseline, or a fix deletes an entry. The gate
|
||||||
mechanical, so it ages badly for no reason.
|
fails on an entry whose finding is gone, so the deletion is not optional.
|
||||||
Workaround: none.
|
Workaround: none needed. Reachability claims are checkable now. Read the
|
||||||
|
baseline before trusting that a target reporting clean means the tree is clean.
|
||||||
None of `staticcheck`, `govulncheck` or `deadcode` is installed on this box or
|
|
||||||
wired into a make target. `make audit` is a git-grep inventory over loc, todo,
|
|
||||||
stubs, docs, tests and gaps. **Do not read it as a static-analysis gate.** That
|
|
||||||
gate is part of this entry.
|
|
||||||
|
|||||||
+38
-1
@@ -1,6 +1,6 @@
|
|||||||
# Session workflow: the five stores and the guards
|
# Session workflow: the five stores and the guards
|
||||||
|
|
||||||
*Last verified: 2026-08-09 @ a9b480a*
|
*Last verified: 2026-08-11 @ 557f5a3*
|
||||||
|
|
||||||
How a session starts, where each kind of writing belongs, and what the hooks
|
How a session starts, where each kind of writing belongs, and what the hooks
|
||||||
refuse. `CLAUDE.md` carries the commands. This file carries the reasoning.
|
refuse. `CLAUDE.md` carries the commands. This file carries the reasoning.
|
||||||
@@ -78,3 +78,40 @@ blocks further edits past 600 changed lines on a `task/` branch.
|
|||||||
budget read high.
|
budget read high.
|
||||||
|
|
||||||
`--no-verify` exists. Using it means saying why in the commit body.
|
`--no-verify` exists. Using it means saying why in the commit body.
|
||||||
|
|
||||||
|
## Static gates
|
||||||
|
|
||||||
|
Three analyzers, one target each, and `make analyze` for all three. The
|
||||||
|
2026-08-10 audit asked for them because none was installed on the box and
|
||||||
|
`make audit` is a git-grep inventory, not analysis. Do not read `make audit` as
|
||||||
|
a gate.
|
||||||
|
|
||||||
|
- `make vuln`, govulncheck over `./...` (V-682).
|
||||||
|
- `make lint`, staticcheck over `./...` (V-694).
|
||||||
|
- `make deadcode`, deadcode with `-test` over `./...` (V-694).
|
||||||
|
|
||||||
|
None of the three joins `make test`. All three install over the network, and
|
||||||
|
`test` has to pass on a box with no route out. `vuln` reads the advisory
|
||||||
|
database at run time as well. Run `make analyze` before a dependency or
|
||||||
|
toolchain bump lands, and before calling a symbol unreachable.
|
||||||
|
|
||||||
|
Each tool is pinned in the Makefile beside `GO_VERSION`. A gate that moves on
|
||||||
|
its own is not a gate. Each installs into `deps/bin`, because a tool is not a
|
||||||
|
dependency of the module.
|
||||||
|
|
||||||
|
**staticcheck and deadcode pass against a baseline, not against zero.** The
|
||||||
|
accepted findings live in `scripts/analyzers/*.baseline`, one line each. A key
|
||||||
|
holds file, check id and message, never a line number. A line number goes stale
|
||||||
|
on the next edit above it. The output then reports moved findings as new ones,
|
||||||
|
and the reader learns to skip it.
|
||||||
|
|
||||||
|
`scripts/analyzer-gate.sh` gives the verdict. A finding absent from the baseline
|
||||||
|
fails. So does a baseline entry whose finding is gone, which is what stops the
|
||||||
|
accepted set from outliving the repo. Deleting the entry is part of each fix.
|
||||||
|
|
||||||
|
`deadcode` runs with `-test` because a test is a caller. Without the flag the
|
||||||
|
report is 172 lines, most of `internal/router/eval`, none of it a mistake.
|
||||||
|
|
||||||
|
A baseline entry carries the reason it stays. Three reasons appear. Another task
|
||||||
|
owns the finding. The check cannot see through a false positive. A cosmetic
|
||||||
|
finding waits for a sweep.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module github.com/kami/maven
|
module github.com/kami/maven
|
||||||
|
|
||||||
go 1.25.5
|
go 1.25.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/coder/websocket v1.8.12
|
github.com/coder/websocket v1.8.12
|
||||||
@@ -22,7 +22,7 @@ require (
|
|||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
golang.org/x/text v0.14.0
|
golang.org/x/text v0.40.0
|
||||||
modernc.org/libc v1.74.1 // indirect
|
modernc.org/libc v1.74.1 // indirect
|
||||||
modernc.org/mathutil v1.7.1 // indirect
|
modernc.org/mathutil v1.7.1 // indirect
|
||||||
modernc.org/memory v1.11.0 // indirect
|
modernc.org/memory v1.11.0 // indirect
|
||||||
|
|||||||
@@ -25,13 +25,13 @@ github.com/yalue/onnxruntime_go v1.31.0 h1:1ln4YW1SFOFfGJZXe3jNOb2JUSt+l2pEneZfV
|
|||||||
github.com/yalue/onnxruntime_go v1.31.0/go.mod h1:b4X26A8pekNb1ACJ58wAXgNKeUCGEAQ9dmACut9Sm/4=
|
github.com/yalue/onnxruntime_go v1.31.0/go.mod h1:b4X26A8pekNb1ACJ58wAXgNKeUCGEAQ9dmACut9Sm/4=
|
||||||
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
||||||
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
||||||
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek=
|
||||||
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
||||||
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
|
||||||
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
|
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
|
||||||
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
|
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
|
||||||
modernc.org/cc/v4 v4.29.0 h1:CXgwL8cvxmyzBQZzbSl/6xFtMCryb6u8IOqDci39cgc=
|
modernc.org/cc/v4 v4.29.0 h1:CXgwL8cvxmyzBQZzbSl/6xFtMCryb6u8IOqDci39cgc=
|
||||||
|
|||||||
Executable
+97
@@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# analyzer-gate.sh — turn an analyzer's output into a pass/fail verdict.
|
||||||
|
#
|
||||||
|
# The 2026-08-10 audit asked for staticcheck, govulncheck and deadcode
|
||||||
|
# (V-694). govulncheck needed no gate of this shape because it already
|
||||||
|
# reported zero after the toolchain bump. The other two do not: staticcheck
|
||||||
|
# reports 20 findings today and deadcode reports 11 unreachable symbols, and
|
||||||
|
# three of those eleven are deliberate. A target that fails on the first run
|
||||||
|
# is not a gate, it is a target nobody runs. So the accepted set is written
|
||||||
|
# down, and only what is NOT in it fails.
|
||||||
|
#
|
||||||
|
# staticcheck ./... | scripts/analyzer-gate.sh staticcheck
|
||||||
|
# deadcode -test ./... | scripts/analyzer-gate.sh deadcode
|
||||||
|
#
|
||||||
|
# The baseline is keyed on file, check id and message, never on line number.
|
||||||
|
# A key carrying a line number goes stale on the next edit above it and then
|
||||||
|
# reports moved findings as new ones, which trains the reader to ignore it.
|
||||||
|
# The cost of dropping the line is that two identical findings in one file
|
||||||
|
# share one key, so the second is accepted with the first. That is the right
|
||||||
|
# way round: the same check firing twice on the same file is one thing to fix.
|
||||||
|
#
|
||||||
|
# A baseline entry with no finding left also fails. Fixing something and
|
||||||
|
# leaving its entry behind is how the accepted set stops describing the repo.
|
||||||
|
# The fix is one line: delete the entry the failure names.
|
||||||
|
#
|
||||||
|
# Reads stdin, writes a report, never writes a file.
|
||||||
|
|
||||||
|
set -uo pipefail
|
||||||
|
cd "$(dirname "$0")/.." || exit 1
|
||||||
|
|
||||||
|
tool="${1:?usage: analyzer-gate.sh <staticcheck|deadcode>}"
|
||||||
|
baseline="scripts/analyzers/$tool.baseline"
|
||||||
|
[ -f "$baseline" ] || { printf 'analyzer-gate: no baseline at %s\n' "$baseline" >&2; exit 2; }
|
||||||
|
|
||||||
|
# Normalise to "<file>\t<id>\t<message>". Anything that does not parse is an
|
||||||
|
# analyzer error, not a finding, and it fails without consulting the baseline.
|
||||||
|
# staticcheck: path.go:12:34: message (SA1234)
|
||||||
|
# deadcode: path.go:12:34: unreachable func: Symbol
|
||||||
|
found=$(mktemp) || exit 2
|
||||||
|
malformed=$(mktemp) || exit 2
|
||||||
|
trap 'rm -f "$found" "$malformed"' EXIT
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
[ -n "$line" ] || continue
|
||||||
|
case "$tool" in
|
||||||
|
staticcheck)
|
||||||
|
if [[ "$line" =~ ^([^:]+):[0-9]+:[0-9]+:\ (.*)\ \(([A-Z]+[0-9]+)\)$ ]]; then
|
||||||
|
# SA1019 ends its message with a space. Trim, so no baseline entry
|
||||||
|
# depends on trailing whitespace surviving an editor.
|
||||||
|
msg="${BASH_REMATCH[2]}"
|
||||||
|
printf '%s\t%s\t%s\n' "${BASH_REMATCH[1]}" "${BASH_REMATCH[3]}" "${msg%"${msg##*[![:space:]]}"}" >>"$found"
|
||||||
|
else
|
||||||
|
printf '%s\n' "$line" >>"$malformed"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
deadcode)
|
||||||
|
if [[ "$line" =~ ^([^:]+):[0-9]+:[0-9]+:\ unreachable\ func:\ (.*)$ ]]; then
|
||||||
|
printf '%s\tunreachable\t%s\n' "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" >>"$found"
|
||||||
|
else
|
||||||
|
printf '%s\n' "$line" >>"$malformed"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*) printf 'analyzer-gate: unknown tool %s\n' "$tool" >&2; exit 2 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -s "$malformed" ]; then
|
||||||
|
printf '%s: the analyzer said something that is not a finding:\n' "$tool" >&2
|
||||||
|
sed 's/^/ /' "$malformed" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
accepted=$(mktemp) || exit 2
|
||||||
|
trap 'rm -f "$found" "$malformed" "$accepted"' EXIT
|
||||||
|
grep -v '^[[:space:]]*\(#\|$\)' "$baseline" | sort -u >"$accepted"
|
||||||
|
sort -u "$found" -o "$found"
|
||||||
|
|
||||||
|
new=$(comm -23 "$found" "$accepted")
|
||||||
|
gone=$(comm -13 "$found" "$accepted")
|
||||||
|
status=0
|
||||||
|
|
||||||
|
if [ -n "$new" ]; then
|
||||||
|
printf '%s: %d finding(s) not in %s:\n' "$tool" "$(printf '%s\n' "$new" | wc -l)" "$baseline"
|
||||||
|
printf '%s\n' "$new" | sed 's/^/ /'
|
||||||
|
printf 'Fix it, or add the line to the baseline with the reason it stays.\n'
|
||||||
|
status=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$gone" ]; then
|
||||||
|
printf '%s: %d baseline entry/entries no longer found:\n' "$tool" "$(printf '%s\n' "$gone" | wc -l)"
|
||||||
|
printf '%s\n' "$gone" | sed 's/^/ /'
|
||||||
|
printf 'Delete them from %s.\n' "$baseline"
|
||||||
|
status=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ "$status" -eq 0 ] && printf '%s: clean against %d accepted finding(s)\n' "$tool" "$(wc -l <"$accepted")"
|
||||||
|
exit "$status"
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# deadcode — the unreachable symbols this repo accepts today.
|
||||||
|
#
|
||||||
|
# Keyed "<file>\t unreachable \t<symbol>", tab separated, no line numbers.
|
||||||
|
# Generated from the first gated run on 2026-08-11 and edited by hand since.
|
||||||
|
# `make deadcode` fails on anything absent here and on any entry left behind
|
||||||
|
# after its symbol is deleted.
|
||||||
|
#
|
||||||
|
# The gate runs with -test, so a test file counts as a root. Without it the
|
||||||
|
# whole of internal/router/eval is unreachable and the report is 172 lines of
|
||||||
|
# fixtures nobody wrote by mistake.
|
||||||
|
#
|
||||||
|
# Eleven of these are V-686, from the 2026-08-10 audit. Three of the eleven
|
||||||
|
# must stay and the audit says why: HisGender is a documented seam tied to
|
||||||
|
# V-399, AudioDuration should call internal/audio rather than be deleted, and
|
||||||
|
# CountWord is a safe delete. Read docs/caveats/layering.md#deadcode before
|
||||||
|
# removing any of them.
|
||||||
|
cmd/mavwaked/vad.go unreachable AudioDuration
|
||||||
|
cmd/mavwaked/vad.go unreachable PCMToF32
|
||||||
|
internal/crawl/watch.go unreachable Watcher.Watches
|
||||||
|
internal/phraser/confirm.go unreachable IsC
|
||||||
|
internal/phraser/eval/checks.go unreachable HisGender
|
||||||
|
internal/phraser/plural.go unreachable CountWord
|
||||||
|
internal/update/update.go unreachable WithClock
|
||||||
|
internal/voice/errors.go unreachable jsonMarshal
|
||||||
|
internal/voice/errors.go unreachable jsonUnmarshal
|
||||||
|
internal/webauthn/cbor.go unreachable cborValue.At
|
||||||
|
internal/worker/server.go unreachable Server.SetSynthesizer
|
||||||
|
|
||||||
|
# Two test helpers the audit did not count, because it listed production
|
||||||
|
# symbols only. A helper no test calls is dead the same way.
|
||||||
|
cmd/mavend/replier_llm_test.go unreachable assertStub
|
||||||
|
cmd/mavwaked/vad_test.go unreachable frameRMSQuick
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# staticcheck — the findings this repo accepts today.
|
||||||
|
#
|
||||||
|
# Keyed "<file>\t<check>\t<message>", tab separated, no line numbers.
|
||||||
|
# Generated from the first gated run on 2026-08-11 and edited by hand since.
|
||||||
|
# `make lint` fails on anything absent here and on any entry left behind after
|
||||||
|
# its finding is fixed, so emptying this file is done one line at a time.
|
||||||
|
#
|
||||||
|
# The sweep that empties it is V-701, which carries the judgement on each
|
||||||
|
# entry. What follows is the short reason only.
|
||||||
|
|
||||||
|
# V-687. The dedupe check runs after the phraser has already been paid.
|
||||||
|
cmd/mavend/tick_digest.go SA4006 this value of deduped is never used
|
||||||
|
|
||||||
|
# V-686, the eleven unreachable symbols the 2026-08-10 audit listed, seen from
|
||||||
|
# the other side. Three of them must stay: docs/caveats/layering.md#deadcode.
|
||||||
|
cmd/mavend/replier_llm_test.go U1000 func assertStub is unused
|
||||||
|
cmd/mavwaked/vad_test.go U1000 func frameRMSQuick is unused
|
||||||
|
cmd/mavweb/handlers_test.go U1000 field signalErr is unused
|
||||||
|
internal/voice/errors.go U1000 func jsonMarshal is unused
|
||||||
|
internal/voice/errors.go U1000 func jsonUnmarshal is unused
|
||||||
|
|
||||||
|
# False positives, checked. The code is right and the check cannot see why.
|
||||||
|
# RenderICal is called twice because rendering twice is the assertion. The
|
||||||
|
# morning loop reads the first rune after the hedge and breaks on purpose. The
|
||||||
|
# task_phrases line is prose about //go:embed and the real directive is below it.
|
||||||
|
internal/calendar/ical_render_test.go SA4000 identical expressions on the left and right side of the '!=' operator
|
||||||
|
internal/morning/plan_test.go SA4004 the surrounding loop is unconditionally terminated
|
||||||
|
internal/router/task_phrases.go SA9009 ineffectual compiler directive due to extraneous space: "// go:embed, so the single-binary deploy is unchanged: the JSON is compiled into"
|
||||||
|
|
||||||
|
# At EOF the wake loop trims partial and returns, so audio past one frame is
|
||||||
|
# dropped. Harmless where it sits, misleading to read. V-701.
|
||||||
|
cmd/mavwaked/main.go SA4006 this value of partial is never used
|
||||||
|
|
||||||
|
# Cosmetic and mechanical. V-701 sweeps them.
|
||||||
|
cmd/mavweb/voiceproxy.go ST1013 should use constant http.StatusMethodNotAllowed instead of numeric literal 405
|
||||||
|
cmd/mavweb/voiceproxy.go ST1013 should use constant http.StatusServiceUnavailable instead of numeric literal 503
|
||||||
|
internal/ipc/client.go S1016 should convert r (type chatResp) to ChatReply instead of using struct literal
|
||||||
|
internal/ipc/server.go S1016 should convert reply (type ChatReply) to chatResp instead of using struct literal
|
||||||
|
internal/memory/behavior_test.go S1011 should replace loop with obs = append(obs, habitHistory("calendar_event_20260804_standup", time.Tuesday, 10, 0, 3, now)...)
|
||||||
|
internal/memory/behavior_test.go S1011 should replace loop with obs = append(obs, habitHistory("cooldown:water", time.Tuesday, 9, 0, 3, now)...)
|
||||||
|
cmd/mavend/continuation_test.go SA1012 do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use
|
||||||
|
|
||||||
|
# Deprecated since Go 1.25. Replacing it means rewriting both guards on
|
||||||
|
# golang.org/x/tools/go/packages, which is a decision and not a sweep.
|
||||||
|
internal/ipc/maperr_test.go SA1019 parser.ParseDir has been deprecated since Go 1.25 and an alternative has been available since Go 1.11: ParseDir does not consider build tags when associating files with packages. For precise information about the relationship between packages and files, use golang.org/x/tools/go/packages, which can also optionally parse and type-check the files too.
|
||||||
|
internal/phraser/persona_floor_test.go SA1019 parser.ParseDir has been deprecated since Go 1.25 and an alternative has been available since Go 1.11: ParseDir does not consider build tags when associating files with packages. For precise information about the relationship between packages and files, use golang.org/x/tools/go/packages, which can also optionally parse and type-check the files too.
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
Copyright 2009 The Go Authors.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
modification, are permitted provided that the following conditions are
|
modification, are permitted provided that the following conditions are
|
||||||
@@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer.
|
|||||||
copyright notice, this list of conditions and the following disclaimer
|
copyright notice, this list of conditions and the following disclaimer
|
||||||
in the documentation and/or other materials provided with the
|
in the documentation and/or other materials provided with the
|
||||||
distribution.
|
distribution.
|
||||||
* Neither the name of Google Inc. nor the names of its
|
* Neither the name of Google LLC nor the names of its
|
||||||
contributors may be used to endorse or promote products derived from
|
contributors may be used to endorse or promote products derived from
|
||||||
this software without specific prior written permission.
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
|||||||
+26
-9
@@ -13,15 +13,18 @@ import "encoding/binary"
|
|||||||
// a rune to a uint16. The values take two forms. For v >= 0x8000:
|
// a rune to a uint16. The values take two forms. For v >= 0x8000:
|
||||||
// bits
|
// bits
|
||||||
// 15: 1 (inverse of NFD_QC bit of qcInfo)
|
// 15: 1 (inverse of NFD_QC bit of qcInfo)
|
||||||
// 13..7: qcInfo (see below). isYesD is always true (no decomposition).
|
// 12..7: qcInfo (see below). isYesD is always true (no decomposition).
|
||||||
// 6..0: ccc (compressed CCC value).
|
// 6..0: ccc (compressed CCC value).
|
||||||
// For v < 0x8000, the respective rune has a decomposition and v is an index
|
// For v < 0x8000, the respective rune has a decomposition and v is an index
|
||||||
// into a byte array of UTF-8 decomposition sequences and additional info and
|
// into a byte array of UTF-8 decomposition sequences and additional info and
|
||||||
// has the form:
|
// has the form:
|
||||||
// <header> <decomp_byte>* [<tccc> [<lccc>]]
|
// <header> <decomp_byte>* [<tccc> [<lccc>]]
|
||||||
// The header contains the number of bytes in the decomposition (excluding this
|
// The header contains the number of bytes in the decomposition (excluding this
|
||||||
// length byte). The two most significant bits of this length byte correspond
|
// length byte), with 33 mapped to 31 to fit in 5 bits.
|
||||||
// to bit 5 and 4 of qcInfo (see below). The byte sequence itself starts at v+1.
|
// (If any 31- or 32-byte decompositions come along, we could switch to using
|
||||||
|
// use a general lookup table as long as there are at most 32 distinct lengths.)
|
||||||
|
// The three most significant bits of this length byte correspond
|
||||||
|
// to bit 5, 4, and 3 of qcInfo (see below). The byte sequence itself starts at v+1.
|
||||||
// The byte sequence is followed by a trailing and leading CCC if the values
|
// The byte sequence is followed by a trailing and leading CCC if the values
|
||||||
// for these are not zero. The value of v determines which ccc are appended
|
// for these are not zero. The value of v determines which ccc are appended
|
||||||
// to the sequences. For v < firstCCC, there are none, for v >= firstCCC,
|
// to the sequences. For v < firstCCC, there are none, for v >= firstCCC,
|
||||||
@@ -32,8 +35,8 @@ import "encoding/binary"
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
qcInfoMask = 0x3F // to clear all but the relevant bits in a qcInfo
|
qcInfoMask = 0x3F // to clear all but the relevant bits in a qcInfo
|
||||||
headerLenMask = 0x3F // extract the length value from the header byte
|
headerLenMask = 0x1F // extract the length value from the header byte (31 => 33)
|
||||||
headerFlagsMask = 0xC0 // extract the qcInfo bits from the header byte
|
headerFlagsMask = 0xE0 // extract the qcInfo bits from the header byte
|
||||||
)
|
)
|
||||||
|
|
||||||
// Properties provides access to normalization properties of a rune.
|
// Properties provides access to normalization properties of a rune.
|
||||||
@@ -109,17 +112,21 @@ func (p Properties) BoundaryAfter() bool {
|
|||||||
return p.isInert()
|
return p.isInert()
|
||||||
}
|
}
|
||||||
|
|
||||||
// We pack quick check data in 4 bits:
|
// We pack quick check data in 6 bits:
|
||||||
//
|
//
|
||||||
// 5: Combines forward (0 == false, 1 == true)
|
// 5: Combines forward (0 == false, 1 == true)
|
||||||
// 4..3: NFC_QC Yes(00), No (10), or Maybe (11)
|
// 4..3: NFC_QC Yes(00), No (10), or Maybe (11)
|
||||||
// 2: NFD_QC Yes (0) or No (1). No also means there is a decomposition.
|
// 2: NFD_QC Yes (0) or No (1). No also means there is a decomposition.
|
||||||
// 1..0: Number of trailing non-starters.
|
// 1..0: Number of trailing non-starters.
|
||||||
//
|
//
|
||||||
// When all 4 bits are zero, the character is inert, meaning it is never
|
// When all 6 bits are zero, the character is inert, meaning it is never
|
||||||
// influenced by normalization.
|
// influenced by normalization.
|
||||||
|
//
|
||||||
|
// We set flags to 0x80 (high bit 7 unused in quick check data) to indicate an invalid rune.
|
||||||
type qcInfo uint8
|
type qcInfo uint8
|
||||||
|
|
||||||
|
func (p Properties) isInvalid() bool { return p.flags == 0x80 }
|
||||||
|
|
||||||
func (p Properties) isYesC() bool { return p.flags&0x10 == 0 }
|
func (p Properties) isYesC() bool { return p.flags&0x10 == 0 }
|
||||||
func (p Properties) isYesD() bool { return p.flags&0x4 == 0 }
|
func (p Properties) isYesD() bool { return p.flags&0x4 == 0 }
|
||||||
|
|
||||||
@@ -152,6 +159,9 @@ func (p Properties) Decomposition() []byte {
|
|||||||
}
|
}
|
||||||
i := p.index
|
i := p.index
|
||||||
n := decomps[i] & headerLenMask
|
n := decomps[i] & headerLenMask
|
||||||
|
if n == 31 {
|
||||||
|
n = 33
|
||||||
|
}
|
||||||
i++
|
i++
|
||||||
return decomps[i : i+uint16(n)]
|
return decomps[i : i+uint16(n)]
|
||||||
}
|
}
|
||||||
@@ -241,6 +251,9 @@ func (f Form) PropertiesString(s string) Properties {
|
|||||||
// to a Properties. See the comment at the top of the file
|
// to a Properties. See the comment at the top of the file
|
||||||
// for more information on the format.
|
// for more information on the format.
|
||||||
func compInfo(v uint16, sz int) Properties {
|
func compInfo(v uint16, sz int) Properties {
|
||||||
|
if sz == 0 {
|
||||||
|
return Properties{flags: 0x80, size: 1}
|
||||||
|
}
|
||||||
if v == 0 {
|
if v == 0 {
|
||||||
return Properties{size: uint8(sz)}
|
return Properties{size: uint8(sz)}
|
||||||
} else if v >= 0x8000 {
|
} else if v >= 0x8000 {
|
||||||
@@ -248,7 +261,7 @@ func compInfo(v uint16, sz int) Properties {
|
|||||||
size: uint8(sz),
|
size: uint8(sz),
|
||||||
ccc: uint8(v),
|
ccc: uint8(v),
|
||||||
tccc: uint8(v),
|
tccc: uint8(v),
|
||||||
flags: qcInfo(v >> 8),
|
flags: qcInfo(v>>8) & 0x3f,
|
||||||
}
|
}
|
||||||
if p.ccc > 0 || p.combinesBackward() {
|
if p.ccc > 0 || p.combinesBackward() {
|
||||||
p.nLead = uint8(p.flags & 0x3)
|
p.nLead = uint8(p.flags & 0x3)
|
||||||
@@ -260,7 +273,11 @@ func compInfo(v uint16, sz int) Properties {
|
|||||||
f := (qcInfo(h&headerFlagsMask) >> 2) | 0x4
|
f := (qcInfo(h&headerFlagsMask) >> 2) | 0x4
|
||||||
p := Properties{size: uint8(sz), flags: f, index: v}
|
p := Properties{size: uint8(sz), flags: f, index: v}
|
||||||
if v >= firstCCC {
|
if v >= firstCCC {
|
||||||
v += uint16(h&headerLenMask) + 1
|
n := uint16(h & headerLenMask)
|
||||||
|
if n == 31 {
|
||||||
|
n = 33
|
||||||
|
}
|
||||||
|
v += n + 1
|
||||||
c := decomps[v]
|
c := decomps[v]
|
||||||
p.tccc = c >> 2
|
p.tccc = c >> 2
|
||||||
p.flags |= qcInfo(c & 0x3)
|
p.flags |= qcInfo(c & 0x3)
|
||||||
|
|||||||
+2
-6
@@ -376,16 +376,12 @@ func nextComposed(i *Iter) []byte {
|
|||||||
goto doNorm
|
goto doNorm
|
||||||
}
|
}
|
||||||
prevCC = i.info.tccc
|
prevCC = i.info.tccc
|
||||||
sz := int(i.info.size)
|
p := outp + int(i.info.size)
|
||||||
if sz == 0 {
|
|
||||||
sz = 1 // illegal rune: copy byte-by-byte
|
|
||||||
}
|
|
||||||
p := outp + sz
|
|
||||||
if p > len(i.buf) {
|
if p > len(i.buf) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
outp = p
|
outp = p
|
||||||
i.p += sz
|
i.p += int(i.info.size)
|
||||||
if i.p >= i.rb.nsrc {
|
if i.p >= i.rb.nsrc {
|
||||||
i.setDone()
|
i.setDone()
|
||||||
break
|
break
|
||||||
|
|||||||
+10
-10
@@ -148,7 +148,7 @@ func (f Form) IsNormalString(s string) bool {
|
|||||||
// patched buffer and whether the decomposition is still in progress.
|
// patched buffer and whether the decomposition is still in progress.
|
||||||
func patchTail(rb *reorderBuffer) bool {
|
func patchTail(rb *reorderBuffer) bool {
|
||||||
info, p := lastRuneStart(&rb.f, rb.out)
|
info, p := lastRuneStart(&rb.f, rb.out)
|
||||||
if p == -1 || info.size == 0 {
|
if p == -1 || info.isInvalid() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
end := p + int(info.size)
|
end := p + int(info.size)
|
||||||
@@ -225,7 +225,7 @@ func doAppend(rb *reorderBuffer, out []byte, p int) []byte {
|
|||||||
}
|
}
|
||||||
fd := &rb.f
|
fd := &rb.f
|
||||||
if doMerge {
|
if doMerge {
|
||||||
var info Properties
|
info := Properties{flags: 0x80, size: 1} // invalid rune
|
||||||
if p < n {
|
if p < n {
|
||||||
info = fd.info(src, p)
|
info = fd.info(src, p)
|
||||||
if !info.BoundaryBefore() || info.nLeadingNonStarters() > 0 {
|
if !info.BoundaryBefore() || info.nLeadingNonStarters() > 0 {
|
||||||
@@ -235,7 +235,7 @@ func doAppend(rb *reorderBuffer, out []byte, p int) []byte {
|
|||||||
p = decomposeSegment(rb, p, true)
|
p = decomposeSegment(rb, p, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if info.size == 0 {
|
if info.isInvalid() {
|
||||||
rb.doFlush()
|
rb.doFlush()
|
||||||
// Append incomplete UTF-8 encoding.
|
// Append incomplete UTF-8 encoding.
|
||||||
return src.appendSlice(rb.out, p, n)
|
return src.appendSlice(rb.out, p, n)
|
||||||
@@ -314,7 +314,7 @@ func (f *formInfo) quickSpan(src input, i, end int, atEOF bool) (n int, ok bool)
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
info := f.info(src, i)
|
info := f.info(src, i)
|
||||||
if info.size == 0 {
|
if info.isInvalid() {
|
||||||
if atEOF {
|
if atEOF {
|
||||||
// include incomplete runes
|
// include incomplete runes
|
||||||
return n, true
|
return n, true
|
||||||
@@ -379,7 +379,7 @@ func (f Form) firstBoundary(src input, nsrc int) int {
|
|||||||
// CGJ insertion points correctly. Luckily it doesn't have to.
|
// CGJ insertion points correctly. Luckily it doesn't have to.
|
||||||
for {
|
for {
|
||||||
info := fd.info(src, i)
|
info := fd.info(src, i)
|
||||||
if info.size == 0 {
|
if info.isInvalid() {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
if s := ss.next(info); s != ssSuccess {
|
if s := ss.next(info); s != ssSuccess {
|
||||||
@@ -424,7 +424,7 @@ func (f Form) nextBoundary(src input, nsrc int, atEOF bool) int {
|
|||||||
}
|
}
|
||||||
fd := formTable[f]
|
fd := formTable[f]
|
||||||
info := fd.info(src, 0)
|
info := fd.info(src, 0)
|
||||||
if info.size == 0 {
|
if info.isInvalid() {
|
||||||
if atEOF {
|
if atEOF {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
@@ -435,7 +435,7 @@ func (f Form) nextBoundary(src input, nsrc int, atEOF bool) int {
|
|||||||
|
|
||||||
for i := int(info.size); i < nsrc; i += int(info.size) {
|
for i := int(info.size); i < nsrc; i += int(info.size) {
|
||||||
info = fd.info(src, i)
|
info = fd.info(src, i)
|
||||||
if info.size == 0 {
|
if info.isInvalid() {
|
||||||
if atEOF {
|
if atEOF {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
@@ -465,7 +465,7 @@ func lastBoundary(fd *formInfo, b []byte) int {
|
|||||||
if p == -1 {
|
if p == -1 {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
if info.size == 0 { // ends with incomplete rune
|
if info.isInvalid() { // ends with incomplete rune
|
||||||
if p == 0 { // starts with incomplete rune
|
if p == 0 { // starts with incomplete rune
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
@@ -504,7 +504,7 @@ func lastBoundary(fd *formInfo, b []byte) int {
|
|||||||
func decomposeSegment(rb *reorderBuffer, sp int, atEOF bool) int {
|
func decomposeSegment(rb *reorderBuffer, sp int, atEOF bool) int {
|
||||||
// Force one character to be consumed.
|
// Force one character to be consumed.
|
||||||
info := rb.f.info(rb.src, sp)
|
info := rb.f.info(rb.src, sp)
|
||||||
if info.size == 0 {
|
if info.isInvalid() {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
if s := rb.ss.next(info); s == ssStarter {
|
if s := rb.ss.next(info); s == ssStarter {
|
||||||
@@ -528,7 +528,7 @@ func decomposeSegment(rb *reorderBuffer, sp int, atEOF bool) int {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
info = rb.f.info(rb.src, sp)
|
info = rb.f.info(rb.src, sp)
|
||||||
if info.size == 0 {
|
if info.isInvalid() {
|
||||||
if !atEOF {
|
if !atEOF {
|
||||||
return int(iShortSrc)
|
return int(iShortSrc)
|
||||||
}
|
}
|
||||||
|
|||||||
-7657
File diff suppressed because it is too large
Load Diff
-7693
File diff suppressed because it is too large
Load Diff
-7710
File diff suppressed because it is too large
Load Diff
+1478
-1478
File diff suppressed because it is too large
Load Diff
Generated
Vendored
+3532
-3188
File diff suppressed because it is too large
Load Diff
-7637
File diff suppressed because it is too large
Load Diff
Vendored
+2
-2
@@ -40,8 +40,8 @@ github.com/yalue/onnxruntime_go
|
|||||||
## explicit; go 1.25.0
|
## explicit; go 1.25.0
|
||||||
golang.org/x/sys/unix
|
golang.org/x/sys/unix
|
||||||
golang.org/x/sys/windows
|
golang.org/x/sys/windows
|
||||||
# golang.org/x/text v0.14.0
|
# golang.org/x/text v0.40.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.25.0
|
||||||
golang.org/x/text/transform
|
golang.org/x/text/transform
|
||||||
golang.org/x/text/unicode/norm
|
golang.org/x/text/unicode/norm
|
||||||
# modernc.org/libc v1.74.1
|
# modernc.org/libc v1.74.1
|
||||||
|
|||||||
Reference in New Issue
Block a user