@resolveio/server-lib 22.3.226 → 22.3.228
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
|
@@ -1,4 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
|
|
3
|
+
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
|
|
4
|
+
return cooked;
|
|
5
|
+
};
|
|
6
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
7
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
8
|
+
if (!m) return o;
|
|
9
|
+
var i = m.call(o), r, ar = [], e;
|
|
10
|
+
try {
|
|
11
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
12
|
+
}
|
|
13
|
+
catch (error) { e = { error: error }; }
|
|
14
|
+
finally {
|
|
15
|
+
try {
|
|
16
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
17
|
+
}
|
|
18
|
+
finally { if (e) throw e.error; }
|
|
19
|
+
}
|
|
20
|
+
return ar;
|
|
21
|
+
};
|
|
22
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
23
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
24
|
+
if (ar || !(i in from)) {
|
|
25
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
26
|
+
ar[i] = from[i];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
30
|
+
};
|
|
2
31
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
32
|
exports.buildResolveIORunnerQaEnvScript = buildResolveIORunnerQaEnvScript;
|
|
4
33
|
exports.buildResolveIORunnerQaPreflightScript = buildResolveIORunnerQaPreflightScript;
|
|
@@ -1738,8 +1767,10 @@ function buildResolveIORunnerQaLiveDataSeederScript() {
|
|
|
1738
1767
|
' const start = Math.max(0, match.index - 120);',
|
|
1739
1768
|
' const end = Math.min(text.length, match.index + 144);',
|
|
1740
1769
|
' const around = text.slice(start, end);',
|
|
1741
|
-
'
|
|
1742
|
-
'
|
|
1770
|
+
' const before = text.slice(Math.max(0, match.index - 48), match.index);',
|
|
1771
|
+
' const after = text.slice(match.index, Math.min(text.length, match.index + 72));',
|
|
1772
|
+
' if (/\\b(id_yard|yard\\s*id)\\b/i.test(before)) { yardIds.add(String(match[0]).toLowerCase()); continue; }',
|
|
1773
|
+
' if (/\\b(id_part|part\\s*id|affected\\s+part)\\b/i.test(before + after)) partIds.add(String(match[0]).toLowerCase());',
|
|
1743
1774
|
' }',
|
|
1744
1775
|
' }',
|
|
1745
1776
|
' return { partIds: Array.from(partIds).slice(0, 16), yardIds: Array.from(yardIds).slice(0, 16), dayKeys: Array.from(dayKeys).slice(0, 12) };',
|
|
@@ -1840,7 +1871,10 @@ function buildResolveIORunnerQaLiveDataSeederScript() {
|
|
|
1840
1871
|
' if (/^(true|1|yes|on)$/i.test(explicit)) return true;',
|
|
1841
1872
|
' if (/^(false|0|no|off)$/i.test(explicit)) return false;',
|
|
1842
1873
|
' const text = readSeedHintText();',
|
|
1843
|
-
'
|
|
1874
|
+
' const billingSurface = /\\b(invoice|invoicing|billing|billable|tax|taxes|surcharge|checkout|check\\s*out|pick\\s*ticket)\\b/i.test(text);',
|
|
1875
|
+
' if (billingSurface) return true;',
|
|
1876
|
+
' if (shouldSeedPartInventorySnapshotContext()) return false;',
|
|
1877
|
+
' return /\\binventory\\b/i.test(text);',
|
|
1844
1878
|
'}',
|
|
1845
1879
|
'',
|
|
1846
1880
|
'function shouldSeedPricingImportFixtures() {',
|
|
@@ -2669,8 +2703,11 @@ function buildResolveIORunnerBugfixComparisonQaScript() {
|
|
|
2669
2703
|
''
|
|
2670
2704
|
].join('\n');
|
|
2671
2705
|
}
|
|
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');
|
|
2708
|
+
}
|
|
2672
2709
|
function buildResolveIORunnerQaWorkflowProbeScript() {
|
|
2673
|
-
return [
|
|
2710
|
+
return __spreadArray(__spreadArray([
|
|
2674
2711
|
'#!/usr/bin/env node',
|
|
2675
2712
|
"'use strict';",
|
|
2676
2713
|
'',
|
|
@@ -3452,7 +3489,8 @@ function buildResolveIORunnerQaWorkflowProbeScript() {
|
|
|
3452
3489
|
' matrix.updated_at = new Date().toISOString();',
|
|
3453
3490
|
' writeJson(matrixPath, matrix);',
|
|
3454
3491
|
' return payload;',
|
|
3455
|
-
'}'
|
|
3492
|
+
'}'
|
|
3493
|
+
], __read(buildResolveIOPartInventorySnapshotProofScriptLines()), false), [
|
|
3456
3494
|
'function updateMatrix(status, screenshotPath, caption, assertion) {',
|
|
3457
3495
|
' const matrix = readJson(matrixPath) || { status: "started", rows: [] };',
|
|
3458
3496
|
' const routeProbePassed = status === "route_probe_pass" || status === "pass";',
|
|
@@ -3495,6 +3533,11 @@ function buildResolveIORunnerQaWorkflowProbeScript() {
|
|
|
3495
3533
|
' let specializedProofPath = specializedProof ? path.join(artifactDir, "qa-pricing-import-proof.json") : "";',
|
|
3496
3534
|
' let specializedProofLabel = specializedProof ? "Pricing import workbook business proof" : "";',
|
|
3497
3535
|
' if (!specializedProof) {',
|
|
3536
|
+
' specializedProof = await runPartInventorySnapshotMethodProof(page, summary, auth);',
|
|
3537
|
+
' specializedProofPath = specializedProof ? path.join(artifactDir, "qa-part-inventory-snapshot-proof.json") : "";',
|
|
3538
|
+
' specializedProofLabel = specializedProof ? "Part inventory snapshot report method business proof" : "";',
|
|
3539
|
+
' }',
|
|
3540
|
+
' if (!specializedProof) {',
|
|
3498
3541
|
' specializedProof = await runAssetLocationRowProof(page, summary);',
|
|
3499
3542
|
' specializedProofPath = specializedProof ? path.join(artifactDir, "qa-asset-location-proof.json") : "";',
|
|
3500
3543
|
' specializedProofLabel = specializedProof ? "Asset location list/detail/edit business proof" : "";',
|
|
@@ -3544,7 +3587,7 @@ function buildResolveIORunnerQaWorkflowProbeScript() {
|
|
|
3544
3587
|
' }',
|
|
3545
3588
|
'})();',
|
|
3546
3589
|
''
|
|
3547
|
-
].join('\n');
|
|
3590
|
+
], false).join('\n');
|
|
3548
3591
|
}
|
|
3549
3592
|
function buildResolveIORunnerQaToolsReadme(options) {
|
|
3550
3593
|
if (options === void 0) { options = {}; }
|
|
@@ -3583,6 +3626,7 @@ function buildResolveIORunnerQaToolsReadme(options) {
|
|
|
3583
3626
|
'For From/To, source/target, dropdown, combobox, rio-select, filter, item, customer, yard, chemical, or treatment-plan selection workflows, capture pass screenshots only after the selected values are visible in the controls/chips/labels. The QA matrix data/assertion/caption must name the selected values; empty controls, placeholder text, or route-load screenshots are blocker evidence, not pass evidence.',
|
|
3584
3627
|
'For import/export/form-submit/data workflows, prove before/action/after with representative data and a concrete row/count/value assertion.',
|
|
3585
3628
|
'For pricing import/upload bugs, drive the actual Manage Pricing browser import for the attached/template variants and assert localhost Mongo pricing row/count/value changes. Validator-only proof must fail.',
|
|
3629
|
+
'For Part Inventory Snapshot / reportDailyInventorySnapshot warehouse bugs, use the deterministic method proof in `qa-workflow-probe.js`: it calls the local websocket method for the seeded day/Parts section, compares returned `warehouse_location` values against seeded yard lineage, and writes `aiqa-business-assertion.json` plus `support-business-proof-before-after.png` without launching another model or Angular build.',
|
|
3586
3630
|
'For asset location/current-yard bugs, prove the exact asset/unit on list, detail, and edit/save screens, with a joined/canonical yard assertion and stale yard name absence proof.',
|
|
3587
3631
|
'For Update Interchangeables/Mass Update chemical bugs, select the real source and target chemicals, run the update, and assert before/after treatment-plan/tank document counts or ids in localhost Mongo. Route-load or dropdown-only proof must fail.',
|
|
3588
3632
|
'For data-backed workflows, run `qa-live-data-seed.js` after the local app is ready and before browser clickthrough. It reads a bounded live-data slice from `RESOLVEIO_QA_LIVE_MONGO_URL` or staged mongo context, writes only to localhost QA Mongo, prefers ticket-mentioned invoice/BOL/order/ticket identifiers, and records `qa-artifacts/qa-live-data-seed-result.json`.',
|
|
@@ -3597,5 +3641,6 @@ function buildResolveIORunnerQaToolsReadme(options) {
|
|
|
3597
3641
|
''
|
|
3598
3642
|
].filter(function (line) { return line !== ''; }).join('\n');
|
|
3599
3643
|
}
|
|
3644
|
+
var templateObject_1;
|
|
3600
3645
|
|
|
3601
3646
|
//# sourceMappingURL=ai-runner-qa-tools.js.map
|