Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
a9a66e8
feat(files): add read-only Files card, reader, and rich viewer
tab11pm Oct 4, 2026
82aaed0
fix(files): make root containment resolve paths consistently on Windows
tab11pm Oct 4, 2026
2b39815
Fix native clipboard editing in fields and plugin pages
BIackFIame Oct 5, 2026
22620f3
Preserve edit chords in shortcut recorders
BIackFIame Oct 5, 2026
5f68cf6
feat(materials): handoff delivery for remarks (PR#3)
SaneSanders Oct 1, 2026
bbdd535
fix(materials): ship the handoff dialog styles with the dialog
SaneSanders Oct 2, 2026
8aae329
fix(materials): deliver handoffs only after the state is durable
SaneSanders Oct 2, 2026
9e4c530
perf(canvas): load the handoff dialog on demand
SaneSanders Oct 3, 2026
6d023ad
fix(materials): validate handoff delivery and preserve file paths
SaneSanders Oct 5, 2026
a0a3815
fix(materials): contain handoff dialog focus and defer loading
SaneSanders Oct 5, 2026
01dd06c
fix(materials): preserve handoff packages when state cannot load
SaneSanders Oct 5, 2026
a372342
test(materials): include handoff state in shortcut fixtures
SaneSanders Oct 5, 2026
c0f999b
fix(materials): harden handoff storage and state recovery
SaneSanders Oct 6, 2026
4ea550b
fix(materials): confirm deletion after handoff
SaneSanders Oct 6, 2026
03e9007
fix(materials): constrain handoff recipient rows
SaneSanders Oct 6, 2026
fcf73c4
test(materials): make handoff fixtures portable
SaneSanders Oct 6, 2026
b691ed7
fix: preserve edit menus in plugin windows and whitespace selections
BIackFIame Oct 7, 2026
ca65284
feat(usage): add quota history and session estimates
pepechka-kun Oct 7, 2026
33bc269
Merge main into Files PR and resolve canvas conflicts
tab11pm Oct 8, 2026
58aa3a2
test(browser): avoid treating wheel idle as surface transition failure
tab11pm Oct 8, 2026
94e38ca
feat: add Codex mascot creation pipeline and canvas integration
CLOSETTTY Oct 9, 2026
a32808d
ci: verify packaged mascot resources on Linux
CLOSETTTY Oct 9, 2026
7179de1
ci: verify mascot pipeline and packaged resources on macOS
CLOSETTTY Oct 9, 2026
10e3f12
fix(pty): close macOS native descriptors and verify packaged cleanup
teo-nex Oct 10, 2026
eba2ac5
test(pty): distinguish runtime stdio reuse from leaked PTYs
teo-nex Oct 10, 2026
50e8a6c
fix(ci): recognize checksum-pinned public vendor source metadata
teo-nex Oct 10, 2026
da37267
test(pty): use the application's ASAR import route
teo-nex Oct 10, 2026
cb2f786
ci(pty): retain ad-hoc signing in read-only PR builds
teo-nex Oct 10, 2026
4598cbd
Merge approved PR #125: read-only file cards by @tab11pm
howdeploy Oct 12, 2026
cace825
Merge approved PR #130: material remark handoff by @SaneSanders
howdeploy Oct 12, 2026
c979053
Merge approved PR #131: macOS clipboard fixes by @BIackFIame
howdeploy Oct 12, 2026
3f413f4
Merge approved PR #138: usage history by @pepechka-kun
howdeploy Oct 12, 2026
60791a0
Merge approved PR #139: interactive mascots by @CLOSETTTY
howdeploy Oct 12, 2026
fbca6d0
Merge approved PR #140: macOS PTY leak fix by @teo-nex
howdeploy Oct 12, 2026
fe6efc5
fix(materials): stabilize handoff icon and align dialog actions
howdeploy Oct 12, 2026
1bcb4a8
fix(minimap): keep camera frame inside the overview
howdeploy Oct 12, 2026
07658ef
fix(minimap): fit camera and canvas objects together
howdeploy Oct 12, 2026
7db0dd9
Polish usage history navigation and cover camera-inclusive minimap bo…
howdeploy Oct 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@
# scripts/build-native-helpers.mjs generates (LF). Checked out with LF everywhere, a Windows checkout
# (core.autocrlf=true) matches and a helper built there embeds the same bytes as one built on macOS or Linux.
native/canvastty-helper/catalog.json text eol=lf

# Unified diffs require space-prefixed blank context lines, including at EOF.
# Preserve the patch bytes across Windows checkouts without treating that
# required patch syntax as trailing whitespace in application code.
patches/*.patch text eol=lf whitespace=-blank-at-eol,-blank-at-eof
37 changes: 37 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,25 @@ env:
CANVASTTY_REQUIRE_NATIVE_HELPERS: "1"

jobs:
mascot-pipeline:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 10
steps:
- name: Check out repository
uses: actions/checkout@v7
- name: Install mascot pipeline dependencies in a virtual environment
run: |
python3 -m venv .mascot-venv
.mascot-venv/bin/python -m pip install -r assets/mascot-pipeline/requirements.txt
- name: Verify mascot intake, build, review, and delivery contracts
run: .mascot-venv/bin/python -B assets/mascot-pipeline/tests/smoke_pipeline.py
- name: Verify placement against bundled accepted artwork
run: .mascot-venv/bin/python -B assets/mascot-pipeline/tests/placement_regression.py

verify:
runs-on: ubuntu-latest
steps:
Expand Down Expand Up @@ -49,6 +68,17 @@ jobs:
run: npm run typecheck
- name: Build production bundles
run: npm run build
- name: Build Linux installers and verify bundled mascot resources
run: |
npm run package:linux
test -f release/linux-unpacked/resources/mascot-pipeline/SKILL.md
test -f release/linux-unpacked/resources/mascot-pipeline/scripts/prepare_input.py
test -f release/linux-unpacked/resources/mascot-pipeline/templates/plugin/player.js
- name: Install AppImage runtime dependency
run: sudo apt-get update && sudo apt-get install --no-install-recommends -y libfuse2t64
- name: Smoke-test packaged Linux AppImage
timeout-minutes: 2
run: xvfb-run -a npm run smoke:appimage
- name: Verify hidden terminal rendering and state restoration
timeout-minutes: 2
run: xvfb-run -a npm run smoke:terminal-hidden
Expand Down Expand Up @@ -116,6 +146,13 @@ jobs:
env:
SPARKLE_PUBLIC_ED_KEY: ${{ vars.SPARKLE_PUBLIC_ED_KEY || 'iojj3XQJ8ZX9UtstPLpdcspnCb8dlBIb83SIAbQPb1w=' }}
run: npm run package:mac
- name: Verify bundled macOS mascot resources
run: |
app="$(find release -type d -name 'CanvasTTY.app' -print -quit)"
test -n "$app"
test -f "$app/Contents/Resources/mascot-pipeline/SKILL.md"
test -f "$app/Contents/Resources/mascot-pipeline/scripts/prepare_input.py"
test -f "$app/Contents/Resources/mascot-pipeline/templates/plugin/player.js"
- name: Smoke-test packaged macOS CLI resolution
run: npm run smoke:cli-resolution:mac
- name: Verify hidden terminal rendering and state restoration on macOS
Expand Down
106 changes: 106 additions & 0 deletions .github/workflows/pty-resources.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: macOS PTY resources

on:
push:
paths:
- ".github/workflows/pty-resources.yml"
- "patches/**"
- "package.json"
- "package-lock.json"
- "electron-builder.yml"
- "scripts/smoke-pty-resources.mjs"
- "scripts/audit-pty-test-bundle.mjs"
- "scripts/fixtures/public-speech-source-path-hashes.json"
- "tests/node-pty*"
pull_request:
paths:
- ".github/workflows/pty-resources.yml"
- "patches/**"
- "package.json"
- "package-lock.json"
- "electron-builder.yml"
- "scripts/smoke-pty-resources.mjs"
- "scripts/audit-pty-test-bundle.mjs"
- "scripts/fixtures/public-speech-source-path-hashes.json"
- "tests/node-pty*"
workflow_dispatch:

permissions:
contents: read

jobs:
native-and-packaged:
runs-on: macos-latest
timeout-minutes: 45
env:
CANVASTTY_REQUIRE_NATIVE_HELPERS: "1"
steps:
- name: Check out repository
uses: actions/checkout@v7
- name: Set up Node.js
uses: actions/setup-node@v7
with:
node-version: 22
cache: npm
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: native/canvastty-helper/go.mod
cache: false
- name: Install locked dependencies without applying the patch yet
run: npm ci --ignore-scripts
- name: Build the unpatched control for Electron from source
run: |
npx --no-install install-electron
npx --no-install electron-rebuild -f -w node-pty --build-from-source
- name: Reproduce the original leak and stop at the first growth
run: node scripts/smoke-pty-resources.mjs --cycles 3 --expect-leak --report .pty-results/unpatched.json
- name: Apply the tracked patch and rebuild for Electron
run: npm run postinstall
- name: Check cleanup under injected native failures
run: node --test tests/node-pty-patch.test.mjs tests/node-pty-bundle-audit.test.mjs
- name: Verify 400 cycles in one persistent Electron parent
run: node scripts/smoke-pty-resources.mjs --cycles 400 --report .pty-results/source.json
- name: Verify every combination of closed standard descriptors
run: |
for mask in 1 2 3 4 5 6 7; do
node scripts/smoke-pty-resources.mjs --cycles 8 --stdio-mask "$mask" --report ".pty-results/source-stdio-$mask.json"
done
- name: Build a separate macOS application without publishing it
env:
# Hosted read-only PR runner; mac.identity is explicitly ad-hoc ("-").
# No signing certificate/keychain secrets are provided to this job.
CSC_FOR_PULL_REQUEST: "true"
SPARKLE_PUBLIC_ED_KEY: "iojj3XQJ8ZX9UtstPLpdcspnCb8dlBIb83SIAbQPb1w="
run: npm run package:mac
- name: Audit the separate test bundle
run: node scripts/audit-pty-test-bundle.mjs release/mac-arm64/CanvasTTY.app
- name: Verify the new bundle signature
run: codesign --verify --deep --strict release/mac-arm64/CanvasTTY.app
- name: Verify 400 cycles using the packaged native addon
run: node scripts/smoke-pty-resources.mjs --app release/mac-arm64/CanvasTTY.app --cycles 400 --report .pty-results/packaged.json
- name: Verify closed standard descriptors in the packaged addon
run: |
for mask in 1 2 3 4 5 6 7; do
node scripts/smoke-pty-resources.mjs --app release/mac-arm64/CanvasTTY.app --cycles 8 --stdio-mask "$mask" --report ".pty-results/packaged-stdio-$mask.json"
done
- name: Retain synthetic test evidence even on failure
if: always()
uses: actions/upload-artifact@v7
with:
name: macos-pty-resources
if-no-files-found: warn
retention-days: 14
include-hidden-files: true
path: |
.pty-results/*.json
- name: Retain the separate build only after all safety and runtime gates
if: success()
uses: actions/upload-artifact@v7
with:
name: macos-pty-test-build
if-no-files-found: error
retention-days: 14
path: |
release/*.zip
release/*.dmg
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ yarn-debug.log*
yarn-error.log*
.cache/
.electron/
__pycache__/
*.pyc
/.mascot-venv/
settings.json
.pty-results/

# Local agent and planning context — never publish
.agents/
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

[English](CHANGELOG.md) · [Русский](CHANGELOG.ru.md) · [简体中文](CHANGELOG.zh-CN.md)

## Unreleased

- Added a rich file viewer to the **Files** card: Markdown files (`.md`, `.markdown`, `.mdown`, `.mkd`) render as formatted GitHub-Flavored Markdown with headings, lists, task lists, tables, blockquotes, horizontal rules, inline code, and fenced code blocks with syntax highlighting, recognized code files are syntax-highlighted by the language detected from their extension while unknown languages stay plain monospaced text, all rendered content is sanitized so raw HTML, scripts, event-handler attributes, and dangerous link schemes never render, `http(s)` links open in the app's built-in browser with other schemes inert, only embedded `data:` images show while remote or relative sources fall back to alt text or a placeholder without a network request, and text and code files above the rich-rendering size threshold fall back to plain text with a notice.
- Added a read-only **Files** canvas card and reader: open it from the empty-canvas context menu or the `Cmd/Ctrl+K` palette, root it at a live terminal session working directory or a folder picked in a native dialog, browse a directory tree that loads on demand, and read text/code as selectable monospace (bounded at 2 MB with a truncation marker and total size) or supported images (bounded at 25 MB) with explicit binary, unsupported, and too-large states. Quick open searches file names inside the active root, each card's root, bounds, open file, and expanded folders persist and restore with an unavailable state when the root is gone, and a new main-process `FileAccessService` enforces `realpath` containment so every listing, read, and search uses relative paths strictly inside registered roots with no write, rename, or delete capability.

## 1.7.1

- Added built-in stable-release updates with explicit download and installation, active-session shutdown confirmation, and signed Sparkle updates on macOS. Install this first updater-enabled release manually; later compatible releases can be installed from the app.
Expand Down
Loading
Loading