feat(integration): wire v2 workstreams together (engine policy/budget, sandbox, tenant checks, order route, docs)
Engine honours org policy and monthly budget, legacy runner skips engine tasks, sandbox session provisioned on demand, project fallback for threads, reviewer fallback, tenant checks on project ids, memory reflection respects grants, expiry worker, MCP pipeline_status, login redirect, sharing settings, e2e smoke. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
36564e3f2b
commit
fef5a9deab
@@ -0,0 +1,138 @@
|
||||
"""Integration: the owner's org policy is honoured by the real scheduler tick.
|
||||
|
||||
The tick reads the policy through the manager's grants port, once per
|
||||
organization, and checks two of its switches before a turn is spent:
|
||||
|
||||
* ``automation_enabled`` off stops every turn and every merge. The stage does not
|
||||
move, so switching automation back on resumes the task where it was (the
|
||||
owner's human-off switch).
|
||||
* ``monthly_credit_budget`` is a ceiling on the organization's spend since the
|
||||
first day of the UTC month. Spend at or above it pauses the task.
|
||||
|
||||
With no policy (the default), the tick behaves as the flow tests pin it.
|
||||
|
||||
The fixtures and the scheduler wiring come from ``tests.test_engine_flow``; this
|
||||
module adds the owner's policy and the spend guard on top of them.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from app.application.engine.scheduler import Scheduler
|
||||
from app.application.ports.delivery_hooks import NullDeliveryHooks
|
||||
from app.application.ports.model_grants import DefaultOrgPolicy, OrgPolicyView
|
||||
from app.application.ports.repo_workspace import FakeRepoWorkspace
|
||||
from app.domain.workforce.pipeline import Stage
|
||||
from app.infrastructure.db.models import UsageEventRow
|
||||
from app.infrastructure.repositories.engine import PipelineStateRepository, TaskSpendRepository
|
||||
from tests.engine_fakes import (
|
||||
FakeGrants,
|
||||
FakeSandbox,
|
||||
RecordingMemory,
|
||||
ScriptedModel,
|
||||
ScriptedReply,
|
||||
)
|
||||
from tests.test_engine_flow import _run, _scheduler, _task, _team
|
||||
from tests.test_engine_flow import world as flow_world
|
||||
|
||||
#: The flow tests' organization fixture. Binding it under its own name registers it
|
||||
#: for this module's tests (a bare import would be flagged as unused and shadowed).
|
||||
world = flow_world
|
||||
|
||||
|
||||
async def _wired(
|
||||
session, world, *, scripted: ScriptedModel, policy: OrgPolicyView | None
|
||||
) -> Scheduler:
|
||||
"""The flow test's scheduler, with the owner's policy and the spend guard wired in."""
|
||||
scheduler = _scheduler(
|
||||
session,
|
||||
world,
|
||||
scripted=scripted,
|
||||
sandbox=FakeSandbox(),
|
||||
workspace=FakeRepoWorkspace(),
|
||||
memory=RecordingMemory(),
|
||||
delivery=NullDeliveryHooks(),
|
||||
)
|
||||
# The tick reads the owner's policy through the manager's grants port.
|
||||
scheduler.manager.grants = FakeGrants({world.strong_id: "strong"}, policy=policy)
|
||||
scheduler.spend = TaskSpendRepository(session)
|
||||
return scheduler
|
||||
|
||||
|
||||
def _usage(world, total_price: float) -> UsageEventRow:
|
||||
"""A ledger row for this organization, stamped now (so it falls in this month)."""
|
||||
return UsageEventRow(
|
||||
organization_id=world.organization_id,
|
||||
unit="model_input_tokens",
|
||||
quantity=1000.0,
|
||||
unit_price=0.0000004,
|
||||
total_price=total_price,
|
||||
)
|
||||
|
||||
|
||||
async def test_automation_off_stops_the_turn_and_moves_no_stage(world, session_factory):
|
||||
"""The owner's human-off switch: no turn is spent and the task keeps its stage."""
|
||||
scripted = ScriptedModel([ScriptedReply(content="[[ASSIGN/]]")])
|
||||
async with session_factory() as session:
|
||||
await _team(session, world)
|
||||
row = await _task(session, world, stage=Stage.PENDING_MANAGER_REVIEW)
|
||||
await session.commit()
|
||||
scheduler = await _wired(
|
||||
session, world, scripted=scripted, policy=DefaultOrgPolicy(automation_enabled=False)
|
||||
)
|
||||
report = await scheduler.tick()
|
||||
state = await PipelineStateRepository(session).get(row.id)
|
||||
|
||||
assert state is not None and state.stage is Stage.PENDING_MANAGER_REVIEW
|
||||
assert report.skipped == 1
|
||||
assert scripted.calls == 0
|
||||
|
||||
|
||||
async def test_a_spent_monthly_budget_pauses_before_a_turn_is_spent(world, session_factory):
|
||||
"""A budget of 0.0 with any spend this month is used up, so the task pauses."""
|
||||
scripted = ScriptedModel([ScriptedReply(content="[[ASSIGN/]]")])
|
||||
async with session_factory() as session:
|
||||
await _team(session, world)
|
||||
row = await _task(session, world, stage=Stage.PENDING_MANAGER_REVIEW)
|
||||
session.add(_usage(world, total_price=0.25))
|
||||
await session.commit()
|
||||
scheduler = await _wired(
|
||||
session, world, scripted=scripted, policy=DefaultOrgPolicy(monthly_credit_budget=0.0)
|
||||
)
|
||||
await _run(scheduler, session, 1)
|
||||
state = await PipelineStateRepository(session).get(row.id)
|
||||
|
||||
assert state is not None and state.stage is Stage.PAUSED
|
||||
assert scripted.calls == 0
|
||||
|
||||
|
||||
async def test_spend_under_the_monthly_budget_does_not_pause(world, session_factory):
|
||||
"""Spend below the monthly budget leaves the task free to take its turn."""
|
||||
scripted = ScriptedModel([ScriptedReply(content="[[ASSIGN/]]")])
|
||||
async with session_factory() as session:
|
||||
await _team(session, world)
|
||||
row = await _task(session, world, stage=Stage.PENDING_MANAGER_REVIEW)
|
||||
session.add(_usage(world, total_price=0.25))
|
||||
await session.commit()
|
||||
scheduler = await _wired(
|
||||
session, world, scripted=scripted, policy=DefaultOrgPolicy(monthly_credit_budget=10.0)
|
||||
)
|
||||
await _run(scheduler, session, 1)
|
||||
state = await PipelineStateRepository(session).get(row.id)
|
||||
|
||||
assert state is not None and state.stage is not Stage.PAUSED
|
||||
assert scripted.calls == 1
|
||||
|
||||
|
||||
async def test_no_policy_keeps_the_default_behaviour(world, session_factory):
|
||||
"""With no owner policy the default applies: automation on, no monthly budget."""
|
||||
scripted = ScriptedModel([ScriptedReply(content="[[ASSIGN/]]")])
|
||||
async with session_factory() as session:
|
||||
await _team(session, world)
|
||||
row = await _task(session, world, stage=Stage.PENDING_MANAGER_REVIEW)
|
||||
await session.commit()
|
||||
scheduler = await _wired(session, world, scripted=scripted, policy=None)
|
||||
await _run(scheduler, session, 1)
|
||||
state = await PipelineStateRepository(session).get(row.id)
|
||||
|
||||
assert state is not None and state.stage is not Stage.PAUSED
|
||||
assert scripted.calls == 1
|
||||
Reference in New Issue
Block a user