mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
* feat(b3-6): contract drift — generated route, table and config-key indexes B3-6 item 9 (workstream 10). `check:server` already diffs the two generators; this adds a third for the three server contracts that only prose described until now. `Server/cmd/gendocs` rewrites one marked block per document: - `docs/api.md` "Route index (generated)" — 111 rows from `chi.Walk` over the production router built with uploads, voice and the GIF proxy on, the same scaffolding `api/absence_contract_test.go` uses. Carries that test's vacuity guards: fewer than 100 routes, or no `/admin/` route, fails the run. - `docs/schema.md` "Table index (generated)" — 34 rows from `sqlite_master` and `pragma_table_info` on an in-memory database with the migrations applied. sqlc exposes no catalog, so the migrated schema is the catalog. - `docs/server-configuration.md` "Key index (generated)" — 56 keys from the koanf struct tags, each mapped to the `###` section of the hand-written reference that names it. A key documented nowhere fails the run by name. Output is padded exactly the way Prettier formats a table, so the drift check and the hygiene gate agree instead of undoing each other. Wiring, copied from protocol-verify: `make docs-generate` / `make docs-verify`, a `DOCS_VERIFY` step in `check:server` and the generator in `generate` (`scripts/run.mjs`), a CI step on the ubuntu leg of `server-build-test`, and a `.githooks/pre-commit` block on router, handler, migration, config and generator paths. Everything hand-written in the three documents is untouched. The new `cmd/gendocs` file imports `db` for the catalog, so it takes a boundary row in the B3-0 inventory and `server-boundaries.md` is regenerated with it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmiqjgTuov1stBTB6uGkvo * docs(b3-6): evidence block for item 9 (machine-readable contract drift) Records the three RED controls and their restore, the counts (111 routes, 34 tables, 56 config keys, 0 undocumented), and two corrections to the item's spec: the configuration reference table lives in docs/server-configuration.md, not docs/deployment.md, and sqlc exposes no catalog — the migrated in-memory schema is the catalog. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmiqjgTuov1stBTB6uGkvo * fix(b3-6): gendocs — exclude ANALYZE artifacts, honest hook message, admin routes trigger the hook, generate order, width ceiling Review findings on item 9. 1. The table index dropped `sqlite_stat1` / `sqlite_stat4`. `db.Migrate` runs ANALYZE after applying migrations, so those hold planner statistics, not schema — and `sqlite_stat4` exists only because the current modernc.org/sqlite build has STAT4, so a driver bump would have failed the docs drift check on an unrelated dependency PR. Filtered with GLOB (LIKE's `_` is a wildcard), block regenerated, header line's justification corrected: 34 -> 32 tables. 2. The pre-commit message now covers both failure modes — stale blocks are regenerated and staged, a key the tool named as undocumented is documented in docs/server-configuration.md. 3. `Server/admin/.*\.go` added to the hook's trigger: the 34 `/admin/api/*` routes are registered there, not in api/router.go, so a new admin route could commit stale docs locally. 4. `run.mjs` `generate` runs gendocs after `sqlc generate` — gendocs compiles the api package, which imports db/dbgen. 5. The vacuity guard now requires a traversed `/admin/api/` subroute rather than any `/admin/` path, which the per-method mount catch-alls satisfied on their own, so its message is true. `writeTable` gained a comment naming its ceiling: padding counts runes, Prettier counts display width, so a full-width cell would diverge — none exists in the generated content. Evidence block updated for the new table count. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmiqjgTuov1stBTB6uGkvo * fix(b3-6): gendocs — generate the route index from the full-tag build with telemetry on; the hook triggers on every api/ and admin/ Go file (Codex P2s on #1456) 1. `/metrics` was missing from the route index. It mounts only when `telemetry.PrometheusHandler()` returns non-nil (api/router.go:431-437), which needs the otel build tag AND telemetry enabled at runtime; the generator ran in the default build with telemetry unset, so the index omitted a production route. The route index is now the superset build. The scaffold config enables telemetry with the Prometheus exporter and the tool calls telemetry.Init the way main.go does, and every invocation passes -tags otel,wazero: Makefile docs-generate/docs-verify, scripts/run.mjs (DOCS_VERIFY and generate), .githooks/pre-commit, the regenCmd quoted into all three block header lines, and the CLAUDE.md row. ci.yml inherits it through `make docs-verify`. The route block's header line now says which build it came from and what is enabled. Rather than a build-tag constant, the tool checks the condition that actually gates the route: if telemetry.Init leaves no Prometheus handler it exits non-zero naming the tags, so the default build cannot quietly generate a short index. Nothing under Server/api or Server/admin carries a build constraint, so wazero adds and removes no route; it rides along so one build serves the whole repository. Route count 111 -> 121 (ten per-method rows for the /metrics mount, the same shape chi gives /admin and /livekit). 2. The pre-commit trigger named individual api/ files and missed client_update.go, whose MountClientUpdateRoute registers a route directly. It is now the whole of Server/api/ and Server/admin/ — naming files individually is how a trigger goes stale — plus the existing migrations/, config/config.go and cmd/gendocs/ patterns. Evidence block updated: route count and the tagged-build decision. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KmiqjgTuov1stBTB6uGkvo --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
125 lines
6.2 KiB
Bash
Executable File
125 lines
6.2 KiB
Bash
Executable File
#!/bin/sh
|
|
# OwnCord pre-commit hook — fast, staged-file-aware checks that mirror CI's
|
|
# cheapest gates so errors surface in seconds instead of a 15-minute CI run.
|
|
#
|
|
# Enable once per clone: npm run hooks:install (git config core.hooksPath .githooks)
|
|
# Bypass in an emergency: git commit --no-verify or OWNCORD_SKIP_HOOKS=1
|
|
# CI still enforces everything — bypassing only defers the failure.
|
|
|
|
[ "${OWNCORD_SKIP_HOOKS:-0}" = "1" ] && exit 0
|
|
|
|
repo_root=$(git rev-parse --show-toplevel) || exit 1
|
|
cd "$repo_root" || exit 1
|
|
|
|
staged=$(git diff --cached --name-only --diff-filter=ACMR)
|
|
[ -z "$staged" ] && exit 0
|
|
|
|
fail() {
|
|
printf '\npre-commit: FAIL: %s\n(bypass with --no-verify; CI will still enforce this)\n' "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
# ---------- Server (Go) ----------
|
|
go_staged=$(printf '%s\n' "$staged" | grep '^Server/.*\.go$' | grep -v '^Server/db/dbgen/')
|
|
if [ -n "$go_staged" ]; then
|
|
if command -v go >/dev/null 2>&1 && command -v gofmt >/dev/null 2>&1; then
|
|
# Word splitting is intended: repo paths contain no spaces.
|
|
# shellcheck disable=SC2086
|
|
unformatted=$(gofmt -l $go_staged)
|
|
[ -n "$unformatted" ] && fail "gofmt needed (run gofmt -w on): $unformatted"
|
|
(cd Server && go vet ./...) || fail "go vet"
|
|
else
|
|
printf 'pre-commit: WARNING: go/gofmt not installed; skipping Go checks.\n' >&2
|
|
fi
|
|
fi
|
|
|
|
# These two blocks inline what `make sqlc-verify` / `make protocol-verify` reduce
|
|
# to (Server/Makefile), rather than shelling out to make. `make` is not on PATH on
|
|
# a stock Windows box, and a guard on `go`/`sqlc` does not imply it: the old code
|
|
# probed one command and invoked another, so a contributor with Go but no make was
|
|
# told "protocol constants are stale" when nothing had been generated or compared.
|
|
|
|
# sqlc inputs changed -> regenerated db/dbgen must be part of the same commit.
|
|
if printf '%s\n' "$staged" | grep -qE '^Server/(db/queries/|migrations/|sqlc\.yaml|sqlc\.version)'; then
|
|
if command -v sqlc >/dev/null 2>&1; then
|
|
(cd Server && sqlc generate && git diff --exit-code db/dbgen) \
|
|
|| fail "db/dbgen is stale — run 'sqlc generate' in Server/ and stage the result"
|
|
else
|
|
printf 'pre-commit: WARNING: sqlc not installed; skipping the db/dbgen check. Install the version pinned in Server/sqlc.version. CI will run it.\n' >&2
|
|
fi
|
|
fi
|
|
|
|
# Protocol schema changed -> regenerated Go + TS constants must be in the same commit.
|
|
if printf '%s\n' "$staged" | grep -qE '^(protocol/schema\.json|Server/cmd/genprotocol/)'; then
|
|
if command -v go >/dev/null 2>&1; then
|
|
(cd Server && go run ./cmd/genprotocol \
|
|
&& git diff --exit-code ws/message_types.go ../Client/src/lib/protocolTypes.ts) \
|
|
|| fail "protocol constants are stale — run 'go run ./cmd/genprotocol' in Server/ and stage the result"
|
|
else
|
|
printf 'pre-commit: WARNING: go not installed; skipping the protocol-constants check. CI will run it.\n' >&2
|
|
fi
|
|
fi
|
|
|
|
# Any api/ or admin/ Go file, the migrations, the config or the generator
|
|
# changed -> the regenerated docs index blocks must be part of the same commit.
|
|
# The route trigger is deliberately the whole of api/ and admin/: routes are
|
|
# registered in router.go, in the *_handler.go files, in client_update.go's
|
|
# MountClientUpdateRoute, and in the admin package's own mux — naming files
|
|
# individually is how this goes stale.
|
|
#
|
|
# Inlined like the two blocks above, and for the same reason: make is not on
|
|
# PATH on a stock Windows box. -tags otel,wazero is the build the route index
|
|
# is generated from; the tool refuses to run without it.
|
|
if printf '%s\n' "$staged" | grep -qE '^Server/(api|admin)/.*\.go$|^Server/(migrations/|config/config\.go|cmd/gendocs/)'; then
|
|
if command -v go >/dev/null 2>&1; then
|
|
(cd Server && go run -tags otel,wazero ./cmd/gendocs \
|
|
&& git diff --exit-code ../docs/api.md ../docs/schema.md ../docs/server-configuration.md) \
|
|
|| fail "generated docs blocks are stale, or a config key is undocumented — if gendocs named keys above, document them in docs/server-configuration.md; otherwise run 'go run -tags otel,wazero ./cmd/gendocs' in Server/ and stage the result"
|
|
else
|
|
printf 'pre-commit: WARNING: go not installed; skipping the generated-docs check. CI will run it.\n' >&2
|
|
fi
|
|
fi
|
|
|
|
# Findings ledger changed -> it must still be valid. Unlike the two blocks
|
|
# above there is nothing to diff: FINDINGS.md is not tracked (RL-07), so a
|
|
# stale rendering cannot be committed. --check is the whole gate here, and it
|
|
# writes nothing. render-ledger.mjs is Node-stdlib-only, so `node` alone is the
|
|
# probe — no node_modules guard, unlike the prettier block below.
|
|
if printf '%s\n' "$staged" | grep -qE '^\.superpowers/(findings-ledger\.json|render-ledger\.mjs)$'; then
|
|
if command -v node >/dev/null 2>&1; then
|
|
node .superpowers/render-ledger.mjs --check \
|
|
|| fail "findings-ledger.json is invalid — see the INVALID lines above"
|
|
else
|
|
printf 'pre-commit: WARNING: node not installed; skipping the ledger check. CI will run it.\n' >&2
|
|
fi
|
|
fi
|
|
|
|
# ---------- Formatting (repository-wide) ----------
|
|
# Prettier is configured once at the repository root (.prettierrc.json) and
|
|
# covers every material tracked source, not just client TypeScript.
|
|
# --ignore-unknown drops the Go/Rust/binary paths it has no parser for.
|
|
if [ -d node_modules ]; then
|
|
# Word splitting is intended: repo paths contain no spaces.
|
|
# shellcheck disable=SC2086
|
|
npx prettier --check --ignore-unknown $staged || fail "prettier (run: npm run format)"
|
|
else
|
|
printf 'pre-commit: WARNING: node_modules missing at the repository root; skipping prettier.\n' >&2
|
|
fi
|
|
|
|
# ---------- Client (TypeScript) ----------
|
|
ts_staged=$(printf '%s\n' "$staged" | grep -E '^Client/(src|tests)/.*\.ts$' | grep -v '/generated/')
|
|
if [ -n "$ts_staged" ]; then
|
|
if [ ! -d Client/node_modules ]; then
|
|
printf 'pre-commit: WARNING: node_modules missing in Client; skipping client checks (run npm install there).\n' >&2
|
|
else
|
|
rel=$(printf '%s\n' "$ts_staged" | sed 's|^Client/||')
|
|
cd Client || exit 1
|
|
# shellcheck disable=SC2086
|
|
npx oxlint $rel || fail "oxlint"
|
|
npm run -s typecheck || fail "tsc --noEmit"
|
|
cd "$repo_root" || exit 1
|
|
fi
|
|
fi
|
|
|
|
exit 0
|