Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/batches.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/bindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions go/chtypes/chtypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 <new
// expr>` 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.
Expand Down
7 changes: 4 additions & 3 deletions go/chtypes/linked.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions go/chtypes/multiversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion go/chtypes/multiversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion go/chtypes/parity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Loading