Define original-value text templates and YAML fallback

This commit is contained in:
2026-11-06 21:40:52 +00:00
parent 408383db60
commit c52034f3fe
2 changed files with 89 additions and 52 deletions

View File

@@ -163,13 +163,15 @@ steps. No delivery date or final API is selected here.
The [shared core report output prerequisite](promptkit-v0.19.0.md#shared-core-report-output-prerequisite)
is now part of the working adoption roadmap. It records application-owned
content selection, core-owned rendering, a text fallback with optional templates,
content selection, core-owned rendering, text output with optional templates,
and universal format availability. Explicit operator selection wins; otherwise
core selects text for a supplied template or chooses from the logical report
shape. Command-specific format defaults are omitted from the initial API.
Plain text, YAML, and JSON land together. The roadmap selects standard Go JSON
serialization conventions for ordinary report values, with separate core
adaptation for native configuration YAML. Text-template and native-document
serialization conventions for core-serialized report values, with separate core
adaptation for native configuration YAML. Text templates use Go's `text/template`
with the original Go report value. Without a template, structured text output
reuses the YAML renderer; template errors never trigger fallback. Native-document
decisions remain there. XML is removed from current consideration.
Markdown and other potential formats are not selected for this adoption; new
core formats will work with

View File

@@ -399,9 +399,12 @@ existing reporting facility rather than creating a second delivery lifecycle.
### Agreed shared representation rules
**Agreed:** use Go's standard `encoding/json` serialization conventions to
interpret ordinary Go report values. Prepare one logical representation for
automatic selection and rendering in text, YAML, and JSON. This selects how Go
values become report data; it does not select JSON as the default output format.
interpret ordinary Go report values for core serialization. Prepare one logical
representation for YAML/JSON output and for automatic selection and text
rendering when no text template is used. Application-supplied text templates instead
receive the original Go value, as specified below. JSON conventions do not
select JSON as the default output format or expose core's intermediate data
representation as a public template contract.
Reuse the standard library's field selection, JSON tags, omission rules, nested
value handling, and supported custom JSON serialization. Avoid a new CommandKit
@@ -409,9 +412,10 @@ tag convention or reflection-based serialization engine. Suitable upstream
values can reuse their existing JSON contract; thin projections remain useful
when the desired operator content differs from that representation.
- **One field interpretation.** JSON field tags and custom serialization govern
ordinary values in every output format. Conflicting YAML tags or YAML-specific
serialization do not change that interpretation. For example, a field tagged
- **One serialized field interpretation.** JSON field tags and custom
serialization govern ordinary values in core-serialized outputs. Conflicting
YAML tags or YAML-specific serialization do not change that interpretation.
For example, a field tagged
`json:"retry_count" yaml:"retries"` appears as `retry_count` in both JSON and
YAML. Do not independently serialize the original Go value with each encoder.
- **Explicit omission.** Honor omissions selected by the JSON contract. Core
@@ -422,9 +426,11 @@ when the desired operator content differs from that representation.
including accidental rounding of large integers through floating point. This
preserves the serialized value rather than promising precision beyond the
supplied value and its serialization contract.
- **Observable failures.** Values rejected by the serialization contract produce
presentation errors through the existing reporting lifecycle. Do not silently
drop unsupported data or substitute arbitrary string representations.
- **Observable failures.** When serialization is used, values rejected by its
contract produce presentation errors through the existing reporting lifecycle.
Do not silently drop unsupported data or substitute arbitrary string
representations. Templated text executes against the original value without
requiring a JSON round trip.
**Agreed separate treatment:** native configuration YAML uses explicit core
adaptation with defined cross-format mappings, not blind conversion through the
@@ -442,32 +448,47 @@ assuming that an upstream type can be handed off without adaptation.
### Agreed plain-text rendering
Core provides a default plain-text fallback and accepts an optional template
from the application or integration as part of the report handoff. When text is
selected, core uses the template if supplied and otherwise renders the selected
report data using its standard fallback. A template selects text automatically
only when the operator omits `--format`; explicit YAML or JSON takes precedence.
YAML and JSON use the same selected content and shared representation rules,
independently of the text
template. Applications do not supply separate YAML/JSON writers.
**Agreed template boundary:** applications and integrations own the report value
and optional text template. Core prepares and executes templates using Go's
built-in `text/template`, passing the original Go value supplied in the report
handoff. Templates use Go field names, types, and standard template behavior,
not JSON field names or CommandKit's intermediate representation. For example,
a Go field `PromptID` tagged `json:"prompt_id"` is accessed as `.PromptID`.
Recommend a readable hierarchical fallback with named fields, nested values,
and list items. A template can arrange the supplied content as a sentence,
table, or another useful presentation. Core owns template execution, shared
formatting helpers, and delivery errors. Go's `text/template` and reusable
templates declared once are implementation candidates; the template API,
helper set, and exact fallback layout still need design.
JSON tags and custom JSON serialization govern structured rendering, not the
template's field access. An exported field tagged `json:"-"` remains accessible
to the application's template, and custom JSON serialization does not replace
the template input. The application owns that text content choice. Core retains
ownership of execution, shared helpers, delivery, and presentation failures.
Prefer reusable templates prepared during setup; exact public preparation and
handoff signatures and the small helper set remain implementation design tasks.
This resolves the earlier human-oriented presentation discussion (point 4).
Universal core formats resolve point 5; per-command supported-format lists and
per-format application renderers are not the selected mechanism.
When text is selected and a template is supplied, execute it as supplied and
deliver its output without applying a second formatting pass. Template syntax
or execution errors are errors, not a reason to fall back to another renderer.
Use standard `text/template` semantics rather than introducing a new template
language. A template selects text automatically only when the operator omits
`--format`; explicit YAML or JSON takes precedence and does not execute it.
**Agreed text behavior without a template:** use core's logical report
representation to select the following rendering behavior:
- Print strings directly, nonempty sequences containing only strings one item per line,
and numbers or booleans as their values.
- For mappings, nested or mixed collections, empty collections, and null, reuse
the shared YAML renderer. Empty sequences use this rule even when their Go
element type is string, retaining the visible `[]` result.
Automatic selection already chooses YAML for the second group. The additional
case is explicit `--format text` with structured data and no template, such as
`config show --format text`. Text and YAML intentionally coincide in that case.
This retains universal format support without a separate hierarchical text
renderer or pretty-printer. It supersedes the proposed generic text outline.
Applications do not supply separate YAML/JSON writers, and a failing template
never enters this no-template path.
### Remaining core reporting decisions
- **Text handoff.** Settle the template API and helper functions, whether
templates receive the original Go value or shared representation, fallback
conventions, and template preparation and failure behavior. Prefer a small
reusable mechanism; applications select content and layout, core renders it.
- **Native documents and multiple results.** Define how native safe YAML
snapshots and ordered multi-scope documents enter the shared representation,
and how multiple documents/results appear in JSON and text. Preserve native
@@ -475,10 +496,12 @@ per-format application renderers are not the selected mechanism.
commands from universal format support. Keep format translation in core and
domain evidence selection in the integrations.
Exact public signatures, flag integration/collision handling, and replacement
of existing format plumbing are implementation design tasks. The decisions
above do not reopen content selection, JSON conventions for ordinary report
values, universal formats, automatic selection, or joint format delivery.
Exact public signatures, reusable template preparation and helper functions,
flag integration/collision handling, and replacement of existing format plumbing
are implementation design tasks. The decisions above do not reopen content
selection, JSON conventions for core serialization, original Go values for text
templates, no-template text rendering, universal formats, automatic selection,
or joint format delivery.
Report serialization does not settle the separate JSON input-number conversion
choices in OD-2 and OD-11.
@@ -502,8 +525,8 @@ projection using the agreed JSON serialization conventions. Do not mirror a
whole upstream object graph just to rename fields or rearrange equivalent data.
Reuse small path, snapshot,
location, and duration projections where they are genuinely needed. Core reuses
the JSON contract across renderers; migrate YAML-only report tags or provide a
thin projection where necessary. Native configuration documents follow their
the JSON contract across its serialization paths; migrate YAML-only report tags
or provide a thin projection where necessary. Native configuration documents follow their
explicit adaptation path rather than the ordinary Go-value path.
Exceptions serve concrete report semantics: preserving absent/null/false/zero
@@ -517,8 +540,10 @@ design, not an integration-owned alternative formatting pipeline.
Separate content projection from format rendering and from invocation delivery.
Use the existing Reporter and outcome lifecycle for delivery and failures.
Share common helpers without forcing text output through a YAML round trip or
forcing semantically different reports into one schema. Validate representative
Text templates receive original Go values. Simple text output uses the logical
report values directly, while structured text without a template delegates to
the YAML renderer without a YAML encode/decode round trip. Do not force
semantically different reports into one schema. Validate representative
reports and meaningful adaptation boundaries, rather than freezing every
incidental formatting detail in tests.
@@ -526,15 +551,15 @@ incidental formatting detail in tests.
1. **Confirm remaining implementation choices.** Use the accepted flags, report
content, and automatic format policy as the MVP target. Resolve the remaining
text-template and native-document decisions; specify the public API and
internal conversion design under the agreed JSON representation contract.
native-document decisions; specify the public API, reusable template helpers,
and internal conversion design under the agreed JSON representation contract.
Resolve outstanding acquisition/binding grammar and flag collisions; use
concrete examples to review report details during implementation rather than
reopening accepted scope.
2. **Implement shared core report output.** Deliver the agreed automatic format
policy, universal `--format` selection, format-independent Reporter
operation, writer-based API, and shared representation/encoding machinery.
Deliver YAML encoding, text fallback/templates, and JSON encoding together
Deliver YAML encoding, text printing/templates, and JSON encoding together
in the core feature release. Exercise the public API with core reporting
and an application-owned command example, and consolidate suitable existing
integration reports onto it. Cover the selected contracts and update their
@@ -584,7 +609,7 @@ CommandKit to retest PromptKit rendering, schema, namespace, or ConfigKit
resolution algorithms.
Default tests remain offline and independent of real credentials.
- [ ] Remaining text-template and native-document decisions are recorded.
- [ ] Remaining native-document decisions are recorded.
Public signatures and shared representation conventions are
documented with implementation.
- [ ] Core owns universal `--format` options, help, validation, and selection.
@@ -600,14 +625,24 @@ Default tests remain offline and independent of real credentials.
configuration values. Focused configuration values follow the same rules.
- [ ] Plain text, YAML, and JSON ship together; representative reports exercise
shared representation and explicit selection across all three.
- [ ] Plain text uses the supplied template or core's fallback. Core owns
rendering and errors in both cases. The integration chooses concise/detailed
content; changing format does not implicitly change the selected detail level.
- [ ] Text templates execute with standard `text/template` behavior against the
original Go report value, retaining field names and types. JSON tags and custom
JSON serialization do not rename, omit, or replace the template input.
Explicit YAML/JSON output does not execute the text template.
- [ ] Template syntax and execution failures remain observable errors; a failing
template never falls back to scalar printing or YAML output.
- [ ] Text without a template prints strings, nonempty string lists, numbers,
and booleans directly; structured values, empty collections, and null use the
shared YAML renderer. Cover explicit `--format text` for those values without
introducing a separate pretty-printer.
- [ ] The integration chooses concise/detailed content; changing format does
not implicitly change the selected detail level. Core owns rendering and
delivery in both templated and non-templated paths.
- [ ] The invocation and writer-based public APIs share rendering behavior;
handlers submit report data without their own format switches or encoder
setup. Existing quiet-mode, presentation-failure, and domain-outcome behavior
is preserved through the Reporter lifecycle.
- [ ] Ordinary Go reports follow the standard JSON contract across formats,
- [ ] Core-serialized ordinary Go reports follow the standard JSON contract,
including JSON tags, supported custom serialization, and selected omissions.
Conflicting YAML tags do not rename fields or change values in YAML output.
Verify that automatic selection follows the resulting logical shape.
@@ -771,7 +806,7 @@ These decisions concern significant choices within the proposed scope. Resolved
items retain their numbers and record the agreed decision. OD numbers are local
to this roadmap, not the retired adoption documents.
The core ownership, JSON representation conventions, text fallback/template,
The core ownership, JSON representation conventions, text printing/templates,
universal-format, automatic-selection, and joint format-delivery decisions are
now agreed above. Remaining details are listed under
[remaining core reporting decisions](#remaining-core-reporting-decisions).
@@ -798,7 +833,7 @@ calling the model."
Document resource I/O and rendered content disclosure directly in help and CLI
guidance. The report is an inspection snapshot, not a saved execution handle or
a guarantee that later execution uses the same snapshot or succeeds. Core's
text fallback supplies explicit `--format text` output without requiring a
YAML renderer also supplies explicit `--format text` output without requiring a
dedicated preview template; a specialized template is not required for initial delivery.
### OD-2: Request controls and provider-parameter grammar
@@ -1019,7 +1054,7 @@ has an explicit empty difference list. Both concise and detailed comparison
hand off structured mappings without a text template; core's automatic policy
selects YAML. Universal format choices supersede the earlier YAML-only detailed
restriction. The same selected comparison evidence is handed to core in every
format; explicit text uses core's fallback.
format; explicit text without a template reuses core's YAML renderer.
Keep the projection close to native report values, using the
[shared reporting approach](#initial-report-implementation-approach) rather than