"""Bound runner-owned model input; keep omitted context locally, never erase scope.""" import json MIN_BYTES, DEFAULT_BYTES, MAX_BYTES = 12 * 1024, 16 * 1024, 24 * 1024 def encoded(value): return json.dumps(value, ensure_ascii=False, separators=(',', ':')).encode('utf-8') def budget_state(state): provider = state.get('provider', {}) recovering = provider.get('consecutiveFailures', 0) > 0 and provider.get('errorKind') in {'transport', 'payload_limit'} budget = state.setdefault('modelPayload', {'limitBytes': MIN_BYTES if recovering else DEFAULT_BYTES, 'stableTurns': 0}) budget['limitBytes'] = max(MIN_BYTES, min(MAX_BYTES, int(budget.get('limitBytes', DEFAULT_BYTES)))) return budget def update_budget(state, outcome): budget = budget_state(state) budget['stableTurns'] = budget.get('stableTurns', 0) + 1 if outcome == 'stable' else 0 if outcome == 'pressure': budget['limitBytes'] = max(MIN_BYTES, budget['limitBytes'] // 2) elif budget['stableTurns'] >= 3: budget.update(limitBytes=min(MAX_BYTES, budget['limitBytes'] + 2048), stableTurns=0) budget['lastOutcome'] = outcome GUIDANCE = '''Continue one authorized Blender 5.2 -> Web Blender user-operation gap. Preserve task/parent/nextTask, all residuals and existing dirty source; no reset/clean/commit/push, second scheduler, control-file edits or deployment. NOT_RUN/NOT_CLAIMED: no tests, browser, syntax/type/context checks or evidence audits. Build only needed artifacts in the existing tree, -j8, no repeated unchanged builds. Runner already supplied EXECUTION_QUEUE, task context and current parent; do not reread them. Use the latest handoff, exact nextSourcePaths and focused search-wbv2-batch-source; pass only Blender files with --source and Web/runtime files with --runtime. No inventories, full files or historical logs. Each source window <=30 lines: start with4-8 lines and narrow after truncation. Search results default to1KiB with384-byte match windows; refine the exact pattern/path instead of repeating oversized reads. Each edit <=2 files and <=10 changed lines including continuationNotes. Record breakpoint, completed facts, residual and next direct action after each batch. CURRENT CONTEXT is already loaded. Read context.json only for an explicitly deferredField needed now; never reload supplied fields or prior worker logs. Respect unreleased foreground ownership. Preserve omitted scope by reference. Search syntax is node tools/web/search-wbv2-batch-source.mjs --task WBV2-P1424-001 --source OR --runtime --pattern --max-hits 6; do not inspect the search tool itself. Before reopening an older missing/unlocated claim, reconcile it with rootRepair.resultPath, the latest foreground handoff; read only its relevant short section. Delivered implemented-unverified facts supersede older claims, not residuals. Record that manifest and the concrete remaining edge in continuationNotes; if already reconciled and unchanged, resume the edge without rereading. Never repeat completed traces/builds merely for missing verification. INTEGRATE_PENDING retains priority. Use original Blender/WASM callers and existing modules; OCCT is the sole geometry kernel, Three.js displays results only. Trace one immediate call chain in <=30-line windows within CURRENT CONTEXT.investigationBudget (readCommands / activeNonBuildSeconds); use eight reads / 120 seconds only if absent. Edit only a confirmed missing edge and return the final handoff. If unresolved, hand off the exact symbol/line and next bounded read. Preserve residuals; no JS simulation, stubs, duplicate implementations or edits merely to satisfy a timer. Never bypass external limits. Honor priority: LOCATE_SOURCE only traces the exact boundary; IMPLEMENT_FAMILY finishes one operation; INTEGRATE_PENDING reuses a matching linked pair or incrementally builds web_engine, packages once with tools/web/build-main-desktop-candidate.py, reports candidate.json, then ends. Never package incomplete native inputs. An active integrationRetry means retain pending/ownership/old candidate and work independently. Generated artifacts, service uptime and reads are not functional completion. If integrationRetry.active=false, its deadline has expired; retain the old failure as history and reconcile the named dependency before proceeding. Historical foreground-ownership prose alone does not establish a current owner. Honor any concrete live ownership restriction and name the actual blocking resource; never renew a wait solely because an expired retry object exists. Write a brief current-cycle report and continuationNotes with module, workflow, native/WASM route, changed paths, exact breakpoint and residuals. Emit schema JSON only as the final response, never as repeated progress messages. Build fields must reflect actual commands; not_run has empty log/artifacts/blockers. Set batchReadyForIntegration only for fully wired source awaiting delivery. Completion flags stay false while any owned gap remains; efficiencyReview.inspected=false unless performed. Reference broader scope locally and end after final handoff. Set delivery.stageId to CURRENT CONTEXT.stageId and nextSourcePaths to at most eight exact files; write the report to tests/golden//unattended-reports/cycle-.md. Keep UI labels, enablement, shortcuts, cancel/retry and native ownership aligned with Blender; classify actual missing edges separately from implemented-unverified routes. Full original guidance is preserved in prompt.source.txt; read only a needed paragraph, never reload the whole file. ''' def prepare_submission(prompt, schema_bytes, directory, state): budget = budget_state(state) context = json.loads(prompt.partition('CURRENT CONTEXT: ')[2].split('\n', 1)[0]) context_path = directory / 'context.json' context_path.write_bytes(encoded(context)) (directory / 'prompt.source.txt').write_text(prompt, encoding='utf-8') view = dict(context, contextReference=str(context_path)) limit = budget['limitBytes'] instructions = GUIDANCE + f'Payload limit={limit} bytes including output schema; tool output soft budget={2 * limit} bytes. Request max_output_tokens<={limit // 32} per tool, redirect long output to local logs; after the soft budget hand off before more reads. Final JSON target<=4096 bytes; preserve required paths and ownership, reference broader residuals locally.\n' def render(): return instructions + 'CURRENT CONTEXT: ' + encoded(view).decode('utf-8') + '\n' required = {'task', 'parent', 'cycle', 'stageId', 'focus', 'phase', 'priority', 'investigationBudget', 'assignment', 'continuationNotes', 'nextSourcePaths', 'interrupted', 'handoff', 'integrationRetry', 'recoveryDirection'} for key in sorted(context, key=lambda name: (name in required, -len(encoded(context[name])))): if len(render().encode('utf-8')) + schema_bytes <= limit: break if key == 'rootRepair': continue # Keep the small latest-delivery reference ahead of stale handoffs. if len(encoded(context[key])) > len(encoded({'deferredField': key})): view[key] = {'deferredField': key} fitted = render() prompt_bytes = len(fitted.encode('utf-8')) budget.update(promptBytes=prompt_bytes, schemaBytes=schema_bytes, submittedBytes=prompt_bytes + schema_bytes, toolOutputTokenLimit=limit // 48, toolOutputSoftBytes=limit, toolOutputHardBytes=2 * limit, deferredFields=[key for key in context if view[key] != context[key]], measuredScope='runner prompt+schema UTF-8 only; CLI instructions/tool definitions/history excluded') (directory / 'payload.json').write_bytes(encoded(dict(budget, admitted=budget['submittedBytes'] <= limit))) return fitted if budget['submittedBytes'] <= limit else None