epic: the gate scopes to the change, runs heavy tests as their own stage, and reads as a list of guarantees #767

Open
opened 2026-10-14 20:10:56 +00:00 by hexajon · 0 comments
Owner

Problem

The gate is one lump, and three problems follow.

  1. It runs everything regardless of the change. A doc-only edit runs the full
    suite. The one exception is a single hardcoded path that drops to two checks
    when every changed file ends in .md - a one-off, because there is no
    structure to scope a run to a change.

  2. The skip flags name what they turn off, not what the check does or why it
    needs its environment. --no-forge, --no-conformance, and
    --skip-remote-issues say nothing about the forge integration test, the MCP
    schema conformance check, or the issue-state check behind them.

  3. The heavy forge tests run in the default local gate, which needs the Incus
    VM, while CI skips them with --no-forge. That is backwards: the default run
    should be fast, and heavy tests should run as their own stage. A contributor
    with no VM cannot get a green default run, and CI - the side with the
    infrastructure - does not run the forge tests at all, against #678.

Direction

  • The default run is fast and scoped to the change. The dev runs the target for
    what they touched: a doc target, a code target, a lint target. CI selects the
    matching stage with path filters. There is no diff-detector.
  • A scoped target states the file classes it covers, checks that the diff stays
    inside them, and fails closed when the diff spills out, naming the target to
    run instead. A scoped pass is a checked claim, not a silent subset. This
    replaces the hardcoded .md shortcut.
  • The heavy forge tests leave the default run and run as their own stage, in CI
    and on demand. They are already tagged //go:build forge; the stage owns
    them, not the default. No contributor needs a VM for a green default run. This
    is the forge half of #678 and #692.
  • The formatter and the Go linters move behind golangci-lint. One config names
    every linter and its settings, so the config is the description. The
    staticcheck export-data gap that #741 tracks is resolved in that work: either
    the bundled staticcheck clears it, or staticcheck stays a pinned step beside
    the config.
  • Each check states what it proves and what it needs, so the gate reads as a
    list of guarantees, not a set of negative flags.

Children

To file once this is agreed.

  • The formatter and Go linters run behind golangci-lint, with the staticcheck
    export-data gap resolved.
  • The gate splits into scoped targets that fail closed when the diff exceeds
    their scope, replacing the .md shortcut.
  • Each check states what it proves and what it needs; the negative skip flags
    become derived, not hand-set.
  • A decision record captures the structure.

The forge stage is #678 and #692, not duplicated here.

Relates to #674 (the forge apparatus), #678 (forge tests in the gate and CI),
#766 (shellcheck on every script), #741 (staticcheck in the gate).

## Problem The gate is one lump, and three problems follow. 1. It runs everything regardless of the change. A doc-only edit runs the full suite. The one exception is a single hardcoded path that drops to two checks when every changed file ends in `.md` - a one-off, because there is no structure to scope a run to a change. 2. The skip flags name what they turn off, not what the check does or why it needs its environment. `--no-forge`, `--no-conformance`, and `--skip-remote-issues` say nothing about the forge integration test, the MCP schema conformance check, or the issue-state check behind them. 3. The heavy forge tests run in the default local gate, which needs the Incus VM, while CI skips them with `--no-forge`. That is backwards: the default run should be fast, and heavy tests should run as their own stage. A contributor with no VM cannot get a green default run, and CI - the side with the infrastructure - does not run the forge tests at all, against #678. ## Direction - The default run is fast and scoped to the change. The dev runs the target for what they touched: a doc target, a code target, a lint target. CI selects the matching stage with path filters. There is no diff-detector. - A scoped target states the file classes it covers, checks that the diff stays inside them, and fails closed when the diff spills out, naming the target to run instead. A scoped pass is a checked claim, not a silent subset. This replaces the hardcoded `.md` shortcut. - The heavy forge tests leave the default run and run as their own stage, in CI and on demand. They are already tagged `//go:build forge`; the stage owns them, not the default. No contributor needs a VM for a green default run. This is the forge half of #678 and #692. - The formatter and the Go linters move behind golangci-lint. One config names every linter and its settings, so the config is the description. The staticcheck export-data gap that #741 tracks is resolved in that work: either the bundled staticcheck clears it, or staticcheck stays a pinned step beside the config. - Each check states what it proves and what it needs, so the gate reads as a list of guarantees, not a set of negative flags. ## Children To file once this is agreed. - The formatter and Go linters run behind golangci-lint, with the staticcheck export-data gap resolved. - The gate splits into scoped targets that fail closed when the diff exceeds their scope, replacing the `.md` shortcut. - Each check states what it proves and what it needs; the negative skip flags become derived, not hand-set. - A decision record captures the structure. The forge stage is #678 and #692, not duplicated here. Relates to #674 (the forge apparatus), #678 (forge tests in the gate and CI), #766 (shellcheck on every script), #741 (staticcheck in the gate).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
sixfold-space/madtea#767
No description provided.