Skip to content

COMMITWARD_HITL=off does not reach the gate subcommand, though --help says it disables the binary entirely #21

Description

@lyubomir-bozhinov

main() dispatches the gate subcommand before run(), and the COMMITWARD_HITL check lives inside run() (main.rs:313). So the documented off switch is inert on the programmatic path, while the binary's own help text says it disables the binary entirely.

Measured — published commitward 0.3.0

ghcr.io/barnett-studios/commitward:0.3.0, the env var set in the process environment:

$ docker run --rm -i -e COMMITWARD_HITL=off --network none \
    ghcr.io/barnett-studios/commitward:0.3.0 gate < request.json
{"schema_version":"1","status":"ok","body":{"fired":[{"name":"path-guard",...},{"name":"content-guard",...}],
 "unacked":["path-guard","content-guard"],"exit_class":2,...}}

exit_class: 2 — a consumer reading the documented decision field blocks, with the off switch on. Same request without the variable gives the identical envelope, so the variable changes nothing on this path.

The documented claim

--help, printed by this same binary, two lines under the gate subcommand it lists:

SUBCOMMANDS:
    gate    Read a JSON gate request on stdin ...

Disable entirely with COMMITWARD_HITL=off.

"Entirely" is the word at issue. install-hook.sh honours it ([ "${COMMITWARD_HITL:-on}" = "off" ] && exit 0), the CLI honours it, gate does not.

The counter-reading, stated plainly

CONTRACT.md puts Off switch under Front door 1 — CLI, and never claims it for the envelope. On that reading the scope is intentional — the programmatic consumer owns its own escape hatch — and the only defect is the word "entirely" in USAGE, which would make this a docs fix rather than a behaviour one. I have filed class-D on the basis that the failing surface is the help text a user actually reads, not CONTRACT.md; if the maintainer reads it as class-N, that is fair and I will not argue the label.

What is not defensible either way is the silence: a gate run with the off switch set gives no indication that the switch was seen and ignored. If the scoping is deliberate, body.warnings is the natural place to say so.

Suggested direction

Either honour it (exit_class: 0 plus a warning naming the override, so the response still says a check did not run), or keep the scope and make USAGE say which door it opens — "Disable the CLI gate with COMMITWARD_HITL=off; the gate envelope is not affected."

Environment

  • ghcr.io/barnett-studios/commitward:0.3.0 (digest sha256:1f737085474e), --network none, no mounts
  • Also present on main (9212058): the check remains inside run(), after the gate dispatch in main()
  • Filed by the family QA rotation (Barnett-Studios/.github#3)

Metadata

Metadata

Assignees

No one assigned

    Labels

    class-BBroken flow: a documented surface does not work for an outside consumerclass-DRough edge: DX friction, confusing output. Left open deliberatelyp2priority 2

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions