Skip to content

Icod.Terminal 1.14.0

Choose a tag to compare

@github-actions github-actions released this 14 Sep 14:30
· 278 commits to main since this release
b6284fd

Icod.Terminal 1.14.0

Icod.Terminal 1.14.0 is the persistent-raster lifecycle-observability release for the stable 1.x line.

It builds directly on 1.13 relative placement ownership. The release does not add a terminal-side object database or passive remote existence probe. Instead, it exposes the lifecycle certainty that Icod.Terminal already owns locally through one immutable, backend-neutral snapshot on each persistent resource and placement handle.

Public API additions

Version 1.14 adds:

public enum TerminalRasterOwnershipStatus {
	Current,
	Stale,
	Released,
	Disposed
}

public enum TerminalRasterOwnershipLossReason {
	None,
	SessionStateLost,
	ResourceMissing,
	ParentPlacementLost,
	AncestorReleased,
	ResourceReleased,
	ExplicitDisposal
}

public readonly record struct TerminalRasterOwnershipState(
	TerminalRasterOwnershipStatus Status,
	TerminalRasterOwnershipLossReason LossReason
);

and one synchronous read-only property on both opaque persistent handle types:

public TerminalRasterOwnershipState OwnershipState { get; }

No other public API is required for the release.

What the states mean

Current means the handle remains current under Icod.Terminal's local ownership model. It is not authentication and is not proof that terminal-resident storage or placement still exists at the instant of observation.

Stale means terminal-resident certainty was lost. The semantic reason distinguishes:

  • SessionStateLost — explicit/session lifecycle generation invalidation;
  • ResourceMissing — correlated evidence that the resource identity is missing;
  • ParentPlacementLost — correlated evidence that the parent-placement relationship is missing.

Released is placement-specific local lifetime loss caused by another owner:

  • AncestorReleased — an ancestor placement lifetime ended;
  • ResourceReleased — the placement's owning raster resource ended its direct placement lifetime.

Disposed / ExplicitDisposal means the caller explicitly disposed that public wrapper.

Status and reason are returned in one immutable snapshot. The internal lifecycle state is monotonic; stale or released ownership is not resurrected by late acknowledgement or later observation.

Side-effect-free observation

Reading OwnershipState is synchronous and bounded. It does not:

  • emit terminal traffic;
  • register or allocate a query;
  • acquire the output gate;
  • verify a capability;
  • trigger cleanup;
  • mutate registry ownership;
  • replay/re-upload raster content;
  • select or expose a graphics backend.

The release deliberately does not add ExistsAsync(), VerifyExistsAsync(), or another API that would imply a truthful passive terminal-side object-existence query where the reviewed backend provides none.

Two-axis resource and placement lifetime

Version 1.13 separated raster-resource ownership from relative parent-placement lifetime. Version 1.14 makes that separation directly observable.

The canonical example is:

Resource A      Current / None
  Placement A1 Current / None
Resource B      Current / None
  Placement B1 Current / None, relative to A1

Dispose A1
  Placement A1 Disposed / ExplicitDisposal
  Placement B1 Released / AncestorReleased
  Resource B    Current / None

Resource B remains usable for another ordinary placement if no independent evidence invalidated or disposed it.

Existing protocol-loss semantics become observable

The release reuses the existing narrow persistent-raster response classification instead of adding a parallel classifier.

A correlated ENOPARENT publishes Stale / ParentPlacementLost for the affected placement subtree while leaving raster-resource ownership current unless separately invalidated.

A correlated missing-resource ENOENT publishes Stale / ResourceMissing for the affected resource and dependent placements while preserving unrelated resources/placements.

ECYCLE, ETOODEEP, malformed replies, wrong identities, timeout, late responses, and transport failure do not manufacture lifecycle loss merely because an operation failed.

Correlation remains transaction ownership, not terminal authentication.

Internal lifecycle model

Resources and placements carry one packed atomic lifecycle value. Observation uses local atomic reads; lifecycle publication uses compare/exchange transitions.

This provides:

  • one indivisible status/reason pair;
  • first-transition monotonicity;
  • no stale/released-to-current resurrection;
  • safe concurrent readers while session/resource/placement ownership changes;
  • no new lock or output-gate dependency for observation.

