Release 1.0.0: release-readiness review, API hardening, and pipeline gates - #26
Merged
Conversation
ganda repo audit flagged missing kanban stage directories, the memsearch scaffold (config + git hooks), and VS Code window-title/icon configuration. All generated by the audit fixer so the repo passes the compliance profile. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- TimeWarp.Nuru/DevCli 3.0.0-beta.71: audit requires latest Nuru; DevCli must match for the shared dev-cli endpoint sources - TimeWarp.Jaribu 1.0.0-beta.13 + TimeWarp.Amuru 1.0.0-beta.34: Jaribu beta.12 pulled Amuru beta.21 -> StreamJsonRpc -> MessagePack 2.5.198, which trips NU1902/NU1903 vulnerability errors under TreatWarningsAsErrors; the new pair drops that chain - TimeWarp.Build.Tasks 1.0.0: required by the assembly-metadata audit check - TimeWarp.Builder 1.0.0-beta.3, NetAnalyzers 10.0.301: routine updates Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The analyzer bump surfaced ~250 latent style violations (IDE0011 braces, IDE0072 switch exhaustiveness, formatting) that blocked every build, which in turn blocked installing bin/dev. Fixes are mechanical with no behavior change: braces added, switch arms named explicitly with identical results, doc-comment XML repaired. Root causes addressed alongside: - .editorconfig had csharp_prefer_braces = when-multiline (hyphen), an invalid value the analyzer silently ignores; corrected to when_multiline:warning so the intended rule is actually enforced - GenerateDocumentationFile is now on (required for IDE0005 to run on build) with CS1591 suppressed - dev-cli suppresses style rules violated by TimeWarp.Nuru.DevCli content files compiled from the NuGet cache, where .editorconfig cannot reach - runfiles (tests/samples/dev-cli) use the portable env -S shebang per audit policy and IDE0211 is suppressed for them since file-based apps require top-level statements Verified: solution builds 0/0, all 33 test runfiles pass, all 5 samples verify, ganda audit 19/19. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The integration itself landed in 1e930f5 but the card was never updated. All checklist items verified working (self-install, clean, check-version via the shared TimeWarp.Nuru.DevCli beta.71 endpoints); Results section records where the final shape differs from the original plan. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… 022 Full library review (25 files, ~7,200 lines) across six subsystem passes ahead of the beta -> 1.0.0 move. 4 blockers (ambiguous WritePanel overload, colored-rule crash on long titles, Unix CursorVisible no-op, prerelease TimeWarp.Builder dependency), 22 majors, ~28 minors. Majors emphasize behavioral contracts that become breaking changes once 1.0 ships. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Terminal.WritePanel("content") and Terminal.WritePanel("content", "header")
were CS0121 ambiguous for consumers because both the 2-param and 4-param
string overloads required default-argument substitution, so neither was
better. The library never noticed: no in-repo code used the positional
forms (tests used named args or the ITerminal extension) and the only
occurrence was an uncompiled XML doc example.
The surviving 4-param overload accepts every previously-compilable call,
so this is source-compatible. Adds a positional-call regression test whose
compilation is the assertion.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Rule.Render: colored rules with titles longer than the width crashed with ArgumentOutOfRangeException because the color branch recomputed the layout from scratch, bypassing the title-only fallback. Layout is now computed once and color only wraps the segments; width is clamped to >= 0. Regression test added. - CursorVisible setter: was Windows-gated so hide/show cursor silently no-oped on Linux/macOS, but only the BCL getter is Windows-only. Gate removed; verified ESC[?25l/h are emitted under a Linux TTY. - TimeWarp.Builder: bumped prerelease beta.3 to the stable 1.0.0 so a stable TimeWarp.Terminal 1.0.0 won't depend on a prerelease (NU5104). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Cross-platform gating corrected to match the BCL: Title setter and parameterless Beep() work on Unix (only their getter/overload counterparts are Windows-only), so their gates are removed. KeyAvailable now also catches InvalidOperationException, which Console throws under redirected stdin — the exact scenario its fallback exists for. Packaging: PackageReadmeFile so nuget.org renders the readme, snupkg symbol packages, and ContinuousIntegrationBuild on release pack. Pipeline: the test step (dev test and both workflow paths) ran `dotnet test` against a solution with zero VSTest projects — a false green. It now runs the tests/*.cs runfiles and fails on any failure, and the release path gains verify-samples + test before pack, so 1.0 cannot publish from an untested commit. README: removed nonexistent .Shrink() from the table quickstart. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Test doubles now match System.Console semantics: Read() consumes constructor input when the key queue is empty (Read/ReadLine share one stream), KeyAvailable reflects every source ReadKey draws from, QueueKey honors shift/ctrl when computing KeyChar, and TestTerminalContext. ClearCurrent can no longer leave a disposed TestTerminal installed as the global Instance. Table contracts: Grow columns floor at max(4, MinWidth) instead of collapsing to zero width, Expand respects MaxWidth caps, AddRow(null) throws eagerly, and TableBuilder.Build() returns an independent snapshot so post-Build builder calls cannot mutate built tables. Security/parity: OSC 8 hyperlink URLs are sanitized (C0 controls and DEL percent-encoded) closing a terminal escape-injection vector, and the static Terminal facade gains the CancelKeyPress event it was missing relative to ITerminal and System.Console. Docs: ITerminal members that platform-gate or swallow exceptions now say so in <remarks> — the silent-failure contract ships documented rather than frozen implicitly at 1.0. All changes covered by new regression tests; full suite 33/33, samples verified, audit 19/19. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The format overloads now use FormatProvider ?? CurrentCulture resolved per call, matching System.Console (and TextWriter.FormatProvider semantics) instead of silently diverging for code migrated from Console. Null default resolves lazily so cultures set after startup (or per-request) are honored; set InvariantCulture for deterministic output. Typed IFormatProvider per BCL convention and placed on Terminal itself for discoverability. TestTerminalContext snapshots and restores it alongside Instance. Release note: format overloads previously used InvariantCulture; they now default to the current culture. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All ConsoleColor-parameter paths — facade Write/WriteLine/WriteErrorLine, static WritePanel/WriteTable, and the ITerminal panel/table extension helpers — now degrade to plain text when the terminal reports SupportsColor false, so NO_COLOR and redirected output no longer receive raw ANSI escapes. Caller-embedded ANSI (string.Cyan(), BorderColor) remains the caller's choice. Release note: colored overloads previously emitted ANSI unconditionally. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Static Terminal.WriteLink now checks SupportsHyperlinks and writes the plain display text when unsupported, matching the ITerminal extension — same philosophy as the SupportsColor gating. Terminal.Instance resolution is now "AsyncLocal wins": the getter returns TestTerminalContext.Current ?? the process-global field, and SetCurrent/Use/ClearCurrent only touch the AsyncLocal — the global is never mutated by the context. This makes the documented parallel test isolation actually true (regression test runs two concurrent Use scopes), moots the disposed-terminal leak path, and keeps direct Terminal.Instance assignment working for serial tests. FormatProvider snapshot/restore is retained. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Unicode width now follows Unicode 16 EAW/emoji-presentation data: the blanket 0x1F000-0x1FAFF wide range made playing cards, alchemical symbols, and dingbats wide and hid the regional-indicator branch, while Tangut/Kana/Nushu and BMP tails were missing. Grapheme measurement no longer hardcodes multi-rune clusters to 2, so NFD combining sequences (decomposed accents) measure 1 while emoji ZWJ/VS16/flag/skin-tone clusters stay 2. ANSI handling covers real streams: the strip/measure regex now matches all CSI finals, all OSC commands, and two-byte ESC sequences instead of SGR-only; WrapText tokenizes on visible whitespace so mid-word styling no longer splits words; hyperlink and SGR are independent wrap carry channels (closed links stay closed across line breaks). Truncation preserves styling: new ANSI/grapheme-aware TruncateVisible helpers back both panel WordWrap(false) lines (which previously overflowed through the right border) and table cell End/Start/Middle truncation (which previously stripped all color). Style at a cut is reset before ellipsis/border; style opened before a Start/Middle cut replays onto the kept tail. All behavior covered by new regression tests; suite 33/33, samples verified, audit 19/19. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ReadKey() lived on IConsole, forcing stream-oriented implementations like TestConsole to throw NotSupportedException in violation of the interface docs. Key-by-key input is interactive-terminal functionality, so it now lives on ITerminal alongside ReadKey(bool); TestConsole's throwing member and TimeWarpConsole's implementation are removed, and a contract test pins the placement. BREAKING for IConsole consumers that called ReadKey (intentional pre-1.0 correction). The IsAotCompatible claim is now verified rather than asserted: the blanket IL* NoWarn is removed from the root props, the library builds clean under full trim/AOT analysis, and the dev-cli native AOT publish consuming it succeeds. IL suppressions remain only in tools/dev-cli, scoped and documented, for TimeWarp.Nuru.DevCli package-content files that use reflection-based JsonSerializer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…5.6.0 No new diagnostics under the newer analyzer; full build, all 33 test runfiles, sample verification, AOT dev-cli publish, and audit all green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Core terminal: NO_COLOR honored per spec (non-empty only) plus TERM=dumb; GetCursorPosition atomic; TreatControlCAsInput follows the swallow-and-default policy; IsInteractive requires both stdin and stdout unredirected. Color/facade: ConsoleColor SGR mapping corrected (Dark* = 30-37, normal = bright 90-97 — visible-output release note); null colored messages write plain per docs; symmetry overloads added (Write and WriteErrorLine fg+bg, WriteLinkLine); CreateLink parameter order aligned to (url, displayText) matching WriteLink (breaking vs beta); widget fg/bg colors survive embedded resets from BorderColor/styled cells; Pad*/Center clamp negative widths. Test double: EOF sentinel, [CLEAR] marker, and single-threaded design documented publicly; SimulateCancelKeyPress throws instead of silently no-oping; Dispose no longer disposes consumer-assigned streams. Pipeline/docs: release runs fail when the GitHub tag mismatches the props version; PackageProjectUrl/RepositoryType/PackageReleaseNotes added; README leads with TestTerminalContext; Expand/BorderStyle.None interaction documented. Five judgment items accepted with rationale on the card (Windows-legacy interface members, unambiguous overload pairs, net10.0-only TFM, Terminal type name, grow-overhead moot after earlier fix). Task 022 checklist is now fully resolved: 4 blockers, 28 majors, all minors fixed or explicitly accepted. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All 56 findings resolved across 12 commits: 4 blockers and 28 majors fixed, minors fixed or explicitly accepted with rationale recorded per item. The library is release-ready pending the version bump to 1.0.0 and release notes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MoveBufferArea, CursorSize, SetWindowSize, SetWindowPosition, SetBufferSize, WindowLeft, WindowTop, LargestWindowWidth, and LargestWindowHeight are legacy Windows console-host features that do not work in Windows Terminal (the Windows 11 default) let alone anywhere else. Keeping them in ITerminal would freeze a permanent stub burden into the 1.0 contract for every implementer, for behavior nobody can rely on. Removed from ITerminal, TimeWarpTerminal, TestTerminal, and the static Terminal facade. WindowWidth/WindowHeight/BufferWidth/BufferHeight are demoted to get-only on the interface and facade (setters were conhost-only); TestTerminal keeps public setters so tests can configure geometry. Reverses the earlier "accepted for Console parity" triage decision on task 022 — parity with APIs that no modern terminal honors is tech debt, not compatibility. BREAKING vs beta (intentional, pre-1.0). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The 1.0 readiness sweep changed behavior the skill still described: CreateLink's example used the pre-1.0 reversed argument order (it would have linked to the URL "text"), MinWidth's property default is null (4 is the layout floor, not the stored default), and the static testing section taught the raw Instance swap instead of the parallel-safe TestTerminalContext.Use scope. Also documents the new surface: FormatProvider culture contract, static WriteLinkLine, CancelKeyPress, fg+bg overload symmetry, get-only geometry properties, ReadKey's home on ITerminal, and the self-gating color/hyperlink behavior (pitfall updated to scope the manual SupportsColor check to embedded ANSI only). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
timewarp-software's rebuild.yml already listens for repository_dispatch (type: rebuild) from library repos; this implements the sending side. After a successful NuGet push, the release workflow fires the dispatch with the package id and version in the client payload so the site reflects the new release immediately instead of waiting for the nightly cron. Best effort by design: a dispatch failure warns but never fails a release that already pushed, since the nightly rebuild is the documented backstop. Auth: locally gh's stored credentials suffice. In Actions the default GITHUB_TOKEN cannot reach other repos (the recent Copilot-CLI PAT changelog does not change this), so workflow.yml passes GH_TOKEN from a REBUILD_DISPATCH_TOKEN secret — a fine-grained PAT or GitHub App token with write access to timewarp-software; absent secret = skipped dispatch with a warning. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replaces the fine-grained-PAT secret approach with a short-lived installation token minted per release run via actions/create-github-app-token, using org-level configuration (REBUILD_APP_ID variable + REBUILD_APP_PRIVATE_KEY secret) so every library repo can adopt the same pattern unchanged. No long-lived PAT, nothing expires annually, and the token is scoped to exactly timewarp-software for the duration of one run. The mint step is guarded: unconfigured app = skipped step = empty GH_TOKEN = the dev-cli dispatch warns non-fatally and the nightly rebuild remains the backstop. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
First stable release, following the full release-readiness review (task 022). Release notes accompany the GitHub release. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Promotes TimeWarp.Terminal from 1.0.0-beta.13 to the first stable release. Everything here came out of the full release-readiness code review (task 022: 4 blockers, 28 majors, all minors fixed or explicitly accepted), executed across 22 commits.
Breaking changes vs 1.0.0-beta.13
Terminal.Write/WriteLine(format, ...)now use the current culture (Console parity) instead of InvariantCulture. SetTerminal.FormatProvider = CultureInfo.InvariantCultureto restore deterministic output.ReadKey()moved fromIConsoletoITerminal: key-by-key input is interactive-terminal functionality;TestConsole.ReadKey()(which threwNotSupportedException) andTimeWarpConsole.ReadKey()are removed.ITerminal/implementations/static facade:MoveBufferArea,CursorSize,SetWindowSize,SetWindowPosition,SetBufferSize,WindowLeft,WindowTop,LargestWindowWidth,LargestWindowHeight.WindowWidth/WindowHeight/BufferWidth/BufferHeightare now get-only on the interface and facade (TestTerminalkeeps setters for test configuration). These APIs don't work in Windows Terminal, let alone elsewhere.AnsiHyperlinks.CreateLink(url, displayText): parameter order aligned withWriteLink.TableBuilder.Build()returns a snapshot: building twice yields independent tables; post-Build builder calls no longer mutate built tables.Dark*colors map to SGR 30-37 and normal colors to bright 90-97 (previously dark/normal collided) — visible output changes forConsoleColoroverload users.WritePanel(string, string?)overload removed: it madeTerminal.WritePanel("content")ambiguous (CS0121); the remaining overload accepts every previously-compilable call.Highlights
ConsoleColoroverloads,WritePanel/WriteTablecolors, andWriteLink/WriteLinkLinedegrade to plain text whenSupportsColor/SupportsHyperlinksis false (honors non-emptyNO_COLOR,TERM=dumb, redirection).Terminal.Instanceresolves through the async-localTestTerminalContext, making the documented parallel test isolation actually true; the context never mutates the global.WordWrap(false)truncates instead of breaking the border.CursorVisible/Titlesetters andBeep()now work on Linux/macOS (the BCL gates only their getters/overloads);KeyAvailableno longer throws under redirected stdin; platform contracts documented on everyITerminalmember.Read/ReadLine/ReadKeyshare one input source,KeyAvailablereflects all key sources,QueueKeyhonors shift/ctrl.Verification
Solution builds 0 warnings / 0 errors under the strict analyzer set, all 33 test runfiles pass, all 5 samples verify,
ganda repo audit19/19, native AOT publish succeeds.🤖 Generated with Claude Code