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
@@ -14,7 +14,7 @@ git (in-memory ``FakeRepoWorkspace``) are fakes. What it defends:
|
||||
* red tests and a forbidden diff send the work *back* with cycle + 1 instead of
|
||||
merging it
|
||||
* ``analysis_only`` never creates a worktree
|
||||
* an empty wallet pauses the task before a single turn is spent
|
||||
* an overdrawn wallet pauses the task before a single turn is spent
|
||||
* a transient provider failure is retried, then handed to the manager
|
||||
"""
|
||||
|
||||
@@ -85,23 +85,29 @@ class _World:
|
||||
strong_id: str
|
||||
|
||||
|
||||
class _EmptyWallet:
|
||||
"""A wallet with no credit, and no way to top it up in a test."""
|
||||
class _OverdrawnWallet:
|
||||
"""A wallet below zero: the org is overdrawn, so the engine stops before a turn."""
|
||||
|
||||
balance = -1.0
|
||||
|
||||
|
||||
class _ZeroWallet:
|
||||
"""A wallet at exactly zero: the normal starting state of a fresh, post-paid org."""
|
||||
|
||||
balance = 0.0
|
||||
|
||||
|
||||
class _Wallets:
|
||||
def __init__(self, wallet: _EmptyWallet | None) -> None:
|
||||
def __init__(self, wallet: _OverdrawnWallet | _ZeroWallet | None) -> None:
|
||||
self._wallet = wallet
|
||||
|
||||
async def get_for_org(self, organization_id: str):
|
||||
return self._wallet
|
||||
|
||||
|
||||
class _EmptyWalletRepo(_Wallets):
|
||||
class _OverdrawnWalletRepo(_Wallets):
|
||||
def __init__(self) -> None:
|
||||
super().__init__(_EmptyWallet())
|
||||
super().__init__(_OverdrawnWallet())
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
@@ -532,7 +538,7 @@ async def test_analysis_only_finishes_without_a_worktree(world, session_factory)
|
||||
assert _calls(workspace, "commit") == []
|
||||
|
||||
|
||||
async def test_an_empty_wallet_pauses_the_task_before_a_turn_is_spent(
|
||||
async def test_an_overdrawn_wallet_pauses_the_task_before_a_turn_is_spent(
|
||||
world, session_factory
|
||||
):
|
||||
scripted = ScriptedModel([ScriptedReply(content="[[ASSIGN/]]")])
|
||||
@@ -549,7 +555,7 @@ async def test_an_empty_wallet_pauses_the_task_before_a_turn_is_spent(
|
||||
workspace=workspace,
|
||||
memory=RecordingMemory(),
|
||||
delivery=NullDeliveryHooks(),
|
||||
wallets=_EmptyWalletRepo(),
|
||||
wallets=_OverdrawnWalletRepo(),
|
||||
)
|
||||
await _run(scheduler, session, 1)
|
||||
state = await PipelineStateRepository(session).get(row.id)
|
||||
@@ -561,6 +567,38 @@ async def test_an_empty_wallet_pauses_the_task_before_a_turn_is_spent(
|
||||
assert BUDGET_PAUSED_MESSAGE
|
||||
|
||||
|
||||
async def test_a_zero_wallet_does_not_pause_a_fresh_org(world, session_factory):
|
||||
"""A 0.0 balance is every org's starting state, so it must not pause the task.
|
||||
|
||||
This is an intentional behaviour change. The scheduler used to pause on
|
||||
``balance <= 0``, which froze every new org before its first turn: usage is
|
||||
post-paid and nothing debits a wallet. Only an overdrawn wallet (below zero)
|
||||
pauses now. The old test that encoded the previous rule was renamed and
|
||||
updated, as PLAN-v2 §7.4 requires for a deliberate behaviour change.
|
||||
"""
|
||||
scripted = ScriptedModel([ScriptedReply(content="[[ASSIGN/]]")])
|
||||
workspace = FakeRepoWorkspace()
|
||||
async with session_factory() as session:
|
||||
await _team(session, world)
|
||||
row = await _task(session, world, stage=Stage.PENDING_MANAGER_REVIEW)
|
||||
await session.commit()
|
||||
scheduler = _scheduler(
|
||||
session,
|
||||
world,
|
||||
scripted=scripted,
|
||||
sandbox=FakeSandbox(),
|
||||
workspace=workspace,
|
||||
memory=RecordingMemory(),
|
||||
delivery=NullDeliveryHooks(),
|
||||
wallets=_Wallets(_ZeroWallet()),
|
||||
)
|
||||
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_a_task_waits_for_its_dependencies(world, session_factory):
|
||||
scripted = ScriptedModel(
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user