fix(retirement): close projection and launch contract gaps
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02b7c-1c49-76a0-955a-49e7b3ddfc0d
This commit is contained in:
parent
c43266f626
commit
b0e1af24f9
13 changed files with 1717 additions and 50 deletions
|
|
@ -21,9 +21,9 @@ from api.services.execution_queue import (
|
|||
ACTIVITY_CORE_RESPONSIBILITIES,
|
||||
CONCURRENCY_MODES,
|
||||
EXECUTION_STATES,
|
||||
EXECUTION_REPLACEMENTS,
|
||||
LAUNCH_MODES,
|
||||
STATE_HUB_RESPONSIBILITIES,
|
||||
execution_state_for_launch,
|
||||
queue_sort_key,
|
||||
workplan_blockers,
|
||||
)
|
||||
|
|
@ -43,6 +43,8 @@ async def execution_semantics() -> ExecutionSemantics:
|
|||
concurrency_modes=CONCURRENCY_MODES,
|
||||
state_hub_responsibility=STATE_HUB_RESPONSIBILITIES,
|
||||
activity_core_responsibility=ACTIVITY_CORE_RESPONSIBILITIES,
|
||||
launch_requests_accepted=False,
|
||||
replacements=EXECUTION_REPLACEMENTS,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -161,37 +163,27 @@ async def workplan_stack(
|
|||
|
||||
@router.post(
|
||||
"/launch-requests",
|
||||
response_model=LaunchRequestRead,
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
status_code=status.HTTP_410_GONE,
|
||||
)
|
||||
async def create_launch_request(
|
||||
request: Request,
|
||||
response: Response,
|
||||
body: LaunchRequestCreate,
|
||||
session: AsyncSession = Depends(get_session),
|
||||
) -> WorkplanLaunchRequest:
|
||||
ws = await session.get(Workplan, body.workplan_id)
|
||||
if ws is None:
|
||||
raise HTTPException(status_code=404, detail="Workplan not found")
|
||||
|
||||
launch_request = WorkplanLaunchRequest(
|
||||
workplan_id=ws.id,
|
||||
requested_by=body.requested_by,
|
||||
requested_actor=body.requested_actor,
|
||||
launch_mode=body.launch_mode,
|
||||
concurrency_mode=body.concurrency_mode,
|
||||
priority=body.priority or ws.planning_priority,
|
||||
repo_id=body.repo_id or ws.repo_id,
|
||||
branch_preference=body.branch_preference,
|
||||
immediate_pickup=body.immediate_pickup,
|
||||
notes=body.notes,
|
||||
request_metadata=body.request_metadata,
|
||||
) -> None:
|
||||
del body # Request shape stays documented while the retired route returns 410.
|
||||
await retire_legacy_route(
|
||||
session=session,
|
||||
request=request,
|
||||
response=response,
|
||||
interface_key="rest_api:POST /execution/launch-requests",
|
||||
replacement_ref="repo file queue or activity-core ActivityDefinition + ops_run",
|
||||
detail=(
|
||||
"State Hub workplan launch requests are retired: no consumer picks up these rows. "
|
||||
"Queue development work in the authoritative repository file; use an "
|
||||
"ActivityDefinition and activity-core ops_run only for recurring or operational fires."
|
||||
),
|
||||
)
|
||||
ws.launch_mode = body.launch_mode
|
||||
ws.concurrency_mode = body.concurrency_mode
|
||||
ws.execution_state = execution_state_for_launch(body.launch_mode, body.immediate_pickup)
|
||||
session.add(launch_request)
|
||||
await session.commit()
|
||||
await session.refresh(launch_request)
|
||||
return launch_request
|
||||
|
||||
|
||||
@router.get("/launch-requests", response_model=list[LaunchRequestRead])
|
||||
|
|
|
|||
44
api/routers/identifier_migrations.py
Normal file
44
api/routers/identifier_migrations.py
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
from dataclasses import asdict
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from api.database import get_session
|
||||
from api.schemas.identifier_migration import (
|
||||
SealedProjectionRepairReceiptRead,
|
||||
SealedProjectionRepairSubmit,
|
||||
)
|
||||
from api.services.work_record_identifier_migration import (
|
||||
IdentifierMigrationError,
|
||||
repair_absent_prederivation_projection,
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/identifier-migrations", tags=["identifier-migrations"])
|
||||
|
||||
|
||||
@router.post(
|
||||
"/sealed-projection-repairs",
|
||||
response_model=SealedProjectionRepairReceiptRead,
|
||||
)
|
||||
async def repair_sealed_projection(
|
||||
body: SealedProjectionRepairSubmit,
|
||||
session: AsyncSession = Depends(get_session),
|
||||
) -> dict:
|
||||
"""Restore one exact pre-derivation workplan unit into an absent projection."""
|
||||
try:
|
||||
receipt = await repair_absent_prederivation_projection(
|
||||
session,
|
||||
body.plan,
|
||||
body.repo_slug,
|
||||
body.unit,
|
||||
expected_plan_sha256=body.expected_plan_sha256,
|
||||
source_revision=body.source_revision,
|
||||
source_fingerprint=body.source_fingerprint,
|
||||
source_clean=body.source_clean,
|
||||
source_synchronized=body.source_synchronized,
|
||||
primary_confirmed=body.primary_confirmed,
|
||||
projection_identity=body.projection_identity,
|
||||
)
|
||||
except IdentifierMigrationError as exc:
|
||||
raise HTTPException(status_code=409, detail=str(exc)) from exc
|
||||
return asdict(receipt)
|
||||
Loading…
Add table
Add a link
Reference in a new issue