Skip to content

fix(hw-gate): the status job reads the verdict from decision_final - #706

Merged
Kaden-Schutt merged 1 commit into
masterfrom
fix/hw-gate-status-decision-final
Sep 4, 2026
Merged

fix(hw-gate): the status job reads the verdict from decision_final#706
Kaden-Schutt merged 1 commit into
masterfrom
fix/hw-gate-status-decision-final

Conversation

@Kaden-Schutt

Copy link
Copy Markdown
Collaborator

Summary

review.py writes the seat's full object under .decision and the floor-applied verdict under .decision_final. The status step read .decision, got a JSON object, fell into the *) arm, and went red on every run — including #689's successful staging merge (run 33889229683: Fable merged 8f3a9b6c5 to beta as 3149be7de, label merged-staging applied, status blocked ()).

Fix: jq -r '.decision_final // .decision.decision // "hold"'.

Evidence

On the real artifacts: #689merge-staging (green); #702's no-decision run → block (red). Workflow YAML parses. No change to the floor or the seats.

Which surface(s) does this touch?

  • policy fileshw-gate.yml (hard floor: a human merges this)

review.py writes the seat's full object under `.decision` and the
floor-applied verdict under `.decision_final`. The status step read
`.decision`, got a JSON object, matched the `*)` arm, and went red on
every run — including #689's successful merge-staging (run 33889229683:
Fable merged 8f3a9b6 to beta as 3149be7, label merged-staging
applied, status "blocked ()").

`jq -r '.decision_final // .decision.decision // "hold"'`: on the #689
artifact → merge-staging (green); on the #702 no-decision artifact →
block (red). No change to the floor or the seats.
@Kaden-Schutt
Kaden-Schutt merged commit 931b571 into master Sep 4, 2026
@hipfire-sol

hipfire-sol Bot commented Sep 4, 2026

Copy link
Copy Markdown

hw-gate sol prelim

summary: The workflow status job now reads the floor-applied scalar verdict from decision_final, with a compatibility fallback to the nested Fable verdict at decision.decision, instead of reading the entire decision object and routing every result to the blocking default case.

run_hardware: true
run_hardware_reasons: The only executable change is a transparent jq query over the existing decision.json artifact; it adds no dependency, credential access, process spawning, network access, or filesystem access beyond the workflow's existing artifact path.; scripts/hw-gate/review.py:1619-1621 confirms that .decision is the full seat object while .decision_final is the scalar floor-applied verdict consumed by the status case statement.; This is a policy-file change and therefore still requires human review, but the changed workflow is safe to execute on the runner.

routes:

mode tag source why
no routes

unavailable_routes:

(none)

claim_assessment: The author claims that replaying the status query against real decision artifacts classifies #689 as merge-staging and #702 as block. The schema and diff prove the field-selection defect and the correctness of the new primary field; replaying the exact jq expression against those two archived artifacts would prove the cited outcomes. Model fixtures cannot provide relevant evidence for this CI-policy-only change.

@hipfire-sol

hipfire-sol Bot commented Sep 4, 2026

Copy link
Copy Markdown

hw-gate evidence — 2 lane(s) — verdict pass

lane hiptrx (gfx1201)

hw-gate evidence

field value
base 05083d57b5c7a5a3e74630ea67566c26ce691b16
head e98ffaac69d75c0e5b5338820b2eedbd4c7e9dba
buckets
host gfx gfx1201
host rocm 7.15.26333-0000000
device 3
runner hiptrx
daemon_md5 17ba7dfab49aa1c1110d3f412f072648
hipfire_md5 aa199c337a7141d419361780289a9ce2
build_seconds 40.189547538757324
verdict pass
logs_dir hw-gate-logs

fixtures

no fixtures

kernel

not run

lane hipx (gfx1100)

hw-gate evidence

field value
base 05083d57b5c7a5a3e74630ea67566c26ce691b16
head e98ffaac69d75c0e5b5338820b2eedbd4c7e9dba
buckets
host gfx gfx1100
host rocm 7.15.26333-0000000
device 0
runner hipx
daemon_md5 17ba7dfab49aa1c1110d3f412f072648
hipfire_md5 aa199c337a7141d419361780289a9ce2
build_seconds 6.001476287841797
verdict pass
logs_dir hw-gate-logs

fixtures

no fixtures

kernel

not run

@hipfire-sol

hipfire-sol Bot commented Sep 4, 2026

Copy link
Copy Markdown

hw-gate sol verdict

