Below is a first-pass design document for the small commands layer, written for humans, not the compiler. It is intentionally concrete but language-agnostic enough that we can still tweak it before coding.


1. Goals and scope

The commands layer sits between:

Its responsibilities:

  1. Accept command requests as JSON structures, regardless of origin.
  2. Perform sanity checks and rule checks (including dice rolls, modifiers, resource pre-checks).
  3. Decide whether the command is:
  4. Optionally schedule commands (and “macro” commands) into a command queue for future execution.
  5. Persist:

The commands layer does not:


2. Command lifecycle overview

2.1 Sources of commands

Commands can originate from:

All of these flow through the same commands layer; the origin is recorded in metadata and can influence permissions but not core structure.

2.2 Processing stages

For each incoming JSON command request:

  1. Ingress & parsing
  2. Static validation
  3. Rule evaluation & dice
  4. Enqueueing
  5. Response
  6. Persistence

3. Command data model

3.1 CommandRequest (input)

A CommandRequest is the normalized, in-memory representation of what the caller asked for.

Key fields (conceptual):

Constraints:

3.2 Command (internal)

We may distinguish:

A Command object could be:

JSON persistence of Command remains straightforward; this supports crash recovery and debugging.

3.3 CommandResult (output)

Represents what the server decided about a command and is sent back to callers.

Fields:

This object is also kept JSON-friendly so it can be persisted in Mongo for audit and replay.[6]


4. Command handling architecture

4.1 CommandHandler interface

Define a polymorphic handler abstraction, but keep it small:

Handlers do not:

4.2 Registry/dispatcher

A central CommandDispatcher:

This ensures extensibility:

No need to modify every caller.


5. Command queue and scheduling

In the “small layer” design, we do not create a new clock or independent loop. We keep a minimal CommandQueue that:

Key design ideas:

5.1 Queue structure

Conceptual fields per queued item:

The queue itself is:

This is incremental: we can start without macros and only add the macroState aspects once needed.


6. Command macros

Macros are commands that expand into sequences or trees of other commands.

Examples:

Design decisions:

Important constraint: macros should still have a single CommandResult visible to the caller, summarizing success/failure and key timings.


7. Persistence strategy

We already have Mongo infrastructure. The commands layer should use it to persist:[6]

7.1 Collections

  1. commands_requests
  2. commands_results
  3. commands_queue (optional at first)

The galaxy state (entities, vessels, resources, crew, sectors) and the simulation time are persisted via your core layer’s mechanisms as you already plan.[7][8][9][2][3][4][1]

7.2 Crash and restart

On restart:

This design assumes that SimEvents themselves are either:


8. Integration with existing core

Key integration points:

This keeps OO boundaries clear:


9. Open design questions

Before we move to code, I’d like your preferences on a few points:

  1. Macro complexity, phase 1
  2. Where should the command queue live?
  3. Command schema style
  4. Permission model / originType

Once we settle these, we can:

Sources [1] controller.d https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/attachments/15197330/30070de6-50df-460f-b02c-2a9cd68e6c9a/controller.d [2] crew.d https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/attachments/15197330/794663ff-d875-49a3-a1c1-ce265991ed36/crew.d [3] location.d https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/attachments/15197330/80ddf50c-7272-434d-bd62-ef1664b18fda/location.d [4] resource.d https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/attachments/15197330/4fccda02-b426-497f-a2a7-e2bc96f6880e/resource.d [5] system.d https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/attachments/15197330/61f75032-a0aa-4045-a886-95657f8543fa/system.d [6] mongoClient.d https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/attachments/15197330/28aa99b4-3c99-4894-ad79-71638b111e61/mongoClient.d [7] entity.d https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/attachments/15197330/8ed0db1a-fa9b-43b9-aa4f-a2ec4f274a42/entity.d [8] vessel.d https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/attachments/15197330/1ad364aa-3c6e-4e56-bcc1-fccc120f24f0/vessel.d [9] sector.d https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/attachments/15197330/78c63c35-c826-4c97-83c6-64e677f23f9b/sector.d [10] singleShipAgent.md https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/collection_06cc074f-93d4-4c2f-adcf-a637e908c6ce/4b377787-43a1-44a0-b4e2-2749e13f8588/singleShipAgent.md [11] dub.selections.json https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/collection_06cc074f-93d4-4c2f-adcf-a637e908c6ce/2c693b58-f401-467f-a3ce-6f059f6d6234/dub.selections.json [12] dub.json https://ppl-ai-file-upload.s3.amazonaws.com/web/direct-files/collection_06cc074f-93d4-4c2f-adcf-a637e908c6ce/085c0316-6f7d-44f9-aa11-4cab94022ee6/dub.json