Skip to content

feat: expose capability API 1.3 host services - #3693

Merged
SpicyMarinara merged 27 commits into
Pasta-Devs:stagingfrom
thetopham:release/hierarchical-maps-api-1.2-engine-2.3
Jul 16, 2026
Merged

SpicyMarinara merged 27 commits into
Pasta-Devs:stagingfrom
thetopham:release/hierarchical-maps-api-1.2-engine-2.3

Conversation

@thetopham

@thetopham thetopham commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

Linked issue

Closes #3690

Why this change

  • Engine staging exposes capability API 1.0, so it rejects downloadable packages that require the generic API 1.3 host contract.
  • Packages need safe access to Engine-owned persistence, history, resources, model routing, logging, and client contribution lifecycle without importing private Engine code.
  • Hierarchical Maps is the first consumer, but its implementation remains package-owned in Pasta-Devs/Marinara-Agents.

What changed

  • Expose capability API 1.3 with public package logging, language-model, normalized resource, route, persistence, definition-metadata, transaction, and history/checkpoint operations.
  • Add package-generic client-module loading, readiness, error, retry, contribution-host behavior, and feature-agent detail hosting.
  • Delegate spatial prompt/history compatibility calls through registered package services instead of passing Engine database objects into the package.
  • Preserve Engine ownership of storage integrity, chat/message/swipe/checkpoint transactions, provider credentials, package loading, shared contracts, and compatibility handling.
  • Keep Maps source, drafting, routes, movement/domain logic, prompt formatting, package UI, manifests, bundles, artifacts, and catalog entries out of Marinara Engine.

Validation

  • pnpm check passes locally
  • Container (Docker / Podman) built and ran without issue
  • Ran the app, clicked through the changes manually
  • Checked edge cases (light + dark mode, mobile viewport, empty states, error paths)
  • Above manual verification completed (describe below)
  • Read and followed CONTRIBUTING.md

Manual verification notes

  • Current merged-head validation at d1308698c:
    • pnpm check — passed.
    • pnpm regression:spatial — passed.
    • pnpm regression:prompt — passed.
    • git diff --check — passed.
    • Capability package lifecycle regression — passed.
    • Browser matrix — 25 passed, with 7 intentional mobile skips reserved for real-device sign-off.
  • Merged current staging (29f8b7d6e). The earlier chat settings conflict was resolved in favor of staging's package-owned settings placement; the server route resolution retains both API 1.3 game-state parsing and staging's speaker-tag cleanup. The latest staging sync merged without additional conflicts.
  • The validated API 1.3 implementation baseline 7d5c09975abfd28e7e5e6645ff3b0bdeef86e1d7 is merged with the CodeRabbit correctness fixes at current head d1308698c.
  • Earlier paired-candidate sign-off confirmed package readiness, visible retry recovery, uninstall/reinstall recovery, and unchanged definition/snapshot fingerprints.
  • Real-device host-layout failures remain tracked in [Issue]: Mobile Game controls are crowded, can't view CYOA choices #3691 and [Issue]: Hierarchical Maps mobile chrome and minimap editing affordance need recovery Marinara-Agents#51.

Docs and release impact

  • No docs changes needed
  • Updated docs (README / CONTRIBUTING / android/README / CHANGELOG) as needed
  • Version/release files updated (only if this PR includes a version bump)

This PR targets staging and does not directly prepare or publish a main release. The paired package work is Pasta-Devs/Marinara-Agents#50 and Pasta-Devs/Marinara-Agents#52.

UI evidence (if applicable)

No screenshots are attached. Engine supplies generic contribution hosts and package loading/recovery states; all Hierarchical Maps presentation belongs to Marinara Agents. Known real-device mobile issues are tracked separately in #3691 and Pasta-Devs/Marinara-Agents#51.

Summary by CodeRabbit

  • New Features

    • Added richer capability runtime support for logging, language models, resources, persistence, transactions, and spatial snapshots.
    • Improved capability loading and runtime error states with clearer messages and retry controls.
    • Added checkpoint snapshot preservation and safer restoration behavior.
    • Enhanced lorebook content in live prompt previews.
    • Improved spatial transition handling and map generation guidance.
  • Bug Fixes

    • Ensured chat and game-state timestamps remain correctly ordered.
    • Added support for restoring checkpoint messages as visible game-state anchors.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a681e916-b07b-48a4-a27e-7406d11f18ec

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change introduces Capability API 1.2 runtime contracts and server hosts, adds client capability loading and recovery states, persists checkpoint snapshots, expands prompt preview lore processing, improves map-generation guidance, and enforces timestamp and spatial-storage boundaries.

Changes

Capability API runtime

