Skip to content

deck: the inspector's states, read from the model - #507

Merged
ymote merged 1 commit into
mainfrom
feat/deck-inspector-states
Oct 11, 2026
Merged

ymote merged 1 commit into
mainfrom
feat/deck-inspector-states

Conversation

@ymote

@ymote ymote commented Oct 11, 2026

Copy link
Copy Markdown
Contributor

Why

Quick Deck v2's inspector shows several states as off, or by name only, because the deck service doesn't report them yet: colour schemes come by name only, there's no current scheme or footer state, a box's anchor and autofit are missing, and so are a chart's and a table's options. This follows #503, as the maintainer saw on the approved sign-off page. It also picks up the reviewer's two nits on #503.

What

Every new value is read from the open document's model (deckcraft-model), read-only, beside the engine commands each method already runs. There is no new engine command and nothing is written.

  • deck.themes: color_schemes is now [{name, colors}], the engine's built-in colour schemes from deckcraft_model::theme::builtin_color_schemes, which design.themes names only. colors holds twelve hex colours in the engine's order (dk1, lt1, dk2, lt2, accent1 to accent6, hlink, folHlink), as each theme's colors already does.
  • deck.open and deck.state: these now report color_scheme and font_scheme, taken from the first master's theme (the master document.inspect reports theme from). They also report footer from the deck's header and footer settings, in the keys deck.design {footer} takes. deck.state also gains theme. All four sit in deck.state as well as deck.open, so the inspector can follow an undo or a redo without reopening.
  • deck.format_state: now reports anchor and autofit as the box draws them, through resolve::body: the box's own setting, else what its layout and master placeholders give, else the engine's defaults. Values are in deck.format's words.
  • deck.slide: a chart's summary gains legend, data_labels, gridlines and palette, and a table's gains options, in the keys deck.chart and deck.table {op: "options"} take. slide.inspect leaves these out.
  • Review nit (a): the_guards_reader_reads_as_open_presentation now includes a package that repair visibly changes. Its slide is 5,000 points wide: the package reader keeps that (it takes up to 20,000), and repair narrows it to 4,000. With repair dropped from engine_read, the test fails (tried on the build host, then restored).
  • Review nit (b): an Office package whose main part is a document or a workbook (.docx, .xlsx) is now unsupported:, not damaged:. That covers files written by Office or laid out as LibreOffice writes them. The mapping sits in read_guarded's error mapping, beside "not a presentation DeckCraft can read".
  • apps/AGENTS.md: one sentence on where the inspector's states come from.

Contract additions for SERVICE.md

These are written here for the coordinator to carry into SERVICE.md after #506. This PR changes neither SERVICE.md nor apps/quickdeck/.

Method New field Type Example
deck.themes color_schemes (was [name]) [{name: string, colors: [12 × "#RRGGBB"]}], colours in dk1, lt1, dk2, lt2, accent1–6, hlink, folHlink order {"name": "Ocean", "colors": ["#000000", "#FFFFFF", "#13293D", "#E8F1F2", "#006494", "#247BA0", "#1B98E0", "#6CC1E8", "#13293D", "#0B3954", "#1B98E0", "#6CC1E8"]}
deck.open, deck.state color_scheme, font_scheme string (the first master's theme), or null with no master "color_scheme": "Ocean", "font_scheme": "Classic"
deck.open, deck.state footer {slide_numbers: bool, footer: bool, footer_text: string, date: bool, hide_on_title: bool}, the keys deck.design {footer} takes {"slide_numbers": true, "footer": true, "footer_text": "Board", "date": true, "hide_on_title": true}
deck.state theme string or null (as deck.open's) "theme": "DeckCraft"
deck.format_state anchor "top", "middle", "bottom" (deck.format's), or "justified", "distributed" from an imported deck "anchor": "top"
deck.format_state autofit "none", "shrink" or "resize" (deck.format's) "autofit": "shrink" (a body placeholder, from its master)
deck.slide, a chart's chart legend, data_labels, gridlines, palette legend: a position code ("b", "t", "l", "r", or another the deck holds, such as "tr") or "none"; two booleans; a palette name {"type": …, "title": …, "categories": […], "series": […], "legend": "b", "data_labels": false, "gridlines": true, "palette": "colorful1"}
deck.slide, a table's table options {header_row, total_row, banded_rows, first_column, last_column, banded_columns}, all bool "options": {"header_row": true, "total_row": false, "banded_rows": true, "first_column": false, "last_column": false, "banded_columns": false}
deck.open, deck.cover (error) a .docx or .xlsx unsupported: this is an Office document but not a presentation, which the deck engine doesn't read (.pptx, .deckcraft, or outline .txt or .md)

Review note per new read

Read Source Why it's safe
Colour schemes with colours deckcraft_model::theme::builtin_color_schemes() A built-in constant list, the same one design.themes names and design.colors {name} chooses from. Thirteen schemes of twelve colours each.
Current colour and font scheme deck.masters.first() → theme.colors.name, theme.fonts.name Two strings off the open document. Same master as document.inspect's theme.
Footer deck.header_footer (slide_number, footer, footer_text, date, hide_on_title) Five fields off the open document. footer_text is the deck's own text: bounded by the session's character ceiling, and what deck.design set.
Anchor and autofit deckcraft_model::resolve::body(ctx, shape), the function the renderer draws a box's body with Pure: clones the box's body properties and inherits from its layout and master placeholders. No command and no selection change. Runs after format_state's existing read, which puts its selection back.
Chart options ShapeKind::Chart → legend, data_labels, gridlines, palette Four fields off the model, added to slide.inspect's chart summary
Table options ShapeKind::Table → first_row, last_row, band_row, first_col, last_col, band_col Six booleans off the model, added to slide.inspect's table summary

The answers stay small: one 12-colour list per scheme in deck.themes, five footer fields, and a few values per chart, table or box.

Tests

On the Linux build host (x86_64), at head 0cefcaac on main 202d7cc8:

  • cargo test --locked -p octosense-deck-service -p octosense-engine-area: the deck service's lib tests, 86 passed and 1 ignored (the timing test); first_call 1 and skill 1 passed; engine-area 28 passed.
  • cargo clippy --locked -p octosense-deck-service -p octosense-engine-area --all-targets --no-deps: no findings.
  • New: the_inspector_reads_the_decks_design_and_its_objects:
    • the defaults of the scheme names and footer;
    • after deck.design {colors, fonts, footer}, in deck.state, after a save and reopen in deck.open, and after an undo;
    • the colour schemes' colours against the engine's list;
    • anchor and autofit: a body placeholder top and shrink, a text box resize, and both after deck.format;
    • a chart's and a table's options, before and after deck.chart and deck.table {op: "options"}.
  • New: an_office_document_that_is_not_a_presentation_is_unsupported. An Office-written .docx and .xlsx, and a .docx with its content types last and past 4 KiB as LibreOffice writes one, are all unsupported: on deck.open and deck.cover.
  • Changed: the_guards_reader_reads_as_open_presentation now includes the wide package. It fails without repair and passes with it.
  • Updated: state_close_and_unsaved_changes checks deck.state's whole new answer, and layouts_themes_fonts_and_shapes checks color_schemes' new shape.

The shell's host_tools and system_chat weren't run: no shared crate changed (engine-area is untouched), and the agent's deck tools didn't change.

Not run: the Quick Deck UI (its wiring follows once SERVICE.md has these), no shell or desktop run, no real LibreOffice or Office files (synthetic fixtures only).

🤖 Generated with Claude Code

Quick Deck v2's inspector shows these as off, or by name only, today. The
service now reads each from the open document's model (deckcraft-model),
read-only, with no new engine command:

- deck.themes: color_schemes as [{name, colors}], the engine's built-in
  schemes (builtin_color_schemes, which design.themes names only) with
  their twelve colours in the engine's order
- deck.open and deck.state: theme (state), color_scheme, font_scheme (the
  first master's, as document.inspect reports the theme) and footer
  {slide_numbers, footer, footer_text, date, hide_on_title}, the keys
  deck.design {footer} takes; in deck.state too, so an undo shows
- deck.format_state: anchor and autofit as the box draws them
  (resolve::body: its own, else its layout's and master's, else the
  engine's defaults), in deck.format's words
- deck.slide: a chart's legend, data_labels, gridlines and palette, and a
  table's options {header_row, total_row, banded_rows, first_column,
  last_column, banded_columns}, as deck.chart and deck.table take them

Review nits on #503:
- the reader-parity test now includes a package that repair visibly
  changes (a slide 5,000 points wide, which repair narrows to 4,000), so
  dropping repair from engine_read fails it (tried, then restored)
- an Office package whose main part is a document or a workbook (.docx,
  .xlsx, written by Office or laid out as LibreOffice writes one) is
  unsupported:, not damaged:

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ymote
ymote marked this pull request as ready for review October 11, 2026 21:16
@ymote
ymote force-pushed the feat/deck-inspector-states branch from 0cefcaa to 171fefa Compare October 11, 2026 21:16
@ymote

ymote commented Oct 11, 2026

Copy link
Copy Markdown
Contributor Author

Local CI passed on 171fefa (tools/ci-local.sh --only all --linux-host --offload, 14m23s, Darwin arm64; the ubuntu jobs and the macOS jobs' portable steps (their macOS steps ran here) on the Linux build host, Linux x86_64).

GitHub would run for this PR: desktop.yml, phone.yml, apps.yml. Merged on this local pass (macOS runner queue); GitHub CI runs on the merge commit on main.

Job Step Result Time
ci-local / drift The local mapping fits the workflows PASS -
desktop.yml / desktop Prepare the pinned framework sources PASS 1s
desktop.yml / desktop Compile the desktop with the shared runtime PASS 4m09s
desktop.yml / desktop Desktop tools and scripts PASS 16s
desktop.yml / desktop (linux) Prepare the pinned framework sources PASS 1s
desktop.yml / desktop (linux) One copy of every shell source PASS -
desktop.yml / desktop (linux) In-app updater and installer handoff PASS 1m37s
desktop.yml / desktop (linux) One Makepad, App Hub, octos and Rinx in the locked graph PASS 2s
desktop.yml / desktop (linux) The native apps' generated places match native-apps.json PASS 0s
desktop.yml / native-host-api Prepare the pinned framework sources PASS 1s
desktop.yml / native-host-api Build the native acceptance host and pinned Hub CLI PASS 13s
desktop.yml / native-host-api Signed app tool calls a real OS permission API PASS 3s
phone.yml / home Prepare pinned sources and the reviewed runtime patch PASS 1s
phone.yml / home Validate launcher icons and Apple asset catalogs PASS 4s
phone.yml / home Compile Home and its bundled modules PASS 3m33s
phone.yml / home (linux) Prepare pinned sources and the reviewed runtime patch PASS 0s
phone.yml / home (linux) Verify the single runtime graph PASS 2s
phone.yml / home (linux) The native apps' generated places match native-apps.json PASS 0s
phone.yml / home (linux) The pinned octos revision PASS 0s
phone.yml / home (linux) Build octos (unless cached) PASS -
phone.yml / home (linux) Build Home, App Hub admission and runtime policy tests PASS 3m18s
phone.yml / home (linux) Test Home, App Hub admission and runtime policy PASS 42s
phone.yml / home (linux) Two-lane scenario (real kernel, scripted model) PASS 27s
phone.yml / home (linux) Build opt-in AppCard tests PASS 2m42s
phone.yml / home (linux) Test opt-in AppCard PASS 1s
phone.yml / home (linux) Build craft-engine relay and system-chat tests PASS 2m57s
phone.yml / home (linux) Test craft-engine relay and system chat PASS 4s
phone.yml / home (linux) Build linked Terminal tests PASS 2m28s
phone.yml / home (linux) Test linked Terminal PASS 1s
phone.yml / home (linux) Build Wasm and runtime policy tests PASS 1m16s
phone.yml / home (linux) Test Wasm and runtime policy PASS 11s
apps.yml / services (linux) python3 tools/setup.py PASS 0s
apps.yml / services (linux) Shared system app interface PASS 0s
apps.yml / services (linux) Kernel service PASS 18s
apps.yml / services (linux) OctoSense release updater PASS 6s
apps.yml / services (linux) App peers PASS 29s
apps.yml / services (linux) AI providers config PASS 5s
apps.yml / services (linux) Connected provider protocols and Linux host adapter PASS 47s
apps.yml / services (linux) L0 in-card chat (sys.chat, host side) PASS 10s
apps.yml / services (linux) System toolbox (workflow templates) PASS 1m29s
apps.yml / kernel-security (linux) python3 tools/setup.py PASS 0s
apps.yml / kernel-security (linux) The pinned octos revision PASS -
apps.yml / kernel-security (linux) Build octos (unless cached) PASS -
apps.yml / kernel-security (linux) Real-kernel tests PASS 41s
apps.yml / apps (linux) python3 tools/setup.py PASS 0s
apps.yml / apps (linux) Host services (Mail, AI providers, News) PASS 2m08s
apps.yml / apps (linux) Connected accounts and Rinx editor PASS 1m31s
apps.yml / apps (linux) Shell AI services (crates/ai-host) PASS 2m55s
apps.yml / apps (linux) AppCard runtime setup safeguards PASS 0s
apps.yml / apps (linux) AppCard clippy (own crates; shared runtime compiles) PASS 27s
apps.yml / apps (linux) AppCard transport and store PASS 7s
apps.yml / apps (linux) One Makepad, App Hub, octos and Rinx in the locked graph PASS 3s
rom.yml / product (linux) python3 -m unittest discover -s tests -v SKIPPED (!) -
rom.yml / product (linux) Check generated Agent Binder client SKIPPED (!) -
rom.yml / product (linux) bash -n scripts/stage-forks.sh scripts/publish-release.sh scripts/apply-to-tree.sh scripts/build-rom.sh PASS -
rom.yml / web-installer (linux) npm ci --ignore-scripts --no-audit --no-fund SKIPPED (!) -
rom.yml / web-installer (linux) npm test SKIPPED (!) -
rom.yml / web-installer (linux) npx playwright install --with-deps chromium SKIPPED (!) -
rom.yml / web-installer (linux) npm run test:browser SKIPPED (!) -
rom.yml / web-installer (linux) python3 -m unittest discover -s tests -p test_installer_manifest.py -v SKIPPED (!) -
rom.yml / web-installer (linux) bash -n scripts/release.sh SKIPPED (!) -
linux-host / sandbox (linux) python3 tools/setup.py PASS 0s
linux-host / sandbox (linux) Process sandbox on Linux (Landlock, seccomp) PASS 1m49s

Skipped (these did NOT pass; (!) marks a skip that blocks tools/ci-local-merge.sh):

  • rom.yml / product (linux): python3 -m unittest discover -s tests -v: javac -version does not work here: install a JDK (17 or newer) and put its bin/ on PATH or set JAVA_HOME
  • rom.yml / product (linux): Check generated Agent Binder client: needs build-tools/35.0.0/aidl, platforms/android-35/framework.aidl in the Android SDK (no Android SDK found): install the SDK packages 'build-tools;35.0.0' and 'platforms;android-35' (sdkmanager) and set ANDROID_HOME
  • rom.yml / web-installer (linux): npm ci --ignore-scripts --no-audit --no-fund: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): npm test: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): npx playwright install --with-deps chromium: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): npm run test:browser: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): python3 -m unittest discover -s tests -p test_installer_manifest.py -v: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH
  • rom.yml / web-installer (linux): bash -n scripts/release.sh: no node, npm, npx on PATH (the workflow uses node 24); put node on PATH

Notes:

  • GitHub runs Python 3.12; this run used Python 3.9.6
  • GitHub runs Python 3.12; the Linux host used Python 3.14.4

@ymote
ymote merged commit eb2fd5d into main Oct 11, 2026
2 of 6 checks passed
@ymote
ymote deleted the feat/deck-inspector-states branch October 11, 2026 21:32
chrislearn pushed a commit to chrislearn/OctoSense that referenced this pull request Oct 12, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
chrislearn pushed a commit to chrislearn/OctoSense that referenced this pull request Oct 12, 2026
)

The Theme tab marks the deck's colour set and font pair (deck.open and
deck.state's color_scheme and font_scheme; a built-in theme's own pair by
its families) and shows every colour set's colours and the deck's real
footer; the Format tab's Box switches show the box's anchor and autofit
(deck.format_state); a chart's elements and palette and a table's options
(now all six) show deck.slide's values. A change shows at once and the
service's next answer replaces it. After Undo or Redo, and after any design
change, deck.state and deck.slide bring the deck's own values back without
reopening, and the inspector keeps its scroll (refresh_view) so the control
just used stays in view. The Fonts hint follows a theme change, a .docx or
.xlsx refused as unsupported: is explained, and each segment, colour set,
font pair and palette says whether it's chosen (View.selected) for tools.
The pixel maps' notes follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
chrislearn pushed a commit to chrislearn/OctoSense that referenced this pull request Oct 12, 2026
The dev fixture answers OctoSense-org#507's fields as the service does (colour sets
with their colours, the deck's colour set, font pair and footer, a box's
anchor and autofit, a chart's legend, data labels, gridlines and palette,
a table's options) and keeps an undo history of the deck's data. ui.py's
fixture journey checks the switches and marks against it, adds the table's
and the footer's controls, and checks a change and its Undo; the shell
journey's light pass changes a box's anchor and autofit, a chart's data
labels, a table's total row, the colour set and the footer, reads each back
from the engine and checks each Undo. --bundle and --grabs-only take
another bundle's frames for a before and after. The model tests cover the
new rules.

Co-Authored-By: Claude Opus 5.5 <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.

1 participant