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:
mjalmoudy94
2026-10-14 20:57:56 +03:30
co-authored by Claude Sonnet 5.5
parent 36564e3f2b
commit fef5a9deab
43 changed files with 3024 additions and 221 deletions
+46 -8
View File
@@ -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(
[