Skip to content

Add frozen raw-class startup and 30-second symbolic probes - #512

Open
CaelmBleidd wants to merge 7 commits into
mainfrom
caelmbleidd/calls-class-start-smoke
Open

CaelmBleidd wants to merge 7 commits into
mainfrom
caelmbleidd/calls-class-start-smoke

Conversation

@CaelmBleidd

@CaelmBleidd CaelmBleidd commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

Real classes can be rejected by observation-domain/native admission before the symbolic engine starts. Add frozen raw-class startup and exploratory symbolic probe commands to load each complete original class through the bundled frontend, materialize its IR bodies, and run a real TsMachine while keeping every failed or pending class in the original denominator.

class-start-smoke requires a modeled initial state and an interpreter callback inside an original target-class statement. Scheduling and synthetic constructor returns cannot establish it. First-call residual/runtime stops remain STARTED_WITH_LIMITATION; successful transitions, stage failures, timeouts, unknown calls, full failure stacks, and generated versus actually selected initial-state counts stay separate. Durable source-entry receipts survive later child termination. Qualification verifies the external acquisition receipt and its explicit completion evidence; installation alone does not qualify.

class-symbolic-probe reuses the same loading/entry/cache contracts for fixed 30-second runs, seed 17, CLASS scope, 250ms solver checks, 25ms entry quanta, and no terminal-state cap. Its four-profile driver requires a completed matching startup screen with at least 180/200 qualifying starts, freezes all 200 original classes for 800 cells, and preserves returned/exceptional/unsupported states, residual prefixes, remaining queued states, actual solver/quanta/overrun data, and source-mapped IR entry metrics. State provenance/constraints and unknown-call decisions are appended durably; snapshot failures and unavailable metrics remain explicit. Remaining states are drained only after the machine computes its real stop reason.

Runtime class selection uses the exact file/name/CLASS category and retains merged interfaces in the scene. Lowered closure bodies remain loaded and reachable through their owning members; the runner records why they cannot be independent entries with fabricated capture environments. A default-no-op interpreter observer hook reports statement entry after preparation and before dispatch, including property definitions. Both frontend script/directory overrides are rejected; the measurement gate requires the exact startup runtime bytes, and frontend IR cache keys include the actual provider binary hash.

Source-mapped IR universes are frozen before search and must match between profiles. The drivers freeze manifest/runtime identities, isolate each class in a child JVM, kill complete process groups on timeout, and share only verified immutable frontend IR. These symbolic diagnostics do not claim native coverage, concrete replay witnesses, or scientific campaign readiness. Native class coverage remains unavailable in the diagnostic summary.

Related to #498 and #483. Standalone instructions are in usvm-ts-calls/CLASS_START_SMOKE.md.

Validation: 10 focused Kotlin raw-start/probe tests, 12 Python integrity/protocol tests, TS main and Calls main/test Detekt with zero findings, installed distribution build, and git diff --check. Focused fixtures cover original class startup, actual residual dispatch, unsupported frontend values, synthetic/uninitialized source rejection, durable prefixes/state snapshots, source drift, failed/pending denominator retention, 180/200 gate enforcement, fixed profiles/options, and unavailable metrics. Broad suites are left to CI as requested.

Review hotspots: source entry versus successful-transition attribution, acquisition/runtime resume identity, stopped-prefix and remaining-state retention, and immutable source-mapped IR universes across profiles.

Prove interpreter entry into frozen original class statements separately from successful transitions. Retain acquisition, frontend, kernel, timeout, and residual-call evidence for every frozen class.
Gate the unchanged 200-class cohort on 180 qualifying startup receipts. Retain terminal states, stopped prefixes, queued states, immutable source-mapped IR points, solver metrics, and budget overruns without claiming native coverage.
@CaelmBleidd CaelmBleidd changed the title Add isolated raw class startup probes with source entry receipts Add frozen raw-class startup and 30-second symbolic probes Oct 14, 2026
Select runtime class declarations without dropping merged interfaces. Keep lowered closure bodies in the scene but enter them through their owning member. Observe actual statement dispatch, reject frontend overrides, and bind the measurement gate and IR cache to verified runtime bytes.
writer.appendLine(encodeCallsArtifact(saved))
1L
}
} catch (failure: Throwable) {
val added = gzip.bufferedWriter(Charsets.UTF_8).use { writer -> write(writer) }
output.force(true)
records += added
} catch (failure: Throwable) {
path = path.fileName.toString(),
records = records,
compressedBytes = Files.size(path),
sha256 = digest.digest().joinToString(separator = "") { byte -> "%02x".format(byte.toInt() and 0xff) },
@@ -0,0 +1,123 @@
package org.usvm.ts.calls

import io.ksmt.KContext
assertTrue(states.complete)
assertTrue(expressions.complete)
assertEquals(callsArtifactSha256(Files.readAllBytes(directory.resolve(states.path))), states.sha256)
assertEquals(callsArtifactSha256(Files.readAllBytes(directory.resolve(expressions.path))), expressions.sha256)
assertTrue(states.complete)
assertTrue(expressions.complete)
assertEquals(callsArtifactSha256(Files.readAllBytes(directory.resolve(states.path))), states.sha256)
assertEquals(callsArtifactSha256(Files.readAllBytes(directory.resolve(expressions.path))), expressions.sha256)
assertTrue(states.complete)
assertTrue(expressions.complete)
assertEquals(callsArtifactSha256(Files.readAllBytes(directory.resolve(states.path))), states.sha256)
assertEquals(callsArtifactSha256(Files.readAllBytes(directory.resolve(expressions.path))), expressions.sha256)
assertTrue(states.complete)
assertTrue(expressions.complete)
assertEquals(callsArtifactSha256(Files.readAllBytes(directory.resolve(states.path))), states.sha256)
assertEquals(callsArtifactSha256(Files.readAllBytes(directory.resolve(expressions.path))), expressions.sha256)
assertTrue(states.complete)
assertTrue(expressions.complete)
assertEquals(callsArtifactSha256(Files.readAllBytes(directory.resolve(states.path))), states.sha256)
assertEquals(callsArtifactSha256(Files.readAllBytes(directory.resolve(expressions.path))), expressions.sha256)
assertTrue(states.complete)
assertTrue(expressions.complete)
assertEquals(callsArtifactSha256(Files.readAllBytes(directory.resolve(states.path))), states.sha256)
assertEquals(callsArtifactSha256(Files.readAllBytes(directory.resolve(expressions.path))), expressions.sha256)
Consume the sorted file stream through a Kotlin sequence instead of Stream.toList(), which requires Java 16. Preserve relative-path ordering and hashes.
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.

2 participants