Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
aecfa02
docs(openspec): add progress consolidation arc changes
abiswas97 Jun 12, 2026
e7bf135
feat(progress): add consolidated progress package vocabulary, runner,…
abiswas97 Jun 12, 2026
913472f
refactor: migrate pipeline importers to internal/progress
abiswas97 Jun 12, 2026
1b13e8d
refactor(tui): consume the exported progress fold
abiswas97 Jun 12, 2026
6f4b430
refactor(integration): emit progress events from the manager
abiswas97 Jun 12, 2026
120f460
refactor(worktree): emit progress events from the deleter
abiswas97 Jun 12, 2026
da34bf5
docs: record progress consolidation in decision log and tasks
abiswas97 Jun 12, 2026
d353915
docs: place consolidation entry inside the decision log
abiswas97 Jun 12, 2026
f7bcfde
feat(progress): plan declarations, checkpoints, close markers, settle…
abiswas97 Jun 12, 2026
b2dfdb2
feat(integration): declare apply plans upfront, worktree-outer execution
abiswas97 Jun 12, 2026
6e2cf42
feat(tui): removal flow declares teardown plans and removal checkpoints
abiswas97 Jun 12, 2026
2fa0778
feat(creator,repo): declare known steps and close phases in pipeline …
abiswas97 Jun 12, 2026
453788d
feat(tui): checkpoint-derived bar and settled-gated phase collapse
abiswas97 Jun 12, 2026
548e976
feat(tui): unconditional state-relative completion settle
abiswas97 Jun 12, 2026
120c314
feat(tui): truth polish for errors title, failed counts, skip traces,…
abiswas97 Jun 12, 2026
4b8372f
docs: check off arc tasks and record decisions
abiswas97 Jun 12, 2026
aca8cb8
test: hermetically isolate git from user and repo config
abiswas97 Jun 12, 2026
778421a
chore(hooks): refuse commits under a leaked git identity
abiswas97 Jun 12, 2026
8a2e202
docs: design truthful pinned progress arc
abiswas97 Jul 14, 2026
fae8e21
docs: plan progress arc correctness implementation
abiswas97 Jul 14, 2026
b5b5665
feat(progress): make plans own terminal state
abiswas97 Jul 14, 2026
b7adb31
fix(progress): harden execution concurrency contract
abiswas97 Jul 14, 2026
c23ae8f
fix(progress): flush terminal events before finish
abiswas97 Jul 14, 2026
2f0b476
fix(integration): freeze exact apply plans
abiswas97 Jul 14, 2026
2dea12c
fix(integration): surface prepared apply failures
abiswas97 Jul 15, 2026
d692f8c
fix(integration): reject incomplete apply results
abiswas97 Jul 15, 2026
abfe5f1
feat(progress): finalize execution contracts
abiswas97 Jul 15, 2026
15a909a
fix(progress): require stable stream labels
abiswas97 Jul 15, 2026
a2f18e4
fix(integration): complete frozen operation engine
abiswas97 Jul 15, 2026
f38c862
fix(integration): preserve detection fallback
abiswas97 Jul 15, 2026
7b79972
fix(creator): settle the prepared creation plan
abiswas97 Jul 15, 2026
9e988a7
fix(creator): preserve independent setup fallbacks
abiswas97 Jul 15, 2026
011b7ce
fix(repo): execute frozen repository plans
abiswas97 Jul 15, 2026
54cff72
fix(repo): preserve migration recovery metadata
abiswas97 Jul 15, 2026
f79f28a
refactor(progress): unify removal and retire legacy streams
abiswas97 Jul 15, 2026
c851159
fix(removal): report all frozen execution failures
abiswas97 Jul 15, 2026
d8c080c
feat(tui): pin the progress live region
abiswas97 Jul 15, 2026
c50160b
fix(tui): preserve omitted progress details
abiswas97 Jul 15, 2026
e236c0b
fix(tui): scope progress motion
abiswas97 Jul 15, 2026
37a7e55
fix(hooks): install hooks in shared git dir
abiswas97 Jul 15, 2026
75cc8d9
fix(tui): prevent stale progress motion
abiswas97 Jul 15, 2026
c638375
test(hooks): isolate hook fixtures
abiswas97 Jul 15, 2026
11563b5
test(hooks): clear inherited git identities
abiswas97 Jul 15, 2026
0cd8462
fix(tui): settle progress summaries cleanly
abiswas97 Jul 15, 2026
4f3c592
test(demos): record deterministic progress flows
abiswas97 Jul 15, 2026
04d5a5f
fix(tui): keep removal summaries truthful
abiswas97 Jul 15, 2026
6acf04f
test(demos): exit the baseline summary deterministically
abiswas97 Jul 15, 2026
552f70f
fix(demos): fail closed outside fixture
abiswas97 Jul 15, 2026
4bc307c
fix(repo): preserve backup on partial restore
abiswas97 Jul 15, 2026
17c83ae
fix(tui): bound settled summaries
abiswas97 Jul 15, 2026
32449b7
docs(progress): remove trailing whitespace
abiswas97 Jul 15, 2026
a0bff9d
fix(repo): reserve migration backups safely
abiswas97 Jul 15, 2026
ebff4c1
fix(integration): contain destructive operations
abiswas97 Jul 15, 2026
07cac82
fix(tui): bound progress views to the terminal
abiswas97 Jul 15, 2026
a23a6bd
test(demo): harden progress fixture boundaries
abiswas97 Jul 15, 2026
06c9737
fix(tui): preserve narrow progress details
abiswas97 Jul 15, 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
47 changes: 47 additions & 0 deletions .demos/progress-arc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Progress arc deterministic recordings

