Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
49cdf5f
ci: gate releases on native validation and verified artifacts
niklas-heer Sep 11, 2026
d874405
test: explicitly select ConPTY in Windows smoke harness
niklas-heer Sep 11, 2026
513ba71
feat(tui): add saved views and reliable platform clipboard
niklas-heer Sep 11, 2026
2d4cc15
fix(views): handle cleanup and fixture errors explicitly
niklas-heer Sep 11, 2026
52dc489
ci: replay structural edits in bounded and scheduled checks
niklas-heer Sep 11, 2026
37e0864
docs(spec): define approved workflow reliability improvements
niklas-heer Sep 11, 2026
b97f963
feat(markdown): expose loaded revision preconditions
niklas-heer Sep 11, 2026
9c91b3b
feat(cli): add filtered snapshots and retry-safe guarded edits
niklas-heer Sep 11, 2026
5a3c0a7
feat(tdx): expose automation commands and saved view configuration
niklas-heer Sep 11, 2026
65393f1
fix(markdown): preserve document source across structural edits
niklas-heer Sep 11, 2026
4adecdb
fix(editor): preserve task subtrees and atomic bulk edits
niklas-heer Sep 11, 2026
d03def0
test(usage): replay structural edits and minimize failures
niklas-heer Sep 11, 2026
504aafc
feat(usage): expose structural campaigns and reduced replay artifacts
niklas-heer Sep 11, 2026
c40d07d
docs: explain saved views guarded automation and verified releases
niklas-heer Sep 11, 2026
6844c92
test(usability): add explicitly synthetic five-person rehearsal data
niklas-heer Sep 11, 2026
6043928
docs(spec): record implemented workflow improvements
niklas-heer Sep 11, 2026
be20327
fix(markdown): align task indexes around opaque quoted examples
niklas-heer Sep 11, 2026
319f217
ci: prevent compiler and terminal contention in portable checks
niklas-heer Sep 11, 2026
df6737e
test(cli): cover quoted checkbox section indexes
niklas-heer Sep 12, 2026
5d8f492
test(tdx): use executable extension on Windows
niklas-heer Sep 12, 2026
46afe37
docs(spec): archive validated workflow improvements
niklas-heer Sep 12, 2026
570bdae
test(tdx): surface launch errors and use portable absolute paths
niklas-heer Sep 12, 2026
02e743f
style(spec): remove archive trailing blank lines
niklas-heer Sep 12, 2026
31c5db6
ci: use supported artifact upload runtime
niklas-heer Sep 12, 2026
1a2e899
test: retry transient Windows sharing conflicts in terminal polling
niklas-heer Sep 12, 2026
4ed670f
docs(spec): define bounded inline rendering correction
niklas-heer Sep 12, 2026
870b524
fix(tui): keep inline frames stable and selection visible
niklas-heer Sep 12, 2026
368b6d4
test(tui): enforce stable terminal frames across modes and resize
niklas-heer Sep 12, 2026
00c524d
test(tui): verify inline screens and scrollback in native PTYs
niklas-heer Sep 12, 2026
c36c846
fix(tui): keep diff browser controls within terminal bounds
niklas-heer Sep 12, 2026
989d31e
docs(spec): archive verified inline rendering fix
niklas-heer Sep 12, 2026
dce0354
fix(config): preserve empty heading labels in saved views
niklas-heer Sep 12, 2026
35b3049
fix(tui): restore recent cursor after applying destination views
niklas-heer Sep 12, 2026
5c3e554
chore(config): declare saved view restoration default explicitly
niklas-heer Sep 12, 2026
f256b3e
fix(tui): preserve nesting when reordering unfiltered tasks
niklas-heer Sep 12, 2026
dfd3c03
docs(spec): clarify final review edge cases
niklas-heer Sep 12, 2026
fbf169c
docs(spec): define continuation edits and nested reordering
niklas-heer Sep 12, 2026
6750601
test(markdown): clarify continuation edit boundaries
niklas-heer Sep 12, 2026
b0fea83
test(usage): validate structural action ownership and placement
niklas-heer Sep 12, 2026
44ac77c
docs(spec): archive verified review follow-ups
niklas-heer Sep 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
29 changes: 7 additions & 22 deletions .dagger/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"fmt"
"strconv"
"strings"
"sync"

"dagger/tdx-ci/internal/dagger"
"dagger/tdx-ci/pipeline"
Expand All @@ -24,8 +23,8 @@ type TdxCi struct{}

