#!/usr/bin/env node const assert = require("assert"); const fs = require("fs"); const path = require("path"); const repo = path.resolve(__dirname, ".."); function read(relativePath) { return fs.readFileSync(path.join(repo, relativePath), "utf8"); } function expect(source, name, pattern) { assert.match(source, pattern, `missing node lifecycle evidence: ${name}`); } const nodeMain = read("crates/disasmer-node/src/main.rs"); const nodeLib = read("crates/disasmer-node/src/lib.rs"); const coordinatorCore = read("crates/disasmer-coordinator/src/lib.rs"); const coordinatorService = read("crates/disasmer-coordinator/src/service.rs"); const localServicesSmoke = read("scripts/local-services-smoke.js"); const cancellationSmoke = read("scripts/cancellation-smoke.js"); const wasmtimeSmoke = read("scripts/wasmtime-node-smoke.js"); const debugCore = read("crates/disasmer-core/src/debug.rs"); const readme = read("README.md"); assert.strictEqual( (nodeMain.match(/CoordinatorSession::connect/g) || []).length, 1, "node runtime should open one coordinator session in the local process-boundary runtime" ); for (const [name, pattern] of [ ["enrollment exchange over session", /"type": "exchange_node_enrollment_grant"/], ["node attach over session", /"type": "attach_node"/], ["heartbeat over session", /"type": "node_heartbeat"/], ["capability report over session", /"type": "report_node_capabilities"/], ["task placement over session", /"type": "schedule_task"/], ["process start over session", /"type": "start_process"/], ["reconnect over session", /"type": "reconnect_node"/], ["debug command polling over session", /"type": "poll_debug_command"/], ["log event over session", /"type": "report_task_log"/], ["VFS metadata over session", /"type": "report_vfs_metadata"/], ["task control polling over session", /"type": "poll_task_control"/], ["completion over session", /"type": "task_completed"/], ["cancellation uses same session", /wait_for_cancellation\(session, args, &task\)/], ["request count is reported", /session\.requests\(\)/], ]) { expect(nodeMain, name, pattern); } for (const [name, pattern] of [ ["local smoke asserts persistent request count", /assert\.strictEqual\(report\.session_requests, 10\)/], ["local smoke uses enrollment exchange", /assert\.strictEqual\(report\.registration_response\.type, "node_enrollment_exchanged"\)/], ["local smoke verifies capability report", /assert\.strictEqual\(report\.capability_response\.type, "node_capabilities_recorded"\)/], ["local smoke verifies task placement", /assert\.strictEqual\(report\.task_assignment_response\.type, "task_placement"\)/], ["local smoke verifies debug command channel", /assert\.strictEqual\(report\.debug_command_response\.type, "debug_command"\)/], ["local smoke verifies log event", /assert\.strictEqual\(report\.log_event_response\.type, "task_log_recorded"\)/], ["local smoke verifies VFS metadata", /assert\.strictEqual\(report\.vfs_metadata_response\.type, "vfs_metadata_recorded"\)/], ["local smoke records task completion", /assert\.strictEqual\(report\.coordinator_response\.type, "task_recorded"\)/], ["local smoke verifies artifact metadata", /assert\.strictEqual\(events\.events\[0\]\.artifact_path, "\/vfs\/artifacts\/demo-test-output\.txt"\)/], ["local smoke verifies output accounting", /assert\.strictEqual\(events\.events\[0\]\.status_code, 0\)/], ]) { expect(localServicesSmoke, name, pattern); } for (const [name, pattern] of [ ["cancellation request is external client request", /type: "cancel_task"/], ["node reports cancelled terminal state", /assert\.strictEqual\(report\.terminal_state, "cancelled"\)/], ["cancelled completion is recorded", /assert\.strictEqual\(report\.coordinator_response\.type, "task_recorded"\)/], ["coordinator stores cancelled task event", /assert\.strictEqual\(events\.events\[0\]\.terminal_state, "cancelled"\)/], ["control flag is cleared after terminal state", /assert\.strictEqual\(control\.cancel_requested, false\)/], ]) { expect(cancellationSmoke, name, pattern); } for (const [name, pattern] of [ ["coordinator rejects stale process ownership", /fn node_reconnect_rejects_stale_process_epoch_after_restart\(\)/], ["reconnect preserves enrolled node identity", /reconnect_node\(&NodeId::from\("node"\), None\)/], ["stale process epoch is rejected", /CoordinatorError::StaleProcessEpoch/], ]) { expect(coordinatorCore, name, pattern); } for (const [name, pattern] of [ ["coordinator delivers cancellation to connected node", /fn service_delivers_cancellation_to_connected_node_and_records_terminal_state\(\)/], ["node polls task control", /CoordinatorRequest::PollTaskControl/], ["cancelled terminal state is recorded", /TaskTerminalState::Cancelled/], ]) { expect(coordinatorService, name, pattern); } for (const [name, pattern] of [ ["native lifecycle test exists", /fn linux_task_lifecycle_supports_cancel_and_all_stop_freeze_resume\(\)/], ["native freeze succeeds when supported", /lifecycle\.freeze_for_debug_epoch\(\)\.unwrap\(\)/], ["native resume succeeds", /lifecycle\.resume_after_debug_epoch\(\)/], ["native cancel reaches lifecycle", /lifecycle\.cancel\(\)/], ["unsupported freeze errors", /BackendError::DebugFreezeUnsupported/], ["wasmtime runtime exposes freeze resume probe", /pub fn freeze_resume_i32_export_probe/], ["wasmtime runtime captures Wasm frame locals", /debug_i32_export_snapshot[\s\S]*local_values/], ["wasmtime runtime creates Wasm debug participant", /kind: DebugParticipantKind::WasmTask/], ["wasmtime debug participant carries local values", /local_values: snapshot\.local_values\.clone\(\)/], ["wasmtime runtime resumes after freeze", /epoch\.continue_all\(\)/], ]) { expect(nodeLib, name, pattern); } for (const [name, pattern] of [ ["wasmtime smoke runs debug freeze resume mode", /--debug-freeze-resume/], ["wasmtime smoke verifies frozen state", /debugReport\.frozen_state, "Frozen"/], ["wasmtime smoke verifies resumed state", /debugReport\.resumed_state, "Running"/], ["wasmtime smoke verifies frame local values", /debugReport\.local_values[\s\S]*wasm_local_0/], ["wasmtime smoke proves node runtime reached wasm task", /node_runtime_reached_wasm_task/], ["wasmtime smoke proves node captured locals", /node_runtime_captured_wasm_locals/], ]) { expect(wasmtimeSmoke, name, pattern); } for (const [name, pattern] of [ ["debug model freezes wasm and command participants", /fn breakpoint_creates_all_stop_debug_epoch_for_wasm_and_command_tasks\(\)/], ["debug model rejects unsupported freeze", /fn debug_epoch_reports_freeze_failure_instead_of_claiming_all_stop\(\)/], ["debug model resumes frozen participants", /fn continue_resumes_every_frozen_participant\(\)/], ["debug model includes captured locals", /local_values/], ["wasm participants are modeled", /DebugParticipantKind::WasmTask/], ["controlled native command participants are modeled", /DebugParticipantKind::ControlledNativeCommand/], ]) { expect(debugCore, name, pattern); } for (const [name, pattern] of [ ["docs describe one node coordinator session", /keeps one node-to-coordinator JSON-line session open/], ["docs describe cancellation terminal event", /records a cancelled terminal event/], ["docs describe failed freeze diagnostic", /Failed debug freezes/], ]) { expect(readme, name, pattern); } console.log("Node lifecycle contract smoke passed");