Skip to content

Design reusable README terminal demo automation #458

Open

Description

@ss-o

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

  1. Select the capture/rendering tool and supported output format after comparing maintenance, reproducibility, CI complexity, and supply-chain risk.
  2. Define the caller-owned scenario file, fixtures, generated-asset path, and local command contract.
  3. Decide whether the reusable workflow verifies committed output, uploads a preview artifact, or both; it must not create automatic asset churn.
  4. Select the second plugin pilot and a stable behavior-focused scenario.
  5. 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-eza has 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 .tape scenario 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-action defaults its tool version to latest, 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-eza is the first pilot: render a fixed directory/Git fixture and demonstrate ll plus tree behavior without network or host data.
  • zsh-fancy-completions is the strongest second pilot: a controlled filename-completion scenario exercises scripted keypresses and transient interactive frames, complementing the simpler zsh-eza case.
  • 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/.github owns 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 .tape scenario, 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-eza validates ordinary command output; zsh-fancy-completions validates scripted interactive keypresses and transient completion frames.
  • Do not promote the experiment to PATTERNS.md or 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.
  • render regenerates committed assets. verify renders 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 verify entrypoint 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 to docs/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, and PATH.
  • 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-eza pilot uses a fixed fixture and checksum-pinned real eza; the zsh-fancy-completions pilot 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.md occurs 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-eza pilot, zsh-fancy-completions pilot, 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-458 now 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 exact origin/main commit 8ee041623cd5a2892887357ea9f0fb443ff3d2b4.
  • 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 /dev plus the sole non-persistent write sink landlock.RWFiles("/dev/null"); it does not grant write access to the /dev hierarchy or another device.
  • Tests must validate no-follow device identities 1:3 and 1:5, prove /dev/zero writable before restriction, close the descriptor, then prove after exact Landlock V3 restriction that /dev/null writes succeed and /dev/zero write-open fails specifically with EACCES.
  • Two independent reviews found no remaining critical or important issue at spec SHA-256 8829effd3d0402f2b6f879e8d2852b90065f37d8734ed0a07bae96ee102071e9 and plan SHA-256 5a1745b094c62c8c2c169254d74358ee6a05d7e7f5768e3c1be8b49e525c7ca9.
  • 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~deb13u1 proves the setuid path is disabled by PR_SET_NO_NEW_PRIVS and the namespace fallback fails with EPERM.
  • Implementation stopped without --no-sandbox, removal of no-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_SANDBOX control is now an explicit exception only in the already-restricted capture-child environment; ineffective CHROME_BIN is 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/chromium against SHA-256 2c8d32d29dc6781c35ae196ea83299d507ac88fc339301abe74672feda299779. Failure is sanitized renderer-unavailable before 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; immediate unix.Exec. Every post-lock failure uses a non-returning SYS_EXIT_GROUP loop, with a live-sibling regression test.
  • The image must not install chromium-sandbox or another setuid helper. Capability additions, disabling no-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…, plan 7c8c6d41…, and Task 1 brief 3ae882cd…; the mechanically approved final file hashes are spec ea3730cc…, plan 8c63ca1a…, and brief 3ae882cd…. The private contract commit is d95b4ba20ed72c64b863e45c8ab342305b363b67.

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

