Skip to content

feat: v0.6.0 — Oneline-first default output#249

Open
richlander wants to merge 35 commits intomainfrom
feature/oneline-default
Open

feat: v0.6.0 — Oneline-first default output#249
richlander wants to merge 35 commits intomainfrom
feature/oneline-default

Conversation

@richlander
Copy link
Owner

Summary

Breaking change: switches dotnet-inspect to oneline columnar output by default, making the tool agent-first. Inspired by git log --oneline and docker images.

Key Changes

Foundation

  • OutputFormat resolver — New DOTNET_INSPECT_FORMAT env var (oneline|markdown|json). Precedence: CLI flags → env → default (oneline)
  • --markout--markdown — Renamed for clarity. This is the opt-in for rich document output
  • Version bump to 0.6.0, Markout upgraded to 0.9.0

Default Switching

  • Oneline is the default for all commands. No verbosity levels in oneline mode
  • -v:* implies --markdown — Any verbosity flag switches to markdown document view
  • Type shows --shape by default for single-type resolution (e.g., type System.Text.Json JsonSerializer)

Data Model Cleanup

  • Find — Unified FindResultView/FindRow serves both OneLineWriter and MarkdownWriter. Deleted separate oneline view
  • TypeApiOneLineRow uses ReturnType + Detail columns (overload counts, accessors) instead of raw Signature
  • Service refactoring — Match classification moved from FindCommand into TypeSearchService. FindCommand is now a thin orchestrator (~110 lines, down from ~326)

Dead Code Removal

  • Removed unused FindJsonContext/FindCompactJsonContext (replaced by TypeFindResult contexts)
  • Removed unused WriteJsonOutput method and Showing/totalCount plumbing

Docs

  • SKILL.md — Updated for v0.6.0 defaults, removed --oneline from all examples
  • llms.txt — Updated LLM guide for new defaults
  • Design doc — Service model refactoring roadmap (docs/design/service-model-refactoring.md)

Testing

All 621 tests pass (0 failures, 31 skips for missing optional tools). Smoke tested: type surface, single type (shape), member, find, package, -v:m markdown switch.

What's Next (not in this PR)

  • --select/--columns/--fields unified projection (replacing -s/-S)
  • Assembly/library oneline support

richlander and others added 29 commits February 23, 2026 15:55
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add OutputFormat enum (OneLine, Markdown, Json) and OutputFormatResolver
- Precedence: explicit CLI flags (--json/--markdown/-v:*) → DOTNET_INSPECT_FORMAT env → default (OneLine)
- Any -v:* flag implies --markdown (verbosity is a markdown concept)
- Rename --markout to --markdown across SharedOptions and command definitions
- Add SharedOptions.ResolveFormat() helper for parsers

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- All parsers now use opts.ResolveOneLine() which defaults to OneLine
- --markdown or any -v:* flag switches to markdown output
- DOTNET_INSPECT_FORMAT env var can override (oneline|markdown|json)
- Propagate OneLine/NoHeader through RouteToPlatformAssembly for
  platform→package fallthrough (e.g., System.CommandLine)
- Precedence: explicit CLI flags → env → default (oneline)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Unify find views: merge FindOneLineView into FindResultView with
  Match/Sim columns. One view serves both OneLineWriter and
  MarkdownWriter via [MarkoutIgnoreFields] attributes.
- Type oneline: ApiOneLineRow now uses ReturnType + Detail columns
  (from recovery branch) instead of raw Signature.
- Shape default: single-type resolution shows --shape by default.
  Markdown (-v:* or --markdown) overrides to table view.
- Simplify FindCommand output: one WriteOutput path picks writer
  based on OneLine flag, eliminating separate rendering methods.
- Delete FindOneLineView/FindOneLineRow (consolidated into FindRow).
- Update tests for unified view model and new defaults.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove --oneline from examples where it's now the default
- Document --markdown flag and -v:* for rich output
- Update decision tree: shape is default for single type
- Update version to 0.6.0 in SKILL.md header
- Add --markdown to flag compatibility matrix

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Documents the gap between service models (TypeSearchResult,
InspectionResult) and view models, with concrete proposals for
pushing oneline-compatible shapes into the service layer.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ervice

FindCommand is now a thin orchestrator: parse options → call service → route output.

- Add FindTypesAsync to TypeSearchService that returns List<TypeFindResult> directly
- Move multi-pattern matching, partial matching, similarity scoring into service
- Delete ExecuteMultiPatternAsync, ExecuteSinglePatternAsync, ConvertToRawData
- Remove dead FindJsonContext/FindCompactJsonContext (replaced by TypeFindResult contexts)
- Remove unused Showing field and totalCount/limit params from BuildView
- Preserve optimized single-pattern path for non-oneline queries

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Member smoke test: drop 'JsonSerializer' grep (not in oneline member output)
- Add separate oneline (.txt) and markdown (.md) smoke tests for type/member
- Rename oneline output files to .txt so markdownlint only validates markdown
- Fix markdownlint: add language tags to fenced code blocks in design doc

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
One compact JSON object per line, like `docker images --format json`.
Streaming-friendly: each line is a self-contained TypeFindResult that
can be piped through grep and jq independently.

- Replace FindJsonWriter array serialization with per-line JSONL
- Consolidate two JSON contexts into single TypeFindResultJsonlContext
- Update test to validate JSONL (each line is valid JSON object)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Same pattern as find: one compact JSON object per line.
Consolidate two JSON contexts into single PackageSearchJsonlContext.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Eliminates confusion: 'search' was an alias for 'find' (type search),
while 'package search' searches NuGet. Now only 'find' does type search
and 'package search' remains the NuGet discovery command.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ryLines

Add SelectResolver with WriteDiscoveryLines helper that formats discovery
output with consistent 24-char padding and Debug.Assert for name overflow.
Replace all 10 inline Console.WriteLine discovery patterns across 5 files.

Assert immediately catches 'RID-Specific Pointer Package' (28 chars)
overflowing the column — left as-is to observe before renaming.

Add output-format-analysis.md documenting insights from the older
feature/default-oneline branch: verbosity as writer property, renderer
registry pattern, library oneline gap.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- type --tree is alias for --shape (type hierarchy + members)
- package --tree is alias for --layout (file tree)
- Deprecate --dependencies on package and library with tips
  pointing to 'depends' command
- Rename 'RID-Specific Pointer Package' to 'RID Pointer Package'
  to fit 24-char discovery column (Debug.Assert was catching it)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Library/assembly command now defaults to oneline like package/type/member.
Markdown output activates with --markdown or any -v:* flag (UseMarkdown
computed property: Markdown || Verbosity >= Normal).

- Add Markdown, OneLine properties to AssemblyOptions
- Add UseMarkdown computed property for format branching
- Wire --markdown, -S, --select into library command parser
- Add bare -S discovery (sections + fields) to AssemblyCommand
- Branch OutputFormatter.WriteLibraryResult into oneline vs markdown
- Multi-assembly WriteLibraryResults renders each via OneLineWriter

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add Columns and Fields options to SharedOptions with ZeroOrOne arity
(same discovery pattern as --select). Bare flag = discover, with
value = filter.

- Add --columns and --fields to SharedOptions, wire into all parsers
- Add Columns/Fields properties to all option records
- Split BuildProjection to accept separate select/columns/fields arrays
- Columns → MarkoutProjection.IncludeColumns, Fields → IncludeFields
- --select remains for section selection (backpressure)
- Add IsDiscoveryMode helper (any bare flag = discovery)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace per-command bare -S handling with unified SelectResolver.Discover
that handles all three bare flags (--select, --columns, --fields).

Discovery mode (any bare flag):
- --select bare → sections + root fields
- --columns bare → columns from schema
- --fields bare → fields from schema

Execute mode (all flags have values):
- --select → section filter (backpressure)
- --columns → MarkoutProjection.IncludeColumns
- --fields → MarkoutProjection.IncludeFields

- Add SelectResolver.IsDiscovery and Discover methods
- Replace ListSelect parse results with Discovery(select, columns, fields)
- Remove ListSelectableNames helpers (dead code)
- All commands use consistent detection via opts.IsDiscoveryMode

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When --select has values in execute mode, resolve matching section names
and set IncludeSections for backpressure. This lets -S replace -s for
section selection with the same verbosity promotion behavior.

- Add SelectResolver.ResolveSelectAsSections (case-insensitive match)
- Wire into PackageCommand, AssemblyCommand, ApiCommand after discovery
- Section names win: if value matches a known section, it becomes a filter
- Existing verbosity promotion (GetRequiredVerbosity) applies automatically

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add [MarkoutIgnoreFields(nameof(OneLineWriter))] to LibraryInspectionView
so OneLineWriter skips field-list rendering instead of emitting a warning.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Switch from [MarkoutIgnoreFields(nameof(OneLineWriter))] on view classes
to MarkoutWriterOptions.SuppressedShapes on the writer options. This is
the global opt-out for the expert lifestyle — set once at the call site
rather than annotating every view class.

- Revert MarkoutIgnoreFields on LibraryInspectionView
- Set SuppressedShapes = MarkoutShape.FieldList on library OneLineWriter opts
- Switch to ProjectReference for local Markout (pending 0.9.2 publish)
- Suppress MARKOUT005 (field/section name collisions to fix separately)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fields are not a separate projection axis — in oneline mode they don't
exist (the data is columns), and in markdown mode they're fixed summary
data. The projection model is now two axes: sections (--select) and
columns (--columns).

- Remove Fields option from SharedOptions, all option records, all parsers
- Remove ParseFields, bare --fields discovery branch from SelectResolver
- Remove fields parameter from BuildProjection and all Discover/IsDiscovery calls
- 19 files changed, net -53 lines

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SuppressedShapes is now available in the published package.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Both the file-path route and platform assembly route were missing
Markdown = parseResult.GetValue(opts.Markdown) when constructing
AssemblyOptions. This caused --markdown to be ignored when using
the router (e.g. 'dotnet-inspect System.Text.Json --markdown').

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace AutoFields=false + hand-written GetCompactFields() with
AutoFieldsCount=7 on LibraryInspectionView. The first 7 scalar
properties (Name, Version, TFM, Arch, Size, Source, Modified) are
now declared as real properties and auto-rendered as the hero summary.

- Delete GetCompactFields() and Summary property
- Delete ~15 dead scalar properties (FileType, PdbFormat, etc.)
- Inline SourceLinkStatus into GetSymbolsFields()
- Update test to assert hero line IS present (was asserting absence)
- Net -91 lines
- Requires Markout 0.9.3 (ProjectReference for now)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Includes AutoFieldsCount, NamingPolicy, type-level SkipNull,
and test parallelism fix.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The hero field list (Name | Version | TFM | ...) is 100% redundant
with the Library Info section table. Now only shown at -v:q where
no sections appear. --markdown (default minimal) goes straight to
the Library Info table.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Picks up NamingPolicy, FieldLayout, and SkipNull propagation to
nested/element types, enabling declarative section types.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the imperative 40-line GetAssemblyInfoFields() method with a
declarative LibraryInfoSection class using Markout source generation.

The section class uses:
- NamingPolicy.PascalCaseWords for display names (AssemblyVersion -> Assembly Version)
- FieldLayout.LineBreaks for individual field rendering
- [MarkoutSkipNull] to hide null/empty fields
- [MarkoutBoolFormat] for Deterministic/Reproducible (Yes/No)

This changes Library Info from a field table (Property|Value columns)
to a field list (Key: Value per line), which is cleaner and consistent
with other section rendering.

Requires Markout 0.9.5 (PR #75 + PR #76).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ction types

Replace the two remaining imperative field-builder methods with
declarative [MarkoutSerializable] classes following the LibraryInfoSection
pattern:

- SymbolsSection: PDB format/location, SourceLink status, publisher,
  repository, and Windows PDB warnings. Uses [MarkoutPropertyName] for
  acronyms (PDB Format, PDB Location, PDB Path, Repository URL).

- SourceLinkAuditSection: Status and embedded count.

- Missing Source Files: Separate List<string> section rendered as a
  bulleted list, independently queryable via --select.

Both use NamingPolicy.PascalCaseWords, FieldLayout.LineBreaks, and
[MarkoutSkipNull]. This removes ~60 lines of imperative if/add boilerplate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@richlander richlander force-pushed the feature/oneline-default branch from 69df382 to 1a37a43 Compare February 25, 2026 05:07
richlander and others added 6 commits February 24, 2026 22:19
Move Source, Lowered C#, IL, and Annotated IL code sections from
ApiTypeView to a new MemberCodeView class. These sections are only
populated by the member command path, not by the type command.

This eliminates the MARKOUT005 'Source' field/section collision —
the Source field (Platform/NuGet origin) and Source section (decompiled
code) were different concepts sharing the same name on one type.

MemberCodeView is serialized separately after the main view, preserving
the existing output format. ApiTypeView holds a [MarkoutIgnore] reference
to MemberCodeView for the command layer to populate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Markout 0.9.7 removes the MARKOUT005 diagnostic entirely, so the
NoWarn suppression is no longer needed. TreatWarningsAsErrors remains
enabled with zero warnings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Switch to ProjectReference for local Markout development
- FieldLayout: LineBreaks/LineBreaksDoubleSpace → Vertical
- Add FieldLayout.Inline on hero summary views (LibraryInspectionView,
  TypeView, CliApiSurface) since default changed from OneLine to Vertical
- Remove SuppressedShapes=FieldList (OneLineWriter now handles fields)
- Remove MarkoutIgnoreFields from FindViews, add MarkoutIgnore on Matches
- MarkoutField.Create → constructor with string values
- TreeNode(text, children) → TreeNode(text) { Children = children }
- WriteList/WriteField API signature updates
- UseMarkdown: Verbosity >= Normal → Minimal so any -v flips to markdown

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add -k/--kind option to filter by type kind (class, struct, interface,
enum, delegate) in multi-type listings and by member kind (method,
property, field, event, constructor) in single-type views. Supports
abbreviations (prop, ctor) and plurals (methods, properties).

Remove --sourcelink-only CLI option and its backing implementation
as dead code — the SourceLinkOnly property was set but never read.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the ApiOptions god-object with a proper type hierarchy:
ApiOptions (base) → TypeOptions and MemberOptions. Each command now
has its own ExecuteAsync with only the logic it needs, while shared
helpers (source resolution, output rendering) stay on ApiCommand.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant