Adopt JSON conventions for shared report representation

This commit is contained in:
2026-11-06 21:09:19 +00:00
parent e82101434f
commit 408383db60
2 changed files with 72 additions and 42 deletions

View File

@@ -167,8 +167,10 @@ content selection, core-owned rendering, a text fallback 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; representation, template, and
native-document details remain there. XML is removed from current consideration.
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
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
existing commands without per-command adoption.

View File

@@ -398,24 +398,47 @@ existing reporting facility rather than creating a second delivery lifecycle.
### Agreed shared representation rules
Centralize representation rules as well as encoders. Define how report fields,
field names, omissions, numbers, and custom serialized values become output so
different renderers do not silently give the same report different meanings.
The objective is to prepare a report once and render that representation in
multiple formats, avoiding a separate translation tree per format.
**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.
Use Go report values with small, explicit adaptations where needed. Owned
report values follow shared naming and representation conventions; suitable
upstream values can reuse their established serialization contracts through a
shared adapter. Preserve meaningful distinctions among absent, null, false,
zero, and empty values, and avoid numeric precision loss in intermediate
conversions. Paths, durations, and other values needing a different presentation
can use thin projections. Do not assume JSON tags or custom JSON serialization
automatically have the same meaning to a YAML encoder.
Reuse the standard library's field selection, JSON tags, omission rules, nested
value handling, and supported custom JSON serialization. Avoid a new CommandKit
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.
Exact conventions, serialization-contract selection, and adapter APIs need to be
specified during design. A large public document model or custom reflection
framework is not selected by this decision.
- **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
`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
does not additionally hide zero, false, empty, or null values for brevity.
Preserve the remaining distinctions among absent, null, false, zero, and empty
values through conversion and rendering.
- **Preserved numeric values.** Avoid precision loss in intermediate conversion,
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.
**Agreed separate treatment:** native configuration YAML uses explicit core
adaptation with defined cross-format mappings, not blind conversion through the
ordinary JSON path. Preserve native YAML semantics and disclosure rules when
YAML is requested, and avoid silent loss of richer YAML information. The adapter
API, supported mappings, and multiple-document behavior remain part of the
native-document decision below. This is not an exemption from universal formats
or permission for integration-owned formatting pipelines.
This approach reduces new machinery by reusing standard serialization and
centralizing the remaining conversion and rendering work. Exact internal
representation and adapter APIs remain implementation design tasks; a large
public document model is not selected. Validate representative reports before
assuming that an upstream type can be handed off without adaptation.
### Agreed plain-text rendering
@@ -441,10 +464,6 @@ per-format application renderers are not the selected mechanism.
### Remaining core reporting decisions
- **Shared representation contract.** Specify field/tag and custom-marshaling
precedence, omission and scalar rules, supported Go report values, and how
unsupported values are reported. Keep adapters explicit and avoid silent
numeric loss. This concerns report data, not arbitrary runtime objects.
- **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
@@ -458,8 +477,10 @@ per-format application renderers are not the selected mechanism.
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, universal formats, automatic selection,
or delivery of all three initial formats together.
above do not reopen content selection, JSON conventions for ordinary report
values, 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.
## Initial report implementation approach
@@ -476,13 +497,14 @@ Use the capability in core, both integrations, and a maintained application-owne
command example. A separately versioned output module or custom serialization
engine is not needed. Follow module release/dependency ordering under OD-7.
Prefer directly encoding suitable native inspection/report values or a thin Go
projection with serialization tags. 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. Types whose
intended representation depends on JSON tags or custom JSON serialization cannot
be assumed to encode identically under YAML; reuse their supported serialization
or provide a small explicit adapter rather than inventing a reflection framework.
Prefer handing off suitable native inspection/report values or a thin Go
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
explicit adaptation path rather than the ordinary Go-value path.
Exceptions serve concrete report semantics: preserving absent/null/false/zero
and empty collections, expressing paths and durations readably, projecting safe
@@ -504,8 +526,8 @@ 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
core representation, text-template, and native-document decisions; specify
the public API.
text-template and native-document decisions; specify the public API 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.
@@ -562,8 +584,8 @@ CommandKit to retest PromptKit rendering, schema, namespace, or ConfigKit
resolution algorithms.
Default tests remain offline and independent of real credentials.
- [ ] Remaining representation, text-template, and native-document decisions
are recorded. Public signatures and shared representation conventions are
- [ ] Remaining text-template and native-document decisions are recorded.
Public signatures and shared representation conventions are
documented with implementation.
- [ ] Core owns universal `--format` options, help, validation, and selection.
Added core formats work with existing commands without refactoring or local
@@ -585,10 +607,15 @@ Default tests remain offline and independent of real credentials.
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.
- [ ] Representative report values preserve field meanings, selected omission
rules, null/false/zero/empty distinctions, and numeric values. Explicit
upstream serialization adapters honor the selected contract rather than
accidentally applying a different encoder's tag or marshaling rules.
- [ ] Ordinary Go reports follow the standard JSON contract across formats,
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.
- [ ] Representative reports retain null/false/zero/empty distinctions and
numeric values through conversion, including large integers. Unsupported
values and serialization failures remain observable presentation failures.
- [ ] Native YAML follows explicit core adaptation with the selected mappings,
retaining native meaning without silent loss through JSON conversion.
- [ ] Core, both integrations, and a maintained application-owned command
exercise the public reporting capability. Suitable duplicate selection and
encoding code is removed; core has no optional integration dependencies.
@@ -744,9 +771,10 @@ 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, text fallback/template, universal-format, automatic-selection,
and joint format-delivery decisions are now agreed above. Their remaining design
details are listed under [remaining core reporting decisions](#remaining-core-reporting-decisions).
The core ownership, JSON representation conventions, text fallback/template,
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).
Outstanding integration choices are provider JSON decoding in OD-2, namespace
applicability in OD-3, empty comparison collections and binding design in OD-9,
and override grammar/acquisition details in OD-11. Exact helper names and report