You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add a bounded-output layer that mirrors the bounded 1 MiB input cap (spec 001): --fields field projection, --limit/--cursor pagination, and envelope-level truncated: true / next_cursor signaling for list commands. Unbounded list
output otherwise lands directly in an agent's context window, defeating the
determinism and predictability guarantees the library exists to protect.
User Story
As an LLM agent driving an ax-go CLI, I want list commands to project only the
fields I ask for and page results under an explicit limit, So that a large
result set cannot blow my context window and I can resume iteration with a
stable cursor instead of re-fetching everything.
Problem Statement
ax-go caps input at 1 MiB at the read boundary (spec 001, config/ DefaultMaxBytes), but places no ceiling on output. A list command
over a large collection emits every row, every field, in one payload — the
bounded-input discipline has no bounded-output counterpart. Agents pay for
every token; an unbounded list is both a cost and a correctness hazard (the
tail may be silently dropped by a downstream buffer with no truncated signal).
This is P2 because cursor semantics across heterogeneous commands need a real
design pass (opaque vs. field-based cursors, stability under concurrent
mutation, determinism of the cursor token itself).
Proposed Solution
Introduce an additive output-budget layer in the contract packages plus opt-in
persistent flags, framed as complementary to the existing NDJSON streaming and
output-determinism harness (spec 006):
Technical Approach
Add three optional persistent flags alongside the existing agent-safety set: --fields (comma-separated projection allowlist), --limit (max items), --cursor (opaque continuation token). Register them the same way --format/--dry-run/--idempotency-key are registered, via internal/cli constants + EnsurePersistentStringFlag/Int.
Define an additive list-result envelope in contract/: either a dedicated ListEnvelope[T] wrapping Envelope[T] with Truncated bool + NextCursor string (omitempty), or a Page *PageInfo sub-struct on the
envelope. Chosen shape is a Spec Kit design decision; both stay additive and
additive-tolerant (Constitution XI) — existing non-list envelopes are
unaffected.
Provide a projection helper (contract-side) that filters marshaled output to
the --fields allowlist deterministically (stable key order), so projection
never introduces non-determinism.
Cursor semantics are the hard part and get their own research pass: token must
be opaque, deterministic for identical inputs, and documented as
non-deterministic only where it legitimately encodes position state.
Server-side/database pagination adapters — the library defines the envelope + flag contract, not storage integration
Retrofitting pagination onto NDJSON streaming (streaming is inherently unbounded-by-design; this targets bounded list envelopes)
Technical Notes
New envelope fields and flag/schema metadata live in the CONTRACT packages
(contract/, schema/), never the runtime facade, so thin consumers pin the
shape without compiling the telemetry stack. Everything is additive and
additive-tolerant (Constitution XI) — a new flag/field is additive; renaming or
retyping an existing one would be breaking (not proposed here). Output stays
byte-identical deterministic; the cursor token, if position-encoding, must be
documented as a non-deterministic field. Routes through the Spec Kit workflow
(issue → spec → plan → tasks); the cursor-semantics design is the core research
question and should not be pre-decided in this issue.
Testing Strategy
Unit tests for --fields projection (key allowlist, stable order) and --limit truncation boundary
Golden-file tests for the list envelope with truncated/next_cursor and for the __schema output gaining the three flags
Round-trip test: next_cursor fed back as --cursor yields the contiguous next page
Determinism harness (spec 006 / internal/testutil) coverage on the paginated + projected path
Overview
Add a bounded-output layer that mirrors the bounded 1 MiB input cap (spec 001):
--fieldsfield projection,--limit/--cursorpagination, and envelope-leveltruncated: true/next_cursorsignaling for list commands. Unbounded listoutput otherwise lands directly in an agent's context window, defeating the
determinism and predictability guarantees the library exists to protect.
User Story
As an LLM agent driving an ax-go CLI, I want list commands to project only the
fields I ask for and page results under an explicit limit, So that a large
result set cannot blow my context window and I can resume iteration with a
stable cursor instead of re-fetching everything.
Problem Statement
ax-go caps input at 1 MiB at the read boundary (spec 001,
config/DefaultMaxBytes), but places no ceiling on output. Alistcommandover a large collection emits every row, every field, in one payload — the
bounded-input discipline has no bounded-output counterpart. Agents pay for
every token; an unbounded list is both a cost and a correctness hazard (the
tail may be silently dropped by a downstream buffer with no
truncatedsignal).This is P2 because cursor semantics across heterogeneous commands need a real
design pass (opaque vs. field-based cursors, stability under concurrent
mutation, determinism of the cursor token itself).
Proposed Solution
Introduce an additive output-budget layer in the contract packages plus opt-in
persistent flags, framed as complementary to the existing NDJSON streaming and
output-determinism harness (spec 006):
Technical Approach
--fields(comma-separated projection allowlist),--limit(max items),--cursor(opaque continuation token). Register them the same way--format/--dry-run/--idempotency-keyare registered, viainternal/cliconstants +EnsurePersistentStringFlag/Int.contract/: either a dedicatedListEnvelope[T]wrappingEnvelope[T]withTruncated bool+NextCursor string(omitempty), or aPage *PageInfosub-struct on theenvelope. Chosen shape is a Spec Kit design decision; both stay additive and
additive-tolerant (Constitution XI) — existing non-list envelopes are
unaffected.
the
--fieldsallowlist deterministically (stable key order), so projectionnever introduces non-determinism.
be opaque, deterministic for identical inputs, and documented as
non-deterministic only where it legitimately encodes position state.
__schemaautomatically (they flow throughinternal/schemaflag reflection) — this is where Richer per-flag __schema semantics (defaults/enums/examples) #28's richer per-flagsemantics would describe them.
Files Likely Affected
internal/cli/cli.go- new flag-name constants +EnsurePersistentIntFlagexecute.go- register the new persistent flags inprepareCommandcontract/json.go- additive list/pagination envelope shape + projection helpercontract/context.go- context carriers for resolved limit/cursor/fields (optional)json.go- root-package re-exports of any new contract symbolsschema/schema.go/internal/schema/schema.go- flag reflection surfaces the new flagsexamples/integration/main.go- demonstrate a paginated/projected list command (thestreamcommand atstreamCommandNameis the model)internal/testutil- determinism harness coverage for the paginated pathAcceptance Criteria
--fields,--limit,--cursorare recognized persistent flags surfaced in__schema--limitemitstruncated: trueand a non-emptynext_cursor; passing that cursor back returns the next page deterministically--fieldsprojects output to exactly the requested keys with stable orderingEnvelope[T]output is byte-identical for non-list commandsOut of Scope
Technical Notes
New envelope fields and flag/schema metadata live in the CONTRACT packages
(
contract/,schema/), never the runtime facade, so thin consumers pin theshape without compiling the telemetry stack. Everything is additive and
additive-tolerant (Constitution XI) — a new flag/field is additive; renaming or
retyping an existing one would be breaking (not proposed here). Output stays
byte-identical deterministic; the cursor token, if position-encoding, must be
documented as a non-deterministic field. Routes through the Spec Kit workflow
(issue → spec → plan → tasks); the cursor-semantics design is the core research
question and should not be pre-decided in this issue.
Testing Strategy
--fieldsprojection (key allowlist, stable order) and--limittruncation boundarytruncated/next_cursorand for the__schemaoutput gaining the three flagsnext_cursorfed back as--cursoryields the contiguous next pageinternal/testutil) coverage on the paginated + projected pathRelated
__schemasemantics for the new flags), feat: unified multi-format JSON codec (JSON/Hujson/JSON5/NDJSON/JSONL) with auto-detection and convert API #53 (multi-format JSON codec), __schema: enumerate non-deterministic fields per command output #16 (non-deterministic field enumeration fornext_cursor)