From ee8e9228a1fbbbf670dfe5ee8f705d7ae2d559a4 Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Wed, 30 Sep 2026 23:39:58 -0700 Subject: [PATCH] Walkieware: turn off model thinking for visible speed, kidlisp stop button A desktop replay of the slow wwGihap edit through the same relay took 23.7 s over three rounds, and two thirds of all output tokens were DeepSeek's hidden thinking: 11.8 s and 6.3 s before the first visible line, while headers took 0.6 s and code streamed at about 320 tokens/s. Thinking also counts against max_tokens, which is why the phone run hit the output limit. Walkieware now asks for reasoning {effort:"none"}. AcServer forwards a reasoning object when given one; the relay validates OpenRouter's documented shapes (effort, max_tokens, enabled, exclude) and passes them upstream. The deployed relay still drops the field, so the phone benefits after the next lith deploy. The pending row's stop control is kidlisp.com's red disc with a white rounded square. run.sh picks only the physical paired iPhone, since a booted simulator also reports as an iPhone. Builds 70 and 71 recorded in checks.json. Co-Authored-By: Claude Fable 5.1 --- aesel/src/ac-server.mjs | 7 + aesel/test/ac-server.test.mjs | 10 + apple/walkieware/Resources/Web/engine.mjs | 2 +- .../walkieware/Sources/WalkiewareScreen.swift | 28 +- apple/walkieware/Tests/checks.json | 1506 +++++++++-------- .../Walkieware.xcodeproj/project.pbxproj | 4 +- apple/walkieware/project.yml | 2 +- apple/walkieware/run.sh | 2 +- system/backend/easel-policy.mjs | 26 +- system/netlify/functions/easel-inference.mjs | 5 +- system/tests/easel-braincells.test.mjs | 11 + 11 files changed, 851 insertions(+), 752 deletions(-) diff --git a/aesel/src/ac-server.mjs b/aesel/src/ac-server.mjs index 827c421f0e..5244e5249c 100644 --- a/aesel/src/ac-server.mjs +++ b/aesel/src/ac-server.mjs @@ -136,6 +136,11 @@ export class AcServer extends EventEmitter { frameCapture = true, layeredEdits = false, outputContinuations = 0, + // OpenRouter's `reasoning` object, forwarded as given. A surface that shows + // the piece being written wants {effort:"none"}: a reasoning model's + // hidden thinking streams nothing visible, and on Walkieware it measured + // as two thirds of all output tokens and ten seconds before the first line. + reasoning = null, } = {}) { super(); this.cwd = cwd; @@ -148,6 +153,7 @@ export class AcServer extends EventEmitter { this.frameCapture = frameCapture; this.layeredEdits = layeredEdits; this.outputContinuations = Math.max(0, Math.min(8, outputContinuations)); + this.reasoning = reasoning && typeof reasoning === "object" ? reasoning : null; this.approvals = new Map(); this.model = (Object.hasOwn(models, model) ? models[model] : model) || fallbackModel; // No model named on the relay is Automatic: the request names none, and @@ -408,6 +414,7 @@ export class AcServer extends EventEmitter { tools, // A workspace turn writes whole files; the relay allows it up to 32,000. max_tokens: this.endpoint || this.workspace ? 32000 : 8192, + ...(this.reasoning ? {reasoning: this.reasoning} : {}), ...(this.endpoint ? {stream: true} : {}), }), }), {controller, timeoutMs:this.networkTimeouts.connect}); } diff --git a/aesel/test/ac-server.test.mjs b/aesel/test/ac-server.test.mjs index e1ac65295f..32b7227325 100644 --- a/aesel/test/ac-server.test.mjs +++ b/aesel/test/ac-server.test.mjs @@ -376,6 +376,16 @@ test('embedded preview can retain runtime feedback without offering desktop fram } }); +test('a reasoning object is forwarded as given, and absent by default',async t=>{ + const dir=await mkdtemp(join(tmpdir(),'ac-reasoning-'));t.after(()=>rm(dir,{recursive:true,force:true})); + const file=join(dir,'piece.mjs');await writeFile(file,'export function paint(){}'); + for(const reasoning of [undefined,{effort:'none'},'none']){ + let sent;const engine=new AcServer({cwd:dir,piece:{file},reasoning,jev:null,token:()=> 'test',fetch:async(url,options)=>{sent=JSON.parse(options.body);return serving(say('done'))();}}); + await engine.startTurn('test'); + if(reasoning&&typeof reasoning==='object')assert.deepEqual(sent.reasoning,reasoning);else assert.equal('reasoning' in sent,false); + } +}); + test('layered edits reject stale/ambiguous/broken changes and apply small valid replacements',async t=>{ const dir=await mkdtemp(join(tmpdir(),'ac-layer-'));t.after(()=>rm(dir,{recursive:true,force:true})); const file=join(dir,'piece.mjs');const original='export function paint({wipe}) { wipe("pink"); }\n'; diff --git a/apple/walkieware/Resources/Web/engine.mjs b/apple/walkieware/Resources/Web/engine.mjs index 5f4a87f1d2..cdfd8035a2 100644 --- a/apple/walkieware/Resources/Web/engine.mjs +++ b/apple/walkieware/Resources/Web/engine.mjs @@ -202,7 +202,7 @@ vfs.setWriteHandler((path,value)=>{ const guides = vfs.preload(['pieces.md','screen.md','hand.md','kidlisp.md','api.json'].map(name=>'/easel/context/'+name)); function makeServer(){ const value=new AcServer({cwd:'/piece',piece:{file,checkpoint:async()=>{const target=source.trimEnd();for(let i=0;i<100;i++){if(painted&&lastPaintedSource.trimEnd()===target)return;await new Promise(resolve=>setTimeout(resolve,20));}}},frameCapture:false,layeredEdits:true,token:()=>token,model:window.__walkiewareModel||DEFAULT_MODEL, - fetch:async(...args)=>{benchmark('requestDispatched');const response=await globalThis.fetch(...args);benchmark('inferenceHeaders',{status:response.status});return response;},preview:true,rounds:12,outputContinuations:4, + fetch:async(...args)=>{benchmark('requestDispatched');const response=await globalThis.fetch(...args);benchmark('inferenceHeaders',{status:response.status});return response;},preview:true,rounds:12,outputContinuations:4,reasoning:{effort:'none'}, developerInstructions:GENERATION_INSTRUCTIONS}); value.runtimeFeedback=()=>feedback; value.on('notification',({method,params})=>{ diff --git a/apple/walkieware/Sources/WalkiewareScreen.swift b/apple/walkieware/Sources/WalkiewareScreen.swift index 9ad7aa89cb..7dc81b6e9f 100644 --- a/apple/walkieware/Sources/WalkiewareScreen.swift +++ b/apple/walkieware/Sources/WalkiewareScreen.swift @@ -282,7 +282,7 @@ struct VersionFeed: View { .font(.custom("ComicRelief-Regular", size: textSize, relativeTo: .title3)) .lineLimit(1).truncationMode(.tail).frame(maxWidth: .infinity, alignment: .trailing) if snapshot.busy { - Button(action: stop) { Image(systemName: "stop.fill").frame(width: 32, height: 44) }.accessibilityLabel("Stop generation") + Button(action: stop) { KidlispStopMark() }.buttonStyle(KidlispStopStyle()).accessibilityLabel("Stop generation") } else if attempt.status == "interrupted" || attempt.status == "failed" { Button("Try again", action: retry).disabled(disabled) } @@ -321,6 +321,32 @@ struct VersionWaveform: View { } } +// kidlisp.com's stop button: a red disc with a white rounded square, lifted by +// a soft drop shadow and a hairline highlight along its top edge. +struct KidlispStopMark: View { + @Environment(\.colorScheme) private var scheme + var diameter: CGFloat = 44 + private var red: Color { scheme == .dark ? Color(red: 239 / 255, green: 83 / 255, blue: 80 / 255) : Color(red: 244 / 255, green: 67 / 255, blue: 54 / 255) } + var body: some View { + ZStack { + Circle().fill(red) + .overlay(Circle().strokeBorder(.white.opacity(scheme == .dark ? 0.3 : 0.2), lineWidth: 1).mask(LinearGradient(colors: [.white, .clear], startPoint: .top, endPoint: .center))) + .shadow(color: .black.opacity(scheme == .dark ? 0.6 : 0.3), radius: 3, y: 3) + RoundedRectangle(cornerRadius: 2, style: .continuous).fill(.white).frame(width: diameter * 14 / 48, height: diameter * 14 / 48) + } + .frame(width: diameter, height: diameter) + .contentShape(Circle()) + } +} + +struct KidlispStopStyle: ButtonStyle { + func makeBody(configuration: Configuration) -> some View { + configuration.label + .scaleEffect(configuration.isPressed ? 0.95 : 1) + .animation(.easeOut(duration: 0.2), value: configuration.isPressed) + } +} + struct ComicTitle: View { let text: String var colors: [[Double]] = [] diff --git a/apple/walkieware/Tests/checks.json b/apple/walkieware/Tests/checks.json index 34f56391f5..6e3365bc07 100644 --- a/apple/walkieware/Tests/checks.json +++ b/apple/walkieware/Tests/checks.json @@ -1,763 +1,783 @@ { - "build": 42, - "date": "2026-09-30", - "deviceBuild": "passed; signed; installed", - "deviceLaunch": "Build42 installed and launched; wwVufor connected and initial checkpoint painted", - "simulatorBuild": "passed", - "nativePreview": "AC runtime loaded; injected checkpoint visibly painted; native-preview-smoke.png", - "streamTest": "PASS: native bridge regression including 32 local edits, rollback, progressive rendering, and typed engine API; speech/inference mocked.", - "latency": "16ms release-to-request in fixture run, excluding speech recognition and model/network latency", - "liveEndToEnd": "passed twice on physical iPhone using real-time Jeffrey ElevenLabs PCM fixture, on-device recognition, authenticated AC inference, and painted checkpoint evidence", - "implementation": "shared Aesel AcServer; native speech; native PKCE/Keychain; seeded bundled guides; local previews; no automatic publishing", - "latencyMs": { - "audioDuration": 1301, - "firstRecognizedWords": 569, - "firstVisibleWords": 577, - "releaseToRequest": 26, - "requestToFirstModelOutput": 1459, - "requestToFirstCheckpoint": 1827, - "releaseToFirstPaint": 1906 + "build": 42, + "date": "2026-09-30", + "deviceBuild": "passed; signed; installed", + "deviceLaunch": "Build42 installed and launched; wwVufor connected and initial checkpoint painted", + "simulatorBuild": "passed", + "nativePreview": "AC runtime loaded; injected checkpoint visibly painted; native-preview-smoke.png", + "streamTest": "PASS: native bridge regression including 32 local edits, rollback, progressive rendering, and typed engine API; speech/inference mocked.", + "latency": "16ms release-to-request in fixture run, excluding speech recognition and model/network latency", + "liveEndToEnd": "passed twice on physical iPhone using real-time Jeffrey ElevenLabs PCM fixture, on-device recognition, authenticated AC inference, and painted checkpoint evidence", + "implementation": "shared Aesel AcServer; native speech; native PKCE/Keychain; seeded bundled guides; local previews; no automatic publishing", + "latencyMs": { + "audioDuration": 1301, + "firstRecognizedWords": 569, + "firstVisibleWords": 577, + "releaseToRequest": 26, + "requestToFirstModelOutput": 1459, + "requestToFirstCheckpoint": 1827, + "releaseToFirstPaint": 1906 + }, + "fixes": [ + "canonical bundle path comparison on physical iOS", + "native loading/error/reload and content process recovery", + "native seeding of guide texts avoids status-0 custom scheme fetch", + "larger controls and text; footer replaced by Type and Account buttons", + "Removed Type button; retained Account and voice controls." + ], + "incrementalCompiler": "PASS: complete exported paint prefixes accepted; unfinished functions/strings rejected; no fabricated syntax.", + "providerComparison": "audio/comparison.json; existing DeepSeek default retained after serial relay samples", + "phoneNetwork": "Passed: AC HEAD 250ms cold / 41ms reused; OpenRouter models HEAD 125ms cold / 39ms reused. Public transport checks exclude inference compute.", + "deviceMode": "Normal mode: wwHesop, head 70, Ready to play, no runtime errors.", + "sequenceBenchmark": { + "build": 12, + "runID": "91FA6332-9E99-41D3-A0A5-2EFA4E6BCF57", + "passed": 32, + "total": 32, + "nativeScreenshots": 96, + "behavioralFrames": 46080, + "firstPaintMs": { + "median": 4151, + "p95": 6992, + "max": 10111 }, - "fixes": [ - "canonical bundle path comparison on physical iOS", - "native loading/error/reload and content process recovery", - "native seeding of guide texts avoids status-0 custom scheme fetch", - "larger controls and text; footer replaced by Type and Account buttons", - "Removed Type button; retained Account and voice controls." + "scope": "32 consecutive text edits, one live phone and model session; excludes speech." + }, + "sharedEngineTests": "22/22 focused engine, version ledger and scenario tests passed", + "pixelReview": "All 29 OCR-flagged screenshots visually reviewed; labels present. Counter/playfield contrast remains a design improvement.", + "layeredEdits": { + "enabled": "Walkieware only; shared engine default remains off", + "versioning": "One local snapshot per successfully completed and painted ask; multiple preview layers; failed asks restore parent; undo retains branches", + "stressRun": "9D11077E-5968-4405-9247-F80B6B02D960", + "passedMoves": 12, + "failedMove": 13, + "failure": "Stopped after six tool rounds; rolled back", + "followup": "Instruct model to group patches and await revision before next call" + }, + "sceneTest": { + "runID": "C63B453C-B449-4078-A3EA-28658C411161", + "verifiedLocally": [ + 1, + 2 ], - "incrementalCompiler": "PASS: complete exported paint prefixes accepted; unfinished functions/strings rejected; no fabricated syntax.", - "providerComparison": "audio/comparison.json; existing DeepSeek default retained after serial relay samples", - "phoneNetwork": "Passed: AC HEAD 250ms cold / 41ms reused; OpenRouter models HEAD 125ms cold / 39ms reused. Public transport checks exclude inference compute.", - "deviceMode": "Normal mode: wwHesop, head 70, Ready to play, no runtime errors.", - "sequenceBenchmark": { - "build": 12, - "runID": "91FA6332-9E99-41D3-A0A5-2EFA4E6BCF57", - "passed": 32, - "total": 32, - "nativeScreenshots": 96, - "behavioralFrames": 46080, - "firstPaintMs": { - "median": 4151, - "p95": 6992, - "max": 10111 - }, - "scope": "32 consecutive text edits, one live phone and model session; excludes speech." + "firstPaintMs": [ + 22768, + 7209 + ], + "scope": "Real model text asks on physical phone; separate version per ask; source probes at two sizes; screenshots reviewed. Later moves unverified due intermittent developer connection." + }, + "jevProbe": { + "requests": 10, + "successful": 10, + "expectedMatches": 9, + "medianMs": 129, + "maxMs": 338, + "scope": "Synthetic bounded decisions from development host; not measured phone end-to-end speedup", + "phoneEnabled": true + }, + "mixedInput": { + "build": 16, + "scope": "Physical iPhone; synthetic PCM injected in real time through on-device Speech and the same local music analyzer as microphone input. Real authenticated inference and AC painting. Microphone hardware and natural singing not tested.", + "tests": [ + { + "fixture": "sine-tone", + "passed": true, + "releaseToRequestMs": 34, + "releaseToPaintMs": 61040, + "evidence": "apple/walkieware/Tests/audio/sine-tone-285BC25A-011B-4E31-AF8B-5A587C271D8B/result.json" + }, + { + "fixture": "whistle-sweep", + "passed": true, + "releaseToRequestMs": 28, + "releaseToPaintMs": 7774, + "evidence": "apple/walkieware/Tests/audio/whistle-sweep-BE01074A-D906-4565-941D-945CDD175B60/result.json" + }, + { + "fixture": "mixed-request", + "passed": true, + "releaseToRequestMs": 31, + "releaseToPaintMs": 11150, + "evidence": "apple/walkieware/Tests/audio/mixed-request-37B14D0D-2FBE-4072-BDF0-7FD8C2CE5A8B/result.json" + } + ], + "limitations": [ + "Dominant monophonic pitch estimates, not chord/instrument recognition", + "Energy onsets, not established tempo or beats", + "Creative mappings are model interpretations" + ] + }, + "jevIntegration": { + "build": 17, + "deployedRevision": "0e9914452c", + "endpoint": "/api/easel-musical-jev", + "scope": "Physical iPhone, real-time synthetic PCM through on-device recognition and local DSP, authenticated production Jev and code inference. Microphone hardware excluded.", + "transport": "Bounded incremental authenticated HTTP observations; aggregate features only to Jev; session and sequence identity; stale responses rejected.", + "unitTests": "8/8 focused musical Jev tests passed; native musical bridge and Swift DSP checks passed.", + "mixed": { + "runID": "4389E5CA-9E94-4C18-9DB9-E7293C30AB44", + "passed": true, + "result": "apple/walkieware/Tests/audio/mixed-request-4389E5CA-9E94-4C18-9DB9-E7293C30AB44/result.json", + "firstVisibleWordsMs": 664, + "appliedAdvice": { + "choice": "follow_speech", + "elapsedMs": 253 + }, + "releaseToRequestMs": 296, + "releaseToPaintMs": 21742 }, - "sharedEngineTests": "22/22 focused engine, version ledger and scenario tests passed", - "pixelReview": "All 29 OCR-flagged screenshots visually reviewed; labels present. Counter/playfield contrast remains a design improvement.", - "layeredEdits": { - "enabled": "Walkieware only; shared engine default remains off", - "versioning": "One local snapshot per successfully completed and painted ask; multiple preview layers; failed asks restore parent; undo retains branches", - "stressRun": "9D11077E-5968-4405-9247-F80B6B02D960", - "passedMoves": 12, - "failedMove": 13, - "failure": "Stopped after six tool rounds; rolled back", - "followup": "Instruct model to group patches and await revision before next call" + "whistle": { + "runID": "61A7587F-ED25-4A98-8A91-51CBC10AD624", + "choice": "trace_pitch", + "decisionMs": 482, + "cachedBeforeRelease": true, + "releaseToRequestMs": 36, + "releaseToPaintMs": 53051, + "note": "Passed prior cache-specific checks; predates jevApplied marker." }, - "sceneTest": { - "runID": "C63B453C-B449-4078-A3EA-28658C411161", - "verifiedLocally": [ - 1, - 2 - ], - "firstPaintMs": [ - 22768, - 7209 - ], - "scope": "Real model text asks on physical phone; separate version per ask; source probes at two sizes; screenshots reviewed. Later moves unverified due intermittent developer connection." + "earlierFailures": [ + "Initial phone run exposed Safari fetch receiver bug; fixed and deployed.", + "Prior mixed run failed overly strict cache-hit expectation despite successful generation; final evidence now verifies advice applied and permits changed-feature refresh." + ], + "normalMode": "Relaunched with audio/sequence/network fixtures disabled and saved sequence version 4 restored to normal ledger. Console confirmed controls ready, preview runtime ready, checkpoint painted.", + "limitations": [ + "Jev chooses bounded optional interpretation cues, not code.", + "Code model latency remains variable; no end-to-end speedup established." + ] + }, + "socketIntegration": { + "build": 18, + "deployedRevision": "c40d07222f", + "endpoint": "wss://aesthetic.computer/api/easel-musical-stream", + "host": "Existing Lith DigitalOcean service", + "validation": { + "focusedTests": "12/12 passed, including real local WebSocket authentication, coalescing, abort, renewal, reconnect, HTTP fallback and timing", + "nativeBridge": "Passed musical mode with mocked speech/inference", + "iosBuild": "Passed; installed on physical iPhone", + "production": "Revision verified; WebSocket upgraded successfully and unauthenticated observation closed with code 1008" }, - "jevProbe": { - "requests": 10, - "successful": 10, - "expectedMatches": 9, - "medianMs": 129, - "maxMs": 338, - "scope": "Synthetic bounded decisions from development host; not measured phone end-to-end speedup", - "phoneEnabled": true + "phoneBenchmark": { + "status": "passed", + "runID": "C79C1A68-8513-49AC-B573-464EE1C1F503", + "result": "apple/walkieware/Tests/audio/mixed-request-C79C1A68-8513-49AC-B573-464EE1C1F503/result.json", + "scope": "Fresh piece; real-time synthetic speech and whistle PCM through on-device recognition and local DSP; real authenticated socket and inference; microphone hardware excluded.", + "finalAdvice": { + "choice": "follow_speech", + "elapsedMs": 232, + "providerMs": 174, + "serverMs": 202, + "transport": "socket", + "transportMs": 30 + }, + "firstWordsVisibleMs": 715, + "releaseToRequestMs": 275, + "releaseToFirstPaintMs": 15460, + "screenshot": "preview.png visually inspected; pink circle visible; animation not evaluated from this still" }, - "mixedInput": { - "build": 16, - "scope": "Physical iPhone; synthetic PCM injected in real time through on-device Speech and the same local music analyzer as microphone input. Real authenticated inference and AC painting. Microphone hardware and natural singing not tested.", - "tests": [ - { - "fixture": "sine-tone", - "passed": true, - "releaseToRequestMs": 34, - "releaseToPaintMs": 61040, - "evidence": "apple/walkieware/Tests/audio/sine-tone-285BC25A-011B-4E31-AF8B-5A587C271D8B/result.json" - }, - { - "fixture": "whistle-sweep", - "passed": true, - "releaseToRequestMs": 28, - "releaseToPaintMs": 7774, - "evidence": "apple/walkieware/Tests/audio/whistle-sweep-BE01074A-D906-4565-941D-945CDD175B60/result.json" - }, - { - "fixture": "mixed-request", - "passed": true, - "releaseToRequestMs": 31, - "releaseToPaintMs": 11150, - "evidence": "apple/walkieware/Tests/audio/mixed-request-37B14D0D-2FBE-4072-BDF0-7FD8C2CE5A8B/result.json" - } - ], - "limitations": [ - "Dominant monophonic pitch estimates, not chord/instrument recognition", - "Energy onsets, not established tempo or beats", - "Creative mappings are model interpretations" - ] + "limitations": [ + "Provider Decisions call remains HTTP", + "Raw microphone audio stays on device", + "One successful phone run does not establish a controlled end-to-end speedup" + ], + "normalMode": "Installed debug build with audio fixture promotion; relaunched with fixtures disabled, new pink-circle version copied to normal ledger, rope sequence ledger retained. Console verified controls ready, preview runtime ready and checkpoint painted." + }, + "instantPiece": { + "build": 19, + "runID": "8465746E-1FD1-4E24-A3F4-3B6A65802B01", + "passed": true, + "checks": { + "soundSubmitted": true, + "requestDispatched": true, + "finished": true, + "painted": true, + "pitchDetected": true, + "wordsPreserved": true, + "wordsTimestamped": true, + "jevDecisionReceived": true, + "currentAdviceApplied": true, + "socketAdviceApplied": true, + "socketAcknowledged": true, + "starterPainted": true, + "starterBeforeModel": true, + "starterUnder200ms": true }, - "jevIntegration": { - "build": 17, - "deployedRevision": "0e9914452c", - "endpoint": "/api/easel-musical-jev", - "scope": "Physical iPhone, real-time synthetic PCM through on-device recognition and local DSP, authenticated production Jev and code inference. Microphone hardware excluded.", - "transport": "Bounded incremental authenticated HTTP observations; aggregate features only to Jev; session and sequence identity; stale responses rejected.", - "unitTests": "8/8 focused musical Jev tests passed; native musical bridge and Swift DSP checks passed.", - "mixed": { - "runID": "4389E5CA-9E94-4C18-9DB9-E7293C30AB44", - "passed": true, - "result": "apple/walkieware/Tests/audio/mixed-request-4389E5CA-9E94-4C18-9DB9-E7293C30AB44/result.json", - "firstVisibleWordsMs": 664, - "appliedAdvice": { - "choice": "follow_speech", - "elapsedMs": 253 - }, - "releaseToRequestMs": 296, - "releaseToPaintMs": 21742 - }, - "whistle": { - "runID": "61A7587F-ED25-4A98-8A91-51CBC10AD624", - "choice": "trace_pitch", - "decisionMs": 482, - "cachedBeforeRelease": true, - "releaseToRequestMs": 36, - "releaseToPaintMs": 53051, - "note": "Passed prior cache-specific checks; predates jevApplied marker." - }, - "earlierFailures": [ - "Initial phone run exposed Safari fetch receiver bug; fixed and deployed.", - "Prior mixed run failed overly strict cache-hit expectation despite successful generation; final evidence now verifies advice applied and permits changed-feature refresh." - ], - "normalMode": "Relaunched with audio/sequence/network fixtures disabled and saved sequence version 4 restored to normal ledger. Console confirmed controls ready, preview runtime ready, checkpoint painted.", - "limitations": [ - "Jev chooses bounded optional interpretation cues, not code.", - "Code model latency remains variable; no end-to-end speedup established." - ] + "scope": "Physical iPhone; real-time synthetic speech and whistle PCM, on-device recognition and DSP, authenticated production socket and code model. Microphone hardware excluded.", + "implementation": "Fresh explicit circle/square requests get local editable AC source before Jev or code inference completes. Existing pieces are preserved; starter and refinements share one version. Provider failure preserves a painted starter; cancellation rolls back.", + "timingMs": { + "firstPainted": 91, + "starterPainted": 93, + "requestDispatched": 194, + "firstModelOutput": 23791, + "firstCheckpoint": 25292, + "generationFinished": 33265 }, - "socketIntegration": { - "build": 18, - "deployedRevision": "c40d07222f", - "endpoint": "wss://aesthetic.computer/api/easel-musical-stream", - "host": "Existing Lith DigitalOcean service", - "validation": { - "focusedTests": "12/12 passed, including real local WebSocket authentication, coalescing, abort, renewal, reconnect, HTTP fallback and timing", - "nativeBridge": "Passed musical mode with mocked speech/inference", - "iosBuild": "Passed; installed on physical iPhone", - "production": "Revision verified; WebSocket upgraded successfully and unauthenticated observation closed with code 1008" - }, - "phoneBenchmark": { - "status": "passed", - "runID": "C79C1A68-8513-49AC-B573-464EE1C1F503", - "result": "apple/walkieware/Tests/audio/mixed-request-C79C1A68-8513-49AC-B573-464EE1C1F503/result.json", - "scope": "Fresh piece; real-time synthetic speech and whistle PCM through on-device recognition and local DSP; real authenticated socket and inference; microphone hardware excluded.", - "finalAdvice": { - "choice": "follow_speech", - "elapsedMs": 232, - "providerMs": 174, - "serverMs": 202, - "transport": "socket", - "transportMs": 30 - }, - "firstWordsVisibleMs": 715, - "releaseToRequestMs": 275, - "releaseToFirstPaintMs": 15460, - "screenshot": "preview.png visually inspected; pink circle visible; animation not evaluated from this still" - }, - "limitations": [ - "Provider Decisions call remains HTTP", - "Raw microphone audio stays on device", - "One successful phone run does not establish a controlled end-to-end speedup" - ], - "normalMode": "Installed debug build with audio fixture promotion; relaunched with fixtures disabled, new pink-circle version copied to normal ledger, rope sequence ledger retained. Console verified controls ready, preview runtime ready and checkpoint painted." + "advice": { + "choice": "follow_speech", + "elapsedMs": 160, + "providerMs": 95, + "serverMs": 122, + "transport": "socket", + "transportMs": 69 }, - "instantPiece": { - "build": 19, - "runID": "8465746E-1FD1-4E24-A3F4-3B6A65802B01", - "passed": true, + "coldSocketFallback": true, + "sourceEvidence": "apple/walkieware/Tests/audio/mixed-request-8465746E-1FD1-4E24-A3F4-3B6A65802B01/result.json", + "visualReview": "Screenshot inspected: pink circle visible. Still image does not verify animation.", + "focusedTests": "4 local source tests plus native bridge: starter/refinement one version, retained starter on provider failure, no replacement of existing pieces, cancel during interpretation prevents request/version.", + "modelComparison": { + "simple": "audio/provider-1790810920467.json", + "mixedWithStarter": "audio/provider-1790811108615.json", + "decision": "Retain DeepSeek; no demonstrated faster equivalent refinement. Model latency remains variable." + }, + "limitations": [ + "Under-200ms result is one warm-preview fixture run, not a latency percentile or general guarantee.", + "Local vocabulary currently circles and squares; other requests still depend on code inference.", + "Model refinement took 33.3 seconds after release in this run." + ], + "normalMode": "Relaunched with audio/sequence/network fixtures disabled and latest result promoted into normal ledger. Console confirmed controls, preview runtime and painted checkpoint. Attached devicectl console timed out after launch." + }, + "localIteration": { + "build": 21, + "implementation": "Canonical editable circle/square scene with local color, size, position, bounce, speed, freeze and center commands. No code inference for supported local commands. Unsupported commands or modified sources use existing model path. No Keep requirement before next ask.", + "unitTests": "32 sequential edits, exact expected properties, 3840 simulated frames across two sizes, one version per ask and undo all 32 passed. Unsupported/modified inputs and bounds tested.", + "browserTests": "32 local edits with undo/replay each passed, zero inference requests, next voice ask enabled. Painted acknowledgements mocked. Existing generation/refinement/cancellation regressions passed.", + "phoneRun": { + "runID": "09CDBEB7-B67C-4451-B0CC-B2A83F45F208", + "complete": true, + "verifiedMoves": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32 + ], + "paintMs": { + "median": 48, + "p95": 62, + "max": 63 + }, + "scope": "Local text ask to painted frame on physical iPhone. Speech and provider latency excluded. Every move checked properties, one version, undo/replay, paint, and three screenshots.", + "screenshots": 96, + "inferenceRequests": 0, + "visualReview": "All 96 screenshot frames inspected in review.png: expected color, size and position changes visible; frozen frames stable and bouncing frames vary. Sparse captures do not prove frame-by-frame continuity." + }, + "limitations": [ + "Supported unchanged canonical scenes only; other requests use code generation.", + "Live edits still reload source, but build 21 shares motion state in memory." + ], + "normalMode": "Build 21 relaunched with all fixtures disabled and tested local scene promoted to normal ledger. Controls, preview runtime, and painted checkpoint confirmed. Rope scene remains in its separate sequence ledger.", + "phasePreservation": { + "build": 21, + "unitTests": "Shared runtime store preserves phase across color/size/speed edits and undo. Freeze retains current height; a new scene starts independently.", + "phoneValidation": "All 32 moves passed with stateful motion source, including freeze and resume. Exact phase continuity tested with shared-store module reloads in focused tests; phone snapshots are sparse motion evidence." + }, + "previousPhoneRun": { + "runID": "B0D61081-9B9B-4203-94A2-A2742C0968E3", + "complete": true, + "verifiedMoves": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32 + ], + "paintMs": { + "median": 49, + "p95": 56, + "max": 79 + }, + "scope": "Local text ask to first painted frame; physical iPhone. Excludes speech and model latency. One version, undo/replay and properties verified for every move; 96 screenshots retained.", + "visualReview": "All 96 frames inspected in review.png contact sheet; colors, sizes and position changes visible. Three-frame samples are not continuous motion recordings." + } + }, + "spaceIteration": { + "build": 23, + "scope": "Six successive text asks on physical iPhone. First line local; remaining edits real code model. Speech excluded. Screenshots and source reviewed; 720-frame probes at two sizes per stage.", + "steps": [ + { + "index": 1, + "prompt": "Make a white line", + "runID": "5238B9C7-94D7-43F0-B8B8-A3DE56402062", "checks": { - "soundSubmitted": true, - "requestDispatched": true, - "finished": true, - "painted": true, - "pitchDetected": true, - "wordsPreserved": true, - "wordsTimestamped": true, - "jevDecisionReceived": true, - "currentAdviceApplied": true, - "socketAdviceApplied": true, - "socketAcknowledged": true, - "starterPainted": true, - "starterBeforeModel": true, - "starterUnder200ms": true - }, - "scope": "Physical iPhone; real-time synthetic speech and whistle PCM, on-device recognition and DSP, authenticated production socket and code model. Microphone hardware excluded.", - "implementation": "Fresh explicit circle/square requests get local editable AC source before Jev or code inference completes. Existing pieces are preserved; starter and refinements share one version. Provider failure preserves a painted starter; cancellation rolls back.", - "timingMs": { - "firstPainted": 91, - "starterPainted": 93, - "requestDispatched": 194, - "firstModelOutput": 23791, - "firstCheckpoint": 25292, - "generationFinished": 33265 - }, - "advice": { - "choice": "follow_speech", - "elapsedMs": 160, - "providerMs": 95, - "serverMs": 122, - "transport": "socket", - "transportMs": 69 + "committedSourcePainted": true, + "featureTests": true, + "finished": true, + "noRuntimeErrors": true, + "oneVersionPerAsk": true, + "sourceBounded": true, + "sourceChanged": true, + "threeFramesCaptured": true }, - "coldSocketFallback": true, - "sourceEvidence": "apple/walkieware/Tests/audio/mixed-request-8465746E-1FD1-4E24-A3F4-3B6A65802B01/result.json", - "visualReview": "Screenshot inspected: pink circle visible. Still image does not verify animation.", - "focusedTests": "4 local source tests plus native bridge: starter/refinement one version, retained starter on provider failure, no replacement of existing pieces, cancel during interpretation prevents request/version.", - "modelComparison": { - "simple": "audio/provider-1790810920467.json", - "mixedWithStarter": "audio/provider-1790811108615.json", - "decision": "Retain DeepSeek; no demonstrated faster equivalent refinement. Model latency remains variable." - }, - "limitations": [ - "Under-200ms result is one warm-preview fixture run, not a latency percentile or general guarantee.", - "Local vocabulary currently circles and squares; other requests still depend on code inference.", - "Model refinement took 33.3 seconds after release in this run." - ], - "normalMode": "Relaunched with audio/sequence/network fixtures disabled and latest result promoted into normal ledger. Console confirmed controls, preview runtime and painted checkpoint. Attached devicectl console timed out after launch." - }, - "localIteration": { - "build": 21, - "implementation": "Canonical editable circle/square scene with local color, size, position, bounce, speed, freeze and center commands. No code inference for supported local commands. Unsupported commands or modified sources use existing model path. No Keep requirement before next ask.", - "unitTests": "32 sequential edits, exact expected properties, 3840 simulated frames across two sizes, one version per ask and undo all 32 passed. Unsupported/modified inputs and bounds tested.", - "browserTests": "32 local edits with undo/replay each passed, zero inference requests, next voice ask enabled. Painted acknowledgements mocked. Existing generation/refinement/cancellation regressions passed.", - "phoneRun": { - "runID": "09CDBEB7-B67C-4451-B0CC-B2A83F45F208", - "complete": true, - "verifiedMoves": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32 - ], - "paintMs": { - "median": 48, - "p95": 62, - "max": 63 - }, - "scope": "Local text ask to painted frame on physical iPhone. Speech and provider latency excluded. Every move checked properties, one version, undo/replay, paint, and three screenshots.", - "screenshots": 96, - "inferenceRequests": 0, - "visualReview": "All 96 screenshot frames inspected in review.png: expected color, size and position changes visible; frozen frames stable and bouncing frames vary. Sparse captures do not prove frame-by-frame continuity." + "visualAndRuntimePassed": true, + "nativeVerdictAcknowledged": true, + "paintMs": 51, + "finishedMs": 61, + "version": 1 + }, + { + "index": 2, + "prompt": "Transform this horizontal line into a small pointed spaceship hull, facing upward. Preserve its visual continuity: the old line becomes the wide base and two new diagonal edges meet at a nose above it. White outline on the same dark background. Static; no wings, windows, stars or exhaust yet.", + "runID": "5238B9C7-94D7-43F0-B8B8-A3DE56402062", + "checks": { + "committedSourcePainted": true, + "featureTests": true, + "finished": true, + "noRuntimeErrors": true, + "oneVersionPerAsk": true, + "sourceBounded": true, + "sourceChanged": true, + "threeFramesCaptured": true }, - "limitations": [ - "Supported unchanged canonical scenes only; other requests use code generation.", - "Live edits still reload source, but build 21 shares motion state in memory." - ], - "normalMode": "Build 21 relaunched with all fixtures disabled and tested local scene promoted to normal ledger. Controls, preview runtime, and painted checkpoint confirmed. Rope scene remains in its separate sequence ledger.", - "phasePreservation": { - "build": 21, - "unitTests": "Shared runtime store preserves phase across color/size/speed edits and undo. Freeze retains current height; a new scene starts independently.", - "phoneValidation": "All 32 moves passed with stateful motion source, including freeze and resume. Exact phase continuity tested with shared-store module reloads in focused tests; phone snapshots are sparse motion evidence." + "visualAndRuntimePassed": true, + "nativeVerdictAcknowledged": true, + "paintMs": 7855, + "finishedMs": 9650, + "version": 2 + }, + { + "index": 3, + "prompt": "Add two symmetric swept-back wings to the same hull. Make the silhouette clearly recognizable as a little spaceship, keeping the pointed nose and body. Static; no stars or exhaust yet.", + "runID": "5238B9C7-94D7-43F0-B8B8-A3DE56402062", + "checks": { + "committedSourcePainted": true, + "featureTests": true, + "finished": true, + "noRuntimeErrors": true, + "oneVersionPerAsk": true, + "sourceBounded": true, + "sourceChanged": true, + "threeFramesCaptured": true }, - "previousPhoneRun": { - "runID": "B0D61081-9B9B-4203-94A2-A2742C0968E3", - "complete": true, - "verifiedMoves": [ - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 10, - 11, - 12, - 13, - 14, - 15, - 16, - 17, - 18, - 19, - 20, - 21, - 22, - 23, - 24, - 25, - 26, - 27, - 28, - 29, - 30, - 31, - 32 - ], - "paintMs": { - "median": 49, - "p95": 56, - "max": 79 - }, - "scope": "Local text ask to first painted frame; physical iPhone. Excludes speech and model latency. One version, undo/replay and properties verified for every move; 96 screenshots retained.", - "visualReview": "All 96 frames inspected in review.png contact sheet; colors, sizes and position changes visible. Three-frame samples are not continuous motion recordings." - } - }, - "spaceIteration": { - "build": 23, - "scope": "Six successive text asks on physical iPhone. First line local; remaining edits real code model. Speech excluded. Screenshots and source reviewed; 720-frame probes at two sizes per stage.", - "steps": [ - { - "index": 1, - "prompt": "Make a white line", - "runID": "5238B9C7-94D7-43F0-B8B8-A3DE56402062", - "checks": { - "committedSourcePainted": true, - "featureTests": true, - "finished": true, - "noRuntimeErrors": true, - "oneVersionPerAsk": true, - "sourceBounded": true, - "sourceChanged": true, - "threeFramesCaptured": true - }, - "visualAndRuntimePassed": true, - "nativeVerdictAcknowledged": true, - "paintMs": 51, - "finishedMs": 61, - "version": 1 - }, - { - "index": 2, - "prompt": "Transform this horizontal line into a small pointed spaceship hull, facing upward. Preserve its visual continuity: the old line becomes the wide base and two new diagonal edges meet at a nose above it. White outline on the same dark background. Static; no wings, windows, stars or exhaust yet.", - "runID": "5238B9C7-94D7-43F0-B8B8-A3DE56402062", - "checks": { - "committedSourcePainted": true, - "featureTests": true, - "finished": true, - "noRuntimeErrors": true, - "oneVersionPerAsk": true, - "sourceBounded": true, - "sourceChanged": true, - "threeFramesCaptured": true - }, - "visualAndRuntimePassed": true, - "nativeVerdictAcknowledged": true, - "paintMs": 7855, - "finishedMs": 9650, - "version": 2 - }, - { - "index": 3, - "prompt": "Add two symmetric swept-back wings to the same hull. Make the silhouette clearly recognizable as a little spaceship, keeping the pointed nose and body. Static; no stars or exhaust yet.", - "runID": "5238B9C7-94D7-43F0-B8B8-A3DE56402062", - "checks": { - "committedSourcePainted": true, - "featureTests": true, - "finished": true, - "noRuntimeErrors": true, - "oneVersionPerAsk": true, - "sourceBounded": true, - "sourceChanged": true, - "threeFramesCaptured": true - }, - "visualAndRuntimePassed": true, - "nativeVerdictAcknowledged": true, - "paintMs": 5497, - "finishedMs": 9103, - "version": 3 - }, - { - "index": 4, - "prompt": "Add a cyan cockpit window inside the upper hull and a small pink stripe on each wing. Keep all existing ship geometry. Static, no extra text or interface.", - "runID": "5238B9C7-94D7-43F0-B8B8-A3DE56402062", - "checks": { - "committedSourcePainted": true, - "featureTests": true, - "finished": true, - "noRuntimeErrors": true, - "oneVersionPerAsk": true, - "sourceBounded": true, - "sourceChanged": true, - "threeFramesCaptured": true - }, - "visualAndRuntimePassed": true, - "nativeVerdictAcknowledged": true, - "paintMs": 6273, - "finishedMs": 7813, - "version": 4 - }, - { - "index": 5, - "prompt": "Add a warm orange and yellow exhaust flame below the ship. Animate its length with a gentle repeating pulse, while the hull and wings remain stationary. Keep the cockpit and stripes. IMPORTANT: the nozzle is at the center of the REARMOST horizontal edge (the existing tail coordinate), not at the original horizontal line y inside the body. Both flame edges must start exactly at tail, with all flame geometry below tail. Pulse its length between 5% and 15% of screen height, clamping to leave a margin at the bottom. No flame inside the body. No stars yet.", - "runID": "CF7BBDFF-0C91-4754-B1C3-1C7878099F31", - "checks": { - "animationChanged": true, - "committedSourcePainted": true, - "featureTests": true, - "finished": true, - "motionFramesCaptured": true, - "noRuntimeErrors": true, - "oneVersionPerAsk": true, - "sourceBounded": true, - "sourceChanged": true - }, - "visualAndRuntimePassed": true, - "nativeVerdictAcknowledged": true, - "paintMs": 10705, - "finishedMs": 14917, - "version": 6 - }, - { - "index": 6, - "prompt": "Make the same spaceship fly through space: add a sparse field of small stars moving downward behind it, with wrapping at the screen edge, and a slight gentle bank of the complete ship. Preserve the hull, two wings, cyan cockpit, pink stripes, and attached animated exhaust. Keep the ship fully on screen. No text or extra interface.", - "runID": "CF7BBDFF-0C91-4754-B1C3-1C7878099F31", - "checks": { - "animationChanged": true, - "committedSourcePainted": true, - "finished": true, - "motionFramesCaptured": true, - "noRuntimeErrors": true, - "oneVersionPerAsk": true, - "sourceBounded": true, - "sourceChanged": true - }, - "visualAndRuntimePassed": true, - "nativeVerdictAcknowledged": false, - "paintMs": 45921, - "finishedMs": 51763, - "version": 7 - } - ], - "rejectedAttempts": [ - { - "runID": "5238B9C7-94D7-43F0-B8B8-A3DE56402062", - "index": 5, - "reason": "Flame began inside body; rejected and undone" - }, - { - "runID": "084761A5-3954-472F-8F61-4F625AF31E64", - "index": 5, - "reason": "No verified version committed; previous scene retained" - } - ], - "motionReview": "24 chronological phone snapshots each for accepted thruster and flight; source confirms downward star wrapping and shared rotation of all ship parts.", - "normalMode": "Not confirmed: developer connection dropped after uploading final acceptance, before normal-mode launch could succeed." - }, - "walkiewareThreads": { - "backendRevision": "34291d3d74", - "focusedTests": 9, - "phoneCode": "wwHesop", - "remoteEditRoundTripMs": 943, - "remoteEditVersion": 69, - "guardedUndoHead": 68, - "currentHeadAfterUserEdit": 70, - "build27RestoredHead": 70, - "scope": "Remote edit timing includes rendering and saved acknowledgement, excludes speech and generation.", - "acRouteVerification": "Route reaches sign-in screen in browser harness; authenticated playback not yet verified.", - "threeDimensionalDemo": { - "code": "wwLehoh", - "reviewedFrames": 48, - "video": "threads/wwLehoh/spaceship-3d.mp4", - "scope": "Separate browser demo; CPU-projected 3D geometry. Generation attempt hit output limit; direct source edit verified." - } - }, - "versionFeed": { - "utterances": true, - "currentVersionHighlighted": true, - "idleStatusRemoved": true, - "codeActivityRemoved": true, - "failedAttemptPreservesWorkingHead": true, - "musicalContour": true, - "relativeTimestamps": true, - "tapToCheckout": true, - "branchRetainsFutureVersions": true, - "keepUndoRemoved": true, - "branchParentVisible": true - }, - "utteranceLimit": { - "seconds": 8, - "nativeDeadline": true, - "visibleCountdown": true, - "browserAutoSubmitTest": "passed", - "duplicateReleaseTest": "passed", - "scope": "Browser speech bridge mocked; native signed build passed." - }, - "previewStyle": "Plain 4:3 aspect ratio, normal colors, no bezel or filter; native bridge pins zero runtime gap", - "framing": { - "before": { - "x": 4, - "y": 4, - "width": 422, - "height": 292, - "viewport": [ - 430, - 300 - ] + "visualAndRuntimePassed": true, + "nativeVerdictAcknowledged": true, + "paintMs": 5497, + "finishedMs": 9103, + "version": 3 + }, + { + "index": 4, + "prompt": "Add a cyan cockpit window inside the upper hull and a small pink stripe on each wing. Keep all existing ship geometry. Static, no extra text or interface.", + "runID": "5238B9C7-94D7-43F0-B8B8-A3DE56402062", + "checks": { + "committedSourcePainted": true, + "featureTests": true, + "finished": true, + "noRuntimeErrors": true, + "oneVersionPerAsk": true, + "sourceBounded": true, + "sourceChanged": true, + "threeFramesCaptured": true }, - "after": { - "x": 0, - "y": 0, - "width": 431, - "height": 300, - "viewport": [ - 431, - 300 - ] + "visualAndRuntimePassed": true, + "nativeVerdictAcknowledged": true, + "paintMs": 6273, + "finishedMs": 7813, + "version": 4 + }, + { + "index": 5, + "prompt": "Add a warm orange and yellow exhaust flame below the ship. Animate its length with a gentle repeating pulse, while the hull and wings remain stationary. Keep the cockpit and stripes. IMPORTANT: the nozzle is at the center of the REARMOST horizontal edge (the existing tail coordinate), not at the original horizontal line y inside the body. Both flame edges must start exactly at tail, with all flame geometry below tail. Pulse its length between 5% and 15% of screen height, clamping to leave a margin at the bottom. No flame inside the body. No stars yet.", + "runID": "CF7BBDFF-0C91-4754-B1C3-1C7878099F31", + "checks": { + "animationChanged": true, + "committedSourcePainted": true, + "featureTests": true, + "finished": true, + "motionFramesCaptured": true, + "noRuntimeErrors": true, + "oneVersionPerAsk": true, + "sourceBounded": true, + "sourceChanged": true }, - "scope": "Real AC browser runtime; force no-gap and viewport resize", - "deployedRevision": "e4cf37115b", - "productionResizeCheck": { - "nogap": true, - "x": 0, - "y": 0, - "width": 404, - "height": 303, - "viewport": [ - 404, - 303 - ] - } - }, - "identityHeader": "@handle / wwCode below preview, aligned to picture right edge; character colors and comic styling retained", - "liveLayout": { - "code": "wwFifuh", - "acknowledged": true, - "unchangedLedger": true, - "transport": "owner-authenticated WebSocket", - "scope": "CSS updated open physical phone app after launch, no restart for layout command" - }, - "freshScreen": "Prototype controls and blank preview caption hidden; old review MutationObserver and gamepad/keyboard controller removed from generated bundle; initial version persisted", - "historyPlacement": "Immediately beneath preview caption; scroll occupies remaining space above talk button", - "nativeShell": { - "nativeControls": [ - "header", - "preview caption", - "version feed", - "musical contour", - "recording transcript", - "hold progress", - "account/new-piece menu" - ], - "engine": "Dedicated Walkieware HTML; JS ledger remains authoritative; typed display snapshots; throttled/deduplicated; history only on change", - "runtime": "Persistent WKWebView through version and card changes; separate weak coordinator", - "progress": "Native TimelineView begins on listening event; eight-second native deadline retained", - "screenshots": [ - "native-shell/walkieware-native-empty.png", - "native-shell/walkieware-native-history.png", - "native-shell/walkieware-native-recording.png" - ], - "screenshotScope": "Simulator; populated and recording screens are isolated fixtures, not live microphone recordings", - "contractTests": "Passed: early provisional previews, snapshots without source/token, delta history, native checkout, native layout tokens", - "physicalLiveLayout": { - "code": "wwFifuh", - "head": 0, - "unchangedLedger": true, - "fromSpacing": 12, - "toSpacing": 10, - "nativeAcknowledgement": true, - "restartedForLayout": false - } - }, - "swipeToType": { - "directions": [ - "left", - "right" - ], - "revealThresholdPoints": 18, - "openThresholdPoints": 72, - "characterLimit": 96, - "voiceCancelledOnSwipe": true, - "tests": "Native XCTest case passed both directions, truncation and no version change on cancel; speech mocked in simulator fixture. Xcode result finalization stalled after passed suite and was interrupted." - }, - "basePiece": { - "source": "noiseTinted([128,128,128],0,0)", - "head": 0, - "code": "wwVufor", - "versions": 1, - "devicePainted": true, - "runtimeErrors": [], - "oldBlankThread": "archived locally before assigning new immutable v0", - "existingEditedHistory": "preserved", - "screenshot": "native-shell/walkieware-native-static.png" - }, - "latestIteration": { - "build": 46, - "installedOnPhone": true, - "uiTest": "Passed: Type left / Talk right, inline typing, 96-character cap, preview above keyboard, cancel preserves version in light and dark appearances", - "bridgeTest": "Passed native-shell contract", - "dragRepair": { - "thread": "wwVufor", - "version": 14, - "cause": "API guide incorrectly documented id instead of pointerId", - "validation": "Grab, move, release with pointerId zero passed; device accepted repaired version" + "visualAndRuntimePassed": true, + "nativeVerdictAcknowledged": true, + "paintMs": 10705, + "finishedMs": 14917, + "version": 6 + }, + { + "index": 6, + "prompt": "Make the same spaceship fly through space: add a sparse field of small stars moving downward behind it, with wrapping at the screen edge, and a slight gentle bank of the complete ship. Preserve the hull, two wings, cyan cockpit, pink stripes, and attached animated exhaust. Keep the ship fully on screen. No text or extra interface.", + "runID": "CF7BBDFF-0C91-4754-B1C3-1C7878099F31", + "checks": { + "animationChanged": true, + "committedSourcePainted": true, + "finished": true, + "motionFramesCaptured": true, + "noRuntimeErrors": true, + "oneVersionPerAsk": true, + "sourceBounded": true, + "sourceChanged": true }, - "theme": "Slab status colors across background, controls, ink and history; system/light/dark selection", - "screenshots": "native-shell/walkieware-ready-{light,dark}.png (simulator fixtures, before final dock background mask)" - }, - "buttonLabelIteration": { - "build": 47, - "installedOnPhone": true, - "validation": "Device and simulator builds passed; two simulator frames visually inspected", - "type": "Cyan, bold monospace, type-in animation", - "talk": "Orange, comic font, outward-moving rays", - "reduceMotion": "Both labels remain static", - "launch": "Blocked: device locked" - }, - "layoutIteration": { - "build": 52, - "installedAndLaunched": true, - "base": "Random CSS hex color persisted in v0; no automatic title", - "caption": "Running version left, handle/code right, below preview", - "history": "Alternating backgrounds, outlined comic version labels", - "validation": [ - "base-piece tests: 2 passed", - "native bridge contract passed", - "device and simulator builds passed" - ] - }, - "storyContextAndRecording": { - "build": 57, - "validation": [ - "Device build passed", - "9 focused JS tests passed", - "Native fullscreen story UI test passed on build55; selected version restored", - "Original PCM file round-trip preserved duration, sample rate and sample values", - "Native bridge output streaming/recovery/story checks passed on final build57 bundle" - ], - "changes": [ - "Bounded live output feed", - "Selected branch ancestry sent with each request", - "Ordinary spoken edits do not imply transcript or acoustic visualization", - "Recover interrupted request once, then explicit retry", - "Original microphone recordings saved locally and linked through version request metadata", - "No prompt or generated instruction beneath preview" - ], - "limits": [ - "Original microphone playback only available for newly captured recordings on this device; old/typed versions fall back to speech synthesis", - "Hardware microphone capture/playback not yet auditioned", - "Intent policy evaluated against saved wwMupol/wwTamof evidence, not a fresh live model replay", - "No confirmed native crash report; reload recovery tested, not a forced physical-device crash" - ], - "installedOnPhone": true - }, - "inferenceIsolation": { - "build": 58, - "installed": true, - "validation": [ - "Device build passed", - "3 input-routing tests passed", - "Browser test confirmed ordinary spoken request reaches mocked provider without mixed-input wrapper or recording ID; history/recovery/live-output checks passed" - ], - "behavior": "Ordinary transcripts only; retain audio in version history. Sound evidence and Jev advice only for nonverbal input or explicit sound references.", - "limits": "Sound references use a conservative phrase rule, not a learned speech-versus-music classifier. Existing generated scenes are not automatically rewritten. No fresh live provider quality evaluation." - }, - "compactPlayback": { - "build": 60, - "installedAndLaunched": true, - "features": [ - "One-line version and content with background RMS waveform", - "Current spoken word follows original audio player clock; silent gaps clear the word", - "Playback trims leading/trailing silence with 80ms/120ms padding; original recording preserved" - ], - "validation": [ - "Device build passed", - "Native fullscreen playback/restore UI test passed", - "Native browser bridge test passed", - "Swift word onset/offset/gap checks passed", - "Swift silence trimming and internal pause checks passed", - "Actual wwBonog recording inspected: playback range 0.68\u20133.78 seconds; all recognized words retained" - ], - "limits": [ - "Trim uses energy threshold; noisy recordings may retain ambient sound", - "Timestamp accuracy depends on on-device speech recognition", - "Original recording playback on phone has not been manually auditioned this turn" - ] - }, - "playOnlyNarration": { - "build": 61, - "installed": true, - "validation": "Device build passed; version selection calls checkout without scheduling speech; word UI gated on fullscreen playback", - "behavior": "Tapping versions is silent, with no spoken-word label. Play retains fullscreen original recording playback and synced words." - }, - "rolodex": { - "build": 64, - "installedAndLaunched": true, - "behavior": "Top-anchored snapping version rows select silently after 160ms settling; preview and version/content caption follow selection; identity remains above preview; fullscreen Play unchanged.", - "validation": [ - "Device build passed", - "Native swipe UI test passed (15.5 seconds): selected version changed, spoken-word label absent, identity remained visible" - ], - "limits": "UI swipe test passed on build63; build64 removes top padding and moves snap anchor to top after screenshot review. Xcode test runner was interrupted after suite passed because report finalization stalled." - }, - "continuousVersions": { - "build": 66, - "installedAndLaunched": true, - "behavior": "Single continuous list below preview; active version appears once; version labels left, utterances right; fixed row height and font size; no scaling transition; silent snap selection. Fullscreen Play keeps its own version/word caption.", - "validation": [ - "Device build passed", - "Native scrolling selection test passed (13.2 seconds)" - ] + "visualAndRuntimePassed": true, + "nativeVerdictAcknowledged": false, + "paintMs": 45921, + "finishedMs": 51763, + "version": 7 + } + ], + "rejectedAttempts": [ + { + "runID": "5238B9C7-94D7-43F0-B8B8-A3DE56402062", + "index": 5, + "reason": "Flame began inside body; rejected and undone" + }, + { + "runID": "084761A5-3954-472F-8F61-4F625AF31E64", + "index": 5, + "reason": "No verified version committed; previous scene retained" + } + ], + "motionReview": "24 chronological phone snapshots each for accepted thruster and flight; source confirms downward star wrapping and shared rotation of all ship parts.", + "normalMode": "Not confirmed: developer connection dropped after uploading final acceptance, before normal-mode launch could succeed." + }, + "walkiewareThreads": { + "backendRevision": "34291d3d74", + "focusedTests": 9, + "phoneCode": "wwHesop", + "remoteEditRoundTripMs": 943, + "remoteEditVersion": 69, + "guardedUndoHead": 68, + "currentHeadAfterUserEdit": 70, + "build27RestoredHead": 70, + "scope": "Remote edit timing includes rendering and saved acknowledgement, excludes speech and generation.", + "acRouteVerification": "Route reaches sign-in screen in browser harness; authenticated playback not yet verified.", + "threeDimensionalDemo": { + "code": "wwLehoh", + "reviewedFrames": 48, + "video": "threads/wwLehoh/spaceship-3d.mp4", + "scope": "Separate browser demo; CPU-projected 3D geometry. Generation attempt hit output limit; direct source edit verified." + } + }, + "versionFeed": { + "utterances": true, + "currentVersionHighlighted": true, + "idleStatusRemoved": true, + "codeActivityRemoved": true, + "failedAttemptPreservesWorkingHead": true, + "musicalContour": true, + "relativeTimestamps": true, + "tapToCheckout": true, + "branchRetainsFutureVersions": true, + "keepUndoRemoved": true, + "branchParentVisible": true + }, + "utteranceLimit": { + "seconds": 8, + "nativeDeadline": true, + "visibleCountdown": true, + "browserAutoSubmitTest": "passed", + "duplicateReleaseTest": "passed", + "scope": "Browser speech bridge mocked; native signed build passed." + }, + "previewStyle": "Plain 4:3 aspect ratio, normal colors, no bezel or filter; native bridge pins zero runtime gap", + "framing": { + "before": { + "x": 4, + "y": 4, + "width": 422, + "height": 292, + "viewport": [ + 430, + 300 + ] }, - "singlePendingRow": { - "build": 68, - "installed": true, - "validation": [ - "Device build passed", - "Source review confirms only pending row has generation spinner" - ], - "behavior": "No Building status line; one pending utterance row, spinner and stop icon. Pending row stays visible above scroll targets; live output stream retained." + "after": { + "x": 0, + "y": 0, + "width": 431, + "height": 300, + "viewport": [ + 431, + 300 + ] }, - "outputContinuation": { - "build": 69, - "installed": true, - "validation": [ - "22 AcServer tests passed, including completed-tool retention, truncated-argument discard, continuation exhaustion", - "8 recovery/context/input tests passed", - "Browser bridge test passed including checkpoint restored into next provider request", - "Device build passed" - ], - "behavior": "Walkieware permits 4 output-limit continuations without consuming tool rounds; 12 tool rounds; failed attempts retain last rendered source for retry. Native feed shows streamed code rather than tool JSON. Generic failure line removed from upper UI.", - "limits": "Provider/billing limits remain. Repeated output cutoffs eventually pause with resumable checkpoint. Existing wwGihap failure predates checkpoint persistence; retry begins from saved v2. No live provider replay yet." + "scope": "Real AC browser runtime; force no-gap and viewport resize", + "deployedRevision": "e4cf37115b", + "productionResizeCheck": { + "nogap": true, + "x": 0, + "y": 0, + "width": 404, + "height": 303, + "viewport": [ + 404, + 303 + ] } -} + }, + "identityHeader": "@handle / wwCode below preview, aligned to picture right edge; character colors and comic styling retained", + "liveLayout": { + "code": "wwFifuh", + "acknowledged": true, + "unchangedLedger": true, + "transport": "owner-authenticated WebSocket", + "scope": "CSS updated open physical phone app after launch, no restart for layout command" + }, + "freshScreen": "Prototype controls and blank preview caption hidden; old review MutationObserver and gamepad/keyboard controller removed from generated bundle; initial version persisted", + "historyPlacement": "Immediately beneath preview caption; scroll occupies remaining space above talk button", + "nativeShell": { + "nativeControls": [ + "header", + "preview caption", + "version feed", + "musical contour", + "recording transcript", + "hold progress", + "account/new-piece menu" + ], + "engine": "Dedicated Walkieware HTML; JS ledger remains authoritative; typed display snapshots; throttled/deduplicated; history only on change", + "runtime": "Persistent WKWebView through version and card changes; separate weak coordinator", + "progress": "Native TimelineView begins on listening event; eight-second native deadline retained", + "screenshots": [ + "native-shell/walkieware-native-empty.png", + "native-shell/walkieware-native-history.png", + "native-shell/walkieware-native-recording.png" + ], + "screenshotScope": "Simulator; populated and recording screens are isolated fixtures, not live microphone recordings", + "contractTests": "Passed: early provisional previews, snapshots without source/token, delta history, native checkout, native layout tokens", + "physicalLiveLayout": { + "code": "wwFifuh", + "head": 0, + "unchangedLedger": true, + "fromSpacing": 12, + "toSpacing": 10, + "nativeAcknowledgement": true, + "restartedForLayout": false + } + }, + "swipeToType": { + "directions": [ + "left", + "right" + ], + "revealThresholdPoints": 18, + "openThresholdPoints": 72, + "characterLimit": 96, + "voiceCancelledOnSwipe": true, + "tests": "Native XCTest case passed both directions, truncation and no version change on cancel; speech mocked in simulator fixture. Xcode result finalization stalled after passed suite and was interrupted." + }, + "basePiece": { + "source": "noiseTinted([128,128,128],0,0)", + "head": 0, + "code": "wwVufor", + "versions": 1, + "devicePainted": true, + "runtimeErrors": [], + "oldBlankThread": "archived locally before assigning new immutable v0", + "existingEditedHistory": "preserved", + "screenshot": "native-shell/walkieware-native-static.png" + }, + "latestIteration": { + "build": 46, + "installedOnPhone": true, + "uiTest": "Passed: Type left / Talk right, inline typing, 96-character cap, preview above keyboard, cancel preserves version in light and dark appearances", + "bridgeTest": "Passed native-shell contract", + "dragRepair": { + "thread": "wwVufor", + "version": 14, + "cause": "API guide incorrectly documented id instead of pointerId", + "validation": "Grab, move, release with pointerId zero passed; device accepted repaired version" + }, + "theme": "Slab status colors across background, controls, ink and history; system/light/dark selection", + "screenshots": "native-shell/walkieware-ready-{light,dark}.png (simulator fixtures, before final dock background mask)" + }, + "buttonLabelIteration": { + "build": 47, + "installedOnPhone": true, + "validation": "Device and simulator builds passed; two simulator frames visually inspected", + "type": "Cyan, bold monospace, type-in animation", + "talk": "Orange, comic font, outward-moving rays", + "reduceMotion": "Both labels remain static", + "launch": "Blocked: device locked" + }, + "layoutIteration": { + "build": 52, + "installedAndLaunched": true, + "base": "Random CSS hex color persisted in v0; no automatic title", + "caption": "Running version left, handle/code right, below preview", + "history": "Alternating backgrounds, outlined comic version labels", + "validation": [ + "base-piece tests: 2 passed", + "native bridge contract passed", + "device and simulator builds passed" + ] + }, + "storyContextAndRecording": { + "build": 57, + "validation": [ + "Device build passed", + "9 focused JS tests passed", + "Native fullscreen story UI test passed on build55; selected version restored", + "Original PCM file round-trip preserved duration, sample rate and sample values", + "Native bridge output streaming/recovery/story checks passed on final build57 bundle" + ], + "changes": [ + "Bounded live output feed", + "Selected branch ancestry sent with each request", + "Ordinary spoken edits do not imply transcript or acoustic visualization", + "Recover interrupted request once, then explicit retry", + "Original microphone recordings saved locally and linked through version request metadata", + "No prompt or generated instruction beneath preview" + ], + "limits": [ + "Original microphone playback only available for newly captured recordings on this device; old/typed versions fall back to speech synthesis", + "Hardware microphone capture/playback not yet auditioned", + "Intent policy evaluated against saved wwMupol/wwTamof evidence, not a fresh live model replay", + "No confirmed native crash report; reload recovery tested, not a forced physical-device crash" + ], + "installedOnPhone": true + }, + "inferenceIsolation": { + "build": 58, + "installed": true, + "validation": [ + "Device build passed", + "3 input-routing tests passed", + "Browser test confirmed ordinary spoken request reaches mocked provider without mixed-input wrapper or recording ID; history/recovery/live-output checks passed" + ], + "behavior": "Ordinary transcripts only; retain audio in version history. Sound evidence and Jev advice only for nonverbal input or explicit sound references.", + "limits": "Sound references use a conservative phrase rule, not a learned speech-versus-music classifier. Existing generated scenes are not automatically rewritten. No fresh live provider quality evaluation." + }, + "compactPlayback": { + "build": 60, + "installedAndLaunched": true, + "features": [ + "One-line version and content with background RMS waveform", + "Current spoken word follows original audio player clock; silent gaps clear the word", + "Playback trims leading/trailing silence with 80ms/120ms padding; original recording preserved" + ], + "validation": [ + "Device build passed", + "Native fullscreen playback/restore UI test passed", + "Native browser bridge test passed", + "Swift word onset/offset/gap checks passed", + "Swift silence trimming and internal pause checks passed", + "Actual wwBonog recording inspected: playback range 0.68\u20133.78 seconds; all recognized words retained" + ], + "limits": [ + "Trim uses energy threshold; noisy recordings may retain ambient sound", + "Timestamp accuracy depends on on-device speech recognition", + "Original recording playback on phone has not been manually auditioned this turn" + ] + }, + "playOnlyNarration": { + "build": 61, + "installed": true, + "validation": "Device build passed; version selection calls checkout without scheduling speech; word UI gated on fullscreen playback", + "behavior": "Tapping versions is silent, with no spoken-word label. Play retains fullscreen original recording playback and synced words." + }, + "rolodex": { + "build": 64, + "installedAndLaunched": true, + "behavior": "Top-anchored snapping version rows select silently after 160ms settling; preview and version/content caption follow selection; identity remains above preview; fullscreen Play unchanged.", + "validation": [ + "Device build passed", + "Native swipe UI test passed (15.5 seconds): selected version changed, spoken-word label absent, identity remained visible" + ], + "limits": "UI swipe test passed on build63; build64 removes top padding and moves snap anchor to top after screenshot review. Xcode test runner was interrupted after suite passed because report finalization stalled." + }, + "continuousVersions": { + "build": 66, + "installedAndLaunched": true, + "behavior": "Single continuous list below preview; active version appears once; version labels left, utterances right; fixed row height and font size; no scaling transition; silent snap selection. Fullscreen Play keeps its own version/word caption.", + "validation": [ + "Device build passed", + "Native scrolling selection test passed (13.2 seconds)" + ] + }, + "singlePendingRow": { + "build": 68, + "installed": true, + "validation": [ + "Device build passed", + "Source review confirms only pending row has generation spinner" + ], + "behavior": "No Building status line; one pending utterance row, spinner and stop icon. Pending row stays visible above scroll targets; live output stream retained." + }, + "outputContinuation": { + "build": 69, + "installed": true, + "validation": [ + "22 AcServer tests passed, including completed-tool retention, truncated-argument discard, continuation exhaustion", + "8 recovery/context/input tests passed", + "Browser bridge test passed including checkpoint restored into next provider request", + "Device build passed" + ], + "behavior": "Walkieware permits 4 output-limit continuations without consuming tool rounds; 12 tool rounds; failed attempts retain last rendered source for retry. Native feed shows streamed code rather than tool JSON. Generic failure line removed from upper UI.", + "limits": "Provider/billing limits remain. Repeated output cutoffs eventually pause with resumable checkpoint. Existing wwGihap failure predates checkpoint persistence; retry begins from saved v2. No live provider replay yet." + }, + "kidlispStop": { + "build": 70, + "installedAndLaunched": true, + "behavior": "Pending-row stop control is kidlisp.com's: red disc (244,67,54 light / 239,83,80 dark) with a white 2pt-rounded square, drop shadow and top highlight, 0.95 press scale.", + "validation": [ + "Device build passed", + "Installed and launched on the iPhone 14 Pro Max" + ], + "limits": "Visual check on device by @jeffrey; no simulator fixture renders the busy state yet." + }, + "reasoningOff": { + "build": 71, + "finding": "Desktop replay of the wwGihap \"Someone is eating them\" edit: 23.7s over 3 rounds; 4876 of 7396 output tokens were DeepSeek thinking, first visible code at 11.8s and 6.3s per round, headers in 0.6s, streaming about 320 tokens/s.", + "change": "Walkieware asks for reasoning {effort:\"none\"}; AcServer forwards a reasoning object; the relay validates and passes it to OpenRouter.", + "validation": [ + "13 relay policy tests passed incl. reasoning shapes", + "AcServer tests passed" + ], + "limits": "Needs a lith deploy before the phone benefits; the deployed relay drops the field. Live re-measure owed after deploy." + } +} \ No newline at end of file diff --git a/apple/walkieware/Walkieware.xcodeproj/project.pbxproj b/apple/walkieware/Walkieware.xcodeproj/project.pbxproj index 901199b841..b8e3c0921d 100644 --- a/apple/walkieware/Walkieware.xcodeproj/project.pbxproj +++ b/apple/walkieware/Walkieware.xcodeproj/project.pbxproj @@ -374,7 +374,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 69; + CURRENT_PROJECT_VERSION = 71; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = FB5948YR3S; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -441,7 +441,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 69; + CURRENT_PROJECT_VERSION = 71; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = FB5948YR3S; ENABLE_NS_ASSERTIONS = NO; diff --git a/apple/walkieware/project.yml b/apple/walkieware/project.yml index 9bd861e7dd..cd73c3ade4 100644 --- a/apple/walkieware/project.yml +++ b/apple/walkieware/project.yml @@ -9,7 +9,7 @@ settings: CODE_SIGN_STYLE: Automatic SWIFT_VERSION: "5.0" MARKETING_VERSION: "0.1.0" - CURRENT_PROJECT_VERSION: "69" + CURRENT_PROJECT_VERSION: "71" targets: Walkieware: type: application diff --git a/apple/walkieware/run.sh b/apple/walkieware/run.sh index f48dcca7d8..a3de675914 100755 --- a/apple/walkieware/run.sh +++ b/apple/walkieware/run.sh @@ -16,7 +16,7 @@ if [[ "$mode" == simulator ]]; then elif [[ "$mode" == device ]]; then derived=${DERIVED:-/tmp/walkieware-dd} xcodebuild -project Walkieware.xcodeproj -scheme Walkieware -configuration Debug -destination 'generic/platform=iOS' -derivedDataPath "$derived" -allowProvisioningUpdates -jobs 2 build - device=${DEVICE:-$(xcrun devicectl list devices --json-output - 2>/dev/null | python3 -c 'import json,sys; devices=json.load(sys.stdin).get("result",{}).get("devices",[]); matches=[d["identifier"] for d in devices if d.get("hardwareProperties",{}).get("deviceType")=="iPhone" and d.get("connectionProperties",{}).get("pairingState")=="paired"]; print(matches[0] if len(matches)==1 else "")')} + device=${DEVICE:-$(xcrun devicectl list devices --json-output - 2>/dev/null | python3 -c 'import json,sys; devices=json.load(sys.stdin).get("result",{}).get("devices",[]); matches=[d["identifier"] for d in devices if d.get("hardwareProperties",{}).get("deviceType")=="iPhone" and d.get("hardwareProperties",{}).get("reality")=="physical" and d.get("connectionProperties",{}).get("pairingState")=="paired"]; print(matches[0] if len(matches)==1 else "")')} [[ -n "$device" ]] || { echo 'Select a paired iPhone with DEVICE=.' >&2; exit 1; } xcrun devicectl device install app --device "$device" "$derived/Build/Products/Debug-iphoneos/Walkieware.app" xcrun devicectl device process launch --device "$device" --terminate-existing computer.aesthetic.walkieware diff --git a/system/backend/easel-policy.mjs b/system/backend/easel-policy.mjs index 0bc182339c..9d82aa3506 100644 --- a/system/backend/easel-policy.mjs +++ b/system/backend/easel-policy.mjs @@ -32,7 +32,31 @@ export function inferenceRequest(body) { const wanted = body.max_tokens === undefined ? DEFAULT_MAX_TOKENS : body.max_tokens; if (!Number.isSafeInteger(wanted) || wanted < 1) throw new Error("max_tokens must be a positive integer."); if (!Array.isArray(body.messages) || body.messages.length === 0) throw new Error("At least one message is required."); - return { model, maxTokens: Math.min(wanted, HOSTED_MAX_TOKENS) }; + return { model, maxTokens: Math.min(wanted, HOSTED_MAX_TOKENS), reasoning: reasoningRequest(body.reasoning) }; +} + +// OpenRouter's `reasoning` object, forwarded only in the shapes its docs name. +// A surface that paints the piece as it streams asks for {effort:"none"}: +// hidden thinking is paid for, counts against max_tokens, and shows nothing. +const REASONING_EFFORTS = new Set(["none", "minimal", "low", "medium", "high"]); +export function reasoningRequest(reasoning) { + if (reasoning === undefined || reasoning === null) return null; + if (typeof reasoning !== "object" || Array.isArray(reasoning)) throw new Error("reasoning must be an object."); + const out = {}; + if (reasoning.effort !== undefined) { + if (!REASONING_EFFORTS.has(reasoning.effort)) throw new Error("reasoning.effort must be none, minimal, low, medium or high."); + out.effort = reasoning.effort; + } + if (reasoning.max_tokens !== undefined) { + if (!Number.isSafeInteger(reasoning.max_tokens) || reasoning.max_tokens < 0 || reasoning.max_tokens > HOSTED_MAX_TOKENS) throw new Error("reasoning.max_tokens must be a non-negative integer."); + out.max_tokens = reasoning.max_tokens; + } + for (const flag of ["enabled", "exclude"]) { + if (reasoning[flag] === undefined) continue; + if (typeof reasoning[flag] !== "boolean") throw new Error(`reasoning.${flag} must be a boolean.`); + out[flag] = reasoning[flag]; + } + return Object.keys(out).length ? out : null; } export function inferenceBudgetFailure(budget, handle) { diff --git a/system/netlify/functions/easel-inference.mjs b/system/netlify/functions/easel-inference.mjs index 4dd210dd9d..715cd53545 100644 --- a/system/netlify/functions/easel-inference.mjs +++ b/system/netlify/functions/easel-inference.mjs @@ -98,8 +98,8 @@ export const handler = stream(async (event) => { return fail(400, `Malformed request: ${error.message}`); } - let model, maxTokens; - try { ({ model, maxTokens } = inferenceRequest(body)); } + let model, maxTokens, reasoning; + try { ({ model, maxTokens, reasoning } = inferenceRequest(body)); } catch (error) { return fail(400, error.message); } // Has this handle spent its day? Over budget is a refusal here rather than a @@ -152,6 +152,7 @@ export const handler = stream(async (event) => { system: body.system, messages: body.messages, tools: body.tools, + ...(reasoning ? { reasoning } : {}), stream: true, }), }); diff --git a/system/tests/easel-braincells.test.mjs b/system/tests/easel-braincells.test.mjs index 7719f0ba9a..170e76b27b 100644 --- a/system/tests/easel-braincells.test.mjs +++ b/system/tests/easel-braincells.test.mjs @@ -62,6 +62,17 @@ test('the six open models are allowed, flash is the default, and workspace turns assert.equal(inferenceRequest({messages,model:'openai/gpt-5.6-luna'}).model,'openai/gpt-5.6-luna','installed clients keep working'); }); +test('a reasoning object passes through in the documented shapes only',()=>{ + const messages=[{role:'user',content:'hi'}]; + assert.equal(inferenceRequest({messages}).reasoning,null,'absent stays absent'); + assert.deepEqual(inferenceRequest({messages,reasoning:{effort:'none'}}).reasoning,{effort:'none'},'Walkieware turns thinking off'); + assert.deepEqual(inferenceRequest({messages,reasoning:{effort:'low',max_tokens:512,exclude:true,enabled:true,tone:'x'}}).reasoning,{effort:'low',max_tokens:512,enabled:true,exclude:true},'unknown keys are dropped'); + assert.throws(()=>inferenceRequest({messages,reasoning:{effort:'maximum'}}),/reasoning\.effort/); + assert.throws(()=>inferenceRequest({messages,reasoning:{max_tokens:-1}}),/reasoning\.max_tokens/); + assert.throws(()=>inferenceRequest({messages,reasoning:'none'}),/must be an object/); + assert.equal(inferenceRequest({messages,reasoning:{}}).reasoning,null,'an empty object sends nothing'); +}); + test('a reported cost is billed at twice the price, at pack value',()=>{ assert.equal(INFERENCE_MARKUP,2); assert.equal(BRAINCELLS_PER_USD,CREDIT_PACK.credits/(CREDIT_PACK.amount/100)); -- 2.51.2