#439

Surface backend readiness blockers in text-mode `zero check`

OpenU0001F3A2opened 24d ago

zero check --target win32-x64.exe prints ok for programs that zero build --target win32-x64.exe then rejects with BLD004. On a Windows host (v0.3.4) the same happens for the host target with std.args.get.

Repro on main @ 7e1a64d (linux host), with a probe that calls std.fmt.u32:

  • zero check --target win32-x64.exe . prints ok
  • with --json it gives "ok": true and targetReadiness: {ok: false, buildable: false} with BLD004 IR_VALUE_FMT_U32
  • zero build --target win32-x64.exe . fails with that BLD004, exit 1

std.parse.parseU16 and rescue behave the same.

I know the split is intended (program_graph_check_gate.c:8-15, conformance/run.mjs:1255-1260). The trouble is that text mode never shows readiness (main.c:15430-15432), and the docs are mixed. docs/articles/cross-compilation.md:42 says to use check --json, but its example at line 47 drops --json, and skill-data/builds.md:96 shows the plain form too. skill-data/diagnostics.md doesn't mention targetReadiness. The comment at main.c:15405-15407 also says check fails with the same BLD004 that build would report.

Suggestions:

  • Update the docs to tell agents to read targetReadiness.buildable, and use the JSON form in readiness examples.
  • Print the blocker as a stderr note in text mode when readiness is false. stdout stays ok and exit stays 0, so the pinned contract holds. The patch below does this for the graph-store path (+21 -1), tested with the three probes above. JSON is unchanged apart from timing and cache fields. The .0 source path isn't covered.
patch against 7e1a64d
--- a/native/zero-c/src/main.c
+++ b/native/zero-c/src/main.c
@@ -12113,6 +12113,22 @@
   return out->ready;
 }
 
+/*
+ * Plain-mode readiness note: target-specific backend buildability blockers
+ * stay targetReadiness facts (check still prints ok and exits 0), but text
+ * mode has no targetReadiness field, so surface the blocker zero build would
+ * report as a stderr note instead of a bare ok.
+ */
+static void repository_graph_check_print_readiness_note(const Command *command, SourceInput *input, const ZProgramGraphStore *store, const ZTargetInfo *target, RepositoryGraphCheckReadiness *readiness) {
+  if (!readiness->ran) repository_graph_check_readiness_compute(command, input, store, target, readiness);
+  if (readiness->ready) return;
+  const ZDiag *diag = &readiness->diag;
+  fprintf(stderr, "note: language check passed, but target %s is not buildable for --emit %s (targetReadiness.ok=false); zero build would fail with:\n",
+          target && target->name ? target->name : z_host_target(),
+          emit_kind_name(command ? command->emit : EMIT_EXE));
+  print_diag(diag->path ? diag->path : (input ? input->source_file : NULL), diag);
+}
+
 static bool append_repository_graph_target_readiness_json(ZBuf *buf, SourceInput *input, const ZProgramGraphStore *store, const ZProgramGraphResolutionFacts *resolution, const ZTargetInfo *target, const Command *command, RepositoryGraphCheckReadiness *readiness, long long *lower_ms_out, bool *graph_mir_used_out) {
   (void)resolution;
   if (!readiness->ran) repository_graph_check_readiness_compute(command, input, store, target, readiness);
@@ -15429,7 +15445,11 @@
 
   if (ok) {
     if (command->json) print_repository_graph_check_json_success(command, target, &input, &store, &resolution, &readiness, load_ms, resolve_ms, input.check_ms, cache_ms);
-    else printf("ok\n");
+    else {
+      printf("ok\n");
+      fflush(stdout);
+      repository_graph_check_print_readiness_note(command, &input, &store, target, &readiness);
+    }
   } else {
     if (command->json) print_command_diag_json(command, diag.path ? diag.path : command->input, &diag);
     else print_diag(diag.path ? diag.path : command->input, &diag);

Activity

0

No activity yet.