Skip to content

C4b: allocation accounting, fetch/exec byte caps, and --deadline - #112

Merged
howlcipher merged 1 commit into
mainfrom
okabe/c4b-resource-limits
Oct 6, 2026
Merged

howlcipher merged 1 commit into
mainfrom
okabe/c4b-resource-limits

Conversation

@howlcipher

Copy link
Copy Markdown
Owner

Summary

Implements review candidate C4b on top of C4a (#111 / cdf2e2fc): bytecode runner resource limits for S4/S6/S7.

  • Allocation accounting against MaxMemoryBytes (default 64 MiB, --max-memory-bytes). Cumulative approximate charges on string concat, append, MAKE_LIST/MAKE_DICT, str_split/str_join, read_file, fetch/exec bodies, encode_json, and related large sites. Shared counter across SPAWN_AGENT children. Exceed → structured LIMIT_EXCEEDED.
  • Fetch body / exec output caps (default 10 MiB each; --max-fetch-bytes, --max-exec-output-bytes). LimitReader / bounded combined stdout+stderr; fail-closed for non-positive ceilings in the VM; CLI rejects <= 0.
  • --deadline optional positive time.ParseDuration wall-clock budget on ExecutionPolicy. Threaded context.Context into fetch, exec, sleep, and model HTTP calls; instruction loop also checks cancellation. Absent flag = no deadline; explicit 0s/invalid rejected.
  • CLI wired on both legacy -run-bc and howlframe run (bytecode/bc), alongside existing --max-instructions / --max-call-depth.
  • Docs: change_log.md, journal docs/journals/2026-10-06_c4b_resource_limits.md, doc 11 C4 status, S4/S6/S7 honestly marked PARTIAL where AST/print/read_line remain open.

Hard nos intact

No prod -compile-bc/HFIR flip; #90 stays Partial; no HFBC/opcode change; no DOM invent; no C5 receipts/harness; C4a MaxCallDepth behavior preserved.

Defaults

Flag Default
--max-memory-bytes 67108864 (64 MiB)
--max-fetch-bytes 10485760 (10 MiB)
--max-exec-output-bytes 10485760 (10 MiB)
--deadline absent (none)

Deferrals

AST interpreter memory/deadline/recursion still open; print uncapped; blocking read_line (and some host I/O) not deadline-cancelled; charges are approximate construction accounting, not exact RSS.

Test plan

  • gofmt -l . clean
  • go vet ./...
  • go test ./internal/vm/ -count=1 (incl. new resource limit / deadline / byte-cap tests)
  • go test ./... -count=1 green outside sandbox (Go 1.24.4)
  • C4a call-depth / instruction-limit CLI regressions still pass

Review C4b (S4/S6/S7): bytecode runner now enforces cumulative allocation
charges against MaxMemoryBytes (default 64 MiB), caps fetch bodies and
exec combined output (default 10 MiB each), and accepts an optional
wall-clock --deadline that cancels fetch/exec/sleep/model work and is
checked in the instruction loop. Exceeded ceilings raise structured
LIMIT_EXCEEDED. Shared allocation counter and context propagate to
SPAWN_AGENT children. Flags wired on -run-bc and howlframe run
(--max-memory-bytes, --max-fetch-bytes, --max-exec-output-bytes,
--deadline). AST interpreter unchanged; print and blocking read_line
remain open; no C5, no HFBC/opcode change, no prod -compile-bc flip;
#90 stays Partial. Journal: docs/journals/2026-10-06_c4b_resource_limits.md

Co-authored-by: howlcipher <howlcipher@users.noreply.github.com>

@howlcipher howlcipher left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dev-lead COMMENT (head 9f55bc65aeee607b09276422f6faab9a4355e297)

Verdict: merge-ready. Diff matches claimed C4b scope. CI build green. Undraft + squash-merge when you are ready.

What matches

  • Memory: shared allocationBudget (mutex, never reclaimed) charged at concat/convert strings, MAKE_LIST/MAKE_DICT, APPEND, STR_SPLIT/JOIN, map_set new keys, map_keys slots, encode_json, HTML escape, read_file/fetch/exec via chargeBytes (source + 8× slot ≈ 9n), and model response strings. Overflow-safe chargeSlots. Fail-closed for MaxMemoryBytes <= 0 on positive charges. Shared into SPAWN_AGENT, legacy SPAWN, and HTTP handler children.
  • Fetch/exec caps: default 10 MiB each; LimitReader(max+1) then reject; limitedOutput Write-only (no ReadFrom bypass) + cancel on overflow; under-cap nonzero exit stays IO_ERROR. CLI + VM fail-closed for <= 0.
  • Deadline: optional ExecutionPolicy.Deadline; WithTimeout shared with children; instruction-loop checkDeadline; sleep select; fetch/exec/model via context; deadline → structured LIMIT_EXCEEDED (not IO_ERROR). Absent = none; CLI rejects 0s/invalid.
  • CLI: --max-memory-bytes / --max-fetch-bytes / --max-exec-output-bytes / --deadline on -run-bc and run (bytecode), via resourcePolicy. C4a --max-call-depth / MaxCallDepth preserved.
  • Tests: defaults, opcode boundaries, spawn share, fetch/exec caps (httptest + in-memory transport), deadline sleep/loop/exec/fetch/model/response-body, CLI both runners, inherited exec without deadline unchanged.
  • Docs: S4/S6/S7 honestly PARTIAL; deferrals (AST, uncapped print, read_line not cancelled, approximate ≠ RSS) match the code.

Non-blockers (documented)

  • Append charges full list size each time (cumulative overcharge vs live heap) — intentional approximate policy.
  • Model response bodies have no dedicated byte cap (only alloc charge + request deadline).
  • Deferred paths as claimed: AST interpreter, print, blocking read_line / some host I/O.

Hard nos

Intact: no prod HFIR / -compile-bc flip, #90 Partial, no HFBC/opcode change, no C5/harness/DOM; C4a call-depth behavior preserved.

No blockers.

@howlcipher
howlcipher marked this pull request as ready for review October 6, 2026 12:40
@howlcipher
howlcipher merged commit 9360cbf into main Oct 6, 2026
1 check passed
@howlcipher
howlcipher deleted the okabe/c4b-resource-limits branch October 6, 2026 12:40
@howlcipher howlcipher mentioned this pull request Oct 6, 2026
6 tasks done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant