Skip to content

story(cli): the command that reads a revision runs from the image the project publishes #228

Description

@Zaba505

Description

dfcad review is the one command a consumer cannot run the way this project ships itself.

The published image is scratch — there is no shell in it, which is right, and no git
either. review shells out to git, so against the image it fails before it reads anything:

$ podman run --rm -v $PWD:/model:ro \
    ghcr.io/z5labs/dfcad@sha256:f3f36430d3dc212f9590ab1c5997a62ec5be233b1e8c454f1610ad37a5e3c01d \
    review --root /model
dfcad review: git rev-parse --show-toplevel in /model: git is not on the path
exit 2, stdout 0 bytes

Measured 2026-08-11 against d9e9cab. Every other command in the pipeline works from the image
check, measure, plan, tessellate, export and export-map all ran clean against a
read-only mount in the same session, byte-identically across two runs. review is the only
hole, and it is the command whose whole job is to report what changed in a revision, so a
consumer's model gate is exactly where it would be called.

The result is that a repository consuming dfcad as a container — which is what
docs/decisions/0019-the-registry-is-the-distribution-channel.md says the distribution channel
is — can gate on every rule the model states and cannot gate on whether a change needed an
explanation. The workaround available today is extracting the binary
out of the image and running it on a host that has git, which gives up the pinned, stamped,
attested artefact for the one command that needed it most.

This is a report about a boundary, not a request for a particular fix. Three shapes exist
and they are genuinely different decisions:

  • Put git in the image. Cheapest, and it stops the image being scratch — which is a real
    cost, not a bookkeeping one, since the current image is the reason the attestations mean
    something.
  • Read the revision without shelling out, so review needs no git on the path.
  • Say plainly that review is a host command, document it beside the others as such, and let
    a consumer's gate stop expecting it. This is a legitimate answer and it is better than the
    status quo, because right now the boundary is discovered by hitting it.

Consumer context: Zaba505/mi-casa records this in its own adoption and gate stories
(Zaba505/mi-casa#76, Zaba505/mi-casa#83), which currently plan around it by extracting the
binary. It was not one of the eleven issues filed as #206#216 — it surfaced while verifying
those against the container rather than a local build.

Acceptance Criteria

  • It is decided in writing which of the three shapes above this project takes, and the
    decision names the cost it accepts
  • Either dfcad review runs against the published image, or the documentation states that
    it does not and why — in the same place a reader learns what review is for, not only in
    a decision record
  • Where review stays a host command, docs/publishing.md says which commands the image
    is a complete answer for, so a consumer building a gate knows the boundary before it
    writes one
  • The failure keeps naming the cause. git is not on the path is a good diagnostic and the
    exit-2-with-empty-stdout behaviour is correct; whatever changes, a consumer still gets a
    sentence rather than a silent empty result

Related Issues

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    storyA unit of user-facing work

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions