Skip to content

feat: make interaction budgets a first-class participant behavior member - #1469

Closed
doublewhy wants to merge 6 commits into
devfrom
310-participant-interaction-budget-support
Closed

doublewhy wants to merge 6 commits into
devfrom
310-participant-interaction-budget-support

Conversation

@doublewhy

@doublewhy doublewhy commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Stacked on #1467 (DSL-121, #308) at its current head 6da04a44, which is stacked on #1466 (SEM-223, #306) at its current head 11fcd577. Those PRs' four commits appear in this diff until they merge; the own commits here are the last two.

Implements ACT-624 as the issue #122 design specifies (specs/formal/participant-episode-model/README.md: the ACT-624 commitments, the issue table row "First-class interaction-budget model member, backend capability declaration, conformance", and the matrix rows for EBM-03, EBM-05 and "First-class attachment across kinds (ACT-623/624)").

  • First-class member. behavior_specifications.<spec>.resource_budget is a new member of the behavior aggregate, so a human, scripted, replayed, policy-directed, mixed-control or autonomous-mode participant can carry an interaction budget. It is the ADR-097 budget policy shape (owners, fairness, dimensions) with the DSL-121 kinds and rules. It is not a second budget root and compiles into the same owner, demand and fairness IR as a v3 budget, as ParticipantBehaviorSpecificationRuntime.interaction_budget.
  • What it bounds. It governs every action attempt of the participants its specification selects. Validation uses the compiler's selection (select_participants): the participant_refs and every participant whose effective role is one of the participant_role_refs. Unlike the v3 profile it bounds only the dimensions it declares, so action rate, turns, steps, logical time, tokens and tool use can each be bounded alone. A dimension that counts scenario time, resets per time segment, or uses a window needs clock_ref. The SEM-223 owner rules apply, and its quotas stay hidden. A participant-owned dimension on a specification that selects more than one participant is rejected (EBM-03), whether the others are listed or selected by role, and the error names the governed participants; feat!: define participant budget exhaustion and limit-effect semantics #1466 applies the same check to v3 budgets.
  • One governing budget. A specification with an autonomous execution profile keeps declaring its budget in the v3 profile, and an aggregate budget there is rejected. Validation also rejects a participant that more than one budget-carrying specification selects, v3 or aggregate, so no attempt is governed twice. While a participant or role ref is still a variable, both participant checks wait for instantiation, which validates the resolved scenario again.
  • Backend declaration. A backend declares support in the existing participant_runtime capability root with a new evidence-required behavior feature, interaction_budgets, its feature_support entry, and resource_budgets capabilities. Budget capabilities no longer require autonomous execution support when the feature is declared. Planner admission refuses an aggregate budget unless the backend declares the feature, then admits it the way it admits a v3 budget. A pool that a v3 policy shares with an aggregate budget is checked against both limits.
  • Conformance. A declaration is not proof of enforcement (EBM-09). participant_interaction_budget_conformance_diagnostics (new, raes_conformance) reads recorded evidence. Every terminal attempt of a governed participant must carry the budget's admission: a reserve event on every compiled dimension, or a reject or throttle on one of them. Given budgets that overlap anyway, it checks each attempt against every budget that governs the participant, and a refusal by any of them stands for all. Every realized budget state must keep its compiled dimension's kind, unit, accounting mode, meter, limit and reset. The function is invoked directly, today only by tests. run_target_conformance does not call it and the raes_conformance facade does not export it, as with the ACT-614 probe participant_temporal_scenario_case (tracked in Run the participant conformance probes from run_target_conformance #1523).
  • Reference runtime. The reference runtime enforces budgets only through autonomous v3 policies and does not realize an aggregate budget itself. Its control plane now refuses a manual action of a governed participant unless the backend declares interaction_budgets, the way it already refuses manual submission of shared-time-bound actions. A declaring backend realizes the budget, and conformance checks the evidence it records.

The SDL authoring, instantiated, snapshot, materialized and satisfiability schemas change for the new member. backend-manifest-v2 changes for the new feature term. Each has a ledger entry. The new SDL refs are registered in specs/sdl/references.md and the catalog parity expectations, and the lineage ledger names the member as RAES-defined.

Merge hazard (the schema budget is tracked in #1556): implementations/python/tests/test_issue_1241_schema_publication_size.py caps contracts/schemas/sdl/materialized-scenario-v1.json at 500 × 1024 = 512,000 bytes, and the repository policy caps raes/validator/_content_objectives.py at 500 lines. #1467 now shares repeated propertyNames subschemas in that schema, and ParticipantInteractionBudget's schema description is one sentence (it was 379 bytes), so the schema is 502,735 bytes here (507,530 at the previous head 28e1694c) and _content_objectives.py is 474 lines. In a local merge of the posted order with every PR's current head, the schema is 511,867 bytes after #1463 and #1465, 507,572 after #1467 and 508,366 after this PR; _content_objectives.py is 497 lines after #1446, 498 after #1466, 492 after #1467 and 491 after this PR.

Because this changes source bound by the research evidence, both captures are republished one release above #1467 (specification coverage 71.0.0, formal validation 72.0.0). Retained outcomes, classifications and claim limits are unchanged.

Requirement UIDs

Related Issues

Closes #310

ADR Impact

Changes

  • SDL:
    • raes/participant_resource_budgets.py: ParticipantInteractionBudget, the budget policy without the v3 complete-vector rule and with clock_ref; its schema description is one sentence and the rest is a code comment. Tool scope now takes its governed actions explicitly: dispatched actions for v3, declared actions for the aggregate.
    • raes/participant_behavior_specification.py: the resource_budget member, counted as a behavior surface and rejected beside an autonomous profile.
    • raes/validator/_participant_resource_budget_owners.py: feat!: define participant budget exhaustion and limit-effect semantics #1466's owner rules, over the participants select_participants picks, now also cover aggregate budgets, and a participant that two budget-carrying specifications select is rejected. Both participant checks wait for instantiation while a participant or role ref is a variable. _content_objectives.py passes the effective roles it already computes for the behavior analysis to feat: support authored participant interaction budgets #1467's participant_resource_budget_errors.
    • raes/validator/_participant_resource_budget_scopes.py: tool-scope and clock checks for aggregate budgets; participant_resource_budget_errors passes the scenario to the owner checks and its clocks to these checks.
    • raes/composition/_behavior.py: aggregate owner refs and clock_ref rewritten on namespaced import.
  • Compiler and planner:
    • raes_processor/compiler/participant_resource_budget_projection.py (new): the budget projection shared by v3 and aggregate budgets, and the aggregate compilation. participant_autonomous_execution.py now calls it; participant_behaviors.py sets the member.
    • raes_processor/models/participant_resources.py: ParticipantInteractionBudgetRuntime, on ParticipantBehaviorSpecificationRuntime.interaction_budget.
    • raes_processor/planner/core.py: participant.interaction-budget-unsupported diagnostics.
  • Backend declaration:
    • raes_contracts/manifest_authority.py and contracts/concept-authority/controlled-vocabularies-v1.json (plus its reference fixture): the evidence-required interaction_budgets term and the contracts it requires.
    • raes_contracts/contracts/manifests.py and raes_backend_protocols/participant_capabilities.py: the term requires budget capabilities, and budget capabilities with the term no longer count as autonomous configuration.
    • raes_backend_protocols/participant_resource_admission.py: participant_interaction_budget_gaps, reusing the v3 admission checks.
    • contracts/fixtures/backend-manifest/backend-manifest-v2/valid/stub.json: the stub's unsupported declaration of the term.
  • Runtime and conformance:
    • raes_runtime/participant_submission_options.py: the manual-submission refusal. The existing shared-time refusal moves into the same helper with its message unchanged.
    • raes_conformance/conformance/participant_interaction_budgets.py (new): the conformance diagnostics. The facade export list is unchanged.
  • Schemas: 6 schemas regenerated through schema_bundle(), with 6 contracts/schema-publication/entries records.
  • Catalog and lineage: three behavior_specifications.*.resource_budget rows in specs/sdl/references.md, after the mixed_control rows, with expectations in tools/sdl_catalog_parity/_expectations_3.py. The sdl-field:behavior_specifications divergence in contracts/provenance/sdl-lineage-ledger-v2.json and an ACT-624 bullet in docs/explain/sdl/lineage.md.
  • Docs and records:
  • Tests: test_issue_310_act_624_participant_interaction_budgets.py (new, 41 tests).
  • Research evidence (stacked on feat: support authored participant interaction budgets #1467):
    • Specification-coverage release 71.0.0 (execution-snapshot-v71.json, analysis-v71.json, issue-310 bundle) replays the retained matrix against this branch's source.
    • Formal-validation release 72.0.0 (execution-snapshot-v72.json, analysis-v72.json, retest-v72.json) replays the retained formal cases with baseline 71.0.0.
    • Revision pins advanced in tools/check_specification_coverage.py, tools/formal_semantic_validation/, and the three evidence test modules. Both research indexes record the new releases.

Test Plan

  • Unit tests pass

  • Integration tests pass if applicable

  • Full completion suite required in CI before merge

  • No coverage regression

  • New module. uv run --project implementations/python --frozen --all-extras python -m pytest implementations/python/tests/test_issue_310_act_624_participant_interaction_budgets.py -q -p no:cacheprovider: 41 passed. With -m integration or -m fuzz, all 41 are deselected.

    • The aggregate member validates and compiles for all seven governed behavior_mode terms and for a specification without one. It names its participants, satisfies the aggregate alone, and is rejected beside an autonomous profile.
    • It bounds only declared dimensions where a v3 policy needs the full vector. Its clock rule is checked for scenario time, time-segment resets, windows and an unused clock, and unknown clocks and affordances are rejected. A participant-owned dimension is rejected when the specification would count a second participant, listed or selected by its green role (EBM-03), and its refs stay bound under a namespaced import.
    • A participant selected by two budget-carrying specifications is rejected for a v3 budget plus an aggregate budget, two aggregate budgets, and a second aggregate budget that selects it by role. Two specifications that budget different participants (the mixed-control fixture's red-agent and supervisor-agent) still compile. A participant named through a variable passes parse-time validation and is checked after instantiation: it compiles when the variable resolves to the only green participant, and instantiation rejects the participant-owned dimension once a second green agent exists.
    • The manifest tests cover a declaration without its evidence entry, without budget capabilities, and budget capabilities without the feature, and they read interaction_budgets from the evidence-required feature enum of the published participant_runtime.feature_support schema. Planner admission is checked against a backend whose budget support is autonomous-only (the matrix negative "budget available only on the autonomous profile"), a missing kind, and a pool that each family fits alone but not together. plan() reports participant.interaction-budget-unsupported for the stub manifest and nothing for a declaring manifest.
    • Conformance runs on real attempts recorded by the reference v3 scheduler. Without the budget's events every attempt is reported; with admission run through the runtime accounting functions nothing is. A substituted limit is reported. With a second governing budget and no evidence, every attempt is reported against both budgets. An attempt the first budget admitted is reported against the second one, and attempts the first budget throttled or rejected are not. The reference control plane refuses a manual action of a governed participant for a backend without the feature and lets a declaring backend run it.
  • Regression proof. With the package files set back to feat: support authored participant interaction budgets #1467's head 6da04a44, the module cannot be collected, because ParticipantInteractionBudget, which it imports, does not exist there. At this head I applied 21 single-point source mutations, one at a time, and restored each before the next run. Each made at least one test of the module fail. They removed the aggregate-surface entry, the autonomous-profile exclusion, the vector exemption, the clock rule, clock resolution, aggregate owner checks, the namespaced clock rewrite, both manifest decouplings, the admission feature check, shared-pool counting, both conformance checks, and the manual-submission guard. They also reverted owner selection to explicit refs, removed the wait for unresolved participant variables, removed the one-budget check, removed the rule that a refusal by one budget stands for all, checked only the first governing budget, swapped the planner call's budget arguments, and discarded the planner's budget diagnostics.

  • Related suites. The Participant Interaction Budgets And Quotas (ACT-624) #310, Participant Interaction Budget Surface (DSL-121) #308, Participant Budget, Quota, And Exhaustion Semantics (SEM-223) #306 (both), Add participant activity resource budgets and shared-service fairness contracts #899 and Backends have no way to attest to what they added in-world; require a post-materialization attestation in valid RAES SDL #1241 modules together: 144 passed. The 272 modules that reference resource budgets, behavior specifications, schema_bundle, the materialized schema, observation boundaries, view rules, autonomous execution, tool affordances, participant selection or roles, raes_conformance, the planner, backend manifests or participant capabilities, catalog parity or lineage, plus test_sdl_validator.py and the composition modules: 7,565 passed, 2 skipped (4 xdist workers, 634 s on a loaded machine).

  • Schema and governance checks. tools/check_generated_schemas.py, tools/check_schema_publication.py --base-rev origin/308-participant-interaction-budgets, make policy and nox -s lint pass; the contracts lane below also runs SDL catalog parity and SDL lineage. Relative to the previous head, the five SDL schemas differ because ParticipantInteractionBudget's description is shorter, and the materialized schema also because of feat: support authored participant interaction budgets #1467's factoring; their entries keep this PR's summaries with recomputed hashes.

  • Evidence and gates. Both evidence checker CLIs pass. The three evidence modules pass with default markers (209 passed, 19 deselected) and with -m integration (19 passed), with no formal deviations and no pinned artifact changed. nox -s verify-fast-feedback -- --base-rev origin/308-participant-interaction-budgets passes (29 stages, requirement governance skipped; the directly changed test modules, this PR's and the three evidence modules: 250 passed, 19 deselected), and nox -s contracts -- --base-rev origin/308-participant-interaction-budgets passes all 14 contract steps. The republish helper's --check against origin/308-participant-interaction-budgets reports the evidence current.

  • Coverage. At head e7df797f the SonarCloud PR gate is OK (95.8% new-code coverage, 0 new violations, 0.0% duplication; analysis 2026-10-09T23:23Z), and canonical / coverage-reduce passed in CI run 38002299710, where all 32 checks pass and deploy is skipped.

Ground Control Checks

  • Repository policy command passes
  • Pre-push code review and test-quality review completed, or not run for this lane

make policy passes. A pre-push self-review of the own commit ran before the evidence republish. It removed a redundant plan-level refusal in favor of the manual-submission guard, and cut the admission function to three returns. An independent review then found that owner checks counted only listed participants and that two specifications could budget one participant. This revision fixes both, as the What it bounds, One governing budget and Conformance bullets describe. This revision rebases the own commit onto #1467's current head. The owner module, the validator hook, the materialized schema and its ledger entry conflicted: the owner module keeps #1466's participant-scope rules (listed refs and governed participants may be named, and the error lists the governed participants) and adds the aggregate budgets, the one-budget check and the wait for unresolved variables; the hook calls #1467's entry point; the schemas are regenerated. The 21 mutations above, re-run at this head, check that the new tests are not vacuous.

Traceability

  • IMPLEMENTS: implementations/python/packages/raes/participant_resource_budgets.py, implementations/python/packages/raes/participant_behavior_specification.py, implementations/python/packages/raes/validator/_participant_resource_budget_owners.py, implementations/python/packages/raes/validator/_participant_resource_budget_scopes.py, implementations/python/packages/raes/validator/_content_objectives.py, implementations/python/packages/raes/composition/_behavior.py, implementations/python/packages/raes_contracts/manifest_authority.py, implementations/python/packages/raes_contracts/contracts/manifests.py, implementations/python/packages/raes_backend_protocols/participant_capabilities.py, implementations/python/packages/raes_backend_protocols/participant_resource_admission.py, implementations/python/packages/raes_processor/models/participant_resources.py, implementations/python/packages/raes_processor/models/behavior_resources.py, implementations/python/packages/raes_processor/models/__init__.py, implementations/python/packages/raes_processor/compiler/participant_resource_budget_projection.py, implementations/python/packages/raes_processor/compiler/participant_autonomous_execution.py, implementations/python/packages/raes_processor/compiler/participant_resource_scopes.py, implementations/python/packages/raes_processor/compiler/participant_behaviors.py, implementations/python/packages/raes_processor/planner/core.py, implementations/python/packages/raes_runtime/participant_submission_options.py, implementations/python/packages/raes_conformance/conformance/participant_interaction_budgets.py (all ACT-624 lines in docs/requirements/ACT-624/requirement.md)
  • TESTS: implementations/python/tests/test_issue_310_act_624_participant_interaction_budgets.py

Checklist

  • Code follows the project coding standards
  • FM level classified if semantic change
  • Published contract schemas regenerated if models changed
  • PR title is a Conventional Commit (release-please derives the version and CHANGELOG.md from it)
  • Architectural docs updated if applicable

FM3 (stateful and control semantics), per the #122 design. No executable or runtime adoption is claimed: the reference runtime does not realize an aggregate budget, its control plane refuses a manual bypass, and conformance checks evidence a backend records.

Nonclaims, as stated in the spec:

Documentation

Updated: specs/formal/participant-semantics/autonomous-execution.md, docs/explain/sdl/sections.md, docs/explain/sdl/lineage.md, specs/sdl/references.md, docs/explain/reference/shared-semantic-integrity.md, docs/requirements/ACT-624/requirement.md, specs/formal/assurance-fulfillment.yaml.

SEM-223 gives the v3 resource budget its interaction-level meaning from the
issue #122 design. Exhaustion is derived from remaining capacity. A
reservation that any logical budget cannot admit is a typed reject event,
checked across the whole vector before any shared pool, and the governed
attempt becomes an undispatched SEM-211 rejected attempt with the resource
precondition and the resource_exhausted failure class, settled by the
policy's failure disposition. The reject event and the attempt commit
together. Shared-pool contention stays a throttle.

Settlement is fenced to the reserving generation and happens exactly once. A
shared-clock reset reconciles episode-owned dimensions only when it reset the
bound episodes. Participant-owned budgets may not count other owners' or
other participants' use; the governed participants include agents selected
through participant_role_refs, not only those named in participant_refs. The
runtime result path and published snapshot conformance reject future,
cross-generation, repeated, or rewritten budget events, exhaustion recorded
outside SEM-211, disclosed budget identity, and backend-local limits presented
as portable exhaustion.

This breaks v3 documents and consumers that relied on the old behavior: a v3
behavior specification must now govern exactly one participant, a budget of
another owner can no longer name a participant-owned parent, and a logical
shortfall is a reject event with a rejected attempt instead of a throttle that
failed the scheduler pass. docs/migration/autonomous-execution-v3.md records
the migration.
@doublewhy
doublewhy force-pushed the 310-participant-interaction-budget-support branch from 0fe5891 to 413a051 Compare October 9, 2026 19:16
@doublewhy
doublewhy force-pushed the 310-participant-interaction-budget-support branch from 413a051 to 28e1694 Compare October 9, 2026 20:29
@doublewhy
doublewhy marked this pull request as ready for review October 9, 2026 21:28
@doublewhy
doublewhy marked this pull request as draft October 9, 2026 21:37
DSL-121 lets a v3 resource budget bound participant interaction with the same
ADR-097 dimensions. The governed catalog adds interaction_steps,
interaction_turns, tool_invocations, and scenario_time with fixed units and
compatible accounting modes; tokens keep inference_tokens. The six initial
kinds stay required and the interaction kinds are optional.

A tool_invocations dimension names the behavior specification's tool
affordances and counts only the dispatched action contracts they bind;
validation and compilation share that rule. Other attempts reserve zero from
it, and a zero quantity never refuses.

A scenario_time dimension bounds elapsed time on the policy's shared clock.
RAES meters it from the clock history since the latest reset (time_segment)
or since initialization (run): each admitted attempt reserves the ticks
elapsed since the last charge plus its allowance and commits the elapsed
ticks. Host or watchdog meters are rejected on every scenario-time contract.

A quota stays hidden unless the policy's observation boundary discloses the
dimension through a sensitive resource_budget view rule, including under a
namespaced import. A disclosed dimension that rejects an attempt reports its
used amount, authored limit, remaining amount, and the request in the
attempt's observations, read from this policy's own reject event.

The published policy demand can carry the tool scope, and the policy
identity of a budget without the new fields is unchanged; a valid and an
invalid policy fixture carry a tool_invocations demand with and without
action_contract_refs. The thirteen schemas that embed the catalog are
rebuilt, each with a ledger entry.

The validator runs the owner, tool-scope and disclosure checks through one
entry point. Schema factoring also shares repeated propertyNames subschemas,
which keeps materialized-scenario-v1 within its publication size budget.
ACT-624 attaches an interaction budget to the behavior-specification
aggregate itself, so any participant kind can carry one, not only the v3
autonomous profile. behavior_specifications.<spec>.resource_budget takes the
ADR-097 budget policy shape with the DSL-121 kinds and rules. It bounds only
the dimensions it declares, counts ticks, segments and windows on its
clock_ref, and governs every action attempt of the specification's
participants. It compiles into the same owner, demand and fairness IR as a
v3 budget. An autonomous profile keeps its own budget, so an aggregate budget
beside one is rejected.

Aggregate budgets get the owner validation v3 budgets have, over the
participants the compiler selects, participant_role_refs included, so a
participant-owned dimension cannot count a second participant. A participant
that two budget-carrying specifications select is rejected, so no attempt is
governed twice. While a participant or role ref is a variable, both
participant checks wait for instantiation, which validates the resolved
scenario again.

A backend declares support in the participant_runtime capability root with
the evidence-required interaction_budgets behavior feature and resource-budget
capabilities, which then no longer require autonomous execution support.
Planner admission refuses an aggregate budget without that declaration and
otherwise admits it like a v3 budget, checking pools a v3 policy shares
against both limits.

A declaration is not proof of enforcement. New conformance diagnostics check
that each recorded attempt of a governed participant carries the admission of
every budget that governs it, a refusal by any of them standing for all, and
that realized budget states keep their compiled dimensions. The reference
control plane refuses a manual action of a governed participant unless the
backend declares the feature.

The SDL and backend-manifest schemas that embed the new member and term are
rebuilt, each with a ledger entry, and the new SDL refs are cataloged. The
member's schema description is one sentence, which keeps
materialized-scenario-v1 within its publication size budget.
@doublewhy

Copy link
Copy Markdown
Contributor Author

Closing to keep work in milestone order. This stack sits on #1463/#1465 and edits participant_behavior_specification.py and composition/_behavior.py, which Runtime Refactor #1363 (ADR-110) reworks. #310 stays open and the branch is kept.

@doublewhy doublewhy closed this Oct 12, 2026
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