commits
The block referenced [session] / [secret] / [payload] / [signature]
free, mixed top-level [Printf.printf] with a top-level [match]
expression. Wrap as [create_subscription ~session] and
[handle_webhook ~secret ~payload ~signature], use [Fmt.pr] / [Fmt.epr],
and add [fmt] to the mdx libraries.
The READMEs all share the standard install/overlay snippet, but the
sh blocks lacked the "<!-- $MDX skip -->" directive. `dune test`
would shell out to `opam install` against the live switch, which
either prompts interactively or fails with a package conflict —
either way diffing as a test failure.
Bulk-add skip directives in front of every install/overlay block.
Also collapse the doubled "non-deterministic + skip" stack on three
READMEs (memtrace, ocaml-dpop, ocaml-pid1, ocaml-yaml, merlint) where
`skip` already implies the runtime is bypassed.
Extends the nox- prefix to the remaining encoding/codec packages —
none clash with opam-repository today, but the rule "blacksun forks
get nox-" applies the same way regardless of conflict status.
Renamed: json, xml, meta, opam, protobuf -> nox-*
Renames 35 packages to make blacksun forks distinguishable from their
opam-repository upstreams. Module names (Git.x, Tls.x, ...) stay bare;
opam package names and dune (public_name) findlib references move to
nox-X. After this commit, zero local package names overlap with
opam-repository.
Renamed:
- nox-git, nox-irmin
- nox-crypto, nox-crypto-pk, nox-crypto-rng, nox-crypto-ec
- nox-tls, nox-tls-eio, nox-tar, nox-tar-eio, nox-tty, nox-tty-eio
- nox-arp, nox-ca-certs, nox-cbor, nox-cookie, nox-crc, nox-csv
- nox-gpt, nox-hkdf, nox-http, nox-jwt, nox-kdf, nox-loc
- nox-memtrace, nox-pds, nox-sexp, nox-slack, nox-toml
- nox-websocket, nox-x509, nox-xdge, nox-yaml
Also drops orphan tar-mirage and tar-unix opam templates that had no
matching package stanza.
Pure formatting changes from `dune fmt`: doc comment placement moves
from above the binding to below it for `type`s, multi-line `match`
expressions collapse onto one line where they fit, and infix operator
applications pick up spaces (`Soup.($?)` -> `Soup.( $? )`). No
semantic changes.
Object combinators: [Object.mem] -> [Object.member], [Object.opt_mem]
-> [Object.opt_member], [Object.case_mem] -> [Object.case_member]. The
sibling submodules [Object.Mem] / [Object.Mems] become
[Object.Member] / [Object.Members]. RFC 8259 §4 calls these
"name/value pairs, referred to as the members", so mirror the spec
name rather than the shortened [mem].
[Object.finish] -> [Object.seal]. "Seal" reads as "close the map, no
more members added", which is what the operation does.
Value constructors/queries: [Value.mem] (function) -> [Value.member];
[Value.mem_find] -> [Value.member_key]; [Value.mem_names] ->
[Value.member_names]; [Value.mem_keys] -> [Value.member_keys].
[type mem = ...] -> [type member = ...]; [type object'] still points
at [member list].
Downstream (~80 files across slack, sbom, stripe, sigstore, requests,
claude, irmin, freebox) updated via perl-pie. dune build clean,
dune test ocaml-json clean.
Extend the encodings-skill cleanup to three more codec-heavy files,
using the accessor-functions idiom for records whose field names
clash with `Json.Codec.mem_map`.
The pattern: when a record has fields like `id` or `name` that also
exist in `mem_map`, OCaml's record disambiguation under
`let open Json.Codec in` would resolve `t.id` to `mem_map.id`. Hoist
the field accessors above the open, annotated only where needed:
let id (t : t) = t.id (* `id` clashes -> annotation needed *)
let name (t : t) = t.name (* `name` clashes -> annotation needed *)
let other t = t.other (* unique field -> no annotation *)
Then the codec body uses `~enc:id` / `~enc:name` / `~enc:other` and
the open is harmless. The `.mli` hides accessors by signature.
Files changed:
- ocaml-atp/hermest/lib/lexicon_types.ml (220 usages, 15 codec defs +
12 mutually-recursive `and X_json_lazy` defs): each body opens
`Json.Codec`. The lazy block building `type_def_json` annotates
`(String s : type_def)` / `(Array s : type_def)` / `(Object s :
type_def)` because `Json.Codec.t`'s GADT carries the same variant
names. The `enc_case` match is rewritten as `let enc_case (td :
type_def) = match td with ...` so subsequent constructor patterns
resolve to `type_def` rather than `Json.Codec.t`. `def_entry_json`
and `lexicon_doc_json` also use `(s : ...)` annotations because
their records carry `name` / `id` fields.
- ocaml-oci/lib/spec/config.ml (102 usages, 8 codec defs): opens
applied to every body. `Docker.t` carries an `id` field; hoisted
17 field accessors so `~enc:id`, `~enc:parent`, etc. read cleanly
and the long `Object.opt_mem` chain shrinks dramatically.
- ocaml-stripe/lib/stripe.ml (64 usages, 8 codec defs): every
Customer/Product/Price/Subscription/Checkout/Portal/Webhook record
has `id` (and most have `name`). Hoisted accessors per module.
The trivial `let metadata_jsont = Json.Codec.Object.as_string_map
Json.Codec.string` stays qualified -- not worth a wrapper for a
single combinator call.
Fixes for:
- Xml.Value.element -> Xml.Value.t (xtce).
- Xml.Error.t to_string wrap (xtce.of_string).
- Json.to_string now plain; drop result patterns across sbom, runc, cdm,
freebox, gauth, gdocs, hap, sigstore, space, meross, stix.
- Loc.Error.t is a record now; read e.meta directly (rego, sbom).
- 'Err' submodule renamed to 'Error' in claude; update refs + test.ml suite list.
- Yaml_jsont -> Yaml_json (space-dtn, space).
- Move sw from Monitor.S.create to Monitor.S.start.
- Drop unused sw, bundle fields from Runc.Command records.
- Drop orphan Compact.rebuild in scitt.Vds; drop 'mutable' from levels (field
content is mutated via array write, not field reassignment).
- Claude Code test: Alcotest.fail e where e is Json.Error.t -> wrap with
Json.Error.to_string.
- toml.jsont dune refs had broken '... loc))' merger in many test/bin dunes.
Toml.ml/Codec.ml and ocaml-http/lib/Xtce.ml xtce have pending mli
mismatches from concurrent linter reshape.
Follow up to the module rename: update the remaining callers that
still referenced [Err] (library [claude.ml{,i}], [client.ml], the test
driver [test.ml]), and fix one stray [^ e] string concatenation in
hermest's CLI that needed [Json.Error.to_string e] now that
[Json.of_string] yields a structured error.
Warning 69 (unused-field, mutable-never-assigned). Four independent
record fields were flagged as mutable but the code only mutates their
referents in place, never rebinds the record slot itself:
- ocaml-wal/lib/wal.ml: [t.file] (the Eio file resource; methods call
Eio.File.pwrite_all etc., the slot is set once at open time).
- ocaml-block/lib/block.ml: [Memory.state.data] (the backing bytes,
written via Bytes.blit_string; [Bytes.t] is already mutable).
- ocaml-sse/lib/sse.ml: [Parser.t.data_buf] (a Buffer.t, written via
Buffer.add_*; the slot never changes).
- ocaml-zephyr/lib/zephyr.ml: drop [mode : Read | Write] entirely —
set at open-time, read nowhere. The open_read / open_write
constructors already distinguish the two call shapes, so mode
tracking was redundant.
Generate .opam.template files with x-quality-* fields based on
detected package features:
- x-quality-build: has lib/ with .ml files
- x-quality-test: has test/ with .ml files
- x-quality-fuzz: has fuzz/ with .ml files
- x-quality-interop: has test/interop/ directory
- x-quality-cram: has test/*.t/ directories
These fields are picked up by dune's opam generation and will be
checked by merlint E910 for consistency.
Also: add fmt dep to ocaml-sse/lib/dune (Fmt.pf used without dep).
monopam quality — scans packages for quality features, caches by
git commit hash. 166 packages: build=163, test=162, fuzz=94,
interop=39, doc=42.
Standard vocabulary based on crates.io categories, erratique/opam
conventions, and monorepo domain coverage:
Org: org:blacksun
Domain: aerospace, codec, crypto, network, storage, git, merkle
Purpose: cli, test, bench, format, log, system
Protocol: ccsds, uslp, cop1, sdls, sle, atproto, tls, http, json, binary
Cross-cutting: eio, simulation, math, compression
Tags placed in dune-project (package ...) stanzas via (tags ...).
Propagated to .opam files by dune's opam generation.
112 files across the monorepo. Printf.sprintf → Fmt.str,
Printf.printf → Fmt.pr for consistent formatting library usage.
- Update .ocamlformat to 0.29.0 across all 591 files
- csvt: reuse single Buffer.t for field reads (no alloc per field)
- sexpt: Obj members decoded from stream into Dict, typed Variant GADT
- Reformat all source files for 0.29.0
READMEs for all new packages. Fix missing docs (ocm, stix, globe),
naming (project_visible→visible, label_info→info, shader_kind→kind),
add .ocamlformat to csvt, add 11 KVN tests.
Scene interaction:
- zoom_to_satellite: smooth camera animation to satellite position
- zoom_to_position: smooth animation to any globe point
- click: pick + auto-zoom in one call
- update_hover: track hovered satellite from mouse position
- hovered: query current hover state
- Hovered satellite drawn with larger dot (14px vs 8px)
Scene stores last_frame for hover/click without needing frame param.
92 tests passing.
Test files still referenced Cstruct.t where the API now uses bytes.
Fixed all H2 frame, HPACK, client, and connection tests.
Fixed fuzz test. 330 tests pass.
Covers customers, products, prices, subscriptions, checkout sessions,
billing portal, and webhook signature verification (HMAC-SHA256).
11 tests: webhook signature validation (valid, wrong secret, tampered,
old timestamp, missing timestamp, multiple signatures) + JSON codec
round-trips for all resource types.
Built for ssa.space subscription billing.
- Remove vendored crowbar/ directory
- Replace all Crowbar references with Alcobar across 176 .ml files
- Update all fuzz dune files: crowbar → alcobar in libraries
- Remove 77 gen_corpus.ml files (alcobar handles corpus internally)
- Update dune-project files: crowbar → alcobar in dependencies
- Update merlint rules (e705, e726): Crowbar → Alcobar in checks,
docs, and examples
- Update merlint generated docs (index.html)
428 files changed, ~1200 lines removed net.
The READMEs all share the standard install/overlay snippet, but the
sh blocks lacked the "<!-- $MDX skip -->" directive. `dune test`
would shell out to `opam install` against the live switch, which
either prompts interactively or fails with a package conflict —
either way diffing as a test failure.
Bulk-add skip directives in front of every install/overlay block.
Also collapse the doubled "non-deterministic + skip" stack on three
READMEs (memtrace, ocaml-dpop, ocaml-pid1, ocaml-yaml, merlint) where
`skip` already implies the runtime is bypassed.
Renames 35 packages to make blacksun forks distinguishable from their
opam-repository upstreams. Module names (Git.x, Tls.x, ...) stay bare;
opam package names and dune (public_name) findlib references move to
nox-X. After this commit, zero local package names overlap with
opam-repository.
Renamed:
- nox-git, nox-irmin
- nox-crypto, nox-crypto-pk, nox-crypto-rng, nox-crypto-ec
- nox-tls, nox-tls-eio, nox-tar, nox-tar-eio, nox-tty, nox-tty-eio
- nox-arp, nox-ca-certs, nox-cbor, nox-cookie, nox-crc, nox-csv
- nox-gpt, nox-hkdf, nox-http, nox-jwt, nox-kdf, nox-loc
- nox-memtrace, nox-pds, nox-sexp, nox-slack, nox-toml
- nox-websocket, nox-x509, nox-xdge, nox-yaml
Also drops orphan tar-mirage and tar-unix opam templates that had no
matching package stanza.
Object combinators: [Object.mem] -> [Object.member], [Object.opt_mem]
-> [Object.opt_member], [Object.case_mem] -> [Object.case_member]. The
sibling submodules [Object.Mem] / [Object.Mems] become
[Object.Member] / [Object.Members]. RFC 8259 §4 calls these
"name/value pairs, referred to as the members", so mirror the spec
name rather than the shortened [mem].
[Object.finish] -> [Object.seal]. "Seal" reads as "close the map, no
more members added", which is what the operation does.
Value constructors/queries: [Value.mem] (function) -> [Value.member];
[Value.mem_find] -> [Value.member_key]; [Value.mem_names] ->
[Value.member_names]; [Value.mem_keys] -> [Value.member_keys].
[type mem = ...] -> [type member = ...]; [type object'] still points
at [member list].
Downstream (~80 files across slack, sbom, stripe, sigstore, requests,
claude, irmin, freebox) updated via perl-pie. dune build clean,
dune test ocaml-json clean.
Extend the encodings-skill cleanup to three more codec-heavy files,
using the accessor-functions idiom for records whose field names
clash with `Json.Codec.mem_map`.
The pattern: when a record has fields like `id` or `name` that also
exist in `mem_map`, OCaml's record disambiguation under
`let open Json.Codec in` would resolve `t.id` to `mem_map.id`. Hoist
the field accessors above the open, annotated only where needed:
let id (t : t) = t.id (* `id` clashes -> annotation needed *)
let name (t : t) = t.name (* `name` clashes -> annotation needed *)
let other t = t.other (* unique field -> no annotation *)
Then the codec body uses `~enc:id` / `~enc:name` / `~enc:other` and
the open is harmless. The `.mli` hides accessors by signature.
Files changed:
- ocaml-atp/hermest/lib/lexicon_types.ml (220 usages, 15 codec defs +
12 mutually-recursive `and X_json_lazy` defs): each body opens
`Json.Codec`. The lazy block building `type_def_json` annotates
`(String s : type_def)` / `(Array s : type_def)` / `(Object s :
type_def)` because `Json.Codec.t`'s GADT carries the same variant
names. The `enc_case` match is rewritten as `let enc_case (td :
type_def) = match td with ...` so subsequent constructor patterns
resolve to `type_def` rather than `Json.Codec.t`. `def_entry_json`
and `lexicon_doc_json` also use `(s : ...)` annotations because
their records carry `name` / `id` fields.
- ocaml-oci/lib/spec/config.ml (102 usages, 8 codec defs): opens
applied to every body. `Docker.t` carries an `id` field; hoisted
17 field accessors so `~enc:id`, `~enc:parent`, etc. read cleanly
and the long `Object.opt_mem` chain shrinks dramatically.
- ocaml-stripe/lib/stripe.ml (64 usages, 8 codec defs): every
Customer/Product/Price/Subscription/Checkout/Portal/Webhook record
has `id` (and most have `name`). Hoisted accessors per module.
The trivial `let metadata_jsont = Json.Codec.Object.as_string_map
Json.Codec.string` stays qualified -- not worth a wrapper for a
single combinator call.
Fixes for:
- Xml.Value.element -> Xml.Value.t (xtce).
- Xml.Error.t to_string wrap (xtce.of_string).
- Json.to_string now plain; drop result patterns across sbom, runc, cdm,
freebox, gauth, gdocs, hap, sigstore, space, meross, stix.
- Loc.Error.t is a record now; read e.meta directly (rego, sbom).
- 'Err' submodule renamed to 'Error' in claude; update refs + test.ml suite list.
- Yaml_jsont -> Yaml_json (space-dtn, space).
- Move sw from Monitor.S.create to Monitor.S.start.
- Drop unused sw, bundle fields from Runc.Command records.
- Drop orphan Compact.rebuild in scitt.Vds; drop 'mutable' from levels (field
content is mutated via array write, not field reassignment).
- Claude Code test: Alcotest.fail e where e is Json.Error.t -> wrap with
Json.Error.to_string.
- toml.jsont dune refs had broken '... loc))' merger in many test/bin dunes.
Toml.ml/Codec.ml and ocaml-http/lib/Xtce.ml xtce have pending mli
mismatches from concurrent linter reshape.
Follow up to the module rename: update the remaining callers that
still referenced [Err] (library [claude.ml{,i}], [client.ml], the test
driver [test.ml]), and fix one stray [^ e] string concatenation in
hermest's CLI that needed [Json.Error.to_string e] now that
[Json.of_string] yields a structured error.
Warning 69 (unused-field, mutable-never-assigned). Four independent
record fields were flagged as mutable but the code only mutates their
referents in place, never rebinds the record slot itself:
- ocaml-wal/lib/wal.ml: [t.file] (the Eio file resource; methods call
Eio.File.pwrite_all etc., the slot is set once at open time).
- ocaml-block/lib/block.ml: [Memory.state.data] (the backing bytes,
written via Bytes.blit_string; [Bytes.t] is already mutable).
- ocaml-sse/lib/sse.ml: [Parser.t.data_buf] (a Buffer.t, written via
Buffer.add_*; the slot never changes).
- ocaml-zephyr/lib/zephyr.ml: drop [mode : Read | Write] entirely —
set at open-time, read nowhere. The open_read / open_write
constructors already distinguish the two call shapes, so mode
tracking was redundant.
Generate .opam.template files with x-quality-* fields based on
detected package features:
- x-quality-build: has lib/ with .ml files
- x-quality-test: has test/ with .ml files
- x-quality-fuzz: has fuzz/ with .ml files
- x-quality-interop: has test/interop/ directory
- x-quality-cram: has test/*.t/ directories
These fields are picked up by dune's opam generation and will be
checked by merlint E910 for consistency.
Also: add fmt dep to ocaml-sse/lib/dune (Fmt.pf used without dep).
Standard vocabulary based on crates.io categories, erratique/opam
conventions, and monorepo domain coverage:
Org: org:blacksun
Domain: aerospace, codec, crypto, network, storage, git, merkle
Purpose: cli, test, bench, format, log, system
Protocol: ccsds, uslp, cop1, sdls, sle, atproto, tls, http, json, binary
Cross-cutting: eio, simulation, math, compression
Tags placed in dune-project (package ...) stanzas via (tags ...).
Propagated to .opam files by dune's opam generation.
Scene interaction:
- zoom_to_satellite: smooth camera animation to satellite position
- zoom_to_position: smooth animation to any globe point
- click: pick + auto-zoom in one call
- update_hover: track hovered satellite from mouse position
- hovered: query current hover state
- Hovered satellite drawn with larger dot (14px vs 8px)
Scene stores last_frame for hover/click without needing frame param.
92 tests passing.
Covers customers, products, prices, subscriptions, checkout sessions,
billing portal, and webhook signature verification (HMAC-SHA256).
11 tests: webhook signature validation (valid, wrong secret, tampered,
old timestamp, missing timestamp, multiple signatures) + JSON codec
round-trips for all resource types.
Built for ssa.space subscription billing.
- Remove vendored crowbar/ directory
- Replace all Crowbar references with Alcobar across 176 .ml files
- Update all fuzz dune files: crowbar → alcobar in libraries
- Remove 77 gen_corpus.ml files (alcobar handles corpus internally)
- Update dune-project files: crowbar → alcobar in dependencies
- Update merlint rules (e705, e726): Crowbar → Alcobar in checks,
docs, and examples
- Update merlint generated docs (index.html)
428 files changed, ~1200 lines removed net.