docs(contract): §4 — add a JSON scalar-typing clause - #29
Merged
Conversation
Closes #27. §4 pinned down which codecs exist and the stdout/stderr split, and §2 pins timestamp formatting, but nothing pinned the JSON type of an individual field. That gap produced the same class of bug four times across two repos (liftoff #33 quoted-string bodyweight, liftoff #36 duration-only-as-prose, withings #27/#20/#42 key-and-type drift). One unwritten rule violated repeatedly. Adds a Scalar typing subsection under §4 with three requirements — numbers are JSON numbers not strings; a logical field has one type (and null, not ""/0, when absent) across every subcommand; a human-formatted quantity ships a canonical-unit sibling — plus the timestamp carve-out (§2 already fixes their shape). Status table gains a JSON-scalar-typing row: liftoff is human-attested (fixed its known violations in v1.3.0), withings and crono stay at — (withings has open violations #27/#20/#42; crono is unaudited). Not machine-attested yet: a compat/scalars bundle is the follow-up, and it inherits the enforcement-reach gap #27 flags — liftoff and withings import only compat/formats, so a new bundle needs their imports widened to actually run in their CI. Tracked separately rather than bundled into this text change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MvqxTC64Z9EEDewCUbNNo
DTTerastar
enabled auto-merge (squash)
August 2, 2026 04:37
DTTerastar
disabled auto-merge
August 2, 2026 04:38
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #27.
Problem
§4 pins down which codecs exist and the stdout/stderr split; §2 pins timestamp formatting. Nothing pinned the JSON type of an individual field — so the same class of bug appeared four times across two repos:
bodyweightwas a quoted string ("175") inworkouts list/showbut a number inworkouts stats. One field, two types.sessionDurationshipped only as prose ("01 hours 06 minutes") next to numericcaloriesBurned/prCount. No arithmetic without parsing English.datetakes three shapes across five subcommands.Each was fixed or filed as a local wart. They're one unwritten rule violated repeatedly.
Change (docs only)
A Scalar typing subsection under §4, three requirements:
null(not""/0) when absent.sessionDurationSeconds), unit in the key name, additive.Plus the timestamp carve-out: §2 already fixes their shape, so a
dateMAY be a formatted string — but the same string across every subcommand of a CLI.Status table gains a JSON scalar typing row:
liftoff is human-attested (fixed #33/#36 in v1.3.0); withings has open violations (#27/#20/#42); crono is unaudited.
Not in this PR
The
compat/scalarsbundle that would make this machine-attestable. It's a larger piece, and it inherits the enforcement-reach gap #27 itself flags — liftoff and withings currently import onlycompat/formats, so a scalar bundle won't run in their CI until those imports are widened. Better as its own PR than smuggled into a text change. I can pick it up next if you want it.🤖 Generated with Claude Code
https://claude.ai/code/session_012MvqxTC64Z9EEDewCUbNNo