@juspay/neurolink 12.35.3 β†’ 12.35.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2336,61 +2336,61 @@
2336
2336
  {"objectID":"06453fe78480b6ae73c599e3820862490a2b30ddd72bd4dc0d65052855dae72c","title":"Test Data Requirements:","url":"/docs/development/testing-plan#test-data-requirements","content":"Mock AI provider responses\nTest WebSocket messages\nSample telemetry data\nChat conversation samples","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ COMPREHENSIVE TESTING & VERIFICATION PLAN","lvl2":"Test Data Requirements:","lvl3":""}},
2337
2337
  {"objectID":"759cf99082dba9a208b8b190c152cc5fc54c637c0e8826d7369b8994ab20ac6f","title":"Test Results Documentation:","url":"/docs/development/testing-plan#test-results-documentation","content":"Phase Results Summary - Pass/fail status for each phase\nPerformance Benchmarks - Before/after performance metrics\nIntegration Test Results - Real-world scenario outcomes\nBug Report - Any issues discovered during testing\nProduction Readiness Certificate - Final validation sign-off","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ COMPREHENSIVE TESTING & VERIFICATION PLAN","lvl2":"Test Results Documentation:","lvl3":""}},
2338
2338
  {"objectID":"2866fdda44a9f55d463a0c10f0d478793ec401edbb3ac475a9ff2a3cbbaf019d","title":"Updated Documentation:","url":"/docs/development/testing-plan#updated-documentation","content":"API Reference - Reflecting actual implementation\nExamples & Tutorials - Working code samples\nTroubleshooting Guide - Common issues and solutions\nPerformance Guide - Optimization recommendations\n\nReady for Execution: This plan provides comprehensive validation of all Lighthouse integration work while ensuring zero breaking changes and optimal performance.\n\nEstimated Total Time: 3 hours for complete validation\nCritical Path: Phase A must pass before proceeding to subsequent phases\nSuccess Rate Target: 100% pass rate for Critical criteria, 90%+ for Important criteria","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ COMPREHENSIVE TESTING & VERIFICATION PLAN","lvl2":"Updated Documentation:","lvl3":""}},
2339
- {"objectID":"51b6b861923c4ecf8410549bd73ebac7e465ba84aef90c9a499f86d45bd8225b","title":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","url":"/docs/development/testing","content":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI\n\nπŸŽ‰ Provider Testing Status\n\n44 providers supported β€” validated in CI where credentials are configured (unconfigured providers are skipped): OpenAI, Anthropic, Google AI, Google Vertex, AWS Bedrock, Azure OpenAI, Mistral, Hugging Face, Ollama, LiteLLM, AWS SageMaker, OpenAI-compatible, OpenRouter, DeepSeek, NVIDIA NIM, LM Studio, llama.cpp, TypeSafe Jev β€” plus voice (OpenAI TTS, ElevenLabs, Deepgram, Azure Speech, Google TTS/STT, Whisper, OpenAI Realtime, Gemini Live).\n\nQuick Provider Validation\n\nComprehensive Testing\n\nExpected Results\n\nCLI Enhancement Output:\n\nSDK Enhancement Output:\n\nProvider Testing\n\nGoogle AI Provider Validation\n\nOpenAI Provider Validation\n\nMulti-Provider Testing\n\nBackward Compatibility Testing\n\nEnsure No Breaking Changes\n\nTest Existing SDK Integration\n\nError Handling Testing\n\nInvalid Model Names\n\nMissing API Keys\n\nNetwork Issues\n\nPerformance Testing\n\nResponse Time Validation\n\nToken Counting Accuracy\n\nEnhancement Feature Validation\n\nAnalytics Data Completeness\n\nEvaluation Data Validation\n\nContext Flow Testing\n\nTroubleshooting Guide\n\nCommon Issues\nEmpty Responses from Google AI\nCheck model name in .env file\nUse gemini-2.5-pro instead of deprecated models\nVerify API key is valid\nNaN Token Counts\nUsually indicates provider API failure\nCheck model configuration and API keys\nTest with --debug flag for detailed logs\nEnhancement Data Missing\nEnsure using --debug flag to see enhancement output\nVerify enhancement flags are correctly specified\nCheck that provider is working (not falling back)\nCLI Commands Not Found\nRun npm run build:cli to rebuild CLI\nCheck that dist/cli/index.js exists\nVerify Node.js version compatibility\n\nDebug Commands\n\nTest Automation\n\nValidation Script Usage\n\nCI/CD Integration\n\nThis testing guide ensures all enhancement features work correctly while maintaining backward compatibility and providing clear troubleshooting guidance.","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"","lvl3":""}},
2340
- {"objectID":"4d9bb1de4ad3dfd116e55dc2d6b220825f5b43875d3fd78069496be8d856ff06","title":"πŸŽ‰ Provider Testing Status","url":"/docs/development/testing#-provider-testing-status","content":"44 providers supported β€” validated in CI where credentials are configured (unconfigured providers are skipped): OpenAI, Anthropic, Google AI, Google Vertex, AWS Bedrock, Azure OpenAI, Mistral, Hugging Face, Ollama, LiteLLM, AWS SageMaker, OpenAI-compatible, OpenRouter, DeepSeek, NVIDIA NIM, LM Studio, llama.cpp, TypeSafe Jev β€” plus voice (OpenAI TTS, ElevenLabs, Deepgram, Azure Speech, Google TTS/STT, Whisper, OpenAI Realtime, Gemini Live).","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"πŸŽ‰ Provider Testing Status","lvl3":""}},
2341
- {"objectID":"8fc0eade856296973641598d92d1d671410031324b34910f255b9daf62bbc200","title":"Quick Provider Validation","url":"/docs/development/testing#quick-provider-validation","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Quick Provider Validation","lvl3":""}},
2342
- {"objectID":"e522bb68d746cfa26559e2fe3c17775ecced454e5eb5b1672cc734c310a125aa","title":"Test any provider via the CLI","url":"/docs/development/testing#test-any-provider-via-the-cli","content":"pnpm cli generate \"test\" --provider openai\npnpm cli generate \"test\" --provider anthropic\npnpm cli generate \"test\" --provider google-ai\npnpm cli generate \"test\" --provider deepseek\npnpm cli generate \"test\" --provider nvidia-nim\npnpm cli generate \"test\" --provider lm-studio\npnpm cli generate \"test\" --provider llamacpp\npnpm cli generate \"test\" --provider azure\npnpm cli generate \"test\" --provider mistral\npnpm cli generate \"test\" --provider ollama\npnpm cli generate \"test\" --provider vertex","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test any provider via the CLI","lvl3":""}},
2343
- {"objectID":"8304dacf623fd9daa0ab9a22acb9078e123f9aa467efbddbbe074af13c2cdd7a","title":"Test with enhancements (any provider works)","url":"/docs/development/testing#test-with-enhancements-any-provider-works","content":"pnpm cli generate \"test\" --provider google-ai --enable-analytics --enable-evaluation --debug\n`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test with enhancements (any provider works)","lvl3":""}},
2344
- {"objectID":"962667c0956afc2243878258732206629fd012fb4cb4e266ca1cc92a76ec19ff","title":"Comprehensive Testing","url":"/docs/development/testing#comprehensive-testing","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Comprehensive Testing","lvl3":""}},
2345
- {"objectID":"2abd04954506b423a74683585841f9bb5def930dedf02265b11096a04f7206e8","title":"Run full validation suite","url":"/docs/development/testing#run-full-validation-suite","content":"./validate-fixes.sh","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Run full validation suite","lvl3":""}},
2346
- {"objectID":"c0b895cc1390ca0f55f528c530bfe7f242648eb4408ae0634ae626fd6fcddc85","title":"Run comprehensive CLI tests","url":"/docs/development/testing#run-comprehensive-cli-tests","content":"node CLICOMPREHENSIVETESTS.js","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Run comprehensive CLI tests","lvl3":""}},
2347
- {"objectID":"1444bf3290ae917bf6534b6e32f1f109f4451832b05c5743fa58efce2c979f7b","title":"Run before/after comparison","url":"/docs/development/testing#run-beforeafter-comparison","content":"node BEFOREAFTERCOMPARISON.js\n`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Run before/after comparison","lvl3":""}},
2348
- {"objectID":"08c576cff131fac374c1c3a4375497793b511d4a53730510268c77e78416c89c","title":"Google AI Provider Validation","url":"/docs/development/testing#google-ai-provider-validation","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Google AI Provider Validation","lvl3":""}},
2349
- {"objectID":"dbbd1df0dafb3c972c66761e7a286f29d6c648b6e9c5578051e634ad2e3401c7","title":"Test working model","url":"/docs/development/testing#test-working-model","content":"node ./dist/cli/index.js generate \"Hello\" --provider google-ai --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test working model","lvl3":""}},
2350
- {"objectID":"0216650963a9f582f523ec8c08f4fab7eb75ba4754d4ec751c1d8d9e6bfb400e","title":"Expected: No empty responses or fallbacks","url":"/docs/development/testing#expected-no-empty-responses-or-fallbacks","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Expected: No empty responses or fallbacks","lvl3":""}},
2351
- {"objectID":"13e82c8c22a2f7a24a2f34bc6d2183eb55ecff140bbd00ae93a892baaa9bd135","title":"OpenAI Provider Validation","url":"/docs/development/testing#openai-provider-validation","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"OpenAI Provider Validation","lvl3":""}},
2352
- {"objectID":"f03fd4d28918a7fd77dbac824938c702f1486b54448009be7671ddd21f42591b","title":"Test OpenAI fallback","url":"/docs/development/testing#test-openai-fallback","content":"node ./dist/cli/index.js generate \"Hello\" --provider openai --enable-analytics --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test OpenAI fallback","lvl3":""}},
2353
- {"objectID":"7de61b60e3aa538d051db0159fc80e3cbb63e4d0e4e04f37b6e801dad8a5f53f","title":"Expected: Accurate token counting (no NaN values)","url":"/docs/development/testing#expected-accurate-token-counting-no-nan-values","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Expected: Accurate token counting (no NaN values)","lvl3":""}},
2354
- {"objectID":"f33aaba473bdf45c26d05793d64b2496936048e97d7e18b4e7cd943a60fec0db","title":"Multi-Provider Testing","url":"/docs/development/testing#multi-provider-testing","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Multi-Provider Testing","lvl3":""}},
2355
- {"objectID":"3040499d040ec7a9763949d3a928959dcf5ac65b964393671e1449b704c14857","title":"Test provider auto-selection","url":"/docs/development/testing#test-provider-auto-selection","content":"node ./dist/cli/index.js generate \"Hello\" --enable-analytics --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test provider auto-selection","lvl3":""}},
2356
- {"objectID":"6fcbf2c32c2277f72918a7923d587cecc8cf1e24d899694c95a46e1c2c25a8cd","title":"Expected: Graceful fallback if primary provider fails","url":"/docs/development/testing#expected-graceful-fallback-if-primary-provider-fails","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Expected: Graceful fallback if primary provider fails","lvl3":""}},
2357
- {"objectID":"dbd1a1a8d7dc9ac0d259cdeef2ab1f7f5342e4e7d8c76def6624531e85139ac1","title":"Ensure No Breaking Changes","url":"/docs/development/testing#ensure-no-breaking-changes","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Ensure No Breaking Changes","lvl3":""}},
2358
- {"objectID":"03974bf1b097b8efb16b817e92ef49803eacd3d3e178b4a1aa07b45a1a4ac866","title":"Test existing CLI commands (no enhancement flags)","url":"/docs/development/testing#test-existing-cli-commands-no-enhancement-flags","content":"node ./dist/cli/index.js generate \"Simple test\"\nnode ./dist/cli/index.js generate \"Simple test\"\nnode ./dist/cli/index.js gen \"Simple test\"","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test existing CLI commands (no enhancement flags)","lvl3":""}},
2359
- {"objectID":"8fb36dbdf2d8b1b6eb3d7edcdc8304649093d7b7a6cf9da64944bc1932382b8d","title":"Expected: All existing functionality works","url":"/docs/development/testing#expected-all-existing-functionality-works","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Expected: All existing functionality works","lvl3":""}},
2360
- {"objectID":"a0cab3a3fc984cfbe3985ae09fe6e79f141999deddd7b70548cfa578e9051a34","title":"Invalid Model Names","url":"/docs/development/testing#invalid-model-names","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Invalid Model Names","lvl3":""}},
2361
- {"objectID":"c27b650b086910c0aeea0926a7081ace904ca5b4225d6a65de89c53f291e8484","title":"Test deprecated model handling","url":"/docs/development/testing#test-deprecated-model-handling","content":"node ./dist/cli/index.js generate \"test\" --provider google-ai --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test deprecated model handling","lvl3":""}},
2362
- {"objectID":"1012fab5a00e125facac7dd6150f09d516d8f6af8e942b1dcca53b81bceb0f40","title":"Expected: Clear error message or automatic correction","url":"/docs/development/testing#expected-clear-error-message-or-automatic-correction","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Expected: Clear error message or automatic correction","lvl3":""}},
2363
- {"objectID":"5ddd754a280b4b927eb3dc046a889c6532f10c54a985864fd8228bda0a9f92d4","title":"Missing API Keys","url":"/docs/development/testing#missing-api-keys","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Missing API Keys","lvl3":""}},
2364
- {"objectID":"ef41be5889fafebb18d04e1c630e4960538a9cb519889de44c5160c0b98213f7","title":"Test without API keys","url":"/docs/development/testing#test-without-api-keys","content":"unset GOOGLEAIAPI_KEY\nunset OPENAIAPIKEY\nnode ./dist/cli/index.js generate \"test\" --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test without API keys","lvl3":""}},
2365
- {"objectID":"3e6ecdfc6fc0f3b6fbc2b555bc4872547b558fca8f46928ad51cd5439dde5dd4","title":"Expected: Helpful setup instructions","url":"/docs/development/testing#expected-helpful-setup-instructions","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Expected: Helpful setup instructions","lvl3":""}},
2366
- {"objectID":"6f84c9acd43c65eed6e126ecb28707eac9dbf9d2251aa495da657c84519144ac","title":"Network Issues","url":"/docs/development/testing#network-issues","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Network Issues","lvl3":""}},
2367
- {"objectID":"535fb979e4072fd5943718b60f942cfe2581e59d94f02bf0ab3f9c5296aed133","title":"Test with invalid API endpoint (simulated)","url":"/docs/development/testing#test-with-invalid-api-endpoint-simulated","content":"node ./dist/cli/index.js generate \"test\" --timeout 5s --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test with invalid API endpoint (simulated)","lvl3":""}},
2368
- {"objectID":"4a4ddc7e1ba7da05e8ac247d462c74e1d4796c47ca815b27edd6210911545a66","title":"Expected: Fallback to other providers if available","url":"/docs/development/testing#expected-fallback-to-other-providers-if-available","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Expected: Fallback to other providers if available","lvl3":""}},
2369
- {"objectID":"732e97053310081527b3956475ec8f9543528f27634cb9a9437be97491fc022e","title":"Response Time Validation","url":"/docs/development/testing#response-time-validation","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Response Time Validation","lvl3":""}},
2370
- {"objectID":"83436dd951e6c29193b97a7214bf39e68bba4321e298f87657bd15499ff55728","title":"Test response times with analytics","url":"/docs/development/testing#test-response-times-with-analytics","content":"node ./dist/cli/index.js generate \"Short prompt\" --enable-analytics --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test response times with analytics","lvl3":""}},
2371
- {"objectID":"54a5273f2a0a118c577477cba7fa9d269a1f8bb310d8094e136c6392808b60ee","title":"Expected: Analytics data doesn't significantly slow requests","url":"/docs/development/testing#expected-analytics-data-doesnt-significantly-slow-requests","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Expected: Analytics data doesn't significantly slow requests","lvl3":""}},
2372
- {"objectID":"e5a5c046c23621ae139301e8c65dd604dc84439b8e7b885e3334496a1056537c","title":"Token Counting Accuracy","url":"/docs/development/testing#token-counting-accuracy","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Token Counting Accuracy","lvl3":""}},
2373
- {"objectID":"ccd90219360ecc36f15b0643eba076beb6ece97d47df2e726c02d5551923af2f","title":"Test accurate token counting","url":"/docs/development/testing#test-accurate-token-counting","content":"node ./dist/cli/index.js generate \"This is a test prompt for token counting\" --enable-analytics --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test accurate token counting","lvl3":""}},
2374
- {"objectID":"33c361903e5d2155aee10120ed991aaf5c4ebc49b12169c7ffeb49e51b659acf","title":"Expected: Token counts match actual usage","url":"/docs/development/testing#expected-token-counts-match-actual-usage","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Expected: Token counts match actual usage","lvl3":""}},
2375
- {"objectID":"b879714c080fe2a85b50539fb224809866bec0b5ae9df829069f821f3356d017","title":"Analytics Data Completeness","url":"/docs/development/testing#analytics-data-completeness","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Analytics Data Completeness","lvl3":""}},
2376
- {"objectID":"ab64c1128474c05c7de4a45c9d0206d74b008e7e99e3de844bbb54a021289d3e","title":"Test analytics data structure","url":"/docs/development/testing#test-analytics-data-structure","content":"node ./dist/cli/index.js generate \"Business email\" --enable-analytics --context '{\"project\":\"test\"}' --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test analytics data structure","lvl3":""}},
2377
- {"objectID":"f785281351d1476ace01b4412ce6621b8a6e47dc55e1f7263e647a4fa5ddc580","title":"- timestamp: ISO string","url":"/docs/development/testing#--timestamp-iso-string","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"- timestamp: ISO string","lvl3":""}},
2378
- {"objectID":"83e222546aabbdc6c7bc9f23c5d11b80d63b2b7fef71fcbe3ea2093f44cfb7d8","title":"Evaluation Data Validation","url":"/docs/development/testing#evaluation-data-validation","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Evaluation Data Validation","lvl3":""}},
2379
- {"objectID":"cb4404c5157f480b12911f00292e0578971e88becf2998f836a5f86f2e82139c","title":"Test evaluation scoring","url":"/docs/development/testing#test-evaluation-scoring","content":"node ./dist/cli/index.js generate \"Explain quantum physics\" --enable-evaluation --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test evaluation scoring","lvl3":""}},
2380
- {"objectID":"ab73a02c6fd432b8740d1624770287217547ab7d9cea1f53080f9611db83937b","title":"- evaluationTime: number","url":"/docs/development/testing#--evaluationtime-number","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"- evaluationTime: number","lvl3":""}},
2381
- {"objectID":"a762e4c091d9b3e54bd2a51a4cdf02851c6636cae857996467d2a9437ec085a2","title":"Context Flow Testing","url":"/docs/development/testing#context-flow-testing","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Context Flow Testing","lvl3":""}},
2382
- {"objectID":"d7eb0273fcdf438807e6ad66b71d1b1511436d60f50712f7246d76e3a4441865","title":"Test context preservation","url":"/docs/development/testing#test-context-preservation","content":"node ./dist/cli/index.js generate \"Help with task\" --context '{\"userId\":\"123\",\"department\":\"sales\"}' --enable-analytics --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test context preservation","lvl3":""}},
2383
- {"objectID":"f4d4540747aa848513d17bd416fc18287b535713ed1a03fbce8f311b4fe6bdf6","title":"Expected: Context available throughout request chain","url":"/docs/development/testing#expected-context-available-throughout-request-chain","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Expected: Context available throughout request chain","lvl3":""}},
2384
- {"objectID":"19720de4c8ed35a547ab099355e2fd5175800e0930b25b1d218940db0baf60f1","title":"Common Issues","url":"/docs/development/testing#common-issues","content":"Empty Responses from Google AI\nCheck model name in .env file\nUse gemini-2.5-pro instead of deprecated models\nVerify API key is valid\nNaN Token Counts\nUsually indicates provider API failure\nCheck model configuration and API keys\nTest with --debug flag for detailed logs\nEnhancement Data Missing\nEnsure using --debug flag to see enhancement output\nVerify enhancement flags are correctly specified\nCheck that provider is working (not falling back)\nCLI Commands Not Found\nRun npm run build:cli to rebuild CLI\nCheck that dist/cli/index.js exists\nVerify Node.js version compatibility","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Common Issues","lvl3":""}},
2385
- {"objectID":"66eea4e65b778a0521203afbc43ff698e78df2a376ad66427ac83c227d77c081","title":"Debug Commands","url":"/docs/development/testing#debug-commands","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Debug Commands","lvl3":""}},
2386
- {"objectID":"67d89ab41aec29dc1893e5e5fc6f086c5b1b31a95c6b6aa40677d932d03c9594","title":"Comprehensive debug information","url":"/docs/development/testing#comprehensive-debug-information","content":"node ./dist/cli/index.js generate \"debug test\" --provider google-ai --enable-analytics --enable-evaluation --context '{\"debug\":true}' --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Comprehensive debug information","lvl3":""}},
2387
- {"objectID":"d6a5b4654b0448dc17e98a0644da6c0251088520c2b778bd1b2fcf5169c5abd5","title":"Check provider status","url":"/docs/development/testing#check-provider-status","content":"node ./dist/cli/index.js status","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Check provider status","lvl3":""}},
2388
- {"objectID":"da0c759ab4959c695f7ba6d3682869e4b64af5010353fe3dfbcfed51eedec072","title":"Test specific provider","url":"/docs/development/testing#test-specific-provider","content":"node ./dist/cli/index.js generate \"provider test\" --provider openai --debug\n`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Test specific provider","lvl3":""}},
2389
- {"objectID":"5b50f79d5e15b3b0476213bafa40c4be8a431bdd409be9330906e070ad72fb52","title":"Validation Script Usage","url":"/docs/development/testing#validation-script-usage","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Validation Script Usage","lvl3":""}},
2390
- {"objectID":"838736a3fa982ded222301f415ca1ecc28a8bd1b718e40878f35ec514a555c23","title":"Run complete validation suite","url":"/docs/development/testing#run-complete-validation-suite","content":"./validate-fixes.sh","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Run complete validation suite","lvl3":""}},
2391
- {"objectID":"489bc8592279699a24f5d95b3f635c1f1f30a8310b3d5d247e1f3109c6228d23","title":"Run specific test categories","url":"/docs/development/testing#run-specific-test-categories","content":"./validate-fixes.sh --cli-only\n./validate-fixes.sh --sdk-only\n./validate-fixes.sh --providers-only\n`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Run specific test categories","lvl3":""}},
2392
- {"objectID":"b9d3b2dedf68c9fecf0095380d37100ad6f63a1a5b4166af3428764814c5a2e4","title":"CI/CD Integration","url":"/docs/development/testing#cicd-integration","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"CI/CD Integration","lvl3":""}},
2393
- {"objectID":"8914e25e0d42823489948b21e26bde8f722750852c2514cf994cdc6e6b720611","title":"Add to CI pipeline","url":"/docs/development/testing#add-to-ci-pipeline","content":"npm run test\nnpm run build:cli\n./validate-fixes.sh --ci-mode\n`\n\nThis testing guide ensures all enhancement features work correctly while maintaining backward compatibility and providing clear troubleshooting guidance.","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 40 Providers, Validated in CI","lvl2":"Add to CI pipeline","lvl3":""}},
2339
+ {"objectID":"51b6b861923c4ecf8410549bd73ebac7e465ba84aef90c9a499f86d45bd8225b","title":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","url":"/docs/development/testing","content":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI\n\nπŸŽ‰ Provider Testing Status\n\n44 providers supported β€” validated in CI where credentials are configured (unconfigured providers are skipped): OpenAI, Anthropic, Google AI, Google Vertex, AWS Bedrock, Azure OpenAI, Mistral, Hugging Face, Ollama, LiteLLM, AWS SageMaker, OpenAI-compatible, OpenRouter, DeepSeek, NVIDIA NIM, LM Studio, llama.cpp, TypeSafe Jev β€” plus voice (OpenAI TTS, ElevenLabs, Deepgram, Azure Speech, Google TTS/STT, Whisper, OpenAI Realtime, Gemini Live).\n\nQuick Provider Validation\n\nComprehensive Testing\n\nExpected Results\n\nCLI Enhancement Output:\n\nSDK Enhancement Output:\n\nProvider Testing\n\nGoogle AI Provider Validation\n\nOpenAI Provider Validation\n\nMulti-Provider Testing\n\nBackward Compatibility Testing\n\nEnsure No Breaking Changes\n\nTest Existing SDK Integration\n\nError Handling Testing\n\nInvalid Model Names\n\nMissing API Keys\n\nNetwork Issues\n\nPerformance Testing\n\nResponse Time Validation\n\nToken Counting Accuracy\n\nEnhancement Feature Validation\n\nAnalytics Data Completeness\n\nEvaluation Data Validation\n\nContext Flow Testing\n\nTroubleshooting Guide\n\nCommon Issues\nEmpty Responses from Google AI\nCheck model name in .env file\nUse gemini-2.5-pro instead of deprecated models\nVerify API key is valid\nNaN Token Counts\nUsually indicates provider API failure\nCheck model configuration and API keys\nTest with --debug flag for detailed logs\nEnhancement Data Missing\nEnsure using --debug flag to see enhancement output\nVerify enhancement flags are correctly specified\nCheck that provider is working (not falling back)\nCLI Commands Not Found\nRun npm run build:cli to rebuild CLI\nCheck that dist/cli/index.js exists\nVerify Node.js version compatibility\n\nDebug Commands\n\nTest Automation\n\nValidation Script Usage\n\nCI/CD Integration\n\nThis testing guide ensures all enhancement features work correctly while maintaining backward compatibility and providing clear troubleshooting guidance.","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"","lvl3":""}},
2340
+ {"objectID":"4d9bb1de4ad3dfd116e55dc2d6b220825f5b43875d3fd78069496be8d856ff06","title":"πŸŽ‰ Provider Testing Status","url":"/docs/development/testing#-provider-testing-status","content":"44 providers supported β€” validated in CI where credentials are configured (unconfigured providers are skipped): OpenAI, Anthropic, Google AI, Google Vertex, AWS Bedrock, Azure OpenAI, Mistral, Hugging Face, Ollama, LiteLLM, AWS SageMaker, OpenAI-compatible, OpenRouter, DeepSeek, NVIDIA NIM, LM Studio, llama.cpp, TypeSafe Jev β€” plus voice (OpenAI TTS, ElevenLabs, Deepgram, Azure Speech, Google TTS/STT, Whisper, OpenAI Realtime, Gemini Live).","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"πŸŽ‰ Provider Testing Status","lvl3":""}},
2341
+ {"objectID":"8fc0eade856296973641598d92d1d671410031324b34910f255b9daf62bbc200","title":"Quick Provider Validation","url":"/docs/development/testing#quick-provider-validation","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Quick Provider Validation","lvl3":""}},
2342
+ {"objectID":"e522bb68d746cfa26559e2fe3c17775ecced454e5eb5b1672cc734c310a125aa","title":"Test any provider via the CLI","url":"/docs/development/testing#test-any-provider-via-the-cli","content":"pnpm cli generate \"test\" --provider openai\npnpm cli generate \"test\" --provider anthropic\npnpm cli generate \"test\" --provider google-ai\npnpm cli generate \"test\" --provider deepseek\npnpm cli generate \"test\" --provider nvidia-nim\npnpm cli generate \"test\" --provider lm-studio\npnpm cli generate \"test\" --provider llamacpp\npnpm cli generate \"test\" --provider azure\npnpm cli generate \"test\" --provider mistral\npnpm cli generate \"test\" --provider ollama\npnpm cli generate \"test\" --provider vertex","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test any provider via the CLI","lvl3":""}},
2343
+ {"objectID":"8304dacf623fd9daa0ab9a22acb9078e123f9aa467efbddbbe074af13c2cdd7a","title":"Test with enhancements (any provider works)","url":"/docs/development/testing#test-with-enhancements-any-provider-works","content":"pnpm cli generate \"test\" --provider google-ai --enable-analytics --enable-evaluation --debug\n`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test with enhancements (any provider works)","lvl3":""}},
2344
+ {"objectID":"962667c0956afc2243878258732206629fd012fb4cb4e266ca1cc92a76ec19ff","title":"Comprehensive Testing","url":"/docs/development/testing#comprehensive-testing","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Comprehensive Testing","lvl3":""}},
2345
+ {"objectID":"2abd04954506b423a74683585841f9bb5def930dedf02265b11096a04f7206e8","title":"Run full validation suite","url":"/docs/development/testing#run-full-validation-suite","content":"./validate-fixes.sh","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Run full validation suite","lvl3":""}},
2346
+ {"objectID":"c0b895cc1390ca0f55f528c530bfe7f242648eb4408ae0634ae626fd6fcddc85","title":"Run comprehensive CLI tests","url":"/docs/development/testing#run-comprehensive-cli-tests","content":"node CLICOMPREHENSIVETESTS.js","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Run comprehensive CLI tests","lvl3":""}},
2347
+ {"objectID":"1444bf3290ae917bf6534b6e32f1f109f4451832b05c5743fa58efce2c979f7b","title":"Run before/after comparison","url":"/docs/development/testing#run-beforeafter-comparison","content":"node BEFOREAFTERCOMPARISON.js\n`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Run before/after comparison","lvl3":""}},
2348
+ {"objectID":"08c576cff131fac374c1c3a4375497793b511d4a53730510268c77e78416c89c","title":"Google AI Provider Validation","url":"/docs/development/testing#google-ai-provider-validation","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Google AI Provider Validation","lvl3":""}},
2349
+ {"objectID":"dbbd1df0dafb3c972c66761e7a286f29d6c648b6e9c5578051e634ad2e3401c7","title":"Test working model","url":"/docs/development/testing#test-working-model","content":"node ./dist/cli/index.js generate \"Hello\" --provider google-ai --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test working model","lvl3":""}},
2350
+ {"objectID":"0216650963a9f582f523ec8c08f4fab7eb75ba4754d4ec751c1d8d9e6bfb400e","title":"Expected: No empty responses or fallbacks","url":"/docs/development/testing#expected-no-empty-responses-or-fallbacks","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Expected: No empty responses or fallbacks","lvl3":""}},
2351
+ {"objectID":"13e82c8c22a2f7a24a2f34bc6d2183eb55ecff140bbd00ae93a892baaa9bd135","title":"OpenAI Provider Validation","url":"/docs/development/testing#openai-provider-validation","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"OpenAI Provider Validation","lvl3":""}},
2352
+ {"objectID":"f03fd4d28918a7fd77dbac824938c702f1486b54448009be7671ddd21f42591b","title":"Test OpenAI fallback","url":"/docs/development/testing#test-openai-fallback","content":"node ./dist/cli/index.js generate \"Hello\" --provider openai --enable-analytics --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test OpenAI fallback","lvl3":""}},
2353
+ {"objectID":"7de61b60e3aa538d051db0159fc80e3cbb63e4d0e4e04f37b6e801dad8a5f53f","title":"Expected: Accurate token counting (no NaN values)","url":"/docs/development/testing#expected-accurate-token-counting-no-nan-values","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Expected: Accurate token counting (no NaN values)","lvl3":""}},
2354
+ {"objectID":"f33aaba473bdf45c26d05793d64b2496936048e97d7e18b4e7cd943a60fec0db","title":"Multi-Provider Testing","url":"/docs/development/testing#multi-provider-testing","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Multi-Provider Testing","lvl3":""}},
2355
+ {"objectID":"3040499d040ec7a9763949d3a928959dcf5ac65b964393671e1449b704c14857","title":"Test provider auto-selection","url":"/docs/development/testing#test-provider-auto-selection","content":"node ./dist/cli/index.js generate \"Hello\" --enable-analytics --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test provider auto-selection","lvl3":""}},
2356
+ {"objectID":"6fcbf2c32c2277f72918a7923d587cecc8cf1e24d899694c95a46e1c2c25a8cd","title":"Expected: Graceful fallback if primary provider fails","url":"/docs/development/testing#expected-graceful-fallback-if-primary-provider-fails","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Expected: Graceful fallback if primary provider fails","lvl3":""}},
2357
+ {"objectID":"dbd1a1a8d7dc9ac0d259cdeef2ab1f7f5342e4e7d8c76def6624531e85139ac1","title":"Ensure No Breaking Changes","url":"/docs/development/testing#ensure-no-breaking-changes","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Ensure No Breaking Changes","lvl3":""}},
2358
+ {"objectID":"03974bf1b097b8efb16b817e92ef49803eacd3d3e178b4a1aa07b45a1a4ac866","title":"Test existing CLI commands (no enhancement flags)","url":"/docs/development/testing#test-existing-cli-commands-no-enhancement-flags","content":"node ./dist/cli/index.js generate \"Simple test\"\nnode ./dist/cli/index.js generate \"Simple test\"\nnode ./dist/cli/index.js gen \"Simple test\"","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test existing CLI commands (no enhancement flags)","lvl3":""}},
2359
+ {"objectID":"8fb36dbdf2d8b1b6eb3d7edcdc8304649093d7b7a6cf9da64944bc1932382b8d","title":"Expected: All existing functionality works","url":"/docs/development/testing#expected-all-existing-functionality-works","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Expected: All existing functionality works","lvl3":""}},
2360
+ {"objectID":"a0cab3a3fc984cfbe3985ae09fe6e79f141999deddd7b70548cfa578e9051a34","title":"Invalid Model Names","url":"/docs/development/testing#invalid-model-names","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Invalid Model Names","lvl3":""}},
2361
+ {"objectID":"c27b650b086910c0aeea0926a7081ace904ca5b4225d6a65de89c53f291e8484","title":"Test deprecated model handling","url":"/docs/development/testing#test-deprecated-model-handling","content":"node ./dist/cli/index.js generate \"test\" --provider google-ai --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test deprecated model handling","lvl3":""}},
2362
+ {"objectID":"1012fab5a00e125facac7dd6150f09d516d8f6af8e942b1dcca53b81bceb0f40","title":"Expected: Clear error message or automatic correction","url":"/docs/development/testing#expected-clear-error-message-or-automatic-correction","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Expected: Clear error message or automatic correction","lvl3":""}},
2363
+ {"objectID":"5ddd754a280b4b927eb3dc046a889c6532f10c54a985864fd8228bda0a9f92d4","title":"Missing API Keys","url":"/docs/development/testing#missing-api-keys","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Missing API Keys","lvl3":""}},
2364
+ {"objectID":"ef41be5889fafebb18d04e1c630e4960538a9cb519889de44c5160c0b98213f7","title":"Test without API keys","url":"/docs/development/testing#test-without-api-keys","content":"unset GOOGLEAIAPI_KEY\nunset OPENAIAPIKEY\nnode ./dist/cli/index.js generate \"test\" --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test without API keys","lvl3":""}},
2365
+ {"objectID":"3e6ecdfc6fc0f3b6fbc2b555bc4872547b558fca8f46928ad51cd5439dde5dd4","title":"Expected: Helpful setup instructions","url":"/docs/development/testing#expected-helpful-setup-instructions","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Expected: Helpful setup instructions","lvl3":""}},
2366
+ {"objectID":"6f84c9acd43c65eed6e126ecb28707eac9dbf9d2251aa495da657c84519144ac","title":"Network Issues","url":"/docs/development/testing#network-issues","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Network Issues","lvl3":""}},
2367
+ {"objectID":"535fb979e4072fd5943718b60f942cfe2581e59d94f02bf0ab3f9c5296aed133","title":"Test with invalid API endpoint (simulated)","url":"/docs/development/testing#test-with-invalid-api-endpoint-simulated","content":"node ./dist/cli/index.js generate \"test\" --timeout 5s --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test with invalid API endpoint (simulated)","lvl3":""}},
2368
+ {"objectID":"4a4ddc7e1ba7da05e8ac247d462c74e1d4796c47ca815b27edd6210911545a66","title":"Expected: Fallback to other providers if available","url":"/docs/development/testing#expected-fallback-to-other-providers-if-available","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Expected: Fallback to other providers if available","lvl3":""}},
2369
+ {"objectID":"732e97053310081527b3956475ec8f9543528f27634cb9a9437be97491fc022e","title":"Response Time Validation","url":"/docs/development/testing#response-time-validation","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Response Time Validation","lvl3":""}},
2370
+ {"objectID":"83436dd951e6c29193b97a7214bf39e68bba4321e298f87657bd15499ff55728","title":"Test response times with analytics","url":"/docs/development/testing#test-response-times-with-analytics","content":"node ./dist/cli/index.js generate \"Short prompt\" --enable-analytics --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test response times with analytics","lvl3":""}},
2371
+ {"objectID":"54a5273f2a0a118c577477cba7fa9d269a1f8bb310d8094e136c6392808b60ee","title":"Expected: Analytics data doesn't significantly slow requests","url":"/docs/development/testing#expected-analytics-data-doesnt-significantly-slow-requests","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Expected: Analytics data doesn't significantly slow requests","lvl3":""}},
2372
+ {"objectID":"e5a5c046c23621ae139301e8c65dd604dc84439b8e7b885e3334496a1056537c","title":"Token Counting Accuracy","url":"/docs/development/testing#token-counting-accuracy","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Token Counting Accuracy","lvl3":""}},
2373
+ {"objectID":"ccd90219360ecc36f15b0643eba076beb6ece97d47df2e726c02d5551923af2f","title":"Test accurate token counting","url":"/docs/development/testing#test-accurate-token-counting","content":"node ./dist/cli/index.js generate \"This is a test prompt for token counting\" --enable-analytics --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test accurate token counting","lvl3":""}},
2374
+ {"objectID":"33c361903e5d2155aee10120ed991aaf5c4ebc49b12169c7ffeb49e51b659acf","title":"Expected: Token counts match actual usage","url":"/docs/development/testing#expected-token-counts-match-actual-usage","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Expected: Token counts match actual usage","lvl3":""}},
2375
+ {"objectID":"b879714c080fe2a85b50539fb224809866bec0b5ae9df829069f821f3356d017","title":"Analytics Data Completeness","url":"/docs/development/testing#analytics-data-completeness","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Analytics Data Completeness","lvl3":""}},
2376
+ {"objectID":"ab64c1128474c05c7de4a45c9d0206d74b008e7e99e3de844bbb54a021289d3e","title":"Test analytics data structure","url":"/docs/development/testing#test-analytics-data-structure","content":"node ./dist/cli/index.js generate \"Business email\" --enable-analytics --context '{\"project\":\"test\"}' --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test analytics data structure","lvl3":""}},
2377
+ {"objectID":"f785281351d1476ace01b4412ce6621b8a6e47dc55e1f7263e647a4fa5ddc580","title":"- timestamp: ISO string","url":"/docs/development/testing#--timestamp-iso-string","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"- timestamp: ISO string","lvl3":""}},
2378
+ {"objectID":"83e222546aabbdc6c7bc9f23c5d11b80d63b2b7fef71fcbe3ea2093f44cfb7d8","title":"Evaluation Data Validation","url":"/docs/development/testing#evaluation-data-validation","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Evaluation Data Validation","lvl3":""}},
2379
+ {"objectID":"cb4404c5157f480b12911f00292e0578971e88becf2998f836a5f86f2e82139c","title":"Test evaluation scoring","url":"/docs/development/testing#test-evaluation-scoring","content":"node ./dist/cli/index.js generate \"Explain quantum physics\" --enable-evaluation --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test evaluation scoring","lvl3":""}},
2380
+ {"objectID":"ab73a02c6fd432b8740d1624770287217547ab7d9cea1f53080f9611db83937b","title":"- evaluationTime: number","url":"/docs/development/testing#--evaluationtime-number","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"- evaluationTime: number","lvl3":""}},
2381
+ {"objectID":"a762e4c091d9b3e54bd2a51a4cdf02851c6636cae857996467d2a9437ec085a2","title":"Context Flow Testing","url":"/docs/development/testing#context-flow-testing","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Context Flow Testing","lvl3":""}},
2382
+ {"objectID":"d7eb0273fcdf438807e6ad66b71d1b1511436d60f50712f7246d76e3a4441865","title":"Test context preservation","url":"/docs/development/testing#test-context-preservation","content":"node ./dist/cli/index.js generate \"Help with task\" --context '{\"userId\":\"123\",\"department\":\"sales\"}' --enable-analytics --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test context preservation","lvl3":""}},
2383
+ {"objectID":"f4d4540747aa848513d17bd416fc18287b535713ed1a03fbce8f311b4fe6bdf6","title":"Expected: Context available throughout request chain","url":"/docs/development/testing#expected-context-available-throughout-request-chain","content":"`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Expected: Context available throughout request chain","lvl3":""}},
2384
+ {"objectID":"19720de4c8ed35a547ab099355e2fd5175800e0930b25b1d218940db0baf60f1","title":"Common Issues","url":"/docs/development/testing#common-issues","content":"Empty Responses from Google AI\nCheck model name in .env file\nUse gemini-2.5-pro instead of deprecated models\nVerify API key is valid\nNaN Token Counts\nUsually indicates provider API failure\nCheck model configuration and API keys\nTest with --debug flag for detailed logs\nEnhancement Data Missing\nEnsure using --debug flag to see enhancement output\nVerify enhancement flags are correctly specified\nCheck that provider is working (not falling back)\nCLI Commands Not Found\nRun npm run build:cli to rebuild CLI\nCheck that dist/cli/index.js exists\nVerify Node.js version compatibility","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Common Issues","lvl3":""}},
2385
+ {"objectID":"66eea4e65b778a0521203afbc43ff698e78df2a376ad66427ac83c227d77c081","title":"Debug Commands","url":"/docs/development/testing#debug-commands","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Debug Commands","lvl3":""}},
2386
+ {"objectID":"67d89ab41aec29dc1893e5e5fc6f086c5b1b31a95c6b6aa40677d932d03c9594","title":"Comprehensive debug information","url":"/docs/development/testing#comprehensive-debug-information","content":"node ./dist/cli/index.js generate \"debug test\" --provider google-ai --enable-analytics --enable-evaluation --context '{\"debug\":true}' --debug","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Comprehensive debug information","lvl3":""}},
2387
+ {"objectID":"d6a5b4654b0448dc17e98a0644da6c0251088520c2b778bd1b2fcf5169c5abd5","title":"Check provider status","url":"/docs/development/testing#check-provider-status","content":"node ./dist/cli/index.js status","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Check provider status","lvl3":""}},
2388
+ {"objectID":"da0c759ab4959c695f7ba6d3682869e4b64af5010353fe3dfbcfed51eedec072","title":"Test specific provider","url":"/docs/development/testing#test-specific-provider","content":"node ./dist/cli/index.js generate \"provider test\" --provider openai --debug\n`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Test specific provider","lvl3":""}},
2389
+ {"objectID":"5b50f79d5e15b3b0476213bafa40c4be8a431bdd409be9330906e070ad72fb52","title":"Validation Script Usage","url":"/docs/development/testing#validation-script-usage","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Validation Script Usage","lvl3":""}},
2390
+ {"objectID":"838736a3fa982ded222301f415ca1ecc28a8bd1b718e40878f35ec514a555c23","title":"Run complete validation suite","url":"/docs/development/testing#run-complete-validation-suite","content":"./validate-fixes.sh","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Run complete validation suite","lvl3":""}},
2391
+ {"objectID":"489bc8592279699a24f5d95b3f635c1f1f30a8310b3d5d247e1f3109c6228d23","title":"Run specific test categories","url":"/docs/development/testing#run-specific-test-categories","content":"./validate-fixes.sh --cli-only\n./validate-fixes.sh --sdk-only\n./validate-fixes.sh --providers-only\n`","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Run specific test categories","lvl3":""}},
2392
+ {"objectID":"b9d3b2dedf68c9fecf0095380d37100ad6f63a1a5b4166af3428764814c5a2e4","title":"CI/CD Integration","url":"/docs/development/testing#cicd-integration","content":"`bash","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"CI/CD Integration","lvl3":""}},
2393
+ {"objectID":"8914e25e0d42823489948b21e26bde8f722750852c2514cf994cdc6e6b720611","title":"Add to CI pipeline","url":"/docs/development/testing#add-to-ci-pipeline","content":"npm run test\nnpm run build:cli\n./validate-fixes.sh --ci-mode\n`\n\nThis testing guide ensures all enhancement features work correctly while maintaining backward compatibility and providing clear troubleshooting guidance.","hierarchy":{"lvl0":"Development","lvl1":"πŸ§ͺ NeuroLink Testing Guide β€” 44 Providers, Validated in CI","lvl2":"Add to CI pipeline","lvl3":""}},
2394
2394
  {"objectID":"6e38e7480932000ddf9ecf61ffb29cd5ba0b87e39894e3871a18a9f6f8dc5524","title":"Documentation Versioning","url":"/docs/development/versioning","content":"Documentation Versioning\n\nManaging documentation versions across releases using mike\n\nOverview\n\nNeuroLink documentation uses mike to maintain multiple versions of documentation for different releases. This allows users to view documentation for the specific version they're using.\n\nBenefits\nVersion-specific docs: Users can view docs matching their installed version\nPreserved history: Old versions remain accessible\nEasy switching: Version selector in navigation\nAutomated deployment: Integrate with CI/CD for automatic publishing\n\nSetup\nInstall Dependencies\nVerify Configuration\n\nThe mkdocs.yml already includes mike configuration:\n\nLocal Usage\n\nCreate First Version\n\nDeploy New Version\n\nList All Versions\n\nOutput:\n\nServe Versioned Docs Locally\n\nVisit http://localhost:8000 to test version switching.\n\nDelete a Version\n\nVersion Management Workflow\n\nFor Minor Releases (1.0 β†’ 1.1)\n\nFor Major Releases (1.x β†’ 2.0)\n\nFor Patch Releases (1.0.0 β†’ 1.0.1)\n\nCI/CD Integration\n\nGitHub Actions Workflow\n\nCreate .github/workflows/docs.yml:\n\nAutomatic Version Detection\n\nBest Practices\nVersion Naming\nStable releases: 1.0, 1.1, 2.0 (match npm version)\nPre-releases: 1.0-beta, 2.0-rc1\nDevelopment: dev (always latest from main branch)\nAlias Strategy\nVersion Cleanup\nDocumentation Updates\n\nFor bug fixes to old versions:\n\nAdvanced Configuration\n\nCustom Version Selector\n\nAdd to mkdocs.yml:\n\nVersion Warnings\n\nAdd version-specific warnings in docs/index.md:\n\nTroubleshooting\n\nIssue: \"gh-pages branch not found\"\n\nIssue: Version selector not appearing\n\nVerify mike is installed:\n\nCheck mkdocs.yml configuration:\n\nIssue: Wrong default version\n\nVersion History\n\n| Version | Release Date | Status | Notes |\n| ------- | ---------------- | -------------- | --------------------- |\n| 7.47.x | Current | βœ… Active | Latest features |\n| 7.46.x | 2024-12 | βœ… Active | Previous stable |\n| 7.45.x | 2024-11 | ⚠️ Old | Security updates only |\n| < 7.45 | 2024 and earlier | ❌ Unsupported | Upgrade recommended |\n\nRelated Documentation\nContributing - How to contribute documentation\nDevelopment Setup - Local development environment\nArchitecture - Documentation structure\n\nAdditional Resources\nmike Documentation - Official mike guide\nMkDocs Material Versioning - Material theme versioning\nGitHub Pages - Hosting documentation","hierarchy":{"lvl0":"Development","lvl1":"Documentation Versioning","lvl2":"","lvl3":""}},
2395
2395
  {"objectID":"e93b7f831e0fae0433eba697498889c8d09b69aecf3fbf3eda30c0965c348afa","title":"Documentation Versioning","url":"/docs/development/versioning#documentation-versioning","content":"Managing documentation versions across releases using mike","hierarchy":{"lvl0":"Development","lvl1":"Documentation Versioning","lvl2":"Documentation Versioning","lvl3":""}},
2396
2396
  {"objectID":"9cd60208b8c84605e89660a919d9094bb8345ba244f95c376d65305ad8e80ea3","title":"Overview","url":"/docs/development/versioning#overview","content":"NeuroLink documentation uses mike to maintain multiple versions of documentation for different releases. This allows users to view documentation for the specific version they're using.","hierarchy":{"lvl0":"Development","lvl1":"Documentation Versioning","lvl2":"Overview","lvl3":""}},
@@ -4412,11 +4412,11 @@
4412
4412
  {"objectID":"b802832537c22912fff88f6ef9ed79b85fd26dc3b69b61b0a52eb261feff8297","title":"Common Errors","url":"/docs/features/streaming#common-errors","content":"| Error | Cause | Solution |\n| ------------------------- | ------------------------------------------ | --------------------------------------------------- |\n| SESSION_BUDGET_EXCEEDED | Session cost exceeded maxBudgetUsd limit | Increase budget or start a new session |\n| PROVIDER_AUTH_ERROR | Missing or invalid API key | Set the provider's API key environment variable |\n| TIMEOUT | Request exceeded timeout | Increase timeout or use abortSignal for control |\n| MODEL_NOT_FOUND | Invalid model name | Check provider docs for supported model names |","hierarchy":{"lvl0":"Features","lvl1":"Streaming Guide","lvl2":"Common Errors","lvl3":""}},
4413
4413
  {"objectID":"1949a330d8bfb85ec15c527f519bf4eefb0b571f2db1027d8d568edd39986091","title":"Provider Support","url":"/docs/features/streaming#provider-support","content":"All NeuroLink providers support streaming:\n\n| Provider | Streaming | Notes |\n| ----------------- | --------- | ----------------------------------------------------------- |\n| OpenAI | Yes | Full streaming with tool support |\n| Anthropic | Yes | Full streaming with tool support |\n| Google AI Studio | Yes | Full streaming with tool support |\n| Google Vertex AI | Yes | Full streaming with tool support |\n| Amazon Bedrock | Yes | Full streaming with tool support |\n| Azure OpenAI | Yes | Full streaming with tool support |\n| Mistral | Yes | Full streaming with tool support |\n| LiteLLM | Yes | Full streaming; tool support depends on underlying model |\n| Ollama | Yes | Full streaming; tool support depends on model |\n| Hugging Face | Yes | Streaming support; tool support varies by model |\n| Amazon SageMaker | Limited | Falls back to fake streaming (generate then emit as chunks) |\n| OpenAI-Compatible | Yes | Depends on the endpoint's streaming support |\n\nWhen real streaming is not available for a provider or model, NeuroLink transparently falls back to \"fake streaming\" -- it generates the full response and then emits it as chunks. Your consuming code does not need to change.","hierarchy":{"lvl0":"Features","lvl1":"Streaming Guide","lvl2":"Provider Support","lvl3":""}},
4414
4414
  {"objectID":"a65ae1b5264ffcf3bd257c1a2666704dd13916433e8fe9af65ee41cc79288854","title":"See Also","url":"/docs/features/streaming#see-also","content":"Advanced Streaming Guide -- Enterprise streaming patterns, backpressure, and event types\nTTS Guide -- Text-to-speech audio streaming\nRAG Guide -- Retrieval-augmented generation with streaming\nThinking Configuration -- Extended thinking with streaming\nMultimodal Guide -- Images, PDFs, and files with streaming","hierarchy":{"lvl0":"Features","lvl1":"Streaming Guide","lvl2":"See Also","lvl3":""}},
4415
- {"objectID":"5a947cc17681ddd7c40d18de744818974a4dbb4e1a3a1884ffedcd192f89c8ff","title":"Structured Output with Zod Schemas","url":"/docs/features/structured-output","content":"Structured Output with Zod Schemas\n\nGenerate type-safe, validated JSON responses using Zod schemas. Both generate() and stream() accept schema; generate() returns structuredData directly, while a fully drained stream exposes it as result.metadata.structuredData.\n\nQuick Start\n\nRequirements\nschema: A Zod schema defining the output structure β€” always required.\noutput.format: Must be \"json\" or \"structured\" to get a JSON string\n in result.content (defaults to \"text\" if not specified). This is\n independent of structuredData: passing schema alone, with no\n output.format, is enough for result.structuredData to be populated β€”\n this is the path the tools section below uses.\n\nComplex Schemas\n\nWorks with Tools\n\nStructured output works seamlessly with MCP tools:\n\nHow this works on OpenAI-compatible providers\n\nOpenAI-compatible vendors vary in whether they accept response_format and\ntools in the same request. NeuroLink is conservative by default and does not\nsend them together. For catalog providers whose combined request has been\nverified live, capabilities.structuredOutputWithTools: true opts both\ngenerate() and stream() into sending them together, so the vendor can use\nnative constrained decoding without an extra formatting request. Separate\nsuccessful tool and structured-output probes are not enough to enable the flag.\n\nWhen a provider is not opted in, the tool turn runs untouched. If its answer\ndoes not satisfy your schema, the SDK re-asks once with the tools removed,\nwhich is what makes native response_format legal again. That second pass only\nreformats an answer the model has already produced, so tool results still drive\nthe content; toolsUsed, toolExecutions and usage cover the whole turn, not\njust the reformat. If an opted-in provider later rejects the combined request,\nthe same conflict recovery retries without structured output, so a stale\ncapability flag costs one request rather than the turn.\n\nTwo consequences worth knowing:\nA generate({ schema }) call that needed the reformat costs two requests.\n Calls whose first answer already satisfies the schema cost one, as before.\nThe reformat is accepted only if it actually produced a schema-valid value.\n If it fails, if the SDK's own turn deadline is reached, or if it comes back as\n prose anyway, the original answer is returned rather than an error β€” so this\n can improve an outcome but never degrade one. A caller that cancels the\n request still gets its cancellation. In those cases structuredData may still\n be unset, which is the honest signal that the model never produced the value.\n\nThe schema is deliberately not injected into the tool turn's system prompt.\nSome models read a JSON Schema sitting next to a tool list as another tool and\nanswer by calling one that does not exist β€” Groq's llama-3.3-70b-versatile\ntries to call a tool named json, which the server rejects outright.\n\nThe re-ask is not a single attempt. It tries native response_format first,\nbecause removing the tools is precisely what makes that legal again. Some\nvendors then reject the schema itself rather than the request: Groq answers\na non-object root with invalid JSON schema for response_format: schema must\nhave type 'object', so an array- or scalar-rooted schema fails at this stage.\nWhen that happens the SDK degrades a second time and re-runs the same tools-free\npass with the schema spelled into the prompt instead. That is why a\nz.array(z.string()) schema returns [\"red\",\"blue\",\"yellow\"] with matching\nstructuredData rather than prose. Both stages run without tools; only the way\nthe schema is communicated changes.\n\nImportant: Google Gemini Providers Limitation\n\nGoogle API Constraint: Google Gemini (both Vertex AI and Google AI Studio) cannot combine function calling with structured output (JSON schema validation). This is a documented Google API limitation, not a NeuroLink issue.\n\nGemini 3 / Gemini 2.5 Note: This limitation applies to all Gemini models, including the latest Gemini 3 and Gemini 2.5 series (e.g., gemini-2.5-pro, gemini-2.5-flash). While these models have excellent JSON schema support for structured output, they still cannot use tools and JSON schema validation together in the same request.\n\nError Message:\n\nSolution: Use disableTools: true when using schemas with Google providers:\n\nThis is Industry Standard: All major AI frameworks (LangChain, Vercel AI SDK, Agno, Instructor) use the same approach - disabling tools when using response schemas with Google models.\n\nWorkarounds for Gemini Tools + Structured Output\n\nIf you need both tool execution and structured output with Gemini, consider these approaches:\nTwo-Step Approach: First call with tools enabled (no schema), then a second call with schema to format the result:\nUse a Different Provider: OpenAI and Anthropic support tools and structured output together:\nChoose One or the Other: Design your workflow to use either tools OR structured output per request, not both.\n\nRelated Limitation: Complex schemas may trigger \"Too many","hierarchy":{"lvl0":"Features","lvl1":"Structured Output with Zod Schemas","lvl2":"","lvl3":""}},
4415
+ {"objectID":"5a947cc17681ddd7c40d18de744818974a4dbb4e1a3a1884ffedcd192f89c8ff","title":"Structured Output with Zod Schemas","url":"/docs/features/structured-output","content":"Structured Output with Zod Schemas\n\nGenerate type-safe, validated JSON responses using Zod schemas. Both generate() and stream() accept schema; generate() returns structuredData directly, while a fully drained stream exposes it as result.metadata.structuredData.\n\nQuick Start\n\nRequirements\nschema: A Zod schema defining the output structure β€” always required.\noutput.format: Must be \"json\" or \"structured\" to get a JSON string\n in result.content (defaults to \"text\" if not specified). This is\n independent of structuredData: passing schema alone, with no\n output.format, is enough for result.structuredData to be populated β€”\n this is the path the tools section below uses.\n\nComplex Schemas\n\nWorks with Tools\n\nStructured output works seamlessly with MCP tools:\n\nHow this works on OpenAI-compatible providers\n\nOpenAI-compatible vendors vary in whether they accept response_format and\ntools in the same request. NeuroLink is conservative by default and does not\nsend them together. For catalog providers whose combined request has been\nverified live, capabilities.structuredOutputWithTools: true opts both\ngenerate() and stream() into sending them together, so the vendor can use\nnative constrained decoding without an extra formatting request. Separate\nsuccessful tool and structured-output probes are not enough to enable the flag.\n\nWhen a provider is not opted in, the tool turn runs untouched. If its answer\ndoes not satisfy your schema, the SDK re-asks once with the tools removed,\nwhich is what makes native response_format legal again. That second pass only\nreformats an answer the model has already produced, so tool results still drive\nthe content; toolsUsed, toolExecutions and usage cover the whole turn, not\njust the reformat. If an opted-in provider later rejects the combined request,\nthe same conflict recovery retries without structured output, so a stale\ncapability flag costs one request rather than the turn.\n\nTwo consequences worth knowing:\nA generate({ schema }) call that needed the reformat costs up to three\n requests: the original tool turn, the response_format re-ask, and β€” only\n if the vendor rejects the schema itself (a non-object root) rather than the\n request β€” a third tools-free pass with the schema spelled into the prompt\n instead, described below. Calls whose first answer already satisfies the\n schema cost one, as before.\nThe reformat is accepted only if it actually produced a schema-valid value.\n If it fails, if the SDK's own turn deadline is reached, or if it comes back as\n prose anyway, the original answer is returned rather than an error β€” so this\n can improve an outcome but never degrade one. A caller that cancels the\n request still gets its cancellation. In those cases structuredData may still\n be unset, which is the honest signal that the model never produced the value.\n\nThe schema is deliberately not injected into the tool turn's system prompt.\nSome models read a JSON Schema sitting next to a tool list as another tool and\nanswer by calling one that does not exist β€” Groq's llama-3.3-70b-versatile\ntries to call a tool named json, which the server rejects outright.\n\nThe re-ask is not a single attempt. It tries native response_format first,\nbecause removing the tools is precisely what makes that legal again. Some\nvendors then reject the schema itself rather than the request: Groq answers\na non-object root with invalid JSON schema for response_format: schema must\nhave type 'object', so an array- or scalar-rooted schema fails at this stage.\nWhen that happens the SDK degrades a second time and re-runs the same tools-free\npass with the schema spelled into the prompt instead. That is why a\nz.array(z.string()) schema returns [\"red\",\"blue\",\"yellow\"] with matching\nstructuredData rather than prose. Both stages run without tools; only the way\nthe schema is communicated changes.\n\nImportant: Google Gemini Providers Limitation\n\nGoogle API Constraint: Google Gemini (both Vertex AI and Google AI Studio) cannot combine function calling with structured output (JSON schema validation). This is a documented Google API limitation, not a NeuroLink issue.\n\nGemini 3 / Gemini 2.5 Note: This limitation applies to all Gemini models, including the latest Gemini 3 and Gemini 2.5 series (e.g., gemini-2.5-pro, gemini-2.5-flash). While these models have excellent JSON schema support for structured output, they still cannot use tools and JSON schema validation together in the same request.\n\nError Message:\n\nSolution: Use disableTools: true when using schemas with Google providers:\n\nThis is Industry Standard: All major AI frameworks (LangChain, Vercel AI SDK, Agno, Instructor) use the same approach - disabling tools when using response schemas with Google models.\n\nWorkarounds for Gemini Tools + Structured Output\n\nIf you need both tool execution and structured output with Gemini, consider these approaches:\nTwo-Step Approach: First call with tools enabled (no schema), then a second call with schema to format the result:\nUse a ","hierarchy":{"lvl0":"Features","lvl1":"Structured Output with Zod Schemas","lvl2":"","lvl3":""}},
4416
4416
  {"objectID":"82da02b8aebfda79a43e92c60a33f5fe1bb8e84ba9ba8ac0a42d36f0df945844","title":"Structured Output with Zod Schemas","url":"/docs/features/structured-output#structured-output-with-zod-schemas","content":"Generate type-safe, validated JSON responses using Zod schemas. Both generate() and stream() accept schema; generate() returns structuredData directly, while a fully drained stream exposes it as result.metadata.structuredData.","hierarchy":{"lvl0":"Features","lvl1":"Structured Output with Zod Schemas","lvl2":"Structured Output with Zod Schemas","lvl3":""}},
4417
4417
  {"objectID":"8786915973a894e8ce2e6fd18a7da976c109949f20b7549c63b50d98d05bd821","title":"Requirements","url":"/docs/features/structured-output#requirements","content":"schema: A Zod schema defining the output structure β€” always required.\noutput.format: Must be \"json\" or \"structured\" to get a JSON string\n in result.content (defaults to \"text\" if not specified). This is\n independent of structuredData: passing schema alone, with no\n output.format, is enough for result.structuredData to be populated β€”\n this is the path the tools section below uses.","hierarchy":{"lvl0":"Features","lvl1":"Structured Output with Zod Schemas","lvl2":"Requirements","lvl3":""}},
4418
4418
  {"objectID":"239e70c6bb43d051b5ce01d19d01e865b6eab69208cea7c37f849114a7766afb","title":"Works with Tools","url":"/docs/features/structured-output#works-with-tools","content":"Structured output works seamlessly with MCP tools:","hierarchy":{"lvl0":"Features","lvl1":"Structured Output with Zod Schemas","lvl2":"Works with Tools","lvl3":""}},
4419
- {"objectID":"970f3f5cf5c095a627ebce241052024f34fb08a9916fb006fb0c3dadd3ecc43f","title":"How this works on OpenAI-compatible providers","url":"/docs/features/structured-output#how-this-works-on-openai-compatible-providers","content":"OpenAI-compatible vendors vary in whether they accept response_format and\ntools in the same request. NeuroLink is conservative by default and does not\nsend them together. For catalog providers whose combined request has been\nverified live, capabilities.structuredOutputWithTools: true opts both\ngenerate() and stream() into sending them together, so the vendor can use\nnative constrained decoding without an extra formatting request. Separate\nsuccessful tool and structured-output probes are not enough to enable the flag.\n\nWhen a provider is not opted in, the tool turn runs untouched. If its answer\ndoes not satisfy your schema, the SDK re-asks once with the tools removed,\nwhich is what makes native response_format legal again. That second pass only\nreformats an answer the model has already produced, so tool results still drive\nthe content; toolsUsed, toolExecutions and usage cover the whole turn, not\njust the reformat. If an opted-in provider later rejects the combined request,\nthe same conflict recovery retries without structured output, so a stale\ncapability flag costs one request rather than the turn.\n\nTwo consequences worth knowing:\nA generate({ schema }) call that needed the reformat costs two requests.\n Calls whose first answer already satisfies the schema cost one, as before.\nThe reformat is accepted only if it actually produced a schema-valid value.\n If it fails, if the SDK's own turn deadline is reached, or if it comes back as\n prose anyway, the original answer is returned rather than an error β€” so this\n can improve an outcome but never degrade one. A caller that cancels the\n request still gets its cancellation. In those cases structuredData may still\n be unset, which is the honest signal that the model never produced the value.\n\nThe schema is deliberately not injected into the tool turn's system prompt.\nSome models read a JSON Schema sitting next to a tool list as another tool and\nanswer by calling one that does not exist β€” Groq's llama-3.3-70b-versatile\n","hierarchy":{"lvl0":"Features","lvl1":"Structured Output with Zod Schemas","lvl2":"How this works on OpenAI-compatible providers","lvl3":""}},
4419
+ {"objectID":"970f3f5cf5c095a627ebce241052024f34fb08a9916fb006fb0c3dadd3ecc43f","title":"How this works on OpenAI-compatible providers","url":"/docs/features/structured-output#how-this-works-on-openai-compatible-providers","content":"OpenAI-compatible vendors vary in whether they accept response_format and\ntools in the same request. NeuroLink is conservative by default and does not\nsend them together. For catalog providers whose combined request has been\nverified live, capabilities.structuredOutputWithTools: true opts both\ngenerate() and stream() into sending them together, so the vendor can use\nnative constrained decoding without an extra formatting request. Separate\nsuccessful tool and structured-output probes are not enough to enable the flag.\n\nWhen a provider is not opted in, the tool turn runs untouched. If its answer\ndoes not satisfy your schema, the SDK re-asks once with the tools removed,\nwhich is what makes native response_format legal again. That second pass only\nreformats an answer the model has already produced, so tool results still drive\nthe content; toolsUsed, toolExecutions and usage cover the whole turn, not\njust the reformat. If an opted-in provider later rejects the combined request,\nthe same conflict recovery retries without structured output, so a stale\ncapability flag costs one request rather than the turn.\n\nTwo consequences worth knowing:\nA generate({ schema }) call that needed the reformat costs up to three\n requests: the original tool turn, the response_format re-ask, and β€” only\n if the vendor rejects the schema itself (a non-object root) rather than the\n request β€” a third tools-free pass with the schema spelled into the prompt\n instead, described below. Calls whose first answer already satisfies the\n schema cost one, as before.\nThe reformat is accepted only if it actually produced a schema-valid value.\n If it fails, if the SDK's own turn deadline is reached, or if it comes back as\n prose anyway, the original answer is returned rather than an error β€” so this\n can improve an outcome but never degrade one. A caller that cancels the\n request still gets its cancellation. In those cases structuredData may still\n be unset, which is the honest signal that the model ne","hierarchy":{"lvl0":"Features","lvl1":"Structured Output with Zod Schemas","lvl2":"How this works on OpenAI-compatible providers","lvl3":""}},
4420
4420
  {"objectID":"cc660b57647a3a31ebe3aca058136232c61bddb59022c34114e48727143b0a74","title":"Important: Google Gemini Providers Limitation","url":"/docs/features/structured-output#important-google-gemini-providers-limitation","content":"Google API Constraint: Google Gemini (both Vertex AI and Google AI Studio) cannot combine function calling with structured output (JSON schema validation). This is a documented Google API limitation, not a NeuroLink issue.\n\nGemini 3 / Gemini 2.5 Note: This limitation applies to all Gemini models, including the latest Gemini 3 and Gemini 2.5 series (e.g., gemini-2.5-pro, gemini-2.5-flash). While these models have excellent JSON schema support for structured output, they still cannot use tools and JSON schema validation together in the same request.\n\nError Message:\n\nSolution: Use disableTools: true when using schemas with Google providers:\n\nThis is Industry Standard: All major AI frameworks (LangChain, Vercel AI SDK, Agno, Instructor) use the same approach - disabling tools when using response schemas with Google models.","hierarchy":{"lvl0":"Features","lvl1":"Structured Output with Zod Schemas","lvl2":"Important: Google Gemini Providers Limitation","lvl3":""}},
4421
4421
  {"objectID":"72d39c1123edc80bab2c387126c4257c184aae7ad60046baf6698df58b5be31b","title":"Workarounds for Gemini Tools + Structured Output","url":"/docs/features/structured-output#workarounds-for-gemini-tools-structured-output","content":"If you need both tool execution and structured output with Gemini, consider these approaches:\nTwo-Step Approach: First call with tools enabled (no schema), then a second call with schema to format the result:\nUse a Different Provider: OpenAI and Anthropic support tools and structured output together:\nChoose One or the Other: Design your workflow to use either tools OR structured output per request, not both.\n\nRelated Limitation: Complex schemas may trigger \"Too many states for serving\" errors. Solutions:\nSimplify schema structure\nReduce nested objects\nUse disableTools: true to reduce state complexity","hierarchy":{"lvl0":"Features","lvl1":"Structured Output with Zod Schemas","lvl2":"Workarounds for Gemini Tools + Structured Output","lvl3":""}},
4422
4422
  {"objectID":"1075ae3db0656103e73fad23d48fb13a44ce2db31f37066e7de3168378c5e6b8","title":"Important Notes","url":"/docs/features/structured-output#important-notes","content":"Available in generate() and stream() - generate() exposes result.structuredData; after the stream is fully drained, stream() exposes result.metadata.structuredData\noutput.format controls result.content - If it is not \"json\" or \"structured\", result.content is plain text even with a schema; result.structuredData can still be populated from schema alone (see Requirements)\nAuto-validated, with a no-throw fallback when tools are involved - Without tools, an invalid response throws NoObjectGeneratedError with validation details. With tools attached, a failed schema match triggers the tool-free re-ask described in Works with Tools; if that also fails, the original answer is returned rather than an error, and structuredData is left unset\nProvider support - Works with OpenAI, Anthropic, Google AI Studio, Vertex AI\nGemini JSON Schema Support - Gemini 3 / Gemini 2.5 models have excellent native JSON schema support\nGemini Tools Limitation - All Gemini models (including Gemini 3) cannot combine tools with schemas - use disableTools: true","hierarchy":{"lvl0":"Features","lvl1":"Structured Output with Zod Schemas","lvl2":"Important Notes","lvl3":""}},
@@ -5609,15 +5609,15 @@
5609
5609
  {"objectID":"9d254192d1446a6d2433b439814e2084c26cfc40cf978f2b58ee92d11ad94842","title":"Configuration Reference","url":"/docs/getting-started/providers/flatkey#configuration-reference","content":"| Variable | Required | Description |\n| ---------------------------- | -------- | ----------------------------------------------------------- |\n| OPENAI_COMPATIBLE_BASE_URL | Yes | Flatkey endpoint β€” https://router.flatkey.ai/v1 |\n| OPENAI_COMPATIBLE_API_KEY | Yes | API key from the console |\n| OPENAI_COMPATIBLE_MODEL | No | Default model; overridable per request |\n\nFlatkey routes to upstream providers, so per-model availability follows the live\ncatalog rather than a fixed list. A machine-readable integration summary is\npublished at https://flatkey.ai/SKILL.md.","hierarchy":{"lvl0":"Getting Started","lvl1":"Flatkey Provider Guide","lvl2":"Configuration Reference","lvl3":""}},
5610
5610
  {"objectID":"550c70ada734bc846e71a11aa4a04f5a7d5c588444eb1013973cd3466274b520","title":"Troubleshooting","url":"/docs/getting-started/providers/flatkey#troubleshooting","content":"401 Unauthorized\nThe key is missing or malformed. Keys start with sk-fk- and are\nissued at https://console.flatkey.ai/keys. Confirm the value is exported in\nthe environment NeuroLink runs in.\n\n404 on chat completions\nCheck that OPENAI_COMPATIBLE_BASE_URL ends with /v1. The gateway follows the\nOpenAI path layout, so the version segment is part of the base URL.\n\nModel not found\nModel IDs must match the live catalog exactly. List what your key can reach:\n\nEmpty or truncated responses\nUpstream providers apply their own limits. Try a different model from the\ncatalog to isolate whether the behaviour is model-specific.","hierarchy":{"lvl0":"Getting Started","lvl1":"Flatkey Provider Guide","lvl2":"Troubleshooting","lvl3":""}},
5611
5611
  {"objectID":"1f92b8bd349af9436446b4060203d2a61b288d38359030bc83db930dceee4076","title":"See Also","url":"/docs/getting-started/providers/flatkey#see-also","content":"OpenAI-Compatible Providers Guide\nOpenRouter Provider Guide\nLiteLLM Provider Guide","hierarchy":{"lvl0":"Getting Started","lvl1":"Flatkey Provider Guide","lvl2":"See Also","lvl3":""}},
5612
- {"objectID":"b49adfb9356e8bb74d8cd90813f7848391c5bd042cf3f6ce2c741f11cca4e8e1","title":"FriendliAI Provider Guide","url":"/docs/getting-started/providers/friendli","content":"FriendliAI Provider Guide\n\nFriendliAI is a Tier-2 catalog provider: OpenAI-wire-compatible with no\nbehavioural quirks, so its entire integration is one JSON file\n(src/lib/providers/catalog/friendli.json) rather than hand-written code. That\nfile is the source of truth for everything on this page.\n\nKey Facts\nProvider id: friendli\nProtocol: OpenAI-compatible (/chat/completions)\nBase URL: https://api.friendli.ai/serverless/v1\nDefault model: zai-org/GLM-5.3\nModels in catalog: 7\nStreaming: supported\nTool calling: supported (native)\nStructured output: supported β€” but not combined with tools in one\n request: Friendli rejects tools + response_format together with HTTP\n 422 (\"response_format\" field cannot be set when tools are specified).\n NeuroLink handles this the same way as Groq (isToolsSchemaConflictError):\n it retries the call without response_format.\nEmbeddings: not supported\nBilling: free-tier\nKey format: none declared\nRate limits: tight β€” pace requests at least 20 seconds apart\n\nQuick Start\nGet an API key\nVisit: https://suite.friendli.ai/ and sign in\nCreate a Personal Access Token for the serverless endpoints\nNew accounts start with trial credit; confirm current billing terms in the console before heavy use\nSet FRIENDLI_API_KEY in your .env file\nConfigure\nUse it\n\nPer-request credentials work as they do for every provider:\n\nModels\n\n| Model | Context | Vision | $/M in Β· out | Notes |\n| --------------------------- | ------- | ------ | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| zai-org/GLM-5.3 ⭐ | 1M | no | $1.4 / $4.4 (cached $0.26) | Recommended β€” the only model in this roster capability-probed end to end (real tool call, SSE streaming, json_object). Heavy internal reasoner via reasoning/reasoning_content β€” give it a generous maxTokens. Rejects image/video input (HTTP 422). |\n| zai-org/GLM-5.3-Flash | 1M | no | β€” | Lighter/faster sibling of the default; roster-listed only, not itself capability-probed; fallback. |\n| zai-org/GLM-5.2 | 1M | no | β€” | Prior GLM generation; roster-listed only; fallback. |\n| zai-org/GLM-5.1 | 1M | no | β€” | Prior GLM generation; roster-listed only; fallback. |\n| google/gemma-4-31B-it | 1M | no | β€” | Google Gemma 4 31B instruct-tuned; roster-listed only; fallback. |\n| deepseek-ai/DeepSeek-V3.2 | 1M | no | β€” | DeepSeek V3.2; roster-listed only; fallback. |\n| MiniMaxAI/MiniMax-M2.5 | 1M | no | β€” | MiniMax M2.5; roster-listed only; fallback. |\n\nContext window shown is the catalog default of 1,048,576 tokens; the default\nmax output is 131,072 tokens (zai-org/GLM-5.3's documented per-request\noutput ceiling, distinct from the context window).\n\nFallback order when the default is unavailable: zai-org/GLM-5.3-Flash β†’\nzai-org/GLM-5.2 β†’ zai-org/GLM-5.1 β†’ google/gemma-4-31B-it β†’\ndeepseek-ai/DeepSeek-V3.2 β†’ MiniMaxAI/MiniMax-M2.5.\n\nVerification status\n\nTier-2 onboarding requires evidence before a provider is accepted, and\npnpm run verify:provider-onboarding gates it in CI. This is what the\ncatalog records for FriendliAI:\n\n| Probe | Result ","hierarchy":{"lvl0":"Getting Started","lvl1":"FriendliAI Provider Guide","lvl2":"","lvl3":""}},
5612
+ {"objectID":"b49adfb9356e8bb74d8cd90813f7848391c5bd042cf3f6ce2c741f11cca4e8e1","title":"FriendliAI Provider Guide","url":"/docs/getting-started/providers/friendli","content":"FriendliAI Provider Guide\n\nFriendliAI is a Tier-2 catalog provider: OpenAI-wire-compatible with no\nbehavioural quirks, so its entire integration is one JSON file\n(src/lib/providers/catalog/friendli.json) rather than hand-written code. That\nfile is the source of truth for everything on this page.\n\nKey Facts\nProvider id: friendli\nProtocol: OpenAI-compatible (/chat/completions)\nBase URL: https://api.friendli.ai/serverless/v1\nDefault model: zai-org/GLM-5.3\nModels in catalog: 7\nStreaming: supported\nTool calling: supported (native)\nStructured output: supported. Friendli rejects tools + response_format\n together with HTTP 422 (\"response_format\" field cannot be set when tools\nare specified), so NeuroLink proactively omits response_format whenever\n tools are present, before the request is sent β€” it does not wait for the\n 422 and retry.\nEmbeddings: not supported\nBilling: free-tier\nKey format: none declared\nRate limits: tight β€” pace requests at least 20 seconds apart\n\nQuick Start\nGet an API key\nVisit: https://suite.friendli.ai/ and sign in\nCreate a Personal Access Token for the serverless endpoints\nNew accounts start with trial credit; confirm current billing terms in the console before heavy use\nSet FRIENDLI_API_KEY in your .env file\nConfigure\nUse it\n\nPer-request credentials work as they do for every provider:\n\nModels\n\n| Model | Context | Vision | $/M in Β· out | Notes |\n| --------------------------- | ------- | ------ | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| zai-org/GLM-5.3 ⭐ | 1M | no | $1.4 / $4.4 (cached $0.26) | Recommended β€” the only model in this roster capability-probed end to end (real tool call, SSE streaming, json_object). Heavy internal reasoner via reasoning/reasoning_content β€” give it a generous maxTokens. Rejects image/video input (HTTP 422). |\n| zai-org/GLM-5.3-Flash | 1M | no | β€” | Lighter/faster sibling of the default; roster-listed only, not itself capability-probed; fallback. |\n| zai-org/GLM-5.2 | 1M | no | β€” | Prior GLM generation; roster-listed only; fallback. |\n| zai-org/GLM-5.1 | 1M | no | β€” | Prior GLM generation; roster-listed only; fallback. |\n| google/gemma-4-31B-it | 1M | no | β€” | Google Gemma 4 31B instruct-tuned; roster-listed only; fallback. |\n| deepseek-ai/DeepSeek-V3.2 | 1M | no | β€” | DeepSeek V3.2; roster-listed only; fallback. |\n| MiniMaxAI/MiniMax-M2.5 | 1M | no | β€” | MiniMax M2.5; roster-listed only; fallback. |\n\nContext window shown is the catalog default of 1,048,576 tokens; the default\nmax output is 131,072 tokens (zai-org/GLM-5.3's documented per-request\noutput ceiling, distinct from the context window).\n\nFallback order when the default is unavailable: zai-org/GLM-5.3-Flash β†’\nzai-org/GLM-5.2 β†’ zai-org/GLM-5.1 β†’ google/gemma-4-31B-it β†’\ndeepseek-ai/DeepSeek-V3.2 β†’ MiniMaxAI/MiniMax-M2.5.\n\nVerification status\n\nTier-2 onboarding requires evidence before a provider is accepted, and\npnpm run verify:provider-onboarding gates it in CI. This is what the\ncatalog records for FriendliAI:\n\n| Probe | Result ","hierarchy":{"lvl0":"Getting Started","lvl1":"FriendliAI Provider Guide","lvl2":"","lvl3":""}},
5613
5613
  {"objectID":"3fb06fe52ebad07b008fc3e35e116b6189c226a6650eba037def86f1183b305e","title":"FriendliAI Provider Guide","url":"/docs/getting-started/providers/friendli#friendliai-provider-guide","content":"FriendliAI is a Tier-2 catalog provider: OpenAI-wire-compatible with no\nbehavioural quirks, so its entire integration is one JSON file\n(src/lib/providers/catalog/friendli.json) rather than hand-written code. That\nfile is the source of truth for everything on this page.","hierarchy":{"lvl0":"Getting Started","lvl1":"FriendliAI Provider Guide","lvl2":"FriendliAI Provider Guide","lvl3":""}},
5614
- {"objectID":"901e86d320bbeefec291bde97052ba20256a0e571c5c5e3a8c5348adecead50e","title":"Key Facts","url":"/docs/getting-started/providers/friendli#key-facts","content":"Provider id: friendli\nProtocol: OpenAI-compatible (/chat/completions)\nBase URL: https://api.friendli.ai/serverless/v1\nDefault model: zai-org/GLM-5.3\nModels in catalog: 7\nStreaming: supported\nTool calling: supported (native)\nStructured output: supported β€” but not combined with tools in one\n request: Friendli rejects tools + response_format together with HTTP\n 422 (\"response_format\" field cannot be set when tools are specified).\n NeuroLink handles this the same way as Groq (isToolsSchemaConflictError):\n it retries the call without response_format.\nEmbeddings: not supported\nBilling: free-tier\nKey format: none declared\nRate limits: tight β€” pace requests at least 20 seconds apart","hierarchy":{"lvl0":"Getting Started","lvl1":"FriendliAI Provider Guide","lvl2":"Key Facts","lvl3":""}},
5614
+ {"objectID":"901e86d320bbeefec291bde97052ba20256a0e571c5c5e3a8c5348adecead50e","title":"Key Facts","url":"/docs/getting-started/providers/friendli#key-facts","content":"Provider id: friendli\nProtocol: OpenAI-compatible (/chat/completions)\nBase URL: https://api.friendli.ai/serverless/v1\nDefault model: zai-org/GLM-5.3\nModels in catalog: 7\nStreaming: supported\nTool calling: supported (native)\nStructured output: supported. Friendli rejects tools + response_format\n together with HTTP 422 (\"response_format\" field cannot be set when tools\nare specified), so NeuroLink proactively omits response_format whenever\n tools are present, before the request is sent β€” it does not wait for the\n 422 and retry.\nEmbeddings: not supported\nBilling: free-tier\nKey format: none declared\nRate limits: tight β€” pace requests at least 20 seconds apart","hierarchy":{"lvl0":"Getting Started","lvl1":"FriendliAI Provider Guide","lvl2":"Key Facts","lvl3":""}},
5615
5615
  {"objectID":"3b505650bea29496f59be24689157bff939b626ff4f22ffc51253cb59e72c7d5","title":"1. Get an API key","url":"/docs/getting-started/providers/friendli#1-get-an-api-key","content":"Visit: https://suite.friendli.ai/ and sign in\nCreate a Personal Access Token for the serverless endpoints\nNew accounts start with trial credit; confirm current billing terms in the console before heavy use\nSet FRIENDLI_API_KEY in your .env file","hierarchy":{"lvl0":"Getting Started","lvl1":"FriendliAI Provider Guide","lvl2":"1. Get an API key","lvl3":""}},
5616
5616
  {"objectID":"e429f8ec995eebc8e5b148f5c505da49f68c8a6d155fa512a8f162266c44b607","title":"3. Use it","url":"/docs/getting-started/providers/friendli#3-use-it","content":"`bash","hierarchy":{"lvl0":"Getting Started","lvl1":"FriendliAI Provider Guide","lvl2":"3. Use it","lvl3":""}},
5617
5617
  {"objectID":"9f40a517994a669fac5089e4975087ec49eb4a129a0b88f78ee137ca51b6c352","title":"CLI","url":"/docs/getting-started/providers/friendli#cli","content":"npx @juspay/neurolink generate \"Hello\" --provider friendli\ntypescript\nawait neurolink.generate({\n input: { text: \"Hello\" },\n provider: \"friendli\",\n credentials: { friendli: { apiKey: process.env.FRIENDLIAPIKEY } },\n});\n`","hierarchy":{"lvl0":"Getting Started","lvl1":"FriendliAI Provider Guide","lvl2":"CLI","lvl3":""}},
5618
5618
  {"objectID":"b66c8029693af65986440601e71042fc07bea17a333d634287f211acaaa3b6ad","title":"Models","url":"/docs/getting-started/providers/friendli#models","content":"| Model | Context | Vision | $/M in Β· out | Notes |\n| --------------------------- | ------- | ------ | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| zai-org/GLM-5.3 ⭐ | 1M | no | $1.4 / $4.4 (cached $0.26) | Recommended β€” the only model in this roster capability-probed end to end (real tool call, SSE streaming, json_object). Heavy internal reasoner via reasoning/reasoning_content β€” give it a generous maxTokens. Rejects image/video input (HTTP 422). |\n| zai-org/GLM-5.3-Flash | 1M | no | β€” | Lighter/faster sibling of the default; roster-listed only, not itself capability-probed; fallback. |\n| zai-org/GLM-5.2 | 1M | no | β€” | Prior GLM generation; roster-listed only; fallback. |\n| zai-org/GLM-5.1 | 1M | no | β€” | Prior GLM generation; roster-listed only; fallback. |\n| google/gemma-4-","hierarchy":{"lvl0":"Getting Started","lvl1":"FriendliAI Provider Guide","lvl2":"Models","lvl3":""}},
5619
5619
  {"objectID":"341bb86e88577c8982f565e3bb49d1faa5c1449e8cd5310b8df239e829efdb9e","title":"Verification status","url":"/docs/getting-started/providers/friendli#verification-status","content":"Tier-2 onboarding requires evidence before a provider is accepted, and\npnpm run verify:provider-onboarding gates it in CI. This is what the\ncatalog records for FriendliAI:\n\n| Probe | Result |\n| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| Roster | authenticated GET /serverless/v1/models, HTTP 200, 2026-09-06 |\n| Auth rejection | HTTP 401, 2026-09-06 ","hierarchy":{"lvl0":"Getting Started","lvl1":"FriendliAI Provider Guide","lvl2":"Verification status","lvl3":""}},
5620
- {"objectID":"7d5ebae39916c5745bbc01788b7092e2fa3f81495e1375fc9d720eb326bee964","title":"Troubleshooting","url":"/docs/getting-started/providers/friendli#troubleshooting","content":"| Symptom | Cause | Fix |\n| ----------------------------------------- | ---------------------------------------------------------------- | --------------------------------------------------------------------------------- |\n| Invalid Friendli API key | FRIENDLI_API_KEY unset or wrong | Check the key at https://suite.friendli.ai/ |\n| Model not found | The roster changed since 2026-09-06 | Pick a current id from the authenticated /serverless/v1/models roster |\n| Frequent 429s | Friendli's rate limits are tight | Pace requests at least 20 seconds apart and retry |\n| HTTP 422 when tools + schema are both set | Friendli rejects response_format when tools is present | NeuroLink retries automatically without response_format (same handling as Groq) |\n| Empty content at a small maxTokens | zai-org/GLM-5.3 spends its budget on reasoning_content first | Give reasoning prompts a generous maxTokens budget |","hierarchy":{"lvl0":"Getting Started","lvl1":"FriendliAI Provider Guide","lvl2":"Troubleshooting","lvl3":""}},
5620
+ {"objectID":"7d5ebae39916c5745bbc01788b7092e2fa3f81495e1375fc9d720eb326bee964","title":"Troubleshooting","url":"/docs/getting-started/providers/friendli#troubleshooting","content":"| Symptom | Cause | Fix |\n| ------------------------------------------------------ | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |\n| Invalid Friendli API key | FRIENDLI_API_KEY unset or wrong | Check the key at https://suite.friendli.ai/ |\n| Model not found | The roster changed since 2026-09-06 | Pick a current id from the authenticated /serverless/v1/models roster |\n| Frequent 429s | Friendli's rate limits are tight | Pace requests at least 20 seconds apart and retry |\n| Structured output silently dropped when tools are used | Friendli rejects response_format when tools is present (HTTP 422) | NeuroLink omits response_format automatically whenever tools are present, before sending β€” this is expected, not a bug |\n| Empty content at a small maxTokens | zai-org/GLM-5.3 spends its budget on reasoning_content first | Give reasoning prompts a generous maxTokens budget |","hierarchy":{"lvl0":"Getting Started","lvl1":"FriendliAI Provider Guide","lvl2":"Troubleshooting","lvl3":""}},
5621
5621
  {"objectID":"9a2b3c1a8e2b87f12be59e06d2a131fcba54035f11d0fa25b11030eebc0064f7","title":"See also","url":"/docs/getting-started/providers/friendli#see-also","content":"Provider setup overview\nAll providers\nTier-2 onboarding β€” how this provider's JSON becomes a working integration\nProvider feature compatibility","hierarchy":{"lvl0":"Getting Started","lvl1":"FriendliAI Provider Guide","lvl2":"See also","lvl3":""}},
5622
5622
  {"objectID":"3f4a67c46fcd7980b7a40666e1ec1dcc4a4f71af4691b96f8f3893ccfe3932ab","title":"GMI Cloud Provider Guide","url":"/docs/getting-started/providers/gmicloud","content":"GMI Cloud Provider Guide\n\nGMI Cloud is a Tier-2 catalog provider: OpenAI-wire-compatible with no\nbehavioural quirks, so its entire integration is one JSON file\n(src/lib/providers/catalog/gmicloud.json) rather than hand-written code. That\nfile is the source of truth for everything on this page.\n\nKey Facts\nProvider id: gmicloud (aliases: gmi-cloud)\nProtocol: OpenAI-compatible (/chat/completions)\nBase URL: https://api.gmi-serving.com/v1\nDefault model: MiniMaxAI/MiniMax-M3\nModels in catalog: 1\nStreaming: supported\nTool calling: supported (native)\nStructured output: supported\nEmbeddings: not supported\nBilling: free-tier\nKey format: ^eyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+$\n\nQuick Start\nGet an API key\nVisit: https://console.gmicloud.ai\nSign in and select the Inference service\nCreate an API key; check Console β†’ Inference β†’ Model Hub for current model pricing\nSet GMICLOUD_API_KEY in your .env file\nConfigure\nUse it\n\nPer-request credentials work as they do for every provider:\n\nModels\n\n| Model | Context | Vision | $/M in Β· out | Notes |\n| ------------------------- | ------- | ------ | ------------ | -------------------------------------------------- |\n| MiniMaxAI/MiniMax-M3 ⭐ | 1M | no | β€” | MiniMaxAI/MiniMax-M3 β€” live GMI Cloud-probed model |\n\nFallback order when the default is unavailable: MiniMaxAI/MiniMax-M3.\n\nVerification status\n\nTier-2 onboarding requires evidence before a provider is accepted, and\npnpm run verify:provider-onboarding gates it in CI. This is what the\ncatalog records for GMI Cloud:\n\n| Probe | Result |\n| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Roster | authenticated GET /v1/models, HTTP 200, 2026-09-03 |\n| Auth rejection | HTTP 401, 2026-09-03 |\n| Live capability sweep | 2026-09-03 β€” MiniMax-M3 accepted maxcompletiontokens=524288 and rejected 1048576 with an explicit 524288 limit. Structured output: the endpoint ignores responseformat (jsonschema and json_object both return prose with no prompt h |\n\nTroubleshooting\n\n| Symptom | Cause | Fix |\n| --------------------------- | ----------------------------------- | ----------------------------------------------------------------- |\n| Invalid GMI Cloud API key | GMICLOUD_API_KEY unset or wrong | Check the key at https://console.gmicloud.ai |\n| Model not found | The roster changed since 2026-09-03 | Pick a current id; catalog providers retire models without notice |\n\nSee also\nProvider setup overview\nAll providers\nTier-2 onboarding β€” how this provider's JSON becomes a working integration\nProvider feature compatibility","hierarchy":{"lvl0":"Getting Started","lvl1":"GMI Cloud Provider Guide","lvl2":"","lvl3":""}},
5623
5623
  {"objectID":"1eb70df9354621e43dbd2fef9c02cbba04abccfd67b8519feca9b39bdd2d597a","title":"GMI Cloud Provider Guide","url":"/docs/getting-started/providers/gmicloud#gmi-cloud-provider-guide","content":"GMI Cloud is a Tier-2 catalog provider: OpenAI-wire-compatible with no\nbehavioural quirks, so its entire integration is one JSON file\n(src/lib/providers/catalog/gmicloud.json) rather than hand-written code. That\nfile is the source of truth for everything on this page.","hierarchy":{"lvl0":"Getting Started","lvl1":"GMI Cloud Provider Guide","lvl2":"GMI Cloud Provider Guide","lvl3":""}},
@@ -5893,7 +5893,7 @@
5893
5893
  {"objectID":"faae7281e5a366b4892035d92012602a9e7aaa15cc9d96556b20493e25562498","title":"🧠 Decision-Only Providers {#decision-only-providers}","url":"/docs/getting-started/providers#-decision-only-providers-decision-only-providers","content":"The two providers that serve decide rather than generate/stream. Each\nreturns typed, calibrated judgments and emits no text, so neither appears in\ngeneration fallback chains or the health sweep.","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"🧠 Decision-Only Providers {#decision-only-providers}","lvl3":""}},
5894
5894
  {"objectID":"50860d1f7a27dbe3ad7452ad7079ea437658db372b97081d0a509429369cacc6","title":"[TypeSafe (Jev)](/docs/getting-started/providers/typesafe)","url":"/docs/getting-started/providers#typesafe-jevdocsgetting-startedproviderstypesafe","content":"Typed, calibrated judgments instead of text\n🎯 boolean / choice / score answers, each with a calibrated confidence\n⚑ Latency flat in question count β€” 1 question ~393 ms, 400 questions ~465 ms\nπŸ’° ~$0.00002 per decision (~$0.042/M input, output billed at zero)\nπŸ”Œ Two transports: TypeSafe direct, or the Vercel AI Gateway\nπŸ›‘οΈ Fails open β€” with no key configured, every consumer behaves exactly as before\nπŸ”‘ API key from console.typesafe.ai/keys\nπŸ”„ Aliases: jev, typesafe-ai\n\nSetup Guide β†’","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"[TypeSafe (Jev)](/docs/getting-started/providers/typesafe)","lvl3":""}},
5895
5895
  {"objectID":"43b838d60f2794ce46361196d6fc8a708b3a301398dd55f2c8015d567aa21c2c","title":"[Laya](/docs/getting-started/providers/laya)","url":"/docs/getting-started/providers#layadocsgetting-startedproviderslaya","content":"Open-weights decision provider β€” the same typed boolean/choice/score answers as Jev, from Convai Innovations' Apache-2.0 checkpoints, at a Laya server or LiteLLM proxy route you configure\n🧭 Serves decide only; built-in features use it when its key and base URL are set and neither TYPESAFE_API_KEY nor AI_GATEWAY_API_KEY is\nπŸ“ Refuses more than ~768 tokens of state (320 on english) before any network call, since its encoders read only 1,024 (512)\nπŸ”Œ No built-in endpoint: LAYA_BASE_URL (or credentials.laya.baseURL) names a Laya server or a LiteLLM pass-through route to one\nπŸ”‘ LAYA_API_KEY is the key that endpoint accepts; on LiteLLM, the route must be in the key's Allowed Routes\n\nSetup Guide β†’","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"[Laya](/docs/getting-started/providers/laya)","lvl3":""}},
5896
- {"objectID":"c98403894a115164f29a019817b7f39c93b59623a9854b4575ad06bc5f597320","title":"🧩 Additional Catalog Providers","url":"/docs/getting-started/providers#-additional-catalog-providers","content":"Every provider below is a Tier-2 catalog entry β€” OpenAI-wire-compatible\nwith no behavioural quirks, so the whole integration is one JSON file under\nsrc/lib/providers/catalog/. Each page is generated from that file, which is\nalso what the CI onboarding gate reads.","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"🧩 Additional Catalog Providers","lvl3":""}},
5896
+ {"objectID":"c98403894a115164f29a019817b7f39c93b59623a9854b4575ad06bc5f597320","title":"🧩 Additional Catalog Providers","url":"/docs/getting-started/providers#-additional-catalog-providers","content":"Every provider below is a Tier-2 catalog entry. Provider-specific\nbehavioural quirks may apply, so check the provider's catalog file. The whole\nintegration is one JSON file under src/lib/providers/catalog/. Each page is\ngenerated from that file, which is also what the CI onboarding gate reads.","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"🧩 Additional Catalog Providers","lvl3":""}},
5897
5897
  {"objectID":"026138da0a559269ecd9f0b2ceb72d9039096e72e064142afb7bfb74a5cb7455","title":"[API Route](/docs/getting-started/providers/api-route)","url":"/docs/getting-started/providers#api-routedocsgetting-startedprovidersapi-route","content":"Claude Sonnet 4.6\nπŸ€– 8 models; default claude-sonnet-4-6 (1M context)\nπŸ› οΈ Native tool calling + structured output together\nπŸ’³ Free tier available\nβœ… Roster verified 2026-09-17 (authenticated GET /v1/models)\nπŸ”‘ API key from api-route.com\nπŸ”„ Aliases: apiroute\n\nSetup Guide β†’","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"[API Route](/docs/getting-started/providers/api-route)","lvl3":""}},
5898
5898
  {"objectID":"85aa65949d959db077347ecf93a4c40ade9ebab4300d4d52c62c702f6929053b","title":"[Baseten](/docs/getting-started/providers/baseten)","url":"/docs/getting-started/providers#basetendocsgetting-startedprovidersbaseten","content":"GLM 5.3 Flash\nπŸ€– 16 models; default zai-org/GLM-5.3-Flash (1M context)\nπŸ› οΈ Native tool calling + structured output together\nπŸ’³ Free tier available\nβœ… Roster verified 2026-09-03 (authenticated GET /v1/models)\nπŸ”‘ API key from app.baseten.co\n\nSetup Guide β†’","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"[Baseten](/docs/getting-started/providers/baseten)","lvl3":""}},
5899
5899
  {"objectID":"a63f2c06a13bf6cfc44ae46ceeced786bb08ec6a5a641e0603509b440cf7efcf","title":"[Friendli](/docs/getting-started/providers/friendli)","url":"/docs/getting-started/providers#friendlidocsgetting-startedprovidersfriendli","content":"zai-org/GLM-5.3\nπŸ€– 7 models; default zai-org/GLM-5.3 (1M context)\nπŸ› οΈ Native tool calling β€” not combined with structured output in one request (HTTP 422 if both are set)\nπŸ’³ Free tier available (rate limits are tight β€” pace requests 20s+ apart)\nβœ… Roster verified 2026-09-06 (authenticated GET /serverless/v1/models)\nπŸ”‘ API key from suite.friendli.ai\n\nSetup Guide β†’","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"[Friendli](/docs/getting-started/providers/friendli)","lvl3":""}},
@@ -6998,9 +6998,9 @@
6998
6998
  {"objectID":"5e419fd378ccf967026f166ff17ca26ff25e33bee3a5e5f1ff6294df4c06bb12","title":"Set in Vercel dashboard or CLI","url":"/docs/guides/frameworks/sveltekit#set-in-vercel-dashboard-or-cli","content":"vercel env add OPENAIAPIKEY\nvercel env add ANTHROPICAPIKEY\nvercel env add JWT_SECRET\n`","hierarchy":{"lvl0":"Guides","lvl1":"SvelteKit Integration Guide","lvl2":"Set in Vercel dashboard or CLI","lvl3":""}},
6999
6999
  {"objectID":"a86f4915394a5106e65dd50477d31423486db347ca83c02354ed3a06df8cdc62","title":"Related Documentation","url":"/docs/guides/frameworks/sveltekit#related-documentation","content":"API Reference - NeuroLink SDK\nStreaming Guide - Real-time responses\nCompliance Guide - Security and authentication\nCost Optimization - Reduce costs\nFastify Integration - High-performance Node.js framework with schema validation","hierarchy":{"lvl0":"Guides","lvl1":"SvelteKit Integration Guide","lvl2":"Related Documentation","lvl3":""}},
7000
7000
  {"objectID":"dae99b935ff34c8fd5f10f0ac1f2f4fdffb0cd777d7bb45c7bc7f4b91059014c","title":"Additional Resources","url":"/docs/guides/frameworks/sveltekit#additional-resources","content":"SvelteKit Documentation - Official SvelteKit docs\nSvelte Tutorial - Learn Svelte\nSvelteKit Examples - Example apps\n\nNeed Help? Join our GitHub Discussions or open an issue.","hierarchy":{"lvl0":"Guides","lvl1":"SvelteKit Integration Guide","lvl2":"Additional Resources","lvl3":""}},
7001
- {"objectID":"8f31aec32f066055dee31be79a01ee297a435bbf7f901cce7785983b2e27e1eb","title":"GitHub Action Guide","url":"/docs/guides/github-action","content":"GitHub Action Guide\n\nLast Updated: January 10, 2026\nNeuroLink Version: 8.32.0\n\nRun AI-powered workflows with 44 providers directly in GitHub Actions. The NeuroLink GitHub Action enables automated code review, issue triage, content generation, and more.\n\nOverview\n\nThe NeuroLink GitHub Action provides a unified interface to integrate AI capabilities into your CI/CD workflows. It supports all 40 NeuroLink providers through a single, consistent configuration.\n\nKey Features:\nMulti-provider support - 44 AI providers with unified interface\nPR/Issue comments - Auto-post AI responses with intelligent comment updates\nCost tracking - Built-in analytics with usage metrics\nQuality evaluation - Response scoring and validation\nMultimodal - Support for images, PDFs, CSVs, and videos\nExtended thinking - Deep reasoning with thinking tokens\nJob summaries - Detailed execution summaries in workflow runs\n\nQuick Start\n\nBasic Usage\n\nAuto Provider Detection\n\nWhen you set provider: auto (the default), NeuroLink automatically selects the best available provider based on which API keys you provide:\n\nProvider Configuration\n\nNeuroLink supports 44 AI providers. Configure each by providing the required credentials as secrets.\n\nProvider Quick Reference\n\n| Provider | Required Inputs | Example Models |\n| ----------------- | ------------------------------------------------------------------ | ------------------------------------------ |\n| OpenAI | openai_api_key | gpt-4o, gpt-4o-mini, o1 |\n| Anthropic | anthropic_api_key | claude-sonnet-4-20250514, claude-3-5-haiku |\n| Google AI Studio | google_ai_api_key | gemini-2.5-pro, gemini-2.5-flash |\n| Vertex AI | google_vertex_project, google_application_credentials | gemini-\\, claude-\\ |\n| Amazon Bedrock | aws_access_key_id, aws_secret_access_key | claude-\\, titan-\\, nova-\\* |\n| Azure OpenAI | azure_openai_api_key, azure_openai_endpoint | gpt-4o, gpt-4-turbo |\n| Mistral | mistral_api_key | mistral-large, mistral-small |\n| Hugging Face | huggingface_api_key | Various open models |\n| OpenRouter | openrouter_api_key | 300+ models |\n| LiteLLM | litellm_api_key, litellm_base_url | Proxy to 100+ models |\n| Ollama | - | Local models |\n| SageMaker | aws_access_key_id, aws_secret_access_key, sagemaker_endpoint | Custom endpoints |\n| OpenAI-Compatible | openai_compatible_api_key, openai_compatible_base_url | vLLM, custom APIs |\n\nOpenAI\n\nEnvironment Variables:\nOPENAI_API_KEY - Your OpenAI API key (starts with sk-)\n\nAvailable Models:\ngpt-4o - Most capable model\ngpt-4o-mini - Fast and cost-effective\no1 - Advanced reasoning model\ngpt-4-turbo - Previous generation flagship\n\nAnthropic\n\nEnvironment Variables:\nANTHROPIC_API_KEY - Your Anthropic API key (starts with sk-ant-)\n\nAvailable Models:\nclaude-sonnet-4-20250514 - Best overall performance\nclaude-3-5-haiku - Fast and efficient\nclaude-opus-4-20250514 - Maximum capability\n\nExtended Thinking Support: Anthropic models support extended thinking for deep reasoning tasks.\n\nGoogle AI Studio\n\nEnvironment Variables:\nGOOGLE_AI_API_KEY - Your Google AI Studio API key\n\nAvailable Models:\ngemini-2.5-pro - Most capable Gemini model\ngemini-2.5-flash - Fast and cost-effective\ngemini-2.0-flash - Previous generation\n\nFree Tier: Google AI Studio offers a generous free tier (1M tokens/day).\n\nGoogle Vertex AI\n\nEnvironment Variables:\nGOOGLE_VERTEX_PROJECT - Your GCP project ID\nGOOGLE_VERTEX_LOCATION - GCP region (default: us-central1)\nGOOGLE_APPLICATION_CREDENTIALS - Base64-encoded service account JSON\n\nSetup Service Account:\n\nAmazon Bedrock\n\nEnvironment Variables:\nAWS_ACCESS_KEY_ID - AWS access key\nAWS_SECRET_ACCESS_KEY - AWS secret key\nAWS_REGION - AWS region (default: us-east-1)\nAWS_SESSION_TOKEN - Optional session token for temporary credentials\n\nAvailable Models:\nanthropic.claude-3-5-sonnet-20241022-v2:0 - Claude on Bedrock\namazon.titan-text-express-v1 - Amazon Titan\namazon.nova-pro-v1:0 - Amazon Nova\n\nOIDC Authentication (Recommended):\n\nFor better security, use GitHub OIDC instead of static credentials:\n\nAzure OpenAI\n\nEnvironment Variables:\nAZURE_OPENAI_API_KEY - Azure OpenAI API key\nAZURE_OPENAI_ENDPOINT - Azure OpenAI endpoi","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"","lvl3":""}},
7001
+ {"objectID":"8f31aec32f066055dee31be79a01ee297a435bbf7f901cce7785983b2e27e1eb","title":"GitHub Action Guide","url":"/docs/guides/github-action","content":"GitHub Action Guide\n\nLast Updated: January 10, 2026\nNeuroLink Version: 8.32.0\n\nRun AI-powered workflows with 44 providers directly in GitHub Actions. The NeuroLink GitHub Action enables automated code review, issue triage, content generation, and more.\n\nOverview\n\nThe NeuroLink GitHub Action provides a unified interface to integrate AI capabilities into your CI/CD workflows. It supports all 44 NeuroLink providers through a single, consistent configuration.\n\nKey Features:\nMulti-provider support - 44 AI providers with unified interface\nPR/Issue comments - Auto-post AI responses with intelligent comment updates\nCost tracking - Built-in analytics with usage metrics\nQuality evaluation - Response scoring and validation\nMultimodal - Support for images, PDFs, CSVs, and videos\nExtended thinking - Deep reasoning with thinking tokens\nJob summaries - Detailed execution summaries in workflow runs\n\nQuick Start\n\nBasic Usage\n\nAuto Provider Detection\n\nWhen you set provider: auto (the default), NeuroLink automatically selects the best available provider based on which API keys you provide:\n\nProvider Configuration\n\nNeuroLink supports 44 AI providers. Configure each by providing the required credentials as secrets.\n\nProvider Quick Reference\n\n| Provider | Required Inputs | Example Models |\n| ----------------- | ------------------------------------------------------------------ | ------------------------------------------ |\n| OpenAI | openai_api_key | gpt-4o, gpt-4o-mini, o1 |\n| Anthropic | anthropic_api_key | claude-sonnet-4-20250514, claude-3-5-haiku |\n| Google AI Studio | google_ai_api_key | gemini-2.5-pro, gemini-2.5-flash |\n| Vertex AI | google_vertex_project, google_application_credentials | gemini-\\, claude-\\ |\n| Amazon Bedrock | aws_access_key_id, aws_secret_access_key | claude-\\, titan-\\, nova-\\* |\n| Azure OpenAI | azure_openai_api_key, azure_openai_endpoint | gpt-4o, gpt-4-turbo |\n| Mistral | mistral_api_key | mistral-large, mistral-small |\n| Hugging Face | huggingface_api_key | Various open models |\n| OpenRouter | openrouter_api_key | 300+ models |\n| LiteLLM | litellm_api_key, litellm_base_url | Proxy to 100+ models |\n| Ollama | - | Local models |\n| SageMaker | aws_access_key_id, aws_secret_access_key, sagemaker_endpoint | Custom endpoints |\n| OpenAI-Compatible | openai_compatible_api_key, openai_compatible_base_url | vLLM, custom APIs |\n\nOpenAI\n\nEnvironment Variables:\nOPENAI_API_KEY - Your OpenAI API key (starts with sk-)\n\nAvailable Models:\ngpt-4o - Most capable model\ngpt-4o-mini - Fast and cost-effective\no1 - Advanced reasoning model\ngpt-4-turbo - Previous generation flagship\n\nAnthropic\n\nEnvironment Variables:\nANTHROPIC_API_KEY - Your Anthropic API key (starts with sk-ant-)\n\nAvailable Models:\nclaude-sonnet-4-20250514 - Best overall performance\nclaude-3-5-haiku - Fast and efficient\nclaude-opus-4-20250514 - Maximum capability\n\nExtended Thinking Support: Anthropic models support extended thinking for deep reasoning tasks.\n\nGoogle AI Studio\n\nEnvironment Variables:\nGOOGLE_AI_API_KEY - Your Google AI Studio API key\n\nAvailable Models:\ngemini-2.5-pro - Most capable Gemini model\ngemini-2.5-flash - Fast and cost-effective\ngemini-2.0-flash - Previous generation\n\nFree Tier: Google AI Studio offers a generous free tier (1M tokens/day).\n\nGoogle Vertex AI\n\nEnvironment Variables:\nGOOGLE_VERTEX_PROJECT - Your GCP project ID\nGOOGLE_VERTEX_LOCATION - GCP region (default: us-central1)\nGOOGLE_APPLICATION_CREDENTIALS - Base64-encoded service account JSON\n\nSetup Service Account:\n\nAmazon Bedrock\n\nEnvironment Variables:\nAWS_ACCESS_KEY_ID - AWS access key\nAWS_SECRET_ACCESS_KEY - AWS secret key\nAWS_REGION - AWS region (default: us-east-1)\nAWS_SESSION_TOKEN - Optional session token for temporary credentials\n\nAvailable Models:\nanthropic.claude-3-5-sonnet-20241022-v2:0 - Claude on Bedrock\namazon.titan-text-express-v1 - Amazon Titan\namazon.nova-pro-v1:0 - Amazon Nova\n\nOIDC Authentication (Recommended):\n\nFor better security, use GitHub OIDC instead of static credentials:\n\nAzure OpenAI\n\nEnvironment Variables:\nAZURE_OPENAI_API_KEY - Azure OpenAI API key\nAZURE_OPENAI_ENDPOINT - Azure OpenAI endpoi","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"","lvl3":""}},
7002
7002
  {"objectID":"7ff4c3df91e5e1c298b72c9c4582ecd6d75ff6486e6af5c4ef96766507050d2b","title":"GitHub Action Guide","url":"/docs/guides/github-action#github-action-guide","content":"Last Updated: January 10, 2026\nNeuroLink Version: 8.32.0\n\nRun AI-powered workflows with 44 providers directly in GitHub Actions. The NeuroLink GitHub Action enables automated code review, issue triage, content generation, and more.","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"GitHub Action Guide","lvl3":""}},
7003
- {"objectID":"33dd9029b76affe39c2b849f369b0629e6061d643568bcefd1ab923e2653bd90","title":"Overview","url":"/docs/guides/github-action#overview","content":"The NeuroLink GitHub Action provides a unified interface to integrate AI capabilities into your CI/CD workflows. It supports all 40 NeuroLink providers through a single, consistent configuration.\n\nKey Features:\nMulti-provider support - 44 AI providers with unified interface\nPR/Issue comments - Auto-post AI responses with intelligent comment updates\nCost tracking - Built-in analytics with usage metrics\nQuality evaluation - Response scoring and validation\nMultimodal - Support for images, PDFs, CSVs, and videos\nExtended thinking - Deep reasoning with thinking tokens\nJob summaries - Detailed execution summaries in workflow runs","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Overview","lvl3":""}},
7003
+ {"objectID":"33dd9029b76affe39c2b849f369b0629e6061d643568bcefd1ab923e2653bd90","title":"Overview","url":"/docs/guides/github-action#overview","content":"The NeuroLink GitHub Action provides a unified interface to integrate AI capabilities into your CI/CD workflows. It supports all 44 NeuroLink providers through a single, consistent configuration.\n\nKey Features:\nMulti-provider support - 44 AI providers with unified interface\nPR/Issue comments - Auto-post AI responses with intelligent comment updates\nCost tracking - Built-in analytics with usage metrics\nQuality evaluation - Response scoring and validation\nMultimodal - Support for images, PDFs, CSVs, and videos\nExtended thinking - Deep reasoning with thinking tokens\nJob summaries - Detailed execution summaries in workflow runs","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Overview","lvl3":""}},
7004
7004
  {"objectID":"3bb997302dc433bdb7ccaa27311d8b28539d24f519d50d7777495c4477c52933","title":"Auto Provider Detection","url":"/docs/guides/github-action#auto-provider-detection","content":"When you set provider: auto (the default), NeuroLink automatically selects the best available provider based on which API keys you provide:","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Auto Provider Detection","lvl3":""}},
7005
7005
  {"objectID":"a0196ac56db4df812b123855c3b7524934cf265a63e96a8ba68334d3206c0fe1","title":"Provider Configuration","url":"/docs/guides/github-action#provider-configuration","content":"NeuroLink supports 44 AI providers. Configure each by providing the required credentials as secrets.","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Provider Configuration","lvl3":""}},
7006
7006
  {"objectID":"e323a8ed54e480b24ca441ae97e154de2fc279ab13289c50496ffb1c1040dbbd","title":"Provider Quick Reference","url":"/docs/guides/github-action#provider-quick-reference","content":"| Provider | Required Inputs | Example Models |\n| ----------------- | ------------------------------------------------------------------ | ------------------------------------------ |\n| OpenAI | openai_api_key | gpt-4o, gpt-4o-mini, o1 |\n| Anthropic | anthropic_api_key | claude-sonnet-4-20250514, claude-3-5-haiku |\n| Google AI Studio | google_ai_api_key | gemini-2.5-pro, gemini-2.5-flash |\n| Vertex AI | google_vertex_project, google_application_credentials | gemini-\\, claude-\\ |\n| Amazon Bedrock | aws_access_key_id, aws_secret_access_key | claude-\\, titan-\\, nova-\\* |\n| Azure OpenAI | azure_openai_api_key, azure_openai_endpoint | gpt-4o, gpt-4-turbo |\n| Mistral | mistral_api_key | mistral-large, mistral-small |\n| Hugging Face | huggingface_api_key | Various open models |\n| OpenRouter | openrouter_api_key | 300+ models |\n| LiteLLM | litellm_api_key, litellm_base_url | Proxy to 100+ models |\n| Ollama | - | Local models |\n| SageMaker | aws_access_key_id, aws_secret_access_key, sagemaker_endpoint | Custom endpoints |\n| OpenAI-Compatible | openai_compatible_api_key, openai_compatible_base_url | vLLM, custom APIs |","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Provider Quick Reference","lvl3":""}},
@@ -8943,7 +8943,7 @@
8943
8943
  {"objectID":"cbc4193e5e9ffb4c77dd167fe137bc62cfbab5adbe808e814a374670bef12175","title":"Shared adapter needed (9)","url":"/docs/provider-integration/migration-ledger#shared-adapter-needed-9","content":"Three adapter families, not nine one-off migrations:\n\nLocal-runtime adapter (ollama, lm-studio, llamacpp) β€” one OpenAI-compatible local-runtime adapter with optional auth, model discovery/probe, actionable transport errors, timeout policy, optional embeddings. Vendor-specific pull/diagnostic guidance becomes adapter data.\n\nEmbedding-only adapter (voyage, jina, cohere) β€” one embedding-only provider adapter parameterized by path, request shape, batch size, response-extraction/index policy, unsupported-surface messages. jina extends it with an optional rerank operation profile (don't force reranking into the boolean capability shape). cohere composes this with a generic OpenAI chat adapter (it has both /compatibility/v1 chat and native /v2/embed); preserve its batch limit and body-field quirks in the embedding profile.\n\nImage-generation adapter (stability, ideogram, recraft) β€” one image-generation adapter family: explicit multipart vs JSON request profile, base64-vs-URL response profile, custom auth-header support, model-path mapping as data. SSRF and bounded-read policy remain shared mandatory behavior, not per-vendor opt-outs.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Shared adapter needed (9)","lvl3":""}},
8944
8944
  {"objectID":"14456bd556dd45363546785079362ce7acbd26bfa6a65a06c638acb656fbbce2","title":"Must remain class (13)","url":"/docs/provider-integration/migration-ledger#must-remain-class-13","content":"| Provider | Why |\n| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| bedrock | AWS SigV4/Converse protocol, custom loop, not OpenAI-compatible. Tier 4. |\n| openai | Chat portion is catalog-shaped, but embeddings, image generation, and OpenAI-specific telemetry/errors are executable behavior. |\n| vertex | Two native protocols (Google GenAI + Anthropic-on-Vertex) and multiple modality pipelines behind one provider identity. |\n| anthropic | Native Messages API auth/message/tool semantics are executable protocol behavior.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Must remain class (13)","lvl3":""}},
8945
8945
  {"objectID":"a4f69e09308f075830f2efa7c1b0126236c5ec0fc12bfe08be21764a627e47a5","title":"Must remain core class (1)","url":"/docs/provider-integration/migration-ledger#must-remain-core-class-1","content":"| Provider | Why |\n| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| openai-compatible | This is the generic protocol surface itself, not a direct vendor. It should consume shared descriptor/config primitives but must never become a fixed-vendor JSON row β€” collapsing it into the catalog would conflate \"the adapter\" with \"an entry in the adapter's catalog.\" |","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Must remain core class (1)","lvl3":""}},
8946
- {"objectID":"235850085d9102413140920b9d5e5e2ff6113d007c865f5d78012af80fbf1843","title":"Suggested execution order","url":"/docs/provider-integration/migration-ledger#suggested-execution-order","content":"Steps 1–2 below (mistral; huggingface, deepseek) are complete β€” see Migrated above. What remains:\nThree shared adapters (local-runtime, embedding-only, image-generation) β€” each unlocks 3 providers at once; build once, migrate three.\ngoogle-ai descriptor-only JSON metadata β€” proof of concept for moving static descriptor data out of a \"must remain class\" provider without touching its execution.\nDirect-vendor \"must remain class\" providers (bedrock, openai, vertex, anthropic, azure, sagemaker, nvidia-nim) get descriptor-only JSON metadata migrations, execution untouched β€” lower priority, cosmetic consolidation only.\nAggregators (litellm, openrouter), the core adapter (openai-compatible), and the decision-only providers (typesafe, laya) are excluded from the first-class-count migration priority entirely β€” the first three add no direct-vendor coverage however they're implemented, and typesafe/laya are decide-only providers with no generate/stream surface to migrate at all.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Suggested execution order","lvl3":""}},
8946
+ {"objectID":"235850085d9102413140920b9d5e5e2ff6113d007c865f5d78012af80fbf1843","title":"Suggested execution order","url":"/docs/provider-integration/migration-ledger#suggested-execution-order","content":"The former steps 1–2 below (mistral; huggingface, deepseek) are complete β€” see Migrated above. What remains:\nThree shared adapters (local-runtime, embedding-only, image-generation) β€” each unlocks 3 providers at once; build once, migrate three.\ngoogle-ai descriptor-only JSON metadata β€” proof of concept for moving static descriptor data out of a \"must remain class\" provider without touching its execution.\nDirect-vendor \"must remain class\" providers (bedrock, openai, vertex, anthropic, azure, sagemaker, nvidia-nim) get descriptor-only JSON metadata migrations, execution untouched β€” lower priority, cosmetic consolidation only.\nAggregators (litellm, openrouter), the core adapter (openai-compatible), and the decision-only providers (typesafe, laya) are excluded from the first-class-count migration priority entirely β€” the first three add no direct-vendor coverage however they're implemented, and typesafe/laya are decide-only providers with no generate/stream surface to migrate at all.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Suggested execution order","lvl3":""}},
8947
8947
  {"objectID":"6122b2e83358a45c64da87c1ca80a2d579cdfb087a6d9dc58b1e02805296b14a","title":"OpenAI-Compatible Provider Catalog","url":"/docs/provider-integration/openai-compat-catalog","content":"OpenAI-Compatible Provider Catalog\n\nSixteen OpenAI-compatible providers β€” API Route, Baseten, SambaNova,\nCerebras, Groq, xAI, Together AI, Fireworks AI, Perplexity, Mistral,\nCloudflare Workers AI, GMI Cloud, Inception Labs, io.net Intelligence,\nMancer, Upstage β€” are registered from one JSON file each, under\nsrc/lib/providers/catalog/<id>.json, and served by one generic class,\nConfiguredOpenAICompatProvider\n(src/lib/providers/configuredOpenAICompat.ts). Adding another provider to\nthis family means adding one JSON file β€” no subclass, no registry edit, no\nhand-written enum member, no test edit.\n\nThe JSON is the source of truth\n\nOPENAI_COMPAT_CATALOG still exists and keeps its name and element type,\nbut it is now built by the loader (src/lib/providers/catalog/loader.ts)\nfrom the JSON files rather than hand-written. Two consumers read the JSON:\nCodegen (pnpm run codegen:catalog) writes the compile-time\n artifacts into marked regions β€” the AIProviderName member, the\n <Name>Models enum, the NeurolinkCredentials key β€” plus the generated\n index. Pre-commit and CI fail on stale output.\nThe loader builds the runtime entry; the descriptor, config options,\n context windows, pricing, vision map and model-choice tables all derive\n from it, as do the provider test suites' rows and counts.\n\nEach file is validated by a zod schema (src/lib/providers/catalog/schema.ts)\nwith a mirrored provider-catalog.schema.json for editor squiggles.\nProbe evidence (roster/auth/billing dates, live-matrix result, PR URL)\nlives in the file's evidence block β€” the old\ndocs/provider-integration/manifests/<id>.json files were folded into it.\n\nField-by-field reference and the escape hatches:\ntiers/tier-2-catalog-entry.md. Design rationale and the approved rulings:\ndocs/superpowers/plans/2026-08-28-provider-json-catalog-spec.md.\n\nWhen a provider belongs in the catalog\n\nA provider belongs in the JSON catalog if it needs only:\na credential (API key, optionally an extra field like Cloudflare's account id)\na base URL (static default + optional env override, or computed from an\n extra credential field)\na default/fallback model\nerror-message classification (auth / rate-limit / invalid-model / generic)\na named, closed catalog quirk. DeepSeek is the worked example: it 400s on\n json_schema structured-output requests, so deepseek.json sets\n quirks.responseFormatDowngrade: \"json-schema-to-json-object\" and the\n generic ConfiguredOpenAICompatProvider downgrades to json_object before\n sending β€” no subclass. It also sets quirks.replayReasoningContent: true:\n DeepSeek documents that each assistant turn's reasoning_content must go\n back on later requests once tools are in play, so the shared message\n converter and the streaming tool loop send it β€” for this quirk only, since\n strict OpenAI-compatible backends reject the unknown field.\na wire-proven capability such as\n capabilities.structuredOutputWithTools. The generic provider suppresses\n response_format when tools are attached by default; an explicit true\n keeps it on the same generate() or stream() request. Set this only after\n a combined tools-plus-schema request returned successfully. Separate tool\n and structured-output probes are not evidence for the combined capability.\n A stale opt-in is still protected by the runtime conflict retry, which drops\n structured output and retries rather than losing the turn.\n\nThe currently opted-in providers are Baseten, DeepSeek, Fireworks AI, GMI\nCloud, Inception Labs, io.net Intelligence, Novita AI, Together AI, Upstage and\nxAI. API Route remains opted out because its evidence verifies the features\nseparately, not together in one request. Mistral remains opted out because its\ncombined probes returned 429 twice, not a successful capability response.\n\nWhen a provider needs a dedicated subclass instead\n\nAzure OpenAI is deliberately not in the catalog because it overrides real\nrequest-shaping behavior that no named catalog quirk expresses:\nAzure OpenAI (src/lib/providers/azureOpenai.ts) overrides four hooks:\n getChatCompletionsURL (deployment-name URL routing across two Azure\n endpoint schemes), getAuthHeaders (Azure's api-key header instead of\n Authorization: Bearer), adjustRequestBody (renames max_tokens to\n max_completion_tokens for o-series/gpt-5+ deployments), and\n suppressResponseFormatWithTools (Azure supports both at once).\n\nIf a future provider needs any hook beyond the 3 mandatory ones\n(getProviderName, getDefaultModel, formatProviderError) or the 2\npurely-declarative optional ones (getFallbackModelName,\ngetFallbackModels) and that hook is not already a named catalog quirk, it\nneeds either a new closed quirk (the DeepSeek route) or a dedicated subclass\n(the Azure OpenAI route).\n\nError-message fidelity\n\nEach entry's errorRules is a direct, order-preserving translation of its\noriginal subclass's formatProviderError if/else ladder into rule data\n(status code and/or case-insensitive pattern), classified via\nclassifyProviderError()\n(src/lib/utils/err","hierarchy":{"lvl0":"Provider Integration","lvl1":"OpenAI-Compatible Provider Catalog","lvl2":"","lvl3":""}},
8948
8948
  {"objectID":"9a91a5b4a32a9f1e89c6a28f762c3594c4a39d96d32cc9e6e1fa0f5cb3f609e4","title":"OpenAI-Compatible Provider Catalog","url":"/docs/provider-integration/openai-compat-catalog#openai-compatible-provider-catalog","content":"Sixteen OpenAI-compatible providers β€” API Route, Baseten, SambaNova,\nCerebras, Groq, xAI, Together AI, Fireworks AI, Perplexity, Mistral,\nCloudflare Workers AI, GMI Cloud, Inception Labs, io.net Intelligence,\nMancer, Upstage β€” are registered from one JSON file each, under\nsrc/lib/providers/catalog/<id>.json, and served by one generic class,\nConfiguredOpenAICompatProvider\n(src/lib/providers/configuredOpenAICompat.ts). Adding another provider to\nthis family means adding one JSON file β€” no subclass, no registry edit, no\nhand-written enum member, no test edit.","hierarchy":{"lvl0":"Provider Integration","lvl1":"OpenAI-Compatible Provider Catalog","lvl2":"OpenAI-Compatible Provider Catalog","lvl3":""}},
8949
8949
  {"objectID":"16e60ee66171009a6638b5110cc8693f90c1a2cfde796c6932c3512d7f7421fb","title":"The JSON is the source of truth","url":"/docs/provider-integration/openai-compat-catalog#the-json-is-the-source-of-truth","content":"OPENAI_COMPAT_CATALOG still exists and keeps its name and element type,\nbut it is now built by the loader (src/lib/providers/catalog/loader.ts)\nfrom the JSON files rather than hand-written. Two consumers read the JSON:\nCodegen (pnpm run codegen:catalog) writes the compile-time\n artifacts into marked regions β€” the AIProviderName member, the\n <Name>Models enum, the NeurolinkCredentials key β€” plus the generated\n index. Pre-commit and CI fail on stale output.\nThe loader builds the runtime entry; the descriptor, config options,\n context windows, pricing, vision map and model-choice tables all derive\n from it, as do the provider test suites' rows and counts.\n\nEach file is validated by a zod schema (src/lib/providers/catalog/schema.ts)\nwith a mirrored provider-catalog.schema.json for editor squiggles.\nProbe evidence (roster/auth/billing dates, live-matrix result, PR URL)\nlives in the file's evidence block β€” the old\ndocs/provider-integration/manifests/<id>.json files were folded into it.\n\nField-by-field reference and the escape hatches:\ntiers/tier-2-catalog-entry.md. Design rationale and the approved rulings:\ndocs/superpowers/plans/2026-08-28-provider-json-catalog-spec.md.","hierarchy":{"lvl0":"Provider Integration","lvl1":"OpenAI-Compatible Provider Catalog","lvl2":"The JSON is the source of truth","lvl3":""}},
@@ -10196,14 +10196,14 @@
10196
10196
  {"objectID":"f2ff95a8517aa1bc258524b78aac7ade9816a77b7432d61a3b412f397f7d689b","title":"Client-bundle dependencies β€” needs-review","url":"/docs/security/subpackage-advisories#client-bundle-dependencies-needs-review","content":"| Severity | Module | GHSA | Chain | Why it's different | Triage |\n| --- | --- | --- | --- | --- | --- |\n| Moderate | @opentelemetry/core | GHSA-8988-4f7v-96qf | posthog-js > @opentelemetry/exporter-logs-otlp-http > @opentelemetry/core (2 paths) | posthog-js ships in the browser bundle for analytics; this specific package is the OTLP log-export path, which sends telemetry out, it doesn't parse attacker-supplied baggage headers inbound. | Accept-risk β€” outbound-only code path; re-review if posthog-js is ever used to ingest, not just emit, telemetry. |\n| Moderate | protobufjs | GHSA-j3f2-48v5-ccww, GHSA-jfj6-75fj-8934 | posthog-js > @opentelemetry/exporter-logs-otlp-http > @opentelemetry/otlp-transformer > protobufjs | Same outbound-only OTLP export path as above. | Accept-risk, same reasoning. |\n| Moderate | fflate | GHSA-px8p-9vwx-vf98 | posthog-js > fflate | Ships in the client bundle; posthog-js uses it for its own asset compression, not for parsing user-supplied archives. | Accept-risk, low reachability. |\n| Moderate | dompurify | GHSA-55q2-fjhq-7xh7, GHSA-cmwh-pvxp-8882 | isomorphic-dompurify > dompurify | Sanitizes HTML that ends up rendered in the browser. Content sanitized here is this repo's own authored MDX/docs, not arbitrary visitor input β€” but a sanitizer bypass is exactly the class of bug that matters most if that assumption ever changes. | Needs-upgrade. A fixed dompurify is published (>=3.4.13 / >=3.4.11); whatever pulls isomorphic-dompurify should get it bumped, or the dependency dropped if it renders nothing but static build-time content. |\n| Low | dompurify | GHSA-c2j3-45gr-mqc4 | isomorphic-dompurify > dompurify | Same chain as above. | Needs-upgrade, same fix as the moderate dompurify rows. |","hierarchy":{"lvl0":"Security","lvl1":"Subpackage Dependency Advisories","lvl2":"Client-bundle dependencies β€” needs-review","lvl3":""}},
10197
10197
  {"objectID":"d060d41f0402f33d02d94eeae0d16c494860addcf47ca14b51ab2fabef4ee1ce","title":"Recommendation","url":"/docs/security/subpackage-advisories#recommendation","content":"No action required to keep the critical-only gate green β€” it already\n is, in both trees, and stays that way regardless of anything in this\n document.\nlanding/: the next time landing/package.json is edited, add\n brace-expansion: \">=5.0.9\" and fflate: \">=0.8.3\" to its existing\n pnpm.overrides block (it already carries five other overrides for the\n same class of transitive-vulnerability problem β€” tar, devalue,\n rollup, minimatch, cookie, esbuild β€” so this is precedent, not a\n new pattern). That closes all 4 brace-expansion findings and the one\n runtime-reachable finding in either tree.\ndocs-site/: find and either upgrade or remove whatever pulls in\n isomorphic-dompurify; it is the only docs-site/ finding with a\n reachable-in-the-browser exploit class (XSS) and an available fix.\n Everything else in docs-site/ tracks @docusaurus/core's own upstream\n releases β€” re-measure after the next Docusaurus bump rather than chasing\n individual transitive pins.\nRaising --audit-level from critical to high in ci.yml needs the\n two needs-upgrade items above resolved first (per ci.yml's own\n comment); the accept-risk rows would still need an explicit\n pnpm audit --ignore (or equivalent) per advisory to avoid re-blocking on\n findings this document already reviewed. Not done as part of this pass β€”\n flagged here for whoever picks that decision up.","hierarchy":{"lvl0":"Security","lvl1":"Subpackage Dependency Advisories","lvl2":"Recommendation","lvl3":""}},
10198
10198
  {"objectID":"1080399eefc78beb7860fc2379dec788e8e825df30255c2e9061b40fbbdc767b","title":"Next review","url":"/docs/security/subpackage-advisories#next-review","content":"Re-run the Methodology commands: at minimum whenever\nlanding/pnpm-lock.yaml or docs-site/pnpm-lock.yaml changes, and\notherwise on the same quarterly cadence as docs/development/package-overrides.md.","hierarchy":{"lvl0":"Security","lvl1":"Subpackage Dependency Advisories","lvl2":"Next review","lvl3":""}},
10199
- {"objectID":"2d54764a0f90619f4dfe26cb0c85428f75091a63091f6cc73b70defe3139e6a8","title":"NeuroLink Usage Guide","url":"/docs/skills/neurolink-guide/SKILL","content":"NeuroLink Usage Guide\n\nNeuroLink is an enterprise AI development platform providing unified access to 44 AI providers (text, decision-making, voice, multimodal) through a single API. It ships as both a TypeScript SDK (@juspay/neurolink) and a professional CLI.\n\nQuick Navigation\n\nBased on your query, I'll guide you to the right documentation:\nGetting Started β†’ Read sdk-quickstart.md\nProvider Setup β†’ Read providers.md\nMultimodal (images, PDFs, files) β†’ Read multimodal.md\nMCP Tools Integration β†’ Read tools-mcp.md\nRAG Pipelines β†’ Read rag-integration.md\nConversation Memory β†’ Read memory-conversations.md\nCLI Commands β†’ Read cli-reference.md\nAdvanced Features β†’ Read advanced-features.md\nTroubleshooting β†’ Read troubleshooting.md\n\nTopic Routing\n\nIf the user asked about $ARGUMENTS:\n\n| Topic Keywords | Reference File |\n| -------------------------------------------------------------------------- | ----------------------- |\n| install, setup, start, begin, quickstart | sdk-quickstart.md |\n| provider, openai, anthropic, vertex, bedrock, azure, gemini, claude, model | providers.md |\n| image, pdf, csv, excel, document, file, multimodal, vision | multimodal.md |\n| tool, mcp, server, GitHub, external, function | tools-mcp.md |\n| rag, retrieval, chunk, vector, embed, document search | rag-integration.md |\n| memory, conversation, history, session, redis, context | memory-conversations.md |\n| cli, command, terminal, generate, stream, loop, serve | cli-reference.md |\n| hitl, workflow, agent, observe, telemetry, deploy, server | advanced-features.md |\n| error, issue, problem, fix, debug, not working | troubleshooting.md |\n\nInstallation\n\nMinimal Example\n\nKey Capabilities\n\n| Feature | Description |\n| ----------------- | ---------------------------------------------------------------- |\n| 40 Providers | OpenAI, Anthropic, Vertex, Bedrock, Azure, Mistral, Ollama, etc. |\n| Multimodal | Images, PDFs, CSV, Excel, Word, 50+ file types |\n| MCP Tools | 58+ tools via Model Context Protocol |\n| RAG | Built-in chunking, embedding, vector search |\n| Memory | Conversation history with Redis support |\n| Streaming | Real-time token streaming |\n| HITL | Human-in-the-loop approval workflows |\n| Observability | Langfuse, OpenTelemetry integration |\n\nCode Templates\n\nReady-to-use examples in templates/:\ntemplates/basic-setup.ts - Basic SDK initialization\ntemplates/streaming.ts - Streaming responses\ntemplates/with-tools.ts - Tool integration\ntemplates/rag-pipeline.ts - RAG usage\ntemplates/server-deploy.ts - HTTP server deployment\n\nCLI Quick Reference\n\nEnvironment Variables\n\nSet up your provider credentials:\n\nType Imports\n\nGetting Help\nCheck the relevant reference file above\nReview troubleshooting.md for common issues\nLook at code templates in templates/\nRead the full CLAUDE.md in the project root for architecture details\n\nInstructions for Claude: Based on the user's query about $ARGUMENTS, read the appropriate reference file and provide specific guidance. If no topic is specified, give a general overview of NeuroLink capabilities and ask what they'd like help with.","hierarchy":{"lvl0":"Skills","lvl1":"NeuroLink Usage Guide","lvl2":"","lvl3":""}},
10199
+ {"objectID":"2d54764a0f90619f4dfe26cb0c85428f75091a63091f6cc73b70defe3139e6a8","title":"NeuroLink Usage Guide","url":"/docs/skills/neurolink-guide/SKILL","content":"NeuroLink Usage Guide\n\nNeuroLink is an enterprise AI development platform providing unified access to 44 AI providers (text, decision-making, voice, multimodal) through a single API. It ships as both a TypeScript SDK (@juspay/neurolink) and a professional CLI.\n\nQuick Navigation\n\nBased on your query, I'll guide you to the right documentation:\nGetting Started β†’ Read sdk-quickstart.md\nProvider Setup β†’ Read providers.md\nMultimodal (images, PDFs, files) β†’ Read multimodal.md\nMCP Tools Integration β†’ Read tools-mcp.md\nRAG Pipelines β†’ Read rag-integration.md\nConversation Memory β†’ Read memory-conversations.md\nCLI Commands β†’ Read cli-reference.md\nAdvanced Features β†’ Read advanced-features.md\nTroubleshooting β†’ Read troubleshooting.md\n\nTopic Routing\n\nIf the user asked about $ARGUMENTS:\n\n| Topic Keywords | Reference File |\n| -------------------------------------------------------------------------- | ----------------------- |\n| install, setup, start, begin, quickstart | sdk-quickstart.md |\n| provider, openai, anthropic, vertex, bedrock, azure, gemini, claude, model | providers.md |\n| image, pdf, csv, excel, document, file, multimodal, vision | multimodal.md |\n| tool, mcp, server, GitHub, external, function | tools-mcp.md |\n| rag, retrieval, chunk, vector, embed, document search | rag-integration.md |\n| memory, conversation, history, session, redis, context | memory-conversations.md |\n| cli, command, terminal, generate, stream, loop, serve | cli-reference.md |\n| hitl, workflow, agent, observe, telemetry, deploy, server | advanced-features.md |\n| error, issue, problem, fix, debug, not working | troubleshooting.md |\n\nInstallation\n\nMinimal Example\n\nKey Capabilities\n\n| Feature | Description |\n| ----------------- | ---------------------------------------------------------------- |\n| 44 Providers | OpenAI, Anthropic, Vertex, Bedrock, Azure, Mistral, Ollama, etc. |\n| Multimodal | Images, PDFs, CSV, Excel, Word, 50+ file types |\n| MCP Tools | 58+ tools via Model Context Protocol |\n| RAG | Built-in chunking, embedding, vector search |\n| Memory | Conversation history with Redis support |\n| Streaming | Real-time token streaming |\n| HITL | Human-in-the-loop approval workflows |\n| Observability | Langfuse, OpenTelemetry integration |\n\nCode Templates\n\nReady-to-use examples in templates/:\ntemplates/basic-setup.ts - Basic SDK initialization\ntemplates/streaming.ts - Streaming responses\ntemplates/with-tools.ts - Tool integration\ntemplates/rag-pipeline.ts - RAG usage\ntemplates/server-deploy.ts - HTTP server deployment\n\nCLI Quick Reference\n\nEnvironment Variables\n\nSet up your provider credentials:\n\nType Imports\n\nGetting Help\nCheck the relevant reference file above\nReview troubleshooting.md for common issues\nLook at code templates in templates/\nRead the full CLAUDE.md in the project root for architecture details\n\nInstructions for Claude: Based on the user's query about $ARGUMENTS, read the appropriate reference file and provide specific guidance. If no topic is specified, give a general overview of NeuroLink capabilities and ask what they'd like help with.","hierarchy":{"lvl0":"Skills","lvl1":"NeuroLink Usage Guide","lvl2":"","lvl3":""}},
10200
10200
  {"objectID":"96aa85169d914ba98c31e12923e593471d8584415add8a7583153796c856955d","title":"NeuroLink Usage Guide","url":"/docs/skills/neurolink-guide/SKILL#neurolink-usage-guide","content":"NeuroLink is an enterprise AI development platform providing unified access to 44 AI providers (text, decision-making, voice, multimodal) through a single API. It ships as both a TypeScript SDK (@juspay/neurolink) and a professional CLI.","hierarchy":{"lvl0":"Skills","lvl1":"NeuroLink Usage Guide","lvl2":"NeuroLink Usage Guide","lvl3":""}},
10201
10201
  {"objectID":"21b1f230a7feb082ffa13eb9ce75c5ec9268a2a0d7eac96bb086d500d9f3e6c7","title":"Quick Navigation","url":"/docs/skills/neurolink-guide/SKILL#quick-navigation","content":"Based on your query, I'll guide you to the right documentation:\nGetting Started β†’ Read sdk-quickstart.md\nProvider Setup β†’ Read providers.md\nMultimodal (images, PDFs, files) β†’ Read multimodal.md\nMCP Tools Integration β†’ Read tools-mcp.md\nRAG Pipelines β†’ Read rag-integration.md\nConversation Memory β†’ Read memory-conversations.md\nCLI Commands β†’ Read cli-reference.md\nAdvanced Features β†’ Read advanced-features.md\nTroubleshooting β†’ Read troubleshooting.md","hierarchy":{"lvl0":"Skills","lvl1":"NeuroLink Usage Guide","lvl2":"Quick Navigation","lvl3":""}},
10202
10202
  {"objectID":"e605615042f0ca67afbb7328516b1ae5c0f0863857354643925f4b34f31bc28a","title":"Topic Routing","url":"/docs/skills/neurolink-guide/SKILL#topic-routing","content":"If the user asked about $ARGUMENTS:\n\n| Topic Keywords | Reference File |\n| -------------------------------------------------------------------------- | ----------------------- |\n| install, setup, start, begin, quickstart | sdk-quickstart.md |\n| provider, openai, anthropic, vertex, bedrock, azure, gemini, claude, model | providers.md |\n| image, pdf, csv, excel, document, file, multimodal, vision | multimodal.md |\n| tool, mcp, server, GitHub, external, function | tools-mcp.md |\n| rag, retrieval, chunk, vector, embed, document search | rag-integration.md |\n| memory, conversation, history, session, redis, context | memory-conversations.md |\n| cli, command, terminal, generate, stream, loop, serve | cli-reference.md |\n| hitl, workflow, agent, observe, telemetry, deploy, server | advanced-features.md |\n| error, issue, problem, fix, debug, not working | troubleshooting.md |","hierarchy":{"lvl0":"Skills","lvl1":"NeuroLink Usage Guide","lvl2":"Topic Routing","lvl3":""}},
10203
10203
  {"objectID":"e16256b54ee1cd840e3970192de5a57174044100e1c685badadf0e717b4b3a00","title":"Installation","url":"/docs/skills/neurolink-guide/SKILL#installation","content":"`bash\nnpm install @juspay/neurolink","hierarchy":{"lvl0":"Skills","lvl1":"NeuroLink Usage Guide","lvl2":"Installation","lvl3":""}},
10204
10204
  {"objectID":"90d0cc22bb8b605323ec98ea6e43db5a596b931d0b41e310504be40d6ff4f0cc","title":"or","url":"/docs/skills/neurolink-guide/SKILL#or","content":"pnpm add @juspay/neurolink","hierarchy":{"lvl0":"Skills","lvl1":"NeuroLink Usage Guide","lvl2":"or","lvl3":""}},
10205
10205
  {"objectID":"d1eb1a2c3cefd0cd4e82e8e0ec91fdd2d3425bf01fb2afdc9abc85ee3afff52a","title":"or","url":"/docs/skills/neurolink-guide/SKILL#or-1","content":"yarn add @juspay/neurolink\n`","hierarchy":{"lvl0":"Skills","lvl1":"NeuroLink Usage Guide","lvl2":"or","lvl3":""}},
10206
- {"objectID":"b83b01d704e8b8b320f14011bcefb90b05a6145656cbe07f1eaa885a91416a1e","title":"Key Capabilities","url":"/docs/skills/neurolink-guide/SKILL#key-capabilities","content":"| Feature | Description |\n| ----------------- | ---------------------------------------------------------------- |\n| 40 Providers | OpenAI, Anthropic, Vertex, Bedrock, Azure, Mistral, Ollama, etc. |\n| Multimodal | Images, PDFs, CSV, Excel, Word, 50+ file types |\n| MCP Tools | 58+ tools via Model Context Protocol |\n| RAG | Built-in chunking, embedding, vector search |\n| Memory | Conversation history with Redis support |\n| Streaming | Real-time token streaming |\n| HITL | Human-in-the-loop approval workflows |\n| Observability | Langfuse, OpenTelemetry integration |","hierarchy":{"lvl0":"Skills","lvl1":"NeuroLink Usage Guide","lvl2":"Key Capabilities","lvl3":""}},
10206
+ {"objectID":"b83b01d704e8b8b320f14011bcefb90b05a6145656cbe07f1eaa885a91416a1e","title":"Key Capabilities","url":"/docs/skills/neurolink-guide/SKILL#key-capabilities","content":"| Feature | Description |\n| ----------------- | ---------------------------------------------------------------- |\n| 44 Providers | OpenAI, Anthropic, Vertex, Bedrock, Azure, Mistral, Ollama, etc. |\n| Multimodal | Images, PDFs, CSV, Excel, Word, 50+ file types |\n| MCP Tools | 58+ tools via Model Context Protocol |\n| RAG | Built-in chunking, embedding, vector search |\n| Memory | Conversation history with Redis support |\n| Streaming | Real-time token streaming |\n| HITL | Human-in-the-loop approval workflows |\n| Observability | Langfuse, OpenTelemetry integration |","hierarchy":{"lvl0":"Skills","lvl1":"NeuroLink Usage Guide","lvl2":"Key Capabilities","lvl3":""}},
10207
10207
  {"objectID":"7c62327f85fac881c0aac6f869de31dc4136684a6a52de22a2e71ee7b5c42249","title":"Code Templates","url":"/docs/skills/neurolink-guide/SKILL#code-templates","content":"Ready-to-use examples in templates/:\ntemplates/basic-setup.ts - Basic SDK initialization\ntemplates/streaming.ts - Streaming responses\ntemplates/with-tools.ts - Tool integration\ntemplates/rag-pipeline.ts - RAG usage\ntemplates/server-deploy.ts - HTTP server deployment","hierarchy":{"lvl0":"Skills","lvl1":"NeuroLink Usage Guide","lvl2":"Code Templates","lvl3":""}},
10208
10208
  {"objectID":"d246524cc9ee34af8df00dea1fed367e2889a07e140681aa82675e41294c0ee7","title":"CLI Quick Reference","url":"/docs/skills/neurolink-guide/SKILL#cli-quick-reference","content":"`bash","hierarchy":{"lvl0":"Skills","lvl1":"NeuroLink Usage Guide","lvl2":"CLI Quick Reference","lvl3":""}},
10209
10209
  {"objectID":"d3f7af50ff6bbbb77e5eee065fed0c6a826ef462086f48c15eb152f7b5629f05","title":"Generate content","url":"/docs/skills/neurolink-guide/SKILL#generate-content","content":"neurolink generate \"Your prompt\"","hierarchy":{"lvl0":"Skills","lvl1":"NeuroLink Usage Guide","lvl2":"Generate content","lvl3":""}},
@@ -10772,6 +10772,116 @@
10772
10772
  {"objectID":"25e1ac265c89596a09bce35c4ba7b8d82ccf92f016708d1f6f4826b290af00ae","title":"Delivery","url":"/docs/superpowers/specs/2026-09-23-proxy-account-routing-policies-design#delivery","content":"juspay/neurolink merges one commit per PR, so two PRs:\nRefactor, no behaviour change: extract the comparator into accountRanking.ts and count in-flight on the unlimited lease. Proven by the replay and the existing route tests.\nPolicies: headroom-first, prefer-primary, session affinity, spill, config, telemetry, /status, and the documentation correction below.","hierarchy":{"lvl0":"Superpowers","lvl1":"Proxy Account Routing Policies Design","lvl2":"Delivery","lvl3":""}},
10773
10773
  {"objectID":"06eb4e8ea79a4077f7cb445c1ec17985516046ab28d49d3c87b85ade0155f2c1","title":"Documentation","url":"/docs/superpowers/specs/2026-09-23-proxy-account-routing-policies-design#documentation","content":"docs/features/claude-proxy-config-reference.md gains the five keys. The primary-account text and source comments that still say the primary is \"tried first under fill-first\" are corrected: with quota routing the primary is the final tiebreaker unless prefer-primary is set.","hierarchy":{"lvl0":"Superpowers","lvl1":"Proxy Account Routing Policies Design","lvl2":"Documentation","lvl3":""}},
10774
10774
  {"objectID":"1cf022d6f43b961b6fd1c13d8a5677077f9109584a3a5e67d837c4d5f6e613da","title":"Out of scope","url":"/docs/superpowers/specs/2026-09-23-proxy-account-routing-policies-design#out-of-scope","content":"Per-model policies, weighted scoring, persisting affinity across restarts, an account reserve, and changes to cooldown classification, in-stream rate-limit handling or state persistence. Those last three are separate designs.","hierarchy":{"lvl0":"Superpowers","lvl1":"Proxy Account Routing Policies Design","lvl2":"Out of scope","lvl3":""}},
10775
+ {"objectID":"f0109d9239beed7372578f5d0ad41b745b321c526407db0d3bbb32adced24e2e","title":"Codex Outbound Fallback — Design","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design","content":"Codex Outbound Fallback — Design\n\nStatus: design complete, implementation not started. Produced by 22 parallel agents\n(6 grounding, 8 design, 8 adversarial review) plus 8 resolution passes; every design\nclaim below was checked against the code by a reviewer whose brief was to refute it.\n\nGoal\n\nA native Codex client request that its own account pool cannot serve currently fails to the\nclient. This design gives the Codex engine an outbound fallback chain to the Anthropic OAuth\npool and to Vertex, so the request is served instead — with prompt caching preserved across\nthe hop, tool calls translated faithfully in both directions, and no client-visible protocol\nanomaly.\n\nEvidence\nsrc/lib/server/routes/codexProxyRoutes.ts has no outbound fallback. Its only fallback\n references are a string-default helper (line 138) and code recognising when the Codex engine\n is itself invoked as an inner Anthropic fallback (lines 666, 817, CODEX_FALLBACK_METADATA_KEY\n at 109). On pool exhaustion it returns a terminal error: buildCodexErrorResponse\n (1458-1462), or buildCodexQuotaExhaustedResponse (909-914) when every account is already\n cooling.\nThree directions exist and work: Claude Code → Anthropic pool; Claude/Anthropic → Codex\n (executeClaudeCodexFallback, claudeProxyRoutes.ts:5499, called at 6131, in-process — no\n HTTP hop); Claude/Anthropic → Vertex (vertexAnthropicFallback.ts:611, gated on\n isVertexAnthropicModel, 576).\nThree do not exist: Vertex → Anthropic, native Codex → Anthropic, native Codex →\n Vertex. PR #1782 fixed translation defects in the existing Claude → Vertex direction; it\n did not add a reverse path.\nCodex prompt caching is live but partial. proxy_tokens_cache_read by model:\n gpt-5.6-sol 566,657,536; gpt-6-astra 3,285,888; gpt-5.6-terra 490,752;\n gpt-5.6-luna 5,888. proxy_tokens_cache_creation is 0 for every Codex series, which is\n correct — OpenAI caching is automatic and has no explicit write.\nThe caching asymmetry is the central design constraint. Anthropic caching is explicit:\n up to 4 cache_control breakpoints over a tools → system → messages prefix, write at\n 1.25x base input (5-minute TTL) or 2x (1-hour), read at 0.1x, and each account holds its\n own cache. A Codex request translated to Anthropic arrives with no breakpoints at all,\n so it would be cached not at all unless the translator inserts them deliberately.\nSince Claude-on-Vertex speaks the Anthropic Messages wire format, one Codex→Anthropic\n translator covers both targets. There is no smaller Vertex-only variant of this work.\n\nBuild order\n\nDependency-ordered; each step is one reviewable PR under the one-commit-per-PR policy. Default\noff at every step, so behaviour is byte-for-byte unchanged until the final enable.\n\n| # | PR | Depends on | Gate |\n| --- | ------------------------------------------------------------------- | ---------- | -------------------------------------------- |\n| 1 | IR types + codec contract (src/lib/types/proxyIR.ts) | — | typecheck; exhaustiveness is a compile error |\n| 2 | Request codec Codex → Anthropic (codexOutboundFallback.ts) | 1 | offline shape suite |\n| 3 | Response/stream codec Anthropic → Codex | 1 | offline event-order suite |\n| 4 | Tool fidelity + id correlation | 2, 3 | offline round-trip suite |\n| 5 | Cache breakpoints + prefix byte-stability (codexOutboundCache.ts) | 2 | byte-stability assertion across two turns |\n| 6 | Trigger policy, commitment rule, loop prevention, accounting | 2-4 | totality + commitment suites |\n| 7 | Config keys, kill switch, metrics | 6 | config validation suite |\n| 8 | Enable + live model matrix | all | live pass criteria |\n\nOpen questions gating the build\n\nEvery one needs the same thing: real captured native Codex traffic. The repo has 4 synthetic\nfixtures and one real single-turn capture (test/fixtures/codex-response-usage.sse, captured\n2026-08-21). These are listed here because two of them can invalidate a whole section, so they\nshould be settled by capture before the PRs that depend on them are written.\n\n| Question | Blocks | Settled by |\n| ---------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------- |\n| Does the real Codex CLI accept a call_id it did not mint (a toolu_-shaped id)? | PR 4 | serve one turn through the fallback ","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"","lvl3":""}},
10776
+ {"objectID":"6034ef59cb5b3d2520fa92f2f181aca534a58aa28338f3411aa9d28d998e487e","title":"Codex Outbound Fallback β€” Design","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#codex-outbound-fallback-design","content":"Status: design complete, implementation not started. Produced by 22 parallel agents\n(6 grounding, 8 design, 8 adversarial review) plus 8 resolution passes; every design\nclaim below was checked against the code by a reviewer whose brief was to refute it.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Codex Outbound Fallback β€” Design","lvl3":""}},
10777
+ {"objectID":"580c5a06163d1e603bb34f5f3b51c78e4efa36e12426cf22b63706680af0ea56","title":"Goal","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#goal","content":"A native Codex client request that its own account pool cannot serve currently fails to the\nclient. This design gives the Codex engine an outbound fallback chain to the Anthropic OAuth\npool and to Vertex, so the request is served instead β€” with prompt caching preserved across\nthe hop, tool calls translated faithfully in both directions, and no client-visible protocol\nanomaly.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Goal","lvl3":""}},
10778
+ {"objectID":"ed180fb4ca61ad0027c4359503ac6ea54b391281020d32b2a9b498cd6c83abeb","title":"Evidence","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#evidence","content":"src/lib/server/routes/codexProxyRoutes.ts has no outbound fallback. Its only fallback\n references are a string-default helper (line 138) and code recognising when the Codex engine\n is itself invoked as an inner Anthropic fallback (lines 666, 817, CODEX_FALLBACK_METADATA_KEY\n at 109). On pool exhaustion it returns a terminal error: buildCodexErrorResponse\n (1458-1462), or buildCodexQuotaExhaustedResponse (909-914) when every account is already\n cooling.\nThree directions exist and work: Claude Code → Anthropic pool; Claude/Anthropic → Codex\n (executeClaudeCodexFallback, claudeProxyRoutes.ts:5499, called at 6131, in-process — no\n HTTP hop); Claude/Anthropic → Vertex (vertexAnthropicFallback.ts:611, gated on\n isVertexAnthropicModel, 576).\nThree do not exist: Vertex → Anthropic, native Codex → Anthropic, native Codex →\n Vertex. PR #1782 fixed translation defects in the existing Claude → Vertex direction; it\n did not add a reverse path.\nCodex prompt caching is live but partial. proxy_tokens_cache_read by model:\n gpt-5.6-sol 566,657,536; gpt-6-astra 3,285,888; gpt-5.6-terra 490,752;\n gpt-5.6-luna 5,888. proxy_tokens_cache_creation is 0 for every Codex series, which is\n correct — OpenAI caching is automatic and has no explicit write.\nThe caching asymmetry is the central design constraint. Anthropic caching is explicit:\n up to 4 cache_control breakpoints over a tools → system → messages prefix, write at\n 1.25x base input (5-minute TTL) or 2x (1-hour), read at 0.1x, and each account holds its\n own cache. A Codex request translated to Anthropic arrives with no breakpoints at all,\n so it would be cached not at all unless the translator inserts them deliberately.\nSince Claude-on-Vertex speaks the Anthropic Messages wire format, one Codex→Anthropic\n translator covers both targets. There is no smaller Vertex-only variant of this work.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"Evidence","lvl3":""}},
10779
+ {"objectID":"a5aa19ce68fa1175c4bade50ae303cc0a954bf1128588e294af993c049e2f466","title":"Build order","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#build-order","content":"Dependency-ordered; each step is one reviewable PR under the one-commit-per-PR policy. Default\noff at every step, so behaviour is byte-for-byte unchanged until the final enable.\n\n| # | PR | Depends on | Gate |\n| --- | ------------------------------------------------------------------- | ---------- | -------------------------------------------- |\n| 1 | IR types + codec contract (src/lib/types/proxyIR.ts) | β€” | typecheck; exhaustiveness is a compile error |\n| 2 | Request codec Codex β†’ Anthropic (codexOutboundFallback.ts) | 1 | offline shape suite |\n| 3 | Response/stream codec Anthropic β†’ Codex | 1 | offline event-order suite |\n| 4 | Tool fidelity + id correlation | 2, 3 | offline round-trip suite |\n| 5 | Cache breakpoints + prefix byte-stability (codexOutboundCache.ts) | 2 | byte-stability assertion across two turns |\n| 6 | Trigger policy, commitment rule, loop prevention, accounting | 2-4 | totality + commitment suites |\n| 7 | Config keys, kill switch, metrics | 6 | config validation suite |\n| 8 | Enable + live model matrix | all | live pass criteria |","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Build order","lvl3":""}},
10780
+ {"objectID":"db4fcb5c145b85c8e756be096fdda4d88c5f6fc576ec62653a8545735ff1a653","title":"Open questions gating the build","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#open-questions-gating-the-build","content":"Every one needs the same thing: real captured native Codex traffic. The repo has 4 synthetic\nfixtures and one real single-turn capture (test/fixtures/codex-response-usage.sse, captured\n2026-08-21). These are listed here because two of them can invalidate a whole section, so they\nshould be settled by capture before the PRs that depend on them are written.\n\n| Question | Blocks | Settled by |\n| ---------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------- |\n| Does the real Codex CLI accept a call_id it did not mint (a toolu_-shaped id)? | PR 4 | serve one turn through the fallback and observe the next turn |\n| Does Anthropic/Vertex accept a non-toolu_-shaped tool_use.id in history? | PR 4 | one live call with such an id in history |\n| Are the developer-role prefix blocks byte-identical turn to turn? | PR 5 | capture 2 turns of one session, diff input[0..4] |\n| Does a genuine first-turn request omit all of prompt_cache_key / thread_id / session_id? | PR 5 | capture one true first-turn request |\n| Does native Codex ever send top-level tools / reasoning / stream:false? | PR 2 | one live capture with non-default reasoning |\n| Is a resumed session's input full-history or incremental? | PR 2, 5 | capture two turns of a resumed session |","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Open questions gating the build","lvl3":""}},
10781
+ {"objectID":"a85c34c0265b0c27d696611075427124ef72062ef3e1248bf75ddc2f859229d0","title":"Contents","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#contents","content":"Translation layer: canonical IR and codec contract\nRequest translation: Codex Responses β†’ Anthropic Messages\nResponse translation: Anthropic β†’ Codex wire format\nTool-call fidelity in both directions\nPreserving prompt caching across the hop\nTrigger policy, commitment safety, loop prevention, accounting\nConfiguration surface and staged rollout\nValidation plan","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Contents","lvl3":""}},
10782
+ {"objectID":"62546125e30c54bebd2104e396943d1fb60478f7d22873e75792c81c408d2791","title":"Consolidated unresolved items","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#consolidated-unresolved-items","content":"ir-and-types β€” whether native Codex ever sends top-level reasoning/tools on a genuine inbound request β€” the one check that would settle it is a live-captured native Codex CLI request with non-default reasoning effort set.\nir-and-types β€” whether Anthropic's live API ever rejects consecutive same-role messages in some edge case β€” the one check that would settle it is a probe request against the real API with two consecutive user messages.\nir-and-types β€” the storage/lifetime contract for a resumed session's id map spanning multiple proxy requests β€” the one check that would settle it is reading how originSessionId/originThreadId are persisted by the session-affinity\nir-and-types β€” above.\nrequest-translation β€” in Β§10. It converts an unknown into a loud, caller-visible failure instead of a silent one, which is what the \"nothing may break silently\" requirement demands even without live traffic.\nrequest-translation β€” whether additional_tools/developer items can appear anywhere other than before the first user item in real traffic β€” the one check that would settle it: capture one real Codex CLI multi-turn session with a mid-conv\nrequest-translation β€” whether a resumed-session request's input is genuinely full-history or incremental β€” the one check that would settle it: capture one real resumed-session Codex Responses request (the referenced ~/.neurolink/reference/\n- **request-translation** β€” whether toolchoice or reasoning ever appear on genuine inbound requests at all (absent from all 4 fixtures) β€” the one check that would settle it: grep captured production Codex traffic logs (once available) for eith\n- **request-translation** β€” whether more than one additionaltools item can appear in one request β€” the one check that would settle it: same real-traffic capture as (1).\n- **response-translation** β€” a genuine live-captured native Codex Responses SSE transcript (text, tool-call, incomplete/error cases) β€” the check that would settle it is running a real Codex client through this","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Consolidated unresolved items","lvl3":""}},
10783
+ {"objectID":"b890fc666ae87c04302cb9122b852c6e394f3a6eb3ad2c2a3b90aed60a49e057","title":"Decision (kept)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#decision-kept","content":"Single canonical IR, not ClaudeRequest-as-hub, not pairwise codecs. Verified: openaiFormat.ts/geminiFormat.ts already use ClaudeRequest as an implicit hub only because it is also the literal Anthropic wire type; codexFallback.ts already needs a role cast ((message.role as string) !== \"system\", line 154) to special-case Claude Code's inline-system convention inside a converter meant to be neutral. A new file, src/lib/types/proxyIR.ts, holds a real wire-neutral IR. ClaudeRequest/ClaudeResponse (proxy.ts:154, :187) stay untouched β€” the Anthropic hot path (claudeProxyRoutes.ts) never changes.\n\nVertex needs no separate codec. Confirmed: executeVertexAnthropicFallback (vertexAnthropicFallback.ts:605-665) forwards the upstream body/stream untouched with a code comment that it is \"already Anthropic-shaped\"; buildVertexAnthropicPayload (line 399) only strips UNSUPPORTED_FIELDS = [\"model\", \"context_management\"] (line 42). Vertex reuses anthropicMessagesIRCodec.buildRequest's output as-is.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Decision (kept)","lvl3":""}},
10784
+ {"objectID":"a1d8a0c721ce132a2ececad931143e90dddbb50e47f04652ec692c3c3e12a040","title":"codexFallback.ts: left unrefactored this PR","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#codexfallbackts-left-unrefactored-this-pr","content":"It already implements, in the new vocabulary, the codex-responses request builder (convertClaudeRequestToCodex, line 407) and response parser (parseCodexFallbackSSE line 592, createCodexFallbackStream line 719) β€” never a request parser or response renderer, since Codex there is a fallback target, not a served client. Deferred to a named follow-up PR (one-commit-per-PR; mixing a mechanical port with new functional work is out of scope). Coexistence cost: convertClaudeRequestToCodex and the new anthropicMessagesIRCodec/codexNativeRequestCodec independently implement the same tool_choice bijection (any↔required, tool↔function) and the same reasoning-effort concept in reverse; a fix to one will not propagate until the follow-up ports codexFallback.ts onto the same 4 capabilities, verified byte-for-byte against test/continuous-test-suite-codex.ts.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"codexFallback.ts: left unrefactored this PR","lvl3":""}},
10785
+ {"objectID":"6a41248b50b7d11345c624537be172f4317d8a583d937c841b1f804ccfe4397f","title":"Grounding notes from the fixtures (all 4 read in full)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#grounding-notes-from-the-fixtures-all-4-read-in-full","content":"test/fixtures/codex-request-{exec-mode,interactive-mode,resumed-session,tool-result-turn}.json. Each fixture's body.input[0] is one {type:\"additional_tools\", role:\"developer\", tools:{functions:[...], collaboration:[...]}} item. Correction to the original design's blanket claim (\"no Anthropic tool shape maps to collaboration, genuinely unmappable\"): the collaboration bucket is not grammar-only. In all 4 fixtures it holds exactly two tools β€” exec (type:\"custom\", has a grammar string, no parameters) and request_review (no type tag, has a plain JSON-Schema parameters object, no grammar β€” structurally identical to a functions entry, just filed under the wrong bucket on the wire). Mappability is a per-tool fact keyed on presence of grammar, never inferable from which array a tool sits in.\n\nfunction_call.arguments is not guaranteed JSON: codex-request-tool-result-turn.json's function_call (call_id:\"call_synthetic_0001\", name:\"exec\") has arguments: \"ls -la\" β€” a bare string, since exec is grammar-typed. codexFallback.ts's parseFunctionArguments (line 466) throws today on exactly this input (JSON.parse(\"ls -la\") fails, hits catch, throws) β€” confirmed by reading the function. A tool-call IR part therefore needs argumentsRaw: string as the source of truth always, argumentsJson only when it happens to parse as an object.\n\nAll 4 fixtures: additional_tools is the single, first input item; 4 contiguous developer-role message items follow (indices 1-4); then 2 consecutive user-role message items (confirmed non-hypothetical β€” tool-result-turn's second user item carries an <environment_context> block, not a second real user turn); tool-result-turn additionally has one function_call/function_call_output pair. No fixture shows an assistant-role message item, even resumed-session. Top-level body keys across all 4: {model, stream, store, input} plus {session_id, thread_id} only on resumed-session β€” never top-level tools or reasoning.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Grounding notes from the fixtures (all 4 read in full)","lvl3":""}},
10786
+ {"objectID":"424fc6f4902b0c29d8dd38467ae0905dd58e47c6770b0e69d5a0fd3cdd4d0218","title":"Exact IR types β€” new file src/lib/types/proxyIR.ts (barrel-exported via src/lib/types/index.ts)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#exact-ir-types-new-file-srclibtypesproxyirts-barrel-exported-via-srclibtypesindexts","content":"UsageContext reused verbatim (confirmed at src/lib/types/proxy.ts:2254): {inputIncludesCachedTokens?, inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens, cacheReadTokensObserved?, cacheCreationTokensObserved?, reasoningTokens?, rateLimitAfter5h?, rateLimitAfter7d?} β€” do not reshape it; proxyTokenUsage() (src/lib/proxy/proxyTokenUsage.ts) already consumes this exact shape and stays provider-agnostic.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Exact IR types β€” new file src/lib/types/proxyIR.ts (barrel-exported via src/lib/types/index.ts)","lvl3":""}},
10787
+ {"objectID":"3a41ee7a4a999b3a77bdac7946a4b90ddf99b33d7aa45a38dc6d1285d8db3790","title":"Codec contract β€” 4 independent capability types (not one monolith)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#codec-contract-4-independent-capability-types-not-one-monolith","content":"Matches what is true per format today: Anthropic needs a parser+builder+response-parser+renderer (all net new β€” grep confirms zero existing outbound-fallback or additional_tools/session_id/developer-role parsing anywhere in src/lib/server/routes/codexProxyRoutes.ts); Codex-native needs a parser (net new) and a renderer (net new, CodexResponsesStreamSerializer) but never a builder or a buffered/stream response parser in this PR (Codex is never dispatched to as the IR target here, only received from).","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Codec contract β€” 4 independent capability types (not one monolith)","lvl3":""}},
10788
+ {"objectID":"6c48b495bf6af1232e29b65dc2d8e19afc2e2b0be7fe2c0bfffae21f74a34f8b","title":"Native-Codex request wire type β€” superseded by the tool-fidelity section's corrected types","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#native-codex-request-wire-type-superseded-by-the-tool-fidelity-sections-corrected-types","content":"Reconciliation (post-review): this subsection originally proposed CodexNativeToolFunction, CodexNativeGrammarTool, CodexNativeAdditionalToolsItem, CodexNativeMessageItem, CodexNativeFunctionCallItem, CodexNativeFunctionCallOutputItem, CodexNativeInputItem and CodexNativeRequestBody, grounded only against the 4 synthetic fixtures. The tool-call-fidelity section later read the real captured wire sample (~/.neurolink/reference/codex-cli-wire-sample.json) and found two of this block's assumptions wrong: additional_tools.tools is an array of {type:\"namespace\", ...} objects, not a flat {functions, collaboration} object, and the identity fields (session_id/thread_id) live nested inside client_metadata, never at the top level CodexNativeRequestBody claimed. Its own \"Β§8. Types β€” exact, corrected\" is the single authoritative version (CodexNativeRole, CodexNativeMessageInputItem, CodexNativeFunctionToolDeclaration, CodexNativeCustomToolFormat, CodexNativeCustomToolDeclaration, CodexNativeToolDeclaration, CodexNativeToolNamespace, CodexNativeAdditionalToolsInputItem, CodexNativeFunctionCallInputItem, CodexNativeFunctionCallOutputInputItem, CodexNativeInputItem, CodexNativeToolChoice, CodexNativeRequest) β€” reuse those names verbatim; nothing in this subsection's original block ships.\n\nThis PR (PR 1, already merged) never added any of these types in the first place β€” only the wire-neutral IR (src/lib/proxy/proxyIR.ts, src/lib/types/proxyIR.ts) shipped. The Codex-native wire types belong to PR 4 (tool fidelity) and are added there, in their corrected form, not here.\n\nNo collisions: CodexContentPart, CodexResponsesInputItem, CodexReasoningEffort, CodexResponsesRequest, CodexFallbackResult/CodexFallbackStream are all distinct existing exports (confirmed via full read of src/lib/types/codex.ts, 218 lines) and stay untouched regardless of which generation of Codex-native types lands.\n\nUnresolved, provisional: whether additional_tools is always exactly one item and always first β€” 4 syn","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Native-Codex request wire type β€” superseded by the tool-fidelity section's corrected types","lvl3":""}},
10789
+ {"objectID":"2cb07e4755f10b979b80fb885e75b1b1b2c71c67dd08d2c5876f81704b5eca62","title":"Exhaustiveness and the 3 tiers of explicit unmappable handling","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#exhaustiveness-and-the-3-tiers-of-explicit-unmappable-handling","content":"New runtime module src/lib/proxy/proxyIR.ts:\n\nBlocker resolved (adopted, refined by code check): the review is right that blanket Tier-1-fatal rejection of every custom_grammar tool defeats the feature on almost all real traffic β€” exec is present in all 4 fixtures and its grammar (start: command\\ncommand: WORD (\" \" ARG)*) is a single free-text argument. Adopt the review's fix with one refinement the code check surfaced: request_review, despite living in the wire's collaboration bucket, is not a custom_grammar tool at all β€” it has parameters, not grammar, so it already maps as ProxyIRFunctionToolDeclaration and never reaches this gate. So the gate only ever needs to special-case tools that genuinely carry a grammar field:\nTier 1 (fatal, whole-request, pre-dispatch): a custom_grammar tool whose grammar is NOT a single free-text argument (isDegradableSingleArgGrammar β€” a narrow EBNF check for exactly one WORD/ARG-style free-text production; anything with more structure is rejected). Thrown before buildRequest runs, before any account slot or Vertex call is spent β€” joins the existing pre-dispatch gate list in proxyTranslationEngine.ts next to ProxyContextPreflightError (proxyContextPreflight.ts:17) and getProxyTokenBudgetError (proxyTokenBudget.ts:56) β€” both confirmed present and already checked together at multiple sites in that engine.\nDegraded-but-working mapping (new, adopted from the review): a custom_grammar tool that IS a single free-text argument (covers exec in all 4 fixtures) maps to {kind:\"function\", name, description, parametersSchema:{type:\"object\", properties:{command:{type:\"string\"}}, required:[\"command\"], additionalProperties:false}}. anthropicMessagesIRCodec.buildRequest renders this as an ordinary ClaudeTool; the reverse mapping on tool-call parsing keeps the single argument as the raw command string under argumentsRaw.\nTier 2 (per-field, non-fatal, explicit sentinel): unparsed tool-call arguments and any ProxyIRUnmappedPart β€” raw wire bytes are always","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Exhaustiveness and the 3 tiers of explicit unmappable handling","lvl3":""}},
10790
+ {"objectID":"df66cce92162a94b26da8402634198b3fb0198e511e280aca2b8c8666e5c3c0a","title":"Developer/system-role hoisting (major finding — adopted in full)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#developersystem-role-hoisting-major-finding-adopted-in-full","content":"Resolved: confirmed by reading codexFallback.ts:134-148 (buildSystemInstructions joins all system/developer text with \"\\n\\n\", discarding position — the review correctly ties this to the repo's own prior ~41% caching-hit-rate regression) and by the fixture read (4 separate contiguous developer-role items in every fixture). Adopted rule for codexNativeRequestCodec.parseRequest → ProxyIRRequest.messages, and for anthropicMessagesIRCodec.buildRequest's IR→ClaudeRequest.system step:\nClaudeMessage.role is a closed \"user\" | \"assistant\" union (confirmed, proxy.ts:132-135) with no system/developer member, so hoisting is mandatory, not optional.\nDeveloper/system-role IR messages are hoisted to ClaudeRequest.system as an array of one ClaudeTextBlock per original segment (never one joined string), preserving segment boundaries so applyClaudeRequestCacheBreakpoints (anthropicCacheBreakpoints.ts:217, confirmed pure, clone-based, idempotent via countAnthropicCacheMarkers at line 97) can mark the correct sub-boundary.\nPosition rule: a developer-role IR message NOT contiguous at the head (position 0) is a protocol violation for this PR's scope — parseRequest throws ProxyIRUnmappableRequestError naming the offending index, rather than silently merging-forward or reordering. All 4 fixtures show developer messages contiguous at head only, so this is a documented refusal for a shape nothing here has observed, not a live-traffic-blocking restriction today.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"Developer/system-role hoisting (major finding — adopted in full)","lvl3":""}},
10791
+ {"objectID":"39ba5a50c2b29553399249537678355899e65a4c040ae32d2278c685eecfced8","title":"Consecutive same-role messages (minor finding β€” adopted)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#consecutive-same-role-messages-minor-finding-adopted","content":"Resolved: confirmed non-hypothetical (tool-result-turn.json input indices 5-6, both role:\"user\", the second carrying an <environment_context> block). Rule: anthropicMessagesIRCodec.buildRequest does not merge adjacent same-role IR messages β€” it emits separate consecutive ClaudeMessage entries. Anthropic's Messages API accepts consecutive same-role messages (no strict alternation requirement), and merging would invent a content-block-join rule with no wire precedent; separate entries are the identity mapping and the lower-risk default. UNRESOLVED: whether Anthropic's live API ever rejects consecutive same-role messages in some edge case β€” the one check that would settle it is a probe request against the real API with two consecutive user messages.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Consecutive same-role messages (minor finding β€” adopted)","lvl3":""}},
10792
+ {"objectID":"8ae7d0bf29a2d6dea60be8efbfe308cd1aadd4502fee43ac7f1d64714ed23bb0","title":"Tool-call id correlation (major finding β€” adopted, scoped)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#tool-call-id-correlation-major-finding-adopted-scoped","content":"Resolved: confirmed gap β€” CodexResponsesInputItem's function_call/function_call_output variants (codex.ts:155-165) and the tool-fidelity section's corrected CodexNativeFunctionCallInputItem/CodexNativeFunctionCallOutputInputItem are both keyed by a single opaque call_id string; nothing in codex.ts types an id-translation record, and tool-result-turn.json (call_id:\"call_synthetic_0001\") must round-trip unchanged across the pair while also surviving translation to/from an Anthropic toolu_* id on the fallback hop. ProxyIRToolCallPart.callId is scoped to this section only as the id the IR received from its source wire β€” never reused as the id sent to a different target wire. Add:\n\nSubstitution boundary: anthropicMessagesIRCodec.buildRequest mints a fresh toolu_* id per tool call via the existing generateToolUseId (confirmed exported from claudeFormat.ts, already imported by codexFallback.ts) and records {inboundWireId: irPart.callId, outboundWireId: mintedId}; the response codec looks up by outboundWireId to restore inboundWireId before rendering a tool_call_done/function_call_output pair to the original Codex client. The map is request-scoped only β€” cross-turn/resumed-session persistence is out of scope here. UNRESOLVED: the storage/lifetime contract for a resumed session's id map spanning multiple proxy requests β€” the one check that would settle it is reading how originSessionId/originThreadId are persisted by the session-affinity design (cache-anthropic/cache-codex-prefix, named below).","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Tool-call id correlation (major finding β€” adopted, scoped)","lvl3":""}},
10793
+ {"objectID":"a523897bed279d26de1747bb37395902d0fd9945c6bf8012654c8667bbb571ca","title":"Stream serializer reuse (major finding β€” adopted, FILES corrected)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#stream-serializer-reuse-major-finding-adopted-files-corrected","content":"Resolved: confirmed by reading claudeFormat.ts:441-530 β€” ClaudeStreamSerializer's constructor takes (model, inputTokens) and ensureMessageStarted emits message_start/ping events shaped exactly like the Anthropic Messages API (SSEMessageStart wrapping a ClaudeResponse-shaped message). It is not reused for the native-Codex-inbound direction, since that direction never emits Anthropic-shaped SSE β€” a native Codex client only ever needs Codex-Responses-shaped SSE. Corrected FILES entry: claudeFormat.ts is reused only for its generateToolUseId helper (already imported by codexFallback.ts) and stays otherwise untouched; the outbound-to-Codex-client stream is rendered exclusively by the new CodexResponsesStreamSerializer inside codexNativeRequestCodec.ts.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Stream serializer reuse (major finding β€” adopted, FILES corrected)","lvl3":""}},
10794
+ {"objectID":"68bb4710fa66eaf0eb9924248640f292aa7e1a11e01fce9dd0ae985692eac0c7","title":"Files","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#files","content":"| Path | Action | Purpose |\n| ------------------------------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| src/lib/types/proxyIR.ts | create | Canonical wire-neutral request/response IR types + 4-capability codec contract |\n| src/lib/types/codex.ts | modify | Add CodexNative* types, additive only; existing types untouched |\n| src/lib/types/index.ts | modify | Add export * from \"./proxyIR.js\"; per barrel-only rule 10 |\n| src/lib/proxy/proxyIR.ts | create | assertProxyIRExhaustive, assertProxyIRRequestMappable, ProxyIRUnmappableRequestError,","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Files","lvl3":""}},
10795
+ {"objectID":"ed2d1dd1f2268b6ea569df738cb11af721dea28a0871c007992141dd05a480a4","title":"Tests","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#tests","content":"All assertions below live in one new file, test/continuous-test-suite-proxy-ir-codec.ts β€” a new determinism-exception suite (pure translation-table functions; header names the exception per the repo's own convention documented for the vector-store suites):\nGolden-fixture round-trip for all 4 test/fixtures/codex-request-*.json: codexNativeRequestCodec.parseRequest β†’ ProxyIRRequest β†’ anthropicMessagesIRCodec.buildRequest β†’ exactly one cache_control marker present on the last system-derived ClaudeTextBlock, and 1:1 tool/message order preservation (array length and per-index role/kind match input).\nA custom_grammar tool with a multi-token grammar (a synthetic fixture variant, not exec) must throw ProxyIRUnmappableRequestError before buildRequest/parseResponseStream is ever called β€” assert via a spy/counter that the downstream call was never invoked, not just that the throw happened.\nexec's function_call (arguments: \"ls -la\") from codex-request-tool-result-turn.json renders through anthropicMessagesIRCodec as ClaudeToolUseBlock.input = {[UNPARSED_TOOL_ARGUMENTS_KEY]: \"ls -la\"} β€” assert the exact key and value, never an empty object and never a thrown error.\nrequest_review (from any fixture's collaboration array) is classified as ProxyIRFunctionToolDeclaration, not ProxyIRCustomGrammarToolDeclaration β€” assert tool.kind === \"function\" and tool.parametersSchema matches its fixture parameters object verbatim.\nThe 4 contiguous developer messages in codex-request-exec-mode.json map to 4 distinct ClaudeTextBlock entries in ClaudeRequest.system (array length 4), never one joined string.\nThe 2 consecutive user messages in codex-request-tool-result-turn.json map to 2 separate ClaudeMessage entries (array length 2 at that position), not one merged message.\nExhaustiveness: a ProxyIRContentPart variant added to the union without a matching case in every consumer switch must fail tsc, verified by a // @ts-expect-error fixture asserting assertProxyIRExhaustive is the reachable default ","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Tests","lvl3":""}},
10796
+ {"objectID":"4a5660476c63fddef96520cc9eea37fdd9fb8bcad379ba2ddec1e7ff23716c67","title":"Dependencies on other sections (named, unresolved here by design)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#dependencies-on-other-sections-named-unresolved-here-by-design","content":"cache-anthropic / cache-codex-prefix (session-affinity): consumes originSessionId/originThreadId/promptCachePrefixKey; this section only guarantees those values survive parseRequest, and owns the cross-turn ProxyIRToolCallIdMap persistence question left UNRESOLVED above.\ncache-vertex: must confirm the same-wire-codec-as-Anthropic simplification holds; if Vertex ever needs a field Anthropic's wire lacks, that assumption breaks and Vertex needs its own thin adapter.\nFailure-taxonomy/commit-boundary design: owns exactly where ProxyIRUnmappableRequestError is checked relative to ProxyContextPreflightError/getProxyTokenBudgetError in proxyTranslationEngine.ts, and the pre-commit/post-commit split for the new response stream β€” parseResponseStream is a plain AsyncGenerator specifically so a caller can peek-then-commit like existing preflight stream buffering.\nproxy-waste (fallback telemetry): the new Codex-outbound leg needs its own attempt-recording call (zero call sites exist today in codexProxyRoutes.ts, confirmed via grep); this section only notes the codec boundary is the natural place to hang it.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Dependencies on other sections (named, unresolved here by design)","lvl3":""}},
10797
+ {"objectID":"f3c9478912b34e48a4808d6325e810e74f96737c04909bcf2a0b8611caaa3bf3","title":"Risks (kept, one added)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#risks-kept-one-added","content":"Native Codex requests may not always place additional_tools as the single first input item β€” 4 synthetic, not live-captured, fixtures only.\nReasoning-effort-to-thinking-budget mapping has no existing precedent here; any bucketing table is new policy needing owner sign-off, not decided here.\nLeaving codexFallback.ts unrefactored means two independently maintained tool_choice/reasoning bijections exist until the named follow-up PR.\nTier-3 thinking-to-Codex rendering has no verified real wire target; shipping a guess risks an SSE frame no real Codex CLI understands β€” worse than withholding, so withholding stays the default.\nAdded: the collaboration-bucket/grammar-field distinction (this section's own code-check finding) is grounded in only 4 fixtures with only 2 collaboration tools (exec, request_review); a third collaboration tool with a different shape (parameters AND grammar both present, or a multi-token grammar) is unverified and needs isDegradableSingleArgGrammar to handle it explicitly rather than silently misclassifying it as a plain function.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Risks (kept, one added)","lvl3":""}},
10798
+ {"objectID":"b735a043f1f3af7383db3a2ba9533c4837eee9bb9a838d781a546da7e823afaf","title":"Request translation: Codex Responses request β†’ ClaudeRequest","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#request-translation-codex-responses-request-clauderequest","content":"Recovered section for \"Codex outbound fallback\" (native Codex client β†’ Anthropic/Vertex fallback). Grounded against /Users/sachinsharma/Developer/Official/fix/proxy-ci-gaps-and-dead-leg-alert (read-only).","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Request translation: Codex Responses request β†’ ClaudeRequest","lvl3":""}},
10799
+ {"objectID":"712eb4de989934c49bc5d08130e851855d1f6f76130b968f28e06e244cb3bc2c","title":"0. Boundary","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#0-boundary","content":"Owns one thing: untrusted inbound Codex Responses JSON β†’ a typed ClaudeRequest. Does not own: target/model selection (orchestration section supplies target: {provider, model}), response/stream translation back to Codex wire format (sibling section owns ClaudeThinkingBlock, ClaudeStreamSerializer), tool execution, or dispatch/HTTP. Vertex/Anthropic dispatch is named in Β§6 only to fix a wrong hand-off found in review; this section still does not own it.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"0. Boundary","lvl3":""}},
10800
+ {"objectID":"44d4e6a3c5e7beda3f95d4ab3e78954b9616be8ae4d49d5c947efde1b75af32b","title":"1. Ground truth (re-verified directly against test/fixtures/codex-request-{interactive-mode,tool-result-turn,resumed-session,exec-mode}.json, generated by scripts/generate-codex-fixtures.mjs)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#1-ground-truth-re-verified-directly-against-testfixturescodex-request-interactive-modetool-result-turnresumed-sessionexec-modejson-generated-by-scriptsgenerate-codex-fixturesmjs","content":"Top level: { model, stream, store, input } (+ session_id/thread_id only on codex-request-resumed-session.json). No top-level tools/instructions in any of the 4.\ninput is flat. Tool declarations ride inside one { type: \"additional_tools\", role: \"developer\", tools: { functions, collaboration } } item, never a top-level field.\n4 separate developer-role message items per fixture (persona / sandbox policy / tool-usage rule / output-format rule), all before the first user item in all 4 fixtures.\nEvery fixture has two consecutive user items (real prompt, then a synthetic <environment_context>...</environment_context> message) β€” the concrete proof that the flat stream violates Anthropic's strict user/assistant alternation unless coalesced.\nContent parts observed: input_text only, in all 4 fixtures β€” 0 occurrences of output_text or input_image, and 0 assistant-role message items. Correction to the first design pass, which claimed all three CodexContentPart variants were \"confirmed against the fixtures\": only input_text is fixture-confirmed; output_text/input_image handling is carried over from the pre-existing CodexContentPart type (src/lib/types/codex.ts:144-147) by structural assumption, not fixture evidence. Flagged in Β§10.\ntest/fixtures/codex-request-tool-result-turn.json (not exec-mode.json β€” corrected misread: exec-mode.json contains no function_call item at all, verified by listing its input array) is the one fixture with a function_call/function_call_output pair: {\"type\":\"function_call\",\"call_id\":\"call_synthetic_0001\",\"name\":\"exec\",\"arguments\":\"ls -la\"} β€” a raw shell string, not JSON.\nadditional_tools.tools.collaboration is a mixed-shape array, verified in codex-request-interactive-mode.json: entry 1 is {\"name\":\"exec\",\"type\":\"custom\",\"description\":...,\"grammar\":\"start: command\\n...\"} (no JSON schema); entry 2 is {\"name\":\"request_review\",\"description\":...,\"parameters\":{\"type\":\"object\",\"properties\":{\"summary\":{\"type\":\"string\"}},\"required\":[\"summary\"],\"additionalPropert","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"1. Ground truth (re-verified directly against test/fixtures/codex-request-{interactive-mode,tool-result-turn,resumed-session,exec-mode}.json, generated by scripts/generate-codex-fixtures.mjs)","lvl3":""}},
10801
+ {"objectID":"f9de43f2eeb41f722c0e053c6f5ba6ee0456f248944e59932babb9dfa80eaa68","title":"2. Types β€” superseded by the tool-fidelity section's corrected types (reconciled post-review)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#2-types-superseded-by-the-tool-fidelity-sections-corrected-types-reconciled-post-review","content":"This subsection's original type block does not ship. It was grounded only against the 4 synthetic fixtures and named CodexNativeAdditionalToolsItem (a flat, required {functions, collaboration} object) β€” the same review pass that flagged this (finding, PR #1825) confirmed the tool-fidelity section independently read the real captured wire sample and found that shape wrong: real traffic's additional_tools.tools is an array of {type:\"namespace\", name, description, tools} objects, discriminated per-declaration by each tool's own type field, never by which bucket it sits in. That section's \"Β§8. Types β€” exact, corrected\" (CodexNativeRole, CodexNativeMessageInputItem, CodexNativeFunctionToolDeclaration, CodexNativeCustomToolFormat, CodexNativeCustomToolDeclaration, CodexNativeToolDeclaration, CodexNativeToolNamespace, CodexNativeAdditionalToolsInputItem, CodexNativeFunctionCallInputItem, CodexNativeFunctionCallOutputInputItem, CodexNativeInputItem, CodexNativeToolChoice, CodexNativeRequest) is the single source of truth; CodexReasoningEffort/CodexContentPart/CodexResponsesInputItem/CodexResponsesRequest stay untouched and out of scope for this reconciliation, exactly as originally stated.\n\nΒ§3.1's guard and Β§3.4's tool mapping below are rewritten to import and use those corrected names directly, rather than duplicating or re-deriving them here.\n\nConfig key (reconciled, see also the rollout-and-config section): the codexFallbackChain?: FallbackEntry[] field this subsection originally proposed for src/lib/types/subscription.ts is superseded by the rollout-and-config section's three-key scheme β€” codexOutboundFallbackEnabled/codexOutboundFallbackTargets/codexOutboundFallbackModelMappings on ProxyRoutingConfig, kebab-cased as codex-outbound-fallback-{enabled,targets,model-mappings} in proxy-config.yaml β€” which is the canonical, later-written, and more completely integrated design (it is read through the same readRoutingPolicyKey/hot-reload wiring every existing routing key uses,","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"2. Types β€” superseded by the tool-fidelity section's corrected types (reconciled post-review)","lvl3":""}},
10802
+ {"objectID":"16682080b9d0bc79b91c88dc0d4fedb4ab8fe44601741fd804855196db7f0f34","title":"3. New module — src/lib/proxy/codexOutboundFallback.ts (create)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#3-new-module-srclibproxycodexoutboundfallbackts-create","content":"Named to mirror the existing asymmetry (codexFallback.ts = Claude engine's fallback into Codex; this file = Codex engine's fallback out).\n\nBoth return a Result union — never throw — resolving review's major finding (\"no runtime validation boundary\"; a type is compile-time only, and a malformed/duck-typed inbound body would otherwise throw an uncaught TypeError deep inside the translator). parseCodexNativeRequest is the untrusted-JSON→typed boundary; translateCodexRequestToClaude assumes an already-narrowed CodexNativeRequest and only fails on the partial-history check in §5.\nInternal (not exported): isRecord, isCodexContentPart, isCodexNativeToolDeclaration, isCodexNativeToolNamespace, isCodexNativeInputItem, isCodexNativeToolChoice, isCodexNativeReasoning, coalesceCodexInputToClaudeMessages, toClaudeContentPart, mapCodexFunctionToolToClaude, mapCodexCustomToolToClaude, mapCodexToolDeclarationToClaude, mapCodexToolChoiceToClaude, mapCodexReasoningToThinking, parseInboundToolArguments, hasFreshSessionPreamble.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"3. New module — src/lib/proxy/codexOutboundFallback.ts (create)","lvl3":""}},
10803
+ {"objectID":"8edd7cc6d36eaf7260ff16e35617ecbe01208c21528c0d37c6e33cd71d15a0e0","title":"3.1 parseCodexNativeRequest","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#31-parsecodexnativerequest","content":"(Structural narrowing only, no field-by-field cast beyond the final assignment, which is sound because every field was checked above β€” this is the one place as is acceptable, since it follows, not replaces, exhaustive narrowing.)","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"3.1 parseCodexNativeRequest","lvl3":""}},
10804
+ {"objectID":"3d0ff8e0bdbbde880b04406c71a3bd999dc3e73ca2ffd805f32717b40c651ee2","title":"3.2 Field-by-field mapping (translateCodexRequestToClaude, after the guard in Β§3.5)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#32-field-by-field-mapping-translatecodexrequesttoclaude-after-the-guard-in-35","content":"| Codex field | Anthropic field | Rule |\n| ---------------------------------------------------------------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| (routing) | model | target.model, passed in; never invented here. |\n| input[] where role:\"developer\" | system: ClaudeTextBlock[] | One block per developer message, original order, array form (Β§4 β€” required for cache-breakpoint eligibility). |\n| input[] message/function_call/function_call_output | messages: ClaudeMessage[] | Coalesced by logical role, Β§4. |\n| content parts | ClaudeTextBlock/ClaudeImageBlock | toClaudeContentPart, Β§3.7 (data-URI fix). ","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"3.2 Field-by-field mapping (translateCodexRequestToClaude, after the guard in Β§3.5)","lvl3":""}},
10805
+ {"objectID":"bdf260c076ed776a9f41958b5ac59bfa2f1f5adc68bcc24688d1410badfe4337","title":"3.3 tool_choice β€” exact inversion of codexFallback.ts:445-456","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#33-tool_choice-exact-inversion-of-codexfallbackts445-456","content":"| Codex tool_choice | Anthropic tool_choice |\n| ---------------------------- | ------------------------ |\n| \"required\" | { type: \"any\" } |\n| { type: \"function\", name } | { type: \"tool\", name } |\n| \"auto\" | { type: \"auto\" } |\n| \"none\" | { type: \"none\" } |\n| absent | omit field |\n\nUnobserved in all 4 fixtures β€” the table is derived correctly from the existing forward code but not empirically confirmed on genuine traffic (Β§10).","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"3.3 tool_choice β€” exact inversion of codexFallback.ts:445-456","lvl3":""}},
10806
+ {"objectID":"96f6c9a3725d152c9185173a6fd6478d2923eee9e61415407c98b7dd425f823c","title":"3.4 Tools: flattened across namespaces, split by each declaration's own type (corrected β€” was per-namespace)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#34-tools-flattened-across-namespaces-split-by-each-declarations-own-type-corrected-was-per-namespace","content":"Reconciled with the tool-fidelity section's real-capture correction: the prior version of this subsection discriminated by which bucket a tool sat in (functions vs collaboration), grounded only against the 4 synthetic fixtures. The real captured wire sample shows the opposite: additional_tools.tools is an array of namespaces (e.g. \"functions\", \"collaboration\"), and inside a namespace, individual declarations can be either kind β€” in the real capture, the \"functions\" namespace holds two type:\"function\" tools (wait, request_user_input) and one type:\"custom\" tool (exec, grammar-based). Discriminating by namespace name would have misclassified exec. The correct split reads each declaration's own type field, across every namespace, in namespace order then declaration order:\n\nThe input key in the custom-tool branch's schema is deliberate: it must match what parseInboundToolArguments (Β§3.6) synthesizes for that tool's non-JSON function_call.arguments β€” the schema and the argument fallback are two halves of one contract.\nCardinality: only one additional_tools item is handled (last one wins if more than one appears β€” unobserved whether that's possible, Β§10); this should become a hard MALFORMED_REQUEST once real traffic confirms the cardinality, rather than silently dropping a tool set.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"3.4 Tools: flattened across namespaces, split by each declaration's own type (corrected β€” was per-namespace)","lvl3":""}},
10807
+ {"objectID":"70b3041ee1546d049ae4cae0d253a97d82aa469ecdbb8a895b4f4fc92bdd78d3","title":"3.5 Reasoning: reasoning.effort β†’ thinking","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#35-reasoning-reasoningeffort-thinking","content":"No existing precedent (zero references anywhere in the codebase) β€” novel and unvalidated against real responses.\n\n| effort | thinking |\n| ----------------- | ------------------------------------------- |\n| none, minimal | omit |\n| low | { type: \"enabled\", budget_tokens: 4096 } |\n| medium | { type: \"enabled\", budget_tokens: 8192 } |\n| high | { type: \"enabled\", budget_tokens: 16384 } |\n| xhigh | { type: \"enabled\", budget_tokens: 24576 } |\n| max | { type: \"enabled\", budget_tokens: 32768 } |\n\nClaudeRequest.thinking.type is a loose string, not a literal union, in the pre-existing shared type (src/lib/types/proxy.ts:168) β€” not fixed here; other call sites share it.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"3.5 Reasoning: reasoning.effort β†’ thinking","lvl3":""}},
10808
+ {"objectID":"d9b395b9e31a46c2a1c39966b7a0570f26b83e253ca9f747e48c81dea6fcc576","title":"3.6 Non-JSON function_call.arguments","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#36-non-json-function_callarguments","content":"The existing parseFunctionArguments() (src/lib/proxy/codexFallback.ts:466-482) throws on non-JSON and must not be reused β€” it parses the response-side leg (Codex's own model output, always valid JSON), whereas this leg parses a client-supplied history replay, which for exec is a raw shell string (arguments: \"ls -la\", confirmed in test/fixtures/codex-request-tool-result-turn.json).\n\nNever throws. { input: raw } matches Β§3.4's grammar-tool schema exactly.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"3.6 Non-JSON function_call.arguments","lvl3":""}},
10809
+ {"objectID":"f029310667c9be66e1ee89127b06183f34f9a5e5e63561fa67db9e5fc050fbd4","title":"3.7 Content parts, with the image fix","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#37-content-parts-with-the-image-fix","content":"Major finding resolved: the first design pass mapped every input_image.image_url to {type:\"url\", url: image_url}. But Codex's own image_url field routinely carries a data: base64 URI — proven by this same codebase's opposite-direction code, imageUrlForBlock (src/lib/proxy/codexFallback.ts:171-180), which constructs data:${media_type};base64,${data} when going Claude→Codex. Feeding that string into Anthropic's url source variant is invalid; it must become the base64 variant.\n\nNo fixture contains an input_image part (§1) — this branch is untested by any existing fixture; §9 adds an inline-constructed test case for it since no fixture covers it.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"3.7 Content parts, with the image fix","lvl3":""}},
10810
+ {"objectID":"2249cd74240d9d808f8a5fef515aa1bd9e5c1d4c1bf107628a8607be140e164d","title":"4. Role-alternation coalescing","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#4-role-alternation-coalescing","content":"Anthropic enforces strict user/assistant alternation; the fixtures prove Codex's flat stream does not (two consecutive user items in all 4). The algorithm walks input once, appending to or flushing one \"open group,\" never reordering:\n\nTwo consecutive user items β†’ one message, two text blocks (fixture-proven). N consecutive function_call β†’ one assistant message with N tool_use blocks, id = verbatim call_id (this is Anthropic's parallel-tool-call shape, no separate code path). N consecutive function_call_output β†’ one user message with N tool_result blocks, tool_use_id matching verbatim.\nUnresolved, not silently assumed (Β§10): every fixture puts all developer items before the first user item; the algorithm folds every developer item into the system prefix regardless of position, which is only correct if real traffic never sends a mid-conversation developer nudge.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"4. Role-alternation coalescing","lvl3":""}},
10811
+ {"objectID":"b724788e010b711c8df065aadaa32d68058d50f1c93ceb45d8c3b7a12f1cc06d","title":"5. Blocker resolved: resumed-session history contract","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#5-blocker-resolved-resumed-session-history-contract","content":"The first design pass's translator silently assumed input always holds full conversation history, even on a resumed session. codex-request-resumed-session.json replays an input array identical to codex-request-interactive-mode.json's (same 7 items, same roles) while carrying session_id/thread_id β€” but the generator's own header states these are hand-built approximations of a wire sample \"NOT available in this environment,\" so this is the fixture generator's assumption, not observed Codex CLI behavior. Given the Responses API's stateful design (session_id/thread_id imply server-side memory) and Anthropic's Messages API having none, a resumed request that in reality carries only incremental turns would make this translator silently produce an amnesiac ClaudeRequest with no visible error.\nResolution adopted (review's option (a) fail-loud, not option (b) history-cache β€” a persisted-history cache is a stateful, session-routing concern that belongs with the orchestration/affinity section, not a pure translator): detect the shape and refuse translation rather than guess.\n\nThis is a static best-effort guard, not proof of the real wire contract β€” see UNRESOLVED in Β§10. It converts an unknown into a loud, caller-visible failure instead of a silent one, which is what the \"nothing may break silently\" requirement demands even without live traffic.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"5. Blocker resolved: resumed-session history contract","lvl3":""}},
10812
+ {"objectID":"60e9333a338ac3f72459202b690775115c51efb22bc8c13c60628cbc17634508","title":"6. Vertex delta β€” corrected hand-off","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#6-vertex-delta-corrected-hand-off","content":"ClaudeRequest has no output_config field (src/lib/types/proxy.ts:154-169); output_config is a Claude-Code-CLI-specific dial that buildVertexAnthropicPayload (src/lib/proxy/vertexAnthropicFallback.ts:399-428) hoists/strips on its own untyped passthrough path β€” unrelated to thinking. buildVertexAnthropicPayload only reads/rewrites model (dropped β€” Vertex encodes it in the URL, UNSUPPORTED_FIELDS at line 42), context_management, output_config, messages, system; it never inspects thinking, so thinking.budget_tokens flows through untouched as the same standard Anthropic field. No second reasoning table needed for Vertex.\nMajor finding resolved: the first design pass's illustrative dispatch code called buildVertexAnthropicPayload/buildVertexAnthropicUrl directly and did a raw fetch(...) β€” that omits Google ADC bearer-token acquisition, non-2xx error handling, and usage telemetry, all of which the already-exported executeVertexAnthropicFallback (src/lib/proxy/vertexAnthropicFallback.ts:611-666) provides; confirmed its real signature is (args: { body: Readonly<Record<string, unknown>>; model: string; signal?: AbortSignal; onTerminal?: (t: VertexPassthroughTerminal) => void }) => Promise<Response> β€” it resolves projectId/location itself via resolveVertexTarget() and calls dispatchVertexAnthropicPassthrough internally, so those two builders are implementation details, not a standalone caller's building blocks:\n\ntranslated.value.model is required by the type and used for the Anthropic-direct leg/logging, but must never be read back out for the Vertex model β€” Vertex resolves its own target.model independently (the dropped field, per UNSUPPORTED_FIELDS).","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"6. Vertex delta β€” corrected hand-off","lvl3":""}},
10813
+ {"objectID":"d90f2bab67865a3271d300b6ec12f3a2412ac5f481479abe2d9cb1259dc59ed3","title":"7. Determinism ledger (cache-prefix stability), with the corrected marker claim","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#7-determinism-ledger-cache-prefix-stability-with-the-corrected-marker-claim","content":"Tool array order: namespace order, then declaration order within each namespace, via nested .flatMap(), never through a name-keyed Map (corrected β€” Β§3.4).\nMessage/system order preserved 1:1 from input; coalescing merges only adjacent same-role items.\ntool_use.id/tool_result.tool_use_id = verbatim Codex call_id β€” never generateToolUseId() (src/lib/proxy/claudeFormat.ts:35-37, randomBytes-based, confirmed non-deterministic); this module imports nothing from it.\ngenerateMessageId() (claudeFormat.ts:28) is response-serializer-only, never imported here.\nsystem must be array-form, never a string β€” minor finding resolved on where the marker actually lands: applyClaudeRequestCacheBreakpoints (src/lib/utils/anthropicCacheBreakpoints.ts:217-271) marks the last system block whenever Array.isArray(out.system) && out.system.length > 0 (line 244), and only falls through to marking the last tool when system is absent/empty (line 252) β€” a branch that is unreachable for any translated request here, since every genuine Codex request carries β‰₯1 developer message and this design always emits array-form system. The first design pass's ledger framed tool-array order as the operative cache-key constraint in the common case; corrected: for real Codex-origin traffic the marker lands on the last system block, and tool-array order matters only for the (here, unreachable) empty-system path. Tool-array ordering (point 1) still matters for its own sake (a stable tools array is part of what gets hashed into the prefix even when the breakpoint itself sits on system).\nNo cache-key derivation on this leg β€” codexPromptCacheKey/codexCachePrefix exist only for the other (Claudeβ†’Codex, OpenAI-caching) direction; Anthropic's caching is marker-based and needs none invented here.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"7. Determinism ledger (cache-prefix stability), with the corrected marker claim","lvl3":""}},
10814
+ {"objectID":"b2e2c7923039d9a884b29933f4a378d010bab5bc9c58da7b27b2029a27b82b7f","title":"8. CI gating gap found by grounding (not in either design or review pass)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#8-ci-gating-gap-found-by-grounding-not-in-either-design-or-review-pass","content":"The design's file list creates test/continuous-test-suite-codex-outbound-translation.ts but never wires it to run. scripts/run-proxy-reliability.mjs's checks array is a hardcoded list β€” a new file in test/ runs in CI only if added there (or to another script+workflow step). Precedent: this exact wrapper's own comment explains it added test/continuous-test-suite-vertex-anthropic-fallback.ts for the identical reason (\"It had no npm script and no workflow reference, so its 51 cases never ran anywhere\"). This section's suite must be added the same way:\n\nscripts/run-proxy-reliability.mjs (modify): add [\"tsx\", \"test/continuous-test-suite-codex-outbound-translation.ts\"] to the checks array (same pattern as the vertex-anthropic-fallback entry, with a comment stating why it's not proxy-*-templated). This keeps it gated by test:proxy-reliability (package.json:170) β†’ .github/workflows/ci.yml:445 inside provider-safety-net-shards (matrix rest) β†’ required provider-safety-net job, satisfying the repo's \"npm script AND workflow runs it\" gating rule.\n\nscripts/generate-codex-fixtures.mjs (modify): none of the 4 existing fixtures exercise N-parallel tool calls. Generalize the two zero-arg helpers with defaults that reproduce today's output byte-for-byte (functionCallItem(callId = \"call_synthetic_0001\", name = \"exec\", args = \"ls -la\"), functionCallOutputItem(callId = \"call_synthetic_0001\", output = JSON.stringify({stdout:\"total 0\\ndrwxr-xr-x 2 codex staff 64 Jan 1 00:00 .\\n\",stderr:\"\",exit_code:0}))), then append one new fixtures[] entry, codex-request-parallel-tool-calls.json, with extraInputItems: [functionCallItem(\"call_synthetic_0001\",\"exec\",\"ls -la\"), functionCallItem(\"call_synthetic_0002\",\"read_file\", JSON.stringify({path:\"src/index.ts\"})), functionCallOutputItem(\"call_synthetic_0001\"), functionCallOutputItem(\"call_synthetic_0002\", JSON.stringify({content:\"export {};\\n\"}))] β€” 2 consecutive function_call then 2 consecutive function_call_output, one JSON args one non-JSON args","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"8. CI gating gap found by grounding (not in either design or review pass)","lvl3":""}},
10815
+ {"objectID":"0786d2230d6d50da3ac9c06fba3f2135868a43e69c7e525bf5ebfec680214899","title":"9. Tests","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#9-tests","content":"All in test/continuous-test-suite-codex-outbound-translation.ts (new; #!/usr/bin/env tsx, plain test()/asyncTest() + passed counter + console.log(\"Passed: N; Failed: 0; RESULT: PASS\") pattern, matching test/continuous-test-suite-vertex-anthropic-fallback.ts):\nparseCodexNativeRequest returns ok:false, code:\"MALFORMED_REQUEST\" for a body missing input, and ok:true for all 5 fixture bodies (4 existing + new parallel-tool-calls one).\nFeed all 5 fixtures through translateCodexRequestToClaude twice each; assert JSON.stringify equality both times (determinism).\nAssert .value.system is always ClaudeTextBlock[], never a string, for every fixture (cache-breakpoint array-gate dependency, Β§7 point 5).\ncodex-request-interactive-mode.json: assert its two consecutive user items collapse into one Claude message with exactly two content blocks (alternation invariant), and that its namespace's mixed-kind declarations map to two ClaudeTools where the type:\"custom\" entry's input_schema is the single-input-string fallback schema and the type:\"function\" entry's input_schema equals its original parameters object byte-for-byte (per-declaration-type split, Β§3.4). Depends on the fixture regeneration tool-fidelity Β§10 test #26 already tracks β€” today's test/fixtures/codex-request-*.json still use the flat, pre-correction {functions, collaboration} shape (confirmed \"still wrong relative to the real capture\"), so this assertion cannot pass until those fixtures are regenerated to the namespace-array shape; it is not a new gap introduced here.\nNew codex-request-parallel-tool-calls.json: assert the 2 consecutive function_call items become one assistant message with 2 tool_use blocks whose ids are call_synthetic_0001/call_synthetic_0002 verbatim, and the 2 function_call_output items become one user message with 2 tool_result blocks whose tool_use_ids match; assert call_synthetic_0001's parsed input is {input: \"ls -la\"} and call_synthetic_0002's is {path: \"src/index.ts\"} (both JSON and non-JSON argum","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"9. Tests","lvl3":""}},
10816
+ {"objectID":"1c25d7cf90dac3c24fe3aacba825502c32e23103138a39f3c4715f7e40eb8c4c","title":"10. Explicitly missing facts","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#10-explicitly-missing-facts","content":"UNRESOLVED: whether additional_tools/developer items can appear anywhere other than before the first user item in real traffic — the one check that would settle it: capture one real Codex CLI multi-turn session with a mid-conversation system nudge (e.g. a compaction event) and inspect its input ordering.\nUNRESOLVED: whether a resumed-session request's input is genuinely full-history or incremental — the one check that would settle it: capture one real resumed-session Codex Responses request (the referenced ~/.neurolink/reference/codex-cli-wire-sample.json is not available in this environment) and compare its input.length against the same session's prior turn.\nUNRESOLVED: whether tool_choice or reasoning ever appear on genuine inbound requests at all (absent from all 4 fixtures) — the one check that would settle it: grep captured production Codex traffic logs (once available) for either key.\nUNRESOLVED: whether more than one additional_tools item can appear in one request — the one check that would settle it: same real-traffic capture as (1).\nProduct sign-off still needed on the lossy grammar→single-string-parameter mapping in §3.4 (behavior-changing, not just encoding) and on the {input: raw} non-JSON fallback's downstream effect on tool execution (owned by the tool-fidelity section).","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"10. Explicitly missing facts","lvl3":""}},
10817
+ {"objectID":"bf904f3a68ba7f893922b7bfb2cbc7f96184272624bef1401a06de08af93bb14","title":"11. Files this section touches","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#11-files-this-section-touches","content":"src/lib/types/codex.ts (append types, per the tool-fidelity section's Β§8 β€” see the reconciliation note above), src/lib/proxy/codexOutboundFallback.ts (create), scripts/generate-codex-fixtures.mjs (generalize two helpers, add one fixture), test/fixtures/codex-request-parallel-tool-calls.json (generated, not hand-authored), test/continuous-test-suite-codex-outbound-translation.ts (create), scripts/run-proxy-reliability.mjs (add the new suite to checks), eslint.config.js (add the new suite to neurolink/e2e-tests-only allow). The config key lives in src/lib/proxy/proxyConfig.ts/runtimeConfig.ts per the rollout-and-config section's codex-outbound-fallback-{enabled,targets,model-mappings}, not src/lib/types/subscription.ts/codexFallbackChain? as this subsection originally proposed.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"11. Files this section touches","lvl3":""}},
10818
+ {"objectID":"9071e70cbb3446b69f045596793feee6859618efbc074d93e1a96029486e268c","title":"Response translation: Anthropic β†’ Codex wire format","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#response-translation-anthropic-codex-wire-format","content":"Wire-level translation from an Anthropic-shaped upstream result (ClaudeResponse JSON, or the\nAnthropic SSE vocabulary message_start/content_block_start/content_block_delta/content_block_stop/\nmessage_delta/message_stop/ping) into the Codex Responses shape a native Codex client expects\n(response.* SSE events, or one non-streaming Response JSON body). Out of scope: engine selection /\nfallback trigger, OAuth/account selection, retry/cooldown policy, analytics recording β€” owned by sibling\nsections proxy-waste, cache-anthropic, cache-vertex. Assumes an outer route already has an\nAnthropic-shaped Response (from the Claude Code OAuth pool or Vertex) to translate; this section does not\ntouch src/lib/server/routes/codexProxyRoutes.ts.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Response translation: Anthropic β†’ Codex wire format","lvl3":""}},
10819
+ {"objectID":"9d2410fda9c55c78bd2184a368781a456c353350ac9ae2154480c17eb42f00af","title":"1. Grounded facts (verified against /Users/sachinsharma/Developer/Official/fix/proxy-ci-gaps-and-dead-leg-alert)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#1-grounded-facts-verified-against-userssachinsharmadeveloperofficialfixproxy-ci-gaps-and-dead-leg-alert","content":"ClaudeUsage (src/lib/types/proxy.ts:177) = { input_tokens, output_tokens, cache_creation_input_tokens?, cache_read_input_tokens? }. ClaudeThinkingBlock (:118) = { type:\"thinking\"; thinking: string }, no signature. ClaudeContentBlock (:124) union has no refusal variant. ClaudeToolUseBlock.input (:103) is Record<string, unknown>, never undefined β€” so JSON.stringify(block.input ?? {}) is defensive-only, not load-bearing.\nCorrected citation (was Blocker, resolved): message_start carries input_tokens/cache_creation_input_tokens/cache_read_input_tokens; message_delta carries only the running output_tokens total. Verified directly in this repo's own reader for the identical Anthropic-shape wire, readUsageEvent (src/lib/proxy/vertexAnthropicFallback.ts:669-696): it sets input+cache fields only inside if (event.type === \"message_start\"), and unconditionally overwrites outputTokens from message_delta/message_start's usage.output_tokens. The original draft of this section called message_start a no-op and read cache fields from message_delta; that was backwards and would have zeroed cache accounting on every response. Fixed in Β§4/Β§5 below.\nSSEContentBlockDescriptor (proxy.ts:203-206) gives tool id/name at content_block_start, so the Codex function_call item can be opened immediately, not deferred to block close.\nSSEDeltaDescriptor (proxy.ts:208-212) = text_delta | thinking_delta | input_json_delta; input_json_delta.partial_json is a plain string, not individually valid JSON β€” confirmed against this repo's own reverse-direction parser, parseFunctionArguments (src/lib/proxy/codexFallback.ts:466-484), which requires a fully-accumulated string before JSON.parse. A serializer method that validates JSON per-chunk cannot forward these incrementally; Β§3 fixes this with a raw-chunk delta method (was Major finding).\nSSEPing (proxy.ts:266-268) is a real member of SSEEvent, and this repo's own emitter proves it is not rare: ClaudeStreamSerializer.ensureMessageStarted (src/lib/proxy/claudeF","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"1. Grounded facts (verified against /Users/sachinsharma/Developer/Official/fix/proxy-ci-gaps-and-dead-leg-alert)","lvl3":""}},
10820
+ {"objectID":"373c6bf35b43bb70b4f709b8b3d5c60c65f74b2759c0f18dc8fd903a35933c67","title":"5. Concrete event-to-event mapping (streaming path)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#5-concrete-event-to-event-mapping-streaming-path","content":"Ordering invariants (asserted by construction of closedItems/outputIndex, not just described):\nExactly one response.created precedes every other response.* event.\nresponse.output_item.added for output_index=i precedes any content_part.*/output_text.*/function_call_arguments.* carrying that same i.\nItems never interleave (external knowledge: Anthropic's public streaming contract β€” see Β§1 correction).\nExactly one terminal event (response.completed XOR response.incomplete XOR response.failed) is last; any push after it throws (assertNotTerminal).\nA terminal event's response.output[] equals, in order, exactly this.closedItems β€” true by construction (both are populated by the same close calls), not by analogy to the reverse direction.\n\nText block, itemId = generateCodexItemId(\"message\"):\n\nTool-use block, itemId = generateCodexItemId(\"function_call\"), call_id = codexCallIdFromToolUseId(block.id):\n\nAlways emit at least one function_call_arguments.delta even for a zero-argument tool call (mirrors ClaudeStreamSerializer.pushToolUse never skipping emission for empty input, claudeFormat.ts:634-650).\n\nUnmapped events (fixes former Major finding β€” now explicit, not implicit): ping, thinking_delta, content_block_start type:\"thinking\", and any other event type not named above are consumed and produce zero Codex-shape frames. This is what makes ClaudeStreamSerializer.ensureMessageStarted's guaranteed post-message_start ping (claudeFormat.ts:511) harmless rather than a crash via assertNotTerminal.\n\nThinking block: not translated β€” ClaudeThinkingBlock has no signature (nothing to represent faithfully as a reasoning item), and no reasoning-stream event name is evidenced in this repo (Β§1). Extended-thinking content silently disappears across this fallback hop; flagged for reviewer awareness even though omission is the safest available choice.\n\nTool-call id decision: reuse tool_use.id (toolu_...) verbatim as call_id. Reason: nothing in this codebase validates call_id format on the way i","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"5. Concrete event-to-event mapping (streaming path)","lvl3":""}},
10821
+ {"objectID":"0d0fa858e150b3b657632b4f4581cce1989db31d05cd336d49e9d45e0a040e6a","title":"6. Failure handling and the commit boundary","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#6-failure-handling-and-the-commit-boundary","content":"Pre-commit (nothing flushed): preflightAnthropicStream classifies sse_error/transport_error/empty before serializer.start() ever runs. The driver throws AnthropicFallbackStreamError/AnthropicFallbackResponseError; the (sibling-owned) outer route may try the next engine.\nPost-commit (β‰₯1 frame flushed): a silent swap is impossible. serializer.emitFailure(status, message, code) closes any open item as status:\"incomplete\" (now typeable, Β§2) and emits one response.failed, never a bare error frame.\nMalformed tool-call JSON (fixes former Major finding β€” was unhandled): closeToolCall() throws when JSON.parse(this.argsAccum || \"{}\") fails. The driver's content_block_stop branch for an open function_call must try/catch this specific throw and route it through serializer.emitFailure(502, \"Codex fallback tool arguments were not valid JSON\", \"invalid_tool_arguments\") β€” a named case, not a fallthrough unhandled exception, mirroring parseFunctionArguments's discipline that the caller must never retry after emitting output (codexFallback.ts:715-718).\nGotcha specific to this direction: preflight's buffered chunks must run THROUGH the interpreter before the live remainder β€” never replayed raw, unlike the Claude-facing route where upstream shape equals client shape.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"6. Failure handling and the commit boundary","lvl3":""}},
10822
+ {"objectID":"7faba2a26c3700bb7e5476a985c323b6e2d2251a93f939b592ffe36d6c9df3b7","title":"7. Non-streaming JSON path","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#7-non-streaming-json-path","content":"When the inbound Codex request's stream is falsy/absent, return serializeCodexResponse(claudeResponse, model) directly as the HTTP JSON body (Content-Type: application/json) β€” the document root IS a CodexResponseEnvelope, the same shape carried inside response.completed.response. buildCodexResponseItem is shared with the streaming path so item shape is defined once. Resolved (Β§1): codexProxyRoutes.ts hardcodes stream: true and has no branch reading an inbound stream field, so this path is currently unreachable from the native Codex route β€” implement it for completeness and for a future client, but do not write a test asserting it is exercised end-to-end through that route today (there is no such route yet).","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"7. Non-streaming JSON path","lvl3":""}},
10823
+ {"objectID":"54527782a3cd8670d5ab329c9e7b09cc2c22401e0937132fc7b70b98f022d5e8","title":"8. Scope boundary on CodexResponseEnvelope's fields","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#8-scope-boundary-on-codexresponseenvelopes-fields","content":"Real OpenAI Responses API envelopes carry more fields (temperature, tool_choice, tools, metadata, previous_response_id, parallel_tool_calls, truncation, text, reasoning, user, …). This design specifies only id, object, created_at, status, model, output, usage, incomplete_details, error β€” the minimal subset a client needs for content/tool-calls/usage/status. Echoing more fields back from the original inbound request is an optional enhancement (the outer route would need to retain that request), not a gap.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"8. Scope boundary on CodexResponseEnvelope's fields","lvl3":""}},
10824
+ {"objectID":"8f54aa72a39df6d3a6d0b8b26e154c9f1b05dc6a26837f3b4a2d15f9469fbe25","title":"9. Tests and CI gating","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#9-tests-and-ci-gating","content":"New fixture test/fixtures/anthropic-to-codex-golden.sse: one synthetic Anthropic SSE transcript (text + tool_use blocks, including a ping and a multi-chunk input_json_delta) with its exact expected Codex-shape SSE output, byte-for-byte.\n\nNew suite test/continuous-test-suite-codex-response-translation.ts (create). Must open with a \"Determinism exception (CLAUDE.md rule 15)\" header mirroring test/continuous-test-suite-codex.ts:5-19 (importing codexResponsesFormat.js/codexToAnthropicFallback.js internals directly to unit-test deterministic SSE translation and ordering invariants β€” a live backend cannot be made to emit a specific malformed-JSON or interleaved-ping sequence on demand). Defines its own local HTTP-fixture helper (not imported β€” withHttpFixture in continuous-test-suite-proxy-telemetry.ts:698 is unexported).\ntest/continuous-test-suite-codex-response-translation.ts: \"golden frame byte comparison\" β€” feed the fixture transcript through createAnthropicFallbackStream, join emitted frames, assert exact string equality against anthropic-to-codex-golden.sse.\ntest/continuous-test-suite-codex-response-translation.ts: \"message_start populates cache usage\" β€” feed a transcript whose message_start.message.usage has cache_read_input_tokens:900, cache_creation_input_tokens:100, input_tokens:500 and whose message_delta omits both cache fields; assert the terminal envelope's usage.input_tokens_details equals {cached_tokens:900, cache_write_tokens:100} (fixes the former Blocker β€” this assertion fails against the pre-fix no-op design).\ntest/continuous-test-suite-codex-response-translation.ts: \"tool-call arguments forward incrementally, not buffered\" β€” feed 3 separate input_json_delta frames for one tool call; assert 3 distinct response.function_call_arguments.delta SSE frames are emitted (not 1), each carrying its own raw chunk unmodified.\ntest/continuous-test-suite-codex-response-translation.ts: \"malformed tool JSON routes to response.failed\" β€” feed an input_json_delta sequenc","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"9. Tests and CI gating","lvl3":""}},
10825
+ {"objectID":"71cd62de4c2b9cb70c38378938a4bc8e81eb3f29493489b515d0b7deb357054b","title":"10. Dependencies on sibling sections","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#10-dependencies-on-sibling-sections","content":"cache-anthropic: whether request-side cache_control breakpoints are inserted determines whether cache_read_input_tokens/cache_creation_input_tokens are ever populated on the Anthropic response this section reads from message_start. This section's mapping is correct either way (absent fields omitted, never zeroed).\ncache-codex-prefix: owns Codex-side prompt_cache_key/prefix mechanics; relevant only if a fallback chain nests.\ncache-vertex: this layer is upstream-provider-agnostic β€” it consumes only the ClaudeResponse/SSE shape β€” provided cache-vertex's own normalization funnels Vertex output into that same shape before it reaches this driver.\nproxy-waste: owns engine selection, when to trigger fallback, and pre-commit/post-commit routing. This section provides consumeAnthropicFallbackResponse/createAnthropicFallbackStream and the Β§6 boundary contract; it does not decide when to retry another engine, and does not touch codexProxyRoutes.ts.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"10. Dependencies on sibling sections","lvl3":""}},
10826
+ {"objectID":"0ce17a82c7bfe7fd513a44a2736440b45ff9ff6394f996af91a3c473d419b488","title":"11. Files this section touches","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#11-files-this-section-touches-1","content":"src/lib/types/codex.ts β€” modify, add the 8 types in Β§2.\nsrc/lib/proxy/codexResponsesFormat.ts β€” create, Β§3.\nsrc/lib/proxy/codexToAnthropicFallback.ts β€” create, Β§4.\nscripts/run-proxy-reliability.mjs β€” modify, one new checks entry (Β§9).\ntest/fixtures/anthropic-to-codex-golden.sse β€” create.\ntest/continuous-test-suite-codex-response-translation.ts β€” create.\n\nNot touched by this section (sibling-owned): src/lib/server/routes/codexProxyRoutes.ts, src/lib/proxy/codexFallback.ts (the recommended sseFrameScanner.ts extraction remains an optional, explicitly-deferred follow-up β€” duplicating the carry/searchFrom loop once more in codexToAnthropicFallback.ts is acceptable if the implementation PR must be strictly additive; state which option was taken in the PR description).","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"11. Files this section touches","lvl3":""}},
10827
+ {"objectID":"bf0c0fa9b8ff68aed588ac3eecb3f98aa37146306a1f2f140bcd4158f6ff3048","title":"Tool-call fidelity (Codex-outbound fallback) β€” resolved","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#tool-call-fidelity-codex-outbound-fallback-resolved","content":"Scope: the tool-related constructs for a native Codex Responses-API request served, transparently, by the Anthropic OAuth pool or Vertex-Claude. Declarations, tool_choice/parallel_tool_calls, model-emitted calls, client results, argument parsing, schema limits, and the request/response boundary those depend on. General plain-text message-role mapping (developer/user/assistant β†’ Claude system/user/assistant) is the sibling Request translation section's mandate; this section only reaches into it where a tool-call grouping fix cannot be made without touching the same array (see Β§2).\n\nAll facts below were re-verified this session directly against /Users/sachinsharma/Developer/Official/fix/proxy-ci-gaps-and-dead-leg-alert (read-only) and against ~/.neurolink/reference/codex-cli-wire-sample.json (a real captured Codex CLI 0.155.1 request, body.* nesting). Every resolution below is inline; there is no separate changelog.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Tool-call fidelity (Codex-outbound fallback) β€” resolved","lvl3":""}},
10828
+ {"objectID":"96e436064b53fd332f9f6b5d58ab76bf5c6d91bae91527569b91bc9e56e61b85","title":"0. Baseline facts confirmed this pass","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#0-baseline-facts-confirmed-this-pass","content":"src/lib/types/codex.ts (219 lines) has no CodexNative* name yet β€” zero collision risk. Barrel line: src/lib/types/index.ts:19 (export * from \"./codex.js\";).\nsrc/lib/types/proxy.ts:154-170 β€” current ClaudeRequest.tool_choice is {type:\"auto\"|\"any\"|\"none\"} | {type:\"tool\"; name}, no disable_parallel_tool_use. ClaudeTool (138-143), ClaudeToolUseBlock (103-108), ClaudeToolResultBlock (111-116), ClaudeMessage (132-135), ClaudeUsage (177-182), ProxyMetrics (2177-2194) all confirmed as designed.\nsrc/lib/proxy/codexFallback.ts: convertClaudeMessage (226-288) β€” one-to-many split via a flushMessage closure (238-241) that batches plain content into one Codex item and emits function_call/function_call_output as their own items; buildSystemInstructions (134-168) extracts every Claude system-role message's text (wherever it appears in messages) and joins with \"\\n\\n\" into Codex's flat instructions string; parseFunctionArguments (466-483) is module-private (grepped every ^export line: only CodexFallbackResponseError, CodexFallbackStreamError, codexPromptCacheKey, convertClaudeRequestToCodex, parseCodexFallbackSSE, consumeCodexFallbackResponse, createCodexFallbackStream are exported).\nnode_modules/.pnpm/@anthropic-ai+sdk@0.102.0_zod@4.3.6/.../resources/messages/messages.d.ts:1247-1300 β€” real SDK: ToolChoiceAuto/ToolChoiceAny/ToolChoiceTool each carry disable_parallel_tool_use?: boolean; ToolChoiceNone does not. Same file, MessageCreateParams.messages doc: \"Consecutive user or assistant turns in your request will be combined into a single turn\" β€” a real safety net, not a reason to skip correct grouping (see Β§2).\n~/.neurolink/reference/codex-cli-wire-sample.json: body top-level keys are client_metadata, include, input, model, parallel_tool_calls, prompt_cache_key, reasoning, store, stream, text, tool_choice β€” no top-level session_id/thread_id. body.client_metadata = {thread_id, turn_id, root_turn_id, session_id, x-codex-installation-id, x-codex-window-id, x-codex-turn-metadata}, and bo","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"0. Baseline facts confirmed this pass","lvl3":""}},
10829
+ {"objectID":"c2e5c7087b40a1031b4cb0acd97fa1bfe013a8a76797afb29c9f26bf50094489","title":"1. Tool declaration (unchanged from prior design, confirmed sound)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#1-tool-declaration-unchanged-from-prior-design-confirmed-sound","content":"Real wire shape: one input item {type:\"additional_tools\", id, role:\"developer\", tools: CodexNativeToolNamespace[]}, each namespace {type:\"namespace\", name, description, tools: CodexNativeToolDeclaration[]}, each declaration {type:\"function\", name, description?, strict, parameters} or {type:\"custom\", name, description?, format:{type:\"grammar\", syntax:\"lark\"|\"regex\", definition}}.\n\nMapping Codex→Claude: flatten every namespace's tools in order (namespace order, then declaration order) into one ClaudeTool[] via .map()/concat, never a Record keyed by name (would silently alphabetize and break cache-breakpoint-pinned-to-last-tool). function → {name, description, input_schema: parameters}, strict dropped with reason:\"strict_mode_flag_dropped\". custom → degrade, never drop: {name, description: (description ?? \"\") + \"\\n\\n[Argument grammar, enforced by the original client, not by this model]:\\n\" + format.definition, input_schema: {type:\"object\", properties:{input:{type:\"string\"}}, required:[\"input\"], additionalProperties:false}}, reason:\"custom_tool_wrapped\". Resolves minor finding: description is optional on CodexNativeCustomToolDeclaration (confirmed) — the concatenation must use ??, not bare +, or an omitted description silently becomes the literal string \"undefined\\n\\n...\". Namespace grouping does not round-trip; state that plainly, no reconstruction attempt.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"1. Tool declaration (unchanged from prior design, confirmed sound)","lvl3":""}},
10830
+ {"objectID":"e7488830efba84257b169f8aeb55da12214c3b226b65670de30cfb945bf5c1d6","title":"2. tool_choice + parallel_tool_calls β€” corrected as one mapping, not two","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#2-tool_choice-parallel_tool_calls-corrected-as-one-mapping-not-two","content":"Resolves major finding: the prior design called parallel_tool_calls: false unrepresentable and specified dropping it with a counter. That is factually wrong β€” confirmed directly in the installed SDK (messages.d.ts:1264,1277,1300): Anthropic's tool_choice carries disable_parallel_tool_use?: boolean on the auto/any/tool variants (inverted polarity: disable_parallel_tool_use: true ≑ parallel_tool_calls: false), just not on none. src/lib/types/proxy.ts's own ClaudeRequest.tool_choice doesn't model the field yet β€” a type-completeness gap in this repo, not evidence the protocol lacks it.\n\nType change, src/lib/types/proxy.ts:165-167 (replacing the existing 3-line union in place):\n\nmapCodexToolChoiceToClaude now takes both source fields, because the flag rides on the same object the bijection produces:\n\nBijection table (base cases, unchanged β€” matches codexFallback.ts:436-446 convertClaudeRequestToCodex's inverse and openaiFormat.ts:674-686 convertOpenAIToClaudeRequest's identical precedent, both confirmed verbatim this session):\n\n| Codex native | Claude tool_choice |\n| ------------------------- | --------------------- |\n| \"auto\" / absent | {type:\"auto\"} |\n| \"required\" | {type:\"any\"} |\n| \"none\" | {type:\"none\"} |\n| {type:\"function\", name} | {type:\"tool\", name} |\n\nNo counter fires for parallel_tool_calls any more β€” it is translated, not degraded, so proxy_codex_outbound_unsupported_field_total drops the parallel_tool_calls reason entirely (Β§6 shrinks by one label value).","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"2. tool_choice + parallel_tool_calls β€” corrected as one mapping, not two","lvl3":""}},
10831
+ {"objectID":"57100b7a1b6caea08aedb70914bf077b92b81152d9cbe2faef8d60fd410e9397","title":"3. Model-emitted tool call / client tool result (unchanged, confirmed sound)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#3-model-emitted-tool-call-client-tool-result-unchanged-confirmed-sound","content":"ClaudeToolUseBlock{type:\"tool_use\", id, name, input} ↔ Codex {type:\"function_call\", call_id, name, arguments: string}: id ↔ call_id verbatim, no re-minting (Design 1, Β§5). input β†’ arguments: JSON.stringify(input) unless name was declared custom this turn, then bare String(input.input ?? \"\"), using the same per-request toolKindByName map built at request-translation time.\n\nClaudeToolResultBlock{tool_use_id, content: string | ClaudeContentBlock[]} ↔ Codex {type:\"function_call_output\", call_id, output: string} (confirmed hard string-only ceiling, codex.ts:161-165): call_id ↔ tool_use_id verbatim, output ↔ content as the identical string.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"3. Model-emitted tool call / client tool result (unchanged, confirmed sound)","lvl3":""}},
10832
+ {"objectID":"49a0e637681813144714917cfa9d862d8d7b8c1b6a17f793ee70a7f5d41497e4","title":"4. Parallel/multiple tool calls β€” corrected grouping (resolves the blocker)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#4-parallelmultiple-tool-calls-corrected-grouping-resolves-the-blocker","content":"The finding: a per-item function convertCodexInputItemToClaudeMessages(item, toolKindByName): ClaudeMessage[] cannot produce test-required grouping β€” two sibling function_call items followed by two sibling function_call_output items must collapse into one assistant message (2 tool_use blocks) then one user message (2 tool_result blocks), not four separate messages. A per-item function can only emit 0-1 messages per call, i.e. four messages (assistant, assistant, user, user) for that shape.\n\nAdopted correction, mirroring convertClaudeMessage's flush-accumulator (codexFallback.ts:226-288) run in reverse (many-source-items β†’ one-destination-message instead of one-source-message β†’ many-destination-items):\n\nTwo further corrections (review findings, reconciled against the request-translation section's own Β§4, which solved both of these already for its own, differently-shaped function):\nAdjacent same-role plain messages must coalesce. The version below originally pushed each plain user/assistant item as its own ClaudeMessage. The real capture and every fixture send two consecutive user items (a real prompt, then a synthetic <environment_context> message) β€” exactly the shape assertClaudeMessagesAlternate (cache-preservation section) rejects. A third run buffer, messageRun, coalesces by role the same way the tool-call runs already do. It is flushed only when a tool-call run needs to start (the two kinds of run cannot coexist) β€” not on additional_tools/developer, for the same reason the tool-call runs are not flushed there either: a developer item never itself becomes a messages entry, so flushing early would only reopen a fresh, wrongly-separate group for the next same-role item.\nDeveloper text must stay in array form. systemTexts.push(flattenCodexContentParts(...)) joined every developer message into one string. The request-translation section's cache contract (Β§2, Β§4 there) requires one ClaudeTextBlock per developer segment for cache-breakpoint eligibility β€” a string here ","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"4. Parallel/multiple tool calls β€” corrected grouping (resolves the blocker)","lvl3":""}},
10833
+ {"objectID":"4db3603d29927aec3d3788b582f9716c855b573098d2ace819bddbc309a29743","title":"5. Empty/malformed arguments and oversized payloads (unchanged in substance, function renamed)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#5-emptymalformed-arguments-and-oversized-payloads-unchanged-in-substance-function-renamed","content":"name resolves to custom this turn β†’ arguments is opaque text, wrap {input: arguments}.\nname resolves to function, arguments === \"\" β†’ {}.\nname resolves to function, JSON.parse fails β†’ never throw; degrade to {input: <raw text>}, reason:\"malformed_arguments_wrapped\". This is deliberately asymmetric with parseFunctionArguments (codexFallback.ts:466, which throws): that function sits on the model-output-parsing hot path where a hard failure is correct; this sits on request-ingestion, where fabricating a well-formed fallback and continuing is correct, because failing here fails the whole incoming request pre-dispatch.\nname does not resolve to any currently-declared tool β†’ still emit the best-guess wrapped pair; dropping produces an unbalanced tooluse/toolresult set Anthropic's own validation rejects, strictly worse than a degraded-but-present pair.\n\nResolves minor finding on \"reuse, not duplicate\": the prior design claimed parseCodexNativeFunctionArguments \"reuses parseFunctionArguments via a shared helper\" β€” false, since parseFunctionArguments is module-private and no shared module was ever named. Rejecting the reviewer's alternative (a) (extract an exported helper both directions import) for a technical reason: the two functions have deliberately opposite failure-mode contracts by design (Β§1.6 of the original / Β§5 here) β€” one throws on purpose, one must never throw β€” and the only line-for-line-shared logic is a single JSON.parse(x || \"{}\") try/catch (~4 lines); forcing both through one function needs a boolean/enum mode flag coupling two independently-evolving call sites for a four-line saving, which is a worse trade than accepting the small, documented duplication. Adopted correction: new, independent function in a new module, and the false \"reuse\" claim is dropped, not carried forward.\n\nSize ceilings: reuse the existing numeric constants from codexFallback.ts (maxChars = 16 * 1024 * 1024, toolCalls.size >= 4096 β€” cited, not re-verified line-for-line this pass) via a ","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"5. Empty/malformed arguments and oversized payloads (unchanged in substance, function renamed)","lvl3":""}},
10834
+ {"objectID":"1c404502e5139a9e2b23ddb7a10b5919e560f43f42f32b1f469b2c39dc96aa87","title":"6. Identifier mapping β€” unchanged (Design 1), cross-turn key corrected","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#6-identifier-mapping-unchanged-design-1-cross-turn-key-corrected","content":"Design 1 stands: pass tool_use.id/call_id straight through, no re-minting, no map, in both this new response serializer and the new request translator β€” mirrors this repo's own dominant idiom (openaiFormat.ts:266, tc.toolCallId || generateOpenAIToolCallId() β€” prefer real id, mint only as fallback) rather than codexFallback.ts's response-streaming re-mint, which is the outlier here, not the rule.\n\nResolves major finding on session/thread scoping: the prior design claimed \"top-level session_id/thread_id fields (confirmed live)\" on genuine Codex requests. False β€” re-parsed the real capture directly: body.session_id/body.thread_id are both absent; the only place those identifiers exist is nested, body.client_metadata.{thread_id, turn_id, root_turn_id, session_id}, and body.prompt_cache_key is set to the exact same string as client_metadata.thread_id. The top-level-fields shape belongs only to test/fixtures/codex-request-resumed-session.json, an admittedly-synthetic fixture (_fixtureMeta.basedOn: \"shape only, not copied verbatim\"). Correction adopted: CodexNativeRequest (Β§7) drops the speculative top-level session_id?/thread_id? fields entirely β€” client_metadata?: Record<string, unknown> already covers the real shape structurally, no type change needed there, only the false \"top-level, confirmed live\" prose is removed. Design 2 (the id-remapping fallback, not the default β€” kept unchanged in shape) should key its Map<anthropicToolUseId, codexCallId> by client_metadata.thread_id (or simply the already-present prompt_cache_key, verified to carry the same value), not by invented top-level fields.\n\nResolves major finding on \"resent verbatim every turn\": the prior design told the cache-codex-prefix section it could skip its own dedup/hash logic because \"the whole additional_tools item is resent verbatim by the Codex client on every turn of one thread (confirmed structurally)\". Downgraded: the one real capture is a single first-turn request with zero function_call/function_call","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"6. Identifier mapping β€” unchanged (Design 1), cross-turn key corrected","lvl3":""}},
10835
+ {"objectID":"5f7d76935018ad2c8e0a940bacaf46457ff7f85b68a6cb14f78fe3e1dcc5a2e6","title":"7. JSON-schema translation limits (unchanged, confirmed sound)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#7-json-schema-translation-limits-unchanged-confirmed-sound","content":"| Construct | Decision | Mechanism |\n| ---------------------------------- | --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| plain object/array/required/enum | PASSTHROUGH | input_schema = parameters unchanged |\n| strict:true + all-required trick | PASSTHROUGH, drift undocumented in-band | out of scope to reverse-engineer the nullable-optional trick |\n| format keyword | PASSTHROUGH | not independently verified against live Anthropic this session |\n| oneOf/anyOf/allOf | PASSTHROUGH | not observed in the one real sample; absence isn't proof of absence |\n| $ref/$defs/definitions | FLATTEN | call inlineJsonSchema (src/lib/utils/schemaConversion.ts:105) directly, confirmed exported, confirmed signature (schema, definitions?, visited?, rootSchema?): Record<string, unknown> |\n| circular $ref | DEGRADE | inlineJsonSchema's existing {type:\"object","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"7. JSON-schema translation limits (unchanged, confirmed sound)","lvl3":""}},
10836
+ {"objectID":"b5df2b5ba85927a731ef6ea194054367843b175b0ed01649a010f138e7e2923e","title":"8. Types β€” exact, corrected (src/lib/types/codex.ts, add)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#8-types-exact-corrected-srclibtypescodexts-add","content":"(CodexReasoningEffort already exists, codex.ts:168-175, reused as-is.)\n\nsrc/lib/types/proxy.ts β€” modify ClaudeRequest.tool_choice in place at lines 165-167 (exact replacement text in Β§2).\nsrc/lib/types/proxy.ts β€” modify ProxyMetrics (2177-2194): add schemaDegradedTotal: Counter; and unsupportedFieldTotal: Counter;.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"8. Types β€” exact, corrected (src/lib/types/codex.ts, add)","lvl3":""}},
10837
+ {"objectID":"56d1ba0024a783227c2920a17c276b69022fdf2bbf2b9ae6f5a5eb0e64bb53c0","title":"9. New files and exact signatures","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#9-new-files-and-exact-signatures","content":"src/lib/proxy/streamLimits.ts (new) β€” Β§5.\nsrc/lib/proxy/argumentParsing.ts (new) β€” Β§5, exports parseToolArguments only (kept private: isPlainRecord).\n\nsrc/lib/proxy/codexRequestTranslator.ts (new):\n\nconvertCodexNativeRequestToClaude calls flattenCodexToolNamespaces on the additional_tools item (there is at most one per request, confirmed), then convertCodexInputItemsToClaudeMessages on the full input array, then sets claudeRequest.system = systemBlocks (array assignment, no join) when systemBlocks.length > 0, then mapCodexToolChoiceToClaude(body.tool_choice, body.parallel_tool_calls).\n\nsrc/lib/proxy/codexResponseSerializer.ts (new β€” tool-frame shapes only; the driving byte-buffering/commit-boundary loop is out of scope, owned elsewhere):\n\nsrc/lib/proxy/proxyTracer.ts (modify, alongside proxyTracer.ts:135-148):\n\nTypes introduced: CodexNativeRole, CodexNativeMessageInputItem, CodexNativeFunctionToolDeclaration, CodexNativeCustomToolFormat, CodexNativeCustomToolDeclaration, CodexNativeToolDeclaration, CodexNativeToolNamespace, CodexNativeAdditionalToolsInputItem, CodexNativeFunctionCallInputItem, CodexNativeFunctionCallOutputInputItem, CodexNativeInputItem, CodexNativeToolChoice, CodexNativeToolKind, CodexNativeRequest, CodexNativeStreamError β€” all globally unique (grepped, zero collisions in src/lib/types/).","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"9. New files and exact signatures","lvl3":""}},
10838
+ {"objectID":"d03a06aa285913166a0a136707c39fc8dd13194a9606c1bdebb350cd01e12ff0","title":"10. Test matrix β€” test/continuous-test-suite-codex-outbound-tool-fidelity.ts (new)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#10-test-matrix-testcontinuous-test-suite-codex-outbound-tool-fidelityts-new","content":"Header carries the mandatory determinism-exception note (rule 15's allow-list contract, confirmed pattern at test/continuous-test-suite-proxy-fallback-errors.ts:1-4): \"Determinism exception: exact tool-declaration/argument/id-passthrough shapes need controlled Codex-native request bodies a live model cannot reliably reproduce turn-for-turn; imports only the isolated src/ module graph, mirroring continuous-test-suite-proxy-fallback-errors.ts.\" All assertions below live in this one file unless noted.\ntool_declaration_function_roundtrip β€” one type:\"function\" tool, plain schema β†’ ClaudeTool.input_schema deep-equals parameters; name/description preserved.\ntool_declaration_order_preserved_across_namespaces β€” 2 namespaces Γ— 2+ tools, alphabetical-by-name order β‰  declaration order β†’ output order is declaration order, never alphabetical.\ntool_declaration_custom_grammar_degrades_not_drops β€” real exec/lark shape β†’ tool still emitted, wrapped single-string schema, reason:\"custom_tool_wrapped\" fires.\ntool_declaration_custom_grammar_wrap_survives_missing_description β€” same shape with description omitted β†’ wrapped description is exactly the grammar-notice text, never contains the literal substring \"undefined\" (resolves the ?? finding).\ntool_choice_bijection β€” table-driven \"auto\"|\"required\"|\"none\"|{type:\"function\",name}, parallel_tool_calls absent β†’ exact base tool_choice per case, no disable_parallel_tool_use key present in any case.\ntool_choice_absent_defaults_auto β€” no top-level field β†’ explicit {type:\"auto\"}, not undefined.\nparallel_tool_calls_false_sets_disable_flag_on_auto β€” tool_choice absent, parallel_tool_calls:false β†’ {type:\"auto\", disable_parallel_tool_use:true} (resolves the blocker-adjacent major finding; no counter fires, since this is a full mapping, not a drop).\nparallel_tool_calls_false_sets_disable_flag_on_required_and_function β€” same, for \"required\" β†’ {type:\"any\", disable_parallel_tool_use:true} and {type:\"function\",name} β†’ {type:\"tool\", name, disable_parallel_to","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"10. Test matrix β€” test/continuous-test-suite-codex-outbound-tool-fidelity.ts (new)","lvl3":""}},
10839
+ {"objectID":"24ca22601e1616507858cc4c55c3f62dc6fcf8a69052458145b0f551f39c6f5e","title":"11. CI wiring β€” the part that makes any of this gated","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#11-ci-wiring-the-part-that-makes-any-of-this-gated","content":"None of the above runs in CI merely by existing in test/ or by having an npm script. Confirmed the required path: provider-safety-net (required check, .github/workflows/ci.yml:330) needs provider-safety-net-shards (350-352, matrix [contract, rest]) to succeed; the rest shard's step at .github/workflows/ci.yml:446-448 runs pnpm run test:proxy-reliability, which is node scripts/run-proxy-reliability.mjs (package.json:170), a hardcoded array of suites (scripts/run-proxy-reliability.mjs:4-21) β€” adding a file under test/ or even a new package.json script does not add it to that array.\n\nRequired change: append one entry to scripts/run-proxy-reliability.mjs's checks array (after the existing non-proxy-* entry, following the exact precedent already in that file for continuous-test-suite-vertex-anthropic-fallback.ts, which is not name-templated because it also isn't a proxy-* suite):\n\nNo ci.yml change needed β€” this reuses the existing required rest shard step verbatim. (The alternative β€” a standalone test:codex-outbound-tool-fidelity script plus a new ci.yml step under matrix.group == 'rest', mirroring how test:codex is wired at ci.yml:450-452 β€” is viable but adds a second CI touchpoint for no benefit here, since this suite's runtime cost is comparable to the other wrapper entries; not adopted.)","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"11. CI wiring β€” the part that makes any of this gated","lvl3":""}},
10840
+ {"objectID":"819b151980a89f6934e20b1c96a1d3f58f89f40bdf002b24ad0ba6d17864953f","title":"12. Dependencies on other design sections (unchanged except where corrected)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#12-dependencies-on-other-design-sections-unchanged-except-where-corrected","content":"cache-anthropic / cache-vertex: flattenCodexToolNamespaces still produces a ClaudeTool[] in stable, deterministic order (never a Record), unchanged.\ncache-codex-prefix: session/thread-affinity fact corrected per §6 — use client_metadata.thread_id or prompt_cache_key (verified identical), not invented top-level fields; tool-list turn-over-turn stability is assumed, not confirmed (§6) — that section should not skip its own dedup/hash logic on the strength of this design alone.\nproxy-waste: the two new counters (§7, §9) must still conform to whatever label-cardinality standard that section sets.\nmain / streaming-loop owner: CodexNativeStreamSerializer is still a pure, stateless-per-call emitter, driven by that section's byte-buffering/commit-boundary loop; id-passthrough (§6) remains loop/routing-agnostic.\nRequest translation section: owns codexContentPartToClaudeBlock/plain content-part mapping that convertCodexInputItemsToClaudeMessages (§4) calls into for non-tool message items — this section only owns the tool-call grouping and developer→system extraction inside that same array walk, and hands off content-part-level mapping rather than re-specifying it.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"12. Dependencies on other design sections (unchanged except where corrected)","lvl3":""}},
10841
+ {"objectID":"843927e6ac7457b0a3397cd146775412ac4ffbff1dd35785b43071b7a7835bea","title":"13. Facts still unresolved","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#13-facts-still-unresolved","content":"UNRESOLVED: whether the real Codex CLI validates/enforces any format on a function_call.call_id it did not itself mint β€” the linchpin of Design 1 (Β§6). The one check that would settle it: serve a turn through this fallback so Anthropic mints a toolu_-shaped id, emit it as call_id to a real Codex CLI, confirm it's accepted unmodified on the next turn.\nUNRESOLVED: whether Anthropic's real Messages API enforces any format constraint on an inbound (history) tool_use.id/tool_result.tool_use_id. The one check that would settle it: a live call with a deliberately non-toolu_-shaped id embedded in history, confirming 200 not 400.\nUNRESOLVED: whether Vertex's Claude backend has the same tolerance as #2. The one check that would settle it: the same live-id test run against the Vertex path specifically.\nUNRESOLVED: whether OpenAI's real custom-tool format union has variants beyond the single {type:\"grammar\", syntax:\"lark\", definition} observed. The one check that would settle it: a second real capture containing a custom tool declared without a grammar (e.g. free-text).\nUNRESOLVED: whether a genuine Codex CLI ever nests a namespace inside another, or declares more than the two observed (functions, collaboration). The one check that would settle it: a real capture from a session with MCP servers or many plugins attached.\nUNRESOLVED: whether tool-list content is truly stable turn-over-turn in one thread (Β§6, downgraded this pass from \"confirmed\" to \"assumed\"). The one check that would settle it: a real multi-turn capture (2+ turns, same thread) to diff additional_tools items across turns.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"13. Facts still unresolved","lvl3":""}},
10842
+ {"objectID":"b929fcfbba7f7643df68339e3f78539325b88df64ac2935c7cfa8f31fea3392b","title":"Codex→Anthropic fallback: preserving prompt caching across the hop","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#codexanthropic-fallback-preserving-prompt-caching-across-the-hop","content":"Resolved section for cache-preservation. Depends on cache-codex-prefix for CodexNativeRequest and convertCodexRequestToClaudeRequest; both are cross-section contracts, not code that exists today (confirmed: zero hits for either name under test/ or src/lib/proxy/*.ts).","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"Codex→Anthropic fallback: preserving prompt caching across the hop","lvl3":""}},
10843
+ {"objectID":"99c1a0c1a0b3328b4edececb48a8caf62224168f6fde1a8b664a1be0281a1978","title":"0. Grounding corrections (read before the rest)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#0-grounding-corrections-read-before-the-rest","content":"Two corrections to the original design's own grounding, found by spot-checking real data that already sits in this environment β€” neither was carried into the design, and both are load-bearing.\n\nA real Codex wire capture exists and was not consulted. scripts/generate-codex-fixtures.mjs's header comment says the shape is \"modeled on a real redacted codex_exec/0.155.1 capture (~/.neurolink/reference/codex-cli-wire-sample.json), which is NOT available in this environment.\" That file is present (note: \"Real Codex CLI 0.155.1 /responses request captured 2026-09-21 via a local listener\", read directly this pass). It changes two assumptions:\nIdentity fields are nested, not top-level. The real capture has body.prompt_cache_key: \"01a0c461-7737-7350-9e45-27875f2a6f40\" and body.client_metadata: { thread_id: \"01a0c461-...\", session_id: \"01a0c461-...\", turn_id, root_turn_id, ... } (prompt_cache_key === client_metadata.thread_id verbatim) β€” there is no top-level body.thread_id/body.session_id. The synthetic test/fixtures/codex-request-resumed-session.json puts session_id/thread_id at the top level of body, which this one real sample does not corroborate. Every affinity-key check must read client_metadata, not top-level fields (Β§6 below fixes this β€” resolves review Finding 3, adopted).\nThe functions/collaboration split is per-tool, not per-namespace. additional_tools.tools in the real capture is an array of two {type:\"namespace\", name, tools:[...]} objects. Inside the \"functions\" namespace: wait and request_user_input are type:\"function\" (JSON-schema parameters), but exec is type:\"custom\" with format:{type:\"grammar\", syntax:\"lark\", definition:\"...\"} β€” grammar, not JSON schema. Inside \"collaboration\": all six tools (followup_task, interrupt_agent, list_agents, send_message, spawn_agent, wait_agent) are type:\"function\" with normal parameters. This is the opposite of the synthetic generator's modeled assumption (\"the exec tool lives in collaboration, is type:custom\") and of the origin","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"0. Grounding corrections (read before the rest)","lvl3":""}},
10844
+ {"objectID":"9251bfea08d8fd0980ec18ec3f71cf753c0aafc26288f5906cd4ff275e483a09","title":"1. Types (add to src/lib/types/proxy.ts; already barrel-exported)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#1-types-add-to-srclibtypesproxyts-already-barrel-exported","content":"src/lib/types/index.ts:65 already has export * from \"./proxy.js\" β€” no index.ts edit is needed (the original design listed it as a file to modify; dropped, it was redundant with the existing wildcard export).\n\nNote (resolves review Finding 6, adopted): ClaudeCacheControl (src/lib/types/proxy.ts:73-81) already has ttl?: \"5m\" | \"1h\" with a doc comment describing the 1.25x/2x tradeoff β€” confirmed zero live producers repo-wide (grep -rn '\"1h\"' src/lib hits only this type declaration and unrelated timeRange/timeout-string types). The real gap is narrower than \"add a field to the wire type\": it's that no function threads a caller-supplied ttl into the existing field.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"1. Types (add to src/lib/types/proxy.ts; already barrel-exported)","lvl3":""}},
10845
+ {"objectID":"4a6e2cf01e9eb178bc84bd288224335a6dc3c5abfdd5364c41733a25ce8e5454","title":"2. Breakpoint placement + enforced system-shape invariant","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#2-breakpoint-placement-enforced-system-shape-invariant","content":"Given ClaudeRequest (from cache-codex-prefix) with tools: ClaudeTool[] and system: ClaudeTextBlock[] (ClaudeRequest.system?: string | ClaudeTextBlock[], src/lib/types/proxy.ts:158):\n\nContract cache-codex-prefix must satisfy, enforced defensively here (resolves review Finding 1, adopted): system contains exactly the developer-role-derived blocks and nothing else β€” today length === 4, confirmed across all 4 synthetic fixtures and the one real capture (Β§0). environment_context and any other per-turn payload belong in messages, never appended to system. system[system.length-1] is only a safe breakpoint-1 anchor while this invariant holds; trusting it silently is exactly the \"silent length change with no visible symptom other than a slow cache-hit-rate metric\" the review flagged.\n\nPlacement (unchanged mechanism, now guarded):\nBreakpoint 1: call assertClaudeSystemPrefixShape(request.system, 4) first; on success mark cache_control on system[system.length-1] β€” exactly applyClaudeRequestCacheBreakpoints's existing branch (src/lib/utils/anthropicCacheBreakpoints.ts:244-251, Array.isArray(out.system) && out.system.length > 0 && existing === 0). Because Anthropic renders tools β†’ system β†’ messages, this one marker covers the tool-declarations prefix and all four developer blocks together. No change needed to this branch itself.\nBreakpoints 2-4: exactly applyClaudeHistoryBreakpoints (anthropicCacheBreakpoints.ts:287-324) β€” walks messages from the tail, marks the last text/tool_result block of up to 3 messages, skips a message with no markable block without spending budget. Unchanged.\n\nRequired code change: CLAUDE_EPHEMERAL (anthropicCacheBreakpoints.ts:273, { type: \"ephemeral\" }, no ttl) means every call gets the 5-minute default. Thread an optional TTL into breakpoint 1 only:\n\nAdd function ephemeral(ttl?: \"5m\" | \"1h\"): ClaudeCacheControl { return ttl ? { type: \"ephemeral\", ttl } : CLAUDE_EPHEMERAL; }, used only for breakpoint 1 (the system/tools branch at line 244-251 and the ar","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"2. Breakpoint placement + enforced system-shape invariant","lvl3":""}},
10846
+ {"objectID":"8c09a99076f710a38637f03840911ef761fa74f01b04f14a815f85f40c5aa30b","title":"3. TTL choice: 1 hour on breakpoint 1, 5 minutes on breakpoints 2-4","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#3-ttl-choice-1-hour-on-breakpoint-1-5-minutes-on-breakpoints-2-4","content":"Verified rates, src/lib/utils/pricing.ts:170-175 (claude-sonnet-5): input $2.00/MTok, output $10.00/MTok, cache read $0.20/MTok (0.1x), cache write $2.50/MTok at 5m (1.25x). CATALOG_PRICING's type (pricing.ts:31-40) has a single cacheCreation?: number field, applied unconditionally in the cost formula regardless of the request's actual TTL (pricing.ts:1061-1064, verified: cost += usage.cacheCreationTokens * (rates.cacheCreation ?? rates.input) with no TTL branch) β€” there is no distinct 1-hour rate field today; a 1h-TTL write is silently billed at the 5m/1.25x rate unless pricing.ts gains one (Risk, unresolved by this section β€” belongs to whoever owns cost tracking).\n\nUsing codexFallback.ts's own measured stable-head size (3,700 tokens, cited at codexFallback.ts:340-361) as the worked example, 20 turns:\nAll gaps 5 min (codexFallback.ts:296-298: \"a fallback that arrives in bursts separated by long gaps\" β€” confirmed, this exact phrase is in the file): 5m TTL pays a second write: 2 writes + 18 reads = $0.0330. 1h TTL unchanged at $0.0288 β€” now cheaper, and every additional gap widens the gap further.\n\nChoice: 1-hour TTL on breakpoint 1 only (tools+system prefix, the segment Β§0 shows is plausibly stable in shape and, per the still-open turn-to-turn question, at least stable in developer-block count); 5-minute default (unchanged) on breakpoints 2-4, which slide forward every turn or two (Β§7) β€” paying 2x to protect a marker about to be superseded is pure waste. What this gives up: if Codex-fallback bursts always land inside 5 minutes of each other, this costs ~24% more on breakpoint 1's write for zero benefit β€” an assumption from codexFallback.ts's own comment about the opposite-direction traffic pattern, not a measured fact for this direction (no baseline exists; the feature doesn't exist yet). Revisit using Β§8's measurement once live.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"3. TTL choice: 1 hour on breakpoint 1, 5 minutes on breakpoints 2-4","lvl3":""}},
10847
+ {"objectID":"9344170e321d638525649dd89fe78ee85d350131e6470bc2f4114323c75b6d0f","title":"4. Role-alternation precondition (resolves review blocker 2, corrected)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#4-role-alternation-precondition-resolves-review-blocker-2-corrected","content":"The hazard is real. Anthropic requires alternating user/assistant roles in messages; this codebase already treats consecutive same-role messages as a defect elsewhere: src/lib/context/stages/slidingWindowTruncator.ts:29-38 (validateRoleAlternation, which warns Role alternation broken at index ${i}), src/lib/providers/anthropic/client.ts:2417 (\"Anthropic requires user/assistant alternation around tool blocks\"), test/continuous-test-suite-tasks.ts:2466 (asserts alternation as an invariant). Per Β§0, the real capture's input[5]/input[6] are both role:\"user\" back to back (an auto-injected <recommended_plugins> notice, then the literal user text \"say OK\", no assistant turn between) β€” the same hazard shape as the synthetic fixtures' user-ask-then-environment_context pair, just in reverse order. If cache-codex-prefix maps these 1:1 into two separate ClaudeMessage entries, the request has two back-to-back user messages and Anthropic returns 400 on every Codex-fallback request that hits it.\n\nCorrection to the review's own fix: the review cited openaiFormat.ts:604-654 as \"the pattern this same repo's OpenAI bridge already uses for tool-role folding\" β€” verified false. Read directly: that block pushes one separate {role:\"user\", content:[...]} message per OpenAI \"tool\"-role input (openaiFormat.ts:652-662), with no merge/coalesce step anywhere in the file (grep -n \"messages\\[messages.length - 1\\]\\|merge\\|fold\" src/lib/proxy/openaiFormat.ts β†’ zero hits). Multiple consecutive OpenAI tool messages would produce the identical back-to-back-user hazard in the existing, shipped bridge β€” there is no working precedent to reuse; the repo-wide search for any merge/coalesce helper (mergeConsecutive|foldConsecutive|coalesceMessages|mergeSameRole) matches only the truncator's warn-only validateRoleAlternation.\n\nResolution, scoped to avoid regressing the existing OpenAI bridge: do not add a hard throw inside the shared applyClaudeRequestCacheBreakpoints (it would newly reject already-shipped, al","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"4. Role-alternation precondition (resolves review blocker 2, corrected)","lvl3":""}},
10848
+ {"objectID":"06b4d4d74c1d28bd3985348f5f6cfcacbd6f4ee5cb4671ea467a6ef527feffe6","title":"5. Prefix determinism as an enforceable property + test","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#5-prefix-determinism-as-an-enforceable-property-test","content":"Property: for two consecutive turns of the same conversation with no tool added/removed, tools and system (all 4 elements, per Β§2's enforced invariant) must serialize to byte-identical JSON. messages is explicitly excluded β€” it's expected to vary.\n\nWhat must be byte-stable: no timestamp, request id, or per-turn nonce anywhere in tools or system. None of the fixtures nor the one real sample currently carry one; the hazard is a future Codex CLI version injecting one, which nothing in this repo can prevent upstream β€” only detect via this test.\n\nTest β€” test/continuous-test-suite-codex.ts (CI-gated: package.json:173 defines \"test:codex\": \"pnpm exec tsx test/continuous-test-suite-codex.ts\"; .github/workflows/ci.yml:452 runs pnpm run test:codex under the provider-safety-net-shards job's matrix.group == 'rest' β€” same job, same shard group, as test:proxy-reliability at ci.yml:445, so both are gated together). Uses the file's actual idiom, verified by reading it: import { assert, assertEqual, defineSuite, runCLI } from \"./helpers/harness.js\" (line 87), const { test, runSuite } = defineSuite(\"Codex Pool Engine\", { offline: true }) (line 89) β€” not raw node:assert.\n\nJSON.stringify is safe here (no canonical serializer needed) only because every object on this path is built via .map()/spread over source arrays in fixed field order (Β§2's ordering constraint) β€” if cache-codex-prefix ever stages a field through a Record, this equality check goes flaky on key order and must switch to a sorted-key serializer. Needs new fixture test/fixtures/codex-request-turn2-same-session.json (see Files).\n\nNaming contract on cache-codex-prefix (resolves review Finding 5, adopted β€” neither helper exists today, confirmed via grep): loadCodexFixture(name: string): CodexNativeRequest and convertCodexRequestToClaudeRequest(native: CodexNativeRequest): ClaudeRequest are net-new; this section only names and consumes them, it does not own their implementation.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"5. Prefix determinism as an enforceable property + test","lvl3":""}},
10849
+ {"objectID":"2672bf49096d7f39fe0c3a0c661cdfff223c1a06b455e7f3e0e2d181796d2161","title":"6. Account cache locality (affinity)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#6-account-cache-locality-affinity","content":"Verified: selectClaudeProxyAccountOrder's sessionId param (src/lib/server/routes/claudeProxyRoutes.ts:2638-2645) is a plain string | undefined with zero format validation, flowing straight into sessionAffinity.get(sessionId, now, idleTtlMs) / .bind(sessionId, accountKey, now) (src/lib/proxy/sessionAffinity.ts:13,32 β€” both plain-string keyed, no parsing). The only restriction to Claude-Code-shaped ids lives entirely in extractSnapshotBody (claudeProxyRoutes.ts:3133) β†’ parseClaudeCodeUserId (src/lib/auth/anthropicOAuth.ts:143, requiring metadata.user_id to parse as {device_id: 64-hex, account_uuid: uuid, session_id: uuid}). The storage/routing layer needs no changes; the gap is only that nothing hands it a key for Codex-origin traffic today.\n\nIdentity a Codex request can supply β€” corrected against the real capture (resolves review Finding 3, adopted): the original design's priority list (body.thread_id, then body.session_id, both top-level, from the synthetic resumed-session fixture) is contradicted by the one real sample, which has neither top-level field but does have body.prompt_cache_key (top-level) and body.client_metadata.thread_id / body.client_metadata.session_id (nested), with prompt_cache_key === client_metadata.thread_id verbatim. Prefer the client's own pre-computed key β€” it is already exactly the signal being reconstructed, and it's the same key the real Codex client uses for its own infra affinity:\n\nThe three-way prefix (codex-thread:/codex-session:/codex-prefix:) keeps this from colliding with a Claude-Code metadata.user_id-derived UUID or with itself across cases. Reserve the codex-prefix: hash fallback for when the wire genuinely carries none of prompt_cache_key/client_metadata.thread_id/client_metadata.session_id β€” UNRESOLVED: whether a genuinely first-turn native Codex request ever omits all three β€” the one real sample has all three populated. The check that would settle it: capture one real first-turn (no prior /backend-api/codex call in that sessi","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"6. Account cache locality (affinity)","lvl3":""}},
10850
+ {"objectID":"67524fc996c119db0518a5872294d5cc29a6c67e83aed840d35ba49956ce95bd","title":"7. How breakpoints move as the conversation grows","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#7-how-breakpoints-move-as-the-conversation-grows","content":"No new mechanism: applyClaudeHistoryBreakpoints (Β§2.2) already rolls forward every turn β€” it re-marks the last block of the newest ~3 messages each call; a byte-identical previously-marked prefix from last turn is a cache read this turn, not a re-write, so re-marking it is free. The stable head (breakpoint 1) never moves. Depends on cache-compaction: if compaction rewrites or drops messages inside the currently-marked rolling window (rather than only older, already-unmarked history), every breakpoint at or after the rewritten point misses for that turn β€” inherent to Anthropic's byte-identity cache semantics. cache-compaction's design should prefer compacting only messages strictly older than the last-3-marked window, or account for the resulting cache-miss cost explicitly.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"7. How breakpoints move as the conversation grows","lvl3":""}},
10851
+ {"objectID":"3d1f1497e53e438047d4a4922022c85f719ac41d33aa4d9f9a0b33ec3e6244fd","title":"8. Expected cache-hit outcome and the exact measurement","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#8-expected-cache-hit-outcome-and-the-exact-measurement","content":"Fix: widen proxyTracer.ts's tokenLabels (verified exact shape, src/lib/proxy/proxyTracer.ts:891-893: { model: this.model, account: this.accountEmail ?? \"unknown\" }, no origin field) with one new low-cardinality field, mirroring the existing setServedAccount (proxyTracer.ts:502) / setModelSubstitution (proxyTracer.ts:638) pattern β€” both verified real, both mutate a private field then call this.rootSpan.setAttribute(...):\n\nCall tracer.setRequestOrigin(\"codex-fallback\") at the point the new outbound path enters the Anthropic dispatch β€” same unresolved entry-point location as Β§6.\n\nExpected outcome: proxy_tokens_cache_read for origin='codex-fallback' should become non-zero and dominate over proxy_tokens_cache_creation after the first turn of each conversation/prefix-bucket. No specific target ratio is asserted β€” no baseline exists for this direction yet.\n\nPost-rollout query (columns previously verified live against this environment's metrics store; cumulative-monotonic counter, so MAX(value) per series key before summing, never SUM(value) directly):\n\nRun identically against proxy_tokens_cache_creation; hit rate = cache_read / (cache_read + cache_creation). Pair with the same WHERE/GROUP against proxy_tokens_input as a sanity control β€” an empty result on the cache queries is \"not measured,\" not \"zero,\" unless the input-token control for the same filter is non-empty (proving traffic flowed at all). Not done in this pass: no live baseline query was run β€” the origin label doesn't exist yet.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"8. Expected cache-hit outcome and the exact measurement","lvl3":""}},
10852
+ {"objectID":"fe3f1b672ec6687f716ce5c95641ad2af12f53fe38d35c0174b7a6455b6fc457","title":"Files","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#files-1","content":"| Path | Action | Purpose |\n| ----------------------------------------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| src/lib/utils/anthropicCacheBreakpoints.ts | modify | Add optional ClaudeCacheBreakpointOptions param to applyClaudeRequestCacheBreakpoints, applied only to breakpoint 1 via a new ephemeral(ttl?) builder; breakpoints 2-4 unchanged. |\n| src/lib/proxy/codexOutboundCache.ts | create | assertClaudeSystemPrefixShape, assertClaudeMessagesAlternate, codexAnthropicAffinityKey, ClaudeSystemPrefixShapeError. |\n| src/lib/types/proxy.ts | modify | Add ProxyRequestOrigin, ClaudeCacheBreakpointOptions, CodexAnthropicAffinityKey. |\n| src/lib/proxy/proxyTracer.ts | modify | Add requestOrigin field (default \"native\"), setRequestOrigin(), widen tokenLabels on the token/cost counters at lines 891-922. |\n| test/continuous-test-suite-codex.ts | modify | Add Β§5's determinism + placement test, using the file's existing defineSuite/test/assertEqual/assert idiom (imported line 87, instantiated line 89). |\n| test/fixtures/codex-request-turn2-same-session.json | create | Second-turn fixture: same tools + 4 developer messages as codex-request-interactive-mode.js","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Files","lvl3":""}},
10853
+ {"objectID":"63d19325ea8b0ea3f493aca4cc3efa4a4fafb6646af6297666c8b9996e577bb3","title":"Tests","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#tests-1","content":"Byte-stability + placement determinism β€” test/continuous-test-suite-codex.ts, new test(...) block (Β§5): two consecutive-turn fixtures with unchanged tools/developer-messages produce (a) system.length === 4 on both turns, (b) JSON.stringify-identical tools and system, (c) system[3].cache_control.ttl === \"1h\" on both β€” not just prefix-slice equality, which would pass even with a misplaced marker (Finding 4 fix).\nTTL selection β€” same file: applyClaudeRequestCacheBreakpoints(request, { ttl: \"1h\" }) sets system[system.length-1].cache_control.ttl === \"1h\" on breakpoint 1 while rolling message breakpoints 2-4 keep cache_control.ttl undefined (5m default).\nBudget ceiling β€” same file: a Codex-shaped request already carrying one cache_control marker in its message history never exceeds ANTHROPIC_MAX_CACHE_BREAKPOINTS (4, anthropicCacheBreakpoints.ts:32) after applyClaudeRequestCacheBreakpoints runs, reusing the existing countAnthropicCacheMarkers (anthropicCacheBreakpoints.ts:97) invariant.\nSystem-shape guard β€” same file: assertClaudeSystemPrefixShape throws ClaudeSystemPrefixShapeError when given a system array of length 5 (simulating environment_context leaking into system), and passes silently at length 4.\nRole-alternation guard β€” same file: assertClaudeMessagesAlternate throws naming the offending index on a [user, user] messages array (the exact real-capture and synthetic-fixture shape from Β§4), and passes on a well-formed alternating array.\nAffinity-key derivation β€” same file: four fixtures (has prompt_cache_key / has only client_metadata.thread_id / has only client_metadata.session_id / has none) produce correctly-prefixed codexAnthropicAffinityKey values (codex-thread:/codex-thread:/codex-session:/codex-prefix:); two \"none\" fixtures with identical tools+developer-messages but different environment_context/user turns produce the same codex-prefix: key, proving it is prefix-derived, not full-body-derived.\nPost-rollout live measurement (not a unit test, an explicit accep","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Tests","lvl3":""}},
10854
+ {"objectID":"d9e5c4fb16eb23fa18343d304300da51315a3f7e739b75e62249044245095b77","title":"Risks","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#risks","content":"1-hour TTL on breakpoint 1 costs ~24% more than 5-minute if Codex-fallback bursts always land under 5 minutes apart β€” an assumption borrowed from codexFallback.ts's comment about the opposite-direction traffic pattern, not a measured fact for this direction; no baseline exists yet (Β§3).\nFirst-turn Codex session identity beyond prompt_cache_key/client_metadata is still unverified against more than one live capture (Β§0, Β§6 UNRESOLVED) β€” if it is ever genuinely absent, concurrent distinct conversations sharing one Codex agent config collide into the same prefix-derived affinity bucket until each gets its own id.\nHard architectural blocker, unchanged: codexAnthropicAffinityKey can only reach selectClaudeProxyAccountOrder/bindSessionAfterServe if the not-yet-decided Anthropic dispatch entry point exposes an explicit sessionAffinityKey override seam instead of hardcoding extractSnapshotBody(body) β€” verified current call site (claudeProxyRoutes.ts:5364-5366) has no such seam today.\npricing.ts has no dedicated 1-hour cache-write rate field (verified, Β§3) β€” any cost computation for this path that doesn't add one silently uses the 5-minute (1.25x) rate and under-reports actual spend on 1h-TTL writes.\nIf cache-compaction rewrites a message inside the currently-marked rolling window, every breakpoint at or after that point misses simultaneously for that turn β€” a full-price spike indistinguishable from normal operation unless the new origin-labeled counters (Β§8) are actively watched for a drop-then-plateau pattern.\nWidening proxyTracer's tokenLabels with a new origin field changes the label set of an already-live, already-queried OTLP counter β€” confirm no existing dashboard/alert assumes exactly {model, account} as the complete label set before shipping.\nThe role-alternation guard (Β§4) and system-shape guard (Β§2) are scoped to the new Codex-fallback entry point only, by design, to avoid regressing the existing OpenAI bridge's already-shipped (separately latent, out-of-scope-here","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Risks","lvl3":""}},
10855
+ {"objectID":"df035c62f0167fe540ffd558b538382bef1d43eb53c97d1989ad4159183c789c","title":"Codex Outbound Fallback β€” Trigger Policy, In-Flight Commitment Safety, Loop Prevention, Accounting","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#codex-outbound-fallback-trigger-policy-in-flight-commitment-safety-loop-prevention-accounting","content":"Resolved section for \"Codex outbound fallback\" (native Codex client request falls back to Anthropic/Vertex). All line numbers below are approximate (~) pointers verified against /Users/sachinsharma/Developer/Official/fix/proxy-ci-gaps-and-dead-leg-alert on 2026-09-27; re-grep before wiring, this repo's own CI-reading lessons apply to source line drift too.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Codex Outbound Fallback β€” Trigger Policy, In-Flight Commitment Safety, Loop Prevention, Accounting","lvl3":""}},
10856
+ {"objectID":"aa4bc8159eafd24e706ac51252e8c06f580647a3cb2445aa1e9a9c585e5c2cfb","title":"0. Corrections carried in from design + review, confirmed by direct read this session","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#0-corrections-carried-in-from-design-review-confirmed-by-direct-read-this-session","content":"Four pre-commit insertion points, not two (design's own correction, re-verified): codexProxyRoutes.ts:878 (accounts.length===0), :895-896 (eligible.length===0), :1057-1076 (non-retryable transport error inside the inner per-account fetch catch, un-rotated single-account terminal return), :1454-1458 (end-of-account-loop fallthrough). Confirmed the third site verbatim: the catch block computes errorCode, and only rotates (break) when errorCode is one of UND_ERR_CONNECT_TIMEOUT|ECONNREFUSED|ENOTFOUND|EAI_AGAIN; every other transport error hits return buildCodexErrorResponse(502, ...) immediately, trying no other account.\nProxyContextPreflightError/token-budget errors are not \"re-thrown past\" the fallback sites β€” they never reach them. Corrected from the design's own Β§1 table: codexProxyRoutes.ts:850-861 catches ProxyContextPreflightError locally and returns buildCodexErrorResponse directly inside dispatch()'s own outer try, before any account is even loaded; :961-972 does the same for getProxyTokenBudgetError. Both are independent, self-contained terminal returns, not exceptions that skip past the four insertion points listed above β€” they simply never touch those four call sites at all. The trigger-table conclusion (never fall back) is unchanged; only the mechanism description changes.\nServerContext.metadata is Record<string, unknown> at src/lib/types/server.ts:291 (design cited :256; corrected pointer, same fact).\nrecordFallbackAttempt's shape, classifyProxyFailureCode's vocabulary, preflightAnthropicStream's four-kind result, buildProxyTranslationPlan's single-entry dedup, executeClaudeCodexFallback's nested-ctx pattern (${ctx.requestId}:codex-fallback), and test:codex β†’ test/continuous-test-suite-codex.ts β€” all re-read this session and match exactly as designed/reviewed.\nCI job naming (review's minor finding, adopted): the required check is provider-safety-net (ci.yml:330), which is a thin needs:[provider-safety-net-shards] pass-through with if: always(). The actual","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"0. Corrections carried in from design + review, confirmed by direct read this session","lvl3":""}},
10857
+ {"objectID":"b7f180f9d8a074c15628193e2b7b0db775850568f4aae519251dfbec51372b8b","title":"1. Trigger policy β€” total function over a classified error","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#1-trigger-policy-total-function-over-a-classified-error","content":"New type, src/lib/types/codex.ts (named export, type alias only β€” no interface, per repo rule 7):\n\n\"context_preflight\" and \"token_budget\" are dropped from this union (review-adjacent correction, Β§0): those two conditions never reach a call site that would construct a CodexOutboundFailureInput at all (see Β§0), so encoding them as classifier inputs was dead code the classifier could never receive. Not modeled β‡’ not silently mis-triggered.\n\nNew function, src/lib/proxy/codexOutboundFallback.ts (new file):\n\nclassifyProxyFailureCode is reused unchanged from src/lib/proxy/proxyFailureDetails.ts:4-29 (confirmed vocabulary: cyber_policy|content_policy_violation|content_filter|safety_violation β†’ {403,false}; max_output_tokens|context_length_exceeded|invalid_request_error|empty_response β†’ {undefined,false}; else {status: code==='rate_limit_exceeded'?429:undefined, retryable:undefined}).\n\nTrigger/no-trigger table:\n| Condition | Fallback? | Why |\n|---|---|---|\n| no_accounts / all_accounts_cooling | yes | unconditionally terminal today; says nothing about request validity |\n| 429 on an account, mid-rotation | no fallback here | existing cooldown+rotate already tries the next Codex account; only account_loop_exhausted with a still-429-shaped lastStatus triggers fallback |\n| 401/403 exhausted after refresh+rotate | yes, via account_loop_exhausted | credential failure on Codex's OAuth pool says nothing about Anthropic's |\n| 5xx exhausted after rotation | yes, via account_loop_exhausted | classic provider-outage case |\n| non-retryable transport error, single account | yes, via network_error_unretryable | corrected insertion point #3; today silently terminal, zero retries |\n| retryable transport error | no fallback here | existing same-account/rotate logic handles it; only exhaustion reaches account_loop_exhausted |\n| deliberate 4xx about request validity (any code classifyProxyFailureCode marks non-retryable, or an unrecognized code with lastStatus in 400-499 excluding 429) | never |","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"1. Trigger policy β€” total function over a classified error","lvl3":""}},
10858
+ {"objectID":"34488fbb61f78386866bbc43fa18d62d49c42f1e2f39daedae7ad8b6e4b63372","title":"2. Streaming commitment semantics","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#2-streaming-commitment-semantics","content":"Corrected commit point (review [blocker] + [major], both adopted β€” this materially changes the design from the prior draft):\n\nThe prior draft planned to re-run preflightAnthropicStream(reader) on the value returned by handleAnthropicRoutedClaudeRequest and to treat kind:\"transport_error\" the same as empty/sse_error (both \"safe to try next leg\"). Both are wrong, confirmed by direct read:\nhandleAnthropicRoutedClaudeRequest already ran the full account loop internally, including preflightAnthropicStream, before ever returning to its caller (claudeProxyRoutes.ts:10949, return successResult.response; β€” the loop only exits once an account's attempt is fully resolved as served/terminal). Re-running the preflight on the returned value re-buffers bytes that already passed and cannot produce a different verdict, and has no way to unwind an already-finalized account selection if it tried to. Do not call preflightAnthropicStream a second time anywhere in the Codex-outbound path.\nhandleAnthropicStreamingSuccessResponse's own transport_error branch (claudeProxyRoutes.ts:7106-7135) is categorically terminal, never rotated, with an explicit comment: \"The POST has already returned a response. The upstream may have started processing it, so replaying it on another account could duplicate work\" β†’ it returns served:false via finalizeAnthropicTerminalTransportError, which itself is folded into whatever handleAnthropicRoutedClaudeRequest ultimately returns as a terminal failure, not a retry signal. The ambiguous-side-effects concern is generic to \"did the POST already leave the process,\" not specific to same-vs-cross-engine, so it transfers unchanged to this hop: Codex must not further rotate to Vertex/a different Anthropic account past this outcome either. Because it is already terminal inside handleAnthropicRoutedClaudeRequest, no special casing is needed at the Codex-outbound layer β€” it simply falls out of the ordinary \"did this call succeed\" check in Β§4 below as a failure with status","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"2. Streaming commitment semantics","lvl3":""}},
10859
+ {"objectID":"8f67bd3d725852b79afe878544b4af7a1bad8a426ffefe6f47555bc14a460b99","title":"3. Loop prevention","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#3-loop-prevention","content":"Existing state (confirmed): CODEX_FALLBACK_METADATA_KEY = \"neurolink.codexFallback\" (codexProxyRoutes.ts:109), read at :542,:556,:670 (accounting/logging only, no routing gate). isFallbackRequest computed at :669-670. buildProxyTranslationPlan (routingPolicy.ts:33-75, confirmed) dedupes only an exact match against primary {provider,model}; appends auto-provider only when allowAutoFallback is explicitly true and the chain is empty/already-deduped-to-one. No chain-wide visited-set.\n\nInvariant: at most one engine crossing per client request per direction; a leg that is itself already an inner fallback of the other engine may never itself fall outbound. Formally: the ordered sequence of engines serving any one client request has length ≀ 2 with no repeat β€” [codex], [anthropic], [codex,anthropic], [anthropic,codex] are the only allowed sequences.\n\nTwo independent mechanisms:\nMarker-based cut (primary).\nAt the top of dispatch() in codexProxyRoutes.ts, where isFallbackRequest is already computed (:669-670): if isFallbackRequest === true, skip every call to classifyCodexOutboundFailure/attemptCodexOutboundFallback unconditionally at all four insertion points β€” they fall straight through to their existing terminal responses, unchanged.\nattemptCodexOutboundFallback builds the nested Anthropic-facing ServerContext (mirrors executeClaudeCodexFallback's nested-ctx construction, codexProxyRoutes.ts pattern at claudeProxyRoutes.ts:5564-5619, inverted) and sets:\n \n on the same untyped ServerContext.metadata bag (types/server.ts:291) β€” no type change, matching the \"neurolink.codexFallback\" convention exactly.\nOne additive line inside handleAnthropicRoutedClaudeRequest (claudeProxyRoutes.ts:10241, its existing buildProxyTranslationPlan call):\n \n buildProxyTranslationPlan's signature is untouched. Confirmed grep -rn '\"neurolink.codexOutboundFallback\"' returns zero existing writers today, so this filter is provably a no-op for every current caller.\nDepth counter (defens","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"3. Loop prevention","lvl3":""}},
10860
+ {"objectID":"946d37ca9df040de443c00067c0e76808ee77cb46209fbad6aa54fab1d2868ba","title":"4. Accounting","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#4-accounting","content":"Decision: mirror the nested-ctx pattern (Codex-as-fallback-target), inverted — not the flat/shared-ctx Vertex pattern. Anthropic's own account rotation (ranking, admission leases, cooldowns, session affinity) is reachable only through a route-shaped, currently-unexported function (handleAnthropicRoutedClaudeRequest, confirmed not exported today), structurally identical to why Codex needed the heavier pattern in the existing Claude→Codex direction. The lightweight Vertex pattern is unavailable without duplicating Anthropic's rotation logic in codexProxyRoutes.ts (rejected) or genuinely reusing the route function (this design).\n\nNew minimal export, src/lib/server/routes/claudeProxyRoutes.ts:\n\nEvery routing/account-strategy field mirrors handleAnthropicRoutedClaudeRequest's own parameter list exactly (confirmed at claudeProxyRoutes.ts:10193-10214) and must be read from the same live ProxyRuntimeConfigSnapshot the real /v1/messages handler resolves (requestRouting at the route registration, :11241) — never hand-rolled defaults, or the two paths drift.\n\nNew type, src/lib/types/codex.ts:\n\nStatus recovery — the corrected mechanism (§0's new finding drives this; the prior draft's plan to read outcome.status off a uniform shape does not survive contact with the code):\n\nexecuteAnthropicRoutedRequestForFallback builds its own child runtime context via createClaudeRequestRuntimeContext with one additive, optional field:\n\nWhen true, the returned logFinalRequest closure (built at claudeProxyRoutes.ts:9316-9333) becomes a no-op for the client-facing final-request-log row and this leg's own span-end only. It must NOT be a pure no-op: executeAnthropicRoutedRequestForFallback wraps it in its own outer closure that captures the call arguments into a local variable before discarding them, because logFinalRequest(status, accountLabel, accountType, errorType?, errorMessage?, extra?) is confirmed to be called synchronously, on every exit path except one, with the real numeric status, befo","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"4. Accounting","lvl3":""}},
10861
+ {"objectID":"610f05cb555bbf7c9d413bd14f4b98d80438ffbc77ff71462f071ca59aa386b7","title":"Risks / open items","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#risks-open-items","content":"The native Codex passthrough path (upstream.ok) still has no preflight-buffering equivalent to preflightAnthropicStream; unrelated pre-existing gap, not fixed here.\ntest/continuous-test-suite-proxy.ts is not invoked by any CI workflow; any new determinism case must land in test/continuous-test-suite-codex.ts or it gates nothing.\nproxy_fallback_* keeps {provider, model} labels; per-account attribution requires correlating against proxy_cost_usd_total instead.\nThis section assumes a translated ClaudeRequest and CodexResponsesStreamSerializer/translateAnthropicToCodexResponse already exist by the time attemptCodexOutboundFallback runs; both are explicitly owned by the translation-layer section.\nUNRESOLVED: whether a genuine native Codex client ever sends stream:false β€” the repo shows convertClaudeRequestToCodex always setting stream:true for the existing, opposite-direction leg, but nothing in this repo constrains what a real Codex CLI client sends inbound. The one check that would settle it: read the Codex Responses API client behavior directly (upstream OpenAI docs or a captured real request), not this repo, since this repo is the proxy, not the client.\nUNRESOLVED: the exact Response-vs-plain-object status of tryConfiguredClaudeFallbackChain's own .response field was not traced to its own terminal builder in this pass (time-bounded); Β§4's result instanceof Response / captured-logFinalRequest discriminator is designed to cover it either way, but the one check that would settle it with certainty is reading tryConfiguredClaudeFallbackChain (claudeProxyRoutes.ts:6035 onward) end to end before implementation.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Risks / open items","lvl3":""}},
10862
+ {"objectID":"0c56ec28b220ccaf05ed1d82358778678878bfc0414bfa2de8bb1a9873f7bf94","title":"Configuration surface, staged rollout β€” Codex outbound fallback","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#configuration-surface-staged-rollout-codex-outbound-fallback","content":"Scope: config schema, validation, runtime wiring, kill switch, PR sequencing, observability, docs. Does\nnot own translation (Codex Responses ⇄ Anthropic Messages body/stream), tool-call fidelity, or\ncache-breakpoint placement β€” those belong to cache-codex-prefix / cache-anthropic / cache-vertex. Every\ncitation below was re-read from .../fix/proxy-ci-gaps-and-dead-leg-alert on 2026-09-27; where the prior\ndesign's citation was off, the number here is the one actually in the file.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"Configuration surface, staged rollout β€” Codex outbound fallback","lvl3":""}},
10863
+ {"objectID":"2d83e96fc0cc8aab2b8cb841ab658256fd8c98bbf95477af98105ba95561a576","title":"A. Types","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#a-types","content":"src/lib/types/subscription.ts, new type placed beside ModelMapping (1186–1190) and\nFallbackEntry (1193–1198), inside ProxyRoutingConfig (1201–1256, spillInflight is its last field\nat 1255):\n\nAdd to ProxyRoutingConfig after spillInflight (after line 1255):\n\nFallbackEntry reuse was checked and rejected β€” it carries reasoningEffort (\"Explicit Codex fallback\neffort\"), meaningless once the request is already Anthropic-format. ModelMapping's generic\n{from,to,provider} is reused for the override map β€” no direction-specific semantics baked in.\n\nsrc/lib/types/proxy.ts, ProxyRequestRoutingSnapshot (3744–3761) β€” add the same 3 fields,\nnon-optional/defaulted (request-time code reads via ProxyRuntimeConfigProvider = () =>\nProxyRequestRoutingSnapshot, 3819):\n\nProxyRuntimeConfigSnapshot = ProxyRequestRoutingSnapshot & {...} (3768) inherits them automatically β€”\nno separate edit there.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"A. Types","lvl3":""}},
10864
+ {"objectID":"63260f4c94ef47b8181dfc8f45559626aac250bdde0e1b3427293c36bc36aa85","title":"B. Config parsing β€” src/lib/proxy/proxyConfig.ts","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#b-config-parsing-srclibproxyproxyconfigts","content":"Kebab keys: codex-outbound-fallback-enabled, codex-outbound-fallback-targets,\ncodex-outbound-fallback-model-mappings. All three read via readRoutingPolicyKey() (325–333,\npresence-based, explicit null rejected) β€” not readLegacyRoutingKey() (303–315, null-means-unset),\nwhich exists only for keys predating the routing-policy convention.\n\nHard validator, inside validateProxyConfig (339+), insert after the spill-inflight block (568–578,\nbefore line 579's closing brace of the hasRouting block):\n\nMAX_CODEX_OUTBOUND_FALLBACK_TARGETS = 8 is a new module constant next to MIN_SPILL_INFLIGHT/\nMAX_SPILL_INFLIGHT (274–277) β€” the prior design left this uncapped and flagged it as an open risk\n(unbounded chain degrades worst-case exhausted-turn latency linearly); 8 is a deliberate decision here (2\nproviders Γ— up to 4 models each is generous headroom), following this file's precedent of small named\nMIN/MAX constants for array-shaped routing keys.\n\nSoft parser, inside parseRoutingConfig (684–1024, returns Partial<ProxyRoutingConfig> | undefined),\ninsert right before return result; (1024). Correction to the prior design: it cited account-allowlist's\nsoft-parse as the \"per-entry-drop\" precedent; re-read, account-allowlist (928–932) does no per-entry\nvalidation β€” it just coerces every entry to a trimmed string via String(entry).trim(). The real\nper-entry-drop precedent is model-mappings/fallback-chain (700–726, 730–760): each maps every entry,\ndrops ones missing required string fields with a logger.warn, filters nulls β€” the pattern to copy:\n\nNote (unchanged from prior design, re-verified): the two validators intentionally disagree on\nstrictness β€” hard validator rejects outright, soft parser drops the one bad entry β€” matching this file's\nexisting convention for the other 5 routing-policy keys.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"B. Config parsing β€” src/lib/proxy/proxyConfig.ts","lvl3":""}},
10865
+ {"objectID":"8d534dc0d39936fdf8de1682a7584fa4bb73fe2c818737d071d252df6b7d1280","title":"C. Runtime wiring","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#c-runtime-wiring","content":"src/lib/proxy/runtimeConfig.ts, buildCandidate() (236–345): routing there is\nproxyConfig?.routing (287), typed Partial<ProxyRoutingConfig> | undefined, so\nrouting?.codexOutboundFallbackTargets etc. type-check once section A lands. Add, next to the existing\nspillInflight read (358):\n\n...then add all three to fingerprintSource's JSON.stringify (359–373 β€” already includes routing:\nrouting ?? null, so raw values are change-covered; the extra fields just give request-time code one\nalready-defaulted read) and to the frozen snapshot return (Object.freeze({...}), 376–400), in the same\nposition spillInflight occupies in each β€” copy-paste-and-rename, not a new mechanism.\n\nKill switch, mirroring resolveQuotaRoutingEnabled (62–70) with one deliberate default difference:\n\nEnv var NEUROLINK_PROXY_CODEX_OUTBOUND_FALLBACK β€” no collision with NEUROLINK_PROXY_CODEX_CAPTURE\n(unrelated debug flag, codexUsage.ts:211) or the mirrored precedent NEUROLINK_PROXY_QUOTA_ROUTING\n(runtimeConfig.ts:312). Env wins whenever set, identical precedence to quota routing.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"C. Runtime wiring","lvl3":""}},
10866
+ {"objectID":"cb97cd01523849f93508e9bb06f26653a08ac66c697de22270abd670c0a702a8","title":"D. The two call sites that need a runtimeConfigProvider β€” corrected scope","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#d-the-two-call-sites-that-need-a-runtimeconfigprovider-corrected-scope","content":"Review finding, CONFIRMED by direct read, adopted: the prior design's PR2 claimed\nroutes/index.ts:75 could \"just also pass the existing runtimeConfigProvider\" into\ncreateCodexProxyRoutes alongside the other engines. That is false. There are two independent call\npaths, and only one of them has a provider today:\nsrc/cli/commands/proxy.ts (neurolink proxy start, live path) β€” runtimeConfigProvider IS\n built here, at 2209 (runtimeConfigStore ? () => runtimeConfigStore.getSnapshot() : undefined), and IS\n already passed to createClaudeProxyRoutes (2212–2222), createOpenAIProxyRoutes (2226–2231, 5th arg\n (request) => app.fetch(request), confirmed in-process not a socket call), and createGeminiProxyRoutes\n (2236–2240). createCodexProxyRoutes(\"\") at line 2235 is the one call passing only basePath β€” the\n real \"just thread the existing provider\" site, one line: createCodexProxyRoutes(\"\", runtimeConfigProvider).\nsrc/lib/server/routes/index.ts, createAllRoutes() (40–83) β€” the SDK-embeddable path. No\n engine receives a provider here: createClaudeProxyRoutes(undefined, basePath) (67),\n createOpenAIProxyRoutes(undefined, basePath) (71), createCodexProxyRoutes(basePath) (75),\n createGeminiProxyRoutes(undefined, basePath) (79) are all 2-arg calls, and CreateRoutesOptions\n (src/lib/types/server.ts:1410–1426) has no field for one β€” a pre-existing gap, not Codex-specific.\n\nResolution (scoped narrowly β€” no retroactive fix to openai/gemini's gap, out of scope here and risks a\nbehavior change on two engines nobody asked to touch): add one optional field to CreateRoutesOptions and\nthread it only to Codex:\n\nAn SDK consumer of createAllRoutes who never passes runtimeConfigProvider gets undefined threaded\nthrough exactly as codexProxyRoutes.ts already treats an absent provider (Β§E) β€” zero behavior change for\nevery existing caller.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"D. The two call sites that need a runtimeConfigProvider β€” corrected scope","lvl3":""}},
10867
+ {"objectID":"35f1811a690ce842a5f2d72eeaf42861cf1ac0d83634e22bf8c208f65d7d27ec","title":"E. createCodexProxyRoutes signature extension β€” src/lib/server/routes/codexProxyRoutes.ts","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#e-createcodexproxyroutes-signature-extension-srclibserverroutescodexproxyroutests","content":"Confirmed: export function createCodexProxyRoutes(basePath: string = \"\"): RouteGroup (1666), handlers\n(ctx) => handleCodexResponsesRequest(ctx) / (ctx) => handleCodexModelsRequest(ctx) β€” single-arg,\nnothing closed over. RouteGroup (src/lib/types/server.ts:443–457) has no config-provider slot, unlike\nopenaiProxyRoutes.ts/geminiProxyRoutes.ts (explicit positional param) or claudeProxyRoutes.ts (union\n6th param AccountAllowlist | ClaudeProxyRouteRuntimeOptions, disambiguated by\nisClaudeProxyRouteRuntimeOptions() at 11097). Decision (re-verified sound): plain optional 2nd\nparameter, matching openai/gemini β€” Codex has no allowlist to disambiguate against, so Claude's\nunion-type trick is pure overhead here:\n\nThreaded down: handleCodexResponsesRequest(ctx, runtimeConfigProvider?) (539) β†’\nexecuteCodexResponsesRequest(ctx, runtimeConfigProvider?) (623, currently single-arg).","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"E. createCodexProxyRoutes signature extension β€” src/lib/server/routes/codexProxyRoutes.ts","lvl3":""}},
10868
+ {"objectID":"af188c55bf16f287c28724969ae67edea089750934253d0936134977f126a528","title":"F. Insertion points and the budget-lease requirement they must satisfy","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#f-insertion-points-and-the-budget-lease-requirement-they-must-satisfy","content":"Two insertion points, both confirmed by direct read:\n~895–896: if (eligible.length === 0) { ... } β€” today, an immediate buildCodexQuotaExhaustedResponse\n (429). New: before building that response, if runtimeConfigProvider?.().codexOutboundFallbackEnabled\n AND targets non-empty AND !isFallbackRequest, attempt the outbound chain instead.\n~1458–1461: end of the for (const account of eligible) loop β€”\n await recordFinalOutcome(lastAttemptedAccount, lastErrorStatus, {...}); return\nbuildCodexErrorResponse(...);. Same gate, symmetric (every pooled account tried and failed).\n\nReview finding, CONFIRMED, adopted as a hard requirement β€” missing from the prior design entirely.\nrecordFinalOutcome (738–760+) calls await settleBudget(...) as its literal first statement (744),\nbefore the finalOutcomeRecorded latch, writeFinalLog, or tracer?.end(). settleBudget (635–657)\neither confirms the last-attempted account's ProxyTokenBudgetLease via\nsettleProxyTokenBudget(budgetLease, actualTokens) when dispatched, or cancels via\nbudgetLease.cancelBeforeDispatch(). The per-account loop settles each iteration's lease at the top of the\nnext iteration (947–951) β€” but there is no next iteration once the pool is exhausted. The outer\ncatch (1465–1467) also calls settleBudget(), but only on a thrown error, not in a finally. If a new\noutbound-fallback branch returns a translated success response instead of falling through to\nrecordFinalOutcome/buildCodexErrorResponse, the last-attempted account's budgetLease is never\nsettled and its reserved token budget leaks indefinitely.\n\nRequirement, binding on PR 4/5: the outbound-fallback code at both insertion points must call\nawait settleBudget(actualTokens) (the closure already in scope inside executeCodexResponsesRequest)\nbefore returning any response β€” success or failure β€” since it cannot assume recordFinalOutcome runs\nafterward (on the success path it will not).","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"F. Insertion points and the budget-lease requirement they must satisfy","lvl3":""}},
10869
+ {"objectID":"a97e847933a8a10199f19a9dbcd7510dd1c77676094d93ca76210d2f73bb76a3","title":"G. Reentrancy guard (unchanged, re-verified sound)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#g-reentrancy-guard-unchanged-re-verified-sound","content":"CODEX_FALLBACK_METADATA_KEY = \"neurolink.codexFallback\" (codexProxyRoutes.ts:109), read as\nisFallbackRequest = ctx.metadata?.[CODEX_FALLBACK_METADATA_KEY] === true (669–670), set by\nclaudeProxyRoutes.ts when Claude falls back into Codex. Both new insertion points (Β§F) must add\n!isFallbackRequest to their gate β€” without it, Claude β†’ Codex (exhausted) β†’ Anthropic β†’ (fails) β†’ Codex\nagain can loop; the flag already exists for exactly this hazard and the new direction must inherit it.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"G. Reentrancy guard (unchanged, re-verified sound)","lvl3":""}},
10870
+ {"objectID":"d4b27ab316c85018a16aef24ad0db5672fbc010fb85baa1b677cd6d7561325c0","title":"H. Dispatch-target gap β€” still open, framing corrected","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#h-dispatch-target-gap-still-open-framing-corrected","content":"Review finding, CONFIRMED, adopted: the prior design characterized the loopback-dispatch option (Codex\nβ†’ Claude engine via an HTTP-shaped internal request, the pattern openaiProxyRoutes.ts uses for its own\nbridge) as costing \"a real network hop.\" Not true of this repo's deploy path: openaiProxyRoutes.ts takes\ninternalDispatch?: (request: Request) => Response | Promise<Response> (line 295), dispatching via\ninternalDispatch ? internalDispatch(new Request(...)) : fetch(...) (432–433); cli/commands/proxy.ts\n(2226–2231) constructs createOpenAIProxyRoutes with (request) => app.fetch(request) as that 5th arg β€”\nconfirmed in-process, no socket. A Codex β†’ Claude loopback built the same way is not inherently a\nnetwork-cost tradeoff; the real difference vs. a direct in-process ctx-spread call\n(executeClaudeCodexFallback, claudeProxyRoutes.ts:5564–5603, confirmed not exported) is API shape\n(Request/Response marshaling vs. direct ctx reuse), not transport cost.\n\nThis does not resolve the gap β€” genuinely open, not this section's call. claudeProxyRoutes.ts exports\nexactly 14 top-level symbols (resolveServedFallbackModel, createClaudeProxyRoutes,\ngetTransientSameAccountRetryDelayMs, getOverloadRotationDelayMs, parseClaudeErrorBody,\nisInvalidRequestError, isSubscriptionBetaRejection, isAccountEntitlementError,\nisDurableEntitlementBlock, buildProxyFallbackOptions, isTransientHttpFailure, isUpstreamOverload,\nredactProviderErrorMessage, __testHooks), none a symmetric handleClaudeMessagesRequest. Exposing one,\nor wiring the already-in-process openai-style loopback, is PR 3's job and not decided here β€” a\ntranslation/dispatch question for whichever sibling section (closest candidate: cache-anthropic) touches\nclaudeProxyRoutes.ts's export surface. executeVertexAnthropicFallback(args: {body, model, signal?,\nonTerminal?}): Promise<Response> (vertexAnthropicFallback.ts:611, shape confirmed) remains immediately\nreusable as-is for Codex β†’ Vertex β€” zero new dispatch surface for that leg.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"H. Dispatch-target gap β€” still open, framing corrected","lvl3":""}},
10871
+ {"objectID":"5f21ea053c45174cb01d896637af02ccdbbb42c6eeadb91ed46e6f72c62c214d","title":"I. Staged rollout (one commit per PR, scope-mandatory conventional commit, e.g.","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#i-staged-rollout-one-commit-per-pr-scope-mandatory-conventional-commit-eg","content":"feat(proxy-codex-fallback): ...; each PR must independently pass pnpm run check:all)\n\nPR 1 β€” No-op skeleton. Files: src/lib/types/subscription.ts (Β§A), src/lib/types/proxy.ts (Β§A),\nsrc/lib/proxy/proxyConfig.ts (Β§B). Nothing else changes; nothing reads the new fields yet. Test:\nvalidateProxyConfig accepts/rejects the 3 new keys in isolation.\n\nPR 2 β€” Runtime plumbing and both call sites, still no-op. Files: src/lib/proxy/runtimeConfig.ts (Β§C),\nsrc/lib/types/server.ts (Β§D, CreateRoutesOptions field), src/lib/server/routes/index.ts (Β§D),\nsrc/cli/commands/proxy.ts (Β§D, line 2235), src/lib/server/routes/codexProxyRoutes.ts (Β§E signature\nextension only β€” insertion points ~896/~1458 stay byte-identical; the new parameter is accepted, stored,\nnever branched on). Corrects the prior design's understated scope: explicitly includes the\nCreateRoutesOptions field and routes/index.ts threading, not just a one-line change at a site that\nturned out not to exist. Tests: configHash changes when -enabled flips (fingerprint wiring);\ncreateCodexProxyRoutes() with no 2nd arg still compiles/behaves identically; a\ncontinuous-test-suite-codex.ts regression booting routes with codexOutboundFallbackEnabled: true\nasserts the all-accounts-cooling 429 is unchanged.\n\nPR 3 β€” Claude-engine dispatch surface (blocked on Β§H). Adds only that surface plus its own tests, no\ncaller from codexProxyRoutes.ts yet β€” isolates the riskiest change (a 12.9k-line file, 14 exports) into\nits own revertable unit.\n\nPR 4 β€” Codex β†’ Vertex leg. Lowest risk: executeVertexAnthropicFallback is already standalone.\nWires insertion points ~896/~1458 gated on codexOutboundFallbackEnabled && targets.some(t =>\nt.provider === \"vertex\") && !isFallbackRequest, applies the Β§F budget-settlement requirement, ships Β§J's\nobservability for this leg. Can land and be flag-tested before PR 3/5 are ready.\n\nPR 5 β€” Codex β†’ Anthropic-pool leg. Depends on PR 3. Same insertion points for provider === \"anthropic\"\ntargets, applies codexOutboundFallbac","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"I. Staged rollout (one commit per PR, scope-mandatory conventional commit, e.g.","lvl3":""}},
10872
+ {"objectID":"4cf63af89729ff03412018d25d0be2a2b67ad64e615127b5c0c3700738b847bf","title":"J. Observability","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#j-observability","content":"tracer.setModelSubstitution(requestedModel, actualModel, actualProvider?) (proxyTracer.ts:638,\nconfirmed) feeds proxy_model_substitution_total{requested_model,actual_model} and needs zero code\nchanges β€” already called this way at the Vertex-fallback site (claudeProxyRoutes.ts:6180:\ntracer?.setModelSubstitution(body.model, vertexModel, \"vertex\")). A Codex model (gpt-5.x-*) as\nrequested_model cannot collide with any existing call site. Hard requirement on PR 4/5: call\nsetModelSubstitution(requestedCodexModel, actualModel, targetProvider).\n\nrecordFallbackAttempt (proxyTracer.ts:1082–1112) is called only from claudeProxyRoutes.ts today (6\nsites: 5722, 6214, 6244, 6340, 6445, 6478), signature {provider, model, status, errorMessage?,\ndurationMs}. Extend additively:\n\nReview finding, adopted, corrects the prior design's compatibility claim: the 3 fallback counters\n(fallbackAttemptsTotal/fallbackSuccessTotal/fallbackFailureTotal, meter.createCounter(...) at\nproxyTracer.ts:136-147) are cumulative monotonic OTel instruments. Adding direction to their label set\nis not backward-compatible β€” per this repo's own MAX-per-series-then-SUM convention a label-set\nchange starts a new series, exactly like the legKey text-format change below. Any dashboard/alert\nsumming these without grouping by direction silently under/double-counts once mixed-direction data\nexists, until updated (or treats pre-rollout data as implicitly claude-outbound) β€” remediate in the\nsame PR that ships the label.\n\nConfirmed pre-existing bug this change would otherwise inherit: trackFallbackLegHealth's legKey is\n ${provider}/${model} only (proxyTracer.ts:1092, no direction). A Codex-outbound-to-Anthropic leg\nand an existing Claude-outbound-to-Vertex leg sharing a {provider,model} would merge failure streaks β€”\none direction's burst could trip or reset the other's dead-leg alert. DEAD_FALLBACK_LEG_THRESHOLD = 20\nand MAX_TRACKED_FALLBACK_LEGS = 256 (proxyTracer.ts:1001,1013) stay unchanged (targets capped at 8,\nΒ§B, no","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"J. Observability","lvl3":""}},
10873
+ {"objectID":"edc03fe124d27a81c7bbb6c043422639879695e1cc6b884c7b4b51e5507d0bb0","title":"K. Documentation (PR 6)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#k-documentation-pr-6","content":"docs/features/claude-proxy-config-reference.md β€” 3 new \"Routing Fields\" rows (-enabled:\n boolean/false/No; -targets: CodexFallbackTarget[]/[]/No; -model-mappings: ModelMapping[]/[]/No);\n a \"CodexFallbackTarget Fields\" sub-table; a Validation Rules bullet: provider must be\n anthropic|vertex (hard error), array capped at 8.\ndocs/features/codex-proxy-support.md β€” new \"Outbound fallback (Codex β†’ Anthropic/Vertex)\" section:\n off by default, config keys, env kill switch, reentrancy guard, per-stage status line.\ndocs/features/claude-proxy-observability.md β€” the Β§J queries, plus a note that legKey's format\n changes for every existing leg once PR 4/5 ship.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"K. Documentation (PR 6)","lvl3":""}},
10874
+ {"objectID":"6613cb6c3d39455c967885d1bd473d97c14cc9cbb457f5da7bebc2e14b76411f","title":"L. Tests (exact file + assertion)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#l-tests-exact-file-assertion","content":"test/continuous-test-suite-proxy-config.ts _(confirm exact filename at implementation time — nearest\n existing proxy-config suite)_: validateProxyConfig accepts a valid codex-outbound-fallback-targets\n array; rejects provider: \"openai\" (hard error) and an empty model; accepts \"true\"/\"false\" string\n spellings of -enabled; rejects a 9-entry target list (MAX_CODEX_OUTBOUND_FALLBACK_TARGETS);\n parseRoutingConfig drops one malformed entry from a 3-entry array without blanking the other two;\n kebab/camel dual-acceptance for all 3 keys, explicit null rejected per readRoutingPolicyKey's\n presence-based contract; NEUROLINK_PROXY_CODEX_OUTBOUND_FALLBACK=off disables the feature even with\n codex-outbound-fallback-enabled: true in config (mirrors the NEUROLINK_PROXY_QUOTA_ROUTING precedence\n test shape).\ntest/continuous-test-suite-proxy-reliability.ts (or the suite run-proxy-reliability.mjs names —\n confirm at implementation time): configHash changes when -enabled flips unset→true (proves\n fingerprintSource wiring); a reload with an invalid -targets value keeps the last-known-good snapshot\n (mirrors the existing performReload rejection pattern).\ntest/continuous-test-suite-codex.ts: createCodexProxyRoutes() with no 2nd argument still compiles,\n byte-identical (signature backward-compat); a runtimeConfigProvider snapshot with\n codexOutboundFallbackEnabled: true and empty targets still returns the existing 429 on\n all-accounts-cooling (PR 2 no-op); once PR 4 lands — cooling pool + one Vertex target asserts a served\n 200 with setModelSubstitution/setServedAccount called correctly and recordFallbackAttempt firing\n direction: \"codex-outbound\"; a ctx carrying CODEX_FALLBACK_METADATA_KEY: true must NOT trigger\n outbound fallback even with flag+targets set (§G); a request reaching the outbound branch and succeeding\n must still settle the last-attempted account's budget lease — assert via token-budget test hooks that no\n lease is left \"reserved\" (§F); once PR 5 lands —","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"L. Tests (exact file + assertion)","lvl3":""}},
10875
+ {"objectID":"4ca35be2343f331f568f96285b22b0666630ff7e4b93e481d32292e5eb2c5373","title":"M. Unresolved","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#m-unresolved","content":"UNRESOLVED: which suite file already covers validateProxyConfig/parseRoutingConfig unit cases for\n the routing-policy keys, so new tests extend it rather than duplicate it β€” settle with\n grep -rl \"validateProxyConfig(\" test/ and confirm which file is registered in a gated test:* script.\nUNRESOLVED: the account-label string PR 4/5 passes to setServedAccount for a Codex-outbound-served\n turn (cf. vertexAccount = vertex/${vertexModel} ) β€” depends on Β§H's dispatch-surface decision, not\n this section's to make; settle once the cache-anthropic/translation section lands.\nUNRESOLVED: whether proxy_errors_total's label set can filter to \"codex route only\" for a\n would-have-failed-anyway comparison β€” only its counter name was reconfirmed this pass; settle by\n reading the errorsTotal counter's add(...) call sites in proxyTracer.ts and listing every label key.\nUNRESOLVED (genuinely open per Β§H): whether PR 3 exports a new handleClaudeMessagesRequest-shaped\n handler from claudeProxyRoutes.ts or reuses the already-in-process openaiProxyRoutes.ts-style\n loopback β€” settle via the cache-anthropic section's own design once synthesized.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"M. Unresolved","lvl3":""}},
10876
+ {"objectID":"a72edc69a633a801e4e1955addaa70789cb67bcd33d82733bb66633f3fd4fa07","title":"Codex outbound-fallback: validation plan","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#codex-outbound-fallback-validation-plan","content":"Scope: this section owns test suites, fixtures, CI gating, the live model matrix, and\nred-green defect injection for the Codex→Anthropic/Vertex outbound-fallback feature. It\ndoes not own the translator's type layer, trigger-policy gate, or rollout/config surface —\nthose are named where relied on and flagged depends_on at the end.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback — Design","lvl2":"Codex outbound-fallback: validation plan","lvl3":""}},
10877
+ {"objectID":"eb302d8a59b4f6f0fc02548b85039561399daa3a8aee006b01c066bbe800580b","title":"0. Verified premise (spot-checked against the worktree, not carried forward blind)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#0-verified-premise-spot-checked-against-the-worktree-not-carried-forward-blind","content":"additional_tools is two namespaces, not one, confirmed byte-for-byte in all 4 fixtures\n(test/fixtures/codex-request-{exec-mode,interactive-mode,resumed-session,tool-result-turn}.json)\nand in scripts/generate-codex-fixtures.mjs's own FUNCTION_TOOLS/COLLABORATION_TOOLS\nconstants (lines ~35–79) plus its header comment (lines 2–19):\nfunctions: read_file, apply_patch β€” ordinary {name, description, parameters} JSON-schema tools.\ncollaboration: exec (type:\"custom\", a grammar field holding a Lark grammar string,\n no parameters) and request_review (parameters, no type/grammar).\n\nClaudeTool (src/lib/types/proxy.ts:138–143, re-read directly) is exactly\n{ name: string; description?: string; input_schema: Record<string, unknown>; cache_control?: ClaudeCacheControl }\nβ€” no grammar field, no custom-tool discriminant, anywhere in src/lib/. A native exec\ndeclaration has no faithful destination shape. This is a type ceiling, not a bug to patch\nlater. Whichever section owns the translator (codex-outbound-fallback.ts /\ntypes/codex.ts, likely cache-codex-prefix) must pick one of: (a) drop collaboration\nsilently β€” rejected, a coding agent's shell-exec capability vanishes with no signal; (b) a\nlossy JSON-schema wrapper that can't enforce the grammar; (c) fail the outbound fallback\nclosed whenever additional_tools.collaboration contains a type:\"custom\" entry. This plan\ndoes not pick for them, but every test and live scenario below is written so it fails\nloudly if no case exists for a type:\"custom\" tool, whichever of (a)/(b)/(c) is chosen.\n\nAlso confirmed live in the tool-result-turn fixture: exec's function_call.arguments is\nthe plain string \"ls -la\" β€” not JSON. Any translator step that does JSON.parse on\nfunction_call.arguments unconditionally will throw on real exec calls; A.1 has an\nexplicit case for this.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"0. Verified premise (spot-checked against the worktree, not carried forward blind)","lvl3":""}},
10878
+ {"objectID":"9443571a0c7c812d3f771a6b8724f137b291a210df527a7e148a9aa84fc71c2e","title":"1. Suite placement and CI gating (resolved: 2 findings folded in)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#1-suite-placement-and-ci-gating-resolved-2-findings-folded-in","content":"Two new suites, both integration/pure-function style matching the two existing patterns in\nthis repo (test/continuous-test-suite-proxy-fallback-parent.ts, 1331 lines, confirmed\ncreateProxyStartApp/InMemorySpanExporter/FixtureMetricReader; and\ntest/continuous-test-suite-proxy-fallback-errors.ts, 125 lines, confirmed a determinism-\nexception header importing pure functions from codexFallback.ts with no server/network):\n\n| New file | Model | Covers |\n| ------------------------------------------------------------- | --------------------- | ---------------------------------------------------------------------------- |\n| test/continuous-test-suite-proxy-codex-outbound-fallback.ts | -fallback-parent.ts | A.8 trigger-policy totality, A.9 loop prevention, A.10 commit-boundary rules |\n| test/continuous-test-suite-codex-outbound-translation.ts | -fallback-errors.ts | A.1–A.7, A.11 (pure functions, no server) |\n\nGating (verified directly, not from the grounding's stale numbers): both suites must be\nadded to scripts/run-proxy-reliability.mjs's checks array, which backs\npackage.json's test:proxy-reliability, run at .github/workflows/ci.yml:448\n(re-grepped: the grounding's :445 is stale by 3 lines β€” git show 47c4d1c7d added 3\ncomment lines near ci.yml:196, shifting everything below; test:proxy-telemetry is now at\nline 444, test:codex at line 452). That step runs inside job provider-safety-net-shards\nwith matrix.group == 'rest' (ci.yml:351–352), which provider-safety-net (ci.yml:330,\nneeds: [provider-safety-net-shards]) aggregates as the actually-required check\n(ci.yml:320–343) β€” this is the required gate the repo rules refer to.\n\nResolved placement finding (minor, adopted): scripts/run-proxy-reliability.mjs\ncurrently has exactly one raw, untemplated checks entry\n([\"tsx\", \"test/continuous-test-suite-vertex-a","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"1. Suite placement and CI gating (resolved: 2 findings folded in)","lvl3":""}},
10879
+ {"objectID":"45cfbab0e864d257c19eb71c3092282209c0e43c267a488553f28aec187ab234","title":"2. Fixtures","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#2-fixtures","content":"Existing (reused, unmodified): the 4 codex-request-*.json files above, all confirmed\nstore:false, all confirmed carrying additional_tools with both namespaces on every\nturn including the resumed-session and tool-result-turn fixtures (turn N of an ongoing\nconversation still resends the identical block β€” store:false means Codex never assumes the\nserver remembers prior tool declarations).\n\nNew, for A.6 byte-stability: test/fixtures/codex-native-request-cache-turn1.json and\n...-turn2.json, generated by extending scripts/generate-codex-fixtures.mjs (which already\nexports the exact building blocks needed β€” confirmed present: additionalToolsItem(),\ndeveloperMessageItems(), userMessageItem(text), functionCallItem(),\nfunctionCallOutputItem(), baseHeaders(...), baseBody({input, sessionId, threadId}),\nbuildFixture({...})). Add two more entries to the fixtures array:\nturn1: buildFixture({ mode: \"exec\", betaCompaction: true, betaResponsesLite: true, userTexts: [...] }) β€” i.e. the same additionalToolsItem() + developerMessageItems() prefix as the existing exec-mode fixture, so the stable prefix is byte-identical by construction.\nturn2: same buildFixture call plus extraInputItems: [functionCallItem(), functionCallOutputItem(), userMessageItem(\"<new turn text>\")] appended after the two turn-1 user messages.\n Both call the same additionalToolsItem()/developerMessageItems() functions β€” do not\n hand-duplicate the tool/developer-message literals into the new fixture pair, since a\n hand-duplicated copy is exactly the kind of accidental byte drift A.6 exists to catch.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"2. Fixtures","lvl3":""}},
10880
+ {"objectID":"910a89bb8b208d89e88cf56fc3dfb334a3557ed512e3e6dab40d0798497e8e78","title":"3. Part A β€” deterministic offline suites","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#3-part-a-deterministic-offline-suites","content":"A.1 Request translation shape (file: test/continuous-test-suite-codex-outbound-translation.ts;\nfunction under test: convertCodexNativeRequestToClaude(body: CodexNativeRequestBody): ClaudeRequest,\nproposed new pure function in new src/lib/proxy/codexOutboundFallback.ts, structural\ninverse of the confirmed-existing convertClaudeRequestToCodex(body: ClaudeRequest, model: string, reasoningEffort?: CodexReasoningEffort): CodexResponsesRequest\nat src/lib/proxy/codexFallback.ts:407; CodexNativeRequestBody is a new type in\nsrc/lib/types/codex.ts, distinct from the existing CodexResponsesRequest type there,\nbecause CodexResponsesRequest is this repo's own outgoing shape for the forward\ndirection and has no additional_tools/namespace concept at all):\ndeveloper-role messages map to system text in order β€” load codex-request-exec-mode.json (4 developer messages), assert joined system text contains all 4 in original order.\nuser-role messages map to Claude user messages verbatim β€” byte-identical text per message, including the <environment_context> synthetic wrapper string.\nfunctions-namespace tools rename parameters to input_schema, deep-equal β€” result.tools entries for read_file/apply_patch deep-equal source parameters.\ncollaboration custom-grammar tool (exec) is dropped or fails closed β€” direct test of Section 0: assert either exec is absent from result.tools and an explicit diagnostic is set, or the converter throws a typed CodexOutboundUnsupportedToolError naming exec and type:\"custom\". One of these two must hold under whichever policy (a)/(b)/(c) lands; this case must exist regardless.\ncollaboration parameter-based tool (request_review) is translated identically to a functions-namespace tool β€” proves dispatch is by shape (grammar-present vs parameters-present), not by namespace name.\nfunction_call + function_call_output pair becomes assistant tool_use + user tool_result β€” load codex-request-tool-result-turn.json (call_id: \"call_synthetic_0001\", name: \"exec\", arguments: \"ls -","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"3. Part A β€” deterministic offline suites","lvl3":""}},
10881
+ {"objectID":"301681bab93ede4ff7555497d54ae1214baa55c54a252b30c18c77cc7206e199","title":"CI-gating summary","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#ci-gating-summary","content":"| Suite | npm script | Workflow line | Required |\n| -------------------------------------------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------- | -------------------------------------------- |\n| continuous-test-suite-proxy-codex-outbound-fallback.ts (new) | test:proxy-reliability via run-proxy-reliability.mjs (templated entry) | ci.yml:448 | yes, provider-safety-net-shards/rest |\n| continuous-test-suite-codex-outbound-translation.ts (new) | same wrapper (raw entry) | ci.yml:448 | yes, same job |\n| continuous-test-suite-codex.ts (existing, untouched) | test:codex | ci.yml:452 | yes, out of scope per this plan's non-choice |\n| continuous-test-suite-proxy.ts (existing, 14598 lines) | test:proxy | none (confirmed no run: line anywhere in ci.yml) | no β€” do not rely on it |","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"CI-gating summary","lvl3":""}},
10882
+ {"objectID":"da4c59d0b64ced4009b9a44e7b6c213b7e7d85158fcf74bba4a58772f8bbf3c5","title":"4. Part B β€” live matrix (Codex quota reset; both Anthropic [3 OAuth accounts] and Vertex live-callable)","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#4-part-b-live-matrix-codex-quota-reset-both-anthropic-3-oauth-accounts-and-vertex-live-callable","content":"Resolved framing (blocker, adopted): the review is correct that additional_tools.collaboration\ncarries exec on every live Codex CLI request (confirmed: store:false means every\nturn, including a resumed session and a mid-conversation tool-result turn, resends the\nidentical additional_tools block β€” there is no \"tool-free\" native Codex session). B1–B7\nbelow therefore do not validate a hypothetical tool-free subset; every one of them\ninherently exercises whichever policy Section 0 resolves to (drop/lossy-wrap/fail-closed),\nbecause exec rides along on every request regardless of what the human operator typed.\nEach scenario's pass criterion below adds an explicit clause for this. If the chosen policy\nis fail-closed (option c), every scenario B1–B7 will observe a clean, Codex-shaped\nclosed-fail at the translation step rather than a model response β€” that is a valid, expected\noutcome under that policy and must be asserted as such, not treated as an unexplained\nfailure. A live run against a real exec-bearing session, observing which of the two\noutcomes actually happens, is the only way to close UNRESOLVED-2 below.\n\n| # | Model | Target | Scenario | Pass criterion ","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"4. Part B β€” live matrix (Codex quota reset; both Anthropic [3 OAuth accounts] and Vertex live-callable)","lvl3":""}},
10883
+ {"objectID":"864ca0b9722ca970f05f9d97d0fe4922d671c0783ce3e5290bcfdd507b7f65bd","title":"5. Part C β€” red-green discipline","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#5-part-c-red-green-discipline","content":"No telemetry exists yet at the current service_versions β€” run Part B scenarios 1–2 once\nagainst today's code first (force a Codex failure with no outbound fallback at all,\nconfirm the client simply sees a failure) and record the exact service_versions/timestamps\nreturned, rather than assuming a prior baseline exists.\n\n| # | Behavior | Defect to inject | Where | Expected failure without fix |\n| --- | ----------------------------------------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| 1 | Byte-stability (A.6) | Embed Date.now() or a fresh id into the synthesized system/tools prefix | system-assembly step | A.6 byte-stability case fails |\n| 2 | Cache marker placement (A.5) | Skip stringβ†’block-array promotion, emit system as a bare string | converter's system-shape choice | applyClaudeRequestCacheBreakpoints places 0 markers (array-branch guard requires Array.isArray); A.5 promotion case fails ","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"5. Part C β€” red-green discipline","lvl3":""}},
10884
+ {"objectID":"f7fac43bfed8a1c9df20ae06397f4d5758acf069d0888e304900c2ae3a606320","title":"6. Dependencies on other sections / UNRESOLVED","url":"/docs/superpowers/specs/2026-09-27-codex-outbound-fallback-design#6-dependencies-on-other-sections-unresolved","content":"Exact translator names/types (convertCodexNativeRequestToClaude, CodexNativeRequestBody,\n the functions/collaboration union) are proposed here for concreteness; owned by whichever\n section designs the request-parsing/type layer (likely cache-codex-prefix). If it settles\n on different names, only the symbol names here change β€” file placement, CI gating, the case\n list, and the live-matrix scenarios are structural and independent of the exact names.\nAccount-affinity/session-pinning feeding a Codex-derived cache key into account selection β€”\n confirmed sessionId parameter accepts an arbitrary string with no format validation, so\n this plan's assumption is safe, but the hook itself belongs to cache-anthropic.\ncache_control TTL policy choice beyond straight reuse of applyClaudeRequestCacheBreakpoints\n β€” likely cache-anthropic/cache-compaction.\nVertex-specific leg differences for scenario 5's account-label assertions β€” likely cache-vertex.\nThe actual trigger-policy gate function body, hop-depth mechanism, and routing-config key\n name β€” likely cache-guardrails; this plan only names the test surface for it.\nAny new proxy_fallback_* observability labels β€” likely proxy-waste.\nUNRESOLVED-1: exact wire shape for a Codex reasoning output item (A.2) β€” see A.2 above; the\n one check that would settle it is a live capture of a real reasoning-effort Codex turn.\nUNRESOLVED-2: whether the real ChatGPT Codex backend validates function_call.call_id\n format server-side β€” the one check that would settle it is Part B scenario 4.\nUNRESOLVED-3: whether Section 0's policy choice ((a)/(b)/(c)) is fail-closed or lossy β€”\n owned by the translator section; this plan's Part B framing is written to be correct under\n either outcome, but the actual observed behavior (clean fail-closed vs. a live 400) is only\n settled by running scenarios 1/3/4 once the translator lands.","hierarchy":{"lvl0":"Superpowers","lvl1":"Codex Outbound Fallback β€” Design","lvl2":"6. Dependencies on other sections / UNRESOLVED","lvl3":""}},
10775
10885
  {"objectID":"28a39199473cf2c61c15cd3a935a0539698770b87d0db0b52dca6387739180e0","title":"NeuroLink Universal AI Platform - Final Comprehensive Test Report","url":"/docs/test-reports/final-comprehensive-test-report","content":"NeuroLink Universal AI Platform - Final Comprehensive Test Report\n\n⚠️ HISTORICAL DOCUMENT (August 2025)\nThis audit was conducted when NeuroLink shipped 9 providers. At audit time, v9.62.0 (May 2026) shipped 24 providers including DeepSeek, NVIDIA NIM, LM Studio, llama.cpp, plus voice (TTS/STT/realtime). References to \"9 providers\" or \"8/9 working\" in this file reflect the state at time of analysis.\nFor current capabilities see README on GitHub and Provider Capabilities Audit.\n\n🎯 Executive Summary\n\nTest Execution Completed: 2025-07-11T12:42:34.297Z \nOverall Success Rate: 99.1% (319/322 tests passed) \nTotal Execution Time: 1025.5 seconds (17.1 minutes) \nTest Coverage: 100% (All 322 test cases executed) \nStatus: βœ… COMPREHENSIVE TEST EXECUTION SUCCESSFUL\n\nπŸ“Š Overall Results\n\n| Metric | Value |\n| -------------------- | ------- |\n| Total Tests | 322 |\n| Passed | 319 |\n| Failed | 3 |\n| Success Rate | 99.1% |\n| Execution Time | 1025.5s |\n| Parallel Workers | 10 |\n\nπŸ† Phase-by-Phase Performance\n\nPhase 1: Critical Priority Tests\nTests: 26\nSuccess Rate: 100%\nStatus: βœ… PERFECT\n\nPhase 2: High Priority Tests\nTests: 45\nSuccess Rate: 100%\nStatus: βœ… PERFECT\n\nPhase 3: Medium Priority Tests\nTests: 120\nSuccess Rate: 100%\nStatus: βœ… PERFECT\n\nPhase 4: Low Priority Tests\nTests: 139\nSuccess Rate: 97.8% (3 failures)\nStatus: ⚠️ MINOR ISSUES\n\n❌ Failed Test Analysis\n\nTest Failures (3 total)\nCLI-002.1.1 - Test timeout (Position 141/322)\nCLI-002.1.2 - Test timeout (Position 144/322)\nCLI-002.2.1 - Test timeout (Position 145/322)\n\nRoot Cause: All failures are timeout-related in CLI testing scenarios, likely due to:\nNetwork latency in provider response times\nCLI command execution overhead\nResource contention during parallel execution\n\nImpact: Minimal - Only affects 0.9% of test suite, all in low-priority category\n\nβœ… Key Achievements\nPerfect Critical & High Priority Coverage: 100% success rate for all mission-critical functionality\nComprehensive Provider Testing: All 9 AI providers tested successfully\nParallel Execution Efficiency: 10-worker parallel execution completed in under 18 minutes\nEnvironment Fixes Applied: Resolved authentication and provider fallback issues\nFresh Execution Success: Clean restart achieved excellent results\n\nπŸ”§ Technical Improvements Made\n\nPre-Execution Fixes\nEnvironment Variable Loading: Added dotenv configuration to test executor\nProvider Fallback Logic: Simplified provider selection to prevent unwanted fallbacks\nSDK-to-CLI Conversion: Enhanced test reliability by preferring CLI execution\nOllama Configuration: Updated to use breezehq.dev endpoint with proper model\n\nExecution Optimizations\nParallel execution with 10 concurrent workers\nReal-time progress tracking and monitoring\nComprehensive logging and result collection\nAutomatic retry mechanisms for transient failures\n\nπŸ“ˆ Performance Metrics\nAverage Test Duration: 3.2 seconds per test\nThroughput: ~19 tests per minute\nPeak Concurrency: 10 simultaneous tests\nResource Utilization: Optimal CPU and memory usage\n\n🎯 Provider Success Rates\n\n| Provider | Status | Success Rate |\n| ------------ | ------ | ------------ |\n| OpenAI | βœ… | 100% |\n| Anthropic | βœ… | 100% |\n| Google AI | βœ… | 100% |\n| Vertex AI | βœ… | 100% |\n| AWS Bedrock | βœ… | 100% |\n| Azure OpenAI | βœ… | 100% |\n| HuggingFace | βœ… | 100% |\n| Ollama | βœ… | 100% |\n| Mistral | βœ… | 100% |\n\nπŸ” Quality Assessment\n\nEXCELLENT: The NeuroLink Universal AI Platform demonstrates exceptional stability and reliability:\n99.1% success rate exceeds industry standards\nZero critical or high-priority failures\nAll provider integrations functioning perfectly\nRobust error handling and fallback mechanisms\nComprehensive test coverage across all system components\n\nπŸ“‹ Recommendations\n\nImmediate Actions\nTimeout Optimization: Review CLI timeout settings for the 3 failed tests\nMonitoring Enhancement: Implement production monitoring for timeout scenarios\n\nFuture Improvements\nLoad Testing: Add stress testing for high-concurrency scenarios\nPerformance Benchmarking: Establish baseline performance metrics\nAutomated Regression: Integrate into CI/CD pipeline\n\nπŸ“ Test Artifacts\n\nExecution Log: comprehensive-test-execution-full.log \nTracker File: TEST-EXECUTION-TRACKER.md \nTest Results: test-executions/comprehensive-parallel/ \nConfiguration: execute-all-tests-parallel.js\n\nReport Generated: 2025-07-11T12:44:00.000Z \nStatus: βœ… COMPREHENSIVE TEST EXECUTION SUCCESSFUL \nNext Review: As needed for system updates","hierarchy":{"lvl0":"Test Reports","lvl1":"NeuroLink Universal AI Platform - Final Comprehensive Test Report","lvl2":"","lvl3":""}},
10776
10886
  {"objectID":"9efef22578ee5bce54f82bb2792f3abadec2c2cd589f3d3e7a344d8f97452bcb","title":"NeuroLink Universal AI Platform - Final Comprehensive Test Report","url":"/docs/test-reports/final-comprehensive-test-report#neurolink-universal-ai-platform---final-comprehensive-test-report","content":"⚠️ HISTORICAL DOCUMENT (August 2025)\nThis audit was conducted when NeuroLink shipped 9 providers. At audit time, v9.62.0 (May 2026) shipped 24 providers including DeepSeek, NVIDIA NIM, LM Studio, llama.cpp, plus voice (TTS/STT/realtime). References to \"9 providers\" or \"8/9 working\" in this file reflect the state at time of analysis.\nFor current capabilities see README on GitHub and Provider Capabilities Audit.","hierarchy":{"lvl0":"Test Reports","lvl1":"NeuroLink Universal AI Platform - Final Comprehensive Test Report","lvl2":"NeuroLink Universal AI Platform - Final Comprehensive Test Report","lvl3":""}},
10777
10887
  {"objectID":"83a1048b43754bd7ff2d757e77d271214bc8a26295dedb913166858cbea14143","title":"🎯 Executive Summary","url":"/docs/test-reports/final-comprehensive-test-report#-executive-summary","content":"Test Execution Completed: 2025-07-11T12:42:34.297Z \nOverall Success Rate: 99.1% (319/322 tests passed) \nTotal Execution Time: 1025.5 seconds (17.1 minutes) \nTest Coverage: 100% (All 322 test cases executed) \nStatus: βœ… COMPREHENSIVE TEST EXECUTION SUCCESSFUL","hierarchy":{"lvl0":"Test Reports","lvl1":"NeuroLink Universal AI Platform - Final Comprehensive Test Report","lvl2":"🎯 Executive Summary","lvl3":""}},