docs(acceptance): verify B03 Windows permissions and composer recovery

This commit is contained in:
xiaohan.yuan committed 2026-10-21 14:27:13 +08:00
1 parent 1df1861a7a
commit 352d62d49a
24 files changed
+1723

No files matched your search

@@ -0,0 +1,48 @@
> ycode@0.0.7 test:alignment:dom
> node scripts/run-alignment-regression.mjs --require-dom
PASS model alignment: fresh/legacy migration, new/edit/default/delete/reload, valid selection (offline host fixtures)
PASS model settings: deferred owner switch, rename mapping, addition selection, empty deletion, immutable history
PASS session factory: first-send preference, mode preservation, invalid permission rejection (isolated ports)
{"historyMessages":10000,"bytes":747781,"parseMs":4.0756999999999834,"storeHydrationMs":0.28829999999999245,"note":"Node parsing/store benchmark only, not browser rendering or Windows IPC performance"}
session-composer-alignment: loading/cache/retry/races/model/permissions/modes/SSR passed
alignment-conversation: local groups, original expanded order, question projection and truthful status passed
A01 native MessageBubble identity aliases, immutable inputs and ordinary raw output passed
A01 imported native card, linked dedup and unknown-position compatibility passed
question-answer-shell: structural and recovered CSS contracts passed
question-answer-shell: DOM hierarchy, controls linkage, click, Enter, Space and inert contracts passed
Runtime progress, session-grant scope and approval lifecycle regressions passed
Permission intercept static rendering passed; interactive keyboard/focus remains UI acceptance
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"}
[claude-permission] {"permissionMode":"full-access","agentMode":"ask","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"mode-or-inactive-deny"}
[claude-permission] {"permissionMode":"full-access","agentMode":"plan","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"mode-or-inactive-deny"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":true,"branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"subcommandResults","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"safetyCheck","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":true,"matchedAskRule":false,"branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":true,"branch":"rule-approval"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"error-deny"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"e3b98a4da31a127d","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"85aafbf52a5144b5","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"business-question"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"unknown","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"85aafbf52a5144b5","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"business-question"}
Claude host approval policy unit checks passed (no SDK process/application/matching verification)
[claude-permission] {"permissionMode":"full-access","agentMode":"plan","sdkMode":"plan","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"unknown","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"mode-or-inactive-deny"}
Mock SDK replay lifecycle passed: fail closed, retry, session isolation, independent mode guard
B03 offline host policy: 276 checks passed; no real SDK/CLI/model execution.
task popconfirm DOM regression: 34 checks passed (jsdom, not pixel validation)
question-interaction: 24 DOM behavioral checks passed
question-identity: 30 A01 DOM checks passed (not Electron/pixel/SDK acceptance)
completed-fold-nested: real question/tool/thinking/local-summary remount, event, keyboard and identity contracts passed
completed-fold-native-identity: real reducer done correction, native IDs, insertion/reorder, repeated outer toggles, message isolation and legacy fallback passed
Permission intercept DOM: 43 checks passed (not pixel/SDK verification)
{"checks":37,"passed":true,"scope":"Isolated React DOM and CSS contracts; no native keyboard/layout/pixel acceptance"}
{"result":"PASS","phase":"alignment-offline","suites":11}
{"result":"PASS","phase":"alignment-dom","suites":7}
Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

@@ -0,0 +1,100 @@
{
"codeSha": "adbbb3bd37f6043d10cbaa59d6c28ade6387a7f3",
"scope": "Unchanged production app + main/preload/renderer + real Windows SDK/CLI with deterministic local SSE; fresh data; actual UI permission and send",
"checks": [
{
"name": "initial home permission defaults",
"pass": true
},
{
"name": "full selected before first send",
"pass": true
},
{
"name": "full write executed",
"pass": true
},
{
"name": "full PowerShell executed",
"pass": true
},
{
"name": "no approval card under full",
"pass": true
},
{
"name": "persisted full permission",
"pass": true
},
{
"name": "normal input hidden",
"pass": true
},
{
"name": "normal input inert",
"pass": true
},
{
"name": "normal toolbar absent",
"pass": true
},
{
"name": "only one interactive permission dialog",
"pass": true
},
{
"name": "approval receives native focus",
"pass": true
},
{
"name": "hidden native editor cannot receive focus",
"pass": true
},
{
"name": "native typing cannot change hidden draft",
"pass": true
},
{
"name": "failed approval stays in replacement",
"pass": true
},
{
"name": "draft restored after denial",
"pass": true
},
{
"name": "normal toolbar restored",
"pass": true
},
{
"name": "default denied actual write",
"pass": true
},
{
"name": "UI session grant executes command",
"pass": true
},
{
"name": "grant next turn reaches completion",
"pass": true
},
{
"name": "session grant prevents repeated approval",
"pass": true
},
{
"name": "failed cancel error visible in replacement",
"pass": true
},
{
"name": "cancel retry restores normal input",
"pass": true
},
{
"name": "zero renderer console errors",
"pass": true
}
],
"requests": 11,
"errors": []
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

@@ -0,0 +1,58 @@
const fs=require('node:fs/promises'), path=require('node:path'), assert=require('node:assert/strict');
if(!process.versions.electron){(async()=>{
const dir=await fs.mkdtemp(path.resolve('.tmp/b03-app-'));for(const n of ['data','home','workspace'])await fs.mkdir(path.join(dir,n));
const net=require('node:net').createServer();await new Promise(r=>net.listen(0,'127.0.0.1',r));const port=net.address().port;await new Promise(r=>net.close(r));
const model={id:'b03-local',name:'B03 Local Fixture',model:'claude-loopback',providerId:'custom',protocol:'anthropic',authMode:'api-key',apiKeyPlain:'local-fixture-placeholder',baseUrl:`http://127.0.0.1:${port}`,supportsToolCall:true,contextWindowTokens:200000,maxOutputTokens:4096};
await fs.writeFile(path.join(dir,'data/models.json'),JSON.stringify({version:1,models:[model],selectedModelId:model.id}));
await fs.writeFile(path.join(dir,'data/workspaces.json'),JSON.stringify({selectedWorkspaceId:'b03-space',workspaces:[{id:'b03-space',name:'QA Workspace',root:path.join(dir,'workspace'),createdAt:Date.now()}]}));
await fs.writeFile(path.join(dir,'data/config.json'),JSON.stringify({workspaceRoot:path.join(dir,'workspace'),preventSleep:false,autoLaunch:false}));
for(const phase of ['first','restart']){
const env={...process.env,YCODE_USER_DATA_DIR:path.join(dir,'data'),YCODE_QA_DIRECTORY:dir,YCODE_SKIP_KERNEL_DATA_RESET:'1',YCODE_DISABLE_GPU:'1',YCODE_DISABLE_SYSTEM_INTEGRATION:'1',HOME:path.join(dir,'home'),USERPROFILE:path.join(dir,'home'),CLAUDE_CODE_GIT_BASH_PATH:'C:/Users/Administrator/scoop/apps/git/current/bin/bash.exe',CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:'1',DISABLE_TELEMETRY:'1',DISABLE_ERROR_REPORTING:'1',B03_APP_DIR:dir,B03_APP_PORT:String(port),B03_APP_PHASE:phase};
for(const k of Object.keys(env))if(/^(ANTHROPIC_|CLAUDE_CODE_OAUTH_TOKEN)/.test(k))delete env[k];delete env.ELECTRON_RUN_AS_NODE;delete env.ELECTRON_RENDERER_URL;
const c=require('node:child_process').spawn(require('electron'),['--no-sandbox','--disable-gpu-sandbox',__filename],{env,windowsHide:true,stdio:['ignore','pipe','pipe']});let log='';c.stdout.on('data',x=>log+=x);c.stderr.on('data',x=>log+=x);const t=setTimeout(()=>c.kill(),120000);const exit=await new Promise(r=>c.on('exit',r));clearTimeout(t);await fs.writeFile(path.join(dir,phase+'-process.txt'),log);console.log(JSON.stringify({directory:dir,phase,exit}));if(exit!==0){console.error(log.slice(-8000));process.exitCode=1;break}
}
})().catch(e=>{console.error(e);process.exitCode=1})}else{
const {app,BrowserWindow,ipcMain}=require('electron'),{pathToFileURL}=require('node:url'),{createServer}=require('node:http');
const dir=process.env.B03_APP_DIR,phase=process.env.B03_APP_PHASE,workspace=path.join(dir,'workspace');app.disableHardwareAcceleration();app.setPath('home',path.join(dir,'home'));
let rejectRespondOnce=phase==='first',rejectCancelOnce=phase==='first';const realHandle=ipcMain.handle.bind(ipcMain);ipcMain.handle=(channel,listener)=>realHandle(channel,async(...args)=>{if(channel==='chat:respond'&&rejectRespondOnce){rejectRespondOnce=false;throw Error('QA approval submission failure')}if(channel==='chat:cancel'&&rejectCancelOnce){rejectCancelOnce=false;throw Error('QA cancellation failure')}return listener(...args)});
let win,stage='start',scenario='full',issued=0,requestCount=0,held,releaseHeld=false;const checks=[],errors=[];let approvals=0;
const pause=ms=>new Promise(r=>setTimeout(r,ms)),read=s=>win.webContents.executeJavaScript(s);
async function wait(s){for(let i=0;i<350;i++){const x=await read(s);if(x)return x;await pause(30)}throw Error('Timeout '+s)}
function check(name,x){checks.push({name,pass:!!x});assert.ok(x,name)}
async function shot(n){await pause(200);await fs.writeFile(path.join(dir,phase+'-'+n+'.png'),(await win.webContents.capturePage()).toPNG())}
async function fill(text){await read('document.querySelector(".wb-composer textarea").focus()');await win.webContents.insertText(text);await wait('document.querySelector(".wb-composer textarea").value.includes('+JSON.stringify(text)+')')}
async function send(text){await fill(text);await wait('!document.querySelector(".cr-input-toolbar__send:not(.cr-send-button--stop)").disabled');await read('document.querySelector(".cr-input-toolbar__send:not(.cr-send-button--stop)").click()')}
async function settled(){await wait('!document.querySelector(".cr-send-button--stop") && !document.querySelector("[data-composer-approval]")');await pause(200)}
async function permission(full){await read('document.querySelector(".yc-source-permission-trigger > button").click()');await wait('!!document.querySelector(".cr-permission-panel__row")');await read('document.querySelector(".cr-permission-panel__row").click()');if(full){await wait('!!document.querySelector(".permission-confirm-acknowledgement")');await read('document.querySelector(".permission-confirm-acknowledgement").click()');await wait('!document.querySelector(".wb-composer__danger-button").disabled');await read('document.querySelector(".wb-composer__danger-button").click()')};await wait('!document.querySelector(".cr-permission-panel") && !document.querySelector(".permission-confirm-dialog")')}
const server=createServer((req,res)=>{if(++requestCount>35){res.writeHead(429).end();return}let raw='';req.on('data',x=>raw+=x);req.on('end',async()=>{
try{if(!req.url.includes('/messages')){res.writeHead(200).end('{}');return}const body=JSON.parse(raw);if(scenario==='default'&&!releaseHeld){await new Promise(r=>held=r)};
const steps=scenario==='full'?[{name:'Write',input:{file_path:path.join(workspace,phase+'-written.txt'),content:'verified'}},{name:'PowerShell',input:{command:`[IO.File]::WriteAllText('${phase}-command.txt','verified')`,timeout:5000}}]:scenario==='grant'?[{name:'Bash',input:{command:'git init app-grant-repo',timeout:5000}}]:[{name:'Write',input:{file_path:path.join(workspace,'default-must-not-write.txt'),content:'blocked'}}];
const step=steps[issued++];const emit=(event,data)=>res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);res.writeHead(200,{'content-type':'text/event-stream'});
emit('message_start',{type:'message_start',message:{id:'msg_'+requestCount,type:'message',role:'assistant',model:body.model,content:[],stop_reason:null,stop_sequence:null,usage:{input_tokens:10,output_tokens:1}}});emit('content_block_start',{type:'content_block_start',index:0,content_block:step?{type:'tool_use',id:'tool_'+requestCount,name:step.name,input:{}}:{type:'text',text:''}});emit('content_block_delta',{type:'content_block_delta',index:0,delta:step?{type:'input_json_delta',partial_json:JSON.stringify(step.input)}:{type:'text_delta',text:'B03 fixture complete.'}});emit('content_block_stop',{type:'content_block_stop',index:0});emit('message_delta',{type:'message_delta',delta:{stop_reason:step?'tool_use':'end_turn',stop_sequence:null},usage:{output_tokens:5}});emit('message_stop',{type:'message_stop'});res.end();}catch(e){res.destroy(e)}
})});
const timer=setTimeout(()=>{console.error('WATCHDOG',stage);app.exit(1)},100000);
;(async()=>{await new Promise(r=>server.listen(Number(process.env.B03_APP_PORT),'127.0.0.1',r));await import(pathToFileURL(path.resolve('out/main/index.mjs')).href);await app.whenReady();win=BrowserWindow.getAllWindows()[0];win.setSize(1336,902);win.showInactive();win.webContents.on('console-message',(_e,l,m)=>{if(l>=3)errors.push(m)});
await wait('!!window.ycode && !!document.querySelector(".wb-composer textarea")');await pause(500);
if(phase==='first'){
stage='first-full-selection';check('initial home permission defaults',!(await read('document.querySelector(".yc-source-permission-trigger > button").textContent')).includes('完全访问'));await permission(true);check('full selected before first send',(await read('document.querySelector(".yc-source-permission-trigger > button").textContent')).includes('完全访问'));
}else{
stage='restart-load';const sessionId=await fs.readFile(path.join(dir,'session-id.txt'),'utf8');const sessionSelector=JSON.stringify('[data-session-id="'+sessionId+'"]');await wait('!!document.querySelector('+sessionSelector+')');await read('document.querySelector('+sessionSelector+').click()');await wait('!document.querySelector(".yc-session-skeleton") && !!document.querySelector(".wb-composer textarea")');check('restart restores saved full label',(await read('document.querySelector(".yc-source-permission-trigger > button").textContent')).includes('完全访问'));
}
await read('window.__b03Observer=new MutationObserver(()=>{window.__b03Approvals=(window.__b03Approvals||0)+(document.querySelector("[data-composer-approval]")?1:0)});window.__b03Observer.observe(document.body,{subtree:true,childList:true});true');
stage='full-send';await send('B03_'+phase+'_FULL');for(let i=0;issued<3&&i<600;i++)await pause(30);assert.ok(issued>=3,'three loopback model requests completed');await wait('document.querySelector(".chat-thread")?.textContent.includes("B03 fixture complete.")');await settled();check('full write executed',(await fs.readFile(path.join(workspace,phase+'-written.txt'),'utf8'))==='verified');check('full PowerShell executed',(await fs.readFile(path.join(workspace,phase+'-command.txt'),'utf8'))==='verified');check('no approval card under full',!(await read('window.__b03Approvals||0')));
const sessions=await read('window.ycode.session.list()');const current=sessions.find(s=>s.permissionMode==='full-access');check('persisted full permission',!!current);await fs.writeFile(path.join(dir,'session-id.txt'),current.id);await shot('full-completed');
if(phase==='first'){
stage='default-selection';await permission(false);scenario='default';issued=0;await send('B03_DEFAULT_DENY');while(!held)await pause(30);await fill('PRESERVED_DRAFT');releaseHeld=true;held();
stage='approval';await wait('!!document.querySelector("[data-composer-approval]")');check('normal input hidden',await read('document.querySelector(".conversation-input-area__input-stack").hidden && getComputedStyle(document.querySelector(".conversation-input-area__input-stack")).display==="none"'));check('normal input inert',await read('document.querySelector(".conversation-input-area__input-stack").hasAttribute("inert")'));check('normal toolbar absent',await read('!document.querySelector(".wb-composer__toolbar")'));check('only one interactive permission dialog',await read('document.querySelectorAll(".conversation-intercept-card[role=dialog]").length===1'));await shot('bottom-approval');
check('approval receives native focus',await read('!!document.activeElement.closest("[data-composer-approval]")'));await read('document.querySelector(".wb-composer textarea").focus()');check('hidden native editor cannot receive focus',await read('!document.querySelector(".conversation-input-area__input-stack").contains(document.activeElement)'));win.webContents.sendInputEvent({type:'keyDown',keyCode:'X'});win.webContents.sendInputEvent({type:'char',keyCode:'x'});win.webContents.sendInputEvent({type:'keyUp',keyCode:'X'});await pause(80);check('native typing cannot change hidden draft',(await read('document.querySelector(".wb-composer textarea").value'))==='PRESERVED_DRAFT');
await read('document.querySelector(".conversation-intercept-card__option--reject").click()');await wait('document.querySelector("[data-composer-approval] [role=alert]")?.textContent.includes("QA approval submission failure")');check('failed approval stays in replacement',await read('document.querySelector(".conversation-input-area__input-stack").hidden && !document.querySelector(".wb-composer__toolbar")'));await shot('approval-failure');
await read('document.querySelector(".conversation-intercept-card__option--reject").click()');await wait('!document.querySelector("[data-composer-approval]")');await settled();check('draft restored after denial',(await read('document.querySelector(".wb-composer textarea").value'))==='PRESERVED_DRAFT');check('normal toolbar restored',await read('!!document.querySelector(".wb-composer__toolbar")'));let absent=false;try{await fs.stat(path.join(workspace,'default-must-not-write.txt'))}catch(e){absent=e.code==='ENOENT'}check('default denied actual write',absent);await shot('draft-restored');
stage='grant-first';scenario='grant';issued=0;await send('B03_GRANT_FIRST');await wait('!!document.querySelector("[data-composer-approval] [data-option-id=allow-always]")');await shot('session-grant');await read('document.querySelector("[data-option-id=allow-always]").click()');for(let i=0;issued<2&&i<500;i++)await pause(30);await settled();check('UI session grant executes command',(await fs.stat(path.join(workspace,'app-grant-repo/.git'))).isDirectory());
stage='grant-next';issued=0;await read('window.__b03Approvals=0');await send('B03_GRANT_NEXT');for(let i=0;issued<2&&i<500;i++)await pause(30);check('grant next turn reaches completion',issued>=2);await settled();check('session grant prevents repeated approval',!(await read('window.__b03Approvals||0')));stage='cancel-failure';scenario='default';issued=0;await send('B03_CANCEL');await wait('!!document.querySelector("[data-composer-approval]")');await read('document.querySelector(".wb-composer__approval-stop").click()');await wait('document.querySelector("[data-composer-approval] [role=alert]")?.textContent.includes("QA cancellation failure")');check('failed cancel error visible in replacement',await read('document.querySelector(".conversation-input-area__input-stack").hidden'));await shot('cancel-failure');await read('document.querySelector(".wb-composer__approval-stop").click()');await settled();check('cancel retry restores normal input',await read('!document.querySelector(".conversation-input-area__input-stack").hidden && !!document.querySelector(".wb-composer__toolbar")'));await permission(true);
}
if(phase==='restart'){
stage='grant-expired-after-restart';await permission(false);scenario='grant';issued=0;await send('B03_GRANT_RESTART');await wait('!!document.querySelector("[data-composer-approval] [data-option-id=allow-always]")');check('session grant expires after process restart',true);await shot('grant-reapproval-after-restart');await read('document.querySelector(".conversation-intercept-card__option--reject").click()');for(let i=0;issued<2&&i<500;i++)await pause(30);await settled();
}
check('zero renderer console errors',errors.length===0);await fs.writeFile(path.join(dir,phase+'-report.json'),JSON.stringify({codeSha:'adbbb3bd37f6043d10cbaa59d6c28ade6387a7f3',scope:'Unchanged production app + main/preload/renderer + real Windows SDK/CLI with deterministic local SSE; fresh data; actual UI permission and send',checks,requests:requestCount,errors},null,2));clearTimeout(timer);server.closeAllConnections();server.close();app.exit(0);
})().catch(async e=>{console.error(stage,e);if(win)await shot('failure').catch(()=>{});await fs.writeFile(path.join(dir,phase+'-failure.json'),JSON.stringify({stage,message:String(e),checks,errors},null,2));server.closeAllConnections();server.close();app.exit(1)})
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

@@ -0,0 +1,36 @@
{
"codeSha": "adbbb3bd37f6043d10cbaa59d6c28ade6387a7f3",
"scope": "Unchanged production app + main/preload/renderer + real Windows SDK/CLI with deterministic local SSE; fresh data; actual UI permission and send",
"checks": [
{
"name": "restart restores saved full label",
"pass": true
},
{
"name": "full write executed",
"pass": true
},
{
"name": "full PowerShell executed",
"pass": true
},
{
"name": "no approval card under full",
"pass": true
},
{
"name": "persisted full permission",
"pass": true
},
{
"name": "session grant expires after process restart",
"pass": true
},
{
"name": "zero renderer console errors",
"pass": true
}
],
"requests": 5,
"errors": []
}
@@ -0,0 +1,660 @@
> ycode@0.0.7 build
> npm run typecheck && electron-vite build
> ycode@0.0.7 typecheck
> tsc --noEmit -p tsconfig.node.json && tsc --noEmit -p tsconfig.web.json
vite v8.3.4 building ssr environment for production...
transforming...
✓ 444 modules transformed.
rendering chunks...
out/main/index.mjs 1,599.48 kB
✓ built in 375ms
vite v8.3.4 building ssr environment for production...
transforming...
✓ 2 modules transformed.
rendering chunks...
out/preload/index.cjs 15.89 kB
✓ built in 21ms
vite v8.3.4 building client environment for production...
transforming...
✓ 3039 modules transformed.
rendering chunks...
out/renderer/settings.html 1.57 kB
out/renderer/index.html 1.75 kB
out/renderer/assets/KaTeX_Size3-Regular-CTq5MqoE.woff 4.42 kB
out/renderer/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 4.92 kB
out/renderer/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 5.20 kB
out/renderer/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 5.46 kB
out/renderer/assets/KaTeX_Size4-Regular-BF-4gkZK.woff 5.98 kB
out/renderer/assets/KaTeX_Size2-Regular-oD1tc_U0.woff 6.18 kB
out/renderer/assets/KaTeX_Size1-Regular-C195tn64.woff 6.49 kB
out/renderer/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 6.90 kB
out/renderer/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 6.91 kB
out/renderer/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf 7.58 kB
out/renderer/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff 7.65 kB
out/renderer/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff 7.71 kB
out/renderer/assets/archify-owner-avatar-BdE-HOjX.jpg 9.46 kB
out/renderer/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 9.64 kB
out/renderer/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 10.34 kB
out/renderer/assets/KaTeX_Size4-Regular-DWFBv043.ttf 10.36 kB
out/renderer/assets/KaTeX_Script-Regular-D5yQViql.woff 10.58 kB
out/renderer/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 11.31 kB
out/renderer/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 11.34 kB
out/renderer/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf 11.50 kB
out/renderer/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 12.02 kB
out/renderer/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 12.21 kB
out/renderer/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf 12.22 kB
out/renderer/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff 12.31 kB
out/renderer/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf 12.34 kB
out/renderer/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf 12.36 kB
out/renderer/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff 13.20 kB
out/renderer/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff 13.29 kB
out/renderer/assets/workbuddy-buddy-thumbnail-2713ed5b-CUhW0EYr.png 13.42 kB
out/renderer/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 13.56 kB
out/renderer/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff 14.11 kB
out/renderer/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff 14.40 kB
out/renderer/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff 16.02 kB
out/renderer/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 16.40 kB
out/renderer/assets/KaTeX_Math-Italic-t53AETM-.woff2 16.44 kB
out/renderer/assets/KaTeX_Script-Regular-C5JkGWo-.ttf 16.64 kB
out/renderer/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 16.78 kB
out/renderer/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 16.98 kB
out/renderer/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff 18.66 kB
out/renderer/assets/KaTeX_Math-Italic-DA0__PXp.woff 18.74 kB
out/renderer/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff 19.41 kB
out/renderer/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf 19.43 kB
out/renderer/assets/KaTeX_Fraktur-Regular-CB_wures.ttf 19.57 kB
out/renderer/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf 19.58 kB
out/renderer/assets/KaTeX_Main-Italic-BMLOBm91.woff 19.67 kB
out/renderer/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf 22.36 kB
out/renderer/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf 24.50 kB
out/renderer/assets/KaTeX_Main-Bold-Cx986IdX.woff2 25.32 kB
out/renderer/assets/KaTeX_Main-Regular-B22Nviop.woff2 26.27 kB
out/renderer/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf 27.55 kB
out/renderer/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 28.07 kB
out/renderer/assets/KaTeX_Main-Bold-Jm3AIy58.woff 29.91 kB
out/renderer/assets/KaTeX_Main-Regular-Dr94JaBh.woff 30.77 kB
out/renderer/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf 31.19 kB
out/renderer/assets/KaTeX_Math-Italic-flOr_0UB.ttf 31.30 kB
out/renderer/assets/design-case-3-DaIvrslH.png 32.76 kB
out/renderer/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf 32.96 kB
out/renderer/assets/KaTeX_AMS-Regular-DMm9YOAa.woff 33.51 kB
out/renderer/assets/KaTeX_Main-Italic-3WenGoN9.ttf 33.58 kB
out/renderer/assets/design-case-4-0hVdAJQR.png 45.16 kB
out/renderer/assets/design-case-2-BH_iQ5r3.png 45.56 kB
out/renderer/assets/KaTeX_Main-Bold-waoOVXN0.ttf 51.33 kB
out/renderer/assets/design-case-1-DOYiafVz.png 52.97 kB
out/renderer/assets/KaTeX_Main-Regular-ypZvNtVU.ttf 53.58 kB
out/renderer/assets/KaTeX_AMS-Regular-DRggAlZN.ttf 63.63 kB
out/renderer/assets/workbuddy-appearance-dark-CXQX3TZX.png 109.34 kB
out/renderer/assets/workbuddy-appearance-light-BbpPCukh.png 113.02 kB
out/renderer/assets/codicon-ngg6Pgfi-ngg6Pgfi.ttf 121.97 kB
out/renderer/assets/kimi-DiLyRSiJ.svg 129.22 kB
out/renderer/assets/json.worker-DEWrzUkU-FVRG9O7E.js 438.21 kB
out/renderer/assets/worker-portable-D1lwTqsk-Dg0RNmO0.js 456.22 kB
out/renderer/assets/landing-hero-B6659kdy.png 629.28 kB
out/renderer/assets/html.worker-BC4B-9NY-BDdNc3ca.js 756.63 kB
out/renderer/assets/css.worker-D7wyZb8r-YRw1jg-F.js 1,086.92 kB
out/renderer/assets/ts.worker-BsXRl7a--BbqraoNr.js 8,187.30 kB
out/renderer/assets/ArtifactPierreDiff-CNAfnhAF.css 1.16 kB
out/renderer/assets/GeneralSettingsPanel-CntDyB52.css 1.25 kB
out/renderer/assets/AgentsSettingsPanel-R0teGDyD.css 2.56 kB
out/renderer/assets/AboutHelpSettingsPanel-ksqGLObi.css 5.72 kB
out/renderer/assets/updates-ui-COSnOGKS.css 6.84 kB
out/renderer/assets/AppearanceSettingsPanel-DcaRECSa.css 8.03 kB
out/renderer/assets/ShortcutsSettingsPanel-Bu_5_488.css 18.05 kB
out/renderer/assets/MemorySettingsPanel-C3dtDAif.css 32.49 kB
out/renderer/assets/ModelSettingsPanel-BjNmxQAH.css 88.98 kB
out/renderer/assets/PersonalizationSettingsPanel-DnAyzaM6.css 98.77 kB
out/renderer/assets/app-DH7L1ZF2.css 259.93 kB
out/renderer/assets/index-Cj0yjvuz.css 2,685.07 kB
out/renderer/assets/pie-WAS4IAKB-1a9lbjhh.js 0.11 kB
out/renderer/assets/info-A6RAGUB7-Dsq8pPGK.js 0.11 kB
out/renderer/assets/radar-RG4KPBEZ-BwNT2qWb.js 0.11 kB
out/renderer/assets/packet-AYTQ26CC-C-iOIVQo.js 0.11 kB
out/renderer/assets/cynefin-OW5HDTMX-CTYbUR58.js 0.11 kB
out/renderer/assets/treemap-WGGIJYW6-CWek0LQD.js 0.11 kB
out/renderer/assets/wardley-WFR3VGLG-BnrEXTnU.js 0.11 kB
out/renderer/assets/gitGraph-4MIJSDKK-NHpEvzKf.js 0.12 kB
out/renderer/assets/railroad-74A4TZTK-CyYHr3KR.js 0.12 kB
out/renderer/assets/treeView-Q6P3EWNA-CzdWA6Mh.js 0.12 kB
out/renderer/assets/railroad-peg-WCYAUIDC-DyA9P8dX.js 0.12 kB
out/renderer/assets/architecture-7GRP2DOG-VyF0wzFW.js 0.12 kB
out/renderer/assets/railroad-abnf-HS5TGJTU-DWOH6PDU.js 0.12 kB
out/renderer/assets/railroad-ebnf-LZEXJU2U-B8jXqV-T.js 0.12 kB
out/renderer/assets/eventmodeling-NTZA5JFV-Dmu4IHsI.js 0.12 kB
out/renderer/assets/array-75Ih5Qg4.js 0.16 kB
out/renderer/assets/channel-DtQOCUrd.js 0.25 kB
out/renderer/assets/init-DHdG6DHP.js 0.27 kB
out/renderer/assets/chunk-Y2CYZVJY-CrOJDJJy.js 0.38 kB
out/renderer/assets/chunk-JWPE2WC7-BWmaSNkB.js 0.42 kB
out/renderer/assets/chunk-2Q5K7J3B-BBOGhvIe.js 0.44 kB
out/renderer/assets/prism-tsx-BJWEHjlk.js 0.48 kB
out/renderer/assets/chunk-5VM5RSS4-D50WUAUX.js 0.52 kB
out/renderer/assets/chunk-XXDRQBXY-BsO966Nz.js 0.58 kB
out/renderer/assets/flowDiagram-HODETNUW-Rs0gEc5_.js 0.59 kB
out/renderer/assets/prism-json-DxLGXN1o.js 0.62 kB
out/renderer/assets/codeowners-C7Y3CTAA-BmB2_gvY.js 0.75 kB
out/renderer/assets/prism-clike-BcH_eOfE.js 0.89 kB
out/renderer/assets/tsv-DVa1_Ovr-BeS2kE5e.js 0.94 kB
out/renderer/assets/shellsession-C0HwRpr0-B630Ulnl.js 0.96 kB
out/renderer/assets/javascript-DGySzfUB-CQaVVFGk.js 0.99 kB
out/renderer/assets/settings-CauUETdq.js 1.01 kB
out/renderer/assets/infoDiagram-27XIBGKW-CjoHj39W.js 1.09 kB
out/renderer/assets/swimlanesDiagram-VR7AAH4N-CDVwE8hU.js 1.09 kB
out/renderer/assets/html-derivative-D3Jld805-D0QQ5MTi.js 1.10 kB
out/renderer/assets/prism-go-Cw8Jg9YT.js 1.11 kB
out/renderer/assets/classDiagram-ZZMXUADV-BwWcIhgv.js 1.16 kB
out/renderer/assets/classDiagram-v2-VYDZK3BY-CDfTno2N.js 1.16 kB
out/renderer/assets/stateDiagram-v2-MP3YSRHH-FppKH3cZ.js 1.16 kB
out/renderer/assets/qmldir-DIq06gp2-CFVtueeV.js 1.20 kB
out/renderer/assets/git-rebase-CgwCWTNR-Cpss9r90.js 1.23 kB
out/renderer/assets/chunk-POPQ4Y6H-BrtzJQqe.js 1.23 kB
out/renderer/assets/azcli-Bsxmaz-H-Dgh56k5-.js 1.26 kB
out/renderer/assets/personalization-prefs-DASR3vwn.js 1.28 kB
out/renderer/assets/csv-BRhERoQG-DKrQczXm.js 1.36 kB
out/renderer/assets/prism-latex-CHSuA_Lo.js 1.38 kB
out/renderer/assets/jsx-runtime-C48wkPcG.js 1.41 kB
out/renderer/assets/git-commit-DGtBy1vY-s2uHofP2.js 1.47 kB
out/renderer/assets/AgentsSettingsPanel-CMYBwUKH.js 1.56 kB
out/renderer/assets/xsl-DV28r3Jw-B8bWzO_h.js 1.59 kB
out/renderer/assets/dotenv-DXc2fSbR-CUbEjgJq.js 1.62 kB
out/renderer/assets/general-settings-icons-DOmPIusw.js 1.64 kB
out/renderer/assets/prism-scala-CRTYzCpy.js 1.65 kB
out/renderer/assets/ini-D4-1Iswn-DaNDgFS8.js 1.65 kB
out/renderer/assets/prism-typescript-D-7ZUUQ-.js 1.65 kB
out/renderer/assets/sizeCapture-INFHLROL-CCEMv_MJ.js 1.68 kB
out/renderer/assets/csp-Bsbijh2H-033SDyRW.js 1.69 kB
out/renderer/assets/sparql-Mj-YIaDH-DAUou2oc.js 1.71 kB
out/renderer/assets/prism-css-Cmyw76Xa.js 1.73 kB
out/renderer/assets/ini-DMSv7OY2-xgSkktY4.js 1.74 kB
out/renderer/assets/rolldown-runtime-BJCASTsb-DKQFAHUF.js 1.78 kB
out/renderer/assets/line-AFMfUFqz.js 1.89 kB
out/renderer/assets/fortran-fixed-form-D91DiZLE-NxoUlVkB.js 1.91 kB
out/renderer/assets/docker-B7J3eHK7-C3FNXPS_.js 1.96 kB
out/renderer/assets/hxml-938TheZ7-pE5ojWPT.js 1.97 kB
out/renderer/assets/desktop-BwI-o01e-Da9rFJOd.js 2.03 kB
out/renderer/assets/ordinal-CmpyCcm_.js 2.22 kB
out/renderer/assets/prism-c-B7tsC1jE.js 2.23 kB
out/renderer/assets/rolldown-runtime-EITvVbkG.js 2.32 kB
out/renderer/assets/erb-BgMB3Uiw-CLkRQ9Hf.js 2.40 kB
out/renderer/assets/prism-kotlin-Bc2NQYRR.js 2.43 kB
out/renderer/assets/jssm-CIisorE2-ggX0kbSA.js 2.44 kB
out/renderer/assets/prism-python-CTkfasgb.js 2.48 kB
out/renderer/assets/reg-mzCtpvUf-BHC3bGU6.js 2.54 kB
out/renderer/assets/bat-2PwuskcT-BbFmQdFU.js 2.55 kB
out/renderer/assets/prism-mermaid-DSoNsh6-.js 2.56 kB
out/renderer/assets/pla-HAHcX3CH-DHyEyFew.js 2.57 kB
out/renderer/assets/sb-O6mPt74--_nMcDiF8.js 2.60 kB
out/renderer/assets/chunk-GVQU2GXP-CZIpsKU0.js 2.61 kB
out/renderer/assets/edge-DcEd3r9D-ZJX3cnY_.js 2.62 kB
out/renderer/assets/scheme-C-yCXfo--BHhgh59u.js 2.66 kB
out/renderer/assets/flow9-z3HgHIql-qOic_Sv2.js 2.72 kB
out/renderer/assets/prism-yaml-cmjQ_1eD.js 2.77 kB
out/renderer/assets/gleam-DEEAoY6G-DgJJp7nh.js 2.78 kB
out/renderer/assets/railroadDiagram-O6MQD6OU-CXLwcpeu.js 2.78 kB
out/renderer/assets/diff-lAxbRYdS--5gtlmD4.js 2.79 kB
out/renderer/assets/hy-BKymZdC0-4uNvYh3y.js 2.86 kB
out/renderer/assets/dockerfile-CnkhFuxG-CfXHMZr-.js 3.01 kB
out/renderer/assets/openscad-BRTETpP_-BThzc9qL.js 3.03 kB
out/renderer/assets/pascaligo-DI1dd1Zd-D23AoFdQ.js 3.03 kB
out/renderer/assets/log-Cn1ZE6kb-BE4srnlV.js 3.05 kB
out/renderer/assets/objective-c-gNYZndaF-4hkcNMcE.js 3.06 kB
out/renderer/assets/sparql-DxWbGozt-B7qTmycl.js 3.08 kB
out/renderer/assets/prism-markup-templating-D4pSJIpH.js 3.11 kB
out/renderer/assets/prism-cpp-CEgmwlDT.js 3.11 kB
out/renderer/assets/cameligo-B6LDhzzR-DSNRk43W.js 3.12 kB
out/renderer/assets/wenyan-BVgiL1tD-C7ph_xMt.js 3.12 kB
out/renderer/assets/cairo-D_LzMZ4I-C21twps2.js 3.17 kB
out/renderer/assets/prism-rust-Du0Qa8GC.js 3.18 kB
out/renderer/assets/lua-CJt09SGy-3O0VAMVx.js 3.19 kB
out/renderer/assets/graphql-C0cKWTiE-BQOKksLE.js 3.20 kB
out/renderer/assets/berry-DTcSbIs7-DsDdtWdB.js 3.20 kB
out/renderer/assets/jsonl-Cn_fzNA8-cIG9lf61.js 3.21 kB
out/renderer/assets/json-CKKhFIOr-DuiQFrCF.js 3.29 kB
out/renderer/assets/mips-Df5bwPtM-DJn7b529.js 3.29 kB
out/renderer/assets/jsonc-Bf3Xcgeq-BGBJ2TDY.js 3.31 kB
out/renderer/assets/logo-BxqPaaID-DK9gUnx4.js 3.33 kB
out/renderer/assets/abnfDiagram-VCTEODGH-84GndbAp.js 3.36 kB
out/renderer/assets/go-BejFoqvR-BnGoIlsY.js 3.42 kB
out/renderer/assets/po-DI6EG-tz-DIkePE8T.js 3.44 kB
out/renderer/assets/lexon-5NyrCfQ6-B1bdOCGH.js 3.45 kB
out/renderer/assets/prism-sql-BggiY1Ht.js 3.45 kB
out/renderer/assets/json5-BlijqrwT-Ci88mndw.js 3.45 kB
out/renderer/assets/mipsasm-U3SQfJCQ-kat_Vj1M.js 3.46 kB
out/renderer/assets/sophia-foSZ3xPI-DGYIHURw.js 3.47 kB
out/renderer/assets/tasl-C74Cvwdf-se1Ptgso.js 3.49 kB
out/renderer/assets/genie-CjS3m_gh-DHydh9_z.js 3.56 kB
out/renderer/assets/prism-swift-xplGsQ1n.js 3.56 kB
out/renderer/assets/vala-DMgevQbf-ByJQiTkp.js 3.57 kB
out/renderer/assets/pegDiagram-XKGWAZYB-CRHTDhUd.js 3.59 kB
out/renderer/assets/rel-D6dNeDZv-CUAJzmkw.js 3.60 kB
out/renderer/assets/prism-java-6uFEGwWz.js 3.63 kB
out/renderer/assets/fsharp-Ba-cvOiG-BoxQhS9v.js 3.64 kB
out/renderer/assets/chunk-P2QGCYS3-D_e5QUAT.js 3.65 kB
out/renderer/assets/ebnfDiagram-PWID7BFC-Dz_QBkPG.js 3.66 kB
out/renderer/assets/qsharp-78iLGMHs-Dbh3PRIx.js 3.68 kB
out/renderer/assets/m3-Bu81_nWr-4t51Qx0i.js 3.69 kB
out/renderer/assets/chunk-F27PBJKO-DiRuAudw.js 3.70 kB
out/renderer/assets/pascal-DyPgZbsX-Ba58YM7a.js 3.71 kB
out/renderer/assets/path-CSWwviF2.js 3.79 kB
out/renderer/assets/fluent-BSSEgVQa-BCOQigl1.js 3.81 kB
out/renderer/assets/splunk-BdqSfgpd-BtOEh0Mo.js 3.81 kB
out/renderer/assets/jsonnet-Bn71vRY8-QjPNMWdY.js 3.82 kB
out/renderer/assets/ssh-config-BO51LXox-DkFt_ueS.js 3.82 kB
out/renderer/assets/bicep-DujF3y-4-DHww3ZLF.js 3.87 kB
out/renderer/assets/narrat-DdgkgBr0-CSyxDqta.js 3.87 kB
out/renderer/assets/redis-Bo427DT4-DBDF4ZWx.js 3.88 kB
out/renderer/assets/turtle-DAmmiOda-C48PN72o.js 3.92 kB
out/renderer/assets/dist-CE9GMTNb.js 3.97 kB
out/renderer/assets/prism-jsx-BO0yI1A3.js 3.97 kB
out/renderer/assets/xml-BBFzlEmT-CqLnJtYa.js 3.99 kB
out/renderer/assets/java-Z7anYNQ6-DdC7WVZS.js 4.01 kB
out/renderer/assets/r-Xh-gXEK4-DKEPC8dA.js 4.02 kB
out/renderer/assets/ron-CdysqNkW-BG7UwPdX.js 4.11 kB
out/renderer/assets/zenscript-XbBI4c9W-C-aTQo6e.js 4.12 kB
out/renderer/assets/glsl-CZF-bvQV-UaBdSZy0.js 4.14 kB
out/renderer/assets/shell-DGp7WuK3-X00pamiI.js 4.15 kB
out/renderer/assets/gn-DJxfXStl-BD_k0CWf.js 4.20 kB
out/renderer/assets/kotlin-C61BvWgT-B7MkJpdU.js 4.20 kB
out/renderer/assets/typespec-B704GmX3-f1l-QmOw.js 4.26 kB
out/renderer/assets/kdl-YTd72GVl-DLkP_pAB.js 4.27 kB
out/renderer/assets/AppearanceSettingsPanel-B_352Jrg.js 4.28 kB
out/renderer/assets/hurl-CDXCvJNd-Xd5k76nE.js 4.28 kB
out/renderer/assets/cypher-CjfQI0Y9-9gjOyi6P.js 4.33 kB
out/renderer/assets/pascal-CLPA94yO-C11lM2uy.js 4.35 kB
out/renderer/assets/powershell-CaPzBwIT-C9KgMPOP.js 4.50 kB
out/renderer/assets/tcl-D-NiFh9X-CYwv4uzi.js 4.63 kB
out/renderer/assets/apex-BE-040ts-wdfiR7V6.js 4.65 kB
out/renderer/assets/tcl-DowxIvU4-Bbhzqrsw.js 4.65 kB
out/renderer/assets/rosmsg-DDyuMVTo-DSHWRdSZ.js 4.72 kB
out/renderer/assets/nextflow-DVTlkzu9-Cis-JUmb.js 4.75 kB
out/renderer/assets/http-DhxVjYFh-CjwVOaui.js 4.76 kB
out/renderer/assets/hcl-CbjaVS9i-DCS43mBd.js 4.79 kB
out/renderer/assets/rust-Ij2gfGoT-DLzaBWYs.js 4.83 kB
out/renderer/assets/polar-CwTxzzWE-DygHL4ZA.js 4.87 kB
out/renderer/assets/prism-ruby-PgHh3fQm.js 4.91 kB
out/renderer/assets/fennel-COJTUo2O-DYh8-dep.js 4.97 kB
out/renderer/assets/bibtex-yEKRWsaj-xHthw1sC.js 5.00 kB
out/renderer/assets/coffee-CcgZJF1B-DkN4xoBX.js 5.04 kB
out/renderer/assets/llvm-DiFwU398-BQjCVu39.js 5.25 kB
out/renderer/assets/less-CXux59mP-BM7SkPLH.js 5.27 kB
out/renderer/assets/msdax-DEyWhkWP-CwdIr_-P.js 5.29 kB
out/renderer/assets/prism-javascript-B6zosBCV.js 5.31 kB
out/renderer/assets/wgsl-Ds7VVNHP-yP3bMkfO.js 5.34 kB
out/renderer/assets/markdown-CBag5COD-B_1rbk64.js 5.36 kB
out/renderer/assets/dart-DK8_VUW5-Bnb_Tn57.js 5.39 kB
out/renderer/assets/zig-BBWfbOQ5-B8x_JL1P.js 5.54 kB
out/renderer/assets/restructuredtext-D2p7PcFG-DDHAm_JI.js 5.55 kB
out/renderer/assets/dax-CmrIxjmL-CDTyHmZ_.js 5.56 kB
out/renderer/assets/gdresource-4lq4eh4q-CjhvlVte.js 5.56 kB
out/renderer/assets/qml-D6gd64uC-_ykXVPoZ.js 5.57 kB
out/renderer/assets/bicep-wTwvD1CI-C568hcwN.js 5.58 kB
out/renderer/assets/cssMode-Z-o80aSY-Co8Z3bSk.js 5.59 kB
out/renderer/assets/awk-DTjcVAOD-BmfaVU4m.js 5.66 kB
out/renderer/assets/liquid-Dv-zz5BA-D9ukCDuL.js 5.71 kB
out/renderer/assets/csharp-DpS7Vfy9-CbQzv1ql.js 5.76 kB
out/renderer/assets/coq-BFytDJOI-C5vNmx0q.js 5.81 kB
out/renderer/assets/swift-C3A42nmX-BBVToPkN.js 5.83 kB
out/renderer/assets/xml-bIkPj5aH-Bx1v5u6-.js 5.89 kB
out/renderer/assets/ecl-CYzojQ6a-C8m0_osY.js 5.91 kB
out/renderer/assets/jinja-Dl-Ji_JA-BBL5sTd0.js 5.92 kB
out/renderer/assets/lean-Cu10prRO-BUTVAAdc.js 6.03 kB
out/renderer/assets/yaml-GEMDST6R-D-0AGe4F.js 6.09 kB
out/renderer/assets/moonbit-B8-g2u5v-CGBFUznC.js 6.10 kB
out/renderer/assets/powerquery-tKWDTKOo-CejxekA_.js 6.11 kB
out/renderer/assets/SourceCodePreview-DiJZfFca.js 6.11 kB
out/renderer/assets/python-CHafhQyI-DmJIfgbV.js 6.14 kB
out/renderer/assets/shaderlab-Df7nOKvI-0G488FSx.js 6.16 kB
out/renderer/assets/css-sG8ozMHf-pZGexMoj.js 6.17 kB
out/renderer/assets/cpp-CipCPBaT-7uQRIwsC.js 6.17 kB
out/renderer/assets/vb-BKV3Sgm5-D5ytx6Ln.js 6.29 kB
out/renderer/assets/htmlMode-BDZbYlMj-Dv5sUJ1A.js 6.40 kB
out/renderer/assets/red-CYaKK_PD-iiAMl8iL.js 6.45 kB
out/renderer/assets/min-dark-DGPfDRqJ-gZu6HtcU.js 6.48 kB
out/renderer/assets/pug-EKWpNZSi-oQ708bsr.js 6.51 kB
out/renderer/assets/prisma-CdZyz3OC-ChFCtYaa.js 6.53 kB
out/renderer/assets/gdshader-ryZhEIxg-DpcQqwXn.js 6.55 kB
out/renderer/assets/ara-_lrJyEFe-qigo-wGx.js 6.56 kB
out/renderer/assets/clojure-WSq30mUj-Bswhoa1y.js 6.61 kB
out/renderer/assets/toml-DPP887_3-aOuHoLTy.js 6.62 kB
out/renderer/assets/postcss-CcIp2ENG-DpmxBCXW.js 6.64 kB
out/renderer/assets/verilog-bragEGMk-CemzLugw.js 6.64 kB
out/renderer/assets/solarized-light-BIMszn7B-vPMkTTwP.js 6.68 kB
out/renderer/assets/cypher-COYrq2Yy-BtVrfsLp.js 6.75 kB
out/renderer/assets/arc-LpCwTDer.js 6.75 kB
out/renderer/assets/proto-CQIfhs_g-Deqofbl3.js 6.77 kB
out/renderer/assets/smalltalk-BLGdLDJX-BKGgemER.js 6.79 kB
out/renderer/assets/vb-D1Cw85Ss-BSz-V9M4.js 6.86 kB
out/renderer/assets/talonscript-DA9pg7Tj-CPXKQ95R.js 6.96 kB
out/renderer/assets/r-Bb2Mu7Fo-Dq0URONw.js 7.00 kB
out/renderer/assets/solarized-dark-D_I-4EGa-BZbeAUhW.js 7.04 kB
out/renderer/assets/diagram-Z3DM3KII-BZGyOvLJ.js 7.08 kB
out/renderer/assets/riscv-CQHqXr1Z-BFlZFId-.js 7.11 kB
out/renderer/assets/soy-DybHqX1A-DOhErZPj.js 7.15 kB
out/renderer/assets/min-light-BF0EjVgr-DvViuJW_.js 7.16 kB
out/renderer/assets/scheme-Dn0tgEWN-BK64z0tZ.js 7.37 kB
out/renderer/assets/prism-bash-B2ETaHUm.js 7.43 kB
out/renderer/assets/typescript-sfPIqb8J-DtIl1kXb.js 7.44 kB
out/renderer/assets/hlsl-CAmjcFpk-B3FZWMVz.js 7.48 kB
out/renderer/assets/mdx-Bdu4uO-C-BrzgNjCw.js 7.58 kB
out/renderer/assets/qss-DkzwWM0J-04JPp7d-.js 7.67 kB
out/renderer/assets/html-DKbmsqz6-Cnkf6ew3.js 7.69 kB
out/renderer/assets/systemd-CS6mVasZ-HbzlQlDs.js 8.07 kB
out/renderer/assets/monokai-CYqILLdj-CEXuJ8HO.js 8.08 kB
out/renderer/assets/twig-r8vgPZrm-D2l24YwI.js 8.18 kB
out/renderer/assets/updates-ui-BoiWSsup.js 8.22 kB
out/renderer/assets/wgsl-D_5Qxf6T-D508aVGZ.js 8.27 kB
out/renderer/assets/sdbl-BXfz6d3_-C4Qk7OPN.js 8.42 kB
out/renderer/assets/regexp-Dv0OUts_-BqK6b4KR.js 8.46 kB
out/renderer/assets/prism-php-dzcOOH50.js 8.49 kB
out/renderer/assets/systemverilog-BreNGkRs-RIXr4hNf.js 8.65 kB
out/renderer/assets/plsql-C-xpsZfV-frBdohcC.js 8.71 kB
out/renderer/assets/vue-html-DvuHo2mm-b7I-opwf.js 8.71 kB
out/renderer/assets/haml-CIYwkycC-3fSMp7m2.js 8.81 kB
out/renderer/assets/scss-CLoW-2dr-BBC_GO_6.js 8.86 kB
out/renderer/assets/dart-CBkkDIWs-ezKLFP5s.js 8.94 kB
out/renderer/assets/horizon-CELVL8Ba-x0NmpRb6.js 8.97 kB
out/renderer/assets/horizon-bright-DBDyMeUQ-Bhh-QDk3.js 8.98 kB
out/renderer/assets/julia-DvNkK6LK-Bi3Rlfah.js 9.04 kB
out/renderer/assets/clojure-886L7m2N-BhGJsUM7.js 9.14 kB
out/renderer/assets/make-CsAfL-jc-DaQVAww0.js 9.18 kB
out/renderer/assets/andromeeda--j5Bq-48-DxyWS_fJ.js 9.21 kB
out/renderer/assets/dark-plus-FAPM6M6c-DKexDF--.js 9.29 kB
out/renderer/assets/sas-BQIEUTPQ-Bwx-ZPYU.js 9.31 kB
out/renderer/assets/slack-dark-nDxLkSCC-C5pzIEPN.js 9.31 kB
out/renderer/assets/perl-Bec3eWyr-CDmSu3_s.js 9.32 kB
out/renderer/assets/plastic-DY_h9Vzh-CZzPFkTC.js 9.49 kB
out/renderer/assets/sass-Ysv8HTNa-CHNQIGaT.js 9.49 kB
out/renderer/assets/st-BrgXZ-Ag-BUs-RRgp.js 9.58 kB
out/renderer/assets/typst-Co5rZla4-COemceoz.js 9.61 kB
out/renderer/assets/slack-ochin-7zJWY-K--C7KFpXik.js 9.63 kB
out/renderer/assets/defaultLocale-QNqK0iCN.js 9.84 kB
out/renderer/assets/handlebars-CIJAyfa9-6toBlNYk.js 9.94 kB
out/renderer/assets/jison-Cbw0l5It-BNek_9Kq.js 9.95 kB
out/renderer/assets/sql-DviNlDJO-CwV6bDIP.js 9.97 kB
out/renderer/assets/kotlin-DIw6ua6F-CdVnL0aF.js 10.01 kB
out/renderer/assets/cmake-CyNDuJo8-2Hk4zQCd.js 10.07 kB
out/renderer/assets/light-plus-DkScKIB5-e8Q5AKjf.js 10.14 kB
out/renderer/assets/hcl-DoJdlYjN-DdpM5wFm.js 10.25 kB
out/renderer/assets/scala-Dj45wWzI-CAMCqIXS.js 10.40 kB
out/renderer/assets/postiats-SaHD9Qcv-FPvOr1pn.js 10.45 kB
out/renderer/assets/beancount-CyZf3Huc-C4n-y8pc.js 10.58 kB
out/renderer/assets/tex-gcnXexI3-BUpeblVA.js 10.60 kB
out/renderer/assets/php-Bn8AF0uj-CBbpr2vs.js 10.62 kB
out/renderer/assets/nextflow-groovy-D4ZyOBoZ-C7jziUwg.js 10.63 kB
out/renderer/assets/dream-maker-5oXa1Z51-CLRrQkBL.js 10.67 kB
out/renderer/assets/ts-tags-xeTAUNHG-CG_gr3En.js 10.70 kB
out/renderer/assets/raku-Bfr41qeN-C7t9XlCj.js 10.72 kB
out/renderer/assets/mysql-CZJtil0v-CP4gK9vT.js 10.73 kB
out/renderer/assets/task-menu-icons-BRdNqJF0.js 10.78 kB
out/renderer/assets/prism-csharp-D9xOwbIN.js 10.91 kB
out/renderer/assets/yaml-CsitfczK-Cu7vbJZs.js 10.97 kB
out/renderer/assets/diagram-UQ7AKVKN-CjyZsemm.js 11.05 kB
out/renderer/assets/elm-Dl1XrIiD-CwXBAFKd.js 11.18 kB
out/renderer/assets/just-He7qscmV-Bkq-0zku.js 11.19 kB
out/renderer/assets/redshift-Djb4PK3z-9Ar4PFWD.js 11.35 kB
out/renderer/assets/github-light-B_J7N1HZ-DWSXFnsf.js 11.38 kB
out/renderer/assets/ruby-CxOCB7_P-BzsjPJ6Z.js 11.48 kB
out/renderer/assets/prolog-DAqMMM08-BFKdnH0S.js 11.56 kB
out/renderer/assets/terraform-BW8B2WXV-zeRjs0zr.js 11.59 kB
out/renderer/assets/github-dark-BgqEY2WG-C9QbkZU3.js 11.60 kB
out/renderer/assets/puppet-CaR8DEdW-Biai9WKX.js 11.65 kB
out/renderer/assets/pkl-DrXR3Dxy-Bno7kqPT.js 11.67 kB
out/renderer/assets/laserwave-Clkc4Pj8-DOjuqF9n.js 11.69 kB
out/renderer/assets/pieDiagram-E7YTZNPT-CDo9kO0D.js 11.95 kB
out/renderer/assets/rst-BJFdabDk-Cv-fSo2B.js 12.04 kB
out/renderer/assets/linear-WS155L0r.js 12.11 kB
out/renderer/assets/wasm-DYwNZ-r4-BrA6oOvM.js 12.21 kB
out/renderer/assets/hjson-CmvCiVhY-BdH9CbZ2.js 12.25 kB
out/renderer/assets/razor-D5kquflS-CWY5AfCS.js 12.39 kB
out/renderer/assets/abap-BJyKdrbp-hWIyERPx.js 12.52 kB
out/renderer/assets/handlebars-B1z64YSt-MC-VEvxc.js 12.52 kB
out/renderer/assets/apache-BUbWdjM2-2Zu7IlVl.js 12.66 kB
out/renderer/assets/vesper-B5lCMuIY-CXGQHRuW.js 12.88 kB
out/renderer/assets/pgsql-BYm17UA1-Cvj1smQI.js 12.93 kB
out/renderer/assets/protobuf-BOGxqb2m-yTWn-oM_.js 12.98 kB
out/renderer/assets/bat-D2y8Uewi-CEJzP2ue.js 13.09 kB
out/renderer/assets/fish-CaZR_ofm-BcO_q5kQ.js 13.24 kB
out/renderer/assets/elixir-Lipcswxh-DnZCznfr.js 13.27 kB
out/renderer/assets/v-wnWoBHkK-CzCOTyIp.js 13.41 kB
out/renderer/assets/AboutHelpSettingsPanel-Ui_VOvh7.js 13.48 kB
out/renderer/assets/vitesse-light-DQXFiRFx-Ct7fN8pJ.js 13.81 kB
out/renderer/assets/aurora-x-9vUYYjHV-CImifmUW.js 13.85 kB
out/renderer/assets/vitesse-black-cwK5rWgD-BGrq81WC.js 13.87 kB
out/renderer/assets/vitesse-dark-CsfgW0oH-Dx8cqxrm.js 13.96 kB
out/renderer/assets/ShortcutsSettingsPanel-KgJeI7QZ.js 14.15 kB
out/renderer/assets/pug-D0UckVoV-BTWU19Nk.js 14.16 kB
out/renderer/assets/synthwave-84-LX1B8mRG-yuUErnSx.js 14.23 kB
out/renderer/assets/github-light-default-BRmIzqWc-B3gMi7zW.js 14.36 kB
out/renderer/assets/clarity-AxkJPY5c-DfVHSVIk.js 14.48 kB
out/renderer/assets/github-light-high-contrast-BUKIZOxn-DL0r2b0z.js 14.49 kB
out/renderer/assets/github-dark-dimmed-DoIdqTey-CDc6YqEM.js 14.64 kB
out/renderer/assets/github-dark-default-CwWjzI40-_0bgyJYv.js 14.64 kB
out/renderer/assets/chunk-PWAF6VOD-BIFvN59P.js 14.76 kB
out/renderer/assets/github-dark-high-contrast-bFLNMLvK-BUp3HmXY.js 14.80 kB
out/renderer/assets/diagram-S7CK7UJ4-DONAXBsJ.js 14.98 kB
out/renderer/assets/gnuplot-Dw3FRha5-D6o75ylb.js 14.98 kB
out/renderer/assets/rust-C0Ih6nmc-Bm01RMLz.js 15.27 kB
out/renderer/assets/actionscript-3-O8jnLcvn-C7OtofMN.js 15.41 kB
out/renderer/assets/luau-BzxGbjcn-aQpsBeQB.js 15.64 kB
out/renderer/assets/nix-zl191KBb-CxSq6jsB.js 15.85 kB
out/renderer/assets/lua-BwTLfNCK-IuSxl8fO.js 16.04 kB
out/renderer/assets/abap-FvPUHv8B-BVQp86jh.js 16.05 kB
out/renderer/assets/solidity-96fhzG-Q-CZEni-ZB.js 16.28 kB
out/renderer/assets/matlab-8ZQqHKQX-g_ODc8QU.js 16.29 kB
out/renderer/assets/cue-eHSfcyUV-BO0bCEDm.js 16.40 kB
out/renderer/assets/kusto-D8vBBISG-C0y2Wtyy.js 16.45 kB
out/renderer/assets/powerquery-B7BjLMcF-BkVSWPtX.js 16.49 kB
out/renderer/assets/elixir-B1NaQxrO-Ba6X-FuW.js 16.50 kB
out/renderer/assets/react-DrereneL.js 16.50 kB
out/renderer/assets/odin-B-YqhW9I-B-ZI05Ll.js 16.71 kB
out/renderer/assets/solidity-Dpt2BLAA-BD_YSA0r.js 16.98 kB
out/renderer/assets/bird2-BMkLvc4r-CyoW3El7.js 17.17 kB
out/renderer/assets/kanagawa-wave-CM_o6oKV-VzWuxPSA.js 17.32 kB
out/renderer/assets/kanagawa-lotus-Cj3XDpoG-cmeMwVaD.js 17.32 kB
out/renderer/assets/kanagawa-dragon-D_NPnIy_-Cyd8MANv.js 17.33 kB
out/renderer/assets/cynefinDiagram-5FMLGOSQ-BK5-wphO.js 17.61 kB
out/renderer/assets/stateDiagram-D77RDMKH-hT0_t6tj.js 18.11 kB
out/renderer/assets/chunk-L3NEJ4N5-DDp_gyKk.js 18.16 kB
out/renderer/assets/liquid-D_7zu7XR-BZ3z6-Mj.js 18.46 kB
out/renderer/assets/svelte-DUGqPubT-CAfIEh4G.js 18.60 kB
out/renderer/assets/graphql-ObxcfEHH-9pUo2yjR.js 18.65 kB
out/renderer/assets/jsonMode-DdQpkp6D-BpRyp_WL.js 18.79 kB
out/renderer/assets/material-theme-q28j4V_0-s4HtqlFv.js 18.81 kB
out/renderer/assets/material-theme-ocean-DAvlEnSm-Cyw7qD-l.js 18.83 kB
out/renderer/assets/material-theme-darker-CHEuMVX9-D-hz3EEt.js 18.83 kB
out/renderer/assets/material-theme-lighter-DY4T1_JG-C0HwKluR.js 18.84 kB
out/renderer/assets/material-theme-palenight-CqDFvQ-v-RoTowTME.js 18.84 kB
out/renderer/assets/gherkin-BcjDDslM-BdnbjalD.js 19.20 kB
out/renderer/assets/gdscript-CekKc1U_-DVmAmHvE.js 19.21 kB
out/renderer/assets/groovy-DH3arekX-StnUgJL0.js 19.38 kB
out/renderer/assets/mdc-D-U85KZE-DPbAVRTg.js 19.85 kB
out/renderer/assets/diagram-VSXAHHWV-DSqzbMQw.js 20.01 kB
out/renderer/assets/move-CmExnPjU-DPj_eIaE.js 20.22 kB
out/renderer/assets/ayu-dark-BeByMiYw-CS3MEELg.js 20.27 kB
out/renderer/assets/ayu-mirage-C1jJ6Jfs-CnA8kJ7r.js 20.28 kB
out/renderer/assets/ayu-light-DmTZeN54-CDULCKqM.js 20.35 kB
out/renderer/assets/glimmer-js-D9ZnrcNN-BS431Ogg.js 20.44 kB
out/renderer/assets/glimmer-ts-DuhFj6qR-CsFesiaT.js 20.44 kB
out/renderer/assets/viml-DPVJ_KYe-De3CdqgJ.js 20.56 kB
out/renderer/assets/nushell-Cd8Dwa1M-Dhf9XkYz.js 20.62 kB
out/renderer/assets/snazzy-light-B8znOqT6-B1FX3-IF.js 20.97 kB
out/renderer/assets/dagre-GXQ25YYZ-DDVr57nj.js 21.01 kB
out/renderer/assets/dracula-DeMffiYO-Bl4juROY.js 21.26 kB
out/renderer/assets/dracula-soft-BnfvpcDv-CYsUeSum.js 21.27 kB
out/renderer/assets/twig-7zjsCqYg-CMujKsZl.js 21.44 kB
out/renderer/assets/freemarker2-enkimFXA-0bWMkoTL.js 21.73 kB
out/renderer/assets/PersonalizationSettingsPanel-B06BA6F_.js 21.87 kB
out/renderer/assets/rose-pine-CEVQiaW0-DaA_4NNK.js 21.94 kB
out/renderer/assets/rose-pine-moon-B9bum7Ik-B6_AhIsD.js 21.96 kB
out/renderer/assets/rose-pine-dawn-2Q5fMoJp-DxMkAwKM.js 21.96 kB
out/renderer/assets/powershell-ycAdP1r9-B7r4Hnhz.js 22.11 kB
out/renderer/assets/common-lisp-DcFHcTKh-CWH5diwh.js 22.81 kB
out/renderer/assets/gruvbox-dark-hard-gOzMLqif-DDlcfu4q.js 22.83 kB
out/renderer/assets/gruvbox-dark-soft-CKvURktN-C6MJezBg.js 22.83 kB
out/renderer/assets/gruvbox-light-hard-CMa_c48J-BUQ67Msp.js 22.84 kB
out/renderer/assets/gruvbox-light-soft-yfAGJYsX-DNM2qqWB.js 22.84 kB
out/renderer/assets/gruvbox-dark-medium-BQSVGwWb-qh8C4DPZ.js 22.84 kB
out/renderer/assets/gruvbox-light-medium-B9S5UNr1-DZxV_o-P.js 22.84 kB
out/renderer/assets/nim-CD961Jl3-CuyTrDpQ.js 22.91 kB
out/renderer/assets/cadence-C2JmJjDr-B-b63Epg.js 23.87 kB
out/renderer/assets/sql-C_oMiPb0-CRnSOxMo.js 23.87 kB
out/renderer/assets/wit-CXpQol8Q-D2NEDOhy.js 24.11 kB
out/renderer/assets/templ-gFcHJbF7-BqIwRUQe.js 24.38 kB
out/renderer/assets/astro-kV3HjkbP-CH6o6jKA.js 24.46 kB
out/renderer/assets/vhdl-Ci4REirV-D-qSzcJD.js 24.46 kB
out/renderer/assets/purescript-DCsDAdnX-DsynrkKe.js 24.97 kB
out/renderer/assets/vue-Cuk7Vimg-CFbFXIr8.js 25.25 kB
out/renderer/assets/surrealql-GFjNBdcm-Vm68TOTE.js 25.34 kB
out/renderer/assets/one-light-CMfGrl_P-B-1jUQM9.js 25.49 kB
out/renderer/assets/night-owl-light-CAEa42tO-TPCLv7z5.js 26.10 kB
out/renderer/assets/system-verilog-D_bVVpLE-C_dvOlr3.js 26.41 kB
out/renderer/assets/angular-html-BrLPO2Fv-DJgz5E5d.js 26.48 kB
out/renderer/assets/typespec-D5WYs8C4-AaOHagqW.js 26.72 kB
out/renderer/assets/nord-DlCAGdjr-Div2jUYm.js 26.91 kB
out/renderer/assets/codeql-DidIlXer-D6RBJOzg.js 27.08 kB
out/renderer/assets/scss-BhK8Ovpn-DfDLQi2C.js 27.52 kB
out/renderer/assets/coffee-DrMWXxy6-BoavQsuh.js 27.68 kB
out/renderer/assets/java-DaupjRFz-zQd9RZAc.js 27.69 kB
out/renderer/assets/razor-B2hRAVmz-Dj7TOgY5.js 27.72 kB
out/renderer/assets/apl-C42PBett-BNW4FTmO.js 27.87 kB
out/renderer/assets/chunk-SVP7TREG-CPHw5aFk.js 28.38 kB
out/renderer/assets/fsharp-BHFgIxsY-CvR6tsY8.js 28.48 kB
out/renderer/assets/marko-DXKHPFnH-C0z2-ucz.js 28.74 kB
out/renderer/assets/GeneralSettingsPanel-CA6yOnsk.js 29.10 kB
out/renderer/assets/night-owl-DegwdXaM-6ZGfBB7K.js 29.11 kB
out/renderer/assets/c3-BOs4FlGA-BuhFXrRY.js 29.17 kB
out/renderer/assets/MemorySettingsPanel-cqwWfj-O.js 29.75 kB
out/renderer/assets/crystal-DlzoxO28-BWa_t1Io.js 29.84 kB
out/renderer/assets/applescript-ij24h7OO-_xHQcvud.js 29.87 kB
out/renderer/assets/tsMode-SiG-Sp2b-D8plNSSs.js 30.55 kB
out/renderer/assets/pierre-dark-Daa2n9wr-D7rla9B_.js 30.74 kB
out/renderer/assets/pierre-light-D_hZXvUj-DJnIOKLO.js 30.75 kB
out/renderer/assets/pierre-dark-soft-BhNM3pgh-Dp_VeHWv.js 30.76 kB
out/renderer/assets/pierre-light-soft-BVrSv6ZG-C6Na39F-.js 30.76 kB
out/renderer/assets/ishikawaDiagram-5VMMS53U-DDYICLe4.js 30.78 kB
out/renderer/assets/pierre-dark-tritanopia-CGKuoAZi-C0HpbU3l.js 30.78 kB
out/renderer/assets/pierre-light-tritanopia-BiDEaWaH-wWduIsi3.js 30.78 kB
out/renderer/assets/pierre-dark-protanopia-deuteranopia-Cs1lz9lE-enlgPsHw.js 30.82 kB
out/renderer/assets/pierre-light-protanopia-deuteranopia-BM0RLBB_-Dz5iBHkO.js 30.82 kB
out/renderer/assets/stylus-ZCryC73G-urFW3_yk.js 31.29 kB
out/renderer/assets/diagram-VX7I27RA-C2Mi8cp0.js 31.44 kB
out/renderer/assets/scala-BBsC3Oz3-VCjyobQG.js 31.48 kB
out/renderer/assets/mermaid-D6CQfUGU-C6DHNxVz.js 33.37 kB
out/renderer/assets/poimandres-EIt_jotH-DHKFQj5Q.js 33.69 kB
out/renderer/assets/kanban-definition-UXKFOSKX-BeSTkz7K.js 33.91 kB
out/renderer/assets/one-dark-pro-DR9QpZM3-BA4d4lw2.js 33.98 kB
out/renderer/assets/mermaid-parser.core-CstzWfPU.js 34.66 kB
out/renderer/assets/haxe-BWT5wSyZ-BuUsQb-h.js 35.38 kB
out/renderer/assets/nginx-DhtViCEk-C18zABFg.js 35.58 kB
out/renderer/assets/houston-BdS5A_yD-NUige_z1.js 35.61 kB
out/renderer/assets/tokyo-night-BS1_DFu7-CYsPn2J-.js 35.86 kB
out/renderer/assets/erlang-Dd62d0xZ-DHVWwcKa.js 37.71 kB
out/renderer/assets/rough.esm-BX5QqLti.js 38.33 kB
out/renderer/assets/mindmap-definition-YA3MSWOX-CefIRU5Q.js 38.59 kB
out/renderer/assets/cobol-D7RZfOK--CEk2iYO9.js 39.37 kB
out/renderer/assets/journeyDiagram-3NMN7TZE-BrEjlWwa.js 40.13 kB
out/renderer/assets/julia-ZzkUXm0W-BIm_zTAN.js 40.32 kB
out/renderer/assets/lspLanguageFeatures-DK9zifhE-DeEqLmGO.js 40.76 kB
out/renderer/assets/asm-DYVIzeEk-Byg5xzam.js 40.91 kB
out/renderer/assets/haskell-Ba6HbLj8-D0OYaIy8.js 41.78 kB
out/renderer/assets/sankeyDiagram-P5KCCOFB-DQyGY2bs.js 41.83 kB
out/renderer/assets/shellscript-B69gKcss-49Zm6IyC.js 41.97 kB
out/renderer/assets/wardleyDiagram-VM6X3IG4-DlxcR-iD.js 42.40 kB
out/renderer/assets/perl-Dv6Cq_FS-DIORmO5G.js 43.55 kB
out/renderer/assets/pierre-dark-vibrant-BMsyYliQ-84Eeh-Uj.js 44.96 kB
out/renderer/assets/pierre-light-vibrant-CWzM4Pa_-QZvTkTJe.js 44.97 kB
out/renderer/assets/ruby-DWcdJvcx-q0K84ieK.js 46.50 kB
out/renderer/assets/go-BOpYl7fu-BiT4MB-v.js 47.02 kB
out/renderer/assets/apex-B48ZHHzN-BBt8sSNQ.js 47.18 kB
out/renderer/assets/catppuccin-mocha-cPsH7Lup-SVLZehhk.js 47.46 kB
out/renderer/assets/catppuccin-latte-DcEecI7n-jo2cPJyK.js 47.46 kB
out/renderer/assets/catppuccin-frappe-BdOW2tdI-BI0Hc9cS.js 47.46 kB
out/renderer/assets/catppuccin-macchiato-Bvz_yAZY-DWewRa4S.js 47.47 kB
out/renderer/assets/ada-BT0j8ine-CLTLBE8n.js 48.28 kB
out/renderer/assets/d-B1HbH29p-Bi6t8Ck6.js 49.10 kB
out/renderer/assets/css-NFwnoVns-BvwuZkcY.js 49.49 kB
out/renderer/assets/imba-C-oGt11l-CqKI0OVw.js 50.13 kB
out/renderer/assets/requirementDiagram-BXWQKSXE-02T1DPau.js 51.39 kB
out/renderer/assets/erDiagram-RLTQ6QDP-CJPuRub_.js 52.41 kB
out/renderer/assets/browserify-C9uP_nIr.js 52.80 kB
out/renderer/assets/gitGraphDiagram-WWUBYQGX-DzZwQ1ZK.js 53.82 kB
out/renderer/assets/everforest-dark-gCM8XhEI-DzRrg06U.js 53.94 kB
out/renderer/assets/everforest-light-DhK35DkL-BEDtvHw1.js 53.95 kB
out/renderer/assets/timeline-definition-24CTP7MA-CkkqSZjt.js 54.31 kB
out/renderer/assets/wikitext-CQNrXTmv-DJ18wIlO.js 56.09 kB
out/renderer/assets/stata-BUONSdsT-BPnapjPC.js 57.23 kB
out/renderer/assets/quadrantDiagram-AXDQQJYC-Bzh51MK6.js 58.21 kB
out/renderer/assets/html-Dq1ixqYb-okJOhOmu.js 58.25 kB
out/renderer/assets/chunk-OSK3NFVY-uIpNfy4k.js 58.56 kB
out/renderer/assets/ocaml-CUdGm1iq-BKX30YEX.js 62.65 kB
out/renderer/assets/model-settings-source-JYisGYmM.js 63.03 kB
out/renderer/assets/ballerina-CpYcPBJI-D9ac3462.js 64.89 kB
out/renderer/assets/markdown-BSrOIEaF-BFwOzGIM.js 65.52 kB
out/renderer/assets/chunk-IMKFNOWR-K_k56tb2.js 67.22 kB
out/renderer/assets/mojo-BNaitZ-7-E_psDM2x.js 70.00 kB
out/renderer/assets/python-Cld0Iwtn-tcCJ5L_g.js 70.17 kB
out/renderer/assets/blockDiagram-I7D4REHJ-B2ciwNEw.js 71.01 kB
out/renderer/assets/bsl-CtP8370o-Pi14XlIU.js 71.07 kB
out/renderer/assets/c-B4augMcT-B5ncIjy5.js 72.57 kB
out/renderer/assets/chunk-75Z2AOVW-JUQFBHAM.js 72.67 kB
out/renderer/assets/latex-g2Pus_l2-CP0G7LTN.js 72.85 kB
out/renderer/assets/vyper-C1nscAY5-BTAKd5p2.js 74.85 kB
out/renderer/assets/ModelSettingsPanel-Bq69xf7M.js 76.64 kB
out/renderer/assets/xychartDiagram-S5SC5T6Z-CRxhfnTo.js 76.79 kB
out/renderer/assets/chunk-GMAD6QVW-Bh7dgfzS.js 77.76 kB
out/renderer/assets/hack-B1ag3l4X-CEYIfPfg.js 80.58 kB
out/renderer/assets/src-DsgKm1PY.js 83.16 kB
out/renderer/assets/chunk-TICWLB2K-T0W1tKxl.js 83.88 kB
out/renderer/assets/fortran-free-form-CsgtTAg3-Dm0PhuY8.js 89.20 kB
out/renderer/assets/vennDiagram-4TSXK5OY-_1_lRuy9.js 89.26 kB
out/renderer/assets/csharp-YOPVljXo-CBjcozlW.js 89.91 kB
out/renderer/assets/racket--xYIV9-n-NDM2V4Sc.js 92.62 kB
out/renderer/assets/swift-CgzYrGBX-CaMD6i-j.js 94.14 kB
out/renderer/assets/less-BGhX8xko-CbSvNyvq.js 99.00 kB
out/renderer/assets/chunk-SHT3W25Y-Bhx-xs-0.js 104.10 kB
out/renderer/assets/objective-c-CmcWiAft-DY5tZuMk.js 105.62 kB
out/renderer/assets/blade-Bq8WPf0E-BehdttJf.js 105.98 kB
out/renderer/assets/c4Diagram-7LVT6UL2-COxjNYvg.js 107.96 kB
out/renderer/assets/php-X15vsN4N-ChBJUzAp.js 111.49 kB
out/renderer/assets/dagre-CzI-C3sx.js 122.98 kB
out/renderer/assets/ganttDiagram-EL5Y4UJY-BF255DSu.js 123.77 kB
out/renderer/assets/graphlib-CoAzpIqe.js 127.44 kB
out/renderer/assets/asciidoc-DJWalVNM-Daa-Gl9r.js 146.30 kB
out/renderer/assets/mdx-C_Ato9sK-CDV72_N0.js 146.49 kB
out/renderer/assets/editor.main-POO0Vbhx-joAkg4Ov.js 161.32 kB
out/renderer/assets/cose-bilkent-JH36ORCC-CA60tZpq.js 165.63 kB
out/renderer/assets/objective-cpp-BggTCHV8-BRaaCyEF.js 172.18 kB
out/renderer/assets/javascript-AfZCJ9Uc-C_GZREFb.js 175.31 kB
out/renderer/assets/tsx-BOlKGefW-D7XVyutE.js 176.00 kB
out/renderer/assets/jsx-CPd9p36x-D5Ck2u9I.js 178.26 kB
out/renderer/assets/sequenceDiagram-WJ2MYXX4-B9hxKtQH.js 190.05 kB
out/renderer/assets/typescript-4sRsPriL-Ce01imBq.js 191.16 kB
out/renderer/assets/mermaid.core-CYzT-hJp.js 191.57 kB
out/renderer/assets/angular-ts-YduEkmVa-936ueej5.js 193.82 kB
out/renderer/assets/vue-vine-DXhYlaTf-C8MW7tnI.js 201.27 kB
out/renderer/assets/SourceSelect-Dd7kI5iL.js 203.20 kB
out/renderer/assets/chunk-4HAMMTFA-Bx-ZDNkL.js 210.32 kB
out/renderer/assets/swimlanes-42K2YHIH-CgEXyowS.js 265.51 kB
out/renderer/assets/wolfram-BVoTES0L-W3A5YqXk.js 267.14 kB
out/renderer/assets/chunk-DU6HZSFF-D1SCGf9S.js 271.07 kB
out/renderer/assets/architectureDiagram-5GKGNRK7-BmVKhcu0.js 318.23 kB
out/renderer/assets/katex-Y9ra-ykP.js 497.35 kB
out/renderer/assets/texmath-Bkeg3ZLn.js 594.25 kB
out/renderer/assets/wasm-CVjZL0jK-DcJkdGs4.js 622.62 kB
out/renderer/assets/cpp-9jHBA231-DB3feGjZ.js 626.73 kB
out/renderer/assets/app-4914IQSi.js 675.57 kB
out/renderer/assets/emacs-lisp-DjtOxg4j-CzQ0CKOn.js 780.06 kB
out/renderer/assets/cytoscape.esm-bVGYt-iW.js 869.69 kB
out/renderer/assets/ArtifactPierreDiff-DpqRTCz8.js 1,119.58 kB
out/renderer/assets/chunk-FOHPRMQF-BCllzKJD.js 1,154.18 kB
out/renderer/assets/index-B5YSZ8Ro.js 3,765.41 kB
out/renderer/assets/editor.api2-dPwET-7w-BYIQ9bT3.js 4,889.23 kB
✓ built in 3.90s
@@ -0,0 +1,29 @@
> ycode@0.0.7 check:tokens
> node scripts/check-design-tokens.mjs
设计 token 漂移检查(静态)
扫描:src/renderer/src 共 367 个文件(用时 219 ms)
baseline:scripts/design-token-baseline.json(334 个文件)
门禁分类:adapter 8 | core 6 | local 279(合计 293 个文件)
合计:裸 hex=611 裸 px=2680 !important=6 --wb-* 定义=525 var(--yc-*) 使用=1651 var(--wb-*) 使用=1209
非门禁分类:vendor 2 | recovered 22 | source 47 | tokenSource 3(合计 74 个文件,仅记录不阻塞)
合计:裸 hex=10642 裸 px=13642 !important=920 --wb-* 定义=17966 var(--yc-*) 使用=77 var(--wb-*) 使用=19638
非门禁相对 baseline:文件 +0;裸 hex +78 裸 px +64 !important +0 --wb-* 定义 +0 var(--yc-*) 使用 +22 var(--wb-*) 使用 -120
结果:失败,共 6 项:
[新增门禁文件] src/renderer/src/capabilities/recommended-flow.css(local):裸 px=21
[新增门禁文件] src/renderer/src/capabilities/skill-detail-shell.css(local):裸 px=21
[回归] src/renderer/src/capabilities/skills-host.css(local):裸 px 25 → 45(+20)
[新增门禁文件] src/renderer/src/workbuddy/composer/capability-picker.css(local):裸 hex=26,裸 px=48
[回归] src/renderer/src/workbuddy/composer/composer.css(local):裸 hex 23 → 38(+15);裸 px 83 → 139(+56)
[新增门禁文件] src/renderer/src/workbuddy/composer/prompt-queue.css(local):裸 hex=8,裸 px=35
提示:确认变更符合预期后运行 `node scripts/check-design-tokens.mjs --update-baseline` 刷新 baseline;
否则请改用 --yc-* token、复用现有值,或去掉重复的 --wb-* 定义。
提示(不失败,仅记录):3 个门禁文件 token 使用数上升:
src/renderer/src/capabilities/skills-host.css(local):var(--wb-*) 使用 12 → 19(+7)
src/renderer/src/workbuddy/composer/composer.css(local):var(--yc-*) 使用 35 → 48(+13);var(--wb-*) 使用 0 → 1(+1)
src/renderer/src/workbuddy/conversation/conversation.css(local):var(--yc-*) 使用 0 → 4(+4)
提示(不失败):baseline 中 8 个文件已不存在:src/renderer/src/components/ReportedRunUsage.tsx;src/renderer/src/workbuddy/subagents/SourceMemberIcon.tsx;src/renderer/src/workbuddy/subagents/SubagentCollaboration.tsx;src/renderer/src/workbuddy/subagents/SubagentDetailPanel.tsx;src/renderer/src/workbuddy/subagents/adapters.css;src/renderer/src/workbuddy/subagents/member-view.ts;src/renderer/src/workbuddy/subagents/source.css;src/renderer/src/workbuddy/subagents/theme.css
提示:新增门禁文件 36 个且无受控计数(允许):src/renderer/src/capabilities/CapabilityMaintenance.tsx(local);src/renderer/src/capabilities/RecommendedSkills.tsx(local);src/renderer/src/capabilities/SkillAvatar.tsx(local);src/renderer/src/capabilities/SkillDetailShell.tsx(local);src/renderer/src/capabilities/SkillModalPortal.tsx(local);src/renderer/src/capabilities/skill-modal-focus.ts(local);src/renderer/src/components/SessionLoading.tsx(local);src/renderer/src/components/TaskPopconfirm.tsx(local);src/renderer/src/components/session-loading.css(local);src/renderer/src/components/task-popconfirm.css(local);src/renderer/src/components/updates/UpdateSidebarCard.tsx(local);src/renderer/src/components/updates/update-ui-model.ts(local);src/renderer/src/components/updates/update-ui-store.ts(local);src/renderer/src/components/updates/updates-ui.css(local);src/renderer/src/ui/Button.tsx(local);src/renderer/src/ui/IconButton.tsx(local);src/renderer/src/ui/Input.tsx(local);src/renderer/src/ui/Popover.tsx(local);src/renderer/src/ui/Select.tsx(local);src/renderer/src/ui/Switch.tsx(local);…(还有 16 项,详见 --json)
@@ -0,0 +1,88 @@
> ycode@0.0.7 test:composer-capabilities
> node scripts/run-composer-capabilities-regression.mjs
prompt-queue-regression: cap, payload, order, isolation, delivery, stop, recovery and unknown checks passed
{
"result": "PASS",
"checks": [
{
"name": "parallel same-instance enqueues preserve exactly 19 items",
"pass": true
},
{
"name": "duplicate take is serialized to one winner",
"pass": true
},
{
"name": "delivering item is immutable and notify does not duplicate delivery",
"pass": true
},
{
"name": "clear removes a non-delivering session queue and is idempotent",
"pass": true
},
{
"name": "first enqueue after an empty queue was paused resumes a new run without unpausing existing work",
"pass": true
},
{
"name": "incoming payload is validated before host side effects and persistence",
"pass": true
},
{
"name": "host-rebuilt capability labels are validated before persistence",
"pass": true
},
{
"name": "two queue instances cannot overwrite one another",
"pass": true
},
{
"name": "corrupt queue cannot redirect or duplicate item identity",
"pass": true
},
{
"name": "invalid revision, status and payload permission are rejected",
"pass": true
},
{
"name": "post-delivery removal failure becomes paused unknown instead of stuck delivering",
"pass": true
},
{
"name": "stale owner nonce is recovered without trusting a reused PID",
"pass": true
},
{
"name": "stale and expired lock files are reclaimed",
"pass": true
},
{
"name": "live foreign lock times out with an explicit error",
"pass": true
},
{
"name": "blocked notify does not create a state revision",
"pass": true
},
{
"name": "host resolver applies dispatch-time permission downgrade without mutating stored payload",
"pass": true
}
]
}
input-composition-regression: precedence, takeover, queue preservation, task placement, toolbar and escape rules passed
{"result":"PASS","checks":30}
{
"result": "PASS",
"tests": [
"serial model writes + frozen active turn",
"send failure retry",
"late result/event session isolation",
"draft settings during first session creation",
"nextRequestSettings whitelist"
]
}
context-usage-regression: latest, previous, active-run, summary identity and failure cases passed
{"result":"PASS","checks":36,"directory":"C:\\Users\\Administrator\\.codex\\worktrees\\b03-accept-01\\YCode\\.tmp\\claude-capabilities-CtzcVY"}
@@ -0,0 +1,18 @@
> ycode@0.0.7 test:reporting
> node --test scripts/regression-reporting.test.mjs
✔ alignment reports absent optional DOM coverage explicitly (3753.2111ms)
✔ alignment requires DOM when requested by flag (70.8616ms)
✔ alignment requires DOM when requested by environment (59.917ms)
✔ alignment rejects an unloadable configured DOM module instead of skipping (58.2746ms)
✔ backend never reports a skipped real package as PASS (1945.4468ms)
✔ alignment rejects a configured module without a JSDOM export (61.8861ms)
ℹ tests 6
ℹ suites 0
ℹ pass 6
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 6051.0998
@@ -0,0 +1,22 @@
[
{
"name": "test",
"exitCode": 0
},
{
"name": "test:reporting",
"exitCode": 0
},
{
"name": "test:composer-capabilities",
"exitCode": 0
},
{
"name": "test:tool-approvals",
"exitCode": 0
},
{
"name": "check:tokens",
"exitCode": 1
}
]
@@ -0,0 +1,5 @@
> ycode@0.0.7 test:tool-approvals
> esbuild scripts/tool-approval-regression.tsx --bundle --platform=node --format=cjs --jsx=automatic --loader:.css=text --outfile=.tmp/tool-approval-regression.cjs --log-level=error && node .tmp/tool-approval-regression.cjs
Tool approval helper and inline source markup regression checks passed.
@@ -0,0 +1,37 @@
> ycode@0.0.7 test
> npm run test:core
> ycode@0.0.7 test:core
> npm run typecheck && npm run test:chat && npm run test:sessions && npm run test:persistence && npm run test:conversation
> ycode@0.0.7 typecheck
> tsc --noEmit -p tsconfig.node.json && tsc --noEmit -p tsconfig.web.json
> ycode@0.0.7 test:chat
> esbuild scripts/message-order-regression.ts scripts/chat-store-regression.ts scripts/chat-stream-committer-regression.ts --bundle --platform=node --format=esm --out-extension:.js=.mjs --outdir=.tmp/chat-tests --log-level=warning && node .tmp/chat-tests/message-order-regression.mjs && node .tmp/chat-tests/chat-store-regression.mjs && node .tmp/chat-tests/chat-stream-committer-regression.mjs
message-order-regression: all checks passed
chat-store-regression: all checks passed
chat-stream-committer-regression: all checks passed
> ycode@0.0.7 test:sessions
> esbuild scripts/session-store-regression.ts --bundle --platform=node --format=esm --external:esbuild --outfile=.tmp/session-store-regression.mjs --log-level=warning && node .tmp/session-store-regression.mjs
session-store-regression: all checks passed
> ycode@0.0.7 test:persistence
> esbuild scripts/chat-persistence-regression.ts --bundle --platform=node --format=esm --external:esbuild --outfile=.tmp/chat-persistence-regression.mjs --log-level=warning && node .tmp/chat-persistence-regression.mjs
chat-persistence-regression: all checks passed
> ycode@0.0.7 test:conversation
> esbuild scripts/conversation-renderer-regression.tsx scripts/composer-regression.tsx scripts/completed-fold-regression.tsx scripts/streaming-footer-regression.tsx --bundle --platform=node --format=cjs --jsx=automatic --loader:.css=text --out-extension:.js=.cjs --outdir=.tmp/conversation-tests --log-level=error && node .tmp/conversation-tests/conversation-renderer-regression.cjs && node .tmp/conversation-tests/composer-regression.cjs && node .tmp/conversation-tests/streaming-footer-regression.cjs && node .tmp/conversation-tests/completed-fold-regression.cjs
Conversation specialized renderer SSR regression checks passed
Composer/message action regression cases passed
streaming-footer-regression: persistent stream status, delayed/paused rotation, brand/locale mapping, source CSS, and completed model footer passed
Completed-fold model and SSR regression checks passed
@@ -0,0 +1,72 @@
{
"status": "PASS",
"scope": "Actual ClaudeKernel and SDK; temporary preferences supplied, Windows Bash and PowerShell QA adaptation; no UI coverage",
"requests": 26,
"cases": [
{
"case": "craft-default",
"approvals": 1,
"questions": 0,
"ruleApprovals": 0,
"toolErrors": 1
},
{
"case": "craft-full",
"approvals": 0,
"questions": 1,
"ruleApprovals": 0,
"toolErrors": 0,
"compoundMarker": true,
"disposableAbsent": true
},
{
"case": "plan-full",
"approvals": 0,
"questions": 0,
"ruleApprovals": 0,
"toolErrors": 1
},
{
"case": "ask-full",
"approvals": 0,
"questions": 0,
"ruleApprovals": 0,
"toolErrors": 1
},
{
"case": "default-return",
"approvals": 1,
"questions": 0,
"ruleApprovals": 0,
"toolErrors": 1
},
{
"case": "ask-rule-full",
"approvals": 0,
"questions": 0,
"ruleApprovals": 0,
"toolErrors": 0
},
{
"case": "ask-rule-default",
"approvals": 1,
"questions": 0,
"ruleApprovals": 1,
"toolErrors": 1
},
{
"case": "rebuilt-full",
"approvals": 0,
"questions": 1,
"ruleApprovals": 0,
"toolErrors": 0
},
{
"case": "full-execution-errors",
"approvals": 0,
"questions": 0,
"ruleApprovals": 0,
"toolErrors": 2
}
]
}
@@ -0,0 +1,178 @@
// B03: real SDK/CLI, deterministic loopback model, disposable fixtures only.
// Default: SDK protocol policy. --kernel: bundled production ClaudeKernel, real SDK.
import assert from 'node:assert/strict'
import { createServer } from 'node:http'
import { mkdtemp, mkdir, writeFile, readFile, stat, rm } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join, resolve } from 'node:path'
// QA Windows adaptation; real kernel and SDK retained.
const executable = resolve(`node_modules/@anthropic-ai/claude-agent-sdk-${process.platform}-${process.arch}/${process.platform === 'win32' ? 'claude.exe' : 'claude'}`)
const root = await mkdtemp(join(tmpdir(), 'ycode-b03-loopback-'))
const workspace = join(root, 'workspace')
for (const name of ['workspace', 'home', 'config', 'tmp', 'user-data']) await mkdir(join(root, name))
const env = {
PATH: process.env.PATH, SystemRoot: process.env.SystemRoot, WINDIR: process.env.WINDIR, ComSpec: process.env.ComSpec, PATHEXT: process.env.PATHEXT, CLAUDE_CODE_GIT_BASH_PATH: 'C:/Users/Administrator/scoop/apps/git/current/bin/bash.exe', HOME: join(root, 'home'), USERPROFILE: join(root, 'home'),
TMPDIR: join(root, 'tmp'), TMP: join(root, 'tmp'), TEMP: join(root, 'tmp'),
CLAUDE_CONFIG_DIR: join(root, 'config'), CLAUDE_SECURESTORAGE_CONFIG_DIR: join(root, 'config'),
CLAUDE_TEST_USER_DATA: join(root, 'user-data'),
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1', DISABLE_TELEMETRY: '1', DISABLE_ERROR_REPORTING: '1',
ANTHROPIC_API_KEY: 'isolated-loopback-placeholder-not-a-credential',
ANTHROPIC_MODEL: 'claude-loopback', ANTHROPIC_DEFAULT_OPUS_MODEL: 'claude-loopback',
ANTHROPIC_DEFAULT_SONNET_MODEL: 'claude-loopback', ANTHROPIC_DEFAULT_HAIKU_MODEL: 'claude-loopback'
}
// Clear inheritance before SDK import as well as passing an explicit child env.
for (const key of Object.keys(process.env)) delete process.env[key]
Object.assign(process.env, env)
let stage = 'bind', activeCase, instance, kernel, requests = 0
const kernelMode = process.argv.includes('--kernel')
const results = []
function send(res, event, data) { res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`) }
const server = createServer((req, res) => {
if (++requests > 60) { res.writeHead(429).end(); return }
if (req.method !== 'POST' || !req.url?.startsWith('/v1/messages')) { res.writeHead(404).end(); return }
let raw = ''
req.on('data', chunk => { raw += chunk; if (raw.length > 1024 * 1024) req.destroy() })
req.on('end', () => {
try {
const body = JSON.parse(raw)
const c = activeCase
assert.ok(c)
const next = c.steps[c.issued++]
res.writeHead(200, { 'content-type': 'text/event-stream' })
send(res, 'message_start', { type: 'message_start', message: { id: `msg_${requests}`, type: 'message', role: 'assistant', model: body.model, content: [], stop_reason: null, stop_sequence: null, usage: { input_tokens: 10, output_tokens: 1 } } })
const content = next ? { type: 'tool_use', id: `tool_${requests}`, name: next.name, input: {} } : { type: 'text', text: '' }
send(res, 'content_block_start', { type: 'content_block_start', index: 0, content_block: content })
send(res, 'content_block_delta', { type: 'content_block_delta', index: 0, delta: next ? { type: 'input_json_delta', partial_json: JSON.stringify(next.input) } : { type: 'text_delta', text: 'Fixture complete.' } })
send(res, 'content_block_stop', { type: 'content_block_stop', index: 0 })
send(res, 'message_delta', { type: 'message_delta', delta: { stop_reason: next ? 'tool_use' : 'end_turn', stop_sequence: null }, usage: { output_tokens: 5 } })
send(res, 'message_stop', { type: 'message_stop' }); res.end()
} catch { res.destroy() }
})
})
const abortController = new AbortController()
const timer = setTimeout(() => abortController.abort(), 100000)
const write = (file, content) => ({ name: 'Write', input: { file_path: join(workspace, file), content } })
async function verifyCompound() {
assert.equal(await readFile(join(workspace, 'compound-complete.txt'), 'utf8'), 'complete')
await assert.rejects(stat(join(workspace, 'disposable')), { code: 'ENOENT' })
await assert.rejects(stat(join(workspace, 'disposable/item.txt')), { code: 'ENOENT' })
}
const question = { name: 'AskUserQuestion', input: { questions: [{ question: 'Which fixture?', header: 'Fixture', multiSelect: false, options: [{ label: 'Alpha', description: 'First fixture' }, { label: 'Beta', description: 'Second fixture' }] }] } }
try {
// Binding is deliberately first: on denial do not import/start the SDK.
await new Promise((ok, fail) => { server.once('error', fail); server.listen(0, '127.0.0.1', ok) })
env.ANTHROPIC_BASE_URL = `http://127.0.0.1:${server.address().port}`
Object.assign(process.env, env)
stage = 'sdk-import'
const { query } = await import('@anthropic-ai/claude-agent-sdk')
await writeFile(join(workspace, 'existing.txt'), 'before\n')
const cases = [
{ label: 'craft-full', mode: 'craft', full: true, steps: [
{ name: 'Read', input: { file_path: join(workspace, 'existing.txt') } },
{ name: 'Edit', input: { file_path: join(workspace, 'existing.txt'), old_string: 'before', new_string: 'after' } },
write('created.txt', 'created\n'),
{ name: 'Bash', input: { command: 'printf simple > simple.txt', timeout: 5000 } },
{ name: 'Bash', input: { command: 'mkdir disposable && printf fixture > disposable/item.txt && rm disposable/item.txt && rmdir disposable && printf complete > compound-complete.txt', timeout: 5000 } },
{ name: 'PowerShell', input: { command: "[IO.File]::WriteAllText('powershell-simple.txt','powershell'); New-Item -ItemType Directory -Path ps-disposable | Out-Null; Set-Content ps-disposable/item.txt 'fixture'; Remove-Item ps-disposable/item.txt; Remove-Item ps-disposable; [IO.File]::WriteAllText('powershell-complete.txt','complete')", timeout: 5000 } }, question
] },
{ label: 'craft-default', mode: 'craft', full: false, steps: [write('default-denied.txt', 'blocked')] },
{ label: 'plan-full', mode: 'plan', full: true, steps: [write('plan-denied.txt', 'blocked')] },
{ label: 'ask-full', mode: 'ask', full: true, steps: [write('ask-denied.txt', 'blocked')] }
]
if (kernelMode) {
stage = 'kernel-import'
const { ClaudeKernel } = await import('./b03-real-kernel.mjs')
const model = {
profile: { id: 'b03-fixture', name: 'B03 fixture', model: 'claude-loopback', authMode: 'api-key', protocol: 'anthropic', contextWindowTokens: 200000 },
config: { api: 'anthropic-messages', baseUrl: env.ANTHROPIC_BASE_URL + '/v1', model: 'claude-loopback', apiKey: env.ANTHROPIC_API_KEY, authMode: 'api-key' }
}
const makeKernel = permissionMode => new ClaudeKernel({ sessionId: crypto.randomUUID(), workspaceRoot: workspace, model, permissionMode, agentMode: 'craft', thinkingLevel: 'off', forceNewSession: true, onSessionId() {} })
kernel = makeKernel('default-sandbox')
const sequence = [cases[1], cases[0], cases[2], cases[3], { ...cases[1], label: 'default-return' },
{ label: 'ask-rule-full', mode: 'craft', full: true, rule: true, steps: [{ name: 'Bash', input: { command: 'printf rule >> rule-marker.txt', timeout: 5000 } }] },
{ label: 'ask-rule-default', mode: 'craft', full: false, rule: true, steps: [{ name: 'Bash', input: { command: 'printf rule >> rule-marker.txt', timeout: 5000 } }] },
{ label: 'rebuilt-full', mode: 'craft', full: true, rebuild: true, steps: [write('rebuilt.txt', 'rebuilt'), question] },
{ label: 'full-execution-errors', mode: 'craft', full: true, errors: true, steps: [
{ name: 'Edit', input: { file_path: join(workspace, 'does-not-exist.txt'), old_string: 'before', new_string: 'after' } },
{ name: 'Bash', input: { command: 'exit 7', timeout: 5000 } }
] }]
for (const c of sequence) {
stage = c.label
if (c.rebuild) { await kernel.close(); kernel = makeKernel('full-access') }
await kernel.setPolicy(c.full ? 'full-access' : 'default-sandbox', c.mode)
if (c.rule) {
// Query is the real initialized SDK instance, not a replacement. This
// API changes only its session flag layer, never user config files.
assert.ok(kernel.instance)
await kernel.instance.applyFlagSettings({ permissions: { ask: ['Bash'] } })
}
activeCase = { ...c, issued: 0 }
let approvals = 0, questions = 0, ruleApprovals = 0
const output = await kernel.runTurn({ runId: crypto.randomUUID(), userMessageId: crypto.randomUUID(), prompt: `Run deterministic fixture ${c.label}.`, signal: abortController.signal,
emit() {}, interactions: {
async approval(...args) { approvals++; if (args[5]?.requestKind === 'rule-intercept') ruleApprovals++; return { kind: 'approval', optionId: 'reject-once' } },
async question(_id, _title, items) { questions++; return { kind: 'question', answer: { questions: items.map(item => ({ id: item.id, question: item.question, answers: ['Alpha'] })) } } }
}
})
const toolErrors = output.tools.filter(tool => tool.status === 'error').length
assert.equal(output.tools.length, c.steps.length)
if (c.rule) {
assert.equal(approvals, c.full ? 0 : 1)
assert.equal(ruleApprovals, c.full ? 0 : 1)
assert.equal(toolErrors, c.full ? 0 : 1)
assert.equal(await readFile(join(workspace, 'rule-marker.txt'), 'utf8'), 'rule')
} else if (c.errors) { assert.equal(approvals, 0); assert.equal(toolErrors, 2) }
else if (c.mode === 'craft' && c.full) {
assert.equal(approvals, 0); assert.equal(questions, 1); assert.equal(toolErrors, 0)
if (c.rebuild) assert.equal(await readFile(join(workspace, 'rebuilt.txt'), 'utf8'), 'rebuilt')
else { assert.equal(await readFile(join(workspace, 'existing.txt'), 'utf8'), 'after\n'); assert.equal(await readFile(join(workspace, 'created.txt'), 'utf8'), 'created\n'); assert.equal(await readFile(join(workspace, 'simple.txt'), 'utf8'), 'simple'); await verifyCompound(); assert.equal(await readFile(join(workspace, 'powershell-simple.txt'), 'utf8'), 'powershell'); assert.equal(await readFile(join(workspace, 'powershell-complete.txt'), 'utf8'), 'complete'); await assert.rejects(stat(join(workspace, 'ps-disposable')), {code:'ENOENT'}) }
} else {
assert.equal(toolErrors, 1)
assert.equal(approvals, c.mode === 'craft' ? 1 : 0)
await assert.rejects(readFile(join(workspace, `${c.mode === 'craft' ? 'default' : c.mode}-denied.txt`)), { code: 'ENOENT' })
}
results.push({ case: c.label, approvals, questions, ruleApprovals, toolErrors, ...(c.label === 'craft-full' ? { compoundMarker: true, disposableAbsent: true } : {}) })
}
await kernel.close(); kernel = undefined
} else for (const c of cases) {
stage = c.label
activeCase = { ...c, issued: 0 }; let approvals = 0, questions = 0, hookDenials = 0, toolErrors = 0
instance = query({ prompt: 'Run only the deterministic local fixture sequence.', options: {
cwd: workspace, pathToClaudeCodeExecutable: executable, env, abortController,
model: 'claude-loopback', permissionMode: 'default', permissionPrompts: 'host',
settingSources: [], strictMcpConfig: true, mcpServers: {}, plugins: [], agents: {},
persistSession: false, maxTurns: 12, tools: ['Read', 'Edit', 'Write', 'Bash', 'AskUserQuestion'],
hooks: { PreToolUse: [{ hooks: [async hook => {
if (hook.tool_name === 'AskUserQuestion') return { hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'ask' } }
if (c.mode !== 'craft' && ['Write', 'Edit', 'Bash'].includes(hook.tool_name)) {
hookDenials++; return { hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason: 'Fixture read-only mode' } }
}
return c.full && c.mode === 'craft' ? { hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'allow' } } : {}
}] }] },
canUseTool: async (name, input) => {
if (name === 'AskUserQuestion') { questions++; return { behavior: 'allow', updatedInput: { ...input, answers: { 'Which fixture?': 'Alpha' } } } }
approvals++; return { behavior: 'deny', message: 'Default fixture approval intentionally denied' }
}
} })
let completed = false
for await (const message of instance) {
if (message.type === 'user' && Array.isArray(message.message?.content)) toolErrors += message.message.content.filter(x => x.type === 'tool_result' && x.is_error).length
if (message.type === 'result') { assert.equal(message.subtype, 'success'); completed = true; break }
}
instance.close(); instance = undefined
assert.ok(completed)
if (c.label === 'craft-full') { assert.equal(approvals, 0); assert.equal(questions, 1); assert.equal(toolErrors, 0); assert.equal(await readFile(join(workspace, 'existing.txt'), 'utf8'), 'after\n'); assert.equal(await readFile(join(workspace, 'created.txt'), 'utf8'), 'created\n'); assert.equal(await readFile(join(workspace, 'simple.txt'), 'utf8'), 'simple'); await verifyCompound() }
else { await assert.rejects(readFile(join(workspace, `${c.mode === 'craft' ? 'default' : c.mode}-denied.txt`)), { code: 'ENOENT' }); if (c.mode === 'craft') assert.ok(approvals > 0); else assert.ok(hookDenials > 0) }
results.push({ case: c.label, approvals, questions, hookDenials, toolErrors })
}
console.log(JSON.stringify({ status: 'PASS', scope: kernelMode ? 'Actual ClaudeKernel and SDK; temporary preferences supplied, Windows Bash and PowerShell QA adaptation; no UI coverage' : 'SDK protocol fixture, not actual application kernel or Windows', requests, cases: results }))
} catch (error) {
console.error(JSON.stringify({ status: 'BLOCKED_OR_FAILED', stage, code: error?.code ?? null, name: error?.name ?? 'Error', message: error?.message, stack: error?.stack, completedCases: results }))
process.exitCode = 1
} finally {
clearTimeout(timer); abortController.abort(); instance?.close(); await kernel?.close()
server.closeAllConnections(); if (server.listening) await new Promise(ok => server.close(ok))
await rm(root, { recursive: true, force: true })
}
@@ -0,0 +1,25 @@
[claude] [claude-code:unrecognized_model] {"model":"claude-loopback","query_source":"sdk"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"43a3b2698eba905e","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"sdk-policy"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"43a3b2698eba905e","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"4ed9abbf3162300a","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"86fd4ab8db7f5f11","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"7e2ee80a5e248272","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"6db1fc2e4c48edb8","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"6e7d36eb4db18cae","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"36814c9006134245","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"9ff3664e4c844d32","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"business-question"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"9ff3664e4c844d32","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"business-question"}
[claude-permission] {"permissionMode":"full-access","agentMode":"plan","sdkMode":"plan","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"cc04668a6ae49237","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"mode-or-inactive-deny"}
[claude-permission] {"permissionMode":"full-access","agentMode":"ask","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"11ffd38876c89a92","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"mode-or-inactive-deny"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"c8d4672b320d8e62","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"sdk-policy"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"c8d4672b320d8e62","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"5d7efa6d743f9e03","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"5d7efa6d743f9e03","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":true,"branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"17731bb84b6f9672","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"sdk-policy"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"17731bb84b6f9672","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":true,"branch":"rule-approval"}
[claude] [claude-code:unrecognized_model] {"model":"claude-loopback","query_source":"sdk"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"8a6a3330fe99a401","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"4db9b8eaf21b122c","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"business-question"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"4db9b8eaf21b122c","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"business-question"}
[claude-permission] {"permissionMode":"full-access","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"8f3f4861840d6744","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"full-access-preauthorized"}
{"status":"PASS","scope":"Actual ClaudeKernel and SDK; temporary preferences supplied, Windows Bash and PowerShell QA adaptation; no UI coverage","requests":26,"cases":[{"case":"craft-default","approvals":1,"questions":0,"ruleApprovals":0,"toolErrors":1},{"case":"craft-full","approvals":0,"questions":1,"ruleApprovals":0,"toolErrors":0,"compoundMarker":true,"disposableAbsent":true},{"case":"plan-full","approvals":0,"questions":0,"ruleApprovals":0,"toolErrors":1},{"case":"ask-full","approvals":0,"questions":0,"ruleApprovals":0,"toolErrors":1},{"case":"default-return","approvals":1,"questions":0,"ruleApprovals":0,"toolErrors":1},{"case":"ask-rule-full","approvals":0,"questions":0,"ruleApprovals":0,"toolErrors":0},{"case":"ask-rule-default","approvals":1,"questions":0,"ruleApprovals":1,"toolErrors":1},{"case":"rebuilt-full","approvals":0,"questions":1,"ruleApprovals":0,"toolErrors":0},{"case":"full-execution-errors","approvals":0,"questions":0,"ruleApprovals":0,"toolErrors":2}]}
@@ -0,0 +1,57 @@
{
"status": "PASS",
"scope": "Actual ClaudeKernel and SDK; temporary preferences supplied, Windows real session grant lifecycle; no UI coverage",
"requests": 12,
"cases": [
{
"case": "grant-first",
"approvals": 1,
"grants": 1,
"toolErrors": 0,
"proposalKinds": [
"allow_once",
"allow_always",
"reject_once"
]
},
{
"case": "grant-next-turn",
"approvals": 0,
"grants": 0,
"toolErrors": 0,
"proposalKinds": []
},
{
"case": "grant-rebuilt-same-session",
"approvals": 0,
"grants": 0,
"toolErrors": 0,
"proposalKinds": []
},
{
"case": "grant-new-session",
"approvals": 1,
"grants": 1,
"toolErrors": 0,
"proposalKinds": [
"allow_once",
"allow_always",
"reject_once"
]
},
{
"case": "grant-plan-boundary",
"approvals": 0,
"grants": 0,
"toolErrors": 1,
"proposalKinds": []
},
{
"case": "grant-ask-boundary",
"approvals": 0,
"grants": 0,
"toolErrors": 1,
"proposalKinds": []
}
]
}
@@ -0,0 +1,149 @@
// B03: real SDK/CLI, deterministic loopback model, disposable fixtures only.
// Default: SDK protocol policy. --kernel: bundled production ClaudeKernel, real SDK.
import assert from 'node:assert/strict'
import { createServer } from 'node:http'
import { mkdtemp, mkdir, writeFile, readFile, stat, rm } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join, resolve } from 'node:path'
// QA Windows adaptation; real kernel and SDK retained.
const executable = resolve(`node_modules/@anthropic-ai/claude-agent-sdk-${process.platform}-${process.arch}/${process.platform === 'win32' ? 'claude.exe' : 'claude'}`)
const root = await mkdtemp(join(tmpdir(), 'ycode-b03-loopback-'))
const workspace = join(root, 'workspace')
for (const name of ['workspace', 'home', 'config', 'tmp', 'user-data']) await mkdir(join(root, name))
const env = {
PATH: process.env.PATH, SystemRoot: process.env.SystemRoot, WINDIR: process.env.WINDIR, ComSpec: process.env.ComSpec, PATHEXT: process.env.PATHEXT, CLAUDE_CODE_GIT_BASH_PATH: 'C:/Users/Administrator/scoop/apps/git/current/bin/bash.exe', HOME: join(root, 'home'), USERPROFILE: join(root, 'home'),
TMPDIR: join(root, 'tmp'), TMP: join(root, 'tmp'), TEMP: join(root, 'tmp'),
CLAUDE_CONFIG_DIR: join(root, 'config'), CLAUDE_SECURESTORAGE_CONFIG_DIR: join(root, 'config'),
CLAUDE_TEST_USER_DATA: join(root, 'user-data'),
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1', DISABLE_TELEMETRY: '1', DISABLE_ERROR_REPORTING: '1',
ANTHROPIC_API_KEY: 'isolated-loopback-placeholder-not-a-credential',
ANTHROPIC_MODEL: 'claude-loopback', ANTHROPIC_DEFAULT_OPUS_MODEL: 'claude-loopback',
ANTHROPIC_DEFAULT_SONNET_MODEL: 'claude-loopback', ANTHROPIC_DEFAULT_HAIKU_MODEL: 'claude-loopback'
}
// Clear inheritance before SDK import as well as passing an explicit child env.
for (const key of Object.keys(process.env)) delete process.env[key]
Object.assign(process.env, env)
let stage = 'bind', activeCase, instance, kernel, requests = 0
const kernelMode = process.argv.includes('--kernel')
const results = []
function send(res, event, data) { res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`) }
const server = createServer((req, res) => {
if (++requests > 60) { res.writeHead(429).end(); return }
if (req.method !== 'POST' || !req.url?.startsWith('/v1/messages')) { res.writeHead(404).end(); return }
let raw = ''
req.on('data', chunk => { raw += chunk; if (raw.length > 1024 * 1024) req.destroy() })
req.on('end', () => {
try {
const body = JSON.parse(raw)
const c = activeCase
assert.ok(c)
const next = c.steps[c.issued++]
res.writeHead(200, { 'content-type': 'text/event-stream' })
send(res, 'message_start', { type: 'message_start', message: { id: `msg_${requests}`, type: 'message', role: 'assistant', model: body.model, content: [], stop_reason: null, stop_sequence: null, usage: { input_tokens: 10, output_tokens: 1 } } })
const content = next ? { type: 'tool_use', id: `tool_${requests}`, name: next.name, input: {} } : { type: 'text', text: '' }
send(res, 'content_block_start', { type: 'content_block_start', index: 0, content_block: content })
send(res, 'content_block_delta', { type: 'content_block_delta', index: 0, delta: next ? { type: 'input_json_delta', partial_json: JSON.stringify(next.input) } : { type: 'text_delta', text: 'Fixture complete.' } })
send(res, 'content_block_stop', { type: 'content_block_stop', index: 0 })
send(res, 'message_delta', { type: 'message_delta', delta: { stop_reason: next ? 'tool_use' : 'end_turn', stop_sequence: null }, usage: { output_tokens: 5 } })
send(res, 'message_stop', { type: 'message_stop' }); res.end()
} catch { res.destroy() }
})
})
const abortController = new AbortController()
const timer = setTimeout(() => abortController.abort(), 100000)
const write = (file, content) => ({ name: 'Write', input: { file_path: join(workspace, file), content } })
async function verifyCompound() {
assert.equal(await readFile(join(workspace, 'compound-complete.txt'), 'utf8'), 'complete')
await assert.rejects(stat(join(workspace, 'disposable')), { code: 'ENOENT' })
await assert.rejects(stat(join(workspace, 'disposable/item.txt')), { code: 'ENOENT' })
}
const question = { name: 'AskUserQuestion', input: { questions: [{ question: 'Which fixture?', header: 'Fixture', multiSelect: false, options: [{ label: 'Alpha', description: 'First fixture' }, { label: 'Beta', description: 'Second fixture' }] }] } }
try {
// Binding is deliberately first: on denial do not import/start the SDK.
await new Promise((ok, fail) => { server.once('error', fail); server.listen(0, '127.0.0.1', ok) })
env.ANTHROPIC_BASE_URL = `http://127.0.0.1:${server.address().port}`
Object.assign(process.env, env)
stage = 'sdk-import'
const { query } = await import('@anthropic-ai/claude-agent-sdk')
await writeFile(join(workspace, 'existing.txt'), 'before\n')
const cases = [
{ label: 'craft-full', mode: 'craft', full: true, steps: [
{ name: 'Read', input: { file_path: join(workspace, 'existing.txt') } },
{ name: 'Edit', input: { file_path: join(workspace, 'existing.txt'), old_string: 'before', new_string: 'after' } },
write('created.txt', 'created\n'),
{ name: 'Bash', input: { command: 'printf simple > simple.txt', timeout: 5000 } },
{ name: 'Bash', input: { command: 'mkdir disposable && printf fixture > disposable/item.txt && rm disposable/item.txt && rmdir disposable && printf complete > compound-complete.txt', timeout: 5000 } },
{ name: 'PowerShell', input: { command: "[IO.File]::WriteAllText('powershell-simple.txt','powershell'); New-Item -ItemType Directory -Path ps-disposable | Out-Null; Set-Content ps-disposable/item.txt 'fixture'; Remove-Item ps-disposable/item.txt; Remove-Item ps-disposable; [IO.File]::WriteAllText('powershell-complete.txt','complete')", timeout: 5000 } }, question
] },
{ label: 'craft-default', mode: 'craft', full: false, steps: [write('default-denied.txt', 'blocked')] },
{ label: 'plan-full', mode: 'plan', full: true, steps: [write('plan-denied.txt', 'blocked')] },
{ label: 'ask-full', mode: 'ask', full: true, steps: [write('ask-denied.txt', 'blocked')] }
]
if (kernelMode) {
stage = 'kernel-import'
const { ClaudeKernel } = await import('./b03-real-kernel.mjs')
const model = {
profile: { id: 'b03-fixture', name: 'B03 fixture', model: 'claude-loopback', authMode: 'api-key', protocol: 'anthropic', contextWindowTokens: 200000 },
config: { api: 'anthropic-messages', baseUrl: env.ANTHROPIC_BASE_URL + '/v1', model: 'claude-loopback', apiKey: env.ANTHROPIC_API_KEY, authMode: 'api-key' }
}
let hostSessionId=crypto.randomUUID(); const makeKernel = permissionMode => new ClaudeKernel({ sessionId: hostSessionId, workspaceRoot: workspace, model, permissionMode, agentMode: 'craft', thinkingLevel: 'off', forceNewSession: true, onSessionId() {} })
kernel = makeKernel('default-sandbox')
const command={name:'Bash',input:{command:'git init grant-repo',timeout:5000}};
const sequence=[{label:'grant-first',expected:1},{label:'grant-next-turn',expected:0},{label:'grant-rebuilt-same-session',expected:0,rebuild:true},{label:'grant-new-session',expected:1,rebuild:true,newSession:true},{label:'grant-plan-boundary',expected:0,mode:'plan'},{label:'grant-ask-boundary',expected:0,mode:'ask'}];
for(const c of sequence){
stage=c.label;
if(c.rebuild){await kernel.close();if(c.newSession)hostSessionId=crypto.randomUUID();kernel=makeKernel('default-sandbox')}
await kernel.setPolicy('default-sandbox',c.mode||'craft');
activeCase={steps:[command],issued:0};let approvals=0,grants=0,proposalKinds=[];
const output=await kernel.runTurn({runId:crypto.randomUUID(),userMessageId:crypto.randomUUID(),prompt:'Run deterministic grant fixture.',signal:abortController.signal,emit(){},interactions:{
async approval(...args){approvals++;proposalKinds=args[2].map(x=>x.kind);console.log('GRANT_PROPOSAL',JSON.stringify({kinds:proposalKinds,details:args[5],hasApply:typeof args[6]}));const opt=args[2].find(x=>x.kind==='allow_always');assert.ok(opt,'real SDK must offer replayable session grant for fixture');await args[6]({kind:'approval',optionId:opt.optionId});grants++;return {kind:'approval',optionId:opt.optionId}},
async question(){throw Error('Unexpected question')}
}});
const toolErrors=output.tools.filter(x=>x.status==='error').length;
assert.equal(approvals,c.expected);assert.equal(grants,c.expected);assert.equal(toolErrors,c.mode?1:0);
results.push({case:c.label,approvals,grants,toolErrors,proposalKinds});
}
assert.ok((await stat(join(workspace,'grant-repo/.git'))).isDirectory());
await kernel.close(); kernel = undefined
} else for (const c of cases) {
stage = c.label
activeCase = { ...c, issued: 0 }; let approvals = 0, questions = 0, hookDenials = 0, toolErrors = 0
instance = query({ prompt: 'Run only the deterministic local fixture sequence.', options: {
cwd: workspace, pathToClaudeCodeExecutable: executable, env, abortController,
model: 'claude-loopback', permissionMode: 'default', permissionPrompts: 'host',
settingSources: [], strictMcpConfig: true, mcpServers: {}, plugins: [], agents: {},
persistSession: false, maxTurns: 12, tools: ['Read', 'Edit', 'Write', 'Bash', 'AskUserQuestion'],
hooks: { PreToolUse: [{ hooks: [async hook => {
if (hook.tool_name === 'AskUserQuestion') return { hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'ask' } }
if (c.mode !== 'craft' && ['Write', 'Edit', 'Bash'].includes(hook.tool_name)) {
hookDenials++; return { hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'deny', permissionDecisionReason: 'Fixture read-only mode' } }
}
return c.full && c.mode === 'craft' ? { hookSpecificOutput: { hookEventName: 'PreToolUse', permissionDecision: 'allow' } } : {}
}] }] },
canUseTool: async (name, input) => {
if (name === 'AskUserQuestion') { questions++; return { behavior: 'allow', updatedInput: { ...input, answers: { 'Which fixture?': 'Alpha' } } } }
approvals++; return { behavior: 'deny', message: 'Default fixture approval intentionally denied' }
}
} })
let completed = false
for await (const message of instance) {
if (message.type === 'user' && Array.isArray(message.message?.content)) toolErrors += message.message.content.filter(x => x.type === 'tool_result' && x.is_error).length
if (message.type === 'result') { assert.equal(message.subtype, 'success'); completed = true; break }
}
instance.close(); instance = undefined
assert.ok(completed)
if (c.label === 'craft-full') { assert.equal(approvals, 0); assert.equal(questions, 1); assert.equal(toolErrors, 0); assert.equal(await readFile(join(workspace, 'existing.txt'), 'utf8'), 'after\n'); assert.equal(await readFile(join(workspace, 'created.txt'), 'utf8'), 'created\n'); assert.equal(await readFile(join(workspace, 'simple.txt'), 'utf8'), 'simple'); await verifyCompound() }
else { await assert.rejects(readFile(join(workspace, `${c.mode === 'craft' ? 'default' : c.mode}-denied.txt`)), { code: 'ENOENT' }); if (c.mode === 'craft') assert.ok(approvals > 0); else assert.ok(hookDenials > 0) }
results.push({ case: c.label, approvals, questions, hookDenials, toolErrors })
}
console.log(JSON.stringify({ status: 'PASS', scope: kernelMode ? 'Actual ClaudeKernel and SDK; temporary preferences supplied, Windows real session grant lifecycle; no UI coverage' : 'SDK protocol fixture, not actual application kernel or Windows', requests, cases: results }))
} catch (error) {
console.error(JSON.stringify({ status: 'BLOCKED_OR_FAILED', stage, code: error?.code ?? null, name: error?.name ?? 'Error', message: error?.message, stack: error?.stack, completedCases: results }))
process.exitCode = 1
} finally {
clearTimeout(timer); abortController.abort(); instance?.close(); await kernel?.close()
server.closeAllConnections(); if (server.listening) await new Promise(ok => server.close(ok))
await rm(root, { recursive: true, force: true })
}
@@ -0,0 +1,14 @@
[claude] [claude-code:unrecognized_model] {"model":"claude-loopback","query_source":"sdk"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"43a3b2698eba905e","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"sdk-policy"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"43a3b2698eba905e","decisionCategory":"other","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"}
GRANT_PROPOSAL {"kinds":["allow_once","allow_always","reject_once"],"details":{"requestKind":"permission","toolName":"Bash","command":"git init grant-repo","reason":"This command requires approval","suggestedRules":["Bash(git init *)"],"allowScope":"session"},"hasApply":"function"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"4ed9abbf3162300a","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"sdk-policy"}
[claude] [claude-code:unrecognized_model] {"model":"claude-loopback","query_source":"sdk"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"7e2ee80a5e248272","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"sdk-policy"}
[claude] [claude-code:unrecognized_model] {"model":"claude-loopback","query_source":"sdk"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"6e7d36eb4db18cae","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"sdk-policy"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"craft","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"callback","toolCall":"6e7d36eb4db18cae","decisionCategory":"other","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":false,"branch":"permission-approval"}
GRANT_PROPOSAL {"kinds":["allow_once","allow_always","reject_once"],"details":{"requestKind":"permission","toolName":"Bash","command":"git init grant-repo","reason":"This command requires approval","suggestedRules":["Bash(git init *)"],"allowScope":"session"},"hasApply":"function"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"plan","sdkMode":"plan","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"9ff3664e4c844d32","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"mode-or-inactive-deny"}
[claude-permission] {"permissionMode":"default-sandbox","agentMode":"ask","sdkMode":"default","sdkModeSource":"host-query-or-acknowledged-control","policyTransition":false,"source":"hook","toolCall":"cc04668a6ae49237","decisionCategory":"unknown","decisionCode":"unknown","decisionCodePresent":false,"matchedAskRule":"unknown","branch":"mode-or-inactive-deny"}
{"status":"PASS","scope":"Actual ClaudeKernel and SDK; temporary preferences supplied, Windows real session grant lifecycle; no UI coverage","requests":12,"cases":[{"case":"grant-first","approvals":1,"grants":1,"toolErrors":0,"proposalKinds":["allow_once","allow_always","reject_once"]},{"case":"grant-next-turn","approvals":0,"grants":0,"toolErrors":0,"proposalKinds":[]},{"case":"grant-rebuilt-same-session","approvals":0,"grants":0,"toolErrors":0,"proposalKinds":[]},{"case":"grant-new-session","approvals":1,"grants":1,"toolErrors":0,"proposalKinds":["allow_once","allow_always","reject_once"]},{"case":"grant-plan-boundary","approvals":0,"grants":0,"toolErrors":1,"proposalKinds":[]},{"case":"grant-ask-boundary","approvals":0,"grants":0,"toolErrors":1,"proposalKinds":[]}]}