Skip to content

fix(hw-gate): drive DFlash in the gate; stop refusing user-path CLI diffs - #718

Merged
Kaden-Schutt merged 1 commit into
masterfrom
fix/hw-gate-dflash-route-and-sol-policy
Sep 5, 2026
Merged

fix(hw-gate): drive DFlash in the gate; stop refusing user-path CLI diffs#718
Kaden-Schutt merged 1 commit into
masterfrom
fix/hw-gate-dflash-route-and-sol-policy

Conversation

@Kaden-Schutt

Copy link
Copy Markdown
Collaborator

Two policy gaps this ladder exposed. Both are gate plumbing, no product code.

1 · The gate has never run DFlash

#686 (draft sidecars), #691 (draft ctor rollback), #692 (primer replay) and #702 (dedicated verify kernels) all went through this gate with every lane green while speculation never once executed. #692's DFlash-arm defect — primer replay systematically missing the most recent assistant body — surfaced only because a seat thought to drive twenty turns by hand. That is not a gate.

The load bucket now runs battery-dflash, the serve bucket chain-dflash: the same prompts with --dflash on and an explicit --draft.

  • on, not autoauto silently falls back to AR when the draft is missing, and a route that can pass without speculating proves nothing.
  • explicit --draft — the canonical xt trunk is a symlink out of the models dir, so the daemon's filename auto-match finds nothing and would quietly run AR.
  • dflash_draft is a candidate list, because the lanes hold different drafts: hiptrx has qwen36-27b-dflash-mq4.hfq and no qwen38, hipx has qwen38-27b-dflash-mq4.hfq and no qwen36.

skip is neither pass nor fail

This is the part worth reviewing. The aggregation was all(status == "pass"), so a skipped mode would have counted as a fixture failure — a false negative on evidence the host never had — while treating it as a pass would claim coverage that did not happen. Skips are now recorded, reported in the reason string, and excluded from the verdict; a genuine failure alongside a skip still fails.

Coverage is asymmetric until both hosts hold both drafts. Pulling qwen38-27b-dflash-mq4.hfq to hiptrx and qwen36-27b-dflash-mq4.hfq to hipx (0.92 GB each) makes it symmetric — that is a disk decision, so this reports skip rather than silently pulling ~2 GB onto your machines.

2 · Sol refused hardware for user-path CLI diffs

The rule "filesystem access beyond model/cache/temp paths" caught #689 for adding --prompt-file to hipfire bench, and cost that rung a hardware lane until hw-run overrode it. hipfire is a CLI inference engine: users name models, prompts, drafts and sidecars at invocation, and the gate's own harness passes exactly those flags.

sol.md now separates whose path it is. An explicit argument is ordinary product work; credentials, dotfiles, SSH or cloud config, /proc//sys beyond device enumeration, traversal assembled from something other than an argument, or a read whose result leaves the process still warrant refusal.

Tests

Eight new cases: flag translation (battery-dflash--mode battery --dflash on --draft …), plain battery never receiving a draft, per-lane draft selection, skip-not-fail with the harness never invoked, chain-dflash keeping its own prompts, the skip-vs-genuine-failure aggregation, and a manifest assertion that the buckets carry the routes. 113/113 hw-gate tests pass.

Policy-floor by construction, so it cannot self-merge.

@hipfire-sol

hipfire-sol Bot commented Sep 4, 2026

Copy link
Copy Markdown

hw-gate sol prelim

summary: Changes hardware-gate policy and orchestration: load/serve buckets gain DFlash variants, those variants translate to existing battery/chain harness modes with forced speculation and an explicit locally selected draft, absent draft candidates produce recorded skips, and skipped modes are excluded from fixture aggregation. It also narrows Sol's filesystem-refusal policy for explicit user-supplied CLI paths.

run_hardware: true
run_hardware_reasons: The diff is safe to execute: it invokes the existing checked-in serve harness, reads only declared local model/draft fixtures and gate prompt files, and adds no network, credential, dependency, toolchain, unsafe, or opaque behavior.; The harness changes are understandable and bounded, but real execution is needed to determine whether cross-version draft pairing loads and genuinely speculates rather than failing or silently losing coverage.

routes:

