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) 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 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 and universal format availability. Explicit operator selection wins; otherwise
core selects text for a supplied template or chooses from the logical report core selects text for a supplied template or chooses from the logical report
shape. Command-specific format defaults are omitted from the initial API. shape. Command-specific format defaults are omitted from the initial API.
Plain text, YAML, and JSON land together. The roadmap selects standard Go JSON Plain text, YAML, and JSON land together. The roadmap selects standard Go JSON
serialization conventions for ordinary report values, with separate core serialization conventions for core-serialized report values, with separate core
adaptation for native configuration YAML. Text-template and native-document 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. decisions remain there. XML is removed from current consideration.
Markdown and other potential formats are not selected for this adoption; new Markdown and other potential formats are not selected for this adoption; new
core formats will work with 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 shared representation rules
**Agreed:** use Go's standard `encoding/json` serialization conventions to **Agreed:** use Go's standard `encoding/json` serialization conventions to
interpret ordinary Go report values. Prepare one logical representation for interpret ordinary Go report values for core serialization. Prepare one logical
automatic selection and rendering in text, YAML, and JSON. This selects how Go representation for YAML/JSON output and for automatic selection and text
values become report data; it does not select JSON as the default output format. 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 Reuse the standard library's field selection, JSON tags, omission rules, nested
value handling, and supported custom JSON serialization. Avoid a new CommandKit 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 values can reuse their existing JSON contract; thin projections remain useful
when the desired operator content differs from that representation. when the desired operator content differs from that representation.
- **One field interpretation.** JSON field tags and custom serialization govern - **One serialized field interpretation.** JSON field tags and custom
ordinary values in every output format. Conflicting YAML tags or YAML-specific serialization govern ordinary values in core-serialized outputs. Conflicting
serialization do not change that interpretation. For example, a field tagged 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 `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. YAML. Do not independently serialize the original Go value with each encoder.
- **Explicit omission.** Honor omissions selected by the JSON contract. Core - **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 including accidental rounding of large integers through floating point. This
preserves the serialized value rather than promising precision beyond the preserves the serialized value rather than promising precision beyond the
supplied value and its serialization contract. supplied value and its serialization contract.
- **Observable failures.** Values rejected by the serialization contract produce - **Observable failures.** When serialization is used, values rejected by its
presentation errors through the existing reporting lifecycle. Do not silently contract produce presentation errors through the existing reporting lifecycle.
drop unsupported data or substitute arbitrary string representations. 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 **Agreed separate treatment:** native configuration YAML uses explicit core
adaptation with defined cross-format mappings, not blind conversion through the 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 ### Agreed plain-text rendering
Core provides a default plain-text fallback and accepts an optional template **Agreed template boundary:** applications and integrations own the report value
from the application or integration as part of the report handoff. When text is and optional text template. Core prepares and executes templates using Go's
selected, core uses the template if supplied and otherwise renders the selected built-in `text/template`, passing the original Go value supplied in the report
report data using its standard fallback. A template selects text automatically handoff. Templates use Go field names, types, and standard template behavior,
only when the operator omits `--format`; explicit YAML or JSON takes precedence. not JSON field names or CommandKit's intermediate representation. For example,
YAML and JSON use the same selected content and shared representation rules, a Go field `PromptID` tagged `json:"prompt_id"` is accessed as `.PromptID`.
independently of the text
template. Applications do not supply separate YAML/JSON writers.
Recommend a readable hierarchical fallback with named fields, nested values, JSON tags and custom JSON serialization govern structured rendering, not the
and list items. A template can arrange the supplied content as a sentence, template's field access. An exported field tagged `json:"-"` remains accessible
table, or another useful presentation. Core owns template execution, shared to the application's template, and custom JSON serialization does not replace
formatting helpers, and delivery errors. Go's `text/template` and reusable the template input. The application owns that text content choice. Core retains
templates declared once are implementation candidates; the template API, ownership of execution, shared helpers, delivery, and presentation failures.
helper set, and exact fallback layout still need design. 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). When text is selected and a template is supplied, execute it as supplied and
Universal core formats resolve point 5; per-command supported-format lists and deliver its output without applying a second formatting pass. Template syntax
per-format application renderers are not the selected mechanism. 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 ### 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 - **Native documents and multiple results.** Define how native safe YAML
snapshots and ordered multi-scope documents enter the shared representation, snapshots and ordered multi-scope documents enter the shared representation,
and how multiple documents/results appear in JSON and text. Preserve native 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 commands from universal format support. Keep format translation in core and
domain evidence selection in the integrations. domain evidence selection in the integrations.
Exact public signatures, flag integration/collision handling, and replacement Exact public signatures, reusable template preparation and helper functions,
of existing format plumbing are implementation design tasks. The decisions flag integration/collision handling, and replacement of existing format plumbing
above do not reopen content selection, JSON conventions for ordinary report are implementation design tasks. The decisions above do not reopen content
values, universal formats, automatic selection, or joint format delivery. 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 Report serialization does not settle the separate JSON input-number conversion
choices in OD-2 and OD-11. 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. whole upstream object graph just to rename fields or rearrange equivalent data.
Reuse small path, snapshot, Reuse small path, snapshot,
location, and duration projections where they are genuinely needed. Core reuses location, and duration projections where they are genuinely needed. Core reuses
the JSON contract across renderers; migrate YAML-only report tags or provide a the JSON contract across its serialization paths; migrate YAML-only report tags
thin projection where necessary. Native configuration documents follow their or provide a thin projection where necessary. Native configuration documents follow their
explicit adaptation path rather than the ordinary Go-value path. explicit adaptation path rather than the ordinary Go-value path.
Exceptions serve concrete report semantics: preserving absent/null/false/zero 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. Separate content projection from format rendering and from invocation delivery.
Use the existing Reporter and outcome lifecycle for delivery and failures. Use the existing Reporter and outcome lifecycle for delivery and failures.
Share common helpers without forcing text output through a YAML round trip or Text templates receive original Go values. Simple text output uses the logical
forcing semantically different reports into one schema. Validate representative 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 reports and meaningful adaptation boundaries, rather than freezing every
incidental formatting detail in tests. incidental formatting detail in tests.
@@ -526,15 +551,15 @@ incidental formatting detail in tests.
1. **Confirm remaining implementation choices.** Use the accepted flags, report 1. **Confirm remaining implementation choices.** Use the accepted flags, report
content, and automatic format policy as the MVP target. Resolve the remaining content, and automatic format policy as the MVP target. Resolve the remaining
text-template and native-document decisions; specify the public API and native-document decisions; specify the public API, reusable template helpers,
internal conversion design under the agreed JSON representation contract. and internal conversion design under the agreed JSON representation contract.
Resolve outstanding acquisition/binding grammar and flag collisions; use Resolve outstanding acquisition/binding grammar and flag collisions; use
concrete examples to review report details during implementation rather than concrete examples to review report details during implementation rather than
reopening accepted scope. reopening accepted scope.
2. **Implement shared core report output.** Deliver the agreed automatic format 2. **Implement shared core report output.** Deliver the agreed automatic format
policy, universal `--format` selection, format-independent Reporter policy, universal `--format` selection, format-independent Reporter
operation, writer-based API, and shared representation/encoding machinery. 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 in the core feature release. Exercise the public API with core reporting
and an application-owned command example, and consolidate suitable existing and an application-owned command example, and consolidate suitable existing
integration reports onto it. Cover the selected contracts and update their 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. resolution algorithms.
Default tests remain offline and independent of real credentials. 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 Public signatures and shared representation conventions are
documented with implementation. documented with implementation.
- [ ] Core owns universal `--format` options, help, validation, and selection. - [ ] 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. configuration values. Focused configuration values follow the same rules.
- [ ] Plain text, YAML, and JSON ship together; representative reports exercise - [ ] Plain text, YAML, and JSON ship together; representative reports exercise
shared representation and explicit selection across all three. shared representation and explicit selection across all three.
- [ ] Plain text uses the supplied template or core's fallback. Core owns - [ ] Text templates execute with standard `text/template` behavior against the
rendering and errors in both cases. The integration chooses concise/detailed original Go report value, retaining field names and types. JSON tags and custom
content; changing format does not implicitly change the selected detail level. 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; - [ ] The invocation and writer-based public APIs share rendering behavior;
handlers submit report data without their own format switches or encoder handlers submit report data without their own format switches or encoder
setup. Existing quiet-mode, presentation-failure, and domain-outcome behavior setup. Existing quiet-mode, presentation-failure, and domain-outcome behavior
is preserved through the Reporter lifecycle. 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. including JSON tags, supported custom serialization, and selected omissions.
Conflicting YAML tags do not rename fields or change values in YAML output. Conflicting YAML tags do not rename fields or change values in YAML output.
Verify that automatic selection follows the resulting logical shape. 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 items retain their numbers and record the agreed decision. OD numbers are local
to this roadmap, not the retired adoption documents. 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 universal-format, automatic-selection, and joint format-delivery decisions are
now agreed above. Remaining details are listed under now agreed above. Remaining details are listed under
[remaining core reporting decisions](#remaining-core-reporting-decisions). [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 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 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 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. dedicated preview template; a specialized template is not required for initial delivery.
### OD-2: Request controls and provider-parameter grammar ### 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 hand off structured mappings without a text template; core's automatic policy
selects YAML. Universal format choices supersede the earlier YAML-only detailed selects YAML. Universal format choices supersede the earlier YAML-only detailed
restriction. The same selected comparison evidence is handed to core in every 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 Keep the projection close to native report values, using the
[shared reporting approach](#initial-report-implementation-approach) rather than [shared reporting approach](#initial-report-implementation-approach) rather than