These VHS sources exercise the real Sentei binary against a fixed, local-only
bare repository. Generated binaries, repositories, GIFs, and inspection frames
stay under `/tmp/sentei-vhs-progress-arc` and are never committed.

```bash
.demos/progress-arc/setup-fixture_test.sh
.demos/progress-arc/setup-fixture.sh
mkdir -p /tmp/sentei-vhs-progress-arc/bin
git worktree add --detach /tmp/sentei-vhs-progress-arc/source-before 778421a
(cd /tmp/sentei-vhs-progress-arc/source-before && go build -o /tmp/sentei-vhs-progress-arc/bin/sentei-before .)
printf '%s\n' 778421a >/tmp/sentei-vhs-progress-arc/bin/sentei-before.sha
go build -o /tmp/sentei-vhs-progress-arc/bin/sentei-after .
git rev-parse --short=12 HEAD >/tmp/sentei-vhs-progress-arc/bin/sentei-after.sha
vhs validate .demos/progress-arc/*.tape
vhs .demos/progress-arc/removal-success.tape
```

Each tape first changes to `/`, runs `setup-fixture.sh`, chains setup with
`&&`, then changes to the fixture repository with another fail-closed `&&`
before launching Sentei. A missing fixture can therefore never fall back to
the caller's working directory. Setup recreates
only named children of the exact fixture root. It rejects symlinked, non-owned,
or canonically mismatched fixture paths, including symlinks anywhere beneath
retained output trees, before resetting anything. It isolates HOME/XDG and Git
identity and installs runtime shims. The Git shim denies
network-capable verbs and
rejects absolute worktree paths outside the fixture. Network clients, package
managers, and `gh` fail closed. The `ccc` shim proves presence and initialization,
then exits 17 from `ccc index`, making the integration-failure tape show the
failed index and skipped dependent work.

The tapes set the PTY to 80 columns by 24 rows and use `SENTEI_MOTION=off`.
Their 960×672 pixel canvas leaves enough physical room for all 24 rows at the
recording font and line height.

After rendering, verify GIF metadata with `ffprobe`. Decode from frame zero
before selecting representative active, failure, and final frames; seeking
before the GIF input can inspect an incomplete delta frame. For example:

```bash
ffmpeg -i /tmp/sentei-vhs-progress-arc/outputs/removal-success.gif \
-ss 9 -frames:v 1 /tmp/sentei-vhs-progress-arc/frames/removal-final.png
```