mode tag source why
battery qwen3.6:27b sol Exercise the changed load-oriented harness path on the canonical dense target; hardware evidence must show whether the available draft pairing is compatible and coherent.
chain qwen3.8:27b-mq4-xt sol Exercise multi-turn state behavior on the xt target whose explicit draft selection motivated the change.

unavailable_routes:

(none)

claim_assessment: The author claims the new routes force DFlash, choose a lane-local draft, and preserve a neutral skip state. Unit-test counts do not prove that. Evidence must show the selected draft is model-compatible, the daemon actually enters speculation, decoded battery/chain turns remain coherent, and a lane with no draft is reported as uncovered without allowing required DFlash coverage to disappear from the overall gate verdict.

questions_for_author:

  • What establishes that qwen36 and qwen38 DFlash drafts are valid interchangeable partners for both target fixtures?
  • Why does the implementation skip when all explicitly declared draft candidates are absent despite the code comment and manifest invariant saying a missing declared artifact remains a hard failure?

@hipfire-sol

hipfire-sol Bot commented Sep 5, 2026

Copy link
Copy Markdown

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

lane hiptrx (gfx1201)

hw-gate evidence

field value
base d1da3eae2835e3b87134f2747f3d01e9978e4fb9
head 744aeb3b3eaedc495a6d8e62b8b769c6630dee88
buckets
host gfx gfx1201
host rocm 7.15.26333-0000000
device 1
runner hiptrx
daemon_md5 17ba7dfab49aa1c1110d3f412f072648
hipfire_md5 cb62380a15b0e3481fad7fdfb1ae04ee
build_seconds 42.72876310348511
verdict pass
logs_dir hw-gate-logs

fixtures

qwen3.6:27b

source: sol sha256_ok: ✅ size_ok: ✅ status: pass reason:

battery — exit 0 seconds 31.3 status pass

mode idx genre finish ctx cached gen ans_words prefill_tok_s decode_tok_s attractor empty runaway recall_ok
battery 0 stop 34 0 132 62 3.1 15.2 False False False True
battery 1 stop 30 0 83 72 504.5 36.0 False False False True
battery 2 stop 31 0 19 16 521.9 36.2 False False False True
battery 3 stop 47 0 31 8 565.0 36.1 False False False True
battery 4 stop 47 0 17 7 563.7 36.1 False False False True
qwen3.6:27b battery turn 0
```python
def longest_substring_without_repeating(s: str) -> str:
    char_index = {}
    start = 0
    max_len = 0
    max_start = 0
    
    for end, char in enumerate(s):
        if char in char_index and char_index[char] >= start:
            start = char_index[char] + 1
        char_index[char] = end
        if end - start + 1 > max_len:
            max_len = end - start + 1
            max_start = start
            
    return s[max_start:max_start + max_len]
```
qwen3.6:27b battery turn 1
During the day, sunlight scatters off air molecules in all directions, with shorter blue wavelengths dispersing more effectively to make the sky appear blue. As the sun sets, its light travels through a thicker layer of the atmosphere, causing most of the blue light to scatter away before reaching your eyes. This leaves the longer red and orange wavelengths to dominate the visual field, resulting in the characteristic red hues of sunset.
qwen3.6:27b battery turn 2
The capital of France is Paris, and the river that runs through it is the Seine.
qwen3.6:27b battery turn 3
{
  "name": "Alice",
  "age": 34,
  "city": "Lisbon"
}
qwen3.6:27b battery turn 4
17 + 26 = 43

Answer: 43

qwen3.8:27b-mq4-xt

source: sol sha256_ok: ✅ size_ok: ✅ status: pass reason:

chain — exit 0 seconds 35.3 status pass

mode idx genre finish ctx cached gen ans_words prefill_tok_s decode_tok_s attractor empty runaway recall_ok
chain 0 stop 44 0 120 51 11.3 13.6 False False False True
chain 1 stop 224 0 209 115 102.4 65.5 False False False True
chain 2 stop 463 0 82 67 191.1 36.3 False False False True
chain 3 stop 583 0 121 95 722.3 35.4 False False False True
chain 4 stop 740 0 72 55 802.5 31.5 False False False True
qwen3.8:27b-mq4-xt chain turn 0
```python
def merge_sorted(a, b):
    """Merge two sorted lists into a single sorted list."""
    result = []
    i, j = 0, 0
    while i < len(a) and j < len(b):
        if a[i] <= b[j]:
            result.append(a[i])
            i += 1
        else:
            result.append(b[j])
            j += 1
    # Append remaining elements
    result.extend(a[i:])
    result.extend(b[j:])
    return result
```
qwen3.8:27b-mq4-xt chain turn 1
To find the total distance traveled, we calculate the distance for each segment of the trip and then add them together. The formula for distance is:

