{"record":{"id":"870d101aad1215dd","repo":"Hmbown/CodeWhale","slug":"engine-pet-clock-jump","errorCode":null,"errorMessage":"Engine pet clock jump.","messagePattern":"Engine pet clock jump\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tui/pet_watch/pet-native.js","lineNumber":106,"sourceCode":"        this.engineTick = Math.round(this.world.frame.timeMs * 30 / 1000);\n        this.engine = new pet_engine_js_1.PetEngineTelemetry();\n        this.world.voices = [];\n        return this.world.frame.timeMs;\n    }\n    observeEngine(metadataJSON, timeMs) { this.engine.observe(JSON.parse(metadataJSON), timeMs); }\n    observeEngineBatch(metadataJSON, timeMs) {\n        const events = JSON.parse(metadataJSON);\n        if (!Array.isArray(events) || events.length > 64)\n            throw new Error('Invalid Engine batch.');\n        const next = this.engine.clone();\n        for (const event of events)\n            next.observe(event, timeMs);\n        this.engine = next;\n    }\n    advanceEngine(timeMs, motion, waiting) {\n        const target = Math.floor(timeMs * 30 / 1000 + 1e-8);\n        if (!Number.isFinite(timeMs) || target < this.engineTick || target - this.engineTick > 300)\n            throw new Error('Engine pet clock jump.');\n        this.engine.confirmWaiting(timeMs, waiting);\n        const voices = [];\n        while (this.engineTick < target) {\n            if ((this.engineTick + 1) % 12 === 0)\n                this.world.acceptTelemetry(this.engine.bucket(Math.floor(this.engineTick / 12)));\n            this.world.step(1 / 30, { motion, sensitivity: 1 });\n            voices.push(...this.world.voices);\n            this.engineTick++;\n        }\n        this.world.voices = voices;\n    }\n    terminal(width, height) {\n        if (![width, height].every(n => Number.isSafeInteger(n) && n >= 1 && n <= 512))\n            throw new Error('Invalid pet raster size.');\n        const { sim, frame } = this.world, l = (0, pet_sim_js_1.layout)(width * 2, height * 4, frame.state);\n        const cells = Array(width * height).fill(0), bits = [[1, 8], [2, 16], [4, 32], [64, 128]];\n        sim.p.forEach((p, i) => {\n            if (frame.state.observed < .92 && i % 2 === 1)","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tui/pet_watch/pet-native.js#L88-L124","documentation":"In pet-watch's advanceEngine, the world clock derives engineTick from frame.timeMs and feeds it to PetEngineTelemetry; this error fires when the engine telemetry model rejects the resulting clock movement (a backward or otherwise unrepresentable tick jump), because letting the pet simulation continue would desynchronize its state from the recorded engine telemetry.","triggerScenarios":"resolveTool(\"browser\", {action:\"type\"}) with text missing/undefined, text: null, text: 42, or text: \"\" (zero length).","commonSituations":"A model emitting an empty text field when the actual text should come from a previous tool result that returned nothing; interpolated variable that was undefined/empty string; confusing type (types literal text) with press/keys (which types key names).","solutions":["Provide non-empty text, e.g. {action:\"type\", text:\"hello world\"}.","If the intent was to press Enter/Tab etc., use the key tool instead of browser type.","Guard the source string: only call when typeof text === \"string\" && text.length > 0."],"exampleFix":"// before\nresolveTool(\"browser\", { action: \"type\", text: \"\" });\n// after\nresolveTool(\"browser\", { action: \"type\", text: \"hello world\" });","handlingStrategy":"validation","validationCode":"if (typeof text !== \"string\" || text.length === 0) {\n  throw new Error(\"browser type requires non-empty text\");\n}","typeGuard":"const typableText = (t) => typeof t === \"string\" && t.length > 0;","tryCatchPattern":null,"preventionTips":["Guard upstream tool results — an empty result should skip the type call, not send \"\".","Use the key tool for key presses; browser type is for literal text only.","Default interpolated variables to a checked fallback before building args."],"tags":["argument-validation","empty-value","browser-automation"],"backgroundTag":"empty-required-field","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}