From 4d37e42c7bead5aeb1f71bd75232bc3e8a97204c Mon Sep 17 00:00:00 2001 From: Eric Andrechek Date: Fri, 11 Sep 2026 14:39:07 -0400 Subject: [PATCH] lint: nothing may cite a repository path that is not here (+ 11 that did) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lint-public.sh catches the private repository by NAME. This is the other half of the same failure: a path that is simply not in this repository. Neither rule would have caught the other's cases. WHAT WAS FOUND. `docs/proposals/rows-export.md` was cited SIX times — in include/chtypes.h and in the Go, Python, Rust and TypeScript sources, five of which ship inside the crate, the sdist, the module and the npm tarball (confirmed by unzipping the Go module from proxy.golang.org and building the sdist). The file is not here; it went to the core repository with the rest of the SDK-authoring material. Four more of the same shape: docs/defaults-matrix.md go/chtypes/transform.go, chtypes.go ships docs/type-coverage.md include/chtypes.h, chtypes.go ships docs/fetch.md 4 files + both parity JSONs (38x) moved under guides/ scripts/check-parity-doc.sh both parity JSONs never existed The last one is worth naming: the manifest said that script "asserts the two agree on the object-model table". The check is real and has been running all along — it lives in python/tests/test_parity.py — but anyone looking for it by the name given would have concluded there was no check. Where the surrounding prose already stated the rule, the dead citation is simply dropped rather than pointed somewhere a reader cannot go. docs/fetch.md became docs/guides/fetch.md, which exists and still has the cited §6. Also swept, same family: three `ci/steps/*` paths and one `tests/acceptance` /`tests/arbiter` pair that exist only in the private repository, and four citations of a `certify` workflow renamed to sdk-suites on 2026-09-11 — a stale name for another repository's workflow, now described instead of named. THE GUARD. scripts/lint-paths.sh resolves every cited repository path and fails on the ones that are not there, blocking in the existing `public` job (no new job, so no required-check rename). A path may resolve against the repository root or any of the four binding roots, because this repository is four sibling packages and a doc-comment inside rust/ naming tests/x.rs is correct. Skips are four, each for a reason and not to make the check pass: generated fixtures, .gitignore (patterns), Cargo.toml (crate-relative), and CHANGELOG.md (deliberately names removed things). `--selftest` proves it fires on a dead path AND stays silent on a live one and a crate-relative one — a rule that matches nothing passes silently, which is the failure this exists to prevent. It was also run against the real tree with two of the real dead citations planted back, and caught both. On its first run it caught 38 occurrences of docs/fetch.md that my own regex had missed, having fixed exactly one spelling of it. Unrelated, found by the docs read: docs/guides/batches.md gave the doc-flag constants as DOC_VALUES/DOC_TRANSFORMS/DOC_DEFAULTS, which is correct only for Python and TypeScript. Go spells them DocValues and Rust DocFlags::VALUES (per tests/parity/manifest.json, the machine-readable contract). A Go or Rust reader following that line would not compile. Now given per language. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_018ckJDLjWhAAttQVrYnQEJD --- .github/workflows/ci.yml | 15 ++++-- docs/guides/batches.md | 2 +- docs/reference/bindings.md | 2 +- go/chtypes/chtypes.go | 4 +- go/chtypes/linked.go | 7 +-- go/chtypes/multiversion.go | 4 +- go/chtypes/multiversion_test.go | 2 +- go/chtypes/parity_test.go | 2 +- go/chtypes/testdata/parity.json | 44 ++++++++-------- go/chtypes/transform.go | 1 - include/chtypes.h | 6 +-- python/pyproject.toml | 4 +- python/src/chtypes/registry.py | 5 +- python/tests/conftest.py | 2 +- rust/src/schema.rs | 3 +- rust/tests/parity.rs | 2 +- scripts/check-standalone.sh | 2 +- scripts/check-suite.sh | 2 +- scripts/lint-paths.sh | 89 +++++++++++++++++++++++++++++++++ tests/parity/manifest.json | 44 ++++++++-------- ts/src/schema.ts | 3 +- ts/test/chtypes.test.ts | 4 +- 22 files changed, 175 insertions(+), 74 deletions(-) create mode 100755 scripts/lint-paths.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1edde77..b086250 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -323,9 +323,10 @@ jobs: public: # BLOCKING, and a pure function of the diff. This repository is public; a # pointer into the private core repository is a dead end for every reader - # who is not us. The rules are two literal strings with no allowlist, so - # there is nothing to quietly grow — see scripts/lint-public.sh for why it - # exists and what to write instead. + # who is not us, and so is a path that is not in this repository at all. + # lint-public's rules are two literal strings with no allowlist; lint-paths + # resolves every cited repository path and fails on the ones that are not + # there. Each script's header says why it exists and what to write instead. name: "public — no pointers into the private repository" runs-on: ubuntu-latest timeout-minutes: 5 @@ -336,6 +337,14 @@ jobs: # to prevent, so prove both rules fire before trusting either verdict. - run: scripts/lint-public.sh --selftest - run: scripts/lint-public.sh + # The other half of the same failure. lint-public catches the private + # repository by NAME; lint-paths catches a citation of a path that is + # simply not here — which is how one proposals document that this + # repository does not contain was cited six times, from the C header and + # all four bindings' source, every one of which ships inside a published + # package. Selftest first, same reason. + - run: scripts/lint-paths.sh --selftest + - run: scripts/lint-paths.sh prose: # BLOCKING. It was report-only while the tree was still hard-wrapped, which diff --git a/docs/guides/batches.md b/docs/guides/batches.md index 34a7243..660e824 100644 --- a/docs/guides/batches.md +++ b/docs/guides/batches.md @@ -158,7 +158,7 @@ let batch = schema.rows_export( Three payload states, and they are distinct: absent means no export was requested, it was declined (the reason is in `export_declined`), or a call-level verdict preempted it; present-but-empty means the export ran and emitted nothing. The bytes are copied out of the C buffer and freed before the call returns, so no ownership crosses the boundary. -**Document flags** thin the _description_ without ever changing the _verdict_. Passing an export format defaults them to lean — verdicts only — because the usual reason to export is to forward bytes rather than to read a report. Ask for `DOC_VALUES`, `DOC_TRANSFORMS` or `DOC_DEFAULTS` back explicitly if you want them. A plain `rows` call is the all-flags spelling and stays byte-identical to what it always returned. +**Document flags** thin the _description_ without ever changing the _verdict_. Passing an export format defaults them to lean — verdicts only — because the usual reason to export is to forward bytes rather than to read a report. Ask for the values, transforms or defaults back explicitly if you want them — `DocValues` / `DocTransforms` / `DocDefaults` in Go, `DOC_VALUES` / `DOC_TRANSFORMS` / `DOC_DEFAULTS` in Python and TypeScript, `DocFlags::VALUES` / `DocFlags::TRANSFORMS` / `DocFlags::DEFAULTS` in Rust. A plain `rows` call is the all-flags spelling and stays byte-identical to what it always returned. ## Next diff --git a/docs/reference/bindings.md b/docs/reference/bindings.md index 5d5dd66..fb72c2f 100644 --- a/docs/reference/bindings.md +++ b/docs/reference/bindings.md @@ -50,7 +50,7 @@ A binding MAY additionally expose the statically linked, single-version shape (t At ABI revision 3 the C `chs_rows` gained `export_format`, `doc_flags` and `out_bytes`, and `chs_filter_compile` / `chs_filter_free` / `chs_filter_rows` joined the surface (§Filters). What that means for a binding: - **`Rows()` keeps today's behavior exactly**: one `chs_rows` call with `export_format = CHS_EXPORT_NONE` (`-1`) and `doc_flags = CHS_DOC_ALL` (`7`), `out_bytes = NULL`. The document that comes back is byte-identical to revision 2's, so nothing downstream moves. -- **`RowsExport()`** (per `docs/proposals/rows-export.md`: flags 0 by default, the bitmask exposed, `Payload []byte` + `Spans` from `out_bytes` + `row_spans`) and the filter SDK surface (`CompileFilter` / verdict types) were specified for the SDK cycle that FOLLOWS the C surface — this revision's bindings changes were the mechanical pass-through above and the hand-kept `ABI_REVISION` mirrors bumping to 3 in the same cycle, nothing more. One C call per SDK method, always; never a second call, never re-parsing. **That follow-on cycle has landed**, in all four bindings, at some point before the repository split squashed its history: the export channel and the filter surface are in the object-model table above and `tests/parity/manifest.json` enforces both. This paragraph is kept as the statement of the sequencing rule — the C surface first, the SDK surface in the cycle after — not as a description of what is missing. +- **`RowsExport()`** (flags 0 by default, the bitmask exposed, `Payload []byte` + `Spans` from `out_bytes` + `row_spans`) and the filter SDK surface (`CompileFilter` / verdict types) were specified for the SDK cycle that FOLLOWS the C surface — this revision's bindings changes were the mechanical pass-through above and the hand-kept `ABI_REVISION` mirrors bumping to 3 in the same cycle, nothing more. One C call per SDK method, always; never a second call, never re-parsing. **That follow-on cycle has landed**, in all four bindings, at some point before the repository split squashed its history: the export channel and the filter surface are in the object-model table above and `tests/parity/manifest.json` enforces both. This paragraph is kept as the statement of the sequencing rule — the C surface first, the SDK surface in the cycle after — not as a description of what is missing. - **Lean documents stay SDK-derivable.** Under `CHS_DOC_TRANSFORMS` without `CHS_DOC_VALUES` the C layer retains every `cols[]` entry any spec'd detector could fire on, with the full field set (the conservative byte-equality retention rule. A binding runs the SAME detectors of §Transformed over the retained entries — no new classifier exists on either side, and the reason vocabulary does not move into C. Under `CHS_DOC_VALUES` without `CHS_DOC_TRANSFORMS` the reference parse is skipped C-side (`ref` is `null`, no `wire`), so detectors 2 and 3 have nothing to run on — that is the caller's explicit choice, not data loss. - **Filter verdicts map to a four-state type, and two of the states are fail-closed.** `'t'`/`'f'` are answers; `'e'` (the predicate threw on this row — the server would have failed the whole query) and `'d'` (this library declines) are NOT answers, and a caller enforcing visibility MUST hide the row / fail the request on both. A binding MUST NOT collapse `'e'` or `'d'` into `false`-the-answer: under `NOT`, a decline-read-as-false inverts fail-closed into fail-open — the measured leak class. Unknown verdict characters degrade to the decline state, mirroring the unknown- `outcome` rule below. **No SDK may offer filter-backed read-side enforcement until the WHERE-truth rig gates green**; until then the surface is shadow/replay. - A filter handle wraps BOTH pointers' lifetimes: the SDK object MUST keep its schema object alive (a reference, not a copy) and free the filter before the schema — the C layer does not refcount. diff --git a/go/chtypes/chtypes.go b/go/chtypes/chtypes.go index 964938b..c992f31 100644 --- a/go/chtypes/chtypes.go +++ b/go/chtypes/chtypes.go @@ -291,7 +291,7 @@ const ( // vendored ISerialization::deserializeBinary — the reader // BinaryRowInputFormat uses. Framing faults are one code (33), batches // are all-or-nothing, and input_format_allow_errors_* never applies - // (docs/type-coverage.md §11). Requires an artifact built at or after the + // Requires an artifact built at or after the // RowBinary exposure; older artifacts reject with "unknown format". RowBinary // RowBinaryWithDefaults adds the measured per-column marker byte: any @@ -526,7 +526,7 @@ type RowResult struct { // ALIAS is deliberately absent. It is computable by exactly the same // machinery, and it is measured that `ALTER ... MODIFY COLUMN a ALIAS ` RETROACTIVELY CHANGES what already-inserted rows read back as - // (docs/defaults-matrix.md §6.5). An ALIAS is therefore a fact about + // An ALIAS is therefore a fact about // the schema at read time, not about the row, and this library will not // present one as a stored value. A caller that wants to show it must ask // the server, and must label it computed-at-read. diff --git a/go/chtypes/linked.go b/go/chtypes/linked.go index c3055f7..e48ea67 100644 --- a/go/chtypes/linked.go +++ b/go/chtypes/linked.go @@ -23,8 +23,8 @@ package chtypes // carries a copy it asserts identical at build time. WHERE the library is // comes from outside: this file names only `-lchtypes`, and the caller that // wants the linked path supplies the search path and a build-tree rpath -// through CGO_LDFLAGS (the core repo's ci/steps/_lib.sh `linked_env` sets -// them to its lib/build; `CHTYPES_LIB_BUILD` names the same directory for +// through CGO_LDFLAGS (the core repository's build tooling sets them to +// its build tree; `CHTYPES_LIB_BUILD` names the same directory for // unsafe_families.txt discovery). A shipped binary needs an rpath relative // to itself, or the RUNPATH points at the builder's filesystem and the // library is unfindable in a runtime image: Linux is the shipping target, @@ -840,7 +840,8 @@ func (cs *CompiledSchema) Rows(format Format, body []byte, settings map[string]s // RowsExport is Rows with the revision-3 export and document-flag channels // exposed: ONE chs_rows call, never a second, never re-parsing -// (docs/proposals/rows-export.md; the C ABI contract §Rows is normative). +// (the C ABI contract §Rows is normative; include/chtypes.h is its +// public authority). // // exportFormat is ExportNone (no bytes; the docFlags still thin the // document) or a Format this artifact can SERIALIZE — this revision exactly diff --git a/go/chtypes/multiversion.go b/go/chtypes/multiversion.go index f64c349..91c3fd6 100644 --- a/go/chtypes/multiversion.go +++ b/go/chtypes/multiversion.go @@ -337,7 +337,7 @@ import ( // into a TSan-compiled stress driver that mirrors these tests' workload // (steady distinct handles + compile/engine churn + validate, DEFAULT/TTL // evaluation included). Its runs are TSan-clean with ZERO suppressions -// (tests/tsan/RESULTS.md — the run of record: ~33 M concurrent calls, 0 +// (the run of record, in the core repository: ~33 M concurrent calls, 0 // reports, 0 mismatches). SCOPE, stated rather than implied: one version // (25.8, the reference line), one platform (darwin-arm64), that workload, // and the executed interleavings — other vendored lines share this wrapper @@ -535,7 +535,7 @@ func openLibrary(path string) (*Library, error) { // Key on the RESOLVED path, not the spelling: dlopen refcounts one image // per file, so `./x/libchtypes.so` and its absolute spelling — or a // legacy-name symlink like the libchtypes.so -> libchtypes_s1.so bridge - // ci/steps/stage-lib-build.sh stages — are the SAME image, and missing + // the core repository's build staging creates — are the SAME image, and missing // the map here would run chs_init a second time on live state (the "AT // MOST ONCE PER PROCESS" invariant below). key := path diff --git a/go/chtypes/multiversion_test.go b/go/chtypes/multiversion_test.go index 0f558ab..16f2936 100644 --- a/go/chtypes/multiversion_test.go +++ b/go/chtypes/multiversion_test.go @@ -85,7 +85,7 @@ func testRegistryDir(t *testing.T) string { // skipNoArtifacts is the one skip every registry test lands on when the // registry it was pointed at holds nothing. It is the right verdict — a // hosted CI runner has no artifacts, and the artifact-backed proof runs in -// the core repository's certify workflow against this same tree — but never a +// the core repository's server-truth suites against this same tree — but never a // quiet one: the message names the directory, what was wrong with it, and the // one command that fills it. func skipNoArtifacts(t *testing.T, dir, detail string) { diff --git a/go/chtypes/parity_test.go b/go/chtypes/parity_test.go index 153ceb2..e465200 100644 --- a/go/chtypes/parity_test.go +++ b/go/chtypes/parity_test.go @@ -351,7 +351,7 @@ var goValues = map[string]any{ "DocDefaults": int(chtypes.DocDefaults), "DocAll": int(chtypes.DocAll), - // docs/fetch.md §6 — the machine-readable codes the four CLIs print. + // docs/guides/fetch.md §6 — the machine-readable codes the four CLIs print. "CodeArtifactMissing": string(chtypes.CodeArtifactMissing), "CodeArtifactUntrusted": string(chtypes.CodeArtifactUntrusted), "CodeArtifactCorrupt": string(chtypes.CodeArtifactCorrupt), diff --git a/go/chtypes/testdata/parity.json b/go/chtypes/testdata/parity.json index afc916d..9136296 100644 --- a/go/chtypes/testdata/parity.json +++ b/go/chtypes/testdata/parity.json @@ -2,7 +2,7 @@ "schema": 1, "title": "The chtypes binding parity contract, machine-readable", "about": [ - "This file is the ONE machine-readable source of truth for what every binding must expose. docs/reference/bindings.md is the prose that explains why; this is what the four test suites actually run against, and scripts/check-parity-doc.sh asserts the two agree on the object-model table.", + "This file is the ONE machine-readable source of truth for what every binding must expose. docs/reference/bindings.md is the prose that explains why; this is what the four test suites actually run against, and python/tests/test_parity.py asserts the two agree on the object-model table.", "Each entry is a LOGICAL capability, not a name. The four columns are that capability's spelling in each language, and a spelling that follows the language's own idiom (CompileDDL / compile_ddl / compileDdl / compile) is the point, not a divergence. What must never drift is which capabilities exist and, where a `value` is given, what they answer.", "A binding that genuinely should not have a capability declares it as {\"absent\": \"\"}. An absent with no reason fails the manifest's own integrity check, so a gap cannot be recorded silently.", "The `unlisted` map is the other half of the contract: public names a binding exports that the others deliberately do not need. Each one carries a reason, the no-undeclared-surface check fails on anything that is neither a capability spelling nor listed there, and an entry naming something the binding no longer exports fails too \u2014 an excuse with nothing behind it hides the next real gap.", @@ -16,9 +16,9 @@ "filter": "The revision 3/4 filter and block surface (§Revision 3, §Revision 4).", "results": "The result types every binding hands back (§Result types).", "vocabulary": "Shared value sets. These carry a `value`: the four bindings must answer with the same bytes, not merely have a symbol.", - "errors": "The refusal/decline split and the artifact error family (§Conformance rule 12, docs/fetch.md §6).", + "errors": "The refusal/decline split and the artifact error family (§Conformance rule 12, docs/guides/fetch.md §6).", "discovery": "The three canonical connect-time queries and their parsers (§Discovery).", - "fetch": "Installing and verifying artifacts (docs/fetch.md).", + "fetch": "Installing and verifying artifacts (docs/guides/fetch.md).", "cli": "The `chtypes` command every SDK ships." }, "floors": { @@ -31,7 +31,7 @@ "id": "registry.construct", "group": "registry", "kind": "ctor", - "what": "Open a registry: an explicit artifact directory, or the docs/fetch.md §1 search path when none is given", + "what": "Open a registry: an explicit artifact directory, or the docs/guides/fetch.md §1 search path when none is given", "go": "NewRegistry", "python": "Registry", "ts": "Registry", @@ -928,7 +928,7 @@ "id": "errors.artifact-missing", "group": "errors", "kind": "type", - "what": "No artifact for this line on the search path (docs/fetch.md §6, exit 1)", + "what": "No artifact for this line on the search path (docs/guides/fetch.md §6, exit 1)", "go": "ErrArtifactMissing", "python": "ArtifactMissingError", "ts": "ArtifactMissingError", @@ -987,37 +987,37 @@ { "id": "errors.artifact-code-missing", "group": "errors", "kind": "constant", "value": "CHTYPES_ARTIFACT_MISSING", - "what": "The docs/fetch.md §6 machine-readable code, which the four CLIs print identically", + "what": "The docs/guides/fetch.md §6 machine-readable code, which the four CLIs print identically", "go": "CodeArtifactMissing", "python": "CODE_ARTIFACT_MISSING", "ts": "CODE_ARTIFACT_MISSING", "rust": "CODE_ARTIFACT_MISSING" }, { "id": "errors.artifact-code-untrusted", "group": "errors", "kind": "constant", "value": "CHTYPES_ARTIFACT_UNTRUSTED", - "what": "docs/fetch.md §6", + "what": "docs/guides/fetch.md §6", "go": "CodeArtifactUntrusted", "python": "CODE_ARTIFACT_UNTRUSTED", "ts": "CODE_ARTIFACT_UNTRUSTED", "rust": "CODE_ARTIFACT_UNTRUSTED" }, { "id": "errors.artifact-code-corrupt", "group": "errors", "kind": "constant", "value": "CHTYPES_ARTIFACT_CORRUPT", - "what": "docs/fetch.md §6", + "what": "docs/guides/fetch.md §6", "go": "CodeArtifactCorrupt", "python": "CODE_ARTIFACT_CORRUPT", "ts": "CODE_ARTIFACT_CORRUPT", "rust": "CODE_ARTIFACT_CORRUPT" }, { "id": "errors.artifact-code-pinned", "group": "errors", "kind": "constant", "value": "CHTYPES_ARTIFACT_PINNED", - "what": "docs/fetch.md §6", + "what": "docs/guides/fetch.md §6", "go": "CodeArtifactPinned", "python": "CODE_ARTIFACT_PINNED", "ts": "CODE_ARTIFACT_PINNED", "rust": "CODE_ARTIFACT_PINNED" }, { "id": "errors.artifact-code-unpublished", "group": "errors", "kind": "constant", "value": "CHTYPES_ARTIFACT_UNPUBLISHED", - "what": "docs/fetch.md §6", + "what": "docs/guides/fetch.md §6", "go": "CodeArtifactUnpublished", "python": "CODE_ARTIFACT_UNPUBLISHED", "ts": "CODE_ARTIFACT_UNPUBLISHED", "rust": "CODE_ARTIFACT_UNPUBLISHED" }, { "id": "errors.artifact-code-source-unreachable", "group": "errors", "kind": "constant", "value": "CHTYPES_SOURCE_UNREACHABLE", - "what": "docs/fetch.md §6", + "what": "docs/guides/fetch.md §6", "go": "CodeSourceUnreachable", "python": "CODE_SOURCE_UNREACHABLE", "ts": "CODE_SOURCE_UNREACHABLE", "rust": "CODE_SOURCE_UNREACHABLE" }, @@ -1082,7 +1082,7 @@ { "id": "fetch.ensure", "group": "fetch", "kind": "function", - "what": "Install one line, verified, into the registry directory (docs/fetch.md)", + "what": "Install one line, verified, into the registry directory (docs/guides/fetch.md)", "go": "Ensure", "python": "ensure", "ts": "ensure", "rust": "ensure" }, { @@ -1106,7 +1106,7 @@ { "id": "fetch.registry-search-path", "group": "fetch", "kind": "function", - "what": "The docs/fetch.md §1 search path, in order, for this host", + "what": "The docs/guides/fetch.md §1 search path, in order, for this host", "go": "RegistrySearchPath", "python": "registry_search_path", "ts": "registrySearchPath", "rust": "registry_search_path" }, { @@ -1154,7 +1154,7 @@ { "id": "fetch.release-public-key", "group": "fetch", "kind": "constant", "value": "fdb5f06a8d4c9918d049a5f1748fa2e3b3238c3f2000986d5bb9e31beff778fc", - "what": "The raw 32-byte ed25519 release public key, hex, as docs/fetch.md §4 publishes it", + "what": "The raw 32-byte ed25519 release public key, hex, as docs/guides/fetch.md §4 publishes it", "go": "ReleasePublicKeyHex", "python": "RELEASE_PUBLIC_KEY", "ts": {"absent": "TS exports RELEASE_PUBLIC_KEYS, a LIST of trusted keys for rotation, rather than one scalar. The list's first element is this value; the parity test checks that instead."}, "rust": "fetch::RELEASE_PUBLIC_KEY_HEX" }, { @@ -1184,21 +1184,21 @@ { "id": "fetch.env-registry", "group": "fetch", "kind": "constant", "value": "CHTYPES_REGISTRY", - "what": "The environment variable naming an explicit registry (docs/fetch.md §1)", + "what": "The environment variable naming an explicit registry (docs/guides/fetch.md §1)", "go": {"absent": "Go spells the name inline in RegistrySearchPath and exports no constant for it. NEEDS A DECISION — the other three export one."}, "python": "ENV_REGISTRY", "ts": {"absent": "TS spells the name inline in resolveRegistryDir. NEEDS A DECISION."}, "rust": "REGISTRY_ENV" }, { "id": "fetch.env-autofetch", "group": "fetch", "kind": "constant", "value": "CHTYPES_AUTOFETCH", - "what": "The environment variable turning lazy fetch on (docs/fetch.md §6)", + "what": "The environment variable turning lazy fetch on (docs/guides/fetch.md §6)", "go": {"absent": "Spelled inline; see fetch.env-registry."}, "python": "ENV_AUTOFETCH", "ts": {"absent": "Spelled inline; see fetch.env-registry."}, "rust": "AUTOFETCH_ENV" }, { "id": "fetch.command", "group": "fetch", "kind": "constant", - "what": "This SDK's own fetch command, as the docs/fetch.md §7 message spells it. The VALUE is deliberately per-language — it is the command a caller of THIS SDK runs", + "what": "This SDK's own fetch command, as the docs/guides/fetch.md §7 message spells it. The VALUE is deliberately per-language — it is the command a caller of THIS SDK runs", "go": "GoFetchCommand", "python": {"absent": "The Python message builds the command inline in errors.py's ArtifactMissingError. NEEDS A DECISION — Go, TS and Rust export it."}, "ts": "FETCH_COMMAND", "rust": "FETCH_COMMAND" }, @@ -1256,7 +1256,7 @@ "LockFile.Write": "Write a lock file.", "NewLockFile": "Construct a lock file.", "LockKey": "The platform/line key a pin is stored under.", - "ExitCode": "Map an error to the docs/fetch.md §6 exit status; the other CLIs map it internally.", + "ExitCode": "Map an error to the docs/guides/fetch.md §6 exit status; the other CLIs map it internally.", "ErrorCode": "The artifact error code as a named string type.", "ErrorCode.ExitCode": "Accessor.", "ErrorCode.Sentinel": "Accessor.", @@ -1266,7 +1266,7 @@ "ArtifactError.Unwrap": "errors.Unwrap support.", "SchemaError.Error": "error interface.", "UnsupportedError.Error": "error interface.", - "SystemRegistryDirs": "The two system roots of docs/fetch.md §1.", + "SystemRegistryDirs": "The two system roots of docs/guides/fetch.md §1.", "DefaultRegistryDirFor": "The per-user cache for another platform.", "ValidPlatform": "Platform-key validation.", "QuoteIdentifier": "Backtick-quoting for reconstruct; the others keep it private.", @@ -1367,7 +1367,7 @@ "resolvePlatform": "Platform key resolution.", "isPlatformKey": "Platform-key validation.", "cacheRegistryDir": "The per-user cache for a platform.", - "systemRegistryDirs": "The two system roots of docs/fetch.md §1.", + "systemRegistryDirs": "The two system roots of docs/guides/fetch.md §1.", "looksLikeRegistry": "Whether a directory holds artifacts.", "resolveRegistryDir": "The first search-path entry that held something.", "selectArtifact": "Pick one release row for a spelling.", @@ -1426,7 +1426,7 @@ "Error": "The one error enum.", "Error::code": "The ClickHouse code, when there is one.", "Error::is_unsupported": "The explicit both-arms predicate; see errors.base.", - "Error::artifact_code": "The docs/fetch.md §6 code, when there is one.", + "Error::artifact_code": "The docs/guides/fetch.md §6 code, when there is one.", "Error::Registry": "Registry-layer error.", "Error::Load": "Load failure.", "Error::NotAnArtifact": "Load failure.", @@ -1460,7 +1460,7 @@ "DEFAULT_TIMEZONE": "The UTC default.", "REGISTRY_ENV": "Environment variable name.", "AUTOFETCH_ENV": "Environment variable name.", - "SYSTEM_ARTIFACT_ROOTS": "The two system roots of docs/fetch.md §1.", + "SYSTEM_ARTIFACT_ROOTS": "The two system roots of docs/guides/fetch.md §1.", "cache_dir_for": "The per-user cache for a platform.", "install_dir_for": "Where a fetch for another platform writes.", "search_path_for": "The search path for another platform.", diff --git a/go/chtypes/transform.go b/go/chtypes/transform.go index 098ecf6..89a3d35 100644 --- a/go/chtypes/transform.go +++ b/go/chtypes/transform.go @@ -105,7 +105,6 @@ const ( // its own clock and the caller must send as an explicit column. A separate // reason from default_filled because the claim is different: the tenant is // being shown a value the *gateway* invented, not one the server chose. - // docs/defaults-matrix.md §5.4(3) asks for exactly this. ReasonDefaultMaterialized = "default_materialized" // The storage layer's own verdicts on rows the type layer accepted, diff --git a/include/chtypes.h b/include/chtypes.h index 5ae96b9..cb28339 100644 --- a/include/chtypes.h +++ b/include/chtypes.h @@ -49,7 +49,7 @@ extern "C" { * The RowBinary family reads the value in ClickHouse's own storage encoding * (ISerialization::deserializeBinary — the exact reader BinaryRowInputFormat * uses), so every parse-time text guard is bypassed exactly as it is on a real - * server (docs/type-coverage.md §11): one error code (33) for any framing + * server: one error code (33) for any framing * fault, all-or-nothing batches, input_format_allow_errors_* never applies. * CHS_ROW_BINARY_WITH_DEFAULTS adds the measured per-column marker byte * (any nonzero byte = compute the column's DEFAULT, read no value bytes). @@ -608,8 +608,8 @@ typedef struct chs_bytes * then logs only a count), reported verbatim. The batch verdict, rows_read * and rows_skipped are exactly what they were when skips were silent. * - * THE EXPORT CHANNEL (revision 3; docs/proposals/rows-export.md, normative - * text in the C ABI contract §Rows). `export_format` is CHS_EXPORT_NONE or an + * THE EXPORT CHANNEL (revision 3; the normative text is the C ABI + * contract §Rows, for which this header is the public authority). `export_format` is CHS_EXPORT_NONE or an * enum chs_format value this artifact can SERIALIZE — this revision exactly * CHS_JSON_COMPACT_EACH_ROW. With an export requested, out_bytes (required * non-NULL, always initialized to {NULL,0} at entry) receives the batch's diff --git a/python/pyproject.toml b/python/pyproject.toml index 788e421..fc3862a 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -54,7 +54,7 @@ src = ["src", "tests"] # the classes that have actually cost time here — unused imports and names (F), # style errors that hide real ones (E), import order drift across 20 files (I), # syntax this project's floor already allows (UP), and the mutable-default / -# loop-variable-capture family (B). `just lint` and ci/steps/static-checks.sh -# both run this, so a finding is a gate failure, not advice. +# loop-variable-capture family (B). `just lint` and the core repository's +# static checks both run this, so a finding is a gate failure, not advice. [tool.ruff.lint] select = ["E", "F", "I", "UP", "B"] diff --git a/python/src/chtypes/registry.py b/python/src/chtypes/registry.py index 2679587..d5972fb 100644 --- a/python/src/chtypes/registry.py +++ b/python/src/chtypes/registry.py @@ -370,8 +370,9 @@ def rows( `BatchResult.rows` as `Outcome.SKIPPED`, carrying the server's own caught error verbatim (2026-08-27). - **The revision-3 export channel** (the C ABI contract §Rows; - docs/proposals/rows-export.md) — still ONE `chs_rows` call, never a + **The revision-3 export channel** (the C ABI contract §Rows, for + which `include/chtypes.h` is the public authority) — still ONE + `chs_rows` call, never a second, never re-parsing: `export` is None (no bytes — today's path, byte-identical documents) diff --git a/python/tests/conftest.py b/python/tests/conftest.py index f09aa5f..bbd5cf8 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -2,7 +2,7 @@ not run at all — it skips, loudly, by name. The fetch, CLI and pure-Python tests need none and always run; that is what this repository's CI proves on hosted runners, and the artifact-backed proof is the core repository's -`certify` workflow against this same tree. +server-truth suites against this same tree. The registry comes from the search path (docs/guides/fetch.md §1): `$CHTYPES_REGISTRY`, else the per-user artifact cache for this host (`chtypes.default_registry_dir()`: diff --git a/rust/src/schema.rs b/rust/src/schema.rs index 7f422fb..0c3b1f4 100644 --- a/rust/src/schema.rs +++ b/rust/src/schema.rs @@ -256,7 +256,8 @@ impl Schema { /// [`Schema::rows`] with the revision-3 export and document-flag channels /// exposed: ONE `chs_rows` call, never a second, never re-parsing - /// (`docs/proposals/rows-export.md`; the C ABI contract §Rows is normative). + /// (the C ABI contract §Rows is normative; `include/chtypes.h` is its + /// public authority). /// /// `export` is `None` (no bytes; `doc_flags` still thins the document) or /// `Some(format)` for a [`Format`] this artifact can SERIALIZE — this diff --git a/rust/tests/parity.rs b/rust/tests/parity.rs index 8077306..0b15037 100644 --- a/rust/tests/parity.rs +++ b/rust/tests/parity.rs @@ -456,7 +456,7 @@ fn rust_values() -> BTreeMap<&'static str, Val> { m.insert("DocFlags::DEFAULTS", i(DocFlags::DEFAULTS.bits() as i64)); m.insert("DocFlags::ALL", i(DocFlags::ALL.bits() as i64)); - // docs/fetch.md §6 — the machine-readable codes the four CLIs print. + // docs/guides/fetch.md §6 — the machine-readable codes the four CLIs print. m.insert("CODE_ARTIFACT_MISSING", s(chtypes::CODE_ARTIFACT_MISSING)); m.insert( "CODE_ARTIFACT_UNTRUSTED", diff --git a/scripts/check-standalone.sh b/scripts/check-standalone.sh index 0383a5a..0308796 100755 --- a/scripts/check-standalone.sh +++ b/scripts/check-standalone.sh @@ -21,7 +21,7 @@ # Without a registry — a hosted CI runner, a fresh clone — the suite still # runs: the fetch, fixture and CLI tests need no artifact, and every test that # does SKIPS, by name, in the census; the golden set and the registry suite -# are then the core repository's certify workflow's to prove. --no-artifacts +# are then the core repository's server-truth suites' to prove. --no-artifacts # reproduces that runner here: an empty XDG_CACHE_HOME and no # $CHTYPES_REGISTRY, so this machine's own cache is invisible. # --require-artifacts is the opposite rule, for CI's artifact-backed run: diff --git a/scripts/check-suite.sh b/scripts/check-suite.sh index fddb0e9..952adf3 100755 --- a/scripts/check-suite.sh +++ b/scripts/check-suite.sh @@ -23,7 +23,7 @@ # and no test may have skipped for want of a registry. # # The artifact-backed proof beyond these — the server-truth suites, the -# oracle, the rigs — is the core repository's certify workflow. +# oracle, the rigs — is the core repository's server-truth suites. set -euo pipefail SCRIPTS="$(cd "$(dirname "$0")" && pwd)" diff --git a/scripts/lint-paths.sh b/scripts/lint-paths.sh new file mode 100755 index 0000000..b941650 --- /dev/null +++ b/scripts/lint-paths.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash +# lint-paths.sh — no tracked file may cite a repository path that does not exist. +# +# WHY THIS EXISTS. `docs/proposals/rows-export.md` was cited six times — in +# include/chtypes.h and in all four bindings' source, every one of which ships +# inside the crate, the sdist, the module and the npm tarball — for a file that +# is not in this repository. Four more dead citations were found the same way +# (`docs/defaults-matrix.md`, `docs/type-coverage.md`, `docs/fetch.md` after it +# moved under guides/, and a `scripts/check-parity-doc.sh` that has never +# existed while the check it named was real and living in the Python suite). +# +# Each was a pointer a public reader cannot follow. lint-public.sh catches the +# private repository by NAME; this catches the other half of the same failure — +# a path that simply is not there. Between them a sweep that "removed" a +# pointer by changing its shape cannot pass quietly again. +# +# scripts/lint-paths.sh check every tracked file +# scripts/lint-paths.sh --selftest prove the rule fires, and does not overfire +set -euo pipefail +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +scan() { + ( cd "$1" && git ls-files -z | python3 -c ' +import os, re, sys + +# Top-level directories whose names are unambiguous repository paths. +TOP = r"(?:docs|examples|scripts|include|goldens|spec|tests)" +# A real extension is required: a bare word after a slash is a glob or prose. +PAT = re.compile(r"(? "$tmp/docs/guides/fetch.md" + printf 'ok\n' > "$tmp/rust/tests/integration.rs" + printf 'see docs/gone/missing.md\n' > "$tmp/planted.md" + printf 'see docs/guides/fetch.md\n' > "$tmp/live.md" + printf '// see tests/integration.rs\n' > "$tmp/rust/lib.rs" + printf 'run pytest tests/integration.rs from rust/\n' > "$tmp/sibling.md" + git -C "$tmp" add -A + out="$(scan "$tmp" 2>&1)" && { echo "SELFTEST FAILED: the planted dead path was not caught" >&2; exit 1; } + printf '%s\n' "$out" | grep -q 'planted.md' || { echo "SELFTEST FAILED: rule did not fire on planted.md" >&2; exit 1; } + printf '%s\n' "$out" | grep -q 'live.md' && { echo "SELFTEST FAILED: a path that exists was flagged" >&2; exit 1; } + printf '%s\n' "$out" | grep -q 'rust/lib.rs' && { echo "SELFTEST FAILED: a crate-relative path was flagged" >&2; exit 1; } + echo "lint-paths: selftest ok — fires on a dead path, silent on live and crate-relative ones" + exit 0 +fi + +scan "$HERE" +echo "lint-paths: ok — every cited repository path exists" diff --git a/tests/parity/manifest.json b/tests/parity/manifest.json index afc916d..9136296 100644 --- a/tests/parity/manifest.json +++ b/tests/parity/manifest.json @@ -2,7 +2,7 @@ "schema": 1, "title": "The chtypes binding parity contract, machine-readable", "about": [ - "This file is the ONE machine-readable source of truth for what every binding must expose. docs/reference/bindings.md is the prose that explains why; this is what the four test suites actually run against, and scripts/check-parity-doc.sh asserts the two agree on the object-model table.", + "This file is the ONE machine-readable source of truth for what every binding must expose. docs/reference/bindings.md is the prose that explains why; this is what the four test suites actually run against, and python/tests/test_parity.py asserts the two agree on the object-model table.", "Each entry is a LOGICAL capability, not a name. The four columns are that capability's spelling in each language, and a spelling that follows the language's own idiom (CompileDDL / compile_ddl / compileDdl / compile) is the point, not a divergence. What must never drift is which capabilities exist and, where a `value` is given, what they answer.", "A binding that genuinely should not have a capability declares it as {\"absent\": \"\"}. An absent with no reason fails the manifest's own integrity check, so a gap cannot be recorded silently.", "The `unlisted` map is the other half of the contract: public names a binding exports that the others deliberately do not need. Each one carries a reason, the no-undeclared-surface check fails on anything that is neither a capability spelling nor listed there, and an entry naming something the binding no longer exports fails too \u2014 an excuse with nothing behind it hides the next real gap.", @@ -16,9 +16,9 @@ "filter": "The revision 3/4 filter and block surface (§Revision 3, §Revision 4).", "results": "The result types every binding hands back (§Result types).", "vocabulary": "Shared value sets. These carry a `value`: the four bindings must answer with the same bytes, not merely have a symbol.", - "errors": "The refusal/decline split and the artifact error family (§Conformance rule 12, docs/fetch.md §6).", + "errors": "The refusal/decline split and the artifact error family (§Conformance rule 12, docs/guides/fetch.md §6).", "discovery": "The three canonical connect-time queries and their parsers (§Discovery).", - "fetch": "Installing and verifying artifacts (docs/fetch.md).", + "fetch": "Installing and verifying artifacts (docs/guides/fetch.md).", "cli": "The `chtypes` command every SDK ships." }, "floors": { @@ -31,7 +31,7 @@ "id": "registry.construct", "group": "registry", "kind": "ctor", - "what": "Open a registry: an explicit artifact directory, or the docs/fetch.md §1 search path when none is given", + "what": "Open a registry: an explicit artifact directory, or the docs/guides/fetch.md §1 search path when none is given", "go": "NewRegistry", "python": "Registry", "ts": "Registry", @@ -928,7 +928,7 @@ "id": "errors.artifact-missing", "group": "errors", "kind": "type", - "what": "No artifact for this line on the search path (docs/fetch.md §6, exit 1)", + "what": "No artifact for this line on the search path (docs/guides/fetch.md §6, exit 1)", "go": "ErrArtifactMissing", "python": "ArtifactMissingError", "ts": "ArtifactMissingError", @@ -987,37 +987,37 @@ { "id": "errors.artifact-code-missing", "group": "errors", "kind": "constant", "value": "CHTYPES_ARTIFACT_MISSING", - "what": "The docs/fetch.md §6 machine-readable code, which the four CLIs print identically", + "what": "The docs/guides/fetch.md §6 machine-readable code, which the four CLIs print identically", "go": "CodeArtifactMissing", "python": "CODE_ARTIFACT_MISSING", "ts": "CODE_ARTIFACT_MISSING", "rust": "CODE_ARTIFACT_MISSING" }, { "id": "errors.artifact-code-untrusted", "group": "errors", "kind": "constant", "value": "CHTYPES_ARTIFACT_UNTRUSTED", - "what": "docs/fetch.md §6", + "what": "docs/guides/fetch.md §6", "go": "CodeArtifactUntrusted", "python": "CODE_ARTIFACT_UNTRUSTED", "ts": "CODE_ARTIFACT_UNTRUSTED", "rust": "CODE_ARTIFACT_UNTRUSTED" }, { "id": "errors.artifact-code-corrupt", "group": "errors", "kind": "constant", "value": "CHTYPES_ARTIFACT_CORRUPT", - "what": "docs/fetch.md §6", + "what": "docs/guides/fetch.md §6", "go": "CodeArtifactCorrupt", "python": "CODE_ARTIFACT_CORRUPT", "ts": "CODE_ARTIFACT_CORRUPT", "rust": "CODE_ARTIFACT_CORRUPT" }, { "id": "errors.artifact-code-pinned", "group": "errors", "kind": "constant", "value": "CHTYPES_ARTIFACT_PINNED", - "what": "docs/fetch.md §6", + "what": "docs/guides/fetch.md §6", "go": "CodeArtifactPinned", "python": "CODE_ARTIFACT_PINNED", "ts": "CODE_ARTIFACT_PINNED", "rust": "CODE_ARTIFACT_PINNED" }, { "id": "errors.artifact-code-unpublished", "group": "errors", "kind": "constant", "value": "CHTYPES_ARTIFACT_UNPUBLISHED", - "what": "docs/fetch.md §6", + "what": "docs/guides/fetch.md §6", "go": "CodeArtifactUnpublished", "python": "CODE_ARTIFACT_UNPUBLISHED", "ts": "CODE_ARTIFACT_UNPUBLISHED", "rust": "CODE_ARTIFACT_UNPUBLISHED" }, { "id": "errors.artifact-code-source-unreachable", "group": "errors", "kind": "constant", "value": "CHTYPES_SOURCE_UNREACHABLE", - "what": "docs/fetch.md §6", + "what": "docs/guides/fetch.md §6", "go": "CodeSourceUnreachable", "python": "CODE_SOURCE_UNREACHABLE", "ts": "CODE_SOURCE_UNREACHABLE", "rust": "CODE_SOURCE_UNREACHABLE" }, @@ -1082,7 +1082,7 @@ { "id": "fetch.ensure", "group": "fetch", "kind": "function", - "what": "Install one line, verified, into the registry directory (docs/fetch.md)", + "what": "Install one line, verified, into the registry directory (docs/guides/fetch.md)", "go": "Ensure", "python": "ensure", "ts": "ensure", "rust": "ensure" }, { @@ -1106,7 +1106,7 @@ { "id": "fetch.registry-search-path", "group": "fetch", "kind": "function", - "what": "The docs/fetch.md §1 search path, in order, for this host", + "what": "The docs/guides/fetch.md §1 search path, in order, for this host", "go": "RegistrySearchPath", "python": "registry_search_path", "ts": "registrySearchPath", "rust": "registry_search_path" }, { @@ -1154,7 +1154,7 @@ { "id": "fetch.release-public-key", "group": "fetch", "kind": "constant", "value": "fdb5f06a8d4c9918d049a5f1748fa2e3b3238c3f2000986d5bb9e31beff778fc", - "what": "The raw 32-byte ed25519 release public key, hex, as docs/fetch.md §4 publishes it", + "what": "The raw 32-byte ed25519 release public key, hex, as docs/guides/fetch.md §4 publishes it", "go": "ReleasePublicKeyHex", "python": "RELEASE_PUBLIC_KEY", "ts": {"absent": "TS exports RELEASE_PUBLIC_KEYS, a LIST of trusted keys for rotation, rather than one scalar. The list's first element is this value; the parity test checks that instead."}, "rust": "fetch::RELEASE_PUBLIC_KEY_HEX" }, { @@ -1184,21 +1184,21 @@ { "id": "fetch.env-registry", "group": "fetch", "kind": "constant", "value": "CHTYPES_REGISTRY", - "what": "The environment variable naming an explicit registry (docs/fetch.md §1)", + "what": "The environment variable naming an explicit registry (docs/guides/fetch.md §1)", "go": {"absent": "Go spells the name inline in RegistrySearchPath and exports no constant for it. NEEDS A DECISION — the other three export one."}, "python": "ENV_REGISTRY", "ts": {"absent": "TS spells the name inline in resolveRegistryDir. NEEDS A DECISION."}, "rust": "REGISTRY_ENV" }, { "id": "fetch.env-autofetch", "group": "fetch", "kind": "constant", "value": "CHTYPES_AUTOFETCH", - "what": "The environment variable turning lazy fetch on (docs/fetch.md §6)", + "what": "The environment variable turning lazy fetch on (docs/guides/fetch.md §6)", "go": {"absent": "Spelled inline; see fetch.env-registry."}, "python": "ENV_AUTOFETCH", "ts": {"absent": "Spelled inline; see fetch.env-registry."}, "rust": "AUTOFETCH_ENV" }, { "id": "fetch.command", "group": "fetch", "kind": "constant", - "what": "This SDK's own fetch command, as the docs/fetch.md §7 message spells it. The VALUE is deliberately per-language — it is the command a caller of THIS SDK runs", + "what": "This SDK's own fetch command, as the docs/guides/fetch.md §7 message spells it. The VALUE is deliberately per-language — it is the command a caller of THIS SDK runs", "go": "GoFetchCommand", "python": {"absent": "The Python message builds the command inline in errors.py's ArtifactMissingError. NEEDS A DECISION — Go, TS and Rust export it."}, "ts": "FETCH_COMMAND", "rust": "FETCH_COMMAND" }, @@ -1256,7 +1256,7 @@ "LockFile.Write": "Write a lock file.", "NewLockFile": "Construct a lock file.", "LockKey": "The platform/line key a pin is stored under.", - "ExitCode": "Map an error to the docs/fetch.md §6 exit status; the other CLIs map it internally.", + "ExitCode": "Map an error to the docs/guides/fetch.md §6 exit status; the other CLIs map it internally.", "ErrorCode": "The artifact error code as a named string type.", "ErrorCode.ExitCode": "Accessor.", "ErrorCode.Sentinel": "Accessor.", @@ -1266,7 +1266,7 @@ "ArtifactError.Unwrap": "errors.Unwrap support.", "SchemaError.Error": "error interface.", "UnsupportedError.Error": "error interface.", - "SystemRegistryDirs": "The two system roots of docs/fetch.md §1.", + "SystemRegistryDirs": "The two system roots of docs/guides/fetch.md §1.", "DefaultRegistryDirFor": "The per-user cache for another platform.", "ValidPlatform": "Platform-key validation.", "QuoteIdentifier": "Backtick-quoting for reconstruct; the others keep it private.", @@ -1367,7 +1367,7 @@ "resolvePlatform": "Platform key resolution.", "isPlatformKey": "Platform-key validation.", "cacheRegistryDir": "The per-user cache for a platform.", - "systemRegistryDirs": "The two system roots of docs/fetch.md §1.", + "systemRegistryDirs": "The two system roots of docs/guides/fetch.md §1.", "looksLikeRegistry": "Whether a directory holds artifacts.", "resolveRegistryDir": "The first search-path entry that held something.", "selectArtifact": "Pick one release row for a spelling.", @@ -1426,7 +1426,7 @@ "Error": "The one error enum.", "Error::code": "The ClickHouse code, when there is one.", "Error::is_unsupported": "The explicit both-arms predicate; see errors.base.", - "Error::artifact_code": "The docs/fetch.md §6 code, when there is one.", + "Error::artifact_code": "The docs/guides/fetch.md §6 code, when there is one.", "Error::Registry": "Registry-layer error.", "Error::Load": "Load failure.", "Error::NotAnArtifact": "Load failure.", @@ -1460,7 +1460,7 @@ "DEFAULT_TIMEZONE": "The UTC default.", "REGISTRY_ENV": "Environment variable name.", "AUTOFETCH_ENV": "Environment variable name.", - "SYSTEM_ARTIFACT_ROOTS": "The two system roots of docs/fetch.md §1.", + "SYSTEM_ARTIFACT_ROOTS": "The two system roots of docs/guides/fetch.md §1.", "cache_dir_for": "The per-user cache for a platform.", "install_dir_for": "Where a fetch for another platform writes.", "search_path_for": "The search path for another platform.", diff --git a/ts/src/schema.ts b/ts/src/schema.ts index 29820ef..e49f574 100644 --- a/ts/src/schema.ts +++ b/ts/src/schema.ts @@ -49,7 +49,8 @@ export interface EngineOptions { /** * Options for `Schema#rows` — the revision-3 export and document-flag - * channels (the C ABI contract §Rows; docs/proposals/rows-export.md). Whatever the + * channels (the C ABI contract §Rows, for which include/chtypes.h is the + * public authority). Whatever the * options, `rows()` is always ONE `chs_rows` call — never a second call, * never re-parsing. */ diff --git a/ts/test/chtypes.test.ts b/ts/test/chtypes.test.ts index 9467d5d..b94ce34 100644 --- a/ts/test/chtypes.test.ts +++ b/ts/test/chtypes.test.ts @@ -3,8 +3,8 @@ * registry. Nothing here asserts on an exit code or a self-report: every case * asserts on the document the library produced. * - * Level 3 (semantic) conformance is the rigs' job — `tests/acceptance` and - * `tests/arbiter` score an implementation against ground truth captured from real + * Level 3 (semantic) conformance is the rigs' job — the core repository's + * acceptance and arbiter rigs score an implementation against ground truth captured from real * ClickHouse servers — and no unit test can stand in for it. * * Float expectations are deliberately absent: macOS's `long double` is 53-bit, so