Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions docs/ink-compat/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Ink-Compat Architecture (Fresh Start)

## Scope
`@rezi-ui/ink-compat` is rebuilt from scratch as a compatibility adapter that prioritizes mainstream Ink behavior first (Tier-1 contract), with deterministic behavior gates.

Design principle for this pass: keep runtime behavior aligned with locked Ink baseline by delegating core rendering/hook semantics to locked Ink APIs, then layer strict invariants/tests around the adapter surface.

- Locked baseline: `ink@6.7.0`, commit `135cb23ae3b7ca94918b1cd913682f6356f12c5c`
- No reuse of prior `ink-compat` implementation
- No C engine/runtime changes

## Adapter Boundaries
1. Public API boundary (`@rezi-ui/ink-compat`):
- Exposes Ink-compatible `render` lifecycle API and mainstream component/hook exports.
- Adds deterministic key normalization wrapper for Tier-1 key contract.

2. Execution boundary (upstream Ink runtime):
- Rendering, reconciliation, stream integration, focus handling, and hook internals are delegated to locked Ink runtime.
- This gives immediate mainstream parity for Tier-1 primitives.

3. Validation boundary (tests/docs):
- Deterministic parity tests enforce IKINV contracts.
- Missing capabilities are explicitly documented and prioritized.

## Data Flow
1. App calls `render(tree, options)` on `@rezi-ui/ink-compat`.
2. Adapter normalizes options and forwards to locked Ink `render`.
3. Ink runtime manages stream IO + lifecycle.
4. Adapter returns normalized instance (`rerender/unmount/waitUntilExit/clear/cleanup`).

Input flow:
1. Ink stream input triggers `useInput` callback.
2. Adapter `useInput` wrapper normalizes mainstream key aliases/flags.
3. App receives deterministic `input,key` payload.

## Lifecycle Mapping
- `render`: create/attach Ink instance and return wrapped instance handle (IKINV-001, IKINV-009).
- `rerender`: forward to Ink rerender path (IKINV-001, IKINV-002).
- `unmount`/`waitUntilExit`: forward and preserve deterministic shutdown semantics (IKINV-001, IKINV-007).
- `clear`: forward with deterministic no-throw contract in non-TTY mode (IKINV-008).
- `cleanup`: deterministic wrapper cleanup that is safe and idempotent (IKINV-007).

## Unsupported/Deferred Areas
- Rezi-native rendering backend parity (out-of-scope in this pass; mainstream compatibility-first delivery).
- Deep transform/static/focus edge semantics beyond baseline behavior probes.
- Ink features outside Tier-1/Tier-2 contract when they require ABI/runtime expansion.

## Baseline Evidence
- API + lifecycle: <https://github.com/vadimdemedes/ink/blob/135cb23ae3b7ca94918b1cd913682f6356f12c5c/src/render.ts>
- Components docs: <https://github.com/vadimdemedes/ink/blob/135cb23ae3b7ca94918b1cd913682f6356f12c5c/readme.md#components>
- Hooks docs: <https://github.com/vadimdemedes/ink/blob/135cb23ae3b7ca94918b1cd913682f6356f12c5c/readme.md#hooks>
- useInput key model: <https://github.com/vadimdemedes/ink/blob/135cb23ae3b7ca94918b1cd913682f6356f12c5c/src/hooks/use-input.ts>
42 changes: 42 additions & 0 deletions docs/ink-compat/audit-consensus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Ink-Compat Audit Consensus

## Subsystem 1..11 Consensus Sets

