canned-prompts/reference
tegwick 169db25d25 CANP-WP-0002 T01: input defaults, static and derived
Closes the gap that made optional inputs unusable: rendering rule 5.1(4)
made any unresolved placeholder an error while inputs had no `default`, so
an input marked `required: false` and referenced from the template failed
every render in which the caller omitted it — including the spec's own
section 4 example.

Section 10 already carried the derivation mechanism (`requirement: generate`,
resolution deliberately undefined), so a derived default needed a binding
rather than a new concept: the input's default names a declared prompt
dependency.

Spec:
- 5.1 rewritten as "Resolution and rendering". Resolution may be
  non-deterministic and must report what it derived; rendering is
  deterministic and must not derive. A tool that handles only supplied
  values and static defaults is stated to be conforming.
- 6.1 (new) covers both declaration forms. Reference form is preferred, with
  the reason stated — an inline prompt is anonymous, so unversioned,
  unprovenanced and un-evaluable — and validators should warn when a
  published package derives inline.
- A derived default may declare a static fallback `value`. Without one the
  input stays unresolved, which is an error; derivation never silently
  yields empty content.
- 4, 10, 18 (rules 11-13), 19 (two new MUST NOTs), 21 updated accordingly.

Reference CLI:
- New `resolve` verb reporting the origin of every value.
- `Resolution` dataclass and `resolve_inputs`; `resolve_values` kept as a
  wrapper so existing callers are unaffected.
- `render` refuses with a specific error naming underivable inputs rather
  than substituting empty text.
- Tests 3 -> 11. Example package lifecycle re-verified end to end.

INTENT.md is unchanged: splitting resolve from render preserves success
criterion 4 (deterministic rendering) as written.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bjefh8NUiEiahN4JLwoSKM

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 388925@bnt-lap001
Assistant-Session: 3507023f-e0fd-4a1e-9d90-a0d4217d1502
2026-09-06 00:59:20 +02:00
..
tests CANP-WP-0002 T01: input defaults, static and derived 2026-09-06 00:59:20 +02:00
canned_prompts.py CANP-WP-0002 T01: input defaults, static and derived 2026-09-06 00:59:20 +02:00
pyproject.toml Register with Custodian State Hub and seed format open-questions workplan 2026-09-06 00:45:28 +02:00
README.md CANP-WP-0002 T01: input defaults, static and derived 2026-09-06 00:59:20 +02:00
requirements-dev.txt Register with Custodian State Hub and seed format open-questions workplan 2026-09-06 00:45:28 +02:00
requirements.txt Register with Custodian State Hub and seed format open-questions workplan 2026-09-06 00:45:28 +02:00

canned-prompts reference CLI

This is intentionally a small reference implementation, not the intended final architecture.

It demonstrates seven verbs:

add      PATH
search   QUERY
show     ID
resolve  ID --set key=value
render   ID --set key=value
install  ID [--version VERSION]
publish  PATH

The implementation uses a local catalog plus a filesystem registry and performs no model calls.

resolve and render are separate because the specification separates them (§ 5.1): resolution decides each value and may be non-deterministic, rendering substitutes and always is. resolve prints where every value came from — supplied, default, or fallback — before any prompt is produced.

Stores

Default locations:

~/.canned-prompts/catalog
~/.canned-prompts/registry

Catalog and registry both store packages as:

<store>/<id path>/<version>/...

For example:

~/.canned-prompts/catalog/practice/pqrst-estimate/0.1.0/

Design choices

  • YAML manifest via PyYAML.
  • {{ name }} template substitution only.
  • No arbitrary expression/code execution.
  • Published versions are immutable by default.
  • install copies from registry to catalog.
  • add copies a package directly to catalog.
  • search, show, resolve, and render operate on catalog packages.
  • Static input defaults are applied; derived defaults (§ 6.1) are not. This tool never calls a model, so a derived default is satisfied only by its static fallback value. Without one, resolve reports the input as unresolved and render refuses rather than substituting empty text.

Use this implementation to challenge the format. Replace it once real usage reveals the right architecture.