feat(slides): bucket C — slide linking, hash-based staleness, folder.pick (closes #54) #55

Merged
mik-tf merged 1 commit from development_mik into development 2026-05-10 19:33:41 +00:00
Owner

Closes #54

Implements the five JSON-RPC methods declared in openrpc.json that were returning -32000 "Method not found": slide.setLink, slide.clearLink, slide.getStaleness, deck.staleness, folder.pick.

Per the locked design in #54 (mik-tf, 2026-05-10) with three reconciliations vs the issue body, all captured in decisions/D-09-slide-linking-and-staleness.md in the workspace tracker:

  1. Staleness uses the existing ADR-0007 hash infrastructure (compute_inputs_hash, DeckInputsContext, last_generated snapshot) rather than file mtimes. Produces per-component reasons: content_edited / theme_edited / context_edited / prompts_edited / model_changed / link_broken / never_generated / inputs_changed.
  2. Linking persists via the existing typed SlideLink + SlideMetaEntry.source_link rather than a raw linked_to string. Cycle detection at setLink time rejects A→B→A loops. setLink copies the source slide PNG into the destination output/ for immediate display; clearLink removes the link but leaves the PNG.
  3. folder.pick reads a hero_proc secret allowlist (folder_pick_allowed_roots, context hero_slides, newline-separated) with ~/Documents fallback. Schema description flipped from "native OS dialog" (architecturally wrong over JSON-RPC) to allowlist semantics. Params/result shape unchanged.

Also fixes a pre-existing bug surfaced during e2e verification: slide_generate_with_selection and slide_generate_with_context only persisted SlideMetaEntry.hash on successful AI render, never the ADR-0007 inputs-hash snapshot fields. Without those, every generated slide stayed in the back-fill rule forever and content_edited never fired. Snapshot is now written in both functions.

openrpc.client.generated.rs is the build.rs regeneration of the typed client (deck.staleness + slide.getStaleness param flip to {collection, deck[, slide]}, plus new reasons field).

Test plan (verified locally before push)

  • folder.pick returns ~/Documents via dashboard rpc()
  • deck.staleness + slide.getStaleness with correct reasons attribution on real post-ADR-0007 entry
  • slide.setLink cycle rejection (self-link + A→B→A both error)
  • slide.setLink source-PNG mirror verified md5-byte-for-byte to destination
  • slide.clearLink removes source_link from metadata, leaves PNG
  • Full AI-generate round-trip through Gemini Flash Image via hero_aibroker (real 1.3 MB PNG output, valid ADR-0007 snapshot in metadata.toml)

Requires the matching aibroker fix at https://forge.ourworld.tf/lhumina_code/hero_aibroker for image response passthrough.

Signed-off-by: mik-tf

Closes https://forge.ourworld.tf/lhumina_code/hero_slides/issues/54 Implements the five JSON-RPC methods declared in `openrpc.json` that were returning `-32000 "Method not found"`: `slide.setLink`, `slide.clearLink`, `slide.getStaleness`, `deck.staleness`, `folder.pick`. Per the locked design in #54 (mik-tf, 2026-05-10) with three reconciliations vs the issue body, all captured in `decisions/D-09-slide-linking-and-staleness.md` in the workspace tracker: 1. **Staleness uses the existing ADR-0007 hash infrastructure** (`compute_inputs_hash`, `DeckInputsContext`, `last_generated` snapshot) rather than file mtimes. Produces per-component reasons: `content_edited` / `theme_edited` / `context_edited` / `prompts_edited` / `model_changed` / `link_broken` / `never_generated` / `inputs_changed`. 2. **Linking persists via the existing typed `SlideLink` + `SlideMetaEntry.source_link`** rather than a raw `linked_to` string. Cycle detection at `setLink` time rejects A→B→A loops. `setLink` copies the source slide PNG into the destination `output/` for immediate display; `clearLink` removes the link but leaves the PNG. 3. **`folder.pick`** reads a hero_proc secret allowlist (`folder_pick_allowed_roots`, context `hero_slides`, newline-separated) with `~/Documents` fallback. Schema description flipped from "native OS dialog" (architecturally wrong over JSON-RPC) to allowlist semantics. Params/result shape unchanged. **Also fixes a pre-existing bug** surfaced during e2e verification: `slide_generate_with_selection` and `slide_generate_with_context` only persisted `SlideMetaEntry.hash` on successful AI render, never the ADR-0007 inputs-hash snapshot fields. Without those, every generated slide stayed in the back-fill rule forever and `content_edited` never fired. Snapshot is now written in both functions. `openrpc.client.generated.rs` is the `build.rs` regeneration of the typed client (`deck.staleness` + `slide.getStaleness` param flip to `{collection, deck[, slide]}`, plus new `reasons` field). ## Test plan (verified locally before push) - [x] `folder.pick` returns `~/Documents` via dashboard `rpc()` - [x] `deck.staleness` + `slide.getStaleness` with correct reasons attribution on real post-ADR-0007 entry - [x] `slide.setLink` cycle rejection (self-link + A→B→A both error) - [x] `slide.setLink` source-PNG mirror verified md5-byte-for-byte to destination - [x] `slide.clearLink` removes `source_link` from metadata, leaves PNG - [x] Full AI-generate round-trip through Gemini Flash Image via hero_aibroker (real 1.3 MB PNG output, valid ADR-0007 snapshot in metadata.toml) **Requires the matching aibroker fix at** https://forge.ourworld.tf/lhumina_code/hero_aibroker for image response passthrough. Signed-off-by: mik-tf
feat(slides): bucket C — slide linking, hash-based staleness, folder.pick (closes #54)
Some checks failed
Test / test (push) Failing after 16s
Test / test (pull_request) Failing after 22s
d78fb3d89f
Implements the five JSON-RPC methods declared in openrpc.json that were
returning -32000 "Method not found": slide.setLink, slide.clearLink,
slide.getStaleness, deck.staleness, folder.pick. Per
#54
locked design (mik-tf, 2026-05-10) with three reconciliations vs the
issue body, all captured in decisions/D-09-slide-linking-and-staleness.md
in the workspace tracker:

1. Staleness uses the existing ADR-0007 hash infrastructure
   (compute_inputs_hash, DeckInputsContext, last_generated snapshot)
   rather than file mtimes. Produces per-component reasons:
   content_edited / theme_edited / context_edited / prompts_edited /
   model_changed / link_broken / never_generated / inputs_changed.

2. Linking persists via the existing typed SlideLink +
   SlideMetaEntry.source_link rather than a raw `linked_to` string.
   Cycle detection at setLink time rejects A->B->A loops. setLink
   copies the source slide's rendered PNG into the destination
   output/ for immediate display; clearLink removes the link but
   leaves the PNG (operator may regenerate or delete).

3. folder.pick reads a hero_proc secret allowlist
   (folder_pick_allowed_roots, context hero_slides, newline-separated)
   with ~/Documents fallback. Schema description flipped from
   "native OS dialog" (architecturally wrong over JSON-RPC) to
   allowlist semantics. Params/result shape unchanged.

Also fixes a pre-existing bug surfaced during e2e verification:
slide_generate_with_selection and slide_generate_with_context only
persisted SlideMetaEntry.hash on successful AI render, never the
ADR-0007 inputs-hash snapshot fields (last_generated,
last_theme_hash, last_context_fingerprint, last_prompts_hash,
last_image_model). Without those, every generated slide stayed in
the "legacy back-fill = not stale" rule forever and the
content_edited reason never fired. Snapshot is now written in
both functions.

openrpc.client.generated.rs is the build.rs regeneration of the
typed client from the updated openrpc.json schema (deck.staleness +
slide.getStaleness param shape flip from {path}/{deck_path,slide_name}
to {collection, deck[, slide]}, plus the new `reasons` field on both
result schemas).

Verified locally end-to-end: folder.pick returns ~/Documents,
deck.staleness + slide.getStaleness with correct reasons attribution
on real post-ADR-0007 entries, setLink/clearLink with cycle rejection
and source-PNG mirror verified md5-byte-for-byte. Full AI-generate
round trip through Gemini Flash Image via hero_aibroker — requires
the matching aibroker fix at
https://forge.ourworld.tf/lhumina_code/hero_aibroker for image
response passthrough.

Closes #54

Signed-off-by: mik-tf
mik-tf merged commit dd3aed56f8 into development 2026-05-10 19:33:41 +00:00
mik-tf deleted branch development_mik 2026-05-10 19:33:41 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_slides!55
No description provided.