Accumulated uncommitted work: GHOST Web backend, WebGL/GPU web layer, web workflow engine and protocol, tooling, docs and task records. Large generated evidence, user-testing archives, build snapshots and imported test assets remain untracked. Co-Authored-By: Claude Code <noreply@anthropic.com>
69 lines
7.7 KiB
Python
69 lines
7.7 KiB
Python
"""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 <Blender-file> OR --runtime <Web-file> --pattern <exact-symbol> --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/<task>/unattended-reports/cycle-<six-digit-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
|