Inspect the resulting PNGs before accepting the recordings.
42 changes: 42 additions & 0 deletions .demos/progress-arc/before-after.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
Output "/tmp/sentei-vhs-progress-arc/outputs/before-after.gif"
Set Shell "bash"
Set Width 960
Set Height 672
Set FontSize 16
Set TypingSpeed 15ms
Set Framerate 30
Hide
Type "cd / && /Users/abiswas/code/personal/sentei/progress-arc/.demos/progress-arc/setup-fixture.sh >/dev/null && source /tmp/sentei-vhs-progress-arc/demo.env && cd /tmp/sentei-vhs-progress-arc/repo/demo.git && stty rows 24 cols 80" Enter
Show
Type "printf 'BEFORE '; cat /tmp/sentei-vhs-progress-arc/bin/sentei-before.sha" Enter
Type "cd /tmp/sentei-vhs-progress-arc/repo/demo.git && /tmp/sentei-vhs-progress-arc/bin/sentei-before" Enter
Sleep 3s
Down 2
Enter
Sleep 3s
Type "a"
Sleep 1s
Enter
Sleep 1s
Type "y"
Sleep 5s
Type "q"
Sleep 1s
Type "q"
Sleep 1s
Hide
Type "cd / && /Users/abiswas/code/personal/sentei/progress-arc/.demos/progress-arc/setup-fixture.sh >/dev/null && source /tmp/sentei-vhs-progress-arc/demo.env && cd /tmp/sentei-vhs-progress-arc/repo/demo.git && stty rows 24 cols 80" Enter
Show
Type "printf 'AFTER '; cat /tmp/sentei-vhs-progress-arc/bin/sentei-after.sha" Enter
Type "cd /tmp/sentei-vhs-progress-arc/repo/demo.git && /tmp/sentei-vhs-progress-arc/bin/sentei-after" Enter
Sleep 3s
Down 2
Enter
Sleep 3s
Type "a"
Sleep 1s
Enter
Sleep 1s
Type "y"
Sleep 5s
Type "q"
23 changes: 23 additions & 0 deletions .demos/progress-arc/integration-failure.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Output "/tmp/sentei-vhs-progress-arc/outputs/integration-failure.gif"
Set Shell "bash"
Set Width 960
Set Height 672
Set FontSize 16
Set TypingSpeed 20ms
Set Framerate 30
Hide
Type "cd / && /Users/abiswas/code/personal/sentei/progress-arc/.demos/progress-arc/setup-fixture.sh >/dev/null && source /tmp/sentei-vhs-progress-arc/demo.env && cd /tmp/sentei-vhs-progress-arc/repo/demo.git && stty rows 24 cols 80" Enter
Show
Type "cd /tmp/sentei-vhs-progress-arc/repo/demo.git && /tmp/sentei-vhs-progress-arc/bin/sentei-after" Enter
Sleep 3s
Down
Sleep 1s
Enter
Sleep 3s
Down
Sleep 1s
Space
Sleep 1s
Enter
Sleep 5s
Type "q"
22 changes: 22 additions & 0 deletions .demos/progress-arc/removal-success.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Output "/tmp/sentei-vhs-progress-arc/outputs/removal-success.gif"
Set Shell "bash"
Set Width 960
Set Height 672
Set FontSize 16
Set TypingSpeed 20ms
Set Framerate 30
Hide
Type "cd / && /Users/abiswas/code/personal/sentei/progress-arc/.demos/progress-arc/setup-fixture.sh >/dev/null && source /tmp/sentei-vhs-progress-arc/demo.env && cd /tmp/sentei-vhs-progress-arc/repo/demo.git && stty rows 24 cols 80" Enter
Show
Type "cd /tmp/sentei-vhs-progress-arc/repo/demo.git && /tmp/sentei-vhs-progress-arc/bin/sentei-after" Enter
Sleep 3s
Down 2
Enter
Sleep 1s
Type "a"
Sleep 1s
Enter
Sleep 1s
Type "y"
Sleep 5s
Type "q"
172 changes: 172 additions & 0 deletions .demos/progress-arc/setup-fixture.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT=/tmp/sentei-vhs-progress-arc
case "$ROOT" in
/tmp/sentei-vhs-progress-arc) ;;
*) printf 'refusing unsafe fixture root: %s\n' "$ROOT" >&2; exit 64 ;;
esac