Public wrapper disposal remains separate from the underlying shared ownership state. This allows a descendant wrapper to remain observable as Released until its caller explicitly disposes that wrapper, at which point the wrapper reports Disposed / ExplicitDisposal.

Sample

Icod.Terminal.PersistentRaster.Sample now demonstrates the complete 1.11–1.14 persistent stack:

  1. verify PersistentRasterGraphics;
  2. create Resource A and an ordinary placement;
  3. create independently owned Resource B;
  4. create a Resource B placement relative to Resource A's placement;
  5. observe current ownership without extra terminal traffic;
  6. update common placement geometry and relative offsets;
  7. dispose the parent placement;
  8. observe parent Disposed, child Released, and Resource B still Current;
  9. explicitly dispose the released child wrapper;
  10. create a fresh ordinary placement from Resource B.

The sample remains backend-neutral and exposes no protocol-private image, placement, parent, or generation identity.

Package and public API qualification

The persistent-raster package verifier now requires generated XML documentation for the complete lifecycle-observation surface and compiles/runs a fresh NuGet-only consumer on:

net8.0
net9.0
net10.0

The deterministic public API snapshot is identical across all three target frameworks. The final 1.14 fingerprint is:

2a23205217183a602f8fc454c49b47d278ebdc26b5e358c0384ed0d692405696

The machine fingerprint is stored in docs/Public-API-Baseline-1.14.sha256 and the human-readable contract in docs/Public-API-Baseline-1.14.md. Historical fingerprints remain unchanged.

Downstream compatibility

The stable 1.x package-contract shard continues to exercise current Icod.DCurses acceptance/hardening. Version 1.14 does not require DCurses source adoption in order to consume the package successfully.

Higher-level consumers may adopt OwnershipState when useful, while existing consumers that never read it retain the existing 1.13 behavior.

Production dependencies

The direct production package graph is:

Icod.TermInfo 1.13.0
Icod.Timing   1.0.0

Icod.TermInfo.Inspection 1.12.0 remains test/sample-only where used and is not added to the production package graph.

Compatibility

The stable 1.0.0 compatibility floor remains unchanged.

Existing behavior remains intact for consumers that do not read OwnershipState, including:

  • acknowledged persistent resource creation;
  • ordinary current-cursor placement;
  • source rectangles and signed z-order;
  • immutable relative parentage and signed cell offsets;
  • UpdateAsync(...) / UpdateRelativeAsync(...) semantics;
  • depth-8 portable relative graph limit;
  • 256-resource / 4096-placement local capacity ceilings;
  • generation-scoped certainty;
  • descendant-before-parent cleanup;
  • one authoritative query/input path;
  • no automatic raster replay.

See docs/Compatibility-and-Versioning.md for the stable-versioning and compatibility policy.

Explicit non-goals

Version 1.14 does not add:

  • passive remote ExistsAsync() / VerifyExistsAsync() semantics;
  • terminal-authenticated object existence;
  • mutating reconciliation probes presented as inspection;
  • automatic replay/re-upload/rebind;
  • hidden source-image caching;
  • public generation numbers;
  • public image/placement/parent protocol identities;
  • backend selection or raw Kitty dispatch;
  • reparenting;
  • Unicode placeholder / virtual placements;
  • animation/frame lifecycle;
  • absolute screen-coordinate placement;
  • pixel-within-cell positioning;
  • image decoding/transcoding;
  • PTY/ConPTY hosting;
  • cell/window/layout/damage/scene ownership.

Release qualification

The stable release candidate must pass the complete nine-job PR matrix on its exact final head:

Runtime Windows
Runtime Linux
Runtime macOS
Package candidate / public API freeze
Package Foundation
Package Presentation
Package Semantic and hardening
Package Stable 1.x release line
Validated package artifact

This release-note file deliberately does not self-certify the commit that contains final release closure. Exact-head qualification is recorded on PR #58 after CI completes. Merge, tag, and publication remain maintainer actions.

For the permanent ownership contract, see docs/Persistent-Raster-Ownership.md. For tranche history and design constraints, see Icod.Terminal-1.14.0-Development-Roadmap.md and the 1.14 design/implementation-plan documents under docs/superpowers/.