$$ \text{Distance} = \text{Speed} \times \text{Time} $$

**Step 1: Calculate the distance for the first segment**
*   Speed = 60 mph
*   Time = 2.5 hours
*   Distance = $60 \times 2.5 = 150$ miles

**Step 2: Calculate the distance for the second segment**
*   Speed = 40 mph
*   Time = 1.5 hours
*   Distance = $40 \times 1.5 = 60$ miles

**Step 3: Add the distances together**
*   Total Distance = $150 + 60 = 210$ miles

**Final Answer:**
The train traveled a total of **210** miles.
qwen3.8:27b-mq4-xt chain turn 2
The seasons are caused by the tilt of Earth's axis relative to its orbital plane, not by the planet's distance from the Sun. As Earth orbits the Sun, this axial tilt causes specific hemispheres to be angled toward or away from the Sun, changing the intensity and duration of sunlight they receive. This variation in solar exposure drives the cyclical patterns of spring, summer, autumn, and winter.
qwen3.8:27b-mq4-xt chain turn 3
Elias wiped the salt spray from his goggles and stared at the sleek, silver pod resting on the jagged rocks, far from any known shipping lane. He approached cautiously, his boots crunching on the wet stone, until he noticed the faint, rhythmic pulsing of light emanating from the object's seam. When he pried it open with his crowbar, he didn't find cargo or a message, but a single, perfect glass marble containing a swirling, miniature galaxy. He held it up to the dawn, realizing his lonely watch was not over, but had just truly begun.
qwen3.8:27b-mq4-xt chain turn 4
1. Use descriptive variable and function names that clearly convey their purpose.
2. Keep functions small and focused on a single responsibility.
3. Write comprehensive unit tests to verify behavior and catch regressions.
4. Maintain consistent code style and formatting throughout the project.
5. Add concise comments only to explain complex logic, not obvious syntax.

kernel

not run

lane hipx (gfx1100)

hw-gate evidence

field value
base d1da3eae2835e3b87134f2747f3d01e9978e4fb9
head 744aeb3b3eaedc495a6d8e62b8b769c6630dee88
buckets
host gfx gfx1100
host rocm 7.15.26333-0000000
device 0
runner hipx
daemon_md5 17ba7dfab49aa1c1110d3f412f072648
hipfire_md5 cb62380a15b0e3481fad7fdfb1ae04ee
build_seconds 49.09681797027588
verdict pass
logs_dir hw-gate-logs

fixtures

qwen3.6:27b

source: sol sha256_ok: ✅ size_ok: ✅ status: pass reason:

battery — exit 0 seconds 28.5 status pass

mode idx genre finish ctx cached gen ans_words prefill_tok_s decode_tok_s attractor empty runaway recall_ok
battery 0 stop 34 0 146 66 3.3 18.8 False False False True
battery 1 stop 30 0 79 68 437.1 50.3 False False False True
battery 2 stop 31 0 19 16 450.5 50.4 False False False True
battery 3 stop 47 0 31 8 464.9 50.3 False False False True
battery 4 stop 47 0 6 2 463.7 50.2 False False False True
qwen3.6:27b battery turn 0
```python
def longest_substring_without_repeating(s: str) -> str:
    if not s:
        return ""
    
    char_index = {}
    start = 0
    max_length = 0
    max_start = 0
    
    for end, char in enumerate(s):
        if char in char_index and char_index[char] >= start:
            start = char_index[char] + 1
        char_index[char] = end
        current_length = end - start + 1
        if current_length > max_length:
            max_length = current_length
            max_start = start
            
    return s[max_start:max_start + max_length]
```
qwen3.6:27b battery turn 1
During the day, sunlight scatters through the atmosphere, and shorter blue wavelengths are dispersed more effectively than longer red wavelengths, making the sky appear blue. At sunset, sunlight travels through a much thicker layer of the atmosphere to reach your eyes, causing most of the blue light to scatter away completely. This leaves the longer red and orange wavelengths to dominate the sky's appearance as the sun sets.
qwen3.6:27b battery turn 2
The capital of France is Paris, and the river that runs through it is the Seine.
qwen3.6:27b battery turn 3
{
  "name": "Alice",
  "age": 34,
  "city": "Lisbon"
}
qwen3.6:27b battery turn 4
Answer: 43

