@resolveio/server-lib 22.3.229 → 22.3.231
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1866,11 +1866,11 @@ function buildResolveIORunnerQaLiveDataSeederScript() {
|
|
|
1866
1866
|
'function shouldSeedBillingDashboardFixtures() {',
|
|
1867
1867
|
' const force = process.env.RESOLVEIO_QA_FORCE_BILLING_FIXTURES || process.env.RESOLVEIO_SUPPORT_QA_FORCE_BILLING_FIXTURES || process.env.RESOLVEIO_RUNNER_QA_FORCE_BILLING_FIXTURES || "";',
|
|
1868
1868
|
' if (/^(true|1|yes|on)$/i.test(force)) return true;',
|
|
1869
|
+
' if (shouldSeedPartInventorySnapshotContext()) return false;',
|
|
1869
1870
|
' if (shouldSeedPricingImportFixtures()) return false;',
|
|
1870
1871
|
' const explicit = process.env.RESOLVEIO_QA_INCLUDE_BILLING_FIXTURES || process.env.RESOLVEIO_SUPPORT_QA_INCLUDE_BILLING_FIXTURES || process.env.RESOLVEIO_RUNNER_QA_INCLUDE_BILLING_FIXTURES || "";',
|
|
1871
1872
|
' if (/^(true|1|yes|on)$/i.test(explicit)) return true;',
|
|
1872
1873
|
' if (/^(false|0|no|off)$/i.test(explicit)) return false;',
|
|
1873
|
-
' if (shouldSeedPartInventorySnapshotContext()) return false;',
|
|
1874
1874
|
' const text = readSeedHintText();',
|
|
1875
1875
|
' const billingSurface = /\\b(invoice|invoicing|billing|billable|tax|taxes|surcharge|checkout|check\\s*out|pick\\s*ticket)\\b/i.test(text);',
|
|
1876
1876
|
' if (billingSurface) return true;',
|
|
@@ -2704,7 +2704,7 @@ function buildResolveIORunnerBugfixComparisonQaScript() {
|
|
|
2704
2704
|
].join('\n');
|
|
2705
2705
|
}
|
|
2706
2706
|
function buildResolveIOPartInventorySnapshotProofScriptLines() {
|
|
2707
|
-
return String.raw(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\nfunction activeMatrixRow() {\n\tconst matrix = readJson(matrixPath) || {};\n\tconst rows = matrixRows(matrix);\n\treturn rows.find((candidate) => !/^(pass|passed)$/i.test(String(candidate && candidate.status || \"\"))) || rows[0] || {};\n}\nfunction readSeedPartInventorySnapshotContext() {\n\tconst seed = readJson(path.join(artifactDir, \"qa-live-data-seed-result.json\")) || {};\n\tconst selected = seed && seed.selected || {};\n\tconst context = selected.part_inventory_snapshot_context || selected.partInventorySnapshotContext || null;\n\tif (!context || typeof context !== \"object\") return null;\n\tconst partIds = uniqueStrings(context.part_ids || context.partIds || []);\n\tconst dayKeys = uniqueStrings(context.day_keys || context.dayKeys || []);\n\tif (!partIds.length && !dayKeys.length && !Number(context.snapshot_count || context.snapshotCount || 0)) return null;\n\treturn { ...context, part_ids: partIds, day_keys: dayKeys };\n}\nfunction shouldRunPartInventorySnapshotProof() {\n\tconst context = readSeedPartInventorySnapshotContext();\n\tif (!context) return false;\n\tconst text = [activeRowText(), targetRoute].join(\"\n\");\n\treturn /\b(reportDailyInventorySnapshot|inventory-daily-snapshots|dailys+inventorys+snapshot|parts+inventorys+snapshot|warehouse_location|Parts)\b/i.test(text);\n}\nfunction normalizePartSnapshotDayKey(value) {\n\tconst text = String(value || \"\").trim();\n\tconst match = /d{4}-d{2}-d{2}/.exec(text);\n\tif (match) return match[0];\n\tconst date = new Date(text);\n\treturn Number.isFinite(date.getTime()) ? date.toISOString().slice(0, 10) : \"\";\n}\nfunction partSnapshotRowPartId(row) {\n\tconst metadata = row && typeof row.metadata === \"object\" ? row.metadata : {};\n\treturn String(metadata.id_part || row.id_part || row.id_item || row.id_source || \"\").trim();\n}\nfunction partSnapshotRowYardId(row) {\n\tconst metadata = row && typeof row.metadata === \"object\" ? row.metadata : {};\n\tconst explicit = String(metadata.id_yard || row.id_yard || row.id_warehouse_location || \"\").trim();\n\tif (explicit) return explicit;\n\tconst source = String(row && row.id_source || \"\");\n\tconst sourceMatch = /^yard:([A-Za-z0-9_-]+)/i.exec(source);\n\treturn sourceMatch ? sourceMatch[1] : \"\";\n}\nfunction normalizeWarehouseName(value) {\n\treturn String(value || \"\").trim().toLowerCase().replace(/s+/g, \" \");\n}\nfunction methodDateFromDayKey(dayKey) {\n\treturn new Date(dayKey + \"T12:00:00.000Z\");\n}\nfunction resolveWsUrl() {\n\tif (/^https:/i.test(serverUrl)) return serverUrl.replace(/^https:/i, \"wss:\");\n\tif (/^http:/i.test(serverUrl)) return serverUrl.replace(/^http:/i, \"ws:\");\n\treturn serverUrl;\n}\nfunction callResolveIOMethodViaWs(auth, route, methodName, args) {\n\treturn new Promise((resolve, reject) => {\n\t\tconst token = auth && auth.accessToken;\n\t\tif (!token) {\n\t\t\treject(new Error(\"Missing access token for websocket method proof.\"));\n\t\t\treturn;\n\t\t}\n\t\tconst WebSocket = requireQaModule(\"ws\");\n\t\tconst ws = new WebSocket(resolveWsUrl(), [token], { origin: clientUrl });\n\t\tconst messageId = Date.now() + Math.floor(Math.random() * 100000);\n\t\tconst timeout = setTimeout(() => {\n\t\t\ttry { ws.close(); } catch (error) {}\n\t\t\treject(new Error(\"Timed out waiting for \" + methodName + \" websocket response.\"));\n\t\t}, Number(process.env.RESOLVEIO_SUPPORT_QA_METHOD_PROOF_TIMEOUT_MS || 120000));\n\t\tlet settled = false;\n\t\tconst finish = (error, value) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timeout);\n\t\t\ttry { ws.close(); } catch (closeError) {}\n\t\t\tif (error) reject(error);\n\t\t\telse resolve(value);\n\t\t};\n\t\tws.on(\"open\", () => {\n\t\t\tconst payload = [[route || \"/\", new Date().toISOString(), messageId, \"method\", methodName, ...(args || [])]];\n\t\t\tws.send(JSON.stringify(payload));\n\t\t});\n\t\tws.on(\"message\", (raw) => {\n\t\t\tlet payload;\n\t\t\ttry { payload = JSON.parse(Buffer.isBuffer(raw) ? raw.toString(\"utf8\") : String(raw)); }\n\t\t\tcatch (error) { return; }\n\t\t\tif (!payload || payload.messageId !== messageId) return;\n\t\t\tif (payload.data === \"ACK\" && payload.hasError === false) return;\n\t\t\tif (payload.hasError) finish(new Error(typeof payload.data === \"string\" ? payload.data : JSON.stringify(payload.data || {})));\n\t\t\telse finish(null, payload.data);\n\t\t});\n\t\tws.on(\"error\", (error) => finish(error));\n\t});\n}\nasync function readPartInventorySnapshotProofData(context, dayKey) {\n\tconst { MongoClient } = mongoRequire();\n\tconst client = new MongoClient(safeLocalMongoUrl());\n\tawait client.connect();\n\ttry {\n\t\tconst db = client.db();\n\t\tconst query = { section: \"Parts\" };\n\t\tif (dayKey) query.day_key = dayKey;\n\t\tconst partIds = uniqueStrings(context.part_ids || []);\n\t\tif (partIds.length) query.$or = [{ \"metadata.id_part\": { $in: partIds } }, { id_part: { $in: partIds } }];\n\t\tconst snapshots = await db.collection(\"inventory-daily-snapshots\").find(query).sort({ day_key: -1, item_name: 1, location: 1 }).limit(120).toArray();\n\t\tconst yardIds = uniqueStrings(snapshots.map(partSnapshotRowYardId));\n\t\tconst yards = yardIds.length ? await db.collection(\"yards\").find({ _id: { $in: yardIds } }).project({ _id: 1, name: 1 }).toArray() : [];\n\t\tconst yardById = new Map(yards.map((yard) => [String(yard._id), yard]));\n\t\treturn { snapshots, yards, yardById };\n\t} finally {\n\t\tawait client.close().catch(() => undefined);\n\t}\n}\nasync function renderPartInventorySnapshotProofScreenshot(page, payload, rowRoute, screenshotPath) {\n\tconst escapeHtml = (value) => String(value === undefined || value === null ? \"\" : value).replace(/[&<>\"']/g, (char) => ({ \"&\": \"&\", \"<\": \"<\", \">\": \">\", \"\"\": \""\", \"'\": \"'\" }[char]));\n\tconst comparisons = (payload.comparisons || []).slice(0, 12).map((entry) => \"<tr><td>\" + escapeHtml(entry.partId || entry.itemName || \"part\") + \"</td><td>\" + escapeHtml(entry.beforeWarehouse || \"\") + \"</td><td>\" + escapeHtml(entry.expectedYardName || \"\") + \"</td><td>\" + escapeHtml(entry.afterWarehouse || \"\") + \"</td><td>\" + (entry.pass ? \"<span class=\"ok\">PASS</span>\" : \"<span class=\"bad\">FAIL</span>\") + \"</td></tr>\").join(\"\");\n\tconst html = \"<!doctype html><html><head><meta charset=\"utf-8\"><style>body{margin:0;background:#f5f7fb;color:#111827;font-family:Arial,Helvetica,sans-serif}.wrap{padding:42px 52px}.eyebrow{font-size:16px;text-transform:uppercase;color:#475569;font-weight:700}.title{font-size:34px;font-weight:800;margin:10px 0}.caption{font-size:20px;line-height:1.35;color:#1f2937;margin:0 0 22px}.grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px;margin:22px 0}.card{background:white;border:2px solid #d7dde8;border-radius:8px;padding:18px}.label{font-size:14px;color:#64748b;font-weight:700;text-transform:uppercase}.value{font-size:28px;font-weight:800;margin-top:8px}.ok{color:#047857;font-weight:800}.bad{color:#b91c1c;font-weight:800}table{width:100%;border-collapse:collapse;background:white;border:2px solid #d7dde8;border-radius:8px;overflow:hidden;font-size:17px}th{background:#111827;color:white;text-align:left;padding:12px}td{border-top:1px solid #e5e7eb;padding:12px}.footer{margin-top:20px;font-size:16px;color:#475569}.path{font-family:Menlo,Consolas,monospace;font-size:14px;color:#334155}</style></head><body><main class=\"wrap\"><div class=\"eyebrow\">ResolveIO Support QA Business Proof</div><div class=\"title\">Part Inventory Snapshot Warehouse Attribution</div><p class=\"caption\">\" + escapeHtml(payload.caption || \"\") + \"</p><section class=\"grid\"><div class=\"card\"><div class=\"label\">Report Method</div><div class=\"value\">reportDailyInventorySnapshot</div></div><div class=\"card\"><div class=\"label\">Snapshot Date</div><div class=\"value\">\" + escapeHtml(payload.dayKey || \"\") + \"</div></div><div class=\"card\"><div class=\"label\">Stale Rows Corrected</div><div class=\"value \" + (payload.pass ? \"ok\" : \"bad\") + \"\">\" + Number(payload.correctedStaleRows || 0) + \"/\" + Number(payload.staleRows || 0) + \"</div></div></section><table><thead><tr><th>Part</th><th>Before Saved Warehouse</th><th>Expected Yard</th><th>Method Response Warehouse</th><th>Result</th></tr></thead><tbody>\" + comparisons + \"</tbody></table><div class=\"footer\">Before: saved historical Parts snapshot rows contained stale warehouse_location values. Action: called reportDailyInventorySnapshot(date, [\"Parts\"]) on the local QA server. After: the method response used the authoritative yard lineage for the affected part rows.</div><div class=\"footer path\">Route: \" + escapeHtml(rowRoute || targetRoute) + \" | Artifacts: qa-part-inventory-snapshot-proof.json, aiqa-business-assertion.json, qa-coverage-matrix.json</div></main></body></html>\";\n\tawait page.setViewport({ width: Math.max(viewportWidth, 1600), height: Math.max(viewportHeight, 900) }).catch(() => undefined);\n\tawait page.setContent(html, { waitUntil: \"domcontentloaded\", timeout: 30000 });\n\tawait page.screenshot({ path: screenshotPath, type: \"png\", fullPage: false });\n}\nasync function runPartInventorySnapshotMethodProof(page, routeSummary, auth) {\n\tif (!shouldRunPartInventorySnapshotProof()) return null;\n\tconst context = readSeedPartInventorySnapshotContext();\n\tconst row = activeMatrixRow();\n\tconst rowRoute = String(row.route || row.screen || \"/print\").trim() || \"/print\";\n\tconst rowWorkflow = String(row.workflow || row.action_under_test || \"Invoke reportDailyInventorySnapshot(date, [\"Parts\"]) and verify Part warehouse_location uses authoritative yard lineage.\").trim();\n\tconst proofPath = path.join(artifactDir, \"qa-part-inventory-snapshot-proof.json\");\n\tconst businessAssertionPath = path.join(artifactDir, \"aiqa-business-assertion.json\");\n\tconst beforeAfterScreenshotPath = path.join(artifactDir, \"support-business-proof-before-after.png\");\n\tconst requestedDayKeys = uniqueStrings(context.day_keys || []).map(normalizePartSnapshotDayKey).filter(Boolean);\n\tconst dayKey = requestedDayKeys[0] || normalizePartSnapshotDayKey(new Date(Date.now() - 86400000).toISOString());\n\tconst writeFailed = async (message, extra) => {\n\t\tconst payload = { status: \"failed\", targetRoute: rowRoute, dayKey, context, error: message, ...(extra || {}), updated_at: new Date().toISOString() };\n\t\twriteJson(proofPath, payload);\n\t\twriteJson(businessAssertionPath, { assertion: String(row.assertion || row.required_proof || \"Part inventory snapshot warehouse attribution proof\"), status: \"failed\", result: \"business_assertion_failed\", outcome: \"business_assertion_failed\", workflow: rowWorkflow, route: rowRoute, before: \"\", action: \"Attempted deterministic reportDailyInventorySnapshot websocket method proof.\", expected: \"Affected Part rows return the yard named by snapshot metadata.id_yard instead of stale saved warehouse_location.\", after: \"\", observed: message, dataProof: message, mongoDelta: {}, artifactPaths: [proofPath, matrixPath], metadata: { supportDiagnosisProof: false, proofType: \"part_inventory_snapshot_report_method\", generatedBy: \"resolveio_runner_part_inventory_snapshot_business_proof\", generatedAt: new Date().toISOString() } });\n\t\tconst matrix = readJson(matrixPath) || { status: \"started\", rows: [] };\n\t\tconst rows = matrixRows(matrix);\n\t\tconst activeIndex = Math.max(0, rows.indexOf(row));\n\t\tif (rows[activeIndex]) { rows[activeIndex].status = \"failed\"; rows[activeIndex].result = \"failed\"; rows[activeIndex].acceptance_blocked = true; rows[activeIndex].blocker = message; rows[activeIndex].artifact = proofPath; }\n\t\tmatrix.rows = rows;\n\t\tmatrix.status = \"failed\";\n\t\tmatrix.part_inventory_snapshot_proof = proofPath;\n\t\tmatrix.aiqa_business_assertion = businessAssertionPath;\n\t\tmatrix.updated_at = new Date().toISOString();\n\t\twriteJson(matrixPath, matrix);\n\t\treturn payload;\n\t};\n\ttry {\n\t\tconst data = await readPartInventorySnapshotProofData(context, dayKey);\n\t\tif (!data.snapshots.length) return await writeFailed(\"No seeded Part inventory daily snapshot rows were available for day_key \" + dayKey + \".\");\n\t\tconst methodResult = await callResolveIOMethodViaWs(auth, rowRoute, \"reportDailyInventorySnapshot\", [methodDateFromDayKey(dayKey), [\"Parts\"]]);\n\t\tconst responseRows = Array.isArray(methodResult && methodResult.rows) ? methodResult.rows : [];\n\t\tconst comparisons = data.snapshots.map((snapshot) => {\n\t\t\tconst partId = partSnapshotRowPartId(snapshot);\n\t\t\tconst yardId = partSnapshotRowYardId(snapshot);\n\t\t\tconst yard = yardId ? data.yardById.get(String(yardId)) : null;\n\t\t\tconst expectedYardName = String(yard && yard.name || \"\").trim();\n\t\t\tconst beforeWarehouse = String(snapshot.warehouse_location || snapshot.location || \"\").trim();\n\t\t\tconst responseCandidates = responseRows.filter((candidate) => !partId || partSnapshotRowPartId(candidate) === partId || String(candidate.item_name || candidate.name || \"\") === String(snapshot.item_name || snapshot.name || \"\"));\n\t\t\tconst afterRow = responseCandidates.find((candidate) => expectedYardName && normalizeWarehouseName(candidate.warehouse_location || candidate.location) === normalizeWarehouseName(expectedYardName)) || responseCandidates[0] || null;\n\t\t\tconst afterWarehouse = String(afterRow && (afterRow.warehouse_location || afterRow.location) || \"\").trim();\n\t\t\tconst staleBefore = !!expectedYardName && !!beforeWarehouse && normalizeWarehouseName(beforeWarehouse) !== normalizeWarehouseName(expectedYardName);\n\t\t\treturn { partId, itemName: String(snapshot.item_name || snapshot.name || \"\"), dayKey: String(snapshot.day_key || \"\"), beforeWarehouse, expectedYardName, afterWarehouse, staleBefore, pass: staleBefore && !!afterWarehouse && normalizeWarehouseName(afterWarehouse) === normalizeWarehouseName(expectedYardName) };\n\t\t}).filter((entry) => entry.expectedYardName);\n\t\tconst staleRows = comparisons.filter((entry) => entry.staleBefore);\n\t\tconst passedRows = staleRows.filter((entry) => entry.pass);\n\t\tconst pass = staleRows.length > 0 && passedRows.length === staleRows.length;\n\t\tconst caption = pass\n\t\t\t? \"Part inventory snapshot proof passed: \" + passedRows.length + \" stale saved row(s) returned the authoritative yard warehouse in reportDailyInventorySnapshot.\"\n\t\t\t: \"Part inventory snapshot proof failed: staleRows=\" + staleRows.length + \", corrected=\" + passedRows.length + \".\";\n\t\tconst payload = { status: pass ? \"pass\" : \"failed\", targetRoute: rowRoute, dayKey, methodName: \"reportDailyInventorySnapshot\", context, snapshotCount: data.snapshots.length, responseRowCount: responseRows.length, staleRows: staleRows.length, correctedStaleRows: passedRows.length, comparisons, caption, screenshot: beforeAfterScreenshotPath, page: routeSummary, updated_at: new Date().toISOString() };\n\t\tawait renderPartInventorySnapshotProofScreenshot(page, payload, rowRoute, beforeAfterScreenshotPath).catch(() => undefined);\n\t\twriteJson(proofPath, payload);\n\t\tconst businessAssertion = {\n\t\t\tassertion: String(row.assertion || row.required_proof || \"Affected Part warehouse_location maps to authoritative yard lineage in reportDailyInventorySnapshot response.\").trim(),\n\t\t\tstatus: pass ? \"pass\" : \"failed\",\n\t\t\tresult: pass ? \"business_assertion_passed\" : \"business_assertion_failed\",\n\t\t\toutcome: pass ? \"business_assertion_passed\" : \"business_assertion_failed\",\n\t\t\tworkflow: rowWorkflow,\n\t\t\troute: rowRoute,\n\t\t\tbefore: \"Saved non-today Parts snapshot rows for day_key \" + dayKey + \" included \" + staleRows.length + \" stale warehouse_location value(s): \" + staleRows.map((entry) => (entry.itemName || entry.partId) + \"=\" + entry.beforeWarehouse).join(\"; \"),\n\t\t\taction: \"Called reportDailyInventorySnapshot(\" + dayKey + \", [\"Parts\"]) through the local QA websocket method path.\",\n\t\t\texpected: \"Every affected stale Part row returns the yard named by metadata.id_yard in warehouse_location.\",\n\t\t\tafter: \"Method response corrected \" + passedRows.length + \" of \" + staleRows.length + \" stale row(s): \" + passedRows.map((entry) => (entry.itemName || entry.partId) + \"=\" + entry.afterWarehouse).join(\"; \"),\n\t\t\tobserved: caption,\n\t\t\tdataProof: comparisons.map((entry) => (entry.itemName || entry.partId || \"part\") + \": before=\" + entry.beforeWarehouse + \", expected=\" + entry.expectedYardName + \", after=\" + entry.afterWarehouse + \", pass=\" + entry.pass).join(\"\n\"),\n\t\t\tmongoDelta: { collection: \"inventory-daily-snapshots\", day_key: dayKey, staleRows: staleRows.length, correctedStaleRows: passedRows.length, responseRowCount: responseRows.length },\n\t\t\tartifactPaths: [proofPath, beforeAfterScreenshotPath, matrixPath],\n\t\t\tmetadata: { supportDiagnosisProof: pass, proofType: \"part_inventory_snapshot_report_method\", methodPath: \"server/src/methods/report.ts reportDailyInventorySnapshot\", generatedBy: \"resolveio_runner_part_inventory_snapshot_business_proof\", generatedAt: new Date().toISOString() }\n\t\t};\n\t\twriteJson(businessAssertionPath, businessAssertion);\n\t\tconst matrix = readJson(matrixPath) || { status: \"started\", rows: [] };\n\t\tconst rows = matrixRows(matrix);\n\t\tconst rowIndex = rows.findIndex((candidate) => String(candidate && candidate.workflow || \"\") === rowWorkflow) >= 0 ? rows.findIndex((candidate) => String(candidate && candidate.workflow || \"\") === rowWorkflow) : rows.findIndex((candidate) => !/^(pass|passed)$/i.test(String(candidate && candidate.status || \"\")));\n\t\tconst activeIndex = rowIndex >= 0 ? rowIndex : 0;\n\t\tif (rows[activeIndex]) {\n\t\t\trows[activeIndex].status = pass ? \"pass\" : \"failed\";\n\t\t\trows[activeIndex].result = pass ? \"pass\" : \"failed\";\n\t\t\trows[activeIndex].acceptance_blocked = !pass;\n\t\t\trows[activeIndex].screenshot = beforeAfterScreenshotPath;\n\t\t\trows[activeIndex].screenshots = [beforeAfterScreenshotPath, passScreenshotPath].filter(Boolean);\n\t\t\trows[activeIndex].caption = caption;\n\t\t\trows[activeIndex].artifact = proofPath;\n\t\t\trows[activeIndex].artifacts = [{ path: proofPath, caption: \"Part inventory snapshot method response proof.\" }, { screenshot: beforeAfterScreenshotPath, caption }, { path: businessAssertionPath, caption: \"AIQaBusinessAssertion for support diagnosis proof plan.\" }];\n\t\t\trows[activeIndex].persisted_assertion = businessAssertion.dataProof;\n\t\t\tif (!pass) rows[activeIndex].blocker = caption;\n\t\t}\n\t\tmatrix.rows = rows;\n\t\tmatrix.status = pass ? \"pass\" : \"failed\";\n\t\tmatrix.part_inventory_snapshot_proof = proofPath;\n\t\tmatrix.aiqa_business_assertion = businessAssertionPath;\n\t\tmatrix.updated_at = new Date().toISOString();\n\t\twriteJson(matrixPath, matrix);\n\t\treturn payload;\n\t} catch (error) {\n\t\treturn await writeFailed(error && (error.stack || error.message) || String(error));\n\t}\n}\n"], ["\nfunction activeMatrixRow() {\n\tconst matrix = readJson(matrixPath) || {};\n\tconst rows = matrixRows(matrix);\n\treturn rows.find((candidate) => !/^(pass|passed)$/i.test(String(candidate && candidate.status || \"\"))) || rows[0] || {};\n}\nfunction readSeedPartInventorySnapshotContext() {\n\tconst seed = readJson(path.join(artifactDir, \"qa-live-data-seed-result.json\")) || {};\n\tconst selected = seed && seed.selected || {};\n\tconst context = selected.part_inventory_snapshot_context || selected.partInventorySnapshotContext || null;\n\tif (!context || typeof context !== \"object\") return null;\n\tconst partIds = uniqueStrings(context.part_ids || context.partIds || []);\n\tconst dayKeys = uniqueStrings(context.day_keys || context.dayKeys || []);\n\tif (!partIds.length && !dayKeys.length && !Number(context.snapshot_count || context.snapshotCount || 0)) return null;\n\treturn { ...context, part_ids: partIds, day_keys: dayKeys };\n}\nfunction shouldRunPartInventorySnapshotProof() {\n\tconst context = readSeedPartInventorySnapshotContext();\n\tif (!context) return false;\n\tconst text = [activeRowText(), targetRoute].join(\"\\n\");\n\treturn /\\b(reportDailyInventorySnapshot|inventory-daily-snapshots|daily\\s+inventory\\s+snapshot|part\\s+inventory\\s+snapshot|warehouse_location|Parts)\\b/i.test(text);\n}\nfunction normalizePartSnapshotDayKey(value) {\n\tconst text = String(value || \"\").trim();\n\tconst match = /\\d{4}-\\d{2}-\\d{2}/.exec(text);\n\tif (match) return match[0];\n\tconst date = new Date(text);\n\treturn Number.isFinite(date.getTime()) ? date.toISOString().slice(0, 10) : \"\";\n}\nfunction partSnapshotRowPartId(row) {\n\tconst metadata = row && typeof row.metadata === \"object\" ? row.metadata : {};\n\treturn String(metadata.id_part || row.id_part || row.id_item || row.id_source || \"\").trim();\n}\nfunction partSnapshotRowYardId(row) {\n\tconst metadata = row && typeof row.metadata === \"object\" ? row.metadata : {};\n\tconst explicit = String(metadata.id_yard || row.id_yard || row.id_warehouse_location || \"\").trim();\n\tif (explicit) return explicit;\n\tconst source = String(row && row.id_source || \"\");\n\tconst sourceMatch = /^yard:([A-Za-z0-9_-]+)/i.exec(source);\n\treturn sourceMatch ? sourceMatch[1] : \"\";\n}\nfunction normalizeWarehouseName(value) {\n\treturn String(value || \"\").trim().toLowerCase().replace(/\\s+/g, \" \");\n}\nfunction methodDateFromDayKey(dayKey) {\n\treturn new Date(dayKey + \"T12:00:00.000Z\");\n}\nfunction resolveWsUrl() {\n\tif (/^https:/i.test(serverUrl)) return serverUrl.replace(/^https:/i, \"wss:\");\n\tif (/^http:/i.test(serverUrl)) return serverUrl.replace(/^http:/i, \"ws:\");\n\treturn serverUrl;\n}\nfunction callResolveIOMethodViaWs(auth, route, methodName, args) {\n\treturn new Promise((resolve, reject) => {\n\t\tconst token = auth && auth.accessToken;\n\t\tif (!token) {\n\t\t\treject(new Error(\"Missing access token for websocket method proof.\"));\n\t\t\treturn;\n\t\t}\n\t\tconst WebSocket = requireQaModule(\"ws\");\n\t\tconst ws = new WebSocket(resolveWsUrl(), [token], { origin: clientUrl });\n\t\tconst messageId = Date.now() + Math.floor(Math.random() * 100000);\n\t\tconst timeout = setTimeout(() => {\n\t\t\ttry { ws.close(); } catch (error) {}\n\t\t\treject(new Error(\"Timed out waiting for \" + methodName + \" websocket response.\"));\n\t\t}, Number(process.env.RESOLVEIO_SUPPORT_QA_METHOD_PROOF_TIMEOUT_MS || 120000));\n\t\tlet settled = false;\n\t\tconst finish = (error, value) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timeout);\n\t\t\ttry { ws.close(); } catch (closeError) {}\n\t\t\tif (error) reject(error);\n\t\t\telse resolve(value);\n\t\t};\n\t\tws.on(\"open\", () => {\n\t\t\tconst payload = [[route || \"/\", new Date().toISOString(), messageId, \"method\", methodName, ...(args || [])]];\n\t\t\tws.send(JSON.stringify(payload));\n\t\t});\n\t\tws.on(\"message\", (raw) => {\n\t\t\tlet payload;\n\t\t\ttry { payload = JSON.parse(Buffer.isBuffer(raw) ? raw.toString(\"utf8\") : String(raw)); }\n\t\t\tcatch (error) { return; }\n\t\t\tif (!payload || payload.messageId !== messageId) return;\n\t\t\tif (payload.data === \"ACK\" && payload.hasError === false) return;\n\t\t\tif (payload.hasError) finish(new Error(typeof payload.data === \"string\" ? payload.data : JSON.stringify(payload.data || {})));\n\t\t\telse finish(null, payload.data);\n\t\t});\n\t\tws.on(\"error\", (error) => finish(error));\n\t});\n}\nasync function readPartInventorySnapshotProofData(context, dayKey) {\n\tconst { MongoClient } = mongoRequire();\n\tconst client = new MongoClient(safeLocalMongoUrl());\n\tawait client.connect();\n\ttry {\n\t\tconst db = client.db();\n\t\tconst query = { section: \"Parts\" };\n\t\tif (dayKey) query.day_key = dayKey;\n\t\tconst partIds = uniqueStrings(context.part_ids || []);\n\t\tif (partIds.length) query.$or = [{ \"metadata.id_part\": { $in: partIds } }, { id_part: { $in: partIds } }];\n\t\tconst snapshots = await db.collection(\"inventory-daily-snapshots\").find(query).sort({ day_key: -1, item_name: 1, location: 1 }).limit(120).toArray();\n\t\tconst yardIds = uniqueStrings(snapshots.map(partSnapshotRowYardId));\n\t\tconst yards = yardIds.length ? await db.collection(\"yards\").find({ _id: { $in: yardIds } }).project({ _id: 1, name: 1 }).toArray() : [];\n\t\tconst yardById = new Map(yards.map((yard) => [String(yard._id), yard]));\n\t\treturn { snapshots, yards, yardById };\n\t} finally {\n\t\tawait client.close().catch(() => undefined);\n\t}\n}\nasync function renderPartInventorySnapshotProofScreenshot(page, payload, rowRoute, screenshotPath) {\n\tconst escapeHtml = (value) => String(value === undefined || value === null ? \"\" : value).replace(/[&<>\"']/g, (char) => ({ \"&\": \"&\", \"<\": \"<\", \">\": \">\", \"\\\"\": \""\", \"'\": \"'\" }[char]));\n\tconst comparisons = (payload.comparisons || []).slice(0, 12).map((entry) => \"<tr><td>\" + escapeHtml(entry.partId || entry.itemName || \"part\") + \"</td><td>\" + escapeHtml(entry.beforeWarehouse || \"\") + \"</td><td>\" + escapeHtml(entry.expectedYardName || \"\") + \"</td><td>\" + escapeHtml(entry.afterWarehouse || \"\") + \"</td><td>\" + (entry.pass ? \"<span class=\\\"ok\\\">PASS</span>\" : \"<span class=\\\"bad\\\">FAIL</span>\") + \"</td></tr>\").join(\"\");\n\tconst html = \"<!doctype html><html><head><meta charset=\\\"utf-8\\\"><style>body{margin:0;background:#f5f7fb;color:#111827;font-family:Arial,Helvetica,sans-serif}.wrap{padding:42px 52px}.eyebrow{font-size:16px;text-transform:uppercase;color:#475569;font-weight:700}.title{font-size:34px;font-weight:800;margin:10px 0}.caption{font-size:20px;line-height:1.35;color:#1f2937;margin:0 0 22px}.grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px;margin:22px 0}.card{background:white;border:2px solid #d7dde8;border-radius:8px;padding:18px}.label{font-size:14px;color:#64748b;font-weight:700;text-transform:uppercase}.value{font-size:28px;font-weight:800;margin-top:8px}.ok{color:#047857;font-weight:800}.bad{color:#b91c1c;font-weight:800}table{width:100%;border-collapse:collapse;background:white;border:2px solid #d7dde8;border-radius:8px;overflow:hidden;font-size:17px}th{background:#111827;color:white;text-align:left;padding:12px}td{border-top:1px solid #e5e7eb;padding:12px}.footer{margin-top:20px;font-size:16px;color:#475569}.path{font-family:Menlo,Consolas,monospace;font-size:14px;color:#334155}</style></head><body><main class=\\\"wrap\\\"><div class=\\\"eyebrow\\\">ResolveIO Support QA Business Proof</div><div class=\\\"title\\\">Part Inventory Snapshot Warehouse Attribution</div><p class=\\\"caption\\\">\" + escapeHtml(payload.caption || \"\") + \"</p><section class=\\\"grid\\\"><div class=\\\"card\\\"><div class=\\\"label\\\">Report Method</div><div class=\\\"value\\\">reportDailyInventorySnapshot</div></div><div class=\\\"card\\\"><div class=\\\"label\\\">Snapshot Date</div><div class=\\\"value\\\">\" + escapeHtml(payload.dayKey || \"\") + \"</div></div><div class=\\\"card\\\"><div class=\\\"label\\\">Stale Rows Corrected</div><div class=\\\"value \" + (payload.pass ? \"ok\" : \"bad\") + \"\\\">\" + Number(payload.correctedStaleRows || 0) + \"/\" + Number(payload.staleRows || 0) + \"</div></div></section><table><thead><tr><th>Part</th><th>Before Saved Warehouse</th><th>Expected Yard</th><th>Method Response Warehouse</th><th>Result</th></tr></thead><tbody>\" + comparisons + \"</tbody></table><div class=\\\"footer\\\">Before: saved historical Parts snapshot rows contained stale warehouse_location values. Action: called reportDailyInventorySnapshot(date, [\\\"Parts\\\"]) on the local QA server. After: the method response used the authoritative yard lineage for the affected part rows.</div><div class=\\\"footer path\\\">Route: \" + escapeHtml(rowRoute || targetRoute) + \" | Artifacts: qa-part-inventory-snapshot-proof.json, aiqa-business-assertion.json, qa-coverage-matrix.json</div></main></body></html>\";\n\tawait page.setViewport({ width: Math.max(viewportWidth, 1600), height: Math.max(viewportHeight, 900) }).catch(() => undefined);\n\tawait page.setContent(html, { waitUntil: \"domcontentloaded\", timeout: 30000 });\n\tawait page.screenshot({ path: screenshotPath, type: \"png\", fullPage: false });\n}\nasync function runPartInventorySnapshotMethodProof(page, routeSummary, auth) {\n\tif (!shouldRunPartInventorySnapshotProof()) return null;\n\tconst context = readSeedPartInventorySnapshotContext();\n\tconst row = activeMatrixRow();\n\tconst rowRoute = String(row.route || row.screen || \"/print\").trim() || \"/print\";\n\tconst rowWorkflow = String(row.workflow || row.action_under_test || \"Invoke reportDailyInventorySnapshot(date, [\\\"Parts\\\"]) and verify Part warehouse_location uses authoritative yard lineage.\").trim();\n\tconst proofPath = path.join(artifactDir, \"qa-part-inventory-snapshot-proof.json\");\n\tconst businessAssertionPath = path.join(artifactDir, \"aiqa-business-assertion.json\");\n\tconst beforeAfterScreenshotPath = path.join(artifactDir, \"support-business-proof-before-after.png\");\n\tconst requestedDayKeys = uniqueStrings(context.day_keys || []).map(normalizePartSnapshotDayKey).filter(Boolean);\n\tconst dayKey = requestedDayKeys[0] || normalizePartSnapshotDayKey(new Date(Date.now() - 86400000).toISOString());\n\tconst writeFailed = async (message, extra) => {\n\t\tconst payload = { status: \"failed\", targetRoute: rowRoute, dayKey, context, error: message, ...(extra || {}), updated_at: new Date().toISOString() };\n\t\twriteJson(proofPath, payload);\n\t\twriteJson(businessAssertionPath, { assertion: String(row.assertion || row.required_proof || \"Part inventory snapshot warehouse attribution proof\"), status: \"failed\", result: \"business_assertion_failed\", outcome: \"business_assertion_failed\", workflow: rowWorkflow, route: rowRoute, before: \"\", action: \"Attempted deterministic reportDailyInventorySnapshot websocket method proof.\", expected: \"Affected Part rows return the yard named by snapshot metadata.id_yard instead of stale saved warehouse_location.\", after: \"\", observed: message, dataProof: message, mongoDelta: {}, artifactPaths: [proofPath, matrixPath], metadata: { supportDiagnosisProof: false, proofType: \"part_inventory_snapshot_report_method\", generatedBy: \"resolveio_runner_part_inventory_snapshot_business_proof\", generatedAt: new Date().toISOString() } });\n\t\tconst matrix = readJson(matrixPath) || { status: \"started\", rows: [] };\n\t\tconst rows = matrixRows(matrix);\n\t\tconst activeIndex = Math.max(0, rows.indexOf(row));\n\t\tif (rows[activeIndex]) { rows[activeIndex].status = \"failed\"; rows[activeIndex].result = \"failed\"; rows[activeIndex].acceptance_blocked = true; rows[activeIndex].blocker = message; rows[activeIndex].artifact = proofPath; }\n\t\tmatrix.rows = rows;\n\t\tmatrix.status = \"failed\";\n\t\tmatrix.part_inventory_snapshot_proof = proofPath;\n\t\tmatrix.aiqa_business_assertion = businessAssertionPath;\n\t\tmatrix.updated_at = new Date().toISOString();\n\t\twriteJson(matrixPath, matrix);\n\t\treturn payload;\n\t};\n\ttry {\n\t\tconst data = await readPartInventorySnapshotProofData(context, dayKey);\n\t\tif (!data.snapshots.length) return await writeFailed(\"No seeded Part inventory daily snapshot rows were available for day_key \" + dayKey + \".\");\n\t\tconst methodResult = await callResolveIOMethodViaWs(auth, rowRoute, \"reportDailyInventorySnapshot\", [methodDateFromDayKey(dayKey), [\"Parts\"]]);\n\t\tconst responseRows = Array.isArray(methodResult && methodResult.rows) ? methodResult.rows : [];\n\t\tconst comparisons = data.snapshots.map((snapshot) => {\n\t\t\tconst partId = partSnapshotRowPartId(snapshot);\n\t\t\tconst yardId = partSnapshotRowYardId(snapshot);\n\t\t\tconst yard = yardId ? data.yardById.get(String(yardId)) : null;\n\t\t\tconst expectedYardName = String(yard && yard.name || \"\").trim();\n\t\t\tconst beforeWarehouse = String(snapshot.warehouse_location || snapshot.location || \"\").trim();\n\t\t\tconst responseCandidates = responseRows.filter((candidate) => !partId || partSnapshotRowPartId(candidate) === partId || String(candidate.item_name || candidate.name || \"\") === String(snapshot.item_name || snapshot.name || \"\"));\n\t\t\tconst afterRow = responseCandidates.find((candidate) => expectedYardName && normalizeWarehouseName(candidate.warehouse_location || candidate.location) === normalizeWarehouseName(expectedYardName)) || responseCandidates[0] || null;\n\t\t\tconst afterWarehouse = String(afterRow && (afterRow.warehouse_location || afterRow.location) || \"\").trim();\n\t\t\tconst staleBefore = !!expectedYardName && !!beforeWarehouse && normalizeWarehouseName(beforeWarehouse) !== normalizeWarehouseName(expectedYardName);\n\t\t\treturn { partId, itemName: String(snapshot.item_name || snapshot.name || \"\"), dayKey: String(snapshot.day_key || \"\"), beforeWarehouse, expectedYardName, afterWarehouse, staleBefore, pass: staleBefore && !!afterWarehouse && normalizeWarehouseName(afterWarehouse) === normalizeWarehouseName(expectedYardName) };\n\t\t}).filter((entry) => entry.expectedYardName);\n\t\tconst staleRows = comparisons.filter((entry) => entry.staleBefore);\n\t\tconst passedRows = staleRows.filter((entry) => entry.pass);\n\t\tconst pass = staleRows.length > 0 && passedRows.length === staleRows.length;\n\t\tconst caption = pass\n\t\t\t? \"Part inventory snapshot proof passed: \" + passedRows.length + \" stale saved row(s) returned the authoritative yard warehouse in reportDailyInventorySnapshot.\"\n\t\t\t: \"Part inventory snapshot proof failed: staleRows=\" + staleRows.length + \", corrected=\" + passedRows.length + \".\";\n\t\tconst payload = { status: pass ? \"pass\" : \"failed\", targetRoute: rowRoute, dayKey, methodName: \"reportDailyInventorySnapshot\", context, snapshotCount: data.snapshots.length, responseRowCount: responseRows.length, staleRows: staleRows.length, correctedStaleRows: passedRows.length, comparisons, caption, screenshot: beforeAfterScreenshotPath, page: routeSummary, updated_at: new Date().toISOString() };\n\t\tawait renderPartInventorySnapshotProofScreenshot(page, payload, rowRoute, beforeAfterScreenshotPath).catch(() => undefined);\n\t\twriteJson(proofPath, payload);\n\t\tconst businessAssertion = {\n\t\t\tassertion: String(row.assertion || row.required_proof || \"Affected Part warehouse_location maps to authoritative yard lineage in reportDailyInventorySnapshot response.\").trim(),\n\t\t\tstatus: pass ? \"pass\" : \"failed\",\n\t\t\tresult: pass ? \"business_assertion_passed\" : \"business_assertion_failed\",\n\t\t\toutcome: pass ? \"business_assertion_passed\" : \"business_assertion_failed\",\n\t\t\tworkflow: rowWorkflow,\n\t\t\troute: rowRoute,\n\t\t\tbefore: \"Saved non-today Parts snapshot rows for day_key \" + dayKey + \" included \" + staleRows.length + \" stale warehouse_location value(s): \" + staleRows.map((entry) => (entry.itemName || entry.partId) + \"=\" + entry.beforeWarehouse).join(\"; \"),\n\t\t\taction: \"Called reportDailyInventorySnapshot(\" + dayKey + \", [\\\"Parts\\\"]) through the local QA websocket method path.\",\n\t\t\texpected: \"Every affected stale Part row returns the yard named by metadata.id_yard in warehouse_location.\",\n\t\t\tafter: \"Method response corrected \" + passedRows.length + \" of \" + staleRows.length + \" stale row(s): \" + passedRows.map((entry) => (entry.itemName || entry.partId) + \"=\" + entry.afterWarehouse).join(\"; \"),\n\t\t\tobserved: caption,\n\t\t\tdataProof: comparisons.map((entry) => (entry.itemName || entry.partId || \"part\") + \": before=\" + entry.beforeWarehouse + \", expected=\" + entry.expectedYardName + \", after=\" + entry.afterWarehouse + \", pass=\" + entry.pass).join(\"\\n\"),\n\t\t\tmongoDelta: { collection: \"inventory-daily-snapshots\", day_key: dayKey, staleRows: staleRows.length, correctedStaleRows: passedRows.length, responseRowCount: responseRows.length },\n\t\t\tartifactPaths: [proofPath, beforeAfterScreenshotPath, matrixPath],\n\t\t\tmetadata: { supportDiagnosisProof: pass, proofType: \"part_inventory_snapshot_report_method\", methodPath: \"server/src/methods/report.ts reportDailyInventorySnapshot\", generatedBy: \"resolveio_runner_part_inventory_snapshot_business_proof\", generatedAt: new Date().toISOString() }\n\t\t};\n\t\twriteJson(businessAssertionPath, businessAssertion);\n\t\tconst matrix = readJson(matrixPath) || { status: \"started\", rows: [] };\n\t\tconst rows = matrixRows(matrix);\n\t\tconst rowIndex = rows.findIndex((candidate) => String(candidate && candidate.workflow || \"\") === rowWorkflow) >= 0 ? rows.findIndex((candidate) => String(candidate && candidate.workflow || \"\") === rowWorkflow) : rows.findIndex((candidate) => !/^(pass|passed)$/i.test(String(candidate && candidate.status || \"\")));\n\t\tconst activeIndex = rowIndex >= 0 ? rowIndex : 0;\n\t\tif (rows[activeIndex]) {\n\t\t\trows[activeIndex].status = pass ? \"pass\" : \"failed\";\n\t\t\trows[activeIndex].result = pass ? \"pass\" : \"failed\";\n\t\t\trows[activeIndex].acceptance_blocked = !pass;\n\t\t\trows[activeIndex].screenshot = beforeAfterScreenshotPath;\n\t\t\trows[activeIndex].screenshots = [beforeAfterScreenshotPath, passScreenshotPath].filter(Boolean);\n\t\t\trows[activeIndex].caption = caption;\n\t\t\trows[activeIndex].artifact = proofPath;\n\t\t\trows[activeIndex].artifacts = [{ path: proofPath, caption: \"Part inventory snapshot method response proof.\" }, { screenshot: beforeAfterScreenshotPath, caption }, { path: businessAssertionPath, caption: \"AIQaBusinessAssertion for support diagnosis proof plan.\" }];\n\t\t\trows[activeIndex].persisted_assertion = businessAssertion.dataProof;\n\t\t\tif (!pass) rows[activeIndex].blocker = caption;\n\t\t}\n\t\tmatrix.rows = rows;\n\t\tmatrix.status = pass ? \"pass\" : \"failed\";\n\t\tmatrix.part_inventory_snapshot_proof = proofPath;\n\t\tmatrix.aiqa_business_assertion = businessAssertionPath;\n\t\tmatrix.updated_at = new Date().toISOString();\n\t\twriteJson(matrixPath, matrix);\n\t\treturn payload;\n\t} catch (error) {\n\t\treturn await writeFailed(error && (error.stack || error.message) || String(error));\n\t}\n}\n"]))).trim().split('\n');
|
|
2707
|
+
return String.raw(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\nfunction activeMatrixRow() {\n\tconst matrix = readJson(matrixPath) || {};\n\tconst rows = matrixRows(matrix);\n\treturn rows.find((candidate) => !/^(pass|passed)$/i.test(String(candidate && candidate.status || \"\"))) || rows[0] || {};\n}\nfunction readSeedPartInventorySnapshotContext() {\n\tconst seed = readJson(path.join(artifactDir, \"qa-live-data-seed-result.json\")) || {};\n\tconst selected = seed && seed.selected || {};\n\tconst context = selected.part_inventory_snapshot_context || selected.partInventorySnapshotContext || null;\n\tif (!context || typeof context !== \"object\") return null;\n\tconst partIds = uniqueStrings(context.part_ids || context.partIds || []);\n\tconst dayKeys = uniqueStrings(context.day_keys || context.dayKeys || []);\n\tif (!partIds.length && !dayKeys.length && !Number(context.snapshot_count || context.snapshotCount || 0)) return null;\n\treturn { ...context, part_ids: partIds, day_keys: dayKeys };\n}\nfunction shouldRunPartInventorySnapshotProof() {\n\tconst context = readSeedPartInventorySnapshotContext();\n\tif (!context) return false;\n\tconst text = [activeRowText(), targetRoute].join(\"\n\");\n\treturn /\b(reportDailyInventorySnapshot|inventory-daily-snapshots|dailys+inventorys+snapshot|parts+inventorys+snapshot|warehouse_location|Parts)\b/i.test(text);\n}\nfunction normalizePartSnapshotDayKey(value) {\n\tconst text = String(value || \"\").trim();\n\tconst match = /d{4}-d{2}-d{2}/.exec(text);\n\tif (match) return match[0];\n\tconst date = new Date(text);\n\treturn Number.isFinite(date.getTime()) ? date.toISOString().slice(0, 10) : \"\";\n}\nfunction partSnapshotRowPartId(row) {\n\tconst metadata = row && typeof row.metadata === \"object\" ? row.metadata : {};\n\treturn String(metadata.id_part || row.id_part || row.id_item || row.id_source || \"\").trim();\n}\nfunction partSnapshotRowYardId(row) {\n\tconst metadata = row && typeof row.metadata === \"object\" ? row.metadata : {};\n\tconst explicit = String(metadata.id_yard || row.id_yard || row.id_warehouse_location || \"\").trim();\n\tif (explicit) return explicit;\n\tconst source = String(row && row.id_source || \"\");\n\tconst sourceMatch = /^yard:([A-Za-z0-9_-]+)/i.exec(source);\n\treturn sourceMatch ? sourceMatch[1] : \"\";\n}\nfunction normalizeWarehouseName(value) {\n\treturn String(value || \"\").trim().toLowerCase().replace(/s+/g, \" \");\n}\nfunction methodDateFromDayKey(dayKey) {\n\treturn new Date(dayKey + \"T12:00:00.000Z\");\n}\nfunction resolveWsUrl() {\n\tif (/^https:/i.test(serverUrl)) return serverUrl.replace(/^https:/i, \"wss:\");\n\tif (/^http:/i.test(serverUrl)) return serverUrl.replace(/^http:/i, \"ws:\");\n\treturn serverUrl;\n}\nfunction callResolveIOMethodViaWs(auth, route, methodName, args) {\n\treturn new Promise((resolve, reject) => {\n\t\tconst token = auth && auth.accessToken;\n\t\tif (!token) {\n\t\t\treject(new Error(\"Missing access token for websocket method proof.\"));\n\t\t\treturn;\n\t\t}\n\t\tconst WebSocket = requireQaModule(\"ws\");\n\t\tconst { unpack } = requireQaModule(\"msgpackr\");\n\t\tconst ws = new WebSocket(resolveWsUrl(), [token], { origin: clientUrl });\n\t\tconst messageId = Date.now() + Math.floor(Math.random() * 100000);\n\t\tconst timeout = setTimeout(() => {\n\t\t\ttry { ws.close(); } catch (error) {}\n\t\t\treject(new Error(\"Timed out waiting for \" + methodName + \" websocket response.\"));\n\t\t}, Number(process.env.RESOLVEIO_SUPPORT_QA_METHOD_PROOF_TIMEOUT_MS || process.env.RESOLVEIO_RUNNER_QA_METHOD_PROOF_TIMEOUT_MS || 30000));\n\t\tlet settled = false;\n\t\tconst finish = (error, value) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timeout);\n\t\t\ttry { ws.close(); } catch (closeError) {}\n\t\t\tif (error) reject(error);\n\t\t\telse resolve(value);\n\t\t};\n\t\tws.on(\"open\", () => {\n\t\t\tconst payload = [[route || \"/\", new Date().toISOString(), messageId, \"method\", methodName, ...(args || [])]];\n\t\t\tws.send(JSON.stringify(payload));\n\t\t});\n\t\tws.on(\"message\", (raw) => {\n\t\t\tlet messages = [];\n\t\t\tconst text = Buffer.isBuffer(raw) ? raw.toString(\"utf8\") : String(raw || \"\");\n\t\t\tif (text === \"ping\") {\n\t\t\t\ttry { ws.send(\"pong\"); } catch (error) {}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst decoded = Buffer.isBuffer(raw) ? unpack(raw) : JSON.parse(text);\n\t\t\t\tmessages = Array.isArray(decoded) ? decoded : [decoded];\n\t\t\t}\n\t\t\tcatch (error) { return; }\n\t\t\tfor (const payload of messages) {\n\t\t\t\tif (!payload || payload.messageId !== messageId) continue;\n\t\t\t\tif (payload.data === \"ACK\" && payload.hasError === false) continue;\n\t\t\t\tif (payload.hasError) finish(new Error(typeof payload.data === \"string\" ? payload.data : JSON.stringify(payload.data || {})));\n\t\t\t\telse finish(null, payload.data);\n\t\t\t}\n\t\t});\n\t\tws.on(\"error\", (error) => finish(error));\n\t});\n}\nasync function readPartInventorySnapshotProofData(context, dayKey) {\n\tconst { MongoClient } = mongoRequire();\n\tconst client = new MongoClient(safeLocalMongoUrl());\n\tawait client.connect();\n\ttry {\n\t\tconst db = client.db();\n\t\tconst query = { section: \"Parts\" };\n\t\tif (dayKey) query.day_key = dayKey;\n\t\tconst partIds = uniqueStrings(context.part_ids || []);\n\t\tif (partIds.length) query.$or = [{ \"metadata.id_part\": { $in: partIds } }, { id_part: { $in: partIds } }];\n\t\tconst snapshots = await db.collection(\"inventory-daily-snapshots\").find(query).sort({ day_key: -1, item_name: 1, location: 1 }).limit(120).toArray();\n\t\tconst yardIds = uniqueStrings(snapshots.map(partSnapshotRowYardId));\n\t\tconst yards = yardIds.length ? await db.collection(\"yards\").find({ _id: { $in: yardIds } }).project({ _id: 1, name: 1 }).toArray() : [];\n\t\tconst yardById = new Map(yards.map((yard) => [String(yard._id), yard]));\n\t\treturn { snapshots, yards, yardById };\n\t} finally {\n\t\tawait client.close().catch(() => undefined);\n\t}\n}\nasync function renderPartInventorySnapshotProofScreenshot(page, payload, rowRoute, screenshotPath) {\n\tconst escapeHtml = (value) => String(value === undefined || value === null ? \"\" : value).replace(/[&<>\"']/g, (char) => ({ \"&\": \"&\", \"<\": \"<\", \">\": \">\", \"\"\": \""\", \"'\": \"'\" }[char]));\n\tconst comparisons = (payload.comparisons || []).slice(0, 12).map((entry) => \"<tr><td>\" + escapeHtml(entry.partId || entry.itemName || \"part\") + \"</td><td>\" + escapeHtml(entry.beforeWarehouse || \"\") + \"</td><td>\" + escapeHtml(entry.expectedYardName || \"\") + \"</td><td>\" + escapeHtml(entry.afterWarehouse || \"\") + \"</td><td>\" + (entry.pass ? \"<span class=\"ok\">PASS</span>\" : \"<span class=\"bad\">FAIL</span>\") + \"</td></tr>\").join(\"\");\n\tconst html = \"<!doctype html><html><head><meta charset=\"utf-8\"><style>body{margin:0;background:#f5f7fb;color:#111827;font-family:Arial,Helvetica,sans-serif}.wrap{padding:42px 52px}.eyebrow{font-size:16px;text-transform:uppercase;color:#475569;font-weight:700}.title{font-size:34px;font-weight:800;margin:10px 0}.caption{font-size:20px;line-height:1.35;color:#1f2937;margin:0 0 22px}.grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px;margin:22px 0}.card{background:white;border:2px solid #d7dde8;border-radius:8px;padding:18px}.label{font-size:14px;color:#64748b;font-weight:700;text-transform:uppercase}.value{font-size:28px;font-weight:800;margin-top:8px}.ok{color:#047857;font-weight:800}.bad{color:#b91c1c;font-weight:800}table{width:100%;border-collapse:collapse;background:white;border:2px solid #d7dde8;border-radius:8px;overflow:hidden;font-size:17px}th{background:#111827;color:white;text-align:left;padding:12px}td{border-top:1px solid #e5e7eb;padding:12px}.footer{margin-top:20px;font-size:16px;color:#475569}.path{font-family:Menlo,Consolas,monospace;font-size:14px;color:#334155}</style></head><body><main class=\"wrap\"><div class=\"eyebrow\">ResolveIO Support QA Business Proof</div><div class=\"title\">Part Inventory Snapshot Warehouse Attribution</div><p class=\"caption\">\" + escapeHtml(payload.caption || \"\") + \"</p><section class=\"grid\"><div class=\"card\"><div class=\"label\">Report Method</div><div class=\"value\">reportDailyInventorySnapshot</div></div><div class=\"card\"><div class=\"label\">Snapshot Date</div><div class=\"value\">\" + escapeHtml(payload.dayKey || \"\") + \"</div></div><div class=\"card\"><div class=\"label\">Stale Rows Corrected</div><div class=\"value \" + (payload.pass ? \"ok\" : \"bad\") + \"\">\" + Number(payload.correctedStaleRows || 0) + \"/\" + Number(payload.staleRows || 0) + \"</div></div></section><table><thead><tr><th>Part</th><th>Before Saved Warehouse</th><th>Expected Yard</th><th>Method Response Warehouse</th><th>Result</th></tr></thead><tbody>\" + comparisons + \"</tbody></table><div class=\"footer\">Before: saved historical Parts snapshot rows contained stale warehouse_location values. Action: called reportDailyInventorySnapshot(date, [\"Parts\"]) on the local QA server. After: the method response used the authoritative yard lineage for the affected part rows.</div><div class=\"footer path\">Route: \" + escapeHtml(rowRoute || targetRoute) + \" | Artifacts: qa-part-inventory-snapshot-proof.json, aiqa-business-assertion.json, qa-coverage-matrix.json</div></main></body></html>\";\n\tawait page.setViewport({ width: Math.max(viewportWidth, 1600), height: Math.max(viewportHeight, 900) }).catch(() => undefined);\n\tawait page.setContent(html, { waitUntil: \"domcontentloaded\", timeout: 30000 });\n\tawait page.screenshot({ path: screenshotPath, type: \"png\", fullPage: false });\n}\nasync function runPartInventorySnapshotMethodProof(page, routeSummary, auth) {\n\tif (!shouldRunPartInventorySnapshotProof()) return null;\n\tconst context = readSeedPartInventorySnapshotContext();\n\tconst row = activeMatrixRow();\n\tconst rowRoute = String(row.route || row.screen || \"/print\").trim() || \"/print\";\n\tconst rowWorkflow = String(row.workflow || row.action_under_test || \"Invoke reportDailyInventorySnapshot(date, [\"Parts\"]) and verify Part warehouse_location uses authoritative yard lineage.\").trim();\n\tconst proofPath = path.join(artifactDir, \"qa-part-inventory-snapshot-proof.json\");\n\tconst businessAssertionPath = path.join(artifactDir, \"aiqa-business-assertion.json\");\n\tconst beforeAfterScreenshotPath = path.join(artifactDir, \"support-business-proof-before-after.png\");\n\tconst requestedDayKeys = uniqueStrings(context.day_keys || []).map(normalizePartSnapshotDayKey).filter(Boolean);\n\tconst dayKey = requestedDayKeys[0] || normalizePartSnapshotDayKey(new Date(Date.now() - 86400000).toISOString());\n\tconst writeFailed = async (message, extra) => {\n\t\tconst payload = { status: \"failed\", targetRoute: rowRoute, dayKey, context, error: message, ...(extra || {}), updated_at: new Date().toISOString() };\n\t\twriteJson(proofPath, payload);\n\t\twriteJson(businessAssertionPath, { assertion: String(row.assertion || row.required_proof || \"Part inventory snapshot warehouse attribution proof\"), status: \"failed\", result: \"business_assertion_failed\", outcome: \"business_assertion_failed\", workflow: rowWorkflow, route: rowRoute, before: \"\", action: \"Attempted deterministic reportDailyInventorySnapshot websocket method proof.\", expected: \"Affected Part rows return the yard named by snapshot metadata.id_yard instead of stale saved warehouse_location.\", after: \"\", observed: message, dataProof: message, mongoDelta: {}, artifactPaths: [proofPath, matrixPath], metadata: { supportDiagnosisProof: false, proofType: \"part_inventory_snapshot_report_method\", generatedBy: \"resolveio_runner_part_inventory_snapshot_business_proof\", generatedAt: new Date().toISOString() } });\n\t\tconst matrix = readJson(matrixPath) || { status: \"started\", rows: [] };\n\t\tconst rows = matrixRows(matrix);\n\t\tconst activeIndex = Math.max(0, rows.indexOf(row));\n\t\tif (rows[activeIndex]) { rows[activeIndex].status = \"failed\"; rows[activeIndex].result = \"failed\"; rows[activeIndex].acceptance_blocked = true; rows[activeIndex].blocker = message; rows[activeIndex].artifact = proofPath; }\n\t\tmatrix.rows = rows;\n\t\tmatrix.status = \"failed\";\n\t\tmatrix.part_inventory_snapshot_proof = proofPath;\n\t\tmatrix.aiqa_business_assertion = businessAssertionPath;\n\t\tmatrix.updated_at = new Date().toISOString();\n\t\twriteJson(matrixPath, matrix);\n\t\treturn payload;\n\t};\n\ttry {\n\t\tconst data = await readPartInventorySnapshotProofData(context, dayKey);\n\t\tif (!data.snapshots.length) return await writeFailed(\"No seeded Part inventory daily snapshot rows were available for day_key \" + dayKey + \".\");\n\t\tconst methodResult = await callResolveIOMethodViaWs(auth, rowRoute, \"reportDailyInventorySnapshot\", [methodDateFromDayKey(dayKey), [\"Parts\"]]);\n\t\tconst responseRows = Array.isArray(methodResult && methodResult.rows) ? methodResult.rows : [];\n\t\tconst comparisons = data.snapshots.map((snapshot) => {\n\t\t\tconst partId = partSnapshotRowPartId(snapshot);\n\t\t\tconst yardId = partSnapshotRowYardId(snapshot);\n\t\t\tconst yard = yardId ? data.yardById.get(String(yardId)) : null;\n\t\t\tconst expectedYardName = String(yard && yard.name || \"\").trim();\n\t\t\tconst beforeWarehouse = String(snapshot.warehouse_location || snapshot.location || \"\").trim();\n\t\t\tconst responseCandidates = responseRows.filter((candidate) => !partId || partSnapshotRowPartId(candidate) === partId || String(candidate.item_name || candidate.name || \"\") === String(snapshot.item_name || snapshot.name || \"\"));\n\t\t\tconst afterRow = responseCandidates.find((candidate) => expectedYardName && normalizeWarehouseName(candidate.warehouse_location || candidate.location) === normalizeWarehouseName(expectedYardName)) || responseCandidates[0] || null;\n\t\t\tconst afterWarehouse = String(afterRow && (afterRow.warehouse_location || afterRow.location) || \"\").trim();\n\t\t\tconst staleBefore = !!expectedYardName && !!beforeWarehouse && normalizeWarehouseName(beforeWarehouse) !== normalizeWarehouseName(expectedYardName);\n\t\t\treturn { partId, itemName: String(snapshot.item_name || snapshot.name || \"\"), dayKey: String(snapshot.day_key || \"\"), beforeWarehouse, expectedYardName, afterWarehouse, staleBefore, pass: staleBefore && !!afterWarehouse && normalizeWarehouseName(afterWarehouse) === normalizeWarehouseName(expectedYardName) };\n\t\t}).filter((entry) => entry.expectedYardName);\n\t\tconst staleRows = comparisons.filter((entry) => entry.staleBefore);\n\t\tconst passedRows = staleRows.filter((entry) => entry.pass);\n\t\tconst pass = staleRows.length > 0 && passedRows.length === staleRows.length;\n\t\tconst caption = pass\n\t\t\t? \"Part inventory snapshot proof passed: \" + passedRows.length + \" stale saved row(s) returned the authoritative yard warehouse in reportDailyInventorySnapshot.\"\n\t\t\t: \"Part inventory snapshot proof failed: staleRows=\" + staleRows.length + \", corrected=\" + passedRows.length + \".\";\n\t\tconst payload = { status: pass ? \"pass\" : \"failed\", targetRoute: rowRoute, dayKey, methodName: \"reportDailyInventorySnapshot\", context, snapshotCount: data.snapshots.length, responseRowCount: responseRows.length, staleRows: staleRows.length, correctedStaleRows: passedRows.length, comparisons, caption, screenshot: beforeAfterScreenshotPath, page: routeSummary, updated_at: new Date().toISOString() };\n\t\tawait renderPartInventorySnapshotProofScreenshot(page, payload, rowRoute, beforeAfterScreenshotPath).catch(() => undefined);\n\t\twriteJson(proofPath, payload);\n\t\tconst businessAssertion = {\n\t\t\tassertion: String(row.assertion || row.required_proof || \"Affected Part warehouse_location maps to authoritative yard lineage in reportDailyInventorySnapshot response.\").trim(),\n\t\t\tstatus: pass ? \"pass\" : \"failed\",\n\t\t\tresult: pass ? \"business_assertion_passed\" : \"business_assertion_failed\",\n\t\t\toutcome: pass ? \"business_assertion_passed\" : \"business_assertion_failed\",\n\t\t\tworkflow: rowWorkflow,\n\t\t\troute: rowRoute,\n\t\t\tbefore: \"Saved non-today Parts snapshot rows for day_key \" + dayKey + \" included \" + staleRows.length + \" stale warehouse_location value(s): \" + staleRows.map((entry) => (entry.itemName || entry.partId) + \"=\" + entry.beforeWarehouse).join(\"; \"),\n\t\t\taction: \"Called reportDailyInventorySnapshot(\" + dayKey + \", [\"Parts\"]) through the local QA websocket method path.\",\n\t\t\texpected: \"Every affected stale Part row returns the yard named by metadata.id_yard in warehouse_location.\",\n\t\t\tafter: \"Method response corrected \" + passedRows.length + \" of \" + staleRows.length + \" stale row(s): \" + passedRows.map((entry) => (entry.itemName || entry.partId) + \"=\" + entry.afterWarehouse).join(\"; \"),\n\t\t\tobserved: caption,\n\t\t\tdataProof: comparisons.map((entry) => (entry.itemName || entry.partId || \"part\") + \": before=\" + entry.beforeWarehouse + \", expected=\" + entry.expectedYardName + \", after=\" + entry.afterWarehouse + \", pass=\" + entry.pass).join(\"\n\"),\n\t\t\tmongoDelta: { collection: \"inventory-daily-snapshots\", day_key: dayKey, staleRows: staleRows.length, correctedStaleRows: passedRows.length, responseRowCount: responseRows.length },\n\t\t\tartifactPaths: [proofPath, beforeAfterScreenshotPath, matrixPath],\n\t\t\tmetadata: { supportDiagnosisProof: pass, proofType: \"part_inventory_snapshot_report_method\", methodPath: \"server/src/methods/report.ts reportDailyInventorySnapshot\", generatedBy: \"resolveio_runner_part_inventory_snapshot_business_proof\", generatedAt: new Date().toISOString() }\n\t\t};\n\t\twriteJson(businessAssertionPath, businessAssertion);\n\t\tconst matrix = readJson(matrixPath) || { status: \"started\", rows: [] };\n\t\tconst rows = matrixRows(matrix);\n\t\tconst rowIndex = rows.findIndex((candidate) => String(candidate && candidate.workflow || \"\") === rowWorkflow) >= 0 ? rows.findIndex((candidate) => String(candidate && candidate.workflow || \"\") === rowWorkflow) : rows.findIndex((candidate) => !/^(pass|passed)$/i.test(String(candidate && candidate.status || \"\")));\n\t\tconst activeIndex = rowIndex >= 0 ? rowIndex : 0;\n\t\tif (rows[activeIndex]) {\n\t\t\trows[activeIndex].status = pass ? \"pass\" : \"failed\";\n\t\t\trows[activeIndex].result = pass ? \"pass\" : \"failed\";\n\t\t\trows[activeIndex].acceptance_blocked = !pass;\n\t\t\trows[activeIndex].screenshot = beforeAfterScreenshotPath;\n\t\t\trows[activeIndex].screenshots = [beforeAfterScreenshotPath, passScreenshotPath].filter(Boolean);\n\t\t\trows[activeIndex].caption = caption;\n\t\t\trows[activeIndex].artifact = proofPath;\n\t\t\trows[activeIndex].artifacts = [{ path: proofPath, caption: \"Part inventory snapshot method response proof.\" }, { screenshot: beforeAfterScreenshotPath, caption }, { path: businessAssertionPath, caption: \"AIQaBusinessAssertion for support diagnosis proof plan.\" }];\n\t\t\trows[activeIndex].persisted_assertion = businessAssertion.dataProof;\n\t\t\tif (!pass) rows[activeIndex].blocker = caption;\n\t\t}\n\t\tmatrix.rows = rows;\n\t\tmatrix.status = pass ? \"pass\" : \"failed\";\n\t\tmatrix.part_inventory_snapshot_proof = proofPath;\n\t\tmatrix.aiqa_business_assertion = businessAssertionPath;\n\t\tmatrix.updated_at = new Date().toISOString();\n\t\twriteJson(matrixPath, matrix);\n\t\treturn payload;\n\t} catch (error) {\n\t\treturn await writeFailed(error && (error.stack || error.message) || String(error));\n\t}\n}\n"], ["\nfunction activeMatrixRow() {\n\tconst matrix = readJson(matrixPath) || {};\n\tconst rows = matrixRows(matrix);\n\treturn rows.find((candidate) => !/^(pass|passed)$/i.test(String(candidate && candidate.status || \"\"))) || rows[0] || {};\n}\nfunction readSeedPartInventorySnapshotContext() {\n\tconst seed = readJson(path.join(artifactDir, \"qa-live-data-seed-result.json\")) || {};\n\tconst selected = seed && seed.selected || {};\n\tconst context = selected.part_inventory_snapshot_context || selected.partInventorySnapshotContext || null;\n\tif (!context || typeof context !== \"object\") return null;\n\tconst partIds = uniqueStrings(context.part_ids || context.partIds || []);\n\tconst dayKeys = uniqueStrings(context.day_keys || context.dayKeys || []);\n\tif (!partIds.length && !dayKeys.length && !Number(context.snapshot_count || context.snapshotCount || 0)) return null;\n\treturn { ...context, part_ids: partIds, day_keys: dayKeys };\n}\nfunction shouldRunPartInventorySnapshotProof() {\n\tconst context = readSeedPartInventorySnapshotContext();\n\tif (!context) return false;\n\tconst text = [activeRowText(), targetRoute].join(\"\\n\");\n\treturn /\\b(reportDailyInventorySnapshot|inventory-daily-snapshots|daily\\s+inventory\\s+snapshot|part\\s+inventory\\s+snapshot|warehouse_location|Parts)\\b/i.test(text);\n}\nfunction normalizePartSnapshotDayKey(value) {\n\tconst text = String(value || \"\").trim();\n\tconst match = /\\d{4}-\\d{2}-\\d{2}/.exec(text);\n\tif (match) return match[0];\n\tconst date = new Date(text);\n\treturn Number.isFinite(date.getTime()) ? date.toISOString().slice(0, 10) : \"\";\n}\nfunction partSnapshotRowPartId(row) {\n\tconst metadata = row && typeof row.metadata === \"object\" ? row.metadata : {};\n\treturn String(metadata.id_part || row.id_part || row.id_item || row.id_source || \"\").trim();\n}\nfunction partSnapshotRowYardId(row) {\n\tconst metadata = row && typeof row.metadata === \"object\" ? row.metadata : {};\n\tconst explicit = String(metadata.id_yard || row.id_yard || row.id_warehouse_location || \"\").trim();\n\tif (explicit) return explicit;\n\tconst source = String(row && row.id_source || \"\");\n\tconst sourceMatch = /^yard:([A-Za-z0-9_-]+)/i.exec(source);\n\treturn sourceMatch ? sourceMatch[1] : \"\";\n}\nfunction normalizeWarehouseName(value) {\n\treturn String(value || \"\").trim().toLowerCase().replace(/\\s+/g, \" \");\n}\nfunction methodDateFromDayKey(dayKey) {\n\treturn new Date(dayKey + \"T12:00:00.000Z\");\n}\nfunction resolveWsUrl() {\n\tif (/^https:/i.test(serverUrl)) return serverUrl.replace(/^https:/i, \"wss:\");\n\tif (/^http:/i.test(serverUrl)) return serverUrl.replace(/^http:/i, \"ws:\");\n\treturn serverUrl;\n}\nfunction callResolveIOMethodViaWs(auth, route, methodName, args) {\n\treturn new Promise((resolve, reject) => {\n\t\tconst token = auth && auth.accessToken;\n\t\tif (!token) {\n\t\t\treject(new Error(\"Missing access token for websocket method proof.\"));\n\t\t\treturn;\n\t\t}\n\t\tconst WebSocket = requireQaModule(\"ws\");\n\t\tconst { unpack } = requireQaModule(\"msgpackr\");\n\t\tconst ws = new WebSocket(resolveWsUrl(), [token], { origin: clientUrl });\n\t\tconst messageId = Date.now() + Math.floor(Math.random() * 100000);\n\t\tconst timeout = setTimeout(() => {\n\t\t\ttry { ws.close(); } catch (error) {}\n\t\t\treject(new Error(\"Timed out waiting for \" + methodName + \" websocket response.\"));\n\t\t}, Number(process.env.RESOLVEIO_SUPPORT_QA_METHOD_PROOF_TIMEOUT_MS || process.env.RESOLVEIO_RUNNER_QA_METHOD_PROOF_TIMEOUT_MS || 30000));\n\t\tlet settled = false;\n\t\tconst finish = (error, value) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timeout);\n\t\t\ttry { ws.close(); } catch (closeError) {}\n\t\t\tif (error) reject(error);\n\t\t\telse resolve(value);\n\t\t};\n\t\tws.on(\"open\", () => {\n\t\t\tconst payload = [[route || \"/\", new Date().toISOString(), messageId, \"method\", methodName, ...(args || [])]];\n\t\t\tws.send(JSON.stringify(payload));\n\t\t});\n\t\tws.on(\"message\", (raw) => {\n\t\t\tlet messages = [];\n\t\t\tconst text = Buffer.isBuffer(raw) ? raw.toString(\"utf8\") : String(raw || \"\");\n\t\t\tif (text === \"ping\") {\n\t\t\t\ttry { ws.send(\"pong\"); } catch (error) {}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst decoded = Buffer.isBuffer(raw) ? unpack(raw) : JSON.parse(text);\n\t\t\t\tmessages = Array.isArray(decoded) ? decoded : [decoded];\n\t\t\t}\n\t\t\tcatch (error) { return; }\n\t\t\tfor (const payload of messages) {\n\t\t\t\tif (!payload || payload.messageId !== messageId) continue;\n\t\t\t\tif (payload.data === \"ACK\" && payload.hasError === false) continue;\n\t\t\t\tif (payload.hasError) finish(new Error(typeof payload.data === \"string\" ? payload.data : JSON.stringify(payload.data || {})));\n\t\t\t\telse finish(null, payload.data);\n\t\t\t}\n\t\t});\n\t\tws.on(\"error\", (error) => finish(error));\n\t});\n}\nasync function readPartInventorySnapshotProofData(context, dayKey) {\n\tconst { MongoClient } = mongoRequire();\n\tconst client = new MongoClient(safeLocalMongoUrl());\n\tawait client.connect();\n\ttry {\n\t\tconst db = client.db();\n\t\tconst query = { section: \"Parts\" };\n\t\tif (dayKey) query.day_key = dayKey;\n\t\tconst partIds = uniqueStrings(context.part_ids || []);\n\t\tif (partIds.length) query.$or = [{ \"metadata.id_part\": { $in: partIds } }, { id_part: { $in: partIds } }];\n\t\tconst snapshots = await db.collection(\"inventory-daily-snapshots\").find(query).sort({ day_key: -1, item_name: 1, location: 1 }).limit(120).toArray();\n\t\tconst yardIds = uniqueStrings(snapshots.map(partSnapshotRowYardId));\n\t\tconst yards = yardIds.length ? await db.collection(\"yards\").find({ _id: { $in: yardIds } }).project({ _id: 1, name: 1 }).toArray() : [];\n\t\tconst yardById = new Map(yards.map((yard) => [String(yard._id), yard]));\n\t\treturn { snapshots, yards, yardById };\n\t} finally {\n\t\tawait client.close().catch(() => undefined);\n\t}\n}\nasync function renderPartInventorySnapshotProofScreenshot(page, payload, rowRoute, screenshotPath) {\n\tconst escapeHtml = (value) => String(value === undefined || value === null ? \"\" : value).replace(/[&<>\"']/g, (char) => ({ \"&\": \"&\", \"<\": \"<\", \">\": \">\", \"\\\"\": \""\", \"'\": \"'\" }[char]));\n\tconst comparisons = (payload.comparisons || []).slice(0, 12).map((entry) => \"<tr><td>\" + escapeHtml(entry.partId || entry.itemName || \"part\") + \"</td><td>\" + escapeHtml(entry.beforeWarehouse || \"\") + \"</td><td>\" + escapeHtml(entry.expectedYardName || \"\") + \"</td><td>\" + escapeHtml(entry.afterWarehouse || \"\") + \"</td><td>\" + (entry.pass ? \"<span class=\\\"ok\\\">PASS</span>\" : \"<span class=\\\"bad\\\">FAIL</span>\") + \"</td></tr>\").join(\"\");\n\tconst html = \"<!doctype html><html><head><meta charset=\\\"utf-8\\\"><style>body{margin:0;background:#f5f7fb;color:#111827;font-family:Arial,Helvetica,sans-serif}.wrap{padding:42px 52px}.eyebrow{font-size:16px;text-transform:uppercase;color:#475569;font-weight:700}.title{font-size:34px;font-weight:800;margin:10px 0}.caption{font-size:20px;line-height:1.35;color:#1f2937;margin:0 0 22px}.grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px;margin:22px 0}.card{background:white;border:2px solid #d7dde8;border-radius:8px;padding:18px}.label{font-size:14px;color:#64748b;font-weight:700;text-transform:uppercase}.value{font-size:28px;font-weight:800;margin-top:8px}.ok{color:#047857;font-weight:800}.bad{color:#b91c1c;font-weight:800}table{width:100%;border-collapse:collapse;background:white;border:2px solid #d7dde8;border-radius:8px;overflow:hidden;font-size:17px}th{background:#111827;color:white;text-align:left;padding:12px}td{border-top:1px solid #e5e7eb;padding:12px}.footer{margin-top:20px;font-size:16px;color:#475569}.path{font-family:Menlo,Consolas,monospace;font-size:14px;color:#334155}</style></head><body><main class=\\\"wrap\\\"><div class=\\\"eyebrow\\\">ResolveIO Support QA Business Proof</div><div class=\\\"title\\\">Part Inventory Snapshot Warehouse Attribution</div><p class=\\\"caption\\\">\" + escapeHtml(payload.caption || \"\") + \"</p><section class=\\\"grid\\\"><div class=\\\"card\\\"><div class=\\\"label\\\">Report Method</div><div class=\\\"value\\\">reportDailyInventorySnapshot</div></div><div class=\\\"card\\\"><div class=\\\"label\\\">Snapshot Date</div><div class=\\\"value\\\">\" + escapeHtml(payload.dayKey || \"\") + \"</div></div><div class=\\\"card\\\"><div class=\\\"label\\\">Stale Rows Corrected</div><div class=\\\"value \" + (payload.pass ? \"ok\" : \"bad\") + \"\\\">\" + Number(payload.correctedStaleRows || 0) + \"/\" + Number(payload.staleRows || 0) + \"</div></div></section><table><thead><tr><th>Part</th><th>Before Saved Warehouse</th><th>Expected Yard</th><th>Method Response Warehouse</th><th>Result</th></tr></thead><tbody>\" + comparisons + \"</tbody></table><div class=\\\"footer\\\">Before: saved historical Parts snapshot rows contained stale warehouse_location values. Action: called reportDailyInventorySnapshot(date, [\\\"Parts\\\"]) on the local QA server. After: the method response used the authoritative yard lineage for the affected part rows.</div><div class=\\\"footer path\\\">Route: \" + escapeHtml(rowRoute || targetRoute) + \" | Artifacts: qa-part-inventory-snapshot-proof.json, aiqa-business-assertion.json, qa-coverage-matrix.json</div></main></body></html>\";\n\tawait page.setViewport({ width: Math.max(viewportWidth, 1600), height: Math.max(viewportHeight, 900) }).catch(() => undefined);\n\tawait page.setContent(html, { waitUntil: \"domcontentloaded\", timeout: 30000 });\n\tawait page.screenshot({ path: screenshotPath, type: \"png\", fullPage: false });\n}\nasync function runPartInventorySnapshotMethodProof(page, routeSummary, auth) {\n\tif (!shouldRunPartInventorySnapshotProof()) return null;\n\tconst context = readSeedPartInventorySnapshotContext();\n\tconst row = activeMatrixRow();\n\tconst rowRoute = String(row.route || row.screen || \"/print\").trim() || \"/print\";\n\tconst rowWorkflow = String(row.workflow || row.action_under_test || \"Invoke reportDailyInventorySnapshot(date, [\\\"Parts\\\"]) and verify Part warehouse_location uses authoritative yard lineage.\").trim();\n\tconst proofPath = path.join(artifactDir, \"qa-part-inventory-snapshot-proof.json\");\n\tconst businessAssertionPath = path.join(artifactDir, \"aiqa-business-assertion.json\");\n\tconst beforeAfterScreenshotPath = path.join(artifactDir, \"support-business-proof-before-after.png\");\n\tconst requestedDayKeys = uniqueStrings(context.day_keys || []).map(normalizePartSnapshotDayKey).filter(Boolean);\n\tconst dayKey = requestedDayKeys[0] || normalizePartSnapshotDayKey(new Date(Date.now() - 86400000).toISOString());\n\tconst writeFailed = async (message, extra) => {\n\t\tconst payload = { status: \"failed\", targetRoute: rowRoute, dayKey, context, error: message, ...(extra || {}), updated_at: new Date().toISOString() };\n\t\twriteJson(proofPath, payload);\n\t\twriteJson(businessAssertionPath, { assertion: String(row.assertion || row.required_proof || \"Part inventory snapshot warehouse attribution proof\"), status: \"failed\", result: \"business_assertion_failed\", outcome: \"business_assertion_failed\", workflow: rowWorkflow, route: rowRoute, before: \"\", action: \"Attempted deterministic reportDailyInventorySnapshot websocket method proof.\", expected: \"Affected Part rows return the yard named by snapshot metadata.id_yard instead of stale saved warehouse_location.\", after: \"\", observed: message, dataProof: message, mongoDelta: {}, artifactPaths: [proofPath, matrixPath], metadata: { supportDiagnosisProof: false, proofType: \"part_inventory_snapshot_report_method\", generatedBy: \"resolveio_runner_part_inventory_snapshot_business_proof\", generatedAt: new Date().toISOString() } });\n\t\tconst matrix = readJson(matrixPath) || { status: \"started\", rows: [] };\n\t\tconst rows = matrixRows(matrix);\n\t\tconst activeIndex = Math.max(0, rows.indexOf(row));\n\t\tif (rows[activeIndex]) { rows[activeIndex].status = \"failed\"; rows[activeIndex].result = \"failed\"; rows[activeIndex].acceptance_blocked = true; rows[activeIndex].blocker = message; rows[activeIndex].artifact = proofPath; }\n\t\tmatrix.rows = rows;\n\t\tmatrix.status = \"failed\";\n\t\tmatrix.part_inventory_snapshot_proof = proofPath;\n\t\tmatrix.aiqa_business_assertion = businessAssertionPath;\n\t\tmatrix.updated_at = new Date().toISOString();\n\t\twriteJson(matrixPath, matrix);\n\t\treturn payload;\n\t};\n\ttry {\n\t\tconst data = await readPartInventorySnapshotProofData(context, dayKey);\n\t\tif (!data.snapshots.length) return await writeFailed(\"No seeded Part inventory daily snapshot rows were available for day_key \" + dayKey + \".\");\n\t\tconst methodResult = await callResolveIOMethodViaWs(auth, rowRoute, \"reportDailyInventorySnapshot\", [methodDateFromDayKey(dayKey), [\"Parts\"]]);\n\t\tconst responseRows = Array.isArray(methodResult && methodResult.rows) ? methodResult.rows : [];\n\t\tconst comparisons = data.snapshots.map((snapshot) => {\n\t\t\tconst partId = partSnapshotRowPartId(snapshot);\n\t\t\tconst yardId = partSnapshotRowYardId(snapshot);\n\t\t\tconst yard = yardId ? data.yardById.get(String(yardId)) : null;\n\t\t\tconst expectedYardName = String(yard && yard.name || \"\").trim();\n\t\t\tconst beforeWarehouse = String(snapshot.warehouse_location || snapshot.location || \"\").trim();\n\t\t\tconst responseCandidates = responseRows.filter((candidate) => !partId || partSnapshotRowPartId(candidate) === partId || String(candidate.item_name || candidate.name || \"\") === String(snapshot.item_name || snapshot.name || \"\"));\n\t\t\tconst afterRow = responseCandidates.find((candidate) => expectedYardName && normalizeWarehouseName(candidate.warehouse_location || candidate.location) === normalizeWarehouseName(expectedYardName)) || responseCandidates[0] || null;\n\t\t\tconst afterWarehouse = String(afterRow && (afterRow.warehouse_location || afterRow.location) || \"\").trim();\n\t\t\tconst staleBefore = !!expectedYardName && !!beforeWarehouse && normalizeWarehouseName(beforeWarehouse) !== normalizeWarehouseName(expectedYardName);\n\t\t\treturn { partId, itemName: String(snapshot.item_name || snapshot.name || \"\"), dayKey: String(snapshot.day_key || \"\"), beforeWarehouse, expectedYardName, afterWarehouse, staleBefore, pass: staleBefore && !!afterWarehouse && normalizeWarehouseName(afterWarehouse) === normalizeWarehouseName(expectedYardName) };\n\t\t}).filter((entry) => entry.expectedYardName);\n\t\tconst staleRows = comparisons.filter((entry) => entry.staleBefore);\n\t\tconst passedRows = staleRows.filter((entry) => entry.pass);\n\t\tconst pass = staleRows.length > 0 && passedRows.length === staleRows.length;\n\t\tconst caption = pass\n\t\t\t? \"Part inventory snapshot proof passed: \" + passedRows.length + \" stale saved row(s) returned the authoritative yard warehouse in reportDailyInventorySnapshot.\"\n\t\t\t: \"Part inventory snapshot proof failed: staleRows=\" + staleRows.length + \", corrected=\" + passedRows.length + \".\";\n\t\tconst payload = { status: pass ? \"pass\" : \"failed\", targetRoute: rowRoute, dayKey, methodName: \"reportDailyInventorySnapshot\", context, snapshotCount: data.snapshots.length, responseRowCount: responseRows.length, staleRows: staleRows.length, correctedStaleRows: passedRows.length, comparisons, caption, screenshot: beforeAfterScreenshotPath, page: routeSummary, updated_at: new Date().toISOString() };\n\t\tawait renderPartInventorySnapshotProofScreenshot(page, payload, rowRoute, beforeAfterScreenshotPath).catch(() => undefined);\n\t\twriteJson(proofPath, payload);\n\t\tconst businessAssertion = {\n\t\t\tassertion: String(row.assertion || row.required_proof || \"Affected Part warehouse_location maps to authoritative yard lineage in reportDailyInventorySnapshot response.\").trim(),\n\t\t\tstatus: pass ? \"pass\" : \"failed\",\n\t\t\tresult: pass ? \"business_assertion_passed\" : \"business_assertion_failed\",\n\t\t\toutcome: pass ? \"business_assertion_passed\" : \"business_assertion_failed\",\n\t\t\tworkflow: rowWorkflow,\n\t\t\troute: rowRoute,\n\t\t\tbefore: \"Saved non-today Parts snapshot rows for day_key \" + dayKey + \" included \" + staleRows.length + \" stale warehouse_location value(s): \" + staleRows.map((entry) => (entry.itemName || entry.partId) + \"=\" + entry.beforeWarehouse).join(\"; \"),\n\t\t\taction: \"Called reportDailyInventorySnapshot(\" + dayKey + \", [\\\"Parts\\\"]) through the local QA websocket method path.\",\n\t\t\texpected: \"Every affected stale Part row returns the yard named by metadata.id_yard in warehouse_location.\",\n\t\t\tafter: \"Method response corrected \" + passedRows.length + \" of \" + staleRows.length + \" stale row(s): \" + passedRows.map((entry) => (entry.itemName || entry.partId) + \"=\" + entry.afterWarehouse).join(\"; \"),\n\t\t\tobserved: caption,\n\t\t\tdataProof: comparisons.map((entry) => (entry.itemName || entry.partId || \"part\") + \": before=\" + entry.beforeWarehouse + \", expected=\" + entry.expectedYardName + \", after=\" + entry.afterWarehouse + \", pass=\" + entry.pass).join(\"\\n\"),\n\t\t\tmongoDelta: { collection: \"inventory-daily-snapshots\", day_key: dayKey, staleRows: staleRows.length, correctedStaleRows: passedRows.length, responseRowCount: responseRows.length },\n\t\t\tartifactPaths: [proofPath, beforeAfterScreenshotPath, matrixPath],\n\t\t\tmetadata: { supportDiagnosisProof: pass, proofType: \"part_inventory_snapshot_report_method\", methodPath: \"server/src/methods/report.ts reportDailyInventorySnapshot\", generatedBy: \"resolveio_runner_part_inventory_snapshot_business_proof\", generatedAt: new Date().toISOString() }\n\t\t};\n\t\twriteJson(businessAssertionPath, businessAssertion);\n\t\tconst matrix = readJson(matrixPath) || { status: \"started\", rows: [] };\n\t\tconst rows = matrixRows(matrix);\n\t\tconst rowIndex = rows.findIndex((candidate) => String(candidate && candidate.workflow || \"\") === rowWorkflow) >= 0 ? rows.findIndex((candidate) => String(candidate && candidate.workflow || \"\") === rowWorkflow) : rows.findIndex((candidate) => !/^(pass|passed)$/i.test(String(candidate && candidate.status || \"\")));\n\t\tconst activeIndex = rowIndex >= 0 ? rowIndex : 0;\n\t\tif (rows[activeIndex]) {\n\t\t\trows[activeIndex].status = pass ? \"pass\" : \"failed\";\n\t\t\trows[activeIndex].result = pass ? \"pass\" : \"failed\";\n\t\t\trows[activeIndex].acceptance_blocked = !pass;\n\t\t\trows[activeIndex].screenshot = beforeAfterScreenshotPath;\n\t\t\trows[activeIndex].screenshots = [beforeAfterScreenshotPath, passScreenshotPath].filter(Boolean);\n\t\t\trows[activeIndex].caption = caption;\n\t\t\trows[activeIndex].artifact = proofPath;\n\t\t\trows[activeIndex].artifacts = [{ path: proofPath, caption: \"Part inventory snapshot method response proof.\" }, { screenshot: beforeAfterScreenshotPath, caption }, { path: businessAssertionPath, caption: \"AIQaBusinessAssertion for support diagnosis proof plan.\" }];\n\t\t\trows[activeIndex].persisted_assertion = businessAssertion.dataProof;\n\t\t\tif (!pass) rows[activeIndex].blocker = caption;\n\t\t}\n\t\tmatrix.rows = rows;\n\t\tmatrix.status = pass ? \"pass\" : \"failed\";\n\t\tmatrix.part_inventory_snapshot_proof = proofPath;\n\t\tmatrix.aiqa_business_assertion = businessAssertionPath;\n\t\tmatrix.updated_at = new Date().toISOString();\n\t\twriteJson(matrixPath, matrix);\n\t\treturn payload;\n\t} catch (error) {\n\t\treturn await writeFailed(error && (error.stack || error.message) || String(error));\n\t}\n}\n"]))).trim().split('\n');
|
|
2708
2708
|
}
|
|
2709
2709
|
function buildResolveIORunnerQaWorkflowProbeScript() {
|
|
2710
2710
|
return __spreadArray(__spreadArray([
|