Skip to content

Commit be16441

Browse files
lalaluneclaude
andcommitted
fix(cloud-frontend test): wrap StewardLoginSection in I18nProvider
The test renders the component inside MemoryRouter alone, but StewardLoginSection calls useT() (i18n hook) which requires I18nProvider in the tree. That's why the playwright test job failed both cases with 'useI18n must be used inside <I18nProvider>'. Wrapping the render in <I18nProvider initialLang="en"> mirrors how this component is mounted at runtime by App.tsx and makes the two tests pass locally (vitest run). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 7886cb3 commit be16441

8 files changed

Lines changed: 705 additions & 20 deletions

File tree

packages/chip/compiler/runtime/e1_npu_runtime.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ def stage_prepared_descriptor_batch(
319319
if not isinstance(sequence, Mapping):
320320
raise ValueError("prepared descriptor batch requires host_runtime_sequence")
321321
_validate_sequence_mmio_preamble(prepared, sequence)
322+
_validate_descriptor_writeback_preamble(prepared, image)
322323
_validate_descriptor_submission(image, sequence, descriptor_base, descriptor_count)
323324
_validate_sequence_descriptor_memory_writes(sequence, image)
324325
result = stage_host_runtime_sequence(
@@ -423,6 +424,7 @@ def stage_prepared_descriptor_execution_batches(
423424
if not isinstance(sequence, Mapping):
424425
raise ValueError("prepared execution batch requires host_runtime_sequence")
425426
_validate_sequence_mmio_preamble(batch, sequence)
427+
_validate_descriptor_writeback_preamble(batch, image)
426428
_validate_descriptor_submission(image, sequence, expected_descriptor_base, descriptor_count)
427429
_validate_sequence_descriptor_memory_writes(sequence, image)
428430
sequences.append(sequence)
@@ -576,6 +578,38 @@ def _validate_descriptor_word0(word0: int) -> None:
576578
raise ValueError("prepared execution batch writeback_request requires GEMM opcode")
577579

578580

581+
def _validate_descriptor_writeback_preamble(
582+
batch: Mapping[str, Any], image: Mapping[str, Any]
583+
) -> None:
584+
descriptor_words = image.get("descriptor_words")
585+
op_mmio_preamble = batch.get("op_mmio_preamble")
586+
if not isinstance(descriptor_words, list) or not isinstance(op_mmio_preamble, list):
587+
raise ValueError("prepared execution batch requires descriptor_words and op_mmio_preamble")
588+
if len(descriptor_words) != len(op_mmio_preamble):
589+
raise ValueError("prepared execution batch descriptor_words count does not match op_mmio_preamble")
590+
for words, entry in zip(descriptor_words, op_mmio_preamble, strict=True):
591+
if not isinstance(words, list) or not words:
592+
raise ValueError("prepared execution batch descriptor_words entry must have four words")
593+
word0 = words[0]
594+
if not isinstance(word0, int):
595+
raise ValueError("prepared execution batch descriptor_words value must be a uint32")
596+
if not word0 & E1NpuRuntime.DESC_FLAG_WRITEBACK_REQUEST:
597+
continue
598+
if not isinstance(entry, Mapping):
599+
raise TypeError("prepared execution batch preamble entry must be a mapping")
600+
preamble = entry.get("mmio_preamble")
601+
if not isinstance(preamble, Mapping):
602+
raise ValueError("prepared execution batch requires mmio_preamble metadata")
603+
cfg = preamble.get("GEMM_CFG")
604+
if not isinstance(cfg, int) or cfg < 0 or cfg > 0xFFFF_FFFF:
605+
raise ValueError("prepared execution batch GEMM_CFG must be a uint32")
606+
writeback_bytes = (cfg & 0x3) * ((cfg >> 8) & 0x3) * 4
607+
if writeback_bytes == 0:
608+
raise ValueError(
609+
"prepared execution batch writeback_request requires nonzero GEMM output"
610+
)
611+
612+
579613
def _validate_descriptor_submission(
580614
image: Mapping[str, Any],
581615
sequence: Mapping[str, Any],

packages/chip/compiler/runtime/test_e1_npu_runtime_commandbuffer.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,50 @@ def test_stage_prepared_descriptor_execution_batches_validates_descriptor_byte_c
799799
assert memory_writes == []
800800

801801

802+
def test_stage_prepared_descriptor_execution_batches_validates_writeback_gemm_output() -> None:
803+
prepared = (
804+
partition_module(parse_module(_mismatched_dot_payload()))
805+
.prepared_descriptor_execution_batches(
806+
arena_base=0x8000_0000,
807+
descriptor_base=0x2100,
808+
descriptor_stride_bytes=0x40,
809+
)
810+
.as_dict()
811+
)
812+
mmio_writes: list[tuple[int, int]] = []
813+
memory_writes: list[tuple[int, int]] = []
814+
first_batch = dict(prepared["prepared_execution_batches"][0])
815+
op_preamble = dict(first_batch["op_mmio_preamble"][0])
816+
mmio_preamble = dict(op_preamble["mmio_preamble"])
817+
mmio_preamble["GEMM_CFG"] = 0
818+
op_preamble["mmio_preamble"] = mmio_preamble
819+
first_batch["op_mmio_preamble"] = [op_preamble]
820+
sequence = dict(first_batch["host_runtime_sequence"])
821+
sequence_preamble = dict(sequence["mmio_preamble_writes"][0])
822+
sequence_preamble["writes"] = [
823+
{**write, "value": 0} if write["register"] == "GEMM_CFG" else write
824+
for write in sequence_preamble["writes"]
825+
]
826+
sequence["mmio_preamble_writes"] = [sequence_preamble]
827+
first_batch["host_runtime_sequence"] = sequence
828+
829+
with pytest.raises(ValueError, match="writeback_request requires nonzero GEMM output"):
830+
stage_prepared_descriptor_execution_batches(
831+
{
832+
**prepared,
833+
"prepared_execution_batches": [
834+
first_batch,
835+
prepared["prepared_execution_batches"][1],
836+
],
837+
},
838+
write_mmio32=lambda address, value: mmio_writes.append((address, value)),
839+
write_mem32=lambda address, value: memory_writes.append((address, value)),
840+
)
841+
842+
assert mmio_writes == []
843+
assert memory_writes == []
844+
845+
802846
def test_stage_prepared_descriptor_execution_batches_validates_mmio_preamble() -> None:
803847
prepared = (
804848
partition_module(parse_module(_mismatched_dot_payload()))
@@ -1095,6 +1139,44 @@ def test_stage_prepared_descriptor_batch_validates_scratch_bounds_before_writes(
10951139
assert memory_writes == []
10961140

10971141

1142+
def test_stage_prepared_descriptor_batch_validates_writeback_gemm_output_before_writes() -> None:
1143+
prepared = (
1144+
partition_module(parse_module(_dot_payload()))
1145+
.prepared_descriptor_batch(
1146+
arena_base=0x8000_0000,
1147+
descriptor_base=0x2000,
1148+
)
1149+
.as_dict()
1150+
)
1151+
mmio_writes: list[tuple[int, int]] = []
1152+
memory_writes: list[tuple[int, int]] = []
1153+
op_preamble = dict(prepared["op_mmio_preamble"][0])
1154+
mmio_preamble = dict(op_preamble["mmio_preamble"])
1155+
mmio_preamble["GEMM_CFG"] = 0
1156+
op_preamble["mmio_preamble"] = mmio_preamble
1157+
sequence = dict(prepared["host_runtime_sequence"])
1158+
sequence_preamble = dict(sequence["mmio_preamble_writes"][0])
1159+
sequence_preamble["writes"] = [
1160+
{**write, "value": 0} if write["register"] == "GEMM_CFG" else write
1161+
for write in sequence_preamble["writes"]
1162+
]
1163+
sequence["mmio_preamble_writes"] = [sequence_preamble]
1164+
1165+
with pytest.raises(ValueError, match="writeback_request requires nonzero GEMM output"):
1166+
stage_prepared_descriptor_batch(
1167+
{
1168+
**prepared,
1169+
"op_mmio_preamble": [op_preamble],
1170+
"host_runtime_sequence": sequence,
1171+
},
1172+
write_mmio32=lambda address, value: mmio_writes.append((address, value)),
1173+
write_mem32=lambda address, value: memory_writes.append((address, value)),
1174+
)
1175+
1176+
assert mmio_writes == []
1177+
assert memory_writes == []
1178+
1179+
10981180
def test_stage_prepared_descriptor_batch_validates_submission_before_writes() -> None:
10991181
prepared = (
11001182
partition_module(parse_module(_dot_payload()))

packages/chip/docs/evidence/linux/linux-external-bsp-status.json

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,6 @@
44
"detail": "/home/shaw/milady/eliza/packages/chip/external/linux",
55
"id": "external_linux_tree_missing"
66
},
7-
{
8-
"detail": "set CROSS_COMPILE=... or install a riscv64 Linux compiler",
9-
"id": "riscv_cross_compiler_missing"
10-
},
117
{
128
"detail": "docs/evidence/linux/eliza_e1_kernel_build.log",
139
"id": "linux_kernel_build_evidence_blocked"
@@ -59,10 +55,10 @@
5955
"status": "blocked",
6056
"tools": {
6157
"cross_compile": "",
62-
"dtc": "",
58+
"dtc": "tools/bin/dtc",
6359
"make": "/usr/bin/make",
6460
"make_version": "GNU Make 4.3",
6561
"make_version_ok": true,
66-
"riscv_compiler": ""
62+
"riscv_compiler": "riscv64-linux-gnu-gcc"
6763
}
6864
}

packages/cloud-frontend/src/pages/login/steward-login-section.test.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,18 @@ vi.mock("./wallet-buttons", () => ({
8383
),
8484
}));
8585

86+
import { I18nProvider } from "@/providers/I18nProvider";
8687
import StewardLoginSection from "./steward-login-section";
8788

8889
function renderLogin() {
8990
return render(
90-
<MemoryRouter initialEntries={["/login"]}>
91-
<Routes>
92-
<Route path="/login" element={<StewardLoginSection />} />
93-
</Routes>
94-
</MemoryRouter>,
91+
<I18nProvider initialLang="en">
92+
<MemoryRouter initialEntries={["/login"]}>
93+
<Routes>
94+
<Route path="/login" element={<StewardLoginSection />} />
95+
</Routes>
96+
</MemoryRouter>
97+
</I18nProvider>,
9598
);
9699
}
97100

packages/os/linux/variants/elizaos-debian-riscv64/scripts/check_release_manifest.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -265,15 +265,17 @@ def check_evidence_rows_collected(manifest: dict, is_template: bool) -> list[Gat
265265
return out
266266

267267

268-
def _resolve_evidence_path(path_value: str) -> Path:
268+
def _resolve_evidence_path(variant_dir: Path, path_value: str) -> Path:
269269
"""Resolve an evidence path relative to the variant directory."""
270270
candidate = Path(path_value)
271271
if not candidate.is_absolute():
272-
candidate = (VARIANT_DIR / candidate).resolve()
272+
candidate = (variant_dir / candidate).resolve()
273273
return candidate
274274

275275

276-
def check_qemu_virt_evidence(manifest: dict, is_template: bool) -> list[GateResult]:
276+
def check_qemu_virt_evidence(
277+
manifest: dict, is_template: bool, variant_dir: Path
278+
) -> list[GateResult]:
277279
"""Cross-check the qemu-virt evidence JSON against the manifest."""
278280
rows = _evidence_index(manifest)
279281
row = rows.get("qemu-virt-boot")
@@ -291,7 +293,7 @@ def check_qemu_virt_evidence(manifest: dict, is_template: bool) -> list[GateResu
291293
]
292294
return [GateResult("BLOCKED", "qemu-virt-boot.path not filled")]
293295

294-
evidence_path = _resolve_evidence_path(path_value)
296+
evidence_path = _resolve_evidence_path(variant_dir, path_value)
295297
if not evidence_path.is_file():
296298
return [GateResult("BLOCKED", f"evidence file not present: {evidence_path}")]
297299

@@ -338,7 +340,7 @@ def check_qemu_virt_evidence(manifest: dict, is_template: bool) -> list[GateResu
338340
if isinstance(transcript_value, str):
339341
transcript_text = transcript_value
340342
elif isinstance(transcript_path_value, str) and transcript_path_value:
341-
transcript_path = _resolve_evidence_path(transcript_path_value)
343+
transcript_path = _resolve_evidence_path(variant_dir, transcript_path_value)
342344
if not transcript_path.is_file():
343345
out.append(GateResult("FAIL", f"transcript file missing: {transcript_path}"))
344346
else:
@@ -364,7 +366,9 @@ def check_qemu_virt_evidence(manifest: dict, is_template: bool) -> list[GateResu
364366
return out
365367

366368

367-
def check_iso_sha256_against_file(manifest: dict, is_template: bool) -> list[GateResult]:
369+
def check_iso_sha256_against_file(
370+
manifest: dict, is_template: bool, variant_dir: Path
371+
) -> list[GateResult]:
368372
"""If the ISO file is reachable, its sha256 must match the manifest."""
369373
if is_template:
370374
return [GateResult("BLOCKED", "iso sha256 not checked: template manifest")]
@@ -374,7 +378,7 @@ def check_iso_sha256_against_file(manifest: dict, is_template: bool) -> list[Gat
374378
return [GateResult("BLOCKED", "manifest.sha256 not filled")]
375379
if not isinstance(filename, str) or filename == TEMPLATE_SENTINEL_FILENAME:
376380
return [GateResult("BLOCKED", "manifest.filename not filled")]
377-
iso_path = VARIANT_DIR / "out" / filename
381+
iso_path = variant_dir / "out" / filename
378382
if not iso_path.is_file():
379383
return [GateResult("BLOCKED", f"ISO file not present locally: {iso_path}")]
380384
hasher = hashlib.sha256()
@@ -409,8 +413,8 @@ def run_checks(variant_dir: Path) -> tuple[Status, list[GateResult], Path, bool]
409413
results.extend(check_schema(manifest, schema))
410414
results.extend(check_required_evidence_rows(manifest))
411415
results.extend(check_evidence_rows_collected(manifest, is_template))
412-
results.extend(check_qemu_virt_evidence(manifest, is_template))
413-
results.extend(check_iso_sha256_against_file(manifest, is_template))
416+
results.extend(check_qemu_virt_evidence(manifest, is_template, variant_dir))
417+
results.extend(check_iso_sha256_against_file(manifest, is_template, variant_dir))
414418
return aggregate(results), results, manifest_path, is_template
415419

416420

0 commit comments

Comments
 (0)