Implement bounded Recursive Language Model completion runtime (#9) #28

Merged
lost-rob0t merged 27 commits from feature/issue-9-rlm-completion into main 2026-08-12 15:15:57 +00:00
lost-rob0t commented 2026-08-12 14:50:44 +00:00 (Migrated from github.com)

Closes #9.

Public runtime

  • add rlm_completion/4, llm_query/3, and rlm_query/4
  • expose cancellation-token creation/cancel operations and the default completion budget through the public rlm entrypoint
  • accept opaque context handles/refs or context sources that are registered and cleaned up by the supervisor

Root planner + typed execution

  • the root model receives the goal, context metadata, capability declarations, and registered tool schemas without implicitly receiving the full opaque context
  • planner output must parse through the existing closed typed-plan runtime
  • direct non-recursive completion remains valid when decomposition is unnecessary
  • production execution uses rlm_chain:model_complete/3; deterministic handler injection is test-only and explicit, with no fake-provider fallback

Depth-1 recursion and authority

  • default recursive hard ceiling is depth 1
  • validate recursive fingerprints, reject obvious duplicate/cyclic recursive calls, and reject recursive retries that would repeat the same child work
  • child capabilities are derived with capabilities_narrow/3 and prevalidated against every child operation
  • a child needs rlm authority only if it attempts to recurse again

Budgets

Completion-level hard limits cover:

  • iterations/plan steps
  • recursion depth
  • concurrent subcalls
  • model calls
  • tool calls
  • context operations
  • wall time
  • provider-reported tokens
  • provider-reported cost
  • output bytes

Planner calls consume the same model/token/cost envelope. Planned model generation ceilings are tightened against remaining token budget before execution. Unknown provider usage remains explicitly unknown rather than fabricated.

Cancellation and cleanup

  • cancellation tokens track active execution threads
  • rlm_cancel/1 marks the token and signals pending work
  • cancellation and call_with_time_limit remain control signals rather than being swallowed as handler errors
  • context/cancellation resources use cleanup paths even on cancellation or timeout

Trajectory

  • return root planner event, model-call events, recursion statistics/fingerprints, plan transitions, child capability set, and aggregate visible provider usage
  • trajectory records why the root planned and identifies depth-aware child model execution

Deterministic acceptance

The branch-head deterministic suite is green and covers:

  • direct non-recursive completion
  • hard depth rejection
  • duplicate recursive-call rejection
  • child capability narrowing
  • planner/model-call budget exhaustion
  • cancellation before side effects
  • mid-flight cancellation of a pending model operation
  • wall-time interruption
  • provider-reported token overage
  • provider-reported cost overage
  • llm_query/3 and depth-bounded rlm_query/4
  • static loading of the live recursive integration test without credentials

REAL OpenRouter acceptance gate

Same-repository PR CI must execute this production path before merge:

real OpenRouter root planner -> opaque external context slice -> registered project_read tool -> exactly one rlm child -> real OpenRouter child model call -> child final -> root final

The live test also verifies project_read authorization/status and the fixture token PROLOG_RLM_TOOL_OK, recursion depth/count, child HTTP 200, and total real model-call count.

Live evidence is limited to non-secret status fields. Planner JSON, model text/reasoning, API keys, Authorization headers, and environment dumps are not intentionally logged.

Do not merge until deterministic CI and the REAL OpenRouter PR job are both green and the final diff/credential scan is clean.

Closes #9. ## Public runtime - add `rlm_completion/4`, `llm_query/3`, and `rlm_query/4` - expose cancellation-token creation/cancel operations and the default completion budget through the public `rlm` entrypoint - accept opaque context handles/refs or context sources that are registered and cleaned up by the supervisor ## Root planner + typed execution - the root model receives the goal, context metadata, capability declarations, and registered tool schemas without implicitly receiving the full opaque context - planner output must parse through the existing closed typed-plan runtime - direct non-recursive completion remains valid when decomposition is unnecessary - production execution uses `rlm_chain:model_complete/3`; deterministic handler injection is test-only and explicit, with no fake-provider fallback ## Depth-1 recursion and authority - default recursive hard ceiling is depth 1 - validate recursive fingerprints, reject obvious duplicate/cyclic recursive calls, and reject recursive retries that would repeat the same child work - child capabilities are derived with `capabilities_narrow/3` and prevalidated against every child operation - a child needs `rlm` authority only if it attempts to recurse again ## Budgets Completion-level hard limits cover: - iterations/plan steps - recursion depth - concurrent subcalls - model calls - tool calls - context operations - wall time - provider-reported tokens - provider-reported cost - output bytes Planner calls consume the same model/token/cost envelope. Planned model generation ceilings are tightened against remaining token budget before execution. Unknown provider usage remains explicitly unknown rather than fabricated. ## Cancellation and cleanup - cancellation tokens track active execution threads - `rlm_cancel/1` marks the token and signals pending work - cancellation and `call_with_time_limit` remain control signals rather than being swallowed as handler errors - context/cancellation resources use cleanup paths even on cancellation or timeout ## Trajectory - return root planner event, model-call events, recursion statistics/fingerprints, plan transitions, child capability set, and aggregate visible provider usage - trajectory records why the root planned and identifies depth-aware child model execution ## Deterministic acceptance The branch-head deterministic suite is green and covers: - direct non-recursive completion - hard depth rejection - duplicate recursive-call rejection - child capability narrowing - planner/model-call budget exhaustion - cancellation before side effects - mid-flight cancellation of a pending model operation - wall-time interruption - provider-reported token overage - provider-reported cost overage - `llm_query/3` and depth-bounded `rlm_query/4` - static loading of the live recursive integration test without credentials ## REAL OpenRouter acceptance gate Same-repository PR CI must execute this production path before merge: `real OpenRouter root planner -> opaque external context slice -> registered project_read tool -> exactly one rlm child -> real OpenRouter child model call -> child final -> root final` The live test also verifies `project_read` authorization/status and the fixture token `PROLOG_RLM_TOOL_OK`, recursion depth/count, child HTTP 200, and total real model-call count. Live evidence is limited to non-secret status fields. Planner JSON, model text/reasoning, API keys, Authorization headers, and environment dumps are not intentionally logged. Do not merge until deterministic CI and the REAL OpenRouter PR job are both green and the final diff/credential scan is clean.
Sign in to join this conversation.
No description provided.