Skip to content

Actions

Generic action, field, and result contracts.

Consumers own the verbs and the effects. Groundskeeping owns the repeatable operator sequence around those verbs: describe fields, parse input, ask policy whether to proceed, run with progress/cancellation context, and render a generic outcome.

Preflight module-attribute

Preflight = Callable[
    [Mapping[str, object]], Sequence[ValidationIssue]
]

Validator module-attribute

Validator = Callable[[object], ValidationIssue | None]

ActionContext dataclass

ActionContext(
    progress: ProgressSink,
    cancellation: CancellationToken,
    action_id: str,
)

Everything a runner may touch while the action is in flight.

Deliberately narrow: a runner reports progress and checks for cancellation through this object, so long-running domain work never needs to import a widget or reach the app.

action_id instance-attribute

action_id: str

cancellation instance-attribute

cancellation: CancellationToken

progress instance-attribute

progress: ProgressSink

emit

emit(
    event: str,
    *,
    phase: str | None = None,
    completed: int = 0,
    total: int | None = None,
    unit: str | None = None,
    message: str | None = None,
) -> None

ActionOutcome dataclass

ActionOutcome(
    status: SemanticStatus,
    summary: str,
    view: SurfaceView,
    detail: object | None = None,
    refresh_pages: frozenset[str] = frozenset(),
)

detail class-attribute instance-attribute

detail: object | None = None

refresh_pages class-attribute instance-attribute

refresh_pages: frozenset[str] = frozenset()

status instance-attribute

status: SemanticStatus

summary instance-attribute

summary: str

view instance-attribute

view: SurfaceView

ActionRegistry

ActionRegistry(
    actions: Sequence[ActionSpec],
    *,
    page_keys: Sequence[str] | None = None,
)

Exact-key lookup for actions with startup validation.

__iter__

__iter__() -> Iterator[ActionSpec]

for_page

for_page(page_key: str) -> tuple[ActionSpec, ...]

get

get(key: str) -> ActionSpec

ActionRunner

Bases: Protocol

__call__

__call__(
    params: Mapping[str, object], context: ActionContext
) -> object

ActionSpec dataclass

ActionSpec(
    key: str,
    page_key: str,
    label: str,
    summary: str,
    runner: ActionRunner,
    command_hint: str | None = None,
    fields: tuple[FieldSpec, ...] = (),
    execution: ExecutionKind = ExecutionKind.QUICK,
    cancellation: CancellationMode = CancellationMode.UNSUPPORTED,
    effect_refs: frozenset[str] = frozenset(),
    resource_refs: frozenset[str] = frozenset(),
    preflight: Preflight | None = None,
)

Declaration of one operator-facing command and the runner that performs it.

The spec carries everything the shell needs to present, gate, and execute the command without knowing what it does: fields to parse, resources and effects for the operation policy to reason about, and the cancellation mode the runner honours.

cancellation class-attribute instance-attribute

cancellation: CancellationMode = (
    CancellationMode.UNSUPPORTED
)

command_hint class-attribute instance-attribute

command_hint: str | None = None

effect_refs class-attribute instance-attribute

effect_refs: frozenset[str] = frozenset()

execution class-attribute instance-attribute

execution: ExecutionKind = ExecutionKind.QUICK

fields class-attribute instance-attribute

fields: tuple[FieldSpec, ...] = ()

key instance-attribute

key: str

label instance-attribute

label: str

long_running property

long_running: bool

needs_params property

needs_params: bool

page_key instance-attribute

page_key: str

preflight class-attribute instance-attribute

preflight: Preflight | None = field(
    default=None, compare=False, repr=False
)

resource_refs class-attribute instance-attribute

resource_refs: frozenset[str] = frozenset()

runner instance-attribute

runner: ActionRunner

summary instance-attribute

summary: str

parse_params

parse_params(
    raw: Mapping[str, object] | None = None,
) -> tuple[dict[str, object], dict[str, object]]

AllowAllOperationPolicy

Default policy for demos and tests; production consumers should be explicit.

blocked_reason

blocked_reason(
    action: ActionSpec,
    params: Mapping[str, object],
    active_jobs: Sequence[object],
) -> str | None

confirmation

confirmation(
    action: ActionSpec, params: Mapping[str, object]
) -> Confirmation | None

describe_effects

describe_effects(
    action: ActionSpec, params: Mapping[str, object]
) -> str

ChoiceOption dataclass

ChoiceOption(
    value: str, label: str, description: str | None = None
)

description class-attribute instance-attribute

description: str | None = None

label instance-attribute

label: str

value instance-attribute

value: str

Confirmation dataclass

Confirmation(
    title: str,
    message: str,
    confirm_label: str = "Run",
    dangerous: bool = False,
)

confirm_label class-attribute instance-attribute

confirm_label: str = 'Run'

dangerous class-attribute instance-attribute

dangerous: bool = False

message instance-attribute

message: str

title instance-attribute

title: str

DefaultResultPresenter

Present plain runner results without imposing a consumer report schema.

present

present(
    action: ActionSpec, result: object
) -> ActionOutcome

ExecutionKind

Bases: StrEnum

BACKGROUND class-attribute instance-attribute

BACKGROUND = 'background'

LONG_RUNNING class-attribute instance-attribute

LONG_RUNNING = 'long_running'

QUICK class-attribute instance-attribute

QUICK = 'quick'

FieldKind

Bases: StrEnum

BOOLEAN class-attribute instance-attribute

BOOLEAN = 'boolean'

CHOICE class-attribute instance-attribute

CHOICE = 'choice'

DECIMAL class-attribute instance-attribute

DECIMAL = 'decimal'

EXISTING_PATH class-attribute instance-attribute

EXISTING_PATH = 'existing_path'

INTEGER class-attribute instance-attribute

INTEGER = 'integer'

MULTILINE class-attribute instance-attribute

MULTILINE = 'multiline'

OUTPUT_PATH class-attribute instance-attribute

OUTPUT_PATH = 'output_path'

SECRET class-attribute instance-attribute

SECRET = 'secret'

TEXT class-attribute instance-attribute

TEXT = 'text'

FieldSpec dataclass

FieldSpec(
    key: str,
    label: str,
    kind: FieldKind = FieldKind.TEXT,
    required: bool = True,
    default: object | None = None,
    help: str | None = None,
    placeholder: str | None = None,
    choices: tuple[ChoiceOption, ...] = (),
    minimum: Decimal | int | None = None,
    maximum: Decimal | int | None = None,
    disabled: bool = False,
    read_only: bool = False,
    sensitive: bool = False,
    secret_clearable: bool = False,
    validator: Validator | None = None,
)

Declarative input field used by forms and headless tests.

choices class-attribute instance-attribute

choices: tuple[ChoiceOption, ...] = ()

default class-attribute instance-attribute

default: object | None = None

disabled class-attribute instance-attribute

disabled: bool = False

help class-attribute instance-attribute

help: str | None = None

key instance-attribute

key: str

kind class-attribute instance-attribute

kind: FieldKind = FieldKind.TEXT

label instance-attribute

label: str

masks_value property

masks_value: bool

maximum class-attribute instance-attribute

maximum: Decimal | int | None = None

minimum class-attribute instance-attribute

minimum: Decimal | int | None = None

placeholder class-attribute instance-attribute

placeholder: str | None = None

read_only class-attribute instance-attribute

read_only: bool = False

required class-attribute instance-attribute

required: bool = True

secret_clearable class-attribute instance-attribute

secret_clearable: bool = False

sensitive class-attribute instance-attribute

sensitive: bool = False

validator class-attribute instance-attribute

validator: Validator | None = field(
    default=None, compare=False, repr=False
)

parse

parse(raw: object) -> ParsedField

Parse one field value and return both real and presentation-safe values.

OperationPolicy

Bases: Protocol

blocked_reason

blocked_reason(
    action: ActionSpec,
    params: Mapping[str, object],
    active_jobs: Sequence[object],
) -> str | None

confirmation

confirmation(
    action: ActionSpec, params: Mapping[str, object]
) -> Confirmation | None

describe_effects

describe_effects(
    action: ActionSpec, params: Mapping[str, object]
) -> str

ParsedField dataclass

ParsedField(key: str, value: object, redacted: object)

key instance-attribute

key: str

redacted instance-attribute

redacted: object

value instance-attribute

value: object

ResultPresenter

Bases: Protocol

present

present(
    action: ActionSpec, result: object
) -> ActionOutcome

ValidationIssue dataclass

ValidationIssue(
    message: str,
    field_key: str | None = None,
    status: SemanticStatus = SemanticStatus.ERROR,
)

field_key class-attribute instance-attribute

field_key: str | None = None

message instance-attribute

message: str

status class-attribute instance-attribute

status: SemanticStatus = SemanticStatus.ERROR

run_action_sync

run_action_sync(
    action: ActionSpec,
    raw_params: Mapping[str, object] | None,
    cancellation: CancellationToken,
    *,
    presenter: ResultPresenter | None = None,
    action_id: str | None = None,
) -> ActionOutcome

Run an action synchronously for tests, demos, and simple quick actions.