refuse() {
printf 'refusing unsafe fixture path: %s (%s)\n' "$1" "$2" >&2
exit 64
}

owner_uid() {
local path=$1
local uid
if uid=$(stat -f '%u' "$path" 2>/dev/null); then
printf '%s\n' "$uid"
return
fi
stat -c '%u' "$path"
}

canonical_dir() {
(cd -P "$1" 2>/dev/null && pwd -P)
}

ROOT_PARENT=$(canonical_dir "$(dirname "$ROOT")") || refuse "$ROOT" 'parent cannot be resolved'
EXPECTED_ROOT="$ROOT_PARENT/$(basename "$ROOT")"

[[ ! -L "$ROOT" ]] || refuse "$ROOT" 'fixture root is a symlink'
if [[ -e "$ROOT" ]]; then
[[ -d "$ROOT" ]] || refuse "$ROOT" 'fixture root is not a directory'
[[ $(owner_uid "$ROOT") == "$(id -u)" ]] || refuse "$ROOT" 'fixture root has a different owner'
CANONICAL_ROOT=$(canonical_dir "$ROOT") || refuse "$ROOT" 'fixture root cannot be resolved'
[[ "$CANONICAL_ROOT" == "$EXPECTED_ROOT" ]] || refuse "$ROOT" 'fixture root resolves outside its boundary'
else
mkdir "$ROOT"
CANONICAL_ROOT=$(canonical_dir "$ROOT") || refuse "$ROOT" 'created fixture root cannot be resolved'
[[ "$CANONICAL_ROOT" == "$EXPECTED_ROOT" ]] || refuse "$ROOT" 'created fixture root resolves outside its boundary'
fi

for child in outputs frames; do
retained="$ROOT/$child"
[[ ! -L "$retained" ]] || refuse "$retained" 'retained directory is a symlink'
if [[ -e "$retained" ]]; then
[[ -d "$retained" ]] || refuse "$retained" 'retained path is not a directory'
[[ $(owner_uid "$retained") == "$(id -u)" ]] || refuse "$retained" 'retained directory has a different owner'
retained_canonical=$(canonical_dir "$retained") || refuse "$retained" 'retained directory cannot be resolved'
[[ "$retained_canonical" == "$CANONICAL_ROOT/$child" ]] || refuse "$retained" 'retained directory resolves outside its boundary'
descendant_symlink=$(find "$retained" -type l -print -quit) || refuse "$retained" 'retained directory cannot be inspected'
[[ -z "$descendant_symlink" ]] || refuse "$descendant_symlink" 'symlink beneath retained directory'
fi
done

for child in home xdg-config xdg-cache xdg-data repo seed shims logs; do
rm -rf "${ROOT:?}/$child"
mkdir -p "$ROOT/$child"
done
mkdir -p "$ROOT/outputs" "$ROOT/frames"

export HOME="$ROOT/home"
export XDG_CONFIG_HOME="$ROOT/xdg-config"
export XDG_CACHE_HOME="$ROOT/xdg-cache"
export XDG_DATA_HOME="$ROOT/xdg-data"
export GIT_CONFIG_GLOBAL="$ROOT/home/gitconfig"
export GIT_CONFIG_SYSTEM=/dev/null
export GIT_AUTHOR_NAME='Sentei Demo'
export GIT_AUTHOR_EMAIL='sentei-demo@example.invalid'
export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"
export GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"
export LC_ALL=C
export TZ=UTC
export TERM=xterm-256color

GIT=/usr/bin/git
"$GIT" config --global init.defaultBranch main
"$GIT" init "$ROOT/seed" >/dev/null
printf '# deterministic sentei demo\n' >"$ROOT/seed/README.md"
"$GIT" -C "$ROOT/seed" add README.md
"$GIT" -C "$ROOT/seed" commit -m 'fixture: initial content' >/dev/null
"$GIT" clone --bare "$ROOT/seed" "$ROOT/repo/demo.git" >/dev/null

for branch in alpha beta gamma; do
path="$ROOT/repo/worktrees/$branch"
mkdir -p "$(dirname "$path")"
"$GIT" --git-dir="$ROOT/repo/demo.git" worktree add -b "demo/$branch" "$path" main >/dev/null
printf '%s\n' "$branch" >"$path/$branch.txt"
"$GIT" -C "$path" add "$branch.txt"
"$GIT" -C "$path" commit -m "fixture: $branch" >/dev/null
done

cat >"$ROOT/shims/git" <<'SHIM'
#!/usr/bin/env bash
set -euo pipefail
ROOT=/tmp/sentei-vhs-progress-arc
printf 'git %q ' "$@" >>"$ROOT/logs/git.log"
printf '\n' >>"$ROOT/logs/git.log"
for arg in "$@"; do
case "$arg" in
*://*|git@*) printf 'network git argument denied: %s\n' "$arg" >&2; exit 90 ;;
esac
done
case " ${*} " in
*' fetch '*|*' pull '*|*' push '*|*' clone '*|*' ls-remote '*)
printf 'network-capable git verb denied\n' >&2
exit 91
;;
esac
if [[ " ${*} " == *' worktree remove '* ]]; then
for arg in "$@"; do
case "$arg" in
/*)
case "$arg" in "$ROOT"/*) ;; *) printf 'worktree escape denied: %s\n' "$arg" >&2; exit 92 ;; esac
;;
esac
done
sleep 0.35
fi
exec /usr/bin/git "$@"
SHIM

cat >"$ROOT/shims/ccc" <<'SHIM'
#!/usr/bin/env bash
set -euo pipefail
ROOT=/tmp/sentei-vhs-progress-arc
printf 'ccc %s\n' "$*" >>"$ROOT/logs/ccc.log"
case "${1:-}" in
init|--version) exit 0 ;;
index) printf 'deterministic index failure\n' >&2; exit 17 ;;
*) exit 0 ;;
esac
SHIM

cat >"$ROOT/shims/python3" <<'SHIM'
#!/usr/bin/env bash
exit 0
SHIM
cat >"$ROOT/shims/uv" <<'SHIM'
#!/usr/bin/env bash
exit 0
SHIM

for denied in gh curl wget brew npm npx pnpm yarn pip pip3 pipx; do
cat >"$ROOT/shims/$denied" <<'SHIM'
#!/usr/bin/env bash
printf 'network or package-manager command denied: %s\n' "$0" >&2
exit 93
SHIM
done
chmod +x "$ROOT/shims/"*

cat >"$ROOT/demo.env" <<EOF
export HOME='$HOME'
export XDG_CONFIG_HOME='$XDG_CONFIG_HOME'
export XDG_CACHE_HOME='$XDG_CACHE_HOME'
export XDG_DATA_HOME='$XDG_DATA_HOME'
export GIT_CONFIG_GLOBAL='$GIT_CONFIG_GLOBAL'
export GIT_CONFIG_SYSTEM=/dev/null
export GIT_AUTHOR_NAME='$GIT_AUTHOR_NAME'
export GIT_AUTHOR_EMAIL='$GIT_AUTHOR_EMAIL'
export GIT_COMMITTER_NAME='$GIT_COMMITTER_NAME'
export GIT_COMMITTER_EMAIL='$GIT_COMMITTER_EMAIL'
export LC_ALL=C
export TZ=UTC
export TERM=xterm-256color
export SENTEI_MOTION=off
export PATH='$ROOT/shims:/usr/bin:/bin'
EOF

printf 'fixture ready: %s\n' "$ROOT/repo/demo.git"
Loading