qwen3.8:27b-mq4-xt

source: sol sha256_ok: ✅ size_ok: ✅ status: pass reason:

chain — exit 0 seconds 42.3 status pass

mode idx genre finish ctx cached gen ans_words prefill_tok_s decode_tok_s attractor empty runaway recall_ok
chain 0 stop 44 0 112 46 16.0 28.1 False False False True
chain 1 stop 216 44 182 90 60.5 48.9 False False False True
chain 2 stop 428 44 75 61 186.9 48.8 False False False True
chain 3 stop 541 44 110 87 278.4 49.2 False False False True
chain 4 stop 687 44 73 55 871.4 49.0 False False False True
qwen3.8:27b-mq4-xt chain turn 0
```python
def merge_sorted(a, b):
    """Merge two already-sorted lists into one sorted list."""
    result = []
    i = j = 0
    while i < len(a) and j < len(b):
        if a[i] <= b[j]:
            result.append(a[i])
            i += 1
        else:
            result.append(b[j])
            j += 1
    result.extend(a[i:])
    result.extend(b[j:])
    return result
```
qwen3.8:27b-mq4-xt chain turn 1
To find the total distance, calculate the distance for each segment separately using the formula:

$$\text{Distance} = \text{Speed} \times \text{Time}$$

**Step 1: Distance for the first segment**
*   Speed = 60 mph
*   Time = 2.5 hours
*   Distance = $60 \times 2.5 = 150$ miles

**Step 2: Distance for the second segment**
*   Speed = 40 mph
*   Time = 1.5 hours
*   Distance = $40 \times 1.5 = 60$ miles

**Step 3: Total distance**
*   Total Distance = $150 + 60 = 210$ miles

**Final Answer:** 210 miles
qwen3.8:27b-mq4-xt chain turn 2
The seasons are caused by the Earth's axial tilt of approximately 23.5 degrees relative to its orbital plane around the Sun. As Earth orbits the Sun, this tilt causes different hemispheres to receive varying amounts of direct sunlight and daylight hours throughout the year. When a hemisphere is tilted toward the Sun, it experiences summer, while the opposite hemisphere experiences winter.
qwen3.8:27b-mq4-xt chain turn 3
Elias wiped the salt from his eyes, expecting nothing but kelp and debris when he stepped out to check the lower rocks at dawn. Instead, he found a sealed brass canister, tarnished by the sea, wedged tightly between two jagged stones. His fingers trembled as he cracked the wax seal, revealing a map drawn in ink that smelled faintly of lavender, not brine. The coordinates on the parchment pointed directly to the small, unmarked island just beyond his horizon, where a light had never before been lit.
qwen3.8:27b-mq4-xt chain turn 4
1. Use descriptive variable and function names to make intent clear without comments.
2. Keep functions small and focused on a single responsibility.
3. Write unit tests for all new logic to prevent regressions.
4. Follow established coding standards and style guides consistently.
5. Add concise comments only to explain complex logic or non-obvious decisions.

kernel

not run

@hipfire-sol

hipfire-sol Bot commented Sep 5, 2026

Copy link
Copy Markdown

hw-gate sol verdict

{
  "claim_verdict": "not-exercised",
  "confidence": 0.98,
  "coverage": {
    "gaps": [
      "The evidence contains only plain battery and chain modes; neither battery-dflash nor chain-dflash ran.",
      "No explicit draft was selected, loaded, or shown to enter speculation.",
      "Cross-version qwen3.6/qwen3.8 draft compatibility was not exercised.",
      "The skip aggregation path was not exercised on hardware, and run.py:542 still permits all declared draft candidates to be absent without failing the fixture.",
      "The changed Sol filesystem policy is a policy-file change requiring human review."
    ],
    "surfaces_evidenced": [
      "load",
      "serve"
    ],
    "surfaces_touched": [
      "policy",
      "load",
      "serve",
      "speculative-decode",
      "harness"
    ]
  },
  "decision": "needs-human",
  "eyeball": [
    "All five qwen3.6 battery responses on gfx1201 and gfx1100 are coherent, answer their prompts, contain required substrings, and show no attractor, empty output, runaway, or special-token leakage.",
    "All five qwen3.8 chain responses on gfx1201 and gfx1100 are coherent; the merge function, 210-mile calculation, seasons explanation, lighthouse story, and coding-practices list answer their prompts without degeneration.",
    "A human should inspect scripts/hw-gate/run.py:542-548 because absence of every explicitly declared draft produces skip and is excluded from the verdict, allowing a selected DFlash route to contribute no evidence."
  ],
  "phase": "verdict",
  "rationale": "The ordinary qwen3.6 battery and qwen3.8 chain routes passed coherently on both gfx1201 and gfx1100, but hw-gate.json contains no *-dflash mode at all. It therefore proves only the existing AR load/serve paths, not the PR's central forced-DFlash routing, lane-local draft selection, cross-version pairing, or skip semantics. Because scripts/hw-gate/fixtures.json, run.py, and sol.md change gate policy and the relevant behavior was not exercised, this requires human review rather than a greenlight.",
  "regressions": []
}

Floor: hard=['policy_paths: scripts/hw-gate/fixtures.json,scripts/hw-gate/run.py,scripts/hw-gate/sol.md,scripts/hw-gate/tests/test_run.py'] soft=["coverage_gaps: ['The evidence contains only plain battery and chain modes; neither battery-dflash nor chain-dflash ran.', 'No explicit draft was selected, loaded, or shown to enter speculation.', 'Cross-version qwen3.6/qwen3.8 draft compatibility was not exercised.', 'The skip aggregation path was not exercised on hardware, and run.py:542 still permits all declared draft candidates to be absent without failing the fixture.', 'The changed Sol filesystem policy is a policy-file change requiring human review.']", '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 hardware run succeeded only as a build: buckets and fixtures are empty, so it provides no evidence for the new DFlash routes or skip semantics. The diff is a policy-floor change and therefore requires human review. In scripts/hw-gate/run.py:621-623, removing every skipped result makes all([]) true, allowing an all-skipped fixture to pass; scripts/hw-gate/tests/test_run.py:971 tests a copied expression rather than _run_fixture_harness, so it does not close that gap.

…iffs

Two policy gaps this ladder exposed.

1. The gate never ran DFlash. #686 (draft sidecars), #691 (draft ctor
   rollback), #692 (primer replay) and #702 (dedicated verify kernels) all went
   through with every lane green while speculation never once executed. #692's
   DFlash-arm defect -- primer replay systematically missing the most recent
   assistant body -- was found only because a seat thought to drive twenty turns
   by hand. That is not a gate.

   The load bucket now runs `battery-dflash` and the serve bucket
   `chain-dflash`: the same prompts with `--dflash on` and an explicit
   `--draft`. `on` rather than `auto` because `auto` silently falls back to AR
   when the draft is missing, and a route that can pass without speculating
   proves nothing. The draft is named explicitly because the canonical xt trunk
   is a symlink out of the models dir, so the daemon's filename auto-match finds
   nothing and would run AR.

   `dflash_draft` is a candidate LIST because the lanes hold different drafts:
   hiptrx has qwen36-27b-dflash-mq4.hfq and no qwen38, hipx has
   qwen38-27b-dflash-mq4.hfq and no qwen36. A lane speculates with the first
   candidate it holds; a lane holding none records `skip`.

   `skip` is neither pass nor fail. The aggregation was
   `all(status == "pass")`, which would have counted a skip as a fixture
   failure -- a false negative on evidence the host never had -- while treating
   it as a pass would claim coverage that did not happen. Skips are recorded and
   reported, and a genuine failure alongside a skip still fails.

   Coverage is asymmetric until both hosts hold both drafts. Pulling
   qwen38-27b-dflash-mq4.hfq to hiptrx and qwen36-27b-dflash-mq4.hfq to hipx
   (0.92 GB each) makes it symmetric; that is a disk decision, so the evidence
   says `skip` rather than silently pulling.

