Skip to content

Type Command by its owners' context and result; drop remaining dead Any - #2762

Merged
trissim merged 8 commits into
mainfrom
next/remaining-explicit-types
Oct 23, 2026
Merged

trissim merged 8 commits into
mainfrom
next/remaining-explicit-types

Conversation

@trissim

@trissim trissim commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Removes the explicit Any from the Command contract and the metadata ratchet. Each Any is replaced by the type its owner already declares.

What changed

Command (command.py): apply(self, ctx: Any) -> Any is now Command[Context, Result] with apply(self, ctx: Context) -> Result. Each root binds what its members already declare:

Root Context -> Result
RuntimeRequest (runtime_requests.py:70) RuntimeRequestContext -> Awaitable[None]
TargetEdit (cli_commands.py:458) Comms -> CliResult
CliExecution[Answer] / CliCommand[Answer] (cli_commands.py:749, :801) Comms -> Answer, the family's own type parameter
ConnectorVerb (connector.py:835) ConnectorStore -> int | str
RelationshipEdit (relationships.py:596) RelationshipEditContext -> tuple[RelationshipDocument, Collaboration | None]; its three apply overrides now declare it
GoalAction[Result] (goal_actions.py:116) GoalActionContext -> Result
TodoCommand (todos.py:2743) Todo -> Todo
NativePackageVerb (cli_native_package.py:26) None -> None

Dead imports: unused Any imports removed from session_lifecycle.py and queued_input.py.

Metadata ratchet (tools/debt_ratchet.py:419-425): reads the real MemberDescriptorType with inspect.getattr_static instead of casting dataclasses.Field through Any.

Counts

rg -n '\bAny\b' src: 68 lines before, 64 after. Python code uses: 42 before, 38 after.

Verified

  • All touched modules import under the project venv with this worktree's src first.
  • get_original_bases shows each root's binding.
  • CliCommand.result_type() resolves for the same 14 commands and refuses the same 74 as main.

Found, not fixed here

Two CliCommand members already break the family's Answer: CliResult bound:

  • cli_commands.py:1412 WatchCliCommand.apply returns AsyncIterator[Message]
  • tools.py:1732 InvokeCliCommand.apply returns dict[str, JsonValue]

Every remaining Any site (file:line) and the unannotated-parameter scan (1673 parameters in 186 files) are owned by draft #2774.

🤖 Generated with Claude Code

@trissim

trissim commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Handoff at ca35aa2 on next/remaining-explicit-types. Main including merged #2764 is merged and pushed; no uncommitted edits remain. The implemented change removes the Any cast around dataclasses.Field.metadata in tools/debt_ratchet.py:420-425, using the actual descriptor via inspect.getattr_static. No further family correction has been implemented.

Remaining inventory at this head: physical src tree has 42 Any uses, including one audit-test fixture; tools has 1. The remaining families are: publication clients (acp.py:294; input_drain.py:605,612,617; transcript_updates.py:32,39; runtime.py:254); native task result ownership (backend.py:267; runtime.py:217 twice; turn_runner.py:99,300,331); Command context/result (command.py:17 twice); launch forwarding (child_process.py:1871); dispatch handlers (mro_dispatch.py:8,34,39,58,62); metaclass SDK namespace/options (declared_family.py:34,38); retained registry fields (registry_document.py:508); FieldCodec decoder generics and Any sentinels (field_codec.py:430,1473,1486,1490,1491,2089,2169,2245,2295,2312,2439,2459,2515,2560,2587,2733,2795); the runtime typing.Any comparison (tools/debt_ratchet.py:1864). No parse omissions were found. Check the current open PR file ownership before editing: #2763 holds field_codec.py; #2765 holds native_pi.py/locked_store.py and installer file ownership. The annotation batch exclusions remain in order-busdel-any2.md.

Exact next edit: begin the missing publication receiver contract at controller.py:21, then migrate SocketClient (runtime.py:75), RuntimeServer (runtime.py:201), and all publication consumers listed above together. Source investigation: ACP SDK owns the full typed SessionNotification record (acp/schema.py:5599); its session_update method manually declares a 13-member external union (acp/agent/connection.py:109-130). Do not copy that union or replace the clients with BaseModel/object/Protocol. Choose a contract consuming the existing SessionNotification, using the inherited ACP connection and existing SDK notification API, and migrate the complete family; no source patch for that shape exists yet. RuntimeServer publication binding is also erased by an object sentinel at runtime.py:67 and _expected_client at :254; working_memory_worker.py:37-39 is its sole bound publisher. Preserve its client/thread/socket checks rather than narrowing the annotation dishonestly. If that coherent publication edit conflicts with an active owner, Command is the independent next family: AST found direct roots in runtime_requests.py:70, cli_commands.py:458/749, connector.py:835, relationships.py:596, goal_actions.py:116, todos.py:2743, cli_native_package.py:26. Parameterize the existing Command contract with each real context/result and migrate every root, rather than hiding Any.

Run no tests: the review fork owns testing under the latest order. The carry deletion is a separate pending order: only after the commander confirms install 22 applied it on the live bus, open a fresh-main PR deleting tools/cutover/carry_selected_tool_slots.py and its tests. That confirmation has not arrived; leave the carry untouched until then.

Ratchet test and others added 3 commits October 23, 2026 08:57
Command.apply took `ctx: Any -> Any`, so every command family's context and
result lived only in the subclass overrides and the base contract said nothing.
Command is now generic over Context and Result, and each root binds the types
its members already declare:

- RuntimeRequest: RuntimeRequestContext -> Awaitable[None]
- TargetEdit: Comms -> CliResult
- CliExecution/CliCommand: Comms -> Answer, the family's own type parameter,
  so a command's declared answer is also its Command result
- ConnectorVerb: ConnectorStore -> int | str
- RelationshipEdit: RelationshipEditContext ->
  tuple[RelationshipDocument, Collaboration | None]; its three apply
  overrides now say so instead of returning unannotated
- GoalAction[Result]: GoalActionContext -> Result
- TodoCommand: Todo -> Todo
- NativePackageVerb: None -> None

Also drops the unused Any imports in session_lifecycle.py and queued_input.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@trissim trissim changed the title Remove remaining explicit Any through declared owners Type Command by its owners' context and result; drop remaining dead Any Oct 23, 2026
@trissim
trissim marked this pull request as ready for review October 23, 2026 13:04
Copilot AI balanced review requested due to automatic review settings October 23, 2026 13:04

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@github-actions

Copy link
Copy Markdown

debt-tools at e2b743b, every finding:

grew StringIdentity:src/agent_comms/todos.py +2

@github-actions

Copy link
Copy Markdown

debt-src at e2b743b, every finding:

grew LintFindings:src/agent_comms/relationships.py +3
grew LintFindings:src/agent_comms/runtime_requests.py +1
grew NoneAbsence:src/agent_comms/relationships.py +4
grew StringIdentity:src/agent_comms/todos.py +2
introduced NoneAbsence:src/agent_comms/relationships.py at lines [597, 607, 611, 638]

Ratchet test and others added 2 commits October 23, 2026 09:10
debt-src caught the first cut restating facts:

- RelationshipEdit bound `Collaboration | None` as every member's result,
  which is the union of two members' answers written on the parent. Retaining
  edits always publish a Collaboration; removal always answers None. The
  family is now generic in its result, like GoalAction, and each branch binds
  its own. The abstract apply that restated Command's is deleted.
- TodoCommand spelled Todo as "Todo" strings. Todo stores these commands, so
  it must be declared after them; a PEP 695 alias reads it lazily instead of
  binding by spelling.
- The RuntimeRequest header is wrapped to the line limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@trissim
trissim merged commit f6fad69 into main Oct 23, 2026
6 of 8 checks passed
trissim pushed a commit that referenced this pull request Oct 23, 2026
upgrade() keeps main's command scope and completes an interrupted restore
first inside it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants