Current specification
Contracts, verification and the milestone ledger are authoritative. Read the owning contract before implementation. Source imports do not transfer acceptance.
Governance
Requirements
| ID | Requirement |
|---|---|
| LTERM-GOV-100 | Protected changes MUST update mapped canonical requirements or record an unchanged-contract justification, validation and milestone review in the same Jujutsu change. |
| LTERM-GOV-101 | Authored specification Markdown MUST stay within 400 lines and 32768 bytes. Every requirement MUST have exactly one verification row. |
| LTERM-GOV-102 | New production files MUST stay within 300 counted lines and tests within 500. Pinned imported exceptions MUST NOT grow. Evidence MUST distinguish fixtures, browser, native and platform acceptance. |
| LTERM-GOV-103 | Boundary, architecture, progress and spec-first checks MUST protect the package. Validation MUST begin at the narrow affected surface and widen for final integration. Committed history is append-only. |
Catalog dependencies use released registry packages. Application shell examples must not introduce a sibling-checkout dependency or a Design Core dependency into the published terminal viewport.
LTERM-GOV-100 is unchanged by the catalog output usage-guide update: it describes existing composition and palette APIs without changing package ownership or validation policy. The catalog output evidence records the regression, validation and M3 review.
The Node-only @lapismd/spec-validator release and tracked QMD collection enable
pnpm spec:search --semantic "topic" over canonical requirements and evidence.
Generated QMD databases remain ignored. Search is local discovery, never a CI
gate. LTERM-GOV-100 and LTERM-GOV-103 retain their existing validation policy.
Repository automation follows LTERM-RELEASE-001 through LTERM-RELEASE-003 in the release contract. Manifest and lockfile metadata map to that chapter; source mappings remain intact. CI checks an explicit committed revision range, including the initial push and dispatched Changesets PRs. No automation-only spec or test exemption is introduced.
The first hosted run exposed installer and private-demo changelog gaps. The hosted bootstrap correction records the exact failures and focused regressions; all ordinary CI gates remain enabled.
The fresh-checkout correction adds the demo asset prerequisite before Rust validation. LTERM-GOV-100 and LTERM-GOV-103 are unchanged: this repairs execution of the existing gates without exemptions.
The composition controls review updates catalog fixtures and their README description. LTERM-GOV-100 and LTERM-GOV-103 remain unchanged; the released viewport and native APIs are not affected. Final integration retains all ordinary verification lanes.
Hosted delivery records remote qualification separately from local checks. LTERM-GOV-100 and LTERM-GOV-103 remain unchanged; milestone completion does not approve visual baselines or authorize registry publication.
The user authorized merging the first version PR, enabling Cargo trusted publishing and protecting main. Publishing evidence records that extension under LTERM-RELEASE-004 and LTERM-RELEASE-005. Future repository changes use PRs and required checks, including automation changes.
Cargo delivery completion records verified registry and OIDC results and the M6 review. LTERM-GOV-100 and LTERM-GOV-103 are unchanged: this documentation-only update records external evidence without relaxing release qualification or package contracts.
The authorized npm release lane extends LTERM-RELEASE-006 and LTERM-RELEASE-007 in the release contract. Release scripts, immutable CI artifacts, registry consumers and protected publication retain LTERM-GOV-100 and LTERM-GOV-103 unchanged. The npm delivery evidence records validation and M5/M6 review without inferring publication from version preparation.
Detached bootstrap signing uses the public pinned Sigstore API in the owning release workflow. LTERM-GOV-100 and LTERM-GOV-103 remain unchanged; signing does not waive exact-main source qualification, registry acceptance or 2FA.
The ordered-capture correction extends runtime/frame-delivery evidence under unchanged LTERM-GOV-100 and LTERM-GOV-103. It retains full native/consumer acceptance and all diagnostics.
The bootstrap identity correction keeps LTERM-GOV-100 and LTERM-GOV-103 unchanged. Public Sigstore integration acceptance uses an immutable public npm provenance fixture and current TUF trust metadata; it never requires a signing or npm credential. Functional policy rejection, cryptographic rejection and eventual hosted signing stay distinct.
The Cargo event relay preserves LTERM-RELEASE-004 qualification and the existing coordinated version policy. Its unsupported-event failure, zero-upload registry inspection and supported recovery are recorded in the bootstrap correction; no local Cargo token, new exception or branch bypass is introduced.
The npm GitHub-metadata correction retains unchanged LTERM-GOV-100 and LTERM-GOV-103 gates. Signature validity, provider schema admission, actual staging/2FA, publication and registry-consumer acceptance remain distinct. No credential log or user npm configuration is read by source verification.
The 0.1.2 delivery receipt keeps current registry/source state separate from prepared metadata. LTERM-GOV-100 and LTERM-GOV-103 retain every functional/native check and explicit platform, consumer and visual qualification boundary.
The replacement sink fence preserves LTERM-GOV-100/LTERM-GOV-103. It changes private Rust synchronization only; source qualification and the original Desktop native gate remain independent.
Engine
Requirements
| ID | Requirement |
|---|---|
| LTERM-ENGINE-001 | The engine MUST own bounded parsing, Unicode grid, scrollback, damage and viewport generations without PTY, Tauri, application or network dependencies. OSC52 clipboard access MUST remain disabled. |
Owned boundary
lapis-terminal-engine exposes Terminal, SharedTerminal, Size, Viewport and
damage encoders. PTY launch, process lifetime and environment utilities belong
to the runtime crate. Imported deterministic suites remain separate from the
ignored idle-host latency benchmark.
Runtime
Requirements
| ID | Requirement |
|---|---|
| LTERM-RUNTIME-001 | The runtime MUST own bounded local-user PTYs with filtered environments, stable open identities, one live subscription per session and explicit close. Detach and renderer reload MUST preserve sessions; close and shutdown MUST terminate owned processes. Restart MUST NOT recreate shells. |
Public lifecycle
Runtime::new(Config) creates an isolated instance. Rust callers provide
LaunchSpec { target, cwd, shell, args, env }; only Target { id, label } is
serialized in session metadata. Defaults and limits are documented in usage.
Open identities are UUIDs. Conflicting or closed identities fail. Detach keeps
the PTY; explicit close is idempotent. Disable closes sessions; enable permits
fresh identities. Shutdown is permanent. No persistence recreates processes.
Attachment captures its bootstrap and installs the subscription while holding the publisher mutex. PTY output arriving during capture is retained for that subscription, even when no further bytes arrive. The publisher-to-engine lock order matches reader snapshot recovery; channel delivery happens after the publisher mutex is released. This private synchronization changes no public API.
Native support is initially qualified on macOS ARM64. Other platforms are unqualified; Windows/mobile adapters are not implemented.
Resize/full captures and PTY reader publication share the publisher-to-engine lock order. Capture selection and offer are one atomic publisher operation, so a stale full snapshot cannot overwrite a newer idle prompt while credit is held. Input, detach, process teardown and public signatures remain unchanged.
Sink installation and subscription capture share the publisher transaction. Detaching a live subscription MUST retain that lock through sink removal; an overtaken detach MUST NOT clear the replacement attachment’s channel. This private fence preserves PTY ownership and every public signature. The hosted qualification completes source and standalone native checks at the qualified immutable Git revision; Desktop adoption retains its independent cold consumer acceptance.
Frame delivery
Requirements
| ID | Requirement |
|---|---|
| LTERM-FLOW-001 | Delivery MUST retain at most one in-flight frame and one replacement full snapshot. Exact subscription and sequence acknowledgements and viewport readiness MUST fence stale messages; resize responses and channel frames may arrive in either order. |
Public frame contract
Messages are tagged frame, title, resetTitle, bell or exit. A frame
carries subscriptionId, sequence, rows/clusters/styles, cursor, full, viewport,
bracketedPaste and focusReporting. Viewports carry generation, columns and
screenLines. The shared JSON fixture checks Rust serialization and TypeScript
consumption. Exit currently carries no process exit-code payload.
Attachment may deliver its initial frame before the invoke response. The client buffers that bootstrap until it knows the subscription. Resize requests are coalesced and ordered through remounts; repeated observations of the requested size cannot create a frame/readiness feedback loop. Old viewports release only their own frame credit. Old attachment callbacks and errors are inert.
Bootstrap capture and subscription installation MUST exclude concurrent frame offers. Output received during attachment MUST appear in the bootstrap or the successor released by its exact acknowledgement. Publication retains the same one-frame credit and viewport fences; initial output requires no later shell activity to become visible.
Every output capture and its publisher offer MUST be ordered atomically under the publisher-to-engine lock order, including initial resize snapshots and PTY reader snapshots. An older blank capture MUST NOT replace newer initial output while bootstrap credit or viewport readiness is held. The latest pending snapshot must reflect capture order, without requiring a subsequent shell byte.
Subscription replacement includes its output sink. Clearing an old sink MUST remain atomic with faulting that subscription; a concurrent replacement MUST retain its bootstrap channel and subsequent output without requiring new input.
Host admission
Requirements
| ID | Requirement |
|---|---|
| LTERM-HOST-001 | Hosts MUST resolve opaque target IDs to trusted launch specifications. Sessions MUST be scoped to their originating host window. Rust owns shell, environment and admitted roots. Inherited credentials MUST NOT reach shells; local-user shells are not sandboxes. |
Application policy
HostPolicy authorizes the actual invoking window/URL and resolves targets in Rust. Every command checks that policy. Each admitted window has its own runtime; knowledge of another window’s session UUID grants no access. A host instance admits at most 32 window runtimes. Target resolution must return the requested target identity. Revocation/selection of application roots remains host-owned; the package does not discover repositories, vaults or services.
The attachment synchronization repair leaves LTERM-HOST-001 unchanged. The runtime fixes its private snapshot/subscription transaction; host admission, window scoping, shell selection and environment filtering remain host-owned.
The ordered-output correction changes only capture/publication internals. LTERM-HOST-001 retains the same host-owned admission, shell/environment, cwd, notification and lifecycle policy. No new renderer input or host authority is introduced; the source regression records exact and wider qualification separately from Desktop acceptance.
Replacement sink fencing preserves LTERM-HOST-001. It changes only the runtime’s private subscription transaction; no new launch authority, window scope, admitted-root rule or environment input is introduced.
Tauri helpers
Requirements
| ID | Requirement |
|---|---|
| LTERM-TAURI-001 | The Tauri plugin MUST provide typed commands, scoped permissions, channels, enable/disable and teardown helpers. Disabled runtimes reject new work and close sessions. Cancelled exit requests MUST preserve sessions; actual exit MUST clean up. Node and Deno MUST NOT be runtime dependencies. |
Integration
The plugin builder installs commands, generated permissions and Channel-based
frame delivery. Its default permission is empty; lapis-terminal:session is
an explicit host grant. Rust TerminalExt exposes enable/disable/shutdown.
ExitRequested and CloseRequested do not tear down sessions; actual Exit and
WindowEvent::Destroyed do. No shell/filesystem/clipboard plugin is required.
The standalone native demo validates these boundaries with production frontend
assets and CSP. Only its native-smoke build feature adds test controls.
The cold macOS native demo now requires the real /bin/sh initial prompt to
reach the viewport before sending any input. This strengthens existing
LTERM-TAURI-001 acceptance without changing plugin commands or host policy;
full runtime captures preserve that idle output across initial resizing.
Terminal presentation
Requirements
| ID | Requirement |
|---|---|
| LTERM-UI-001 | The public viewport MUST support host composition, explicit palette and metrics, keyboard/IME, selection/copy, paste, focus and resize. It MUST NOT own application layouts, global shortcuts, persistence or notifications. Unmount MUST detach without closing a session. |
Composition
The base npm entry has no Svelte/Tauri import. /svelte supplies TerminalViewport
and /tauri supplies the transport factory. A TerminalSession controller has
explicit attach/detach/close; the viewport attaches while mounted. Palette,
font metrics, classes, dimensions, label and key interception are configurable.
Notifications use one typed onError path supplied by the application. Examples
keep layout, global controls and notifications outside production components.
The canvas uses the viewport’s CSS dimensions independently of its scaled backing image, so glyphs, selection and pointer coordinates remain aligned on high-DPI displays. Catalog geometry checks run at device scale factor two.
Catalog
Requirements
| ID | Requirement |
|---|---|
| LTERM-CATALOG-001 | Storybook MUST demonstrate dock and workspace-pane compositions using the same public viewport, plus themes, narrow sizing, input and lifecycle states. Fixtures MUST NOT spawn processes. Interaction and accessibility checks MUST remain distinct from visual approval. |
| LTERM-CATALOG-002 | Representative application stories MUST consume released Design Core public App Shell and Workspace APIs. Both MUST place the terminal below the document; Workspace MUST register it in its native bottom panel. Both MUST include minimal navigation and exercise session retention through shell interactions. |
Acceptance surface
Stories cover dock, workspace panes, bare viewport, light/dark appearance, narrow sizing, Unicode, IME, bracketed paste, explicit selection/copy, resizing, exit, high output and recoverable errors. Both composition examples import the public package. Interaction and axe passes do not approve visual baselines.
The application examples use Design Core navigation, tabs, bottom panels and shell chrome. They are fixture hosts inspired by JJ Store and Lapis Notes, with no dependency on either application. Design Core is a catalog development dependency; the terminal package keeps its layout-neutral public boundary.
The App Shell uses a transparent left sidebar with padded navigation, matching
JJ Store’s surrounding shell chrome. Its terminal toggle uses Design Core’s
standard bottom-panel icon in the top app rail, without a right-sidebar toggle. Workspace
uses its built-in bottom panel, including tabs, sizing and visibility controls.
Its left sidebar starts collapsed, and terminal entries use square-terminal.
All composition stories use a simple App Shell Body, with session actions in its header. One global light/dark control applies across the catalog, including terminal palettes and the Workspace registered view. Per-story theme buttons and duplicate theme-only stories are unnecessary. Both global modes run the same interaction and accessibility suite.
Composition viewports start at the top of their Body, inside its normal padding; only the representative application shells place a terminal below a document. The catalog demonstrates named ANSI palette colors with readable status labels and plain selectable text. Fixture frames may carry styles directly; this does not substitute for native ANSI parsing or process qualification.
Composition target selection uses the released Design Core shadcn Select with keyboard-accessible options. Header actions use labeled icons, and session tabs retain a semantic background at rest with a distinct selected state. The compact example lowers App Shell’s desktop minimum main width through its public prop so the complete framed Body, including both borders and insets, fits its container.
Repository automation and versioning
Requirements
| ID | Requirement |
|---|---|
| LTERM-RELEASE-001 | Changesets MUST prepare one coordinated version for the npm terminal package and its three Cargo crates, update internal version requirements, lockfiles and changelogs for changed workspace packages, retain private tooling/demo packages, and record canonical release evidence. Version preparation MUST NOT merge PRs, create tags or publish registry packages. |
| LTERM-RELEASE-002 | CI MUST validate committed changes on main and PRs with spec-first, governance, formatting, lint, types, unit tests, both Storybook themes, builds, packaged consumers and cold macOS ARM64 native acceptance. Bot version PRs MUST receive the same checks at their exact head. |
| LTERM-RELEASE-003 | The canonical specification MUST build on PRs and publish from main through GitHub Pages artifacts and deployment, with deployment permission limited to the deploy job. Generated books MUST remain untracked. |
| LTERM-RELEASE-004 | Cargo publication MUST use a successful CI revision that is still main, require all source checks and consumed changesets, and use crates.io OIDC restricted to this repository, publish-crates.yml and the crates-io environment. Existing versions MUST be skipped, registry errors MUST fail closed, and unknown upload outcomes MUST NOT be retried automatically. |
| LTERM-RELEASE-005 | Main MUST require pull requests, up-to-date branches and successful macOS ARM64 checks and Build specification checks from GitHub Actions. These requirements MUST apply to administrators, with no PR bypass allowances, force pushes or branch deletion. |
| LTERM-RELEASE-006 | npm publication MUST use the immutable tarball and digest manifest from successful exact-main CI, consumed changesets and protected source checks. Uploads MUST require the npm-production environment, use OIDC after bootstrap and never automatically retry ambiguous outcomes. | | LTERM-RELEASE-007 | Release completion MUST verify the exact registry version, downloaded tarball integrity, cryptographic signatures, source-bound provenance and a clean frozen registry consumer covering every public entrypoint before creating its package-scoped GitHub release. Existing mismatched tags or artifacts MUST fail closed. |
Prepared version: 0.1.2.
The npm @lapismd/terminal package is the Changesets coordinator. The three
Cargo packages, private tooling root, private demo and Tauri demo metadata use
the same version. Version PR #1 prepared 0.1.1 and was merged after its full
checks passed. Registry availability is never inferred from a version string
or a passing archive check.
pnpm release:check rejects version drift, stale Cargo locks, invalid private
package policy and changesets targeting anything other than the coordinator.
pnpm release:version consumes changesets, updates Cargo offline after a locked
fetch, refreshes the pnpm lock, formats generated metadata and adds append-only
release evidence. Manifest/version files map to this chapter; runtime source
retains its existing engine, runtime, Tauri and UI mappings. Version-only PRs
have no exemption from spec-first or other CI checks.
The Changesets workflow uses signed GitHub API commits. Because bot pushes may not trigger ordinary PR workflows, it explicitly dispatches CI and the spec build on the version branch; CI verifies the expected commit SHA. The workflow has no publish command and cannot auto-merge the PR. Cargo publication follows the separately authorized workflow below. npm publication and tagged releases follow the separately authorized workflow below.
Coordinated 0.1.2 consumes the attachment repair, ordered capture correction
and npm delivery changesets. Version PR #5 was approved and merged after its
required PR checks passed. The three Cargo crates are published and registry
consumer acceptance passed. npm 0.1.2 is public at latest with identical qualified bytes, verified signatures and
provenance, a clean frozen registry consumer and its scoped GitHub release.
0.1.2 delivery records exact scope.
Specification tooling uses the released Node-only validator ^0.2.0.
CI qualifies the current macOS ARM64 boundary. Linux builds the specification and prepares release metadata; that is not Linux native terminal acceptance. The catalog remains visual-pending and the idle-host benchmark remains a separate gate. CI caches dependencies/build outputs, never acceptance results.
Version preparation maintains the private demo changelog as well as the public package changelog: Changesets reads both changed workspace packages when constructing the PR. The CI runner installs actionlint from its pinned upstream archive with SHA-256 verification; mdBook uses the pinned installer action.
Fresh CI checkouts build the demo frontend before Rust checks: Tauri’s context macro validates its configured frontend distribution even during Clippy.
Hosted delivery evidence records the first repository, Pages and signed version-PR runs. Later source updates continue through the same full validation, without automatically merging the PR.
Cargo trusted publishing
publish-crates.yml runs after successful main push CI. Its read-only planning
job verifies the revision is still main, the exact CI run passed and both
required GitHub Actions checks succeeded. Coordinated version metadata, consumed
changesets and canonical release evidence are required. It queries each exact
registry version; only 404 means absent. Errors, malformed or yanked versions
stop the release. Fully published versions need no authentication or upload.
Ordinary commits with pending changesets defer publication until the version
PR consumes them. Explicit verification of an unprepared version fails.
Automatic and manual publication additionally require the repository variable
CRATES_IO_BOOTSTRAP_COMPLETE=true, set only after all initial crates and their
publisher registrations are verified. Manual OIDC verification remains usable
during bootstrap; it cannot upload packages.
The publishing job uses the crates-io environment, restricted to the main
branch. Only this job has id-token: write; the pinned official Rust action
exchanges OIDC for a temporary crates.io token and revokes it after the job.
Each of the three crates trusts owner lapismd, repository lapis-terminal,
workflow publish-crates.yml and environment crates-io. No long-lived Cargo
token is stored in GitHub. Node and pnpm remain build/release tooling only.
Cargo publishes missing packages in dependency order with locked dependencies and ordinary archive verification. The job rechecks qualification immediately before uploading and confirms all three versions are visible afterward. Interrupted or ambiguous uploads stop; a later explicit rerun queries registry state before selecting remaining crates. Crates.io rate-limit errors must be honored, not bypassed with alternate credentials or duplicate requests.
Manual dispatch on main defaults to mode=verify, which checks eligibility and
exercises real OIDC without uploading. mode=publish can recover a partial
release after inspecting its outcome. Failed or non-main CI, PR workflows and
fork workflows cannot trigger publication. The private demo is never published.
Crates.io requires an initial publication before publisher registration. The authorized bootstrap uses the existing local Cargo credential from the clean, qualified merged version; that credential is never copied into this repository or GitHub. All later Cargo releases use the registered publisher.
The initial 0.1.1 bootstrap is complete: all three versions and publisher registrations were verified, a registry consumer passed a real PTY example, and hosted OIDC authentication/revocation succeeded. Automatic publishing is enabled. Cargo delivery evidence records the exact runs and registry checks.
Branch protection
Both required checks are bound to GitHub Actions app 15368. PRs must be current with main, and unresolved review conversations block merging. No human approval count is added beyond the user’s PR-and-checks requirement. Administrators and automation receive no bypass. New source checks must be added to protection and the release qualification guard together. Changesets continues to update its own version branch and must pass the ordinary protected merge path.
npm delivery
publish-npm.yml requires an explicit main dispatch. Its read-only plan
rechecks a successful main-push CI run and both protected GitHub Actions checks
at the current main SHA, coordinated versions, consumed changesets and release
evidence. Only registry 404 means absent; authentication, service and malformed
metadata errors fail closed. CI preserves the actual package-check tarball and
a SHA-256/SHA-512 manifest after full native acceptance. Publication downloads
that immutable artifact from the qualified CI run and verifies its source,
version, content and checksums without rebuilding it.
Only the publishing job has OIDC permission and uses the npm-production
environment restricted to main. The initial package requires an already
protected bootstrap credential or a separately approved staged-publication
bootstrap; no user credential is copied into CI. After registration, owner
lapismd, repository lapis-terminal, workflow publish-npm.yml and environment
npm-production define its trusted publisher. Token fallback is rejected.
A missing bootstrap credential fails visibly without attempting an upload.
One upload is attempted. A later explicit rerun rechecks registry state before
selecting work. Existing exact versions skip upload only when their integrity
matches the qualified artifact. Verification retries only bounded registry
propagation 404s. Tarball bytes, npm signatures and provenance must bind the
source SHA, main ref, repository and publishing workflow. A fresh public-only
consumer uses an exact registry version, a generated lockfile and npm ci,
exercises generic, Svelte, Tauri and testing entrypoints, builds with Vite and
runs npm audit signatures to validate cryptography.
The publish-mode GitHub release job runs only after verification. Its scoped
tag is @lapismd/terminal@VERSION; existing mismatched or unstable releases
fail. It attaches the qualified manifest and tarball. Verify mode never uploads
a package or creates a release. Cargo retains its existing coordinated delivery.
Initial npm delivery qualification records the source and external publication gates separately.
For first-package bootstrap without an inherited protected npm credential,
mode=attest requalifies the exact source CI and immutable artifact in
npm-production, probes existing protected authentication without printing
credentials, and signs detached npm-compatible provenance with GitHub OIDC.
It binds the sole npm PURL/SHA-512 subject, source SHA, main workflow and run.
The public pinned Sigstore library verifies the signed bundle against the
expected GitHub issuer and workflow identity before artifact upload. It never
uploads to npm or creates a tag. A task-scoped local npm session can submit
the exact tarball with npm stage publish TARBALL --provenance-file BUNDLE;
npm revalidates the signature, PURL and digest before staging. A maintainer’s
2FA approval completes bootstrap; verification mode must subsequently prove
registry bytes, signatures, provenance and the clean consumer before release.
No local npm credential is read, modified or copied by this repository.
Version PR #5 includes the initial-resize/reader correction, earlier attach repair and npm delivery changes. Source and cold standalone native acceptance passed; the fresh Desktop native consumer gate remains separate.
Detached bootstrap verification passes the issuer/workflow policy as Sigstore’s second argument when verifying an embedded DSSE payload, and independently requires the returned verified signer to have the exact issuer and workflow SAN. A valid signature from another repository does not qualify this artifact. Identity-verification correction records the public-library regression before initial npm publication.
crates.io rejects OIDC from workflow_run. The successful exact-main CI event
therefore performs read-only planning and, only for missing prepared versions,
relays to a new main workflow_dispatch. The supported dispatch repeats source,
check, changeset and registry qualification before entering crates-io and
requesting OIDC. The relay has only scoped Actions dispatch permission and no
OIDC or registry credential. Already published versions and pending changesets
never dispatch another publication. Direct workflow-run uploads are forbidden.
npm provenance MUST include buildDefinition.internalParameters.github with
event_name, repository_id and repository_owner_id, matching the verified
GitHub workflow context. Terminal binds repository 1422167487 and owner 311425888;
missing or foreign IDs fail before signing. Registry provenance verification
also requires those exact fields. The registry-schema correction
retains the rejected staging attempt and exact regression without treating a
cryptographically valid bundle as proof of npm schema admission.
The completed 0.1.2 bootstrap used the signed artifact and maintainer 2FA. Its
registered trusted publisher is GitHub owner lapismd, repository
lapis-terminal, publish-npm.yml, environment npm-production; publish and
stage-publish permissions were independently read back. The source and tag are
9575ac0d0cf02ddf1dea660c2cc3409ba64f7928. Historical verification uses the
scoped tag and attached immutable manifest; the manual workflow qualifies an
exact current-main candidate, not an arbitrary later documentation revision.
The GitHub release job explicitly requires successful plan and verification
results under always(), so an intentionally skipped already-published npm
upload cannot silently skip the final tag. A failed consumer still blocks the
release. The delivery receipt records
the initial skip and guarded exact-source recovery separately.
Distribution
Requirements
| ID | Requirement |
|---|---|
| LTERM-PACKAGE-001 | Versioned Cargo and npm artifacts MUST work without sibling checkouts. Native platform acceptance MUST use a cold production WebView with real PTYs. In-repository examples MUST exercise public APIs. Publication and consumer adoption remain separate work. |
Consumer verification
Cargo packages include license, notice, readme, public source and necessary fixtures. Cargo verifies archives; an isolated fixture runs the packaged Rust PTY example using only extracted archives. An npm tarball is installed in an isolated fixture and its base, Svelte, Tauri and testing exports are bundled. Temporary local archive patches are verification-only, never consumer adoption. Native qualification uses Tauri 2.12.4; compatibility with other Tauri minors requires separate qualification despite compatible manifest version ranges.
Design Core is used only by the repository catalog. It is not a dependency of the distributed terminal package; packaged consumer checks retain that boundary.
Archive checks read the coordinated release version instead of assuming 0.1.0, and select the exact npm tarball for that version. This preserves LTERM-PACKAGE-001 across version PRs. Repository URLs and npm public-access metadata describe the intended distribution; they do not assert publication.
Verification
Attach/output race evidence records the deterministic LTERM-RUNTIME-001 and LTERM-FLOW-001 regression and current gates. Hosted attach qualification completes the source integration gates while retaining the separate Desktop native gate.
Ordered output capture records the additional initial-resize delivery regression; Desktop acceptance remains open.
Replacement attachment sink fence records the forced LTERM-RUNTIME-001/LTERM-FLOW-001 detach/remount regression. Hosted replacement qualification completes full source/native CI while retaining the separate Desktop gate.
Automation follow-up evidence: fresh-checkout CI preparation covers the LTERM-RELEASE-002 prerequisite and unchanged governance gates.
Composition controls evidence extends LTERM-CATALOG-001 with dropdown, action and narrow-frame checks.
Hosted delivery completes remote qualification for LTERM-RELEASE-001, LTERM-RELEASE-002 and LTERM-RELEASE-003.
| ID | Status | Evidence |
|---|---|---|
| LTERM-ENGINE-001 | Implemented | Qualification |
| LTERM-RUNTIME-001 | Implemented | Qualification |
| LTERM-FLOW-001 | Implemented | Qualification |
| LTERM-HOST-001 | Implemented | Qualification |
| LTERM-TAURI-001 | Implemented | Qualification |
| LTERM-UI-001 | Implemented | Qualification Shell examples |
| LTERM-CATALOG-001 | Implemented | Qualification Shell examples, Output alignment and colors |
| LTERM-PACKAGE-001 | Implemented | Qualification Shell examples |
| LTERM-GOV-100 | Implemented | Qualification |
| LTERM-GOV-101 | Implemented | Qualification |
| LTERM-GOV-102 | Implemented | Qualification |
| LTERM-GOV-103 | Implemented | Qualification |
| LTERM-CATALOG-002 | Implemented | Shell examples, Output alignment and colors |
| LTERM-RELEASE-001 | Implemented | GitHub automation |
| LTERM-RELEASE-002 | Implemented | GitHub automation |
| LTERM-RELEASE-003 | Implemented | GitHub automation |
| LTERM-RELEASE-004 | Implemented | Cargo publishing, Cargo delivery |
| LTERM-RELEASE-005 | Implemented | Cargo publishing, Cargo delivery |
| LTERM-RELEASE-006 | Implemented | 0.1.2 delivery |
| LTERM-RELEASE-007 | Implemented | 0.1.2 delivery |
Milestones
Completion is scoped to macOS ARM64 and the acceptance surfaces below. Visual baseline approval, idle-host performance measurement, other platforms and consumer adoption remain separate qualification work.
M1/M4 review: the attach/output race correction adds deterministic initial-output coverage. Hosted qualification completes full source CI, packaged consumers and cold standalone macOS ARM64 acceptance at the immutable correction revision. Desktop native consumer acceptance remains a separate pending gate.
M5 review: main and the signed version PR passed full hosted CI, Pages is live, and version PR #1 was subsequently merged with explicit user authorization. See hosted delivery.
M6 review: all three 0.1.1 Cargo crates are published, publisher registrations are verified, live OIDC authentication and token revocation passed, and the registry consumer ran a real PTY. See Cargo delivery. Main protection applies to administrators and all future changes.
M3 review: composition controls cover the Design Core selector, icon actions, resting tabs and narrow frame. Visual baseline approval remains separate.
| Task | Status | Dependencies | Gate | Evidence | Next action |
|---|---|---|---|---|---|
| M0 | Done | none | Standalone governance and pinned imports | Qualification | Maintain contracts and evidence |
| M1 | Done | M0 | Engine, runtime and real PTY tests | Qualification | Separate idle-host performance gate |
| M2 | Done | M1 | Scoped Tauri helpers and native demo | Qualification | Qualify additional platforms when requested |
| M3 | Done | M1 | Viewport and Storybook interaction/axe | Qualification, Shell examples, Output alignment and colors | Separate visual baseline approval |
| M4 | Done | M2, M3 | Packaged consumers and cold native acceptance | Qualification | Qualify additional consumer adoption independently |
| M5 | Done | M4 | CI, coordinated version PR and specification Pages | GitHub automation, Hosted delivery | Maintain protected version-PR checks |
| M6 | Done | M5 | Protected main and Cargo trusted publishing | Cargo publishing, Cargo delivery | Release future prepared versions through protected PRs and OIDC |
M5/M6 review: the npm delivery lane qualifies immutable artifacts and exact registry verification. npm bootstrap, trusted-publisher registration and completed publication remain explicit gates until external receipts are recorded. Existing source and Cargo evidence stands.
M1/M4 review: ordered output capture tracks the additional idle-prompt resize race. The new exact regression and source/native qualification must pass before the next version PR merges. Desktop native consumer qualification remains separate.
M5/M6 0.1.2 review: the delivery receipt completes the authorized version-PR approval/merge, all three Cargo versions, real registry PTY consumer, npm latest/public bytes, source-bound signatures/ provenance, clean frozen npm consumer, trusted-publisher registration and scoped GitHub release. Native Desktop adoption, other platforms, visual baselines and the known-idle performance gate remain separate.
M1/M4 follow-up: replacement sink fencing retains the published 0.1.2 receipt while qualifying the Rust-only immutable Git consumer repair. Forced interleaving, real PTY and Desktop/native evidence stay separate; no new Cargo publication or visual approval is implied.
Foundation
Revision: enclosing Jujutsu change. Requirements: LTERM-GOV-100 through LTERM-GOV-103. Milestone review: M0 in progress; M1-M4 planned.
Before: test ! -e /Users/stevejuma/code/lapismd/lapis-terminal passed.
No implementation or tests existed. Source repositories were read only.
Toolchain: Rust/Cargo 1.99.0, Node 24.10.0, pnpm 10.32.1.
Initial bootstrap stopped on an incorrect LICENSE filename; source was verified as LICENSE.md and the local scaffold resumed. No source repository changed. All implementation, native, package and visual gates remain pending.
Initial qualification
Revision: enclosing Jujutsu change rumsyqqw. Date: 2026-10-16.
Requirements: LTERM-ENGINE-001, LTERM-RUNTIME-001, LTERM-FLOW-001,
LTERM-HOST-001, LTERM-TAURI-001, LTERM-UI-001, LTERM-CATALOG-001,
LTERM-PACKAGE-001 and LTERM-GOV-100 through LTERM-GOV-103.
This record supersedes the pending gate states in the foundation record without
rewriting that historical before state. All implementation and repository
changes are confined to the new lapismd/lapis-terminal repository. No existing
consumer was migrated and no artifacts were published.
Scope and before state
The directory did not exist before this slice. The acceptance target was a standalone terminal package with a native engine/runtime, reusable Tauri helpers, a flexible Svelte viewport, independent Storybook and working packaged consumers.
crates/lapis-terminal-engine contains parsing and grid state;
crates/lapis-terminal-runtime owns PTYs, admission inputs and process lifetime;
crates/tauri-plugin-lapis-terminal owns the native bridge and window isolation.
packages/terminal contains the client, controller, renderer, viewport,
Tauri adapter and test fixtures. catalog and examples/desktop exercise the
public package with dock and pane compositions. Root scripts, manifests, locks,
guidance and canonical specification establish independent maintenance.
The source import is pinned to jj-store
fe0abc0c930676da9ff5380c314dd333e744deab, retaining Buzz attribution at
ef2aa1ae38fadcc0bc22b8bf6ed96b35933146be. docs/imports.json records 37
source paths, original SHA-256 digests and destinations. The original imported
slicing test is the only non-growing line-count exception. Governance follows
lapis-ai c504af636267aec8183d2e5c37374a78d6d886cd with locally owned checks.
Environment and public formats
Qualified host: macOS 27.0 build 26A428, ARM64, Rust/Cargo 1.99.0, Node 24.10.0 and pnpm 10.32.1. Native acceptance used Tauri 2.12.4 and the system WKWebView. Browser interactions used repository-local Playwright Chromium; Storybook is 10.5.7. Lockfiles record exact dependency versions.
Cargo crates and npm @lapismd/terminal are version 0.1.0. The Rust/TypeScript
wire fixture records tagged messages, frame sequence, subscription ID, viewport
generation, rows, clusters, styles and cursor. Open request IDs and session IDs
are UUIDs; trusted launch paths and environment remain Rust-only. Permissions
default empty, with explicit lapis-terminal:session admission. Exit messages
currently have no process exit-code payload.
Verification commands and results
All commands below ran from this repository. Builds used pnpm dev:cargo,
whose disk preflight protects the repository-local target. Full repository
lanes were warranted because this new package introduces engine, runtime,
native bridge, browser presentation and their shared build/test infrastructure.
| Command | Result |
|---|---|
pnpm install | Installed workspace development dependencies and lockfile. |
pnpm browser:install | Installed repository-local Chromium for browser checks. |
pnpm build:js | Built all public npm entry points and declarations. |
pnpm check:js | Package and native demo: zero errors, zero warnings. |
pnpm test:js | 10 tests passed; no failures or skipped tests. |
pnpm test:rust | Final workspace result: 106 passed, zero failed, one explicitly ignored latency benchmark. |
pnpm test:storybook | Final catalog result: 10 stories passed, including interaction and axe checks. |
pnpm build-storybook | Static Storybook built successfully. |
pnpm dev:cargo -- clippy --workspace --all-targets --locked -- -D warnings | Passed. |
pnpm check | Complete repository governance, formatting, JavaScript/Svelte and Clippy lane passed. |
pnpm test | Complete JavaScript, Rust and Storybook lane passed with the counts above. |
pnpm build | npm package, production demo assets, Storybook and native workspace built. |
pnpm package:check | Publint passed; all three Cargo archives verified; isolated packaged Rust PTY consumer and npm/Svelte/Tauri consumer passed. |
pnpm test:native | Cold production WebView and real PTY acceptance passed; process exit zero and no captured child PIDs survived. |
pnpm spec:validate | 12 requirements, complete verification coverage, document limits and links passed. |
pnpm spec:build | Specification book generated successfully. |
pnpm spec:first | 139 protected files mapped to nine canonical chapters passed before this final evidence update. |
The final product logs are retained locally as .local/check-final.log,
.local/test-final.log, .local/build-final.log, .local/package-final.log
and .local/native-final.log. These ignored logs are supplementary: the actual
results and limitations are recorded here for review after checkout elsewhere.
After the final evidence and milestone updates, pnpm spec:check passed all
seven lanes: validation, formatting, architecture, boundaries, progress,
mdBook and spec-first. Its local log is .local/spec-final.log.
The packaged Rust fixture uses only extracted archives through temporary local patches and runs the runtime’s real shell example. The npm fixture installs the tarball, imports the base entry in Node and bundles the Svelte, Tauri and testing exports with Vite. It does not use sibling source aliases. These are local distribution checks, not registry publication or adoption by another app.
Boundary and lifecycle evidence
Rust coverage includes engine parsing/Unicode/scrollback/resize, environment canaries observed in real children, retained sessions, bounded transport, viewport credit, request identity reuse, disable/shutdown and three host isolation tests. Another window cannot list, attach, input or close an owned session; denied origins and targets fail through host policy.
JavaScript coverage includes early frame delivery before attach returns, stale subscription callbacks, obsolete viewport acknowledgements, resize across remount, prevention of resize/readiness feedback loops, exactly-once discovery error reporting, grapheme selection, keyboard translation and the Rust wire fixture. The frame fixture is consumed without field remapping.
Storybook covers dock, workspace panes, bare viewport, light theme, narrow layout, Unicode input, exited sessions, high output, recoverable errors and IME/paste/copy/resize. The last story checks one IME commit, bracketed paste, selected-cell copy and changed height. Fixtures spawn no processes. Error feedback is supplied by the host rather than duplicated inside the viewport.
The cold native smoke run used production frontend assets and CSP. Its ten
checks passed: PTY cwd/output, canvas, hide/show, workspace panes, Unicode input,
cancelled exit, reload with the same PID, explicit close, disable/enable and
quit cleanup. The final run captured PIDs 78691, 78692 and 78820; the runner
observed none alive after exit. Extra test controls exist only behind the demo’s
native-smoke feature. The app’s ordinary runtime requires no Node or Deno.
Dock and pane screenshots were inspected locally at .local/evidence/dock.png
and .local/evidence/panes.png. This is inspection evidence, not approved visual
baselines. The dock screenshot captures the maximized interaction end state.
Failed attempts and corrections
- Initial Rust compilation rejected process-global
set_varin imported tests under Rust 2024. Canary values now seed the command builder’s captured environment, preserving real-child assertions without unsafe global mutation. - A demo compile failed because its required icon was absent. An original SVG and generated PNG were added; subsequent native builds passed.
- Initial browser execution lacked Chromium. The repository-local browser install resolved it. A separate Storybook Vite configuration error prevented Svelte import transformation; the corrected configuration passed.
- An early browser run stalled in a resize/readiness feedback loop and was stopped. Desired-size deduplication and a regression test resolved it; a separate regression protects a remount resize behind an in-flight request.
- The light-theme story initially failed its assertion; the corrected story and final full catalog pass cover the theme toggle.
- Native smoke twice failed its background-job fixture because macOS’s
interactive shell expanded
!in quoted$!. The fixture now reads the numeric job PID without those quotes. The final native test passed twice. - A transient Workbench edit duplicated Svelte markup and failed type checking; the markup was repaired before the complete check, test and build passes.
- Generated Svelte and Tauri schemas initially appeared in the new JJ change. Build caches were untracked and ignored; intentional plugin permission metadata remains part of its archive.
- The final specification check caught formatting drift in Tauri-generated permission reference Markdown after a native build. Generated permission output is now excluded from Prettier, matching generated schemas; authored documents remain checked.
Storybook emitted Node loader deprecation and large-bundle advisory warnings; these did not fail the final build. No assertion, permission or production CSP was weakened to obtain acceptance.
Milestone review and remaining qualification
M0 is complete for independent governance and pinned imports. M1 is complete for engine/runtime and real PTY coverage. M2 is complete for scoped Tauri helpers and native demo acceptance. M3 is complete for the reusable viewport and interaction/accessibility catalog. M4 is complete for isolated archives and cold native acceptance on the qualified macOS ARM64 host.
Visual baselines remain unapproved. The imported idle-host latency benchmark
g3_renderer_acquire_stays_within_frame_budget remains ignored and is not a
performance claim. Other operating systems, Windows/mobile adapters and other
Tauri minor versions are unqualified. Existing-app integration, publication,
release signing and cross-platform release qualification are outside this slice.
These limits are not failures concealed by the completed scoped milestones.
Next actions are separate visual review and idle-host performance measurement, followed by any explicitly requested platform qualification or consumer adoption.
Design Core shell examples
Revision: enclosing Jujutsu change kzsoxnux. Date: 2026-10-16.
Requirements: LTERM-CATALOG-001, LTERM-CATALOG-002, LTERM-UI-001,
LTERM-PACKAGE-001 and LTERM-GOV-100 through LTERM-GOV-103.
Scope and before state
The initial catalog used a custom Workbench for both dock and pane examples.
pnpm test:storybook -t 'BottomDock|WorkspacePanes' passed two stories with
zero failures and eight skipped, but neither rendered the requested Design
Core application shell. The repository was clean at ca461091 before editing.
Added catalog/shells with a structural App Shell inspired by JJ Store and a
registered-view Workspace inspired by Lapis Notes. Both use public Design Core
0.5.0 exports and prepared styles from the npm registry. The structural shell
places a terminal below its document with hide, maximize and restore controls.
Its transparent, padded left navigation follows JJ Store’s shell presentation;
the standard bottom-panel toggle sits in the top rail and there is no right
sidebar toggle. Workspace registers the terminal in its native bottom panel
below a note, with tabs, file navigation, ribbon, status and resizing controls.
The Workspace sidebar starts collapsed and terminal entries use square-terminal.
The composition/input stories now use a simple Design Core App Shell Body, with all session actions in its header. A shared Storybook appearance control switches every example between light and dark, including canvas palettes and registered Workspace views. Three redundant theme-only stories were removed; the final catalog has eleven stories, exercised in both global modes.
The fixture host explicitly owns its session. Workspace view teardown detaches the viewport; host teardown closes the fixture session. No sibling application, native API or runtime dependency changed. Design Core is a root development dependency; it is absent from the distributed terminal package manifest.
Retina regression
Visual inspection at device scale factor two revealed canvas CSS dimensions
following its backing image. A narrow regression command,
pnpm test:storybook catalog/shells/Shells.stories.svelte -t '^AppShell$',
failed one test before the fix: the canvas was 1920 CSS pixels wide inside a
960-pixel viewport. The viewport now explicitly sets canvas CSS width/height to
100%, independently of its high-resolution backing image. The same command
passed one test afterward, with three skipped.
The catalog browser provider now uses device scale factor two. Both shell stories assert canvas-to-viewport geometry. The App Shell checks hide/show, retained session identity and maximize/restore. Workspace waits for startup, switches panel tabs, closes/reopens the bottom panel, and checks retained session identity. App Shell also verifies the bottom toggle’s top-rail location.
Iteration evidence
pnpm view @lapismd/design-core versionreturned 0.5.0. The quoted commandpnpm add -Dw '@lapismd/design-core@^0.5.0'installed registry artifacts; an initial unquoted shell attempt failed glob expansion before making changes.pnpm check:jsinitially found four unsupportedexactoptions in Testing Library role queries. Removing those options preserved exact string matching; the next run passed with zero errors and zero warnings.- The first new shell run had three passes and one failure because it checked Workspace readiness before startup completed. Waiting for the public ready marker fixed the assertion.
- The next run exposed one dark Workspace story with three contrast findings. The themed host now binds the documented view background/foreground tokens alongside its Lapis theme, so movable views inherit the intended palette. No accessibility rule was disabled. The four-story lane then passed.
- Visual inspection caught missing shared component defaults; importing the
published
@lapismd/design-core/styles.csssupplied the intended geometry, focus treatment and fonts. No consumer Tailwind compiler or source alias was added. pnpm check:architecturepassed.pnpm build:jsrebuilt the public viewport after the canvas fix. Storybook was restarted after dependency/config changes.- Adding PanelToggle initially triggered a late Vite dependency optimization:
four stories failed and two render errors were reported during the reload.
Declaring the public entry point in
optimizeDeps.includestabilized startup; the next four-story run passed, including the revised bottom-panel layout. - The global appearance configuration initially produced two type diagnostics
(missing Vite environment types and an inferred private renderer type).
Adding Vite’s client types and explicitly typing the Preview resolved both;
pnpm check:jsthen passed with zero errors and warnings.
Final verification
Root check/test/build lanes are required because this slice changes the shared catalog provider, dependency graph and a public viewport style.
| Command | Result |
|---|---|
pnpm test:storybook catalog/shells/Shells.stories.svelte | Four intermediate stories passed at device scale factor two, including axe and geometry checks, before consolidation into global themes. |
pnpm test:storybook | All eleven final stories passed in light mode, including interaction and axe checks. |
VITE_STORYBOOK_THEME=dark pnpm test:storybook | All eleven final stories passed in dark mode, including interaction and axe checks. |
pnpm check | Specification, boundaries, architecture, progress, formatting, Svelte/TypeScript and Clippy passed. |
pnpm test | 10 JavaScript tests, 106 Rust tests and all 11 final Storybook stories passed; zero failures. One existing idle-host latency benchmark remains ignored. |
pnpm test:native | All ten cold native checks passed on macOS ARM64; exit zero; captured PIDs 11733, 11736 and 11751 had no survivors. |
pnpm build | Final package, demo, static Storybook and Rust workspace builds passed. |
pnpm package:check | Three Cargo archives, a real packaged PTY consumer, npm/Svelte/Tauri consumer build and publint passed. |
pnpm spec:check | All seven lanes passed after the catalog refinements. |
Logs are retained locally as .local/shell-stories-final.log,
.local/shell-check-full.log, .local/shell-test-full.log,
.local/shell-build-full.log, .local/shell-native.log and
.local/shell-package.log. The final catalog runs are
.local/shell-stories-global-light.log, .local/shell-stories-global-dark.log,
.local/shell-check-final.log and .local/shell-build-final.log.
Tests used Node 24.10.0, pnpm 10.32.1,
Rust 1.99.0, Design Core 0.5.0, Storybook 10.5.7 and Chromium at scale two.
The published styles need no consumer Tailwind compilation. Browser inspection
confirmed both full shells, the native Workspace bottom panel, top-rail toggle,
padded sidebar and corrected terminal geometry. The global theme control was
changed in the browser and retained across composition and Workspace navigation.
A fresh Storybook process serves review on port 6048.
After the final Workspace request, its two application-shell stories were
rerun in both modes with
pnpm test:storybook catalog/shells/Shells.stories.svelte and the same command
prefixed by VITE_STORYBOOK_THEME=dark: two passes per mode. The assertions
confirm the left sidebar starts collapsed and its open control remains present.
Browser reload confirmed the collapsed initial layout and square-terminal icons.
pnpm build-storybook passed again; logs are
.local/shell-stories-collapsed-light.log,
.local/shell-stories-collapsed-dark.log and
.local/shell-build-storybook-collapsed.log.
Milestone review
M3 remains Done with representative Design Core shell and high-DPI interaction and accessibility evidence added. M0-M2 and M4 retain their earlier scope. LTERM-ENGINE-001, LTERM-RUNTIME-001, LTERM-HOST-001 and LTERM-TAURI-001 are unchanged: this slice changes presentation and catalog integration only. The cold native and packaged-consumer evidence remains applicable after the catalog-only refinements. Screenshots are inspection only and the application stories remain visual-pending. Publication, existing-app adoption, other platforms and the ignored idle-host latency benchmark remain out of scope.
Catalog output alignment and colors
Revision: enclosing Jujutsu change zxqyzmwy. Date: 2026-10-16.
Requirements: LTERM-CATALOG-001, LTERM-CATALOG-002, LTERM-UI-001 and LTERM-GOV-100.
Before and change
The working copy was clean at 9abe00b5. CompositionFrame retained
margin-top: auto on dock-mode viewports after the surrounding document had
been removed. High Output and other default-mode examples therefore displayed
an empty body above the terminal. The viewport itself rendered its rows from
the top correctly.
The exact regression command was
pnpm test:storybook catalog/Terminal.stories.svelte -t '^HighOutput$'.
Before the fix: one failure, eight skipped; the viewport started 457 CSS pixels
below the body instead of within its 16-pixel padding allowance. Removing the
auto margin and its conditional class made that same command pass: one pass,
eight skipped. Existing composition interactions now also check top alignment.
CatalogTransport adds deterministic styled spans to the existing fixture transport. INFO, PASS, WARN, FAIL and prompt prefixes exercise named ANSI palette colors and bold rendering. Ordinary text remains selectable. High output alternates status labels; both application examples share the styled fixture. A dedicated Colored Output story checks visible text and actual canvas pixels for green, yellow, red and cyan at device scale factor two. This is a display fixture, not an ANSI parser or native process claim.
No published package, terminal renderer, native runtime or sibling changed. LTERM-UI-001 remains unchanged: composition and frame styling use its existing host and palette contracts. The native ANSI engine remains the parser authority.
Verification
The shared fixture and composition stylesheet affect both story families, so the parent verification ladder requires the complete catalog plus root check/test/build. Final native acceptance is required by the repository guide.
| Command | Result |
|---|---|
| Exact HighOutput command above | One failure before; one pass after. |
pnpm test:storybook catalog/Terminal.stories.svelte -t '^ColoredOutput$' | One pass, nine skipped; canvas colors and axe passed. |
Same ColoredOutput command with VITE_STORYBOOK_THEME=dark | One pass, nine skipped; dark canvas colors and axe passed. |
pnpm check | Passed: spec, architecture, boundaries, progress, formatting, Svelte/TypeScript and Clippy. |
pnpm test | Passed: 10 JavaScript tests, 106 Rust tests and 12 Storybook stories. One existing idle-host benchmark remains ignored. |
VITE_STORYBOOK_THEME=dark pnpm test:storybook | All 12 stories passed, including interaction, axe and canvas color assertions. |
pnpm build | Passed: npm package, demo frontend, static Storybook and Rust workspace. |
pnpm test:native | Ten cold macOS ARM64 checks passed; exit zero; PIDs 32460, 32461 and 32463 had no survivors. |
pnpm spec:check | Initial mapped-governance failure; all seven lanes passed after the unchanged-contract note. |
Logs are local under .local/composition-*.log. Browser inspection confirmed
the removed gap and colored labels. Fresh Vitest browser processes provide
cold catalog runs; the static Storybook build is separately checked. Packaged
consumer checks are not repeated because no published files or dependencies
changed; their prior qualification remains applicable.
The first pnpm spec:check passed validation, formatting, architecture,
boundaries, progress and book generation, then reported one spec-first failure:
the changed docs/usage.md maps to the governance chapter. An explicit
unchanged-contract confirmation and evidence link were added there; no gate
or mapping was relaxed. The first failure is retained in
.local/composition-spec.log; the rerun uses .local/composition-spec-final.log.
Milestone review
M3 remains Done within its existing macOS ARM64 scope, with this catalog regression added to its evidence. M0-M2 and M4 are unchanged. Changed stories remain visual-pending; no visual baselines were approved. Publication, existing app integration and additional platforms remain separate work.
GitHub automation qualification
Enclosing Jujutsu change: wpmwwtms (GitHub CI, Pages and Changesets setup).
Requirements: LTERM-RELEASE-001, LTERM-RELEASE-002, LTERM-RELEASE-003,
LTERM-PACKAGE-001 and LTERM-GOV-100 through LTERM-GOV-103.
Before and scope
The local repository had no remote, workflows, Changesets or release scripts.
GitHub returned 404 for lapismd/lapis-terminal. The working copy was clean at
b6206b74. The README only summarized package purpose and linked local docs.
This slice adds pinned CI and Pages workflows, coordinated Changesets version preparation, public repository/package metadata, exact-version archive checks and an expanded README. The initial patch targets 0.1.1 from the locally qualified 0.1.0 foundation. The first version PR stays open. No registry publish, release tag, consumer adoption or sibling-source change is part of this task.
Spec-first maps manifest/lock/version files to the release chapter, retaining all existing source mappings. Automated versions update that chapter and add append-only preparation evidence. They are not exempt from any checks.
Validation
Full lanes are required because shared release and CI infrastructure affects all distributed packages. Local environment: macOS ARM64, Node 26.9.0, pnpm 10.32.1, Rust/Cargo 1.99.0, mdBook 0.5.4 and actionlint 1.7.12. Hosted workflows pin Node 24, Rust 1.99.0 and the same pnpm/mdBook/actionlint.
| Command | Result |
|---|---|
pnpm install --frozen-lockfile --ignore-pnpmfile | Passed. |
pnpm dev:cargo -- update --workspace --offline | Passed; no dependency updates. |
pnpm dev:cargo -- fetch --locked | Passed; populated all locked platform dependencies for offline preparation. |
pnpm test:release | 3 passed: stale-lock and invalid-package rejection, non-increasing version rejection, real disposable Changesets preparation with formatting and spec-first. |
pnpm exec changeset status | One patch for @lapismd/terminal. |
pnpm check:workflow | Passed with actionlint 1.7.12. |
pnpm spec:check | All 8 lanes passed, including release metadata, mdBook and spec-first. |
pnpm check | Passed; zero Svelte errors/warnings and Clippy warnings denied. |
pnpm test | 3 release, 10 JavaScript, 106 Rust and 12 Storybook tests passed; one existing idle-host benchmark ignored. |
VITE_STORYBOOK_THEME=dark pnpm test:storybook | All 12 stories passed. |
pnpm build | JS, demo, static Storybook and Rust builds passed. |
pnpm package:check | Cargo archives, isolated real PTY consumer and npm base/Svelte/Tauri/testing consumer passed. |
pnpm test:native | 10 cold production WebView/PTY checks passed; PIDs 54064, 54065 and 54096 exited with no survivors. |
ci-range.mjs was exercised with the all-zero first-push base and resolved the
empty tree. An incorrect expected dispatch SHA was rejected. Workflow action
pins were checked against GitHub’s action repositories. Generated Pages paths
are checked during the deployment build; public deployment is pending the push.
The first release test failed because the local cache lacked a locked
cross-platform dependency (jiff-tzdb). Running the documented locked fetch
resolved it. The next run exposed the old broad package pattern also matching
packages/ as governance; the mapping now assigns package source to its actual
UI/package chapters and manifests to release. The negative source-change test
still fails closed. Initial Changesets status needed the new local main
bookmark; status passed after creating it. No assertions or checks were waived.
The public repository and Actions-based Pages site were created at
https://github.com/lapismd/lapis-terminal; Actions uses default read permissions
and may create release PRs. The origin uses the existing SSH authentication.
Hosted main/PR runs and the actual Pages response remain pending at this commit.
No registry publication, tag or PR merge was performed.
Milestone review
M0–M4 remain scoped as previously qualified. M5 is in progress until local validation, main/PR CI, Pages deployment and the open version PR are verified. Visual approval, idle-host measurement, Linux/Windows native qualification and registry publication remain separate.
Hosted bootstrap correction
Enclosing Jujutsu change: qypqkmnx.
Requirements: LTERM-RELEASE-001, LTERM-RELEASE-002, LTERM-RELEASE-003,
LTERM-GOV-100 and LTERM-GOV-103. M5 remains in progress.
Initial source push: fc99030b456da198be068c7a87449fee3477c6f5.
The obsolete local --allow-new push option was rejected without a push; the
installed Jujutsu accepts new named bookmarks directly. The subsequent
jj git push --remote origin --bookmark main succeeded with existing signing.
Hosted before state
- Pages run 38904738424 passed build and deployment. An HTTP request to the published release chapter returned the expected Lapis Terminal specification title.
- CI run 38904738512 failed before tests: the pinned installer does not support actionlint and fell back to a nonexistent Cargo package. Use the upstream macOS ARM64 archive with the release asset’s verified SHA-256 instead.
- Changesets run 38904739134 prepared synchronized 0.1.1 metadata successfully, then failed constructing the PR because the manually versioned private demo had no changelog. The pinned action source confirms it reads changelogs for every changed workspace package. Preparation now maintains that changelog and formats it.
Validation
pnpm test:release with the added changelog assertion first reproduced the
hosted failure: 2 passed and 1 failed with the missing demo changelog. The
upstream actionlint archive download hash matched
aba9ced2dee8d27fecca3dc7feb1a7f9a52caefa1eb46f3271ea66b6e0e6953f.
Post-fix pnpm test:release passed all 3 tests, including real preparation,
formatted private demo changelog and spec-first acceptance. The exact downloaded
actionlint 1.7.12 binary validated the workflows. pnpm spec:check passed all
8 lanes. Hosted reruns are pending this push. No product code changed and
no CI gate was removed. Version PR preparation remains separate from
publication, tags and merging. M0–M4 and native qualification are unchanged.
Fresh-checkout CI preparation
Enclosing Jujutsu change: nyntuyoo. Requirements: LTERM-RELEASE-002,
LTERM-GOV-100 and LTERM-GOV-103. M5 remains in progress; M0–M4 are unchanged.
Main CI run 38905180260
reached Clippy but failed because the demo’s frontendDist did not exist.
Local checks had passed with an existing demo build. Both version PR CI runs
also failed at this fresh-checkout prerequisite. CI now builds the demo before
Rust checks, and the README documents the same preparation. No gate is removed
and runtime contracts are unchanged.
Changesets run 38905180357 opened the signed 0.1.1 version PR #1. It remains open with auto-merge disabled. Pages run 38905180252 deployed the specification; both version PR specification builds passed. No registry packages or tags were published.
pnpm demo:build and the pinned actionlint 1.7.12 binary passed. The initial
pnpm spec:check passed seven lanes, then correctly rejected the missing mapped
governance update. Added that unchanged-contract confirmation. The repeated
spec check passed all eight lanes. Hosted full-suite qualification remains
pending the corrected push; no product code changed in this slice.
Composition controls and narrow frame
Enclosing Jujutsu change: ppyyrpvx. Requirements: LTERM-CATALOG-001,
LTERM-GOV-100 and LTERM-GOV-103. M3 remains Done within its existing fixture
interaction scope; visual baselines remain unapproved. M0–M4 runtime contracts
are unchanged. M5 hosted automation qualification is tracked separately.
Before and implementation
The composition target picker was a native select. New terminal and maximize actions had text, and session controls had no resting background. In the narrow story the 396px shell root contained a 396px main plus two 8px margins: its right edge at 846px was clipped by the root at 838px.
Use the released Design Core shadcn Select and Button APIs, with Lucide icons
from its public WorkspaceIcon. Accessible names include the selected target;
icon buttons retain labels and titles. Session groups use semantic secondary
backgrounds and the active shell has an outlined button. App Shell’s public
desktopMinMainWidth={0} allows the complete frame and margins to fit.
No sibling repository or distributed terminal source changed.
Verification
The initial focused command used -t 'Narrow container', which matched no
normalized Storybook test names. Its cold optimizer also requested Select
prebundling. Added Select to the test optimizer and used -t Narrow.
The next run caught an incorrect test role assumption: the released Select
exposes a button opening a listbox. Corrected the assertion to that API.
The following run caught an axe visible-label mismatch; including the selected
target in the accessible name repaired it without disabling any accessibility
rule. Regression coverage also checks icon-only actions, resting background,
active state, both frame insets, border width and horizontal containment.
pnpm test:storybook catalog/Terminal.stories.svelte -t Narrow passed the one
focused interaction/axe test. Both pnpm test:storybook and
VITE_STORYBOOK_THEME=dark pnpm test:storybook passed all 12 stories. Browser
inspection confirmed the 380px main now has 8px insets on both sides and a 1px
right border. The Design Core popup and both themes were visually inspected;
this is review evidence, not baseline approval.
The first pnpm check caught a testing-library type error from Playwright’s
unsupported exact option. Removing it retained exact string matching, and the
repeated pnpm check passed governance, formatting, types and workspace Clippy.
Final integration additionally runs the full tests, builds, archive consumers
and cold native acceptance because this is the requested initial repository
delivery and AGENTS.md requires those gates. Results follow below.
Final local results:
pnpm test: 3 release-preparation tests, 10 TypeScript tests, 106 Rust tests and 12 Storybook stories passed. The separate idle-host benchmark remains ignored; it is not a performance qualification claim.pnpm build: npm, demo frontend, production Storybook and Rust workspace builds passed.pnpm package:check: actual Cargo PTY consumer and npm/Svelte/Tauri consumer built and passed from archives.pnpm test:native: 10 cold WebView/real-PTY checks passed, including reload retention and shutdown. Fixture PIDs 77582, 77583 and 77588 had no survivors; process exit code was zero.pnpm spec:check: all 8 lanes passed. Documentation-only completion of this record is checked with the same governance/formatting lane before commit.
The local full integration gate is complete. Storybook remains on port 6048 for review. Hosted checks for this UI revision follow the push; publication and merging the first version PR remain outside the authorized task.
Hosted repository delivery
Enclosing Jujutsu change: qpmzqkwv. Requirements: LTERM-RELEASE-001,
LTERM-RELEASE-002, LTERM-RELEASE-003, LTERM-GOV-100 and LTERM-GOV-103.
Repository: https://github.com/lapismd/lapis-terminal. Specification: https://lapismd.github.io/lapis-terminal/. First version PR: https://github.com/lapismd/lapis-terminal/pull/1.
Hosted qualification
Main revision 4008021148a72a5e55e72911f81fea794cbc80d3 includes the
fresh-checkout frontend prerequisite. Its
CI run 38906210536
passed every validation step: committed-range spec-first, workflow lint,
governance/formatting/types/Clippy, release/unit/Rust tests, both Storybook themes,
builds, packaged consumers and cold production WebView/real-PTY acceptance.
Its Pages build/deployment
38906210867
passed, and Changesets
38906211064
updated the existing version PR.
The version PR prepares 0.1.1 across npm, Cargo and the private demo. Reviewed
its file list: version metadata, lockfile, changelogs, consumed changeset and
canonical release evidence only. It remains open with auto-merge disabled.
Exact PR revision a4c4cac4890cb3cc7db33460023e5bebc84ffd6b passed the
explicitly dispatched full CI run 38906307010.
GitHub reports its commit signature as verified and valid. Both corresponding
specification builds passed and correctly skipped deployment from the PR. The
ordinary PR run also reached native acceptance; the dispatched exact-head run
provides the completed full qualification. Main CI completed successfully too.
An HTTP request to the published release chapter returned its expected title.
pnpm spec:validate, pnpm check:progress and targeted Prettier checks passed.
The completed record and M5 review receive pnpm spec:check before commit.
Its first run requested table formatting after M5 changed to Done; Prettier
normalized the milestone table before repeating the full spec check.
The repeated spec check passed all eight lanes.
M5 is Done: the repository is pushed, main and the signed version PR have completed full hosted qualification, and canonical Pages is published. The first version PR remains open. M0–M4 retain their existing scoped acceptance. No registry packages, tags or GitHub releases were published. The latest composition changes have separate full local evidence in the controls review; the combined final push receives the same CI, Pages and Changesets workflows.
Protected Cargo publishing
Enclosing Jujutsu change: mlulymzz. Requirements: LTERM-RELEASE-001 through
LTERM-RELEASE-005, LTERM-GOV-100 and LTERM-GOV-103. The user explicitly authorized
merging PR #1, configuring Cargo trusted publishing and protecting main.
M5 remains Done; M6 tracks registry and OIDC completion. Runtime contracts and
the existing macOS ARM64/visual-pending qualification boundaries are unchanged.
Before and remote changes
PR #1 head 016934a8271af61c2f833749eac1052b72d7af30 had passing full CI and
specification checks. Main had neither branch protection nor a ruleset. The
three crate names were absent from crates.io. Only version preparation and
Pages deployment existed; no registry publishing workflow was configured.
Configured main protection before merging: require PRs, strict/up-to-date
GitHub Actions checks macOS ARM64 checks and Build specification (app 15368),
resolved conversations, administrator enforcement, no bypass list, no force
push and no deletion. No additional human review count was requested. The
initial API request was rejected because contexts and checks were supplied
together; retrying with checks alone succeeded and a fresh GET confirmed it.
gh pr merge 1 --squash --match-head-commit 016934a8271af61c2f833749eac1052b72d7af30
merged through the ordinary protected path as
9e260407c325430c0e300324b8926ad7c18876c0. Main CI run 38915609611 subsequently
passed all validation. Created the crates-io environment with a branch policy
allowing only main. Existing local credentials were not displayed or copied.
Implementation and validation
The new workflow uses read-only planning, exact-revision qualification, a
restricted OIDC job, pinned official authentication, dependency-ordered Cargo
publication and registry confirmation. Unit tests cover failed/foreign/PR
triggers, stale revisions, missing or spoofed checks, registry outages/yanks,
partial releases and unknown upload outcomes. node --test scripts/cargo-release.test.mjs passed all 6 tests after the final fixture
adjustment; actionlint passed.
From a clean checkout of the merged version, pnpm dev:cargo -- publish --workspace --exclude lapis-terminal-demo --locked --dry-run verified all three
0.1.1 archives. Cargo warned about optional repository/homepage/documentation
metadata; these are not required fields. The first real publish attempt was
rejected before any upload by crates.io’s new-crate rate limit (HTTP 429), with
retry time 14:32:50 UTC. No alternative token or identity was used to evade it.
A clean-checkout retry after that time published lapis-terminal-engine 0.1.1.
Crates.io rejected the next new crate with retry time 14:42:50 UTC. Remaining
attempts select only absent crates; the engine will not be uploaded again.
Automatic publication remains disabled behind CRATES_IO_BOOTSTRAP_COMPLETE
until all initial crates and exact publisher registrations are confirmed.
The engine publisher registration was created and read back as ID 26195 with
owner lapismd, repository lapis-terminal, workflow publish-crates.yml and
environment crates-io. A live read-only release plan against main 9e260407
confirmed the engine version and selected only runtime and Tauri plugin as
missing. Runtime and plugin bootstrap remain pending their rate-limit slots.
Release infrastructure affects shared qualification, so the complete integration
lanes were run: pnpm spec:check passed all 8 lanes; pnpm check passed;
pnpm test passed 8 release tests, 10 TypeScript tests, 106 Rust tests (one idle
benchmark ignored), and 12 Storybook interaction/accessibility stories.
VITE_STORYBOOK_THEME=dark pnpm test:storybook passed the same 12 stories.
pnpm build and pnpm package:check passed, including real Cargo archive and
npm/Svelte/Tauri consumers. pnpm test:native passed 10 checks with process IDs
40788, 40789 and 40910; no surviving children and exit 0. Stories remain
visual-pending; other native platforms remain outside qualification.
A subsequent release-only refinement makes ordinary commits with pending
changesets defer publication. pnpm test:release then passed 9 tests, including
6 Cargo release tests. The last fixture-only adjustment passed the same 6
focused tests. Product lanes were not repeated for this release-script change;
the protected PR will run complete CI at its exact revision.
M5 remains Done. M6 remains In progress until all initial crates, their publisher registrations and a real OIDC job are confirmed. The workflow can land safely while its bootstrap variable is unset; this evidence does not claim that the two remaining crates or OIDC verification have completed.
Cargo registry and trusted-publisher completion
Enclosing Jujutsu change: wmmnztxy. Requirements: LTERM-RELEASE-004,
LTERM-RELEASE-005, LTERM-GOV-100 and LTERM-GOV-103. This records completion of
the explicitly authorized release setup. No runtime, package, release-policy
or governance contract changes; the documentation reconciles verified remote
facts with the existing gates. Earlier committed evidence remains unchanged.
Protected integration
PR #2 head 5aaf0a473d4ea746f94a77c4161150e8d109e1c6 passed CI run 38917624700
and specification run 38917624681. gh pr merge 2 --squash --match-head-commit 5aaf0a473d4ea746f94a77c4161150e8d109e1c6 used the ordinary
protected path and produced main f59a16eede5cf8db4afc3a96264b6788510f85f7.
Main CI 38918379135, Pages 38918379101 and Changesets 38918379449 all passed.
Fresh branch-protection reads confirmed PRs, both GitHub Actions checks, strict
up-to-date branches, resolved conversations and administrator enforcement.
Force pushes and branch deletion remain blocked; no bypass allowance was
added. The requested policy requires PRs and checks, without a human review
count. The crates-io deployment environment
accepts only branch main.
Registry bootstrap and consumer
The rate limit reported in setup evidence was honored. From clean qualified main checkouts, these commands completed ordinary Cargo archive verification and publication:
pnpm dev:cargo -- publish -p lapis-terminal-runtime --registry crates-io --lockedpublished runtime 0.1.1 after 14:42:50 UTC from main 9e260407.pnpm dev:cargo -- publish -p tauri-plugin-lapis-terminal --registry crates-io --lockedpublished the Tauri plugin 0.1.1 after the next ten-minute interval from qualified main f59a16ee. The engine 0.1.1 was already published.
Each crate now has an independently read-back trusted-publisher configuration:
engine ID 26195, runtime ID 26197 and plugin ID 26202. All select repository
owner lapismd, repository lapis-terminal, workflow publish-crates.yml and
environment crates-io. The documented crates.io trusted-publishing API used
the existing local credential without displaying or copying it into GitHub.
The live releasePlan against f59a16ee confirmed all three exact 0.1.1 versions
are visible and not yanked, returning missing: []. A disposable consumer
under ignored .local/registry-consumer depends on the public runtime and
plugin at =0.1.1, with no path dependencies or patches. The command
pnpm dev:cargo -- run --manifest-path .local/registry-consumer/Cargo.toml --target-dir target compiled the registry crates and passed the real PTY
example with Native terminal example passed and exit 0.
OIDC and automated delivery
Manual verification run 38919049338 passed before the final crate registration:
it authenticated through the pinned official action, skipped upload and
successfully revoked the temporary token. Once all three public versions and
publisher registrations were verified, gh variable set CRATES_IO_BOOTSTRAP_COMPLETE --body true enabled publication. A fresh API read
confirmed the string value true; no long-lived Cargo credential is stored in
GitHub. Final verification run
38919503295
passed after all three registrations. Its plan and publish jobs succeeded;
OIDC authentication and post-job token revocation passed, while upload was
correctly skipped in verify mode. No artificial version bump, duplicate upload,
npm publication, tag or GitHub release was created to exercise authentication.
M6 is Done for protected Cargo publication on the qualified macOS ARM64 path. Future prepared version PRs use the normal required checks and then OIDC. Consumer adoption, npm publication, other platforms, idle-host performance and visual baseline approval remain separate work. The current slice changes only documentation; its formatter and canonical checks are recorded below.
pnpm exec prettier --write on the seven changed Markdown files passed.
pnpm spec:check passed all 8 lanes, including progress, release metadata,
mdBook and spec-first. Product tests were not repeated locally for this
documentation-only slice; PR #2 and its main revision already passed the full
suite, both Storybook themes, packaged consumers and cold native acceptance.
The evidence PR retains both ordinary required hosted checks before merge.
Prepared release 0.1.1
Enclosing change: the Changesets version PR for 0.1.1.
LTERM-RELEASE-001: synchronized npm, Cargo, demo and lockfile metadata from 0.1.0 to 0.1.1. Existing runtime and UI contracts are unchanged.
Preparation commands: pnpm exec changeset version, offline workspace Cargo
update, lockfile-only pnpm install, pnpm release:check and formatting.
These must succeed before the version commit is created. This is metadata
preparation evidence; the PR’s CI records functional, browser, native and
packaged-consumer results. No test result is inferred from version preparation.
M5 review: release automation remains implemented; registry publication and consumer adoption remain separate. The PR stays open for review.
Attachment initial-output correction
Enclosing Jujutsu change: msmktnzr. Requirements: LTERM-RUNTIME-001,
LTERM-FLOW-001; unchanged host admission: LTERM-HOST-001.
Regression and correction
Desktop native acceptance exposed live shells whose initial prompt never appeared. The runtime captured a blank bootstrap before taking the publisher mutex. PTY output could arrive and be offered without a subscription, then the older blank snapshot was installed. With no later output the prompt stayed invisible indefinitely.
The deterministic private regression coordinates a real engine feed after
bootstrap capture but before subscription installation. The original ordering
fails with initial output must not be lost: one failure, zero passes.
Capture and installation now share the publisher mutex. The same regression
passes: one pass, zero failures. The test also retains exact subscription and
sequence credit and viewport assertions.
Exact command (using the repository’s managed Cargo entry point):
pnpm dev:cargo -- test -p lapis-terminal-runtime --locked session::tests::output_during_attachment_reaches_bootstrap_or_exact_ack_successor -- --exact --nocapture
Reader snapshot recovery already uses publisher-to-engine order. All other inspected paths release the engine lock before taking publisher. Attachment releases publisher before channel delivery, so synchronous sink callbacks do not run under that mutex. No public contract signature changes.
Validation and remaining gates
pnpm dev:cargo -- test -p lapis-terminal-runtime --locked: 31 passed, zero failures, including real PTY lifecycle, environment, wire, credit and viewport tests.- Runtime Clippy with all targets and
-D warnings: passed. - Engine suite: 73 passed, zero failures; the existing idle-host performance gate remains ignored. JavaScript suite: 10 passed, zero failures.
- Both JavaScript checks: zero errors and warnings. Public JavaScript and demo frontend builds passed. Release regression suite: nine passed.
- Fresh-process light and dark Storybook interactions/accessibility: 12 passed per theme, zero failures. Static Storybook build passed.
pnpm spec:checkagainst the committed base: all eight lanes passed, including formatting, architecture, boundaries, progress, coordinated release metadata, mdBook and spec-first.pnpm spec:search --semantic "terminal attachment initial output subscription bootstrap frame credit": QMD returned the canonical frame-delivery chapter and related evidence.- Spec Validator updated to released Node-only 0.2.0. Doctor confirms QMD binary,
native bindings and collection health. Its fixed
spec/src/verification.mdprobe does not recognize this repository’s existingcurrent/verification.mdlayout; this diagnostic is retained, not hidden with a duplicate record. - Complete source CI, packaged consumers, native builds and cold acceptance remain pending for the review branch. Desktop native acceptance must consume the immutable source revision before its initial-output regression is closed.
M1/M4 remain qualified by their historical evidence, with this correction’s remaining integration gates tracked here. No visual baseline approval, additional platform qualification or publication is claimed.
Hosted attachment qualification
Requirements: LTERM-RUNTIME-001, LTERM-FLOW-001, LTERM-RELEASE-002.
The earlier authored correction receipt is
preserved unchanged. Its pending hosted gates were completed afterward at
immutable source revision e5bb735c1225ba2e6a83754170e66c5789418885.
- Source CI 41138998944 completed successfully. It passed specification, workflow, format, type, architecture/boundary/progress/release checks, complete JavaScript and Rust suites, both Storybook interaction/accessibility themes, all builds, packaged Cargo/JavaScript/Svelte/Tauri consumers, and cold production WebView/real PTY acceptance on macOS ARM64.
- Specification run 41138998880 completed successfully at that same revision.
- Ordinary repair PR #4
merged after both runs passed, as merge commit
4c3ae3024ed0346276afc20960f5c83135598542. The exact qualified source revision remains in merged ancestry for downstream Git pins.
M1/M4 source qualification is complete for this correction within the existing macOS ARM64 boundary. Desktop consumer native acceptance remains pending and must consume the exact qualified revision. Its application-owned adapters, source projections and broader native scenarios require separate evidence. Visual approval, idle-host performance and additional platforms retain their existing gates. No version PR merge or registry publication occurred.
npm delivery qualification
Enclosing Jujutsu change: sqykxplu. Requirements: LTERM-RELEASE-002,
LTERM-RELEASE-006, LTERM-RELEASE-007, LTERM-GOV-100 and LTERM-GOV-103.
M5/M6 review preserves existing qualified source/Cargo scope and tracks npm
completion separately. The user explicitly authorized release PR approval,
merge and publication follow-through.
Initial boundary
Terminal attach correction PR #4 merged at
4c3ae3024ed0346276afc20960f5c83135598542. Its complete hosted source CI
41138998944 and spec 41138998880 passed. Evidence PR #6 merged at
33041989963ebf5ab0a577ea5ca9ef02defeda5e after source CI 41140430482
and spec 41140430578 passed. Version PR #5 remains pending while the npm
delivery lane qualifies. All three Cargo crates exist at 0.1.1;
@lapismd/terminal returns npm 404. Existing local npm identity returns E401.
Repository secret inventory is empty, which does not prove inherited protected
organization credentials are absent. No shared authentication was changed.
Implementation and local validation
The CI tarball is preserved with exact source SHA and both checksums. The protected main-only release consumes that immutable artifact, validates exact registry state and source-bound provenance, runs a fresh frozen public consumer and only then creates a scoped GitHub release. It preserves the existing coordinated Cargo version policy and never retries unknown upload outcomes.
Baseline pnpm test:release contained nine release tests. New focused tests
cover rejected triggers, exact CI/check qualification, pending changesets,
artifact tampering, registry errors, provenance mismatch, bounded propagation,
unknown upload outcomes, token rejection and scoped tag identity. Actual local
results: the nine new focused tests passed, followed by all 18 release tests.
pnpm spec:check --base 33041989963ebf5ab0a577ea5ca9ef02defeda5e --head @
passed all eight lanes, including format, architecture, boundaries, progress,
release metadata, mdBook and spec-first. pnpm check:js passed both packages
with zero errors/warnings; pnpm test:js passed ten tests; JS package build
and publint passed. actionlint .github/workflows/*.yml passed; the ordinary
pnpm check:workflow cannot discover a Git root in this non-colocated JJ
workspace, so explicit workflow paths were used. Hosted source CI remains the
full Rust/browser/native gate. The npm-production environment was created
with main-only branch admission and administrator bypass disabled.
Hosted/publication receipts will be appended after qualification.
Specification discovery used QMD semantic search. Validator 0.2.0 is the
latest Deno-free release. Its doctor reports the known hardcoded top-level
verification probe despite the configured canonical current/verification.md;
no duplicate chapter or diagnostic exemption was added.
Pending external gates
Merge the delivery implementation after full protected hosted CI; let Changesets refresh PR #5; review and merge that exact passing version head; verify coordinated Cargo delivery; publish the immutable npm artifact through the protected bootstrap; register trusted publication; verify downloaded npm bytes, signatures, provenance and all public consumer entrypoints; verify the scoped GitHub release; append completion evidence. No publication is claimed.
Detached bootstrap signing follow-up
The first delivery head fdf11d186dee929c56dec83655760abba797a9f1 passed
complete hosted CI 41144329156 and specification 41144329109, including
both Storybook themes, packaged consumers, Rust and cold macOS ARM64 native
acceptance. The real npm tarball and source/checksum manifest were uploaded.
Initial task-scoped local npm authentication was subsequently verified by the release coordinator. To keep that credential outside CI while preserving provenance, explicit attest mode now reuses the exact qualified CI tarball and signs an npm-compatible SLSA bundle through GitHub OIDC. The pinned public Sigstore 4.1.1 API verifies the statement, signature, expected issuer and exact main workflow identity before upload. The workflow reports whether an inherited protected bootstrap credential is present without exposing it. No credential was inspected, copied or stored by this repository.
Two new focused bootstrap-signing tests passed; all 20 release tests and all eight spec-check lanes then passed, and explicit actionlint remained clean. The updated source head still requires its complete hosted CI before merging. The coordinator can stage only the exact immutable tarball with the verified bundle, obtain the required maintainer 2FA approval, then run ordinary registry verification and scoped release completion. This adds no npm authentication or publication permission to the source CI job.
Ordered output capture correction
Enclosing Jujutsu change: ywxyytvn. Requirements: LTERM-RUNTIME-001,
LTERM-FLOW-001, LTERM-GOV-100 and LTERM-GOV-103. M1/M4 review retains the
separate Desktop native gate.
Consumer failure and exact source regression
Desktop hosted native run 41140132320 (Terminal pin e5bb735c) reported
99 passes and 10 failures. Two Terminal cases stopped at the initial $
assertion: cold input/resize/reload and cancelled close. Their DOM receipts
showed eleven blank viewport rows; native session inspection reported one
live session with exited:false. Disable and vault-isolation cases passed
with the same /bin/sh fixture. The revoked-admission case reached only
final native Close and failed forced cleanup; that broader Desktop teardown
issue has separate ownership. No assertion was relaxed.
The previous source correction made bootstrap capture/subscription installation atomic. Initial resize/full snapshots and PTY reader captures still occurred before taking the publisher’s offer lock. An older blank resize capture can therefore replace a newer prompt capture while bootstrap credit is held. Without subsequent output, the renderer remains empty.
Exact command:
pnpm dev:cargo -- test -p lapis-terminal-runtime old_resize_snapshot_cannot_overwrite_newer_initial_output --locked.
The first attempt stopped before compiling: the unchanged build guard required
20 GiB free and reported only 15.0 GiB. That is a host prerequisite failure,
not a functional test result. Shared cleanup is coordinated with the release
owner; no guard or acceptance assertion is bypassed.
The deterministic regression schedules a blank resize capture, a concurrent newer prompt capture, the older offer and the exact bootstrap acknowledgement. Functional before/after counts and wider qualification will be appended after the required host space is available. Version PR #5 remains unmerged.
Deterministic before/after
The release coordinator cleared the existing guard by removing only an unused
Desktop incremental compilation cache; source, profiles, evidence and binaries
were preserved. The exact source regression then compiled and failed 1/1
with an older resize snapshot must not erase newer idle shell output.
The pre-fix helper extracted the original snapshot/capture behavior unchanged.
The corrected helper holds the publisher lock through snapshot selection, engine capture and offer. Both full/resize snapshots and PTY reader frames use that helper; empty reader frames remain inert. The exact regression then passed 1/1. All nested locks follow publisher-to-engine order. Other paths release the engine before acquiring publisher; publication sends after the helper releases publisher. No public API, environment or process policy changed. Wider source, native and Desktop consumer results remain separate gates.
Focused widening passed: pnpm dev:cargo -- test -p lapis-terminal-runtime -p lapis-terminal-engine --locked completed 105 passes, zero failures and one
explicitly ignored known-idle-host performance test. That includes four real
PTY session tests and the wire fixture. Strict Clippy for both crates and all
targets passed with -D warnings. Formatting ran through the owned Cargo
wrapper. Full hosted source CI and a fresh Desktop consumer run remain required.
The first widened specification check passed validation, formatting, architecture, boundaries, progress, release metadata and mdBook, then correctly rejected the missing mapped host chapter. The host chapter now records its unchanged admission/shell/lifecycle contract confirmation; no mapping exemption was added. The same eight-lane command is rerun before committing.
The cold production-WebView/real-PTY source acceptance now checks the initial
/bin/sh prompt before sending any bytes. This preserves the original Desktop
failure boundary in the owning source lane, rather than allowing later input
to repair a missing initial snapshot. Existing input/lifecycle assertions stay.
The same widened specification command subsequently passed all eight lanes, including every mapped canonical chapter. Both JS/demo type checks passed with zero errors or warnings after strengthening the native prompt assertion.
Prepared release 0.1.2
Enclosing change: the Changesets version PR for 0.1.2.
LTERM-RELEASE-001: synchronized npm, Cargo, demo and lockfile metadata from 0.1.1 to 0.1.2. Existing runtime and UI contracts are unchanged.
Preparation commands: pnpm exec changeset version, offline workspace Cargo
update, lockfile-only pnpm install, pnpm release:check and formatting.
These must succeed before the version commit is created. This is metadata
preparation evidence; the PR’s CI records functional, browser, native and
packaged-consumer results. No test result is inferred from version preparation.
M5 review: release automation remains implemented; registry publication and consumer adoption remain separate. The PR stays open for review.
Bootstrap signer identity correction
Enclosing change: oxmwpzpm. Requirements: LTERM-RELEASE-006,
LTERM-RELEASE-007, LTERM-GOV-100 and LTERM-GOV-103. M5/M6 review retains the
actual registry/provenance/consumer completion gates. No npm package, staged
candidate, detached signing artifact or tag was created before this correction.
Reproduction and repair
The published Sigstore 4.1.1 API overload is verify(bundle, policy) for an
embedded DSSE payload. Passing undefined as argument two with a policy as
argument three silently replaces the policy with undefined. Cryptographic
verification still runs, but the requested issuer/SAN policy is ignored.
The initial mock used the same mistaken three-argument contract and missed it.
The corrected public-API call-shape regression in
node --test scripts/npm-provenance.test.mjs failed one of two tests before
the repair because the policy argument was absent. The implementation now calls
the supported two-argument overload and independently checks the verified
signer’s exact issuer and workflow SAN. Missing identity, wrong issuer and a
foreign workflow all fail closed before the bundle is written.
The same focused command then passed three of three tests. The third test uses the real public Sigstore verifier and an immutable signed npm fixture:
- Source:
https://registry.npmjs.org/-/npm/v1/attestations/@lapismd%2fdesign-core@0.7.1. - File:
scripts/fixtures/design-core-0.7.1-provenance.json; 12,005 bytes. - SHA-256:
e68da538522ac91ccf86a1ca0472c71f3895e79a1adf997e27155911c07d7c60. - The unmodified bundle verifies cryptographically as Design Core’s main
release.ymlworkflow. Terminal’s real verifier rejects that valid foreign identity, and rejects a tampered payload. TUF supplies current trust metadata; no signing credential or npm authentication is involved.
The coordinated 0.1.2 version PR #5 was separately approved and merged at
b235b4189fc6c0eccfc8a01285002c21a235fca1 after full required PR CI
41146798073 and specification 41146797902 passed. Earlier dispatched checks
passed too, but GitHub required maintainer approval of the PR-event workflows;
those were approved and passed without bypassing branch protection. Cargo
source is unaffected by this release-tool-only correction. Initial npm signing
and publication wait for the corrected helper’s complete protected source CI.
Local widening passed all 21 release tests and all eight specification lanes, including formatting, architecture, boundaries, progress, coordinated metadata, mdBook and spec-first. The correction remains a release-tool change; full protected hosted CI will still run before merge and bootstrap signing.
Cargo event-trigger correction
The first automatic 0.1.2 Cargo run 41148121586 passed qualification but failed
before authentication/upload: crates.io returned HTTP400 because trusted
publishing does not support workflow_run. Registry inspection confirmed all
three exact 0.1.2 versions absent. The already supported manual main dispatch
was started as 41148378559 after that inspection; no ambiguous upload was
retried and no local token fallback was used.
The automatic workflow now limits workflow-run handling to read-only planning and an Actions-only relay to a new main workflow dispatch. Only that supported event enters protected OIDC publication, and repeats all qualification and registry checks. A focused regression checks the exact scoped dispatch and refuses verify, deferred or already-published plans. Required source/native validation and coordinated Cargo version policy remain intact.
After adding the Cargo relay, focused Cargo/Sigstore tests passed 10/10, all 22 release tests passed, explicit actionlint passed, and all eight specification lanes passed. The supported manual Cargo recovery reached actual publication; its final registry/workflow results remain to be verified before completion.
npm GitHub metadata correction
Enclosing change: lustvvww. Requirements: LTERM-RELEASE-006,
LTERM-RELEASE-007, LTERM-GOV-100 and LTERM-GOV-103. M5/M6 review preserves
actual npm schema/staging/publication/consumer gates separately from signed
artifact preparation and completed Cargo delivery.
Rejected attempt and exact regression
The release coordinator submitted the qualified 0.1.2 tarball with detached
provenance from protected attest run 41149587175, source
2523a0b50a77e22f3b6400b73bf2e3096756c454. npm rejected it with HTTP422
before creating a staged package because the SLSA v1 statement omitted
buildDefinition.internalParameters.github.event_name, repository_id and
repository_owner_id. Expected values were workflow_dispatch, 1422167487
and 311425888. No package or tag was published and no uncertain upload was
retried. Credential/debug logs were not read.
The bundle’s signature and source binding had passed real Sigstore verification; that did not prove provider schema admission. npm’s official provenance generator includes these three internal fields, and the registry binds them to the signed GitHub identity. The owning repository and organization IDs were independently confirmed through the public GitHub repository API.
Exact command: node --test scripts/npm-provenance.test.mjs.
Before repair: three passed, one failed; the concrete schema assertion found
internalParameters undefined. The generator now includes all three fields from
the validated environment. Missing or foreign repository/owner IDs fail before
signing. The registry-side verifier additionally requires the exact internal
fields, alongside source SHA, main ref, publishing workflow and tarball digest.
The existing real cryptographic/foreign-signer/tamper checks remain enabled.
The earlier bundle and attempt remain historical evidence. A fresh complete source qualification and protected exact-main attestation are required before the coordinator submits a newly signed candidate. Initial npm publication and scoped GitHub release remain pending; Cargo 0.1.2 delivery is already verified.
Qualified local results
The repaired focused provenance/registry boundary passed eight of eight
tests. A preserved real Terminal bundle from the rejected attempt is checked by
the actual Sigstore verifier: its correct workflow signature passes, while the
metadata verifier rejects the missing required fields. Public fixture
scripts/fixtures/terminal-rejected-github-metadata.json is 11,886 bytes with
SHA-256 9eabb3d8147ad906a9536d770526a4a77c17c9275cd9de4d9a05ea2887fb78ba.
All 24 release tests passed, including schema admission, foreign/missing IDs, real signature/foreign-signer/tamper checks and coordinated versioning. The full eight-lane specification check passed from source 2523a0b5 through this change, including formatting, architecture, boundaries, progress, release metadata, mdBook and spec-first. Hosted source qualification and renewed signed artifact generation remain required before the next provider submission.
Coordinated 0.1.2 delivery
Enclosing Jujutsu change: qurnqqnu. Requirements: LTERM-RELEASE-001,
LTERM-RELEASE-004, LTERM-RELEASE-006, LTERM-RELEASE-007, LTERM-GOV-100 and
LTERM-GOV-103. M5/M6 review distinguishes version preparation, actual registry
publication and original application acceptance.
Protected source and version delivery
-
Delivery PR #7 merged
6a8dc1bd5009581e2bd740436da2339003f01e25after full CI41144766057and spec41144765950. -
Ordered-capture PR #8 merged
b38ab2076f0a45359776e4642e5f496162df1ecf. Full source CI41146209977and spec41146209921passed. Its cold native receipt includes the idle initial prompt before any input, all existing lifecycle checks, normal exit and zero survivors. The deterministic regression failed 1/1 before repair and passed 1/1 afterward; engine/runtime widening passed 105 cases with zero failures and one separately ignored performance gate. -
Version PR #5 consumed all three patch changesets and was approved at exact head
cd2e0aac6d269bbb12269eeaa3ced8f5bc542fa3. Dispatched checks passed, then GitHub required maintainer approval for the PR-event workflows. Approval was granted; full required PR CI41146798073and spec41146797902passed. The protected merge isb235b4189fc6c0eccfc8a01285002c21a235fca1. -
Publication-gate PR #9 merged
2523a0b50a77e22f3b6400b73bf2e3096756c454after full CI41148588997and spec41148589015. It corrects actual Sigstore policy enforcement and the Cargo provider event restriction, with 22 release tests. Exact-main CI41149183151and spec41149183181also passed. -
GitHub metadata PR #10 merged
9575ac0d0cf02ddf1dea660c2cc3409ba64f7928after full CI41150598922and spec41150598890. The exact-main CI41150958051and spec41150957987also passed. All 24 release regressions include the real rejected signed artifact and npm-required GitHub internal fields.
No branch bypass, weakened assertion, new audit exception or baseline mutation was used. The default workspace’s separate Docker/catalog tooling stack remains untouched. There were no open Dependabot PRs at release preflight.
Actual Cargo delivery
The automatic run 41148121586 failed before token acquisition/upload because
crates.io rejects workflow-run OIDC. All three versions were confirmed absent
before the supported manual dispatch. Run 41148378559 completed real OIDC
authentication, coordinated dependency-order publication and token revocation
from qualified source b235b4189fc6c0eccfc8a01285002c21a235fca1. The new
read-only workflow-run relay uses a supported main workflow dispatch for future
missing versions; current-main run 41149562914 confirmed all versions present
and skipped authentication/upload.
All three 0.1.2 versions were verified non-yanked, downloaded and matched to their registry SHA-256 checksums:
| Crate | SHA-256 |
|---|---|
| lapis-terminal-engine | 487388052891090da10a0b8870f07afa60fdf64f228a582c493219f859dd3446 |
| lapis-terminal-runtime | 94eff086f98b8823f69dadae9f24bd448adebf29ddf419e18a279545efb747a5 |
| tauri-plugin-lapis-terminal | 7f0e4c3407f7619b45ac4b63db2e8d11469207d497ab48810ff28b8d7e4e3bc0 |
Publication timestamps are October 31, 00:10:02–06 UTC. A fresh isolated Cargo
consumer copied the published runtime archive’s examples/basic.rs, resolved
engine/runtime exactly 0.1.2 from crates.io, generated a lockfile and ran:
pnpm dev:cargo -- run --locked --manifest-path .local/cargo-registry-0.1.2/consumer/Cargo.toml --target-dir target.
It passed a real PTY. Lockfile registry sources and checksums match the verified
archives; no path patches or sibling checkout dependencies were used.
Qualified npm bootstrap artifact
The first signed bundle from run 41149587175, source 2523a0b5, passed
cryptography but was rejected before stage creation with npm HTTP422 because
GitHub internal metadata was absent. No placeholder, staged version or package
was created. The initial registry probe remained 404 and the authenticated stage
list was empty. The failed bundle remains a real regression fixture.
Protected main-only attest run 41151430776 reused the real tarball from
successful main CI 41150958051 at source
9575ac0d0cf02ddf1dea660c2cc3409ba64f7928. It signed the corrected
statement using GitHub OIDC and verified the exact issuer/workflow SAN with the
real Sigstore API. The downloaded artifact was independently checked for
coordinated metadata, archive content, checksums, cryptographic identity and
decoded source-bound SLSA. The actual signed GitHub internals are
event_name=workflow_dispatch, repository_id=1422167487 and
repository_owner_id=311425888; all are validated before the renewed handoff.
- Tarball:
lapismd-terminal-0.1.2.tgz, 17,877 bytes. - SHA-256:
cd8d8360bff06e52cbbc30b9efffa91573a3ede74b65025e24877e0bdbaf0fea. - SHA-512 integrity:
sha512-0E6mUoG6gycc3G0nxmkuiZQT31DPnZdscWQdeidxiDNnYFDjb/JKCaOuaIbyn2hjSEd6a9UBu6rteeajuIrDcQ==. - Bundle SHA-256:
e9d15eba0b6e530d4713f254eb289351aaeef33ec1fb787a51514f7120db7023. - Issuer:
https://token.actions.githubusercontent.com. - Verified SAN:
https://github.com/lapismd/lapis-terminal/.github/workflows/publish-npm.yml@refs/heads/main.
The protected initial credential probe reported absent; the release coordinator owns the isolated local npm session and final staging/2FA approval. Its credential was never read or copied by this repository or CI.
The renewed exact-artifact submission was accepted as stage
0f01356a-169f-4191-b9cb-eda8a5285771, proving provider schema admission of
the corrected statement. The user completed the security-key flow, but npm
returned HTTP409 while its automated new-package review was pending. The
coordinator monitors that existing stage rather than uploading another copy.
The subsequent approval exited successfully after the automated review.
The exact 0.1.2 version is public and latest, published October 31 at
00:49:03.639 UTC; no candidate was re-uploaded.
Actual npm and scoped release completion
The public npm 0.1.2 tarball is byte-identical to the governed archive and matches
the SHA-256/SHA-512 values above. Registry provenance binds the exact source,
subject, workflow, main ref and required numeric GitHub identity.
Protected run 41152397561, verify job 124391730477, passed:
- A fresh public-only exact 0.1.2 consumer generated a lockfile, then installed
with
npm ci; the retained lock resolves the real registry URL and exact SRI. - Generic Node import plus Svelte/Vite compilation resolves every public generic, Svelte, Tauri and testing entrypoint.
npm audit signaturesverified 41 registry signatures and 21 attestations.- The registry receipt, consumer manifest and frozen lockfile are retained in
the run’s
npm-registry-receipt-9575ac0d0cf02ddf1dea660c2cc3409ba64f7928artifact.
The npm upload job was correctly skipped because the approved version existed.
GitHub also skipped the release job through its implicit success dependency on
that skipped ancestor, despite verification passing. Before recovery, the tag
and release were confirmed absent. The authorized guarded source helpers then
rechecked the real successful consumer run/job, current main/source CI and
protected checks, coordinated metadata, qualified archive and live registry
provenance. No synthetic trigger, auth context or branch bypass was used.
They created the scoped release
at the exact source 9575ac0d0cf02ddf1dea660c2cc3409ba64f7928.
The independently read-back release is stable, published October 31 at 00:54:12 UTC,
with a commit tag pointing to that exact source. Its tarball asset digest is
sha256:cd8d8360bff06e52cbbc30b9efffa91573a3ede74b65025e24877e0bdbaf0fea;
its attached manifest digest is
sha256:b39cc0ae5369871295c2cf946e3ea1bc50703ae97a93e08aa5521a7f40998e02.
The workflow now explicitly runs the release job only after successful plan and
verification, even when the already-published upload was skipped.
Trusted publisher registration and independent npm trust list read-back
confirmed ID 28f22348-6a3f-4c3c-aa3e-8b68ad014630, GitHub
lapismd/lapis-terminal, publish-npm.yml, environment npm-production, and
createPackage/createStagedPackage permissions (publish/stage-publish CLI
labels). No root npm credential was read, modified or copied into CI or source.
Retained qualification boundaries
Cargo and source-native success do not complete Desktop’s fresh native consumer gate or its unrelated native Close failures. Visual baseline approval, the known-idle-host performance measurement and other platforms remain separate.
The canonical receipt/verification updates and explicit release-job dependency condition passed actionlint and all eight specification-check lanes locally. Repository protection still requires the ordinary full hosted CI before this follow-up merges. No product/runtime source or baselines changed.
Replacement attachment sink fence
Enclosing change: sonttnpn. Requirements: LTERM-RUNTIME-001, LTERM-FLOW-001,
LTERM-GOV-100 and LTERM-GOV-103. M1/M4 review retains separate deterministic,
real PTY, production WebView and Desktop consumer evidence.
Published runtime 0.1.2 exposes a private concurrency defect: detach faults its subscription, releases the publisher lock, then clears the separately locked sink. A replacement can install its sink in that gap and lose it to the old detach. Desktop’s unawaited viewport disposal and remount can overlap these operations; an attached renderer can remain blank without a reported error.
A disposable registry-only consumer exercised the real 0.1.2 runtime and one
local /bin/sh PTY. Across 1,000 concurrent detach/replacements, four successful
replacement calls delivered no bootstrap (iterations 20, 171, 333 and 358).
No shell input, package patch, mock transport or Desktop source edit was used.
The forced-interleaving regression is:
pnpm dev:cargo -- test -p lapis-terminal-runtime stale_detach_cannot_clear_a_replacement_attachment_sink --locked.
Before: one failure, no retained sink instead of the replacement sink. After:
one pass, zero failures. The test
holds the old detach at actual sink removal while a competing attachment either
completes or proves it is blocked by the publisher transaction.
The repair installs the replacement sink within bootstrap capture’s publisher transaction and holds that same publisher lock through old sink removal. Publisher-to-engine ordering, channel delivery outside the publisher lock, bounded frame credit, viewport fences and PTY lifetime remain unchanged.
The user authorized this Rust-only source repair and an immutable Git consumer pin. The already verified 0.1.2 Cargo/npm release remains immutable; this repair does not initiate another crates.io or npm publication wave. Native Desktop correlation and final source/consumer qualification remain pending.
Initial full-workspace Rust validation stopped while compiling the unchanged native demo because its frontend distribution had not been built in this fresh workspace. No runtime test failed. Build the normal JS/demo prerequisites and rerun that same full-workspace command; no distribution shim is permitted.
The first spec check correctly rejected the missing mapped host chapter. Its unchanged-admission confirmation accompanies the runtime/flow updates; all host authority and governance gates remain intact.
Desktop’s existing bundle was used read-only for 14 cold mounts: ten displayed the idle prompt and four stayed blank at the unchanged ten-second timeout. In two failures, a post-failure real Tauri reattachment immediately delivered a complete frame containing the existing shell prompt, with no input and a live shell. This separates intact PTY/engine state from the lost rendered delivery; it does not yet qualify Desktop against the new source repair.
Source qualification
The unchanged real-PTY 1,000-remount diagnostic passes with zero missing bootstraps against the repaired owning runtime source. Its isolated Cargo consumer uses a documented, ignored path override only for this source test; the earlier failure used the unmodified published 0.1.2 runtime.
After normal pnpm build:js and pnpm demo:build prerequisites, the exact
pnpm dev:cargo -- test --workspace --locked command passes 109 cases with zero
failures and the existing one ignored idle-host performance gate. Strict
pnpm dev:cargo -- clippy --workspace --all-targets --locked -- -D warnings
passes. All eight pnpm spec:check lanes, formatting, architecture, boundaries,
milestone links and coordinated release metadata pass.
Required hosted full checks, light/dark interaction/accessibility, cold native demo and the original Desktop consumer gate remain open before final adoption.
Hosted replacement sink qualification
Enclosing change: usnxnuyw. Requirements: LTERM-RUNTIME-001,
LTERM-FLOW-001, LTERM-GOV-100 and LTERM-GOV-103.
The earlier source receipt remains immutable.
Its hosted source gates completed at exact signed source
2463f944149d753eaf638cf876393a6f60f50190:
- Full macOS ARM64 CI passed checks, all unit/runtime tests, light and dark Storybook interactions and accessibility, package/build checks, and the cold production WebView with a real PTY. The native demo requires the idle prompt before sending input and retains its lifecycle/cleanup checks.
- Specification CI passed its protected build.
- PR #12 merged normally
after both required checks passed, at
fe678e9f98f644b32a4cace98cbc602972f3d46b.
M1/M4 review: private source correctness and standalone native acceptance are complete. Desktop must independently pin that qualified owning Git source and pass its original cold native consumer gate. Other platform, visual approval and known-idle performance boundaries remain unchanged.
This Rust-only repair changes no npm payload or release version. The verified 0.1.2 registry artifacts remain immutable; no new npm or crates.io publication wave is prepared or implied.