// Ci runs every portable validation used by GitHub CI.
func (m *TdxCi) Ci(ctx context.Context, source *dagger.Directory) (string, error) {
// golangci-lint has the highest peak memory use, so keep it out of the
// concurrent group to make local runs reliable on smaller Docker VMs.
// Keep memory-intensive checks sequential so a developer's small Docker
// VM does not run multiple Go/Rust compilers alongside terminal contracts.
if _, err := m.Lint(ctx, source); err != nil {
return "", fmt.Errorf("lint: %w", err)
}
Expand Down Expand Up @@ -55,26 +54,10 @@ func (m *TdxCi) Ci(ctx context.Context, source *dagger.Directory) (string, error
}},
}

type result struct {
name string
err error
}
results := make(chan result, len(checks))
var wg sync.WaitGroup
for _, check := range checks {
wg.Add(1)
go func() {
defer wg.Done()
results <- result{name: check.name, err: check.run()}
}()
}
wg.Wait()
close(results)

var failures []error
for result := range results {
if result.err != nil {
failures = append(failures, fmt.Errorf("%s: %w", result.name, result.err))
for _, check := range checks {
if err := check.run(); err != nil {
failures = append(failures, fmt.Errorf("%s: %w", check.name, err))
}
}
if err := errors.Join(failures...); err != nil {
Expand Down Expand Up @@ -282,8 +265,10 @@ func (m *TdxCi) usageCheck(ctx context.Context, source *dagger.Directory) (strin
return m.goBase(source).
WithExec([]string{"go", "build", "-o", "/tmp/tdx-usage-binary", "./cmd/tdx"}).
WithExec([]string{"go", "run", "./cmd/tdx-usage", "-driver", "cli", "-binary", "/tmp/tdx-usage-binary", "-sessions", "1", "-steps", "40"}).
WithExec([]string{"go", "run", "./cmd/tdx-usage", "-driver", "structural", "-sessions", "1", "-steps", "60"}).
WithExec([]string{"sh", "-ec", "apt-get update -qq && apt-get install -y --no-install-recommends python3"}).
WithExec([]string{"python3", "scripts/usage-pty.py", "--binary", "/tmp/tdx-usage-binary"}).
WithExec([]string{"bash", "scripts/test_release_notes.sh"}).
WithExec([]string{"python3", "scripts/test_install.py"}).
Stdout(ctx)
}
53 changes: 3 additions & 50 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,60 +11,13 @@ permissions:
contents: read

jobs:
portable:
name: Portable
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7.0.1

- uses: jdx/mise-action@v4.3.0
- name: Run portable CI
run: mise run ci

native:
name: Native (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, windows-latest]

steps:
- name: Checkout code
uses: actions/checkout@v7.0.1

- name: Set up Go
uses: actions/setup-go@v7.0.0
with:
go-version-file: go.mod
cache-dependency-path: go.sum

- name: Build native binary
shell: bash
run: |
if [ "$RUNNER_OS" = "Windows" ]; then
go build -v -o tdx.exe ./cmd/tdx
else
go build -v -o tdx ./cmd/tdx
fi

- name: Run native filesystem tests
run: go test -v ./internal/markdown ./internal/versioning

- name: Test native binary execution
shell: bash
run: |
if [ "$RUNNER_OS" = "Windows" ]; then
./tdx.exe --version
else
./tdx --version
fi
validate:
uses: ./.github/workflows/validate.yml

coverage-badge:
name: Coverage badge
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: portable
needs: validate
runs-on: ubuntu-latest
permissions:
contents: write
Expand Down
22 changes: 22 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,22 @@ permissions:
contents: read

jobs:
validate:
uses: ./.github/workflows/validate.yml

release:
needs: validate
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
attestations: write

steps:
- name: Checkout code
uses: actions/checkout@v7.0.1
with:
ref: ${{ github.sha }}
fetch-depth: 0
persist-credentials: false

Expand All @@ -36,6 +43,21 @@ jobs:
version: "0.21.9"
call: release-artifacts --source=. export --path=release

- name: Calculate release checksums
working-directory: release
run: sha256sum tdx-* > SHA256SUMS

- name: Attest release artifacts and checksum manifest
id: provenance
uses: actions/attest@v4
with:
subject-path: release/*

- name: Include provenance bundle in release
env:
BUNDLE_PATH: ${{ steps.provenance.outputs.bundle-path }}
run: cp "$BUNDLE_PATH" release/provenance.json

- name: Set up Python
uses: actions/setup-python@v7.0.0
with:
Expand Down
50 changes: 50 additions & 0 deletions .github/workflows/usage-campaign.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Scheduled usage campaign

on:
schedule:
- cron: "23 4 * * 1"
workflow_dispatch:

permissions:
contents: read

jobs:
replay:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v7.0.1
with:
persist-credentials: false
- uses: actions/setup-go@v7.0.0
with:
go-version-file: go.mod
- name: Record replay seed and commit
run: |
mkdir -p dist/usage/campaign
seed=$(date -u +%Y%m%d)
echo "TDX_CAMPAIGN_SEED=$seed" >> "$GITHUB_ENV"
printf 'seed=%s\ncommit=%s\n' "$seed" "$GITHUB_SHA" > dist/usage/campaign/environment.txt
go version >> dist/usage/campaign/environment.txt
- name: Replay rotating TUI sessions
run: go run ./cmd/tdx-usage -seed "$TDX_CAMPAIGN_SEED" -sessions 10 -steps 1800 -output dist/usage/campaign/tui
- name: Replay rotating executable sessions
if: always()
run: |
go build -o /tmp/tdx-campaign ./cmd/tdx
go run ./cmd/tdx-usage -driver cli -binary /tmp/tdx-campaign -seed "$TDX_CAMPAIGN_SEED" -sessions 2 -steps 200 -output dist/usage/campaign/cli
- name: Replay rotating structural edits
if: always()
run: go run ./cmd/tdx-usage -driver structural -seed "$TDX_CAMPAIGN_SEED" -sessions 8 -steps 500 -output dist/usage/campaign/structural
- name: Capture bounded diagnostic profiles
if: always()
run: |
mkdir -p dist/usage/campaign/profile
go test ./internal/usage -run TestSeededSessions -count=1 -cpuprofile=dist/usage/campaign/profile/cpu.pprof -memprofile=dist/usage/campaign/profile/heap.pprof -o dist/usage/campaign/profile/usage.test
- name: Retain replay traces, reduced failures and profiles
if: always()
uses: actions/upload-artifact@v7.0.1
with:
name: usage-campaign-${{ github.run_id }}-${{ github.run_attempt }}
path: dist/usage/campaign
retention-days: 30
75 changes: 75 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Validate commit

on:
workflow_call:

permissions:
contents: read

jobs:
portable:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v7.0.1
with:
ref: ${{ github.sha }}
persist-credentials: false
- uses: jdx/mise-action@v4.3.0
- name: Validate the checked-out commit
run: mise run ci

native:
name: Native (${{ matrix.os }})
runs-on: ${{ matrix.os }}
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v7.0.1
with:
ref: ${{ github.sha }}
persist-credentials: false
- uses: actions/setup-go@v7.0.0
with:
go-version-file: go.mod
- uses: actions/setup-python@v7.0.0
with:
python-version: "3.13"
- name: Run native CLI and filesystem tests
run: go test -v ./cmd/tdx ./internal/cmd ./internal/markdown ./internal/versioning
- name: Build and replay native executable
shell: bash
run: |
binary=tdx
if [ "$RUNNER_OS" = "Windows" ]; then binary=tdx.exe; fi
go build -o "$binary" ./cmd/tdx
go run ./cmd/tdx-usage -driver cli -binary "$binary" -sessions 1 -steps 40 -output dist/usage/cli
- name: Run POSIX terminal contracts
if: runner.os != 'Windows'
run: python scripts/usage-pty.py --binary ./tdx
- name: Install POSIX visual terminal test dependencies
if: runner.os != 'Windows'
run: python -m pip install pyte==0.8.2 wcwidth==0.8.3
- name: Run inline terminal screen and scrollback regressions
if: runner.os != 'Windows'
run: python scripts/visual-pty.py --binary ./tdx
- name: Install Windows terminal test dependency
if: runner.os == 'Windows'
run: python -m pip install pywinpty==3.0.2
- name: Run Windows ConPTY smoke contracts
if: runner.os == 'Windows'
run: python scripts/usage-conpty.py --binary ./tdx.exe
- name: Verify installer failures offline
if: runner.os != 'Windows'
run: python scripts/test_install.py
- name: Retain native replay and terminal diagnostics
if: always()
uses: actions/upload-artifact@v7.0.1
with:
name: native-${{ matrix.os }}-${{ github.sha }}
path: dist/usage
if-no-files-found: ignore
retention-days: 14
Loading