- Prepaid credit system: org wallet, debit on usage, chat gate, admin credit console - Engine UI: /manager, /tasks, /tasks/[id], /workforce, /dashboard, /traces pages - Direct task creation (HTTP POST /tasks, MCP tasks_create) at pending_manager_review - Pause/resume/cancel/answer actions in engine API and UI - Employee cap (7 per org default), review pipeline guard (active reviewer required) - Scheduler: wide window prevents org starvation; archived employees excluded from cap - Tenant isolation: project-id cross-org 404, engine never uses another tenant's sandbox - Order route fix: manager built with pipeline states + employee profiles - Contract extension: ModelGrantPort.get_org_policy with DefaultOrgPolicy - Engine event types in @agy/contracts (task.step, task.gate, run.log, run.tool, team.changed) - api-engine.ts typed client; api-credit.ts client - Alembic migration c4d5e6f7a8b9: prepaid credit + engine UI tables - 859 tests passed, 1 skipped; ruff/mypy/tsc/eslint/vitest all green Refs: PLAN-v2.md §9 (T1–T43), todo-v2-final.md
69 lines
2.9 KiB
Python
69 lines
2.9 KiB
Python
"""The scheduler stores what the task page shows: the last diff and the merged sha.
|
|
|
|
What this test defends:
|
|
|
|
* the diff the diff guard accepted is kept on the state (``last_diff``), so the
|
|
task page can show it after the worktree is gone
|
|
* the sha the platform pushed to ``dev`` is kept on the state (``merged_sha``),
|
|
so the task page can link to it
|
|
|
|
The flow fixtures and the scripted replies come from ``tests.test_engine_flow``.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from app.application.ports.delivery_hooks import NullDeliveryHooks
|
|
from app.application.ports.repo_workspace import DiffResult, FakeRepoWorkspace
|
|
from app.domain.workforce.pipeline import Stage
|
|
from app.infrastructure.repositories.engine import PipelineStateRepository
|
|
from tests.engine_fakes import 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 test_the_last_diff_and_the_merged_sha_are_stored_on_the_state(world, session_factory):
|
|
scripted = ScriptedModel(
|
|
[
|
|
ScriptedReply(content='[[ASSIGN employee="" pipeline="plan_code_review_test"/]]'),
|
|
ScriptedReply(content="[[PLAN_SPEC]]پلان کار[[/PLAN_SPEC]]"),
|
|
ScriptedReply(content="[[WORK_REPORT]]پیادهسازی شد[[/WORK_REPORT]]"),
|
|
ScriptedReply(content="[[REVIEW_PASS]]قابل قبول است[[/REVIEW_PASS]]"),
|
|
ScriptedReply(content="[[TEST_PASS]]سبز است[[/TEST_PASS]]"),
|
|
ScriptedReply(content="[[COMPLETE/]]"),
|
|
]
|
|
)
|
|
sandbox = FakeSandbox()
|
|
workspace = FakeRepoWorkspace()
|
|
memory = RecordingMemory()
|
|
delivery = NullDeliveryHooks()
|
|
diff_text = "--- a/app/main.py\n+++ b/app/main.py\n@@\n+x = 1\n"
|
|
|
|
async with session_factory() as session:
|
|
await _team(session, world)
|
|
row = await _task(session, world, stage=Stage.PENDING_MANAGER_REVIEW)
|
|
workspace.diffs[row.id] = DiffResult(changed_files=["app/main.py"], text=diff_text)
|
|
await session.commit()
|
|
scheduler = _scheduler(
|
|
session,
|
|
world,
|
|
scripted=scripted,
|
|
sandbox=sandbox,
|
|
workspace=workspace,
|
|
memory=memory,
|
|
delivery=delivery,
|
|
)
|
|
await _run(scheduler, session, 7)
|
|
state = await PipelineStateRepository(session).get(row.id)
|
|
|
|
assert state is not None and state.stage is Stage.COMPLETED
|
|
# The fake workspace pushes the merged commit to ``dev``; that is the sha the
|
|
# platform reports, and it must be the one stored on the state.
|
|
pushed_sha = workspace.heads[(world.project_id, "dev")]
|
|
assert len(pushed_sha) == 40
|
|
assert state.last_diff == diff_text
|
|
assert state.merged_sha == pushed_sha
|