2. Sol refused hardware for any diff touching a filesystem path, which caught
   #689 for adding `--prompt-file` to `hipfire bench` and cost that rung a lane
   until `hw-run` overrode it. hipfire is a CLI inference engine: users name
   models, prompts, drafts and sidecars at invocation, and the gate's own
   harness passes exactly those flags. sol.md now separates whose path it is --
   an explicit argument is ordinary product work; credentials, dotfiles, SSH or
   cloud config, /proc or /sys beyond device enumeration, assembled traversal,
   or a read whose result leaves the process still warrant refusal.

Tests: eight new cases in scripts/hw-gate/tests/test_run.py covering flag
translation (battery-dflash -> `--mode battery --dflash on --draft ...`), plain
battery never receiving a draft, per-lane draft selection, skip-not-fail with
the harness never invoked, chain-dflash keeping its own prompts, the
skip-vs-genuine-failure aggregation, and a manifest assertion that the buckets
actually carry the routes. 113/113 hw-gate tests pass.
@Kaden-Schutt
Kaden-Schutt force-pushed the fix/hw-gate-dflash-route-and-sol-policy branch from 4142d17 to 744aeb3 Compare September 5, 2026 00:57
@Kaden-Schutt
Kaden-Schutt merged commit daa1594 into master Sep 5, 2026

@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 ordinary qwen3.6 battery and qwen3.8 chain routes passed coherently on both gfx1201 and gfx1100, but hw-gate.json contains no *-dflash mode at all. It therefore proves only the existing AR load/serve paths, not the PR's central forced-DFlash routing, lane-local draft selection, cross-version pairing, or skip semantics. Because scripts/hw-gate/fixtures.json, run.py, and sol.md change gate policy and the relevant behavior was not exercised, this requires human review rather than a greenlight.

ghazni101 pushed a commit to ghazni101/hipfire that referenced this pull request Sep 5, 2026
…hosts

warpfront#718 concluded DFlash coverage was asymmetric -- hiptrx holding a qwen36 draft
and hipx a qwen38 one -- and left a lane recording `skip`. That was wrong: it
only looked in ~/.hipfire/models. Both hosts carry the whole 3.8 V2 draft
ladder under ~/qcal/ladder-v2/drafts:

    qwen3.8-27b-dflash.mq2v2.hfq   760353792
    qwen3.8-27b-dflash.mq3v2.hfq   984978432
    qwen3.8-27b-dflash.mq4v2.hfq  1209603072
    qwen3.8-27b-dflash.mq5v2.hfq  1434227712
    qwen3.8-27b-dflash.mq6v2.hfq  1658852352

byte-identical across hosts, and the mq4v2 draft is the one the canonical
fixture identity was measured with: md5 013395583cd0 against target
e45d15bfe0c9 (~/qcal/ladder-v2/artifacts/qwen3.8-27b.mq4v2.xt.hfq), giving
157 tokens / 11 cycles / tau 13.1818 / accept 0.8788. Verified on both hosts
just now. So there is nothing to pull and no asymmetry -- the manifest simply
could not name a draft outside the models dir.

- `dflash_draft` candidates are now path-aware: a bare filename still resolves
  under the models dir, anything path-shaped (or `~`-prefixed) is taken as
  given.
- The xt fixture pins ~/qcal/ladder-v2/drafts/qwen3.8-27b-dflash.mq4v2.hfq with
  its sha256, so both lanes speculate against the same artifact the identity was
  measured with, and `chain-dflash`/`battery-dflash` never skip.
- The draft is verified like the target: a sha256 mismatch is a hard fail, not a
  skip. A wrong draft does not fail loudly, it silently changes tau, and tau is
  exactly the number that gets quoted.
- qwen3.6:27b no longer declares a draft. 3.8 mq4v2 supersedes it, and the xt
  fixture carries the DFlash route on both lanes.

Tests: draft outside the models dir resolves and is passed to the harness; a
mismatched sha256 fails without ever speculating; the manifest pins the
canonical draft and hash. 132/132 hw-gate tests pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant