diff --git a/docs/javascript-artifact-reconstruction.md b/docs/javascript-artifact-reconstruction.md index c8e368e398..c7504b0567 100644 --- a/docs/javascript-artifact-reconstruction.md +++ b/docs/javascript-artifact-reconstruction.md @@ -182,6 +182,18 @@ partial Evidence. Cancellation after source analysis begins can also retain completed facts, including when interrupted during cleanup, graph construction, or Evidence sealing. Unexamined relationships remain unknown. +Per-file gaps identify the applicable processing phase: JavaScript source analysis +uses AST authority, while package/JSON, HTML-reference and source-map processing +use artifact-byte authority. File-analysis interruption gaps carry `analysis_status`: +`interrupted` means the phase was entered (including source-worker startup), +and `not-started` means interruption prevented that phase from beginning. +Neither state establishes that parsing completed. Remaining parsers are not run +after interruption just to populate a result. + +Native add-ons remain metadata-only and acquire no JavaScript parse or analysis +gap. This also applies when their paths are outside `source_paths`; their inventory +and caller selection remain available without implying applicable AST work. + MCP returns a `partial_observation` retained reference after recording succeeds; open it with `inspect_analysis_view` on the same connection. If the SDK stopped waiting before receiving the reply, follow [MCP cancellation recovery](mcp-contracts.md#progress-and-cancellation) diff --git a/docs/verification/javascript-interruption-applicability-2026-10-15.json b/docs/verification/javascript-interruption-applicability-2026-10-15.json new file mode 100644 index 0000000000..122b15011a --- /dev/null +++ b/docs/verification/javascript-interruption-applicability-2026-10-15.json @@ -0,0 +1,2641 @@ +{ + "base_revision": "c7f6b8bad1a34d5efb30ff2a017672dea1fcdabb", + "scope": "Static shipped Electron artifact processing applicability and retained Evidence, shared CLI/MCP application boundary; no application/native-provider execution", + "runtime": { + "platform": "Linux x64", + "node": "24.18.0", + "npm": "11.16.0", + "tokenizer": "cl100k_base", + "tiktoken": "0.12.0" + }, + "input": { + "application": "Joplin v3.7.21 Linux AppImage", + "acquisition_reference": "https://github.com/morluto/rea/blob/c7f6b8bad1a34d5efb30ff2a017672dea1fcdabb/docs/verification/javascript-native-handoff-identity-2026-10-15.md", + "appimage_sha256": "5d202dcaca31e14206826aa3f04125e7c218dbc3dc3d98479d811efbd6b856c1", + "asar_sha256": "767df409b18effe60421fbefcca873de237c7e813eac744ecdeebbc5e825a33a", + "keytar_sha256": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "inventory_files": 6324, + "unpacked_entries": 46, + "native_companions_staged": 3, + "other_unpacked_entries_not_staged": 43, + "source_paths": [ + "ElectronAppWrapper.js", + "ElectronAppWrapper.js.map", + "index.html", + "package.json", + "node_modules/keytar/build/Release/keytar.node" + ] + }, + "implementation": { + "owner": "Application artifact analysis produces applicable scope/authority and interruption status; graph consumes these facts. Metadata-only native needs no post-inventory source-processing phase.", + "statuses": { + "interrupted": "Processing phase entered, including worker startup; does not establish completed parsing.", + "not-started": "Interruption prevented phase entry." + }, + "cleanup": "Removed AST-only unavailable helper; corrected normal package/JSON/map gap authority and native caller-exclusion scope; metadata progress consumes same scope owner. No parser resumes after interruption.", + "failure_sharing": "At most5 applicable phase entries per interruption; no persistent cache or freshness assumption.", + "public_contract": "Existing CLI/MCP inputs, selection, schemas and effects retained. analysis_status is an additive graph-observation property; corrected provenance/phase values and removal of false native scopes change derived Evidence identities.", + "semantic_applicability": "Semantic projection recordUnavailableFile owns JavaScript applicability for full and incremental callers; non-JavaScript files add no semantic nodes, limits or unknowns." + }, + "baseline_source_sha256": { + "docs/javascript-artifact-reconstruction.md": "78208db9ec08778d78be295fff7038eeabcd9451f2f9adfc415e7f308614e8d4", + "scripts/verify/javascript/native-handoffs.mjs": "bfdc235cc38a519a39e8b2e772d55259f371ccb15058e6fd241ee5ac05dfef82", + "src/application/javascript/JavaScriptArtifactAnalysis.ts": "ffcd4d42c320a37b5d657cb1cf99f389ed4420befd5c5680dc0032fa4136d458", + "src/application/javascript/JavaScriptArtifactAnalysisTypes.ts": "c6aef4c60cac2016116e620bd960f10c05a8b3287cb2f9df1e16e2dd665c829f", + "src/application/javascript/JavaScriptArtifactGraphContext.ts": "3398e7af6a0414f4532a6c8ac78f3deadf69816b9b95262d8c5c51e378ea7047", + "src/application/javascript/JavaScriptArtifactGraphEvidence.ts": "54c9196c7d7adf945325eb4a08a234624731a4d1b2550983fe06ddb36711def0", + "src/application/javascript/JavaScriptArtifactGraphStructure.ts": "1afdeda88a998133eb2de2cb26cbcffdd51c85f302c2797158e2944874326449", + "src/application/javascript/JavaScriptArtifactReconstruction.ts": "24108a0365ae106e8aca3657f1d88fee7cfa1a2e3ddd379dc2982505382d0d92", + "tests/acceptance/applications/javascriptAnalysisLimits.test.ts": "2001849b4917ab7198025bdd17929ad3e4c18fa250408b4d2cd50a2a2fdb0fc4", + "tests/boundary/filesystem/javascriptArtifactReconstruction.test.ts": "b6a4059f4079cfb1e288fb51a50d79364ea22af0c70681b73e2eff1cd275cc07", + "tests/boundary/javascript/javascriptApplicationCancellation.test.ts": "4af48d06f4f78ace504ea441f3e049db67268af72b25b2689c11ae3672798178", + "src/application/javascript/JavaScriptSemanticGraphBuilder.ts": "6efe0f4695b76722c6d446dcb88a5cbcef3ba762fa553215473359ef4021cc88", + "tests/boundary/filesystem/javascript-applications/javascriptArtifactReconstruction.test.ts": "c14e443a5d7d0dd58de86041cada09da070bbb1b3c572f6e2768b8be0482e8e1" + }, + "baseline_execution_driver_sources": { + "revision": "c7f6b8bad1a34d5efb30ff2a017672dea1fcdabb", + "sha256": { + "scripts/verify/javascript/native-handoffs.mjs": "ff59d57db7ae6b484508dd84637dc2ad789a8604bf85331421a5e4a99a64ef20", + "tests/acceptance/applications/javascriptAnalysisLimits.test.ts": "6d491015ce6edf6e249dc28964e82e9bcdd605328286e8d00bddf411ee8810c8", + "src/application/javascript/JavaScriptArtifactAnalysis.ts": "ffcd4d42c320a37b5d657cb1cf99f389ed4420befd5c5680dc0032fa4136d458", + "src/application/javascript/JavaScriptArtifactAnalysisTypes.ts": "c6aef4c60cac2016116e620bd960f10c05a8b3287cb2f9df1e16e2dd665c829f", + "src/application/javascript/JavaScriptArtifactGraphContext.ts": "3398e7af6a0414f4532a6c8ac78f3deadf69816b9b95262d8c5c51e378ea7047", + "src/application/javascript/JavaScriptArtifactGraphEvidence.ts": "54c9196c7d7adf945325eb4a08a234624731a4d1b2550983fe06ddb36711def0", + "src/application/javascript/JavaScriptArtifactGraphStructure.ts": "1afdeda88a998133eb2de2cb26cbcffdd51c85f302c2797158e2944874326449" + }, + "verifier_v2_export_validation_sha256": "5a1556ce1904fba7b9430492b4c17973ec1e792b109c386ac067946df6b20d34", + "oracle_correction_source_sha256": { + "tests/acceptance/applications/javascriptAnalysisLimits.test.ts": "6d491015ce6edf6e249dc28964e82e9bcdd605328286e8d00bddf411ee8810c8", + "tests/boundary/javascript/javascriptApplicationCancellation.test.ts": "20efdb536709a2c46feb25b4edf55f65f1585a81f56d2afc73d5db93446907b6" + } + }, + "final_source_sha256": { + "docs/javascript-artifact-reconstruction.md": "58c472f61537f7aeca477440712a44a12dc020554f966cfdf7d5c1ea71166895", + "scripts/verify/javascript/native-handoffs.mjs": "1795c183370ed8289eb961da470073530ccbdbb46599d4a8966881639b219155", + "src/application/javascript/JavaScriptArtifactAnalysis.ts": "6d895f0efb37225e9b7f74ab824729e8cf6de3151a7fe4ae9fd599bedfffdd94", + "src/application/javascript/JavaScriptArtifactAnalysisTypes.ts": "4569780dcaff8e783b3169770473373d202e3a8d558e5ea03df88cd3f6853bf7", + "src/application/javascript/JavaScriptArtifactGraphContext.ts": "b1e486b5b29f15466b033464780fc57d5619506aad94f4c5053e1882c4bd30d2", + "src/application/javascript/JavaScriptArtifactGraphEvidence.ts": "4ac2d6c95011ee6a86ef79b3477557fd296df1ebb84e57ebb3d359848ca92cc3", + "src/application/javascript/JavaScriptArtifactGraphStructure.ts": "167be12f869088aeab0e521d6e85ee11348b40f15d5a24dff3030d8dec39b8a3", + "src/application/javascript/JavaScriptArtifactReconstruction.ts": "583e14e34c5f4d2d6118f2dc750862b86f656bf2d98cca5b28fad2620168308c", + "tests/acceptance/applications/javascriptAnalysisLimits.test.ts": "25ea7addf365c3ab992d1f24d65d57b02655033e28b2b100406c9c90712064c7", + "tests/boundary/filesystem/javascriptArtifactReconstruction.test.ts": "bdb6dc9fd8a9921e956d01017ac9d32a499b3815f0611929185add7e42c5ba37", + "tests/boundary/javascript/javascriptApplicationCancellation.test.ts": "c604554072e6f848c24926b8630a738b9247ccd04b337374e8060cfb6a0a069f", + "scripts/lib/javascript-file-scope-oracle.mjs": "e36f0aa114c7c2d2a2e9657f5ef7119f179d7bd6ba4ef899d0fc9ee67b4b7b07", + "scripts/lib/javascript-file-scope-oracle.d.mts": "f3ac21ce936613d650fa6d610b9905406ae02a0afa97afd677b5b11377369134", + "tests/boundary/process/javascriptVerifierScopeOracle.test.ts": "e94c3659b660482aaf75652a60440916f58921c97c4b9bc3182e647a505a2b6b", + "src/application/javascript/JavaScriptSemanticGraphBuilder.ts": "b9e4d45f01ec1dfdf492dbcbdda4fa957d4e8941e1faeff489dadc582d7bd094", + "tests/boundary/filesystem/javascript-applications/javascriptArtifactReconstruction.test.ts": "26993f5cbd2ff862e134f9d364779bbd9432f3cc7be9ddaf1a64fcdb50b54a71" + }, + "preprogress_source_sha256": { + "docs/javascript-artifact-reconstruction.md": "e826a5d17f43a70915326c35cadcd236cb7155c596baefb230b9bc033bd81c74", + "scripts/verify/javascript/native-handoffs.mjs": "10335e8f8a87d01302a314af2ebd23505cb53af892984f89e376f158199e6f13", + "src/application/javascript/JavaScriptArtifactAnalysis.ts": "dc0cc638ac7e8163efbe779f97bd9e945ef43688f71dc2c365de6439cc1823e6", + "src/application/javascript/JavaScriptArtifactAnalysisTypes.ts": "4569780dcaff8e783b3169770473373d202e3a8d558e5ea03df88cd3f6853bf7", + "src/application/javascript/JavaScriptArtifactGraphContext.ts": "b1e486b5b29f15466b033464780fc57d5619506aad94f4c5053e1882c4bd30d2", + "src/application/javascript/JavaScriptArtifactGraphEvidence.ts": "4ac2d6c95011ee6a86ef79b3477557fd296df1ebb84e57ebb3d359848ca92cc3", + "src/application/javascript/JavaScriptArtifactGraphStructure.ts": "167be12f869088aeab0e521d6e85ee11348b40f15d5a24dff3030d8dec39b8a3", + "tests/acceptance/applications/javascriptAnalysisLimits.test.ts": "c2a188b82fb90df9ef7b9e2c6d49027c77a3e0a4bd2a5eaeeb1dc3d1ff99496f", + "tests/boundary/filesystem/javascriptArtifactReconstruction.test.ts": "bdb6dc9fd8a9921e956d01017ac9d32a499b3815f0611929185add7e42c5ba37", + "tests/boundary/javascript/javascriptApplicationCancellation.test.ts": "8880abb141b808767e5c70156fb2908333b00a6cedd2b583ce7603afcf6881bb" + }, + "cohorts": { + "baseline": { + "timeout": { + "result": { + "scope": "Real shipped-ASAR native identity through public CLI/stdio MCP; simulated native Evidence only, no provider/application executed", + "artifact": { + "path": "/tmp/rea-native-handoff-20261015/cases/available/app.asar", + "sha256": "767df409b18effe60421fbefcca873de237c7e813eac744ecdeebbc5e825a33a" + }, + "addon_path": "node_modules/keytar/build/Release/keytar.node", + "companion_sha256_observed": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "prior_native_sha256_supplied": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "source_paths": [ + "ElectronAppWrapper.js", + "ElectronAppWrapper.js.map", + "index.html", + "package.json", + "node_modules/keytar/build/Release/keytar.node" + ], + "preparation_outcome": "provider_timeout", + "analysis_timeout_ms": 1, + "parent_evidence_id": "ev_d5dbad729d69cb9cb442e1e1f9df807bc55dc47bd6e00fede791bea9fa784896", + "trace_evidence_id": "ev_4e763bb77e98e7b2d324cea75dade7bd92d019d08eb4d7a153bbb36e99d03a1c", + "trace_subject": null, + "preparation_ms": 35691.510259, + "samples": [ + { + "round": 0, + "elapsed_ms": 145.09717000000092, + "structured_reply_bytes": 13234, + "full_tool_reply_bytes": 27641 + }, + { + "round": 1, + "elapsed_ms": 101.57486900000367, + "structured_reply_bytes": 13234, + "full_tool_reply_bytes": 27641 + }, + { + "round": 2, + "elapsed_ms": 95.30256999999983, + "structured_reply_bytes": 13234, + "full_tool_reply_bytes": 27641 + } + ], + "safe_identity": true, + "safe_applicability": false, + "native_analysis_scopes": [ + { + "node_id": "jag_node_753686f61d8539b808cabb867b152b07c73e34be67f28c01c5487ee4a30c8931", + "label": "node_modules/keytar/build/Release/keytar.node parse scope", + "source_map_reference": null, + "properties": { + "path": "node_modules/keytar/build/Release/keytar.node", + "operation": "analyze-javascript-source", + "limitation": "Source analysis was interrupted: Analysis operation timed out after 1ms: analyze_javascript_application", + "analysis_failure": { + "code": "provider_timeout", + "category": "timeout", + "message": "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues.", + "retryable": true, + "remediation": { + "action": "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues." + }, + "details": { + "operation": "analyze_javascript_application", + "timeout_ms": 1, + "captured_output": { + "stdout": "", + "stderr": "", + "truncated": false, + "stderr_bytes": 0, + "exit_code": null, + "signal": null + } + } + } + }, + "evidence": { + "authority": "ast-static-analysis", + "state": "unavailable", + "confidence": "unknown", + "artifact": { + "available": true, + "artifact_id": "art_0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "sha256": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a" + }, + "location": { + "available": true, + "value": { + "kind": "artifact-path", + "path": "node_modules/keytar/build/Release/keytar.node" + } + }, + "extractor": { + "name": "rea-javascript-artifact-reconstruction", + "version": "1", + "operation": "analyze-javascript-source", + "executable_sha256": null + }, + "coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + }, + "limitations": [ + "Source analysis was interrupted: Analysis operation timed out after 1ms: analyze_javascript_application" + ], + "evidence_ids": [] + }, + "observation_id": "jag_observation_0648539f0a1147667a79e1169b3421f085850e775e299313bbe6783702f8d84a", + "identifier_strategy": { + "strategy": "semantic-content-sha256", + "stability": "observation-exact" + } + } + ], + "structured_scopes": [ + { + "path": "ElectronAppWrapper.js.map", + "scopes": [ + { + "node_id": "jag_node_2361c5ae8ec571bdd480605526fc5b38900fa7fb94571c5f940fcfdfe3594c25", + "label": "ElectronAppWrapper.js.map parse scope", + "source_map_reference": null, + "properties": { + "path": "ElectronAppWrapper.js.map", + "operation": "analyze-javascript-source", + "limitation": "Source analysis was interrupted: Analysis operation timed out after 1ms: analyze_javascript_application", + "analysis_failure": { + "code": "provider_timeout", + "category": "timeout", + "message": "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues.", + "retryable": true, + "remediation": { + "action": "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues." + }, + "details": { + "operation": "analyze_javascript_application", + "timeout_ms": 1, + "captured_output": { + "stdout": "", + "stderr": "", + "truncated": false, + "stderr_bytes": 0, + "exit_code": null, + "signal": null + } + } + } + }, + "evidence": { + "authority": "ast-static-analysis", + "state": "unavailable", + "confidence": "unknown", + "artifact": { + "available": true, + "artifact_id": "art_825d88385763ad9562a1c901561e263c8cac51a41d8866432d206037cc362bd4", + "sha256": "825d88385763ad9562a1c901561e263c8cac51a41d8866432d206037cc362bd4" + }, + "location": { + "available": true, + "value": { + "kind": "artifact-path", + "path": "ElectronAppWrapper.js.map" + } + }, + "extractor": { + "name": "rea-javascript-artifact-reconstruction", + "version": "1", + "operation": "analyze-javascript-source", + "executable_sha256": null + }, + "coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + }, + "limitations": [ + "Source analysis was interrupted: Analysis operation timed out after 1ms: analyze_javascript_application" + ], + "evidence_ids": [] + }, + "observation_id": "jag_observation_8ea415abaec186c5434fb4c6f10f4d3da2cbe4f762bc22a5e73a139c7d3f67af", + "identifier_strategy": { + "strategy": "semantic-content-sha256", + "stability": "observation-exact" + } + } + ], + "evidence_id": "ev_ca6cd9d1d390d2a7dec04f2622b20d8c8dc0cb00559fe9ed80667b95a942f372", + "source_coverage": { + "status": "partial", + "source_graph_status": "partial", + "total_seed_matches": 3 + }, + "graph_coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + } + }, + { + "path": "index.html", + "scopes": [ + { + "node_id": "jag_node_50b5fa0fa18dcdbba24db324118105d6e47155d571709a0f4a6d21c6212b6efb", + "label": "index.html parse scope", + "source_map_reference": null, + "properties": { + "path": "index.html", + "operation": "analyze-javascript-source", + "limitation": "Source analysis was interrupted: Analysis operation timed out after 1ms: analyze_javascript_application", + "analysis_failure": { + "code": "provider_timeout", + "category": "timeout", + "message": "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues.", + "retryable": true, + "remediation": { + "action": "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues." + }, + "details": { + "operation": "analyze_javascript_application", + "timeout_ms": 1, + "captured_output": { + "stdout": "", + "stderr": "", + "truncated": false, + "stderr_bytes": 0, + "exit_code": null, + "signal": null + } + } + } + }, + "evidence": { + "authority": "ast-static-analysis", + "state": "unavailable", + "confidence": "unknown", + "artifact": { + "available": true, + "artifact_id": "art_a083a1d8a8065872fb74c381730e5b05958a041af717643e2eaeaec8557f6c81", + "sha256": "a083a1d8a8065872fb74c381730e5b05958a041af717643e2eaeaec8557f6c81" + }, + "location": { + "available": true, + "value": { + "kind": "artifact-path", + "path": "index.html" + } + }, + "extractor": { + "name": "rea-javascript-artifact-reconstruction", + "version": "1", + "operation": "analyze-javascript-source", + "executable_sha256": null + }, + "coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + }, + "limitations": [ + "Source analysis was interrupted: Analysis operation timed out after 1ms: analyze_javascript_application" + ], + "evidence_ids": [] + }, + "observation_id": "jag_observation_71d35b3cbaa72f3af99a9735fe9ca4742d3edd84bede8b8be35473c91fc94d03", + "identifier_strategy": { + "strategy": "semantic-content-sha256", + "stability": "observation-exact" + } + } + ], + "evidence_id": "ev_cd8d60ea15721644a33b1e3cfa55ad2d93b7cdd60203c2018d99bd91872a523f", + "source_coverage": { + "status": "partial", + "source_graph_status": "partial", + "total_seed_matches": 3 + }, + "graph_coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + } + }, + { + "path": "package.json", + "scopes": [ + { + "node_id": "jag_node_524ca9edbac1bbf330eb875d57ea59ff058bdb16ff6679e3bc4e3dc643979f78", + "label": "package.json parse scope", + "source_map_reference": null, + "properties": { + "path": "package.json", + "operation": "analyze-javascript-source", + "limitation": "Source analysis was interrupted: Analysis operation timed out after 1ms: analyze_javascript_application", + "analysis_failure": { + "code": "provider_timeout", + "category": "timeout", + "message": "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues.", + "retryable": true, + "remediation": { + "action": "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues." + }, + "details": { + "operation": "analyze_javascript_application", + "timeout_ms": 1, + "captured_output": { + "stdout": "", + "stderr": "", + "truncated": false, + "stderr_bytes": 0, + "exit_code": null, + "signal": null + } + } + } + }, + "evidence": { + "authority": "ast-static-analysis", + "state": "unavailable", + "confidence": "unknown", + "artifact": { + "available": true, + "artifact_id": "art_2caf6a44c578054124684c6ec441eff90e434c09319ea5dd74c69ac1109c1119", + "sha256": "2caf6a44c578054124684c6ec441eff90e434c09319ea5dd74c69ac1109c1119" + }, + "location": { + "available": true, + "value": { + "kind": "artifact-path", + "path": "package.json" + } + }, + "extractor": { + "name": "rea-javascript-artifact-reconstruction", + "version": "1", + "operation": "analyze-javascript-source", + "executable_sha256": null + }, + "coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + }, + "limitations": [ + "Source analysis was interrupted: Analysis operation timed out after 1ms: analyze_javascript_application" + ], + "evidence_ids": [] + }, + "observation_id": "jag_observation_f7a3e40649477744a67fc32c3519afd553d49edfe3814056458cc395b0568e80", + "identifier_strategy": { + "strategy": "semantic-content-sha256", + "stability": "observation-exact" + } + } + ], + "evidence_id": "ev_75dc5c53368e0994d515f17f68f7729031bfff977dc5d05d05a426439c39298a", + "source_coverage": { + "status": "partial", + "source_graph_status": "partial", + "total_seed_matches": 3 + }, + "graph_coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + } + } + ], + "node": { + "node_id": "jag_node_98ccdef0e85d67cba9cc843193c5ba877f0a73ba3fa7d3581f6db0396a707b2d", + "identity": { + "strategy": "content-digest", + "stability": "global-exact", + "sha256": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a" + }, + "unavailable_observed": false, + "basis": [ + { + "authority": "artifact-bytes", + "state": "observed", + "confidence": "exact", + "artifact": { + "available": true, + "artifact_id": "art_0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "sha256": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a" + }, + "location": { + "available": true, + "value": { + "kind": "artifact-path", + "path": "node_modules/keytar/build/Release/keytar.node" + } + } + } + ] + }, + "native_handoffs": [ + { + "native_node_id": "jag_node_98ccdef0e85d67cba9cc843193c5ba877f0a73ba3fa7d3581f6db0396a707b2d", + "artifact_sha256": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "artifact_path": "node_modules/keytar/build/Release/keytar.node", + "export_node_ids": [], + "requested_exports": [], + "status": "evidence-linked", + "providers": [ + { + "id": "ghidra", + "name": "Ghidra", + "version": "simulated" + } + ], + "evidence_ids": [ + "ev_c1bf000c14a18445db1f834b1c6019ae04725dd948951d5b5079184b4524e8d7" + ], + "recommended_tools": [ + "open_binary", + "binary_overview", + "search_procedures", + "analyze_function", + "xrefs" + ] + } + ], + "evidence_links": [ + "ev_c1bf000c14a18445db1f834b1c6019ae04725dd948951d5b5079184b4524e8d7", + "ev_d5dbad729d69cb9cb442e1e1f9df807bc55dc47bd6e00fede791bea9fa784896" + ], + "source_coverage": { + "status": "partial", + "source_graph_status": "partial", + "total_seed_matches": 3 + }, + "graph_coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + }, + "facts_sha256": "77bfc90608098983f646d78a9f49d62adf61f50d6b8871a50597c78b95f6e493", + "cli_parity": { + "exact_cli_mcp_trace_parity": true, + "evidence_id": "ev_4e763bb77e98e7b2d324cea75dade7bd92d019d08eb4d7a153bbb36e99d03a1c" + }, + "token_costs": { + "tokenizer": "cl100k_base", + "tiktoken_version": "0.12.0", + "selected_catalog": 5570, + "full_catalog": 195522, + "requests": 903, + "structured_replies": 14663, + "full_tool_replies": 29995, + "selected_catalog_structured_task": 21136, + "full_catalog_structured_task": 211088, + "selected_catalog_full_reply_task": 36468, + "full_catalog_full_reply_task": 226420 + }, + "conditions": "Fresh MCP session, selected analysis followed by retained traces. Task token counts include one analysis summary or parsed timeout error, one native trace and each requested structured-path trace, with name/description/inputSchema catalog projections. Structured Evidence/parsed error and complete-tool-reply projections are alternatives, not billing. Repeated native rounds, export, CLI parity and tokenizer are validation overhead outside task tokens but inside total resource receipts. Filesystem/build caches uncontrolled. Incorrect identity/applicability is not a successful equivalent task or efficiency credit." + }, + "resources": { + "elapsed_seconds": 60.738, + "cpu_seconds": 60.289464, + "peak_cgroup_bytes": 3092045824, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + }, + "control": { + "result": { + "scope": "Real shipped-ASAR native identity through public CLI/stdio MCP; simulated native Evidence only, no provider/application executed", + "artifact": { + "path": "/tmp/rea-native-handoff-20261015/cases/available/app.asar", + "sha256": "767df409b18effe60421fbefcca873de237c7e813eac744ecdeebbc5e825a33a" + }, + "addon_path": "node_modules/keytar/build/Release/keytar.node", + "companion_sha256_observed": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "prior_native_sha256_supplied": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "source_paths": [ + "ElectronAppWrapper.js", + "ElectronAppWrapper.js.map", + "index.html", + "package.json", + "node_modules/keytar/build/Release/keytar.node" + ], + "preparation_outcome": "completed", + "analysis_timeout_ms": null, + "parent_evidence_id": "ev_b1f947f72911e1a8c7faaca4fd70e084279b791ba3bf4d63bf0cfe87f2c63ed4", + "trace_evidence_id": "ev_515f07a2fc0d4bde44e0e3fb6e83072103dbda12b3653d7e84c3d566e0201e9b", + "trace_subject": null, + "preparation_ms": 38655.830385, + "samples": [ + { + "round": 0, + "elapsed_ms": 152.85529600000154, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + }, + { + "round": 1, + "elapsed_ms": 98.97723499999847, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + }, + { + "round": 2, + "elapsed_ms": 98.40282499999739, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + } + ], + "safe_identity": true, + "safe_applicability": true, + "native_analysis_scopes": [], + "structured_scopes": [ + { + "source": "exported-parent-validation", + "path": "ElectronAppWrapper.js.map", + "scopes": [], + "source_evidence_id": "ev_b1f947f72911e1a8c7faaca4fd70e084279b791ba3bf4d63bf0cfe87f2c63ed4", + "retained_matching_nodes": 1, + "graph_coverage": { + "limits": [], + "omitted_count": null, + "status": "partial", + "truncated": false + } + }, + { + "source": "exported-parent-validation", + "path": "index.html", + "scopes": [], + "source_evidence_id": "ev_b1f947f72911e1a8c7faaca4fd70e084279b791ba3bf4d63bf0cfe87f2c63ed4", + "retained_matching_nodes": 1, + "graph_coverage": { + "limits": [], + "omitted_count": null, + "status": "partial", + "truncated": false + } + }, + { + "source": "exported-parent-validation", + "path": "package.json", + "scopes": [], + "source_evidence_id": "ev_b1f947f72911e1a8c7faaca4fd70e084279b791ba3bf4d63bf0cfe87f2c63ed4", + "retained_matching_nodes": 2, + "graph_coverage": { + "limits": [], + "omitted_count": null, + "status": "partial", + "truncated": false + } + } + ], + "modeled_structured_trace_count": 0, + "node": { + "node_id": "jag_node_98ccdef0e85d67cba9cc843193c5ba877f0a73ba3fa7d3581f6db0396a707b2d", + "identity": { + "strategy": "content-digest", + "stability": "global-exact", + "sha256": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a" + }, + "unavailable_observed": false, + "basis": [ + { + "authority": "artifact-bytes", + "state": "observed", + "confidence": "exact", + "artifact": { + "available": true, + "artifact_id": "art_0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "sha256": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a" + }, + "location": { + "available": true, + "value": { + "kind": "artifact-path", + "path": "node_modules/keytar/build/Release/keytar.node" + } + } + } + ] + }, + "native_handoffs": [ + { + "native_node_id": "jag_node_98ccdef0e85d67cba9cc843193c5ba877f0a73ba3fa7d3581f6db0396a707b2d", + "artifact_sha256": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "artifact_path": "node_modules/keytar/build/Release/keytar.node", + "export_node_ids": [], + "requested_exports": [], + "status": "evidence-linked", + "providers": [ + { + "id": "ghidra", + "name": "Ghidra", + "version": "simulated" + } + ], + "evidence_ids": [ + "ev_c1bf000c14a18445db1f834b1c6019ae04725dd948951d5b5079184b4524e8d7" + ], + "recommended_tools": [ + "open_binary", + "binary_overview", + "search_procedures", + "analyze_function", + "xrefs" + ] + } + ], + "evidence_links": [ + "ev_b1f947f72911e1a8c7faaca4fd70e084279b791ba3bf4d63bf0cfe87f2c63ed4", + "ev_c1bf000c14a18445db1f834b1c6019ae04725dd948951d5b5079184b4524e8d7" + ], + "source_coverage": { + "status": "partial", + "source_graph_status": "partial", + "total_seed_matches": 2 + }, + "graph_coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [] + }, + "facts_sha256": "9380df397cad9764c435870af56ff6eb91aa33b5b6c32a30a5e5d932f27c84bc", + "cli_parity": { + "exact_cli_mcp_trace_parity": true, + "evidence_id": "ev_515f07a2fc0d4bde44e0e3fb6e83072103dbda12b3653d7e84c3d566e0201e9b" + }, + "token_costs": { + "tokenizer": "cl100k_base", + "tiktoken_version": "0.12.0", + "selected_catalog": 5570, + "full_catalog": 195522, + "requests": 627, + "structured_replies": 5579, + "full_tool_replies": 11541, + "selected_catalog_structured_task": 11776, + "full_catalog_structured_task": 201728, + "selected_catalog_full_reply_task": 17738, + "full_catalog_full_reply_task": 207690 + }, + "conditions": "Fresh MCP session, selected analysis followed by retained traces. Task token counts include one analysis summary or parsed timeout error, one native trace and each requested structured-path trace, with name/description/inputSchema catalog projections. Structured Evidence/parsed error and complete-tool-reply projections are alternatives, not billing. Repeated native rounds, export, CLI parity and tokenizer are validation overhead outside task tokens but inside total resource receipts. Filesystem/build caches uncontrolled. Incorrect identity/applicability is not a successful equivalent task or efficiency credit." + }, + "resources": { + "elapsed_seconds": 61.542, + "cpu_seconds": 61.135522, + "peak_cgroup_bytes": 2808336384, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + } + }, + "final": { + "timeout": { + "result": { + "scope": "Real shipped-ASAR native identity through public CLI/stdio MCP; simulated native Evidence only, no provider/application executed", + "artifact": { + "path": "/tmp/rea-native-handoff-20261015/cases/available/app.asar", + "sha256": "767df409b18effe60421fbefcca873de237c7e813eac744ecdeebbc5e825a33a" + }, + "addon_path": "node_modules/keytar/build/Release/keytar.node", + "companion_sha256_observed": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "prior_native_sha256_supplied": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "source_paths": [ + "ElectronAppWrapper.js", + "ElectronAppWrapper.js.map", + "index.html", + "package.json", + "node_modules/keytar/build/Release/keytar.node" + ], + "preparation_outcome": "provider_timeout", + "analysis_timeout_ms": 1, + "parent_evidence_id": "ev_ba7919ad7d538a41c183dfb5e27bb9dff6058a01b83fb583beebf4205c7c9939", + "trace_evidence_id": "ev_c95f2477bbc503d71094288ca11354fbb5bb0d8c86d26c7ea2b373a98458587f", + "trace_subject": null, + "preparation_ms": 34866.233877, + "samples": [ + { + "round": 0, + "elapsed_ms": 153.571864000005, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + }, + { + "round": 1, + "elapsed_ms": 96.07862699999532, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + }, + { + "round": 2, + "elapsed_ms": 92.27811600000132, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + } + ], + "safe_identity": true, + "safe_applicability": true, + "native_analysis_scopes": [], + "structured_scopes": [ + { + "source": "retained-feature-trace", + "path": "ElectronAppWrapper.js.map", + "scopes": [ + { + "node_id": "jag_node_82fcfceda6e334ca0bfdbddf79306a11a5b958e2c65570a1d862dc001e27bbbc", + "label": "ElectronAppWrapper.js.map parse scope", + "source_map_reference": null, + "properties": { + "analysis_status": "not-started", + "path": "ElectronAppWrapper.js.map", + "operation": "parse-local-source-map", + "limitation": "Source analysis was interrupted: Analysis operation timed out after 1ms: analyze_javascript_application", + "analysis_failure": { + "code": "provider_timeout", + "category": "timeout", + "message": "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues.", + "retryable": true, + "remediation": { + "action": "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues." + }, + "details": { + "operation": "analyze_javascript_application", + "timeout_ms": 1, + "captured_output": { + "stdout": "", + "stderr": "", + "truncated": false, + "stderr_bytes": 0, + "exit_code": null, + "signal": null + } + } + } + }, + "evidence": { + "authority": "artifact-bytes", + "state": "unavailable", + "confidence": "unknown", + "artifact": { + "available": true, + "artifact_id": "art_825d88385763ad9562a1c901561e263c8cac51a41d8866432d206037cc362bd4", + "sha256": "825d88385763ad9562a1c901561e263c8cac51a41d8866432d206037cc362bd4" + }, + "location": { + "available": true, + "value": { + "kind": "artifact-path", + "path": "ElectronAppWrapper.js.map" + } + }, + "extractor": { + "name": "rea-javascript-artifact-reconstruction", + "version": "1", + "operation": "parse-local-source-map", + "executable_sha256": null + }, + "coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + }, + "limitations": [ + "Source analysis was interrupted: Analysis operation timed out after 1ms: analyze_javascript_application" + ], + "evidence_ids": [] + }, + "observation_id": "jag_observation_4b04b2982325de96322efd493507386b986aca57309e959870831dbd6dffd4fd", + "identifier_strategy": { + "strategy": "semantic-content-sha256", + "stability": "observation-exact" + } + } + ], + "evidence_id": "ev_bd1433b6c29798e4fab50fc2ceab69468f688f49dd89b3e34c2e7150c7bf0173", + "source_coverage": { + "status": "partial", + "source_graph_status": "partial", + "total_seed_matches": 3 + }, + "graph_coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + } + }, + { + "source": "retained-feature-trace", + "path": "index.html", + "scopes": [ + { + "node_id": "jag_node_6b9579c90a2499e7e799ede95e32f4c3a4f36d4ac205725bcfdb335aa7b77535", + "label": "index.html parse scope", + "source_map_reference": null, + "properties": { + "analysis_status": "not-started", + "path": "index.html", + "operation": "parse-html-script-references", + "limitation": "Source analysis was interrupted: Analysis operation timed out after 1ms: analyze_javascript_application", + "analysis_failure": { + "code": "provider_timeout", + "category": "timeout", + "message": "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues.", + "retryable": true, + "remediation": { + "action": "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues." + }, + "details": { + "operation": "analyze_javascript_application", + "timeout_ms": 1, + "captured_output": { + "stdout": "", + "stderr": "", + "truncated": false, + "stderr_bytes": 0, + "exit_code": null, + "signal": null + } + } + } + }, + "evidence": { + "authority": "artifact-bytes", + "state": "unavailable", + "confidence": "unknown", + "artifact": { + "available": true, + "artifact_id": "art_a083a1d8a8065872fb74c381730e5b05958a041af717643e2eaeaec8557f6c81", + "sha256": "a083a1d8a8065872fb74c381730e5b05958a041af717643e2eaeaec8557f6c81" + }, + "location": { + "available": true, + "value": { + "kind": "artifact-path", + "path": "index.html" + } + }, + "extractor": { + "name": "rea-javascript-artifact-reconstruction", + "version": "1", + "operation": "parse-html-script-references", + "executable_sha256": null + }, + "coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + }, + "limitations": [ + "Source analysis was interrupted: Analysis operation timed out after 1ms: analyze_javascript_application" + ], + "evidence_ids": [] + }, + "observation_id": "jag_observation_f432dffb800852a9d28d2f85c17ae6b5d83b7b2ae5780021169506a8d08f0d35", + "identifier_strategy": { + "strategy": "semantic-content-sha256", + "stability": "observation-exact" + } + } + ], + "evidence_id": "ev_63d3f7670ea3030c3b105d8b265e056306bbb8cd1269bf6f7d90d024d2664fb1", + "source_coverage": { + "status": "partial", + "source_graph_status": "partial", + "total_seed_matches": 3 + }, + "graph_coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + } + }, + { + "source": "retained-feature-trace", + "path": "package.json", + "scopes": [ + { + "node_id": "jag_node_b7c192d0ca620104077a3e4991c8e7615b3098a96e3b78fdea80e5bf3149dc13", + "label": "package.json parse scope", + "source_map_reference": null, + "properties": { + "analysis_status": "not-started", + "path": "package.json", + "operation": "parse-package-json", + "limitation": "Source analysis was interrupted: Analysis operation timed out after 1ms: analyze_javascript_application", + "analysis_failure": { + "code": "provider_timeout", + "category": "timeout", + "message": "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues.", + "retryable": true, + "remediation": { + "action": "Analysis took too long. Try a smaller request, then run `rea doctor` if it continues." + }, + "details": { + "operation": "analyze_javascript_application", + "timeout_ms": 1, + "captured_output": { + "stdout": "", + "stderr": "", + "truncated": false, + "stderr_bytes": 0, + "exit_code": null, + "signal": null + } + } + } + }, + "evidence": { + "authority": "artifact-bytes", + "state": "unavailable", + "confidence": "unknown", + "artifact": { + "available": true, + "artifact_id": "art_2caf6a44c578054124684c6ec441eff90e434c09319ea5dd74c69ac1109c1119", + "sha256": "2caf6a44c578054124684c6ec441eff90e434c09319ea5dd74c69ac1109c1119" + }, + "location": { + "available": true, + "value": { + "kind": "artifact-path", + "path": "package.json" + } + }, + "extractor": { + "name": "rea-javascript-artifact-reconstruction", + "version": "1", + "operation": "parse-package-json", + "executable_sha256": null + }, + "coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + }, + "limitations": [ + "Source analysis was interrupted: Analysis operation timed out after 1ms: analyze_javascript_application" + ], + "evidence_ids": [] + }, + "observation_id": "jag_observation_5dae4759fcf36b25470467347515c95207d69d7ececfc17a1d90ecfbbea4dc79", + "identifier_strategy": { + "strategy": "semantic-content-sha256", + "stability": "observation-exact" + } + } + ], + "evidence_id": "ev_695a324bc600e2a81a36259c8798bcbaa4a38f75abc82adad55f2dc6dec2e473", + "source_coverage": { + "status": "partial", + "source_graph_status": "partial", + "total_seed_matches": 3 + }, + "graph_coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + } + } + ], + "modeled_structured_trace_count": 3, + "node": { + "node_id": "jag_node_98ccdef0e85d67cba9cc843193c5ba877f0a73ba3fa7d3581f6db0396a707b2d", + "identity": { + "strategy": "content-digest", + "stability": "global-exact", + "sha256": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a" + }, + "unavailable_observed": false, + "basis": [ + { + "authority": "artifact-bytes", + "state": "observed", + "confidence": "exact", + "artifact": { + "available": true, + "artifact_id": "art_0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "sha256": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a" + }, + "location": { + "available": true, + "value": { + "kind": "artifact-path", + "path": "node_modules/keytar/build/Release/keytar.node" + } + } + } + ] + }, + "native_handoffs": [ + { + "native_node_id": "jag_node_98ccdef0e85d67cba9cc843193c5ba877f0a73ba3fa7d3581f6db0396a707b2d", + "artifact_sha256": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "artifact_path": "node_modules/keytar/build/Release/keytar.node", + "export_node_ids": [], + "requested_exports": [], + "status": "evidence-linked", + "providers": [ + { + "id": "ghidra", + "name": "Ghidra", + "version": "simulated" + } + ], + "evidence_ids": [ + "ev_c1bf000c14a18445db1f834b1c6019ae04725dd948951d5b5079184b4524e8d7" + ], + "recommended_tools": [ + "open_binary", + "binary_overview", + "search_procedures", + "analyze_function", + "xrefs" + ] + } + ], + "evidence_links": [ + "ev_ba7919ad7d538a41c183dfb5e27bb9dff6058a01b83fb583beebf4205c7c9939", + "ev_c1bf000c14a18445db1f834b1c6019ae04725dd948951d5b5079184b4524e8d7" + ], + "source_coverage": { + "status": "partial", + "source_graph_status": "partial", + "total_seed_matches": 2 + }, + "graph_coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [ + { + "name": "javascript_analysis_worker_timeout_ms", + "value": 1, + "unit": "milliseconds" + } + ] + }, + "facts_sha256": "70adc49dd7b9e13136c9ba3616a9a7210e86c2bacba734c329274f911e38458d", + "cli_parity": { + "exact_cli_mcp_trace_parity": true, + "evidence_id": "ev_c95f2477bbc503d71094288ca11354fbb5bb0d8c86d26c7ea2b373a98458587f" + }, + "token_costs": { + "tokenizer": "cl100k_base", + "tiktoken_version": "0.12.0", + "selected_catalog": 5570, + "full_catalog": 195522, + "requests": 911, + "structured_replies": 13680, + "full_tool_replies": 27990, + "selected_catalog_structured_task": 20161, + "full_catalog_structured_task": 210113, + "selected_catalog_full_reply_task": 34471, + "full_catalog_full_reply_task": 224423 + }, + "conditions": "Fresh MCP session, selected analysis followed by retained traces. Task token counts include one analysis summary or parsed timeout error, one native trace and each requested structured-path trace, with name/description/inputSchema catalog projections. Structured Evidence/parsed error and complete-tool-reply projections are alternatives, not billing. Repeated native rounds, export, CLI parity and tokenizer are validation overhead outside task tokens but inside total resource receipts. Filesystem/build caches uncontrolled. Incorrect identity/applicability is not a successful equivalent task or efficiency credit." + }, + "resources": { + "elapsed_seconds": 57.515, + "cpu_seconds": 57.089883, + "peak_cgroup_bytes": 2763276288, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + }, + "control": { + "result": { + "scope": "Real shipped-ASAR native identity through public CLI/stdio MCP; simulated native Evidence only, no provider/application executed", + "artifact": { + "path": "/tmp/rea-native-handoff-20261015/cases/available/app.asar", + "sha256": "767df409b18effe60421fbefcca873de237c7e813eac744ecdeebbc5e825a33a" + }, + "addon_path": "node_modules/keytar/build/Release/keytar.node", + "companion_sha256_observed": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "prior_native_sha256_supplied": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "source_paths": [ + "ElectronAppWrapper.js", + "ElectronAppWrapper.js.map", + "index.html", + "package.json", + "node_modules/keytar/build/Release/keytar.node" + ], + "preparation_outcome": "completed", + "analysis_timeout_ms": null, + "parent_evidence_id": "ev_11a21c98651e2f165e0a2a223734ceafb44ca8dcc0dd691647053237661b732a", + "trace_evidence_id": "ev_c70e3df14722c16822221309a873d064cb5772f644f0c537d6b3ec3dcee7e3ce", + "trace_subject": null, + "preparation_ms": 143205.272422, + "samples": [ + { + "round": 0, + "elapsed_ms": 634.3961899999995, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + }, + { + "round": 1, + "elapsed_ms": 783.5708970000269, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + }, + { + "round": 2, + "elapsed_ms": 966.7669149999856, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + } + ], + "safe_identity": true, + "safe_applicability": true, + "native_analysis_scopes": [], + "structured_scopes": [ + { + "source": "exported-parent-validation", + "path": "ElectronAppWrapper.js.map", + "scopes": [], + "source_evidence_id": "ev_11a21c98651e2f165e0a2a223734ceafb44ca8dcc0dd691647053237661b732a", + "retained_matching_nodes": 1, + "graph_coverage": { + "limits": [], + "omitted_count": null, + "status": "partial", + "truncated": false + } + }, + { + "source": "exported-parent-validation", + "path": "index.html", + "scopes": [], + "source_evidence_id": "ev_11a21c98651e2f165e0a2a223734ceafb44ca8dcc0dd691647053237661b732a", + "retained_matching_nodes": 1, + "graph_coverage": { + "limits": [], + "omitted_count": null, + "status": "partial", + "truncated": false + } + }, + { + "source": "exported-parent-validation", + "path": "package.json", + "scopes": [], + "source_evidence_id": "ev_11a21c98651e2f165e0a2a223734ceafb44ca8dcc0dd691647053237661b732a", + "retained_matching_nodes": 2, + "graph_coverage": { + "limits": [], + "omitted_count": null, + "status": "partial", + "truncated": false + } + } + ], + "modeled_structured_trace_count": 0, + "node": { + "node_id": "jag_node_98ccdef0e85d67cba9cc843193c5ba877f0a73ba3fa7d3581f6db0396a707b2d", + "identity": { + "strategy": "content-digest", + "stability": "global-exact", + "sha256": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a" + }, + "unavailable_observed": false, + "basis": [ + { + "authority": "artifact-bytes", + "state": "observed", + "confidence": "exact", + "artifact": { + "available": true, + "artifact_id": "art_0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "sha256": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a" + }, + "location": { + "available": true, + "value": { + "kind": "artifact-path", + "path": "node_modules/keytar/build/Release/keytar.node" + } + } + } + ] + }, + "native_handoffs": [ + { + "native_node_id": "jag_node_98ccdef0e85d67cba9cc843193c5ba877f0a73ba3fa7d3581f6db0396a707b2d", + "artifact_sha256": "0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a", + "artifact_path": "node_modules/keytar/build/Release/keytar.node", + "export_node_ids": [], + "requested_exports": [], + "status": "evidence-linked", + "providers": [ + { + "id": "ghidra", + "name": "Ghidra", + "version": "simulated" + } + ], + "evidence_ids": [ + "ev_c1bf000c14a18445db1f834b1c6019ae04725dd948951d5b5079184b4524e8d7" + ], + "recommended_tools": [ + "open_binary", + "binary_overview", + "search_procedures", + "analyze_function", + "xrefs" + ] + } + ], + "evidence_links": [ + "ev_11a21c98651e2f165e0a2a223734ceafb44ca8dcc0dd691647053237661b732a", + "ev_c1bf000c14a18445db1f834b1c6019ae04725dd948951d5b5079184b4524e8d7" + ], + "source_coverage": { + "status": "partial", + "source_graph_status": "partial", + "total_seed_matches": 2 + }, + "graph_coverage": { + "status": "partial", + "truncated": false, + "omitted_count": null, + "limits": [] + }, + "facts_sha256": "1ddcb621546636066ceea7f24b493ea1e2d2578f941ad96ba01bd11e98a673b4", + "cli_parity": { + "exact_cli_mcp_trace_parity": true, + "evidence_id": "ev_c70e3df14722c16822221309a873d064cb5772f644f0c537d6b3ec3dcee7e3ce" + }, + "token_costs": { + "tokenizer": "cl100k_base", + "tiktoken_version": "0.12.0", + "selected_catalog": 5570, + "full_catalog": 195522, + "requests": 621, + "structured_replies": 5529, + "full_tool_replies": 11441, + "selected_catalog_structured_task": 11720, + "full_catalog_structured_task": 201672, + "selected_catalog_full_reply_task": 17632, + "full_catalog_full_reply_task": 207584 + }, + "conditions": "Fresh MCP session, selected analysis followed by retained traces. Task token counts include one analysis summary or parsed timeout error, one native trace and each requested structured-path trace, with name/description/inputSchema catalog projections. Structured Evidence/parsed error and complete-tool-reply projections are alternatives, not billing. Repeated native rounds, export, CLI parity and tokenizer are validation overhead outside task tokens but inside total resource receipts. Filesystem/build caches uncontrolled. Incorrect identity/applicability is not a successful equivalent task or efficiency credit." + }, + "resources": { + "elapsed_seconds": 186.085, + "cpu_seconds": 142.3711, + "peak_cgroup_bytes": 2959585280, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + } + } + }, + "prior_postfix_controls": { + "timeout_initial": { + "result_equivalent_to": "cohorts.final.timeout.result except preparation_ms and sample elapsed_ms", + "parent_evidence_id": "ev_ba7919ad7d538a41c183dfb5e27bb9dff6058a01b83fb583beebf4205c7c9939", + "trace_evidence_id": "ev_c95f2477bbc503d71094288ca11354fbb5bb0d8c86d26c7ea2b373a98458587f", + "facts_sha256": "70adc49dd7b9e13136c9ba3616a9a7210e86c2bacba734c329274f911e38458d", + "preparation_ms": 115261.093735, + "samples": [ + { + "round": 0, + "elapsed_ms": 145.1469300000026, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + }, + { + "round": 1, + "elapsed_ms": 101.51045399998839, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + }, + { + "round": 2, + "elapsed_ms": 97.06579300000158, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + } + ], + "resources": { + "elapsed_seconds": 150.173, + "cpu_seconds": 119.468013, + "peak_cgroup_bytes": 3019853824, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + }, + "timeout_repeat": { + "result_equivalent_to": "cohorts.final.timeout.result except preparation_ms and sample elapsed_ms", + "parent_evidence_id": "ev_ba7919ad7d538a41c183dfb5e27bb9dff6058a01b83fb583beebf4205c7c9939", + "trace_evidence_id": "ev_c95f2477bbc503d71094288ca11354fbb5bb0d8c86d26c7ea2b373a98458587f", + "facts_sha256": "70adc49dd7b9e13136c9ba3616a9a7210e86c2bacba734c329274f911e38458d", + "preparation_ms": 35470.4775, + "samples": [ + { + "round": 0, + "elapsed_ms": 144.9189419999966, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + }, + { + "round": 1, + "elapsed_ms": 103.62069399999746, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + }, + { + "round": 2, + "elapsed_ms": 101.42204499999934, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + } + ], + "resources": { + "elapsed_seconds": 58.827, + "cpu_seconds": 58.482996, + "peak_cgroup_bytes": 3098058752, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + }, + "control": { + "result_equivalent_to": "cohorts.final.control.result except preparation_ms and sample elapsed_ms", + "parent_evidence_id": "ev_11a21c98651e2f165e0a2a223734ceafb44ca8dcc0dd691647053237661b732a", + "trace_evidence_id": "ev_c70e3df14722c16822221309a873d064cb5772f644f0c537d6b3ec3dcee7e3ce", + "facts_sha256": "1ddcb621546636066ceea7f24b493ea1e2d2578f941ad96ba01bd11e98a673b4", + "preparation_ms": 39951.481265, + "samples": [ + { + "round": 0, + "elapsed_ms": 163.74327900000208, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + }, + { + "round": 1, + "elapsed_ms": 112.51611199999752, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + }, + { + "round": 2, + "elapsed_ms": 99.61466400000063, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + } + ], + "resources": { + "elapsed_seconds": 66.135, + "cpu_seconds": 65.681493, + "peak_cgroup_bytes": 3229392896, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + } + }, + "comparisons": { + "timeout": "Artifact/native identity, known-byte provenance, source selection, handoff targets/provider Evidence and nullable trace subject preserved. Corrected global provenance changes parent/trace identities; CLI/MCP parity is exact within each run. Source partial coverage preserved.", + "control": "Artifact/native identity, known-byte provenance, source selection, handoff targets/provider Evidence and nullable trace subject preserved. Corrected global provenance changes parent/trace identities; CLI/MCP parity is exact within each run. Source partial coverage preserved." + }, + "validation": { + "base_public": "Final public timeout case and cancellation case failed on native AST scopes;21 other cases passed. Corrected cancellation oracle then independently reproduced false native AST scope and phantom semantic module,16 controls passed.", + "review_oracle": "Six new passing cases use the actual retained Joplin baseline/final source-map snapshots and counterexamples: wrong metadata operation, entered instead of unvisited status, missing status, missing/empty/mixed scopes, and malformed explicit expectations. No production phase map is imported. 55 distinct passing cases across9files including original49; production source unchanged since pre_review_revision.", + "post_review_static_docs": "Passed on the strict verifier/helper/test changes, including5 consistency tests.", + "shared_boundary_focused": "78 distinct cases across10files passed after centralizing semantic applicability:9file run65/65 and original root reconstruction file13/13. Includes both full/incremental producer paths, all original49cases, six oracle regressions and23cases in the alternate-builder owning test file. No test deadline changed.", + "shared_boundary_static_docs": "Passed including5 consistency tests", + "initial_focused": "49 distinct passing cases across8files through documented invocations; first preprogress7file selection44/44; final7file selection43pass/1testdeadline, unchangednative+CLIcancellation rerun7/7 withone already-passed overlap. No test deadline raised.", + "final_focused": "78 distinct cases across10files passed after centralizing semantic applicability:9file run65/65 and original root reconstruction file13/13. Includes both full/incremental producer paths, all original49cases, six oracle regressions and23cases in the alternate-builder owning test file. No test deadline changed.", + "initial_static_docs": "Passed including5 consistency tests", + "static_docs": "Passed including5 consistency tests" + }, + "validation_resources": { + "preprogress_focused_44": { + "elapsed_seconds": 158.266, + "cpu_seconds": 156.15273, + "peak_cgroup_bytes": 3255263232, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "final_seven_files_43_pass_one_timeout": { + "elapsed_seconds": 286.914, + "cpu_seconds": 238.435334, + "peak_cgroup_bytes": 3164958720, + "payload_exit_code": 1, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "final_native_cli_cancellation_seven": { + "elapsed_seconds": 31.936, + "cpu_seconds": 31.543796, + "peak_cgroup_bytes": 1380851712, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "public_baseline_two_fail_21_pass": { + "elapsed_seconds": 56.508, + "cpu_seconds": 56.00798, + "peak_cgroup_bytes": 1448239104, + "payload_exit_code": 1, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "corrected_cancellation_baseline_one_fail_16_pass": { + "elapsed_seconds": 17.238, + "cpu_seconds": 16.905674, + "peak_cgroup_bytes": 675725312, + "payload_exit_code": 1, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "initial_public_baseline_one_fail_five_pass": { + "elapsed_seconds": 87.361, + "cpu_seconds": 70.256744, + "peak_cgroup_bytes": 1455607808, + "payload_exit_code": 1, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "npm_ci": { + "elapsed_seconds": 15.33, + "cpu_seconds": 15.091731, + "peak_cgroup_bytes": 1635868672, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "baseline_build": { + "elapsed_seconds": 41.23, + "cpu_seconds": 40.907387, + "peak_cgroup_bytes": 3223269376, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "initial_static_lint_length": { + "elapsed_seconds": 52.295, + "cpu_seconds": 36.748379, + "peak_cgroup_bytes": 2142298112, + "payload_exit_code": 1, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "assertion_cleanup_public": { + "elapsed_seconds": 40.818, + "cpu_seconds": 40.423137, + "peak_cgroup_bytes": 1475428352, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "final_static_docs": { + "elapsed_seconds": 165.553, + "cpu_seconds": 150.247257, + "peak_cgroup_bytes": 4232491008, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "review_oracle_six": { + "elapsed_seconds": 1.732, + "cpu_seconds": 1.541615, + "peak_cgroup_bytes": 209133568, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "post_review_static_docs": { + "elapsed_seconds": 111.395, + "cpu_seconds": 110.97971, + "peak_cgroup_bytes": 4347125760, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "full_builder_baseline_failure": { + "elapsed_seconds": 4.753, + "cpu_seconds": 4.55027, + "peak_cgroup_bytes": 490741760, + "payload_exit_code": 1, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "shared_boundary_focused": { + "elapsed_seconds": 260.67, + "cpu_seconds": 222.352926, + "peak_cgroup_bytes": 3058573312, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "shared_boundary_original_root_tests": { + "elapsed_seconds": 16.735, + "cpu_seconds": 15.157791, + "peak_cgroup_bytes": 692125696, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "shared_boundary_static_docs": { + "elapsed_seconds": 117.636, + "cpu_seconds": 117.194118, + "peak_cgroup_bytes": 4263153664, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + }, + "attempts": [ + { + "kind": "verifier-assumption failure", + "detail": "Initial real timeout verifier assumed trace.subject was non-null; partial Evidence legitimately preserved null. Removed this assumption and verified exported parent root_artifact_sha256. Not a product reproduction.", + "resources": { + "elapsed_seconds": 41.725, + "cpu_seconds": 41.52975, + "peak_cgroup_bytes": 1564684288, + "payload_exit_code": 1, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + }, + { + "kind": "preliminary structured-only timeout", + "detail": "Native path was outside caller source_paths, so native interruption was not reproduced; selected map/HTML/package AST misattribution was observed. Native-selected primary baseline is separate.", + "source_paths": [ + "ElectronAppWrapper.js", + "ElectronAppWrapper.js.map", + "index.html", + "package.json" + ], + "observed_native_interruption_scope_count": 0, + "resources": { + "elapsed_seconds": 79.507, + "cpu_seconds": 70.78951, + "peak_cgroup_bytes": 2725289984, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + }, + { + "kind": "oracle correction", + "detail": "Cancellation semantic nodes use identity.module_path. Initial top-level lookup was an invalid absence check; corrected before runtime edits. Corrected baseline proves both false native AST scope and phantom semantic module; actual first-JavaScript facts remain." + }, + { + "kind": "metadata trace delivery failure", + "detail": "Default source analysis completed, then the package.json outgoing trace exceeded stdio admission. This is not a completed equivalent task. Reproduced twice with identical parent/trace IDs and budget. Follow-up #4190.", + "resources": { + "elapsed_seconds": 53.594, + "cpu_seconds": 53.334504, + "peak_cgroup_bytes": 1640468480, + "payload_exit_code": 1, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "repeat_resources": { + "elapsed_seconds": 53.904, + "cpu_seconds": 53.665117, + "peak_cgroup_bytes": 1750102016, + "payload_exit_code": 1, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + }, + "public_reproduction": { + "runtime": { + "built_revision": "c7f6b8bad1a34d5efb30ff2a017672dea1fcdabb", + "js_files": 1627, + "dist_js_tree_sha256": "1aaa381d4ca46cf3ccf17904d7abcfee10f386a70f6d9c8344cc75a5557cd918", + "entry_sha256": "369813033dee10571a83c0656d90b5c8493270556896ddd079afb1bbe4b385ca", + "package_sha256": "cdb2fb0fd3a88790d921aadb560cac382fa360c821a2c3f6960bf75eff292ee8", + "verifier_sha256": "10335e8f8a87d01302a314af2ebd23505cb53af892984f89e376f158199e6f13" + }, + "query": { + "name": "trace_application_feature", + "arguments": { + "application": { + "kind": "retained-evidence", + "evidence_id": "ev_b1f947f72911e1a8c7faaca4fd70e084279b791ba3bf4d63bf0cfe87f2c63ed4" + }, + "native_observations": [], + "seed": { + "kind": "string", + "value": "package.json", + "match": "exact", + "case_sensitive": true + }, + "direction": "outgoing" + } + }, + "error": { + "code": "resource_constraint", + "category": "resource_constraint", + "message": "The operation completed, but its complete MCP response exceeds the stdio response budget. The analysis result was not truncated. Export retained evidence to consume the complete analysis, or use complete CLI JSON output.", + "retryable": false, + "remediation": { + "action": "Discover retained records with get_evidence_bundle and detail: summary, then inspect compatible records through inspect_analysis_view using an exact Evidence reference. Export complete retained session evidence through export_evidence_bundle to a caller-selected path, or use complete CLI JSON output. The connection remains usable." + }, + "details": { + "operation": "trace_application_feature", + "resource": "transport", + "reason": "The operation completed, but its complete MCP response exceeds the stdio response budget. The analysis result was not truncated. Export retained evidence to consume the complete analysis, or use complete CLI JSON output.", + "reported_limits": { + "boundary": "mcp-response", + "default_receive_buffer_bytes": 10485760, + "result_budget_bytes": 10484736, + "max_string_code_units": 536869864, + "response_bytes_at_least": 10587373, + "response_code_units_at_least": 10587373, + "constraint": "receive-buffer", + "evidence_id": "ev_64903e99c2a09d15abd0955b8ddcab0dd4fb01b5a6721c64d2308b3a105df5ac", + "evidence_reference": { + "kind": "retained-evidence", + "evidence_id": "ev_64903e99c2a09d15abd0955b8ddcab0dd4fb01b5a6721c64d2308b3a105df5ac" + } + } + } + } + } + }, + { + "kind": "test deadline", + "detail": "Final seven-file selection passed43 and hit the unchanged30s test deadline in the existing missing-companion native identity case. Same source/test deadline rerun passed both native cases and five CLI cancellation cases; final coverage49 distinct cases across8files. Original failure is retained." + }, + { + "kind": "static test-length failure", + "detail": "First full check stopped at lint: new public callback172lines exceeded150. Extracted a named Evidence assertion helper and consolidated scope observation lookup, retaining/strengthening assertions. Runtime/driver unchanged; targeted six-case file rerun and full gates recorded separately.", + "resources": { + "elapsed_seconds": 52.295, + "cpu_seconds": 36.748379, + "peak_cgroup_bytes": 2142298112, + "payload_exit_code": 1, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + }, + { + "kind": "test command rejected before execution", + "detail": "The development wrapper rejected built-project local mode or unsupported -t filter; no tests ran. The exact Vitest runner then reproduced the baseline on already-built runtime323fae8cb.", + "resources": { + "elapsed_seconds": 0.633, + "cpu_seconds": 0.390636, + "peak_cgroup_bytes": 42291200, + "payload_exit_code": 1, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + }, + { + "kind": "test command rejected before execution", + "detail": "The development wrapper rejected built-project local mode or unsupported -t filter; no tests ran. The exact Vitest runner then reproduced the baseline on already-built runtime323fae8cb.", + "resources": { + "elapsed_seconds": 0.422, + "cpu_seconds": 0.225054, + "peak_cgroup_bytes": 46489600, + "payload_exit_code": 1, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + } + ], + "cost_interpretation": { + "timeout_task": "One expected typed-timeout preparation plus one native and three structured-path inline retained traces, known paths/prior native Evidence supplied. Baseline wrong applicability is not successful task or efficiency credit.", + "control_task": "One default-deadline summary plus one inline native trace. Structured-path correctness additionally checked from complete private exported parent; this diagnostic work is outside modeled native-task tokens and inside total verifier resources. Do not compare this control cost to the four-query timeout task.", + "token_projection": "Count name/description/inputSchema catalog, requests and structured Evidence or parsed text error; complete-tool-reply alternative includes MCP text+structured duplication. Export/CLI parity/tokenizer/repeated native rounds are validation overhead outside the modeled task tokens, inside resources. Host output schemas/rendering/replay, notifications, model reasoning/final answers and billing unmeasured.", + "timing": "First preprogress fixed timeout150.173s wall/119.468013s CPU, exact repeat58.827s/58.482996s with identical non-timing facts/Evidence/BPE. Retain all runs. Cache/scheduler causes not established; no speedup or performance-equivalence claim. Final control186.085s wall/142.371100s CPU also repeated at62.651s/62.240964s with identical non-timing results. The slow final row remains reported; repeats do not replace it.", + "cache_conditions": "Each fresh MCP process follows stream hashing of the input, warming file cache. Build/OS caches and shared-host scheduling uncontrolled. Fresh process does not establish OS-cold conditions. First/repeated retained-query samples separately recorded; query CPU/memory unmeasured." + }, + "resource_policy": { + "hard_bytes": 8589934592, + "early_stop_bytes": 6442450944, + "cpu_quota_percent": 100, + "cpu_affinity": [15], + "pids_max": 192, + "swap": "disabled by observer scope", + "memory": "Process-family cgroup peak includes charged file cache, not summed RSS.", + "accounting": "Counters at payload exit while observer remains alive; not final whole-scope counters. Total verifier includes input hashing, preparation, repeated queries, export/CLI parity and tokenization. All completed receipts verify owned cleanup; no OOM." + }, + "observer_sources_sha256": { + "resource-run.py": "7728862171415e7dee2c11af2ead2b9a54265fccaf82a7113956d36b29065e33", + "resource_payload.py": "6f089e645459eba80c5d73e39c21606c78173a44daf49fabc3b88c4631ce51c6" + }, + "remaining_limits": [ + "Runtime Electron/application execution and real native-provider behavior NOT_ENOUGH_INFO; simulated Evidence is explicitly marked.", + "Windows/macOS runtime behavior and hosted-agent/model costs NOT_ENOUGH_INFO.", + "Normal broad metadata trace delivery remains #4190; complete export remains available.", + "Original applications and large Evidence are regenerable and are not archived." + ], + "final_control_repeat": { + "result_equivalent_to": "cohorts.final.control.result except preparation_ms and sample elapsed_ms", + "parent_evidence_id": "ev_11a21c98651e2f165e0a2a223734ceafb44ca8dcc0dd691647053237661b732a", + "trace_evidence_id": "ev_c70e3df14722c16822221309a873d064cb5772f644f0c537d6b3ec3dcee7e3ce", + "preparation_ms": 39787.412041999996, + "samples": [ + { + "round": 0, + "elapsed_ms": 155.13823799999955, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + }, + { + "round": 1, + "elapsed_ms": 97.110689000001, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + }, + { + "round": 2, + "elapsed_ms": 94.64593900000182, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + } + ], + "resources": { + "elapsed_seconds": 62.651, + "cpu_seconds": 62.240964, + "peak_cgroup_bytes": 2751827968, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + }, + "selected_test_files": [ + "tests/acceptance/applications/javascriptAnalysisLimits.test.ts", + "tests/boundary/javascript/javascriptApplicationCancellation.test.ts", + "tests/boundary/filesystem/javascriptArtifactReconstruction.test.ts", + "tests/boundary/filesystem/javascriptArtifactGraphObservationLookup.test.ts", + "tests/acceptance/applications/javascriptSourceSelectionCli.test.ts", + "tests/boundary/mcp/javascriptNativeHandoffIdentity.test.ts", + "tests/boundary/mcp/javascriptAnalysisResources.test.ts", + "tests/acceptance/applications/javascriptCancellationCli.test.ts", + "tests/boundary/process/javascriptVerifierScopeOracle.test.ts", + "tests/boundary/filesystem/javascript-applications/javascriptArtifactReconstruction.test.ts" + ], + "pre_review_revision": "04ca36ad86831e2d3639141bf41cd6994d8575d7", + "pre_review_source_sha256": { + "docs/javascript-artifact-reconstruction.md": "58c472f61537f7aeca477440712a44a12dc020554f966cfdf7d5c1ea71166895", + "scripts/verify/javascript/native-handoffs.mjs": "10335e8f8a87d01302a314af2ebd23505cb53af892984f89e376f158199e6f13", + "src/application/javascript/JavaScriptArtifactAnalysis.ts": "dc0cc638ac7e8163efbe779f97bd9e945ef43688f71dc2c365de6439cc1823e6", + "src/application/javascript/JavaScriptArtifactAnalysisTypes.ts": "4569780dcaff8e783b3169770473373d202e3a8d558e5ea03df88cd3f6853bf7", + "src/application/javascript/JavaScriptArtifactGraphContext.ts": "b1e486b5b29f15466b033464780fc57d5619506aad94f4c5053e1882c4bd30d2", + "src/application/javascript/JavaScriptArtifactGraphEvidence.ts": "4ac2d6c95011ee6a86ef79b3477557fd296df1ebb84e57ebb3d359848ca92cc3", + "src/application/javascript/JavaScriptArtifactGraphStructure.ts": "167be12f869088aeab0e521d6e85ee11348b40f15d5a24dff3030d8dec39b8a3", + "src/application/javascript/JavaScriptArtifactReconstruction.ts": "583e14e34c5f4d2d6118f2dc750862b86f656bf2d98cca5b28fad2620168308c", + "tests/acceptance/applications/javascriptAnalysisLimits.test.ts": "25ea7addf365c3ab992d1f24d65d57b02655033e28b2b100406c9c90712064c7", + "tests/boundary/filesystem/javascriptArtifactReconstruction.test.ts": "bdb6dc9fd8a9921e956d01017ac9d32a499b3815f0611929185add7e42c5ba37", + "tests/boundary/javascript/javascriptApplicationCancellation.test.ts": "c604554072e6f848c24926b8630a738b9247ccd04b337374e8060cfb6a0a069f" + }, + "post_review_strict_controls": { + "timeout": { + "result_equivalent_to": "cohorts.final.timeout.result except timing and the newly recorded independent structured_expectations input", + "structured_expectations": { + "ElectronAppWrapper.js.map": { + "operation": "parse-local-source-map", + "analysis_status": "not-started" + }, + "index.html": { + "operation": "parse-html-script-references", + "analysis_status": "not-started" + }, + "package.json": { + "operation": "parse-package-json", + "analysis_status": "not-started" + } + }, + "parent_evidence_id": "ev_ba7919ad7d538a41c183dfb5e27bb9dff6058a01b83fb583beebf4205c7c9939", + "trace_evidence_id": "ev_c95f2477bbc503d71094288ca11354fbb5bb0d8c86d26c7ea2b373a98458587f", + "facts_sha256": "70adc49dd7b9e13136c9ba3616a9a7210e86c2bacba734c329274f911e38458d", + "safe_identity": true, + "safe_applicability": true, + "preparation_ms": 126809.012247, + "samples": [ + { + "round": 0, + "elapsed_ms": 140.7263250000251, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + }, + { + "round": 1, + "elapsed_ms": 89.8889719999861, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + }, + { + "round": 2, + "elapsed_ms": 87.59898199999589, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + } + ], + "resources": { + "elapsed_seconds": 162.645, + "cpu_seconds": 125.876114, + "peak_cgroup_bytes": 2809643008, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + }, + "control": { + "result_equivalent_to": "cohorts.final.control.result except timing and the newly recorded independent structured_expectations input", + "structured_expectations": { + "ElectronAppWrapper.js.map": { + "operation": "parse-local-source-map", + "analysis_status": "not-started" + }, + "index.html": { + "operation": "parse-html-script-references", + "analysis_status": "not-started" + }, + "package.json": { + "operation": "parse-package-json", + "analysis_status": "not-started" + } + }, + "parent_evidence_id": "ev_11a21c98651e2f165e0a2a223734ceafb44ca8dcc0dd691647053237661b732a", + "trace_evidence_id": "ev_c70e3df14722c16822221309a873d064cb5772f644f0c537d6b3ec3dcee7e3ce", + "facts_sha256": "1ddcb621546636066ceea7f24b493ea1e2d2578f941ad96ba01bd11e98a673b4", + "safe_identity": true, + "safe_applicability": true, + "preparation_ms": 38557.169505, + "samples": [ + { + "round": 0, + "elapsed_ms": 145.8823429999975, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + }, + { + "round": 1, + "elapsed_ms": 96.55243199999677, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + }, + { + "round": 2, + "elapsed_ms": 96.86316200000147, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + } + ], + "resources": { + "elapsed_seconds": 61.367, + "cpu_seconds": 60.970077, + "peak_cgroup_bytes": 2526949376, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + } + }, + "review_oracle": { + "thread": "https://github.com/morluto/rea/pull/4207#discussion_r4287026723", + "root_cause": "The real verifier previously rejected JavaScript operation names but accepted any other metadata operation and ignored analysis_status. That could falsely accept the wrong metadata phase.", + "correction": "Scenario supplies independent per-path exact operation/status expectations. Every retained gap must also have artifact-bytes authority, unavailable state and unknown confidence. Missing expectations, empty gap sets and any conflicting observation fail.", + "runtime_change": "None in this review correction. Original analytical observations, identities, coverage, token projections and CLI/MCP parity match exactly in both strict reruns; timing receipts are additional runs and do not replace the slower original rows.", + "initial_ci_failure": "At pre_review_revision,36 checks succeeded; Apple fixture hdiutil create failed before REA verification, causing aggregate CI required failure. Apple fixture/workflow code is unchanged; no Apple coverage pass claimed for that attempt." + }, + "pre_shared_boundary_revision": "323fae8cbf3e36677bcb7b22ba31fa1a7e3c5cd4", + "pre_shared_boundary_source_sha256": { + "docs/javascript-artifact-reconstruction.md": "58c472f61537f7aeca477440712a44a12dc020554f966cfdf7d5c1ea71166895", + "scripts/verify/javascript/native-handoffs.mjs": "1795c183370ed8289eb961da470073530ccbdbb46599d4a8966881639b219155", + "src/application/javascript/JavaScriptArtifactAnalysis.ts": "dc0cc638ac7e8163efbe779f97bd9e945ef43688f71dc2c365de6439cc1823e6", + "src/application/javascript/JavaScriptArtifactAnalysisTypes.ts": "4569780dcaff8e783b3169770473373d202e3a8d558e5ea03df88cd3f6853bf7", + "src/application/javascript/JavaScriptArtifactGraphContext.ts": "b1e486b5b29f15466b033464780fc57d5619506aad94f4c5053e1882c4bd30d2", + "src/application/javascript/JavaScriptArtifactGraphEvidence.ts": "4ac2d6c95011ee6a86ef79b3477557fd296df1ebb84e57ebb3d359848ca92cc3", + "src/application/javascript/JavaScriptArtifactGraphStructure.ts": "167be12f869088aeab0e521d6e85ee11348b40f15d5a24dff3030d8dec39b8a3", + "src/application/javascript/JavaScriptArtifactReconstruction.ts": "583e14e34c5f4d2d6118f2dc750862b86f656bf2d98cca5b28fad2620168308c", + "tests/acceptance/applications/javascriptAnalysisLimits.test.ts": "25ea7addf365c3ab992d1f24d65d57b02655033e28b2b100406c9c90712064c7", + "tests/boundary/filesystem/javascriptArtifactReconstruction.test.ts": "bdb6dc9fd8a9921e956d01017ac9d32a499b3815f0611929185add7e42c5ba37", + "tests/boundary/javascript/javascriptApplicationCancellation.test.ts": "c604554072e6f848c24926b8630a738b9247ccd04b337374e8060cfb6a0a069f", + "scripts/lib/javascript-file-scope-oracle.mjs": "e36f0aa114c7c2d2a2e9657f5ef7119f179d7bd6ba4ef899d0fc9ee67b4b7b07", + "scripts/lib/javascript-file-scope-oracle.d.mts": "f3ac21ce936613d650fa6d610b9905406ae02a0afa97afd677b5b11377369134", + "tests/boundary/process/javascriptVerifierScopeOracle.test.ts": "e94c3659b660482aaf75652a60440916f58921c97c4b9bc3182e647a505a2b6b" + }, + "post_shared_boundary_controls": { + "timeout": { + "result_equivalent_to": "cohorts.final.timeout.result except timing and the explicit structured_expectations oracle input", + "structured_expectations": { + "ElectronAppWrapper.js.map": { + "operation": "parse-local-source-map", + "analysis_status": "not-started" + }, + "index.html": { + "operation": "parse-html-script-references", + "analysis_status": "not-started" + }, + "package.json": { + "operation": "parse-package-json", + "analysis_status": "not-started" + } + }, + "parent_evidence_id": "ev_ba7919ad7d538a41c183dfb5e27bb9dff6058a01b83fb583beebf4205c7c9939", + "trace_evidence_id": "ev_c95f2477bbc503d71094288ca11354fbb5bb0d8c86d26c7ea2b373a98458587f", + "facts_sha256": "70adc49dd7b9e13136c9ba3616a9a7210e86c2bacba734c329274f911e38458d", + "safe_identity": true, + "safe_applicability": true, + "preparation_ms": 36108.770459, + "samples": [ + { + "round": 0, + "elapsed_ms": 145.29439700000512, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + }, + { + "round": 1, + "elapsed_ms": 93.87837699999363, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + }, + { + "round": 2, + "elapsed_ms": 93.54142800000409, + "structured_reply_bytes": 9654, + "full_tool_reply_bytes": 20161 + } + ], + "resources": { + "elapsed_seconds": 60.443, + "cpu_seconds": 59.970344, + "peak_cgroup_bytes": 3078295552, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + }, + "control": { + "result_equivalent_to": "cohorts.final.control.result except timing and the explicit structured_expectations oracle input", + "structured_expectations": { + "ElectronAppWrapper.js.map": { + "operation": "parse-local-source-map", + "analysis_status": "not-started" + }, + "index.html": { + "operation": "parse-html-script-references", + "analysis_status": "not-started" + }, + "package.json": { + "operation": "parse-package-json", + "analysis_status": "not-started" + } + }, + "parent_evidence_id": "ev_11a21c98651e2f165e0a2a223734ceafb44ca8dcc0dd691647053237661b732a", + "trace_evidence_id": "ev_c70e3df14722c16822221309a873d064cb5772f644f0c537d6b3ec3dcee7e3ce", + "facts_sha256": "1ddcb621546636066ceea7f24b493ea1e2d2578f941ad96ba01bd11e98a673b4", + "safe_identity": true, + "safe_applicability": true, + "preparation_ms": 39018.51578, + "samples": [ + { + "round": 0, + "elapsed_ms": 155.72985699999845, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + }, + { + "round": 1, + "elapsed_ms": 96.90781799999968, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + }, + { + "round": 2, + "elapsed_ms": 94.82594799999788, + "structured_reply_bytes": 9835, + "full_tool_reply_bytes": 20513 + } + ], + "resources": { + "elapsed_seconds": 63.574, + "cpu_seconds": 63.177884, + "peak_cgroup_bytes": 3189719040, + "payload_exit_code": 0, + "payload_cleanup_verified": true, + "events_at_payload_exit": { + "memory.events": { + "low": 0, + "high": 0, + "max": 0, + "oom": 0, + "oom_kill": 0, + "oom_group_kill": 0 + }, + "pids.events": { + "max": 0 + } + } + } + } + }, + "measurement_source_ownership": { + "cohorts.baseline": "base_revision runtime; baseline_execution_driver_sources identifies supplied verifier versions", + "cohorts.final": "pre_review_revision runtime and pre_review_source_sha256", + "post_review_strict_controls": "pre_shared_boundary_revision; pre_shared_boundary_source_sha256", + "post_shared_boundary_controls": "Current final_source_sha256, after the shared semantic boundary correction" + }, + "shared_semantic_boundary_review": { + "thread": "https://github.com/morluto/rea/pull/4207#discussion_r4287280551", + "observed_baseline": "Actual artifact reader + full analysis + application/semantic graph builders with source_paths=[a.js] created semantic modules for five excluded non-JavaScript kinds: native-addon, JSON, HTML, package-json and source-map. Selected a.js and excluded b.js are positive controls. Baseline regression failed with all7 paths instead of only2 JavaScript paths.", + "root_cause": "Incremental callers guarded semantic applicability individually; the full builder called the same projection without that guard.", + "structural_fix": "The semantic projection recordUnavailableFile entry point now ignores non-JavaScript file kinds before retaining limits, nodes, roots or unknowns. Both construction paths use it; removed3 duplicate caller-side checks. Actual excluded JavaScript continues to produce partial semantic coverage and source-bound unknowns.", + "verification_limits": "Real Joplin controls exercise public incremental CLI/MCP workflows. The alternate full-builder path is verified through the actual filesystem producer boundary, not a separately measured full-builder real-app workflow." + }, + "intermediate_ci": { + "revision": "323fae8cbf3e36677bcb7b22ba31fa1a7e3c5cd4", + "successful_checks": 39, + "apple_fixture": "Passed without Apple code/workflow changes; initial04ca attempt remains recorded", + "final_revision_checks": "Pending after shared semantic boundary correction" + } +} diff --git a/docs/verification/javascript-interruption-applicability-2026-10-15.md b/docs/verification/javascript-interruption-applicability-2026-10-15.md new file mode 100644 index 0000000000..3b63974932 --- /dev/null +++ b/docs/verification/javascript-interruption-applicability-2026-10-15.md @@ -0,0 +1,245 @@ +# Interrupted application processing: applicability and Evidence + +Tracks #3948 under #4027. Measured baseline: +`c7f6b8bad1a34d5efb30ff2a017672dea1fcdabb`. + +The question is which processing phases remain unavailable after a source +interruption, while keeping native inventory and already collected facts. +Native identity and provider linkage must stay independent of application-wide +partial coverage. This is static artifact analysis; no target application or +native provider runs. + +## Observed failure and correction + +The interruption producer previously attached one generic failure to every +remaining relevant file. Graph projection interpreted it as JavaScript AST work. +Real Joplin reproduced an `analyze-javascript-source` / `ast-static-analysis` +unavailable scope on keytar's native binary and on unvisited package, HTML and +source-map files. Public CLI/MCP controls reproduced the same applicability +problem. Deterministic cancellation before native metadata additionally produced +a phantom JavaScript semantic module for the binary. + +The producer now records the applicable operation/authority and whether the +phase was entered. `analysis_status: interrupted` includes worker startup and +does not imply parsing completed; `not-started` identifies unvisited phases. +Native add-ons need no post-inventory source-processing phase, so neither interrupted +nor caller-excluded native files acquire AST scopes or semantic modules. +Actual JavaScript failures, structured-file unknowns, caller selection and byte +identity remain available. The graph consumes these produced facts. + +The AST-only unavailable Evidence helper is replaced by an explicitly typed +static helper. Normal package/JSON/map gaps also retain their artifact-byte +authority. Per-file progress uses the same applicability owner: JavaScript keeps +its source phase, and metadata uses `process_javascript_artifact_metadata`. +Remaining parsers do not run after interruption. Failure sharing is limited to +five applicable phases during one interruption; no persistent cache is added. + +A second review found the alternate full-analysis semantic builder still +created modules for every excluded file kind. An actual filesystem-producer +regression on revision `323fae8cbf3e36677bcb7b22ba31fa1a7e3c5cd4` reproduced +phantom native/JSON/HTML/package/source-map modules, while selected and excluded +JavaScript were positive controls. Semantic applicability now belongs to the +shared `recordUnavailableFile` projection entry point, before retaining limits, +nodes, roots or unknowns. Three duplicate caller checks are removed. Both full +and incremental construction use this boundary; actual excluded JavaScript +continues to carry source-bound unknowns and partial semantic coverage. + +## Real input and reproduction + +Use the [official Joplin v3.7.21 acquisition and extraction instructions](https://github.com/morluto/rea/blob/c7f6b8bad1a34d5efb30ff2a017672dea1fcdabb/docs/verification/javascript-native-handoff-identity-2026-10-15.md). +The AppImage SHA-256 is +`5d202dcaca31e14206826aa3f04125e7c218dbc3dc3d98479d811efbd6b856c1`; +ASAR SHA-256 is +`767df409b18effe60421fbefcca873de237c7e813eac744ecdeebbc5e825a33a`. +The 6,324-file inventory includes 46 unpacked entries. Both cohorts stage all +three native companions; the other 43 unpacked entries remain unavailable. + +Build with pinned Node 24.18.0/npm 11.16.0 and locked dependencies. The extended +existing verifier also runs against the baseline runtime; copy the verifier and +`scripts/lib/javascript-file-scope-oracle.mjs` from the fixed revision into a +built baseline checkout when reproducing the failure. + +```bash +artifact_path="/absolute/path/to/cases/available/app.asar" +common=( + --artifact "$artifact_path" + --addon-path node_modules/keytar/build/Release/keytar.node + --native-sha256 0700016bcd761cbe02d275f2046c7cc42f39f730a50d66e3d3307aa9d413373a + --source-path ElectronAppWrapper.js + --source-path ElectronAppWrapper.js.map + --source-path index.html + --source-path package.json + --source-path node_modules/keytar/build/Release/keytar.node + --structured-path ElectronAppWrapper.js.map + --structured-path index.html + --structured-path package.json + --structured-expectations '{"ElectronAppWrapper.js.map":{"operation":"parse-local-source-map","analysis_status":"not-started"},"index.html":{"operation":"parse-html-script-references","analysis_status":"not-started"},"package.json":{"operation":"parse-package-json","analysis_status":"not-started"}}' + --rounds 3 --cli-parity + --tokenizer-python /absolute/path/to/python-with-tiktoken-0.12.0 +) +node scripts/verify/javascript/native-handoffs.mjs "${common[@]}" \ + --analysis-timeout-ms 1 --expect-timeout --require-safe +node scripts/verify/javascript/native-handoffs.mjs "${common[@]}" \ + --validate-structured-from-export --require-safe +``` + +Omit `--require-safe` on the baseline timeout run to record its incorrect +applicability. Its diagnostic exit 0 is not a passing analyst task. A supported +1 ms deadline includes worker startup; the verifier requires a typed timeout +and retained partial reference for that cohort. Each structured path supplies an +independent expected operation and phase-entry status; the safety oracle matches +all gaps exactly, including unavailable state and unknown confidence. Missing or +conflicting expectations do not pass. + +The native path is explicitly selected. An earlier structured-only run excluded +it and therefore did not reproduce the native interruption. Input selections +and that preliminary result remain recorded. Both final cohorts preserve +partial coverage for unselected/unavailable scopes. + +The supplied native Evidence is simulated solely to check exact subject linkage. +The verifier checks physical companion bytes and the exported parent's root +digest, validates public CLI/MCP native-trace parity, and reports only after +owned transport/command/private-file cleanup. Applications and large Evidence +are regenerable and are not archived. + +## Two distinct task projections + +The **timeout task** includes the expected typed-timeout preparation, one inline +native trace and three inline structured-path traces. It checks that native has +no AST failure and that each unvisited structured phase remains unavailable with +the appropriate artifact-byte authority and `not-started` status. + +The **default-deadline control** models the summary plus one inline native trace. +Its named structured paths are additionally validated from the already exported +complete parent, explicitly labelled `exported-parent-validation`. Those checks +are diagnostic overhead outside the modeled native-task tokens and inside total +verifier resources. They are not presented as inline metadata answers. + +A control that also requested the complete outgoing `package.json` feature trace +hit stdio admission twice: at least 10,587,373 bytes against a 10,484,736-byte +result budget, with identical retained parent/trace identities. It is not a +completed equivalent task or an efficiency baseline. [#4190](https://github.com/morluto/rea/issues/4190) +records the separate need for exact retained metadata/native fact views. Complete +export remains available. Do not compare costs across these different tasks. + +## Measurements + +| Cohort | Revision | Wall s | CPU s | Peak cgroup bytes | Applicability | +| ------------------------------ | -------- | ------: | ---------: | ----------------: | ------------- | +| Timeout, four inline traces | baseline | 60.738 | 60.289464 | 3,092,045,824 | wrong scope | +| Timeout, four inline traces | final | 57.515 | 57.089883 | 2,763,276,288 | pass | +| Default control, native inline | baseline | 61.542 | 61.135522 | 2,808,336,384 | pass | +| Default control, native inline | final | 186.085 | 142.371100 | 2,959,585,280 | pass | + +| Defined task | Selected catalog + parsed/structured replies BPE | Selected catalog + complete tool replies BPE | +| -------------- | -----------------------------------------------: | -------------------------------------------: | +| Timeout | 21,136 → 20,161 | 36,468 → 34,471 | +| Native control | 11,776 → 11,720 | 17,738 → 17,632 | + +The full-catalog alternatives and per-query samples are preserved in JSON. +Native content identity, observed byte provenance, source selection and handoff +provider Evidence remain equal. Corrected global provenance changes derived +parent/trace identities; null partial-Evidence subjects remain null. Both final +runs have exact CLI/MCP native-trace parity and match the earlier post-fix +controls in every recorded non-timing field. + +The whole verifier includes input hashing, analysis, three native trace rounds, +applicable structured queries, export, CLI parity and tokenization. Every heavy +run uses the preserved [resource observer](https://github.com/morluto/rea/blob/b3bdabab694af1f9801eff7caf75001b92314a58/experiments/analysis-efficiency/resource-run.py): +one CPU, 8 GiB hard cap, 6 GiB early stop and no swap. Cgroup peaks include charged +file cache, not summed RSS. Counters are observed at payload exit while the +observer remains alive, not final whole-scope counters. Completed runs verify +owned cleanup and report no OOM. + +Each MCP process is fresh, but input hashing warms its file cache. Build/OS caches +and shared-host scheduling are uncontrolled. First and repeated retained-query +wall samples remain separate; isolated query CPU/memory are unmeasured. An +earlier fixed timeout took 150.173 s wall / 119.468013 s CPU; its exact unchanged +runtime repeat took 58.827 s / 58.482996 s, with identical non-timing facts, +Evidence and BPE. Both receipts are retained. The final default control also took 186.085 s wall / 142.371100 s CPU; its +unchanged-runtime repeat took 62.651 s / 62.240964 s with identical non-timing +results. The slow final row remains reported. Attribution remains unresolved; +these runs establish no speedup or performance-equivalence bound. + +The stricter post-review verifier reruns also passed without changing production +code: timeout 162.645 s wall / 125.876114 s CPU / 2,809,643,008 B peak; default +control 61.367 s / 60.970077 s / 2,526,949,376 B. Both preserve the original final +analytical fields, identities, coverage and BPE exactly; only timings and the new +explicit oracle-input field differ. These additional receipts do not replace the +slower rows above. + +After centralizing semantic applicability, both real public controls passed again: +timeout 60.443 s wall / 59.970344 s CPU / 3,078,295,552 B peak; default control +63.574 s / 63.177884 s / 3,189,719,040 B. Analytical results, identities, coverage, +BPE and exact CLI/MCP parity remain unchanged. JSON identifies the runtime and +verifier source manifests for each cohort and keeps all earlier receipts. + +Static `cl100k_base`/tiktoken 0.12.0 projections include the selected or complete +name/description/inputSchema catalog, requests and structured Evidence or parsed +text errors. Complete-tool-reply alternatives include MCP text/structured +duplication. The selected two-tool catalog is 5,570 BPE; the complete projection +is 195,522. Output schemas, host rendering/replay, notifications, model reasoning, +final answers and billing are unmeasured. Repeated rounds, export, CLI parity, +tokenization and exported-parent diagnostics are validation overhead outside the +defined task tokens but inside resource receipts. Removing unsupported claims +from the incorrect timeout baseline earns no efficiency credit. + +## Verification and limitations + +The initial production fix had 49 distinct passing cases across eight files. The initial +pre-progress-cleanup seven-file selection passed 44/44. After progress cleanup, +the same selection passed 43 and hit the existing 30-second test deadline in one +native identity case; an unchanged two-file rerun passed both native cases and +five public CLI cancellation cases. The original deadline was not increased. +The runtime verifier collects interruption-bearing scopes; separate regressions +cover native caller exclusion and malformed structured data. Source selection, +malformed structures, actual worker resource constraints, +retained large partial observations, cancellation/publication/cleanup, native +identity and both public adapters remain covered. + +The first review found that the real verifier previously accepted any non-JavaScript +operation with artifact-byte authority and ignored phase-entry status. The +scenario now supplies exact operation/status expectations independently of the +production phase map. Six additional oracle cases use the actual retained +Joplin snapshots and reject wrong metadata operations, entered or missing +statuses, and absent or conflicting gaps. They passed, bringing the distinct +coverage to 55 cases across nine files. The production implementation did not +change during this review correction. + +After the shared semantic-boundary correction from the second review, 78 +distinct cases passed across ten files: the nine-file selection passed 65/65, +and the original root reconstruction file passed 13/13. This includes the +alternate-builder owning test file's 23 cases. The new producer-boundary +regression checks both construction paths, all five excluded metadata/native +kinds, and selected/excluded JavaScript controls. Real Joplin controls exercise +the public incremental workflow; the alternate full-builder path has filesystem +boundary verification rather than a separately measured real-app workflow. + +Recorded attempts also include the verifier's initial non-null-subject assumption +and an invalid top-level semantic-module-path absence check. Both were corrected +before their assertions were used as proof. Corrected cancellation reproduction +shows the actual native AST scope and phantom module on the baseline. Final +source and execution-driver versions, source pins, input digests, prior attempts +and resource receipts are in the [compact JSON record](javascript-interruption-applicability-2026-10-15.json). + +Before review, `npm run check && npm run docs:check` passed, including five consistency +tests: 165.553 s wall / 150.247257 s CPU / +4,232,491,008 B peak cgroup memory, clean owned exit and no OOM. +The first full check stopped on a 172-line test callback exceeding the 150-line +rule. A named assertion helper now shares scope lookup across all four public +results; the strengthened six-case file passed again before the final gates. +After the review correction, the full static/docs gate passed again, including +the five consistency tests: 111.395 s wall / 110.979710 s CPU / +4,347,125,760 B peak, with clean owned exit and no OOM. +After centralizing semantic applicability, the final full static/docs gate also +passed, including five consistency tests: 117.636 s wall / 117.194118 s CPU / +4,263,153,664 B peak, clean owned exit and no OOM. + +At the initial PR revision, 36 CI checks passed; macOS `hdiutil create` failed +while creating its DMG fixture before REA verification, also failing the aggregate +check. No Apple fixture/workflow code changed. That attempt provides no passing +Apple runtime evidence. + +Live Electron/application execution, real native-provider behavior, other-platform +runtime coverage and hosted-agent costs are **NOT_ENOUGH_INFO**. The verification +does not claim them. diff --git a/scripts/lib/javascript-file-scope-oracle.d.mts b/scripts/lib/javascript-file-scope-oracle.d.mts new file mode 100644 index 0000000000..89676bb6eb --- /dev/null +++ b/scripts/lib/javascript-file-scope-oracle.d.mts @@ -0,0 +1,28 @@ +import type { z } from "zod"; + +export interface StructuredScopeExpectation { + readonly operation: + | "parse-package-json" + | "parse-json-module" + | "parse-html-script-references" + | "parse-local-source-map"; + readonly analysis_status: "interrupted" | "not-started"; +} + +export interface StructuredProcessingScope { + readonly properties: Readonly>; + readonly evidence: { + readonly authority: string; + readonly state: string; + readonly confidence: string; + }; +} + +export const structuredScopeExpectationsSchema: z.ZodType< + Record +>; + +export function matchesStructuredScopeExpectation( + scopes: readonly StructuredProcessingScope[], + expected: StructuredScopeExpectation | undefined, +): boolean; diff --git a/scripts/lib/javascript-file-scope-oracle.mjs b/scripts/lib/javascript-file-scope-oracle.mjs new file mode 100644 index 0000000000..f2f85906e9 --- /dev/null +++ b/scripts/lib/javascript-file-scope-oracle.mjs @@ -0,0 +1,28 @@ +import { z } from "zod"; + +/** Independent expected outcomes supplied by the verification scenario. */ +export const structuredScopeExpectationsSchema = z.record( + z.string().min(1), + z.strictObject({ + operation: z.enum([ + "parse-package-json", + "parse-json-module", + "parse-html-script-references", + "parse-local-source-map", + ]), + analysis_status: z.enum(["interrupted", "not-started"]), + }), +); + +/** Every retained gap must match the named phase and its unavailable status. */ +export const matchesStructuredScopeExpectation = (scopes, expected) => + expected !== undefined && + scopes.length > 0 && + scopes.every( + ({ evidence, properties }) => + evidence.authority === "artifact-bytes" && + evidence.state === "unavailable" && + evidence.confidence === "unknown" && + properties.operation === expected.operation && + properties.analysis_status === expected.analysis_status, + ); diff --git a/scripts/verify/javascript/native-handoffs.mjs b/scripts/verify/javascript/native-handoffs.mjs index 4ee67aa7c1..2a233e1bd3 100644 --- a/scripts/verify/javascript/native-handoffs.mjs +++ b/scripts/verify/javascript/native-handoffs.mjs @@ -17,6 +17,10 @@ import { runOwnedCommand, } from "../../../dist/process/OwnedCommand.js"; import { closeVerifierResources } from "../../lib/verifier-cleanup.mjs"; +import { + matchesStructuredScopeExpectation, + structuredScopeExpectationsSchema, +} from "../../lib/javascript-file-scope-oracle.mjs"; const { values } = parseArgs({ options: { @@ -24,6 +28,11 @@ const { values } = parseArgs({ "addon-path": { type: "string" }, "native-sha256": { type: "string" }, "source-path": { type: "string", multiple: true }, + "structured-path": { type: "string", multiple: true }, + "structured-expectations": { type: "string" }, + "validate-structured-from-export": { type: "boolean", default: false }, + "analysis-timeout-ms": { type: "string" }, + "expect-timeout": { type: "boolean", default: false }, rounds: { type: "string", default: "3" }, "cli-parity": { type: "boolean", default: false }, "tokenizer-python": { type: "string" }, @@ -50,6 +59,30 @@ assert.match( ); const rounds = Number(values.rounds); assert.ok(Number.isSafeInteger(rounds) && rounds > 0); +const analysisTimeoutMs = + values["analysis-timeout-ms"] === undefined + ? undefined + : Number(values["analysis-timeout-ms"]); +assert.ok( + analysisTimeoutMs === undefined || + (Number.isSafeInteger(analysisTimeoutMs) && analysisTimeoutMs > 0), +); +assert.ok(!values["expect-timeout"] || analysisTimeoutMs !== undefined); +assert.ok(!values["validate-structured-from-export"] || values["cli-parity"]); +const structuredExpectations = structuredScopeExpectationsSchema.parse( + JSON.parse(values["structured-expectations"] ?? "{}"), +); +for (const path of Object.keys(structuredExpectations)) + assert.ok( + values["structured-path"]?.includes(path), + `Expected structured path was not selected for verification: ${path}`, + ); +if (values["expect-timeout"]) + for (const path of values["structured-path"] ?? []) + assert.ok( + Object.hasOwn(structuredExpectations, path), + `--structured-expectations must name the expected operation/status for ${path}`, + ); const environment = { PATH: process.env.PATH ?? "/usr/bin:/bin", REA_LOG_LEVEL: "silent", @@ -139,30 +172,55 @@ try { ), ); assert.equal(selected.length, 2); - const call = async (name, arguments_) => { + const call = async (name, arguments_, allowTimeout = false) => { const response = await client.callTool( { name, arguments: arguments_ }, { timeout: 360_000 }, ); - assert.notEqual(response.isError, true, serialize(response)); - assert.ok(response.structuredContent?.evidence_id); + let projection = response.structuredContent; + if (response.isError === true) { + assert.ok( + allowTimeout, + serialize({ name, arguments: arguments_, response }), + ); + const text = response.content.find(({ type }) => type === "text"); + assert.ok(text?.type === "text"); + projection = JSON.parse(text.text); + assert.equal(projection.error.code, "provider_timeout"); + assert.equal( + projection.error.details.partial_observation.kind, + "retained-evidence", + ); + } else assert.ok(projection?.evidence_id); return { request: { name, arguments: arguments_ }, - response: response.structuredContent, + response: projection, wire_response: response, }; }; const prepStart = performance.now(); - const preparation = await call("analyze_javascript_application", { - input_path: values.artifact, - detail: "summary", - ...(values["source-path"] === undefined - ? {} - : { source_paths: values["source-path"] }), - }); + const preparation = await call( + "analyze_javascript_application", + { + input_path: values.artifact, + detail: "summary", + ...(analysisTimeoutMs === undefined + ? {} + : { analysis_timeout_ms: analysisTimeoutMs }), + ...(values["source-path"] === undefined + ? {} + : { source_paths: values["source-path"] }), + }, + values["expect-timeout"], + ); const preparationMs = performance.now() - prepStart; - assert.equal(preparation.response.subject.digest.sha256, archiveSha256); - const sourceId = preparation.response.normalized_result.parent_evidence_id; + const timedOut = preparation.wire_response.isError === true; + assert.equal(timedOut, values["expect-timeout"]); + if (!timedOut) + assert.equal(preparation.response.subject.digest.sha256, archiveSha256); + const sourceId = timedOut + ? preparation.response.error.details.partial_observation.evidence_id + : preparation.response.normalized_result.parent_evidence_id; assert.match(sourceId, /^ev_[a-f0-9]{64}$/); const query = { application: { kind: "retained-evidence", evidence_id: sourceId }, @@ -221,6 +279,38 @@ try { trace.native_handoffs[0].status === "evidence-linked" && serialize(trace.native_handoffs[0].evidence_ids) === serialize([native.evidence_id])); + const analysisScopes = (result, path) => + result.graph.nodes.flatMap((node) => + node.kind !== "unknown" + ? [] + : node.observations.flatMap((observation) => + observation.properties.path === path && + observation.properties.analysis_failure !== undefined + ? [{ node_id: node.node_id, ...observation }] + : [], + ), + ); + const nativeScopes = analysisScopes(trace, values["addon-path"]); + const structuredQueries = []; + const structuredScopes = []; + for (const path of values["validate-structured-from-export"] + ? [] + : (values["structured-path"] ?? [])) { + const result = await call("trace_application_feature", { + ...query, + native_observations: [], + seed: { ...query.seed, value: path }, + }); + structuredQueries.push(result); + structuredScopes.push({ + source: "retained-feature-trace", + path, + scopes: analysisScopes(result.response.normalized_result, path), + evidence_id: result.response.evidence_id, + source_coverage: result.response.normalized_result.coverage, + graph_coverage: result.response.normalized_result.graph.coverage, + }); + } let cliParity = null; if (values["cli-parity"]) { temporary = await PrivateRuntimeRoot.create({ @@ -237,6 +327,25 @@ try { ({ evidence_id }) => evidence_id === sourceId, ); assert.ok(parent, "Export omitted the retained parent"); + assert.equal(parent.normalized_result.root_artifact_sha256, archiveSha256); + if (values["validate-structured-from-export"]) + for (const path of values["structured-path"] ?? []) { + const retained = parent.normalized_result; + const matchingNodes = retained.graph.nodes.filter((node) => + node.observations.some(({ properties }) => properties.path === path), + ); + assert.ok(matchingNodes.length > 0, `Missing retained path: ${path}`); + // Diagnostic validation of the complete backend record is distinct + // from the inline native analyst task used by this control's tokens. + structuredScopes.push({ + source: "exported-parent-validation", + path, + scopes: analysisScopes(retained, path), + source_evidence_id: parent.evidence_id, + retained_matching_nodes: matchingNodes.length, + graph_coverage: retained.graph.coverage, + }); + } const request = join(temporary.path, "trace.json"); // The CLI's portable file contract takes complete Evidence; MCP resolves a // same-session reference into the same shared application workflow. @@ -259,6 +368,16 @@ try { evidence_id: evidence.evidence_id, }; } + const safeApplicability = + nativeScopes.length === 0 && + structuredScopes.every(({ path, scopes }) => + timedOut + ? matchesStructuredScopeExpectation( + scopes, + structuredExpectations[path], + ) + : scopes.length === 0, + ); let tokenCosts = null; if (values["tokenizer-python"]) { temporary ??= await PrivateRuntimeRoot.create({ @@ -267,7 +386,12 @@ try { const input = join(temporary.path, "token-input.json"); await writeFile( input, - serialize({ catalog, selected, preparation, query: first }), + serialize({ + catalog, + selected, + preparation, + queries: [first, ...structuredQueries], + }), ); const result = await ownedCommand(values["tokenizer-python"], [ "-c", @@ -275,9 +399,9 @@ try { with open(sys.argv[1],encoding='utf-8') as f:d=json.load(f) enc=tiktoken.get_encoding('cl100k_base') def n(v):return len(enc.encode(json.dumps(v,ensure_ascii=False,separators=(',',':')),disallowed_special=())) -requests=n(d['preparation']['request'])+n(d['query']['request']) -structured=n(d['preparation']['response'])+n(d['query']['response']) -full_reply=n(d['preparation']['wire_response'])+n(d['query']['wire_response']) +requests=n(d['preparation']['request'])+sum(n(q['request']) for q in d['queries']) +structured=n(d['preparation']['response'])+sum(n(q['response']) for q in d['queries']) +full_reply=n(d['preparation']['wire_response'])+sum(n(q['wire_response']) for q in d['queries']) s=n(d['selected']);a=n(d['catalog']) print(json.dumps(dict(tokenizer='cl100k_base',tiktoken_version=tiktoken.__version__,selected_catalog=s,full_catalog=a,requests=requests,structured_replies=structured,full_tool_replies=full_reply,selected_catalog_structured_task=s+requests+structured,full_catalog_structured_task=a+requests+structured,selected_catalog_full_reply_task=s+requests+full_reply,full_catalog_full_reply_task=a+requests+full_reply)))`, input, @@ -292,11 +416,19 @@ print(json.dumps(dict(tokenizer='cl100k_base',tiktoken_version=tiktoken.__versio companion_sha256_observed: companionSha256, prior_native_sha256_supplied: values["native-sha256"], source_paths: values["source-path"] ?? null, + preparation_outcome: timedOut ? "provider_timeout" : "completed", + analysis_timeout_ms: analysisTimeoutMs ?? null, parent_evidence_id: sourceId, trace_evidence_id: first.response.evidence_id, + trace_subject: first.response.subject, preparation_ms: preparationMs, samples, safe_identity: safeIdentity, + safe_applicability: safeApplicability, + native_analysis_scopes: nativeScopes, + structured_scopes: structuredScopes, + structured_expectations: structuredExpectations, + modeled_structured_trace_count: structuredQueries.length, node: { node_id: addon.node_id, identity: addon.identity, @@ -322,10 +454,12 @@ print(json.dumps(dict(tokenizer='cl100k_base',tiktoken_version=tiktoken.__versio cli_parity: cliParity, token_costs: tokenCosts, conditions: - "Fresh MCP session, one selected analysis followed by repeated identical retained traces. Filesystem/build caches uncontrolled. Task token counts include one analysis summary and one trace with name/description/inputSchema catalog projections; structured and complete-tool-reply projections are alternatives, not billing. Repeated rounds, export, CLI parity and tokenizer are validation overhead outside that one-task token count but inside total resource receipts. A wrong-identity baseline is not a successful equivalent task or efficiency credit.", + "Fresh MCP session, selected analysis followed by retained traces. Task token counts include one analysis summary or parsed timeout error, one native trace and each requested structured-path trace, with name/description/inputSchema catalog projections. Structured Evidence/parsed error and complete-tool-reply projections are alternatives, not billing. Repeated native rounds, export, CLI parity and tokenizer are validation overhead outside task tokens but inside total resource receipts. Filesystem/build caches uncontrolled. Incorrect identity/applicability is not a successful equivalent task or efficiency credit.", }; - if (values["require-safe"]) + if (values["require-safe"]) { assert.ok(safeIdentity, "Native identity/linkage oracle failed"); + assert.ok(safeApplicability, "File analysis applicability oracle failed"); + } } catch (cause) { primaryError = cause; throw cause; diff --git a/src/application/javascript/JavaScriptArtifactAnalysis.ts b/src/application/javascript/JavaScriptArtifactAnalysis.ts index e721ca450d..a4b3e86bdd 100644 --- a/src/application/javascript/JavaScriptArtifactAnalysis.ts +++ b/src/application/javascript/JavaScriptArtifactAnalysis.ts @@ -22,6 +22,8 @@ import type { } from "../../domain/javascript/javascriptArtifactFiles.js"; import type { AnalyzedJavaScriptArtifactFile, + JavaScriptArtifactAnalysisFailure, + JavaScriptArtifactAnalysisScope, JavaScriptArtifactAnalysis, JavaScriptModuleArtifactAnalysis, JavaScriptModuleSemanticIr, @@ -32,6 +34,7 @@ import type { JavaScriptSourceMapObservation, JavaScriptSourceMapOriginal, } from "./JavaScriptArtifactAnalysisTypes.js"; +import { javascriptArtifactAnalysisScopes } from "./JavaScriptArtifactAnalysisTypes.js"; import { analyzeJavaScriptJsonModule } from "./JavaScriptJsonModules.js"; import { completeJavaScriptAnalysisSteps } from "./JavaScriptAnalysisControl.js"; import { htmlArtifactReferences } from "../../domain/javascript/htmlArtifactReferences.js"; @@ -141,6 +144,7 @@ export const analyzeAndAdoptJavaScriptArtifactFiles = async ( fileSet.files.length - (fileSet.source_selection?.unselected_files ?? 0); let selectedFileIndex = 0; for (const file of fileSet.files) { + let analysisStarted = false; try { await setImmediate(); if (classifyOutsideAnalysisScope(file, state, projection)) { @@ -155,6 +159,7 @@ export const analyzeAndAdoptJavaScriptArtifactFiles = async ( if (signal?.aborted === true) throw new AnalysisCancelledError("analyze_javascript_application"); await beforeFile(file, selectedFileIndex++, selectedFileCount); + analysisStarted = true; if (file.kind !== "javascript" || !file.text.included) { const steps = analyzeArtifactFileSteps(file, { state, @@ -182,10 +187,12 @@ export const analyzeAndAdoptJavaScriptArtifactFiles = async ( : error instanceof AnalysisTimeoutError ? { worker_timeout_ms: error.timeoutMs } : null; - const failure = + const failure: JavaScriptArtifactAnalysisFailure | undefined = error === null ? undefined : { + scope: javascriptArtifactAnalysisScopes.javascript, + status: "interrupted", reason: `${file.path}: ${error.message}`, error: projectAnalysisError(error), limits, @@ -245,15 +252,22 @@ export const analyzeAndAdoptJavaScriptArtifactFiles = async ( ? cause : null; if (interruption !== null) { + const scope = javascriptArtifactAnalysisScopes[file.kind]; state.files.push({ file, javascript: null, semantic: null, - analysis_failure: { - reason: `${file.path}: ${interruption.message}`, - error: projectAnalysisError(interruption), - limits: null, - }, + ...(scope === null + ? {} + : { + analysis_failure: { + scope, + status: analysisStarted ? "interrupted" : "not-started", + reason: `${file.path}: ${interruption.message}`, + error: projectAnalysisError(interruption), + limits: null, + }, + }), }); projection.recordUnavailableFile( file, @@ -277,25 +291,36 @@ export const analyzeAndAdoptJavaScriptArtifactFiles = async ( ? { worker_timeout_ms: interruption.timeoutMs } : null, }; + // This interruption has one cause. Share its immutable failure per phase + // rather than copying it for every unvisited source in a large bundle. + const failures = new Map< + JavaScriptArtifactAnalysisScope, + JavaScriptArtifactAnalysisFailure + >(); for (const file of fileSet.files) { if (analyzedPaths.has(file.path)) continue; if (classifyOutsideAnalysisScope(file, state, projection)) continue; + const scope = javascriptArtifactAnalysisScopes[file.kind]; + let unavailable = scope === null ? undefined : failures.get(scope); + if (scope !== null && unavailable === undefined) { + unavailable = { ...failure, scope, status: "not-started" }; + failures.set(scope, unavailable); + } state.files.push({ file, javascript: null, semantic: null, - analysis_failure: failure, + ...(unavailable === undefined ? {} : { analysis_failure: unavailable }), }); - if (file.kind === "javascript") - projection.recordUnavailableFile( - file, - failure.reason, - failure.limits, - interruption instanceof AnalysisResourceConstraintError || - interruption instanceof AnalysisTimeoutError - ? "resource-limit" - : "incomplete-module", - ); + projection.recordUnavailableFile( + file, + failure.reason, + failure.limits, + interruption instanceof AnalysisResourceConstraintError || + interruption instanceof AnalysisTimeoutError + ? "resource-limit" + : "incomplete-module", + ); } } return { analysis: finalizeArtifactAnalysis(state), interruption }; @@ -423,13 +448,12 @@ const classifyOutsideAnalysisScope = < if (file.text.included || file.text.reason !== "outside-analysis-scope") return false; state.files.push({ file, javascript: null, semantic: null }); - if (file.kind === "javascript") - projection?.recordUnavailableFile( - file, - "Source was not analyzed because it is outside the caller-selected source_paths.", - null, - "incomplete-module", - ); + projection?.recordUnavailableFile( + file, + "Source was not analyzed because it is outside the caller-selected source_paths.", + null, + "incomplete-module", + ); return true; }; diff --git a/src/application/javascript/JavaScriptArtifactAnalysisTypes.ts b/src/application/javascript/JavaScriptArtifactAnalysisTypes.ts index 232570585d..ef174affbb 100644 --- a/src/application/javascript/JavaScriptArtifactAnalysisTypes.ts +++ b/src/application/javascript/JavaScriptArtifactAnalysisTypes.ts @@ -5,7 +5,10 @@ import type { } from "../../domain/javascript/javascriptStaticAnalysisTypes.js"; import type { JavaScriptSemanticIr } from "../../domain/javascript/javascriptSemanticIr.js"; import type { JavaScriptModuleSemanticIr } from "../../domain/javascript/javascriptModuleSemanticIr.js"; -import type { JavaScriptArtifactFile } from "../../domain/javascript/javascriptArtifactFiles.js"; +import type { + JavaScriptArtifactFile, + JavaScriptArtifactFileKind, +} from "../../domain/javascript/javascriptArtifactFiles.js"; import type { JsonValue } from "../../domain/jsonValue.js"; interface JavaScriptStructuredObservation { @@ -107,6 +110,47 @@ export type JavaScriptJsonModuleObservation = JavaScriptStructuredObservation & /** Module facts needed after file-local semantic projection has finished. */ export type { JavaScriptModuleSemanticIr } from "../../domain/javascript/javascriptModuleSemanticIr.js"; +/** Applicable processing of inventoried files; native bytes remain metadata-only. */ +export const javascriptArtifactAnalysisScopes = { + javascript: { + operation: "analyze-javascript-source", + authority: "ast-static-analysis", + }, + "package-json": { + operation: "parse-package-json", + authority: "artifact-bytes", + }, + json: { operation: "parse-json-module", authority: "artifact-bytes" }, + html: { + operation: "parse-html-script-references", + authority: "artifact-bytes", + }, + "source-map": { + operation: "parse-local-source-map", + authority: "artifact-bytes", + }, + "native-addon": null, +} as const satisfies Record< + JavaScriptArtifactFileKind, + { + readonly operation: string; + readonly authority: "artifact-bytes" | "ast-static-analysis"; + } | null +>; + +export type JavaScriptArtifactAnalysisScope = NonNullable< + (typeof javascriptArtifactAnalysisScopes)[JavaScriptArtifactFileKind] +>; + +/** A processing gap preserves applicability and whether the phase was entered. */ +export interface JavaScriptArtifactAnalysisFailure { + readonly scope: JavaScriptArtifactAnalysisScope; + readonly status: "interrupted" | "not-started"; + readonly reason: string; + readonly error: JsonValue; + readonly limits: Readonly> | null; +} + /** One relevant file plus optional AST-only JavaScript facts. */ export interface AnalyzedJavaScriptArtifactFile< SemanticIr extends JavaScriptModuleSemanticIr = JavaScriptSemanticIr, @@ -117,11 +161,7 @@ export interface AnalyzedJavaScriptArtifactFile< readonly ir: SemanticIr; } | null; /** Operational incompleteness, distinct from a malformed source file. */ - readonly analysis_failure?: { - readonly reason: string; - readonly error: JsonValue; - readonly limits: Readonly> | null; - }; + readonly analysis_failure?: JavaScriptArtifactAnalysisFailure; /** Facts retained inline when their expanded graph exceeds available memory. */ readonly application_projection_failure?: { readonly reason: string; diff --git a/src/application/javascript/JavaScriptArtifactGraphContext.ts b/src/application/javascript/JavaScriptArtifactGraphContext.ts index 7bafe00690..db35cdca2a 100644 --- a/src/application/javascript/JavaScriptArtifactGraphContext.ts +++ b/src/application/javascript/JavaScriptArtifactGraphContext.ts @@ -12,6 +12,7 @@ import type { JavaScriptSourceRange } from "../../domain/javascript/javascriptSt import type { JavaScriptHtmlInlineScriptsObservation, JavaScriptModuleArtifactAnalysis, + JavaScriptArtifactAnalysisScope, } from "./JavaScriptArtifactAnalysisTypes.js"; import type { JavaScriptUnanalyzedArtifactLookup } from "../../domain/javascript/javascriptArtifactFiles.js"; import { HTML_INLINE_SCRIPT_LOCATION_LIMIT } from "../../domain/javascript/htmlArtifactReferences.js"; @@ -25,7 +26,7 @@ import { artifactObservationEvidence, astObservationEvidence, staticInferenceEvidence, - unavailableAstEvidence, + unavailableStaticEvidence, } from "./JavaScriptArtifactGraphEvidence.js"; import { artifactPathResolutionProperties, @@ -106,11 +107,12 @@ export interface RoleAssetLinkInput { readonly coverage?: JavaScriptArtifactGraphCoverage; } -/** Explicit package, JavaScript, or source-map parse gap. */ +/** An explicit processing/selection gap with the applicable phase's authority. */ export interface UnavailableParseInput { readonly file: JavaScriptArtifactFile; readonly asset: ApplicationNode; readonly operation: string; + readonly authority: JavaScriptArtifactAnalysisScope["authority"]; readonly limitation: string; readonly failure?: JsonValue; readonly limits?: JavaScriptArtifactGraphCoverage["limits"]; @@ -230,7 +232,8 @@ export const addUnavailableStaticParseScope = ( ? {} : { analysis_failure: input.failure }), }, - evidence: unavailableAstEvidence({ + evidence: unavailableStaticEvidence({ + authority: input.authority, sha256: input.file.sha256, path: input.file.path, operation: input.operation, diff --git a/src/application/javascript/JavaScriptArtifactGraphEvidence.ts b/src/application/javascript/JavaScriptArtifactGraphEvidence.ts index 43821a3fb9..19a3ecc629 100644 --- a/src/application/javascript/JavaScriptArtifactGraphEvidence.ts +++ b/src/application/javascript/JavaScriptArtifactGraphEvidence.ts @@ -1,5 +1,6 @@ import type { ApplicationGraphEvidence } from "../../domain/javascript/javascriptApplicationEvidenceSchemas.js"; import type { JavaScriptSourceRange } from "../../domain/javascript/javascriptStaticAnalysisTypes.js"; +import type { JavaScriptArtifactAnalysisScope } from "./JavaScriptArtifactAnalysisTypes.js"; const EXTRACTOR = { name: "rea-javascript-artifact-reconstruction", @@ -93,11 +94,14 @@ export const staticInferenceEvidence = ( evidence_ids: [], }); -/** Unavailable AST fact that preserves a parse, approval, or limit gap. */ -export const unavailableAstEvidence = ( - input: EvidenceInput & { readonly limitation: string }, +/** Unavailable static fact with the authority of its applicable processing phase. */ +export const unavailableStaticEvidence = ( + input: EvidenceInput & { + readonly authority: JavaScriptArtifactAnalysisScope["authority"]; + readonly limitation: string; + }, ): ApplicationGraphEvidence => ({ - authority: "ast-static-analysis", + authority: input.authority, state: "unavailable", confidence: "unknown", artifact: artifactReference(input.sha256), diff --git a/src/application/javascript/JavaScriptArtifactGraphStructure.ts b/src/application/javascript/JavaScriptArtifactGraphStructure.ts index e96344f073..43c00d93b9 100644 --- a/src/application/javascript/JavaScriptArtifactGraphStructure.ts +++ b/src/application/javascript/JavaScriptArtifactGraphStructure.ts @@ -6,6 +6,7 @@ import { partialApplicationCoverage, } from "../../domain/javascript/javascriptApplicationEvidenceSchemas.js"; import type { JavaScriptModuleArtifactAnalysis } from "./JavaScriptArtifactAnalysisTypes.js"; +import { javascriptArtifactAnalysisScopes } from "./JavaScriptArtifactAnalysisTypes.js"; import { jsonValueSchema } from "../../domain/jsonValue.js"; import { freezeJsonSnapshot } from "../../domain/immutableJson.js"; import type { JavaScriptSourceRange } from "../../domain/javascript/javascriptStaticAnalysisTypes.js"; @@ -211,11 +212,17 @@ export const addJavaScriptArtifactFiles = ( }), }); } - if (!file.text.included && file.text.reason === "outside-analysis-scope") + const analysisScope = javascriptArtifactAnalysisScopes[file.kind]; + if ( + !file.text.included && + file.text.reason === "outside-analysis-scope" && + analysisScope !== null + ) addUnavailableStaticParseScope(context, { file, asset: target, operation: "select-javascript-sources", + authority: analysisScope.authority, limitation: "Source is outside the caller-selected source_paths; it was inventoried but not analyzed.", }); @@ -223,12 +230,13 @@ export const addJavaScriptArtifactFiles = ( addUnavailableStaticParseScope(context, { file, asset: target, - operation: "analyze-javascript-source", + ...analyzed.analysis_failure.scope, limitation: analyzed.analysis_failure.reason, failure: analyzed.analysis_failure.error, limits: javaScriptAnalysisCoverageLimits( analyzed.analysis_failure.limits, ), + details: { analysis_status: analyzed.analysis_failure.status }, }); else if ( file.kind === "javascript" && @@ -239,6 +247,7 @@ export const addJavaScriptArtifactFiles = ( file, asset: target, operation: "parse-javascript", + authority: javascriptArtifactAnalysisScopes.javascript.authority, limitation: file.text.included ? "JavaScript syntax could not be parsed." : `JavaScript text was unavailable: ${file.text.reason}.`, @@ -248,6 +257,7 @@ export const addJavaScriptArtifactFiles = ( file, asset: target, operation: "project-javascript-application", + authority: javascriptArtifactAnalysisScopes.javascript.authority, limitation: analyzed.application_projection_failure.reason, failure: analyzed.application_projection_failure.error, limits: javaScriptAnalysisCoverageLimits( @@ -259,14 +269,14 @@ export const addJavaScriptArtifactFiles = ( addUnavailableStaticParseScope(context, { file, asset: target, - operation: "parse-package-json", + ...javascriptArtifactAnalysisScopes["package-json"], limitation: packageValue.limitation, }); if (jsonValue !== undefined && jsonValue.status !== "included") addUnavailableStaticParseScope(context, { file, asset: target, - operation: "parse-json-module", + ...javascriptArtifactAnalysisScopes.json, limitation: jsonValue.limitation, }); const sourceMap = sourceMapsByPath.get(file.path); @@ -274,7 +284,7 @@ export const addJavaScriptArtifactFiles = ( addUnavailableStaticParseScope(context, { file, asset: target, - operation: "parse-local-source-map", + ...javascriptArtifactAnalysisScopes["source-map"], limitation: sourceMap.limitation, }); const inlineScripts = inlineScriptsByPath.get(file.path); @@ -283,6 +293,7 @@ export const addJavaScriptArtifactFiles = ( file, asset: target, operation: "parse-html-inline-scripts", + authority: javascriptArtifactAnalysisScopes.javascript.authority, limitation: htmlInlineScriptLimitation(inlineScripts), limits: inlineScripts.script_count > inlineScripts.scripts.length diff --git a/src/application/javascript/JavaScriptArtifactReconstruction.ts b/src/application/javascript/JavaScriptArtifactReconstruction.ts index 39eb165c77..cb7d660896 100644 --- a/src/application/javascript/JavaScriptArtifactReconstruction.ts +++ b/src/application/javascript/JavaScriptArtifactReconstruction.ts @@ -20,6 +20,7 @@ import type { ArtifactInventorySnapshot } from "../../domain/artifactInventorySn import type { ArtifactInventoryPartialObservation } from "../../domain/artifactPartialObservation.js"; import type { ArtifactResourceScope } from "../../artifacts/ArtifactResourceScope.js"; import { analyzeAndAdoptJavaScriptArtifactFiles } from "./JavaScriptArtifactAnalysis.js"; +import { javascriptArtifactAnalysisScopes } from "./JavaScriptArtifactAnalysisTypes.js"; import { createJavaScriptSourceAnalysis } from "../../artifacts/javascript/JavaScriptSourceAnalysis.js"; import { JAVASCRIPT_ANALYSIS_RESOURCE_DEFAULTS } from "../../domain/javascript/javascriptAnalysisResourceControls.js"; import { createOwnedJavaScriptApplicationEvidenceCooperatively } from "./JavaScriptApplicationEvidence.js"; @@ -137,7 +138,7 @@ export const reconstructJavaScriptArtifact = async ( ); await reportPhase( "parse_javascript_sources", - `Parsing and projecting ${String(files.files.length - (files.source_selection?.unselected_files ?? 0))} selected application source files`, + `Processing ${String(files.files.length - (files.source_selection?.unselected_files ?? 0))} selected application files`, ); const semanticProjection = createJavaScriptSemanticGraphProjection({ ...(input.max_semantic_nodes === undefined @@ -168,11 +169,16 @@ export const reconstructJavaScriptArtifact = async ( semanticProjection, async (file, completed, total) => { abortIfNeeded(signal); + const ast = + javascriptArtifactAnalysisScopes[file.kind]?.authority === + "ast-static-analysis"; await progress?.report({ - phase: "parse_javascript_source", + phase: ast + ? "parse_javascript_source" + : "process_javascript_artifact_metadata", completed: 0, total: 1, - message: `Parsing and projecting ${file.path} (${String(completed + 1)}/${String(total)})`, + message: `${ast ? "Parsing and projecting" : "Processing metadata for"} ${file.path} (${String(completed + 1)}/${String(total)})`, }); abortIfNeeded(signal); }, diff --git a/src/application/javascript/JavaScriptSemanticGraphBuilder.ts b/src/application/javascript/JavaScriptSemanticGraphBuilder.ts index c9208a39f7..647b350d3a 100644 --- a/src/application/javascript/JavaScriptSemanticGraphBuilder.ts +++ b/src/application/javascript/JavaScriptSemanticGraphBuilder.ts @@ -163,7 +163,7 @@ export interface JavaScriptSemanticGraphProjection { readonly adoptFileProjection: ( projection: JavaScriptSemanticFileProjection, ) => void; - /** Preserve source-bound unknowns for an execution or result-retention failure. */ + /** Preserve JavaScript-source unknowns; other file kinds have no semantic module. */ readonly recordUnavailableFile: ( file: JavaScriptArtifactFile, reason: string, @@ -346,6 +346,9 @@ export const createJavaScriptSemanticGraphProjection = ( if (projection.truncated) truncatedFiles += 1; }, recordUnavailableFile: (file, reason, limits, unknownReason) => { + // Both full and incremental construction enter here. Metadata/native + // processing gaps belong to the application graph, never JavaScript IR. + if (file.kind !== "javascript") return; const retainedLimits = javaScriptAnalysisCoverageLimits(limits); for (const limit of retainedLimits) { executionLimits.set( diff --git a/tests/acceptance/applications/javascriptAnalysisLimits.test.ts b/tests/acceptance/applications/javascriptAnalysisLimits.test.ts index 6f0ba8cefa..b0f180402e 100644 --- a/tests/acceptance/applications/javascriptAnalysisLimits.test.ts +++ b/tests/acceptance/applications/javascriptAnalysisLimits.test.ts @@ -4,8 +4,9 @@ import { join } from "node:path"; import { expect, it } from "vitest"; import { z } from "zod"; -import { parseEvidence } from "../../../src/domain/evidence.js"; +import { parseEvidence, type Evidence } from "../../../src/domain/evidence.js"; import { parseEvidenceBundle } from "../../../src/domain/evidenceBundle.js"; +import { javascriptApplicationAnalysisResultSchema } from "../../../src/domain/javascript/javascriptApplicationAnalysis.js"; import { parseMcpToolError } from "../../fixtures/mcpToolError.js"; import { connectLocalToolsMcp } from "../../fixtures/localToolsMcp.js"; import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js"; @@ -114,35 +115,114 @@ it("preserves MCP analysis limits in retained Evidence and an exported bundle ro expect(await getBundle(client)).toEqual(retained); }, 60_000); -it("retains caller limits in partial Evidence after an actual analysis timeout", async () => { - const root = await createTestTempDirectory("rea-js-limit-timeout-"); - await writeFile(join(root, "main.js"), "export const observed = 7;\n"); - const { client } = await connectLocalToolsMcp({ - NODE_OPTIONS: "--max-old-space-size=512", - }); - const response = await client.callTool({ - name: "analyze_javascript_application", - arguments: { - input_path: root, +cliTest( + "retains caller limits and applicable file scopes after an actual analysis timeout", + async ({ cli }) => { + const root = await createTestTempDirectory("rea-js-limit-timeout-"); + const sourcePaths = [ + "a.js", + "a.js.map", + "data.json", + "index.html", + "package.json", + "z.node", + ]; + await Promise.all( + ( + [ + ["a.js", "export const observed = 7;\n"], + [ + "a.js.map", + JSON.stringify({ + version: 3, + sources: [], + names: [], + mappings: "", + }), + ], + ["data.json", '{"observed":7}'], + ["index.html", ''], + ["package.json", '{"name":"file-scope-control","main":"a.js"}'], + ["z-excluded.js", "export const excluded = true;\n"], + ["z.node", Buffer.from([0, 1, 2, 3])], + ["zz-excluded.node", Buffer.from([3, 2, 1, 0])], + ] as const + ).map(([path, content]) => writeFile(join(root, path), content)), + ); + const { client } = await connectLocalToolsMcp({ + NODE_OPTIONS: "--max-old-space-size=512", + }); + const response = await client.callTool({ + name: "analyze_javascript_application", + arguments: { + input_path: root, + max_heap_mb: 128, + analysis_timeout_ms: 1, + source_paths: sourcePaths, + }, + }); + expect(parseMcpToolError(response)).toMatchObject({ + error: { code: "provider_timeout" }, + }); + const bundle = await getBundle(client); + const partial = bundle.records.find( + (record) => record.operation === "analyze_javascript_application", + ); + expect(partial?.parameters).toEqual({ + format: "auto", + integrity_policy: "fail", max_heap_mb: 128, analysis_timeout_ms: 1, - }, - }); - expect(parseMcpToolError(response)).toMatchObject({ - error: { code: "provider_timeout" }, - }); - const bundle = await getBundle(client); - const partial = bundle.records.find( - (record) => record.operation === "analyze_javascript_application", - ); - expect(partial?.parameters).toEqual({ - format: "auto", - integrity_policy: "fail", - max_heap_mb: 128, - analysis_timeout_ms: 1, - }); - await client.ping(); -}, 30_000); + source_paths: sourcePaths, + }); + if (partial === undefined) + throw new Error("Timeout Evidence was not retained"); + const cliArguments = [ + "analyze-javascript-application", + root, + "--max-heap-mb", + "128", + ...sourcePaths.flatMap((path) => ["--source-path", path]), + "--format", + "json", + ]; + const cliTimeout = await cli.run({ + arguments: [...cliArguments, "--analysis-timeout-ms", "1"], + }); + expect(cliTimeout.exitCode).toBe(1); + const cliFailure = z + .object({ + code: z.literal("provider_timeout"), + details: z.object({ partial_observation: z.unknown() }), + }) + .parse(cliTimeout.json); + const cliPartial = parseEvidence(cliFailure.details.partial_observation); + const control = await client.callTool({ + name: "analyze_javascript_application", + arguments: { + input_path: root, + max_heap_mb: 128, + source_paths: sourcePaths, + }, + }); + expect(control.isError).not.toBe(true); + const controlEvidence = parseEvidence(control.structuredContent); + const cliControl = await cli.run({ arguments: cliArguments }); + expect(cliControl.exitCode, cliControl.stderr).toBe(0); + const cliControlEvidence = parseEvidence(cliControl.json); + expect(cliControlEvidence.evidence_id).toBe(controlEvidence.evidence_id); + // Observe both adapters and successful controls before testing applicability. + for (const [evidence, interrupted] of [ + [partial, true], + [cliPartial, true], + [controlEvidence, false], + [cliControlEvidence, false], + ] as const) + expectFileAnalysisApplicability(evidence, interrupted); + await client.ping(); + }, + 60_000, +); async function getBundle(client: Client) { const response = await client.callTool({ @@ -154,3 +234,59 @@ async function getBundle(client: Client) { z.object({ result: z.unknown() }).parse(response.structuredContent).result, ); } + +function expectFileAnalysisApplicability( + evidence: Evidence, + interrupted: boolean, +) { + const result = javascriptApplicationAnalysisResultSchema.parse( + evidence.normalized_result, + ); + const scopeObservations = result.graph.nodes + .filter(({ kind }) => kind === "unknown") + .flatMap(({ observations }) => observations); + const scopes = (path: string) => + scopeObservations.filter(({ properties }) => properties.path === path); + expect(result.graph.nodes.some(({ kind }) => kind === "native-addon")).toBe( + true, + ); + for (const path of ["z.node", "zz-excluded.node"]) + expect(scopes(path), path).toEqual([]); + const excluded = scopes("z-excluded.js"); + expect(excluded).toHaveLength(1); + expect(excluded[0]).toMatchObject({ + properties: { operation: "select-javascript-sources" }, + evidence: { + authority: "ast-static-analysis", + state: "unavailable", + confidence: "unknown", + }, + }); + expect(excluded[0]?.properties).not.toHaveProperty("analysis_failure"); + for (const [path, operation] of [ + ["a.js", "analyze-javascript-source"], + ["a.js.map", "parse-local-source-map"], + ["data.json", "parse-json-module"], + ["index.html", "parse-html-script-references"], + ["package.json", "parse-package-json"], + ] as const) { + if (!interrupted) expect(scopes(path), path).toEqual([]); + else { + expect(scopes(path), path).toHaveLength(1); + expect(scopes(path)[0]).toMatchObject({ + properties: { + operation, + analysis_status: path === "a.js" ? "interrupted" : "not-started", + }, + evidence: { + authority: path === "a.js" ? "ast-static-analysis" : "artifact-bytes", + state: "unavailable", + confidence: "unknown", + coverage: { status: "partial" }, + }, + }); + } + } + if (interrupted) expect(result.graph.coverage.status).toBe("partial"); + else expect(result.statistics.parsed_javascript_files).toBe(1); +} diff --git a/tests/boundary/filesystem/javascript-applications/javascriptArtifactReconstruction.test.ts b/tests/boundary/filesystem/javascript-applications/javascriptArtifactReconstruction.test.ts index 47c6a93c6a..11ad11cfac 100644 --- a/tests/boundary/filesystem/javascript-applications/javascriptArtifactReconstruction.test.ts +++ b/tests/boundary/filesystem/javascript-applications/javascriptArtifactReconstruction.test.ts @@ -51,6 +51,76 @@ import { import { parseJavaScriptSemanticGraph } from "../../../../src/domain/javascript/javascriptSemanticGraphSerialization.js"; import { writeJavaScriptArtifactFixture } from "../../../fixtures/javascriptArtifactApplication.js"; +it("keeps excluded non-JavaScript files out of both semantic construction paths", async () => { + const root = await createTestTempDirectory("rea-js-semantic-applicability-"); + await Promise.all( + ( + [ + ["a.js", "export const observed = 7;"], + ["b.js", "export const excluded = true;"], + ["native.node", Buffer.from([0, 1, 2, 3])], + ["data.json", '{"observed":7}'], + ["index.html", ''], + ["package.json", '{"name":"applicability","main":"a.js"}'], + [ + "a.js.map", + JSON.stringify({ version: 3, sources: [], names: [], mappings: "" }), + ], + ] as const + ).map(([path, content]) => writeFile(join(root, path), content)), + ); + const snapshot = await scanCanonicalArtifactInventory(root, {}); + const reader = createJavaScriptArtifactReader(root, "directory"); + try { + const files = await readJavaScriptArtifactFiles( + reader, + snapshot, + undefined, + ["a.js"], + ); + expect( + files.files.filter(({ text }) => !text.included).map(({ path }) => path), + ).toEqual([ + "a.js.map", + "b.js", + "data.json", + "index.html", + "native.node", + "package.json", + ]); + const analysis = analyzeJavaScriptArtifactFiles(files); + const applicationGraph = buildJavaScriptArtifactGraph( + snapshot, + files, + analysis, + ); + const full = buildJavaScriptSemanticGraph({ + rootArtifactSha256: snapshot.manifest.root_sha256, + applicationGraph, + analysis, + }); + const incremental = await reconstructJavaScriptArtifact({ + input_path: root, + source_paths: ["a.js"], + }); + for (const graph of [full, incremental.semantic_graph]) { + expect( + graph.nodes + .filter(({ kind }) => kind === "module") + .map(({ identity }) => identity.module_path) + .sort(), + ).toEqual(["a.js", "b.js"]); + expect(graph.coverage.status).toBe("partial"); + expect(graph.unknowns.length).toBeGreaterThan(0); + expect( + new Set(graph.nodes.map(({ identity }) => identity.module_path)), + ).toEqual(new Set(["a.js", "b.js"])); + } + } finally { + await reader.close(); + } +}); + it("reports file progress and honors cancellation before the next source", async () => { const root = await fixtureDirectory(); const controller = new AbortController(); diff --git a/tests/boundary/filesystem/javascriptArtifactReconstruction.test.ts b/tests/boundary/filesystem/javascriptArtifactReconstruction.test.ts index 1254d11dd5..6f5946d59c 100644 --- a/tests/boundary/filesystem/javascriptArtifactReconstruction.test.ts +++ b/tests/boundary/filesystem/javascriptArtifactReconstruction.test.ts @@ -68,6 +68,7 @@ it("keeps malformed JavaScript, package metadata, and source maps as explicit un await Promise.all([ writeFile(join(root, "package.json"), "{"), writeFile(join(root, "broken.js"), "function broken( {"), + writeFile(join(root, "data.json"), "{"), writeFile(join(root, "renderer", "renderer.js.map"), "{"), ]); @@ -90,9 +91,33 @@ it("keeps malformed JavaScript, package metadata, and source maps as explicit un expect.arrayContaining([ "parse-javascript", "parse-package-json", + "parse-json-module", "parse-local-source-map", ]), ); + const gaps = result.graph.nodes + .filter(({ kind }) => kind === "unknown") + .flatMap(({ observations }) => observations); + for (const operation of [ + "parse-javascript", + "parse-package-json", + "parse-json-module", + "parse-local-source-map", + ]) { + const applicable = gaps.filter( + ({ properties }) => properties.operation === operation, + ); + expect(applicable.length).toBeGreaterThan(0); + for (const gap of applicable) + expect(gap.evidence).toMatchObject({ + authority: + operation === "parse-javascript" + ? "ast-static-analysis" + : "artifact-bytes", + state: "unavailable", + confidence: "unknown", + }); + } }); it("retains every source declared by every included local source map", async () => { diff --git a/tests/boundary/javascript/javascriptApplicationCancellation.test.ts b/tests/boundary/javascript/javascriptApplicationCancellation.test.ts index b8d35326a5..cecc0db287 100644 --- a/tests/boundary/javascript/javascriptApplicationCancellation.test.ts +++ b/tests/boundary/javascript/javascriptApplicationCancellation.test.ts @@ -134,6 +134,104 @@ it("preserves imported manifest status when cancelled before visiting manifests" }); }); +it("keeps cancellation before native metadata out of AST scopes and semantic modules", async () => { + const root = await createTestTempDirectory("rea-js-cancel-file-kinds-"); + await Promise.all( + ( + [ + ["a.js", "export const observed = 7;\n"], + ["b.node", Buffer.from([0, 1, 2, 3])], + ["c.json", '{"observed":7}'], + ["d.html", ''], + ["package.json", '{"name":"cancellation-control","main":"a.js"}'], + [ + "z.js.map", + JSON.stringify({ version: 3, sources: [], names: [], mappings: "" }), + ], + ["zz.js", "export const unvisited = true;\n"], + ] as const + ).map(([path, content]) => writeFile(join(root, path), content)), + ); + const controller = new AbortController(); + let reachedNativeMetadata = false; + const result = await analyzeJavaScriptApplication( + { input_path: root, format: "directory" }, + { + signal: controller.signal, + progress: { + async report(event) { + if ( + event.phase === "process_javascript_artifact_metadata" && + event.message.includes("b.node") + ) { + reachedNativeMetadata = true; + controller.abort(); + } + }, + }, + }, + ); + expect(reachedNativeMetadata).toBe(true); + if (result.ok) throw new Error("Cancelled analysis must return a failure"); + const partial = z + .object({ + code: z.literal("cancelled"), + details: z.object({ + partial_observation: z.object({ + normalized_result: javascriptApplicationAnalysisResultSchema, + }), + }), + }) + .parse(projectAnalysisError(result.error)).details + .partial_observation.normalized_result; + expect(partial.statistics.parsed_javascript_files).toBe(1); + expect(partial.graph.nodes.some(({ kind }) => kind === "native-addon")).toBe( + true, + ); + const scopes = (path: string) => + partial.graph.nodes.flatMap((node) => + node.kind !== "unknown" + ? [] + : node.observations.filter( + ({ properties }) => + properties.path === path && + properties.analysis_failure !== undefined, + ), + ); + expect({ + native_ast_scopes: scopes("b.node").map(({ properties, evidence }) => ({ + operation: properties.operation, + authority: evidence.authority, + })), + native_semantic_modules: partial.semantic_graph.nodes + .filter(({ identity }) => identity.module_path === "b.node") + .map(({ kind, label }) => ({ kind, label })), + }).toEqual({ native_ast_scopes: [], native_semantic_modules: [] }); + for (const [path, operation] of [ + ["c.json", "parse-json-module"], + ["d.html", "parse-html-script-references"], + ["package.json", "parse-package-json"], + ["z.js.map", "parse-local-source-map"], + ["zz.js", "analyze-javascript-source"], + ] as const) { + expect(scopes(path)).toHaveLength(1); + expect(scopes(path)[0]).toMatchObject({ + properties: { operation, analysis_status: "not-started" }, + evidence: { + authority: path === "zz.js" ? "ast-static-analysis" : "artifact-bytes", + state: "unavailable", + confidence: "unknown", + }, + }); + } + expect( + partial.semantic_graph.nodes.some( + ({ kind, identity }) => + kind === "module" && identity.module_path === "zz.js", + ), + ).toBe(true); +}); + it("interrupts semantic graph commitment before result validation", async () => { const root = await createTestTempDirectory("rea-js-cancel-semantic-"); await writeFile( diff --git a/tests/boundary/process/javascriptVerifierScopeOracle.test.ts b/tests/boundary/process/javascriptVerifierScopeOracle.test.ts new file mode 100644 index 0000000000..d359624431 --- /dev/null +++ b/tests/boundary/process/javascriptVerifierScopeOracle.test.ts @@ -0,0 +1,116 @@ +import { readFile } from "node:fs/promises"; +import { expect, it } from "vitest"; +import { z } from "zod"; + +import { + matchesStructuredScopeExpectation, + structuredScopeExpectationsSchema, +} from "../../../scripts/lib/javascript-file-scope-oracle.mjs"; + +const scopeSchema = z.object({ + properties: z.record(z.string(), z.unknown()), + evidence: z.object({ + authority: z.string(), + state: z.string(), + confidence: z.string(), + }), +}); +const cohortSchema = z.object({ + timeout: z.object({ + result: z.object({ + structured_scopes: z.array( + z.object({ path: z.string(), scopes: z.array(scopeSchema) }), + ), + }), + }), +}); +const report = z + .object({ + cohorts: z.object({ baseline: cohortSchema, final: cohortSchema }), + }) + .parse( + JSON.parse( + await readFile( + new URL( + "../../../docs/verification/javascript-interruption-applicability-2026-10-15.json", + import.meta.url, + ), + "utf8", + ), + ), + ); +const retainedMapScopes = (cohort: z.infer) => { + const row = cohort.timeout.result.structured_scopes.find( + ({ path }) => path === "ElectronAppWrapper.js.map", + ); + if (row === undefined || row.scopes.length !== 1) + throw new Error("Missing real Joplin scope snapshot"); + return row.scopes; +}; +const correct = retainedMapScopes(report.cohorts.final); +const expected = { + operation: "parse-local-source-map", + analysis_status: "not-started", +} as const; + +it("accepts the retained real source-map phase and rejects the actual baseline misattribution", () => { + expect(matchesStructuredScopeExpectation(correct, expected)).toBe(true); + expect( + matchesStructuredScopeExpectation( + retainedMapScopes(report.cohorts.baseline), + expected, + ), + ).toBe(false); +}); + +it.each([ + { + name: "another structured phase", + operation: "parse-package-json", + analysis_status: "not-started", + }, + { + name: "an entered phase", + operation: "parse-local-source-map", + analysis_status: "interrupted", + }, + { + name: "missing phase-entry status", + operation: "parse-local-source-map", + analysis_status: undefined, + }, +])( + "rejects $name even with artifact-byte authority", + ({ operation, analysis_status }) => { + const altered = correct.map((scope) => ({ + ...scope, + properties: { ...scope.properties, operation, analysis_status }, + })); + expect(matchesStructuredScopeExpectation(altered, expected)).toBe(false); + }, +); + +it("rejects absent gaps, missing expectations and mixed conflicting observations", () => { + expect(matchesStructuredScopeExpectation([], expected)).toBe(false); + expect(matchesStructuredScopeExpectation(correct, undefined)).toBe(false); + const conflict = correct.map((scope) => ({ + ...scope, + properties: { ...scope.properties, analysis_status: "interrupted" }, + })); + expect( + matchesStructuredScopeExpectation([...correct, ...conflict], expected), + ).toBe(false); +}); + +it("parses explicit per-path expectations without borrowing the production phase map", () => { + expect( + structuredScopeExpectationsSchema.parse({ + "ElectronAppWrapper.js.map": expected, + }), + ).toEqual({ "ElectronAppWrapper.js.map": expected }); + expect( + structuredScopeExpectationsSchema.safeParse({ + map: { ...expected, analysis_status: "unknown" }, + }).success, + ).toBe(false); +});