Skip to content

Slice M3.2 - piggyback layer - #392

Merged
failerko merged 18 commits into
AventurasTeam:mainfrom
Pento95:feat/m3-2-piggyback-layer
Jul 23, 2026
Merged

Slice M3.2 - piggyback layer#392
failerko merged 18 commits into
AventurasTeam:mainfrom
Pento95:feat/m3-2-piggyback-layer

Conversation

@Pento95

@Pento95 Pento95 commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements Slice 3.2 — Piggyback layer (docs/implementation/milestones/03-memory-floor/slices/02-piggyback.md), providing the per-turn fast path of the memory cadence. The narrative model emits a tagged <state> block alongside prose, which is parsed and applied to entry metadata, entity states, and computed bookkeeping, with a synchronous per-turn fallback classifier when tagged blocks are unreliable or fail to parse.

Delivered Scope

  • Trailing-block parser (C2): Robust segment isolation for <state> blocks (sceneEntities, currentLocation, worldTimeDelta, visualChanges, transfers, summary) with jsonrepair fallback and bracketed placeholder substitution (c1, l1 -> entity UUIDs).
  • Prompt fragment: <state> emission instructions, staged-entity prompt framing, and calendar vocabulary (tier names, weekdays, eras) in per-turn prompt template.
  • Piggyback apply & narrow actions: Writes sceneEntities, currentLocationId, and worldTime delta to entry metadata; applies visual state updates and item/stackable transfers; filters out non-existent entity IDs to enforce "piggyback creates no rows" and prevent action rejection crashes.
  • Computed bookkeeping: Automates current_location_id tracking for characters in scene and lastSeenAt transitions upon scene exit.
  • Staged-to-active fast path: Auto-promotes staged entities when their ID is first emitted in <scene_entities>.
  • Capability gate & Fallback Classifier: Adds piggybackFallbackClassifierPhase to run a synchronous classifier pass when model capability is uncurated/unreliable or when trailing block parsing fails.
  • <summary> enrichment hand-off: Extracts optional trailing summary for next turn's Q2 structural digest.
  • UI Presentation: Updates EntryCard to strip raw <state> XML blocks from narrative text while providing a Globe header action icon to toggle an expandable preview of state metadata.

Test Plan

  • pnpm typecheck passed with 0 TypeScript errors.
  • Unit test suite for lib/piggyback/ (31/31 tests passing).
  • Pipeline integration tests for per-turn-piggyback (17/17 tests passing).
  • Fault scenario & error logging tests passing.
  • Runtime validation against SQLite DB: verified entry metadata, deltas, and entity tracking.

Summary by CodeRabbit

  • New Features

    • Added structured “world state” extraction with per-turn piggyback scene updates (entities, locations, world-time deltas, visual changes, item/stackable transfers), including a classifier-based fallback.
    • Updated per-turn prompts and context (staged characters, known locations, optional calendar vocabulary, piggyback firing controls).
    • Entry cards now support an optional, toggleable world-state panel.
  • Bug Fixes

    • Delta log now renders correct labels for additional delta sources.
    • Improved entity state patching/merge behavior and staged-promotion concurrency.
    • Updated Electron security policy to allow data:/blob: connections and refined spellcheck lint suppression.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a2ffbd9-4c76-48d4-bf84-b5744b3d4ec3

📥 Commits

Reviewing files that changed from the base of the PR and between 380f91b and 43c6e3f.

📒 Files selected for processing (5)
  • lib/pipeline/definitions/per-turn-piggyback.test.ts
  • lib/pipeline/definitions/per-turn-piggyback.ts
  • lib/prompts/bundled/per-turn.test.ts
  • lib/prompts/bundled/per-turn.ts
  • lib/prompts/bundled/piggyback-fallback-classifier.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • lib/prompts/bundled/piggyback-fallback-classifier.ts
  • lib/prompts/bundled/per-turn.ts
  • lib/pipeline/definitions/per-turn-piggyback.ts
  • lib/pipeline/definitions/per-turn-piggyback.test.ts

📝 Walkthrough

Walkthrough

This PR adds structured piggyback state emission and parsing, entity state-patch actions, per-turn classifier fallback handling, calendar-aware prompt context, expanded narrative prompts, and related UI, logging, schema, and test coverage.

Changes

Piggyback state pipeline

