Skip to content

Campaign file export/import (BYO cloud) - #5

Merged
deepiq2022 merged 7 commits into
mainfrom
feat/campaign-files
Jun 11, 2026
Merged

Campaign file export/import (BYO cloud)#5
deepiq2022 merged 7 commits into
mainfrom
feat/campaign-files

Conversation

@deepiq2022

Copy link
Copy Markdown
Contributor

Export the active campaign to a JSON file and import one back via the system document picker — saving into a cloud-synced folder gives user-owned sync with zero server or network code.

  • Campaign file format: schemaVersion 1, app marker, savedAt, session name, the four store payloads. Import validates everything through the real model parsers — a malformed file is rejected with a readable error instead of bricking a session.
  • Import always creates a new session (no overwrite semantics); export serializes the active one.
  • file_picker ^11 (the one new dependency): saveFile-with-bytes covers Android/iOS/web/desktop; pickFiles(withData) for reading. Picker errors surface as snackbars; cancellations are no-ops.
  • Campaigns dialog gains Export/Import tiles.

Tests 38 → 44. Implements docs/superpowers/plans/2026-06-11-campaign-files.md.

🤖 Generated with Claude Code

jttaylor63 and others added 7 commits June 11, 2026 09:43
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rror

Also commits the regenerated macOS plugin registrant for file_picker.
@deepiq2022
deepiq2022 merged commit 6c4b69d into main Jun 11, 2026
1 check passed
@deepiq2022
deepiq2022 deleted the feat/campaign-files branch June 11, 2026 14:08
deepiq2022 added a commit that referenced this pull request Jun 21, 2026
…108)

At party scale a single oracle/dice result ("fireball hits the party",
"everyone heals d6") had to be scattered by hand across 3-5 character sheets.
Adds an "Effect" button to each roster group header (>1 member) that opens a
modal: a checkbox target list (default all), an HP ±N stepper, and a
condition multi-pick from kConditions. Apply broadcasts to the selected set.

- Character.withHpDelta(int): applies an HP delta to whichever pool the
  character uses — D&D/Shadowdark currentHp (clamped to maxHp) or the first
  track; no-pool sheets (Ironsworn/Starforged condition meters) unchanged.
- CharacterNotifier.applyPartyEffect(ids, {hpDelta, addConditions}): one
  persist over the roster, withHpDelta + set-union conditions for targets,
  others untouched.

Resolves audit item #5.

Tests: withHpDelta (dnd/shadowdark/track/no-pool + clamps); applyPartyEffect
(targeting, condition merge w/o dups, untargeted untouched); a roster UI flow
test (Effect button → damage + condition → both PCs updated). Full suite green
(1052), analyze clean.

Co-authored-by: John Taylor <jttaylor63@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
deepiq2022 added a commit that referenced this pull request Jun 21, 2026
After resolving an Ironsworn move, asking the oracle a quick yes/no is the
most common follow-up. Adds an "Ask oracle" quick-action to the move result
card (via the shared ResultAction slot) that rolls a 50/50 Fate Check and logs
it as a follow-up entry — without leaving the Moves screen.

Closes the remaining audit #1 per-caller result-card wirings. The other
enumerated wirings were assessed and intentionally not built (documented in the
audit doc): save-as-NPC is already covered (contextual Generate-NPC flow +
journal gen-npcs context-menu save); apply-damage/heal and mark-track have no
bound target on a free oracle/dice result (bulk damage is #5's party effect +
per-row HP editing; event-driven clock ticks are gap G5).

Tests: moves_screen_test drives expand → open move → Roll → Ask oracle and
asserts a fate-check entry is logged. Full suite green (1053), analyze clean.

Co-authored-by: John Taylor <jttaylor63@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
deepiq2022 added a commit that referenced this pull request Jun 22, 2026
The combatant row's live HP read-through only checked `char.tracks`, so a
linked D&D or Shadowdark combatant — whose HP lives in `dnd.currentHp` /
`shadowdark.currentHp`, not a track — showed NO HP and inert −/+ steppers in
the turn order. (Ad-hoc and Ironsworn/Starforged track-based combatants were
fine.) This was asymmetric with Character.withHpDelta (the #5 party-effect
helper), which already resolves the sheet pool first.

Now the row resolves HP from the D&D/Shadowdark sheet or the first track, and
the steppers drive damage/heal through Character.withHpDelta — so a D&D party's
combat HP is visible and editable from the encounter.

Found during a review pass over the deferred audit items; the rest of the
audit #10/#13 two-way sync (spell-slot/emulation display) stays deferred.

Tests: encounter_screen_test — a linked D&D combatant shows sheet HP and the
stepper writes back to dnd.currentHp. Full suite green (1068), analyze clean.

Co-authored-by: John Taylor <jttaylor63@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
deepiq2022 added a commit that referenced this pull request Jun 24, 2026
* docs(ai): spec LLM-ranked suggestion chips (AI expansion #5)

Co-Authored-By: Claude <noreply@anthropic.com>

* docs(ai): plan LLM-ranked suggestion chips (AI expansion #5)

Co-Authored-By: Claude <noreply@anthropic.com>

* feat(ai): rankSuggestions seam — RankSuggestionsSeed + buildRankPrompt + tolerant parse

Co-Authored-By: Claude <noreply@anthropic.com>

* feat(ai): rankSuggestions on InterpreterService (+ Gemma + fake)

Co-Authored-By: Claude <noreply@anthropic.com>

* feat(ai): applyRanking — reorder rule chips by RankResult (robust)

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor(ai): rank seam/core review fixups (strict id filter, dartdoc, test gaps)

Co-Authored-By: Claude <noreply@anthropic.com>

* feat(ai): LLM-rank the assistant rail chips + why caption (cached, rule fallback)

Co-Authored-By: Claude <noreply@anthropic.com>

* test(ai): assert collapsed rail does not call the LLM

Co-Authored-By: Claude <noreply@anthropic.com>

* docs: note LLM-ranked suggestions in CLAUDE.md (AI expansion #5)

Co-Authored-By: Claude <noreply@anthropic.com>

* perf(ai): bound the rail rank cache to the most-recent signatures

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: John Taylor <jttaylor63@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
deepiq2022 added a commit that referenced this pull request Jul 24, 2026
Records the shipped "Lamplit Tome" system — warm-only palette, serif for
fiction and sans for machinery, flat-by-default depth — as DESIGN.md plus an
.impeccable/design.json sidecar, and adds PRODUCT.md for the durable product
record. CLAUDE.md working rule #5 makes both binding.

Writing the doc against the source turned up drift the doc then had to fix.
The hero-card border was two near-identical literals (EFC9B4 / F0CDB8) at four
call sites with no dark value at all, so dark mode drew a pale peach ring
around a near-black card; it is now one JuiceTokens.borderHero with a real
dark twin. The campaign identity palette shipped Indigo and Plum, the only
cool values in the app's chrome — rewarmed to Mulberry and Umber, keeping five
identities separated by hue and value. Stock Material colors were doing
semantic work in five places (sketch toolbar, funnel, disposition, AI-ready
check, tally) and now read tokens. Modals were the largest surface still on
raw M3 defaults despite 60+ call sites, so sheets, dialogs and snackbars join
the tome, along with disabled/focus/hover state colors that M3 rendered gray.

test/design_system_test.dart makes six of the named rules mechanical rather
than aspirational: One Shadow, Warm-Only, Two-Voice, identity-spine warmth,
hero-border-is-a-token, and a ratchet pinning raw ColorScheme use at 131 so it
can only shrink. Card and chip theming stay deliberately unthemed — a global
override restyles hundreds of widgets for little gain, and the ratchet is the
mechanism for retiring that debt surface by surface.

Co-authored-by: John Taylor <jttaylor63@gmail.com>
Co-authored-by: Claude <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