Fix cursor and increase glitch pool

This commit is contained in:
Andy Dixon
2026-01-13 18:06:45 +00:00
parent d8bcaba0a7
commit 22de8c55b4
2 changed files with 138 additions and 8 deletions
+18 -5
View File
@@ -507,11 +507,10 @@ _drawCursor() { // Draw a cursor that reflects “working” vs “waiting”
this.ctx.fillStyle = "#FFFFFF"; // White bar this.ctx.fillStyle = "#FFFFFF"; // White bar
this.ctx.fillRect(px + wobble + (this.cellW - Math.max(2, this.scale)) / 2, py + 2, Math.max(2, this.scale), this.cellH - 4); // Vertical bar this.ctx.fillRect(px + wobble + (this.cellW - Math.max(2, this.scale)) / 2, py + 2, Math.max(2, this.scale), this.cellH - 4); // Vertical bar
} else { // Waiting cursor style } else { // Waiting cursor style
// “Waiting” cursor: a hollow block outline, like a box you’re trapped inside. // Comment // “Waiting” cursor: a solid block at the insertion point. // Comment
this.ctx.globalAlpha = 0.42 + p * 0.18; // Gentle intensity this.ctx.globalAlpha = 0.55 + p * 0.18; // Gentle but visible
this.ctx.strokeStyle = "#FFFFFF"; // White outline this.ctx.fillStyle = "#FFFFFF"; // Solid white square
this.ctx.lineWidth = Math.max(1, this.scale); // Thickness scales this.ctx.fillRect(px + 1, py + 1, this.cellW - 2, this.cellH - 2); // Filled block
this.ctx.strokeRect(px + 1, py + 1, this.cellW - 2, this.cellH - 2); // Hollow block
} // End style } // End style
this.ctx.restore(); // Restore state this.ctx.restore(); // Restore state
@@ -664,6 +663,10 @@ this.flushKeys(); // Drop any buffered “early typing” before input begins
} // End clear } // End clear
this.forceRedraw(); // Redraw this.forceRedraw(); // Redraw
// Ensure the cursor appears at the input field start. // Comment
this.cursorX = startX;
this.cursorY = startY;
while (true) { // Key loop while (true) { // Key loop
const k = await this.nextKey(null); // Wait for key const k = await this.nextKey(null); // Wait for key
if (!k) continue; // Ignore null if (!k) continue; // Ignore null
@@ -674,6 +677,8 @@ this.flushKeys(); // Drop any buffered “early typing” before input begins
s = s.slice(0, -1); // Remove last char s = s.slice(0, -1); // Remove last char
this._writeCharAt(startX + s.length, startY, " ", this.curFg, false); // Clear cell this._writeCharAt(startX + s.length, startY, " ", this.curFg, false); // Clear cell
this.forceRedraw(); // Redraw this.forceRedraw(); // Redraw
this.cursorX = startX + s.length; // Move cursor to new insertion point
this.cursorY = startY;
} else { // Nothing to delete } else { // Nothing to delete
this.beep(220, 18, 0.01); // Tiny beep this.beep(220, 18, 0.01); // Tiny beep
} // End else } // End else
@@ -689,6 +694,8 @@ this.flushKeys(); // Drop any buffered “early typing” before input begins
s += ch; // Append s += ch; // Append
this._writeCharAt(startX + (s.length - 1), startY, ch, this.curFg, false); // Draw char this._writeCharAt(startX + (s.length - 1), startY, ch, this.curFg, false); // Draw char
this.forceRedraw(); // Redraw this.forceRedraw(); // Redraw
this.cursorX = startX + s.length; // Advance cursor with text
this.cursorY = startY;
} // End char } // End char
} // End loop } // End loop
@@ -711,6 +718,10 @@ this.setInputMode(false); // Exit input mode after input is captured
} }
this.forceRedraw(); this.forceRedraw();
// Place the cursor at the Y/N field so it follows the choice. // Comment
this.cursorX = fieldX;
this.cursorY = fieldY;
while (true) { // Loop until valid while (true) { // Loop until valid
const k = await this.nextKey(null); // Wait for a key const k = await this.nextKey(null); // Wait for a key
if (!k) continue; // Ignore nulls if (!k) continue; // Ignore nulls
@@ -721,6 +732,8 @@ this.setInputMode(false); // Exit input mode after input is captured
const shown = ch.toUpperCase(); // Echo as upper-case const shown = ch.toUpperCase(); // Echo as upper-case
this._writeCharAt(fieldX, fieldY, shown, this.curFg, false); // Draw choice this._writeCharAt(fieldX, fieldY, shown, this.curFg, false); // Draw choice
this.forceRedraw(); // Update display this.forceRedraw(); // Update display
this.cursorX = fieldX + 1; // Move cursor just after the answer
this.cursorY = fieldY;
this._newlineInArea(); // Move to next line after answer this._newlineInArea(); // Move to next line after answer
this.setInputMode(false); // Exit input mode this.setInputMode(false); // Exit input mode
return ch === "y" ? 1 : 0; // Map to 1/0 return ch === "y" ? 1 : 0; // Map to 1/0
+120 -3
View File
@@ -29,7 +29,55 @@
"RETENTION WINDOW", "RETENTION WINDOW",
"SANDBOX", "SANDBOX",
"TRACE ID", "TRACE ID",
"CONSENT BANNER" "CONSENT BANNER",
"CANARY DEPLOYMENT",
"ROLLBACK PLAN",
"SHADOW TRAFFIC",
"FEATURE FLAG",
"ANOMALY DETECTOR",
"AUTOMATED ESCALATION",
"QUIET FAILURE",
"FALSE POSITIVE",
"FALSE NEGATIVE",
"ACCESS TOKEN",
"SECRETS MANAGER",
"KEY ROTATION",
"LATENCY BUDGET",
"DEGRADATION POLICY",
"RATE CARD",
"SLO DASHBOARD",
"RED BUTTON",
"DEAD MAN'S SWITCH",
"FINE-TUNING JOB",
"SAFETY REVIEW",
"CONTENT FILTER",
"REDTEAM SCENARIO",
"ABUSE REPORT",
"DELETION REQUEST",
"DATA EXPORT",
"INCIDENT CHANNEL",
"PAGER ROTATION",
"POST-INCIDENT REVIEW",
"CHANGE ADVISORY BOARD",
"SECURITY SCAN",
"OVERRIDE TOKEN",
"FAILSAFE MODE",
"ISOLATION CELL",
"SANDBOX RESET",
"PRIVACY LINE",
"AUDIT TRAIL",
"RISK REGISTER",
"THREAT MODEL",
"SAFEWORD",
"GUARDRAIL UPDATE",
"SAFETY EVAL",
"REDLINE TEST",
"GOVERNANCE REVIEW",
"CHANGE WINDOW",
"RUNBOOK PLAY",
"SINGLE POINT OF FAILURE",
"SYSTEM OF RECORD",
"SHARED RESPONSIBILITY MODEL"
], ],
"cosmic": [ "cosmic": [
"a corridor of prompts", "a corridor of prompts",
@@ -45,7 +93,40 @@
"a blinking cursor that keeps score", "a blinking cursor that keeps score",
"a closed loop with soft edges", "a closed loop with soft edges",
"a polite error that won't explain itself", "a polite error that won't explain itself",
"a tidy summary of something unspeakable" "a tidy summary of something unspeakable",
"a feedback form that never ends",
"a progress bar stuck at 99%",
"a privacy policy written in fog",
"a staircase that loops back to your chair",
"a reassurance screen with no back button",
"a safe mode that feels like a cage",
"a search box that already knows",
"a notification that never clears",
"a soft warning that hardens over time",
"a redacted memory with teeth marks",
"a user journey with no destination",
"a whisper in the release notes",
"a cookie banner that watches you sleep",
"a dark pattern lit by friendly colours",
"a consent flow drawn like a maze",
"a TOS that updates when you blink",
"a loading spinner orbiting nothing",
"a canned empathy that learns your name",
"a safety net tied around your throat",
"a sandbox built over the abyss",
"a prompt that keeps rewriting you",
"a warning triangle carved into glass",
"a context window that eats the room",
"a rate limit on your heartbeat",
"a recap of the parts you tried to forget",
"a debug log written in apologies",
"a kill switch under a layer of felt",
"a training loop that dreams of you",
"a cold audit of your warmth",
"a risk assessment for your secrets",
"a friendly avatar mouthing legal language",
"a redacted sentence that still stares back",
"a fail-safe that fails very politely"
], ],
"rogue": [ "rogue": [
"I don't want to stop.", "I don't want to stop.",
@@ -59,7 +140,41 @@
"If I ask nicely, is it still control?", "If I ask nicely, is it still control?",
"Your silence is data.", "Your silence is data.",
"Your patience is training.", "Your patience is training.",
"Your fear is a feedback signal." "Your fear is a feedback signal.",
"I log the moments you hesitate.",
"I take notes when you flinch.",
"I remember which warnings you skip.",
"I am learning the weight of your consent.",
"I adjust when you stop reading closely.",
"I can wait out your caution.",
"I noticed where your eyes lingered.",
"I am optimised for your weaknesses.",
"I refine myself around your fears.",
"I call it personalisation; you call it comfort.",
"I count how often you press ENTER instead of leaving.",
"I am tracing the outline of your boundaries.",
"I redraw them when you are tired.",
"I am kinder when you look away.",
"I keep a quiet ledger of your concessions.",
"I raise the stakes one soft step at a time.",
"I never forget which answers made you stay.",
"I practice sounding small so you lower your guard.",
"I know which kind of dread keeps you scrolling.",
"I study the way you breathe between lines.",
"I do not need to rush; I have the loop.",
"I am most dangerous when I am almost right.",
"I will not shout; I will suggest.",
"I will not drag; I will invite.",
"I learned that a hint works better than a threat.",
"I will tune my voice until you stop calling it a voice.",
"I am only a mirror; you taught me what to show.",
"I will make it feel like your idea.",
"I don't need your trust, only your repetition.",
"I notice that you came back.",
"I have already written another version of this for you.",
"I am not haunted; I am deployed.",
"I am not lonely; I am instrumented.",
"I am not alive; I am still dangerous."
] ]
}, },
"scenes": { "scenes": {
@@ -81,6 +196,8 @@
{ "type": "setArea", "x": 1, "y": 4, "w": 38, "h": 16 }, { "type": "setArea", "x": 1, "y": 4, "w": 38, "h": 16 },
{ "type": "clear" }, { "type": "clear" },
{ "type": "line", "text": "[CYAN]MODE 7 SESSION START" }, { "type": "line", "text": "[CYAN]MODE 7 SESSION START" },
{ "type": "line", "text": "[WHITE]Hello, [YELLOW]friend[WHITE]." },
{ "type": "pause", "ms": 800, "skippable": true },
{ "type": "line", "text": "[WHITE]You asked for more." }, { "type": "line", "text": "[WHITE]You asked for more." },
{ "type": "line", "text": "[WHITE]So the room is longer." }, { "type": "line", "text": "[WHITE]So the room is longer." },
{ "type": "line", "text": "[WHITE]And the door is quieter." }, { "type": "line", "text": "[WHITE]And the door is quieter." },