Activity

  1. ss-o commented on Jul 18, 2026

    @ss-o
    MemberAuthor

    Agent handoff — Chromium sandbox feasibility blocker

    Status: Task 1 is blocked at the exact hardened self-test; branch feature-458 remains uncommitted at 8ee041623cd5a2892887357ea9f0fb443ff3d2b4.

    Verified:

    • The approved /dev/null Landlock amendment passed its exact RED/GREEN test: read-only /dev, sole RWFiles("/dev/null") exception, and preconditioned post-V3 /dev/zero EACCES.
    • Full Go tests, vet, formatting, shell syntax, immutable Docker frontend resolution, and the exact test-image build pass.
    • The unchanged outer self-test exits 5 at capture.
    • Without chromium-sandbox, Chromium reports no usable sandbox. A disposable probe adding exact package chromium-sandbox=150.0.7871.124-1~deb13u1 shows the setuid sandbox is disabled by parent PR_SET_NO_NEW_PRIVS; its namespace fallback fails with EPERM.

    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 of no-new-privileges, added capabilities/privilege, relaxed namespace or seccomp policy, permissive Landlock fallback, commit, push, PR, or publication.

    Exact next steps:

    1. Compare documented, supportable browser-isolation options against the current non-root, no-network, read-only, capability-dropped, Landlock V3 boundary.
    2. If a defensible option requires a contract change, update the design and implementation plan, synchronize both trackers, and obtain independent security and consistency review.
    3. Resume with a fresh TDD implementation turn and rerun the unchanged or newly approved exact self-test boundary.
    4. Do not start Task 2 until Task 1 passes.
  2. ss-o commented on Jul 18, 2026

    @ss-o
    MemberAuthor

    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 is d95b4ba20ed72c64b863e45c8ab342305b363b67.

    Approved final hashes:

    • spec: ea3730cc2b0b420f93b930b09577dcc19dc9e150ef90f1a08424da162db8c2e1
    • plan: 8c63ca1aa7ece3a278be05923b59c9c181ad260468c90d861579f3a576084b75
    • Task 1 brief: 3ae882cd3fffff9b51d60c2b1859a404fb2433ae25a40662c81bcd861e69a7b1

    Exact next steps:

    1. RED/GREEN the complete child-only environment and VHS_NO_SANDBOX=1 boundary.
    2. RED/GREEN exact Chromium preflight, earlier-candidate denial, and no-downloader sentinel.
    3. RED/GREEN LockOSThread/same-TID Landlock exec plus process-wide SYS_EXIT_GROUP failure behavior.
    4. Rebuild the exact image and rerun the unchanged hardened self-test command.
    5. If green, commit the Task 1 slice and submit it to independent task review; if not, stop and synchronize both trackers again.

    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.

  3. ss-o commented on Jul 18, 2026

    @ss-o
    MemberAuthor

    Agent handoff — ABI 3–7 launcher audit

    Task 1 remains uncommitted on feature-458 at base 8ee041623cd5a2892887357ea9f0fb443ff3d2b4.

    Verified progress within the already approved contract:

    • exact private /work state, deterministic Zsh startup, empty eza configuration, and /work/demo cwd are implemented with focused RED/GREEN coverage;
    • the production VHS test override is removed;
    • unsupported-Landlock coverage now reaches the real restricted-exec path after a successful browser seam and proves exit 4 with no VHS sentinel;
    • full Go tests, vet, formatting, shell syntax, and the pinned Go wrapper pass.

    A fresh security audit of the pinned go-landlock v0.9.0 source found a new ABI 3–7 blocker. The current launcher calls close_range(..., CLOSE_RANGE_UNSHARE) and then landlock.V3.RestrictPaths. On ABI 3–7 the library creates the ruleset FD in the caller's unshared FD table and uses an all-thread psx syscall; sibling threads cannot see that FD, so inconsistent results can panic instead of taking the required sanitized SYS_EXIT_GROUP(4) path. The exact Docker build/self-test was intentionally not rerun after this finding.

    Recommended contract amendment:

    1. Build the complete V3 ruleset and exec vectors during fallible preflight.
    2. Preserve only the trusted CLOEXEC ruleset FD while closing inherited descriptors.
    3. On the locked recorded TID, use raw no_new_privs, raw current-thread landlock_restrict_self, close the ruleset FD, recheck TID, and raw execve.
    4. Keep every post-lock failure in the non-returning raw SYS_EXIT_GROUP loop.
    5. Kill the negative PGID on normal direct-child exit as well as timeout, preserve exit 4 as renderer-unavailable, and state honestly that process-group cleanup is lifecycle management rather than an adversarial boundary against native code that deliberately calls setsid.

    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.

  4. ss-o commented on Jul 18, 2026

    @ss-o
    MemberAuthor

    Task 1 specification gate — option 1 recorded

    The approved ABI 3–7 launcher direction is now captured in the canonical private workspace specification.

    • Workspace commit: 3ca4416 (docs(dot-github): specify ABI 3 launcher contract)
    • Specification SHA-256: 1e0c087dddf763e261eb327cb62b2a691cf9021eb4cde5fb2890705a77c0654e
    • Contract: prebuild the exact V3 ruleset and owned raw-exec vectors during fallible preflight; retain an arbitrary verified ruleset FD >= 3 with FD_CLOEXEC; after runtime.LockOSThread and raw TID capture, use split raw close_range calls around that FD with CLOSE_RANGE_UNSHARE, then raw no_new_privs, current-thread restriction, FD close, TID recheck, and execve.
    • Fail-closed behavior: post-lock launcher failures use process-wide EXIT_GROUP; reserved normal exits 4/5 remain distinct from signals and are sanitized by the trusted parent.
    • Lifecycle boundary: negative-PGID cleanup runs after every child outcome and timeout, but is explicitly not claimed as adversarial containment against setsid/setpgid; Landlock and the externally network-isolated container remain the authority boundary.
    • Reviews: security Ready; testability/implementability Ready; full-spec consistency Ready.
    • Verification: git diff --check clean; 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.

  5. ss-o commented on Jul 18, 2026

    @ss-o
    MemberAuthor

    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-458 worktree.

    Authoritative private checkpoint

    • Commit: 04899da — docs(dot-github): approve ABI 3 implementation plan
    • Approved-status specification SHA-256: 7eeb01c85a4971d4212949ef952c4a0af359a63b60dbb6306aa918edb2595721
    • Canonical plan SHA-256: 748d1c8cd11eed2c83f18a1328ae7a7218228cbaf37146507bbcf116252e4d57
    • Task 1 brief SHA-256: c244202268d70b848614f959eaf8c26c55644edd0f17ef8af6828a1e794c7eb0
    • Task 1 report SHA-256: f6b78e4f4dcde64e3b141842f87a3d2c669a176706e18ad183d6ffd3d72eaf1f

    Locked execution contract

    • Preserve the existing branch and untracked feasibility evidence at base 8ee041623cd5a2892887357ea9f0fb443ff3d2b4; do not recreate or clean the worktree.
    • Preflight builds the exact ABI V3 low-level ruleset, validates the same opened rule-source FDs, verifies FD_CLOEXEC, owns NUL-terminated exec vectors, and maps every sanitized pre-lock failure to normal exit 4 after cleanup.
    • The terminal suffix uses raw same-thread syscalls, split close_range around the ruleset FD, raw restriction and execve; runtime/policy/descriptor/TID failures exit-group 4 and returned execve alone exits 5.
    • Only the final VHS raw-execve vector contains one VHS_NO_SANDBOX=1; the trusted parent and pre-Landlock helper do not.
    • Every child outcome gets negative-PGID cleanup and direct-child wait. A fixed Cmd.WaitDelay bounds escaped stdout/stderr holders; PGID cleanup is lifecycle management, not adversarial containment.
    • The final runtime-derived Docker test stage asserts pinned VHS v0.11.0 exits 0 for exact version and 1 for a controlled CLI error, preserving reserved statuses 4/5.

    Review and verification

    • Independent consistency review: Ready.
    • Independent Task 1 executability review: Ready.
    • Independent live-code security/surface review: Ready.
    • Trunk: clean across all four files.
    • Lychee: 24/24 links valid.
    • git diff --check: clean.
    • The checkpoint commit contains exactly four planning/specification files; no child implementation file changed.

    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.

  6. ss-o commented on Jul 18, 2026

    @ss-o
    MemberAuthor

    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-458 worktree.

    Exact Slice 4 RED evidence

    • TestPrepareExecVectors: PASS.
    • TestTerminalFakeRawOperationOrder: PASS.
    • TestTerminalSourceStructure: FAIL because its source assertion searches the whitespace-specific literal fault: terminalFaultNone, while the gofmt-aligned composite literal expresses the same production value with field alignment.
    • This is a test-contract/root-cause checkpoint, not a GREEN or completion claim.

    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.

  7. ss-o commented on Jul 18, 2026

    @ss-o
    MemberAuthor

    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

    • Commit: b632134374e5e8a84564833e6882378f4ff0e4b8 — feat(terminal-demo): enforce raw capture boundary.
    • Scope: 26 files, all under tools/readme-terminal-demo/; child worktree clean.
    • Live Landlock evidence: detected ABI 9.
    • Exact V3 low-level ruleset, owned exec vectors, raw same-thread terminal suffix, split descriptor closure, exit-group semantics, real raw-exec restrictions, all-outcome process cleanup, and reserved exit mapping are covered.
    • Final runtime test stage includes the exact pinned VHS version/status-1 assertion.

    Fresh verification

    • Focused cross-package security boundary: GREEN.
    • Race suite: GREEN.
    • go vet ./...: GREEN.
    • Pinned gofmt gate: GREEN.
    • Cached whitespace and selective staging checks: GREEN.
    • A tool-local Git attribute preserves standard gofmt/go.mod tabs while retaining other whitespace checks; no user or repository Git config was changed.

    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.

  8. ss-o commented on Jul 18, 2026

    @ss-o
    MemberAuthor

    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 remains b632134374e5e8a84564833e6882378f4ff0e4b8 (feat(terminal-demo): enforce raw capture boundary). No pull request or publication exists.

    Preserved Slice 10 work

    • The exact network-none IPv6 reject row 00200200 first reproduced a parser RED; correcting the Linux RTF_REJECT mask to 0x0200 made the focused regression GREEN.
    • Browser-resolution/downloader, pinned dependency, presentation, runtime-probe, and route tests pass.
    • The exact Buildx test target passes full Go tests, vet, build, and PASS TestPinnedVHSExitStatusContract.
    • The unchanged hardened outer self-test now reaches detected Landlock ABI: 9, then times out in capture.

    Root-cause evidence

    • VHS, ttyd, and Chromium start; no media is produced before the bounded timeout.
    • Pinned ttyd listens normally under every outer Docker restriction.
    • Under the exact capture Landlock domain, a bounded loopback client reaches /, /token, and /ws; ttyd then exits with the exact sanitized diagnostic pty_spawn: 13 (Permission denied).
    • This proves the approved read-only /dev plus sole writable /dev/null contract cannot allocate the PTY required by VHS/ttyd.
    • Chromium descendants that deliberately change PGID/session can briefly outlive the best-effort negative-PGID kill, matching the design's stated non-adversarial lifecycle limitation; the disposable container still bounds and terminates them.

    Cleanup and current tree

    • All temporary diagnostic code, container state, and the local diagnostic image were removed.
    • The remaining uncommitted diff is limited to main.go, main_test.go, and testdata/smoke/readme.tape.
    • git diff --check passes and the diagnostic-token scan is empty.
    • No PTY/device grant, capability, namespace, setuid, seccomp/AppArmor, no-new-privileges, Landlock, network, or outer-container relaxation was attempted.

    Decision required before implementation resumes

    1. Amend the written security contract and independently re-review the smallest empirically verified PTY-device authority, with no-follow identity checks, negative device tests, raw-exec inheritance coverage, and continued /dev/zero denial; or
    2. Change renderer architecture so terminal allocation does not broaden the current capture-child device contract.

    After 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.

  9. ss-o commented on Jul 19, 2026

    @ss-o
    MemberAuthor

    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:

    • E0, current policy: /dev/pts/ptmx O_RDWR fails with EACCES.
    • E1, add exact /dev/pts/ptmx WRITE_FILE: the master opens, but the dynamic slave still fails with EACCES.
    • E2, add only WRITE_FILE beneath /dev/pts: master allocation, unlock/number lookup, and dynamic slave O_RDWR all succeed.
    • Every cell also proved /dev/null remains writable and /dev/zero O_WRONLY remains denied specifically with EACCES.

    This proves the capture path does not need MAKE_CHAR, MAKE_DIR, REMOVE_FILE, REMOVE_DIR, TRUNCATE, broad /dev write access, capability additions, namespace/network changes, or seccomp/AppArmor/no-new-privileges relaxation. The disposable test source and image were removed; git diff --check remains clean.

    Recommended amendment for explicit approval and independent security review:

    1. Keep /dev read-only and the existing exact /dev/null exception.
    2. Add a dedicated special-device rule granting only WRITE_FILE beneath no-follow-validated /dev/pts; do not route it through the broad ReadWritePaths mask.
    3. Validate /dev/pts/ptmx as character device 5:2 and fail closed unless the private container devpts mount initially contains only ptmx (the outer invocation remains non-TTY).
    4. Preserve all current outer-container restrictions and regression-test both the PTY round trip and /dev/zero denial.
    5. Keep the known ABI-3 ioctl boundary explicit: this amendment adds no handled ioctl right.

    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.

  10. ss-o commented on Jul 19, 2026

    @ss-o
    MemberAuthor

    Agent handoff — PTY design review and containment evidence (2026-07-19)

    Independent security review recommends the dedicated /dev/pts rule, subject to explicit acceptance conditions. It also clarified that “only WRITE_FILE” is the incremental grant: the existing read-only /dev rule already supplies READ_FILE and READ_DIR.

    New evidence

    • A simultaneous two-container probe used the same pinned image and hardened restrictions. The diagnostic TTY container exposed /dev/pts/0 plus ptmx; the non-TTY container exposed only ptmx. Both reported a real devpts mount at /dev/pts. The absence of container A's slave from container B directly demonstrated per-container devpts isolation for the required Docker runtime.
    • Both probes applied RLIMIT_NOFILE=256.
    • The unchanged exact hardened self-test with only --ulimit nofile=256:256 added still reached detected Landlock ABI: 9 and then the same known execution-failed: capture (capture.timeout) PTY gate. The FD bound therefore introduces no earlier runtime failure.
    • All disposable containers were automatically removed; source and Git state remain unchanged.

    Reviewed amendment conditions

    1. Add a dedicated policy/rule type granting exactly AccessFSWriteFile beneath /dev/pts; never route it through broad ReadWritePaths.
    2. Open /dev/pts no-follow, verify directory identity and DEVPTS_SUPER_MAGIC, then resolve ptmx relative to that same descriptor and require character device 5:2.
    3. Require the non-TTY private topology before capture: exactly ptmx, an exact devpts mount at /dev/pts, no namespace sharing, no host devices, and no injected mount over /dev/pts. Fail closed otherwise.
    4. Add --ulimit nofile=256:256 to 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.
    5. Preserve the read-only /dev, exact /dev/null, /dev/zero == EACCES, exact ABI-3 handled rights, and unchanged outer Docker restrictions.
    6. Add RED/GREEN tests for exact rule construction, mount/device/topology rejection, raw-exec PTY master/slave round trip, unchanged forbidden masks, two-container isolation, and the existing negative-device contract.
    7. Keep the ABI-3 ioctl boundary explicit: required PTY ioctls are not mediated by this ruleset and remain governed by DAC, the default outer seccomp profile, and the container boundary.
    8. Record explicit maintainer acceptance that RLIMIT_NOFILE is 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.
    9. Require the exact Buildx gate and unchanged hardened self-test to pass before Slice 10 can complete.

    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.

  11. ss-o commented on Jul 19, 2026

    @ss-o
    MemberAuthor

    PTY amendment implementation checkpoint — 2026-07-19

    • Maintainer approval is recorded for the exact private-devpts amendment.
    • The authoritative design now includes the approved boundary at SHA-256 588884b35fdfcd4d1dba5b85059d12e226be8809991ae8e5966bb391d7f77c4f.
    • TDD implementation on feature-458 uses a fixed trusted-code toggle and grants only Landlock WRITE_FILE beneath a pinned, verified private /dev/pts. Preflight requires devpts, a distinct mount boundary, initial ptmx-only topology, and relative no-follow character device 5:2 on the same filesystem. Generic writable overlap is rejected.
    • The raw-exec integration opens the PTY master, completes TIOCSPTLCK/TIOCGPTN, opens the dynamic slave, preserves /dev/null write success, and preserves /dev/zero write-open EACCES.
    • The exact linux/amd64 image build passed. The hardened non-TTY self-test retained network none, read-only root, dropped capabilities, no-new-privileges, 128 PIDs, 1 GiB, 2 CPUs, private tmpfs mounts, and literal --ulimit nofile=256:256; it exited 0 after reporting Landlock ABI 9.
    • Landlock ABI 3 still does not mediate device ioctls; no ioctl, capability, namespace, seccomp/AppArmor, device, mount, setuid, or no-new-privileges relaxation was added. The per-process FD limit is not a per-devpts-instance PTY quota; the approved short-lived allocation risk remains bounded by the combined FD/PID/memory/CPU/45-second/ephemeral-runner controls.
    • Fresh race tests, vet, formatting, wrapper, and shell checks are green. Independent final review is in progress and identified a non-canonical-path alias case that will be closed with TDD before publication.

    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.

  12. ss-o commented on Jul 19, 2026

    @ss-o
    MemberAuthor

    Task 1 publication checkpoint — 2026-07-19

    The maintainer-approved private-devpts PTY amendment is implemented and published for review.

    • Commit: abf9119d1b74ab5acb422d8d30b0f9b39b3db1b6 (feat(terminal-demo): prove hardened renderer runtime)
    • Draft PR: z-shell/.github#460
    • Branch: feature-458 (two focused commits, clean worktree)

    The final boundary uses the same no-symlink/no-magic-link openat2 descriptor for validation and Landlock rule installation, verifies a private devpts filesystem with initial ptmx-only topology and character device 5:2, rejects writable physical aliases of devpts, /dev, or /, and adds only incremental WRITE_FILE beneath devpts. Read-only /dev, the exact /dev/null exception, and the post-restriction /dev/zero denial 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:

    • complete race-enabled Go suite
    • vet, gofmt, wrapper contract, shell syntax, and diff checks
    • deterministic process-group cleanup test for 10 consecutive runs
    • exact rebuilt linux/amd64 Buildx test target
    • exact hardened non-root/no-network/read-only/cap-drop/NNP runtime with nofile=256:256, 128 PIDs, 1 GiB, 2 CPUs, exact tmpfs mounts, and no TTY
    • decisive output: detected Landlock ABI: 9 / readme-terminal-demo self-test ok
    • independent final code/security review: Ready, no P0-P3 findings

    go mod tidy -diff still 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.

  13. ss-o commented on Jul 19, 2026

    @ss-o
    MemberAuthor

    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.

  14. ss-o commented on Jul 19, 2026

    @ss-o
    MemberAuthor

    Task 2 publication handoff — 2026-07-19

    Pushed the reviewed Task 2 range to feature-458 and draft PR #460. The PR now points to exact head bd6234ac4e5ab6eebc109c76ce9d21672144da5d (four commits total).

    Completed:

    • immutable V1 resource limits shared by later manifest, tape, fixture, render, and verification work;
    • bounded YAML-node preflight with aliases/anchors, duplicate keys, non-core tags, extra documents, depth/node/scalar limits, and strict manifest-specific scalar/object shapes;
    • typed decoding with KnownFields(true), structural path/extension/alt validation, and synchronized JSON Schema parity fixtures;
    • Reader-only Load orchestration that preserves sanitized typed failures, checks returned-FD types, closes every returned file, requires scenario/fixtures/README inputs, and never opens GIF/PNG outputs;
    • review fixes for yaml/v3 scalar coercion, nested empty-basename schema divergence, defensive file-plus-error closure, and format-only alt text.

    Final evidence from exact head:

    • required failure+manifest focused suite: PASS;
    • required negative-contract selector: PASS;
    • full go test ./... -count=1: PASS, including hardened sandbox;
    • go vet ./...: PASS;
    • pinned gofmt and committed-range diff checks: clean;
    • fresh independent two-commit range re-review: Ready; all prior findings closed; no P0-P3 findings.

    go mod tidy -diff reports 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.

  15. ss-o commented on Jul 19, 2026

    @ss-o
    MemberAuthor

    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.

  16. moved this to Triage in Z-shell Deliveryon Aug 17, 2026
  17. added
    type:featureA request for new behavior or capability.
    area:ciContinuous integration or GitHub Actions work.
    on Aug 18, 2026
  18. ss-o commented on Aug 30, 2026

    @ss-o
    MemberAuthor

    Task 3 implementation handoff, 2026-08-30

    Task 3 (parse behavior-only tapes and compose trusted presentation) is implemented and pushed to feature-458 at exact head 40212258, message feat(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 bd6234ac4e5ab6eebc109c76ce9d21672144da5d on an isolated feature-458 worktree. That state no longer exists: draft PR #460 merged on 2026-07-25 as 6f6b825b, no feature-458 branch survived on origin, and no Task 3 worktree existed. bd6234ac:tools/readme-terminal-demo and origin/main:tools/readme-terminal-demo differ 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 contains bd6234ac as 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) and Compose([]Directive, Config, string) ([]byte, error) plus DefaultConfig(), with Kind as a closed enum over the exact V1 allowlist.
    • Parsing is data-only: no shell, VHS, filesystem, environment, network, or wait-pattern match. Regexes compile only to validate syntax. Line numbers are preserved.
    • Every rejection uses the existing sanitized boundary 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.
    • Composition emits the fixed header in the mandated order: /work .gif output, Set Shell "zsh", 960x540, JetBrains Mono 18 px, Catppuccin Mocha, 30 fps, 35 ms typing speed, cursor blink disabled. Compose requires the exact approved config and independently revalidates directives, so a caller constructing a Directive without Parse cannot 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 args L, and each fixed-timeout wait form parsing as intended. Upstream source confirms the brief's assumptions: lexer.readString performs no escape interpretation and cannot span a newline, and readRegex uses the odd-backslash delimiter rule. Both are mirrored in the parser.

    Defects found and fixed during TDD

    1. Sub-millisecond sleeps parsed but could not be emitted as a VHS time token, so a parse/compose round trip would truncate them. Sleep now must be a whole number of milliseconds.
    2. Compound durations such as 1m30s are rejected in composition, because VHS parseTime accepts exactly one number plus one unit and would misparse the compound Go form.

    Evidence from exact head 40212258

    All commands ran through the pinned scripts/in-go-image.sh wrapper (Go 1.26.5, linux/amd64); host Go was never an acceptance path.

    • RED observed first, then on the real sub-millisecond defect above.
    • 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, including internal/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.

  19. moved this from Triage to In Progress in Z-shell Deliveryon Aug 30, 2026
  20. ss-o commented on Sep 17, 2026

    @ss-o
    MemberAuthor

    Agent handoff

    Status: In progress
    Repository: z-shell/.github
    Branch/PR: feature-458 at 3d2ac97a, draft #581 (Task 4a, internal/repopath)
    Tracker/Issue: #458

    Current state

    • Workspace cleanup on 2026-09-17 verified this is the only unfinished terminal-demo item: feat(terminal-demo): contain untrusted repository paths #581 is still a draft, mergeable, blocked only by its draft state, with CodeQL green on 3d2ac97a.
    • feature-458 is 26 commits behind origin/main (f127b92a); no conflict is reported, but the branch has not been rebased since 2026-08-30.
    • Task 4b (fixture staging, snapshot extraction, README contract, __snapshot wiring) has not been started.
    • The isolated feature-458 worktree is kept locked for this work; the other terminal-demo worktrees from Tasks 1 to 3 were removed after their pull requests merged.

    Verification

    Blockers

    Next steps

    1. In a dedicated session, rebase feature-458 onto current origin/main, re-run the pinned-image verification listed in the feat(terminal-demo): contain untrusted repository paths #581 body, and push.
    2. Mark feat(terminal-demo): contain untrusted repository paths #581 ready and request review; merge as Task 4a.
    3. Implement Task 4b on the merged 4a with the plan's original commit message.
  21. ss-o commented on Sep 18, 2026

    @ss-o
    MemberAuthor

    Agent handoff

    Status: In progress
    Repository: z-shell/.github
    Branch/PR: feature-458 at bd0ebb10, #581 (Task 4a, internal/repopath), now ready for review
    Tracker/Issue: #458

    Current state

    • feature-458 was rebased from 3d2ac97a onto current origin/main (9683d9d9) with no conflicts; no commit on main since the branch base touched tools/readme-terminal-demo, so the diff is unchanged. Pushed with --force-with-lease.
    • feat(terminal-demo): contain untrusted repository paths #581 is marked ready for review. The main ruleset includes copilot_code_review, so a Copilot review is expected on this head.
    • Task 4b (fixture staging, snapshot extraction, README contract, __snapshot wiring) is still not started.

    Verification on exact head bd0ebb10

    All commands ran through the pinned scripts/in-go-image.sh wrapper (Go 1.26.5, linux/amd64); host Go was not used.

    The commit-lint gates added after the branch base (#600 issue traceability, #601 branch shape) were checked against the PR: feature-458 matches the branch pattern and Refs #458 matches the issue-reference pattern.

    Blockers

    • None.

    Next steps

    1. Wait for CodeQL, commit-lint, and the Copilot review on bd0ebb10; act on every review thread (fix or reply) before merge.
    2. Merge feat(terminal-demo): contain untrusted repository paths #581 as Task 4a, then advance the private workspace gitlink.
    3. Implement Task 4b on the merged 4a with the plan's original commit message.
  22. ss-o commented on Sep 18, 2026

    @ss-o
    MemberAuthor

    Agent handoff

    Status: In progress
    Repository: z-shell/.github
    Branch/PR: #581 merged (9841ffbb), #628 merged (4effa4fe); feature-458 deleted on origin
    Tracker/Issue: #458

    Current state

    • Task 4a (internal/repopath) is on main. feat(terminal-demo): contain untrusted repository paths #581 was rebased onto 9683d9d9, marked ready, and merged at fc334a64; its squash tree is byte-identical to that head.
    • Copilot review raised six threads across three passes; all six were fixed and every thread is resolved. Fixes for the first four landed inside feat(terminal-demo): contain untrusted repository paths #581 (2cfe4f8c, fc334a64); the last two, opened after the merge, landed through fix(terminal-demo): serialize replacements and bound the FIFO regression #628.
    • Delivered beyond the original Task 4a diff: non-blocking type-checked opens (FIFO/socket/device rejected), private root descriptor with Close serialized against child acquisition, staging identity verification before and after promotion, per-root serialization of AtomicReplace, and a hang-bounded FIFO regression test.
    • Task 4b (fixture staging, snapshot extraction, README contract, __snapshot wiring) has not been started.

    Verification

    Every command ran through the pinned scripts/in-go-image.sh wrapper (Go 1.26.5, linux/amd64) on each pushed head: go test ./internal/repopath ./internal/manifest -count=1, go test ./... -count=1 (including internal/sandbox), go vet ./..., gofmt -l ., and go 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 on fc334a64 and 6acb78be.

    Blockers

    • None.

    Next steps

    1. Implement Task 4b on main at or after 4effa4fe in a fresh feature-458 worktree, with the plan's original commit message.
    2. The go mod tidy -diff Goldmark pin is consumed by Task 4b's internal/readme; the diff should be empty after it.
  23. ss-o commented on Sep 30, 2026

    @ss-o
    MemberAuthor

    Project 28 triage pass. Blank values filled on this issue (existing values left unchanged):

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:ciContinuous integration or GitHub Actions work.type:featureA request for new behavior or capability.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions