activity-core/src/activity_core/execution_api.py
tegwick f6cfc28c33
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Container Image / build-and-push (push) Successful in 32s
feat(ACTIVITY-WP-0029): inventory callers, retarget sweep, bound execution
Map every State Hub/core-hub caller to a post-retirement owner. Keep the
15-minute sweep schedule here and point the engine at repo-manager
(State Hub dual-run by default, REPO_MANAGER_URL when present). Publish
GET /execution/semantics and 410 workplan launch routes so State Hub
/execution/* is not re-homed as a task database. T03 still waits on
HUB-WP-0004.
2026-08-18 10:52:56 +02:00

88 lines
3 KiB
Python

"""Execution-queue contract surface (ACTIVITY-WP-0029-T04).
Workplan launch rows stay out of this API. Callers that send State Hub
``/execution/*`` workplan shapes get 410 with a replacement pointer.
"""
from __future__ import annotations
from fastapi import APIRouter
from fastapi.responses import JSONResponse
router = APIRouter(prefix="/execution", tags=["execution"])
SEMANTICS = {
"port": "port.schedule",
"document": "docs/execution-queue-boundary.md",
"activity_core_owns": [
"schedules, wakeups, and recurring ActivityDefinition fires",
"POST /activity-definitions/{id}/trigger",
"ops_run claim, heartbeat, complete, and fail",
],
"activity_core_does_not_own": [
"workplan and task files (ADR-001 / repo-manager index)",
"task lifecycle assign/track/close (issue-core / work records)",
"ITC Task Model types",
"policy publication (policy-nexus)",
"C-rule consistency engine (repo-manager)",
],
"replacements": {
"GET /execution/semantics": "GET /execution/semantics",
"GET /execution/launch-requests": "GET /ops-runs",
"POST /execution/launch-requests": (
"POST /activity-definitions/{id}/trigger for a schedule fire; "
"do not POST workplan ids here"
),
"GET /execution/workplan-stack": "repo-manager port.work / hub-core projection",
"PATCH /execution/workplans/{id}/intent": "edit the workplan file in its repo",
},
}
@router.get("/semantics")
async def execution_semantics() -> dict:
return SEMANTICS
def _gone(replacement: str, detail: str) -> JSONResponse:
return JSONResponse(
status_code=410,
content={
"detail": detail,
"replacement_ref": replacement,
"document": "docs/execution-queue-boundary.md",
},
)
@router.api_route("/launch-requests", methods=["GET", "POST"])
async def launch_requests_retired() -> JSONResponse:
return _gone(
SEMANTICS["replacements"]["GET /execution/launch-requests"],
"Workplan launch-requests are not stored in activity-core. "
"Use GET /ops-runs or POST /activity-definitions/{id}/trigger.",
)
@router.get("/workplan-stack")
async def workplan_stack_retired() -> JSONResponse:
return _gone(
SEMANTICS["replacements"]["GET /execution/workplan-stack"],
"Workplan stacks are a work-record index, not an ops-run queue.",
)
@router.patch("/workplans/{workplan_id}/intent")
async def workplan_intent_retired(workplan_id: str) -> JSONResponse:
return _gone(
SEMANTICS["replacements"]["PATCH /execution/workplans/{id}/intent"],
"Execution intent for a workplan belongs in the repo file, not here.",
)
@router.patch("/workstreams/{workstream_id}/intent")
async def workstream_intent_retired(workstream_id: str) -> JSONResponse:
return _gone(
SEMANTICS["replacements"]["PATCH /execution/workplans/{id}/intent"],
"Legacy workstream execution intent is retired with State Hub.",
)