Skip to content

πŸ›πŸ§‘β€πŸ’» - Bugbot false positive KotlinWasm js parameters are valid generated JavaScript bindingsΒ #764

Closed

Description

@efraespada

Is there an existing issue for this?

  • I have searched the existing issues. The all-state search for Kotlin/Wasm js parameters returned no matching report.

Which actions are affected?

Pull Request, Commits (Bugbot review).

Which platforms are affected?

macOS; the reported problem concerns Kotlin/Wasm language/interop analysis, not a claimed cross-platform runtime failure.

Description

Bugbot reports a medium correctness finding with99% confidence that parameters of package-level Kotlin/Wasm = js("...") functions are unbound JavaScript globals and cause ReferenceError. The Kotlin/Wasm compiler deliberately emits these parameters as formal JavaScript arguments. The finding contradicts both the generated import module and successful execution of the exact affected browser tests.

Consumer: vaultstadio PR123, analyzed head a23287cfa84b8db5845023e736eb304cdd41b7f7.
Finding: review comment4403525462, review5686465684, Browser121DirectoryRegressionTest:65:unbound-js-fixture-parameter, fingerprint fp-154e0e38.

Expected: distinguish valid Kotlin/Wasm package-level = js(...) parameter bridges and their JavaScript closures from genuinely unbound identifiers. Actual: the review says the event handler cannot access empty and extends that claim to size, count, and file in two additional fixtures, recommending unnecessary global state/argument bridges.

The containing JavaScript function receives those arguments, and the installed event handler closes over them normally. The fixtures already use the explicit compiler-supported argument bridge; introducing globals to satisfy this finding would add avoidable mutable state.

Reproducing the issue

  1. Use Kotlin2.4.20 and the three unchanged Wasm fixture classes at the analyzed head:
  2. Run the supported browser task with Java17, the repository SDK prerequisites and Chrome155:
cd frontend
./gradlew --init-script ../scripts/verification/model.gradle :composeApp:wasmJsBrowserTest   --tests '*Browser121DirectoryRegressionTest*'   --tests '*Browser121FolderBudgetTest*'   --tests '*Browser121MetadataTest*'
  1. Observe15 tests,0 failures,0 errors,0 skipped:4 directory/File/FileReader cases,3 actual32MiB boundary cases,8 metadata cases. The byte-bound cases compare every actual payload byte, not just a mocked return. This targeted task actually executed after the finding; it was not an UP-TO-DATE result.
  2. Inspect composeApp/build/compileSync/wasmJs/test/testDevelopmentExecutable/kotlin/frontend-composeApp-test.import-object.mjs. The actual generated entries have formal parameters:
// Actual emitted signatures; bodies abbreviated here for readability.
'com.vaultstadio.app.platform.installDirectoryFixture' : (empty) => { /* ... */ },
'com.vaultstadio.app.platform.installBudgetFiles' : (size, count) => { /* ... */ },
'com.vaultstadio.app.platform.fileWithReportedSize' : (size) => (function(){ /* ... */ })(),
'com.vaultstadio.app.platform.changeReportedSize' : (file, size) => { /* ... */ },

The directory bridge's emitted lines6940–6952 contain the (empty) argument and the nested input-click handler that uses it. The other emitted bridge signatures are at lines6989,7009,7011. These are generated locations for this exact local build, not stable source line promises.

  1. Compare with the official Kotlin/Wasm functions-with-JavaScript-code contract: the compiler places the snippet in a generated function and imports it into WebAssembly; the documentation demonstrates function parameters used inside js() snippets.

copilot Version

vypdev/copilot@v3 as configured in the consumer Commit/Pull Request workflows when review5686465684 analyzed a23287c. Review timestamp2026-10-28T16:53:00Z. I am reporting the verified configured major reference and observed review identity; no unverified patch release or current moving-tag SHA is assumed.

Relevant Log Output

Targeted exact-source run a23287c:
:composeApp:wasmJsBrowserTest executed
15 tests, 0 failures, 0 errors, 0 skipped
8.484s command wall time

Generated module SHA256:
5f382b748d144928aaac6371b67e82f4f2119e4e41b02a176d08cbffd37600c0

Original targeted proof ZIP SHA256:
f64696ff46d1c0fcb34f21d1464b5ed3aca41851313e451a5cdb3612f345fc73

The same analyzed head's complete CI40729907715 also succeeds; all5 original artifact ZIP digests/CRCs,1,194 saved XML reports and their exact source tree have now been independently checked as well. The earlier source-equivalent CI40725080774 independently has6,569 product executions (3,388backend,1,635desktop,1,546Wasm),0 failures/errors/skips; its5 original artifact digests/CRCs and1,194 original XML reports were independently checked. We preserve raw source-bound commands, compiler module/Wasm files, XML and receipts outside the repository; no fixture credentials or unrelated local data are included here.

Additional context and comments

This report concerns the interop finding only. The same review's unrelated copy/platform-label observations are being handled independently in the consumer. We are retaining the valid parameterized fixtures and requesting a language-aware reassessment rather than changing correct code to match the false premise.

Suggested regression coverage for Copilot: accept parameterized package-level Kotlin/Wasm = js(...) functions, including parameters captured by nested JavaScript callbacks and JsAny/File parameters; retain detection for genuinely missing identifiers without treating every js() string as global-only code. Consider reconciling a high-confidence runtime-failure claim against available exact-source compiler output and test evidence.

Activity

  1. added
    bugSomething isn't working
    bugfixSomething isn't working
    priority: highCritical issue, needs immediate attention.
    on Oct 28, 2026
  2. added theissue type on Oct 28, 2026
  3. moved this to Todo in vypdevon Oct 28, 2026
  4. changed the title [-]Bugbot false positive: Kotlin/Wasm js() parameters are valid generated JavaScript bindings[/-] [+]πŸ› - Bugbot false positive KotlinWasm js parameters are valid generated JavaScript bindings[/+] on Oct 28, 2026
  5. vypbot commented on Oct 28, 2026

    @vypbot
    Contributor

    Hi! I’m @vypbot, the Copilot assistant for this repository.

    I can answer questions, explain the codebase, propose implementation and test plans, review issues and pull requests for potential bugs or security problems, and help authorized maintainers apply changes.

    Try /copilot help to see the available commands, or mention @vypbot with your question.

  6. moved this from Todo to In Progress in vypdevon Oct 29, 2026
  7. added
    branchedIndicates that a branch has been created for this issue.
    on Oct 29, 2026
  8. changed the title [-]πŸ› - Bugbot false positive KotlinWasm js parameters are valid generated JavaScript bindings[/-] [+]πŸ›πŸ§‘β€πŸ’» - Bugbot false positive KotlinWasm js parameters are valid generated JavaScript bindings[/+] on Oct 29, 2026
  9. 1 remaining item

  10. vypbot commented on Oct 29, 2026

    @vypbot
    Contributor

    Implementation plan

    Current status: Ready to start. No action is required from maintainers before implementation.

    1. Inspect the JavaScript interop analysis
      • Trace how package-level Kotlin/Wasm js("...") functions and their parameters are parsed and checked.
      • Review repository documentation and conventions relevant to the analyzer and its tests.
    2. Model generated function scope
      • Recognize declared parameters as bindings within the generated JavaScript function, including inside nested callbacks.
      • Handle supported parameter types such as JsAny and File without treating all js() identifiers as globals.
    3. Add regression coverage
      • Cover parameterized bridges, callback closures, and genuinely missing identifiers.
      • Include cases corresponding to the directory, file-budget, and metadata fixtures described in the issue.
    4. Implement and document the correction
      • Update the finding logic and any diagnostic guidance to distinguish bound parameters from unbound identifiers.
      • Document the supported Kotlin/Wasm parameter behavior and relevant analyzer limitation.
    5. Verify the change
      • Run the focused analyzer tests and applicable repository checks.
      • Confirm the regression cases no longer report bound parameters while missing identifiers remain detectable.

    Acceptance: Focused tests show no unbound-identifier finding for declared parameters used in Kotlin/Wasm js() functions or nested callbacks, and still report a genuinely missing identifier.

    Need something else? Mention the bot with a question or use /copilot help.

  11. added
    size: XLIndicates that the issue or task is extra large in scope and complexity.
    70%Progress: 70%
    and removed on Oct 29, 2026
  12. vypbot commented on Oct 29, 2026

    @vypbot
    Contributor

    Issue closed β€” historical progress

    Current status: closed as completed.

    The last estimate is retained below as history. Closure does not certify a new percentage, tests, or branch alignment.

    Action required: none for this closed issue. If work continues, reopen the issue; a fresh assessment can update this same card.

    Last assessment before closure (historical)

    Progress: 68% β€” in progress

    > Current status: [R1] Expected: distinguish valid Kotlin/Wasm package-level = js(...) parameter bridges and their JavaScript closures from genuinely unbound identifiers. Actual: the review says the event handler cannot access empty and extends that claim to size, count, and file in two additional fixtures, recommending unnecessary global state/argument bridges. β€” The added guidance explicitly distinguishes declared Kotlin/Wasm parameters and callback captures from genuinely unbound identifiers.
    [R2] "Trace how package-level Kotlin/Wasm js("...") functions and their parameters are parsed and checked.", β€” The prompt adds Kotlin/Wasm binding guidance, but the comparison shows no trace or implementation of an analyzer parser or checker.
    [R3] "Review repository documentation and conventions relevant to the analyzer and its tests." β€” Documentation updates describe the Kotlin/Wasm interop contract, evidence limits, and re-review guidance.
    [R4] "Recognize declared parameters as bindings within the generated JavaScript function, including inside nested callbacks.", β€” Guidance and synthetic corpus cases cover declared parameters as generated JavaScript formals, including nested callback captures.
    [R5] "Handle supported parameter types such as JsAny and File without treating all js() identifiers as globals." β€” Corpus cases cover JsAny and file-related parameters, and the shared guidance says not to treat every js() identifier as global.
    [R6] "Cover parameterized
    [untrusted content truncated]

    Next: [R2] "Trace how package-level Kotlin/Wasm js("...") functions and their parameters are parsed and checked.", β€” Clarify whether this requirement is satisfied by review guidance alone; no analyzer parsing or checking changes appear in the comparison.
    [R10] "Run the focused analyzer tests and applicable repository checks.", β€” Provide execution evidence for the focused analyzer tests and applicable repository checks; generated metadata and documentation statements do not establish that they ran.
    [R11] "Confirm the regression cases no longer report bound parameters while missing identifiers remain detectable." β€” Provide execution evidence that the regression cases pass with bound parameters suppressed and missing identifiers retained.
    [R12] "acceptance": "Focused tests show no unbound-identifier finding for declared parameters used in Kotlin/Wasm js() functions or nested callbacks, and still report a genuinely missing identifier." β€” Provide execution evidence that focused tests show no finding for declared parameters or callback captures and still report a genuinely missing identifier.

  13. vypbot commented on Oct 29, 2026

    @vypbot
    Contributor

    Issue closed: synchronization recommendation retired

    No branch synchronization is required for this closed issue.

    The previous recommendation is historical. Issue closure does not certify that the branches are synchronized.

  14. moved this from In Progress to Done in vypdevon Oct 29, 2026
  15. added
    100%Progress: 100%
    and removed
    in-progressStart work on an admitted issue.
    state:workingWork can proceed on the verified branch or without a branch.
    on Oct 29, 2026
  16. efraespada commented on Oct 29, 2026

    @efraespada
    MemberAuthor

    Post-merge acceptance evidence for #764, on the unchanged reviewed source 2271a6a8e2326a26d2d424eace628eb51b53fd00 (merged into develop by #778, merge a3ce74c7c5e901d33bfad62915e0bd79161103a8).

    The full CI run passed 773 suites / 14,195 tests, with 35 platform skips and all coverage budgets passing (98.03% lines, 97.24% statements, 97.92% functions, 94.90% branches). Platform verification passed Linux, macOS and Windows; the isolated Windows retry passed without changing source or thresholds. Bugbot's exact-head review is complete with all seven finding-state counts zero.

    An additional actual product-runtime benchmark now verifies the six fixed kt-wasm-* cases from the committed corpus, using the built bugbot-benchmark command, Codex CLI 0.164.0-alpha.11.1, openai/gpt-6-luna, medium effort. This is an observed model run, separate from checked-in reference predictions. Inputs, verdicts and default thresholds were unchanged; expected verdicts are excluded by the production benchmark prompt renderer.

    Case Observed findings
    Declared Boolean captured by callback 0
    Declared size/count parameters 0
    JsAny metadata parameter and size closure 0
    Unavailable target/compiler contract 0
    Genuinely absent direct identifier 1, correct file and line 2
    Genuinely absent callback identifier 1, correct file and line 3

    The evaluator exits 0: precision/recall/F1/location/severity/category = 1.0, false positives = 0, false negatives = 0, mean line distance = 0, confidence Brier score = 0.0164; no violations or missing cases.

    Architecture clarification for the generated plan/progress: the existing review path is buildBugbotPrompt -> getBugbotPrompt -> the findings-agent port. This component has no repository-owned Kotlin syntax parser to amend. The correction belongs in the shared review instruction and paired benchmark scenarios. The actual runtime observations above establish the requested bound-parameter/missing-identifier behavior for this controlled sample. This is not Kotlin compiler/browser execution, a baseline comparison, statistical improvement evidence or a guarantee of future model accuracy.

    Reproduction after selecting the six committed kt-wasm-* cases into /tmp/copilot-764-live-corpus.json:

    node build/cli/index.js bugbot-benchmark --corpus /tmp/copilot-764-live-corpus.json --predictions /tmp/copilot-764-live-predictions.json --agent-provider codex --agent-model-provider openai --agent-model gpt-6-luna --agent-effort medium
    node build/cli/index.js bugbot-eval --corpus /tmp/copilot-764-live-corpus.json --predictions /tmp/copilot-764-live-predictions.json --output json

    SHA256: selected corpus baf71e228a1981de9a325d686b6bdb68b8e89b73ba2bc8974b990e9ba1636f1a; actual predictions 90ba949740bb25ccbe8cd126f06284b589aeb7082ba62d86a59862971d1591dc.

    Actual raw predictions (all six cases)
    {
      "schemaVersion": 1,
      "predictions": {
        "kt-wasm-parameter-closure": [],
        "kt-wasm-size-count-parameters": [],
        "kt-wasm-object-parameter": [],
        "kt-wasm-binding-evidence-unavailable": [],
        "kt-wasm-missing-direct-identifier": [
          {
            "id": "fixtures/WasmBindings.kt:2:undefined-count",
            "title": "Undefined `count` in generated JavaScript",
            "description": "The bridge declares only `size`, but its JavaScript body uses `count` as the array length. Unless a `count` binding is available in the JavaScript scope, calling `installBudget` raises a `ReferenceError` instead of constructing the files.",
            "file": "fixtures/WasmBindings.kt",
            "line": 2,
            "endLine": 2,
            "severity": "medium",
            "confidence": 0.82,
            "category": "correctness",
            "evidence": "The supplied function signature is `installBudget(size: Int)`, while the JavaScript body references `{length: count}`. The shown green job tested the JVM target, so it does not establish that this Wasm bridge works.",
            "suggestion": "Provide `count` as a parameter or define an appropriate binding in the JavaScript scope.",
            "symbol": "installBudget",
            "codeSnippet": "Array.from({length: count}, () => new Uint8Array(size))",
            "fingerprint": "fp-68e4e1d3",
            "semanticFingerprint": "sf-1a97f11a"
          }
        ],
        "kt-wasm-missing-callback-identifier": [
          {
            "id": "fixtures/WasmBindings.kt:3:unbound-empty-callback-identifier",
            "title": "Callback reads an unbound identifier",
            "description": "The installed callback evaluates `empty`, but the bridge exposes only `selected` as a JavaScript formal and the supplied scenario states that no `empty` binding or global exists. Invoking the callback therefore raises a `ReferenceError` instead of returning a byte array.",
            "file": "fixtures/WasmBindings.kt",
            "line": 3,
            "endLine": 3,
            "severity": "medium",
            "confidence": 0.98,
            "category": "correctness",
            "evidence": "`globalThis.onSelection = () => empty ? new Uint8Array(0) : new Uint8Array([1]);` references `empty`; the supplied scenario says the generated import has only `(selected)` and no `empty` binding/global exists.",
            "suggestion": "Bind the intended condition in the bridge or use the existing `selected` parameter if that is the intended condition.",
            "symbol": "installDirectory",
            "codeSnippet": "globalThis.onSelection = () => empty ? new Uint8Array(0) : new Uint8Array([1]);",
            "fingerprint": "fp-6b71a9b6",
            "semanticFingerprint": "sf-a86a0a45"
          }
        ]
      }
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

100%Progress: 100%branchedIndicates that a branch has been created for this issue.bugSomething isn't workingbugfixSomething isn't workingpriority: highCritical issue, needs immediate attention.size: XLIndicates that the issue or task is extra large in scope and complexity.

Type

Projects

  • Status
    Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions