From d3837a5880eccf9bf23e2fc5593048e0eb06e395 Mon Sep 17 00:00:00 2001 From: gionag Date: Wed, 30 Sep 2026 14:13:29 +0200 Subject: [PATCH 1/3] test(0.7.1g1G5c): pin the structured-parse-failed diagnostic to the real failure class The existing assertions used startsWith("structured-parse-failed"), which is satisfied both by the authoritative diagnostic (structured-parse-failed: StructuredOutputException) and by the negated-conditional mutant's output (structured-parse-failed: unknown). The assertions now pin the full contract, so the diagnostic's class-name component is observable behaviour rather than an unchecked prefix. --- .../engine/approval/ApprovalResumeSuspensionContractTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tramai-engine/src/test/kotlin/dev/tramai/engine/approval/ApprovalResumeSuspensionContractTest.kt b/tramai-engine/src/test/kotlin/dev/tramai/engine/approval/ApprovalResumeSuspensionContractTest.kt index 8a185e80..140b4183 100644 --- a/tramai-engine/src/test/kotlin/dev/tramai/engine/approval/ApprovalResumeSuspensionContractTest.kt +++ b/tramai-engine/src/test/kotlin/dev/tramai/engine/approval/ApprovalResumeSuspensionContractTest.kt @@ -526,7 +526,7 @@ class ApprovalResumeSuspensionContractTest { assertReachesCaller(thrown, failure) assertThat(audit.uncertainReasons).hasSize(1) - assertThat(audit.uncertainReasons.single()).startsWith("structured-parse-failed") + assertThat(audit.uncertainReasons.single()).isEqualTo("structured-parse-failed: StructuredOutputException") assertThat(audit.uncertainResumes).isEqualTo(1) } @@ -631,7 +631,7 @@ class ApprovalResumeSuspensionContractTest { assertThat(thrown).isInstanceOf(CancellationException::class.java) assertReachesCaller(thrown, cancellation) assertThat(audit.uncertainResumes).isEqualTo(1) - assertThat(audit.uncertainReasons.single()).startsWith("structured-parse-failed") + assertThat(audit.uncertainReasons.single()).isEqualTo("structured-parse-failed: StructuredOutputException") } @Test From 5e275cccda0953ca244f8c8081acafd272a6f83b Mon Sep 17 00:00:00 2001 From: gionag Date: Wed, 30 Sep 2026 14:30:55 +0200 Subject: [PATCH 2/3] docs(0.7.1g1G5c): close the SURVIVED cohort - 1 KILLED, 11 EQUIVALENT Adjudicates the 12 frozen SURVIVED identities at base 42d9d948: 12/12 EXACT mappings (the five G5a ambiguities resolved by canonical identity), 1 semantic KILLED (a9760bea3a92, via an exact diagnostic assertion), 11 instruction-level EQUIVALENT proofs (6 caller-discard, 2 catch-handler dominance, 1 compiler guard, 2 successor convergence), 0 UNDETERMINED, 0 KILLED regressions. No production changes; no authority changes. --- .../TASK-0.7.1g1G5c-SURVIVED-12-MANIFEST.json | 402 ++++++++++++++++++ .../TASK-0.7.1g1G5c-SURVIVED-ADJUDICATION.md | 121 ++++++ 2 files changed, 523 insertions(+) create mode 100644 docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-12-MANIFEST.json create mode 100644 docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-ADJUDICATION.md diff --git a/docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-12-MANIFEST.json b/docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-12-MANIFEST.json new file mode 100644 index 00000000..2345458d --- /dev/null +++ b/docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-12-MANIFEST.json @@ -0,0 +1,402 @@ +{ + "schemaVersion": 1, + "task": "TASK-0.7.1g1G5c", + "parent": "TASK-0.7.1g1G5", + "title": "SURVIVED mapping closure and semantic adjudication (12 identities)", + "base": "42d9d9487ccf59ca3f348d0babfe9bbda232ef0f", + "baseProvenance": "squash merge of #462 on epic/0.7.1-control-plane-authority; frozen parent digest 92a9d06d5a8e43c5fb659f9d65bdd2e73d6ed5f45c1a8536ac70781b03503584 unchanged; admission ledger admissions: []", + "campaigns": { + "control": { + "throwaway": "78458d1eecce60c7f8f307b4564fb47afda0da79", + "measuredCommit": "78458d1eecce60c7f8f307b4564fb47afda0da79", + "configDiff": "family-list narrowing only: 53 deletions in config/quality/test-quality.yml, approval block byte-identical", + "familyCensus": { + "total": 918, + "byModule": { + ":tramai-engine": 492, + ":tramai-security": 426 + }, + "statuses": { + "KILLED": 661, + "SURVIVED": 133, + "NO_COVERAGE": 62, + "TIMED_OUT": 62 + } + }, + "durationSeconds": 1000, + "buildResult": "BUILD SUCCESSFUL" + }, + "candidate": { + "throwaway": "7acbd868adb94658e90ef55d3261d315f6eddda9", + "parent": "78458d1eecce60c7f8f307b4564fb47afda0da79", + "testCommit": "d3837a5880eccf9bf23e2fc5593048e0eb06e395", + "measuredCommit": "7acbd868adb94658e90ef55d3261d315f6eddda9", + "distinctFromControl": "only the test commit", + "familyCensus": { + "total": 918, + "statuses": { + "KILLED": 662, + "SURVIVED": 132, + "NO_COVERAGE": 62, + "TIMED_OUT": 62 + } + }, + "durationSeconds": 923, + "buildResult": "BUILD SUCCESSFUL" + } + }, + "reconciliation": { + "sharedIdentities": 918, + "controlOnly": 0, + "candidateOnly": 0, + "statusMovements": 1, + "movements": [ + { + "identity": "a9760bea3a92f", + "from": "SURVIVED", + "to": "KILLED" + } + ], + "killedRegressions": 0, + "newTimeouts": 0, + "identityLoss": 0, + "identityGain": 0, + "recovered": 12, + "missing": 0, + "duplicates": 0 + }, + "mappingDiscipline": { + "authority": "MutationIdentity.stableKey(): sha256 over module\u241fclass\u241fmethod\u241fdescriptor\u241fmutator\u241fdescription\u241fblock\u241findex; line deliberately excluded", + "verified": "reproduces all 68 identities of the P1 candidate-only manifest exactly", + "superseded": "G5a marked five identities AMBIGUOUS because opcode-shape enumeration cannot recover PIT's block/index coordinates. They are now EXACT: the canonical identity itself carries block/index, so matching PIT's emitted rows resolves each uniquely. The G5a ambiguity is retained here as superseded, not erased." + }, + "hypotheses": { + "A_observable_missing_discriminator": [ + "a9760bea3a92" + ], + "B_value_discarded": [ + "3a5c5213b226", + "56d3366434a6", + "6a1ce2f46d2a", + "a542bbe6db3f", + "f44636049288", + "eb21aaed3192" + ], + "other_structural": [ + "1ce5967ee60b", + "c7774df8ccdc", + "3658ba45eaed", + "8e18b4b48968", + "d38ac52f2843" + ], + "F_unclear": [], + "E_tooling_limitation": [] + }, + "finalTotals": { + "inputSURVIVED": 12, + "KILLED": 1, + "EQUIVALENT": 11, + "UNREACHABLE": 0, + "TOOLING_LIMITATION": 0, + "UNDETERMINED": 0 + }, + "parentAccounting": { + "parent": 52, + "settledByG5b": 36, + "inputG5c": 12, + "killed": 1, + "equivalent": 11, + "remainingForG5d": 4, + "remainingAre": "exactly the frozen NO_COVERAGE identities" + }, + "identities": [ + { + "identity": "1ce5967ee60b6f4380d69dead598dde89212eeb17c2b9be6348bf9dfc3928981", + "className": "dev.tramai.engine.approval.ApprovalResumeCoordinator", + "method": "resume", + "methodDescription": "(Ldev/tramai/engine/ResumeApprovalCommand;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + "mutator": "VoidMethodCall", + "description": "removed call to dev/tramai/core/coroutines/CancellationKt::rethrowIfCancellation", + "sourceLine": 108, + "pitBlock": 91, + "pitIndex": 641, + "bytecodePc": 1100, + "instruction": "invokestatic dev/tramai/core/coroutines/CancellationKt.rethrowIfCancellation", + "g5aOriginalMapping": "AMBIGUOUS (superseded: count mismatch from opcode-shape enumeration; resolved exactly by canonical identity)", + "resolvedExactMapping": "EXACT", + "controlStatus": "SURVIVED", + "controlTestsRun": 20, + "discoveryStatus": "SURVIVED", + "semanticHypothesis": "structural equivalence (successor convergence / handler dominance / compiler guard)", + "proofUsed": "catch-handler dominance: resume's exception table registers CancellationException->1088 and Exception->1093; pc1100 executes inside the 1093 (Exception) handler, and JVM dispatch order guarantees the earlier CancellationException handler wins. The helper's only branch (this is CancellationException) cannot fire, so removing the call cannot change behaviour.", + "killingTest": null, + "finalStatus": "SURVIVED (structurally equivalent)", + "finalDisposition": "EQUIVALENT", + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + }, + { + "identity": "3658ba45eaedbf6a946036d210a91578d65fda8b0f0f295137393d3454e9a5e0", + "className": "dev.tramai.engine.approval.ApprovalSuspensionCoordinator", + "method": "suspendToolExecution", + "methodDescription": "(Ldev/tramai/engine/approval/SuspendToolExecutionRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + "mutator": "VoidMethodCall", + "description": "removed call to kotlin/jvm/internal/Intrinsics::checkNotNull", + "sourceLine": 160, + "pitBlock": 31, + "pitIndex": 168, + "bytecodePc": 287, + "instruction": "invokestatic kotlin/jvm/internal/Intrinsics.checkNotNull", + "g5aOriginalMapping": "AMBIGUOUS (superseded: count mismatch from opcode-shape enumeration; resolved exactly by canonical identity)", + "resolvedExactMapping": "EXACT", + "controlStatus": "SURVIVED", + "controlTestsRun": 95, + "discoveryStatus": "SURVIVED", + "semanticHypothesis": "structural equivalence (successor convergence / handler dominance / compiler guard)", + "proofUsed": "compiler-inserted parameter guard: pc285 aload 7; pc287 checkNotNull; pc290 aload 7; pc293 invokespecial CreateApprovalChallenge(...). The checked value is immediately passed on as a non-null Kotlin constructor parameter, whose own parameter check raises the same NPE one instruction later, so removal cannot change exception type or the observable outcome on any valid path.", + "killingTest": null, + "finalStatus": "SURVIVED (structurally equivalent)", + "finalDisposition": "EQUIVALENT", + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + }, + { + "identity": "3a5c5213b226f1f86b48c12172489ee618b9af890d750ab3ac1d7d2032854e0a", + "className": "dev.tramai.engine.approval.ApprovalSuspensionCoordinator", + "method": "compensateStep", + "methodDescription": "(Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + "mutator": "NullReturnVals", + "description": "replaced return value with null for dev/tramai/engine/approval/ApprovalSuspensionCoordinator::compensateStep", + "sourceLine": 307, + "pitBlock": 17, + "pitIndex": 106, + "bytecodePc": null, + "instruction": "areturn of the Unit value at the function's return", + "g5aOriginalMapping": "EXACT", + "resolvedExactMapping": "EXACT", + "controlStatus": "SURVIVED", + "controlTestsRun": 13, + "discoveryStatus": "SURVIVED", + "semanticHypothesis": "B (returned value semantically discarded)", + "proofUsed": "caller-discard: every call site's resumed path begins with an explicit pop (compensateStep pc252, persistSuspendedInvocation pc1231, persistUngoverned pc880, persistGoverned pc1049, requireExistingAttributionMatches pc699), so the returned Unit value is never observed; replacing it with null cannot change behaviour.", + "killingTest": null, + "finalStatus": "SURVIVED (structurally equivalent)", + "finalDisposition": "EQUIVALENT", + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + }, + { + "identity": "56d3366434a6608d7b5ccd59b6c1377be7324ab2078ec7a09b872153968e4466", + "className": "dev.tramai.engine.approval.DefaultApprovalGateway", + "method": "requireExistingAttributionMatches", + "methodDescription": "(Ldev/tramai/core/approval/ApprovalRequest;Ldev/tramai/core/identity/GovernedRunIdentity;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + "mutator": "NullReturnVals", + "description": "replaced return value with null for dev/tramai/engine/approval/DefaultApprovalGateway::requireExistingAttributionMatches", + "sourceLine": 205, + "pitBlock": 9, + "pitIndex": 50, + "bytecodePc": null, + "instruction": "areturn of the Unit value at the function's return", + "g5aOriginalMapping": "EXACT", + "resolvedExactMapping": "EXACT", + "controlStatus": "SURVIVED", + "controlTestsRun": 6, + "discoveryStatus": "SURVIVED", + "semanticHypothesis": "B (returned value semantically discarded)", + "proofUsed": "caller-discard: every call site's resumed path begins with an explicit pop (compensateStep pc252, persistSuspendedInvocation pc1231, persistUngoverned pc880, persistGoverned pc1049, requireExistingAttributionMatches pc699), so the returned Unit value is never observed; replacing it with null cannot change behaviour.", + "killingTest": null, + "finalStatus": "SURVIVED (structurally equivalent)", + "finalDisposition": "EQUIVALENT", + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + }, + { + "identity": "6a1ce2f46d2ad5cdb7fb857a56fcf4ca0d3d87ffc3825279121386e04c3f7c88", + "className": "dev.tramai.engine.approval.DefaultApprovalGateway", + "method": "requireExistingAttributionMatches", + "methodDescription": "(Ldev/tramai/core/approval/ApprovalRequest;Ldev/tramai/core/identity/GovernedRunIdentity;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + "mutator": "NullReturnVals", + "description": "replaced return value with null for dev/tramai/engine/approval/DefaultApprovalGateway::requireExistingAttributionMatches", + "sourceLine": 219, + "pitBlock": 26, + "pitIndex": 141, + "bytecodePc": null, + "instruction": "areturn of the Unit value at the function's return", + "g5aOriginalMapping": "EXACT", + "resolvedExactMapping": "EXACT", + "controlStatus": "SURVIVED", + "controlTestsRun": 2, + "discoveryStatus": "SURVIVED", + "semanticHypothesis": "B (returned value semantically discarded)", + "proofUsed": "caller-discard: every call site's resumed path begins with an explicit pop (compensateStep pc252, persistSuspendedInvocation pc1231, persistUngoverned pc880, persistGoverned pc1049, requireExistingAttributionMatches pc699), so the returned Unit value is never observed; replacing it with null cannot change behaviour.", + "killingTest": null, + "finalStatus": "SURVIVED (structurally equivalent)", + "finalDisposition": "EQUIVALENT", + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + }, + { + "identity": "8e18b4b48968d65f181bd226d6e81d99c6c9abb3427463ae77773eb4c901e658", + "className": "dev.tramai.engine.approval.ApprovalRunAttributionKt", + "method": "decodeApprovalAttribution", + "methodDescription": "(Ljava/lang/String;Ljava/util/Map;)Ldev/tramai/engine/approval/ApprovalRunAttribution;", + "mutator": "NegateConditionals", + "description": "negated conditional", + "sourceLine": 174, + "pitBlock": 22, + "pitIndex": 127, + "bytecodePc": 189, + "instruction": "ifeq following instanceof Collection (inlined any, _Collections.kt 1807)", + "g5aOriginalMapping": "AMBIGUOUS (superseded: count mismatch from opcode-shape enumeration; resolved exactly by canonical identity)", + "resolvedExactMapping": "EXACT", + "controlStatus": "SURVIVED", + "controlTestsRun": 5, + "discoveryStatus": "SURVIVED", + "semanticHypothesis": "structural equivalence (successor convergence / handler dominance / compiler guard)", + "proofUsed": "successor convergence: negating the inlined fast-path test routes Collection receivers onto the plain-Iterable loop path; empty input returns false on both paths and non-empty input runs the identical loop, so no observable difference exists.", + "killingTest": null, + "finalStatus": "SURVIVED (structurally equivalent)", + "finalDisposition": "EQUIVALENT", + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + }, + { + "identity": "a542bbe6db3f9f551bbbea6972a28dc670945d1232221bd1d9a3f98814a6defb", + "className": "dev.tramai.engine.approval.DefaultApprovalGateway", + "method": "persistGoverned", + "methodDescription": "(Ldev/tramai/engine/approval/ApprovalGatewayPersistenceRequest;Ldev/tramai/core/identity/GovernedRunIdentity;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + "mutator": "NullReturnVals", + "description": "replaced return value with null for dev/tramai/engine/approval/DefaultApprovalGateway::persistGoverned", + "sourceLine": 265, + "pitBlock": 35, + "pitIndex": 204, + "bytecodePc": null, + "instruction": "areturn of the Unit value at the function's return", + "g5aOriginalMapping": "EXACT", + "resolvedExactMapping": "EXACT", + "controlStatus": "SURVIVED", + "controlTestsRun": 3, + "discoveryStatus": "SURVIVED", + "semanticHypothesis": "B (returned value semantically discarded)", + "proofUsed": "caller-discard: every call site's resumed path begins with an explicit pop (compensateStep pc252, persistSuspendedInvocation pc1231, persistUngoverned pc880, persistGoverned pc1049, requireExistingAttributionMatches pc699), so the returned Unit value is never observed; replacing it with null cannot change behaviour.", + "killingTest": null, + "finalStatus": "SURVIVED (structurally equivalent)", + "finalDisposition": "EQUIVALENT", + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + }, + { + "identity": "a9760bea3a92a752255a2becee7edb3ffa0957cf0e88cb75a0a11db850dcc747", + "className": "dev.tramai.engine.approval.ApprovalResumeCoordinator", + "method": "resume", + "methodDescription": "(Ldev/tramai/engine/ResumeApprovalCommand;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + "mutator": "NegateConditionals", + "description": "negated conditional", + "sourceLine": 102, + "pitBlock": 76, + "pitIndex": 533, + "bytecodePc": 912, + "instruction": "ifnonnull (Elvis on e::class.simpleName)", + "g5aOriginalMapping": "EXACT", + "resolvedExactMapping": "EXACT", + "controlStatus": "SURVIVED", + "controlTestsRun": 5, + "discoveryStatus": "SURVIVED", + "semanticHypothesis": "A (observable, missing discriminator)", + "proofUsed": "SURVIVED -> KILLED by measurement at 7acbd868: the diagnostic 'structured-parse-failed: ${e::class.simpleName ?: \"unknown\"}' is now pinned by isEqualTo in ApprovalResumeSuspensionContractTest, instead of the startsWith prefix that both the original and the mutant satisfied.", + "killingTest": "ApprovalResumeSuspensionContractTest.[engine:junit-jupiter]/[class:...ApprovalResumeSuspensionContractTest]/[method:a cancellation resumed into the structured-parse uncertain path is not replaced by the primary failure()]", + "finalStatus": "KILLED", + "finalDisposition": "KILLED", + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + }, + { + "identity": "c7774df8ccdcefaaac0c151f68b24313cc511a6a0800951cd375dfe217d265b6", + "className": "dev.tramai.engine.approval.ApprovalSuspensionCoordinator", + "method": "compensateStep", + "methodDescription": "(Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + "mutator": "VoidMethodCall", + "description": "removed call to dev/tramai/core/coroutines/CancellationKt::rethrowIfCancellation", + "sourceLine": 305, + "pitBlock": 16, + "pitIndex": 101, + "bytecodePc": 155, + "instruction": "invokestatic dev/tramai/core/coroutines/CancellationKt.rethrowIfCancellation", + "g5aOriginalMapping": "AMBIGUOUS (superseded: count mismatch from opcode-shape enumeration; resolved exactly by canonical identity)", + "resolvedExactMapping": "EXACT", + "controlStatus": "SURVIVED", + "controlTestsRun": 4, + "discoveryStatus": "SURVIVED", + "semanticHypothesis": "structural equivalence (successor convergence / handler dominance / compiler guard)", + "proofUsed": "catch-handler dominance: compensateStep registers CancellationException->147 and Exception->150; pc155 executes inside the 150 handler, so the value is never a CancellationException.", + "killingTest": null, + "finalStatus": "SURVIVED (structurally equivalent)", + "finalDisposition": "EQUIVALENT", + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + }, + { + "identity": "d38ac52f2843448a4df4cba789ae27ddf9df3f73356c9c8ef972f2f03cc180c3", + "className": "dev.tramai.engine.approval.ApprovalRunAttributionKt", + "method": "decodeApprovalAttribution", + "methodDescription": "(Ljava/lang/String;Ljava/util/Map;)Ldev/tramai/engine/approval/ApprovalRunAttribution;", + "mutator": "NegateConditionals", + "description": "negated conditional", + "sourceLine": 174, + "pitBlock": 24, + "pitIndex": 131, + "bytecodePc": 189, + "instruction": "ifeq following instanceof Collection (inlined any, _Collections.kt 1807)", + "g5aOriginalMapping": "AMBIGUOUS (superseded: count mismatch from opcode-shape enumeration; resolved exactly by canonical identity)", + "resolvedExactMapping": "EXACT", + "controlStatus": "SURVIVED", + "controlTestsRun": 5, + "discoveryStatus": "SURVIVED", + "semanticHypothesis": "structural equivalence (successor convergence / handler dominance / compiler guard)", + "proofUsed": "same fast-path test in the second inlined stratum copy; identical successor convergence.", + "killingTest": null, + "finalStatus": "SURVIVED (structurally equivalent)", + "finalDisposition": "EQUIVALENT", + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + }, + { + "identity": "eb21aaed31923633c541c603ebf29c170343b1e822874768f732093a099b3a18", + "className": "dev.tramai.engine.approval.ApprovalSuspensionCoordinator", + "method": "persistSuspendedInvocation", + "methodDescription": "(Ldev/tramai/engine/approval/ApprovalSuspensionCoordinator$GovernedSuspension;Ldev/tramai/engine/SuspendedInvocationMetadata;Ldev/tramai/engine/SensitiveReplayEnvelope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + "mutator": "NullReturnVals", + "description": "replaced return value with null for dev/tramai/engine/approval/ApprovalSuspensionCoordinator::persistSuspendedInvocation", + "sourceLine": 284, + "pitBlock": 9, + "pitIndex": 38, + "bytecodePc": null, + "instruction": "areturn of the Unit value at the function's return", + "g5aOriginalMapping": "EXACT", + "resolvedExactMapping": "EXACT", + "controlStatus": "SURVIVED", + "controlTestsRun": 4, + "discoveryStatus": "SURVIVED", + "semanticHypothesis": "B (returned value semantically discarded)", + "proofUsed": "caller-discard: every call site's resumed path begins with an explicit pop (compensateStep pc252, persistSuspendedInvocation pc1231, persistUngoverned pc880, persistGoverned pc1049, requireExistingAttributionMatches pc699), so the returned Unit value is never observed; replacing it with null cannot change behaviour.", + "killingTest": null, + "finalStatus": "SURVIVED (structurally equivalent)", + "finalDisposition": "EQUIVALENT", + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + }, + { + "identity": "f4463604928886b61038161dfacada30be5fa9dcd62178ac329b83c4568e3ffd", + "className": "dev.tramai.engine.approval.DefaultApprovalGateway", + "method": "persistUngoverned", + "methodDescription": "(Ldev/tramai/engine/approval/ApprovalGatewayPersistenceRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + "mutator": "NullReturnVals", + "description": "replaced return value with null for dev/tramai/engine/approval/DefaultApprovalGateway::persistUngoverned", + "sourceLine": 234, + "pitBlock": 29, + "pitIndex": 161, + "bytecodePc": null, + "instruction": "areturn of the Unit value at the function's return", + "g5aOriginalMapping": "EXACT", + "resolvedExactMapping": "EXACT", + "controlStatus": "SURVIVED", + "controlTestsRun": 7, + "discoveryStatus": "SURVIVED", + "semanticHypothesis": "B (returned value semantically discarded)", + "proofUsed": "caller-discard: every call site's resumed path begins with an explicit pop (compensateStep pc252, persistSuspendedInvocation pc1231, persistUngoverned pc880, persistGoverned pc1049, requireExistingAttributionMatches pc699), so the returned Unit value is never observed; replacing it with null cannot change behaviour.", + "killingTest": null, + "finalStatus": "SURVIVED (structurally equivalent)", + "finalDisposition": "EQUIVALENT", + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + } + ] +} \ No newline at end of file diff --git a/docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-ADJUDICATION.md b/docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-ADJUDICATION.md new file mode 100644 index 00000000..6d289ee2 --- /dev/null +++ b/docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-ADJUDICATION.md @@ -0,0 +1,121 @@ +# TASK-0.7.1g1G5c — SURVIVED mapping closure and semantic adjudication + +Parent: **TASK-0.7.1g1G5**. Scope: the **12 frozen SURVIVED identities**, and nothing else. The four NO_COVERAGE identities are untouched. +Base: **`42d9d9487ccf59ca3f348d0babfe9bbda232ef0f`** — the squash merge of #462. Frozen parent digest `92a9d06d5a8e43c5fb659f9d65bdd2e73d6ed5f45c1a8536ac70781b03503584` unchanged; admission ledger still `admissions: []`. + +**Endpoint: G5C SURVIVED COHORT CLOSED — G5 REMAINDER = EXACTLY 4 NO_COVERAGE.** + +## Final accounting + +| | | +| --- | --- | +| input SURVIVED | 12 | +| KILLED | **1** | +| EQUIVALENT | **11** | +| UNREACHABLE | 0 | +| TOOLING_LIMITATION | 0 | +| UNDETERMINED | **0** | +| mappings EXACT | **12 / 12** | +| mappings AMBIGUOUS | 0 | + +## Phase 1 — the five ambiguous mappings, repaired + +G5a marked five identities AMBIGUOUS because an opcode-shape enumeration cannot recover PIT's block/index coordinates. The authority is the repository's own `MutationIdentity.stableKey()`: `sha256(module ␟ class ␟ method ␟ descriptor ␟ mutator ␟ description ␟ block ␟ index)`, with **line deliberately excluded**. It reproduces **all 68** identities of the P1 candidate-only manifest exactly, so the canonical identity itself carries PIT's coordinates — and matching PIT's emitted rows against the frozen identity resolves each ambiguous identity uniquely: + +| identity | resolved line | PIT block/index | instruction | +| --- | --- | --- | --- | +| `1ce5967ee60b` | 108 | 91 / 641 | `pc1100 invokestatic CancellationKt.rethrowIfCancellation` | +| `c7774df8ccdc` | 305 | 16 / 101 | `pc155 invokestatic CancellationKt.rethrowIfCancellation` | +| `3658ba45eaed` | 160 | 31 / 168 | `pc287 invokestatic Intrinsics.checkNotNull` | +| `8e18b4b48968` | 174 | 22 / 127 | `pc189 ifeq` after `instanceof Collection` | +| `d38ac52f2843` | 174 | 24 / 131 | same fast-path test, second inlined stratum copy | + +The G5a AMBIGUOUS determinations are recorded as **superseded, not erased** (see `g5aOriginalMapping` per row). + +**The SMAP matters here.** `ApprovalRunAttributionKt`'s line table has entries at 171–180 while the checked-in `ApprovalRunAttribution.kt` ends at line 169. The `SourceDebugExtension` map explains it: output line 174 comes from stratum **2 = `_Collections.kt` line 1807** (inlined stdlib), and the `KotlinDebug` stratum maps it back to **our line 104** — `expected.any { metadata.getValue(it).isBlank() }`. Treating "174" as a physical line in our file would have been wrong. + +## Phase 2 — control measurement at the new base + +Family-only narrowing (53 deletions, `approval` block byte-identical), throwaway `78458d1eecce60c7f8f307b4564fb47afda0da79`, BUILD SUCCESSFUL in 1000 s, `measuredCommit` equal to the throwaway commit, analyzer semantics unchanged. Census: **918** mutants — engine 492, security 426; KILLED 661, SURVIVED 133, NO_COVERAGE 62, TIMED_OUT 62. + +Recovery: **12 input · 12 recovered · 0 missing · 0 duplicates**, every control status taken from this post-merge tip. All twelve remained SURVIVED (matrix `SURVIVED → SURVIVED` ×12, **status movement 0**), so no identity was incidentally killed by merged tests, and no identity was killed merely to raise a number. + +## Phase 3 — diagnosis + +All twelve had real `numberOfTestsRun` at control (2–95), so E (tooling limitation) was excluded from the outset and no identity was diagnosed from mutator or status similarity. + +| identity | owner | mutator | line | PIT | hypothesis | disposition | +| --- | --- | --- | --- | --- | --- | --- | +| `1ce5967ee60b` | ApprovalResumeCoordinator.resume | VoidMethodCall | 108 | b91/i641 | structural | **EQUIVALENT** | +| `3658ba45eaed` | ApprovalSuspensionCoordinator.suspendToolExecution | VoidMethodCall | 160 | b31/i168 | structural | **EQUIVALENT** | +| `3a5c5213b226` | ApprovalSuspensionCoordinator.compensateStep | NullReturnVals | 307 | b17/i106 | B | **EQUIVALENT** | +| `56d3366434a6` | DefaultApprovalGateway.requireExistingAttributionMatches | NullReturnVals | 205 | b9/i50 | B | **EQUIVALENT** | +| `6a1ce2f46d2a` | DefaultApprovalGateway.requireExistingAttributionMatches | NullReturnVals | 219 | b26/i141 | B | **EQUIVALENT** | +| `8e18b4b48968` | ApprovalRunAttributionKt.decodeApprovalAttribution | NegateConditionals | 174 | b22/i127 | structural | **EQUIVALENT** | +| `a542bbe6db3f` | DefaultApprovalGateway.persistGoverned | NullReturnVals | 265 | b35/i204 | B | **EQUIVALENT** | +| `a9760bea3a92` | ApprovalResumeCoordinator.resume | NegateConditionals | 102 | b76/i533 | A | **KILLED** | +| `c7774df8ccdc` | ApprovalSuspensionCoordinator.compensateStep | VoidMethodCall | 305 | b16/i101 | structural | **EQUIVALENT** | +| `d38ac52f2843` | ApprovalRunAttributionKt.decodeApprovalAttribution | NegateConditionals | 174 | b24/i131 | structural | **EQUIVALENT** | +| `eb21aaed3192` | ApprovalSuspensionCoordinator.persistSuspendedInvocation | NullReturnVals | 284 | b9/i38 | B | **EQUIVALENT** | +| `f44636049288` | DefaultApprovalGateway.persistUngoverned | NullReturnVals | 234 | b29/i161 | B | **EQUIVALENT** | + +## Phase 4 — the one real semantic kill + +`a9760bea3a92` is the `ifnonnull` in `"structured-parse-failed: ${e::class.simpleName ?: "unknown"}"`. The production path already exercised it, but the assertions read `startsWith("structured-parse-failed")` — satisfied both by the authoritative diagnostic and by the mutant's `unknown`. The discriminator was therefore missing, not the coverage. + +The fix is one assertion contract, tightened in place (2 lines, `d3837a58`): `isEqualTo("structured-parse-failed: StructuredOutputException")`. It is about the diagnostic contract, not about PIT: it triggers a real `StructuredOutputException` through the resume path, captures the authoritative uncertain-outcome audit, and pins the class-name component. + +Measurement: candidate `7acbd868adb94658e90ef55d3261d315f6eddda9` — a child of the control throwaway, differing by the test commit alone — BUILD SUCCESSFUL in 923 s. + +| requirement | result | +| --- | --- | +| `a9760bea3a92` | **SURVIVED → KILLED**, killing test named below | +| KILLED regressions | **0** | +| identity loss / gain | 0 / 0 | +| new unexplained timeouts | 0 | +| shared identities | 918 / 918 | + +Killing test: `ApprovalResumeSuspensionContractTest` › *a cancellation resumed into the structured-parse uncertain path is not replaced by the primary failure*, at `resume` line 102. + +## Phase 5 — the eleven equivalence proofs + +**Caller-discard (6 rows, NullReturnVals).** The mutated `areturn` returns the function's Unit value; every call site pops it. The resumed path after each suspend call begins with an explicit `pop`: `compensateStep` pc252, `persistSuspendedInvocation` pc1231, `persistUngoverned` pc880, `persistGoverned` pc1049, `requireExistingAttributionMatches` pc699. The value is never observed, so returning null is unobservable. + +**Catch-handler dominance (2 rows, VoidMethodCall).** `resume` registers `CancellationException → 1088` and `Exception → 1093`, and the mutated `pc1100` executes inside the **1093 (Exception)** handler. `compensateStep` registers `CancellationException → 147` / `Exception → 150`, with `pc155` inside the **150** handler. JVM dispatch order gives the earlier, more specific handler the cancellation, so the helper's only branch (`if (this is CancellationException) throw this`) cannot fire. Removing the call cannot change behaviour. + +**Compiler guard passed on (1 row, VoidMethodCall).** `pc285 aload 7 → pc287 Intrinsics.checkNotNull → pc290 aload 7 → pc293 invokespecial CreateApprovalChallenge(...)`. The guard protects a value that is immediately passed as a non-null Kotlin constructor parameter, whose own parameter check raises the same NPE one instruction later. Same exception type, same observable outcome on any valid path. + +**Successor convergence (2 rows, NegateConditionals).** The mutated conditional is the inlined `any` fast path — `pc186 instanceof Collection; pc189 ifeq` — whose negation routes Collection receivers onto the plain-Iterable loop. Empty input returns `false` on both paths, and non-empty input runs the identical loop, so no observable difference exists. + +Every proof is instruction-level or control-flow-level on this identity. Neighbouring G4 results were used as context only, never as a substitute. + +## Phase 8 — parent accounting + +| | | +| --- | --- | +| G5 parent | 52 | +| G5b TOOLING_LIMITATION | −36 | +| G5c input SURVIVED | 12 | +| G5c KILLED | 1 | +| G5c EQUIVALENT | 11 | +| G5c unresolved | 0 | +| remaining for G5d | **4 — exactly the frozen NO_COVERAGE identities** | + +No widening. P1 mint remains blocked; P2 consumption remains blocked; the final full canonical campaign still runs only after G5d closes. + +## Prohibited changes + +No change to `mutation-baseline.json`, the population-admission ledger, the classification or enrollment ledgers, the mutation-evolution ledger, the mutator set, timeout policy, target-family semantics, mutation ceilings, or verifier/admission semantics. **No production code changed** — no production defect was discovered. The temporary measurement narrowing is evidence machinery only and was never committed to the Epic. + +## Verification + +- frozen parent digest unchanged; admission ledger still empty +- control and candidate campaigns: same base, same narrowing, same analyzer, `measuredCommit` equal to their throwaway commits, 918/918 identities shared +- 12/12 recovered; 12/12 mappings EXACT; 0 UNDETERMINED +- exactly one status movement, 0 KILLED regressions, 0 identity loss/gain, 0 new timeouts +- focused test class green; `spotlessCheck`, `verifyStaticAnalysis`, `verifyChangePolicy -PchangePolicyBase=42d9d9487ccf…` +- exact-head CI is the final authority + +## Limits + +EQUIVALENT here means: on every reachable path, the mutant and the original cannot be distinguished by any observable behaviour — proven at instruction/control-flow level. It does not claim the instruction is unreachable, and it does not claim PIT's TIMED_OUT machinery was involved (no identity in this cohort was a tooling limitation). The four NO_COVERAGE identities are untouched and are G5d's subject. From f19645b8c17778e29ccd2d041ef84f7be0f782f5 Mon Sep 17 00:00:00 2001 From: gionag Date: Wed, 30 Sep 2026 14:46:21 +0200 Subject: [PATCH 3/3] docs(0.7.1g1G5c): fix two custody defects in the SURVIVED manifest 1. reconciliation.movements[0].identity is the full 64-hex canonical identity (was the malformed prefix a9760bea3a92f). 2. The six NullReturnVals rows carry the mutated areturn PCs (161, 100, 244, 341, 267, 54), each re-verified by javap at the census base against the line table, instead of null. Call-site pop PCs remain as supplementary evidence. No disposition changes: 1 KILLED / 11 EQUIVALENT / 0 UNDETERMINED. --- .../TASK-0.7.1g1G5c-SURVIVED-12-MANIFEST.json | 66 +++++++++++++------ .../TASK-0.7.1g1G5c-SURVIVED-ADJUDICATION.md | 2 +- 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-12-MANIFEST.json b/docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-12-MANIFEST.json index 2345458d..c83c47ec 100644 --- a/docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-12-MANIFEST.json +++ b/docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-12-MANIFEST.json @@ -52,9 +52,11 @@ "statusMovements": 1, "movements": [ { - "identity": "a9760bea3a92f", + "identity": "a9760bea3a92a752255a2becee7edb3ffa0957cf0e88cb75a0a11db850dcc747", "from": "SURVIVED", - "to": "KILLED" + "to": "KILLED", + "killingTest": "ApprovalResumeSuspensionContractTest.[method:a cancellation resumed into the structured-parse uncertain path is not replaced by the primary failure()]", + "sourceLine": 102 } ], "killedRegressions": 0, @@ -63,7 +65,8 @@ "identityGain": 0, "recovered": 12, "missing": 0, - "duplicates": 0 + "duplicates": 0, + "movementIdentityNote": "Full 64-hex canonical identities are carried in movement records. An earlier revision of this manifest recorded a malformed prefix (a9760bea3a92f) here; corrected, superseded not erased." }, "mappingDiscipline": { "authority": "MutationIdentity.stableKey(): sha256 over module\u241fclass\u241fmethod\u241fdescriptor\u241fmutator\u241fdescription\u241fblock\u241findex; line deliberately excluded", @@ -168,8 +171,8 @@ "sourceLine": 307, "pitBlock": 17, "pitIndex": 106, - "bytecodePc": null, - "instruction": "areturn of the Unit value at the function's return", + "bytecodePc": 161, + "instruction": "areturn of kotlin/Unit.INSTANCE (preceded by getstatic kotlin/Unit.INSTANCE)", "g5aOriginalMapping": "EXACT", "resolvedExactMapping": "EXACT", "controlStatus": "SURVIVED", @@ -180,7 +183,9 @@ "killingTest": null, "finalStatus": "SURVIVED (structurally equivalent)", "finalDisposition": "EQUIVALENT", - "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table", + "bytecodePcVerifiedBy": "javap at the census base: compensateStep pc161 is areturn, line-table entry 307, preceded by getstatic kotlin/Unit.INSTANCE", + "callSiteDiscardEvidence": "supplementary: the resumed path of every call site pops the result" }, { "identity": "56d3366434a6608d7b5ccd59b6c1377be7324ab2078ec7a09b872153968e4466", @@ -192,8 +197,8 @@ "sourceLine": 205, "pitBlock": 9, "pitIndex": 50, - "bytecodePc": null, - "instruction": "areturn of the Unit value at the function's return", + "bytecodePc": 100, + "instruction": "areturn of kotlin/Unit.INSTANCE (preceded by getstatic kotlin/Unit.INSTANCE)", "g5aOriginalMapping": "EXACT", "resolvedExactMapping": "EXACT", "controlStatus": "SURVIVED", @@ -204,7 +209,9 @@ "killingTest": null, "finalStatus": "SURVIVED (structurally equivalent)", "finalDisposition": "EQUIVALENT", - "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table", + "bytecodePcVerifiedBy": "javap at the census base: requireExistingAttributionMatches pc100 is areturn, line-table entry 205, preceded by getstatic kotlin/Unit.INSTANCE", + "callSiteDiscardEvidence": "supplementary: the resumed path of every call site pops the result" }, { "identity": "6a1ce2f46d2ad5cdb7fb857a56fcf4ca0d3d87ffc3825279121386e04c3f7c88", @@ -216,8 +223,8 @@ "sourceLine": 219, "pitBlock": 26, "pitIndex": 141, - "bytecodePc": null, - "instruction": "areturn of the Unit value at the function's return", + "bytecodePc": 244, + "instruction": "areturn of kotlin/Unit.INSTANCE (preceded by getstatic kotlin/Unit.INSTANCE)", "g5aOriginalMapping": "EXACT", "resolvedExactMapping": "EXACT", "controlStatus": "SURVIVED", @@ -228,7 +235,9 @@ "killingTest": null, "finalStatus": "SURVIVED (structurally equivalent)", "finalDisposition": "EQUIVALENT", - "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table", + "bytecodePcVerifiedBy": "javap at the census base: requireExistingAttributionMatches pc244 is areturn, line-table entry 219, preceded by getstatic kotlin/Unit.INSTANCE", + "callSiteDiscardEvidence": "supplementary: the resumed path of every call site pops the result" }, { "identity": "8e18b4b48968d65f181bd226d6e81d99c6c9abb3427463ae77773eb4c901e658", @@ -264,8 +273,8 @@ "sourceLine": 265, "pitBlock": 35, "pitIndex": 204, - "bytecodePc": null, - "instruction": "areturn of the Unit value at the function's return", + "bytecodePc": 341, + "instruction": "areturn of kotlin/Unit.INSTANCE (preceded by getstatic kotlin/Unit.INSTANCE)", "g5aOriginalMapping": "EXACT", "resolvedExactMapping": "EXACT", "controlStatus": "SURVIVED", @@ -276,7 +285,9 @@ "killingTest": null, "finalStatus": "SURVIVED (structurally equivalent)", "finalDisposition": "EQUIVALENT", - "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table", + "bytecodePcVerifiedBy": "javap at the census base: persistGoverned pc341 is areturn, line-table entry 265, preceded by getstatic kotlin/Unit.INSTANCE", + "callSiteDiscardEvidence": "supplementary: the resumed path of every call site pops the result" }, { "identity": "a9760bea3a92a752255a2becee7edb3ffa0957cf0e88cb75a0a11db850dcc747", @@ -360,8 +371,8 @@ "sourceLine": 284, "pitBlock": 9, "pitIndex": 38, - "bytecodePc": null, - "instruction": "areturn of the Unit value at the function's return", + "bytecodePc": 54, + "instruction": "areturn of kotlin/Unit.INSTANCE (preceded by getstatic kotlin/Unit.INSTANCE)", "g5aOriginalMapping": "EXACT", "resolvedExactMapping": "EXACT", "controlStatus": "SURVIVED", @@ -372,7 +383,9 @@ "killingTest": null, "finalStatus": "SURVIVED (structurally equivalent)", "finalDisposition": "EQUIVALENT", - "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table", + "bytecodePcVerifiedBy": "javap at the census base: persistSuspendedInvocation pc54 is areturn, line-table entry 284, preceded by getstatic kotlin/Unit.INSTANCE", + "callSiteDiscardEvidence": "supplementary: the resumed path of every call site pops the result" }, { "identity": "f4463604928886b61038161dfacada30be5fa9dcd62178ac329b83c4568e3ffd", @@ -384,8 +397,8 @@ "sourceLine": 234, "pitBlock": 29, "pitIndex": 161, - "bytecodePc": null, - "instruction": "areturn of the Unit value at the function's return", + "bytecodePc": 267, + "instruction": "areturn of kotlin/Unit.INSTANCE (preceded by getstatic kotlin/Unit.INSTANCE)", "g5aOriginalMapping": "EXACT", "resolvedExactMapping": "EXACT", "controlStatus": "SURVIVED", @@ -396,7 +409,18 @@ "killingTest": null, "finalStatus": "SURVIVED (structurally equivalent)", "finalDisposition": "EQUIVALENT", - "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table" + "evidenceProvenance": "control campaign 78458d1e @ 42d9d948; candidate campaign 7acbd868 (child of 78458d1e + test d3837a58); javap at the census base with the SMAP-resolved line table", + "bytecodePcVerifiedBy": "javap at the census base: persistUngoverned pc267 is areturn, line-table entry 234, preceded by getstatic kotlin/Unit.INSTANCE", + "callSiteDiscardEvidence": "supplementary: the resumed path of every call site pops the result" + } + ], + "corrections": [ + { + "field": "reconciliation.movements[0].identity and the six NullReturnVals bytecodePc values", + "supersededClaim": "movement identity recorded as the malformed prefix a9760bea3a92f; the six NullReturnVals rows carried bytecodePc=null despite claiming resolvedExactMapping=EXACT", + "correctedClaim": "movement records the full 64-hex canonical identity; the six rows carry the mutated areturn PCs 161, 100, 244, 341, 267, 54, each re-verified by javap at the census base against the line table", + "foundDuring": "owner review of #463 at head 5e275ccc", + "effectOnDispositions": "none \u2014 1 KILLED / 11 EQUIVALENT stands" } ] } \ No newline at end of file diff --git a/docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-ADJUDICATION.md b/docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-ADJUDICATION.md index 6d289ee2..e28a993c 100644 --- a/docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-ADJUDICATION.md +++ b/docs/roadmap/0.7.0/TASK-0.7.1g1G5c-SURVIVED-ADJUDICATION.md @@ -79,7 +79,7 @@ Killing test: `ApprovalResumeSuspensionContractTest` › *a cancellation resumed ## Phase 5 — the eleven equivalence proofs -**Caller-discard (6 rows, NullReturnVals).** The mutated `areturn` returns the function's Unit value; every call site pops it. The resumed path after each suspend call begins with an explicit `pop`: `compensateStep` pc252, `persistSuspendedInvocation` pc1231, `persistUngoverned` pc880, `persistGoverned` pc1049, `requireExistingAttributionMatches` pc699. The value is never observed, so returning null is unobservable. +**Caller-discard (6 rows, NullReturnVals).** The mutated instruction is the function's `areturn`, immediately preceded by `getstatic kotlin/Unit.INSTANCE` — verified at pc161 (`compensateStep`, line 307), pc100 and pc244 (`requireExistingAttributionMatches`, lines 205 and 219), pc341 (`persistGoverned`, line 265), pc267 (`persistUngoverned`, line 234), pc54 (`persistSuspendedInvocation`, line 284). The mutant returns null where Unit was returned; every call site pops it. The resumed path after each suspend call begins with an explicit `pop`: `compensateStep` pc252, `persistSuspendedInvocation` pc1231, `persistUngoverned` pc880, `persistGoverned` pc1049, `requireExistingAttributionMatches` pc699. The value is never observed, so returning null is unobservable. **Catch-handler dominance (2 rows, VoidMethodCall).** `resume` registers `CancellationException → 1088` and `Exception → 1093`, and the mutated `pc1100` executes inside the **1093 (Exception)** handler. `compensateStep` registers `CancellationException → 147` / `Exception → 150`, with `pc155` inside the **150** handler. JVM dispatch order gives the earlier, more specific handler the cancellation, so the helper's only branch (`if (this is CancellationException) throw this`) cannot fire. Removing the call cannot change behaviour.