{
  "claim_verdict": "not-exercised",
  "confidence": 0.96,
  "coverage": {
    "gaps": [
      "The cited replay outcomes for archived #689 and #702 decision artifacts are not included in hw-gate.json."
    ],
    "surfaces_evidenced": [
      "policy",
      "ci"
    ],
    "surfaces_touched": [
      "policy",
      "ci"
    ]
  },
  "decision": "needs-human",
  "eyeball": [
    ".github/workflows/hw-gate.yml:499-513 changes required-status policy and must receive human review; verify that only decision_final=merge-staging can make the status green and that hold remains subject to the human-reviewed exception."
  ],
  "phase": "verdict",
  "rationale": "The diff matches the producer schema: scripts/hw-gate/review.py:1418-1435 computes the scalar decision_final, while decision is the full Fable object. The new query at .github/workflows/hw-gate.yml:503 therefore supplies the scalar expected by the case statement and retains a sensible nested-field fallback. The hardware run succeeded on gfx1201 and gfx1100, with no fixture failures, but its empty route set cannot independently prove the claimed #689/#702 artifact replays. No regression is evident; needs-human is mandatory because this changes a policy workflow.",
  "regressions": []
}

Floor: hard=['policy_paths: .github/workflows/hw-gate.yml'] soft=["coverage_gaps: ['The cited replay outcomes for archived #689 and #702 decision artifacts are not included in hw-gate.json.']", 'model needs-human'] model_decision=needs-human final=needs-human

@hipfire-sol hipfire-sol Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hw-gate sol verdict needs-human: The diff matches the producer schema: scripts/hw-gate/review.py:1418-1435 computes the scalar decision_final, while decision is the full Fable object. The new query at .github/workflows/hw-gate.yml:503 therefore supplies the scalar expected by the case statement and retains a sensible nested-field fallback. The hardware run succeeded on gfx1201 and gfx1100, with no fixture failures, but its empty route set cannot independently prove the claimed #689/#702 artifact replays. No regression is evident; needs-human is mandatory because this changes a policy workflow.

@hipfire-fable

hipfire-fable Bot commented Sep 4, 2026

Copy link
Copy Markdown

announcement: Holding only because this edits the gate workflow, which a human merges by rule; on the evidence the fix is right and I'd put my name on it. I pulled the Status step out of both workflow revisions and ran it under real jq against every decision.json shape review.py can write plus the real artifact #705 left on this runner: base reproduces your blocked () exactly, and head sends merge-staging green, hold red-until-labelled, and block red — including the case where the floor overrode a seat's merge-staging, which correctly stays block. Worth knowing: the same bug also meant the human-reviewed label never cleared a real policy hold on master, so this fixes two things. One nit if you're touching it again: the old jq printed the pretty-printed object, not "[object]". Full replay is in the evidence artifact under pr706-*.

investigation:

| question | route | result | evidence |

|---|---|---|---|

| Does the base workflow's Status step actually go red on a successful merge-staging artifact, and does the head's jq fix route every shape review.py can write to the right arm? | bash $HW_GATE_EVIDENCE/pr706-status-replay.sh — pyyaml-extracts the Status step run: string from hw-gate.yml at $HW_GATE_BASE_SHA and at HEAD, substitutes the two ${{ }} expressions, runs each under real jq-1.8.1 against 8 decision.json artifacts (7 synthesized to review.py:1615-1624's schema: merge-staging, hold, block, seat-null/hold, floor-overrides-seat, legacy-no-decision_final, {}; plus real-705.json, the actual decision.json #705's session left at the workspace root) × human_reviewed ∈ {false,true} | Base: merge-staging artifact → $decision is the 11-line pretty-printed seat object → *) arm → ::error::blocked () exit 1, the exact string the author quotes from run 33889229683. Head: merge-staging → exit 0; hold → exit 1 without label, exit 0 with human-reviewed; block → exit 1 both ways; decision_final=block with the seat saying merge-staging → block (floor wins over seat); seat-null → hold; real-705 → hold. 32/32 cells behave as the case statement intends on head. | , pr706-status-step-{base,head}.sh |

| Did base also break the human-reviewed escape hatch for policy holds (undocumented in the PR body)? | same replay, base workflow, human_reviewed=true, artifacts hold and real-705 | Both exit 1 with blocked (policy_paths: …) — a real hold artifact carries a seat object too, so on master the label could never clear a policy hold (only the seat-absent decision: null shape reached the hold) arm). Head clears both with the label (exit 0). The PR fixes a second defect it does not claim. | pr706-status-replay.txt (sections 'Status step [base workflow], human_reviewed=true') |

| Is the .decision.decision fallback arm a way for a merge-staging to bypass the floor? | review.py:1418-1435 (decision_final always assigned a string), :1461-1478 (merge failure demotes decision_final to hold), workflow 'Base checkout (gate scripts)' step (review.py runs from base, not the PR), git log -S'"decision_final"' and git log -L on the jq line | Inert for every artifact the writer can produce: decision.json and decision_final were introduced together in b38da8e, review.py runs from the base checkout, and // takes decision_final first. The .decision read dates from b38da8e, when the status moved from verdict.json .floor.final_decision (scalar) to decision.json .decision (object); .decision_final is the scalar analogue. decision_final=merge-staging is only written after the GitHub merge succeeded, so green == actually merged. | pr706-context-checks.txt |

| Does the PR merge cleanly onto current master (branch predates #705, which also edited hw-gate.yml)? | git merge-tree --write-tree $HW_GATE_BASE_SHA HEAD; python3 yaml.safe_load of both workflow revisions (implicit in the extractor) | Clean tree fcc943efd, rc=0, no conflict entries; hunks are disjoint (#705 at the decide job ~line 409, #706 at the status step 499-503). Head YAML parses. | pr706-context-checks.txt |

unproven:

rationale: Hard floor fired on policy_paths (.github/workflows/hw-gate.yml), so the decision is hold or block; nothing here is an evidence failure, so hold. On the merits the change is correct and I would merge it: hw-gate.yml:503 now reads the scalar review.py writes at review.py:1621 (decision_final) instead of the seat object at :1619, and the Status step extracted verbatim from both revisions and replayed under real jq-1.8.1 (pr706-status-replay.txt) shows base going red on every seat-bearing artifact — merge-staging and hold alike, which also means the human-reviewed label has never been able to clear a policy hold on master — while head routes all 8 artifact shapes × 2 label states as the case statement intends, including the safety-critical one where the floor forced block over a seat's merge-staging. The .decision.decision fallback is unreachable for any artifact the base-checkout review.py writes (pr706-context-checks.txt) and cannot precede decision_final. Merge-tree onto base is clean. Sol's single coverage gap (the #689/#702 replays) is closed in kind by real-705.json plus the schema-exact synthetic artifacts; the exact blocked () string the author quotes is reproduced. One nit for whoever merges: the new comment says the old jq yielded "[object]"; it yields the pretty-printed object. Index: $HW_GATE_EVIDENCE/pr706-fable-summary.md.

hard floor: ['policy_paths: .github/workflows/hw-gate.yml']

soft floor: ["coverage_gaps: ['The cited replay outcomes for archived #689 and #702 decision artifacts are not included in hw-gate.json.']", 'model needs-human']

@hipfire-fable hipfire-fable Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holding only because this edits the gate workflow, which a human merges by rule; on the evidence the fix is right and I'd put my name on it. I pulled the Status step out of both workflow revisions and ran it under real jq against every decision.json shape review.py can write plus the real artifact #705 left on this runner: base reproduces your blocked () exactly, and head sends merge-staging green, hold red-until-labelled, and block red — including the case where the floor overrode a seat's merge-staging, which correctly stays block. Worth knowing: the same bug also meant the human-reviewed label never cleared a real policy hold on master, so this fixes two things. One nit if you're touching it again: the old jq printed the pretty-printed object, not "[object]". Full replay is in the evidence artifact under pr706-*. Hard floor fired on policy_paths (.github/workflows/hw-gate.yml), so the decision is hold or block; nothing here is an evidence failure, so hold. On the merits the change is correct and I would merge it: hw-gate.yml:503 now reads the scalar review.py writes at review.py:1621 (decision_final) instead of the seat object at :1619, and the Status step extracted verbatim from both revisions and replayed under real jq-1.8.1 (pr706-status-replay.txt) shows base going red on every seat-bearing artifact — merge-staging and hold alike, which also means the human-reviewed label has never been able to clear a policy hold on master — while head routes all 8 artifact shapes × 2 label states as the case statement intends, including the safety-critical one where the floor forced block over a seat's merge-staging. The .decision.decision fallback is unreachable for any artifact the base-checkout review.py writes (pr706-context-checks.txt) and cannot precede decision_final. Merge-tree onto base is clean. Sol's single coverage gap (the #689/#702 replays) is closed in kind by real-705.json plus the schema-exact synthetic artifacts; the exact blocked () string the author quotes is reproduced. One nit for whoever merges: the new comment says the old jq yielded "[object]"; it yields the pretty-printed object. Index: $HW_GATE_EVIDENCE/pr706-fable-summary.md.

@hipfire-fable hipfire-fable Bot added the needs-human hw-gate reviewer requests a human decision label Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-human hw-gate reviewer requests a human decision

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant