Skip to content

program: custom templates in the empty-state placeholder - #563

Merged
edwin-zvs merged 3 commits into
mainfrom
program-custom-templates
Jun 28, 2026
Merged

edwin-zvs merged 3 commits into
mainfrom
program-custom-templates

Conversation

@edwin-zvs

Copy link
Copy Markdown
Contributor

Custom program templates in the empty-state placeholder

Implements all five requested items. The empty-program onboarding placeholder now surfaces every template (built-ins + user-authored), the templates directory is configurable + live-reloading, and templates can carry a docs reference.

What changed (1–5)

  1. All templates as clickable buttons, wrapping across rows. The placeholder renders every non-blank template as a bordered button, packed greedily into rows that never exceed the pane width. Every rendered button (across every row) publishes a hitbox, so all are clickable. When more templates exist than fit the available height, it shows as many as fit plus a trailing "+N more" indicator. The narrow/short → plain-text fallback is preserved, and the invariant that no placeholder line exceeds inner.width is kept (tested).
  2. Name ordering. Buttons are ordered by name (case-insensitive) in the placeholder; "blank" stays excluded. (The daemon's own list order is unchanged.)
  3. Configurable templates directory. New [program].templates_dir config option and CONSTRUCT_PROGRAM_TEMPLATES_DIR env override, resolved env > config > default (<data_dir>/program/templates). Resolved once at daemon start and threaded into Storage via a new override field. The legacy canvas/templates → program/templates migration still runs, but only for the default location (an explicit override is treated as operator-owned). Documented in the config template.
  4. Live reload on open. The client used to cache templates (fetched at start / reconnect only). Now opening the program pane kicks off a non-blocking background re-fetch delivered to the event loop over a channel; the pane opens against the cached list and swaps to the fresh one when it lands (no flicker). Editing or adding a template file now appears on the next open — no daemon restart.
  5. Reference link + syntax cheat. See interpretation below.

⚠️ Point 5 interpretation (please confirm)

Point 5 was flagged ambiguous. My interpretation:

  • Added an optional reference field to ProgramTemplate (protocol) and to the template frontmatter (reference: key, URL value). Built-ins carry a default PROGRAM_DOCS_REFERENCE (https://github.com/zarvis-ai/agentd — swap this for the canonical program-docs URL if there's a better one).
  • The placeholder shows the reference as a single underlined Docs: footer link, not one-per-button (a per-button link would blow out the compact button layout). It shows the first available reference; since built-ins always carry the docs link and the daemon returns them first, the footer is a stable "Docs:" link, while a user template's reference: surfaces only when no earlier template has one.
  • The old "Tip:" line is now a clearer Syntax: reference: @{session:id} embeds · @{harness:name} delegates · select + Run dispatches · :::clip … ::: groups output — consistent with what built-in templates demonstrate.

If you'd rather show a per-template reference, or pick the reference from the display (name-sorted) order instead of daemon order, that's a small change — flagging for your call.

Tests

  • daemon: resolve_program_templates_dir precedence (env > config > default), [program].templates_dir parse, reference: frontmatter parse, override redirects reads (and ignores the default dir).
  • cli: name ordering, wrapping >2 templates with clickable hits across rows, overflow indicator, reference footer, narrow fallback, no-templates fallback. Existing button test updated for the new name order.
  • Full agentd lib (97) + agentd-protocol + the cli placeholder suite pass. (One unrelated cli perf test — pty_render::…many_small_events_stay_fast — flakes under concurrent build load and passes in isolation; not touched by this PR.)

Specs

  • Updated 0049-program-empty-state-onboarding.md (was capped at two buttons).
  • Added 0051-program-custom-templates-source.md (directory source, live reload, reference metadata).

Binary

This PR touches crates/daemon + crates/protocol + crates/cli; the single workspace binary is construct:
/Users/moon/agentd/.claude/worktrees/program-custom-templates/target/debug/construct

Screenshot of the new placeholder (8 templates — 6 custom via CONSTRUCT_PROGRAM_TEMPLATES_DIR + built-in Investigation/Tasks — name-ordered, wrapped across 2 rows, syntax line + Docs footer) posted as a comment.

Show every non-blank program template (built-ins + custom) as a clickable
button in the empty-state placeholder, ordered by name and wrapped across
rows, with a "+N more" overflow indicator and a smart-clip syntax + docs
reference footer. Make the templates directory configurable and reload it
live on every program open.

- protocol: add optional `reference` field to ProgramTemplate + a default
  PROGRAM_DOCS_REFERENCE for built-ins.
- daemon/storage: parse `reference:` frontmatter, carry the docs reference on
  built-ins, and support a program-templates-dir override (legacy
  canvas/templates migration stays default-location only).
- daemon/config: add `[program].templates_dir` + CONSTRUCT_PROGRAM_TEMPLATES_DIR
  (env > config > default), documented in the config template; wire the
  resolved dir into Storage at startup.
- cli/ui: render all non-blank templates as name-ordered, wrapping, fully
  clickable buttons within the pane width; overflow indicator; syntax line +
  reference footer; preserve the narrow/short plain fallback.
- cli/app: background, non-blocking template refresh on program open so file
  edits/new files appear on the next open without a daemon restart.
- specs: update 0049, add 0051.
@edwin-zvs

edwin-zvs commented Jun 28, 2026 •

Copy link
Copy Markdown
Contributor Author

Screenshot of the new empty-state placeholder — 6 custom templates (via CONSTRUCT_PROGRAM_TEMPLATES_DIR) + built-in Investigation/Tasks: name-ordered, wrapped across two rows, every button clickable, Syntax: line, underlined Docs: footer.

The rendered frame and full clip are local artifacts (gh can't upload binary attachments to a comment — please drag them into the PR if you want them inline):

  • /tmp/program-templates-demo/frame_7.png
  • /tmp/program-templates-demo/demo.mp4

…e/frontmatter

A custom program template is now just a .md file: its filename stem (prettified
and title-cased) is its name, and the file contents are the program verbatim.
Remove the per-template reference/docs-link feature and all custom-template
frontmatter parsing. Built-ins keep their descriptions; custom templates carry
none.
@edwin-zvs
edwin-zvs merged commit 1219047 into main Jun 28, 2026
1 check passed
@edwin-zvs
edwin-zvs deleted the program-custom-templates branch June 28, 2026 18:44
edwin-zvs added a commit that referenced this pull request Jun 29, 2026
…053, break pending_block_signatures compat

main advanced with #569 (keep run shimmer alive past owning-session idle),
which reworked the same shimmer lifecycle and added agent_managed to
ProgramRunProgress, plus #563/#568 (specs 0051 custom-templates, 0052
session-removal-cascades).

Reconcile:
- protocol: keep pending_block_ids rename + the declared-shimmer types
  alongside #569's agent_managed field; DROP the pending_block_signatures
  serde alias (clean break, per request) and remove the legacy-compat test.
- daemon: fold #569's agent_managed + inactivity-backstop refresh into the
  declaration-based narrow_program_run and set_program_run_pending so a
  complete/partial declaration also marks the run agent-managed; #569's
  AwaitingInput/terminal stop-signal split is preserved. Adapt #569's two
  lifecycle tests to the id-based API.
- specs 0042/0048: combine #569's stop-signal model with the declared
  per-block-id model; my new spec collides with main's 0051/0052, renumbered
  to specs/0053-program-shimmer-block-addressing and all references updated.

cargo test --workspace green.
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