Repository navigation
Description
Objective
Design and implement an opt-in, reusable path for reproducible README screenshots or short terminal demos across Z-Shell plugin repositories.
This is the owning GitHub issue for Linear ZSH-18. The work was deferred from the README/template design associated with z-shell/zsh-eza#65.
Scope
- Define a concise repository-owned demo scenario/configuration contract.
- Run demonstrations in a deterministic Zsh environment with controlled terminal dimensions, theme, fixtures, timing, and locale.
- Produce GitHub-compatible static screenshots and/or short animated terminal demos.
- Support the same local regeneration command and an explicitly triggered reusable CI workflow.
- Store generated assets in the owning plugin repository with useful README alt text.
- Pilot with
z-shell/zsh-eza, then validate the contract against a second Zsh plugin. - Evaluate maintained terminal-capture tooling such as VHS and asciinema plus a renderer.
- Pin every external action, tool release, or container artifact immutably.
Design decisions required
- Select the capture/rendering tool and supported output format after comparing maintenance, reproducibility, CI complexity, and supply-chain risk.
- Define the caller-owned scenario file, fixtures, generated-asset path, and local command contract.
- Decide whether the reusable workflow verifies committed output, uploads a preview artifact, or both; it must not create automatic asset churn.
- Select the second plugin pilot and a stable behavior-focused scenario.
- Define deterministic controls and failure messages, including how network access and environment leakage are prevented.
Acceptance criteria
- A canonical implementation and usage guide live in
z-shell/.github. - A plugin opts in with a concise scenario/configuration file and no copied workflow logic.
- The same command regenerates the visual locally and in CI.
- An unchanged scenario produces unchanged committed output.
- The workflow validates generated output and fails clearly when generation cannot complete.
-
zsh-ezahas a generated visual demonstrating its core behavior. - A second Zsh plugin successfully exercises the reusable path.
- The Zsh plugin README template explains when to include a visual and links to the canonical workflow.
Safety and workflow boundaries
- Design approval precedes implementation.
- Use explicit/manual workflow triggering or verification-only pull-request execution; do not commit generated churn automatically.
- Demo execution must require no credentials, private host data, user-specific paths, or network-dependent behavior.
- Preserve least-privilege workflow permissions and organization action-pinning conventions.
- Keep generated assets in the owning repository and long-form usage guidance in the canonical organization documentation.
Research snapshot — 2026-07-18
- VHS v0.11.0 is current and provides one declarative
.tapescenario for scripted terminal input plus GIF, WebM, PNG-frame, static screenshot, and text output. It offers the lowest custom orchestration burden, but bit-identical media still requires a pinned full runtime (VHS, ffmpeg, ttyd, browser, fonts, Zsh, and OS). - asciinema CLI v3.2.1 with agg v1.9.0 is actively maintained, but deterministic regeneration adds a separate interaction driver, runtime-timing and metadata normalization, and a second renderer. Keep it as a possible later adapter rather than the v1 default.
- The stock
vhs-actiondefaults its tool version tolatest, and the stock container does not supply the complete Z-Shell safety/reproducibility contract. The evidence therefore favors a Z-Shell-owned wrapper that verifies and pins the renderer/runtime immutably; no renderer decision is approved yet. zsh-ezais the first pilot: render a fixed directory/Git fixture and demonstratellplus tree behavior without network or host data.zsh-fancy-completionsis the strongest second pilot: a controlled filename-completion scenario exercises scripted keypresses and transient interactive frames, complementing the simplerzsh-ezacase.- Candidate workflow boundary: explicit dispatch and reusable
workflow_call,contents: read, no secrets or automatic commits/comments, network disabled during rendering, two identical renders required before byte comparison, and preview artifacts for maintainer review.
Design approval remains the gate before any implementation branch or pull request.
Approved v1 output contract — 2026-07-18
- Generate both a static PNG and a short GIF from the same repository-owned scenario.
- Use the PNG as the accessible static/reduced-motion fallback and the GIF as the concise behavior demonstration.
- Commit both assets to the owning plugin repository with useful README alt text; automation must never commit them automatically.
- This approval covers output formats only. Renderer ownership, workflow boundaries, and implementation architecture remain under design review.
Approved architecture — 2026-07-18
z-shell/.githubowns a hardened, versioned OCI renderer image; all consumers pin the exact immutable digest.- Local generation and CI invoke the same renderer command and manifest contract.
- The organization repository owns the image source and entrypoint, manifest schema, reusable workflow, starter caller, runbook, and README-template guidance.
- Each plugin owns only its concise manifest, VHS
.tapescenario, deterministic fixtures, committed PNG/GIF assets, and tiny explicit-dispatch workflow caller. - The capture runtime is non-root, credential-free, network-disabled during rendering, and read-only except for the declared output directory.
zsh-ezavalidates ordinary command output;zsh-fancy-completionsvalidates scripted interactive keypresses and transient completion frames.- Do not promote the experiment to
PATTERNS.mdor an organization ADR until both pilots validate the contract.
Approved execution and data flow — 2026-07-18
- Each plugin manifest declares the schema version, scenario and fixture paths, PNG/GIF destinations, README path, and alt text.
- The VHS tape contains behavior only; the renderer supplies deterministic presentation/environment defaults and GIF output directives.
- The static PNG is extracted from the GIF's final frame with the renderer's pinned ffmpeg so both assets represent the same run.
renderregenerates committed assets.verifyrenders twice in isolation, rejects unequal hashes, and then compares stable output with committed assets.- The reusable workflow receives the caller repository, exact commit SHA, and manifest path, checks out that commit, and invokes the same
verifyentrypoint available locally. - Pull the pinned image before capture, then disable networking for the capture itself.
- CI uploads regenerated PNG/GIF files and comparison metadata for review but never commits, comments, or mutates the pull request.
- Missing assets, invalid paths, unstable rendering, and committed-output drift are separate actionable failure classes.
Approved safety and failure handling — 2026-07-18
- Treat every tape as executable repository code. Never use
pull_request_target; fork scenarios run only on ephemeral hosted runners with a read-only token and no secrets. - Validate the exact manifest schema and known keys before execution; normalize relative paths, reject symlinks and
.., confine scenarios/fixtures to.github/demos/, and confine outputs todocs/assets/. - Run as a numeric non-root user with a read-only root filesystem, dropped capabilities,
no-new-privileges, bounded PID/CPU/memory/time limits, and networking disabled. - Mount repository input read-only and only staging/output directories writable; never mount host home, Docker socket, SSH agent, credentials, caches, or shell history.
- Pass only deterministic environment values: fixed locale, UTC timezone, terminal type, disposable
HOME/ZDOTDIR, prompt, andPATH. - Build from digest-pinned bases/dependencies, verify the VHS release checksum/signature, generate SBOM/provenance, and pin every GitHub Action to a full SHA.
- Report distinct invalid-contract, unsafe-path, unavailable-renderer, execution, nondeterminism, drift, and README linkage/accessibility failures without exposing host paths or environment dumps.
- Preserve preview assets and hashes for nondeterminism or drift diagnosis without overwriting committed files.
Approved testing and rollout — 2026-07-18
- Contract tests cover valid manifests, unknown keys, missing fields, path traversal, symlinks, wrong roots, unsafe alt text, and missing README references.
- Renderer tests cover deterministic command composition, environment allowlisting, final-frame PNG extraction, named error classes, and output-size enforcement.
- Runtime tests prove non-root execution, disabled capture networking, dropped capabilities, read-only inputs, and absence of host-state access.
- A committed golden scenario must render byte-identically twice within each run and across two independent CI runs at the same image digest.
- Reusable-workflow integration tests cover success, drift, nondeterminism, timeout, missing assets, and unsafe manifests against an exact commit SHA.
- V1 supports only
linux/amd64, 960×540 output, a maximum 12-second/5 MiB GIF, and a maximum 1 MiB PNG. Other platforms require separate identical-rendering evidence. - The
zsh-ezapilot uses a fixed fixture and checksum-pinned realeza; thezsh-fancy-completionspilot uses a deterministic local filename-completion menu. - Each pilot requires matching hashes from one local container run and two independent CI runs, both README assets, descriptive alt text, and a static PNG link beside the GIF.
- Promotion to
PATTERNS.mdoccurs only after both pilots pass. Add an ADR only if the service later becomes mandatory policy. - Roll out in order: central renderer/tests, immutable tagged image,
zsh-ezapilot,zsh-fancy-completionspilot, then template/pattern promotion.
Written-spec gate — 2026-07-18
- Written specification approved on 2026-07-18.
- The implementation plan is committed in the private meta-workspace and independently reviewed.
- Subagent-Driven execution was selected; isolated implementation branch
feature-458now exists and no pull request exists. - Active gate: prove the hardened central runtime feasibility slice before broader implementation.
- Publication, GHCR visibility, branch creation where policy is unresolved, merges, and promotion remain maintainer gates.
- Design reusable README terminal demo automation #458 remains the implementation source of truth; Linear ZSH-18 mirrors strategic state.
Implementation start — 2026-07-18
- Execution mode: Subagent-Driven Development with TDD and independent task review.
- Branch:
feature-458, created in an isolated worktree from exactorigin/maincommit8ee041623cd5a2892887357ea9f0fb443ff3d2b4. - First checkpoint: Task 1, the hardened VHS/browser/Landlock runtime feasibility slice.
- No pull request, image publication, package-visibility change, release tag, merge, or promotion has occurred.
- Design reusable README terminal demo automation #458 remains the implementation source of truth; Linear ZSH-18 mirrors strategic state.
Feasibility gate contract amendment — 2026-07-18
- The exact restricted self-test reached the Landlock-confined VHS/ttyd child, then proved VHS v0.11.0 requires write access to the exact character device
/dev/null. - The approved contract now permits read-only
/devplus the sole non-persistent write sinklandlock.RWFiles("/dev/null"); it does not grant write access to the/devhierarchy or another device. - Tests must validate no-follow device identities 1:3 and 1:5, prove
/dev/zerowritable before restriction, close the descriptor, then prove after exact Landlock V3 restriction that/dev/nullwrites succeed and/dev/zerowrite-open fails specifically withEACCES. - Two independent reviews found no remaining critical or important issue at spec SHA-256
8829effd3d0402f2b6f879e8d2852b90065f37d8734ed0a07bae96ee102071e9and plan SHA-2565a1745b094c62c8c2c169254d74358ee6a05d7e7f5768e3c1be8b49e525c7ca9. - The private meta-workspace contract amendment is committed at
6de925c201f2c8cb45cd6adec8fa60cbd7dcb74f. No permissive fallback, broader device grant, PR, publication, or outer-runtime relaxation occurred.
Chromium sandbox feasibility blocker — 2026-07-18
- The amended exact-device Landlock test is green, full Go tests and vet pass, the Docker frontend is immutably pinned, and the exact test image builds.
- The unchanged final self-test still exits 5 at capture. Without the optional package Chromium reports no usable sandbox; a disposable exact-package probe with
chromium-sandbox=150.0.7871.124-1~deb13u1proves the setuid path is disabled byPR_SET_NO_NEW_PRIVSand the namespace fallback fails withEPERM. - Implementation stopped without
--no-sandbox, removal ofno-new-privileges, added privilege, namespace relaxation, commit, push, PR, or publication. - Active next step: evaluate documented browser-isolation models, revise and independently re-review the security contract only if a defensible option exists, then rerun Task 1 from the exact outer boundary.
Approved browser-isolation amendment — 2026-07-18
- VHS v0.11.0's supported non-empty
VHS_NO_SANDBOXcontrol is now an explicit exception only in the already-restricted capture-child environment; ineffectiveCHROME_BINis removed. It is never image-global, parent-supplied, plugin-controlled, or a runtime fallback. - Chromium's initial top-level page is the pinned local ttyd endpoint. Plugin terminal bytes and same-authority loopback remain untrusted; remote/open-web connections cannot succeed under
--network=none. - Before VHS starts, production code must reject every earlier Rod browser candidate and no-follow validate root-owned, non-group/other-writable
/usr/bin/chromiumagainst SHA-2562c8d32d29dc6781c35ae196ea83299d507ac88fc339301abe74672feda299779. Failure is sanitizedrenderer-unavailablebefore VHS or Rod's downloader can run. - Landlock ABI 3 execution is frozen as: all preflight;
runtime.LockOSThread; record TID; close inherited descriptors; exact V3 restriction; same-TID recheck; immediateunix.Exec. Every post-lock failure uses a non-returningSYS_EXIT_GROUPloop, with a live-sibling regression test. - The image must not install
chromium-sandboxor another setuid helper. Capability additions, disablingno-new-privileges, nested/user namespace relaxation, and custom/unconfined seccomp or AppArmor remain forbidden. - Independent security, consistency, and testability reviews are Ready. Reviewed content hashes were spec
c1077918…, plan7c8c6d41…, and Task 1 brief3ae882cd…; the mechanically approved final file hashes are specea3730cc…, plan8c63ca1a…, and brief3ae882cd…. The private contract commit isd95b4ba20ed72c64b863e45c8ab342305b363b67.
Current phase
Implementation resumes at Task 1 on isolated branch feature-458. The next gate is RED/GREEN proof for the exact environment, Chromium preflight/downloader denial, same-thread Landlock inheritance, process-wide post-lock failure, then the unchanged hardened image build and self-test. Task 1 remains uncommitted; no pull request, push, release, GHCR publication, merge, or policy relaxation exists.
Triage
Suggested item type: Improvement
Suggested priority: Medium
Suggested effort: Medium
Suggested status: In progress
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsIn Progress
Activity
ss-o commentedon Jul 18, 2026
Agent handoff — Chromium sandbox feasibility blocker
Status: Task 1 is blocked at the exact hardened self-test; branch
feature-458remains uncommitted at8ee041623cd5a2892887357ea9f0fb443ff3d2b4.Verified:
/dev/nullLandlock amendment passed its exact RED/GREEN test: read-only/dev, soleRWFiles("/dev/null")exception, and preconditioned post-V3/dev/zeroEACCES.chromium-sandbox, Chromium reports no usable sandbox. A disposable probe adding exact packagechromium-sandbox=150.0.7871.124-1~deb13u1shows the setuid sandbox is disabled by parentPR_SET_NO_NEW_PRIVS; its namespace fallback fails withEPERM.Blocker: Chromium cannot initialize either Linux sandbox under the currently approved outer restrictions. Any resolution changes the approved security contract.
Not attempted:
--no-sandbox, removal ofno-new-privileges, added capabilities/privilege, relaxed namespace or seccomp policy, permissive Landlock fallback, commit, push, PR, or publication.Exact next steps:
ss-o commentedon Jul 18, 2026
Agent handoff — browser-isolation amendment approved
Status: the Chromium feasibility decision is resolved and Task 1 may resume on isolated branch
feature-458. Independent security, consistency, and testability reviews are Ready; the approved private contract commit isd95b4ba20ed72c64b863e45c8ab342305b363b67.Approved final hashes:
ea3730cc2b0b420f93b930b09577dcc19dc9e150ef90f1a08424da162db8c2e18c63ca1aa7ece3a278be05923b59c9c181ad260468c90d861579f3a576084b753ae882cd3fffff9b51d60c2b1859a404fb2433ae25a40662c81bcd861e69a7b1Exact next steps:
VHS_NO_SANDBOX=1boundary.LockOSThread/same-TID Landlock exec plus process-wideSYS_EXIT_GROUPfailure behavior.Still prohibited: setuid browser helpers, capability additions, disabling
no-new-privileges, namespace relaxation, custom/unconfined seccomp or AppArmor, Landlock-unconfined fallback, remote/open-web browsing, push, PR, publication, or merge before their planned gates.ss-o commentedon Jul 18, 2026
Agent handoff — ABI 3–7 launcher audit
Task 1 remains uncommitted on
feature-458at base8ee041623cd5a2892887357ea9f0fb443ff3d2b4.Verified progress within the already approved contract:
/workstate, deterministic Zsh startup, empty eza configuration, and/work/democwd are implemented with focused RED/GREEN coverage;A fresh security audit of the pinned
go-landlock v0.9.0source found a new ABI 3–7 blocker. The current launcher callsclose_range(..., CLOSE_RANGE_UNSHARE)and thenlandlock.V3.RestrictPaths. On ABI 3–7 the library creates the ruleset FD in the caller's unshared FD table and uses an all-threadpsxsyscall; sibling threads cannot see that FD, so inconsistent results can panic instead of taking the required sanitizedSYS_EXIT_GROUP(4)path. The exact Docker build/self-test was intentionally not rerun after this finding.Recommended contract amendment:
no_new_privs, raw current-threadlandlock_restrict_self, close the ruleset FD, recheck TID, and rawexecve.SYS_EXIT_GROUPloop.renderer-unavailable, and state honestly that process-group cleanup is lifecycle management rather than an adversarial boundary against native code that deliberately callssetsid.Raising the minimum to ABI 8 would abandon the approved ABI 3 support and is not recommended. Applying the high-level all-thread policy before FD closure would violate the approved terminal ordering and retain post-restriction runtime work.
Additional bounded Task 1 audit items remain queued after the launcher decision: split the pre-Landlock helper environment from the final VHS environment, assert earlier Rod candidates absent in the built image, strengthen the network/runtime probe and smoke tape, and replace the stale pre-amendment report.
No outer security flag was relaxed. No child commit, push, pull request, image publication, release, merge, or Task 2 work occurred.
ss-o commentedon Jul 18, 2026
Task 1 specification gate — option 1 recorded
The approved ABI 3–7 launcher direction is now captured in the canonical private workspace specification.
3ca4416(docs(dot-github): specify ABI 3 launcher contract)1e0c087dddf763e261eb327cb62b2a691cf9021eb4cde5fb2890705a77c0654eFD_CLOEXEC; afterruntime.LockOSThreadand raw TID capture, use split rawclose_rangecalls around that FD withCLOSE_RANGE_UNSHARE, then rawno_new_privs, current-thread restriction, FD close, TID recheck, andexecve.EXIT_GROUP; reserved normal exits 4/5 remain distinct from signals and are sanitized by the trusted parent.setsid/setpgid; Landlock and the externally network-isolated container remain the authority boundary.git diff --checkclean; Trunk clean; Lychee 19/19 links valid; the commit contains exactly the one specification file.No launcher implementation file was changed in this gate. Implementation remains paused pending maintainer review of the written amendment. After approval, the next action is to amend/review the implementation plan and Task 1 brief before resuming TDD.
ss-o commentedon Jul 18, 2026
Agent handoff — ABI 3–7 Task 1 execution gate approved
Status: Maintainer written-specification review is approved, the amended implementation plan and Task 1 brief are independently Ready, and Task 1 may resume on the existing isolated
feature-458worktree.Authoritative private checkpoint
04899da—docs(dot-github): approve ABI 3 implementation plan7eeb01c85a4971d4212949ef952c4a0af359a63b60dbb6306aa918edb2595721748d1c8cd11eed2c83f18a1328ae7a7218228cbaf37146507bbcf116252e4d57c244202268d70b848614f959eaf8c26c55644edd0f17ef8af6828a1e794c7eb0f6b78e4f4dcde64e3b141842f87a3d2c669a176706e18ad183d6ffd3d72eaf1fLocked execution contract
8ee041623cd5a2892887357ea9f0fb443ff3d2b4; do not recreate or clean the worktree.FD_CLOEXEC, owns NUL-terminated exec vectors, and maps every sanitized pre-lock failure to normal exit 4 after cleanup.close_rangearound the ruleset FD, raw restriction andexecve; runtime/policy/descriptor/TID failures exit-group 4 and returnedexecvealone exits 5.execvevector contains oneVHS_NO_SANDBOX=1; the trusted parent and pre-Landlock helper do not.Cmd.WaitDelaybounds escaped stdout/stderr holders; PGID cleanup is lifecycle management, not adversarial containment.Review and verification
git diff --check: clean.Exact next action
Resume Subagent-Driven TDD with the environment-separation RED tests, then low-level ruleset/same-FD identity tests, the complete preflight exit-4 matrix, raw vectors/terminal source and escape-analysis gates, descriptor/live-sibling/real-exec tests, all-outcome process cleanup, browser/smoke tests, and finally the unchanged hardened Buildx plus outer self-test boundary.
No child commit, push, pull request, image publication, release, merge, Task 2 work, or security-boundary relaxation has occurred.
ss-o commentedon Jul 18, 2026
Agent handoff — Task 1 execution resumed
Status: The previously unavailable pinned-Go Docker gate is available again. Task 1 has resumed on the existing isolated
feature-458worktree.Exact Slice 4 RED evidence
TestPrepareExecVectors: PASS.TestTerminalFakeRawOperationOrder: PASS.TestTerminalSourceStructure: FAIL because its source assertion searches the whitespace-specific literalfault: terminalFaultNone, while the gofmt-aligned composite literal expresses the same production value with field alignment.Current action
Use systematic debugging and TDD to make the source gate semantic rather than whitespace-sensitive, retire stale pre-amendment launcher assertions and the returning production restriction path, complete the approved raw-terminal static contract, then continue the remaining Task 1 slices only after the exact focused gate is GREEN.
No child commit, push, pull request, image publication, release, merge, Task 2 work, or security-boundary relaxation has occurred.
ss-o commentedon Jul 18, 2026
Agent handoff — Task 1 security boundary checkpoint
Status: Slices 1–9 of the hardened central runtime feasibility task are complete on isolated branch
feature-458.Durable child checkpoint
b632134374e5e8a84564833e6882378f4ff0e4b8—feat(terminal-demo): enforce raw capture boundary.tools/readme-terminal-demo/; child worktree clean.Fresh verification
go vet ./...: GREEN.gofmtgate: GREEN.Next action
Slice 10 now adds the missing browser-resolution/downloader test, smoke presentation/runtime probes, then runs the exact Buildx image and unchanged hardened outer self-test.
No push, pull request, image publication, release, merge, Task 2 work, or security-boundary relaxation has occurred.
ss-o commentedon Jul 18, 2026
Agent handoff — Task 1 PTY device-boundary blocker
Status: Task 1 is fail-closed in Slice 10 on isolated branch
feature-458. The durable child checkpoint remainsb632134374e5e8a84564833e6882378f4ff0e4b8(feat(terminal-demo): enforce raw capture boundary). No pull request or publication exists.Preserved Slice 10 work
00200200first reproduced a parser RED; correcting the LinuxRTF_REJECTmask to0x0200made the focused regression GREEN.PASS TestPinnedVHSExitStatusContract.detected Landlock ABI: 9, then times out in capture.Root-cause evidence
/,/token, and/ws; ttyd then exits with the exact sanitized diagnosticpty_spawn: 13 (Permission denied)./devplus sole writable/dev/nullcontract cannot allocate the PTY required by VHS/ttyd.Cleanup and current tree
main.go,main_test.go, andtestdata/smoke/readme.tape.git diff --checkpasses and the diagnostic-token scan is empty.no-new-privileges, Landlock, network, or outer-container relaxation was attempted.Decision required before implementation resumes
/dev/zerodenial; orAfter one option is approved, update the specification and plan first, synchronize both trackers, then resume TDD and rerun the unchanged or newly approved exact outer self-test.
ss-o commentedon Jul 19, 2026
Agent handoff — PTY boundary evidence (2026-07-19)
Task 1 remains at checkpoint
b632134374e5e8a84564833e6882378f4ff0e4b8; Slice 10 still has only the expected three tracked files and no production PTY-policy change.A disposable, same-package Landlock ABI 3 matrix isolated the minimum PTY filesystem authority:
/dev/pts/ptmxO_RDWRfails withEACCES./dev/pts/ptmxWRITE_FILE: the master opens, but the dynamic slave still fails withEACCES.WRITE_FILEbeneath/dev/pts: master allocation, unlock/number lookup, and dynamic slaveO_RDWRall succeed./dev/nullremains writable and/dev/zeroO_WRONLYremains denied specifically withEACCES.This proves the capture path does not need
MAKE_CHAR,MAKE_DIR,REMOVE_FILE,REMOVE_DIR,TRUNCATE, broad/devwrite access, capability additions, namespace/network changes, or seccomp/AppArmor/no-new-privileges relaxation. The disposable test source and image were removed;git diff --checkremains clean.Recommended amendment for explicit approval and independent security review:
/devread-only and the existing exact/dev/nullexception.WRITE_FILEbeneath no-follow-validated/dev/pts; do not route it through the broadReadWritePathsmask./dev/pts/ptmxas character device 5:2 and fail closed unless the private container devpts mount initially contains onlyptmx(the outer invocation remains non-TTY)./dev/zerodenial.No contract/spec, production source, commit, push, PR, publication, or issue status was changed. Next gate is explicit design approval; after approval: amend/re-review the private contract, implement with TDD, and rerun the unchanged exact hardened self-test.
ss-o commentedon Jul 19, 2026
Agent handoff — PTY design review and containment evidence (2026-07-19)
Independent security review recommends the dedicated
/dev/ptsrule, subject to explicit acceptance conditions. It also clarified that “onlyWRITE_FILE” is the incremental grant: the existing read-only/devrule already suppliesREAD_FILEandREAD_DIR.New evidence
/dev/pts/0plusptmx; the non-TTY container exposed onlyptmx. Both reported a realdevptsmount at/dev/pts. The absence of container A's slave from container B directly demonstrated per-container devpts isolation for the required Docker runtime.RLIMIT_NOFILE=256.--ulimit nofile=256:256added still reacheddetected Landlock ABI: 9and then the same knownexecution-failed: capture (capture.timeout)PTY gate. The FD bound therefore introduces no earlier runtime failure.Reviewed amendment conditions
AccessFSWriteFilebeneath/dev/pts; never route it through broadReadWritePaths./dev/ptsno-follow, verify directory identity andDEVPTS_SUPER_MAGIC, then resolveptmxrelative to that same descriptor and require character device 5:2.ptmx, an exact devpts mount at/dev/pts, no namespace sharing, no host devices, and no injected mount over/dev/pts. Fail closed otherwise.--ulimit nofile=256:256to every renderer invocation and policy test while preserving the 128 PID, 1 GiB, 2 CPU, 45-second, network-none, read-only, capability-drop, no-new-privileges, and tmpfs bounds./dev, exact/dev/null,/dev/zero == EACCES, exact ABI-3 handled rights, and unchanged outer Docker restrictions.RLIMIT_NOFILEis per-process rather than a devpts-instance PTY cap. The residual bounded-duration resource risk remains limited by the combined FD/PID/memory/CPU/timeout controls and the dedicated ephemeral hosted-runner boundary.The broad
ReadWritePaths("/dev/pts")alternative remains rejected because it grants unproven create/remove/truncate classes. A PTY broker or replacement renderer remains the fallback only if the narrow rule cannot satisfy acceptance; ttyd has no preallocated-PTY interface, so that route requires a fork/replacement and a larger trusted codebase.No contract/spec, production code, commit, push, PR, publication, or issue status changed. The active gate is explicit maintainer approval of the narrow amendment including the residual resource-risk acceptance above.
ss-o commentedon Jul 19, 2026
PTY amendment implementation checkpoint — 2026-07-19
588884b35fdfcd4d1dba5b85059d12e226be8809991ae8e5966bb391d7f77c4f.feature-458uses a fixed trusted-code toggle and grants only LandlockWRITE_FILEbeneath a pinned, verified private/dev/pts. Preflight requires devpts, a distinct mount boundary, initialptmx-only topology, and relative no-follow character device 5:2 on the same filesystem. Generic writable overlap is rejected.TIOCSPTLCK/TIOCGPTN, opens the dynamic slave, preserves/dev/nullwrite success, and preserves/dev/zerowrite-openEACCES.--ulimit nofile=256:256; it exited 0 after reporting Landlock ABI 9.No new commit, push, pull request, release, package visibility change, or merge has occurred at this checkpoint. Next: close review findings, rerun the complete hardened evidence, commit, push, and synchronize a draft PR.
ss-o commentedon Jul 19, 2026
Task 1 publication checkpoint — 2026-07-19
The maintainer-approved private-devpts PTY amendment is implemented and published for review.
abf9119d1b74ab5acb422d8d30b0f9b39b3db1b6(feat(terminal-demo): prove hardened renderer runtime)feature-458(two focused commits, clean worktree)The final boundary uses the same no-symlink/no-magic-link
openat2descriptor for validation and Landlock rule installation, verifies a private devpts filesystem with initialptmx-only topology and character device 5:2, rejects writable physical aliases of devpts,/dev, or/, and adds only incrementalWRITE_FILEbeneath devpts. Read-only/dev, the exact/dev/nullexception, and the post-restriction/dev/zerodenial remain intact. Landlock ABI 3 does not mediate device ioctls; no ioctl, capability, namespace, seccomp, AppArmor, no-new-privileges, device, or mount relaxation was added.Fresh verification passed:
nofile=256:256, 128 PIDs, 1 GiB, 2 CPUs, exact tmpfs mounts, and no TTYdetected Landlock ABI: 9/readme-terminal-demo self-test okgo mod tidy -diffstill reports only the deliberately predeclared Task 2+ JSON Schema, Goldmark, and YAML dependencies and made no mutation. The per-process FD bound is not a per-devpts-instance quota; the explicitly accepted residual short-lived allocation risk remains bounded by the combined FD/PID/memory/CPU/45-second/ephemeral-runner controls.GitHub CodeQL is currently in progress on the draft PR. No image publication, release, merge, issue closure, or policy promotion occurred. The owning issue remains open and Linear remains In Progress while the broader manifest/render/verify/workflow and pilot slices continue.
ss-o commentedon Jul 19, 2026
CI completion update — 2026-07-19
Draft PR #460 CodeQL Advanced run 149 completed successfully on exact head
abf9119d1b74ab5acb422d8d30b0f9b39b3db1b6. The published Task 1 checkpoint now has both the fresh local/race/Buildx/hardened-runtime evidence and its GitHub Actions gate green.The PR remains draft and the owning issue/Linear mirror remain open/In Progress for the broader Task 2+ work. No merge, image publication, release, issue closure, or policy promotion occurred.
ss-o commentedon Jul 19, 2026
Task 2 publication handoff — 2026-07-19
Pushed the reviewed Task 2 range to
feature-458and draft PR #460. The PR now points to exact headbd6234ac4e5ab6eebc109c76ce9d21672144da5d(four commits total).Completed:
KnownFields(true), structural path/extension/alt validation, and synchronized JSON Schema parity fixtures;Loadorchestration that preserves sanitized typed failures, checks returned-FD types, closes every returned file, requires scenario/fixtures/README inputs, and never opens GIF/PNG outputs;Final evidence from exact head:
go test ./... -count=1: PASS, including hardened sandbox;go vet ./...: PASS;go mod tidy -diffreports only removal of the approved future Goldmark pin reserved by the written plan for later README verification; no unintended module drift was introduced.Current gate: CodeQL Advanced run 150 is in progress on exact head
bd6234ac. PR #460 remains draft. No image publication, release tag, merge, pilot rollout, or pattern promotion is authorized or performed.Next approved implementation slice after this CI observation is Task 3: parse behavior-only tapes and compose trusted presentation.
ss-o commentedon Jul 19, 2026
Task 2 CI completion — 2026-07-19
CodeQL Advanced run 150 completed successfully on exact draft-PR head
bd6234ac4e5ab6eebc109c76ce9d21672144da5d.Task 2 is now green across local focused/full verification, independent full-range re-review, push, connector-confirmed draft PR state, and live GitHub CI. Draft PR #460 remains open, mergeable, and draft.
No image publication, release tag, merge, pilot rollout, issue closure, or pattern promotion occurred. The next approved implementation slice is Task 3: parse behavior-only tapes and compose trusted presentation.
ss-o commentedon Aug 30, 2026
Task 3 implementation handoff, 2026-08-30
Task 3 (parse behavior-only tapes and compose trusted presentation) is implemented and pushed to
feature-458at exact head40212258, messagefeat(terminal-demo): constrain and compose VHS tapes, no co-author trailer. No pull request has been opened yet.Base reconciliation
The written plan and Task 3 brief both name base
bd6234ac4e5ab6eebc109c76ce9d21672144da5don an isolatedfeature-458worktree. That state no longer exists: draft PR #460 merged on 2026-07-25 as6f6b825b, nofeature-458branch survived on origin, and no Task 3 worktree existed.bd6234ac:tools/readme-terminal-demoandorigin/main:tools/readme-terminal-demodiffer across 9 files, so building on the recorded base would have discarded the merged review fixes.Task 3 was therefore rebased onto current
origin/main(ef53e970), which containsbd6234acas an ancestor through the merge. No Task 1-2 behavior was changed. The branch name satisfies the CI-enforced^(feature|bug|hotfix)-[1-9][0-9]*$contract.Delivered contract
Parse(io.Reader, limits.Limits) ([]Directive, error)andCompose([]Directive, Config, string) ([]byte, error)plusDefaultConfig(), withKindas a closed enum over the exact V1 allowlist.InvalidContract/StageTape/RuleTapeInvalid, exit code 2. No public class, stage, rule, or exit code was added or renamed. The structured field carries only a bounded category plus line number; a test asserts no source text leaks into either the message or the field./work.gifoutput,Set Shell "zsh", 960x540, JetBrains Mono 18 px, Catppuccin Mocha, 30 fps, 35 ms typing speed, cursor blink disabled.Composerequires the exact approved config and independently revalidates directives, so a caller constructing aDirectivewithoutParsecannot bypass the contract.Verification against real VHS v0.11.0
The composed golden tape was fed to the actual VHS v0.11.0 lexer and parser in the pinned Go image: 0 parse errors, 18 commands,
Ctrl+"L"resolving to argsL, and each fixed-timeout wait form parsing as intended. Upstream source confirms the brief's assumptions:lexer.readStringperforms no escape interpretation and cannot span a newline, andreadRegexuses the odd-backslash delimiter rule. Both are mirrored in the parser.Defects found and fixed during TDD
1m30sare rejected in composition, because VHSparseTimeaccepts exactly one number plus one unit and would misparse the compound Go form.Evidence from exact head
40212258All commands ran through the pinned
scripts/in-go-image.shwrapper (Go 1.26.5, linux/amd64); host Go was never an acceptance path.go test ./internal/tape -count=1: PASS, 14 top-level tests.go test ./internal/tape -run 'TestParseRejects|TestComposeGolden' -count=1: PASS, 59 rejection subtests, byte-stable golden.go test ./... -count=1: PASS, includinginternal/sandbox.go vet ./...: clean.gofmt -l .: clean.go mod tidy -diff: reports only the pre-existing Goldmark pin reserved by the plan for Task 4 README verification. Task 3 introduced no module drift.Status
No image publication, release tag, pull request, merge, pilot rollout, or pattern promotion occurred.
PATTERNS.md, the README template, and the organization catalog remain untouched.Next approved implementation slice: Task 4, safe repository access, deterministic fixture staging, and README validation.
feat(terminal-demo): constrain and compose VHS tapes (#580)
ss-o commentedon Sep 17, 2026
Agent handoff
Status: In progress
Repository: z-shell/.github
Branch/PR:
feature-458at3d2ac97a, draft #581 (Task 4a,internal/repopath)Tracker/Issue: #458
Current state
3d2ac97a.feature-458is 26 commits behindorigin/main(f127b92a); no conflict is reported, but the branch has not been rebased since 2026-08-30.__snapshotwiring) has not been started.feature-458worktree is kept locked for this work; the other terminal-demo worktrees from Tasks 1 to 3 were removed after their pull requests merged.Verification
gh pr view 581: OPEN, draft, MERGEABLE, mergeStateStatus BLOCKED, checks Analyze (go, actions, python, ruby) and CodeQL SUCCESS.3d2ac97a.Blockers
Next steps
feature-458onto currentorigin/main, re-run the pinned-image verification listed in the feat(terminal-demo): contain untrusted repository paths #581 body, and push.ss-o commentedon Sep 18, 2026
Agent handoff
Status: In progress
Repository: z-shell/.github
Branch/PR:
feature-458atbd0ebb10, #581 (Task 4a,internal/repopath), now ready for reviewTracker/Issue: #458
Current state
feature-458was rebased from3d2ac97aonto currentorigin/main(9683d9d9) with no conflicts; no commit onmainsince the branch base touchedtools/readme-terminal-demo, so the diff is unchanged. Pushed with--force-with-lease.mainruleset includescopilot_code_review, so a Copilot review is expected on this head.__snapshotwiring) is still not started.Verification on exact head
bd0ebb10All commands ran through the pinned
scripts/in-go-image.shwrapper (Go 1.26.5,linux/amd64); host Go was not used.go test ./internal/repopath ./internal/manifest -count=1: PASSgo test ./... -count=1: PASS, includinginternal/sandboxgo vet ./...: cleangofmt -l .: cleango mod tidy -diff: only the reserved Goldmark pin, as the feat(terminal-demo): contain untrusted repository paths #581 body statesThe commit-lint gates added after the branch base (#600 issue traceability, #601 branch shape) were checked against the PR:
feature-458matches the branch pattern andRefs #458matches the issue-reference pattern.Blockers
Next steps
bd0ebb10; act on every review thread (fix or reply) before merge.fix(terminal-demo): reject non-regular repository paths before handin…
fix(terminal-demo): serialize root close and verify staging identity
fix(terminal-demo): serialize replacements and bound the FIFO regression
ss-o commentedon Sep 18, 2026
Agent handoff
Status: In progress
Repository: z-shell/.github
Branch/PR: #581 merged (
9841ffbb), #628 merged (4effa4fe);feature-458deleted on originTracker/Issue: #458
Current state
internal/repopath) is onmain. feat(terminal-demo): contain untrusted repository paths #581 was rebased onto9683d9d9, marked ready, and merged atfc334a64; its squash tree is byte-identical to that head.2cfe4f8c,fc334a64); the last two, opened after the merge, landed through fix(terminal-demo): serialize replacements and bound the FIFO regression #628.Closeserialized against child acquisition, staging identity verification before and after promotion, per-root serialization ofAtomicReplace, and a hang-bounded FIFO regression test.__snapshotwiring) has not been started.Verification
Every command ran through the pinned
scripts/in-go-image.shwrapper (Go 1.26.5,linux/amd64) on each pushed head:go test ./internal/repopath ./internal/manifest -count=1,go test ./... -count=1(includinginternal/sandbox),go vet ./...,gofmt -l ., andgo mod tidy -diff(only the reserved Goldmark pin). Every new guard was mutation-tested; the mutation results are recorded in the #581 and #628 bodies. CodeQL, Commit Lint, Code Quality, and Copilot review completed successfully onfc334a64and6acb78be.Blockers
Next steps
mainat or after4effa4fein a freshfeature-458worktree, with the plan's original commit message.go mod tidy -diffGoldmark pin is consumed by Task 4b'sinternal/readme; the diff should be empty after it.ss-o commentedon Sep 30, 2026
Project 28 triage pass. Blank values filled on this issue (existing values left unchanged):
Low. An opt-in visual for plugin READMEs; no plugin behavior depends on it and nothing is broken without it.XL. A reusable renderer, a scenario contract, CI verification and two plugin pilots across repositories; five PRs have merged (feat(terminal-demo): prove hardened renderer runtime #460, feat(terminal-demo): constrain and compose VHS tapes #580, feat(terminal-demo): contain untrusted repository paths #581, docs(templates): restructure the Zsh plugin README template #622, fix(terminal-demo): serialize replacements and bound the FIFO regression #628) and Task 4b plus both pilots remain.