Skip to content

openkal-kit 0.1.1: the kit reaches the specification the way a consumer does - #14

Merged
Sunrisepeak merged 3 commits into
mainfrom
fix/kit-names-the-specification
Aug 27, 2026
Merged

openkal-kit 0.1.1: the kit reaches the specification the way a consumer does#14
Sunrisepeak merged 3 commits into
mainfrom
fix/kit-names-the-specification

Conversation

@Sunrisepeak

@Sunrisepeak Sunrisepeak commented Aug 27, 2026

Copy link
Copy Markdown
Member

openkal-kit 0.1.0 was published in a form that cannot be used. Its manifest read openkal = { path = ".." } — true inside this repository and inside the tarball it is published from, false for a consumer. A project naming openkal-kit alongside any implementation reached the specification two ways and the build refused, correctly:

error: dependency 'mcpplibs.openkal' is requested as both a path dep (by
       'mcpplibs.openkal-kit@0.1.0') and a version dep (by 'mcpplibs.openkal-musl@0.4.0').

⚠️ Nothing here could have caught it before publication. Every workflow in this ecosystem substitutes working trees, so both routes become paths and agree. The defect needs an implementation naming the specification by version — the published shape, and precisely what no job reproduces. It was found by resolving the published packages in a sandbox.

The specification is not released for this. An earlier revision of this branch bumped openkal to 0.8.1 to obtain a tag containing the repair, and that turned all five conformance rows red on the in-step check. Both that bump and the check relaxation written to accommodate it are reverted: a package's version key need not equal the tag it is published from (grpc-plugin 1.83.0 comes from grpc-m's v1.83.0-4), so openkal-kit 0.1.1 is published from a tag of its own.

What remains:

  • kit/mcpp.toml names openkal = "0.8.0"; version 0.1.0 → 0.1.1.
  • include_dirs = ["../include"] removed — it reaches out of the package, so with the specification resolved by version it would supply the tarball's header copy while the code links the resolved dependency. Measured: the kit compiles and runs without it.
  • run-kit-tests.sh substitutes the kit's own openkal line, which it never needed while that line was a path; asserted like the two beside it.
  • A structural guard in the conformance job: it cannot reproduce a consumer's graph, but it can require the form that avoids the problem.

THE SPECIFICATION TEXT IS UNCHANGED. This release exists because openkal-kit
0.1.0 was published in a form that cannot be used.

Its manifest read `openkal = { path = ".." }`, which is true inside this
repository and true inside the tarball the package is published from. It is not
true for a consumer. A project naming openkal-kit alongside any implementation
reached the specification two ways and the build refused:

    error: dependency 'mcpplibs.openkal' is requested as both a path dep (by
           'mcpplibs.openkal-kit@0.1.0') and a version dep (by
           'mcpplibs.openkal-musl@0.4.0'). Pick one.

The refusal is right. Two routes to one package are two copies of it, and two
copies of a specification are two sets of its modules.

⚠️ NOTHING IN THIS ECOSYSTEM COULD HAVE FOUND IT BEFORE PUBLICATION. Every
workflow substitutes working trees, so both routes become paths and agree. The
defect requires an implementation that names the specification by VERSION,
which is the published shape and precisely what no job reproduces. It was found
by resolving the published packages in a sandbox.

`include_dirs = ["../include"]` goes with it. That directory reaches out of the
package into whatever sits above it; with the specification named by version it
would be the tarball's own copy while the headers actually compiled against come
from the resolved dependency --- two header sets for one contract. openkal
publishes `include` as its own `include_dirs` and a dependency's public
directories reach a consumer. Measured with the specification placed outside the
package: the kit compiles and runs without the line.

tools/run-kit-tests.sh gains a substitution it did not need before. While the
kit named the specification by path it already pointed at this working tree;
now that it names a version, these tests would have run against the PUBLISHED
specification while claiming to test the one written here. The new substitution
is asserted, as the two beside it are.

The guard added to the conformance job is structural rather than behavioural,
and deliberately so: it cannot reproduce the consumer's graph, but it can
require the form that avoids it.

Measured before pushing, with the released engine: the kit's tests build the
specification, the implementation and the tests together and report
`openkal-kit: every observation held`.
Publishing 0.8.1 turned every conformance row red:

    this is openkal 0.8.1 and openkal-linux is written against openkal 0.8.0.
    Nothing is wrong with either; they are not in step.

Correct by the letter of the check and wrong by its meaning. Clause 8 forbids
the specification from altering a declaration it has published, so within one
major.minor series every implementation is written against the same contract; a
patch releases packaging, wording, or a repaired example. Requiring the patch
component to match would make each such release a migration across five
repositories that changes no code in any of them --- and would do it to
announce a change that, by clause 8, cannot have occurred.

⚠️ The minor component still counts. 0.8 → 0.9 is where interfaces are added
and an implementation written for the earlier one does not provide them. That
is the mismatch this check exists to name before the compiler reports it as a
hundred missing declarations.

Self-checked over four pairs: 0.8.1/0.8.0 and 0.8.0/0.8.0 pass; 0.9.0/0.8.0 and
0.8.1/0.7.0 are refused.
The kit fix does not change the specification, and this reverts the two commits
that behaved as though it did.

openkal's version returns to 0.8.0. It was bumped for one reason: openkal-kit is
published out of this repository's tarball, so a repaired kit needs a tag that
contains the repair, and 0.8.0 is already published and immutable. A bump is one
way to obtain a tag. It is not the only one, and this index already establishes
the other: a package's version key need not equal the tag it is published from
--- grpc-plugin 1.83.0 comes from grpc-m's v1.83.0-4. openkal-kit 0.1.1 will
therefore be published from a tag of its own.

The in-step check returns to comparing the whole version. Relaxing it to the
major.minor series is defensible on its own terms --- clause 8 forbids altering
a published declaration, so a patch cannot change the contract --- but it was
written here to accommodate a version change that should not have happened, and
a fix should not carry a rule invented to excuse it. The check turned all five
conformance rows red the moment 0.8.1 appeared, which is the check doing its
job on a release that had no reason to exist.

What remains is the kit's own repair: it names the specification by version
rather than by path, it no longer reaches out of its directory for headers, and
tools/run-kit-tests.sh substitutes the line that used to need no substitution.
@Sunrisepeak Sunrisepeak changed the title openkal 0.8.1: the kit reaches the specification the way a consumer does openkal-kit 0.1.1: the kit reaches the specification the way a consumer does Aug 27, 2026
@Sunrisepeak
Sunrisepeak merged commit 37f4819 into main Aug 27, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants