MAP Commands -- Phase 4 — Implement Internal TypeScript MAP Command Layer
1. Summary (Required)
What is the enhancement?
Implement the internal TypeScript MAP command layer described by TypeScript MAP SDK — Implementation Specification as the authoritative implementation spec for this phase.
This phase delivers the full internal TS layer that sits between the public SDK and the Rust IPC boundary. It is responsible for:
- defining internal wire-facing TypeScript types aligned with the MAP Commands spec
- constructing structural MAP command objects
- constructing
MapIpcRequest
- attaching
request_id and RequestOptions
- invoking the single Tauri IPC entrypoint
- correlating and validating responses
- decoding
MapIpcResponse / MapResultWire
- exposing internal command-layer functions used by the public SDK in Phase 5
This phase must provide exactly one IPC boundary function:
invokeMapCommand(request: MapIpcRequest): Promise<MapIpcResponse>
This phase is internal infrastructure for the SDK. It does not define the public ergonomic SDK surface.
2. Problem Statement (Required)
Why is this needed?
We want a strict separation between:
- the internal TypeScript command layer: structural command construction, wire handling, transport, and result decoding
- the public TypeScript SDK layer: ergonomic developer-facing objects and methods
Without this separation, public SDK semantics, request metadata, wire envelopes, response decoding, and IPC invocation details become entangled.
This phase establishes the TypeScript-side adapter layer corresponding to the host adapter role in the MAP Commands architecture.
It also establishes the only TS-side transport path to:
3. Dependencies (Required)
Does this depend on other issues or features?
- Phase 3 single Tauri command exists:
dispatch_map_command
- The Rust command, wire, and runtime pipeline is available end-to-end
- MAP command and wire contracts are available to TypeScript in a form aligned with:
4. Proposed Solution (Required)
How would you solve it?
Create the internal TypeScript MAP command layer used by the public SDK in Phase 5.
This layer should include four responsibilities:
- internal structural and wire-facing TypeScript types
- transport boundary and IPC envelope handling
- internal command builders
- wire-result decoding and internal result mapping
A. Required transport boundary
Implement:
invokeMapCommand(request: MapIpcRequest): Promise<MapIpcResponse>
invokeMapCommand(request) must:
- accept a fully formed
MapIpcRequest
- call Tauri
invoke("dispatch_map_command", ...)
- return
MapIpcResponse on successful transport
- reject on transport or IPC failure
- perform request/response correlation: compare
response.request_id with request.request_id and reject with MalformedResponseError if they do not match
- fail clearly on other malformed or structurally invalid responses
invokeMapCommand must not:
- infer scope
- invent commands
- perform business logic
- batch commands
- hide multi-command orchestration
- implement runtime lifecycle policy
B. Internal wire-facing and structural types
Define the internal TS structures needed to mirror the current MAP Commands architecture, including equivalents in role to:
MapIpcRequest
MapIpcResponse
RequestOptions
MapCommandWire
SpaceCommandWire
TransactionCommandWire
TransactionActionWire
HolonCommandWire
HolonActionWire
ReadableHolonActionWire
WritableHolonActionWire
- result wire variants needed to decode
MapResultWire
These types must remain internal to the SDK package.
They must structurally align with the current Rust MAP Commands wire contract, including the JSON serialization format produced by serde.
C. Internal command builders
Implement internal command builder functions used by Phase 5 to perform one-command operations.
These functions must:
- choose the correct structural scope
- construct the matching internal command object
- attach required wire-layer identifiers such as
request_id, transaction identity, holon target, and RequestOptions
- wrap the command in
MapIpcRequest
- call
invokeMapCommand
- decode
MapIpcResponse
- return decoded, typed results (e.g.
TxId, HolonReferenceWire, string | null, number) rather than raw MapResultWire variants, so Phase 5 receives structured values it does not need to redispatch
This internal command layer should cover the command surface needed by the SDK implementation spec, including:
- public-SDK-backed commands
- internal-only command support needed for spec alignment
For this phase, dance() and query() should be supported in the internal layer for structural completeness, but they are not required to be exposed as public SDK APIs in Phase 5.
D. Request identity, options, result decoding, and error types
The internal layer must define and implement:
request_id generation and propagation behavior
RequestOptions attachment and defaulting behavior
- explicit default handling for:
snapshot_after
gesture_id
gesture_label
- total decoding over the
MapResultWire variants used by the internal command layer
- TypeScript error types — at minimum
TransportError, MalformedResponseError, and DomainError (or equivalent) — providing enough structure for tests to assert on failure kind without string-matching error messages
- clear distinction between:
- transport failure →
TransportError
- malformed response / adapter failure →
MalformedResponseError
- domain failure returned as
HolonError → DomainError
This layer owns wire-result decoding and internal result mapping.
It does not own public SDK ergonomics.
Constraints:
- no retries
- no hidden sequencing
- no transaction policy
- no lifecycle policy
- no local TS-side reference resolution
- no public SDK ergonomics
- no public export of wire or envelope types
This issue should treat map-ts-sdk-impl.md as the authoritative implementation source for this layer.
5. Scope and Impact (Required)
What does this impact?
- Adds the internal TypeScript command layer used by the public SDK
- Becomes the only TS-side integration point to MAP command IPC
- Establishes the only TS call site for
dispatch_map_command
- Defines the internal TypeScript boundary for:
- command construction
- request metadata attachment
- envelope handling
- transport invocation
- response correlation
- result decoding
This layer is internal SDK infrastructure, not the final public ergonomic API surface.
6. Testing Considerations (Required)
How will this enhancement be tested?
- Add a Rust test in
map_commands_wire that serializes representative MapIpcRequest and MapIpcResponse values to JSON and records the output as fixtures. These fixtures are the ground-truth contract for the TypeScript wire type definitions and guard against serde serialization format drift.
- Unit tests with mocked Tauri
invoke
- Tests for basic
MapIpcRequest / MapIpcResponse transport behavior
- Tests for
request_id generation and propagation behavior
- Tests for
RequestOptions attachment and defaulting behavior
- Tests for request/response correlation failure producing
MalformedResponseError
- Tests for malformed response failure behavior
- Tests for domain error decoding from
HolonError producing DomainError
- Tests for representative structural command construction across:
- Tests for representative result decoding across:
- transaction creation
- reference-returning commands
- scalar-returning commands
- collection/structure-returning commands
- void-returning commands
- Tests confirming the internal layer supports
dance and query internally even if they are not publicly exported by Phase 5
- Contract tests for representative wire request/response shapes
- Optional runtime schema validation tests if adopted
7. Definition of Done (Required)
When is this enhancement complete?
Optional Details (Expand if needed)
8. Alternatives Considered
-
Implement the public SDK directly over Tauri with no separate internal command layer
Rejected: couples public SDK ergonomics and future API evolution directly to wire and IPC concerns.
-
Treat this phase as only a raw invoke() helper with no supporting command builders or result decoders
Rejected: undershoots the current MAP Commands and TS SDK implementation specs, which require structural command construction, request metadata handling, and wire-result decoding at this layer.
-
Put result decoding in the public SDK layer
Rejected: would leak wire concerns upward and blur the boundary between internal adapter logic and public SDK ergonomics.
9. Risks or Concerns
- Type drift between Rust contracts and TS internal typings
- Serde JSON serialization format drift: Rust enums and newtypes serialize in specific formats (externally-tagged enums, transparent newtypes, etc.) that must be matched exactly in TypeScript; a mismatch produces silently incorrect wire data
- Drift between the internal TS command layer and the MAP Commands spec
- Accidental leakage of wire concerns into the public SDK layer
- Confusion between internal-only supported commands and publicly exported SDK methods
Mitigations:
- Rust JSON fixture test in
map_commands_wire establishes the serialization contract
- Keep this issue aligned to
map-ts-sdk-impl.md
- Keep internal command/wire typings structurally aligned to
commands.md
- Confine wire-facing and envelope-facing types to the internal layer
- Make public exports a separate Phase 5 concern
- Verify in tests that internal support does not imply public export
10. Additional Context
This phase is intentionally internal and structural.
It includes:
- wire-facing TypeScript types
- transport boundary implementation
- internal command construction
- request metadata handling
- response validation and decoding
Public SDK ergonomics belong in Phase 5.
Phase 5 should build on this layer rather than reconstructing envelopes, calling Tauri directly, or decoding raw wire results itself.
MAP Commands -- Phase 4 — Implement Internal TypeScript MAP Command Layer
1. Summary (Required)
What is the enhancement?
Implement the internal TypeScript MAP command layer described by TypeScript MAP SDK — Implementation Specification as the authoritative implementation spec for this phase.
This phase delivers the full internal TS layer that sits between the public SDK and the Rust IPC boundary. It is responsible for:
MapIpcRequestrequest_idandRequestOptionsMapIpcResponse/MapResultWireThis phase must provide exactly one IPC boundary function:
invokeMapCommand(request: MapIpcRequest): Promise<MapIpcResponse>This phase is internal infrastructure for the SDK. It does not define the public ergonomic SDK surface.
2. Problem Statement (Required)
Why is this needed?
We want a strict separation between:
Without this separation, public SDK semantics, request metadata, wire envelopes, response decoding, and IPC invocation details become entangled.
This phase establishes the TypeScript-side adapter layer corresponding to the host adapter role in the MAP Commands architecture.
It also establishes the only TS-side transport path to:
dispatch_map_command3. Dependencies (Required)
Does this depend on other issues or features?
dispatch_map_command4. Proposed Solution (Required)
How would you solve it?
Create the internal TypeScript MAP command layer used by the public SDK in Phase 5.
This layer should include four responsibilities:
A. Required transport boundary
Implement:
invokeMapCommand(request: MapIpcRequest): Promise<MapIpcResponse>invokeMapCommand(request)must:MapIpcRequestinvoke("dispatch_map_command", ...)MapIpcResponseon successful transportresponse.request_idwithrequest.request_idand reject withMalformedResponseErrorif they do not matchinvokeMapCommandmust not:B. Internal wire-facing and structural types
Define the internal TS structures needed to mirror the current MAP Commands architecture, including equivalents in role to:
MapIpcRequestMapIpcResponseRequestOptionsMapCommandWireSpaceCommandWireTransactionCommandWireTransactionActionWireHolonCommandWireHolonActionWireReadableHolonActionWireWritableHolonActionWireMapResultWireThese types must remain internal to the SDK package.
They must structurally align with the current Rust MAP Commands wire contract, including the JSON serialization format produced by serde.
C. Internal command builders
Implement internal command builder functions used by Phase 5 to perform one-command operations.
These functions must:
request_id, transaction identity, holon target, andRequestOptionsMapIpcRequestinvokeMapCommandMapIpcResponseTxId,HolonReferenceWire,string | null,number) rather than rawMapResultWirevariants, so Phase 5 receives structured values it does not need to redispatchThis internal command layer should cover the command surface needed by the SDK implementation spec, including:
For this phase,
dance()andquery()should be supported in the internal layer for structural completeness, but they are not required to be exposed as public SDK APIs in Phase 5.D. Request identity, options, result decoding, and error types
The internal layer must define and implement:
request_idgeneration and propagation behaviorRequestOptionsattachment and defaulting behaviorsnapshot_aftergesture_idgesture_labelMapResultWirevariants used by the internal command layerTransportError,MalformedResponseError, andDomainError(or equivalent) — providing enough structure for tests to assert on failure kind without string-matching error messagesTransportErrorMalformedResponseErrorHolonError→DomainErrorThis layer owns wire-result decoding and internal result mapping.
It does not own public SDK ergonomics.
Constraints:
This issue should treat map-ts-sdk-impl.md as the authoritative implementation source for this layer.
5. Scope and Impact (Required)
What does this impact?
dispatch_map_commandThis layer is internal SDK infrastructure, not the final public ergonomic API surface.
6. Testing Considerations (Required)
How will this enhancement be tested?
map_commands_wirethat serializes representativeMapIpcRequestandMapIpcResponsevalues to JSON and records the output as fixtures. These fixtures are the ground-truth contract for the TypeScript wire type definitions and guard against serde serialization format drift.invokeMapIpcRequest/MapIpcResponsetransport behaviorrequest_idgeneration and propagation behaviorRequestOptionsattachment and defaulting behaviorMalformedResponseErrorHolonErrorproducingDomainErrorSpaceTransactionHolondanceandqueryinternally even if they are not publicly exported by Phase 57. Definition of Done (Required)
When is this enhancement complete?
invokeMapCommand(request: MapIpcRequest): Promise<MapIpcResponse>existsdispatch_map_commandMalformedResponseErroron mismatchrequest_idandRequestOptionshandling are implementedTransportError,MalformedResponseError,DomainError) are defined and usedMapResultWiredanceandqueryare supported internally as part of the structural/internal command layermap_commands_wireOptional Details (Expand if needed)
8. Alternatives Considered
Implement the public SDK directly over Tauri with no separate internal command layer
Rejected: couples public SDK ergonomics and future API evolution directly to wire and IPC concerns.
Treat this phase as only a raw
invoke()helper with no supporting command builders or result decodersRejected: undershoots the current MAP Commands and TS SDK implementation specs, which require structural command construction, request metadata handling, and wire-result decoding at this layer.
Put result decoding in the public SDK layer
Rejected: would leak wire concerns upward and blur the boundary between internal adapter logic and public SDK ergonomics.
9. Risks or Concerns
Mitigations:
map_commands_wireestablishes the serialization contractmap-ts-sdk-impl.mdcommands.md10. Additional Context
This phase is intentionally internal and structural.
It includes:
Public SDK ergonomics belong in Phase 5.
Phase 5 should build on this layer rather than reconstructing envelopes, calling Tauri directly, or decoding raw wire results itself.