# 08 - Migration Evidence And Gates (https://jackin.tailrocks.com/reference/research/shared-tui-extraction/08-migration-evidence-and-gates/)



# 08 - Migration Evidence And Gates [#08---migration-evidence-and-gates]

The migration should be driven by checked artifacts rather than a sequence of manual copy-and-fix changes. The donor and target repositories need evidence that answers three questions at every stage:

1. which repository owns each behavior now;
2. whether the extracted API is neutral and reproducible;
3. whether `jackin❯` still renders and behaves the same before local code is deleted.

## Freeze artifacts [#freeze-artifacts]

Create these generated, reviewable artifacts on the single `jackin❯`
implementation branch before filtering history:

| Artifact                | Contents                                                                 | Gate                                                                 |
| ----------------------- | ------------------------------------------------------------------------ | -------------------------------------------------------------------- |
| `public-api.txt`        | donor public item paths/signatures                                       | no unclassified item                                                 |
| `consumer-map.tsv`      | file, crate, imported item, interaction surface                          | no unknown caller                                                    |
| `extraction-ledger.csv` | item/module, decision, target owner, dependencies, tests, docs, reviewer | every row decided                                                    |
| `story-manifest.json`   | story ID, component, dimensions, fixture, product terms                  | every moved story is neutral                                         |
| `render-manifest.json`  | SVG/hash/size and buffer fixture hashes                                  | baseline reproducible                                                |
| `dependency-tree.txt`   | normal/all-feature dependency trees                                      | no hidden product/runtime dependency                                 |
| `provenance.toml`       | donor URL, revision, retained paths, filter command, license decision    | independently reviewed                                               |
| `compatibility.toml`    | Rust, Ratatui core, Crossterm, OS, consumer revision                     | every advertised cell tested                                         |
| `quality-backlog.md`    | known rendering defects carried bug-compatible through extraction        | every defect listed with a post-parity fix note; none fixed silently |

The repository need not preserve these exact filenames forever, but each field and gate needs one machine-readable owner. Generation commands should be checked into the extraction plan or `xtask`; do not rely on a research-session shell history.

Freeze has two prerequisites inside the donor repository. First, wire the lookbook SVG drift check (`tui-lookbook --check`) into `jackin❯` CI: today it is only a documented CLI command, so the 29 committed SVG fixtures are not mechanically proven current, and unverified fixtures cannot serve as parity evidence. The job is added on the implementation branch and attached to the existing required aggregator, so it runs on every PR push and becomes durably required at merge without a separate branch-protection change. Second, correct the stale donor documentation — <RepoFile path="crates/jackin-tui/COMPONENTS.md">`COMPONENTS.md`</RepoFile> points at a lookbook binary and in-crate story module that no longer exist, and the crate root documents a `Theme` type that was never implemented.

## Parity-first sequencing and the quality backlog [#parity-first-sequencing-and-the-quality-backlog]

Two gates would otherwise conflict: `jackin❯` migration requires byte-identical rendering, while per-component conformance requires display-width correctness and non-color cues that the donor demonstrably violates today (character-count width math in hint spans, select-list labels, the status-footer right group, and error-dialog wrapping; a color-only panel focus border). The resolution is explicit sequencing:

1. **Extraction tier — required before the first consumer pin.** Neutral naming, no product dependency, borrowed render data, stable IDs, no-panic tiny/empty rectangles, documented public items, neutral stories, and deterministic renders. Known rendering defects are carried through unchanged and bug-compatible.
2. **Quality tier — required before the first tag.** Display-width correctness everywhere, non-color focus/selection/error cues, and any later non-blocking rendering defect admitted through the reviewed re-freeze protocol below. Each backlog item lands in `termrock` as its own reviewed change with regenerated fixtures and a migration note after `jackin❯` parity passes; `jackin❯` adopts it through a deliberate revision repin that reviews the visual diff.

During extraction and migration no rendering-behavior fix may ride along silently: a parity diff that traces to an unrecorded "improvement" fails the gate, and the quality backlog artifact is the only permitted list of deferred fixes.

If implementation discovers a security defect, data-loss path, or panic on a documented valid input after freeze, the same branch returns to Stage 0, fixes the donor, regenerates the affected fixtures/inventories, and freezes a new baseline before extraction resumes. A newly discovered non-blocking rendering defect is added to the reviewed quality backlog and carried through parity. This is an evidence reset inside the one implementation PR, not permission for a silent TermRock-only fix or a second PR.

## Classification rules [#classification-rules]

Each public item receives one of four decisions:

* **extract:** product-neutral implementation and contract move with history;
* **parameterize:** implementation moves only after product data, text, theme, or runtime policy becomes an input;
* **remain:** behavior belongs to `jackin❯` or another consumer;
* **remove:** redundant compatibility export or unused API has no future owner.

The ledger also records:

```text
current Rust path
current source file and last meaningful donor commit
all direct consumer files
normal and feature-gated dependencies
I/O, executor, global-state, or product-vocabulary flags
unit/render/PTY tests
component docs and lookbook stories
target module and proposed public name
semver and behavior notes
```

No module is moved wholesale merely because most of it is neutral. <RepoFile path="crates/jackin-tui/src/geometry.rs">crates/jackin-tui/src/geometry.rs</RepoFile>, for example, contains reusable display-column/tab geometry and a product-specific agent-name helper. <RepoFile path="crates/jackin-tui/src/components/container_info.rs">crates/jackin-tui/src/components/container\_info.rs</RepoFile> contains reusable detail-row/hit-test mechanics and a `DebugInfo` builder that encodes containers, agents, roles, and jackin❯ versions.

## Refactoring order [#refactoring-order]

Refactor in the dependency direction so a high-level widget never becomes the accidental owner of a lower-level primitive.

### Batch A - foundations [#batch-a---foundations]

1. terminal text sanitization and display-column slicing;
2. logical keys, modifiers, keymaps, and action/hint descriptors;
3. focus and hover ownership;
4. scroll axes, offsets, cursor following, and scrollbar geometry;
5. generic responsive rectangles and hit-test primitives;
6. semantic theme and the Tailrocks phosphor preset.

These packages have the smallest behavioral surface and unlock removal of the five current `jackin_core` reference lines in the donor, measured with `rg -n jackin_core` on 2026-07-15.

### Batch B - leaf widgets [#batch-b---leaf-widgets]

Move simple buffer-rendering components first: panel, modal backdrop, hint bar, button/action strip, toast, and tabs. Convert them to the one stable widget convention and remove public duplicate `render_*` wrappers.

### Batch C - stateful widgets [#batch-c---stateful-widgets]

Move scrollable lists, select list, text input (including the filter composition/preset), dialogs, status slots, detail table, and diff view after the foundation API is exercised. This is where stable IDs, borrowed row models, configurable labels, external validation/filtering, Unicode cursor rules, and explicit state mutation must be resolved. No separate public `FilterField` or modal stack/router is introduced.

### Batch D - terminal and lookbook adapters [#batch-d---terminal-and-lookbook-adapters]

Move the partial-init-safe Crossterm session, event conversion, story protocol, terminal browser, SVG backend, and catalog generator. The lookbook is a consumer of public `termrock`; it must not access crate-private widget helpers just to produce previews.

### Batch E - consumer-only composition [#batch-e---consumer-only-composition]

Keep or rebuild locally:

* `jackin❯` wordmark and launch/closing animations;
* container/debug information constructors;
* exit/data-loss confirmation wording;
* Capsule menu/status policies and host ownership atomics;
* role, mount, source, scope, agent, workspace, and OnePassword components;
* direct output, diagnostics routing, URL-opening, OSC emission policy, and async task spawning.

## History extraction [#history-extraction]

Prepare the repository through a history-preserving path filter, then make debranding and API cleanup as new reviewable commits before the first external source push. Retain the complete history of the two donor crate paths plus exact, path-complete generic lookbook documentation, committed SVG seeds, relevant design files, and the root `LICENSE`/`NOTICE`. Do not filter a mixed `jackin-core` file to capture individual helpers: move or reimplement the neutral code in a new signed commit and record its source file, donor revision, and meaningful source commit in `provenance.toml`. The neutral bootstrap retains the applicable donor notice, may relocate the license text under `LICENSES/`, and creates a TermRock-specific `REUSE.toml` rather than inheriting `jackin❯`'s broad package annotation.

[`git-filter-repo`](https://github.com/newren/git-filter-repo) is the maintained history-rewriting tool referenced by the plan. Run it on a dedicated clone, never on the active jackin❯ workspace. Verify authors, timestamps, file licenses, source-revision mapping, secret scan, binary-size scan, and retained paths before publishing. Historical donor commits may contain product vocabulary and may not build outside the former monorepo; the first published TermRock head and API must be neutral, standalone, and green. Publish only `main`, never donor branches or tags, and treat the first TermRock tag in Stage 5 as the only initial release tag.

Imported commits are provenance and are not retroactively DCO-signed. `provenance.toml` records the inherited boundary; every new TermRock-authored commit after that boundary must carry DCO sign-off and build independently. Create the public GitHub repository empty and do not push the raw filtered tip. The first push contains inherited history plus the reviewed neutralization/bootstrap commits, with the scanned buildable commit as the visible `main` head.

No TablePro, TablePlus, Zedis, or other reference-project source belongs in this history. Those projects may inform product concepts in other repositories; `termrock` contains only Tailrocks-owned/donor code and compatible dependencies with reviewed licenses.

## Cross-repository change graph [#cross-repository-change-graph]

```text
one jackin❯ implementation branch + PR (open through every stage)
        |
        +--> local filtered history -> neutral standalone bootstrap
        |                                  |
        |                                  v
        |                      first/direct-main green checkpoints
        |                                  |
        |                                  v
        |                           immutable TermRock revisions
        |                                  |
        +<--------- exact `rev` repins -----+
        |
        v
jackin❯ migration commits -> parity -> donor/docs deletion
        |
        v
TermRock first tag -> roadmap retirement -> one jackin❯ PR merge
```

During this roadmap, every `jackin❯` checkpoint points at the tested full
TermRock `main` commit in Cargo's `rev` field and commits
<RepoFile path="Cargo.lock" />. It never follows mutable `main` or a feature
branch. Cargo's
[Git dependency syntax](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories)
supports exact revisions; that revision is the reviewed build identity. Branch
and fork iteration is a post-bootstrap workflow documented in chapter 03.

Do not add `pub use termrock::*` as a compatibility facade in `jackin-tui`, and do not retain duplicated types under old paths. jackin❯ is pre-release: migrate each consumer batch to the new owning path, then remove the corresponding donor item in the same implementation branch. The old donor can coexist only for not-yet-migrated modules, with no type duplicated across both ownership boundaries. These batches are commits in the one PR, not separate PRs.

## `jackin❯` migration slices [#jackin-migration-slices]

On 2026-07-15 at donor revision `33896a504e19ef13adb8692550c1845cb86a9504`, `rg -l jackin_tui --glob '*.rs'` found 195 consumer files outside the donor/lookbook. Grouping paths by workspace package produced:

| Consumer                  | Files |
| ------------------------- | ----: |
| `jackin-console`          |   105 |
| `jackin-capsule`          |    42 |
| `jackin-launch-tui`       |    26 |
| root `jackin` package     |    11 |
| `jackin-console-oppicker` |     4 |
| `jackin-runtime`          |     2 |
| `jackin-diagnostics`      |     2 |
| `jackin-core`             |     2 |
| `jackin-host`             |     1 |

This is a file-reference inventory, not an estimate of edit size. Use it to order migration:

1. migrate lower-level `jackin-core`/runtime definitions and remove dependency inversion;
2. migrate the lookbook and launch TUI as bounded consumers;
3. migrate console-op-picker and product-local picker facades;
4. migrate the host console in vertical slices by shared component family;
5. migrate Capsule after raw-byte-to-logical-key and bottom-chrome parity is explicit;
6. remove the donor crates only when the inverse dependency query is empty.

Capsule keeps its locally painted status bar and hand-painted hint rows through migration: it re-implements tab painting today because the donor widget lacks per-tab state glyphs and click regions. The shared `Tabs`/`HintBar` contracts carry those capabilities precisely so Capsule *can* converge, but convergence is a tracked post-parity follow-up, never a migration requirement.

Each slice pins a tested `termrock` revision and runs the whole workspace because changing public Ratatui types can surface failures outside files that import `jackin_tui` directly.

At every stage boundary, compare the frozen donor revision with current `origin/main`. Before final donor deletion and again before the implementation PR merges, merge current `origin/main` with the normal non-rewriting merge-sync policy. If upstream touched a donor module, consumer, fixture, dependency cell, or canonical TUI document, regenerate the affected inventory/parity evidence and port the change to its decided owner before advancing.

No slice merges early. The single implementation PR remains the review surface
for the cumulative migration, while its commit sequence preserves bounded
review and rollback points.

## Parity matrix [#parity-matrix]

| Concern            | Evidence before move                               | Evidence after move                                                                                |
| ------------------ | -------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| exact cells/styles | Ratatui `TestBackend` fixtures                     | same buffer assertions                                                                             |
| browser preview    | 29 committed donor SVGs                            | neutral external SVG + product-local compositions                                                  |
| key dispatch       | keymap unit tests and hint derivation              | logical action + adapter contract tests                                                            |
| focus/hover        | interaction unit tests                             | component state and hit-test parity                                                                |
| Unicode            | display-column tests                               | narrow/wide/grapheme corpus                                                                        |
| resize             | current layout/render fixtures                     | min/normal/wide plus zero/tiny-area no-panic tests                                                 |
| terminal cleanup   | mode/guard tests                                   | partial-init, explicit restore, drop fallback, PTY tests                                           |
| process policy     | rich-surface/diagnostics tests                     | remains entirely in `jackin❯`                                                                      |
| OSC 8/22/52 output | raw overlay bytes emitted post-frame by host loops | typed `osc` regions/requests with pure-encoder unit tests and layout-derived region parity         |
| dependency graph   | donor Cargo tree                                   | no product, Tokio, or Crossterm in base graph                                                      |
| feature additivity | no equivalent donor boundary                       | same component inventory and buffer hashes with/without `crossterm`; only integration API is added |
| docs               | jackin❯ generic lookbook pages                     | external catalog paths and component coverage                                                      |

Every render fixture needs a stated purpose. Byte-identical parity is expected during the `jackin❯` ownership migration. Intended visual changes occur only in later, explicit quality-fix commits in the same implementation PR after parity passes, never hidden inside the ownership move.

## Performance gates [#performance-gates]

Record a baseline before changing data ownership:

* clean/default and all-feature compile time;
* first interactive lookbook frame;
* render time and allocations for tabs, 10/1,000/100,000-row list projections, long Unicode labels, and large diffs;
* SVG catalog generation time and output size;
* terminal restore latency and failure behavior.

The new public component API should allow visible-window projection rather than require cloning every row per frame. Benchmark regressions are advisory during initial neutralization, then become budgeted once `jackin❯` parity is established. A faster implementation is not accepted if it changes clipping, selection, focus, or key behavior without a separate decision.

## Completion gates [#completion-gates]

### External repository ready [#external-repository-ready]

* [ ] Provenance and REUSE checks pass for every extracted and generated file.
* [ ] The Apache license text and applicable original donor `NOTICE` attribution ship in the repository and package artifacts; TermRock's `REUSE.toml` names the new package and only its actual files.
* [ ] The public repository contains only `main`; the first visible head was neutral, standalone, scanned, and buildable, with inherited commits separated from new DCO-signed commits by the recorded provenance boundary.
* [ ] Base `termrock` builds with no product, Tokio, or Crossterm dependency.
* [ ] Every component and logical interaction API builds without features; enabling `crossterm` adds only event/backend/session convenience and preserves canonical renders.
* [ ] Every public item is documented and present in the reviewed API report.
* [ ] Every public component has neutral unit, buffer, story, SVG, docs, and edge-state coverage.
* [ ] Render generation is byte-deterministic.
* [ ] Default, all-feature, feature-powerset, MSRV, macOS, and Linux checks pass; Windows is neither advertised nor required by this revision line.
* [ ] Partial terminal initialization and restoration paths pass PTY tests.
* [ ] The quality backlog is recorded and untouched: no listed defect fixed before `jackin❯` parity, and no unlisted rendering change present.
* [ ] A minimal external program builds from a full Git revision.

### `jackin❯` donor retired [#jackin-donor-retired]

* [ ] The 195-file consumer inventory is regenerated and no old import remains.
* [ ] No neutral helper remains duplicated in `jackin-core` or a product crate.
* [ ] Console, Capsule, launch, picker, modal, mouse, Unicode, SVG, and terminal cleanup parity passes.
* [ ] Product-specific widgets and policies have an explicit local owner.
* [ ] Generic docs/previews point to the external catalog; product decisions remain in jackin❯ docs.
* [ ] `jackin-tui` and `jackin-tui-lookbook` are deleted only after the above checks.

### Program complete [#program-complete]

* [ ] The compatibility matrix records the exact `jackin❯` and TermRock revisions plus reproduction commands and results.
* [ ] No other Tailrocks product repository was checked out, patched, built, validated, migrated, or released by this roadmap.
* [ ] Every quality-backlog fix (display width, non-color cues) landed with regenerated fixtures and a migration note before the first tag.
* [ ] The first tag has semver, package, docs, license, and `jackin❯` compatibility evidence.
* [ ] The first tag is the committed API baseline; automated semver comparison starts with subsequent candidates.
* [ ] TermRock `main` protection is enabled after the final bootstrap checkpoint, before this roadmap closes.

These gates make repository extraction reversible until the donor deletion, while preventing an indefinite dual implementation after ownership changes.
