From a8ebdad50946ecd3f8443eca3f53d4af9e877bcd Mon Sep 17 00:00:00 2001 From: Trong Do Date: Mon, 3 Aug 2026 18:51:46 +0700 Subject: [PATCH 1/4] [FE] Problem 1: Three ways to sum to n --- src/problem1/README.md | 127 +++ src/problem1/STRESS-TEST.md | 78 ++ src/problem1/audit.js | 664 +++++++++++++++ src/problem1/index.js | 427 ++++++++++ src/problem1/logs/.gitignore | 2 + src/problem1/run-stress.cmd | 26 + src/problem1/stress-test.js | 1490 ++++++++++++++++++++++++++++++++++ src/problem1/verify-audit.js | 294 +++++++ 8 files changed, 3108 insertions(+) create mode 100644 src/problem1/README.md create mode 100644 src/problem1/STRESS-TEST.md create mode 100644 src/problem1/audit.js create mode 100644 src/problem1/index.js create mode 100644 src/problem1/logs/.gitignore create mode 100644 src/problem1/run-stress.cmd create mode 100644 src/problem1/stress-test.js create mode 100644 src/problem1/verify-audit.js diff --git a/src/problem1/README.md b/src/problem1/README.md new file mode 100644 index 0000000000..a7587bc68d --- /dev/null +++ b/src/problem1/README.md @@ -0,0 +1,127 @@ +# Problem 1 — Complete quality suite + +## Files + +```text +src/problem1/ +├── index.js +├── audit.js +├── verify-audit.js +├── stress-test.js +├── run-stress.cmd +├── README.md +└── logs/ +``` + +## Normal execution + +```javascript +const { + sum_to_n_a, + sum_to_n_b, + sum_to_n_c, +} = require("./index"); + +console.log(sum_to_n_a(5)); // 15 +``` + +## Mathematical audit + +From `src/problem1`: + +```bat +node audit.js 5 all +``` + +Generated files: + +```text +logs\audit-....log +logs\audit-....jsonl +logs\audit-....manifest.json +``` + +The JSONL evidence uses a SHA-256 hash chain. Every event contains: + +- continuous `globalStep`; +- one `auditId`; +- `previousHash`; +- `eventHash`; +- timestamp; +- algorithm; +- action; +- calculation data. + +## Verify an audit + +```bat +node verify-audit.js logs\.manifest.json +``` + +Expected: + +```text +Audit integrity: VALID +``` + +Any changed, removed, reordered, duplicated, or truncated JSONL event is detected. + +## Run complete testing + +Recommended: + +```bat +node stress-test.js standard +``` + +Or: + +```bat +run-stress.cmd standard +``` + +Modes: + +```text +smoke quick local validation +standard recommended before commit +heavy high-volume validation +``` + +Deterministic seed: + +```bat +node stress-test.js standard 20260803 +``` + +## Coverage + +The suite includes: + +1. Valid positive, negative, zero, and boundary cases. +2. Exhaustive signed integer ranges. +3. Deterministic random tests. +4. BigInt independent oracle comparisons. +5. Precision tests near `Number.MAX_SAFE_INTEGER`. +6. Invalid type and non-integer rejection. +7. Out-of-contract result-overflow rejection. +8. Mathematical invariant testing. +9. Audit callback schema checks. +10. Logger failure propagation. +11. Audit CLI success path. +12. Audit CLI invalid argument paths. +13. File-system failure injection. +14. Algorithm failure injection and partial error audit. +15. Mutation-test sensitivity. +16. Audit tamper detection. +17. Audit truncation detection. +18. Concurrent audit isolation. +19. Subprocess timeout detection. +20. Throughput and long-loop performance checks. + +Reports are written to: + +```text +logs\stress-test-....log +logs\stress-test-....json +``` diff --git a/src/problem1/STRESS-TEST.md b/src/problem1/STRESS-TEST.md new file mode 100644 index 0000000000..2f437284c0 --- /dev/null +++ b/src/problem1/STRESS-TEST.md @@ -0,0 +1,78 @@ +# Problem 1 stress test + +Place these files in: + +```text +D:\99\code-challenge\src\problem1\ +``` + +## Standard run + +When the terminal is already in `src\problem1`: + +```bat +node stress-test.js standard +``` + +Or: + +```bat +run-stress.cmd standard +``` + +From the repository root: + +```bat +node src\problem1\stress-test.js standard +``` + +## Modes + +```text +smoke Fast verification +standard Recommended before committing +heavy High-volume test +``` + +Examples: + +```bat +node stress-test.js smoke +node stress-test.js standard +node stress-test.js heavy +``` + +Use a deterministic seed: + +```bat +node stress-test.js standard 20260803 +``` + +The same mode and seed produce the same random inputs. + +## Coverage + +The stress test checks: + +- edge cases and zero; +- positive and negative integers; +- exhaustive small ranges; +- deterministic randomized inputs; +- precision near `Number.MAX_SAFE_INTEGER`; +- exact BigInt reference values; +- agreement between implementations; +- `S(-n) = -S(n)`; +- `S(n) - S(n - 1) = n`; +- invalid input rejection; +- audit callback events from `index.js`; +- integration with `audit.js`; +- throughput and the long-running O(n) implementation. + +## Reports + +Reports are written to: + +```text +src\problem1\logs\stress-test-....log +src\problem1\logs\stress-test-....json +``` diff --git a/src/problem1/audit.js b/src/problem1/audit.js new file mode 100644 index 0000000000..7afbca5a63 --- /dev/null +++ b/src/problem1/audit.js @@ -0,0 +1,664 @@ +"use strict"; + +/** + * Separate mathematical audit runner. + * + * CLI: + * node audit.js 5 all + * node audit.js -4 a + * + * Environment: + * PROBLEM1_LOG_DIR= + * + * Output: + * *.log Human-readable proof + * *.jsonl Hash-chained raw evidence + * *.manifest.json Integrity manifest + */ + +const crypto = require("node:crypto"); +const fs = require("node:fs"); +const path = require("node:path"); + +const defaultImplementations = require("./index"); + +const DEFAULT_ALGORITHMS = { + a: { + name: "A_COMBINATORICS", + label: "Combinatorics", + run: defaultImplementations.sum_to_n_a, + }, + b: { + name: "B_LINEAR_ALGEBRA", + label: "Linear algebra", + run: defaultImplementations.sum_to_n_b, + }, + c: { + name: "C_PROBABILITY_SYMMETRY", + label: "Probability symmetry", + run: defaultImplementations.sum_to_n_c, + }, +}; + +function parseArguments(argv) { + const rawN = argv[2]; + const selectedAlgorithm = (argv[3] ?? "all").toLowerCase(); + + if (rawN === undefined) { + throw new Error("Missing n. Example: node audit.js 5 all"); + } + + const n = Number(rawN); + + if (!Number.isSafeInteger(n)) { + throw new TypeError("n must be a safe integer"); + } + + if ( + selectedAlgorithm !== "all" && + !Object.hasOwn(DEFAULT_ALGORITHMS, selectedAlgorithm) + ) { + throw new Error('Algorithm must be "a", "b", "c", or "all".'); + } + + return { n, selectedAlgorithm }; +} + +function safeTimestamp() { + return new Date() + .toISOString() + .replaceAll(":", "-") + .replaceAll(".", "-"); +} + +function sha256(text) { + return crypto + .createHash("sha256") + .update(text) + .digest("hex"); +} + +function formatMatrix(matrix) { + if (!Array.isArray(matrix) || matrix.length === 0) { + return String(matrix); + } + + const widths = matrix[0].map((_, column) => + Math.max(...matrix.map((row) => String(row[column]).length)), + ); + + return matrix + .map((row) => { + const cells = row.map((value, column) => + String(value).padStart(widths[column]), + ); + + return `│ ${cells.join(" ")} │`; + }) + .join("\n"); +} + +function formatVector(vector) { + return `[${vector.join(", ")}]^T`; +} + +function append(filepath, text = "") { + fs.appendFileSync(filepath, `${text}\n`, "utf8"); +} + +function writeHeading(filepath, title) { + append(filepath); + append(filepath, "=".repeat(100)); + append(filepath, title); + append(filepath, "=".repeat(100)); +} + +function describeEvent(event) { + const { algorithm, action, data } = event; + + switch (`${algorithm}:${action}`) { + case "AUDIT_SESSION:SESSION_STARTED": + return [ + `Input n = ${data.n}`, + `Selected algorithms = ${data.selectedAlgorithm}`, + ]; + + case "AUDIT_SESSION:ALGORITHM_STARTED": + return [`Start ${data.algorithm}`]; + + case "AUDIT_SESSION:ALGORITHM_COMPLETED": + return [`${data.algorithm} returned ${data.result}`]; + + case "AUDIT_SESSION:RESULTS_CROSS_CHECKED": + return [ + `Results = ${JSON.stringify(data.results)}`, + `Implementations agree = ${data.consistent}`, + ]; + + case "AUDIT_SESSION:INDEPENDENT_REFERENCE_CALCULATED": + return [ + `Independent BigInt reference = ${data.reference}`, + `Every result matches reference = ${data.matches}`, + ]; + + case "AUDIT_SESSION:SESSION_PASSED": + return ["Audit status = PASSED"]; + + case "AUDIT_SESSION:SESSION_FAILED": + return ["Audit status = FAILED"]; + + case "AUDIT_SESSION:SESSION_ERROR": + return [ + `Audit status = ERROR`, + `${data.error.name}: ${data.error.message}`, + ]; + + case "A_COMBINATORICS:INPUT_RECEIVED": + case "B_LINEAR_ALGEBRA:INPUT_RECEIVED": + case "C_PROBABILITY_SYMMETRY:INPUT_RECEIVED": + return [`Receive n = ${data.n}`]; + + case "A_COMBINATORICS:INPUT_VALIDATED": + case "B_LINEAR_ALGEBRA:INPUT_VALIDATED": + case "C_PROBABILITY_SYMMETRY:INPUT_VALIDATED": + return [ + `Input is a safe integer = ${data.isSafeInteger}`, + `Result range is safe = ${data.isWithinSafeResultRange}`, + ]; + + case "A_COMBINATORICS:MAGNITUDE_CALCULATED": + case "B_LINEAR_ALGEBRA:MAGNITUDE_CALCULATED": + case "C_PROBABILITY_SYMMETRY:MAGNITUDE_CALCULATED": + return [`|n| = ${data.magnitude}`]; + + case "A_COMBINATORICS:COMBINATION_IDENTITY_APPLIED": + return [ + `S(n) = C(n + 1, 2) = n(n + 1)/2`, + `Substitute: ${data.leftFactor} × ${data.rightFactor} ÷ ${data.divisor}`, + ]; + + case "A_COMBINATORICS:EVEN_FACTOR_DIVIDED": + return [ + `${data.factor}: ${data.before} ÷ ${data.divisor} = ${data.after}`, + ]; + + case "A_COMBINATORICS:FACTORS_MULTIPLIED": + return [ + `${data.leftFactor} × ${data.rightFactor} = ${data.positiveSum}`, + ]; + + case "A_COMBINATORICS:SIGN_RESTORED": + case "B_LINEAR_ALGEBRA:SIGN_RESTORED": + case "C_PROBABILITY_SYMMETRY:SIGN_RESTORED": + return [ + `Restore sign: ${data.positiveValue} → ${data.result}`, + ]; + + case "A_COMBINATORICS:COMPLETED": + case "B_LINEAR_ALGEBRA:COMPLETED": + case "C_PROBABILITY_SYMMETRY:COMPLETED": + return [ + `Result = ${data.result}`, + `Complexity: ${data.complexity.time} time, ${data.complexity.space} space`, + ]; + + case "B_LINEAR_ALGEBRA:STATE_MODEL_DEFINED": + return [ + `State vector = ${formatVector(data.stateVector)}`, + `Initial vector = ${formatVector(data.initialVector)}`, + `Transition matrix:`, + formatMatrix(data.transitionMatrix), + ]; + + case "B_LINEAR_ALGEBRA:MATRIX_POWER_INITIALIZED": + return [ + `Compute M^${data.targetPower} using exponentiation by squaring`, + `Identity result matrix:`, + formatMatrix(data.resultMatrix), + `Base matrix:`, + formatMatrix(data.baseMatrix), + ]; + + case "B_LINEAR_ALGEBRA:POWER_ROUND_STARTED": + return [ + `Round ${data.round}: exponent ${data.exponent} is ${data.isOdd ? "odd" : "even"}`, + ]; + + case "B_LINEAR_ALGEBRA:ODD_EXPONENT_BRANCH": + return [`${data.operation}`]; + + case "B_LINEAR_ALGEBRA:EVEN_EXPONENT_BRANCH": + return ["Skip result multiplication"]; + + case "B_LINEAR_ALGEBRA:MATRIX_MULTIPLICATION_STARTED": + return [ + `${data.purpose}, round ${data.round}`, + `Left:`, + formatMatrix(data.left), + `Right:`, + formatMatrix(data.right), + ]; + + case "B_LINEAR_ALGEBRA:MATRIX_CELL_CALCULATED": { + const expression = data.terms + .map((term) => `${term.leftValue}×${term.rightValue}`) + .join(" + "); + + return [ + `Cell [${data.row + 1},${data.column + 1}] = ${expression} = ${data.cellValue}`, + ]; + } + + case "B_LINEAR_ALGEBRA:MATRIX_MULTIPLICATION_COMPLETED": + return [ + `${data.purpose} result:`, + formatMatrix(data.result), + ]; + + case "B_LINEAR_ALGEBRA:RESULT_MATRIX_UPDATED": + return [ + `Accumulated result:`, + formatMatrix(data.resultMatrix), + ]; + + case "B_LINEAR_ALGEBRA:BASE_MATRIX_SQUARED": + return [ + `Squared base:`, + formatMatrix(data.baseMatrix), + ]; + + case "B_LINEAR_ALGEBRA:EXPONENT_HALVED": + return [ + `floor(${data.before}/2) = ${data.after}`, + ]; + + case "B_LINEAR_ALGEBRA:MATRIX_POWER_COMPLETED": + return [ + `M^${data.power}:`, + formatMatrix(data.poweredMatrix), + ]; + + case "B_LINEAR_ALGEBRA:INITIAL_VECTOR_APPLIED": + return [ + `${formatVector(data.initialVector)} → ${formatVector(data.resultingVector)}`, + `First component is the sum = ${data.positiveSum}`, + ]; + + case "C_PROBABILITY_SYMMETRY:ANTITHETIC_MODEL_DEFINED": + return [ + `Sample space ${data.sampleSpace}`, + `Mapping ${data.mapping}`, + `Pair count = ${data.pairCount}`, + `Every pair sums to ${data.constantPairSum}`, + ]; + + case "C_PROBABILITY_SYMMETRY:PAIR_ACCUMULATED": + return [ + `Pair ${data.pairIndex}: ${data.left} + ${data.right} = ${data.pairSum}`, + `${data.totalBefore} + ${data.pairSum} = ${data.totalAfter}`, + ]; + + case "C_PROBABILITY_SYMMETRY:MIDDLE_VALUE_ACCUMULATED": + return [ + `Middle value ${data.middleValue}`, + `${data.totalBefore} + ${data.middleValue} = ${data.totalAfter}`, + ]; + + case "C_PROBABILITY_SYMMETRY:MIDDLE_VALUE_NOT_REQUIRED": + return [data.reason]; + + default: + return [JSON.stringify(data)]; + } +} + +function directBigIntReference(n) { + const magnitude = BigInt(Math.abs(n)); + const positive = (magnitude * (magnitude + 1n)) / 2n; + return n < 0 ? -positive : positive; +} + +function selectedEntries(selectedAlgorithm, algorithms) { + if (selectedAlgorithm === "all") { + return Object.entries(algorithms); + } + + return [[selectedAlgorithm, algorithms[selectedAlgorithm]]]; +} + +function createOutputFiles(outputDirectory, n) { + fs.mkdirSync(outputDirectory, { recursive: true }); + + const stat = fs.statSync(outputDirectory); + + if (!stat.isDirectory()) { + throw new Error(`Log path is not a directory: ${outputDirectory}`); + } + + const unique = + `${safeTimestamp()}-pid-${process.pid}-` + + crypto.randomBytes(5).toString("hex"); + const safeN = String(n).replace("-", "minus-"); + const baseName = `audit-${unique}-n-${safeN}`; + + return { + human: path.join(outputDirectory, `${baseName}.log`), + raw: path.join(outputDirectory, `${baseName}.jsonl`), + manifest: path.join(outputDirectory, `${baseName}.manifest.json`), + }; +} + +function createWriter(files, auditId, consoleOutput) { + let globalStep = 0; + let previousHash = "GENESIS"; + const rawLines = []; + + return { + write(event) { + globalStep += 1; + + const unsignedEvent = { + auditId, + timestamp: new Date().toISOString(), + globalStep, + algorithm: event.algorithm, + action: event.action, + data: event.data ?? {}, + previousHash, + }; + + const eventHash = sha256(JSON.stringify(unsignedEvent)); + const completeEvent = { + ...unsignedEvent, + eventHash, + }; + + const rawLine = JSON.stringify(completeEvent); + rawLines.push(rawLine); + append(files.raw, rawLine); + + append( + files.human, + `[${String(globalStep).padStart(4, "0")}] ` + + `${completeEvent.algorithm} :: ${completeEvent.action}`, + ); + + for (const line of describeEvent(completeEvent)) { + for (const subLine of String(line).split("\n")) { + append(files.human, ` ${subLine}`); + } + } + + append(files.human, ` eventHash = ${eventHash}`); + append(files.human); + + if (consoleOutput) { + console.log( + `[${globalStep}] ${completeEvent.algorithm} :: ${completeEvent.action}`, + ); + } + + previousHash = eventHash; + return completeEvent; + }, + + snapshot() { + const rawText = + rawLines.length === 0 + ? "" + : `${rawLines.join("\n")}\n`; + + return { + eventCount: globalStep, + finalEventHash: previousHash, + rawSha256: sha256(rawText), + }; + }, + }; +} + +function writeManifest(files, manifest) { + const humanText = fs.readFileSync(files.human, "utf8"); + const enriched = { + ...manifest, + humanSha256: sha256(humanText), + }; + + fs.writeFileSync( + files.manifest, + JSON.stringify(enriched, null, 2), + "utf8", + ); + + return enriched; +} + +/** + * Programmatic API used by stress-test.js. + */ +function runAudit({ + n, + selectedAlgorithm = "all", + outputDirectory = + process.env.PROBLEM1_LOG_DIR ?? + path.join(__dirname, "logs"), + algorithms = DEFAULT_ALGORITHMS, + consoleOutput = true, +} = {}) { + if (!Number.isSafeInteger(n)) { + throw new TypeError("n must be a safe integer"); + } + + if ( + selectedAlgorithm !== "all" && + !Object.hasOwn(algorithms, selectedAlgorithm) + ) { + throw new Error('Algorithm must be "a", "b", "c", or "all".'); + } + + const auditId = crypto.randomUUID(); + const startedAt = new Date().toISOString(); + const files = createOutputFiles(outputDirectory, n); + + fs.writeFileSync( + files.human, + [ + "99TECH CODE CHALLENGE — PROBLEM 1", + "MATHEMATICAL PROOF AUDIT", + `Audit ID: ${auditId}`, + `Started: ${startedAt}`, + `Input n: ${n}`, + `Selection: ${selectedAlgorithm}`, + "", + ].join("\n"), + "utf8", + ); + fs.writeFileSync(files.raw, "", "utf8"); + + const writer = createWriter(files, auditId, consoleOutput); + const results = {}; + let status = "ERROR"; + let errorData = null; + + writer.write({ + algorithm: "AUDIT_SESSION", + action: "SESSION_STARTED", + data: { + n, + selectedAlgorithm, + }, + }); + + try { + for (const [key, algorithm] of selectedEntries( + selectedAlgorithm, + algorithms, + )) { + writeHeading( + files.human, + `${key.toUpperCase()}. ${algorithm.label.toUpperCase()}`, + ); + + writer.write({ + algorithm: "AUDIT_SESSION", + action: "ALGORITHM_STARTED", + data: { + key, + algorithm: algorithm.name, + }, + }); + + results[key] = algorithm.run( + n, + (event) => writer.write(event), + ); + + writer.write({ + algorithm: "AUDIT_SESSION", + action: "ALGORITHM_COMPLETED", + data: { + key, + algorithm: algorithm.name, + result: results[key], + }, + }); + } + + const values = Object.values(results); + const consistent = + values.length <= 1 || + values.every((value) => value === values[0]); + + writer.write({ + algorithm: "AUDIT_SESSION", + action: "RESULTS_CROSS_CHECKED", + data: { + results, + consistent, + }, + }); + + const reference = directBigIntReference(n); + const matches = values.every( + (value) => BigInt(value) === reference, + ); + + writer.write({ + algorithm: "AUDIT_SESSION", + action: "INDEPENDENT_REFERENCE_CALCULATED", + data: { + reference: reference.toString(), + matches, + }, + }); + + status = consistent && matches ? "PASSED" : "FAILED"; + + writer.write({ + algorithm: "AUDIT_SESSION", + action: + status === "PASSED" + ? "SESSION_PASSED" + : "SESSION_FAILED", + data: { + status, + results, + consistent, + matchesReference: matches, + }, + }); + } catch (error) { + errorData = { + name: error.name, + message: error.message, + stack: error.stack, + }; + + writer.write({ + algorithm: "AUDIT_SESSION", + action: "SESSION_ERROR", + data: { + status: "ERROR", + error: errorData, + partialResults: results, + }, + }); + } + + const integrity = writer.snapshot(); + const completedAt = new Date().toISOString(); + + writeHeading(files.human, "AUDIT SUMMARY"); + append(files.human, `Status: ${status}`); + append(files.human, `Results: ${JSON.stringify(results)}`); + append(files.human, `Events: ${integrity.eventCount}`); + append(files.human, `Final event hash: ${integrity.finalEventHash}`); + append(files.human, `Raw evidence SHA-256: ${integrity.rawSha256}`); + if (errorData) { + append(files.human, `Error: ${errorData.name}: ${errorData.message}`); + } + + const manifest = writeManifest(files, { + schemaVersion: 1, + auditId, + input: n, + selectedAlgorithm, + status, + startedAt, + completedAt, + results, + error: errorData, + eventCount: integrity.eventCount, + finalEventHash: integrity.finalEventHash, + rawSha256: integrity.rawSha256, + files: { + human: path.basename(files.human), + raw: path.basename(files.raw), + manifest: path.basename(files.manifest), + }, + }); + + return { + status, + results, + files, + manifest, + }; +} + +function runCli() { + try { + const { n, selectedAlgorithm } = + parseArguments(process.argv); + + const report = runAudit({ + n, + selectedAlgorithm, + consoleOutput: true, + }); + + console.log(""); + console.log(`Audit status : ${report.status}`); + console.log(`Proof log : ${report.files.human}`); + console.log(`Raw evidence : ${report.files.raw}`); + console.log(`Manifest : ${report.files.manifest}`); + + if (report.status !== "PASSED") { + process.exitCode = 1; + } + } catch (error) { + console.error(`Cannot start audit: ${error.message}`); + process.exitCode = 1; + } +} + +if (require.main === module) { + runCli(); +} + +module.exports = { + DEFAULT_ALGORITHMS, + parseArguments, + runAudit, + sha256, +}; diff --git a/src/problem1/index.js b/src/problem1/index.js new file mode 100644 index 0000000000..8b984db2b4 --- /dev/null +++ b/src/problem1/index.js @@ -0,0 +1,427 @@ +"use strict"; + +/** + * 99Tech Code Challenge — Problem 1 + * + * Three mathematically distinct implementations: + * A. Combinatorics + * B. Linear algebra + * C. Probability symmetry + * + * Normal calls use the required signature: + * sum_to_n_a(n) + * + * A second optional callback is used only by audit.js: + * sum_to_n_a(n, event => ...) + */ + +const MAX_SAFE_SUM_N = 134_217_727; + +function validateInput(n) { + if (!Number.isSafeInteger(n)) { + throw new TypeError("n must be a safe integer"); + } + + if (Math.abs(n) > MAX_SAFE_SUM_N) { + throw new RangeError( + `|n| must be <= ${MAX_SAFE_SUM_N} so the result remains a safe integer`, + ); + } +} + +function emit(audit, algorithm, action, data = {}) { + if (typeof audit === "function") { + audit({ algorithm, action, data }); + } +} + +function restoreSign(n, positiveValue, audit, algorithm) { + const result = n < 0 ? -positiveValue : positiveValue; + + emit(audit, algorithm, "SIGN_RESTORED", { + originalInput: n, + positiveValue, + result, + }); + + return result; +} + +/** + * A — Combinatorics + * + * S(n) = C(n + 1, 2) + * + * Time: O(1) + * Space: O(1) + */ +function sum_to_n_a(n, audit) { + const algorithm = "A_COMBINATORICS"; + + emit(audit, algorithm, "INPUT_RECEIVED", { n }); + + validateInput(n); + emit(audit, algorithm, "INPUT_VALIDATED", { + n, + isSafeInteger: true, + isWithinSafeResultRange: true, + }); + + const magnitude = Math.abs(n); + emit(audit, algorithm, "MAGNITUDE_CALCULATED", { + expression: "|n|", + magnitude, + }); + + let leftFactor = magnitude; + let rightFactor = magnitude + 1; + + emit(audit, algorithm, "COMBINATION_IDENTITY_APPLIED", { + identity: "C(n + 1, 2) = n(n + 1) / 2", + leftFactor, + rightFactor, + divisor: 2, + }); + + if (leftFactor % 2 === 0) { + const before = leftFactor; + leftFactor /= 2; + + emit(audit, algorithm, "EVEN_FACTOR_DIVIDED", { + factor: "leftFactor", + before, + divisor: 2, + after: leftFactor, + }); + } else { + const before = rightFactor; + rightFactor /= 2; + + emit(audit, algorithm, "EVEN_FACTOR_DIVIDED", { + factor: "rightFactor", + before, + divisor: 2, + after: rightFactor, + }); + } + + const positiveSum = leftFactor * rightFactor; + + emit(audit, algorithm, "FACTORS_MULTIPLIED", { + leftFactor, + rightFactor, + positiveSum, + }); + + const result = restoreSign(n, positiveSum, audit, algorithm); + + emit(audit, algorithm, "COMPLETED", { + result, + complexity: { + time: "O(1)", + space: "O(1)", + }, + }); + + return result; +} + +function identityMatrix(size) { + return Array.from( + { length: size }, + (_, row) => + Array.from( + { length: size }, + (_, column) => (row === column ? 1 : 0), + ), + ); +} + +function multiplyMatrices(left, right, audit, context) { + const algorithm = "B_LINEAR_ALGEBRA"; + const size = left.length; + const result = Array.from( + { length: size }, + () => Array(size).fill(0), + ); + + emit(audit, algorithm, "MATRIX_MULTIPLICATION_STARTED", { + ...context, + left, + right, + }); + + for (let row = 0; row < size; row += 1) { + for (let column = 0; column < size; column += 1) { + const terms = []; + + for (let k = 0; k < size; k += 1) { + const product = left[row][k] * right[k][column]; + + terms.push({ + leftValue: left[row][k], + rightValue: right[k][column], + product, + }); + + result[row][column] += product; + } + + emit(audit, algorithm, "MATRIX_CELL_CALCULATED", { + ...context, + row, + column, + terms, + cellValue: result[row][column], + }); + } + } + + emit(audit, algorithm, "MATRIX_MULTIPLICATION_COMPLETED", { + ...context, + result, + }); + + return result; +} + +/** + * B — Linear algebra using fast matrix exponentiation. + * + * State: + * [sum_k, k, 1]^T + * + * Transition: + * [1 1 1] + * [0 1 1] + * [0 0 1] + * + * Time: O(log |n|) + * Space: O(1), fixed 3 × 3 matrices + */ +function sum_to_n_b(n, audit) { + const algorithm = "B_LINEAR_ALGEBRA"; + + emit(audit, algorithm, "INPUT_RECEIVED", { n }); + + validateInput(n); + emit(audit, algorithm, "INPUT_VALIDATED", { + n, + isSafeInteger: true, + isWithinSafeResultRange: true, + }); + + const magnitude = Math.abs(n); + emit(audit, algorithm, "MAGNITUDE_CALCULATED", { + expression: "|n|", + magnitude, + }); + + const transitionMatrix = [ + [1, 1, 1], + [0, 1, 1], + [0, 0, 1], + ]; + + emit(audit, algorithm, "STATE_MODEL_DEFINED", { + stateVector: ["sum_k", "k", "1"], + initialVector: [0, 0, 1], + transitionMatrix, + }); + + let resultMatrix = identityMatrix(3); + let baseMatrix = transitionMatrix; + let exponent = magnitude; + let round = 0; + + emit(audit, algorithm, "MATRIX_POWER_INITIALIZED", { + targetPower: magnitude, + exponent, + resultMatrix, + baseMatrix, + }); + + while (exponent > 0) { + round += 1; + + emit(audit, algorithm, "POWER_ROUND_STARTED", { + round, + exponent, + isOdd: exponent % 2 === 1, + }); + + if (exponent % 2 === 1) { + emit(audit, algorithm, "ODD_EXPONENT_BRANCH", { + round, + operation: "resultMatrix = resultMatrix × baseMatrix", + }); + + resultMatrix = multiplyMatrices( + resultMatrix, + baseMatrix, + audit, + { + round, + purpose: "ACCUMULATE_RESULT", + }, + ); + + emit(audit, algorithm, "RESULT_MATRIX_UPDATED", { + round, + resultMatrix, + }); + } else { + emit(audit, algorithm, "EVEN_EXPONENT_BRANCH", { + round, + operation: "result multiplication skipped", + }); + } + + baseMatrix = multiplyMatrices( + baseMatrix, + baseMatrix, + audit, + { + round, + purpose: "SQUARE_BASE", + }, + ); + + emit(audit, algorithm, "BASE_MATRIX_SQUARED", { + round, + baseMatrix, + }); + + const previousExponent = exponent; + exponent = Math.floor(exponent / 2); + + emit(audit, algorithm, "EXPONENT_HALVED", { + round, + before: previousExponent, + after: exponent, + }); + } + + emit(audit, algorithm, "MATRIX_POWER_COMPLETED", { + power: magnitude, + poweredMatrix: resultMatrix, + }); + + const positiveSum = resultMatrix[0][2]; + + emit(audit, algorithm, "INITIAL_VECTOR_APPLIED", { + poweredMatrix: resultMatrix, + initialVector: [0, 0, 1], + resultingVector: [ + resultMatrix[0][2], + resultMatrix[1][2], + resultMatrix[2][2], + ], + positiveSum, + }); + + const result = restoreSign(n, positiveSum, audit, algorithm); + + emit(audit, algorithm, "COMPLETED", { + result, + complexity: { + time: "O(log |n|)", + space: "O(1)", + }, + }); + + return result; +} + +/** + * C — Probability symmetry / antithetic pairing. + * + * Pair x with n + 1 - x. Every pair totals n + 1. + * + * Time: O(|n|) + * Space: O(1) + */ +function sum_to_n_c(n, audit) { + const algorithm = "C_PROBABILITY_SYMMETRY"; + + emit(audit, algorithm, "INPUT_RECEIVED", { n }); + + validateInput(n); + emit(audit, algorithm, "INPUT_VALIDATED", { + n, + isSafeInteger: true, + isWithinSafeResultRange: true, + }); + + const magnitude = Math.abs(n); + emit(audit, algorithm, "MAGNITUDE_CALCULATED", { + expression: "|n|", + magnitude, + }); + + const pairCount = Math.floor(magnitude / 2); + const constantPairSum = magnitude + 1; + + emit(audit, algorithm, "ANTITHETIC_MODEL_DEFINED", { + sampleSpace: `{1, 2, ..., ${magnitude}}`, + mapping: "x ↔ n + 1 - x", + pairCount, + constantPairSum, + }); + + let positiveSum = 0; + + for (let pairIndex = 1; pairIndex <= pairCount; pairIndex += 1) { + const left = pairIndex; + const right = magnitude + 1 - pairIndex; + const pairSum = left + right; + const totalBefore = positiveSum; + + positiveSum += pairSum; + + emit(audit, algorithm, "PAIR_ACCUMULATED", { + pairIndex, + left, + right, + pairSum, + totalBefore, + totalAfter: positiveSum, + }); + } + + if (magnitude % 2 === 1) { + const middleValue = (magnitude + 1) / 2; + const totalBefore = positiveSum; + + positiveSum += middleValue; + + emit(audit, algorithm, "MIDDLE_VALUE_ACCUMULATED", { + middleValue, + totalBefore, + totalAfter: positiveSum, + }); + } else { + emit(audit, algorithm, "MIDDLE_VALUE_NOT_REQUIRED", { + reason: "The number of values is even", + }); + } + + const result = restoreSign(n, positiveSum, audit, algorithm); + + emit(audit, algorithm, "COMPLETED", { + result, + complexity: { + time: "O(|n|)", + space: "O(1)", + }, + }); + + return result; +} + +module.exports = { + MAX_SAFE_SUM_N, + sum_to_n_a, + sum_to_n_b, + sum_to_n_c, +}; diff --git a/src/problem1/logs/.gitignore b/src/problem1/logs/.gitignore new file mode 100644 index 0000000000..d6b7ef32c8 --- /dev/null +++ b/src/problem1/logs/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/src/problem1/run-stress.cmd b/src/problem1/run-stress.cmd new file mode 100644 index 0000000000..85c00a30d2 --- /dev/null +++ b/src/problem1/run-stress.cmd @@ -0,0 +1,26 @@ +@echo off +setlocal + +cd /d "%~dp0" + +set MODE=%~1 +if "%MODE%"=="" set MODE=standard + +set SEED=%~2 +if "%SEED%"=="" set SEED=20260803 + +echo Running complete Problem 1 quality suite... +echo Mode: %MODE% +echo Seed: %SEED% +echo. + +node stress-test.js %MODE% %SEED% + +echo. +if errorlevel 1 ( + echo QUALITY SUITE FAILED. + exit /b 1 +) + +echo QUALITY SUITE PASSED. +exit /b 0 diff --git a/src/problem1/stress-test.js b/src/problem1/stress-test.js new file mode 100644 index 0000000000..c5c9e29447 --- /dev/null +++ b/src/problem1/stress-test.js @@ -0,0 +1,1490 @@ +"use strict"; + +/** + * Complete functional, negative-path, audit-integrity, concurrency, + * mutation-sensitivity, and performance test suite. + * + * Run: + * node stress-test.js smoke + * node stress-test.js standard + * node stress-test.js heavy + * node stress-test.js standard 20260803 + */ + +const fs = require("node:fs"); +const os = require("node:os"); +const path = require("node:path"); +const { + spawn, + spawnSync, +} = require("node:child_process"); +const { performance } = require("node:perf_hooks"); + +const { + MAX_SAFE_SUM_N, + sum_to_n_a, + sum_to_n_b, + sum_to_n_c, +} = require("./index"); + +const { + DEFAULT_ALGORITHMS, + runAudit, +} = require("./audit"); + +const { + verifyAudit, +} = require("./verify-audit"); + +const MODES = { + smoke: { + exhaustiveLimit: 100, + randomAllCases: 100, + randomFastCases: 500, + propertyCases: 100, + concurrentAudits: 3, + cPerformanceN: 50_000, + performanceCases: 5_000, + }, + standard: { + exhaustiveLimit: 2_000, + randomAllCases: 500, + randomFastCases: 5_000, + propertyCases: 500, + concurrentAudits: 6, + cPerformanceN: 1_000_000, + performanceCases: 50_000, + }, + heavy: { + exhaustiveLimit: 10_000, + randomAllCases: 3_000, + randomFastCases: 50_000, + propertyCases: 5_000, + concurrentAudits: 12, + cPerformanceN: 5_000_000, + performanceCases: 500_000, + }, +}; + +function parseArguments(argv) { + const mode = (argv[2] ?? "standard").toLowerCase(); + const seed = Number(argv[3] ?? 20260803); + + if (!Object.hasOwn(MODES, mode)) { + throw new Error( + `Unknown mode "${mode}". Use smoke, standard, or heavy.`, + ); + } + + if (!Number.isSafeInteger(seed)) { + throw new TypeError("Seed must be a safe integer"); + } + + return { + mode, + seed, + config: MODES[mode], + }; +} + +function createRandom(seed) { + let state = seed >>> 0; + + return function random() { + state += 0x6d2b79f5; + let value = state; + + value = Math.imul(value ^ (value >>> 15), value | 1); + value ^= value + Math.imul(value ^ (value >>> 7), value | 61); + + return ((value ^ (value >>> 14)) >>> 0) / + 4_294_967_296; + }; +} + +function randomInteger(random, minimum, maximum) { + return Math.floor( + random() * (maximum - minimum + 1), + ) + minimum; +} + +function expectedBigInt(n) { + const magnitude = BigInt(Math.abs(n)); + const positive = + (magnitude * (magnitude + 1n)) / 2n; + + return n < 0 ? -positive : positive; +} + +function expectedNumber(n) { + return Number(expectedBigInt(n)); +} + +function safeTimestamp() { + return new Date() + .toISOString() + .replaceAll(":", "-") + .replaceAll(".", "-"); +} + +function formatDuration(milliseconds) { + return milliseconds >= 1_000 + ? `${(milliseconds / 1_000).toFixed(2)} s` + : `${milliseconds.toFixed(2)} ms`; +} + +function spawnPromise(command, arguments_, options = {}) { + return new Promise((resolve) => { + const child = spawn(command, arguments_, options); + let stdout = ""; + let stderr = ""; + + child.stdout?.on("data", (chunk) => { + stdout += chunk; + }); + + child.stderr?.on("data", (chunk) => { + stderr += chunk; + }); + + child.on("error", (error) => { + resolve({ + code: null, + signal: null, + stdout, + stderr, + error, + }); + }); + + child.on("close", (code, signal) => { + resolve({ + code, + signal, + stdout, + stderr, + error: null, + }); + }); + }); +} + +class Runner { + constructor({ mode, seed, config }) { + this.mode = mode; + this.seed = seed; + this.config = config; + this.random = createRandom(seed); + this.suites = []; + this.failures = []; + this.assertions = 0; + this.started = performance.now(); + this.tempRoot = fs.mkdtempSync( + path.join(os.tmpdir(), "problem1-quality-"), + ); + + const logsDirectory = path.join(__dirname, "logs"); + fs.mkdirSync(logsDirectory, { recursive: true }); + + const base = `stress-test-${safeTimestamp()}`; + this.textReport = path.join( + logsDirectory, + `${base}.log`, + ); + this.jsonReport = path.join( + logsDirectory, + `${base}.json`, + ); + + fs.writeFileSync(this.textReport, "", "utf8"); + } + + log(message = "") { + console.log(message); + fs.appendFileSync( + this.textReport, + `${message}\n`, + "utf8", + ); + } + + assert(condition, message, details = {}) { + this.assertions += 1; + + if (!condition) { + const failure = { + message, + details, + }; + + this.failures.push(failure); + throw new Error( + `${message} | ${JSON.stringify(details)}`, + ); + } + } + + async suite(name, operation) { + const before = this.assertions; + const started = performance.now(); + + this.log(`\n[RUN ] ${name}`); + + try { + const metadata = await operation(); + const durationMs = performance.now() - started; + + this.suites.push({ + name, + status: "PASSED", + durationMs, + assertions: this.assertions - before, + metadata: metadata ?? {}, + }); + + this.log( + `[PASS] ${name} | ${formatDuration(durationMs)} | ` + + `${(this.assertions - before).toLocaleString("en-US")} assertions`, + ); + } catch (error) { + const durationMs = performance.now() - started; + + this.suites.push({ + name, + status: "FAILED", + durationMs, + assertions: this.assertions - before, + error: { + name: error.name, + message: error.message, + stack: error.stack, + }, + }); + + this.log(`[FAIL] ${name} | ${error.message}`); + } + } + + assertCorrect(implementation, n, label) { + const expected = expectedNumber(n); + const actual = implementation(n); + + this.assert( + actual === expected, + `${label} returned wrong result`, + { n, expected, actual }, + ); + + this.assert( + Number.isSafeInteger(actual), + `${label} returned unsafe result`, + { n, actual }, + ); + } + + async run() { + this.log("99TECH Problem 1 — Complete quality suite"); + this.log(`Mode: ${this.mode}`); + this.log(`Seed: ${this.seed}`); + this.log(`Node: ${process.version}`); + this.log(`Temporary test root: ${this.tempRoot}`); + + await this.suite( + "Valid edge cases and exact BigInt oracle", + () => this.validEdgeCases(), + ); + + await this.suite( + "Exhaustive signed range", + () => this.exhaustiveRange(), + ); + + await this.suite( + "Deterministic randomized coverage", + () => this.randomCoverage(), + ); + + await this.suite( + "Safe-result boundary precision", + () => this.boundaryPrecision(), + ); + + await this.suite( + "Invalid type and non-integer rejection", + () => this.invalidInputs(), + ); + + await this.suite( + "Out-of-contract safe-result overflow rejection", + () => this.outOfRangeInputs(), + ); + + await this.suite( + "Mathematical invariants", + () => this.mathematicalProperties(), + ); + + await this.suite( + "Audit callback schema and logger failure propagation", + () => this.auditCallbackContract(), + ); + + await this.suite( + "Audit CLI happy path and proof verification", + () => this.auditCliHappyPath(), + ); + + await this.suite( + "Audit CLI invalid argument paths", + () => this.auditCliInvalidArguments(), + ); + + await this.suite( + "File-system failure path", + () => this.fileSystemFailure(), + ); + + await this.suite( + "Injected algorithm failure with partial error audit", + () => this.injectedAlgorithmFailure(), + ); + + await this.suite( + "Mutation-test sensitivity", + () => this.mutationSensitivity(), + ); + + await this.suite( + "Tamper and truncation detection", + () => this.tamperDetection(), + ); + + await this.suite( + "Concurrent audit isolation and filename uniqueness", + () => this.concurrentAudits(), + ); + + await this.suite( + "Subprocess timeout detection", + () => this.timeoutDetection(), + ); + + await this.suite( + "Performance and long-loop execution", + () => this.performanceChecks(), + ); + + const passed = this.suites.filter( + (suite) => suite.status === "PASSED", + ).length; + const status = + passed === this.suites.length + ? "PASSED" + : "FAILED"; + const durationMs = performance.now() - this.started; + + const report = { + status, + mode: this.mode, + seed: this.seed, + node: process.version, + platform: `${process.platform} ${process.arch}`, + assertions: this.assertions, + passedSuites: passed, + totalSuites: this.suites.length, + durationMs, + suites: this.suites, + failures: this.failures, + reports: { + text: this.textReport, + json: this.jsonReport, + }, + }; + + fs.writeFileSync( + this.jsonReport, + JSON.stringify(report, null, 2), + "utf8", + ); + + this.log("\n" + "=".repeat(100)); + this.log(`QUALITY SUITE STATUS: ${status}`); + this.log( + `Suites: ${passed}/${this.suites.length} passed`, + ); + this.log( + `Assertions: ${this.assertions.toLocaleString("en-US")}`, + ); + this.log(`Duration: ${formatDuration(durationMs)}`); + this.log(`Text report: ${this.textReport}`); + this.log(`JSON report: ${this.jsonReport}`); + + try { + fs.rmSync(this.tempRoot, { + recursive: true, + force: true, + }); + } catch { + // Report cleanup failure only as non-fatal diagnostic. + this.log( + `Warning: could not remove temp directory ${this.tempRoot}`, + ); + } + + if (status !== "PASSED") { + process.exitCode = 1; + } + + return report; + } + + validEdgeCases() { + const cases = [ + 0, + -0, + 1, + -1, + 2, + -2, + 3, + -3, + 5, + -5, + 10, + -10, + 99, + -99, + 10_000, + -10_000, + 1_000_000, + -1_000_000, + MAX_SAFE_SUM_N, + -MAX_SAFE_SUM_N, + ]; + + for (const n of cases) { + this.assertCorrect(sum_to_n_a, n, "A"); + this.assertCorrect(sum_to_n_b, n, "B"); + + if (Math.abs(n) <= this.config.cPerformanceN) { + this.assertCorrect(sum_to_n_c, n, "C"); + } + } + + return { + cases: cases.length, + }; + } + + exhaustiveRange() { + const limit = this.config.exhaustiveLimit; + + for (let n = -limit; n <= limit; n += 1) { + const expected = expectedNumber(n); + const a = sum_to_n_a(n); + const b = sum_to_n_b(n); + const c = sum_to_n_c(n); + + this.assert( + a === expected && + b === expected && + c === expected, + "Exhaustive result mismatch", + { n, expected, a, b, c }, + ); + } + + return { + range: `[-${limit}, ${limit}]`, + cases: limit * 2 + 1, + }; + } + + randomCoverage() { + for ( + let index = 0; + index < this.config.randomAllCases; + index += 1 + ) { + const n = randomInteger( + this.random, + -50_000, + 50_000, + ); + const expected = expectedNumber(n); + const a = sum_to_n_a(n); + const b = sum_to_n_b(n); + const c = sum_to_n_c(n); + + this.assert( + a === expected && + b === expected && + c === expected, + "Random all-implementation mismatch", + { index, n, expected, a, b, c }, + ); + } + + for ( + let index = 0; + index < this.config.randomFastCases; + index += 1 + ) { + const n = randomInteger( + this.random, + -MAX_SAFE_SUM_N, + MAX_SAFE_SUM_N, + ); + const expected = expectedNumber(n); + const a = sum_to_n_a(n); + const b = sum_to_n_b(n); + + this.assert( + a === expected && b === expected, + "Random large precision mismatch", + { index, n, expected, a, b }, + ); + } + + return { + allImplementationCases: + this.config.randomAllCases, + fastImplementationCases: + this.config.randomFastCases, + }; + } + + boundaryPrecision() { + const offsets = [ + 0, + 1, + 2, + 3, + 10, + 100, + 1_000, + 1_000_000, + ]; + + for (const offset of offsets) { + const magnitude = MAX_SAFE_SUM_N - offset; + + for (const n of [magnitude, -magnitude]) { + this.assertCorrect(sum_to_n_a, n, "A"); + this.assertCorrect(sum_to_n_b, n, "B"); + } + } + + this.assert( + expectedBigInt(MAX_SAFE_SUM_N) <= + BigInt(Number.MAX_SAFE_INTEGER), + "MAX_SAFE_SUM_N should be valid", + ); + + this.assert( + expectedBigInt(MAX_SAFE_SUM_N + 1) > + BigInt(Number.MAX_SAFE_INTEGER), + "MAX_SAFE_SUM_N + 1 should overflow safe result", + ); + + return { + maximumInput: MAX_SAFE_SUM_N, + maximumResult: + expectedBigInt(MAX_SAFE_SUM_N).toString(), + }; + } + + invalidInputs() { + const invalid = [ + NaN, + Infinity, + -Infinity, + 1.5, + -1.5, + "5", + null, + undefined, + {}, + [], + true, + false, + 5n, + Symbol("5"), + Number.MAX_SAFE_INTEGER + 1, + ]; + + for (const [label, implementation] of [ + ["A", sum_to_n_a], + ["B", sum_to_n_b], + ["C", sum_to_n_c], + ]) { + for (const value of invalid) { + let error; + + try { + implementation(value); + } catch (caught) { + error = caught; + } + + this.assert( + error instanceof TypeError, + `${label} failed to reject invalid input`, + { + type: typeof value, + value: String(value), + error: error?.name, + }, + ); + } + } + + return { + invalidValues: invalid.length, + implementations: 3, + }; + } + + outOfRangeInputs() { + const values = [ + MAX_SAFE_SUM_N + 1, + -(MAX_SAFE_SUM_N + 1), + Number.MAX_SAFE_INTEGER, + -Number.MAX_SAFE_INTEGER, + ]; + + for (const [label, implementation] of [ + ["A", sum_to_n_a], + ["B", sum_to_n_b], + ["C", sum_to_n_c], + ]) { + for (const n of values) { + let error; + + try { + implementation(n); + } catch (caught) { + error = caught; + } + + this.assert( + error instanceof RangeError, + `${label} should reject unsafe-result range`, + { + n, + error: error?.name, + }, + ); + } + } + + return { + rejectedValues: values, + }; + } + + mathematicalProperties() { + const maximum = 50_000; + + for ( + let index = 0; + index < this.config.propertyCases; + index += 1 + ) { + const n = randomInteger( + this.random, + 1, + maximum, + ); + + for (const [label, implementation] of [ + ["A", sum_to_n_a], + ["B", sum_to_n_b], + ["C", sum_to_n_c], + ]) { + const positive = implementation(n); + const negative = implementation(-n); + const previous = implementation(n - 1); + + this.assert( + negative === -positive, + `${label}: S(-n) = -S(n) failed`, + { n, positive, negative }, + ); + + this.assert( + positive - previous === n, + `${label}: recurrence failed`, + { + n, + positive, + previous, + }, + ); + + this.assert( + 2 * positive === n * (n + 1), + `${label}: triangular invariant failed`, + { + n, + positive, + }, + ); + } + } + + return { + cases: this.config.propertyCases, + properties: [ + "S(-n) = -S(n)", + "S(n) - S(n - 1) = n", + "2S(n) = n(n + 1)", + ], + }; + } + + auditCallbackContract() { + for (const [label, algorithm, implementation] of [ + ["A", "A_COMBINATORICS", sum_to_n_a], + ["B", "B_LINEAR_ALGEBRA", sum_to_n_b], + ["C", "C_PROBABILITY_SYMMETRY", sum_to_n_c], + ]) { + const events = []; + const result = implementation( + 5, + (event) => events.push(event), + ); + + this.assert(result === 15, `${label} result mismatch`); + this.assert(events.length > 0, `${label} emitted no events`); + this.assert( + events[0].action === "INPUT_RECEIVED", + `${label} first event mismatch`, + ); + this.assert( + events.at(-1).action === "COMPLETED", + `${label} terminal event mismatch`, + ); + this.assert( + events.every( + (event) => + event.algorithm === algorithm && + typeof event.action === "string" && + event.data && + typeof event.data === "object", + ), + `${label} event schema mismatch`, + ); + } + + const sentinel = new Error("logger failure"); + let propagated; + + try { + sum_to_n_a(5, () => { + throw sentinel; + }); + } catch (error) { + propagated = error; + } + + this.assert( + propagated === sentinel, + "Audit callback failure was silently swallowed", + ); + + return { + implementations: 3, + loggerFailurePropagates: true, + }; + } + + auditCliHappyPath() { + const outputDirectory = path.join( + this.tempRoot, + "audit-happy", + ); + + const result = runAudit({ + n: 5, + selectedAlgorithm: "all", + outputDirectory, + consoleOutput: false, + }); + + this.assert( + result.status === "PASSED", + "Programmatic audit did not pass", + { status: result.status }, + ); + + this.assert( + result.results.a === 15 && + result.results.b === 15 && + result.results.c === 15, + "Programmatic audit results mismatch", + { results: result.results }, + ); + + const verification = + verifyAudit(result.files.manifest); + + this.assert( + verification.valid, + "Fresh audit evidence failed verification", + { errors: verification.errors }, + ); + + const cliDirectory = path.join( + this.tempRoot, + "audit-cli", + ); + + const cli = spawnSync( + process.execPath, + [path.join(__dirname, "audit.js"), "5", "all"], + { + cwd: __dirname, + env: { + ...process.env, + PROBLEM1_LOG_DIR: cliDirectory, + }, + encoding: "utf8", + timeout: 30_000, + }, + ); + + this.assert( + cli.status === 0, + "Audit CLI returned non-zero", + { + status: cli.status, + stderr: cli.stderr, + }, + ); + + const manifests = fs + .readdirSync(cliDirectory) + .filter((name) => + name.endsWith(".manifest.json"), + ); + + this.assert( + manifests.length === 1, + "Audit CLI should create exactly one manifest", + { manifests }, + ); + + const cliVerification = verifyAudit( + path.join(cliDirectory, manifests[0]), + ); + + this.assert( + cliVerification.valid, + "Audit CLI evidence failed verification", + { errors: cliVerification.errors }, + ); + + return { + programmaticManifest: result.files.manifest, + cliManifest: path.join( + cliDirectory, + manifests[0], + ), + }; + } + + auditCliInvalidArguments() { + const auditPath = path.join(__dirname, "audit.js"); + const cases = [ + [], + ["abc"], + ["1.5"], + ["5", "xyz"], + ["Infinity", "all"], + ]; + + for (const arguments_ of cases) { + const result = spawnSync( + process.execPath, + [auditPath, ...arguments_], + { + cwd: __dirname, + encoding: "utf8", + timeout: 10_000, + }, + ); + + this.assert( + result.status !== 0, + "Invalid CLI arguments unexpectedly succeeded", + { + arguments_, + stdout: result.stdout, + stderr: result.stderr, + }, + ); + + this.assert( + result.stderr.includes("Cannot start audit"), + "Invalid CLI failure is not explicit", + { + arguments_, + stderr: result.stderr, + }, + ); + } + + return { + cases: cases.length, + }; + } + + fileSystemFailure() { + const fakeDirectory = path.join( + this.tempRoot, + "not-a-directory", + ); + + fs.writeFileSync( + fakeDirectory, + "I am a file", + "utf8", + ); + + const result = spawnSync( + process.execPath, + [path.join(__dirname, "audit.js"), "5", "all"], + { + cwd: __dirname, + env: { + ...process.env, + PROBLEM1_LOG_DIR: fakeDirectory, + }, + encoding: "utf8", + timeout: 10_000, + }, + ); + + this.assert( + result.status !== 0, + "Audit unexpectedly succeeded with invalid log path", + { + stdout: result.stdout, + stderr: result.stderr, + }, + ); + + this.assert( + result.stderr.includes("Cannot start audit"), + "File-system failure was not surfaced", + { + stderr: result.stderr, + }, + ); + + return { + invalidLogPath: fakeDirectory, + }; + } + + injectedAlgorithmFailure() { + const outputDirectory = path.join( + this.tempRoot, + "injected-error", + ); + + const brokenAlgorithms = { + ...DEFAULT_ALGORITHMS, + b: { + ...DEFAULT_ALGORITHMS.b, + run(n, audit) { + audit({ + algorithm: "B_LINEAR_ALGEBRA", + action: "FAULT_INJECTION_STARTED", + data: { n }, + }); + + throw new Error("Injected matrix failure"); + }, + }, + }; + + const result = runAudit({ + n: 5, + selectedAlgorithm: "all", + outputDirectory, + algorithms: brokenAlgorithms, + consoleOutput: false, + }); + + this.assert( + result.status === "ERROR", + "Injected algorithm failure did not produce ERROR status", + { status: result.status }, + ); + + this.assert( + result.results.a === 15 && + result.results.b === undefined, + "Partial results were not preserved correctly", + { results: result.results }, + ); + + const verification = + verifyAudit(result.files.manifest); + + this.assert( + verification.valid, + "Error audit evidence should remain structurally valid", + { errors: verification.errors }, + ); + + this.assert( + verification.manifest.status === "ERROR", + "Error manifest status mismatch", + ); + + return { + manifest: result.files.manifest, + partialResults: result.results, + }; + } + + mutationSensitivity() { + const mutants = [ + { + name: "off-by-one", + run: (n) => sum_to_n_a(n) + 1, + }, + { + name: "wrong-negative-sign", + run: (n) => + n < 0 + ? Math.abs(sum_to_n_a(n)) + : sum_to_n_a(n), + }, + { + name: "skip-odd-middle", + run(n) { + const magnitude = Math.abs(n); + const pairCount = Math.floor(magnitude / 2); + const positive = pairCount * (magnitude + 1); + return n < 0 ? -positive : positive; + }, + }, + { + name: "matrix-result-column-bug", + run: (n) => Math.abs(n), + }, + ]; + + const detectionCases = [ + -10, + -5, + -1, + 0, + 1, + 2, + 3, + 5, + 10, + 99, + ]; + + for (const mutant of mutants) { + const detectedBy = []; + + for (const n of detectionCases) { + let actual; + + try { + actual = mutant.run(n); + } catch { + detectedBy.push(n); + continue; + } + + if (actual !== expectedNumber(n)) { + detectedBy.push(n); + } + } + + this.assert( + detectedBy.length > 0, + "Test oracle failed to detect mutant", + { + mutant: mutant.name, + }, + ); + } + + return { + mutants: mutants.map((mutant) => mutant.name), + allDetected: true, + }; + } + + tamperDetection() { + const originalDirectory = path.join( + this.tempRoot, + "tamper-original", + ); + + const result = runAudit({ + n: 5, + selectedAlgorithm: "all", + outputDirectory: originalDirectory, + consoleOutput: false, + }); + + this.assert( + verifyAudit(result.files.manifest).valid, + "Original evidence must be valid", + ); + + const tamperDirectory = path.join( + this.tempRoot, + "tamper-copy", + ); + fs.cpSync( + originalDirectory, + tamperDirectory, + { recursive: true }, + ); + + const manifestName = + path.basename(result.files.manifest); + const tamperedManifest = path.join( + tamperDirectory, + manifestName, + ); + + const manifest = JSON.parse( + fs.readFileSync( + tamperedManifest, + "utf8", + ), + ); + const rawPath = path.join( + tamperDirectory, + manifest.files.raw, + ); + + const lines = fs + .readFileSync(rawPath, "utf8") + .trimEnd() + .split(/\r?\n/); + + const event = JSON.parse(lines[4]); + event.data = { + ...event.data, + maliciousChange: true, + }; + lines[4] = JSON.stringify(event); + + fs.writeFileSync( + rawPath, + `${lines.join("\n")}\n`, + "utf8", + ); + + const tamperedVerification = + verifyAudit(tamperedManifest); + + this.assert( + !tamperedVerification.valid, + "Modified JSONL evidence was not detected", + ); + + this.assert( + tamperedVerification.errors.some( + (error) => + error.name.includes("SHA-256") || + error.name.includes("event hash"), + ), + "Tampering failed for the expected reason", + { + errors: tamperedVerification.errors, + }, + ); + + const truncatedDirectory = path.join( + this.tempRoot, + "truncate-copy", + ); + fs.cpSync( + originalDirectory, + truncatedDirectory, + { recursive: true }, + ); + + const truncatedManifest = path.join( + truncatedDirectory, + manifestName, + ); + const truncatedManifestData = JSON.parse( + fs.readFileSync( + truncatedManifest, + "utf8", + ), + ); + const truncatedRaw = path.join( + truncatedDirectory, + truncatedManifestData.files.raw, + ); + const truncatedLines = fs + .readFileSync(truncatedRaw, "utf8") + .trimEnd() + .split(/\r?\n/); + + truncatedLines.pop(); + fs.writeFileSync( + truncatedRaw, + `${truncatedLines.join("\n")}\n`, + "utf8", + ); + + this.assert( + !verifyAudit(truncatedManifest).valid, + "Truncated evidence was not detected", + ); + + return { + modifiedEventDetected: true, + truncationDetected: true, + }; + } + + async concurrentAudits() { + const outputDirectory = path.join( + this.tempRoot, + "concurrent", + ); + fs.mkdirSync(outputDirectory, { + recursive: true, + }); + + const auditPath = path.join( + __dirname, + "audit.js", + ); + + const jobs = Array.from( + { length: this.config.concurrentAudits }, + (_, index) => + spawnPromise( + process.execPath, + [ + auditPath, + String(index + 5), + "all", + ], + { + cwd: __dirname, + env: { + ...process.env, + PROBLEM1_LOG_DIR: outputDirectory, + }, + stdio: [ + "ignore", + "pipe", + "pipe", + ], + }, + ), + ); + + const results = await Promise.all(jobs); + + this.assert( + results.every((result) => result.code === 0), + "One or more concurrent audits failed", + { + results: results.map((result) => ({ + code: result.code, + stderr: result.stderr, + })), + }, + ); + + const manifests = fs + .readdirSync(outputDirectory) + .filter((name) => + name.endsWith(".manifest.json"), + ); + + this.assert( + manifests.length === + this.config.concurrentAudits, + "Concurrent audits did not create unique manifests", + { + expected: this.config.concurrentAudits, + actual: manifests.length, + }, + ); + + const auditIds = new Set(); + const filenames = new Set(); + + for (const name of manifests) { + filenames.add(name); + const verification = verifyAudit( + path.join(outputDirectory, name), + ); + + this.assert( + verification.valid, + "Concurrent audit evidence is invalid", + { + name, + errors: verification.errors, + }, + ); + + auditIds.add( + verification.manifest.auditId, + ); + } + + this.assert( + auditIds.size === + this.config.concurrentAudits, + "Concurrent audit IDs are not unique", + { + uniqueAuditIds: auditIds.size, + }, + ); + + this.assert( + filenames.size === + this.config.concurrentAudits, + "Concurrent filenames collided", + ); + + return { + processes: this.config.concurrentAudits, + uniqueAuditIds: auditIds.size, + uniqueManifests: filenames.size, + }; + } + + timeoutDetection() { + const result = spawnSync( + process.execPath, + [ + "-e", + "setTimeout(() => console.log('late'), 5000)", + ], + { + encoding: "utf8", + timeout: 100, + }, + ); + + this.assert( + result.error?.code === "ETIMEDOUT" || + result.signal !== null, + "Subprocess timeout was not detected", + { + error: result.error?.code, + signal: result.signal, + status: result.status, + }, + ); + + return { + timeoutMilliseconds: 100, + detected: true, + }; + } + + performanceChecks() { + const inputs = Array.from( + { + length: this.config.performanceCases, + }, + () => + randomInteger( + this.random, + -MAX_SAFE_SUM_N, + MAX_SAFE_SUM_N, + ), + ); + + function benchmark(implementation) { + let checksum = 0; + const started = performance.now(); + + for (const n of inputs) { + checksum = + (checksum + implementation(n)) % + 1_000_000_007; + } + + return { + durationMs: + performance.now() - started, + checksum, + }; + } + + const a = benchmark(sum_to_n_a); + const b = benchmark(sum_to_n_b); + + this.assert( + a.checksum === b.checksum, + "Performance batch checksum mismatch", + { a, b }, + ); + + const cInput = this.config.cPerformanceN; + const cStarted = performance.now(); + const cResult = sum_to_n_c(cInput); + const cDuration = + performance.now() - cStarted; + + this.assert( + cResult === expectedNumber(cInput), + "Long-loop C result mismatch", + { + cInput, + cResult, + }, + ); + + this.assert( + cDuration < 20_000, + "Long-loop C exceeded generous 20-second budget", + { + cInput, + cDuration, + }, + ); + + return { + batchCases: inputs.length, + A: a, + B: b, + C: { + input: cInput, + durationMs: cDuration, + }, + }; + } +} + +async function main() { + try { + const arguments_ = parseArguments(process.argv); + const runner = new Runner(arguments_); + await runner.run(); + } catch (error) { + console.error( + `Cannot start quality suite: ${error.message}`, + ); + process.exitCode = 1; + } +} + +main(); diff --git a/src/problem1/verify-audit.js b/src/problem1/verify-audit.js new file mode 100644 index 0000000000..0e7de47aea --- /dev/null +++ b/src/problem1/verify-audit.js @@ -0,0 +1,294 @@ +"use strict"; + +/** + * Verify an audit manifest and its related evidence files. + * + * CLI: + * node verify-audit.js logs/audit-....manifest.json + */ + +const crypto = require("node:crypto"); +const fs = require("node:fs"); +const path = require("node:path"); + +function sha256(text) { + return crypto + .createHash("sha256") + .update(text) + .digest("hex"); +} + +function calculateEventHash(event) { + const unsignedEvent = { + auditId: event.auditId, + timestamp: event.timestamp, + globalStep: event.globalStep, + algorithm: event.algorithm, + action: event.action, + data: event.data, + previousHash: event.previousHash, + }; + + return sha256(JSON.stringify(unsignedEvent)); +} + +function verifyAudit(manifestPath) { + const absoluteManifest = path.resolve(manifestPath); + const directory = path.dirname(absoluteManifest); + + const errors = []; + const checks = []; + + function check(condition, name, details = {}) { + checks.push({ + name, + passed: Boolean(condition), + details, + }); + + if (!condition) { + errors.push({ + name, + details, + }); + } + } + + check( + fs.existsSync(absoluteManifest), + "Manifest file exists", + { manifestPath: absoluteManifest }, + ); + + if (!fs.existsSync(absoluteManifest)) { + return { + valid: false, + checks, + errors, + }; + } + + let manifest; + + try { + manifest = JSON.parse( + fs.readFileSync(absoluteManifest, "utf8"), + ); + check(true, "Manifest JSON is valid"); + } catch (error) { + check(false, "Manifest JSON is valid", { + message: error.message, + }); + + return { + valid: false, + checks, + errors, + }; + } + + const rawPath = path.join(directory, manifest.files.raw); + const humanPath = path.join(directory, manifest.files.human); + + check(fs.existsSync(rawPath), "Raw JSONL file exists", { + rawPath, + }); + check(fs.existsSync(humanPath), "Human log file exists", { + humanPath, + }); + + if (!fs.existsSync(rawPath) || !fs.existsSync(humanPath)) { + return { + valid: false, + manifest, + checks, + errors, + }; + } + + const rawText = fs.readFileSync(rawPath, "utf8"); + const humanText = fs.readFileSync(humanPath, "utf8"); + + check( + sha256(rawText) === manifest.rawSha256, + "Raw file SHA-256 matches manifest", + { + expected: manifest.rawSha256, + actual: sha256(rawText), + }, + ); + + check( + sha256(humanText) === manifest.humanSha256, + "Human log SHA-256 matches manifest", + { + expected: manifest.humanSha256, + actual: sha256(humanText), + }, + ); + + const nonEmptyLines = rawText + .split(/\r?\n/) + .filter((line) => line.trim() !== ""); + + const events = []; + + for (const [index, line] of nonEmptyLines.entries()) { + try { + events.push(JSON.parse(line)); + } catch (error) { + check(false, `JSONL line ${index + 1} is valid JSON`, { + message: error.message, + }); + } + } + + check( + events.length === manifest.eventCount, + "Event count matches manifest", + { + expected: manifest.eventCount, + actual: events.length, + }, + ); + + let expectedPreviousHash = "GENESIS"; + + for (const [index, event] of events.entries()) { + const expectedStep = index + 1; + + check( + event.globalStep === expectedStep, + `Step ${expectedStep} is continuous`, + { + expected: expectedStep, + actual: event.globalStep, + }, + ); + + check( + event.auditId === manifest.auditId, + `Step ${expectedStep} audit ID matches`, + { + expected: manifest.auditId, + actual: event.auditId, + }, + ); + + check( + event.previousHash === expectedPreviousHash, + `Step ${expectedStep} previous hash matches`, + { + expected: expectedPreviousHash, + actual: event.previousHash, + }, + ); + + const recalculated = calculateEventHash(event); + + check( + event.eventHash === recalculated, + `Step ${expectedStep} event hash is valid`, + { + expected: recalculated, + actual: event.eventHash, + }, + ); + + check( + !Number.isNaN(Date.parse(event.timestamp)), + `Step ${expectedStep} timestamp is valid`, + { + timestamp: event.timestamp, + }, + ); + + expectedPreviousHash = event.eventHash; + } + + const lastEvent = events.at(-1); + + check( + lastEvent?.eventHash === manifest.finalEventHash, + "Final event hash matches manifest", + { + expected: manifest.finalEventHash, + actual: lastEvent?.eventHash, + }, + ); + + const expectedTerminalAction = { + PASSED: "SESSION_PASSED", + FAILED: "SESSION_FAILED", + ERROR: "SESSION_ERROR", + }[manifest.status]; + + check( + lastEvent?.action === expectedTerminalAction, + "Terminal event matches manifest status", + { + status: manifest.status, + expected: expectedTerminalAction, + actual: lastEvent?.action, + }, + ); + + check( + events[0]?.action === "SESSION_STARTED", + "First event is SESSION_STARTED", + { + actual: events[0]?.action, + }, + ); + + return { + valid: errors.length === 0, + manifest, + checks, + errors, + files: { + manifest: absoluteManifest, + raw: rawPath, + human: humanPath, + }, + }; +} + +function runCli() { + const manifestPath = process.argv[2]; + + if (!manifestPath) { + console.error( + "Usage: node verify-audit.js ", + ); + process.exitCode = 1; + return; + } + + const report = verifyAudit(manifestPath); + + for (const check of report.checks) { + console.log( + `[${check.passed ? "PASS" : "FAIL"}] ${check.name}`, + ); + } + + console.log(""); + console.log( + `Audit integrity: ${report.valid ? "VALID" : "INVALID"}`, + ); + + if (!report.valid) { + process.exitCode = 1; + } +} + +if (require.main === module) { + runCli(); +} + +module.exports = { + calculateEventHash, + sha256, + verifyAudit, +}; From 3a7dd2ef5231ca344cb0f795e6bb879034a52e7c Mon Sep 17 00:00:00 2001 From: Trong Do Date: Mon, 3 Aug 2026 20:15:36 +0700 Subject: [PATCH 2/4] [FE] Problem 2: Fancy Form --- src/problem2/.gitignore | 4 + src/problem2/README.md | 95 ++ src/problem2/index.html | 559 +++++++- src/problem2/package-lock.json | 1619 +++++++++++++++++++++++ src/problem2/package.json | 18 + src/problem2/script.js | 0 src/problem2/src/domain.test.ts | 96 ++ src/problem2/src/domain.ts | 575 ++++++++ src/problem2/src/main.ts | 1033 +++++++++++++++ src/problem2/src/style.css | 2199 +++++++++++++++++++++++++++++++ src/problem2/style.css | 8 - src/problem2/tsconfig.json | 18 + src/problem2/vite.config.js | 9 + 13 files changed, 6206 insertions(+), 27 deletions(-) create mode 100644 src/problem2/.gitignore create mode 100644 src/problem2/README.md create mode 100644 src/problem2/package-lock.json create mode 100644 src/problem2/package.json delete mode 100644 src/problem2/script.js create mode 100644 src/problem2/src/domain.test.ts create mode 100644 src/problem2/src/domain.ts create mode 100644 src/problem2/src/main.ts create mode 100644 src/problem2/src/style.css delete mode 100644 src/problem2/style.css create mode 100644 src/problem2/tsconfig.json create mode 100644 src/problem2/vite.config.js diff --git a/src/problem2/.gitignore b/src/problem2/.gitignore new file mode 100644 index 0000000000..a62c6b7a50 --- /dev/null +++ b/src/problem2/.gitignore @@ -0,0 +1,4 @@ +node_modules +dist +.vite +*.log diff --git a/src/problem2/README.md b/src/problem2/README.md new file mode 100644 index 0000000000..3fd17a8909 --- /dev/null +++ b/src/problem2/README.md @@ -0,0 +1,95 @@ +# Problem 2 — Intent-Driven Fancy Form + +A differentiated currency-swap experience built with **Vite + TypeScript**. + +Instead of presenting only two inputs and one rate, the form asks the user for an +execution **intent**, compares three simulated routes, explains the recommendation, +and lets the user stress-test the quote against market movement. + +## Creative differentiators + +- **Intent engine:** Max return, Balanced, or Protect +- **Competing route quotes:** Direct Market, Smart Split, and Stable Shield +- **Adaptive recommendation:** route changes according to the selected objective +- **Manual route override:** the user remains in control +- **Execution-confidence ring:** quick visual signal for route reliability +- **Split-route allocation:** shows exactly how an order is distributed +- **What-if simulator:** previews output when destination price moves from -3% to +3% +- **Quote freshness clock:** refreshes the simulated quote every 15 seconds +- **Keyboard shortcuts:** `R` reverses the pair, `M` fills the maximum amount +- **Transparent explanation:** every route shows output, latency, confidence, and risk + +## Highlights + +- Live token prices from the provided Switcheo interview endpoint +- Resilient fallback prices when the endpoint is unavailable +- Token icons from `Switcheo/token-icons` +- Searchable, keyboard-accessible token picker +- Exact exchange-rate calculation from USD token prices +- Amount validation, decimal validation, and balance validation +- Reverse direction, MAX amount, rate inversion, and slippage controls +- Service fee, minimum received, price impact, and route preview +- Simulated asynchronous swap with loading and success receipt +- Dark/light themes persisted in `localStorage` +- Responsive mobile and desktop layout +- Native semantic elements, focus states, live regions, dialogs, and reduced-motion support + +## Project structure + +```text +src/problem2/ +├── index.html +├── package.json +├── tsconfig.json +├── vite.config.js +└── src/ + ├── domain.ts + ├── main.ts + └── style.css +``` + +## Run locally + +From `D:\99\code-challenge\src\problem2`: + +```bat +npm install +npm run dev +``` + +Open the local URL printed by Vite, usually: + +```text +http://localhost:5173 +``` + +## Production build + +```bat +npm run build +npm run preview +``` + +## Calculation + +The API returns token prices denominated in USD. + +```text +exchangeRate = fromToken.price / toToken.price +grossOutput = inputAmount × exchangeRate +serviceFee = grossOutput × 0.001 +netOutput = grossOutput - serviceFee +minimum = netOutput × (1 - slippage / 100) +``` + +## Resilience + +The remote price request is validated and normalized: + +- invalid rows are ignored; +- currencies without a positive finite price are omitted; +- duplicate currencies keep the latest dated price; +- fewer than two valid assets triggers fallback data; +- failed token images fall back to a generated symbol avatar. + +The fallback values are clearly labeled in the interface and exist only to keep the assessment usable when the interview endpoint is offline. diff --git a/src/problem2/index.html b/src/problem2/index.html index 4058a68bff..36061f926a 100644 --- a/src/problem2/index.html +++ b/src/problem2/index.html @@ -1,27 +1,548 @@ - + + + + + + + + Orbit Swap — Currency Exchange + - - - Fancy Form + + + + - - - + - - +
+
+
+ + Smarter asset routing +
+

+ Move value at the + speed of intent. +

+

+ Set your intent, compare competing execution routes, and stress-test + the quote before committing to a simulated swap. +

- - - - +
+
+ $24.8M + Mock volume routed +
+
+ 0.10% + Transparent service fee +
+
+ < 2 sec + Simulated settlement +
+
+
+
+ Optimized route + AUTO +
+
+
+ E + Source +
+
+ + + +
+
+ + Best pool +
+
+ + + +
+
+ $ + Destination +
+
+
+ +
+ +

+ Demo-safe by design. + No wallet connection or real transaction is required. +

+
+
+ +
+
+
+
+

Instant exchange

+

Swap assets

+
+
+ +
+ + + +
+
+ Swap settings + Slippage tolerance +
+
+ + + +
+

Swap reverts if the rate moves beyond this threshold.

+
+
+
+
+ +
+ + Loading market prices… + +
+ +
+ +
+
+
+ Intent engine + What matters most? +
+ ADAPTIVE +
+ +
+ + + +
+ +

+ Balances expected output, execution confidence, and settlement speed. +

+
+ +
+
+ + + Balance: + + +
+ +
+
+ + ≈ $0.00 +
+ + +
+ + +
+ +
+ + + +
+ +
+
+ + Estimated +
+ +
+
+ + ≈ $0.00 +
+ + +
+
+ +
+ + +
+ Route + Intent engine +
+
+ Service fee + +
+
+ Minimum received + +
+
+ Price impact + +
+
+ + +
+
+
+ Quote intelligence + Three routes, one recommendation +
+
+ + 15s +
+
+ +
+
+ 94%confidence +
+
+ Balanced route selected +

+ Optimized across expected output, route variance, and simulated settlement time. +

+
+
+ +
+ +
+
+ Order allocation + +
+
+
+
+ +
+
+
+ What-if simulator + Destination price movement +
+ 0.0% +
+ +
+ -3% cheaper + Market now + +3% costlier +
+
+ Projected receive + + No simulated movement +
+
+
+ + + +

+ Simulated swap for assessment purposes. No real funds move. +

+
+
+ +
+
+ Data source + Switcheo prices +
+
+ Available assets + +
+
+ Quote mode + Balanced +
+
+
+
+ +
+ Problem 2 · Fancy Form + Intent routing · Scenario simulation · Vite + TypeScript +
+ + +
+
+
+

Asset directory

+

Select a token

+
+ +
+ + + + + +
+ Asset + Price +
+
+ +
+
+ + +
+ +

Simulation complete

+

Swap confirmed

+

Your simulated exchange was completed.

+ +
+
+ You paid + +
+
+ You received + +
+
+ Reference + +
+
+ + +
+
+ +
+ + + diff --git a/src/problem2/package-lock.json b/src/problem2/package-lock.json new file mode 100644 index 0000000000..75f9040b3f --- /dev/null +++ b/src/problem2/package-lock.json @@ -0,0 +1,1619 @@ +{ + "name": "99tech-problem2-fancy-form", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "99tech-problem2-fancy-form", + "version": "1.0.0", + "devDependencies": { + "typescript": "^5.8.3", + "vite": "^7.0.0", + "vitest": "^3.2.4" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^22.20 || ^24.12 || >=25" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.4.tgz", + "integrity": "sha512-RrPokAb7dmbxFoeO3TloqHyOjgye8RkBhSqmp4aJMIex4c9r46ZstPnleDQOq1t46VOVjwIuwNogIqbodV1Vvg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.4.tgz", + "integrity": "sha512-JKuJc+pnpks2pjy7L/N3v/cAkZxYlnmuZoD840ldbMI5KDbC4iO9NKwPKYdjYFCMAIIlBzYSFHxIJVYzRo2/8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.4.tgz", + "integrity": "sha512-krw5uS2STmvJ02x0uTXHbqQNuz+9eZ1iw+qXk9dmW2gvV4jV7O2hEoOnuhFrpOPiel1mBFtqbxYZZtC46hXLOw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.4.tgz", + "integrity": "sha512-wsTxtgApb4PrOsNJIm0FZ1h3WvCC+k9uxLJ4ad75hgoS4NiRes2SoJFlDAyMwiUY8IssDqGcHbXuN0sx1tfF1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.4.tgz", + "integrity": "sha512-GUOnQlyZe3yAXhWOtOMsn5Qkrv5E5mZXa0thbARWi5Ei2szlVXJFQhddZ4HbAzh8q92w5twp+CQvs/eFanz9YQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.4.tgz", + "integrity": "sha512-/Y7f3QuxjzPKsjA/rfEDa3+0vXqyjmJ50Ln8dPpCmWkKTrUoWHG1cWhTqaAMLob2m2nESWuC7yGrREz019Ztqg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.4.tgz", + "integrity": "sha512-81wiiX3v7aqy+T+bT61TJ78yJjRquqFFTTbAPt08imfQQzkPIW8t6aJbkTagtCCrXMNc9D66+geqlK7ydLPNqA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.4.tgz", + "integrity": "sha512-9kmDIvNZqdoHOBZgNtpTBeLWYO/LVipM3H/j62P8848/l/VPEQL6N3uxU9pvP1oZAsXyC2MEnFP3ovRjo7WYNQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.4.tgz", + "integrity": "sha512-CcnXHWnXg69g+DX5VWL3FHts3qMRN2uVEHX+BZvGLdd07/gXkn3ePjYtO1LDJvxkGKVHMclKBRa1QUTH+6toYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.4.tgz", + "integrity": "sha512-iFOibiHnTRuhrWLlRsOQFdZJJIa7S8OwkneJr4ocALP16u5yk6lWLINFwhHaEqBFMsKDUZofLkGos7+CPzGB3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.4.tgz", + "integrity": "sha512-XnWYMI7euHlb5a871xPja+Gm7DRCFU+FGRrtS2sMq9N8FvqtpagUy6gD4YOemC5MRk9xbh8+jYMEJbigFQwsgA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.4.tgz", + "integrity": "sha512-qGDAlO0U8xedCcsdRm9oaoQY8DAx/QT7uIxJWhCdx0ceIWX783UC9QSYkdpzAe29wNiVfp24+bZdQmn49o45SQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.4.tgz", + "integrity": "sha512-ru4H6ezD7ysA5EiEK6qkkaEb4modH8CTej6kUy/gQi20u3kB3G7Zn8snXXkeJSCOFKG/rbPPtM/+9Wgas1961w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.4.tgz", + "integrity": "sha512-2W4MO5WQVJnbJaZdvDb9rhBDuFU1nKIepPFpJUBsTh2k1YY2g+ODViaWuyOAjQ5cOP7NvrvLzt3wvHOoiAvc7w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.4.tgz", + "integrity": "sha512-+fxjfuoAmVMCYV5QyjoIpu0cp5DOiOTeqYFk1AVaxGr+/ravWLX89XfQmptsoWcaVy/TGf2hexzbUOrCQIL1CQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.4.tgz", + "integrity": "sha512-jTn8JfHGL4djjFxPuM06LmNUJDsst2jeVlsd9OmIH6zc5sC9K6rIuO4YajXatLUpBmBKl6b35ro1QZocLi+tcA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.4.tgz", + "integrity": "sha512-oCJCJL4pXsoDcP2QZ+JVlPTIRc6266zsIaeJJsWImmF7HO0W8nb6HuSgZlMWxJwaPf8ehbSw8yo0EUw925hKsA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.4.tgz", + "integrity": "sha512-W69hukhZ3KKNRCaMIEzKvcFye42hh0FE1+YoYaf5+Ikacuftoco6yO/xouz0hc5d5W/s3yBro5jRiuEE/Q5vUw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.4.tgz", + "integrity": "sha512-qiXbGG2jkjXhzXpsFZSR2Xpb8DN/UaxYsbb/STbuR/6fpaDgRmmaq1B/LmtF2wQFOFOSsK2jdE0RZ3a0zHn4QA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.4.tgz", + "integrity": "sha512-nWeM//hxv8mIo6jD7Hu4o48DVmV9pbV6gsKaWU+4NFyqHoPKwrkRiZGLKUhOBk8qNmDmpwFtPKg80Bo/Tn4xiQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.4.tgz", + "integrity": "sha512-s62SQ/vgsRSvMwDkOEfTqfgASF0f26ZNaQuTA6Aok5lrikf89yI2W0gFHvZb2Jpgc6N8JnOKZgCK2iciO3CsxQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.4.tgz", + "integrity": "sha512-J6wGf8TVGbXJq+HH+ttTvrcfNKPbuZecV6KT1B8I18BC5IURUh5kl4Yl5OEP5eFIUoI5BWxCsyYMhFsDx8kekw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.4.tgz", + "integrity": "sha512-zmfrQd/0wu6oJs8Vq8KwY/YtsKSsLtKe/HwAP4Wqy8LhWjeT55fHRAkOhYQ12wI3ayS4Tt12d5CDRD7N96SAYQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.4.tgz", + "integrity": "sha512-qPzHqdj9rfUD+w79dtE07zi/kFwKyCJqplp5K5ygeLTp7jLpAoc16OAH39HSmRC9UpozaecsleI8uAdEj6v2yw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.4.tgz", + "integrity": "sha512-zD6NdeWEByGE9QF9vCrlJ5YQB4oq9q91kPZS37Jwj5hOkvR1lTBSpsKhKDw4IJtbQ35LsTS1HD9DZYGKIshU1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vitest/expect": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.7.tgz", + "integrity": "sha512-E8eBXaKibuvH2pSZErOjdVb5vF4PbKYcrnluBTYxEk1l/VhhwZg1kZQsdtjq+CsF5CFydf2Rdkz7jDHKSisi3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.7", + "@vitest/utils": "3.2.7", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.7.tgz", + "integrity": "sha512-Trr0hYO9CM3Wj6ksWHRhK9IZpIY6wTMO5u/MqXurMxT57sWBaOPEtP3Oq60ihZuh5JsiagKfz95OcxdEP6dBrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.7", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.7.tgz", + "integrity": "sha512-KUHlwqVu0sRlhCdyPdQ/wBoTfRahjUky1MubOmYw9fWfIZy1gNoHpuaaQBPAaMaVYdQYHJLurzj8ECCj5OwTqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.7.tgz", + "integrity": "sha512-sB9y4ovltoQP+WaUPwmSxO9WIg9Ig694Di5PalVPsYHklAdE027mehpWF2SQSVq+k6sFgaivbTjTJwZLSHbedA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.2.7", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.7.tgz", + "integrity": "sha512-7C+MwShwtBSI5Buwoyg3s/iY1eHL9PKAf+O1wVh/TdnjXUtkoL/9YQtre90i4MtNXM6edP1wJ2zOBpfCyhIS7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.7", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.7.tgz", + "integrity": "sha512-Q2eQGI6d2L/hBtZ0qNuKcAGid68XK6cv1xsoaIma6PaJhHPoqcEJhYpXZ/5myCMqkNgtP6UKuBhbc0nHKnrkuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^4.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.7.tgz", + "integrity": "sha512-x6BDOd7dyo3PFLY3I9/HJ25X/6OurhGXk2/B9gOZNPF7XDVjeBK4k01lQE5uvDpbuheErh91qYuE1E2OEjK3Rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.7", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/check-error": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.17", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz", + "integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.25", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz", + "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.62.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.4.tgz", + "integrity": "sha512-RXOqwaPsBGjMNMa4sQjDjHieHEZDFoj/Rdr46l2MU5DfEs16wHJPC2RPTPHWhNl+M3aI472LLqFkFKut4SblOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@napi-rs/lzma-linux-x64-gnu": "1.5.1", + "@rollup/rollup-android-arm-eabi": "4.62.4", + "@rollup/rollup-android-arm64": "4.62.4", + "@rollup/rollup-darwin-arm64": "4.62.4", + "@rollup/rollup-darwin-x64": "4.62.4", + "@rollup/rollup-freebsd-arm64": "4.62.4", + "@rollup/rollup-freebsd-x64": "4.62.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.4", + "@rollup/rollup-linux-arm-musleabihf": "4.62.4", + "@rollup/rollup-linux-arm64-gnu": "4.62.4", + "@rollup/rollup-linux-arm64-musl": "4.62.4", + "@rollup/rollup-linux-loong64-gnu": "4.62.4", + "@rollup/rollup-linux-loong64-musl": "4.62.4", + "@rollup/rollup-linux-ppc64-gnu": "4.62.4", + "@rollup/rollup-linux-ppc64-musl": "4.62.4", + "@rollup/rollup-linux-riscv64-gnu": "4.62.4", + "@rollup/rollup-linux-riscv64-musl": "4.62.4", + "@rollup/rollup-linux-s390x-gnu": "4.62.4", + "@rollup/rollup-linux-x64-gnu": "4.62.4", + "@rollup/rollup-linux-x64-musl": "4.62.4", + "@rollup/rollup-openbsd-x64": "4.62.4", + "@rollup/rollup-openharmony-arm64": "4.62.4", + "@rollup/rollup-win32-arm64-msvc": "4.62.4", + "@rollup/rollup-win32-ia32-msvc": "4.62.4", + "@rollup/rollup-win32-x64-gnu": "4.62.4", + "@rollup/rollup-win32-x64-msvc": "4.62.4", + "fsevents": "~2.3.2" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/strip-literal": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", + "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/vite": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz", + "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0 || ^0.28.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.7.tgz", + "integrity": "sha512-KrxIJ62Fd89gfysR4WotlgZABiz2dqFPgqGzX7s+CwsqLFomRH7777ZcrOD6+WVAh7khPQP41A+BKbpcJFrdEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.7", + "@vitest/mocker": "3.2.7", + "@vitest/pretty-format": "^3.2.7", + "@vitest/runner": "3.2.7", + "@vitest/snapshot": "3.2.7", + "@vitest/spy": "3.2.7", + "@vitest/utils": "3.2.7", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.7", + "@vitest/ui": "3.2.7", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + } + } +} diff --git a/src/problem2/package.json b/src/problem2/package.json new file mode 100644 index 0000000000..61589d4c00 --- /dev/null +++ b/src/problem2/package.json @@ -0,0 +1,18 @@ +{ + "name": "99tech-problem2-fancy-form", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc --noEmit && vite build", + "preview": "vite preview", + "check": "tsc --noEmit", + "test": "vitest run" + }, + "devDependencies": { + "typescript": "^5.8.3", + "vite": "^7.0.0", + "vitest": "^3.2.4" + } +} diff --git a/src/problem2/script.js b/src/problem2/script.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/problem2/src/domain.test.ts b/src/problem2/src/domain.test.ts new file mode 100644 index 0000000000..5f680e2013 --- /dev/null +++ b/src/problem2/src/domain.test.ts @@ -0,0 +1,96 @@ +import { describe, expect, it } from "vitest"; +import { + buildRouteQuotes, + calculateQuote, + chooseRecommendedRoute, + normalizePrices, + projectRouteOutput, + validateAmount, +} from "./domain"; + +describe("normalizePrices", () => { + it("drops invalid rows and keeps the latest duplicate", () => { + const tokens = normalizePrices([ + { currency: "AAA", date: "2024-01-01", price: 1 }, + { currency: "AAA", date: "2025-01-01", price: 2 }, + { currency: "BROKEN", price: 0 }, + ]); + + expect(tokens).toHaveLength(1); + expect(tokens[0]?.price).toBe(2); + }); +}); + +describe("calculateQuote", () => { + it("calculates exchange output and fee", () => { + const from = { + symbol: "AAA", + name: "AAA", + price: 10, + date: null, + iconUrl: "", + balance: 100, + }; + const to = { + ...from, + symbol: "BBB", + name: "BBB", + price: 2, + }; + + const quote = calculateQuote(2, from, to, 0.5); + + expect(quote.rate).toBe(5); + expect(quote.grossOutput).toBe(10); + expect(quote.serviceFee).toBe(0.01); + expect(quote.netOutput).toBe(9.99); + }); +}); + +describe("validateAmount", () => { + it("rejects invalid, over-precision, and over-balance values", () => { + expect(validateAmount("", 10)).toBeTruthy(); + expect(validateAmount("1.123456789", 10)).toBeTruthy(); + expect(validateAmount("11", 10)).toBeTruthy(); + expect(validateAmount("5", 10)).toBeNull(); + }); +}); + + +describe("intent route engine", () => { + const from = { + symbol: "ETH", + name: "Ethereum", + price: 3000, + date: null, + iconUrl: "", + balance: 10, + }; + const to = { + symbol: "USDC", + name: "USD Coin", + price: 1, + date: null, + iconUrl: "", + balance: 10000, + }; + + it("builds three distinct routes and recommends by intent", () => { + const routes = buildRouteQuotes(1, from, to, 0.5); + + expect(routes).toHaveLength(3); + expect(chooseRecommendedRoute(routes, "maximize").id).toBe("split"); + expect(chooseRecommendedRoute(routes, "balanced").id).toBe("direct"); + expect(chooseRecommendedRoute(routes, "protect").id).toBe("stable"); + }); + + it("projects less output when destination price rises", () => { + const route = buildRouteQuotes(1, from, to, 0.5)[0]; + expect(route).toBeDefined(); + + if (!route) return; + + expect(projectRouteOutput(route, 2)).toBeLessThan(route.netOutput); + expect(projectRouteOutput(route, -2)).toBeGreaterThan(route.netOutput); + }); +}); diff --git a/src/problem2/src/domain.ts b/src/problem2/src/domain.ts new file mode 100644 index 0000000000..efc7e13b4d --- /dev/null +++ b/src/problem2/src/domain.ts @@ -0,0 +1,575 @@ +export const PRICE_ENDPOINT = "https://interview.switcheo.com/prices.json"; +export const ICON_BASE_URL = + "https://raw.githubusercontent.com/Switcheo/token-icons/main/tokens"; + +export interface RawPrice { + currency?: unknown; + date?: unknown; + price?: unknown; +} + +export interface Token { + symbol: string; + name: string; + price: number; + date: string | null; + iconUrl: string; + balance: number; +} + +export interface TokenLoadResult { + tokens: Token[]; + source: "live" | "fallback"; + loadedAt: Date; + warning?: string; +} + +export interface SwapQuote { + rate: number; + grossOutput: number; + serviceFee: number; + netOutput: number; + minimumReceived: number; + usdValue: number; + priceImpactPercent: number; +} + +export type SwapIntent = "maximize" | "balanced" | "protect"; +export type RouteId = "direct" | "split" | "stable"; + +export interface RouteAllocation { + venue: string; + percentage: number; +} + +export interface RouteQuote extends SwapQuote { + id: RouteId; + label: string; + shortLabel: string; + description: string; + latencySeconds: number; + confidencePercent: number; + riskLabel: "Low" | "Moderate" | "Elevated"; + allocation: RouteAllocation[]; + intentScores: Record; +} + +const TOKEN_NAMES: Record = { + "1INCH": "1inch", + AAVE: "Aave", + ADA: "Cardano", + AKT: "Akash Network", + ALGO: "Algorand", + APT: "Aptos", + ARB: "Arbitrum", + ATOM: "Cosmos", + AVAX: "Avalanche", + BNB: "BNB", + BTC: "Bitcoin", + WBTC: "Wrapped Bitcoin", + BUSD: "Binance USD", + CRO: "Cronos", + DAI: "Dai", + DOT: "Polkadot", + ETH: "Ethereum", + EVMOS: "Evmos", + FTM: "Fantom", + GMX: "GMX", + INJ: "Injective", + IRIS: "IRISnet", + KUJI: "Kujira", + LINK: "Chainlink", + LSI: "Liquid Staking Index", + LUNA: "Terra", + MATIC: "Polygon", + NEAR: "NEAR Protocol", + OKB: "OKB", + OKT: "OKT Chain", + OSMO: "Osmosis", + RATOM: "Stride stATOM", + SOL: "Solana", + STATOM: "Stride stATOM", + STEVMOS: "Stride stEVMOS", + STLUNA: "Stride stLUNA", + STOSMO: "Stride stOSMO", + STRD: "Stride", + SWTH: "Carbon", + UNI: "Uniswap", + USC: "Carbon USD", + USD: "US Dollar", + USDC: "USD Coin", + USDT: "Tether", + WSTETH: "Wrapped stETH", + YIELDUSD: "Yield USD", +}; + +const POPULAR_ORDER = [ + "ETH", + "BTC", + "WBTC", + "USDC", + "USDT", + "ATOM", + "OSMO", + "SWTH", + "LUNA", + "BNB", +]; + +export const FALLBACK_PRICES: RawPrice[] = [ + { currency: "ETH", date: "2026-08-03T00:00:00Z", price: 3550.42 }, + { currency: "BTC", date: "2026-08-03T00:00:00Z", price: 118420.12 }, + { currency: "WBTC", date: "2026-08-03T00:00:00Z", price: 118180.45 }, + { currency: "USDC", date: "2026-08-03T00:00:00Z", price: 1.0 }, + { currency: "USDT", date: "2026-08-03T00:00:00Z", price: 0.9998 }, + { currency: "ATOM", date: "2026-08-03T00:00:00Z", price: 5.18 }, + { currency: "OSMO", date: "2026-08-03T00:00:00Z", price: 0.238 }, + { currency: "SWTH", date: "2026-08-03T00:00:00Z", price: 0.0042 }, + { currency: "LUNA", date: "2026-08-03T00:00:00Z", price: 0.165 }, + { currency: "STRD", date: "2026-08-03T00:00:00Z", price: 0.42 }, + { currency: "EVMOS", date: "2026-08-03T00:00:00Z", price: 0.011 }, + { currency: "STEVMOS", date: "2026-08-03T00:00:00Z", price: 0.014 }, + { currency: "STATOM", date: "2026-08-03T00:00:00Z", price: 6.23 }, + { currency: "STOSMO", date: "2026-08-03T00:00:00Z", price: 0.284 }, + { currency: "KUJI", date: "2026-08-03T00:00:00Z", price: 0.19 }, + { currency: "IRIS", date: "2026-08-03T00:00:00Z", price: 0.012 }, + { currency: "OKB", date: "2026-08-03T00:00:00Z", price: 48.2 }, + { currency: "OKT", date: "2026-08-03T00:00:00Z", price: 7.3 }, + { currency: "BUSD", date: "2026-08-03T00:00:00Z", price: 1.0 }, + { currency: "GMX", date: "2026-08-03T00:00:00Z", price: 17.4 }, +]; + +function tokenName(symbol: string): string { + return TOKEN_NAMES[symbol.toUpperCase()] ?? symbol; +} + +function deterministicBalance(symbol: string, price: number): number { + const uppercase = symbol.toUpperCase(); + + if (["USDC", "USDT", "BUSD", "USD", "USC"].includes(uppercase)) { + return 12_480.25; + } + + if (["BTC", "WBTC"].includes(uppercase)) { + return 0.8426; + } + + if (uppercase === "ETH") { + return 7.824; + } + + let hash = 0; + for (const character of uppercase) { + hash = (hash * 31 + character.charCodeAt(0)) >>> 0; + } + + const targetUsd = 1200 + (hash % 7800); + return Math.max(0.01, targetUsd / price); +} + +function parseDate(value: unknown): string | null { + if (typeof value !== "string") { + return null; + } + + const timestamp = Date.parse(value); + return Number.isNaN(timestamp) ? null : new Date(timestamp).toISOString(); +} + +export function normalizePrices(payload: unknown): Token[] { + if (!Array.isArray(payload)) { + throw new TypeError("Price payload must be an array"); + } + + const latestByCurrency = new Map< + string, + { symbol: string; price: number; date: string | null; timestamp: number } + >(); + + for (const item of payload as RawPrice[]) { + if (!item || typeof item !== "object") { + continue; + } + + const symbol = + typeof item.currency === "string" ? item.currency.trim() : ""; + const price = Number(item.price); + + if (!symbol || !Number.isFinite(price) || price <= 0) { + continue; + } + + const date = parseDate(item.date); + const timestamp = date ? Date.parse(date) : 0; + const key = symbol.toUpperCase(); + const current = latestByCurrency.get(key); + + if (!current || timestamp >= current.timestamp) { + latestByCurrency.set(key, { + symbol, + price, + date, + timestamp, + }); + } + } + + const tokens = [...latestByCurrency.values()].map((entry) => ({ + symbol: entry.symbol, + name: tokenName(entry.symbol), + price: entry.price, + date: entry.date, + iconUrl: `${ICON_BASE_URL}/${encodeURIComponent(entry.symbol)}.svg`, + balance: deterministicBalance(entry.symbol, entry.price), + })); + + return tokens.sort((left, right) => { + const leftIndex = POPULAR_ORDER.indexOf(left.symbol.toUpperCase()); + const rightIndex = POPULAR_ORDER.indexOf(right.symbol.toUpperCase()); + + if (leftIndex !== -1 || rightIndex !== -1) { + if (leftIndex === -1) return 1; + if (rightIndex === -1) return -1; + return leftIndex - rightIndex; + } + + return left.symbol.localeCompare(right.symbol); + }); +} + +export async function loadTokens(signal?: AbortSignal): Promise { + try { + const requestInit: RequestInit = { + headers: { Accept: "application/json" }, + }; + + if (signal) { + requestInit.signal = signal; + } + + const response = await fetch(PRICE_ENDPOINT, requestInit); + + if (!response.ok) { + throw new Error(`Price service returned HTTP ${response.status}`); + } + + const tokens = normalizePrices(await response.json()); + + if (tokens.length < 2) { + throw new Error("Price service returned fewer than two usable assets"); + } + + return { + tokens, + source: "live", + loadedAt: new Date(), + }; + } catch (error) { + if (error instanceof DOMException && error.name === "AbortError") { + throw error; + } + + return { + tokens: normalizePrices(FALLBACK_PRICES), + source: "fallback", + loadedAt: new Date(), + warning: + "Live prices are temporarily unavailable. Showing resilient demo data.", + }; + } +} + +export function calculateQuote( + amount: number, + fromToken: Token, + toToken: Token, + slippagePercent: number, +): SwapQuote { + if (!Number.isFinite(amount) || amount <= 0) { + throw new RangeError("Amount must be greater than zero"); + } + + if (fromToken.symbol.toUpperCase() === toToken.symbol.toUpperCase()) { + throw new Error("Source and destination tokens must differ"); + } + + const rate = fromToken.price / toToken.price; + const grossOutput = amount * rate; + const serviceFee = grossOutput * 0.001; + const netOutput = grossOutput - serviceFee; + const minimumReceived = netOutput * (1 - slippagePercent / 100); + const usdValue = amount * fromToken.price; + + // A small deterministic simulation for presentation only. + const priceImpactPercent = Math.min( + 0.85, + Math.max(0.01, (usdValue / 2_000_000) * 0.12), + ); + + return { + rate, + grossOutput, + serviceFee, + netOutput, + minimumReceived, + usdValue, + priceImpactPercent, + }; +} + + +const ROUTE_CONFIGS: Array<{ + id: RouteId; + label: string; + shortLabel: string; + description: string; + rateAdjustment: number; + feeRate: number; + impactMultiplier: number; + latencySeconds: number; + baseConfidence: number; + riskLabel: RouteQuote["riskLabel"]; + allocation: RouteAllocation[]; + intentScores: Record; +}> = [ + { + id: "direct", + label: "Direct Market", + shortLabel: "Direct", + description: "One venue, minimal hops, and a predictable execution path.", + rateAdjustment: 0, + feeRate: 0.001, + impactMultiplier: 1, + latencySeconds: 1.1, + baseConfidence: 94, + riskLabel: "Moderate", + allocation: [{ venue: "Primary pool", percentage: 100 }], + intentScores: { maximize: 91, balanced: 98, protect: 90 }, + }, + { + id: "split", + label: "Smart Split", + shortLabel: "Split", + description: "Divides the order across three venues to reduce price impact.", + rateAdjustment: 0.0016, + feeRate: 0.0012, + impactMultiplier: 0.56, + latencySeconds: 1.8, + baseConfidence: 96, + riskLabel: "Moderate", + allocation: [ + { venue: "Primary pool", percentage: 54 }, + { venue: "Stable pool", percentage: 31 }, + { venue: "Reserve route", percentage: 15 }, + ], + intentScores: { maximize: 100, balanced: 96, protect: 89 }, + }, + { + id: "stable", + label: "Stable Shield", + shortLabel: "Shield", + description: "Prioritizes low route variance and stronger downside protection.", + rateAdjustment: -0.0011, + feeRate: 0.0007, + impactMultiplier: 0.34, + latencySeconds: 0.9, + baseConfidence: 99, + riskLabel: "Low", + allocation: [ + { venue: "Stable pool", percentage: 82 }, + { venue: "Reserve route", percentage: 18 }, + ], + intentScores: { maximize: 85, balanced: 93, protect: 100 }, + }, +]; + +export function buildRouteQuotes( + amount: number, + fromToken: Token, + toToken: Token, + slippagePercent: number, +): RouteQuote[] { + if (!Number.isFinite(amount) || amount <= 0) { + throw new RangeError("Amount must be greater than zero"); + } + + if (fromToken.symbol.toUpperCase() === toToken.symbol.toUpperCase()) { + throw new Error("Source and destination tokens must differ"); + } + + const baseRate = fromToken.price / toToken.price; + const usdValue = amount * fromToken.price; + const baseImpact = Math.min( + 0.85, + Math.max(0.01, (usdValue / 2_000_000) * 0.12), + ); + + return ROUTE_CONFIGS.map((config) => { + const rate = baseRate * (1 + config.rateAdjustment); + const grossOutput = amount * rate; + const serviceFee = grossOutput * config.feeRate; + const netOutput = grossOutput - serviceFee; + const priceImpactPercent = baseImpact * config.impactMultiplier; + const minimumReceived = netOutput * (1 - slippagePercent / 100); + const confidencePercent = Math.max( + 72, + Math.min(99, config.baseConfidence - priceImpactPercent * 4), + ); + + return { + id: config.id, + label: config.label, + shortLabel: config.shortLabel, + description: config.description, + latencySeconds: config.latencySeconds, + confidencePercent, + riskLabel: config.riskLabel, + allocation: config.allocation, + intentScores: config.intentScores, + rate, + grossOutput, + serviceFee, + netOutput, + minimumReceived, + usdValue, + priceImpactPercent, + }; + }); +} + +export function chooseRecommendedRoute( + routes: RouteQuote[], + intent: SwapIntent, +): RouteQuote { + const sorted = [...routes].sort( + (left, right) => right.intentScores[intent] - left.intentScores[intent], + ); + + const selected = sorted[0]; + if (!selected) { + throw new Error("No route quote is available"); + } + + return selected; +} + +export function projectRouteOutput( + route: RouteQuote, + destinationPriceMovePercent: number, +): number { + if (!Number.isFinite(destinationPriceMovePercent)) { + throw new TypeError("Market movement must be finite"); + } + + const multiplier = 1 + destinationPriceMovePercent / 100; + if (multiplier <= 0) { + throw new RangeError("Market movement produces an invalid price"); + } + + return route.netOutput / multiplier; +} + +export function validateAmount( + rawValue: string, + balance: number, +): string | null { + const normalized = rawValue.trim(); + + if (!normalized) { + return "Enter an amount to continue."; + } + + if (!/^(?:\d+\.?\d*|\.\d+)$/.test(normalized)) { + return "Use numbers and a single decimal point only."; + } + + const decimalPart = normalized.split(".")[1]; + if (decimalPart && decimalPart.length > 8) { + return "Use no more than 8 decimal places."; + } + + const amount = Number(normalized); + + if (!Number.isFinite(amount) || amount <= 0) { + return "Amount must be greater than zero."; + } + + if (amount > balance) { + return `Insufficient demo balance. Available: ${formatTokenAmount(balance)}.`; + } + + return null; +} + +export function formatTokenAmount(value: number, maximumFractionDigits = 6): string { + if (!Number.isFinite(value)) { + return "—"; + } + + if (value !== 0 && Math.abs(value) < 0.000001) { + return value.toExponential(3); + } + + return new Intl.NumberFormat("en-US", { + maximumFractionDigits, + minimumFractionDigits: 0, + }).format(value); +} + +export function formatUsd(value: number): string { + if (!Number.isFinite(value)) { + return "—"; + } + + if (Math.abs(value) < 0.01 && value !== 0) { + return "< $0.01"; + } + + return new Intl.NumberFormat("en-US", { + style: "currency", + currency: "USD", + maximumFractionDigits: value >= 1000 ? 0 : 2, + }).format(value); +} + +export function formatPrice(value: number): string { + if (value >= 1000) { + return formatUsd(value); + } + + if (value >= 1) { + return `$${value.toLocaleString("en-US", { + maximumFractionDigits: 4, + })}`; + } + + return `$${value.toLocaleString("en-US", { + maximumSignificantDigits: 4, + })}`; +} + +export function chooseDefaultPair(tokens: Token[]): [Token, Token] { + const find = (symbol: string) => + tokens.find((token) => token.symbol.toUpperCase() === symbol); + + const from = find("ETH") ?? find("ATOM") ?? tokens[0]; + const to = + find("USDC") ?? + find("USDT") ?? + tokens.find((token) => token !== from) ?? + tokens[1]; + + if (!from || !to) { + throw new Error("At least two priced tokens are required"); + } + + return [from, to]; +} + +export function popularTokens(tokens: Token[]): Token[] { + const popular = POPULAR_ORDER.map((symbol) => + tokens.find((token) => token.symbol.toUpperCase() === symbol), + ).filter((token): token is Token => Boolean(token)); + + return popular.slice(0, 5); +} diff --git a/src/problem2/src/main.ts b/src/problem2/src/main.ts new file mode 100644 index 0000000000..ea1972f069 --- /dev/null +++ b/src/problem2/src/main.ts @@ -0,0 +1,1033 @@ +import "./style.css"; +import { + buildRouteQuotes, + chooseDefaultPair, + chooseRecommendedRoute, + formatPrice, + formatTokenAmount, + formatUsd, + loadTokens, + popularTokens, + projectRouteOutput, + validateAmount, + type RouteId, + type RouteQuote, + type SwapIntent, + type Token, +} from "./domain"; + +type SwapSide = "from" | "to"; + +const INTENT_DESCRIPTIONS: Record = { + maximize: "Prioritizes the largest expected token output, even when the route uses more venues.", + balanced: "Balances expected output, execution confidence, and simulated settlement speed.", + protect: "Prioritizes confidence and low variance over the absolute maximum output.", +}; + +const ALLOCATION_COLORS = ["violet", "mint", "amber"]; + +function requiredElement( + selector: string, + parent: ParentNode = document, +): T { + const element = parent.querySelector(selector); + if (!element) { + throw new Error(`Required element not found: ${selector}`); + } + return element; +} + +const elements = { + html: document.documentElement, + form: requiredElement("#swap-form"), + amountInput: requiredElement("#from-amount"), + outputInput: requiredElement("#to-amount"), + amountError: requiredElement("#amount-error"), + fromField: requiredElement("#from-field"), + fromBalance: requiredElement("#from-balance"), + fromUsd: requiredElement("#from-usd-value"), + toUsd: requiredElement("#to-usd-value"), + fromTrigger: requiredElement("#from-token-trigger"), + toTrigger: requiredElement("#to-token-trigger"), + fromAvatar: requiredElement("#from-token-avatar"), + toAvatar: requiredElement("#to-token-avatar"), + fromSymbol: requiredElement("#from-token-symbol"), + toSymbol: requiredElement("#to-token-symbol"), + fromName: requiredElement("#from-token-name"), + toName: requiredElement("#to-token-name"), + maxButton: requiredElement("#max-button"), + reverseButton: requiredElement("#reverse-button"), + submitButton: requiredElement("#submit-button"), + submitLabel: requiredElement(".submit-label"), + exchangeRate: requiredElement("#exchange-rate"), + feeValue: requiredElement("#fee-value"), + minimumValue: requiredElement("#minimum-value"), + impactValue: requiredElement("#impact-value"), + quotePanel: requiredElement("#quote-panel"), + routeValue: requiredElement("#route-value"), + intelligencePanel: requiredElement("#intelligence-panel"), + intentOptions: [...document.querySelectorAll("[data-intent]")], + intentDescription: requiredElement("#intent-description"), + quoteModeLabel: requiredElement("#quote-mode-label"), + routeComparison: requiredElement("#route-comparison"), + confidenceRing: requiredElement("#confidence-ring"), + confidenceValue: requiredElement("#confidence-value"), + routeReasonTitle: requiredElement("#route-reason-title"), + routeReason: requiredElement("#route-reason"), + allocationTrack: requiredElement("#allocation-track"), + allocationLegend: requiredElement("#allocation-legend"), + allocationLabel: requiredElement("#allocation-label"), + scenarioSlider: requiredElement("#scenario-slider"), + scenarioMove: requiredElement("#scenario-move"), + scenarioOutput: requiredElement("#scenario-output"), + scenarioDelta: requiredElement("#scenario-delta"), + quoteCountdown: requiredElement("#quote-countdown"), + rateToggle: requiredElement("#rate-toggle"), + refreshButton: requiredElement("#refresh-prices"), + priceState: requiredElement("#price-state"), + priceStateText: requiredElement("#price-state-text"), + priceUpdatedAt: requiredElement("#price-updated-at"), + assetCount: requiredElement("#asset-count"), + dataSourceLabel: requiredElement("#data-source-label"), + themeToggle: requiredElement("#theme-toggle"), + tokenDialog: requiredElement("#token-dialog"), + tokenSearch: requiredElement("#token-search"), + tokenList: requiredElement("#token-list"), + popularTokens: requiredElement("#popular-tokens"), + emptyTokenState: requiredElement("#empty-token-state"), + closeTokenDialog: requiredElement("#close-token-dialog"), + successDialog: requiredElement("#success-dialog"), + successSummary: requiredElement("#success-summary"), + receiptPaid: requiredElement("#receipt-paid"), + receiptReceived: requiredElement("#receipt-received"), + receiptReference: requiredElement("#receipt-reference"), + closeSuccessDialog: requiredElement("#close-success-dialog"), + toastRegion: requiredElement("#toast-region"), +}; + +let tokens: Token[] = []; +let fromToken: Token | null = null; +let toToken: Token | null = null; +let quote: RouteQuote | null = null; +let routeQuotes: RouteQuote[] = []; +let swapIntent: SwapIntent = "balanced"; +let manuallySelectedRouteId: RouteId | null = null; +let scenarioMovePercent = 0; +let quoteExpiresAt = 0; +let quoteTimer: number | null = null; +let activePickerSide: SwapSide = "from"; +let slippagePercent = 0.5; +let invertedRate = false; +let isLoadingPrices = false; +let isSubmitting = false; +let refreshController: AbortController | null = null; + +function tokenAvatarMarkup(token: Token, compact = false): string { + const fallback = token.symbol.slice(0, 2).toUpperCase(); + return ` + + + + + `; +} + +function wireImageFallbacks(parent: ParentNode = document): void { + parent.querySelectorAll("[data-token-image]").forEach((image) => { + const revealFallback = () => { + image.hidden = true; + image.parentElement?.classList.add("image-failed"); + }; + + image.addEventListener("error", revealFallback, { once: true }); + + if (image.complete && image.naturalWidth === 0) { + revealFallback(); + } + }); +} + +function renderSelectedToken(side: SwapSide, token: Token): void { + const isFrom = side === "from"; + const avatar = isFrom ? elements.fromAvatar : elements.toAvatar; + const symbol = isFrom ? elements.fromSymbol : elements.toSymbol; + const name = isFrom ? elements.fromName : elements.toName; + + avatar.innerHTML = tokenAvatarMarkup(token); + symbol.textContent = token.symbol; + name.textContent = token.name; + wireImageFallbacks(avatar); +} + +function setPriceState( + state: "loading" | "live" | "fallback" | "error", + message: string, + loadedAt?: Date, +): void { + elements.priceState.dataset.state = state; + elements.priceStateText.textContent = message; + + if (loadedAt) { + elements.priceUpdatedAt.dateTime = loadedAt.toISOString(); + elements.priceUpdatedAt.textContent = loadedAt.toLocaleTimeString([], { + hour: "2-digit", + minute: "2-digit", + }); + } else { + elements.priceUpdatedAt.removeAttribute("datetime"); + elements.priceUpdatedAt.textContent = ""; + } +} + +function setLoadingPrices(loading: boolean): void { + isLoadingPrices = loading; + elements.refreshButton.classList.toggle("is-spinning", loading); + elements.refreshButton.disabled = loading; +} + +async function refreshPrices({ preserveSelection = true } = {}): Promise { + refreshController?.abort(); + refreshController = new AbortController(); + + setLoadingPrices(true); + setPriceState("loading", "Loading market prices…"); + + const previousFrom = fromToken?.symbol.toUpperCase(); + const previousTo = toToken?.symbol.toUpperCase(); + + try { + const result = await loadTokens(refreshController.signal); + tokens = result.tokens; + + const pair = chooseDefaultPair(tokens); + fromToken = + (preserveSelection && + tokens.find((token) => token.symbol.toUpperCase() === previousFrom)) || + pair[0]; + toToken = + (preserveSelection && + tokens.find((token) => token.symbol.toUpperCase() === previousTo)) || + pair[1]; + + if (fromToken.symbol.toUpperCase() === toToken.symbol.toUpperCase()) { + toToken = tokens.find( + (token) => + token.symbol.toUpperCase() !== fromToken?.symbol.toUpperCase(), + ) ?? pair[1]; + } + + renderSelectedToken("from", fromToken); + renderSelectedToken("to", toToken); + + elements.assetCount.textContent = String(tokens.length); + elements.dataSourceLabel.textContent = + result.source === "live" ? "Switcheo live" : "Resilient fallback"; + + setPriceState( + result.source, + result.source === "live" + ? "Live prices connected" + : "Fallback prices active", + result.loadedAt, + ); + + if (result.warning) { + showToast(result.warning, "warning"); + } + + updateForm(); + } catch (error) { + if (error instanceof DOMException && error.name === "AbortError") { + return; + } + + setPriceState("error", "Could not load prices"); + showToast("Price refresh failed. Please try again.", "error"); + } finally { + setLoadingPrices(false); + } +} + +function currentAmount(): number { + return Number(elements.amountInput.value); +} + +function amountError(): string | null { + if (!fromToken) return "Select a source token."; + return validateAmount(elements.amountInput.value, fromToken.balance); +} + +function updateBalance(): void { + elements.fromBalance.textContent = fromToken + ? `${formatTokenAmount(fromToken.balance, 5)} ${fromToken.symbol}` + : "—"; +} + +function updateSubmitState(error: string | null): void { + const hasAmount = elements.amountInput.value.trim().length > 0; + const valid = !error && Boolean(fromToken && toToken && quote); + + elements.submitButton.disabled = + !valid || isLoadingPrices || isSubmitting; + + if (isSubmitting) { + elements.submitLabel.textContent = "Routing swap…"; + return; + } + + if (isLoadingPrices) { + elements.submitLabel.textContent = "Loading prices…"; + return; + } + + if (!hasAmount) { + elements.submitLabel.textContent = "Enter an amount"; + return; + } + + if (error) { + elements.submitLabel.textContent = "Review amount"; + return; + } + + elements.submitLabel.textContent = + `Review ${quote?.shortLabel ?? ""} route`; +} + +function stopQuoteTimer(): void { + if (quoteTimer !== null) { + window.clearInterval(quoteTimer); + quoteTimer = null; + } +} + +function startQuoteTimer(): void { + stopQuoteTimer(); + quoteExpiresAt = Date.now() + 15_000; + + const tick = () => { + const remaining = Math.max(0, Math.ceil((quoteExpiresAt - Date.now()) / 1000)); + elements.quoteCountdown.textContent = `${remaining}s`; + + if (remaining === 0) { + quoteExpiresAt = Date.now() + 15_000; + elements.quoteCountdown.textContent = "15s"; + elements.intelligencePanel.classList.remove("quote-flash"); + requestAnimationFrame(() => + elements.intelligencePanel.classList.add("quote-flash"), + ); + } + }; + + tick(); + quoteTimer = window.setInterval(tick, 1000); +} + +function routeById(routeId: RouteId | null): RouteQuote | null { + return routeQuotes.find((candidate) => candidate.id === routeId) ?? null; +} + +function selectedRouteForIntent(): RouteQuote | null { + if (routeQuotes.length === 0) return null; + return ( + routeById(manuallySelectedRouteId) ?? + chooseRecommendedRoute(routeQuotes, swapIntent) + ); +} + +function renderRouteComparison(): void { + if (!quote) { + elements.routeComparison.replaceChildren(); + return; + } + + const recommended = chooseRecommendedRoute(routeQuotes, swapIntent); + + elements.routeComparison.innerHTML = routeQuotes + .map((route) => { + const selected = route.id === quote?.id; + const delta = + quote && route.id !== quote.id + ? route.netOutput - quote.netOutput + : 0; + + return ` + + `; + }) + .join(""); +} + +function renderAllocation(): void { + if (!quote) { + elements.allocationTrack.replaceChildren(); + elements.allocationLegend.replaceChildren(); + elements.allocationLabel.textContent = "—"; + return; + } + + elements.allocationLabel.textContent = + quote.allocation.length === 1 + ? "Single venue" + : `${quote.allocation.length} venues`; + + elements.allocationTrack.innerHTML = quote.allocation + .map( + (item, index) => ` + + `, + ) + .join(""); + + elements.allocationLegend.innerHTML = quote.allocation + .map( + (item, index) => ` + + + ${item.venue} ${item.percentage}% + + `, + ) + .join(""); +} + +function renderScenario(): void { + const signedMove = + scenarioMovePercent > 0 + ? `+${scenarioMovePercent.toFixed(1)}%` + : `${scenarioMovePercent.toFixed(1)}%`; + elements.scenarioMove.textContent = signedMove; + + if (!quote || !toToken) { + elements.scenarioOutput.textContent = "—"; + elements.scenarioDelta.textContent = "No active quote"; + return; + } + + const projected = projectRouteOutput(quote, scenarioMovePercent); + const delta = projected - quote.netOutput; + elements.scenarioOutput.textContent = + `${formatTokenAmount(projected, 8)} ${toToken.symbol}`; + + if (Math.abs(delta) < 1e-12) { + elements.scenarioDelta.textContent = "No simulated movement"; + elements.scenarioDelta.dataset.tone = "neutral"; + } else { + elements.scenarioDelta.textContent = + `${delta > 0 ? "+" : ""}${formatTokenAmount(delta, 8)} ${toToken.symbol} vs current quote`; + elements.scenarioDelta.dataset.tone = delta > 0 ? "positive" : "negative"; + } +} + +function renderRouteIntelligence(): void { + if (!quote) { + elements.intelligencePanel.classList.remove("has-intelligence"); + renderRouteComparison(); + renderAllocation(); + renderScenario(); + stopQuoteTimer(); + return; + } + + const recommended = chooseRecommendedRoute(routeQuotes, swapIntent); + const manuallyOverridden = quote.id !== recommended.id; + + elements.confidenceRing.style.setProperty( + "--confidence", + quote.confidencePercent.toFixed(0), + ); + elements.confidenceValue.textContent = + `${quote.confidencePercent.toFixed(0)}%`; + elements.routeReasonTitle.textContent = manuallyOverridden + ? `${quote.label} manually selected` + : `${quote.label} matches your intent`; + elements.routeReason.textContent = manuallyOverridden + ? `${quote.description} The intent engine would otherwise recommend ${recommended.label}.` + : quote.description; + + renderRouteComparison(); + renderAllocation(); + renderScenario(); + elements.intelligencePanel.classList.add("has-intelligence"); + startQuoteTimer(); +} + +function renderEmptyQuote(): void { + quote = null; + routeQuotes = []; + elements.outputInput.value = ""; + elements.fromUsd.textContent = "≈ $0.00"; + elements.toUsd.textContent = "≈ $0.00"; + elements.exchangeRate.textContent = "—"; + elements.routeValue.textContent = "Intent engine"; + elements.feeValue.textContent = "—"; + elements.minimumValue.textContent = "—"; + elements.impactValue.textContent = "—"; + elements.quotePanel.classList.remove("has-quote"); + renderRouteIntelligence(); +} + +function updateQuote(): void { + if (!fromToken || !toToken) { + renderEmptyQuote(); + return; + } + + const error = amountError(); + const amount = currentAmount(); + + if (error || !Number.isFinite(amount)) { + renderEmptyQuote(); + return; + } + + routeQuotes = buildRouteQuotes( + amount, + fromToken, + toToken, + slippagePercent, + ); + quote = selectedRouteForIntent(); + + if (!quote) { + renderEmptyQuote(); + return; + } + + elements.outputInput.value = formatTokenAmount(quote.netOutput, 8); + elements.fromUsd.textContent = `≈ ${formatUsd(quote.usdValue)}`; + elements.toUsd.textContent = `≈ ${formatUsd( + quote.netOutput * toToken.price, + )}`; + + const displayedRate = invertedRate ? 1 / quote.rate : quote.rate; + const base = invertedRate ? toToken : fromToken; + const counter = invertedRate ? fromToken : toToken; + + elements.exchangeRate.textContent = + `1 ${base.symbol} = ${formatTokenAmount(displayedRate, 8)} ${counter.symbol}`; + elements.routeValue.textContent = + `${quote.label} · ${quote.latencySeconds.toFixed(1)}s`; + elements.feeValue.textContent = + `${formatTokenAmount(quote.serviceFee, 8)} ${toToken.symbol}`; + elements.minimumValue.textContent = + `${formatTokenAmount(quote.minimumReceived, 8)} ${toToken.symbol}`; + elements.impactValue.textContent = + `${quote.priceImpactPercent.toFixed(2)}%`; + elements.impactValue.classList.toggle( + "warning", + quote.priceImpactPercent >= 0.5, + ); + + elements.quotePanel.classList.add("has-quote"); + renderRouteIntelligence(); +} + +function updateForm(): void { + updateBalance(); + + const error = amountError(); + const shouldShowError = + elements.amountInput.dataset.touched === "true" && + Boolean(elements.amountInput.value.trim()); + + elements.amountError.textContent = shouldShowError ? error ?? "" : ""; + elements.fromField.classList.toggle( + "has-error", + shouldShowError && Boolean(error), + ); + + updateQuote(); + updateSubmitState(error); +} + +function sanitizeAmountInput(value: string): string { + let output = value.replace(/,/g, ".").replace(/[^\d.]/g, ""); + const decimalIndex = output.indexOf("."); + + if (decimalIndex !== -1) { + output = + output.slice(0, decimalIndex + 1) + + output.slice(decimalIndex + 1).replace(/\./g, ""); + } + + if (output.startsWith("00") && !output.startsWith("0.")) { + output = output.replace(/^0+/, "0"); + } + + return output; +} + +function setAmount(value: string, markTouched = true): void { + elements.amountInput.value = value; + if (markTouched) { + elements.amountInput.dataset.touched = "true"; + } + updateForm(); +} + +function reversePair(): void { + if (!fromToken || !toToken) return; + manuallySelectedRouteId = null; + + const previousAmount = currentAmount(); + const previousQuote = quote; + + [fromToken, toToken] = [toToken, fromToken]; + + renderSelectedToken("from", fromToken); + renderSelectedToken("to", toToken); + + if ( + Number.isFinite(previousAmount) && + previousAmount > 0 && + previousQuote + ) { + const newAmount = Math.min( + previousQuote.netOutput, + fromToken.balance, + ); + elements.amountInput.value = formatTokenAmount(newAmount, 8).replace( + /,/g, + "", + ); + } + + elements.reverseButton.classList.remove("rotate-once"); + requestAnimationFrame(() => + elements.reverseButton.classList.add("rotate-once"), + ); + + updateForm(); +} + +function filteredTokens(query: string): Token[] { + const normalized = query.trim().toLowerCase(); + const excluded = + activePickerSide === "from" + ? toToken?.symbol.toUpperCase() + : fromToken?.symbol.toUpperCase(); + + return tokens.filter((token) => { + if (token.symbol.toUpperCase() === excluded) { + return false; + } + + if (!normalized) return true; + + return ( + token.symbol.toLowerCase().includes(normalized) || + token.name.toLowerCase().includes(normalized) + ); + }); +} + +function renderPopularTokens(): void { + elements.popularTokens.innerHTML = popularTokens(tokens) + .filter((token) => { + const excluded = + activePickerSide === "from" + ? toToken?.symbol.toUpperCase() + : fromToken?.symbol.toUpperCase(); + return token.symbol.toUpperCase() !== excluded; + }) + .slice(0, 4) + .map( + (token) => ` + + `, + ) + .join(""); + + wireImageFallbacks(elements.popularTokens); +} + +function renderTokenList(query = ""): void { + const visibleTokens = filteredTokens(query); + elements.emptyTokenState.hidden = visibleTokens.length > 0; + + elements.tokenList.innerHTML = visibleTokens + .map( + (token) => ` + + `, + ) + .join(""); + + wireImageFallbacks(elements.tokenList); +} + +function openTokenPicker(side: SwapSide): void { + activePickerSide = side; + elements.tokenSearch.value = ""; + renderPopularTokens(); + renderTokenList(); + + if (!elements.tokenDialog.open) { + elements.tokenDialog.showModal(); + } + + requestAnimationFrame(() => elements.tokenSearch.focus()); +} + +function selectToken(symbol: string): void { + const token = tokens.find((candidate) => candidate.symbol === symbol); + if (!token) return; + + manuallySelectedRouteId = null; + + if (activePickerSide === "from") { + fromToken = token; + renderSelectedToken("from", token); + } else { + toToken = token; + renderSelectedToken("to", token); + } + + elements.tokenDialog.close(); + updateForm(); +} + +function showToast( + message: string, + tone: "success" | "warning" | "error" = "success", +): void { + const toast = document.createElement("div"); + toast.className = `toast ${tone}`; + toast.innerHTML = ` + + ${message} + `; + + elements.toastRegion.append(toast); + + requestAnimationFrame(() => toast.classList.add("visible")); + + window.setTimeout(() => { + toast.classList.remove("visible"); + window.setTimeout(() => toast.remove(), 220); + }, 3800); +} + +function simulateSwap(): Promise { + return new Promise((resolve) => { + window.setTimeout(resolve, 1250); + }); +} + +async function submitSwap(): Promise { + if (!fromToken || !toToken || !quote) return; + + const error = amountError(); + if (error) { + elements.amountInput.dataset.touched = "true"; + updateForm(); + elements.amountInput.focus(); + return; + } + + isSubmitting = true; + elements.submitButton.classList.add("is-loading"); + updateSubmitState(null); + + const amount = currentAmount(); + const submittedFrom = fromToken; + const submittedTo = toToken; + const submittedQuote = quote; + + try { + await simulateSwap(); + + const reference = `ORB-${Date.now().toString(36).toUpperCase().slice(-7)}`; + + elements.successSummary.textContent = + `Your ${submittedFrom.symbol} was routed into ${submittedTo.symbol} through ${submittedQuote.label}, selected for the ${swapIntent} intent.`; + elements.receiptPaid.textContent = + `${formatTokenAmount(amount, 8)} ${submittedFrom.symbol}`; + elements.receiptReceived.textContent = + `${formatTokenAmount(submittedQuote.netOutput, 8)} ${submittedTo.symbol}`; + elements.receiptReference.textContent = reference; + + elements.successDialog.showModal(); + showToast("Simulated swap completed successfully.", "success"); + + submittedFrom.balance = Math.max(0, submittedFrom.balance - amount); + submittedTo.balance += submittedQuote.netOutput; + + elements.amountInput.value = ""; + elements.amountInput.dataset.touched = "false"; + updateForm(); + } catch { + showToast("The simulated route failed. No balance changed.", "error"); + } finally { + isSubmitting = false; + elements.submitButton.classList.remove("is-loading"); + updateForm(); + } +} + +function applyTheme(theme: "light" | "dark"): void { + elements.html.dataset.theme = theme; + localStorage.setItem("orbit-theme", theme); + elements.themeToggle.setAttribute( + "aria-label", + theme === "dark" ? "Switch to light theme" : "Switch to dark theme", + ); +} + +function initializeTheme(): void { + const stored = localStorage.getItem("orbit-theme"); + + if (stored === "light" || stored === "dark") { + applyTheme(stored); + return; + } + + applyTheme( + window.matchMedia("(prefers-color-scheme: light)").matches + ? "light" + : "dark", + ); +} + +function closeDialogOnBackdrop( + dialog: HTMLDialogElement, + event: MouseEvent, +): void { + const rect = dialog.getBoundingClientRect(); + const outside = + event.clientX < rect.left || + event.clientX > rect.right || + event.clientY < rect.top || + event.clientY > rect.bottom; + + if (outside) dialog.close(); +} + +elements.amountInput.addEventListener("input", () => { + const sanitized = sanitizeAmountInput(elements.amountInput.value); + if (sanitized !== elements.amountInput.value) { + elements.amountInput.value = sanitized; + } + updateForm(); +}); + +elements.amountInput.addEventListener("blur", () => { + elements.amountInput.dataset.touched = "true"; + updateForm(); +}); + +elements.maxButton.addEventListener("click", () => { + if (!fromToken) return; + setAmount( + formatTokenAmount(fromToken.balance, 8).replace(/,/g, ""), + ); + elements.amountInput.focus(); +}); + +elements.reverseButton.addEventListener("click", reversePair); +elements.fromTrigger.addEventListener("click", () => + openTokenPicker("from"), +); +elements.toTrigger.addEventListener("click", () => + openTokenPicker("to"), +); + +elements.tokenSearch.addEventListener("input", () => { + renderTokenList(elements.tokenSearch.value); +}); + +elements.tokenList.addEventListener("click", (event) => { + const button = (event.target as Element).closest( + "[data-token-symbol]", + ); + if (button?.dataset.tokenSymbol) { + selectToken(button.dataset.tokenSymbol); + } +}); + +elements.popularTokens.addEventListener("click", (event) => { + const button = (event.target as Element).closest( + "[data-token-symbol]", + ); + if (button?.dataset.tokenSymbol) { + selectToken(button.dataset.tokenSymbol); + } +}); + +elements.closeTokenDialog.addEventListener("click", () => + elements.tokenDialog.close(), +); +elements.closeSuccessDialog.addEventListener("click", () => + elements.successDialog.close(), +); + +elements.tokenDialog.addEventListener("click", (event) => + closeDialogOnBackdrop(elements.tokenDialog, event), +); +elements.successDialog.addEventListener("click", (event) => + closeDialogOnBackdrop(elements.successDialog, event), +); + +elements.refreshButton.addEventListener("click", () => { + void refreshPrices(); +}); + +elements.rateToggle.addEventListener("click", () => { + invertedRate = !invertedRate; + updateQuote(); +}); + + +elements.intentOptions.forEach((button) => { + button.addEventListener("click", () => { + const intent = button.dataset.intent as SwapIntent | undefined; + if (!intent) return; + + swapIntent = intent; + manuallySelectedRouteId = null; + elements.intentDescription.textContent = INTENT_DESCRIPTIONS[intent]; + elements.quoteModeLabel.textContent = button.querySelector("strong")?.textContent ?? intent; + + elements.intentOptions.forEach((option) => { + const selected = option === button; + option.classList.toggle("active", selected); + option.setAttribute("aria-checked", String(selected)); + }); + + updateQuote(); + }); +}); + +elements.routeComparison.addEventListener("click", (event) => { + const button = (event.target as Element).closest("[data-route-id]"); + const routeId = button?.dataset.routeId as RouteId | undefined; + if (!routeId) return; + + manuallySelectedRouteId = routeId; + quote = routeById(routeId); + if (quote) { + updateQuote(); + showToast(`${quote.label} selected manually.`, "success"); + } +}); + +elements.scenarioSlider.addEventListener("input", () => { + scenarioMovePercent = Number(elements.scenarioSlider.value); + renderScenario(); +}); + +document + .querySelectorAll('input[name="slippage"]') + .forEach((radio) => { + radio.addEventListener("change", () => { + if (radio.checked) { + slippagePercent = Number(radio.value); + updateQuote(); + } + }); + }); + +elements.form.addEventListener("submit", (event) => { + event.preventDefault(); + void submitSwap(); +}); + +elements.themeToggle.addEventListener("click", () => { + applyTheme( + elements.html.dataset.theme === "dark" ? "light" : "dark", + ); +}); + +document.addEventListener("keydown", (event) => { + const typing = + document.activeElement instanceof HTMLInputElement || + document.activeElement instanceof HTMLTextAreaElement; + + if (!typing && event.key.toLowerCase() === "r") { + event.preventDefault(); + reversePair(); + return; + } + + if (!typing && event.key.toLowerCase() === "m" && fromToken) { + event.preventDefault(); + setAmount(formatTokenAmount(fromToken.balance, 8).replace(/,/g, "")); + return; + } + + if ( + event.key === "/" && + !elements.tokenDialog.open && + document.activeElement?.tagName !== "INPUT" + ) { + event.preventDefault(); + openTokenPicker("from"); + } +}); + +initializeTheme(); +elements.amountInput.dataset.touched = "false"; +renderEmptyQuote(); +void refreshPrices({ preserveSelection: false }); diff --git a/src/problem2/src/style.css b/src/problem2/src/style.css new file mode 100644 index 0000000000..3bc3f81dfc --- /dev/null +++ b/src/problem2/src/style.css @@ -0,0 +1,2199 @@ +:root { + color-scheme: dark; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, + "Segoe UI", sans-serif; + font-synthesis: none; + --bg: #080a12; + --bg-elevated: rgba(16, 19, 31, 0.86); + --bg-strong: #111522; + --surface: rgba(19, 23, 37, 0.82); + --surface-strong: #171b2a; + --field: rgba(11, 14, 25, 0.78); + --field-hover: rgba(16, 20, 34, 0.92); + --border: rgba(177, 188, 222, 0.13); + --border-strong: rgba(177, 188, 222, 0.25); + --text: #f7f8fc; + --text-soft: #b1b9cf; + --muted: #7b849c; + --accent: #8b7cff; + --accent-bright: #b7a8ff; + --accent-two: #51e0c2; + --accent-glow: rgba(139, 124, 255, 0.28); + --success: #63e6be; + --warning: #ffcc74; + --error: #ff7a93; + --shadow: + 0 32px 90px rgba(0, 0, 0, 0.38), + 0 2px 0 rgba(255, 255, 255, 0.03) inset; + --radius-xl: 30px; + --radius-lg: 22px; + --radius-md: 16px; + --transition: 180ms cubic-bezier(0.2, 0.8, 0.2, 1); +} + +:root[data-theme="light"] { + color-scheme: light; + --bg: #f1f3f9; + --bg-elevated: rgba(255, 255, 255, 0.9); + --bg-strong: #ffffff; + --surface: rgba(255, 255, 255, 0.84); + --surface-strong: #ffffff; + --field: rgba(244, 246, 252, 0.95); + --field-hover: #ffffff; + --border: rgba(40, 48, 77, 0.11); + --border-strong: rgba(40, 48, 77, 0.2); + --text: #141827; + --text-soft: #4f5871; + --muted: #7a8399; + --accent: #6d5df5; + --accent-bright: #5142dc; + --accent-two: #0ba88b; + --accent-glow: rgba(109, 93, 245, 0.18); + --success: #058764; + --warning: #a86600; + --error: #d43d5d; + --shadow: + 0 30px 70px rgba(42, 52, 84, 0.15), + 0 2px 0 rgba(255, 255, 255, 0.8) inset; +} + +* { + box-sizing: border-box; +} + +html { + min-width: 360px; + min-height: 100%; + scroll-behavior: smooth; +} + +body { + min-height: 100vh; + margin: 0; + overflow-x: hidden; + color: var(--text); + background: + radial-gradient(circle at 12% 18%, rgba(87, 70, 214, 0.12), transparent 31rem), + radial-gradient(circle at 84% 70%, rgba(48, 187, 163, 0.08), transparent 30rem), + var(--bg); + transition: + color var(--transition), + background-color var(--transition); +} + +button, +input { + font: inherit; +} + +button { + color: inherit; +} + +button, +summary { + -webkit-tap-highlight-color: transparent; +} + +button:focus-visible, +input:focus-visible, +summary:focus-visible, +a:focus-visible { + outline: 3px solid color-mix(in srgb, var(--accent) 68%, transparent); + outline-offset: 3px; +} + +button:disabled { + cursor: not-allowed; +} + +a { + color: inherit; + text-decoration: none; +} + +svg { + display: block; + fill: none; + stroke: currentColor; + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 1.8; +} + +.ambient { + position: fixed; + z-index: -3; + border-radius: 999px; + filter: blur(22px); + pointer-events: none; +} + +.ambient-one { + top: 10rem; + left: -15rem; + width: 35rem; + height: 35rem; + background: rgba(109, 87, 255, 0.1); +} + +.ambient-two { + right: -18rem; + bottom: -7rem; + width: 42rem; + height: 42rem; + background: rgba(43, 218, 184, 0.075); +} + +.noise { + position: fixed; + z-index: -2; + inset: 0; + opacity: 0.02; + pointer-events: none; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 180 180' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.92' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.75'/%3E%3C/svg%3E"); +} + +.site-header { + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: center; + width: min(1240px, calc(100% - 40px)); + margin: 0 auto; + padding: 26px 0 12px; +} + +.brand { + display: inline-flex; + align-items: center; + justify-self: start; + gap: 11px; +} + +.brand-mark { + display: grid; + width: 39px; + height: 39px; + place-items: center; + border: 1px solid var(--border-strong); + border-radius: 13px; + color: var(--accent-bright); + background: + linear-gradient(145deg, rgba(139, 124, 255, 0.18), rgba(81, 224, 194, 0.08)), + var(--surface); + box-shadow: 0 9px 28px var(--accent-glow); +} + +.brand-mark svg { + width: 25px; + stroke-width: 1.65; +} + +.brand-mark svg path:first-child { + opacity: 0.42; +} + +.brand > span:last-child { + display: flex; + align-items: baseline; + gap: 7px; +} + +.brand strong { + font-size: 17px; + letter-spacing: -0.03em; +} + +.brand small { + color: var(--muted); + font-size: 9px; + font-weight: 800; + letter-spacing: 0.17em; +} + +.top-nav { + display: flex; + align-items: center; + gap: 7px; + padding: 5px; + border: 1px solid var(--border); + border-radius: 999px; + background: color-mix(in srgb, var(--surface) 78%, transparent); + backdrop-filter: blur(16px); +} + +.top-nav a { + padding: 8px 15px; + border-radius: 999px; + color: var(--muted); + font-size: 13px; + font-weight: 650; + transition: + color var(--transition), + background var(--transition); +} + +.top-nav a:hover { + color: var(--text); +} + +.top-nav a.active { + color: var(--text); + background: var(--surface-strong); + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.12); +} + +.header-actions { + display: flex; + align-items: center; + justify-self: end; + gap: 10px; +} + +.network-status { + display: inline-flex; + align-items: center; + gap: 8px; + color: var(--text-soft); + font-size: 12px; + font-weight: 600; +} + +.status-dot { + width: 7px; + height: 7px; + border-radius: 50%; + background: var(--success); + box-shadow: 0 0 0 5px color-mix(in srgb, var(--success) 12%, transparent); +} + +.icon-button { + display: inline-grid; + width: 39px; + height: 39px; + padding: 0; + place-items: center; + border: 1px solid var(--border); + border-radius: 12px; + color: var(--text-soft); + background: var(--surface); + cursor: pointer; + transition: + color var(--transition), + border-color var(--transition), + transform var(--transition), + background var(--transition); +} + +.icon-button:hover:not(:disabled) { + color: var(--text); + border-color: var(--border-strong); + background: var(--surface-strong); + transform: translateY(-1px); +} + +.icon-button svg { + width: 18px; + height: 18px; +} + +.moon-icon { + display: none; +} + +:root[data-theme="light"] .sun-icon { + display: none; +} + +:root[data-theme="light"] .moon-icon { + display: block; +} + +.app-shell { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(420px, 510px); + gap: clamp(58px, 8vw, 118px); + align-items: center; + width: min(1180px, calc(100% - 40px)); + min-height: calc(100vh - 142px); + margin: 0 auto; + padding: 54px 0 70px; +} + +.hero-panel { + align-self: center; + max-width: 600px; +} + +.eyebrow { + display: flex; + align-items: center; + gap: 11px; + margin-bottom: 22px; + color: var(--accent-two); + font-size: 11px; + font-weight: 800; + letter-spacing: 0.15em; + text-transform: uppercase; +} + +.eyebrow-line { + width: 28px; + height: 1px; + background: currentColor; +} + +.hero-panel h1 { + max-width: 650px; + margin: 0; + font-size: clamp(48px, 6.2vw, 82px); + font-weight: 660; + letter-spacing: -0.067em; + line-height: 0.98; +} + +.hero-panel h1 span { + display: block; + color: transparent; + background: + linear-gradient(102deg, var(--accent-bright) 0%, #9d8cff 38%, var(--accent-two) 105%); + -webkit-background-clip: text; + background-clip: text; +} + +.hero-copy { + max-width: 520px; + margin: 26px 0 0; + color: var(--text-soft); + font-size: 17px; + line-height: 1.7; +} + +.trust-row { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 26px; + margin-top: 41px; +} + +.trust-row div { + position: relative; +} + +.trust-row div:not(:last-child)::after { + position: absolute; + top: 3px; + right: -13px; + width: 1px; + height: 42px; + background: var(--border); + content: ""; +} + +.trust-row strong, +.trust-row span { + display: block; +} + +.trust-row strong { + margin-bottom: 6px; + font-size: 19px; + letter-spacing: -0.035em; +} + +.trust-row span { + color: var(--muted); + font-size: 11px; + line-height: 1.45; +} + +.route-visual { + max-width: 520px; + margin-top: 42px; + padding: 18px 20px; + border: 1px solid var(--border); + border-radius: 19px; + background: color-mix(in srgb, var(--surface) 74%, transparent); + backdrop-filter: blur(16px); +} + +.route-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 17px; + color: var(--text-soft); + font-size: 11px; + font-weight: 700; +} + +.route-badge { + padding: 4px 7px; + border: 1px solid color-mix(in srgb, var(--accent-two) 28%, transparent); + border-radius: 999px; + color: var(--accent-two); + background: color-mix(in srgb, var(--accent-two) 7%, transparent); + font-size: 8px; + letter-spacing: 0.14em; +} + +.route-track { + display: grid; + grid-template-columns: auto 1fr auto 1fr auto; + align-items: center; + gap: 10px; +} + +.route-node { + display: flex; + flex-direction: column; + align-items: center; + gap: 7px; + color: var(--muted); + font-size: 9px; + white-space: nowrap; +} + +.mini-token { + display: grid; + width: 32px; + height: 32px; + place-items: center; + border: 1px solid var(--border-strong); + border-radius: 50%; + color: #fff; + font-size: 11px; + font-weight: 800; +} + +.eth-token { + background: linear-gradient(145deg, #7486ff, #4654bd); +} + +.pool-token { + background: linear-gradient(145deg, #7461eb, #9d60cc); +} + +.usdc-token { + background: linear-gradient(145deg, #3d91df, #226bb5); +} + +.route-line { + display: flex; + align-items: center; +} + +.route-line span { + flex: 1; + height: 1px; + background: linear-gradient(90deg, var(--border), var(--accent)); +} + +.route-line span:last-child { + background: linear-gradient(90deg, var(--accent-two), var(--border)); +} + +.route-line i { + width: 5px; + height: 5px; + border-radius: 50%; + background: var(--accent-two); + box-shadow: 0 0 9px var(--accent-two); +} + +.security-note { + display: flex; + align-items: center; + gap: 11px; + max-width: 520px; + margin-top: 18px; + color: var(--muted); +} + +.security-note svg { + flex: 0 0 auto; + width: 19px; + color: var(--accent-two); +} + +.security-note p { + margin: 0; + font-size: 11px; + line-height: 1.5; +} + +.security-note strong { + color: var(--text-soft); +} + +.swap-column { + width: 100%; +} + +.swap-card { + position: relative; + padding: 27px; + overflow: visible; + border: 1px solid var(--border); + border-radius: var(--radius-xl); + background: + linear-gradient( + 150deg, + color-mix(in srgb, var(--bg-elevated) 96%, var(--accent) 4%), + var(--bg-elevated) + ); + box-shadow: var(--shadow); + backdrop-filter: blur(26px); +} + +.swap-card::before { + position: absolute; + z-index: -1; + inset: -1px; + border-radius: inherit; + background: linear-gradient( + 145deg, + color-mix(in srgb, var(--accent) 22%, transparent), + transparent 30%, + transparent 70%, + color-mix(in srgb, var(--accent-two) 12%, transparent) + ); + content: ""; + opacity: 0.75; + pointer-events: none; +} + +.card-heading { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 20px; +} + +.section-kicker { + margin: 0 0 5px; + color: var(--accent-two); + font-size: 9px; + font-weight: 800; + letter-spacing: 0.16em; + text-transform: uppercase; +} + +.card-heading h2, +.dialog-header h2, +.success-shell h2 { + margin: 0; + font-size: 23px; + letter-spacing: -0.045em; +} + +.card-tools { + display: flex; + gap: 7px; +} + +.settings-menu { + position: relative; +} + +.settings-menu summary { + list-style: none; +} + +.settings-menu summary::-webkit-details-marker { + display: none; +} + +.settings-popover { + position: absolute; + z-index: 20; + top: 48px; + right: 0; + width: 268px; + padding: 17px; + border: 1px solid var(--border-strong); + border-radius: 17px; + background: var(--surface-strong); + box-shadow: 0 22px 50px rgba(0, 0, 0, 0.28); +} + +.settings-title { + display: flex; + align-items: baseline; + justify-content: space-between; +} + +.settings-title strong { + font-size: 13px; +} + +.settings-title span { + color: var(--muted); + font-size: 10px; +} + +.slippage-options { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 7px; + margin-top: 15px; +} + +.slippage-options input { + position: absolute; + opacity: 0; +} + +.slippage-options span { + display: grid; + height: 36px; + place-items: center; + border: 1px solid var(--border); + border-radius: 10px; + color: var(--text-soft); + font-size: 11px; + font-weight: 750; + cursor: pointer; + transition: var(--transition); +} + +.slippage-options input:checked + span { + border-color: color-mix(in srgb, var(--accent) 65%, transparent); + color: var(--accent-bright); + background: color-mix(in srgb, var(--accent) 13%, transparent); +} + +.settings-popover p { + margin: 13px 0 0; + color: var(--muted); + font-size: 10px; + line-height: 1.45; +} + +.price-state { + display: flex; + align-items: center; + gap: 8px; + margin: 20px 0 14px; + padding: 8px 11px; + border: 1px solid var(--border); + border-radius: 11px; + color: var(--muted); + background: color-mix(in srgb, var(--field) 82%, transparent); + font-size: 10px; +} + +.price-state time { + margin-left: auto; +} + +.price-state-dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--muted); +} + +.price-state[data-state="live"] .price-state-dot { + background: var(--success); + box-shadow: 0 0 8px color-mix(in srgb, var(--success) 75%, transparent); +} + +.price-state[data-state="fallback"] .price-state-dot { + background: var(--warning); +} + +.price-state[data-state="loading"] .price-state-dot { + background: var(--accent); + animation: pulse 1s infinite; +} + +.price-state[data-state="error"] .price-state-dot { + background: var(--error); +} + +.asset-field { + padding: 16px; + border: 1px solid var(--border); + border-radius: var(--radius-lg); + background: var(--field); + transition: + border-color var(--transition), + background var(--transition), + box-shadow var(--transition); +} + +.asset-field:focus-within, +.asset-field:hover { + border-color: var(--border-strong); + background: var(--field-hover); +} + +.asset-field:focus-within { + box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 9%, transparent); +} + +.asset-field.has-error { + border-color: color-mix(in srgb, var(--error) 50%, var(--border)); +} + +.asset-field-header, +.asset-field-footer { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; +} + +.asset-field-header { + margin-bottom: 14px; +} + +.asset-field-header label { + color: var(--text-soft); + font-size: 11px; + font-weight: 700; +} + +.asset-field-header span { + color: var(--muted); + font-size: 10px; +} + +.asset-field-header strong { + color: var(--text-soft); + font-weight: 650; +} + +.asset-input-row { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + align-items: center; + gap: 14px; +} + +.amount-control { + min-width: 0; +} + +.amount-control input { + width: 100%; + min-width: 0; + padding: 0; + border: 0; + outline: none; + color: var(--text); + background: transparent; + font-size: clamp(27px, 4vw, 35px); + font-weight: 630; + letter-spacing: -0.05em; +} + +.amount-control input::placeholder { + color: color-mix(in srgb, var(--muted) 52%, transparent); +} + +.amount-control input[readonly] { + cursor: default; +} + +.amount-control span { + display: block; + min-height: 17px; + margin-top: 4px; + color: var(--muted); + font-size: 10px; +} + +.token-trigger { + display: flex; + align-items: center; + gap: 9px; + min-width: 149px; + padding: 8px 10px; + border: 1px solid var(--border); + border-radius: 15px; + color: var(--text); + background: var(--surface); + cursor: pointer; + transition: + border-color var(--transition), + transform var(--transition), + background var(--transition); +} + +.token-trigger:hover { + border-color: var(--border-strong); + background: var(--surface-strong); + transform: translateY(-1px); +} + +.token-trigger > svg { + width: 15px; + margin-left: auto; + color: var(--muted); +} + +.token-trigger-copy { + min-width: 0; + text-align: left; +} + +.token-trigger-copy strong, +.token-trigger-copy small { + display: block; + max-width: 76px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.token-trigger-copy strong { + font-size: 13px; +} + +.token-trigger-copy small { + margin-top: 3px; + color: var(--muted); + font-size: 9px; +} + +.token-avatar { + display: grid; + flex: 0 0 auto; + width: 34px; + height: 34px; + place-items: center; +} + +.token-image-shell { + position: relative; + display: grid; + width: 34px; + height: 34px; + place-items: center; + overflow: hidden; + border: 1px solid var(--border-strong); + border-radius: 50%; + color: #fff; + background: + linear-gradient(145deg, color-mix(in srgb, var(--accent) 72%, #333), color-mix(in srgb, var(--accent-two) 55%, #273044)); + box-shadow: 0 5px 16px rgba(0, 0, 0, 0.18); +} + +.token-image-shell.compact { + width: 25px; + height: 25px; +} + +.token-image-shell img { + position: relative; + z-index: 2; + width: 100%; + height: 100%; + object-fit: cover; + background: var(--surface-strong); +} + +.token-fallback { + position: absolute; + z-index: 1; + font-size: 9px; + font-weight: 850; + letter-spacing: -0.04em; +} + +.image-failed img { + display: none; +} + +.asset-field-footer { + min-height: 19px; + margin-top: 9px; +} + +.asset-field-footer > button { + padding: 0; + border: 0; + color: var(--accent-bright); + background: transparent; + font-size: 9px; + font-weight: 800; + cursor: pointer; + text-transform: uppercase; + letter-spacing: 0.07em; +} + +.field-error { + min-height: 14px; + margin: 0; + color: var(--error); + font-size: 9px; +} + +.swap-direction-wrap { + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: center; + gap: 10px; + margin: 5px 0; +} + +.swap-direction-wrap > span { + height: 1px; + background: var(--border); +} + +.reverse-button { + display: grid; + width: 38px; + height: 38px; + padding: 0; + place-items: center; + border: 5px solid var(--bg-elevated); + border-radius: 13px; + color: var(--accent-bright); + background: color-mix(in srgb, var(--accent) 15%, var(--surface-strong)); + cursor: pointer; + transition: + transform 260ms cubic-bezier(0.2, 0.9, 0.2, 1.2), + background var(--transition); +} + +.reverse-button:hover { + background: color-mix(in srgb, var(--accent) 25%, var(--surface-strong)); +} + +.reverse-button svg { + width: 17px; +} + +.reverse-button.rotate-once { + transform: rotate(180deg); +} + +.quote-panel { + max-height: 0; + margin-top: 0; + overflow: hidden; + opacity: 0; + transition: + max-height 300ms ease, + margin 300ms ease, + opacity 220ms ease; +} + +.quote-panel.has-quote { + max-height: 245px; + margin-top: 16px; + opacity: 1; +} + +.rate-line, +.quote-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + width: 100%; + min-height: 31px; + color: var(--muted); + font-size: 10px; +} + +.rate-line { + padding: 0 0 8px; + border: 0; + border-bottom: 1px solid var(--border); + background: transparent; + cursor: pointer; +} + +.rate-line strong, +.quote-row strong { + margin-left: auto; + color: var(--text-soft); + font-weight: 650; + text-align: right; +} + +.rate-line svg { + width: 14px; + color: var(--muted); +} + +.quote-row:first-of-type { + padding-top: 8px; +} + +.quote-row strong.positive { + color: var(--success); +} + +.quote-row strong.warning { + color: var(--warning); +} + +.submit-button { + position: relative; + display: flex; + width: 100%; + min-height: 53px; + align-items: center; + justify-content: center; + gap: 11px; + margin-top: 18px; + overflow: hidden; + border: 0; + border-radius: 16px; + color: #fff; + background: + linear-gradient(100deg, #6958e8, #8b67ed 46%, #4fc9b3 130%); + box-shadow: 0 14px 32px color-mix(in srgb, var(--accent) 24%, transparent); + cursor: pointer; + font-size: 12px; + font-weight: 780; + letter-spacing: 0.01em; + transition: + transform var(--transition), + filter var(--transition), + opacity var(--transition); +} + +.submit-button::before { + position: absolute; + inset: 0; + background: linear-gradient(110deg, transparent 20%, rgba(255, 255, 255, 0.18), transparent 62%); + content: ""; + transform: translateX(-110%); + transition: transform 600ms ease; +} + +.submit-button:hover:not(:disabled) { + filter: brightness(1.08); + transform: translateY(-2px); +} + +.submit-button:hover:not(:disabled)::before { + transform: translateX(110%); +} + +.submit-button:active:not(:disabled) { + transform: translateY(0); +} + +.submit-button:disabled { + opacity: 0.38; + box-shadow: none; +} + +.submit-button > svg { + width: 16px; +} + +.spinner { + display: none; + width: 15px; + height: 15px; + border: 2px solid rgba(255, 255, 255, 0.35); + border-top-color: #fff; + border-radius: 50%; + animation: spin 800ms linear infinite; +} + +.submit-button.is-loading .spinner { + display: block; +} + +.submit-button.is-loading > svg { + display: none; +} + +.form-disclaimer { + margin: 12px 0 0; + color: var(--muted); + font-size: 9px; + text-align: center; +} + +.market-strip { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1px; + margin: 13px auto 0; + overflow: hidden; + border: 1px solid var(--border); + border-radius: 15px; + background: var(--border); +} + +.market-strip div { + padding: 12px 13px; + background: color-mix(in srgb, var(--surface) 78%, var(--bg)); +} + +.market-strip span, +.market-strip strong { + display: block; +} + +.market-strip span { + margin-bottom: 4px; + color: var(--muted); + font-size: 8px; + text-transform: uppercase; + letter-spacing: 0.06em; +} + +.market-strip strong { + color: var(--text-soft); + font-size: 10px; + font-weight: 700; +} + +.site-footer { + display: flex; + justify-content: space-between; + width: min(1180px, calc(100% - 40px)); + margin: 0 auto; + padding: 0 0 28px; + color: var(--muted); + font-size: 9px; + letter-spacing: 0.04em; +} + +dialog { + padding: 0; + border: 0; + color: var(--text); + background: transparent; +} + +dialog::backdrop { + background: rgba(3, 5, 12, 0.72); + backdrop-filter: blur(8px); +} + +.token-dialog { + width: min(500px, calc(100% - 28px)); + max-height: min(720px, calc(100vh - 32px)); + border-radius: 25px; +} + +.dialog-shell { + padding: 24px; + border: 1px solid var(--border-strong); + border-radius: inherit; + background: var(--bg-strong); + box-shadow: var(--shadow); +} + +.dialog-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 18px; +} + +.search-control { + display: flex; + align-items: center; + gap: 10px; + margin-top: 20px; + padding: 0 13px; + border: 1px solid var(--border); + border-radius: 14px; + background: var(--field); +} + +.search-control:focus-within { + border-color: color-mix(in srgb, var(--accent) 58%, var(--border)); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 9%, transparent); +} + +.search-control svg { + width: 17px; + color: var(--muted); +} + +.search-control input { + flex: 1; + min-width: 0; + height: 47px; + border: 0; + outline: 0; + color: var(--text); + background: transparent; + font-size: 12px; +} + +.search-control input::placeholder { + color: var(--muted); +} + +.search-control kbd { + display: grid; + min-width: 25px; + height: 23px; + place-items: center; + border: 1px solid var(--border); + border-radius: 6px; + color: var(--muted); + background: var(--surface); + font: inherit; + font-size: 10px; +} + +.popular-row { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 7px; + margin-top: 14px; +} + +.popular-token { + display: flex; + align-items: center; + justify-content: center; + gap: 7px; + height: 40px; + border: 1px solid var(--border); + border-radius: 11px; + color: var(--text-soft); + background: var(--surface); + cursor: pointer; + font-size: 10px; + font-weight: 700; + transition: var(--transition); +} + +.popular-token:hover { + border-color: var(--border-strong); + color: var(--text); + background: var(--surface-strong); +} + +.token-list-heading { + display: flex; + justify-content: space-between; + padding: 21px 10px 8px; + color: var(--muted); + font-size: 8px; + font-weight: 750; + letter-spacing: 0.1em; + text-transform: uppercase; +} + +.token-list { + max-height: min(390px, 48vh); + overflow-y: auto; + scrollbar-width: thin; + scrollbar-color: var(--border-strong) transparent; +} + +.token-option { + display: grid; + grid-template-columns: auto minmax(0, 1fr) auto; + align-items: center; + gap: 11px; + width: 100%; + padding: 10px; + border: 0; + border-radius: 13px; + color: var(--text); + background: transparent; + cursor: pointer; + text-align: left; + transition: background var(--transition); +} + +.token-option:hover { + background: var(--field); +} + +.token-option-copy strong, +.token-option-copy small, +.token-price-copy strong, +.token-price-copy small { + display: block; +} + +.token-option-copy strong, +.token-price-copy strong { + font-size: 12px; +} + +.token-option-copy small, +.token-price-copy small { + margin-top: 3px; + color: var(--muted); + font-size: 9px; +} + +.token-price-copy { + text-align: right; +} + +.empty-token-state { + margin: 30px 0 18px; + color: var(--muted); + font-size: 11px; + text-align: center; +} + +.success-dialog { + width: min(430px, calc(100% - 28px)); + border-radius: 25px; +} + +.success-shell { + padding: 31px; + border: 1px solid var(--border-strong); + border-radius: inherit; + background: var(--bg-strong); + box-shadow: var(--shadow); + text-align: center; +} + +.success-mark { + display: grid; + width: 64px; + height: 64px; + margin: 0 auto 20px; + place-items: center; + border: 1px solid color-mix(in srgb, var(--success) 28%, transparent); + border-radius: 50%; + color: var(--success); + background: color-mix(in srgb, var(--success) 10%, transparent); + box-shadow: 0 0 0 10px color-mix(in srgb, var(--success) 4%, transparent); +} + +.success-mark svg { + width: 32px; + stroke-width: 2.3; +} + +.success-shell > p:not(.section-kicker) { + margin: 12px auto 0; + color: var(--text-soft); + font-size: 12px; + line-height: 1.6; +} + +.receipt { + margin-top: 23px; + overflow: hidden; + border: 1px solid var(--border); + border-radius: 15px; +} + +.receipt div { + display: flex; + justify-content: space-between; + gap: 16px; + padding: 12px 14px; + background: var(--field); +} + +.receipt div + div { + border-top: 1px solid var(--border); +} + +.receipt span { + color: var(--muted); + font-size: 10px; +} + +.receipt strong { + color: var(--text-soft); + font-size: 10px; +} + +.success-shell .submit-button { + margin-top: 20px; +} + +.toast-region { + position: fixed; + z-index: 100; + right: 20px; + bottom: 20px; + display: grid; + gap: 10px; + width: min(360px, calc(100% - 40px)); + pointer-events: none; +} + +.toast { + display: flex; + align-items: center; + gap: 11px; + padding: 13px 14px; + border: 1px solid var(--border-strong); + border-radius: 13px; + color: var(--text-soft); + background: var(--surface-strong); + box-shadow: 0 18px 45px rgba(0, 0, 0, 0.28); + font-size: 10px; + line-height: 1.45; + opacity: 0; + transform: translateY(12px); + transition: + opacity 220ms ease, + transform 220ms ease; +} + +.toast.visible { + opacity: 1; + transform: translateY(0); +} + +.toast-icon { + flex: 0 0 auto; + width: 8px; + height: 8px; + border-radius: 50%; + background: var(--success); + box-shadow: 0 0 0 5px color-mix(in srgb, var(--success) 10%, transparent); +} + +.toast.warning .toast-icon { + background: var(--warning); + box-shadow: 0 0 0 5px color-mix(in srgb, var(--warning) 10%, transparent); +} + +.toast.error .toast-icon { + background: var(--error); + box-shadow: 0 0 0 5px color-mix(in srgb, var(--error) 10%, transparent); +} + +.is-spinning svg { + animation: spin 900ms linear infinite; +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} + +@keyframes pulse { + 50% { + opacity: 0.35; + transform: scale(0.75); + } +} + +@media (max-width: 980px) { + .site-header { + grid-template-columns: 1fr auto; + } + + .top-nav { + display: none; + } + + .app-shell { + grid-template-columns: 1fr; + gap: 54px; + max-width: 620px; + padding-top: 65px; + } + + .hero-panel { + max-width: none; + text-align: center; + } + + .hero-panel h1 { + max-width: none; + } + + .hero-copy { + margin-inline: auto; + } + + .eyebrow { + justify-content: center; + } + + .trust-row, + .route-visual, + .security-note { + margin-inline: auto; + } + + .security-note { + justify-content: center; + text-align: left; + } +} + +@media (max-width: 600px) { + .site-header, + .app-shell, + .site-footer { + width: min(100% - 24px, 1180px); + } + + .site-header { + padding-top: 16px; + } + + .network-status { + display: none; + } + + .brand > span:last-child small { + display: none; + } + + .app-shell { + gap: 38px; + padding: 42px 0 48px; + } + + .hero-panel h1 { + font-size: clamp(42px, 13vw, 62px); + } + + .hero-copy { + font-size: 15px; + } + + .trust-row { + gap: 15px; + } + + .trust-row div:not(:last-child)::after { + right: -8px; + } + + .route-visual { + padding: 16px 12px; + } + + .route-track { + gap: 6px; + } + + .route-node span:last-child { + font-size: 8px; + } + + .swap-card { + padding: 19px; + border-radius: 24px; + } + + .asset-field { + padding: 14px; + } + + .asset-input-row { + grid-template-columns: minmax(0, 1fr) 137px; + gap: 9px; + } + + .token-trigger { + min-width: 0; + padding: 7px 8px; + } + + .token-trigger-copy small { + display: none; + } + + .amount-control input { + font-size: 27px; + } + + .market-strip div { + padding-inline: 9px; + } + + .settings-popover { + right: -5px; + width: min(268px, calc(100vw - 48px)); + } + + .dialog-shell { + padding: 19px; + } + + .site-footer { + gap: 20px; + } +} + +@media (max-width: 430px) { + .hero-panel h1 { + font-size: 42px; + } + + .trust-row { + grid-template-columns: 1fr; + gap: 13px; + max-width: 230px; + text-align: left; + } + + .trust-row div { + display: grid; + grid-template-columns: 80px 1fr; + align-items: center; + } + + .trust-row div:not(:last-child)::after { + display: none; + } + + .trust-row strong { + margin: 0; + } + + .route-visual { + display: none; + } + + .security-note { + margin-top: 30px; + } + + .asset-input-row { + grid-template-columns: minmax(0, 1fr) 122px; + } + + .token-image-shell, + .token-avatar { + width: 30px; + height: 30px; + } + + .token-trigger-copy strong { + font-size: 11px; + } + + .market-strip { + grid-template-columns: 1fr; + } + + .site-footer { + display: none; + } + + .popular-row { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + scroll-behavior: auto !important; + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} + + +/* ========================================================= + Intent Engine — creative differentiator + ========================================================= */ + +.intent-lab { + margin-bottom: 14px; + padding: 14px; + border: 1px solid var(--border); + border-radius: 18px; + background: + linear-gradient(130deg, color-mix(in srgb, var(--accent) 8%, var(--field)), var(--field)); +} + +.intent-lab-heading, +.intelligence-heading, +.scenario-heading, +.allocation-heading { + display: flex; + align-items: center; + justify-content: space-between; + gap: 14px; +} + +.intent-lab-heading > div, +.scenario-heading > div { + display: grid; + gap: 3px; +} + +.micro-label { + color: var(--accent-two); + font-size: 8px; + font-weight: 850; + letter-spacing: 0.13em; + text-transform: uppercase; +} + +.intent-lab-heading strong, +.intelligence-heading strong, +.scenario-heading strong { + color: var(--text-soft); + font-size: 11px; +} + +.intent-ai-badge { + padding: 4px 7px; + border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); + border-radius: 999px; + color: var(--accent-bright); + background: color-mix(in srgb, var(--accent) 9%, transparent); + font-size: 7px; + font-weight: 850; + letter-spacing: 0.12em; +} + +.intent-options { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 7px; + margin-top: 12px; +} + +.intent-option { + display: flex; + min-width: 0; + align-items: center; + gap: 8px; + padding: 9px; + border: 1px solid var(--border); + border-radius: 12px; + color: var(--muted); + background: color-mix(in srgb, var(--surface) 55%, transparent); + cursor: pointer; + text-align: left; + transition: + transform var(--transition), + border-color var(--transition), + background var(--transition), + color var(--transition); +} + +.intent-option:hover { + color: var(--text-soft); + border-color: var(--border-strong); + transform: translateY(-1px); +} + +.intent-option.active { + color: var(--text); + border-color: color-mix(in srgb, var(--accent) 48%, var(--border)); + background: + linear-gradient(140deg, color-mix(in srgb, var(--accent) 17%, var(--surface)), var(--surface)); + box-shadow: 0 8px 20px color-mix(in srgb, var(--accent) 8%, transparent); +} + +.intent-icon { + display: grid; + flex: 0 0 auto; + width: 25px; + height: 25px; + place-items: center; + border: 1px solid var(--border); + border-radius: 8px; + color: var(--accent-bright); + font-size: 12px; +} + +.intent-option strong, +.intent-option small { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.intent-option strong { + font-size: 9px; +} + +.intent-option small { + margin-top: 2px; + color: var(--muted); + font-size: 7px; +} + +.intent-description { + min-height: 14px; + margin: 9px 1px 0; + color: var(--muted); + font-size: 8px; + line-height: 1.45; +} + +.intelligence-panel { + max-height: 0; + margin-top: 0; + overflow: hidden; + border: 1px solid transparent; + border-radius: 19px; + opacity: 0; + transform: translateY(-5px); + transition: + max-height 420ms ease, + margin 320ms ease, + padding 320ms ease, + border-color 320ms ease, + opacity 220ms ease, + transform 320ms ease; +} + +.intelligence-panel.has-intelligence { + max-height: 760px; + margin-top: 14px; + padding: 15px; + border-color: var(--border); + opacity: 1; + transform: translateY(0); + background: + radial-gradient(circle at 90% 0%, color-mix(in srgb, var(--accent-two) 8%, transparent), transparent 38%), + color-mix(in srgb, var(--field) 88%, transparent); +} + +.intelligence-panel.quote-flash { + animation: quote-flash 520ms ease; +} + +.quote-clock { + display: inline-flex; + align-items: center; + gap: 6px; + color: var(--muted); + font-size: 9px; + font-variant-numeric: tabular-nums; +} + +.clock-pulse { + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--accent-two); + box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent-two) 9%, transparent); + animation: pulse 1.4s infinite; +} + +.confidence-summary { + display: grid; + grid-template-columns: 74px 1fr; + align-items: center; + gap: 14px; + margin-top: 14px; +} + +.confidence-ring { + --confidence: 0; + display: grid; + width: 68px; + height: 68px; + place-items: center; + border-radius: 50%; + background: + radial-gradient(circle at center, var(--field) 57%, transparent 59%), + conic-gradient(var(--accent-two) calc(var(--confidence) * 1%), var(--border) 0); + box-shadow: 0 0 24px color-mix(in srgb, var(--accent-two) 8%, transparent); +} + +.confidence-ring span { + text-align: center; +} + +.confidence-ring strong, +.confidence-ring small { + display: block; +} + +.confidence-ring strong { + font-size: 15px; + letter-spacing: -0.04em; +} + +.confidence-ring small { + margin-top: 1px; + color: var(--muted); + font-size: 6px; + text-transform: uppercase; + letter-spacing: 0.06em; +} + +.confidence-copy strong { + color: var(--text); + font-size: 11px; +} + +.confidence-copy p { + margin: 5px 0 0; + color: var(--muted); + font-size: 8px; + line-height: 1.5; +} + +.route-comparison { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 7px; + margin-top: 14px; +} + +.route-option { + position: relative; + min-width: 0; + padding: 10px; + border: 1px solid var(--border); + border-radius: 13px; + color: var(--text-soft); + background: var(--surface); + cursor: pointer; + text-align: left; + transition: + transform var(--transition), + border-color var(--transition), + background var(--transition); +} + +.route-option:hover { + transform: translateY(-2px); + border-color: var(--border-strong); +} + +.route-option.selected { + border-color: color-mix(in srgb, var(--accent-two) 45%, var(--border)); + background: + linear-gradient(145deg, color-mix(in srgb, var(--accent-two) 9%, var(--surface)), var(--surface)); + box-shadow: 0 9px 24px color-mix(in srgb, var(--accent-two) 6%, transparent); +} + +.route-option-top { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 5px; +} + +.route-option-top > span:first-child { + min-width: 0; +} + +.route-option-top strong { + display: block; + font-size: 9px; +} + +.recommended-tag { + display: block; + width: fit-content; + margin-top: 3px; + color: var(--accent-two); + font-size: 5px; + font-weight: 900; + letter-spacing: 0.08em; +} + +.route-confidence { + color: var(--accent-two); + font-size: 8px; + font-weight: 800; +} + +.route-output { + display: block; + margin-top: 10px; + overflow: hidden; + color: var(--text); + font-size: 12px; + font-weight: 750; + text-overflow: ellipsis; + white-space: nowrap; +} + +.route-output small { + color: var(--muted); + font-size: 6px; +} + +.route-meta { + display: block; + margin-top: 5px; + overflow: hidden; + color: var(--muted); + font-size: 6px; + text-overflow: ellipsis; + white-space: nowrap; +} + +.allocation-block { + margin-top: 14px; + padding-top: 12px; + border-top: 1px solid var(--border); +} + +.allocation-heading { + color: var(--muted); + font-size: 8px; +} + +.allocation-heading strong { + color: var(--text-soft); + font-size: 8px; +} + +.allocation-track { + display: flex; + height: 7px; + margin-top: 9px; + overflow: hidden; + border-radius: 999px; + background: var(--border); +} + +.allocation-segment { + min-width: 2px; +} + +.violet { + background: var(--accent); +} + +.mint { + background: var(--accent-two); +} + +.amber { + background: var(--warning); +} + +.allocation-legend { + display: flex; + flex-wrap: wrap; + gap: 8px 12px; + margin-top: 8px; + color: var(--muted); + font-size: 7px; +} + +.allocation-legend span { + display: inline-flex; + align-items: center; + gap: 5px; +} + +.allocation-legend i { + width: 5px; + height: 5px; + border-radius: 50%; +} + +.scenario-lab { + margin-top: 14px; + padding: 12px; + border: 1px solid var(--border); + border-radius: 14px; + background: color-mix(in srgb, var(--surface) 58%, transparent); +} + +.scenario-heading output { + color: var(--accent-bright); + font-size: 11px; + font-weight: 800; + font-variant-numeric: tabular-nums; +} + +.scenario-lab input[type="range"] { + width: 100%; + height: 5px; + margin: 14px 0 0; + accent-color: var(--accent); + cursor: ew-resize; +} + +.scenario-scale { + display: flex; + justify-content: space-between; + margin-top: 5px; + color: var(--muted); + font-size: 6px; +} + +.scenario-result { + display: grid; + grid-template-columns: auto 1fr; + align-items: baseline; + gap: 4px 12px; + margin-top: 12px; + padding-top: 10px; + border-top: 1px solid var(--border); +} + +.scenario-result > span { + color: var(--muted); + font-size: 8px; +} + +.scenario-result > strong { + color: var(--text); + font-size: 11px; + text-align: right; +} + +.scenario-result > small { + grid-column: 1 / -1; + color: var(--muted); + font-size: 7px; + text-align: right; +} + +.scenario-result > small[data-tone="positive"] { + color: var(--success); +} + +.scenario-result > small[data-tone="negative"] { + color: var(--error); +} + +@keyframes quote-flash { + 50% { + border-color: color-mix(in srgb, var(--accent-two) 55%, var(--border)); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-two) 7%, transparent); + } +} + +@media (max-width: 600px) { + .intent-options { + grid-template-columns: 1fr; + } + + .intent-option small { + display: block; + } + + .route-comparison { + grid-template-columns: 1fr; + } + + .route-option { + display: grid; + grid-template-columns: 1fr auto; + align-items: center; + } + + .route-option-top { + grid-row: 1 / span 2; + } + + .route-output, + .route-meta { + margin-top: 0; + text-align: right; + } +} diff --git a/src/problem2/style.css b/src/problem2/style.css deleted file mode 100644 index 915af91c72..0000000000 --- a/src/problem2/style.css +++ /dev/null @@ -1,8 +0,0 @@ -body { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - min-width: 360px; - font-family: Arial, Helvetica, sans-serif; -} diff --git a/src/problem2/tsconfig.json b/src/problem2/tsconfig.json new file mode 100644 index 0000000000..507da0b9dd --- /dev/null +++ b/src/problem2/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "moduleResolution": "Bundler", + "allowImportingTsExtensions": false, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "strict": true, + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true + }, + "include": ["src"] +} diff --git a/src/problem2/vite.config.js b/src/problem2/vite.config.js new file mode 100644 index 0000000000..474a0f91d3 --- /dev/null +++ b/src/problem2/vite.config.js @@ -0,0 +1,9 @@ +import { defineConfig } from "vite"; + +export default defineConfig({ + base: "./", + build: { + target: "es2022", + sourcemap: true, + }, +}); From 4aab57c1e12e85c5f7e739437b18f452e1022b16 Mon Sep 17 00:00:00 2001 From: Trong Do Date: Mon, 3 Aug 2026 20:28:00 +0700 Subject: [PATCH 3/4] [FE] Problem 3: Messy React --- src/problem3/README.md | 294 +++++++++++++++++++++++++ src/problem3/WalletPage.refactored.tsx | 92 ++++++++ 2 files changed, 386 insertions(+) create mode 100644 src/problem3/README.md create mode 100644 src/problem3/WalletPage.refactored.tsx diff --git a/src/problem3/README.md b/src/problem3/README.md new file mode 100644 index 0000000000..c134f4fe3a --- /dev/null +++ b/src/problem3/README.md @@ -0,0 +1,294 @@ +# Problem 3 — Messy React + +## Issues and anti-patterns + +### 1. The declared data type does not match the code + +`WalletBalance` declares only `currency` and `amount`, but the implementation +reads `balance.blockchain`. + +This is a compile-time error under normal TypeScript settings. The interface +must include `blockchain`, ideally using a finite union rather than `string`. + +--- + +### 2. `getPriority` accepts `any` + +```tsx +const getPriority = (blockchain: any): number => ... +``` + +`any` disables type checking and allows unsupported values to pass through. +Use a `Blockchain` union and a typed lookup table. + +--- + +### 3. `getPriority` is recreated on every render + +The function does not use component state or props, so defining it inside the +component allocates a new function every render. + +Move the priority map and helper outside the component. + +--- + +### 4. Priority is recalculated repeatedly during sorting + +The comparator calls `getPriority` for both items on every comparison. +Sorting is `O(n log n)`, so the same balance priority can be recalculated many +times. + +Compute each balance's priority once before sorting, then sort by the cached +value. This is a decorate-sort-undecorate pattern. + +--- + +### 5. The filter references an undefined variable + +```tsx +if (lhsPriority > -99) +``` + +`lhsPriority` is not defined in the filter callback. The intended variable +appears to be `balancePriority`. + +This prevents the code from compiling. + +--- + +### 6. The amount filter is probably inverted + +The original filter keeps balances when: + +```tsx +balance.amount <= 0 +``` + +A wallet list normally displays positive balances and excludes zero or +negative balances. The intended condition is likely: + +```tsx +balance.amount > 0 +``` + +The refactor also rejects non-finite amounts. + +--- + +### 7. A magic sentinel value is used + +`-99` is used to mean "unsupported blockchain". Magic values make the logic +harder to understand and easier to break. + +A typed set of supported blockchains removes the need for this sentinel. +Another valid design would return `null` for unsupported chains. + +--- + +### 8. The sort comparator does not return `0` + +When priorities are equal, the comparator returns `undefined`. + +A comparator should always return a number. Returning `0` preserves equality; +a secondary currency comparison can also provide deterministic ordering. + +--- + +### 9. The `useMemo` dependency list is wrong + +The sorted list does not use `prices`, but `prices` is included: + +```tsx +[balances, prices] +``` + +This causes unnecessary re-sorting whenever prices change. + +In the refactor, sorting, formatting, and USD calculation are deliberately +combined into one memoized derivation, so both dependencies are genuinely used. + +--- + +### 10. `formattedBalances` is calculated and then ignored + +The code creates: + +```tsx +const formattedBalances = ... +``` + +but maps `sortedBalances` when rendering. + +This wastes one full `O(n)` pass and means the `formatted` value is never +actually used. + +--- + +### 11. The render map lies to TypeScript + +```tsx +sortedBalances.map((balance: FormattedWalletBalance) => ...) +``` + +Elements of `sortedBalances` are `WalletBalance`, not +`FormattedWalletBalance`. Adding a callback parameter annotation does not +transform the data. + +Consequently, `balance.formatted` is missing and will be `undefined` at +runtime even if the type error is suppressed. + +--- + +### 12. Derived work runs in separate passes + +The original code performs: + +1. filter; +2. sort; +3. formatting map; +4. render map; +5. USD calculation during render. + +Some passes are necessary, but the unused formatting pass is pure waste. +The refactor creates one memoized display model and keeps JSX rendering simple. + +--- + +### 13. Missing prices can produce `NaN` + +```tsx +prices[balance.currency] * balance.amount +``` + +If no price exists for a currency, the result is `NaN`. + +The refactor uses: + +```tsx +const price = prices[balance.currency] ?? 0; +``` + +A production UI might instead omit the row or display an unavailable-price +state, depending on product requirements. + +--- + +### 14. Array indexes are used as React keys + +```tsx +key={index} +``` + +After filtering or sorting, indexes can refer to different balances. React may +reuse the wrong component instance and preserve incorrect local state. + +Use a stable identity such as: + +```tsx +key={`${balance.blockchain}:${balance.currency}`} +``` + +A backend-provided wallet-balance ID would be even better. + +--- + +### 15. `children` is removed and never rendered + +```tsx +const { children, ...rest } = props; +``` + +The component silently discards `children`. + +Either do not accept/destructure children or render them intentionally. + +--- + +### 16. `BoxProps` are spread onto a plain `div` + +If `BoxProps` comes from Material UI, it may contain props such as `sx` that +are meaningful to `` but invalid on a native `
`. + +The refactor renders ``. + +--- + +### 17. `React.FC` plus `(props: Props)` is redundant + +Both annotate the same props type. A plain function is simpler and avoids +unnecessary `React.FC` semantics: + +```tsx +function WalletPage(props: Props) { ... } +``` + +--- + +### 18. The empty `Props` interface adds no value + +```tsx +interface Props extends BoxProps {} +``` + +When no additional fields are needed, a type alias is clearer: + +```tsx +type Props = BoxProps; +``` + +The refactor keeps an interface only because it explicitly documents +`children`; a type alias would also be valid. + +--- + +### 19. `toFixed()` has an implicit precision + +Calling `toFixed()` without an argument rounds to zero decimal places. That is +usually inappropriate for token balances and may hide meaningful fractional +amounts. + +Use an explicit precision or `Intl.NumberFormat`. + +--- + +### 20. Formatting and USD calculations are mixed into rendering + +Keeping calculation logic inside JSX makes rendering harder to read and test. + +The refactor prepares a typed `DisplayWalletBalance` model before JSX. + +--- + +## Complexity + +Let `n` be the number of balances. + +Original intended complexity: + +```text +filter: O(n) +sort: O(n log n), with repeated priority calls +unused formatting: O(n) +render mapping: O(n) +``` + +Refactored complexity remains asymptotically `O(n log n)` because ordering +requires sorting, but it: + +- computes each priority once; +- removes the unused formatting pass; +- moves display calculations out of JSX; +- avoids unnecessary re-sorting dependencies; +- produces stable keys and valid types. + +## Refactored source + +See: + +```text +WalletPage.refactored.tsx +``` + +The exact imports for `useWalletBalances`, `usePrices`, `WalletRow`, and +`classes` should be added according to the skeletal repository's existing +project structure. diff --git a/src/problem3/WalletPage.refactored.tsx b/src/problem3/WalletPage.refactored.tsx new file mode 100644 index 0000000000..ca7d274713 --- /dev/null +++ b/src/problem3/WalletPage.refactored.tsx @@ -0,0 +1,92 @@ +import { useMemo, type ReactNode } from "react"; +import { Box, type BoxProps } from "@mui/material"; + +interface WalletBalance { + currency: string; + blockchain: Blockchain; + amount: number; +} + +type Blockchain = + | "Osmosis" + | "Ethereum" + | "Arbitrum" + | "Zilliqa" + | "Neo"; + +interface Props extends BoxProps { + children?: ReactNode; +} + +interface DisplayWalletBalance extends WalletBalance { + formattedAmount: string; + usdValue: number; + priority: number; +} + +const BLOCKCHAIN_PRIORITY: Readonly> = { + Osmosis: 100, + Ethereum: 50, + Arbitrum: 30, + Zilliqa: 20, + Neo: 20, +}; + +const amountFormatter = new Intl.NumberFormat("en-US", { + minimumFractionDigits: 0, + maximumFractionDigits: 6, +}); + +function getPriority(blockchain: Blockchain): number { + return BLOCKCHAIN_PRIORITY[blockchain]; +} + +export function WalletPage({ children, ...boxProps }: Props) { + const balances = useWalletBalances(); + const prices = usePrices(); + + const displayBalances = useMemo(() => { + return balances + // Decorate once so priority is not recalculated during every sort comparison. + .map((balance) => ({ + ...balance, + priority: getPriority(balance.blockchain), + })) + .filter( + (balance) => + balance.priority >= 0 && + Number.isFinite(balance.amount) && + balance.amount > 0, + ) + .sort( + (left, right) => + right.priority - left.priority || + left.currency.localeCompare(right.currency), + ) + .map((balance) => { + const price = prices[balance.currency] ?? 0; + + return { + ...balance, + formattedAmount: amountFormatter.format(balance.amount), + usdValue: price * balance.amount, + }; + }); + }, [balances, prices]); + + return ( + + {displayBalances.map((balance) => ( + + ))} + + {children} + + ); +} From f8c7a3b0c565fcdabc98789f526bf462ed7ed4ea Mon Sep 17 00:00:00 2001 From: Trong Do Date: Mon, 3 Aug 2026 20:56:27 +0700 Subject: [PATCH 4/4] [FE] Problem 1: Three ways to sum to n (Fix separate pure functions from audit logging) --- src/problem1/README.md | 170 ++-- src/problem1/audit.js | 898 +++++++++++++----- src/problem1/index.js | 409 ++------ src/problem1/logs/.gitignore | 2 - ...-53-29-937Z-pid-37732-d166195fda-n-5.jsonl | 100 ++ ...13-53-29-937Z-pid-37732-d166195fda-n-5.log | 519 ++++++++++ ...37Z-pid-37732-d166195fda-n-5.manifest.json | 38 + .../stress-test-2026-08-03T13-54-01-915Z.json | 213 +++++ .../stress-test-2026-08-03T13-54-01-915Z.log | 64 ++ src/problem1/stress-test.js | 105 +- 10 files changed, 1884 insertions(+), 634 deletions(-) delete mode 100644 src/problem1/logs/.gitignore create mode 100644 src/problem1/logs/audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.jsonl create mode 100644 src/problem1/logs/audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.log create mode 100644 src/problem1/logs/audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.manifest.json create mode 100644 src/problem1/logs/stress-test-2026-08-03T13-54-01-915Z.json create mode 100644 src/problem1/logs/stress-test-2026-08-03T13-54-01-915Z.log diff --git a/src/problem1/README.md b/src/problem1/README.md index a7587bc68d..ff9ffcb89b 100644 --- a/src/problem1/README.md +++ b/src/problem1/README.md @@ -1,4 +1,16 @@ -# Problem 1 — Complete quality suite +# Problem 1 — Three pure functions with a separate audit layer + +## Design + +The implementation and audit responsibilities are deliberately separated: + +```text +index.js → three pure sum functions only +audit.js → calls the functions, builds independent proofs, and writes logs +``` + +`index.js` does not know about log files, hashes, manifests, callbacks, or the +CLI. Each exported solution accepts exactly one argument: `n`. ## Files @@ -13,6 +25,48 @@ src/problem1/ └── logs/ ``` +## The three functions in `index.js` + +### A. Closed-form arithmetic-series formula + +```javascript +sum_to_n_a(n) +``` + +Uses `n(n + 1) / 2`, dividing the even factor before multiplication. + +```text +Time: O(1) +Space: O(1) +``` + +### B. Fast matrix exponentiation + +```javascript +sum_to_n_b(n) +``` + +Uses a fixed 3 × 3 transition matrix and exponentiation by squaring. + +```text +Time: O(log |n|) +Space: O(1) +``` + +### C. Symmetric pairing loop + +```javascript +sum_to_n_c(n) +``` + +Pairs the smallest and largest values. The actual implementation performs the +loop so it remains computationally distinct from solution A. + +```text +Time: O(|n|) +Space: O(1) +``` + ## Normal execution ```javascript @@ -23,9 +77,39 @@ const { } = require("./index"); console.log(sum_to_n_a(5)); // 15 +console.log(sum_to_n_b(5)); // 15 +console.log(sum_to_n_c(5)); // 15 +``` + +Negative input follows this documented convention: + +```javascript +sum_to_n_a(-4); // -10 = -1 + -2 + -3 + -4 ``` -## Mathematical audit +## Separate audit function + +`audit.js` exports: + +```javascript +auditAlgorithm({ key, n, algorithm, writeEvent }) +``` + +For one algorithm it: + +1. calls the pure function from `index.js`; +2. records the returned value; +3. generates a separate mathematical proof inside `audit.js`; +4. compares the implementation result with the proof result; +5. sends structured events to the provided writer. + +The session-level helper is: + +```javascript +runAudit({ n, selectedAlgorithm }) +``` + +## Run an audit From `src/problem1`: @@ -33,7 +117,15 @@ From `src/problem1`: node audit.js 5 all ``` -Generated files: +Or one implementation: + +```bat +node audit.js 5 a +node audit.js 5 b +node audit.js 5 c +``` + +Generated evidence: ```text logs\audit-....log @@ -58,70 +150,40 @@ The JSONL evidence uses a SHA-256 hash chain. Every event contains: node verify-audit.js logs\.manifest.json ``` -Expected: +Expected result: ```text Audit integrity: VALID ``` -Any changed, removed, reordered, duplicated, or truncated JSONL event is detected. +Changed, removed, reordered, duplicated, or truncated evidence is detected. -## Run complete testing +## Run tests -Recommended: +Recommended before commit: ```bat node stress-test.js standard ``` -Or: +Quick mode: ```bat -run-stress.cmd standard -``` - -Modes: - -```text -smoke quick local validation -standard recommended before commit -heavy high-volume validation +node stress-test.js smoke ``` -Deterministic seed: - -```bat -node stress-test.js standard 20260803 -``` - -## Coverage - -The suite includes: - -1. Valid positive, negative, zero, and boundary cases. -2. Exhaustive signed integer ranges. -3. Deterministic random tests. -4. BigInt independent oracle comparisons. -5. Precision tests near `Number.MAX_SAFE_INTEGER`. -6. Invalid type and non-integer rejection. -7. Out-of-contract result-overflow rejection. -8. Mathematical invariant testing. -9. Audit callback schema checks. -10. Logger failure propagation. -11. Audit CLI success path. -12. Audit CLI invalid argument paths. -13. File-system failure injection. -14. Algorithm failure injection and partial error audit. -15. Mutation-test sensitivity. -16. Audit tamper detection. -17. Audit truncation detection. -18. Concurrent audit isolation. -19. Subprocess timeout detection. -20. Throughput and long-loop performance checks. - -Reports are written to: - -```text -logs\stress-test-....log -logs\stress-test-....json -``` +The suite verifies, among other cases: + +- exact results against a BigInt oracle; +- positive, zero, negative, and boundary inputs; +- invalid input rejection; +- all three functions expose one declared parameter; +- audit instrumentation is owned by `audit.js` rather than `index.js`; +- independent proof comparison; +- audit CLI behavior; +- file-system failures; +- injected algorithm failures; +- mutation sensitivity; +- evidence tampering and truncation; +- concurrent audit isolation; +- performance and long-loop behavior. diff --git a/src/problem1/audit.js b/src/problem1/audit.js index 7afbca5a63..a98837735c 100644 --- a/src/problem1/audit.js +++ b/src/problem1/audit.js @@ -1,18 +1,19 @@ "use strict"; /** - * Separate mathematical audit runner. + * Separate audit layer for Problem 1. + * + * index.js contains only pure implementations. This file wraps those + * implementations, records what was called, builds an independent proof for + * each result, and writes tamper-evident logs. * * CLI: * node audit.js 5 all * node audit.js -4 a * - * Environment: - * PROBLEM1_LOG_DIR= - * * Output: * *.log Human-readable proof - * *.jsonl Hash-chained raw evidence + * *.jsonl SHA-256 hash-chained evidence * *.manifest.json Integrity manifest */ @@ -20,23 +21,468 @@ const crypto = require("node:crypto"); const fs = require("node:fs"); const path = require("node:path"); -const defaultImplementations = require("./index"); +const { + MAX_SAFE_SUM_N, + sum_to_n_a, + sum_to_n_b, + sum_to_n_c, +} = require("./index"); + +function validateAuditInput(n) { + if (!Number.isSafeInteger(n)) { + throw new TypeError("n must be a safe integer"); + } + + if (Math.abs(n) > MAX_SAFE_SUM_N) { + throw new RangeError( + `|n| must be <= ${MAX_SAFE_SUM_N} so the result remains a safe integer`, + ); + } +} + +function signedResult(n, positiveValue) { + return n < 0 ? -positiveValue : positiveValue; +} + +function identityMatrix3() { + return [ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + ]; +} + +function multiply3x3WithProof(left, right, emit, context) { + const result = [ + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ]; + + emit({ + algorithm: "B_LINEAR_ALGEBRA", + action: "MATRIX_MULTIPLICATION_STARTED", + data: { + ...context, + left, + right, + }, + }); + + for (let row = 0; row < 3; row += 1) { + for (let column = 0; column < 3; column += 1) { + const terms = []; + + for (let index = 0; index < 3; index += 1) { + const product = left[row][index] * right[index][column]; + result[row][column] += product; + terms.push({ + leftValue: left[row][index], + rightValue: right[index][column], + product, + }); + } + + emit({ + algorithm: "B_LINEAR_ALGEBRA", + action: "MATRIX_CELL_CALCULATED", + data: { + ...context, + row, + column, + terms, + cellValue: result[row][column], + }, + }); + } + } + + emit({ + algorithm: "B_LINEAR_ALGEBRA", + action: "MATRIX_MULTIPLICATION_COMPLETED", + data: { + ...context, + result, + }, + }); + + return result; +} + +/** + * Independent proof for solution A. + * + * This calculation lives in audit.js, not index.js. The production function is + * called separately and its returned value is compared with this proof result. + */ +function proveCombinatorics(n, emit) { + const algorithm = "A_COMBINATORICS"; + const magnitude = Math.abs(n); + let firstFactor = magnitude; + let secondFactor = magnitude + 1; + + emit({ algorithm, action: "INPUT_RECEIVED", data: { n } }); + emit({ + algorithm, + action: "INPUT_VALIDATED", + data: { + n, + isSafeInteger: true, + isWithinSafeResultRange: true, + }, + }); + emit({ + algorithm, + action: "MAGNITUDE_CALCULATED", + data: { expression: "|n|", magnitude }, + }); + emit({ + algorithm, + action: "COMBINATION_IDENTITY_APPLIED", + data: { + identity: "S(n) = n(n + 1) / 2", + firstFactor, + secondFactor, + divisor: 2, + }, + }); + + if (firstFactor % 2 === 0) { + const before = firstFactor; + firstFactor /= 2; + emit({ + algorithm, + action: "EVEN_FACTOR_DIVIDED", + data: { + factor: "firstFactor", + before, + divisor: 2, + after: firstFactor, + }, + }); + } else { + const before = secondFactor; + secondFactor /= 2; + emit({ + algorithm, + action: "EVEN_FACTOR_DIVIDED", + data: { + factor: "secondFactor", + before, + divisor: 2, + after: secondFactor, + }, + }); + } + + const positiveValue = firstFactor * secondFactor; + const result = signedResult(n, positiveValue); + + emit({ + algorithm, + action: "FACTORS_MULTIPLIED", + data: { firstFactor, secondFactor, positiveValue }, + }); + emit({ + algorithm, + action: "SIGN_RESTORED", + data: { originalInput: n, positiveValue, result }, + }); + emit({ + algorithm, + action: "PROOF_COMPLETED", + data: { + result, + complexity: { time: "O(1)", space: "O(1)" }, + }, + }); + + return result; +} + +/** + * Independent proof for solution B using the same mathematical state model, + * but implemented entirely in the audit layer so index.js remains uninstrumented. + */ +function proveLinearAlgebra(n, emit) { + const algorithm = "B_LINEAR_ALGEBRA"; + const magnitude = Math.abs(n); + const transitionMatrix = [ + [1, 1, 1], + [0, 1, 1], + [0, 0, 1], + ]; + + emit({ algorithm, action: "INPUT_RECEIVED", data: { n } }); + emit({ + algorithm, + action: "INPUT_VALIDATED", + data: { + n, + isSafeInteger: true, + isWithinSafeResultRange: true, + }, + }); + emit({ + algorithm, + action: "MAGNITUDE_CALCULATED", + data: { expression: "|n|", magnitude }, + }); + emit({ + algorithm, + action: "STATE_MODEL_DEFINED", + data: { + stateVector: ["sum_k", "k", "1"], + initialVector: [0, 0, 1], + transitionMatrix, + }, + }); + + let exponent = magnitude; + let resultMatrix = identityMatrix3(); + let baseMatrix = transitionMatrix; + let round = 0; + + emit({ + algorithm, + action: "MATRIX_POWER_INITIALIZED", + data: { + targetPower: magnitude, + exponent, + resultMatrix, + baseMatrix, + }, + }); + + while (exponent > 0) { + round += 1; + + emit({ + algorithm, + action: "POWER_ROUND_STARTED", + data: { + round, + exponent, + isOdd: exponent % 2 === 1, + }, + }); + + if (exponent % 2 === 1) { + resultMatrix = multiply3x3WithProof( + resultMatrix, + baseMatrix, + emit, + { round, purpose: "ACCUMULATE_RESULT" }, + ); + + emit({ + algorithm, + action: "RESULT_MATRIX_UPDATED", + data: { round, resultMatrix }, + }); + } else { + emit({ + algorithm, + action: "RESULT_MULTIPLICATION_SKIPPED", + data: { round, reason: "Exponent is even" }, + }); + } + + const previousExponent = exponent; + exponent = Math.floor(exponent / 2); + + emit({ + algorithm, + action: "EXPONENT_HALVED", + data: { + round, + before: previousExponent, + after: exponent, + }, + }); + + if (exponent > 0) { + baseMatrix = multiply3x3WithProof( + baseMatrix, + baseMatrix, + emit, + { round, purpose: "SQUARE_BASE" }, + ); + + emit({ + algorithm, + action: "BASE_MATRIX_SQUARED", + data: { round, baseMatrix }, + }); + } else { + emit({ + algorithm, + action: "FINAL_BASE_SQUARE_SKIPPED", + data: { + round, + reason: "No exponent bits remain", + }, + }); + } + } + + const positiveValue = resultMatrix[0][2]; + const result = signedResult(n, positiveValue); + + emit({ + algorithm, + action: "MATRIX_POWER_COMPLETED", + data: { + power: magnitude, + poweredMatrix: resultMatrix, + }, + }); + emit({ + algorithm, + action: "INITIAL_VECTOR_APPLIED", + data: { + poweredMatrix: resultMatrix, + initialVector: [0, 0, 1], + resultingVector: [ + resultMatrix[0][2], + resultMatrix[1][2], + resultMatrix[2][2], + ], + positiveValue, + }, + }); + emit({ + algorithm, + action: "SIGN_RESTORED", + data: { originalInput: n, positiveValue, result }, + }); + emit({ + algorithm, + action: "PROOF_COMPLETED", + data: { + result, + complexity: { time: "O(log |n|)", space: "O(1)" }, + }, + }); + + return result; +} + +/** + * Independent O(1) proof for solution C. + * + * index.js executes the actual pairing loop. The audit proves the same result + * from pairCount × pairSum (+ middle value), avoiding a second large loop just + * for logging. + */ +function proveSymmetricPairing(n, emit) { + const algorithm = "C_PROBABILITY_SYMMETRY"; + const magnitude = Math.abs(n); + const pairCount = Math.floor(magnitude / 2); + const constantPairSum = magnitude + 1; + const pairedTotal = pairCount * constantPairSum; + const middleValue = magnitude % 2 === 1 + ? (magnitude + 1) / 2 + : 0; + const positiveValue = pairedTotal + middleValue; + const result = signedResult(n, positiveValue); + + emit({ algorithm, action: "INPUT_RECEIVED", data: { n } }); + emit({ + algorithm, + action: "INPUT_VALIDATED", + data: { + n, + isSafeInteger: true, + isWithinSafeResultRange: true, + }, + }); + emit({ + algorithm, + action: "MAGNITUDE_CALCULATED", + data: { expression: "|n|", magnitude }, + }); + emit({ + algorithm, + action: "ANTITHETIC_MODEL_DEFINED", + data: { + sampleSpace: `{1, 2, ..., ${magnitude}}`, + mapping: "x ↔ n + 1 - x", + pairCount, + constantPairSum, + }, + }); + emit({ + algorithm, + action: "PAIRED_TOTAL_CALCULATED", + data: { + pairCount, + constantPairSum, + expression: `${pairCount} × ${constantPairSum}`, + pairedTotal, + }, + }); + + if (middleValue > 0) { + emit({ + algorithm, + action: "MIDDLE_VALUE_ADDED", + data: { + middleValue, + pairedTotal, + positiveValue, + }, + }); + } else { + emit({ + algorithm, + action: "MIDDLE_VALUE_NOT_REQUIRED", + data: { reason: "The number of values is even" }, + }); + } + + emit({ + algorithm, + action: "SIGN_RESTORED", + data: { originalInput: n, positiveValue, result }, + }); + emit({ + algorithm, + action: "PROOF_COMPLETED", + data: { + result, + implementationComplexity: { + time: "O(|n|)", + space: "O(1)", + }, + auditProofComplexity: { + time: "O(1)", + space: "O(1)", + }, + }, + }); + + return result; +} const DEFAULT_ALGORITHMS = { a: { name: "A_COMBINATORICS", - label: "Combinatorics", - run: defaultImplementations.sum_to_n_a, + label: "Closed-form arithmetic series", + run: sum_to_n_a, + prove: proveCombinatorics, }, b: { name: "B_LINEAR_ALGEBRA", - label: "Linear algebra", - run: defaultImplementations.sum_to_n_b, + label: "Fast matrix exponentiation", + run: sum_to_n_b, + prove: proveLinearAlgebra, }, c: { name: "C_PROBABILITY_SYMMETRY", - label: "Probability symmetry", - run: defaultImplementations.sum_to_n_c, + label: "Symmetric pairing", + run: sum_to_n_c, + prove: proveSymmetricPairing, }, }; @@ -49,10 +495,7 @@ function parseArguments(argv) { } const n = Number(rawN); - - if (!Number.isSafeInteger(n)) { - throw new TypeError("n must be a safe integer"); - } + validateAuditInput(n); if ( selectedAlgorithm !== "all" && @@ -92,7 +535,6 @@ function formatMatrix(matrix) { const cells = row.map((value, column) => String(value).padStart(widths[column]), ); - return `│ ${cells.join(" ")} │`; }) .join("\n"); @@ -116,197 +558,150 @@ function writeHeading(filepath, title) { function describeEvent(event) { const { algorithm, action, data } = event; - switch (`${algorithm}:${action}`) { - case "AUDIT_SESSION:SESSION_STARTED": - return [ - `Input n = ${data.n}`, - `Selected algorithms = ${data.selectedAlgorithm}`, - ]; - - case "AUDIT_SESSION:ALGORITHM_STARTED": - return [`Start ${data.algorithm}`]; - - case "AUDIT_SESSION:ALGORITHM_COMPLETED": - return [`${data.algorithm} returned ${data.result}`]; - - case "AUDIT_SESSION:RESULTS_CROSS_CHECKED": - return [ - `Results = ${JSON.stringify(data.results)}`, - `Implementations agree = ${data.consistent}`, - ]; - - case "AUDIT_SESSION:INDEPENDENT_REFERENCE_CALCULATED": - return [ - `Independent BigInt reference = ${data.reference}`, - `Every result matches reference = ${data.matches}`, - ]; - - case "AUDIT_SESSION:SESSION_PASSED": - return ["Audit status = PASSED"]; - - case "AUDIT_SESSION:SESSION_FAILED": - return ["Audit status = FAILED"]; - - case "AUDIT_SESSION:SESSION_ERROR": - return [ - `Audit status = ERROR`, - `${data.error.name}: ${data.error.message}`, - ]; + if (algorithm === "AUDIT_SESSION") { + switch (action) { + case "SESSION_STARTED": + return [ + `Input n = ${data.n}`, + `Selected algorithms = ${data.selectedAlgorithm}`, + ]; + case "ALGORITHM_STARTED": + return [`Start ${data.algorithm}`]; + case "IMPLEMENTATION_CALLED": + return [`Call index.js export ${data.functionName}(${data.n})`]; + case "IMPLEMENTATION_RETURNED": + return [`index.js returned ${data.result}`]; + case "IMPLEMENTATION_VERIFIED": + return [ + `Implementation result = ${data.implementationResult}`, + `Independent proof result = ${data.proofResult}`, + `Match = ${data.matches}`, + ]; + case "ALGORITHM_COMPLETED": + return [`${data.algorithm} audit completed`]; + case "RESULTS_CROSS_CHECKED": + return [ + `Results = ${JSON.stringify(data.results)}`, + `All implementations agree = ${data.consistent}`, + ]; + case "INDEPENDENT_REFERENCE_CALCULATED": + return [ + `BigInt reference = ${data.reference}`, + `All results match reference = ${data.matches}`, + ]; + case "SESSION_PASSED": + return ["Audit status = PASSED"]; + case "SESSION_FAILED": + return ["Audit status = FAILED"]; + case "SESSION_ERROR": + return [ + "Audit status = ERROR", + `${data.error.name}: ${data.error.message}`, + ]; + default: + return [JSON.stringify(data)]; + } + } - case "A_COMBINATORICS:INPUT_RECEIVED": - case "B_LINEAR_ALGEBRA:INPUT_RECEIVED": - case "C_PROBABILITY_SYMMETRY:INPUT_RECEIVED": + switch (action) { + case "INPUT_RECEIVED": return [`Receive n = ${data.n}`]; - - case "A_COMBINATORICS:INPUT_VALIDATED": - case "B_LINEAR_ALGEBRA:INPUT_VALIDATED": - case "C_PROBABILITY_SYMMETRY:INPUT_VALIDATED": + case "INPUT_VALIDATED": return [ `Input is a safe integer = ${data.isSafeInteger}`, `Result range is safe = ${data.isWithinSafeResultRange}`, ]; - - case "A_COMBINATORICS:MAGNITUDE_CALCULATED": - case "B_LINEAR_ALGEBRA:MAGNITUDE_CALCULATED": - case "C_PROBABILITY_SYMMETRY:MAGNITUDE_CALCULATED": + case "MAGNITUDE_CALCULATED": return [`|n| = ${data.magnitude}`]; - - case "A_COMBINATORICS:COMBINATION_IDENTITY_APPLIED": + case "COMBINATION_IDENTITY_APPLIED": return [ - `S(n) = C(n + 1, 2) = n(n + 1)/2`, - `Substitute: ${data.leftFactor} × ${data.rightFactor} ÷ ${data.divisor}`, + data.identity, + `${data.firstFactor} × ${data.secondFactor} ÷ ${data.divisor}`, ]; - - case "A_COMBINATORICS:EVEN_FACTOR_DIVIDED": + case "EVEN_FACTOR_DIVIDED": return [ `${data.factor}: ${data.before} ÷ ${data.divisor} = ${data.after}`, ]; - - case "A_COMBINATORICS:FACTORS_MULTIPLIED": - return [ - `${data.leftFactor} × ${data.rightFactor} = ${data.positiveSum}`, - ]; - - case "A_COMBINATORICS:SIGN_RESTORED": - case "B_LINEAR_ALGEBRA:SIGN_RESTORED": - case "C_PROBABILITY_SYMMETRY:SIGN_RESTORED": + case "FACTORS_MULTIPLIED": return [ - `Restore sign: ${data.positiveValue} → ${data.result}`, + `${data.firstFactor} × ${data.secondFactor} = ${data.positiveValue}`, ]; - - case "A_COMBINATORICS:COMPLETED": - case "B_LINEAR_ALGEBRA:COMPLETED": - case "C_PROBABILITY_SYMMETRY:COMPLETED": - return [ - `Result = ${data.result}`, - `Complexity: ${data.complexity.time} time, ${data.complexity.space} space`, - ]; - - case "B_LINEAR_ALGEBRA:STATE_MODEL_DEFINED": + case "STATE_MODEL_DEFINED": return [ `State vector = ${formatVector(data.stateVector)}`, `Initial vector = ${formatVector(data.initialVector)}`, - `Transition matrix:`, + "Transition matrix:", formatMatrix(data.transitionMatrix), ]; - - case "B_LINEAR_ALGEBRA:MATRIX_POWER_INITIALIZED": + case "MATRIX_POWER_INITIALIZED": return [ - `Compute M^${data.targetPower} using exponentiation by squaring`, - `Identity result matrix:`, + `Compute M^${data.targetPower} by exponentiation by squaring`, + "Initial result matrix:", formatMatrix(data.resultMatrix), - `Base matrix:`, + "Initial base matrix:", formatMatrix(data.baseMatrix), ]; - - case "B_LINEAR_ALGEBRA:POWER_ROUND_STARTED": + case "POWER_ROUND_STARTED": return [ `Round ${data.round}: exponent ${data.exponent} is ${data.isOdd ? "odd" : "even"}`, ]; - - case "B_LINEAR_ALGEBRA:ODD_EXPONENT_BRANCH": - return [`${data.operation}`]; - - case "B_LINEAR_ALGEBRA:EVEN_EXPONENT_BRANCH": - return ["Skip result multiplication"]; - - case "B_LINEAR_ALGEBRA:MATRIX_MULTIPLICATION_STARTED": + case "MATRIX_MULTIPLICATION_STARTED": return [ `${data.purpose}, round ${data.round}`, - `Left:`, + "Left:", formatMatrix(data.left), - `Right:`, + "Right:", formatMatrix(data.right), ]; - - case "B_LINEAR_ALGEBRA:MATRIX_CELL_CALCULATED": { + case "MATRIX_CELL_CALCULATED": { const expression = data.terms .map((term) => `${term.leftValue}×${term.rightValue}`) .join(" + "); - return [ `Cell [${data.row + 1},${data.column + 1}] = ${expression} = ${data.cellValue}`, ]; } - - case "B_LINEAR_ALGEBRA:MATRIX_MULTIPLICATION_COMPLETED": - return [ - `${data.purpose} result:`, - formatMatrix(data.result), - ]; - - case "B_LINEAR_ALGEBRA:RESULT_MATRIX_UPDATED": - return [ - `Accumulated result:`, - formatMatrix(data.resultMatrix), - ]; - - case "B_LINEAR_ALGEBRA:BASE_MATRIX_SQUARED": - return [ - `Squared base:`, - formatMatrix(data.baseMatrix), - ]; - - case "B_LINEAR_ALGEBRA:EXPONENT_HALVED": - return [ - `floor(${data.before}/2) = ${data.after}`, - ]; - - case "B_LINEAR_ALGEBRA:MATRIX_POWER_COMPLETED": - return [ - `M^${data.power}:`, - formatMatrix(data.poweredMatrix), - ]; - - case "B_LINEAR_ALGEBRA:INITIAL_VECTOR_APPLIED": + case "MATRIX_MULTIPLICATION_COMPLETED": + return [`${data.purpose} result:`, formatMatrix(data.result)]; + case "RESULT_MATRIX_UPDATED": + return ["Accumulated result:", formatMatrix(data.resultMatrix)]; + case "RESULT_MULTIPLICATION_SKIPPED": + case "FINAL_BASE_SQUARE_SKIPPED": + return [data.reason]; + case "EXPONENT_HALVED": + return [`floor(${data.before}/2) = ${data.after}`]; + case "BASE_MATRIX_SQUARED": + return ["Squared base:", formatMatrix(data.baseMatrix)]; + case "MATRIX_POWER_COMPLETED": + return [`M^${data.power}:`, formatMatrix(data.poweredMatrix)]; + case "INITIAL_VECTOR_APPLIED": return [ `${formatVector(data.initialVector)} → ${formatVector(data.resultingVector)}`, - `First component is the sum = ${data.positiveSum}`, + `First component = ${data.positiveValue}`, ]; - - case "C_PROBABILITY_SYMMETRY:ANTITHETIC_MODEL_DEFINED": + case "ANTITHETIC_MODEL_DEFINED": return [ `Sample space ${data.sampleSpace}`, `Mapping ${data.mapping}`, `Pair count = ${data.pairCount}`, - `Every pair sums to ${data.constantPairSum}`, + `Each pair sums to ${data.constantPairSum}`, ]; - - case "C_PROBABILITY_SYMMETRY:PAIR_ACCUMULATED": + case "PAIRED_TOTAL_CALCULATED": return [ - `Pair ${data.pairIndex}: ${data.left} + ${data.right} = ${data.pairSum}`, - `${data.totalBefore} + ${data.pairSum} = ${data.totalAfter}`, + `${data.expression} = ${data.pairedTotal}`, ]; - - case "C_PROBABILITY_SYMMETRY:MIDDLE_VALUE_ACCUMULATED": + case "MIDDLE_VALUE_ADDED": return [ - `Middle value ${data.middleValue}`, - `${data.totalBefore} + ${data.middleValue} = ${data.totalAfter}`, + `${data.pairedTotal} + middle ${data.middleValue} = ${data.positiveValue}`, ]; - - case "C_PROBABILITY_SYMMETRY:MIDDLE_VALUE_NOT_REQUIRED": + case "MIDDLE_VALUE_NOT_REQUIRED": return [data.reason]; - + case "SIGN_RESTORED": + return [ + `Restore sign: ${data.positiveValue} → ${data.result}`, + ]; + case "PROOF_COMPLETED": + return [`Proof result = ${data.result}`]; default: return [JSON.stringify(data)]; } @@ -330,7 +725,6 @@ function createOutputFiles(outputDirectory, n) { fs.mkdirSync(outputDirectory, { recursive: true }); const stat = fs.statSync(outputDirectory); - if (!stat.isDirectory()) { throw new Error(`Log path is not a directory: ${outputDirectory}`); } @@ -366,21 +760,16 @@ function createWriter(files, auditId, consoleOutput) { data: event.data ?? {}, previousHash, }; - const eventHash = sha256(JSON.stringify(unsignedEvent)); - const completeEvent = { - ...unsignedEvent, - eventHash, - }; - + const completeEvent = { ...unsignedEvent, eventHash }; const rawLine = JSON.stringify(completeEvent); + rawLines.push(rawLine); append(files.raw, rawLine); - append( files.human, `[${String(globalStep).padStart(4, "0")}] ` + - `${completeEvent.algorithm} :: ${completeEvent.action}`, + `${completeEvent.algorithm} :: ${completeEvent.action}`, ); for (const line of describeEvent(completeEvent)) { @@ -403,10 +792,9 @@ function createWriter(files, auditId, consoleOutput) { }, snapshot() { - const rawText = - rawLines.length === 0 - ? "" - : `${rawLines.join("\n")}\n`; + const rawText = rawLines.length === 0 + ? "" + : `${rawLines.join("\n")}\n`; return { eventCount: globalStep, @@ -434,20 +822,99 @@ function writeManifest(files, manifest) { } /** - * Programmatic API used by stress-test.js. + * Audit one function exported by index.js. + * + * This is the separation requested by the challenge review: + * 1. call the pure implementation; + * 2. generate an independent proof in audit.js; + * 3. log and compare both values. + */ +function auditAlgorithm({ key, n, algorithm, writeEvent }) { + if (!algorithm || typeof algorithm.run !== "function") { + throw new TypeError(`Algorithm ${key} must provide a run function`); + } + + if (typeof algorithm.prove !== "function") { + throw new TypeError(`Algorithm ${key} must provide a prove function`); + } + + if (typeof writeEvent !== "function") { + throw new TypeError("writeEvent must be a function"); + } + + writeEvent({ + algorithm: "AUDIT_SESSION", + action: "ALGORITHM_STARTED", + data: { key, algorithm: algorithm.name }, + }); + writeEvent({ + algorithm: "AUDIT_SESSION", + action: "IMPLEMENTATION_CALLED", + data: { + key, + algorithm: algorithm.name, + functionName: algorithm.run.name || `sum_to_n_${key}`, + n, + }, + }); + + const implementationResult = algorithm.run(n); + + writeEvent({ + algorithm: "AUDIT_SESSION", + action: "IMPLEMENTATION_RETURNED", + data: { + key, + algorithm: algorithm.name, + result: implementationResult, + }, + }); + + const proofResult = algorithm.prove(n, writeEvent); + const matches = implementationResult === proofResult; + + writeEvent({ + algorithm: "AUDIT_SESSION", + action: "IMPLEMENTATION_VERIFIED", + data: { + key, + algorithm: algorithm.name, + implementationResult, + proofResult, + matches, + }, + }); + writeEvent({ + algorithm: "AUDIT_SESSION", + action: "ALGORITHM_COMPLETED", + data: { + key, + algorithm: algorithm.name, + result: implementationResult, + proofResult, + matches, + }, + }); + + return { + result: implementationResult, + proofResult, + matches, + }; +} + +/** + * Programmatic session API used by stress-test.js and the CLI. */ function runAudit({ n, selectedAlgorithm = "all", outputDirectory = - process.env.PROBLEM1_LOG_DIR ?? - path.join(__dirname, "logs"), + process.env.PROBLEM1_LOG_DIR ?? path.join(__dirname, "logs"), algorithms = DEFAULT_ALGORITHMS, consoleOutput = true, } = {}) { - if (!Number.isSafeInteger(n)) { - throw new TypeError("n must be a safe integer"); - } + validateAuditInput(n); if ( selectedAlgorithm !== "all" && @@ -464,11 +931,13 @@ function runAudit({ files.human, [ "99TECH CODE CHALLENGE — PROBLEM 1", - "MATHEMATICAL PROOF AUDIT", + "SEPARATED IMPLEMENTATION AUDIT", `Audit ID: ${auditId}`, `Started: ${startedAt}`, `Input n: ${n}`, `Selection: ${selectedAlgorithm}`, + "index.js: pure implementations only", + "audit.js: wrapper, proof, logging, and integrity", "", ].join("\n"), "utf8", @@ -477,16 +946,14 @@ function runAudit({ const writer = createWriter(files, auditId, consoleOutput); const results = {}; + const proofChecks = {}; let status = "ERROR"; let errorData = null; writer.write({ algorithm: "AUDIT_SESSION", action: "SESSION_STARTED", - data: { - n, - selectedAlgorithm, - }, + data: { n, selectedAlgorithm }, }); try { @@ -499,47 +966,40 @@ function runAudit({ `${key.toUpperCase()}. ${algorithm.label.toUpperCase()}`, ); - writer.write({ - algorithm: "AUDIT_SESSION", - action: "ALGORITHM_STARTED", - data: { - key, - algorithm: algorithm.name, - }, - }); - - results[key] = algorithm.run( + const audited = auditAlgorithm({ + key, n, - (event) => writer.write(event), - ); - - writer.write({ - algorithm: "AUDIT_SESSION", - action: "ALGORITHM_COMPLETED", - data: { - key, - algorithm: algorithm.name, - result: results[key], - }, + algorithm, + writeEvent: (event) => writer.write(event), }); + + results[key] = audited.result; + proofChecks[key] = { + proofResult: audited.proofResult, + matches: audited.matches, + }; } const values = Object.values(results); const consistent = values.length <= 1 || values.every((value) => value === values[0]); + const allProofsMatch = Object.values(proofChecks) + .every((check) => check.matches); writer.write({ algorithm: "AUDIT_SESSION", action: "RESULTS_CROSS_CHECKED", data: { results, + proofChecks, consistent, + allProofsMatch, }, }); const reference = directBigIntReference(n); - const matches = values.every( + const matchesReference = values.every( (value) => BigInt(value) === reference, ); @@ -548,23 +1008,26 @@ function runAudit({ action: "INDEPENDENT_REFERENCE_CALCULATED", data: { reference: reference.toString(), - matches, + matches: matchesReference, }, }); - status = consistent && matches ? "PASSED" : "FAILED"; + status = consistent && allProofsMatch && matchesReference + ? "PASSED" + : "FAILED"; writer.write({ algorithm: "AUDIT_SESSION", - action: - status === "PASSED" - ? "SESSION_PASSED" - : "SESSION_FAILED", + action: status === "PASSED" + ? "SESSION_PASSED" + : "SESSION_FAILED", data: { status, results, + proofChecks, consistent, - matchesReference: matches, + allProofsMatch, + matchesReference, }, }); } catch (error) { @@ -581,6 +1044,7 @@ function runAudit({ status: "ERROR", error: errorData, partialResults: results, + partialProofChecks: proofChecks, }, }); } @@ -591,15 +1055,17 @@ function runAudit({ writeHeading(files.human, "AUDIT SUMMARY"); append(files.human, `Status: ${status}`); append(files.human, `Results: ${JSON.stringify(results)}`); + append(files.human, `Proof checks: ${JSON.stringify(proofChecks)}`); append(files.human, `Events: ${integrity.eventCount}`); append(files.human, `Final event hash: ${integrity.finalEventHash}`); append(files.human, `Raw evidence SHA-256: ${integrity.rawSha256}`); + if (errorData) { append(files.human, `Error: ${errorData.name}: ${errorData.message}`); } const manifest = writeManifest(files, { - schemaVersion: 1, + schemaVersion: 2, auditId, input: n, selectedAlgorithm, @@ -607,6 +1073,7 @@ function runAudit({ startedAt, completedAt, results, + proofChecks, error: errorData, eventCount: integrity.eventCount, finalEventHash: integrity.finalEventHash, @@ -621,6 +1088,7 @@ function runAudit({ return { status, results, + proofChecks, files, manifest, }; @@ -628,9 +1096,7 @@ function runAudit({ function runCli() { try { - const { n, selectedAlgorithm } = - parseArguments(process.argv); - + const { n, selectedAlgorithm } = parseArguments(process.argv); const report = runAudit({ n, selectedAlgorithm, @@ -658,7 +1124,11 @@ if (require.main === module) { module.exports = { DEFAULT_ALGORITHMS, + auditAlgorithm, parseArguments, + proveCombinatorics, + proveLinearAlgebra, + proveSymmetricPairing, runAudit, sha256, }; diff --git a/src/problem1/index.js b/src/problem1/index.js index 8b984db2b4..3174125ed8 100644 --- a/src/problem1/index.js +++ b/src/problem1/index.js @@ -3,20 +3,19 @@ /** * 99Tech Code Challenge — Problem 1 * - * Three mathematically distinct implementations: - * A. Combinatorics - * B. Linear algebra - * C. Probability symmetry - * - * Normal calls use the required signature: - * sum_to_n_a(n) - * - * A second optional callback is used only by audit.js: - * sum_to_n_a(n, event => ...) + * This file contains only the three requested implementations. + * Audit and logging are intentionally kept in audit.js so these functions + * remain small, deterministic, and easy to review. */ const MAX_SAFE_SUM_N = 134_217_727; +/** + * Validate the shared contract for all three implementations. + * + * Negative input follows this convention: + * sum_to_n(-4) = -1 + -2 + -3 + -4 = -10 + */ function validateInput(n) { if (!Number.isSafeInteger(n)) { throw new TypeError("n must be a safe integer"); @@ -29,394 +28,146 @@ function validateInput(n) { } } -function emit(audit, algorithm, action, data = {}) { - if (typeof audit === "function") { - audit({ algorithm, action, data }); - } -} - -function restoreSign(n, positiveValue, audit, algorithm) { - const result = n < 0 ? -positiveValue : positiveValue; - - emit(audit, algorithm, "SIGN_RESTORED", { - originalInput: n, - positiveValue, - result, - }); - - return result; +/** + * Restore the sign after an implementation calculates the positive magnitude. + */ +function withOriginalSign(n, positiveSum) { + return n < 0 ? -positiveSum : positiveSum; } /** - * A — Combinatorics + * Solution A — Closed-form arithmetic-series formula. * - * S(n) = C(n + 1, 2) + * The values 1..n form an arithmetic progression, so: + * S(n) = n(n + 1) / 2 + * + * One of n and n + 1 is always even. Dividing that factor first avoids an + * unnecessarily large intermediate multiplication. * * Time: O(1) * Space: O(1) */ -function sum_to_n_a(n, audit) { - const algorithm = "A_COMBINATORICS"; - - emit(audit, algorithm, "INPUT_RECEIVED", { n }); - +function sum_to_n_a(n) { validateInput(n); - emit(audit, algorithm, "INPUT_VALIDATED", { - n, - isSafeInteger: true, - isWithinSafeResultRange: true, - }); const magnitude = Math.abs(n); - emit(audit, algorithm, "MAGNITUDE_CALCULATED", { - expression: "|n|", - magnitude, - }); - - let leftFactor = magnitude; - let rightFactor = magnitude + 1; - - emit(audit, algorithm, "COMBINATION_IDENTITY_APPLIED", { - identity: "C(n + 1, 2) = n(n + 1) / 2", - leftFactor, - rightFactor, - divisor: 2, - }); - - if (leftFactor % 2 === 0) { - const before = leftFactor; - leftFactor /= 2; + let firstFactor = magnitude; + let secondFactor = magnitude + 1; - emit(audit, algorithm, "EVEN_FACTOR_DIVIDED", { - factor: "leftFactor", - before, - divisor: 2, - after: leftFactor, - }); + if (firstFactor % 2 === 0) { + firstFactor /= 2; } else { - const before = rightFactor; - rightFactor /= 2; - - emit(audit, algorithm, "EVEN_FACTOR_DIVIDED", { - factor: "rightFactor", - before, - divisor: 2, - after: rightFactor, - }); + secondFactor /= 2; } - const positiveSum = leftFactor * rightFactor; - - emit(audit, algorithm, "FACTORS_MULTIPLIED", { - leftFactor, - rightFactor, - positiveSum, - }); - - const result = restoreSign(n, positiveSum, audit, algorithm); - - emit(audit, algorithm, "COMPLETED", { - result, - complexity: { - time: "O(1)", - space: "O(1)", - }, - }); - - return result; -} - -function identityMatrix(size) { - return Array.from( - { length: size }, - (_, row) => - Array.from( - { length: size }, - (_, column) => (row === column ? 1 : 0), - ), - ); + const positiveSum = firstFactor * secondFactor; + return withOriginalSign(n, positiveSum); } -function multiplyMatrices(left, right, audit, context) { - const algorithm = "B_LINEAR_ALGEBRA"; - const size = left.length; - const result = Array.from( - { length: size }, - () => Array(size).fill(0), - ); - - emit(audit, algorithm, "MATRIX_MULTIPLICATION_STARTED", { - ...context, - left, - right, - }); - - for (let row = 0; row < size; row += 1) { - for (let column = 0; column < size; column += 1) { - const terms = []; - - for (let k = 0; k < size; k += 1) { - const product = left[row][k] * right[k][column]; - - terms.push({ - leftValue: left[row][k], - rightValue: right[k][column], - product, - }); +/** + * Multiply two fixed 3 × 3 matrices. + */ +function multiply3x3(left, right) { + const result = [ + [0, 0, 0], + [0, 0, 0], + [0, 0, 0], + ]; - result[row][column] += product; + for (let row = 0; row < 3; row += 1) { + for (let column = 0; column < 3; column += 1) { + for (let index = 0; index < 3; index += 1) { + result[row][column] += + left[row][index] * right[index][column]; } - - emit(audit, algorithm, "MATRIX_CELL_CALCULATED", { - ...context, - row, - column, - terms, - cellValue: result[row][column], - }); } } - emit(audit, algorithm, "MATRIX_MULTIPLICATION_COMPLETED", { - ...context, - result, - }); - return result; } /** - * B — Linear algebra using fast matrix exponentiation. + * Solution B — Fast matrix exponentiation. * - * State: - * [sum_k, k, 1]^T + * State vector: + * [sum(k), k, 1]^T * - * Transition: + * Transition matrix: * [1 1 1] * [0 1 1] * [0 0 1] * + * Raising this matrix to |n| gives the triangular sum in entry [0][2]. + * Exponentiation by squaring reduces the number of matrix multiplications. + * * Time: O(log |n|) - * Space: O(1), fixed 3 × 3 matrices + * Space: O(1), because every matrix is always 3 × 3 */ -function sum_to_n_b(n, audit) { - const algorithm = "B_LINEAR_ALGEBRA"; - - emit(audit, algorithm, "INPUT_RECEIVED", { n }); - +function sum_to_n_b(n) { validateInput(n); - emit(audit, algorithm, "INPUT_VALIDATED", { - n, - isSafeInteger: true, - isWithinSafeResultRange: true, - }); - const magnitude = Math.abs(n); - emit(audit, algorithm, "MAGNITUDE_CALCULATED", { - expression: "|n|", - magnitude, - }); - - const transitionMatrix = [ + let exponent = Math.abs(n); + let resultMatrix = [ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + ]; + let baseMatrix = [ [1, 1, 1], [0, 1, 1], [0, 0, 1], ]; - emit(audit, algorithm, "STATE_MODEL_DEFINED", { - stateVector: ["sum_k", "k", "1"], - initialVector: [0, 0, 1], - transitionMatrix, - }); - - let resultMatrix = identityMatrix(3); - let baseMatrix = transitionMatrix; - let exponent = magnitude; - let round = 0; - - emit(audit, algorithm, "MATRIX_POWER_INITIALIZED", { - targetPower: magnitude, - exponent, - resultMatrix, - baseMatrix, - }); - while (exponent > 0) { - round += 1; - - emit(audit, algorithm, "POWER_ROUND_STARTED", { - round, - exponent, - isOdd: exponent % 2 === 1, - }); - if (exponent % 2 === 1) { - emit(audit, algorithm, "ODD_EXPONENT_BRANCH", { - round, - operation: "resultMatrix = resultMatrix × baseMatrix", - }); - - resultMatrix = multiplyMatrices( - resultMatrix, - baseMatrix, - audit, - { - round, - purpose: "ACCUMULATE_RESULT", - }, - ); - - emit(audit, algorithm, "RESULT_MATRIX_UPDATED", { - round, - resultMatrix, - }); - } else { - emit(audit, algorithm, "EVEN_EXPONENT_BRANCH", { - round, - operation: "result multiplication skipped", - }); + resultMatrix = multiply3x3(resultMatrix, baseMatrix); } - baseMatrix = multiplyMatrices( - baseMatrix, - baseMatrix, - audit, - { - round, - purpose: "SQUARE_BASE", - }, - ); - - emit(audit, algorithm, "BASE_MATRIX_SQUARED", { - round, - baseMatrix, - }); - - const previousExponent = exponent; exponent = Math.floor(exponent / 2); - emit(audit, algorithm, "EXPONENT_HALVED", { - round, - before: previousExponent, - after: exponent, - }); + // Skip the final unnecessary square. Besides doing less work, this keeps + // every intermediate matrix within the safe range implied by the input. + if (exponent > 0) { + baseMatrix = multiply3x3(baseMatrix, baseMatrix); + } } - emit(audit, algorithm, "MATRIX_POWER_COMPLETED", { - power: magnitude, - poweredMatrix: resultMatrix, - }); - const positiveSum = resultMatrix[0][2]; - - emit(audit, algorithm, "INITIAL_VECTOR_APPLIED", { - poweredMatrix: resultMatrix, - initialVector: [0, 0, 1], - resultingVector: [ - resultMatrix[0][2], - resultMatrix[1][2], - resultMatrix[2][2], - ], - positiveSum, - }); - - const result = restoreSign(n, positiveSum, audit, algorithm); - - emit(audit, algorithm, "COMPLETED", { - result, - complexity: { - time: "O(log |n|)", - space: "O(1)", - }, - }); - - return result; + return withOriginalSign(n, positiveSum); } /** - * C — Probability symmetry / antithetic pairing. + * Solution C — Symmetric pairing. + * + * Pair the smallest and largest values: + * 1 + n + * 2 + (n - 1) + * 3 + (n - 2) * - * Pair x with n + 1 - x. Every pair totals n + 1. + * Every pair has the same value, n + 1. For odd n, add the unpaired middle + * value once. This implementation deliberately performs the pairing loop so + * it is computationally different from the O(1) formula in solution A. * * Time: O(|n|) * Space: O(1) */ -function sum_to_n_c(n, audit) { - const algorithm = "C_PROBABILITY_SYMMETRY"; - - emit(audit, algorithm, "INPUT_RECEIVED", { n }); - +function sum_to_n_c(n) { validateInput(n); - emit(audit, algorithm, "INPUT_VALIDATED", { - n, - isSafeInteger: true, - isWithinSafeResultRange: true, - }); const magnitude = Math.abs(n); - emit(audit, algorithm, "MAGNITUDE_CALCULATED", { - expression: "|n|", - magnitude, - }); - const pairCount = Math.floor(magnitude / 2); - const constantPairSum = magnitude + 1; - - emit(audit, algorithm, "ANTITHETIC_MODEL_DEFINED", { - sampleSpace: `{1, 2, ..., ${magnitude}}`, - mapping: "x ↔ n + 1 - x", - pairCount, - constantPairSum, - }); - let positiveSum = 0; - for (let pairIndex = 1; pairIndex <= pairCount; pairIndex += 1) { - const left = pairIndex; - const right = magnitude + 1 - pairIndex; - const pairSum = left + right; - const totalBefore = positiveSum; - - positiveSum += pairSum; - - emit(audit, algorithm, "PAIR_ACCUMULATED", { - pairIndex, - left, - right, - pairSum, - totalBefore, - totalAfter: positiveSum, - }); + for (let pair = 1; pair <= pairCount; pair += 1) { + const oppositeValue = magnitude + 1 - pair; + positiveSum += pair + oppositeValue; } if (magnitude % 2 === 1) { - const middleValue = (magnitude + 1) / 2; - const totalBefore = positiveSum; - - positiveSum += middleValue; - - emit(audit, algorithm, "MIDDLE_VALUE_ACCUMULATED", { - middleValue, - totalBefore, - totalAfter: positiveSum, - }); - } else { - emit(audit, algorithm, "MIDDLE_VALUE_NOT_REQUIRED", { - reason: "The number of values is even", - }); + positiveSum += (magnitude + 1) / 2; } - const result = restoreSign(n, positiveSum, audit, algorithm); - - emit(audit, algorithm, "COMPLETED", { - result, - complexity: { - time: "O(|n|)", - space: "O(1)", - }, - }); - - return result; + return withOriginalSign(n, positiveSum); } module.exports = { diff --git a/src/problem1/logs/.gitignore b/src/problem1/logs/.gitignore deleted file mode 100644 index d6b7ef32c8..0000000000 --- a/src/problem1/logs/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore diff --git a/src/problem1/logs/audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.jsonl b/src/problem1/logs/audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.jsonl new file mode 100644 index 0000000000..4b1966a15b --- /dev/null +++ b/src/problem1/logs/audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.jsonl @@ -0,0 +1,100 @@ +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.938Z","globalStep":1,"algorithm":"AUDIT_SESSION","action":"SESSION_STARTED","data":{"n":5,"selectedAlgorithm":"all"},"previousHash":"GENESIS","eventHash":"885394e565508c5b59a935d93bdc201a76a52f654a4f990829cb1aec8fef5f08"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.946Z","globalStep":2,"algorithm":"AUDIT_SESSION","action":"ALGORITHM_STARTED","data":{"key":"a","algorithm":"A_COMBINATORICS"},"previousHash":"885394e565508c5b59a935d93bdc201a76a52f654a4f990829cb1aec8fef5f08","eventHash":"b60ef86737457650a0c7c997b723afd79d66ca5b0e25815993e066cfda47e121"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.949Z","globalStep":3,"algorithm":"AUDIT_SESSION","action":"IMPLEMENTATION_CALLED","data":{"key":"a","algorithm":"A_COMBINATORICS","functionName":"sum_to_n_a","n":5},"previousHash":"b60ef86737457650a0c7c997b723afd79d66ca5b0e25815993e066cfda47e121","eventHash":"a0900e70b3d40b60be428b3727d25c2a0a00e31f52c23c94dd04448521ebce15"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.950Z","globalStep":4,"algorithm":"AUDIT_SESSION","action":"IMPLEMENTATION_RETURNED","data":{"key":"a","algorithm":"A_COMBINATORICS","result":15},"previousHash":"a0900e70b3d40b60be428b3727d25c2a0a00e31f52c23c94dd04448521ebce15","eventHash":"a43e22e290872538d97bf6fa8229833656e442a5cf929071274f5d66143ef6ea"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.951Z","globalStep":5,"algorithm":"A_COMBINATORICS","action":"INPUT_RECEIVED","data":{"n":5},"previousHash":"a43e22e290872538d97bf6fa8229833656e442a5cf929071274f5d66143ef6ea","eventHash":"0991fe7e3ed9c26c6fce6111b56dd2f51b6161eea948104c85858ebff6ae4c29"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.952Z","globalStep":6,"algorithm":"A_COMBINATORICS","action":"INPUT_VALIDATED","data":{"n":5,"isSafeInteger":true,"isWithinSafeResultRange":true},"previousHash":"0991fe7e3ed9c26c6fce6111b56dd2f51b6161eea948104c85858ebff6ae4c29","eventHash":"d0acd14d7418cd6809f16abc9491415e2030c08adc90f6707d4a113f90b112a9"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.953Z","globalStep":7,"algorithm":"A_COMBINATORICS","action":"MAGNITUDE_CALCULATED","data":{"expression":"|n|","magnitude":5},"previousHash":"d0acd14d7418cd6809f16abc9491415e2030c08adc90f6707d4a113f90b112a9","eventHash":"490c01c79447f2fa8f4a96e640cb58fb178a1674355f6bdff9b51939aac9d0c0"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.954Z","globalStep":8,"algorithm":"A_COMBINATORICS","action":"COMBINATION_IDENTITY_APPLIED","data":{"identity":"S(n) = n(n + 1) / 2","firstFactor":5,"secondFactor":6,"divisor":2},"previousHash":"490c01c79447f2fa8f4a96e640cb58fb178a1674355f6bdff9b51939aac9d0c0","eventHash":"32f3ddb3c4ced45e97a0fe0ed020798499a9859cf1612de679cd19a833c8793e"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.954Z","globalStep":9,"algorithm":"A_COMBINATORICS","action":"EVEN_FACTOR_DIVIDED","data":{"factor":"secondFactor","before":6,"divisor":2,"after":3},"previousHash":"32f3ddb3c4ced45e97a0fe0ed020798499a9859cf1612de679cd19a833c8793e","eventHash":"ea9ac48109331f82aedf381f890aadefe9f75b9d311f1f5d1d5ca6d8acd962d8"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.955Z","globalStep":10,"algorithm":"A_COMBINATORICS","action":"FACTORS_MULTIPLIED","data":{"firstFactor":5,"secondFactor":3,"positiveValue":15},"previousHash":"ea9ac48109331f82aedf381f890aadefe9f75b9d311f1f5d1d5ca6d8acd962d8","eventHash":"547b892c9388331fd3b3d71a27ef4708336b85c403584c83f90a2020fac87b52"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.956Z","globalStep":11,"algorithm":"A_COMBINATORICS","action":"SIGN_RESTORED","data":{"originalInput":5,"positiveValue":15,"result":15},"previousHash":"547b892c9388331fd3b3d71a27ef4708336b85c403584c83f90a2020fac87b52","eventHash":"6de0bd5c19c1a15f0c9182184e72ace8548cb8677177999ee3bbb02d76e06f96"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.957Z","globalStep":12,"algorithm":"A_COMBINATORICS","action":"PROOF_COMPLETED","data":{"result":15,"complexity":{"time":"O(1)","space":"O(1)"}},"previousHash":"6de0bd5c19c1a15f0c9182184e72ace8548cb8677177999ee3bbb02d76e06f96","eventHash":"59263edd1e3b9b9222ed6c7867fa132adb26dbd867f1b8cb701150f3631b3ad3"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.958Z","globalStep":13,"algorithm":"AUDIT_SESSION","action":"IMPLEMENTATION_VERIFIED","data":{"key":"a","algorithm":"A_COMBINATORICS","implementationResult":15,"proofResult":15,"matches":true},"previousHash":"59263edd1e3b9b9222ed6c7867fa132adb26dbd867f1b8cb701150f3631b3ad3","eventHash":"3ba6b8d4e43ac2b9c72b30735a96285c098cd3efb7a359ff56d8fcb4a1b8dbf7"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.959Z","globalStep":14,"algorithm":"AUDIT_SESSION","action":"ALGORITHM_COMPLETED","data":{"key":"a","algorithm":"A_COMBINATORICS","result":15,"proofResult":15,"matches":true},"previousHash":"3ba6b8d4e43ac2b9c72b30735a96285c098cd3efb7a359ff56d8fcb4a1b8dbf7","eventHash":"74c8a2a461c5ef4cdde3a7ea9dc18cc8efe320722733a4a300394cb3829764f5"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.960Z","globalStep":15,"algorithm":"AUDIT_SESSION","action":"ALGORITHM_STARTED","data":{"key":"b","algorithm":"B_LINEAR_ALGEBRA"},"previousHash":"74c8a2a461c5ef4cdde3a7ea9dc18cc8efe320722733a4a300394cb3829764f5","eventHash":"f8df30a87d0d088df05c68a77806b55d37baf9dd3b6c2206c6d22c88f7f75641"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.962Z","globalStep":16,"algorithm":"AUDIT_SESSION","action":"IMPLEMENTATION_CALLED","data":{"key":"b","algorithm":"B_LINEAR_ALGEBRA","functionName":"sum_to_n_b","n":5},"previousHash":"f8df30a87d0d088df05c68a77806b55d37baf9dd3b6c2206c6d22c88f7f75641","eventHash":"9280b5ff9e2dfd9fc8e13d8e077505c6d810926cc8aa496fcc3dd040accee363"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.963Z","globalStep":17,"algorithm":"AUDIT_SESSION","action":"IMPLEMENTATION_RETURNED","data":{"key":"b","algorithm":"B_LINEAR_ALGEBRA","result":15},"previousHash":"9280b5ff9e2dfd9fc8e13d8e077505c6d810926cc8aa496fcc3dd040accee363","eventHash":"5883ec9607b25da5ef18bdf2b3634e35a40d6904120d32211fa770805412460c"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.965Z","globalStep":18,"algorithm":"B_LINEAR_ALGEBRA","action":"INPUT_RECEIVED","data":{"n":5},"previousHash":"5883ec9607b25da5ef18bdf2b3634e35a40d6904120d32211fa770805412460c","eventHash":"e50fe68ff7c623150d1dd50aeaf74d7938f4aef062d27e2379a44833de889237"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.966Z","globalStep":19,"algorithm":"B_LINEAR_ALGEBRA","action":"INPUT_VALIDATED","data":{"n":5,"isSafeInteger":true,"isWithinSafeResultRange":true},"previousHash":"e50fe68ff7c623150d1dd50aeaf74d7938f4aef062d27e2379a44833de889237","eventHash":"428d84f1bfd0dee2bacfebc9180829216cd235484a1de89fe53dc34fdec8531b"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.967Z","globalStep":20,"algorithm":"B_LINEAR_ALGEBRA","action":"MAGNITUDE_CALCULATED","data":{"expression":"|n|","magnitude":5},"previousHash":"428d84f1bfd0dee2bacfebc9180829216cd235484a1de89fe53dc34fdec8531b","eventHash":"b6e6108117171886d75f861366e3e3fd3567bbd76e3d4fef1937c4e8f3a5cadc"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.968Z","globalStep":21,"algorithm":"B_LINEAR_ALGEBRA","action":"STATE_MODEL_DEFINED","data":{"stateVector":["sum_k","k","1"],"initialVector":[0,0,1],"transitionMatrix":[[1,1,1],[0,1,1],[0,0,1]]},"previousHash":"b6e6108117171886d75f861366e3e3fd3567bbd76e3d4fef1937c4e8f3a5cadc","eventHash":"c449dc900dca86f9d58df17f1d9778f3831cda1679cdf0dfcd05bf5768604da8"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.970Z","globalStep":22,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_POWER_INITIALIZED","data":{"targetPower":5,"exponent":5,"resultMatrix":[[1,0,0],[0,1,0],[0,0,1]],"baseMatrix":[[1,1,1],[0,1,1],[0,0,1]]},"previousHash":"c449dc900dca86f9d58df17f1d9778f3831cda1679cdf0dfcd05bf5768604da8","eventHash":"2f8a43d7789e0c9fad1175dc529f5aae1652d65786e2e7bb259900a65b954db9"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.972Z","globalStep":23,"algorithm":"B_LINEAR_ALGEBRA","action":"POWER_ROUND_STARTED","data":{"round":1,"exponent":5,"isOdd":true},"previousHash":"2f8a43d7789e0c9fad1175dc529f5aae1652d65786e2e7bb259900a65b954db9","eventHash":"c5134b3b9842c5cc18ffa3ae57a67be86ff437655ff457f4396fed2d96364eda"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.974Z","globalStep":24,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_MULTIPLICATION_STARTED","data":{"round":1,"purpose":"ACCUMULATE_RESULT","left":[[1,0,0],[0,1,0],[0,0,1]],"right":[[1,1,1],[0,1,1],[0,0,1]]},"previousHash":"c5134b3b9842c5cc18ffa3ae57a67be86ff437655ff457f4396fed2d96364eda","eventHash":"8416bb21dad9195b93d5a5f192c03c5e09b496c121420b374cd8242490a5e840"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.976Z","globalStep":25,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"ACCUMULATE_RESULT","row":0,"column":0,"terms":[{"leftValue":1,"rightValue":1,"product":1},{"leftValue":0,"rightValue":0,"product":0},{"leftValue":0,"rightValue":0,"product":0}],"cellValue":1},"previousHash":"8416bb21dad9195b93d5a5f192c03c5e09b496c121420b374cd8242490a5e840","eventHash":"52b08f88d7e938a1944a161d675cbe0157e6400bae67926b763c8eb45344d1fd"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.977Z","globalStep":26,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"ACCUMULATE_RESULT","row":0,"column":1,"terms":[{"leftValue":1,"rightValue":1,"product":1},{"leftValue":0,"rightValue":1,"product":0},{"leftValue":0,"rightValue":0,"product":0}],"cellValue":1},"previousHash":"52b08f88d7e938a1944a161d675cbe0157e6400bae67926b763c8eb45344d1fd","eventHash":"aeebed7b2271713dd9c30c82603f527c889042ebcef1b6544bf5b6ea15eaa8e0"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.977Z","globalStep":27,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"ACCUMULATE_RESULT","row":0,"column":2,"terms":[{"leftValue":1,"rightValue":1,"product":1},{"leftValue":0,"rightValue":1,"product":0},{"leftValue":0,"rightValue":1,"product":0}],"cellValue":1},"previousHash":"aeebed7b2271713dd9c30c82603f527c889042ebcef1b6544bf5b6ea15eaa8e0","eventHash":"caf780b367a824d2f6ece1cc8f370e7e9b7694bdab8b2e1244a21713e6c1faa7"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.978Z","globalStep":28,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"ACCUMULATE_RESULT","row":1,"column":0,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":1,"rightValue":0,"product":0},{"leftValue":0,"rightValue":0,"product":0}],"cellValue":0},"previousHash":"caf780b367a824d2f6ece1cc8f370e7e9b7694bdab8b2e1244a21713e6c1faa7","eventHash":"cb5f9c106fd2afe6b10be053b4e45d4cb59f793ef6cc365ff1622b6bf73e376a"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.979Z","globalStep":29,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"ACCUMULATE_RESULT","row":1,"column":1,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":1,"rightValue":1,"product":1},{"leftValue":0,"rightValue":0,"product":0}],"cellValue":1},"previousHash":"cb5f9c106fd2afe6b10be053b4e45d4cb59f793ef6cc365ff1622b6bf73e376a","eventHash":"48a8b54e857a113e0019f0b6d96893f6f70d8e690b9d561a65a31bee8934e0ad"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.981Z","globalStep":30,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"ACCUMULATE_RESULT","row":1,"column":2,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":1,"rightValue":1,"product":1},{"leftValue":0,"rightValue":1,"product":0}],"cellValue":1},"previousHash":"48a8b54e857a113e0019f0b6d96893f6f70d8e690b9d561a65a31bee8934e0ad","eventHash":"7e8c30ee0912b415b0a44505aefac7c15e53b0c398939cd2eb5e44841ae23874"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.982Z","globalStep":31,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"ACCUMULATE_RESULT","row":2,"column":0,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":0,"rightValue":0,"product":0},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":0},"previousHash":"7e8c30ee0912b415b0a44505aefac7c15e53b0c398939cd2eb5e44841ae23874","eventHash":"d72e6223afe9874e433e417e70330dc0e35ed0c513f97d3de2aee4a69fc21166"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.982Z","globalStep":32,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"ACCUMULATE_RESULT","row":2,"column":1,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":0,"rightValue":1,"product":0},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":0},"previousHash":"d72e6223afe9874e433e417e70330dc0e35ed0c513f97d3de2aee4a69fc21166","eventHash":"317a0303aaefce315148d589c75edf272cb000a3c4affd09564b5a674b8ab265"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.983Z","globalStep":33,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"ACCUMULATE_RESULT","row":2,"column":2,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":0,"rightValue":1,"product":0},{"leftValue":1,"rightValue":1,"product":1}],"cellValue":1},"previousHash":"317a0303aaefce315148d589c75edf272cb000a3c4affd09564b5a674b8ab265","eventHash":"856484db19bde55cd695a31da782f25359c9517da6cf24f5bcb8c58bb83ca66a"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.984Z","globalStep":34,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_MULTIPLICATION_COMPLETED","data":{"round":1,"purpose":"ACCUMULATE_RESULT","result":[[1,1,1],[0,1,1],[0,0,1]]},"previousHash":"856484db19bde55cd695a31da782f25359c9517da6cf24f5bcb8c58bb83ca66a","eventHash":"9fb33ab3648c93aef1dc987bb3cea8153591087c14527988ea4ce0da2f80d0f6"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.985Z","globalStep":35,"algorithm":"B_LINEAR_ALGEBRA","action":"RESULT_MATRIX_UPDATED","data":{"round":1,"resultMatrix":[[1,1,1],[0,1,1],[0,0,1]]},"previousHash":"9fb33ab3648c93aef1dc987bb3cea8153591087c14527988ea4ce0da2f80d0f6","eventHash":"4ada53af846e3e73d38ace887d4f0d51d1b17f969f028cdcf6d452ab74f56940"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.986Z","globalStep":36,"algorithm":"B_LINEAR_ALGEBRA","action":"EXPONENT_HALVED","data":{"round":1,"before":5,"after":2},"previousHash":"4ada53af846e3e73d38ace887d4f0d51d1b17f969f028cdcf6d452ab74f56940","eventHash":"b91d882b5d4f311630e0051a59f3677dceaa7d787d0654eaba747e0fb1b709ff"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.986Z","globalStep":37,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_MULTIPLICATION_STARTED","data":{"round":1,"purpose":"SQUARE_BASE","left":[[1,1,1],[0,1,1],[0,0,1]],"right":[[1,1,1],[0,1,1],[0,0,1]]},"previousHash":"b91d882b5d4f311630e0051a59f3677dceaa7d787d0654eaba747e0fb1b709ff","eventHash":"3b1d54fdce434a1a1ebc2f23d578f7105a2e5d536f747aa0a3b7076892bf49ae"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.988Z","globalStep":38,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"SQUARE_BASE","row":0,"column":0,"terms":[{"leftValue":1,"rightValue":1,"product":1},{"leftValue":1,"rightValue":0,"product":0},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":1},"previousHash":"3b1d54fdce434a1a1ebc2f23d578f7105a2e5d536f747aa0a3b7076892bf49ae","eventHash":"eb9035743bfab344e2453549f1f05c32fc1ba65958dd1a6d459a114307b20567"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.989Z","globalStep":39,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"SQUARE_BASE","row":0,"column":1,"terms":[{"leftValue":1,"rightValue":1,"product":1},{"leftValue":1,"rightValue":1,"product":1},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":2},"previousHash":"eb9035743bfab344e2453549f1f05c32fc1ba65958dd1a6d459a114307b20567","eventHash":"5b6b9d3b3d982bf7747242cbda950a6d7bfda10ad411306b444e88dfadf8c1c0"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.990Z","globalStep":40,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"SQUARE_BASE","row":0,"column":2,"terms":[{"leftValue":1,"rightValue":1,"product":1},{"leftValue":1,"rightValue":1,"product":1},{"leftValue":1,"rightValue":1,"product":1}],"cellValue":3},"previousHash":"5b6b9d3b3d982bf7747242cbda950a6d7bfda10ad411306b444e88dfadf8c1c0","eventHash":"99846e32da073c1fe7fb80be6616c1a207b95978599e42f66614b74e237d839b"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.991Z","globalStep":41,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"SQUARE_BASE","row":1,"column":0,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":1,"rightValue":0,"product":0},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":0},"previousHash":"99846e32da073c1fe7fb80be6616c1a207b95978599e42f66614b74e237d839b","eventHash":"62c5f1d040b9e6c22be4b3825ee6572ce13b82107437b4690356f2c9054c25fb"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.992Z","globalStep":42,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"SQUARE_BASE","row":1,"column":1,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":1,"rightValue":1,"product":1},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":1},"previousHash":"62c5f1d040b9e6c22be4b3825ee6572ce13b82107437b4690356f2c9054c25fb","eventHash":"2d7793df7188ffc546c567907917393f006357fe1fa72cb20a3801836e241c84"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.993Z","globalStep":43,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"SQUARE_BASE","row":1,"column":2,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":1,"rightValue":1,"product":1},{"leftValue":1,"rightValue":1,"product":1}],"cellValue":2},"previousHash":"2d7793df7188ffc546c567907917393f006357fe1fa72cb20a3801836e241c84","eventHash":"5bd9dcc08e02ac18b97c8fb2d6ead4d57eb95ec6f5ed51be0732edb74c688df2"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.993Z","globalStep":44,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"SQUARE_BASE","row":2,"column":0,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":0,"rightValue":0,"product":0},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":0},"previousHash":"5bd9dcc08e02ac18b97c8fb2d6ead4d57eb95ec6f5ed51be0732edb74c688df2","eventHash":"839365b1d4c0045f9529a9eeba11cce0ca2172414b12d2027c20a6ddd2c0c792"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.994Z","globalStep":45,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"SQUARE_BASE","row":2,"column":1,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":0,"rightValue":1,"product":0},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":0},"previousHash":"839365b1d4c0045f9529a9eeba11cce0ca2172414b12d2027c20a6ddd2c0c792","eventHash":"f2597fb6af4631e31c3e108b6f93d5ed5d5c45fbc13b3ca727a57375746ea50e"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.995Z","globalStep":46,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":1,"purpose":"SQUARE_BASE","row":2,"column":2,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":0,"rightValue":1,"product":0},{"leftValue":1,"rightValue":1,"product":1}],"cellValue":1},"previousHash":"f2597fb6af4631e31c3e108b6f93d5ed5d5c45fbc13b3ca727a57375746ea50e","eventHash":"cd78801f7e2fbda00a728f4dce9982520f6d4158d5dda122145bea1aebb00ced"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.996Z","globalStep":47,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_MULTIPLICATION_COMPLETED","data":{"round":1,"purpose":"SQUARE_BASE","result":[[1,2,3],[0,1,2],[0,0,1]]},"previousHash":"cd78801f7e2fbda00a728f4dce9982520f6d4158d5dda122145bea1aebb00ced","eventHash":"d3b963872020b4f1918a24727d566b0a3e0fc701a4868f54cb481735991e446f"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.997Z","globalStep":48,"algorithm":"B_LINEAR_ALGEBRA","action":"BASE_MATRIX_SQUARED","data":{"round":1,"baseMatrix":[[1,2,3],[0,1,2],[0,0,1]]},"previousHash":"d3b963872020b4f1918a24727d566b0a3e0fc701a4868f54cb481735991e446f","eventHash":"0689195a5f02a18a8e4282da4db7f366b753e627df7492b964712b978b3ddafd"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.998Z","globalStep":49,"algorithm":"B_LINEAR_ALGEBRA","action":"POWER_ROUND_STARTED","data":{"round":2,"exponent":2,"isOdd":false},"previousHash":"0689195a5f02a18a8e4282da4db7f366b753e627df7492b964712b978b3ddafd","eventHash":"c385a4378b90ccffd61000740794d7e6fe15627bc9dfc60cb8dad78f4e419a4b"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.999Z","globalStep":50,"algorithm":"B_LINEAR_ALGEBRA","action":"RESULT_MULTIPLICATION_SKIPPED","data":{"round":2,"reason":"Exponent is even"},"previousHash":"c385a4378b90ccffd61000740794d7e6fe15627bc9dfc60cb8dad78f4e419a4b","eventHash":"e3e15306969e749353dcd1022869323a04e304bcbb3b79a0bca3a6de5c2d508b"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:29.999Z","globalStep":51,"algorithm":"B_LINEAR_ALGEBRA","action":"EXPONENT_HALVED","data":{"round":2,"before":2,"after":1},"previousHash":"e3e15306969e749353dcd1022869323a04e304bcbb3b79a0bca3a6de5c2d508b","eventHash":"d7088b43608b1baf0c575e85d37d080d325f37fcc4990cbd862af51814eb12b7"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.000Z","globalStep":52,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_MULTIPLICATION_STARTED","data":{"round":2,"purpose":"SQUARE_BASE","left":[[1,2,3],[0,1,2],[0,0,1]],"right":[[1,2,3],[0,1,2],[0,0,1]]},"previousHash":"d7088b43608b1baf0c575e85d37d080d325f37fcc4990cbd862af51814eb12b7","eventHash":"1d18aeaf594b6732d9a850ef8da0b28e9cfc0aa7af423f3f7c8b181336bce888"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.001Z","globalStep":53,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":2,"purpose":"SQUARE_BASE","row":0,"column":0,"terms":[{"leftValue":1,"rightValue":1,"product":1},{"leftValue":2,"rightValue":0,"product":0},{"leftValue":3,"rightValue":0,"product":0}],"cellValue":1},"previousHash":"1d18aeaf594b6732d9a850ef8da0b28e9cfc0aa7af423f3f7c8b181336bce888","eventHash":"2d825571f6f72da8f121ca782ca6864055c92b488c53e89d1bafc48e2948632e"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.002Z","globalStep":54,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":2,"purpose":"SQUARE_BASE","row":0,"column":1,"terms":[{"leftValue":1,"rightValue":2,"product":2},{"leftValue":2,"rightValue":1,"product":2},{"leftValue":3,"rightValue":0,"product":0}],"cellValue":4},"previousHash":"2d825571f6f72da8f121ca782ca6864055c92b488c53e89d1bafc48e2948632e","eventHash":"763a2bdc8ec4b7760a86f2d1ded0c363de642c01f6f1d74d8cd77e18abb9cff2"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.002Z","globalStep":55,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":2,"purpose":"SQUARE_BASE","row":0,"column":2,"terms":[{"leftValue":1,"rightValue":3,"product":3},{"leftValue":2,"rightValue":2,"product":4},{"leftValue":3,"rightValue":1,"product":3}],"cellValue":10},"previousHash":"763a2bdc8ec4b7760a86f2d1ded0c363de642c01f6f1d74d8cd77e18abb9cff2","eventHash":"7689478fba94cefe76123337fc86c62fc4ab73b5fdb99243a6424bdfdfbf969c"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.003Z","globalStep":56,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":2,"purpose":"SQUARE_BASE","row":1,"column":0,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":1,"rightValue":0,"product":0},{"leftValue":2,"rightValue":0,"product":0}],"cellValue":0},"previousHash":"7689478fba94cefe76123337fc86c62fc4ab73b5fdb99243a6424bdfdfbf969c","eventHash":"8474bdf99a6484957601be5b7d1002bc7d261622d82284278bbe1d375327321d"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.003Z","globalStep":57,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":2,"purpose":"SQUARE_BASE","row":1,"column":1,"terms":[{"leftValue":0,"rightValue":2,"product":0},{"leftValue":1,"rightValue":1,"product":1},{"leftValue":2,"rightValue":0,"product":0}],"cellValue":1},"previousHash":"8474bdf99a6484957601be5b7d1002bc7d261622d82284278bbe1d375327321d","eventHash":"4c9058c42186c6369a4685842e54fc7b3f9a2e2f0f5b516540e1830e45811698"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.005Z","globalStep":58,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":2,"purpose":"SQUARE_BASE","row":1,"column":2,"terms":[{"leftValue":0,"rightValue":3,"product":0},{"leftValue":1,"rightValue":2,"product":2},{"leftValue":2,"rightValue":1,"product":2}],"cellValue":4},"previousHash":"4c9058c42186c6369a4685842e54fc7b3f9a2e2f0f5b516540e1830e45811698","eventHash":"0b7077086e14e478e06aa4dd36cd6028ad3ab978d41c723eb0212e2046f8306e"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.005Z","globalStep":59,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":2,"purpose":"SQUARE_BASE","row":2,"column":0,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":0,"rightValue":0,"product":0},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":0},"previousHash":"0b7077086e14e478e06aa4dd36cd6028ad3ab978d41c723eb0212e2046f8306e","eventHash":"9fa266a6cd4c48ecd9510927cf48755fa26890faee72446e23e24797dcfb9dcd"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.006Z","globalStep":60,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":2,"purpose":"SQUARE_BASE","row":2,"column":1,"terms":[{"leftValue":0,"rightValue":2,"product":0},{"leftValue":0,"rightValue":1,"product":0},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":0},"previousHash":"9fa266a6cd4c48ecd9510927cf48755fa26890faee72446e23e24797dcfb9dcd","eventHash":"e7089f64a9106283859a752965b5914a76b49a6215e592007e7a99af1e8b2053"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.006Z","globalStep":61,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":2,"purpose":"SQUARE_BASE","row":2,"column":2,"terms":[{"leftValue":0,"rightValue":3,"product":0},{"leftValue":0,"rightValue":2,"product":0},{"leftValue":1,"rightValue":1,"product":1}],"cellValue":1},"previousHash":"e7089f64a9106283859a752965b5914a76b49a6215e592007e7a99af1e8b2053","eventHash":"98109056d4d503a7c9d83ffaf9067ae32d0fb1c7c82b99c437d43a0c2ed193af"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.007Z","globalStep":62,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_MULTIPLICATION_COMPLETED","data":{"round":2,"purpose":"SQUARE_BASE","result":[[1,4,10],[0,1,4],[0,0,1]]},"previousHash":"98109056d4d503a7c9d83ffaf9067ae32d0fb1c7c82b99c437d43a0c2ed193af","eventHash":"fec068e8079982a8feb36e7114e153c87977d3b931100a204800316d2255cb1a"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.008Z","globalStep":63,"algorithm":"B_LINEAR_ALGEBRA","action":"BASE_MATRIX_SQUARED","data":{"round":2,"baseMatrix":[[1,4,10],[0,1,4],[0,0,1]]},"previousHash":"fec068e8079982a8feb36e7114e153c87977d3b931100a204800316d2255cb1a","eventHash":"28301aef3ce38cf6c5169c9584eb35491f7ccfc7129b3b139f23aace32fd3ca0"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.009Z","globalStep":64,"algorithm":"B_LINEAR_ALGEBRA","action":"POWER_ROUND_STARTED","data":{"round":3,"exponent":1,"isOdd":true},"previousHash":"28301aef3ce38cf6c5169c9584eb35491f7ccfc7129b3b139f23aace32fd3ca0","eventHash":"f76837b4362d9c2145a30985bcc33a85ffbafae2fe447411b1615bbb7d7484b3"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.009Z","globalStep":65,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_MULTIPLICATION_STARTED","data":{"round":3,"purpose":"ACCUMULATE_RESULT","left":[[1,1,1],[0,1,1],[0,0,1]],"right":[[1,4,10],[0,1,4],[0,0,1]]},"previousHash":"f76837b4362d9c2145a30985bcc33a85ffbafae2fe447411b1615bbb7d7484b3","eventHash":"7f1e48d63e4350996066ee937a0e1aec8cae6c40ce1b85caa5704d1e235eddd8"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.010Z","globalStep":66,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":3,"purpose":"ACCUMULATE_RESULT","row":0,"column":0,"terms":[{"leftValue":1,"rightValue":1,"product":1},{"leftValue":1,"rightValue":0,"product":0},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":1},"previousHash":"7f1e48d63e4350996066ee937a0e1aec8cae6c40ce1b85caa5704d1e235eddd8","eventHash":"7ab4a371a97f92809d8e60bc0bd4059e7d4ecf70520dfb3b077c42e253bc90a8"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.011Z","globalStep":67,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":3,"purpose":"ACCUMULATE_RESULT","row":0,"column":1,"terms":[{"leftValue":1,"rightValue":4,"product":4},{"leftValue":1,"rightValue":1,"product":1},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":5},"previousHash":"7ab4a371a97f92809d8e60bc0bd4059e7d4ecf70520dfb3b077c42e253bc90a8","eventHash":"a6b24825c3d4f37a3ffef473ec2bc89e0b23ef30cdfd2522335e76d4f680cf0f"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.012Z","globalStep":68,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":3,"purpose":"ACCUMULATE_RESULT","row":0,"column":2,"terms":[{"leftValue":1,"rightValue":10,"product":10},{"leftValue":1,"rightValue":4,"product":4},{"leftValue":1,"rightValue":1,"product":1}],"cellValue":15},"previousHash":"a6b24825c3d4f37a3ffef473ec2bc89e0b23ef30cdfd2522335e76d4f680cf0f","eventHash":"dce3a97f2320c260a4a68871c4c4f30d2a19a19bafdf4fec7f195222ea385c7f"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.013Z","globalStep":69,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":3,"purpose":"ACCUMULATE_RESULT","row":1,"column":0,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":1,"rightValue":0,"product":0},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":0},"previousHash":"dce3a97f2320c260a4a68871c4c4f30d2a19a19bafdf4fec7f195222ea385c7f","eventHash":"c83b86df35a481739e102aca4e41d5972e4ddeeceae0962823e6429a23b67593"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.014Z","globalStep":70,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":3,"purpose":"ACCUMULATE_RESULT","row":1,"column":1,"terms":[{"leftValue":0,"rightValue":4,"product":0},{"leftValue":1,"rightValue":1,"product":1},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":1},"previousHash":"c83b86df35a481739e102aca4e41d5972e4ddeeceae0962823e6429a23b67593","eventHash":"66f87202bc50b0ff3c7a8b5f8381c47569216ed7deeed5616f8a3870f6a4453d"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.014Z","globalStep":71,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":3,"purpose":"ACCUMULATE_RESULT","row":1,"column":2,"terms":[{"leftValue":0,"rightValue":10,"product":0},{"leftValue":1,"rightValue":4,"product":4},{"leftValue":1,"rightValue":1,"product":1}],"cellValue":5},"previousHash":"66f87202bc50b0ff3c7a8b5f8381c47569216ed7deeed5616f8a3870f6a4453d","eventHash":"ee95d060872d58326ee06ca7a3fcd8721c860b9312938ef3af1dad1b0b9c89c4"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.015Z","globalStep":72,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":3,"purpose":"ACCUMULATE_RESULT","row":2,"column":0,"terms":[{"leftValue":0,"rightValue":1,"product":0},{"leftValue":0,"rightValue":0,"product":0},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":0},"previousHash":"ee95d060872d58326ee06ca7a3fcd8721c860b9312938ef3af1dad1b0b9c89c4","eventHash":"bc65394a7c5b803331a8d777265e738a41577808cd100839ff2f4716e80873ed"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.016Z","globalStep":73,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":3,"purpose":"ACCUMULATE_RESULT","row":2,"column":1,"terms":[{"leftValue":0,"rightValue":4,"product":0},{"leftValue":0,"rightValue":1,"product":0},{"leftValue":1,"rightValue":0,"product":0}],"cellValue":0},"previousHash":"bc65394a7c5b803331a8d777265e738a41577808cd100839ff2f4716e80873ed","eventHash":"41b3fdef749f260b26d6cbd430edf3ff3d67d564d4e652b5d6e6bd63b8a4871f"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.016Z","globalStep":74,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_CELL_CALCULATED","data":{"round":3,"purpose":"ACCUMULATE_RESULT","row":2,"column":2,"terms":[{"leftValue":0,"rightValue":10,"product":0},{"leftValue":0,"rightValue":4,"product":0},{"leftValue":1,"rightValue":1,"product":1}],"cellValue":1},"previousHash":"41b3fdef749f260b26d6cbd430edf3ff3d67d564d4e652b5d6e6bd63b8a4871f","eventHash":"5b07e4cf75430ce82b0d24c8d28d30dfdaa239b4a0b98db10d7edce2bfdf02d5"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.017Z","globalStep":75,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_MULTIPLICATION_COMPLETED","data":{"round":3,"purpose":"ACCUMULATE_RESULT","result":[[1,5,15],[0,1,5],[0,0,1]]},"previousHash":"5b07e4cf75430ce82b0d24c8d28d30dfdaa239b4a0b98db10d7edce2bfdf02d5","eventHash":"ef791f6603877bce08bac953bc593a320a19ad3e7fc7f4df1758b17955fef5c8"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.018Z","globalStep":76,"algorithm":"B_LINEAR_ALGEBRA","action":"RESULT_MATRIX_UPDATED","data":{"round":3,"resultMatrix":[[1,5,15],[0,1,5],[0,0,1]]},"previousHash":"ef791f6603877bce08bac953bc593a320a19ad3e7fc7f4df1758b17955fef5c8","eventHash":"3e85f7f6c54ce4364e96725498e1a80dde7a546858c548ac9a3f39b9e7e7327a"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.018Z","globalStep":77,"algorithm":"B_LINEAR_ALGEBRA","action":"EXPONENT_HALVED","data":{"round":3,"before":1,"after":0},"previousHash":"3e85f7f6c54ce4364e96725498e1a80dde7a546858c548ac9a3f39b9e7e7327a","eventHash":"aee57155fcaedf179754033f841f79dc2e5d81e3752a91f2dd8047cb7dcc69e8"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.019Z","globalStep":78,"algorithm":"B_LINEAR_ALGEBRA","action":"FINAL_BASE_SQUARE_SKIPPED","data":{"round":3,"reason":"No exponent bits remain"},"previousHash":"aee57155fcaedf179754033f841f79dc2e5d81e3752a91f2dd8047cb7dcc69e8","eventHash":"7193561a5941ff6ab269a5a848749c895f065c161e5740bf29867d34d163abf4"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.019Z","globalStep":79,"algorithm":"B_LINEAR_ALGEBRA","action":"MATRIX_POWER_COMPLETED","data":{"power":5,"poweredMatrix":[[1,5,15],[0,1,5],[0,0,1]]},"previousHash":"7193561a5941ff6ab269a5a848749c895f065c161e5740bf29867d34d163abf4","eventHash":"868d42c0037f625bec4a1da41a0f185674491e06cb1f5c96c28d5cc221e2b3b6"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.021Z","globalStep":80,"algorithm":"B_LINEAR_ALGEBRA","action":"INITIAL_VECTOR_APPLIED","data":{"poweredMatrix":[[1,5,15],[0,1,5],[0,0,1]],"initialVector":[0,0,1],"resultingVector":[15,5,1],"positiveValue":15},"previousHash":"868d42c0037f625bec4a1da41a0f185674491e06cb1f5c96c28d5cc221e2b3b6","eventHash":"38de863ce4c24bf2910e96a713dde17d08339eb471b9fd131e1769ddbb4c9a17"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.021Z","globalStep":81,"algorithm":"B_LINEAR_ALGEBRA","action":"SIGN_RESTORED","data":{"originalInput":5,"positiveValue":15,"result":15},"previousHash":"38de863ce4c24bf2910e96a713dde17d08339eb471b9fd131e1769ddbb4c9a17","eventHash":"665866ef2140d78af6212ab5264bd801a55fa4c21fbd7925dab257abd82aed87"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.022Z","globalStep":82,"algorithm":"B_LINEAR_ALGEBRA","action":"PROOF_COMPLETED","data":{"result":15,"complexity":{"time":"O(log |n|)","space":"O(1)"}},"previousHash":"665866ef2140d78af6212ab5264bd801a55fa4c21fbd7925dab257abd82aed87","eventHash":"86e803ad74caedfd85495439f687245ccb11360b6659750c1edaae9c4f049aff"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.023Z","globalStep":83,"algorithm":"AUDIT_SESSION","action":"IMPLEMENTATION_VERIFIED","data":{"key":"b","algorithm":"B_LINEAR_ALGEBRA","implementationResult":15,"proofResult":15,"matches":true},"previousHash":"86e803ad74caedfd85495439f687245ccb11360b6659750c1edaae9c4f049aff","eventHash":"f3b6ecf8ec3d06fbc09b8c8642c3b5ce6838a39c356433d15e2ba9fd1456332e"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.023Z","globalStep":84,"algorithm":"AUDIT_SESSION","action":"ALGORITHM_COMPLETED","data":{"key":"b","algorithm":"B_LINEAR_ALGEBRA","result":15,"proofResult":15,"matches":true},"previousHash":"f3b6ecf8ec3d06fbc09b8c8642c3b5ce6838a39c356433d15e2ba9fd1456332e","eventHash":"4812a60375341298e47a3d24c51115c20b905ede6750cb8bb5d8bc97bb95d1f1"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.024Z","globalStep":85,"algorithm":"AUDIT_SESSION","action":"ALGORITHM_STARTED","data":{"key":"c","algorithm":"C_PROBABILITY_SYMMETRY"},"previousHash":"4812a60375341298e47a3d24c51115c20b905ede6750cb8bb5d8bc97bb95d1f1","eventHash":"d49cace64b1dd3f6be950621173803220cc22a31b92450b0675baa16c3ffb0e5"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.025Z","globalStep":86,"algorithm":"AUDIT_SESSION","action":"IMPLEMENTATION_CALLED","data":{"key":"c","algorithm":"C_PROBABILITY_SYMMETRY","functionName":"sum_to_n_c","n":5},"previousHash":"d49cace64b1dd3f6be950621173803220cc22a31b92450b0675baa16c3ffb0e5","eventHash":"0dafc19a3c669003c18ad39e923a3f76fdecc3a79e8a8c0b22d55243c6d66f99"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.026Z","globalStep":87,"algorithm":"AUDIT_SESSION","action":"IMPLEMENTATION_RETURNED","data":{"key":"c","algorithm":"C_PROBABILITY_SYMMETRY","result":15},"previousHash":"0dafc19a3c669003c18ad39e923a3f76fdecc3a79e8a8c0b22d55243c6d66f99","eventHash":"346321b10307343a187d5f266b46b6a2b05ee24952a1509320efe977f23f0316"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.027Z","globalStep":88,"algorithm":"C_PROBABILITY_SYMMETRY","action":"INPUT_RECEIVED","data":{"n":5},"previousHash":"346321b10307343a187d5f266b46b6a2b05ee24952a1509320efe977f23f0316","eventHash":"f23d39a97dd15f84ba32d9856444aeae69d555016b03249a9103898c04bc433e"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.028Z","globalStep":89,"algorithm":"C_PROBABILITY_SYMMETRY","action":"INPUT_VALIDATED","data":{"n":5,"isSafeInteger":true,"isWithinSafeResultRange":true},"previousHash":"f23d39a97dd15f84ba32d9856444aeae69d555016b03249a9103898c04bc433e","eventHash":"2f35ac2f4f28e5289478620e7333f99dbdeff8b9c583b98e69581c9ccd562182"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.031Z","globalStep":90,"algorithm":"C_PROBABILITY_SYMMETRY","action":"MAGNITUDE_CALCULATED","data":{"expression":"|n|","magnitude":5},"previousHash":"2f35ac2f4f28e5289478620e7333f99dbdeff8b9c583b98e69581c9ccd562182","eventHash":"e4781e716c4314c0736ffbbdba0c1726a73a07e6eb9423b4f355edea76198ec7"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.032Z","globalStep":91,"algorithm":"C_PROBABILITY_SYMMETRY","action":"ANTITHETIC_MODEL_DEFINED","data":{"sampleSpace":"{1, 2, ..., 5}","mapping":"x ↔ n + 1 - x","pairCount":2,"constantPairSum":6},"previousHash":"e4781e716c4314c0736ffbbdba0c1726a73a07e6eb9423b4f355edea76198ec7","eventHash":"6d7f1e84d9021d380c8f57e190c4d3c8d1a166dfdb3d1b219db0718ccfd2709f"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.032Z","globalStep":92,"algorithm":"C_PROBABILITY_SYMMETRY","action":"PAIRED_TOTAL_CALCULATED","data":{"pairCount":2,"constantPairSum":6,"expression":"2 × 6","pairedTotal":12},"previousHash":"6d7f1e84d9021d380c8f57e190c4d3c8d1a166dfdb3d1b219db0718ccfd2709f","eventHash":"04276840f7a686c591d7a6000490e241936ea61b33e83673b92e187df9e2e8f0"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.033Z","globalStep":93,"algorithm":"C_PROBABILITY_SYMMETRY","action":"MIDDLE_VALUE_ADDED","data":{"middleValue":3,"pairedTotal":12,"positiveValue":15},"previousHash":"04276840f7a686c591d7a6000490e241936ea61b33e83673b92e187df9e2e8f0","eventHash":"25e4734c3e51ea182d3ee8451dde8e053318f6447be3a51bb4b6dc3430342536"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.034Z","globalStep":94,"algorithm":"C_PROBABILITY_SYMMETRY","action":"SIGN_RESTORED","data":{"originalInput":5,"positiveValue":15,"result":15},"previousHash":"25e4734c3e51ea182d3ee8451dde8e053318f6447be3a51bb4b6dc3430342536","eventHash":"c78980b9365a9d2f97087ab22dfdfeea3e069dabf0ea665618aaada80dc56888"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.034Z","globalStep":95,"algorithm":"C_PROBABILITY_SYMMETRY","action":"PROOF_COMPLETED","data":{"result":15,"implementationComplexity":{"time":"O(|n|)","space":"O(1)"},"auditProofComplexity":{"time":"O(1)","space":"O(1)"}},"previousHash":"c78980b9365a9d2f97087ab22dfdfeea3e069dabf0ea665618aaada80dc56888","eventHash":"3ec24d81a3f26f568bc09f4753d1bf96025d7eb5de776707cef54eab001a3524"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.035Z","globalStep":96,"algorithm":"AUDIT_SESSION","action":"IMPLEMENTATION_VERIFIED","data":{"key":"c","algorithm":"C_PROBABILITY_SYMMETRY","implementationResult":15,"proofResult":15,"matches":true},"previousHash":"3ec24d81a3f26f568bc09f4753d1bf96025d7eb5de776707cef54eab001a3524","eventHash":"b6ab542703131c1839ff735b4c968be5dd824d62e4eca3d262c2ce4ca78842cf"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.036Z","globalStep":97,"algorithm":"AUDIT_SESSION","action":"ALGORITHM_COMPLETED","data":{"key":"c","algorithm":"C_PROBABILITY_SYMMETRY","result":15,"proofResult":15,"matches":true},"previousHash":"b6ab542703131c1839ff735b4c968be5dd824d62e4eca3d262c2ce4ca78842cf","eventHash":"55c4bac5dc320eb94f500defeed4cd9bc851a86076afbd78ba2cdfa6d09baecf"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.037Z","globalStep":98,"algorithm":"AUDIT_SESSION","action":"RESULTS_CROSS_CHECKED","data":{"results":{"a":15,"b":15,"c":15},"proofChecks":{"a":{"proofResult":15,"matches":true},"b":{"proofResult":15,"matches":true},"c":{"proofResult":15,"matches":true}},"consistent":true,"allProofsMatch":true},"previousHash":"55c4bac5dc320eb94f500defeed4cd9bc851a86076afbd78ba2cdfa6d09baecf","eventHash":"9d108dd269190fd7ef22db3beef1b939d399af30f18fa5dd8e581e265183ee9a"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.038Z","globalStep":99,"algorithm":"AUDIT_SESSION","action":"INDEPENDENT_REFERENCE_CALCULATED","data":{"reference":"15","matches":true},"previousHash":"9d108dd269190fd7ef22db3beef1b939d399af30f18fa5dd8e581e265183ee9a","eventHash":"2c5561e4c7f38509df9f1d361b6a24728d34ac793a32b446df348c18286830c3"} +{"auditId":"bd12e062-3452-4783-8449-b9e8111d8807","timestamp":"2026-08-03T13:53:30.038Z","globalStep":100,"algorithm":"AUDIT_SESSION","action":"SESSION_PASSED","data":{"status":"PASSED","results":{"a":15,"b":15,"c":15},"proofChecks":{"a":{"proofResult":15,"matches":true},"b":{"proofResult":15,"matches":true},"c":{"proofResult":15,"matches":true}},"consistent":true,"allProofsMatch":true,"matchesReference":true},"previousHash":"2c5561e4c7f38509df9f1d361b6a24728d34ac793a32b446df348c18286830c3","eventHash":"b92a5d941a1eb3650f22ec4388ebcf9ef56425c685abd6b406e7b02eaeaee1c8"} diff --git a/src/problem1/logs/audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.log b/src/problem1/logs/audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.log new file mode 100644 index 0000000000..c9dbb055de --- /dev/null +++ b/src/problem1/logs/audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.log @@ -0,0 +1,519 @@ +99TECH CODE CHALLENGE — PROBLEM 1 +SEPARATED IMPLEMENTATION AUDIT +Audit ID: bd12e062-3452-4783-8449-b9e8111d8807 +Started: 2026-08-03T13:53:29.936Z +Input n: 5 +Selection: all +index.js: pure implementations only +audit.js: wrapper, proof, logging, and integrity +[0001] AUDIT_SESSION :: SESSION_STARTED + Input n = 5 + Selected algorithms = all + eventHash = 885394e565508c5b59a935d93bdc201a76a52f654a4f990829cb1aec8fef5f08 + + +==================================================================================================== +A. CLOSED-FORM ARITHMETIC SERIES +==================================================================================================== +[0002] AUDIT_SESSION :: ALGORITHM_STARTED + Start A_COMBINATORICS + eventHash = b60ef86737457650a0c7c997b723afd79d66ca5b0e25815993e066cfda47e121 + +[0003] AUDIT_SESSION :: IMPLEMENTATION_CALLED + Call index.js export sum_to_n_a(5) + eventHash = a0900e70b3d40b60be428b3727d25c2a0a00e31f52c23c94dd04448521ebce15 + +[0004] AUDIT_SESSION :: IMPLEMENTATION_RETURNED + index.js returned 15 + eventHash = a43e22e290872538d97bf6fa8229833656e442a5cf929071274f5d66143ef6ea + +[0005] A_COMBINATORICS :: INPUT_RECEIVED + Receive n = 5 + eventHash = 0991fe7e3ed9c26c6fce6111b56dd2f51b6161eea948104c85858ebff6ae4c29 + +[0006] A_COMBINATORICS :: INPUT_VALIDATED + Input is a safe integer = true + Result range is safe = true + eventHash = d0acd14d7418cd6809f16abc9491415e2030c08adc90f6707d4a113f90b112a9 + +[0007] A_COMBINATORICS :: MAGNITUDE_CALCULATED + |n| = 5 + eventHash = 490c01c79447f2fa8f4a96e640cb58fb178a1674355f6bdff9b51939aac9d0c0 + +[0008] A_COMBINATORICS :: COMBINATION_IDENTITY_APPLIED + S(n) = n(n + 1) / 2 + 5 × 6 ÷ 2 + eventHash = 32f3ddb3c4ced45e97a0fe0ed020798499a9859cf1612de679cd19a833c8793e + +[0009] A_COMBINATORICS :: EVEN_FACTOR_DIVIDED + secondFactor: 6 ÷ 2 = 3 + eventHash = ea9ac48109331f82aedf381f890aadefe9f75b9d311f1f5d1d5ca6d8acd962d8 + +[0010] A_COMBINATORICS :: FACTORS_MULTIPLIED + 5 × 3 = 15 + eventHash = 547b892c9388331fd3b3d71a27ef4708336b85c403584c83f90a2020fac87b52 + +[0011] A_COMBINATORICS :: SIGN_RESTORED + Restore sign: 15 → 15 + eventHash = 6de0bd5c19c1a15f0c9182184e72ace8548cb8677177999ee3bbb02d76e06f96 + +[0012] A_COMBINATORICS :: PROOF_COMPLETED + Proof result = 15 + eventHash = 59263edd1e3b9b9222ed6c7867fa132adb26dbd867f1b8cb701150f3631b3ad3 + +[0013] AUDIT_SESSION :: IMPLEMENTATION_VERIFIED + Implementation result = 15 + Independent proof result = 15 + Match = true + eventHash = 3ba6b8d4e43ac2b9c72b30735a96285c098cd3efb7a359ff56d8fcb4a1b8dbf7 + +[0014] AUDIT_SESSION :: ALGORITHM_COMPLETED + A_COMBINATORICS audit completed + eventHash = 74c8a2a461c5ef4cdde3a7ea9dc18cc8efe320722733a4a300394cb3829764f5 + + +==================================================================================================== +B. FAST MATRIX EXPONENTIATION +==================================================================================================== +[0015] AUDIT_SESSION :: ALGORITHM_STARTED + Start B_LINEAR_ALGEBRA + eventHash = f8df30a87d0d088df05c68a77806b55d37baf9dd3b6c2206c6d22c88f7f75641 + +[0016] AUDIT_SESSION :: IMPLEMENTATION_CALLED + Call index.js export sum_to_n_b(5) + eventHash = 9280b5ff9e2dfd9fc8e13d8e077505c6d810926cc8aa496fcc3dd040accee363 + +[0017] AUDIT_SESSION :: IMPLEMENTATION_RETURNED + index.js returned 15 + eventHash = 5883ec9607b25da5ef18bdf2b3634e35a40d6904120d32211fa770805412460c + +[0018] B_LINEAR_ALGEBRA :: INPUT_RECEIVED + Receive n = 5 + eventHash = e50fe68ff7c623150d1dd50aeaf74d7938f4aef062d27e2379a44833de889237 + +[0019] B_LINEAR_ALGEBRA :: INPUT_VALIDATED + Input is a safe integer = true + Result range is safe = true + eventHash = 428d84f1bfd0dee2bacfebc9180829216cd235484a1de89fe53dc34fdec8531b + +[0020] B_LINEAR_ALGEBRA :: MAGNITUDE_CALCULATED + |n| = 5 + eventHash = b6e6108117171886d75f861366e3e3fd3567bbd76e3d4fef1937c4e8f3a5cadc + +[0021] B_LINEAR_ALGEBRA :: STATE_MODEL_DEFINED + State vector = [sum_k, k, 1]^T + Initial vector = [0, 0, 1]^T + Transition matrix: + │ 1 1 1 │ + │ 0 1 1 │ + │ 0 0 1 │ + eventHash = c449dc900dca86f9d58df17f1d9778f3831cda1679cdf0dfcd05bf5768604da8 + +[0022] B_LINEAR_ALGEBRA :: MATRIX_POWER_INITIALIZED + Compute M^5 by exponentiation by squaring + Initial result matrix: + │ 1 0 0 │ + │ 0 1 0 │ + │ 0 0 1 │ + Initial base matrix: + │ 1 1 1 │ + │ 0 1 1 │ + │ 0 0 1 │ + eventHash = 2f8a43d7789e0c9fad1175dc529f5aae1652d65786e2e7bb259900a65b954db9 + +[0023] B_LINEAR_ALGEBRA :: POWER_ROUND_STARTED + Round 1: exponent 5 is odd + eventHash = c5134b3b9842c5cc18ffa3ae57a67be86ff437655ff457f4396fed2d96364eda + +[0024] B_LINEAR_ALGEBRA :: MATRIX_MULTIPLICATION_STARTED + ACCUMULATE_RESULT, round 1 + Left: + │ 1 0 0 │ + │ 0 1 0 │ + │ 0 0 1 │ + Right: + │ 1 1 1 │ + │ 0 1 1 │ + │ 0 0 1 │ + eventHash = 8416bb21dad9195b93d5a5f192c03c5e09b496c121420b374cd8242490a5e840 + +[0025] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [1,1] = 1×1 + 0×0 + 0×0 = 1 + eventHash = 52b08f88d7e938a1944a161d675cbe0157e6400bae67926b763c8eb45344d1fd + +[0026] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [1,2] = 1×1 + 0×1 + 0×0 = 1 + eventHash = aeebed7b2271713dd9c30c82603f527c889042ebcef1b6544bf5b6ea15eaa8e0 + +[0027] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [1,3] = 1×1 + 0×1 + 0×1 = 1 + eventHash = caf780b367a824d2f6ece1cc8f370e7e9b7694bdab8b2e1244a21713e6c1faa7 + +[0028] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [2,1] = 0×1 + 1×0 + 0×0 = 0 + eventHash = cb5f9c106fd2afe6b10be053b4e45d4cb59f793ef6cc365ff1622b6bf73e376a + +[0029] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [2,2] = 0×1 + 1×1 + 0×0 = 1 + eventHash = 48a8b54e857a113e0019f0b6d96893f6f70d8e690b9d561a65a31bee8934e0ad + +[0030] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [2,3] = 0×1 + 1×1 + 0×1 = 1 + eventHash = 7e8c30ee0912b415b0a44505aefac7c15e53b0c398939cd2eb5e44841ae23874 + +[0031] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [3,1] = 0×1 + 0×0 + 1×0 = 0 + eventHash = d72e6223afe9874e433e417e70330dc0e35ed0c513f97d3de2aee4a69fc21166 + +[0032] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [3,2] = 0×1 + 0×1 + 1×0 = 0 + eventHash = 317a0303aaefce315148d589c75edf272cb000a3c4affd09564b5a674b8ab265 + +[0033] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [3,3] = 0×1 + 0×1 + 1×1 = 1 + eventHash = 856484db19bde55cd695a31da782f25359c9517da6cf24f5bcb8c58bb83ca66a + +[0034] B_LINEAR_ALGEBRA :: MATRIX_MULTIPLICATION_COMPLETED + ACCUMULATE_RESULT result: + │ 1 1 1 │ + │ 0 1 1 │ + │ 0 0 1 │ + eventHash = 9fb33ab3648c93aef1dc987bb3cea8153591087c14527988ea4ce0da2f80d0f6 + +[0035] B_LINEAR_ALGEBRA :: RESULT_MATRIX_UPDATED + Accumulated result: + │ 1 1 1 │ + │ 0 1 1 │ + │ 0 0 1 │ + eventHash = 4ada53af846e3e73d38ace887d4f0d51d1b17f969f028cdcf6d452ab74f56940 + +[0036] B_LINEAR_ALGEBRA :: EXPONENT_HALVED + floor(5/2) = 2 + eventHash = b91d882b5d4f311630e0051a59f3677dceaa7d787d0654eaba747e0fb1b709ff + +[0037] B_LINEAR_ALGEBRA :: MATRIX_MULTIPLICATION_STARTED + SQUARE_BASE, round 1 + Left: + │ 1 1 1 │ + │ 0 1 1 │ + │ 0 0 1 │ + Right: + │ 1 1 1 │ + │ 0 1 1 │ + │ 0 0 1 │ + eventHash = 3b1d54fdce434a1a1ebc2f23d578f7105a2e5d536f747aa0a3b7076892bf49ae + +[0038] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [1,1] = 1×1 + 1×0 + 1×0 = 1 + eventHash = eb9035743bfab344e2453549f1f05c32fc1ba65958dd1a6d459a114307b20567 + +[0039] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [1,2] = 1×1 + 1×1 + 1×0 = 2 + eventHash = 5b6b9d3b3d982bf7747242cbda950a6d7bfda10ad411306b444e88dfadf8c1c0 + +[0040] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [1,3] = 1×1 + 1×1 + 1×1 = 3 + eventHash = 99846e32da073c1fe7fb80be6616c1a207b95978599e42f66614b74e237d839b + +[0041] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [2,1] = 0×1 + 1×0 + 1×0 = 0 + eventHash = 62c5f1d040b9e6c22be4b3825ee6572ce13b82107437b4690356f2c9054c25fb + +[0042] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [2,2] = 0×1 + 1×1 + 1×0 = 1 + eventHash = 2d7793df7188ffc546c567907917393f006357fe1fa72cb20a3801836e241c84 + +[0043] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [2,3] = 0×1 + 1×1 + 1×1 = 2 + eventHash = 5bd9dcc08e02ac18b97c8fb2d6ead4d57eb95ec6f5ed51be0732edb74c688df2 + +[0044] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [3,1] = 0×1 + 0×0 + 1×0 = 0 + eventHash = 839365b1d4c0045f9529a9eeba11cce0ca2172414b12d2027c20a6ddd2c0c792 + +[0045] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [3,2] = 0×1 + 0×1 + 1×0 = 0 + eventHash = f2597fb6af4631e31c3e108b6f93d5ed5d5c45fbc13b3ca727a57375746ea50e + +[0046] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [3,3] = 0×1 + 0×1 + 1×1 = 1 + eventHash = cd78801f7e2fbda00a728f4dce9982520f6d4158d5dda122145bea1aebb00ced + +[0047] B_LINEAR_ALGEBRA :: MATRIX_MULTIPLICATION_COMPLETED + SQUARE_BASE result: + │ 1 2 3 │ + │ 0 1 2 │ + │ 0 0 1 │ + eventHash = d3b963872020b4f1918a24727d566b0a3e0fc701a4868f54cb481735991e446f + +[0048] B_LINEAR_ALGEBRA :: BASE_MATRIX_SQUARED + Squared base: + │ 1 2 3 │ + │ 0 1 2 │ + │ 0 0 1 │ + eventHash = 0689195a5f02a18a8e4282da4db7f366b753e627df7492b964712b978b3ddafd + +[0049] B_LINEAR_ALGEBRA :: POWER_ROUND_STARTED + Round 2: exponent 2 is even + eventHash = c385a4378b90ccffd61000740794d7e6fe15627bc9dfc60cb8dad78f4e419a4b + +[0050] B_LINEAR_ALGEBRA :: RESULT_MULTIPLICATION_SKIPPED + Exponent is even + eventHash = e3e15306969e749353dcd1022869323a04e304bcbb3b79a0bca3a6de5c2d508b + +[0051] B_LINEAR_ALGEBRA :: EXPONENT_HALVED + floor(2/2) = 1 + eventHash = d7088b43608b1baf0c575e85d37d080d325f37fcc4990cbd862af51814eb12b7 + +[0052] B_LINEAR_ALGEBRA :: MATRIX_MULTIPLICATION_STARTED + SQUARE_BASE, round 2 + Left: + │ 1 2 3 │ + │ 0 1 2 │ + │ 0 0 1 │ + Right: + │ 1 2 3 │ + │ 0 1 2 │ + │ 0 0 1 │ + eventHash = 1d18aeaf594b6732d9a850ef8da0b28e9cfc0aa7af423f3f7c8b181336bce888 + +[0053] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [1,1] = 1×1 + 2×0 + 3×0 = 1 + eventHash = 2d825571f6f72da8f121ca782ca6864055c92b488c53e89d1bafc48e2948632e + +[0054] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [1,2] = 1×2 + 2×1 + 3×0 = 4 + eventHash = 763a2bdc8ec4b7760a86f2d1ded0c363de642c01f6f1d74d8cd77e18abb9cff2 + +[0055] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [1,3] = 1×3 + 2×2 + 3×1 = 10 + eventHash = 7689478fba94cefe76123337fc86c62fc4ab73b5fdb99243a6424bdfdfbf969c + +[0056] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [2,1] = 0×1 + 1×0 + 2×0 = 0 + eventHash = 8474bdf99a6484957601be5b7d1002bc7d261622d82284278bbe1d375327321d + +[0057] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [2,2] = 0×2 + 1×1 + 2×0 = 1 + eventHash = 4c9058c42186c6369a4685842e54fc7b3f9a2e2f0f5b516540e1830e45811698 + +[0058] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [2,3] = 0×3 + 1×2 + 2×1 = 4 + eventHash = 0b7077086e14e478e06aa4dd36cd6028ad3ab978d41c723eb0212e2046f8306e + +[0059] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [3,1] = 0×1 + 0×0 + 1×0 = 0 + eventHash = 9fa266a6cd4c48ecd9510927cf48755fa26890faee72446e23e24797dcfb9dcd + +[0060] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [3,2] = 0×2 + 0×1 + 1×0 = 0 + eventHash = e7089f64a9106283859a752965b5914a76b49a6215e592007e7a99af1e8b2053 + +[0061] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [3,3] = 0×3 + 0×2 + 1×1 = 1 + eventHash = 98109056d4d503a7c9d83ffaf9067ae32d0fb1c7c82b99c437d43a0c2ed193af + +[0062] B_LINEAR_ALGEBRA :: MATRIX_MULTIPLICATION_COMPLETED + SQUARE_BASE result: + │ 1 4 10 │ + │ 0 1 4 │ + │ 0 0 1 │ + eventHash = fec068e8079982a8feb36e7114e153c87977d3b931100a204800316d2255cb1a + +[0063] B_LINEAR_ALGEBRA :: BASE_MATRIX_SQUARED + Squared base: + │ 1 4 10 │ + │ 0 1 4 │ + │ 0 0 1 │ + eventHash = 28301aef3ce38cf6c5169c9584eb35491f7ccfc7129b3b139f23aace32fd3ca0 + +[0064] B_LINEAR_ALGEBRA :: POWER_ROUND_STARTED + Round 3: exponent 1 is odd + eventHash = f76837b4362d9c2145a30985bcc33a85ffbafae2fe447411b1615bbb7d7484b3 + +[0065] B_LINEAR_ALGEBRA :: MATRIX_MULTIPLICATION_STARTED + ACCUMULATE_RESULT, round 3 + Left: + │ 1 1 1 │ + │ 0 1 1 │ + │ 0 0 1 │ + Right: + │ 1 4 10 │ + │ 0 1 4 │ + │ 0 0 1 │ + eventHash = 7f1e48d63e4350996066ee937a0e1aec8cae6c40ce1b85caa5704d1e235eddd8 + +[0066] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [1,1] = 1×1 + 1×0 + 1×0 = 1 + eventHash = 7ab4a371a97f92809d8e60bc0bd4059e7d4ecf70520dfb3b077c42e253bc90a8 + +[0067] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [1,2] = 1×4 + 1×1 + 1×0 = 5 + eventHash = a6b24825c3d4f37a3ffef473ec2bc89e0b23ef30cdfd2522335e76d4f680cf0f + +[0068] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [1,3] = 1×10 + 1×4 + 1×1 = 15 + eventHash = dce3a97f2320c260a4a68871c4c4f30d2a19a19bafdf4fec7f195222ea385c7f + +[0069] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [2,1] = 0×1 + 1×0 + 1×0 = 0 + eventHash = c83b86df35a481739e102aca4e41d5972e4ddeeceae0962823e6429a23b67593 + +[0070] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [2,2] = 0×4 + 1×1 + 1×0 = 1 + eventHash = 66f87202bc50b0ff3c7a8b5f8381c47569216ed7deeed5616f8a3870f6a4453d + +[0071] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [2,3] = 0×10 + 1×4 + 1×1 = 5 + eventHash = ee95d060872d58326ee06ca7a3fcd8721c860b9312938ef3af1dad1b0b9c89c4 + +[0072] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [3,1] = 0×1 + 0×0 + 1×0 = 0 + eventHash = bc65394a7c5b803331a8d777265e738a41577808cd100839ff2f4716e80873ed + +[0073] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [3,2] = 0×4 + 0×1 + 1×0 = 0 + eventHash = 41b3fdef749f260b26d6cbd430edf3ff3d67d564d4e652b5d6e6bd63b8a4871f + +[0074] B_LINEAR_ALGEBRA :: MATRIX_CELL_CALCULATED + Cell [3,3] = 0×10 + 0×4 + 1×1 = 1 + eventHash = 5b07e4cf75430ce82b0d24c8d28d30dfdaa239b4a0b98db10d7edce2bfdf02d5 + +[0075] B_LINEAR_ALGEBRA :: MATRIX_MULTIPLICATION_COMPLETED + ACCUMULATE_RESULT result: + │ 1 5 15 │ + │ 0 1 5 │ + │ 0 0 1 │ + eventHash = ef791f6603877bce08bac953bc593a320a19ad3e7fc7f4df1758b17955fef5c8 + +[0076] B_LINEAR_ALGEBRA :: RESULT_MATRIX_UPDATED + Accumulated result: + │ 1 5 15 │ + │ 0 1 5 │ + │ 0 0 1 │ + eventHash = 3e85f7f6c54ce4364e96725498e1a80dde7a546858c548ac9a3f39b9e7e7327a + +[0077] B_LINEAR_ALGEBRA :: EXPONENT_HALVED + floor(1/2) = 0 + eventHash = aee57155fcaedf179754033f841f79dc2e5d81e3752a91f2dd8047cb7dcc69e8 + +[0078] B_LINEAR_ALGEBRA :: FINAL_BASE_SQUARE_SKIPPED + No exponent bits remain + eventHash = 7193561a5941ff6ab269a5a848749c895f065c161e5740bf29867d34d163abf4 + +[0079] B_LINEAR_ALGEBRA :: MATRIX_POWER_COMPLETED + M^5: + │ 1 5 15 │ + │ 0 1 5 │ + │ 0 0 1 │ + eventHash = 868d42c0037f625bec4a1da41a0f185674491e06cb1f5c96c28d5cc221e2b3b6 + +[0080] B_LINEAR_ALGEBRA :: INITIAL_VECTOR_APPLIED + [0, 0, 1]^T → [15, 5, 1]^T + First component = 15 + eventHash = 38de863ce4c24bf2910e96a713dde17d08339eb471b9fd131e1769ddbb4c9a17 + +[0081] B_LINEAR_ALGEBRA :: SIGN_RESTORED + Restore sign: 15 → 15 + eventHash = 665866ef2140d78af6212ab5264bd801a55fa4c21fbd7925dab257abd82aed87 + +[0082] B_LINEAR_ALGEBRA :: PROOF_COMPLETED + Proof result = 15 + eventHash = 86e803ad74caedfd85495439f687245ccb11360b6659750c1edaae9c4f049aff + +[0083] AUDIT_SESSION :: IMPLEMENTATION_VERIFIED + Implementation result = 15 + Independent proof result = 15 + Match = true + eventHash = f3b6ecf8ec3d06fbc09b8c8642c3b5ce6838a39c356433d15e2ba9fd1456332e + +[0084] AUDIT_SESSION :: ALGORITHM_COMPLETED + B_LINEAR_ALGEBRA audit completed + eventHash = 4812a60375341298e47a3d24c51115c20b905ede6750cb8bb5d8bc97bb95d1f1 + + +==================================================================================================== +C. SYMMETRIC PAIRING +==================================================================================================== +[0085] AUDIT_SESSION :: ALGORITHM_STARTED + Start C_PROBABILITY_SYMMETRY + eventHash = d49cace64b1dd3f6be950621173803220cc22a31b92450b0675baa16c3ffb0e5 + +[0086] AUDIT_SESSION :: IMPLEMENTATION_CALLED + Call index.js export sum_to_n_c(5) + eventHash = 0dafc19a3c669003c18ad39e923a3f76fdecc3a79e8a8c0b22d55243c6d66f99 + +[0087] AUDIT_SESSION :: IMPLEMENTATION_RETURNED + index.js returned 15 + eventHash = 346321b10307343a187d5f266b46b6a2b05ee24952a1509320efe977f23f0316 + +[0088] C_PROBABILITY_SYMMETRY :: INPUT_RECEIVED + Receive n = 5 + eventHash = f23d39a97dd15f84ba32d9856444aeae69d555016b03249a9103898c04bc433e + +[0089] C_PROBABILITY_SYMMETRY :: INPUT_VALIDATED + Input is a safe integer = true + Result range is safe = true + eventHash = 2f35ac2f4f28e5289478620e7333f99dbdeff8b9c583b98e69581c9ccd562182 + +[0090] C_PROBABILITY_SYMMETRY :: MAGNITUDE_CALCULATED + |n| = 5 + eventHash = e4781e716c4314c0736ffbbdba0c1726a73a07e6eb9423b4f355edea76198ec7 + +[0091] C_PROBABILITY_SYMMETRY :: ANTITHETIC_MODEL_DEFINED + Sample space {1, 2, ..., 5} + Mapping x ↔ n + 1 - x + Pair count = 2 + Each pair sums to 6 + eventHash = 6d7f1e84d9021d380c8f57e190c4d3c8d1a166dfdb3d1b219db0718ccfd2709f + +[0092] C_PROBABILITY_SYMMETRY :: PAIRED_TOTAL_CALCULATED + 2 × 6 = 12 + eventHash = 04276840f7a686c591d7a6000490e241936ea61b33e83673b92e187df9e2e8f0 + +[0093] C_PROBABILITY_SYMMETRY :: MIDDLE_VALUE_ADDED + 12 + middle 3 = 15 + eventHash = 25e4734c3e51ea182d3ee8451dde8e053318f6447be3a51bb4b6dc3430342536 + +[0094] C_PROBABILITY_SYMMETRY :: SIGN_RESTORED + Restore sign: 15 → 15 + eventHash = c78980b9365a9d2f97087ab22dfdfeea3e069dabf0ea665618aaada80dc56888 + +[0095] C_PROBABILITY_SYMMETRY :: PROOF_COMPLETED + Proof result = 15 + eventHash = 3ec24d81a3f26f568bc09f4753d1bf96025d7eb5de776707cef54eab001a3524 + +[0096] AUDIT_SESSION :: IMPLEMENTATION_VERIFIED + Implementation result = 15 + Independent proof result = 15 + Match = true + eventHash = b6ab542703131c1839ff735b4c968be5dd824d62e4eca3d262c2ce4ca78842cf + +[0097] AUDIT_SESSION :: ALGORITHM_COMPLETED + C_PROBABILITY_SYMMETRY audit completed + eventHash = 55c4bac5dc320eb94f500defeed4cd9bc851a86076afbd78ba2cdfa6d09baecf + +[0098] AUDIT_SESSION :: RESULTS_CROSS_CHECKED + Results = {"a":15,"b":15,"c":15} + All implementations agree = true + eventHash = 9d108dd269190fd7ef22db3beef1b939d399af30f18fa5dd8e581e265183ee9a + +[0099] AUDIT_SESSION :: INDEPENDENT_REFERENCE_CALCULATED + BigInt reference = 15 + All results match reference = true + eventHash = 2c5561e4c7f38509df9f1d361b6a24728d34ac793a32b446df348c18286830c3 + +[0100] AUDIT_SESSION :: SESSION_PASSED + Audit status = PASSED + eventHash = b92a5d941a1eb3650f22ec4388ebcf9ef56425c685abd6b406e7b02eaeaee1c8 + + +==================================================================================================== +AUDIT SUMMARY +==================================================================================================== +Status: PASSED +Results: {"a":15,"b":15,"c":15} +Proof checks: {"a":{"proofResult":15,"matches":true},"b":{"proofResult":15,"matches":true},"c":{"proofResult":15,"matches":true}} +Events: 100 +Final event hash: b92a5d941a1eb3650f22ec4388ebcf9ef56425c685abd6b406e7b02eaeaee1c8 +Raw evidence SHA-256: 4d36a57597bdcfe01f923ff3471243a9f56d73c6afc398fc7b6034bbe45ef36b diff --git a/src/problem1/logs/audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.manifest.json b/src/problem1/logs/audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.manifest.json new file mode 100644 index 0000000000..a14aede807 --- /dev/null +++ b/src/problem1/logs/audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.manifest.json @@ -0,0 +1,38 @@ +{ + "schemaVersion": 2, + "auditId": "bd12e062-3452-4783-8449-b9e8111d8807", + "input": 5, + "selectedAlgorithm": "all", + "status": "PASSED", + "startedAt": "2026-08-03T13:53:29.936Z", + "completedAt": "2026-08-03T13:53:30.040Z", + "results": { + "a": 15, + "b": 15, + "c": 15 + }, + "proofChecks": { + "a": { + "proofResult": 15, + "matches": true + }, + "b": { + "proofResult": 15, + "matches": true + }, + "c": { + "proofResult": 15, + "matches": true + } + }, + "error": null, + "eventCount": 100, + "finalEventHash": "b92a5d941a1eb3650f22ec4388ebcf9ef56425c685abd6b406e7b02eaeaee1c8", + "rawSha256": "4d36a57597bdcfe01f923ff3471243a9f56d73c6afc398fc7b6034bbe45ef36b", + "files": { + "human": "audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.log", + "raw": "audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.jsonl", + "manifest": "audit-2026-08-03T13-53-29-937Z-pid-37732-d166195fda-n-5.manifest.json" + }, + "humanSha256": "39bd51c20b90936e42928bd25ad47647c8d747f4c84a33e43f37aab7f9ea6f99" +} \ No newline at end of file diff --git a/src/problem1/logs/stress-test-2026-08-03T13-54-01-915Z.json b/src/problem1/logs/stress-test-2026-08-03T13-54-01-915Z.json new file mode 100644 index 0000000000..78d0092538 --- /dev/null +++ b/src/problem1/logs/stress-test-2026-08-03T13-54-01-915Z.json @@ -0,0 +1,213 @@ +{ + "status": "PASSED", + "mode": "standard", + "seed": 20260803, + "node": "v22.23.2", + "platform": "win32 x64", + "assertions": 14312, + "passedSuites": 17, + "totalSuites": 17, + "durationMs": 2032.4248, + "suites": [ + { + "name": "Valid edge cases and exact BigInt oracle", + "status": "PASSED", + "durationMs": 8.654000000000003, + "assertions": 116, + "metadata": { + "cases": 20 + } + }, + { + "name": "Exhaustive signed range", + "status": "PASSED", + "durationMs": 18.640600000000006, + "assertions": 4001, + "metadata": { + "range": "[-2000, 2000]", + "cases": 4001 + } + }, + { + "name": "Deterministic randomized coverage", + "status": "PASSED", + "durationMs": 36.682199999999995, + "assertions": 5500, + "metadata": { + "allImplementationCases": 500, + "fastImplementationCases": 5000 + } + }, + { + "name": "Safe-result boundary precision", + "status": "PASSED", + "durationMs": 2.126499999999993, + "assertions": 66, + "metadata": { + "maximumInput": 134217727, + "maximumResult": "9007199187632128" + } + }, + { + "name": "Invalid type and non-integer rejection", + "status": "PASSED", + "durationMs": 1.4111000000000047, + "assertions": 45, + "metadata": { + "invalidValues": 15, + "implementations": 3 + } + }, + { + "name": "Out-of-contract safe-result overflow rejection", + "status": "PASSED", + "durationMs": 0.8281999999999812, + "assertions": 12, + "metadata": { + "rejectedValues": [ + 134217728, + -134217728, + 9007199254740991, + -9007199254740991 + ] + } + }, + { + "name": "Mathematical invariants", + "status": "PASSED", + "durationMs": 38.256699999999995, + "assertions": 4500, + "metadata": { + "cases": 500, + "properties": [ + "S(-n) = -S(n)", + "S(n) - S(n - 1) = n", + "2S(n) = n(n + 1)" + ] + } + }, + { + "name": "Pure index functions and separate audit wrapper contract", + "status": "PASSED", + "durationMs": 2.1657000000000153, + "assertions": 28, + "metadata": { + "pureImplementations": 3, + "auditedImplementations": 3, + "writerFailurePropagates": true + } + }, + { + "name": "Audit CLI happy path and proof verification", + "status": "PASSED", + "durationMs": 302.6874, + "assertions": 6, + "metadata": { + "programmaticManifest": "C:\\Users\\TRONGP~1\\AppData\\Local\\Temp\\problem1-quality-naEJkC\\audit-happy\\audit-2026-08-03T13-54-02-060Z-pid-35960-ae0c0708a1-n-5.manifest.json", + "cliManifest": "C:\\Users\\TRONGP~1\\AppData\\Local\\Temp\\problem1-quality-naEJkC\\audit-cli\\audit-2026-08-03T13-54-02-230Z-pid-27940-92348ed637-n-5.manifest.json" + } + }, + { + "name": "Audit CLI invalid argument paths", + "status": "PASSED", + "durationMs": 314.20699999999994, + "assertions": 10, + "metadata": { + "cases": 5 + } + }, + { + "name": "File-system failure path", + "status": "PASSED", + "durationMs": 64.98889999999994, + "assertions": 2, + "metadata": { + "invalidLogPath": "C:\\Users\\TRONGP~1\\AppData\\Local\\Temp\\problem1-quality-naEJkC\\not-a-directory" + } + }, + { + "name": "Injected algorithm failure with partial error audit", + "status": "PASSED", + "durationMs": 26.01329999999996, + "assertions": 4, + "metadata": { + "manifest": "C:\\Users\\TRONGP~1\\AppData\\Local\\Temp\\problem1-quality-naEJkC\\injected-error\\audit-2026-08-03T13-54-02-742Z-pid-35960-0b4d420748-n-5.manifest.json", + "partialResults": { + "a": 15 + } + } + }, + { + "name": "Mutation-test sensitivity", + "status": "PASSED", + "durationMs": 0.6137999999999693, + "assertions": 4, + "metadata": { + "mutants": [ + "off-by-one", + "wrong-negative-sign", + "skip-odd-middle", + "matrix-result-column-bug" + ], + "allDetected": true + } + }, + { + "name": "Tamper and truncation detection", + "status": "PASSED", + "durationMs": 109.45609999999999, + "assertions": 4, + "metadata": { + "modifiedEventDetected": true, + "truncationDetected": true + } + }, + { + "name": "Concurrent audit isolation and filename uniqueness", + "status": "PASSED", + "durationMs": 703.6011, + "assertions": 10, + "metadata": { + "processes": 6, + "uniqueAuditIds": 6, + "uniqueManifests": 6 + } + }, + { + "name": "Subprocess timeout detection", + "status": "PASSED", + "durationMs": 121.19709999999986, + "assertions": 1, + "metadata": { + "timeoutMilliseconds": 100, + "detected": true + } + }, + { + "name": "Performance and long-loop execution", + "status": "PASSED", + "durationMs": 240.7496000000001, + "assertions": 3, + "metadata": { + "batchCases": 50000, + "A": { + "durationMs": 7.491200000000163, + "checksum": 546216287 + }, + "B": { + "durationMs": 225.5766000000001, + "checksum": 546216287 + }, + "C": { + "input": 1000000, + "durationMs": 0.4740999999999076 + } + } + } + ], + "failures": [], + "reports": { + "text": "D:\\99\\code-challenge\\src\\problem1\\logs\\stress-test-2026-08-03T13-54-01-915Z.log", + "json": "D:\\99\\code-challenge\\src\\problem1\\logs\\stress-test-2026-08-03T13-54-01-915Z.json" + } +} \ No newline at end of file diff --git a/src/problem1/logs/stress-test-2026-08-03T13-54-01-915Z.log b/src/problem1/logs/stress-test-2026-08-03T13-54-01-915Z.log new file mode 100644 index 0000000000..54f6d79438 --- /dev/null +++ b/src/problem1/logs/stress-test-2026-08-03T13-54-01-915Z.log @@ -0,0 +1,64 @@ +99TECH Problem 1 — Complete quality suite +Mode: standard +Seed: 20260803 +Node: v22.23.2 +Temporary test root: C:\Users\TRONGP~1\AppData\Local\Temp\problem1-quality-naEJkC + +[RUN ] Valid edge cases and exact BigInt oracle +[PASS] Valid edge cases and exact BigInt oracle | 8.65 ms | 116 assertions + +[RUN ] Exhaustive signed range +[PASS] Exhaustive signed range | 18.64 ms | 4,001 assertions + +[RUN ] Deterministic randomized coverage +[PASS] Deterministic randomized coverage | 36.68 ms | 5,500 assertions + +[RUN ] Safe-result boundary precision +[PASS] Safe-result boundary precision | 2.13 ms | 66 assertions + +[RUN ] Invalid type and non-integer rejection +[PASS] Invalid type and non-integer rejection | 1.41 ms | 45 assertions + +[RUN ] Out-of-contract safe-result overflow rejection +[PASS] Out-of-contract safe-result overflow rejection | 0.83 ms | 12 assertions + +[RUN ] Mathematical invariants +[PASS] Mathematical invariants | 38.26 ms | 4,500 assertions + +[RUN ] Pure index functions and separate audit wrapper contract +[PASS] Pure index functions and separate audit wrapper contract | 2.17 ms | 28 assertions + +[RUN ] Audit CLI happy path and proof verification +[PASS] Audit CLI happy path and proof verification | 302.69 ms | 6 assertions + +[RUN ] Audit CLI invalid argument paths +[PASS] Audit CLI invalid argument paths | 314.21 ms | 10 assertions + +[RUN ] File-system failure path +[PASS] File-system failure path | 64.99 ms | 2 assertions + +[RUN ] Injected algorithm failure with partial error audit +[PASS] Injected algorithm failure with partial error audit | 26.01 ms | 4 assertions + +[RUN ] Mutation-test sensitivity +[PASS] Mutation-test sensitivity | 0.61 ms | 4 assertions + +[RUN ] Tamper and truncation detection +[PASS] Tamper and truncation detection | 109.46 ms | 4 assertions + +[RUN ] Concurrent audit isolation and filename uniqueness +[PASS] Concurrent audit isolation and filename uniqueness | 703.60 ms | 10 assertions + +[RUN ] Subprocess timeout detection +[PASS] Subprocess timeout detection | 121.20 ms | 1 assertions + +[RUN ] Performance and long-loop execution +[PASS] Performance and long-loop execution | 240.75 ms | 3 assertions + +==================================================================================================== +QUALITY SUITE STATUS: PASSED +Suites: 17/17 passed +Assertions: 14,312 +Duration: 2.03 s +Text report: D:\99\code-challenge\src\problem1\logs\stress-test-2026-08-03T13-54-01-915Z.log +JSON report: D:\99\code-challenge\src\problem1\logs\stress-test-2026-08-03T13-54-01-915Z.json diff --git a/src/problem1/stress-test.js b/src/problem1/stress-test.js index c5c9e29447..e103770d44 100644 --- a/src/problem1/stress-test.js +++ b/src/problem1/stress-test.js @@ -29,6 +29,7 @@ const { const { DEFAULT_ALGORITHMS, + auditAlgorithm, runAudit, } = require("./audit"); @@ -325,8 +326,8 @@ class Runner { ); await this.suite( - "Audit callback schema and logger failure propagation", - () => this.auditCallbackContract(), + "Pure index functions and separate audit wrapper contract", + () => this.separatedAuditContract(), ); await this.suite( @@ -743,37 +744,71 @@ class Runner { }; } - auditCallbackContract() { - for (const [label, algorithm, implementation] of [ - ["A", "A_COMBINATORICS", sum_to_n_a], - ["B", "B_LINEAR_ALGEBRA", sum_to_n_b], - ["C", "C_PROBABILITY_SYMMETRY", sum_to_n_c], + separatedAuditContract() { + // index.js functions stay pure: they return a number and do not depend on + // an audit callback or any file-system/logger behavior. + for (const [label, implementation] of [ + ["A", sum_to_n_a], + ["B", sum_to_n_b], + ["C", sum_to_n_c], ]) { - const events = []; - const result = implementation( - 5, - (event) => events.push(event), + this.assert( + implementation.length === 1, + `${label} should expose exactly one declared parameter`, + { declaredParameters: implementation.length }, ); + this.assert( + implementation(5) === 15, + `${label} pure result mismatch`, + ); + } + + // audit.js owns instrumentation. auditAlgorithm wraps an index.js export, + // builds a separate proof, and emits structured events. + for (const [key, expectedAlgorithm] of [ + ["a", "A_COMBINATORICS"], + ["b", "B_LINEAR_ALGEBRA"], + ["c", "C_PROBABILITY_SYMMETRY"], + ]) { + const events = []; + const audited = auditAlgorithm({ + key, + n: 5, + algorithm: DEFAULT_ALGORITHMS[key], + writeEvent: (event) => events.push(event), + }); - this.assert(result === 15, `${label} result mismatch`); - this.assert(events.length > 0, `${label} emitted no events`); this.assert( - events[0].action === "INPUT_RECEIVED", - `${label} first event mismatch`, + audited.result === 15, + `${key.toUpperCase()} audited result mismatch`, + ); + this.assert( + audited.proofResult === 15, + `${key.toUpperCase()} proof result mismatch`, + ); + this.assert( + audited.matches === true, + `${key.toUpperCase()} implementation/proof mismatch`, + ); + this.assert( + events.length > 0, + `${key.toUpperCase()} audit emitted no events`, + ); + this.assert( + events[0].action === "ALGORITHM_STARTED", + `${key.toUpperCase()} first audit event mismatch`, ); this.assert( - events.at(-1).action === "COMPLETED", - `${label} terminal event mismatch`, + events.at(-1).action === "ALGORITHM_COMPLETED", + `${key.toUpperCase()} terminal audit event mismatch`, ); this.assert( - events.every( + events.some( (event) => - event.algorithm === algorithm && - typeof event.action === "string" && - event.data && - typeof event.data === "object", + event.algorithm === expectedAlgorithm && + event.action === "PROOF_COMPLETED", ), - `${label} event schema mismatch`, + `${key.toUpperCase()} proof events missing`, ); } @@ -781,8 +816,13 @@ class Runner { let propagated; try { - sum_to_n_a(5, () => { - throw sentinel; + auditAlgorithm({ + key: "a", + n: 5, + algorithm: DEFAULT_ALGORITHMS.a, + writeEvent() { + throw sentinel; + }, }); } catch (error) { propagated = error; @@ -790,12 +830,13 @@ class Runner { this.assert( propagated === sentinel, - "Audit callback failure was silently swallowed", + "Separate audit writer failure was silently swallowed", ); return { - implementations: 3, - loggerFailurePropagates: true, + pureImplementations: 3, + auditedImplementations: 3, + writerFailurePropagates: true, }; } @@ -998,13 +1039,7 @@ class Runner { ...DEFAULT_ALGORITHMS, b: { ...DEFAULT_ALGORITHMS.b, - run(n, audit) { - audit({ - algorithm: "B_LINEAR_ALGEBRA", - action: "FAULT_INJECTION_STARTED", - data: { n }, - }); - + run() { throw new Error("Injected matrix failure"); }, },