Layer / File(s) Summary
Runtime host contracts and server wiring
docs/development/optional-agent-packages.md, packages/shared/..., packages/server/src/services/capability-packages/..., scripts/regressions/capability-package-lifecycle.regression.ts
Capability API 1.2 contracts, runtime services, persistence/resource hosts, model resolution, compatibility checks, and lifecycle validation are added.
Client loading, failure, and retry flow
packages/client/src/hooks/use-capability-packages.ts, packages/client/src/components/capabilities/CapabilityElement.tsx, packages/client/src/components/{chat,game,layout}/*, e2e/core-flows.e2e.ts
Client module states, retry handling, runtime error events, view-specific failure UI, and pending transition props are implemented and exercised end to end.
Checkpoint snapshots and visible anchors
packages/server/src/db/schema/checkpoints.ts, packages/server/src/services/game/checkpoint.service.ts, packages/server/src/routes/{game,g enerate}*, packages/server/src/services/mari-db/mari-db.service.ts, scripts/regressions/spatial-context.regression.ts
Checkpoint snapshot payloads are stored and restored with chat validation; checkpoint restore messages become visible game-state anchors.
Prompt preview and map guidance
packages/server/src/routes/chats.routes.ts, packages/server/src/services/game/map.service.ts, scripts/regressions/prompt.regression.ts
Live previews process lorebooks for game, roleplay, and visual-novel modes, while node-map prompt guidance and regression assertions discourage repetitive star layouts.
Timestamp and spatial storage boundaries
packages/server/src/services/import/import-timestamps.ts, packages/server/src/services/storage/*, packages/server/src/services/spatial-context/*, scripts/regressions/spatial-context.regression.ts
Message and snapshot timestamps are made strictly increasing, and spatial service contracts no longer pass database handles into capability-owned providers.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant UI
  participant CapabilityElement
  participant ModuleLoader
  participant ClientPackage
  UI->>CapabilityElement: render capability
  CapabilityElement->>ModuleLoader: observe package module
  ModuleLoader->>ClientPackage: import custom element
  ClientPackage-->>CapabilityElement: dispatch runtime error
  CapabilityElement-->>UI: render stopped state
  UI->>CapabilityElement: select Try again
  CapabilityElement->>ModuleLoader: retry module attempt
  ModuleLoader-->>UI: render ready capability
Loading

Possibly related issues

  • Pasta-Devs/Marinara-Agents issue 50 — Defines the Capability API 1.2 runtime and persistence contract implemented by this change.

Possibly related PRs

Suggested labels: refactor

Suggested reviewers: spicymarinara

Poem

New hosts awaken, contracts align,
Snapshots endure in ordered time.
Maps branch wide, lorebooks flow,
Failed capabilities learn to grow.
Retry the spell—errors depart! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The map prompt wording and prompt regression updates go beyond the capability-host boundary work and drift into prompt-formatting changes. Move the map prompt/layout wording changes to the package repo or a separate PR focused on prompt formatting.
Docstring Coverage ⚠️ Warning Docstring coverage is 13.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ⚠️ Warning The title matches the main theme, but the API version is wrong: this PR exposes capability API 1.2 host services, not 1.3. Rename it to reflect capability API 1.2 host services, or use the exact version the PR actually introduces.
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes implement the 1.2 host boundary, safe model/resource/persistence/logging access, and client loading/retry behavior requested in #3690.
Description check ✅ Passed The description follows the template well and includes linked issue, why, what changed, validation, notes, and docs/release impact.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@SpicyMarinara

Copy link
Copy Markdown
Collaborator

Pookie, shouldn't this be pulled to Agents?

@SpicyMarinara

Copy link
Copy Markdown
Collaborator

Okay, all good, but not to main. Needs to be changed to staging.

@thetopham thetopham changed the title fix: release Maps capability API 1.2 on Engine 2.3.x feat: expose capability API 1.2 host services Jul 16, 2026
@thetopham
thetopham changed the base branch from main to staging July 16, 2026 15:04
@github-actions github-actions Bot added the feature New feature or enhancement label Jul 16, 2026
@SpicyMarinara SpicyMarinara self-assigned this Jul 16, 2026
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
gh pr view 3693 --repo Pasta-Devs/Marinara-Engine --json number,baseRefName,headRefName,url --jq '{number, baseRefName, headRefName, url}'

Length of output: 472


@SpicyMarinara The specimen is correctly configured: #3693 already targets staging, not main. No branch-target change is needed.

@thetopham
thetopham marked this pull request as draft July 16, 2026 15:08
@thetopham

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot added the refactor Tracks work against the Tauri/refactor branch label Jul 16, 2026
@thetopham
thetopham marked this pull request as ready for review July 16, 2026 15:33

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/server/src/services/spatial-context/owner-turn.ts (1)

63-66: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Remove vestigial _db parameters from the public interfaces.

Ah, fascinating! You have successfully excised the database dependency from the underlying capability providers. However, you have left these vestigial _db appendages dangling in the exported wrappers. While scientifically harmless for the moment, such evolutionary leftovers clutter our glorious specimen. If you find the resources for a minor operational procedure, consider amputating these unused parameters across the codebase to achieve absolute perfection!

  • packages/server/src/services/spatial-context/owner-turn.ts#L63-L66: Sever the _db parameter from the signature and update the upstream invocations.
  • packages/server/src/services/storage/spatial-context.storage.ts#L55-L56: Excise the unused _db argument from this storage factory.
  • packages/server/src/services/spatial-context/projection.ts#L46-L50: Remove the superfluous _db parameter from the projection resolution wrapper.
  • packages/server/src/services/spatial-context/state-resolution.ts#L46-L51: Amputate the unused _db: SpatialReadConnection parameter from this interface.
  • packages/server/src/services/spatial-context/state-resolution.ts#L63-L66: Perform the same excision for materializeAssistantSpatialState.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/server/src/services/spatial-context/owner-turn.ts` around lines 63 -
66, Remove the unused database parameters from the exported wrappers and update
all callers accordingly:
packages/server/src/services/spatial-context/owner-turn.ts lines 63-66
(commitSpatialOwnerTurn),
packages/server/src/services/storage/spatial-context.storage.ts lines 55-56
(storage factory), packages/server/src/services/spatial-context/projection.ts
lines 46-50 (projection resolution wrapper), and
packages/server/src/services/spatial-context/state-resolution.ts lines 46-51 and
63-66 (state-resolution interface and materializeAssistantSpatialState).
Preserve the existing provider, storage, projection, and state-materialization
behavior while eliminating the obsolete arguments throughout upstream
invocations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/server/src/routes/chats.routes.ts`:
- Around line 2312-2318: Normalize generationLorebookTokenBudget once near
generationTriggers using the resolver’s finite and non-negative validation.
Reuse that normalized budget when invoking each of the three lorebook-generation
paths, including both no-preset branches and the preset branch, so preset
selection does not alter the preview’s lore budget.

In
`@packages/server/src/services/capability-packages/capability-persistence.service.ts`:
- Around line 162-179: Make the composite operations in replaceBootstrap and
replaceAtAnchor atomic by wrapping each delete-and-store sequence in
db.transaction(...), returning the transaction result. Also wrap the message
creation and initial swipe creation flow around the methods at lines 208-234 in
a transaction, preserving operation order and existing behavior; nested
transactions are supported.

---

Nitpick comments:
In `@packages/server/src/services/spatial-context/owner-turn.ts`:
- Around line 63-66: Remove the unused database parameters from the exported
wrappers and update all callers accordingly:
packages/server/src/services/spatial-context/owner-turn.ts lines 63-66
(commitSpatialOwnerTurn),
packages/server/src/services/storage/spatial-context.storage.ts lines 55-56
(storage factory), packages/server/src/services/spatial-context/projection.ts
lines 46-50 (projection resolution wrapper), and
packages/server/src/services/spatial-context/state-resolution.ts lines 46-51 and
63-66 (state-resolution interface and materializeAssistantSpatialState).
Preserve the existing provider, storage, projection, and state-materialization
behavior while eliminating the obsolete arguments throughout upstream
invocations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 262be224-7432-4986-8fd6-44fa93b0b470

📥 Commits

Reviewing files that changed from the base of the PR and between 29f8b7d and 425e1c7.

📒 Files selected for processing (32)
  • docs/development/optional-agent-packages.md
  • e2e/core-flows.e2e.ts
  • packages/client/src/components/capabilities/CapabilityElement.tsx
  • packages/client/src/components/chat/ChatInput.tsx
  • packages/client/src/components/game/GameInput.tsx
  • packages/client/src/components/game/GameMap.tsx
  • packages/client/src/components/layout/AppShell.tsx
  • packages/client/src/hooks/use-capability-packages.ts
  • packages/server/src/db/schema/checkpoints.ts
  • packages/server/src/routes/chats.routes.ts
  • packages/server/src/routes/game.routes.ts
  • packages/server/src/routes/generate/generate-route-utils.ts
  • packages/server/src/services/capability-packages/capability-language-model.service.ts
  • packages/server/src/services/capability-packages/capability-module-runtime.service.ts
  • packages/server/src/services/capability-packages/capability-persistence.service.ts
  • packages/server/src/services/capability-packages/capability-resources.service.ts
  • packages/server/src/services/game/checkpoint.service.ts
  • packages/server/src/services/game/map.service.ts
  • packages/server/src/services/import/import-timestamps.ts
  • packages/server/src/services/mari-db/mari-db.service.ts
  • packages/server/src/services/spatial-context/owner-turn.ts
  • packages/server/src/services/spatial-context/projection.ts
  • packages/server/src/services/spatial-context/state-resolution.ts
  • packages/server/src/services/storage/chats.storage.ts
  • packages/server/src/services/storage/game-state.storage.ts
  • packages/server/src/services/storage/spatial-context.storage.ts
  • packages/shared/src/index.ts
  • packages/shared/src/schemas/capability-package.schema.ts
  • packages/shared/src/types/capability-runtime.ts
  • scripts/regressions/capability-package-lifecycle.regression.ts
  • scripts/regressions/prompt.regression.ts
  • scripts/regressions/spatial-context.regression.ts

Comment on lines +2312 to +2318
const generationTriggers = Array.from(new Set([chatMode, "chat"]));
const forcedLorebookEntryIds =
ownerSpatialProjection &&
(ownerSpatialProjection.ownerMode === chatMode ||
(ownerSpatialProjection.ownerMode === "roleplay" && chatMode === "visual_novel"))
? ownerSpatialProjection.lorebookEntryIds
: [];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

A curious inconsistency: normalize the lorebook budget once.

The no-preset branches ignore generationLorebookTokenBudget, while the preset branch accepts it without the resolver’s finite/non-negative validation. Compute one normalized budget near generationTriggers and pass it to all three paths; otherwise adding/removing a preset changes the preview’s lore content.

Proposed fix
 const generationTriggers = Array.from(new Set([chatMode, "chat"]));
+const lorebookTokenBudget = resolveLorebookTokenBudget({
+  lorebookTokenBudget:
+    chatMeta.lorebookTokenBudget ?? chatMeta.generationLorebookTokenBudget,
+});

-tokenBudget: resolveLorebookTokenBudget(chatMeta),
+tokenBudget: lorebookTokenBudget,

-tokenBudget: resolveLorebookTokenBudget(chatMeta),
+tokenBudget: lorebookTokenBudget,

-lorebookTokenBudget:
-  typeof (chatMeta.lorebookTokenBudget ?? chatMeta.generationLorebookTokenBudget) === "number"
-    ? ((chatMeta.lorebookTokenBudget ?? chatMeta.generationLorebookTokenBudget) as number)
-    : undefined,
+lorebookTokenBudget,

Also applies to: 2389-2389, 2426-2426, 2508-2511

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/server/src/routes/chats.routes.ts` around lines 2312 - 2318,
Normalize generationLorebookTokenBudget once near generationTriggers using the
resolver’s finite and non-negative validation. Reuse that normalized budget when
invoking each of the three lorebook-generation paths, including both no-preset
branches and the preset branch, so preset selection does not alter the preview’s
lore budget.

Comment on lines +162 to +179
async replaceBootstrap(input) {
await db
.delete(spatialContextSnapshots)
.where(and(eq(spatialContextSnapshots.chatId, input.chatId), eq(spatialContextSnapshots.messageId, "")));
return store.create(input);
},
async replaceAtAnchor(input) {
await db
.delete(spatialContextSnapshots)
.where(
and(
eq(spatialContextSnapshots.chatId, input.chatId),
eq(spatialContextSnapshots.messageId, input.messageId),
eq(spatialContextSnapshots.swipeIndex, input.swipeIndex),
),
);
return store.create(input);
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Make composite persistence operations atomic.

These methods are callable outside transaction(). An insertion failure after deletion can erase the prior spatial snapshot; a swipe insertion failure can leave an orphaned message. Wrap each complete operation in db.transaction(...)—nested transactions are already supported.

  • Lines 162-179: atomically delete and replace the snapshot.
  • Lines 208-234: atomically create the message and initial swipe.

Also applies to: 208-234

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/server/src/services/capability-packages/capability-persistence.service.ts`
around lines 162 - 179, Make the composite operations in replaceBootstrap and
replaceAtAnchor atomic by wrapping each delete-and-store sequence in
db.transaction(...), returning the transaction result. Also wrap the message
creation and initial swipe creation flow around the methods at lines 208-234 in
a transaction, preserving operation order and existing behavior; nested
transactions are supported.

@thetopham thetopham changed the title feat: expose capability API 1.2 host services feat: expose capability API 1.3 host services Jul 16, 2026
@thetopham
thetopham marked this pull request as draft July 16, 2026 16:13
@thetopham
thetopham marked this pull request as ready for review July 16, 2026 16:26
@SpicyMarinara
SpicyMarinara merged commit e74f4e6 into Pasta-Devs:staging Jul 16, 2026
6 checks passed
@thetopham
thetopham deleted the release/hierarchical-maps-api-1.2-engine-2.3 branch July 17, 2026 00:41
@thetopham thetopham self-assigned this Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Bug fix client docs feature New feature or enhancement refactor Tracks work against the Tauri/refactor branch server shared

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Issue]: Expose capability API 1.3 host services for downloadable packages

2 participants