Skip to content

v0.3.1

Choose a tag to compare

@ghchinoy ghchinoy released this 16 Aug 21:54
8090ea8

0.3.1 (2026-08-16)

Bug Fixes

  • key docs-impact gate on option text and declare bound (#116) (2548cf7)
  • preserve unchanged pre-existing keys byte-for-byte (427503e)
  • quote SKILL.md description so frontmatter is valid YAML (#90) (568b3c6), closes #88
  • stop code-region stray bracket from swallowing next link (#117) (8d47111)

Continuous Integration

  • enforce PR template docs-impact field (#108) (6bf1f0d)

Documentation

  • add in-memory labeled property graph primer (#110) (31769de)
  • add okf cross-check step to tutorial, de-jargon pass (#105) (57579cb)
  • correct anchor slug rules and name which slug is which (#91) (62ea325)
  • editorial pass on the LPG primer and link it from the guide (#114) (80a8eb6)
  • fix false trust and contract claims in okf-convert skill (#112) (84116dc)
  • focus the README on using binder, not building it (#98) (7e2eb3c)
  • record validate's reserved-file scope in guide and tutorial (#102) (23a82a3), closes #97
  • tidy download v-note and mark JSON output agent-ready (#107) (8ddc8a0)
  • trim README to quickstart, rehome MCP parity to guide (#111) (b10b9ab)

Known issues — present in v0.3.0 and v0.3.1

None of the issues below is fixed in v0.3.1. Fixes are landing in v0.3.2.

These were found by an audit of every guarantee binder states in its help text and documentation: 45
claims were checked by running the binary, and the ones below did not hold. We are listing all of
them, including the ones that reflect badly on us, because binder's central promise is that it never
asserts something it has not verified — and that promise has to bind our release notes too.


1. binder enrich can write frontmatter that binder itself cannot read back

This is the most serious issue here: it can leave a file unusable.

When frontmatter contains a multi-line flow sequence — a [] collection spread over several
lines — and binder appends an entry to it, the collection is re-encoded to block style but its
original closing ] is left orphaned on its own line. The result is not valid YAML.

Given demo/metric.md:

---
type: Metric
verified: [
  { by: human:x, at: 2024-02-01T09:30:00Z },
  { by: human:y, at: 2024-03-01T09:30:00Z },
]
---

# Body

running binder enrich demo --verified-by human:ghchinoy reports success:

1 file(s): 1 enriched, 0 unchanged, 0 skipped
  enriched metric.md (added: generated, title, verified)

but produces frontmatter with a stray ] on its own line:

---
type: Metric
verified:
  - at: "2024-02-01T09:30:00Z"
    by: human:x
  - at: "2024-03-01T09:30:00Z"
    by: human:y
  - at: "2026-08-16T21:53:51Z"
    by: human:ghchinoy
]
title: Body
generated:
  at: "2026-08-16T21:53:51Z"
  by: binder/dev
---

A subsequent run cannot read the file it just wrote:

1 file(s): 0 enriched, 0 unchanged, 1 skipped
  skipped metric.md (unparseable frontmatter: invalid frontmatter: yaml: line 8: did not find expected key)

This transcript is real output, captured from a source build at the v0.3.1 commit — which is why the
provenance line reads binder/dev. The two 2026 timestamps are wall-clock values from that run; your
timestamps will differ, the corruption will not.

If you have run binder enrich over a corpus containing multi-line flow sequences, we recommend
checking that those files still parse.
Single-line flow sequences are not affected. A fix is
landing in v0.3.2.

2. binder enrich inserts a blank line between the frontmatter and the body

If a document's body starts immediately after the closing --- with no blank line, binder inserts
one when it rewrites the file. The body's content is preserved exactly, but its first byte
changes
.

This happens on the default enrich path — it is the common case, not an edge case. It also
happens when only an existing value changes and no key is added at all.

This is a defect, and v0.3.2 is landing a change that makes the byte-faithfulness guarantee true
rather than narrowing it.

Two further deviations are deliberate, documented, and long-standing — design bounds rather than
defects, but listed here because anyone relying on byte-faithfulness needs to predict every
difference between their input bytes and their output bytes:

  • CRLF line endings are normalised to LF.
  • A file that does not end in a newline gains one.

3. Several stated guarantees are broader than the behaviour

v0.3.2 addresses all of these.

  • enrich is described as byte-faithful, without qualification, in the command's help text, in
    README.md, in the packaged skill documentation, and in the ingestion-workflow and JSON-contract
    reference docs. Issue 2 above is why that is currently wrong, everywhere it is stated.
  • convert is described as deterministic, without qualification. Two runs over identical input
    differ in the generated provenance timestamp, which is deliberately a live record of when the run
    happened. Output is byte-identical when the clock is pinned via SOURCE_DATE_EPOCH. The
    behaviour is correct; the description is missing the qualifier
    — which the same user guide
    already applies correctly to enrich.
  • enrich is described as idempotent, without qualification. It is idempotent on the default
    path, including across a live clock. It is not idempotent when --verified-by is used: a
    second run appends a second attestation.
  • enrich is described as adding only absent keys. A trust key that is already present is
    appended to rather than skipped. binder still never clobbers or removes an existing value.

For the avoidance of doubt, the fourth guarantee in that same description — that writes are
atomic — was tested and holds. binder writes to a temporary file in the same directory and
renames it over the target, so an interrupted run leaves either the original file or the complete
replacement, never a partial one.

4. A verified-by value from the environment stamps without an explicit flag

If BINDER_VERIFIED_BY is set, binder writes a verified attestation without --verified-by being
given on the command line. An environment variable can arrive by means other than a deliberate
decision to attest. v0.3.2 is landing a change so that binder refuses to stamp from the
environment alone, and says so. An explicit --verified-by, or a verified-by value in your own
global config
, continues to stamp as before.

5. The JSON report classifies a modified trust key as added

When a trust key that was already present is appended to, the binder.report/v1 envelope lists it
under added. Consumers reading that field programmatically get a wrong classification for the trust
key. The file content is correct; the report's description of what happened to it is not.


The link-resolution bug reported in #99 is fixed and ships in v0.3.1.