| Subsystem | Confirmed issues | Rejected candidates | Consensus achieved |
|---|---|---|---|
| 1. Public API export surface | MCAP-004 (`testing` entrypoint missing). | “Tier-1 exports are missing” rejected via `packages/ink-compat/src/index.ts:1`. | YES |
| 2. Render lifecycle wrapper | No new open issue in this pass. | “`waitUntilExit` not wired” rejected via `packages/ink-compat/src/render.ts:258` and `packages/ink-compat/src/__tests__/lifecycle.behavior.test.tsx:21`. | YES |
| 3. Cleanup and clear semantics | Historical IKINV-008 cluster fixed; no current regression found. | “Non-TTY `clear()` still throws” rejected via `packages/ink-compat/src/render.ts:259` and `packages/ink-compat/src/__tests__/lifecycle.behavior.test.tsx:96`. | YES |
| 4. Text/style primitive behavior | No new open issue in this pass. | “Dim alias is ignored” rejected via `packages/ink-compat/src/components.tsx:28` and `packages/ink-compat/src/__tests__/render.golden.test.tsx:136`. | YES |
| 5. Input normalization semantics | MCAP-002 (extended vectors not yet covered). | “Ctrl+C normalization still mismatched” rejected via `packages/ink-compat/src/keyNormalization.ts:65` and `packages/ink-compat/src/__tests__/input.normalization.test.tsx:108`. | NO |
| 6. Stream hook contract | MCAP-003 (`useStdout`/`useStderr` parity probes missing). | “Unsupported raw mode should silently no-op” rejected; upstream-consistent throw validated in `packages/ink-compat/src/__tests__/non-tty-and-negative.test.tsx:61`. | NO |
| 7. Focus subsystem | MCAP-001 (deterministic focus parity suite missing). | “Focus hooks not exported” rejected via `packages/ink-compat/src/index.ts:14`. | NO |
| 8. Tier-2 `Static` / `Transform` behavior | MCAP-006 (deep edge matrix deferred). | “Static append baseline broken” rejected via `packages/ink-compat/src/__tests__/render.golden.test.tsx:171`. | YES |
| 9. Package scripts and workspace execution | Historical packaging gap fixed in this finalization pass (`build`/`test` scripts now defined). | “Workspace build/test cannot target package directly” rejected via `packages/ink-compat/package.json:16`. | YES |
| 10. Gap documentation and issue hygiene | Missing-capability ledger + out-of-scope issue stubs added in this pass. | “No documented defer path” rejected via `docs/ink-compat/missing-capabilities.md:1`. | YES |
| 11. Runtime backend strategy | MCAP-005 (Rezi-native execution mode deferred). | “Current pass already runs on Rezi native runtime” rejected via `docs/ink-compat/architecture.md:17`. | YES |

## Historical Fixed Clusters

### Cluster A: IKINV-005 (Input delivery determinism)

- Status: FIXED (historical cluster), with one remaining coverage-extension item (MCAP-002).
- Historical issues in the cluster:
- Ctrl+C normalization mismatch and key event filtering behavior.
- Evidence:
- Changelog entry for fixes: `CHANGELOG.md:26`.
- Normalization logic + helper: `packages/ink-compat/src/keyNormalization.ts:32` and `packages/ink-compat/src/keyNormalization.ts:65`.
- Deterministic coverage of mainstream key paths: `packages/ink-compat/src/__tests__/input.normalization.test.tsx:58`.
- Consensus note: the historical regression cluster is closed; only expanded-vector hardening remains open.

### Cluster B: IKINV-008 (Non-TTY deterministic fallback)

- Status: FIXED (historical cluster).
- Historical issues in the cluster:
- Non-TTY `clear()` throw behavior and non-raw stdin path safety concerns.
- Evidence:
- Clear guard for non-TTY outputs: `packages/ink-compat/src/render.ts:245`.
- Deterministic clear and non-TTY behavior tests: `packages/ink-compat/src/__tests__/non-tty-and-negative.test.tsx:32` and `packages/ink-compat/src/__tests__/lifecycle.behavior.test.tsx:96`.
- Non-raw-mode behavior probe: `packages/ink-compat/src/__tests__/non-tty-and-negative.test.tsx:44`.
- Historical related fix note: `CHANGELOG.md:26`.
- Consensus note: cluster accepted as resolved for this pass.
42 changes: 42 additions & 0 deletions docs/ink-compat/design-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Ink-Compat Design Plan (Mainstream-First)

## Strategy
Implement a thin compatibility adapter on locked Ink baseline, then harden with deterministic tests and invariants. This delivers a usable Tier-1 result quickly without reintroducing legacy code.

## Work Plan
1. Package scaffold
- Create `packages/ink-compat` workspace package from scratch.
- Define exports/types for Tier-1 (+ Tier-2 where feasible).
- Invariants: IKINV-009.

2. Render lifecycle adapter
- Implement `render()` wrapper returning `rerender/unmount/waitUntilExit/clear/cleanup`.
- Preserve deterministic behavior and idempotent cleanup.
- Invariants: IKINV-001, IKINV-002, IKINV-007, IKINV-008.

3. Component/hook surface
- Export Box/Text/Newline/Spacer and mainstream hooks.
- Include Tier-2 exports (`Static`, `Transform`, `useFocus`, `useFocusManager`) if pass-through is stable.
- Invariants: IKINV-003, IKINV-004, IKINV-005, IKINV-006, IKINV-009.

4. Stream-hook contract (explicit)
- Export and verify `useStdin`, `useStdout`, and `useStderr` behavior against locked baseline.
- Add deterministic cleanup checks for stream/listener/raw-mode safety.
- Invariants: IKINV-007, IKINV-008, IKINV-009.

5. Input normalization
- Wrap `useInput` and normalize mainstream keys (`arrows`, `return`, `escape`, `tab`, `backspace`, `ctrl+c`, `meta`).
- Invariants: IKINV-005.

6. Deterministic parity harness
- Add >=30 deterministic scenarios across Tier-1.
- Include golden output, lifecycle, input normalization, non-TTY, and negative tests.
- Invariants: IKINV-001..IKINV-009.

7. Gap documentation
- Publish missing/deferred capabilities with evidence + implementation direction.
- Invariants tracked per item.

## Defer Rules
- Tier-2: implement if no ABI/runtime expansion needed.
- Tier-3: defer by default; document with issue stubs and acceptance criteria.
28 changes: 28 additions & 0 deletions docs/ink-compat/invariants.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Ink-Compat Invariants

## IKINV-001 Lifecycle Ordering
`render()` initializes exactly once per instance, `rerender()` updates in order, and `unmount()/exit()` finalize exactly once with deterministic `waitUntilExit()` behavior.

## IKINV-002 Atomic Failure (No Partial Mutation)
If a render/update path throws, the public instance remains in a coherent prior state; no partial lifecycle transitions are externally observable.

## IKINV-003 Style Precedence Determinism
Style resolution for `color`, `backgroundColor`, `bold`, `dim`, and `underline` must be deterministic and stable across rerenders.

## IKINV-004 Text Behavior Determinism
`Text`, `Newline`, and inline text composition produce deterministic output frames for identical trees and options.

## IKINV-005 Input Delivery Determinism
Normalized input callback payload (`input`, `key`) is deterministic for mapped mainstream keys: arrows, enter, escape, tab, backspace, ctrl/meta combinations including ctrl+c.

## IKINV-006 Focus Transition Determinism
Focus hook behavior (`useFocus`, `useFocusManager`) preserves deterministic next/previous/manual transitions and stable activation/deactivation effects.

## IKINV-007 Stream Target + Cleanup Correctness
Writes and lifecycle cleanup target configured `stdout/stderr/stdin`; cleanup/unmount must release listeners and avoid stream leakage.

## IKINV-008 Non-TTY Deterministic Fallback
When output/input streams are non-TTY, behavior remains deterministic with safe fallback semantics (no raw-mode assumptions, stable frame output behavior).

## IKINV-009 Exported API/Type Stability
Public exports and TypeScript surface for Tier-1/Tier-2 APIs remain stable and intentionally versioned.
18 changes: 18 additions & 0 deletions docs/ink-compat/issues/issue-deep-tier2-edge-matrix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Issue Stub: Deep Tier-2 Edge Matrix (`Static` / `Transform` / Focus)

- Linked capability: MCAP-006
- Scope: OUT-OF-SCOPE (current pass)
- Priority: P3
- Labels: `ink-compat`, `out-of-scope`, `tier2`, `priority:P3`, `tests`

## Problem

Current Tier-2 coverage validates mainstream behavior but does not include deep interaction matrices for `Static`, `Transform`, and focus transitions under stress.

## Acceptance Criteria

- Add deterministic integration scenarios covering static append order under repeated rerenders.
- Add transform-chain scenarios that assert frame dimension stability.
- Add mixed scenarios combining focus movement with static/transform updates.
- Record expected frame histories and enforce them in regression tests.
- Publish coverage summary and unresolved edge cases in `docs/ink-compat/`.
18 changes: 18 additions & 0 deletions docs/ink-compat/issues/issue-ink-testing-library-entrypoint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Issue Stub: Add `@rezi-ui/ink-compat/testing` Entrypoint

- Linked capability: MCAP-004
- Scope: OUT-OF-SCOPE (current pass)
- Priority: P1
- Labels: `ink-compat`, `out-of-scope`, `testing`, `priority:P1`, `needs-design`

## Problem

Ink’s testing workflow expects a compatibility render harness, but `@rezi-ui/ink-compat` currently exports only `.` and has no `./testing` surface.

## Acceptance Criteria

- Add package export `./testing` with stable TypeScript types.
- Provide `render()` helper with `lastFrame`, `stdin.write`, `rerender`, `unmount`, `cleanup` semantics.
- Document behavior and constraints under `docs/ink-compat/`.
- Add deterministic contract tests for the testing API surface.
- Verify compatibility against mainstream `ink-testing-library` usage patterns.
18 changes: 18 additions & 0 deletions docs/ink-compat/issues/issue-rezi-native-backend-mode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Issue Stub: Rezi-Native Backend Mode for Ink-Compat

- Linked capability: MCAP-005
- Scope: OUT-OF-SCOPE (current pass)
- Priority: P2
- Labels: `ink-compat`, `out-of-scope`, `runtime`, `priority:P2`, `needs-rfc`

## Problem

The current adapter intentionally delegates execution to upstream Ink runtime; a Rezi-native execution mode is not available.

## Acceptance Criteria

- Design and implement a backend selector for Ink-runtime vs Rezi-runtime execution.
- Preserve Tier-1 API compatibility (`render`, lifecycle, hooks/components) across modes.
- Add parity tests that compare both modes against locked Ink baseline outcomes.
- Document feature gaps and fallback behavior when mode-specific constraints apply.
- Validate non-TTY and cleanup invariants (IKINV-007/IKINV-008) in both modes.
Loading
Loading