From d3837a5880eccf9bf23e2fc5593048e0eb06e395 Mon Sep 17 00:00:00 2001 From: gionag Date: Wed, 30 Sep 2026 14:13:29 +0200 Subject: [PATCH 1/5] 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 8a185e80e..140b4183b 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/5] 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 000000000..2345458d7 --- /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 000000000..6d289ee2d --- /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/5] 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 2345458d7..c83c47ec4 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 6d289ee2d..e28a993c8 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. From 16e598d7c7d66957e1e345780fd4ba053a368687 Mon Sep 17 00:00:00 2001 From: gionag Date: Wed, 30 Sep 2026 20:57:15 +0200 Subject: [PATCH 4/5] docs(0.7.1g1G5d): close the final NO_COVERAGE cohort as UNREACHABLE The four frozen NO_COVERAGE identities are all on the suspension protocol of resolveGovernedSuspension() / resolveGovernedIdentity(), neither of which can suspend (0 getCOROUTINE_SUSPENDED, 0 if_acmpne), so the COROUTINE_SUSPENDED exit and the resumed-path throwOnFailure can never execute. 4/4 mapped to exact bytecode PCs; no tests added (tests are permitted only for proven-reachable identities); no production, authority or test changes. --- ...ASK-0.7.1g1G5d-NO-COVERAGE-4-MANIFEST.json | 272 ++++++++++++++++++ ...ASK-0.7.1g1G5d-NO-COVERAGE-REACHABILITY.md | 108 +++++++ 2 files changed, 380 insertions(+) create mode 100644 docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-4-MANIFEST.json create mode 100644 docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-REACHABILITY.md diff --git a/docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-4-MANIFEST.json b/docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-4-MANIFEST.json new file mode 100644 index 000000000..f27cdaa5e --- /dev/null +++ b/docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-4-MANIFEST.json @@ -0,0 +1,272 @@ +{ + "schemaVersion": 1, + "task": "TASK-0.7.1g1G5d", + "parent": "TASK-0.7.1g1G5", + "base": "cd46f176b20ef7e0e0b2b0e251569214dfc90619", + "baseProvenance": "squash merge of #463; branch directly from it; working tree clean", + "cohort": { + "size": 4, + "note": "exactly the four frozen NO_COVERAGE identities; no widening, no substitution", + "mutatorNamingCorrection": "The task brief labels the two 'NRV' identities NonReturningVoidMethodCall. The frozen manifest records them as org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator, description 'replaced return value with null'. The frozen identities are authoritative and unchanged; this is a label discrepancy, not an identity discrepancy." + }, + "startGate": { + "baseMatches": "cd46f176b20ef7e0e0b2b0e251569214dfc90619", + "cleanTree": true, + "fourPresent": true, + "allFourNoCoverage": true, + "noBaselineOnlyTarget": true, + "noSubstitutedTarget": true, + "noSourceCoordinateApproximation": true, + "authoritativeView": "the G5c candidate campaign (7acbd868) whose production+test content is identical to the merged cd46f176 (the merge squashed that test plus docs), in which all four are present and NO_COVERAGE with numberOfTestsRun=0" + }, + "phaseA": { + "method": "each identity mapped by bracketing: pitBlock is monotone in pc within the method (verified True for both methods), and each method has in-method calibration points from the committed G5b/G5c manifests (pc, pitBlock, pitIndex). The target's pitBlock therefore brackets a byte window containing exactly one candidate instruction of the mutated kind.", + "calibrationPoints": { + "suspendToolExecution": [ + [ + 158, + 11, + 74 + ], + [ + 287, + 31, + 168 + ], + [ + 362, + 35, + 206 + ], + [ + 1072, + 109, + 668 + ], + [ + 1420, + 132, + 853 + ], + [ + 1785, + 157, + 1067 + ] + ], + "requestApproval-Atj0Sqo": [ + [ + 159, + 9, + 68 + ], + [ + 304, + 23, + 160 + ], + [ + 457, + 35, + 243 + ], + [ + 618, + 46, + 328 + ], + [ + 799, + 60, + 426 + ] + ] + }, + "windows": { + "suspendToolExecution": [ + { + "pitBlock": 13, + "between": "pc158 (block 11) and pc287 (block 31)", + "candidates": [ + 194 + ], + "unique": true + }, + { + "pitBlock": 12, + "between": "pc158 (block 11) and pc287 (block 31)", + "candidates": [ + 163 + ], + "unique": true + } + ], + "requestApproval-Atj0Sqo": [ + { + "pitBlock": 11, + "between": "pc159 (block 9) and pc304 (block 23)", + "candidates": [ + 204 + ], + "unique": true + }, + { + "pitBlock": 10, + "between": "pc159 (block 9) and pc304 (block 23)", + "candidates": [ + 164 + ], + "unique": true + } + ] + }, + "pitCounterNote": "PIT never reports bytecode offsets, and its block/index counter counts ASM nodes that javap does not expose (a label/line-count reconstruction matched only 4/36 calibration identities). Bracketing is therefore used, and it is validated by in-method monotonicity plus the uniqueness of each candidate window." + }, + "phaseC": { + "classification": "UNREACHABLE (all four)", + "proof": [ + "Each mutated instruction lies on the suspension protocol of one specific call: resolveGovernedSuspension() at source line 145 in suspendToolExecution, and resolveGovernedIdentity(workflowRunId) at source line 82 in requestApproval.", + "Both callees are declared suspend, but neither body contains a suspension point: resolveGovernedSuspension has 50 instructions with 0 getCOROUTINE_SUSPENDED loads and 0 if_acmpne; resolveGovernedIdentity-jFE5hGw has 32 instructions with 0 getCOROUTINE_SUSPENDED and 0 if_acmpne, invoking only Continuation.getContext, GovernedRunScope$Key accessors, GovernedRunIdentity/RunId getters, Intrinsics.areEqual, makeConcatWithConstants and an exception constructor.", + "GovernedRunScope.resolve(context) is an ordinary non-suspend function; currentCoroutineContext()/Continuation.getContext do not suspend.", + "A suspend function can return COROUTINE_SUSPENDED only through the sentinel comparison emitted after a call. With no such comparison and no suspending callee, both resolvers always return their value directly.", + "Therefore in each caller the sentinel test is always false, so the COROUTINE_SUSPENDED exit (pc163, pc164) cannot execute; and the resumed continuation for that call can only be constructed by a real suspension at that call, so the resumed-path throwOnFailure (pc194, pc204) cannot execute.", + "Nothing else branches to those instructions: no branch or switch entry in either method targets pc194 or pc204." + ], + "whyNotToolingLimitation": "No independent evidence shows the instruction executing while PIT fails to attribute coverage. The instructions cannot execute at all.", + "whyNotEquivalent": "Equivalence answers a different question. These mutants never cross the reachability boundary, so equivalence is neither claimed nor needed.", + "whyNoTestAdded": "Tests are required only for identities proven REACHABLE. A test cannot make an unreachable instruction execute without either changing production semantics or fabricating a coroutine state, both forbidden. Adding one would be 'making PIT green' rather than explaining behaviour." + }, + "phaseE": { + "suspendToolExecution": { + "members": [ + "564517b2fdab", + "66c311cf4f0a" + ], + "sameConstruct": "YES \u2014 one compiler-generated suspension: block 12 is the COROUTINE_SUSPENDED exit, block 13 is the resumed-path throwOnFailure, one block apart", + "sameInstruction": "NO", + "dominates": "NO", + "wouldOneTestCoverBoth": "irrelevant \u2014 neither is reachable", + "statusesDiffer": "they do not" + }, + "requestApproval-Atj0Sqo": { + "members": [ + "5a7edac3a982", + "e52f1c1f6570" + ], + "sameConstruct": "YES \u2014 block 10 = exit, block 11 = resumed unwrap", + "sameInstruction": "NO", + "dominates": "NO", + "wouldOneTestCoverBoth": "irrelevant \u2014 neither is reachable", + "statusesDiffer": "they do not" + }, + "crossMethodNote": "Both pairs attach to a suspend-typed resolver that has no suspension point, so both pairs share one root cause. Block/index proximity was not used as evidence of equivalence." + }, + "finalTotals": { + "KILLED": 0, + "EQUIVALENT": 0, + "UNREACHABLE": 4, + "TOOLING_LIMITATION": 0, + "UNDETERMINED": 0 + }, + "parentAccounting": { + "parent": 52, + "settledByG5b": 36, + "settledByG5c": 12, + "settledByG5d": 4, + "remaining": 0 + }, + "identities": [ + { + "identity": "564517b2fdab899eceefac4eb9dbb40f3a60139a5c6f917f5fe7c1b172fc9d67", + "className": "dev.tramai.engine.approval.ApprovalSuspensionCoordinator", + "method": "suspendToolExecution(Ldev/tramai/engine/approval/SuspendToolExecutionRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + "mutator": "org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator", + "description": "removed call to kotlin/ResultKt::throwOnFailure", + "pitBlock": 13, + "pitIndex": 96, + "bytecodePc": 194, + "instruction": "invokestatic kotlin/ResultKt.throwOnFailure", + "suspensionRole": "resumed-path unwrap of the call to resolveGovernedSuspension() (line 145)", + "originalState": "NO_COVERAGE", + "finalState": "UNREACHABLE", + "finalClassification": "UNREACHABLE", + "reachabilityEvidence": [ + "Each mutated instruction lies on the suspension protocol of one specific call: resolveGovernedSuspension() at source line 145 in suspendToolExecution, and resolveGovernedIdentity(workflowRunId) at source line 82 in requestApproval.", + "Both callees are declared suspend, but neither body contains a suspension point: resolveGovernedSuspension has 50 instructions with 0 getCOROUTINE_SUSPENDED loads and 0 if_acmpne; resolveGovernedIdentity-jFE5hGw has 32 instructions with 0 getCOROUTINE_SUSPENDED and 0 if_acmpne, invoking only Continuation.getContext, GovernedRunScope$Key accessors, GovernedRunIdentity/RunId getters, Intrinsics.areEqual, makeConcatWithConstants and an exception constructor.", + "Therefore in each caller the sentinel test is always false, so the COROUTINE_SUSPENDED exit (pc163, pc164) cannot execute; and the resumed continuation for that call can only be constructed by a real suspension at that call, so the resumed-path throwOnFailure (pc194, pc204) cannot execute." + ], + "testAdded": null, + "killingTest": null, + "evidenceProvenance": "javap at the G5d base (classes identical to the measured campaign); PIT row (line/block/index) from the candidate campaign 7acbd868; pitBlock bracketing against in-method calibration points from the committed G5b and G5c manifests" + }, + { + "identity": "66c311cf4f0ae36396880146f9059264308168b0286cdee72b852076560df61e", + "className": "dev.tramai.engine.approval.ApprovalSuspensionCoordinator", + "method": "suspendToolExecution(Ldev/tramai/engine/approval/SuspendToolExecutionRequest;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + "mutator": "org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator", + "description": "replaced return value with null for ApprovalSuspensionCoordinator::suspendToolExecution", + "pitBlock": 12, + "pitIndex": 78, + "bytecodePc": 163, + "instruction": "areturn (aload 20 \u2014 the COROUTINE_SUSPENDED exit)", + "suspensionRole": "suspend exit of the call to resolveGovernedSuspension() (line 145)", + "originalState": "NO_COVERAGE", + "finalState": "UNREACHABLE", + "finalClassification": "UNREACHABLE", + "reachabilityEvidence": [ + "Each mutated instruction lies on the suspension protocol of one specific call: resolveGovernedSuspension() at source line 145 in suspendToolExecution, and resolveGovernedIdentity(workflowRunId) at source line 82 in requestApproval.", + "Both callees are declared suspend, but neither body contains a suspension point: resolveGovernedSuspension has 50 instructions with 0 getCOROUTINE_SUSPENDED loads and 0 if_acmpne; resolveGovernedIdentity-jFE5hGw has 32 instructions with 0 getCOROUTINE_SUSPENDED and 0 if_acmpne, invoking only Continuation.getContext, GovernedRunScope$Key accessors, GovernedRunIdentity/RunId getters, Intrinsics.areEqual, makeConcatWithConstants and an exception constructor.", + "Therefore in each caller the sentinel test is always false, so the COROUTINE_SUSPENDED exit (pc163, pc164) cannot execute; and the resumed continuation for that call can only be constructed by a real suspension at that call, so the resumed-path throwOnFailure (pc194, pc204) cannot execute." + ], + "testAdded": null, + "killingTest": null, + "evidenceProvenance": "javap at the G5d base (classes identical to the measured campaign); PIT row (line/block/index) from the candidate campaign 7acbd868; pitBlock bracketing against in-method calibration points from the committed G5b and G5c manifests" + }, + { + "identity": "5a7edac3a982221ce692e032184362a1db8efc49292d9ea0b5716824303ecef1", + "className": "dev.tramai.engine.approval.DefaultApprovalGateway", + "method": "requestApproval-Atj0Sqo(Ljava/lang/String;Ldev/tramai/core/approval/gateway/ApprovalRecommendation;Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + "mutator": "org.pitest.mutationtest.engine.gregor.mutators.VoidMethodCallMutator", + "description": "removed call to kotlin/ResultKt::throwOnFailure", + "pitBlock": 11, + "pitIndex": 92, + "bytecodePc": 204, + "instruction": "invokestatic kotlin/ResultKt.throwOnFailure", + "suspensionRole": "resumed-path unwrap of the call to resolveGovernedIdentity(workflowRunId) (line 82)", + "originalState": "NO_COVERAGE", + "finalState": "UNREACHABLE", + "finalClassification": "UNREACHABLE", + "reachabilityEvidence": [ + "Each mutated instruction lies on the suspension protocol of one specific call: resolveGovernedSuspension() at source line 145 in suspendToolExecution, and resolveGovernedIdentity(workflowRunId) at source line 82 in requestApproval.", + "Both callees are declared suspend, but neither body contains a suspension point: resolveGovernedSuspension has 50 instructions with 0 getCOROUTINE_SUSPENDED loads and 0 if_acmpne; resolveGovernedIdentity-jFE5hGw has 32 instructions with 0 getCOROUTINE_SUSPENDED and 0 if_acmpne, invoking only Continuation.getContext, GovernedRunScope$Key accessors, GovernedRunIdentity/RunId getters, Intrinsics.areEqual, makeConcatWithConstants and an exception constructor.", + "Therefore in each caller the sentinel test is always false, so the COROUTINE_SUSPENDED exit (pc163, pc164) cannot execute; and the resumed continuation for that call can only be constructed by a real suspension at that call, so the resumed-path throwOnFailure (pc194, pc204) cannot execute." + ], + "testAdded": null, + "killingTest": null, + "evidenceProvenance": "javap at the G5d base (classes identical to the measured campaign); PIT row (line/block/index) from the candidate campaign 7acbd868; pitBlock bracketing against in-method calibration points from the committed G5b and G5c manifests" + }, + { + "identity": "e52f1c1f657020d5f63b247fbc7fd432c886258cf5059a5e2a9a5fdc4981bc32", + "className": "dev.tramai.engine.approval.DefaultApprovalGateway", + "method": "requestApproval-Atj0Sqo(Ljava/lang/String;Ldev/tramai/core/approval/gateway/ApprovalRecommendation;Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;", + "mutator": "org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator", + "description": "replaced return value with null for DefaultApprovalGateway::requestApproval-Atj0Sqo", + "pitBlock": 10, + "pitIndex": 72, + "bytecodePc": 164, + "instruction": "areturn (aload 12 \u2014 the COROUTINE_SUSPENDED exit)", + "suspensionRole": "suspend exit of the call to resolveGovernedIdentity(workflowRunId) (line 82)", + "originalState": "NO_COVERAGE", + "finalState": "UNREACHABLE", + "finalClassification": "UNREACHABLE", + "reachabilityEvidence": [ + "Each mutated instruction lies on the suspension protocol of one specific call: resolveGovernedSuspension() at source line 145 in suspendToolExecution, and resolveGovernedIdentity(workflowRunId) at source line 82 in requestApproval.", + "Both callees are declared suspend, but neither body contains a suspension point: resolveGovernedSuspension has 50 instructions with 0 getCOROUTINE_SUSPENDED loads and 0 if_acmpne; resolveGovernedIdentity-jFE5hGw has 32 instructions with 0 getCOROUTINE_SUSPENDED and 0 if_acmpne, invoking only Continuation.getContext, GovernedRunScope$Key accessors, GovernedRunIdentity/RunId getters, Intrinsics.areEqual, makeConcatWithConstants and an exception constructor.", + "Therefore in each caller the sentinel test is always false, so the COROUTINE_SUSPENDED exit (pc163, pc164) cannot execute; and the resumed continuation for that call can only be constructed by a real suspension at that call, so the resumed-path throwOnFailure (pc194, pc204) cannot execute." + ], + "testAdded": null, + "killingTest": null, + "evidenceProvenance": "javap at the G5d base (classes identical to the measured campaign); PIT row (line/block/index) from the candidate campaign 7acbd868; pitBlock bracketing against in-method calibration points from the committed G5b and G5c manifests" + } + ] +} \ No newline at end of file diff --git a/docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-REACHABILITY.md b/docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-REACHABILITY.md new file mode 100644 index 000000000..f3659ed15 --- /dev/null +++ b/docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-REACHABILITY.md @@ -0,0 +1,108 @@ +# TASK-0.7.1g1G5d — Exact NO_COVERAGE reachability closure + +Parent: **TASK-0.7.1g1G5**. Scope: exactly the **four frozen NO_COVERAGE identities**. No widening, no substitution, no production change. +Base: **`cd46f176b20ef7e0e0b2b0e251569214dfc90619`** — the squash merge of #463, branched directly from it, clean tree. + +**G5D COMPLETE — FINAL G5 NO_COVERAGE COHORT CLOSED.** (subject to the regression campaign recorded below) + +## Baseline and start gate + +| condition | result | +| --- | --- | +| HEAD == `cd46f176b20e…` | yes, worktree branched directly from that SHA | +| clean working tree | yes | +| four canonical identities exist | 4/4 | +| all four still NO_COVERAGE | 4/4, `numberOfTestsRun = 0` | +| baseline-only target / substituted target | none | +| source-coordinate approximation as the same mutant | none | + +The authoritative view is the G5c candidate campaign (`7acbd868`), whose production+test content is identical to the merged `cd46f176` (the merge squashed exactly that test plus docs). In it all four are present and NO_COVERAGE. + +**Mutator naming:** the task brief labels the two "NRV" identities `NonReturningVoidMethodCall`. The frozen manifest records `org.pitest.mutationtest.engine.gregor.mutators.returns.NullReturnValsMutator`, description *"replaced return value with null"*. The frozen identities are authoritative and unchanged — a label discrepancy, not an identity discrepancy. + +## Identity table + +| identity | owner | mutator | PIT block/index | PC | mutated instruction | state | +| --- | --- | --- | --- | --- | --- | --- | +| `564517b2fdab` | ApprovalSuspensionCoordinator.suspendToolExecution | VoidMethodCallMutator | 13/96 | **pc194** | invokestatic kotlin/ResultKt.throwOnFailure | NO_COVERAGE → **UNREACHABLE** | +| `66c311cf4f0a` | ApprovalSuspensionCoordinator.suspendToolExecution | NullReturnValsMutator | 12/78 | **pc163** | areturn (aload 20 — the COROUTINE_SUSPENDED exit) | NO_COVERAGE → **UNREACHABLE** | +| `5a7edac3a982` | DefaultApprovalGateway.requestApproval-Atj0Sqo | VoidMethodCallMutator | 11/92 | **pc204** | invokestatic kotlin/ResultKt.throwOnFailure | NO_COVERAGE → **UNREACHABLE** | +| `e52f1c1f6570` | DefaultApprovalGateway.requestApproval-Atj0Sqo | NullReturnValsMutator | 10/72 | **pc164** | areturn (aload 12 — the COROUTINE_SUSPENDED exit) | NO_COVERAGE → **UNREACHABLE** | + +## Phase A — bytecode-exact mapping + +PIT never reports bytecode offsets, and its block/index counter includes ASM node kinds that `javap` does not expose — a label-and-line-count reconstruction of that counter matched only 4 of 36 calibration identities, so it was abandoned rather than tuned until it fit. + +Instead each identity is bracketed. `pitBlock` is **monotone in pc within a method** (verified true for both methods), and each method carries in-method calibration points from the committed G5b/G5c manifests with both a known pc and known PIT coordinates: + +- `suspendToolExecution`: (158, 11, 74) · (287, 31, 168) · (362, 35, 206) · (1072, 109, 668) · (1420, 132, 853) · (1785, 157, 1067) +- `requestApproval-Atj0Sqo`: (159, 9, 68) · (304, 23, 160) · (457, 35, 243) · (618, 46, 328) · (799, 60, 426) + +Each target's block therefore brackets a pc window, and exactly one candidate instruction of the mutated kind lies inside: + +| identity | window | candidates in window | selected | +| --- | --- | --- | --- | +| `564517b2fdab` (block 13) | pc158 … pc287 | `throwOnFailure` at 194 | **pc194** | +| `66c311cf4f0a` (block 12) | pc158 … pc287 | `areturn` at 163 | **pc163** | +| `5a7edac3a982` (block 11) | pc159 … pc304 | `throwOnFailure` at 204 | **pc204** | +| `e52f1c1f6570` (block 10) | pc159 … pc304 | `areturn` at 164 | **pc164** | + +Both `areturn` sites are preceded by a load of a local holding `COROUTINE_SUSPENDED` — they are the suspension exits; both `throwOnFailure` sites are the resumed-path unwraps of the same call, one block later. The mapping is additional to, and independent of, the source line, which is useless here: **line 142 is the function header of `suspendToolExecution` and line 73 the header of `requestApproval`**, so every state-machine instruction inherits it. + +## Reachability evidence — all four UNREACHABLE + +Each mutated instruction is on the suspension protocol of one specific call: `resolveGovernedSuspension()` (source line 145) in `suspendToolExecution`, and `resolveGovernedIdentity(workflowRunId)` (source line 82) in `requestApproval`. + +**Neither callee can suspend.** + +- `resolveGovernedSuspension`: 50 instructions, **0 `getCOROUTINE_SUSPENDED` loads, 0 `if_acmpne`** — no sentinel comparison at all. +- `resolveGovernedIdentity-jFE5hGw`: 32 instructions, **0 `getCOROUTINE_SUSPENDED`, 0 `if_acmpne`**; its invokes are only `Continuation.getContext`, `GovernedRunScope$Key` accessors, `GovernedRunIdentity`/`RunId` getters, `Intrinsics.areEqual`, `makeConcatWithConstants` and an exception constructor. +- `GovernedRunScope.resolve(context)` is an ordinary **non-suspend** function, and `currentCoroutineContext()`/`Continuation.getContext` do not suspend. + +A suspend function can return `COROUTINE_SUSPENDED` only through the sentinel comparison emitted after a call. With no such comparison and no suspending callee, both resolvers always return their value directly. Therefore: + +1. in each caller the sentinel test is always false, so the `COROUTINE_SUSPENDED` exit (pc163, pc164) **cannot execute** — the NullReturnVals identity; +2. the resumed continuation for that call can only be constructed by a real suspension at that call, so the resumed-path `throwOnFailure` (pc194, pc204) **cannot execute** — the VoidMethodCall identity; +3. nothing else reaches them: **no branch or switch entry in either method targets pc194 or pc204**. + +That is control-flow dominance plus callee analysis, not "I could not find a test". No legal production execution reaches any of the four. + +**Why not TOOLING_LIMITATION:** there is no independent evidence that the instruction executes while PIT fails to attribute coverage. The instructions cannot execute at all. +**Why not EQUIVALENT:** equivalence answers a different question, and these mutants never cross the reachability boundary. It is neither claimed nor needed. + +## Test evidence + +**No tests were added, and that is the correct outcome.** Tests are permitted only for identities proven REACHABLE. Making these instructions execute would require either changing production semantics (forbidden) or fabricating a coroutine state the runtime cannot produce. A test whose only purpose would be to move PIT's coverage counter is exactly what this task forbids. + +## Phase E — pair analysis + +| pair | same compiler-generated construct | same instruction | one dominates the other | +| --- | --- | --- | --- | +| `564517b2fdab` / `66c311cf4f0a` (`suspendToolExecution`) | **YES** — block 12 is the `COROUTINE_SUSPENDED` exit, block 13 the resumed-path `throwOnFailure`, one block apart | NO | NO | +| `5a7edac3a982` / `e52f1c1f6570` (`requestApproval-Atj0Sqo`) | **YES** — block 10 the exit, block 11 the resumed unwrap | NO | NO | + +Both pairs attach to a suspend-typed resolver with no suspension point, so they share one root cause across both methods. Whether one legitimate test would cover both is moot: neither member is reachable. Block/index adjacency was not treated as evidence of equivalence. + +## Final classification + +| state | count | +| --- | --- | +| KILLED | 0 | +| EQUIVALENT | 0 | +| **UNREACHABLE** | **4** | +| TOOLING_LIMITATION | 0 | +| UNDETERMINED | **0** | + +Parent accounting: 52 = 36 (G5b TOOLING_LIMITATION) + 12 (G5c: 1 KILLED, 11 EQUIVALENT) + 4 (G5d UNREACHABLE). **G5 remainder: 0.** + +## Diff scope + +Tests: none. Production: none. Documentation: this report and the four-identity manifest. The measurement narrowing is evidence machinery, never committed. + +## Regression gate + +The identity-exact campaign runs from a fresh worktree at `cd46f176b20e` with the proven family-only narrowing (53 deletions, `approval` block byte-identical). Results are appended to this report and to the manifest when it completes: 4/4 accounted, 0 identity loss, 0 gain/substitution, 0 new timeouts, 0 regressions of previously KILLED identities, no widening. + +## Limits + +`UNREACHABLE` here rests on the callees being unable to suspend (no sentinel comparison, no suspending callee) plus the absence of any other branch into the resumed block. It is a statement about this compiled artifact at this base: if either resolver ever gains a suspension point — or if a call site acquires a genuine suspension — these instructions become live and these identities must be re-adjudicated rather than inherited. From 158e220c821fad61d87fc2c98d0c06ca01d86ee2 Mon Sep 17 00:00:00 2001 From: gionag Date: Wed, 30 Sep 2026 21:14:56 +0200 Subject: [PATCH 5/5] docs(0.7.1g1G5d): record the regression gate result Identity-exact campaign at cd46f176 (throwaway 56364ae3, family-only narrowing): 918/918 identities, 0 status movements, 0 KILLED regressions, 0 new timeouts, all four targets present and NO_COVERAGE, no widening. --- ...ASK-0.7.1g1G5d-NO-COVERAGE-4-MANIFEST.json | 33 ++++++++++++++++++- ...ASK-0.7.1g1G5d-NO-COVERAGE-REACHABILITY.md | 18 ++++++++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-4-MANIFEST.json b/docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-4-MANIFEST.json index f27cdaa5e..13a9bef26 100644 --- a/docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-4-MANIFEST.json +++ b/docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-4-MANIFEST.json @@ -268,5 +268,36 @@ "killingTest": null, "evidenceProvenance": "javap at the G5d base (classes identical to the measured campaign); PIT row (line/block/index) from the candidate campaign 7acbd868; pitBlock bracketing against in-method calibration points from the committed G5b and G5c manifests" } - ] + ], + "regressionCampaign": { + "campaign": { + "throwaway": "56364ae3970dec4b6edd7e1507b98a9f0d2fc5f1", + "base": "cd46f176b20ef7e0e0b2b0e251569214dfc90619", + "buildResult": "BUILD SUCCESSFUL", + "durationSeconds": 1033, + "population": 918, + "statuses": { + "KILLED": 662, + "NO_COVERAGE": 62, + "SURVIVED": 132, + "TIMED_OUT": 62 + }, + "configDiff": "family-list narrowing only: 53 deletions, approval block byte-identical" + }, + "reference": { + "campaign": "G5c candidate 7acbd868", + "note": "identical production+test content to the G5d base" + }, + "sharedIdentities": 918, + "g5dOnly": 0, + "referenceOnly": 0, + "statusMovements": 0, + "previouslyKilledRegressions": 0, + "newTimeouts": 0, + "cohort": { + "allFourPresent": true, + "allFourNoCoverage": true, + "widening": false + } + } } \ No newline at end of file diff --git a/docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-REACHABILITY.md b/docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-REACHABILITY.md index f3659ed15..11c8b0723 100644 --- a/docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-REACHABILITY.md +++ b/docs/roadmap/0.7.0/TASK-0.7.1g1G5d-NO-COVERAGE-REACHABILITY.md @@ -99,9 +99,23 @@ Parent accounting: 52 = 36 (G5b TOOLING_LIMITATION) + 12 (G5c: 1 KILLED, 11 EQUI Tests: none. Production: none. Documentation: this report and the four-identity manifest. The measurement narrowing is evidence machinery, never committed. -## Regression gate +## Regression gate — PASSED -The identity-exact campaign runs from a fresh worktree at `cd46f176b20e` with the proven family-only narrowing (53 deletions, `approval` block byte-identical). Results are appended to this report and to the manifest when it completes: 4/4 accounted, 0 identity loss, 0 gain/substitution, 0 new timeouts, 0 regressions of previously KILLED identities, no widening. +Identity-exact campaign from a fresh worktree at `cd46f176b20ef7e0e0b2b0e251569214dfc90619`, throwaway `56364ae3970dec4b6edd7e1507b98a9f0d2fc5f1` (family-list narrowing only: 53 deletions, `approval` block byte-identical), BUILD SUCCESSFUL in 17m13s, `measuredCommit` equal to the throwaway commit. + +| requirement | result | +| --- | --- | +| population | 918 (662 KILLED / 132 SURVIVED / 62 NO_COVERAGE / 62 TIMED_OUT) | +| 4/4 frozen identities accounted for | yes — all four present, all four NO_COVERAGE | +| identity loss | 0 | +| identity gain / substitution | 0 | +| shared identities vs the reference campaign | 918 / 918 | +| status movements | 0 | +| new timeouts | 0 | +| regressions of previously KILLED identities | 0 | +| widening beyond the four-target cohort | none (population size unchanged) | + +The reference is the G5c candidate campaign (`7acbd868`), whose production+test content is identical to this base; the two campaigns agree exactly — identity for identity, status for status. ## Limits