Not for the autonomous nightly job — interactive, Opus-driven local spike (fast pyright feedback loop). Deliberately NOT labelled api-convergence.
Context
Follow-up to #393 (typed commands). Core typed commands (ADR 0015 / #388 decision 5), in scope for #393 autonomously, cover:
- Args:
[] | [DT1, DT2, …] (positional, known types)
- Returns:
None | DT (0015 L97)
There is no Command[Any, Any] — a statically-declared command has fully-known P/T; a driver that knows nothing statically builds the whole controller (commands included) at runtime. So this spike is not about a partially-typed command; it is purely about the keyword-arg spelling on an otherwise fully-known signature.
The spike
Keyword-argument commands are the hard part. coretl's sketch (0015 L91):
def fn_spec(named_arg: float) -> int: ...
if TYPE_CHECKING:
def command_spec(spec: Callable[P, T]) -> Command[P, T]: ...
# runtime equivalent TBD
kw_known = command_spec(fn_spec)
Prototype a spelling giving pyright-checked keyword args on a typed command, with a runtime that builds the Command. Ref: bluesky/ophyd-async#1138 (discussion r2965959411).
Resolved: no Command[Any, Any] needed
@Tom-Willemsen confirmed on #402 that SECoP devices are discovered entirely from an over-the-wire describe — you never statically know something is a command without also knowing its signature. There is no "known command, unknown args" middle case, so runtime Command[Any, Any] introspection is not a requirement. Fully-dynamic drivers build their commands programmatically at runtime (each with a concrete signature from the wire datainfo); statically-declared controllers get fully-known Command[P, T]. This spike therefore stands on its own merits — pyright-checked keyword args for statically-declared typed commands — rather than as an alternative to Any.
When / How
Non-blocking; best after #393 core lands so you prototype against the real Command[P, T]. Fresh Claude Code Opus session pointed at this issue, scratch branch, tight pyright loop. Fold back as a follow-up PR to refactor.
Not for the autonomous nightly job — interactive, Opus-driven local spike (fast pyright feedback loop). Deliberately NOT labelled
api-convergence.Context
Follow-up to #393 (typed commands). Core typed commands (ADR 0015 / #388 decision 5), in scope for #393 autonomously, cover:
[]|[DT1, DT2, …](positional, known types)None|DT(0015 L97)There is no
Command[Any, Any]— a statically-declared command has fully-knownP/T; a driver that knows nothing statically builds the whole controller (commands included) at runtime. So this spike is not about a partially-typed command; it is purely about the keyword-arg spelling on an otherwise fully-known signature.The spike
Keyword-argument commands are the hard part. coretl's sketch (0015 L91):
Prototype a spelling giving pyright-checked keyword args on a typed command, with a runtime that builds the
Command. Ref: bluesky/ophyd-async#1138 (discussion r2965959411).Resolved: no
Command[Any, Any]needed@Tom-Willemsen confirmed on #402 that SECoP devices are discovered entirely from an over-the-wire
describe— you never statically know something is a command without also knowing its signature. There is no "known command, unknown args" middle case, so runtimeCommand[Any, Any]introspection is not a requirement. Fully-dynamic drivers build their commands programmatically at runtime (each with a concrete signature from the wiredatainfo); statically-declared controllers get fully-knownCommand[P, T]. This spike therefore stands on its own merits — pyright-checked keyword args for statically-declared typed commands — rather than as an alternative toAny.When / How
Non-blocking; best after #393 core lands so you prototype against the real
Command[P, T]. Fresh Claude Code Opus session pointed at this issue, scratch branch, tightpyrightloop. Fold back as a follow-up PR torefactor.