[pitboss/grind] deferred session-0012 (20260516T052512Z-20f8)

This commit is contained in:
pitboss 2026-05-16 07:24:29 -05:00
parent d126f3c15c
commit b8207a1d1c
4 changed files with 243 additions and 6 deletions

View file

@ -85,13 +85,21 @@ impl LangEmitter for JavaEmitter {
/// Emits a `Step.java` class whose `main` reads `NYX_PREV_OUTPUT` and
/// forwards it on stdout. The command shell-wraps `javac` + `java` so
/// the step actually runs after the build step completes (the
/// `ChainStepHarness.command` slot models a single process). The Java
/// probe shim is class-level and requires `System` / `java.io.*` imports
/// the chain step already pulls in implicitly; wiring the full shim is
/// tracked alongside the Phase 14 emitter follow-up about probe shim
/// splicing.
/// `ChainStepHarness.command` slot models a single process).
///
/// The Java probe shim (`__nyx_probe`, `__nyx_install_crash_guard`,
/// helpers) is spliced as class-member declarations inside `class Step
/// { … }` between the class-open brace and `public static void main`,
/// so a downstream sink rewrite within the step body has the shim
/// helpers already in scope. The shim uses only `java.lang.*` plus
/// fully-qualified `java.util.TreeMap` / `java.io.FileWriter` /
/// `java.nio.charset.StandardCharsets`, so no extra `import` lines
/// are needed beyond what stock Java implicitly imports.
fn chain_step(prev_output: Option<&[u8]>) -> ChainStepHarness {
let source = "public class Step {\n public static void main(String[] args) {\n String prev = System.getenv(\"NYX_PREV_OUTPUT\");\n if (prev == null) prev = \"\";\n System.out.print(prev);\n }\n}\n".to_owned();
let shim = probe_shim();
let source = format!(
"public class Step {{\n{shim}\n public static void main(String[] args) {{\n String prev = System.getenv(\"NYX_PREV_OUTPUT\");\n if (prev == null) prev = \"\";\n System.out.print(prev);\n }}\n}}\n"
);
ChainStepHarness {
source,
filename: "Step.java".to_owned(),
@ -1031,6 +1039,35 @@ mod tests {
assert_eq!(harness.entry_subpath, Some("Entry.java".to_owned()));
}
#[test]
fn chain_step_splices_probe_shim_for_composite_reverify() {
let step = chain_step(Some(b"<prev>"));
assert!(
step.source.contains("__nyx_probe"),
"Java chain step must splice the probe shim"
);
assert!(
step.source.starts_with("public class Step {"),
"Java chain step must open with the `public class Step {{` declaration"
);
assert!(
step.source.contains("System.getenv(\"NYX_PREV_OUTPUT\")"),
"Java chain step must keep its NYX_PREV_OUTPUT forwarder"
);
let shim_pos = step.source.find("__nyx_probe").unwrap();
let driver_pos = step.source.find("System.getenv(\"NYX_PREV_OUTPUT\")").unwrap();
assert!(
shim_pos < driver_pos,
"probe shim must come before the driver so the shim's helpers are in scope when a sink rewrite splices in"
);
let main_pos = step.source.find("public static void main").unwrap();
assert!(
shim_pos < main_pos,
"probe shim members must be declared before `main` so the class compiles cleanly"
);
assert_eq!(step.filename, "Step.java");
}
#[test]
fn detect_shape_reads_file_and_returns_shape() {
// Drive the public `detect_shape(spec)` wrapper end-to-end:

View file

@ -250,6 +250,34 @@ function __nyx_install_crash_guard(sinkCallee) {
} catch (e) { /* runtime refused signal handler */ }
}
}
// Phase 10 (Track D.3) stub helpers. When the verifier spawned a SqlStub it
// publishes the queries-log path through NYX_SQL_LOG; a sink call site that
// wants the host-side stub to see its query appends one record-per-call. The
// helper is a no-op when NYX_SQL_LOG is unset so the same fixture source still
// runs under harness modes that didn't spawn a stub. Mirrors the Python
// shim's __nyx_stub_sql_record so the host-side SqlStub log-line format
// (key/value detail lines prefixed with hash-space, followed by the query
// line) is identical across language emitters.
function __nyx_stub_sql_record(query, detail) {
const _p = process.env.NYX_SQL_LOG;
if (!_p) return;
const _fs = require('fs');
try {
let _buf = '';
if (detail && typeof detail === 'object') {
for (const _k of Object.keys(detail)) {
_buf += '# ' + String(_k) + ': ' + String(detail[_k]) + '\n';
}
}
const _q = String(query);
_buf += _q;
if (!_q.endsWith('\n')) _buf += '\n';
_fs.appendFileSync(_p, _buf);
} catch (e) {
// best-effort: stub recorder write failure is non-fatal.
}
}
"#
}
@ -1029,4 +1057,21 @@ mod tests {
assert_eq!(h_js.entry_subpath, h_ts.entry_subpath);
assert_eq!(h_js.entry_subpath.as_deref(), Some("entry.js"));
}
#[test]
fn probe_shim_publishes_stub_sql_recorder() {
let shim = probe_shim();
assert!(
shim.contains("function __nyx_stub_sql_record"),
"Node probe shim must define __nyx_stub_sql_record"
);
assert!(
shim.contains("NYX_SQL_LOG"),
"stub recorder must read NYX_SQL_LOG"
);
assert!(
shim.contains("appendFileSync"),
"stub recorder must append to the log file"
);
}
}