Commit Graph

222 Commits

Author SHA1 Message Date
Yunfei He 2f60278450 ci: add GitHub Actions workflow mirroring vp run ready
Single job on ubuntu-latest that runs the same checks as `vp run ready`, as
individual labeled steps so the run shows exactly which concern failed: format,
lint, build, type-check, test. Build precedes type-check and test because
@vue-tui/runtime has no "types" export — testing/runtime-tests resolve its
types and runtime from the built dist/*.d.mts, and same-job steps share the
filesystem so the dist persists.

Uses voidzero-dev/setup-vp@v1 (per the Vite+ CI docs), which installs Node, the
vp CLI, and runs vp install automatically (run-install defaults true), so no
separate install step. node-version pins the exact engines.node floor 22.12.0
so CI fails if code relies on a newer Node API; cache enables the pnpm store
cache (off by default). Triggers on pull_request, push to main, and manual
dispatch; concurrency cancels superseded PR runs but never a push-to-main run;
permissions are read-only.

Verified: actionlint reports no issues; both action refs confirmed via
git ls-remote.
2026-05-29 16:54:13 +08:00
Yunfei He 4335cbbc64 refactor(scripts): fold check:fixtures into check:type
A single top-level `vp run check:type` should fan out (-r) and fully type-check
every package, fixtures included — no separate top-level check:fixtures step.
runtime-tests' check:type now runs its main tsc then its fixtures tsc
(check:fixtures stays as a runnable sub-script). Drop the root check:fixtures
entry and its standalone step in ready.
2026-05-29 16:54:13 +08:00
Yunfei He 40d89bdf47 refactor: move type-checking from vp lint to tsc-based check:type
Set lint.options.typeCheck=false so vp lint/check no longer runs the
tsgolint full type-check (typeAware stays on, keeping type-aware lint rules).
Type-checking is now owned by check:type, which runs the real tsc and honors
each tsconfig's project semantics — unlike tsgolint, which ignored tsconfig
exclude/nested configs.

Wire check:type into ready after build (it needs the built dist for
cross-package type resolution): fmt, lint, build, check:type, check:fixtures,
test.

Verified: with typeCheck off, vp lint no longer reports a TS2322 type error
(but keeps its type-aware warnings); check:type catches it via tsc.
2026-05-29 16:54:13 +08:00
Yunfei He 1d6c47ca88 feat(scripts): add check:type running real tsc per package
Each package gets check:type = `tsc --noEmit` (under its own tsconfig); root
check:type = `vp run -r check:type` fans out across the workspace. Unlike vp's
tsgolint-based type-aware path, this is the standard TypeScript compiler, so it
honors each tsconfig's real project semantics.

Additive only here — vp lint still carries typeCheck; the switch-over and ready
rewiring land in the next commit. Note: testing and runtime-tests resolve
@vue-tui/runtime types from its built dist, so check:type requires a prior
build.
2026-05-29 16:54:13 +08:00
Yunfei He 0f60da7ec5 build(cli): add tsconfig and typescript dev dep for type-checking
The cli package had no tsconfig, so it was never type-checked under its own
config. Add a tsconfig (matching the other packages, minus JSX which cli does
not use) and the typescript dev dep so `tsc --noEmit` can run here — a
prerequisite for the upcoming check:type script.
2026-05-29 16:54:13 +08:00
Yunfei He b6e5313611 style(runtime): reformat write-synchronized.ts to satisfy oxfmt
The committed file had unformatted line wrapping that vp fmt --check flags,
which would fail CI the moment check:fmt runs. Reflow to the formatter's
output; no behavior change.
2026-05-29 16:54:13 +08:00
Yunfei He 6ca8990270 refactor(scripts): restructure workspace scripts into check:* / test:* families
Replace the opaque `vp check` bundling and the ad-hoc `ready` chain (which
shelled out via `cd ... && pnpm ...`) with explicit, composable named scripts.

Root delegates; category splits live in the package that owns them:

  root: check:fmt / check:lint / check:fixtures / test / build / ready
  runtime-tests: test = test:integration + test:pty; check:fixtures

`ready` now composes the named scripts in dependency order (fmt, lint, build,
fixtures, test) — build runs before check:fixtures and test:pty, which need
the built dist. Drop the broken root `dev` (referenced a non-existent website
package) and the redundant per-package `check` scripts (fmt/lint already run
workspace-wide from root). Renames: pty-test -> test:pty, typecheck:fixtures
-> check:fixtures.
2026-05-29 16:54:13 +08:00
Yunfei He ddb45a4869 chore: add granular check:fmt / check:lint scripts at root
`vp check` bundles format, lint, and typecheck, which hides which concern
failed and offers no way to run a single slice. Add explicit per-concern
entry points at the workspace root:

  check       -> vp check            (umbrella, unchanged behavior)
  check:fmt   -> vp fmt --check      (format only)
  check:lint  -> vp lint             (lint + typecheck)

No separate check:type: with typeAware/typeCheck enabled in the root config,
vp lint already runs the tsc typecheck, so check:lint covers it.
2026-05-29 16:54:13 +08:00
Yunfei He fb1f6d33d4 refactor(config): drop per-package lint/fmt blocks redundant with root
The root vite.config.ts lint/fmt settings cascade into every workspace
package, and a package-level lint block merges with — rather than replaces —
the root options. So the `lint.options { typeAware, typeCheck }` and the empty
`fmt: {}` repeated in runtime, testing, and runtime-tests only restated what
each package already inherits.

Remove them. runtime-tests keeps just its `ignorePatterns` (the one genuine
per-package override); typeAware/typeCheck now come from root via the merge.
Verified with `vp check`: no lint or typecheck regression, and the PTY
fixtures stay excluded from lint.
2026-05-29 16:54:13 +08:00
Yunfei He 3ef28ca3a1 test(runtime-tests): pin JSX children typing under the automatic runtime
The WithChildren shim is only exercised under jsx:"react-jsx", which lives
solely in integration/pty/fixtures/tsconfig.json. Nothing in `ready` ran tsc
against that config (vp check uses jsx:"preserve" and excludes the fixtures;
pty-test only transpiles them), so a regression in the shim — children
silently rejected, or declared props silently widened away — would pass
verification unnoticed.

Add a type-only regression fixture (not a runnable PTY program; not a
*.test.tsx, so vitest never collects it) that pins both directions of the
contract: children are accepted on Box/Text/Static/Transform, and declared
props stay validated via @ts-expect-error (invalid value, wrong type, unknown
prop, and missing required props on Transform/Static).

Wire `tsc -p integration/pty/fixtures/tsconfig.json --noEmit` into `ready` via
a typecheck:fixtures script, run after build (so @vue-tui/runtime resolves
against fresh dist types) and before pty-test, so the react-jsx path is
actually enforced rather than only manually checkable.
2026-05-28 23:13:03 +08:00
Yunfei He fa0708672c docs(runtime): clarify WithChildren adds a children prop to $props 2026-05-28 23:13:03 +08:00
Yunfei He ab3ae78ba2 fix(runtime-tests): use ignorePatterns for lint, not the invalid exclude
`lint.exclude` is not a property of OxlintConfig (the correct key is
`ignorePatterns`). The invalid property failed defineConfig overload
resolution, which surfaced as a TS2769 plus a TS2321 excessive-stack-depth
error against the recursive vitest-augmented UserConfig. Using
`ignorePatterns` excludes the PTY fixtures from lint as intended and clears
both config type errors.
2026-05-28 23:13:03 +08:00
Yunfei He 304fdf2e21 fix(runtime): accept JSX children on components under automatic runtime
Text/Box/Static/Transform read children via slots but never surfaced
`children` on their JSX `$props`. Under the automatic JSX runtime
(jsx: react-jsx + jsxImportSource: vue), children are passed as a
`children` prop, so `<Text>x</Text>` failed to type-check. Add a
type-only WithChildren cast that declares optional `children` on $props;
Vue routes that prop to the default slot at runtime, so there is no
runtime change.
2026-05-28 23:13:03 +08:00
Yunfei He a5a96fed31 chore: hoist text-measure import in yoga.ts; declare node>=22 engine
Addresses PR #23 review: move the mid-file text-measure import to the
top-level import block, and declare engines.node>=22 to match the
upgraded text stack (cli-truncate@6, slice-ansi@9 require node>=22).
2026-05-28 17:57:52 +08:00
Yunfei He 7b8ed05ef9 test: pin narrow-truncate re-measure parity with Ink 2026-05-28 17:57:52 +08:00
Yunfei He 4696b49313 test: pin absolute-non-edge ZWJ parity with Ink (closes #21 final class) 2026-05-28 17:57:52 +08:00
Yunfei He 1550ab9ad1 fix: measure text naturally like Ink, wrap only when constrained (closes #21 height/wrap classes)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 17:57:52 +08:00
Yunfei He 5c60a0af63 fix: upgrade text stack to grapheme-aware slicing/width (closes #21 grapheme classes)
Bump slice-ansi@9, string-width@8, wrap-ansi@10 and add cli-truncate@6
(both the runtime dep and the pnpm catalog entry for string-width). Rewrite
wrapText truncate variants to delegate to cli-truncate, matching Ink's
wrap-text.ts: grapheme clusters (ZWJ emoji, combining marks) stay whole and
newlines are preserved. Adjust the horizontal-clip left-edge compensation in
paint.ts because slice-ansi@9 drops a straddling wide grapheme whole rather
than splitting it, so lineX must advance by the actually-dropped width.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 17:57:52 +08:00
Yunfei He 1a1d9935d8 fix: skip painting display:none subtrees (closes #21 display-none class)
Adds an early-return guard in paintNode so nodes with DISPLAY_NONE
(already set on their Yoga node) are entirely skipped during paint,
matching Ink's renderNodeToOutput behavior. Without the guard, hidden
text/borders leaked onto visible siblings at x=0.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 17:57:52 +08:00
Yunfei He cd5971e28b fix(runtime): round up scheduler delay; restore spies in scheduler tests 2026-05-28 16:12:31 +08:00
Yunfei He abaf2acbce feat(runtime): provide no-op animation scheduler in renderToString 2026-05-28 16:12:31 +08:00
Yunfei He 00dcaad206 feat(runtime): provide shared animation scheduler per app, dispose on teardown 2026-05-28 16:12:31 +08:00
Yunfei He a016bf3801 refactor(runtime): drive useAnimation via shared scheduler with elapsed-time frames 2026-05-28 16:12:31 +08:00
Yunfei He 15955fdbaf test(runtime): migrate animation fake-timer tests to real-timer behavior tests 2026-05-28 16:12:31 +08:00
Yunfei He 68c09128df feat(runtime): add AnimationSchedulerKey injection key 2026-05-28 16:12:31 +08:00
Yunfei He 9468c34f35 feat(runtime): add shared animation scheduler 2026-05-28 16:12:31 +08:00
Yunfei He 81b068eda1 fix: waitUntilRenderFlush waits for scheduled-but-not-yet-pending commits
Codex review found waitUntilRenderFlush gated the scheduler flush on
hasPending() alone, missing the window after schedule() queues a commit
but before the post-flush callback sets hasPendingFlag — letting the
promise resolve before the pending render flushed. Now delegates to
flush() unconditionally; flush() already short-circuits when nothing is
scheduled or pending, so this only adds the missing wait.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 14:18:23 +08:00
Yunfei He 7d03a110e1 fix: address /simplify review — frame-writer dedup desync, scheduler edge cases
Correctness fixes found by max-effort review of the branch diff:

- frame-writer.sync() now updates lastFrame alongside log-update's
  previousOutput. Previously the two dedup layers desynced after a sync()
  (the clearTerminal path), silently dropping a legitimately-changed frame
  and emitting an empty BSU/ESU pair. Adds a regression test.
- scheduler: the queuePostFlushCb callback now bails if scheduled was reset
  by cancel(), so a stale callback can't commit on a torn-down tree or
  re-arm an uncancellable trailing timer.
- scheduler.flush() now collects multiple concurrent waiters instead of
  overwriting a single resolver — fixes a hang when two waitUntilRenderFlush()
  calls await the same pending commit.
- render teardown nulls mountedClear so a post-unmount app.clear() can't
  write to a torn-down stream.
- test-streams getContentWrites imports bsu/esu instead of hardcoding the
  escape literals.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 14:18:23 +08:00
Yunfei He 1eb30703f9 fix: address PR review — flush hang on cancel, BSU/ESU incremental wrapping
- scheduler.cancel() now resolves a pending flush() waiter, preventing
  waitUntilRenderFlush() from hanging when the app unmounts mid-flush
- BSU/ESU now wrap the actual stream writes instead of being embedded in
  the frame string, so synchronization survives log-update's incremental
  line diffing (matches Ink ink.tsx:1059-1097). Normal branch guarded by
  willRender() to avoid empty synchronized-update pairs on unchanged frames

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 14:18:23 +08:00
Yunfei He 1ffb847a65 feat: test parity final push — 64 new tests, BSU/ESU, clear() API
Closes remaining test gaps between vue-tui and Ink:

Features:
- Add synchronized output (BSU/ESU) via DEC private mode 2026
- Add clear() API to TuiApp for erasing rendered output

Bug fixes:
- Cancel scheduler trailing timer on teardown (prevents stale commits)
- Guard teardown writes against ended/destroyed streams
- Reorder teardown to cancel timer before final commit

Tests (64 new, 2 skipped for known feature gaps):
- 7 BSU/ESU shouldSynchronize tests
- 5 borderBackgroundColor tests
- 13 component edge cases (empty text, number child, OSC hyperlink
  wrap-width, bare-text-in-Box validation, transform multi-line,
  leading whitespace, link escape closing)
- 13 text-width/CJK tests (alignment, truncation, overlay edge cases)
- 4 throttle + unmount edge cases
- 10 waitUntilRenderFlush write-callback-level tests + 1 clear() test
- 3 exit re-entrance tests
- 5 PTY #450 regression tests + 4 inline #450 tests

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 14:18:23 +08:00
Yunfei He 6628dde35e refactor: deduplicate safeSliceEnd into shared export from text-measure 2026-05-28 10:06:36 +08:00
Yunfei He 2c994314e1 fix: reorder clip/transform pipeline so transforms are clipped correctly
Horizontal clipping now runs per-line AFTER transforms instead of before,
preventing Transform-widened text from escaping clip boundaries. Left-edge
clipping also uses the actual removed width to position subsequent text
correctly when a wide char straddles the boundary.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 10:06:36 +08:00
Yunfei He fe98756666 fix: clip border lines to box width for wide corner chars (closes #17)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 10:06:36 +08:00
Yunfei He 1f871e1ba5 chore: bump all packages to 0.0.2
Bump @vue-tui/runtime, @vue-tui/cli, and @vue-tui/testing from 0.0.1 to 0.0.2.
2026-05-28 01:10:20 +08:00
Yunfei He 5d532f47d1 fix: clip wide glyphs that overflow grid/clip boundary (closes #10) (#14)
Absolute-positioned wide characters (CJK, emoji) could paint past the
right edge of a clipped box or the terminal grid, producing output wider
than the column limit. Three fixes:

- Safe-slice after sliceAnsi in clip logic to handle wide char overshoot
- Bounds check in grid write loop to skip chars exceeding grid width
- Width-aware border fill to account for measured corner char widths
2026-05-28 00:42:39 +08:00
Yunfei He 0e7d7753f9 feat: export measureText and kittyModifiers to match Ink public API (#13) 2026-05-27 23:12:20 +08:00
Yunfei He 48beac5673 test: add render lifecycle parity tests from Ink (+10) (#12)
Port missing render lifecycle tests from Ink's test/render.tsx:
- onRender fires on input-triggered state update
- throttle renders to maxFps (leading+trailing pattern)
- immediate scheduler in debug mode commits every mutation
- screen reader mode bypasses throttle (immediate commits)
- exit(error) followed by exit(value) still rejects
- exit(value) resolves even when called rapidly twice
- unmount does not write to ended stdout stream
- non-interactive mode writes only last frame at unmount
- non-interactive mode does not emit erase or cursor sequences
- non-interactive unmount does not crash on ended stdout

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 21:40:47 +08:00
Yunfei He 9227ddf696 test: add Ink component/composable test parity (+130) and fix layout listener bug
* test: add text ANSI sanitization parity tests from Ink (+15)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: add use-animation parity tests from Ink (+43)

Port 43 new tests from Ink's use-animation test suite covering:
- Multiple animations in sync, different rates, sibling unmount
- Timer cleanup/recreation on unmount and remount
- Inactive animations, timer leak prevention
- Edge intervals (NaN, Infinity, -Infinity, oversized, zero, negative)
- isActive toggle resets, pause/resume cycles
- Frame catch-up, time/delta tracking, reset() behavior
- Newly mounted/activated animations don't inherit elapsed time
- Wall clock monotonicity, getter function isActive support

Uses selective fake timers (setInterval + performance only) so that
render()'s internal setImmediate still works on real clocks. Fake timer
tests read refs directly to avoid Vue scheduler flush timing issues.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: add use-box-metrics/measure parity tests from Ink (+16)

Port 16 missing tests from Ink's use-box-metrics, measure-element, and
measure-text test suites. Fix useBoxMetrics to reset metrics to zeros
when the tracked ref detaches (element unmounts or ref switches to null).

3 tests are skipped because vue-tui's useBoxMetrics uses watchPostEffect
(re-runs only when ref.value changes) rather than Ink's layout-commit
listener pattern, so sibling-content and resize-driven re-measurement
is not yet supported.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: add screen-reader parity tests from Ink (+11)

Add 11 screen-reader integration tests covering aria-label substitution on
Text/Box, ANSI styling omission, multiple/nested components, null component,
aria-state variants (busy, disabled, expanded), multi-line roles, and
multiselectable listbox.

Also fix component prop bug: Vue normalizes kebab-case prop names to camelCase
at runtime, so props["aria-label"] was always undefined. Switch Box/Text prop
declarations and access to camelCase (ariaLabel, ariaHidden, ariaRole, ariaState).

Add isScreenReaderEnabled option to renderToString() so tests can exercise
screen-reader output through the component pipeline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: add render-to-string parity tests from Ink (+18)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: add cursor composable parity tests from Ink (+7)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: add 6 missing screen-reader Ink parity tests

Add tests for aria-hidden, select input (list with roles/states/labels),
aria-state.multiline, aria-state.readonly, aria-state.required, and
nested multi-line text rendering in screen-reader mode.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: fix render-to-string missing Ink parity tests (+10)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: fix cursor composable missing Ink parity tests (+6)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: fix use-box-metrics missing Ink parity tests (+4)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: add layout listener so useBoxMetrics updates on resize and sibling changes

Adds a layout listener mechanism to TuiRoot matching Ink's architecture:
- TuiRoot.layoutListeners Set with addLayoutListener/emitLayoutListeners
- emitLayoutListeners called after every yoga.calculateLayout in commit()
- useBoxMetrics subscribes to layout listeners, diffs values before updating

Enables 4 previously-skipped tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 20:42:54 +08:00
Yunfei He 32fff4104c fix: address PR review comments
- sanitize-ansi.test.ts: convert raw ESC/C1 control chars to \u escapes
- frame-writer.test.ts: import cursor escapes from cursor-helpers instead
  of duplicating, add 7 createFrameWriter integration tests
2026-05-27 16:22:15 +08:00
Yunfei He 9f9ce66609 fix: safeSliceStart returns empty when ZWJ emoji exceeds width
slice-ansi can't split within a ZWJ grapheme cluster, so the retry
loop may never find a result that fits. Return empty string instead
of the oversized result.
2026-05-27 16:22:15 +08:00
Yunfei He ec67193250 test: add text-width parity tests from Ink (+9)
Port 9 text-width tests from Ink's test suite covering wide characters
in fixed-width Boxes, CJK width calculation, mixed ASCII+wide chars,
ANSI styled text layout, empty Text siblings, and CJK truncation
(end/middle/start/box-width). Also fix CJK truncation bug where
slice-ansi would overshoot on wide character boundaries.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 16:22:15 +08:00
Yunfei He f5de77a426 test: add frame-writer parity tests from Ink log-update (+41)
Port all 35 test declarations from Ink's log-update test suite,
producing 41 new runtime tests (6 cursor tests run in both standard
and incremental modes via describe.each). Covers standard rendering,
incremental rendering (surgical updates, shrink, grow), clear/done
reset, sync+update, cursor positioning, no-trailing-newline fullscreen
mode, and render-to-empty.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 16:22:15 +08:00
Yunfei He f098a8dc91 test: add cursor-helpers parity tests from Ink (+7)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 16:22:15 +08:00
Yunfei He 3a836c1e5b test: add input-parser parity tests from Ink (+45)
Port all 57 tests from Ink's input-parser test suite (43 named + 14
backspace/delete splitting via test.each). Replaces the previous 12
skeleton tests with full Ink parity covering: CSI parameters, SS3
sequences, meta+CSI/SS3 double escape, escaped printable/supplementary
codepoints, legacy ESC[[ sequences, incomplete holding states, flush
pending, empty chunks, text + incomplete escape, 14 backspace/delete
splitting cases, and 10 bracketed paste tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 16:22:15 +08:00
Yunfei He cc8f4e1a29 test: add ansi-tokenizer parity tests from Ink (+26)
Port all 26 tests from Ink's ansi-tokenizer test suite, covering CSI,
OSC, DCS, SOS, ESC, C1 control tokens and invalid/incomplete sequences.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 16:22:15 +08:00
Yunfei He 6655e32f25 test: add sanitize-ansi parity tests from Ink (+24)
Port 24 missing tests from Ink's sanitize-ansi test suite covering:
- C1 OSC hyperlinks with various terminators (C1 ST, ESC ST, BEL)
- C1 CSI sequences (both SGR and non-SGR)
- DCS passthrough (tmux wrappers, incomplete, BEL in payload)
- SOS control strings (ESC and C1 variants, various terminators)
- Standalone C1 control characters and ST bytes
- ESC ST sequences, malformed ESC sequences, incomplete CSI

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 16:22:15 +08:00
Yunfei He 26d91d9f2d docs: add Ink test parity spec (v3) and implementation plan
Spec: ~233 tests across 3 parts (A: unit +125, B: component +100, D: lifecycle +8)
Plan: 16 tasks, 3 branches, 3 PRs

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 16:22:15 +08:00
Yunfei He 4ca3c70a70 chore: remove docs/ from git and add no-commit rule to AGENTS.md
docs/ is for local working notes and specs — should not be tracked.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 16:08:48 +08:00
Yunfei He 8209f8440b docs: write/optimize READMEs for all published packages
- @vue-tui/runtime: rewrite with pitch, badges, SFC+shallowRef example,
  accurate component/composable tables, app lifecycle examples
- @vue-tui/cli: new README documenting vue-tui dev, HMR, crash recovery
- @vue-tui/testing: rewrite with @testing-library positioning, correct
  async render API, cleanup globals:true requirement
- Add early-stage warning to all sub-packages (matching root README)
- Fix CLI package.json: add license field, correct description

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 16:08:48 +08:00
Yunfei He 098a54080e chore: remove tracked docs/superpowers (already in .gitignore)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 16:08:48 +08:00