Layer / File(s) Summary
State block parsing and action construction
lib/piggyback/*, lib/db/story-entries/*
Adds typed state blocks, resilient parsing, placeholder substitution, world-time normalization, metadata inheritance, transfer handling, and entity action generation.
Entity state handlers and serialized promotion
lib/actions/entities/*, lib/actions/delta/*, lib/db/entities/*, lib/db/system/*, components/compounds/delta-log-row.tsx
Adds visual, inventory, stackable, location, and promotion actions with undo support; serializes concurrent promotions and registers new delta sources.
Per-turn piggyback and classifier fallback
lib/pipeline/definitions/*, lib/pipeline/runtime/*, lib/ai/*, lib/db/app-settings/*
Integrates state parsing into narrative phases, adds a capability-gated classifier fallback phase, exposes model capabilities, and expands pipeline diagnostics.
Generation context and prompt contracts
lib/calendar/*, lib/prompts/*
Adds calendar vocabulary, staged filtering, bracketed entity/location prompt sections, and the state-emission macro.
Entry presentation and supporting runtime behavior
components/compounds/entry-card.tsx, electron/main.ts, lib/spellcheck/*
Displays extracted world-state blocks separately, permits data/blob connections, and filters capitalization-only spelling diagnostics.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers: failerko

Poem

A rabbit hops through state-tagged prose,
With carrots for deltas wherever it goes.
It promotes the staged and tracks every turn,
While calendars glow and classifiers learn.
“Hop, hop!” says the rabbit, “the pipeline is bright!”

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: implementing the piggyback layer for this slice.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

@Pento95 Pento95 changed the title feat(piggyback): filter unknown entity IDs and display UI state toggle Slice M3.2 - feat(piggyback): filter unknown entity IDs and display UI state toggle Jul 22, 2026
@Pento95 Pento95 changed the title Slice M3.2 - feat(piggyback): filter unknown entity IDs and display UI state toggle feat(memory): Slice 3.2 — Piggyback layer, scene metadata & state updates Jul 22, 2026
@Pento95 Pento95 changed the title feat(memory): Slice 3.2 — Piggyback layer, scene metadata & state updates Slice M3.2 - piggyback layer Jul 22, 2026

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (4)
lib/piggyback/apply.test.ts (1)

452-482: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add assertions for item/stackable transfer filtering, not just visual changes.

This test exercises transfers.items/transfers.stackables with a non-existent from id, but only asserts on visualActions. Add assertions confirming the destination-side (char_kael) action is still correctly emitted while the non-existent from (Andrea) is safely dropped — this directly verifies the PR's stated invariant for transfers, not just visual changes.

✅ Proposed additional assertions
     const visualActions = result.actions.filter((a) => a.kind === 'updateEntityVisualState')
     expect(visualActions).toEqual([
       {
         kind: 'updateEntityVisualState',
         source: 'ai_classifier',
         payload: { branchId: 'main', id: 'char_kael', visual: { attire: 'leather jacket' } },
       },
     ])
+
+    const itemActions = result.actions.filter((a) => a.kind === 'updateEntityInventory')
+    expect(itemActions).toEqual([
+      {
+        kind: 'updateEntityInventory',
+        source: 'ai_classifier',
+        payload: { branchId: 'main', id: 'char_kael', equipped_items: [], inventory: ['item_blade'] },
+      },
+    ])
+
+    const stackableActions = result.actions.filter((a) => a.kind === 'updateEntityStackables')
+    expect(stackableActions).toEqual([
+      {
+        kind: 'updateEntityStackables',
+        source: 'ai_classifier',
+        payload: { branchId: 'main', id: 'char_kael', stackables: { coins: 5 } },
+      },
+    ])
🤖 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 `@lib/piggyback/apply.test.ts` around lines 452 - 482, Add assertions to the
existing buildPiggybackActions test for both item and stackable transfer
actions, verifying transfers targeting char_kael are emitted with the expected
payload while entries involving the non-existent from ID Andrea are omitted.
Keep the existing visualActions assertion and filter result.actions by the
transfer action symbols used by the implementation.
lib/actions/delta/apply-delta-action.ts (1)

26-35: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

inFlightByKey entries are never cleaned up.

Each unique promoteStagedEntity:${branchId}:${id} key stays in the map forever once used, even after its promise settles. Over a long-running session this grows unboundedly with the number of distinct entities ever promoted.

♻️ Proposed cleanup on settle
 function withKeyLock<T>(key: string, run: () => Promise<T>): Promise<T> {
   const settled = (inFlightByKey.get(key) ?? Promise.resolve()).then(run, run)
-  inFlightByKey.set(
-    key,
-    settled.catch(() => undefined),
-  )
+  const tracked = settled.catch(() => undefined)
+  inFlightByKey.set(key, tracked)
+  tracked.finally(() => {
+    // Only remove if no newer caller has queued on top of this entry.
+    if (inFlightByKey.get(key) === tracked) inFlightByKey.delete(key)
+  })
   return settled
 }
🤖 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 `@lib/actions/delta/apply-delta-action.ts` around lines 26 - 35, Update
withKeyLock so each inFlightByKey entry is removed after its associated promise
settles, but only when the map still points to that same promise; preserve
chaining so concurrent calls for a key remain serialized and rejected work does
not break later calls.
lib/pipeline/definitions/per-turn-piggyback.ts (2)

80-101: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Reroll branch has no test coverage.

generateClassifierState's reroll-on-negative-worldTimeDelta path isn't exercised by any test in per-turn-piggyback.test.ts (only success/failure-without-reroll paths are covered). Given this logic guards a documented invariant (never let a negative delta through without a second attempt), a test mocking two generateStructuredMock calls (first negative, second non-negative/failed) would give confidence this path works as intended.

🤖 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 `@lib/pipeline/definitions/per-turn-piggyback.ts` around lines 80 - 101, Add
tests in per-turn-piggyback.test.ts covering generateClassifierState’s reroll
path: mock generateStructuredMock to return an initial successful result with a
negative worldTimeDelta, then verify a second call occurs and that a
non-negative successful result is returned. Also cover a second-call failure and
verify the original negative result is retained.

150-160: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Failure logs drop error detail relative to the PR's stated logging goal.

Both warn calls here only log status (or the substitution field names) and omit any richer failure context (e.g. error kind/detail from the failed generateStructured result, or substitution failure reasons beyond field name). The PR objective states pipeline error logging was enhanced with explicit reason/errorKind/errorDetail fields "across relevant pipeline events" — these two log sites in the same cohort appear to have been missed.

♻️ Possible enrichment (adjust field names to match the actual result/failure shape)
   if (result.status !== 'ok') {
-    ctx.log.warn('classifier.piggyback_fallback_failed', { status: result.status })
+    ctx.log.warn('classifier.piggyback_fallback_failed', {
+      reason: result.status,
+      errorKind: 'kind' in result ? result.kind : undefined,
+      errorDetail: 'detail' in result ? result.detail : undefined,
+    })
     return { status: 'completed' }
   }

Please confirm the actual shape of a non-'ok' GenerateStructuredResult (and substitutePiggybackIds failure entries) to pick the right field names.

🤖 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 `@lib/pipeline/definitions/per-turn-piggyback.ts` around lines 150 - 160,
Enrich the warning logs in the fallback handling around substitutePiggybackIds
with the actual failure context. Inspect the non-ok GenerateStructuredResult
shape and substitution failure entries, then include their available
reason/errorKind/errorDetail or equivalent detail fields alongside status and
field names in classifier.piggyback_fallback_failed and
classifier.piggyback_fallback_parse_failed.
🤖 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.

Nitpick comments:
In `@lib/actions/delta/apply-delta-action.ts`:
- Around line 26-35: Update withKeyLock so each inFlightByKey entry is removed
after its associated promise settles, but only when the map still points to that
same promise; preserve chaining so concurrent calls for a key remain serialized
and rejected work does not break later calls.

In `@lib/piggyback/apply.test.ts`:
- Around line 452-482: Add assertions to the existing buildPiggybackActions test
for both item and stackable transfer actions, verifying transfers targeting
char_kael are emitted with the expected payload while entries involving the
non-existent from ID Andrea are omitted. Keep the existing visualActions
assertion and filter result.actions by the transfer action symbols used by the
implementation.

In `@lib/pipeline/definitions/per-turn-piggyback.ts`:
- Around line 80-101: Add tests in per-turn-piggyback.test.ts covering
generateClassifierState’s reroll path: mock generateStructuredMock to return an
initial successful result with a negative worldTimeDelta, then verify a second
call occurs and that a non-negative successful result is returned. Also cover a
second-call failure and verify the original negative result is retained.
- Around line 150-160: Enrich the warning logs in the fallback handling around
substitutePiggybackIds with the actual failure context. Inspect the non-ok
GenerateStructuredResult shape and substitution failure entries, then include
their available reason/errorKind/errorDetail or equivalent detail fields
alongside status and field names in classifier.piggyback_fallback_failed and
classifier.piggyback_fallback_parse_failed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e71cec24-12b2-4a6b-a3c0-ed01348eba2b

📥 Commits

Reviewing files that changed from the base of the PR and between d0bce3f and 07bbb09.

⛔ Files ignored due to path filters (6)
  • docs/architecture.md is excluded by !docs/**
  • docs/data-model.md is excluded by !docs/**
  • docs/implementation/milestones/03-memory-floor/slices/02-piggyback.md is excluded by !docs/**
  • docs/memory/piggyback.md is excluded by !docs/**
  • docs/parked.md is excluded by !docs/**
  • lib/prompts/bundled/__snapshots__/per-turn.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (57)
  • components/compounds/delta-log-row.tsx
  • components/compounds/entry-card.tsx
  • electron/main.ts
  • lib/actions/delta/apply-delta-action.ts
  • lib/actions/entities/register.ts
  • lib/actions/entities/state-patch-actions.test.ts
  • lib/actions/entities/state-patch-actions.ts
  • lib/actions/turns/submit-turn.test.ts
  • lib/actions/turns/submit-turn.ts
  • lib/actions/types.ts
  • lib/ai/generate.ts
  • lib/ai/index.ts
  • lib/ai/model-capabilities.test.ts
  • lib/ai/model-capabilities.ts
  • lib/calendar/index.ts
  • lib/calendar/vocabulary.test.ts
  • lib/calendar/vocabulary.ts
  • lib/db/app-settings/app-settings-schema.ts
  • lib/db/entities/entities-types.ts
  • lib/db/entities/entity-state-schema.test.ts
  • lib/db/entities/entity-state-schema.ts
  • lib/db/index.ts
  • lib/db/story-entries/entry-metadata.test.ts
  • lib/db/story-entries/entry-metadata.ts
  • lib/db/story-entries/inherited-metadata.test.ts
  • lib/db/story-entries/inherited-metadata.ts
  • lib/db/system/system.table.ts
  • lib/piggyback/apply.test.ts
  • lib/piggyback/apply.ts
  • lib/piggyback/index.ts
  • lib/piggyback/parse.test.ts
  • lib/piggyback/parse.ts
  • lib/piggyback/substitute.test.ts
  • lib/piggyback/substitute.ts
  • lib/piggyback/tags.ts
  • lib/piggyback/types.ts
  • lib/piggyback/world-time.test.ts
  • lib/piggyback/world-time.ts
  • lib/pipeline/definitions/generation-context.test.ts
  • lib/pipeline/definitions/generation-context.ts
  • lib/pipeline/definitions/per-turn-piggyback.test.ts
  • lib/pipeline/definitions/per-turn-piggyback.ts
  • lib/pipeline/definitions/per-turn.test.ts
  • lib/pipeline/definitions/per-turn.ts
  • lib/pipeline/runtime/orchestrator.ts
  • lib/prompts/bundled/index.ts
  • lib/prompts/bundled/per-turn.test.ts
  • lib/prompts/bundled/per-turn.ts
  • lib/prompts/bundled/state-emission.ts
  • lib/prompts/bundled/structural-floor.test.ts
  • lib/prompts/filters.test.ts
  • lib/prompts/filters.ts
  • lib/prompts/ids.ts
  • lib/prompts/templateContextMap.ts
  • lib/spellcheck/index.test.ts
  • lib/spellcheck/index.ts
  • lib/undo/index.ts

Pento added 2 commits July 22, 2026 18:32
…uard null lastSeenAt locationId

Preflight now receives storySettings so the piggyback resolver's when-predicate sees the
real piggybackMode; null locationId no longer produces a silently rejected lastSeenAt
delta; unguarded DB row destructure now throws a clear Error.
Comment thread components/compounds/delta-log-row.tsx
Comment thread lib/pipeline/definitions/per-turn-piggyback.ts Outdated
Comment thread lib/prompts/bundled/per-turn.ts Outdated
Comment thread lib/pipeline/definitions/per-turn.ts
Bracket-form and unresolved IDs now fail closed instead of leaking into entry metadata; the fallback classifier's prompt moves into lib/prompts/bundled behind buildGenerationContext like every other story prompt; the narrative prompt skips staged/locations/calendar/state-emission when the fallback will fire anyway; and direct tagged-block deltas get their own source (piggyback_tagged_block) instead of sharing ai_classifier with unrelated writes.

@coderabbitai coderabbitai Bot 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/actions/delta/apply-delta-action.ts (1)

41-49: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Serialize delta-position allocation per branch, not per entity.

The lock key includes payload.id, so concurrent promotions of different staged entities on the same branch still execute in parallel. Both can calculate the same MAX(logPosition) + 1; the unique (branchId, logPosition) index in lib/db/system/system.table.ts then causes one transaction to fail. Hold a branch-scoped lock around position allocation (or make allocation atomic in SQLite).

🤖 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 `@lib/actions/delta/apply-delta-action.ts` around lines 41 - 49, Update
applyDeltaAction so promoteStagedEntity operations use a lock key scoped only to
action.payload.branchId, removing action.payload.id from the withKeyLock key.
Keep the lock around applyDeltaActionUnlocked to serialize log-position
allocation for all promotions on the same branch while preserving parallelism
across different branches.
🤖 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.

Outside diff comments:
In `@lib/actions/delta/apply-delta-action.ts`:
- Around line 41-49: Update applyDeltaAction so promoteStagedEntity operations
use a lock key scoped only to action.payload.branchId, removing
action.payload.id from the withKeyLock key. Keep the lock around
applyDeltaActionUnlocked to serialize log-position allocation for all promotions
on the same branch while preserving parallelism across different branches.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6482e585-31e3-4953-9c80-95e4b869373e

📥 Commits

Reviewing files that changed from the base of the PR and between cdfbda8 and 83af30d.

⛔ Files ignored due to path filters (5)
  • docs/data-model.md is excluded by !docs/**
  • docs/memory/classifier.md is excluded by !docs/**
  • docs/memory/piggyback.md is excluded by !docs/**
  • docs/ui/patterns/delta-log-row.md is excluded by !docs/**
  • lib/prompts/bundled/__snapshots__/per-turn.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (20)
  • components/compounds/delta-log-row.tsx
  • lib/actions/delta/apply-delta-action.ts
  • lib/actions/types.ts
  • lib/db/system/system.table.ts
  • lib/piggyback/apply.ts
  • lib/piggyback/substitute.test.ts
  • lib/piggyback/substitute.ts
  • lib/pipeline/definitions/generation-context.ts
  • lib/pipeline/definitions/per-turn-piggyback.test.ts
  • lib/pipeline/definitions/per-turn-piggyback.ts
  • lib/pipeline/definitions/per-turn.test.ts
  • lib/pipeline/definitions/per-turn.ts
  • lib/pipeline/runtime/orchestrator.ts
  • lib/prompts/bundled/index.ts
  • lib/prompts/bundled/per-turn.test.ts
  • lib/prompts/bundled/per-turn.ts
  • lib/prompts/bundled/piggyback-fallback-classifier.ts
  • lib/prompts/bundled/state-emission.ts
  • lib/prompts/ids.ts
  • lib/prompts/templateContextMap.ts
🚧 Files skipped from review as they are similar to previous changes (10)
  • lib/actions/types.ts
  • lib/prompts/bundled/index.ts
  • lib/prompts/bundled/state-emission.ts
  • lib/pipeline/runtime/orchestrator.ts
  • lib/pipeline/definitions/per-turn.ts
  • lib/prompts/bundled/per-turn.ts
  • lib/pipeline/definitions/per-turn.test.ts
  • lib/pipeline/definitions/per-turn-piggyback.ts
  • lib/pipeline/definitions/per-turn-piggyback.test.ts
  • lib/piggyback/apply.ts

…iting

Visual/inventory/stackable piggyback actions only checked that a referenced
id existed, not that it belonged to a character — a location/item/faction id
could get character-only state fields merged onto it unvalidated. The direct
tagged-block path also skipped type-enum validation the fallback classifier's
zod schema already enforced, letting an arbitrary key pollute state.visual.
Both paths now share one VISUAL_CHANGE_TYPES source of truth.
@Pento95
Pento95 requested a review from failerko July 23, 2026 12:15
Comment thread lib/pipeline/definitions/per-turn-piggyback.ts
Comment thread lib/pipeline/definitions/per-turn-piggyback.ts Outdated
Comment thread lib/prompts/bundled/per-turn.ts Outdated
Pento added 2 commits July 23, 2026 17:30
…sifier

The fallback classifier only saw the AI's reply, missing state
changes described in the user's own action. It also allocated a
fresh IdBiMap instead of the one the narrative phase already stored
on ctx.intermediates, renumbering placeholders mid-turn for no
reason.
Fix 3 had gated the whole staged/locations/calendar block behind
piggybackFires, but the narrative model still needs that info to
write consistently (e.g. introducing a staged character) even when
the fallback classifier will do the extraction afterwards. Only the
bracketed IDs and the ID-usage instructions tied to the tagged-block
output are piggyback-only now.
@failerko
failerko merged commit ae48d45 into AventurasTeam:main Jul 23, 2026
3 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jul 31, 2026
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.

Slice 3.2 — Piggyback layer: trailing block, scene metadata, computed bookkeeping

2 participants