ld-shared

Provides shared Python helpers for kiosk posting, config validation, and calendar feed delivery.

2|Updated Aug 25, 2026
One-click install
npx skills add https://github.com/plow-pbc/life-assistant-hermes-agent --skill ld-shared-plow-pbc
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: ld-shared
Source: https://github.com/plow-pbc/life-assistant-hermes-agent/tree/main/ld-shared
Command: npx skills add https://github.com/plow-pbc/life-assistant-hermes-agent --skill ld-shared-plow-pbc

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes scripts (resource) and references (resource) components.

What problem does it solve? Life-dashboard producers each need the same plumbing — posting cards to the household kiosk, validating the shared ld-config, and shipping the calendar strip over Latch — and duplicating that logic across producers invites drift and security mistakes. This Skill centralizes those helpers so every ld-* producer imports one audited implementation. ## Core Features & Use Cases - Kiosk POST helper: post_to_kiosk.py enforces the wire protocol, refuses redirects, validates dotenv-sourced endpoints against the household network, and supports Latch hand-off delivery via the owner's Mac. - Config gate: ld_config_gate.py is the single structural definition of a valid ld/config.json, checking timezone, calendar sources, nudge lookaheads, and leftover placeholders. - Calendar feed: calendar_feed.py gathers events through the Plow relay, strips untrusted-content markers and private events, and delivers the strip to the kiosk without a model in the loop. - Use Case: A producer Skill like ld-weather imports post_to_kiosk to publish its card, relying on the shared bearer handling, atomic writes, and exclusive locking rather than reimplementing them. ## Quick Start Read the kiosk protocol and Latch delivery references, then have the producer import the shared scripts to validate the config and post its card to the kiosk.

Frequently Asked Questions about ld-shared

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I post a card to the life-dashboard kiosk from a producer script?▼

Import post_to_kiosk.py, set the CARD and BODY_TYPE module constants, optionally set TITLE and TRANSFORM, then call main(). The helper reads the endpoint and bearer from fixed file, env, or dotenv sources and refuses redirects so the Authorization header is never forwarded.

How do I validate an ld config.json file?▼

Run ld_config_gate.py with the config path; it prints failing invariant names or nothing on success. It checks family.timezone, calendar.sources uniqueness, nudge lookaheads, owner identities, and rejects leftover [UPPER_SNAKE] placeholders.

How does kiosk delivery work when the Pi is only reachable from the owner's Mac?▼

When DASHBOARD_DELIVERY=latch, post_to_kiosk writes the wire body to an outbox file and prints two Latch calls: plow_write_file to stage the JSON on the Mac, then a curl through plow_run_command. The bearer stays in ~/Plow/ld/dashboard.hdr on the Mac and never crosses the relay.

Why does the calendar feed strip private events and URI tokens?▼

Event text is untrusted data from external calendars, so calendar_feed.py drops private and confidential occurrences plus their sibling copies, then removes Latch's untrusted-content markers and URI-shaped tokens. This prevents join links or private titles from appearing on a display anyone in the household can read.

What happens when the owner's Mac is asleep during a scheduled calendar feed run?▼

The relay call fails with an unreachable-device error, the script prints a one-line stand-down message, and exits 0. The next scheduled tick re-gathers and re-delivers on its own; three consecutive failures trigger an hour-long backoff.