Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
134fb81
chore(fork-base): fork workflows, stack tools, and docs
github-actions[bot] Jul 31, 2026
95b1a72
feat(tim): import tim-smart/t3code#4
tim-smart Jul 26, 2026
a5a420a
feat(tim): import tim-smart/t3code#5
tim-smart Jul 26, 2026
bdbf176
feat(tim): import tim-smart/t3code#6
tim-smart Jul 26, 2026
58deb5f
feat(tim): import tim-smart/t3code#7
tim-smart Jul 26, 2026
7343b7b
feat(tim): import tim-smart/t3code#8
tim-smart Jul 26, 2026
974887c
feat(tim): import tim-smart/t3code#9
tim-smart Jul 26, 2026
01a5c1e
feat(tim): import tim-smart/t3code#10
tim-smart Jul 26, 2026
77ce384
feat(tim): import tim-smart/t3code#11
tim-smart Jul 26, 2026
9f9948a
feat(tim): import tim-smart/t3code#12
tim-smart Jul 26, 2026
74014e2
feat(tim): import tim-smart/t3code#13
tim-smart Jul 26, 2026
837813f
feat(tim): import tim-smart/t3code#14
tim-smart Jul 26, 2026
3e7efdf
feat(tim): import tim-smart/t3code#15
tim-smart Jul 26, 2026
61bc477
feat(tim): import tim-smart/t3code#16
tim-smart Jul 26, 2026
b208d1b
feat(tim): import tim-smart/t3code#17
tim-smart Jul 26, 2026
4cded7e
test(tim-compat): gate macOS bundle fixture to Darwin
patroza Jul 26, 2026
2adb99d
fix(tim-compat): avoid plutil for custom open-with apps
patroza Jul 26, 2026
83af061
fix(tim-compat): product-merge VCS #4727 with fork failureKind; green…
github-actions[bot] Jul 29, 2026
0cba380
fix(tim): restore resource telemetry join + TRACE2 hook exits
github-actions[bot] Jul 29, 2026
3018b8d
fix(tim): settings search test after worktree-confirm catalog entry
github-actions[bot] Aug 1, 2026
980221b
chore: initialize upstream candidate registry
patroza Jul 25, 2026
580ae52
perf: import bounded web thread history (upstream #4018) (#29)
patroza Jul 25, 2026
4eee93a
perf: import mobile pagination and bounded replay (upstream #3510) (#35)
patroza Jul 25, 2026
f78195c
perf: import bounded long-lived state (upstream #4176) (#34)
patroza Jul 25, 2026
59d8ed2
feat(web): import answered question timeline (upstream #4506) (#44)
patroza Jul 25, 2026
cd5dafa
feat(orchestrator): import upstream follow-up queue (#4245) (#63)
patroza Jul 25, 2026
e302907
fix(client-runtime): re-read network status when the app resumes (ups…
patroza Jul 26, 2026
ab17ec8
perf(server): compress and cache packaged web assets (upstream #4516)
patroza Jul 26, 2026
f93c915
perf(server): back off repeated checkpoint capture failures (upstream…
patroza Jul 26, 2026
cb3b970
fix(server): preserve manually renamed thread titles (upstream #4558)
patroza Jul 26, 2026
74a5478
fix(candidates): rejoin follow-up queue types after tim tip green
github-actions[bot] Jul 29, 2026
8dd6229
fix(candidates): expect thread.unsnoozed on settled turn starts
github-actions[bot] Jul 29, 2026
af4fea3
fix(candidates): align stale-cursor test with #5147 THREAD_RESUME_MAX…
github-actions[bot] Aug 1, 2026
d8b8d75
fix(candidates): accept interleaved sync/live after stale-cursor snap…
github-actions[bot] Aug 1, 2026
88da306
fix(candidates): restore SidebarV2 terminal status after restack
github-actions[bot] Aug 1, 2026
163e7d0
chore(fork): stack docs, overlays, tooling, CI, and workspace
github-actions[bot] Jul 31, 2026
3227c20
feat(contracts): fork protocol and settings schema extensions
github-actions[bot] Jul 31, 2026
bafb366
feat(shared): shared helpers and Hermes lint guards
github-actions[bot] Jul 31, 2026
ed68534
feat(client-runtime): reconnect diagnostics, VCS actions, and list state
github-actions[bot] Jul 31, 2026
682b3ef
feat(packages): ssh, tailscale, and effect-acp fork deltas
github-actions[bot] Jul 31, 2026
080c393
feat(server): queue, recovery, VCS, Jira, orchestration, and RPC auth
github-actions[bot] Jul 31, 2026
944d1d3
feat(web): sidebar, composer, timeline, search, and chrome fork product
github-actions[bot] Jul 31, 2026
a10ec04
feat(mobile): home modes, board, queue composer, and scroll baseline
github-actions[bot] Jul 31, 2026
a962b7b
feat(desktop): packaging, open-with, and backend ownership deltas
github-actions[bot] Jul 31, 2026
439d6a0
fix(desktop): drop obsolete requestSingleInstanceLock from update tests
github-actions[bot] Jul 31, 2026
fa90d1e
fix(mobile,desktop): restore typecheck-green home header and update t…
github-actions[bot] Jul 31, 2026
f763ab0
fix(web): isolate ProjectFavicon test so module mocks apply
github-actions[bot] Jul 31, 2026
17321e0
ci(compose): run only on merges, not branch pushes
github-actions[bot] Jul 31, 2026
8c61eb4
feat(settings): default new threads to new worktree from origin (#252)
omegent-app[bot] Jul 31, 2026
9f45178
ci(fork): disable Blacksmith CI path; green Tim/candidates via Fork CI
github-actions[bot] Jul 31, 2026
647cadf
feat(stack): introduce fork/base for fork-only CI plumbing
github-actions[bot] Jul 31, 2026
3847488
fix(stack): own VS Code build task under vscode overlay
github-actions[bot] Jul 31, 2026
d0d649b
fix(desktop): restore dist:desktop:linux:dir packaging script (#258)
patroza Jul 31, 2026
1e1a4b1
fix(grok): always pin Build to agent mode, never leave ask (#260)
patroza Jul 31, 2026
46f7df5
fix(mobile): unique markdown table cell keys to stop render thrash (#…
patroza Jul 31, 2026
38ed74f
fix(web): reload on stale lazy-chunk load after deploy (#263)
omegent-app[bot] Jul 31, 2026
5e546c7
fix(mobile): hard-unique markdown table cell keys (no table_cell:0:0)…
patroza Jul 31, 2026
ba2e5da
fix(mobile): stop thread outbox drain spin on reconnect (#265)eeeeeeee
patroza Jul 31, 2026
d35922c
feat(web): move message deep-link wiring onto fork/changes (#267)
patroza Jul 31, 2026
2f32479
fix(web): open `?thread=` deep links instead of a new draft (#270)
omegent-app[bot] Jul 31, 2026
87a555a
fix(mobile): ship EAS OTA when Free plan build quota is exhausted (#271)
patroza Jul 31, 2026
9756b9e
fix(web): deep-link open without waiting on shell membership (#272)
omegent-app[bot] Jul 31, 2026
9c34e1f
fix(stack): auto-resolve app.config overlay rebase conflicts (#274)
omegent-app[bot] Jul 31, 2026
153174f
fix(web): green SidebarV2 after restack onto candidates
github-actions[bot] Aug 1, 2026
11eba7a
fix(stack): green changes tip after restack
github-actions[bot] Aug 1, 2026
a966882
fix(mobile): align list snooze API after candidates restack
github-actions[bot] Aug 1, 2026
11c4402
fix(server): durable restartRecovery for post-deploy turn resume (#282)
patroza Aug 1, 2026
5773f2b
feat(mobile): render settled threads as slim history rows (#283)
omegent-app[bot] Aug 1, 2026
dee36d6
feat(server): blocking lifecycle scripts before worktree removal (#284)
omegent-app[bot] Aug 2, 2026
6381dac
ci: add one-shot deploy-key helper to force-update overlay tips (#286)
omegent-app[bot] Aug 2, 2026
1f1e1a9
fix(server): bound provider control commands (#288)
patroza Aug 2, 2026
3dfe045
feat(server): isolate provider commands by thread (#289)
patroza Aug 2, 2026
10124b6
fix(server): retain Grok notification consumer for session (#291)
patroza Aug 2, 2026
ce330c9
feat(tooling): agent ship gate with draft-free push and pr:ready (#290)
omegent-app[bot] Aug 2, 2026
a94ed23
feat(web): proactive reload affordance after web hot-swap (draft) (#294)
patroza Aug 2, 2026
c81f6ae
feat(tooling): shared-hooks dir so `git worktree add` sets up node_mo…
patroza Aug 2, 2026
0cf23ba
feat(web): copy thread ID from sidebar v2 menus (#297)
patroza Aug 3, 2026
366817b
feat(server): include T3 thread links in Jira replies (#298)
patroza Aug 3, 2026
e71cf66
feat(server): make web-asset serving hot-swap safe + classify web-onl…
patroza Aug 3, 2026
d9356c1
feat(server): reap idle dev stacks from a level-triggered sweep (#296)
patroza Aug 3, 2026
cf32ff1
fix(web): align sidebar v1 hide-settled with PR auto-settle (#299)
omegent-app[bot] Aug 3, 2026
3479290
Use repository-owned native Git hooks (#300)
patroza Aug 3, 2026
c251bf6
fix(mobile): tolerate EAS CLI notices in --json output (#301)
patroza Aug 3, 2026
b41c807
Await repository preparation before worktree handoff (#303)
patroza Aug 3, 2026
9a42ebc
fix(agent): gate undrafting a PR instead of refusing it (#302)
patroza Aug 3, 2026
3a9751b
test(stack): stop the git fixtures inheriting the caller's repository…
patroza Aug 3, 2026
a979f68
fix(agent): run the pre-push gate without pnpm exec (#305)
patroza Aug 4, 2026
ce7be30
fix(vcs): treat bare repositories as valid worktree sources (#307)
patroza Aug 4, 2026
aba397c
fix(desktop): isolate DesktopPreReadyPlatform electron mock test
github-actions[bot] Aug 4, 2026
3e71802
fix(agent): static pre-push gate on draft and no-PR pushes (#311)
patroza Aug 4, 2026
a167af1
fix(hooks): wipe TS project emit on branch checkout (#308)
patroza Aug 4, 2026
c1d5d69
fix(server): do not block command readiness on recovery turns (#313)
patroza Aug 4, 2026
93e282c
fix(vcs): name the branch-already-checked-out collision
github-actions[bot] Aug 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
17 changes: 17 additions & 0 deletions .agents/skills/test-t3-app/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,23 @@ Shared browser dev is single-origin: Vite proxies the backend paths, so never se

The dev runner disables browser auto-open by default. Do not pass `--browser` during automated testing: an automatically opened page can consume the one-time bootstrap token before the controlled browser uses it.

### Previewing the dev server from a remote client

When T3 itself is being driven from another machine — the app connected to this environment over a
tailnet or LAN address rather than `localhost` — a dev server bound to loopback is not reachable at
that address just because the hostname is. Opening it does **not** require `--share`: the
environment resolves the port on demand, reusing an existing `tailscale serve` route, using the
environment's own address when the port already answers there, and otherwise publishing a
tailnet-only HTTPS route for the port and withdrawing it when the dev server exits.

Give the preview a `localhost:<port>` URL and let it resolve. Never hand-write the environment's
hostname with the dev port appended — that is the shape that fails, because nothing promises the
dev port is published under the same number or scheme.

If the port cannot be made reachable, the preview reports why and what to do (dev server not
running, tailscale not logged in, no permission to manage routes, tailnet port already taken).
Treat that message as the result; do not retry the same URL.

### Verify a shared environment before human handoff

When another person will use the printed pairing URL, first open the shared origin without the pairing path or fragment in the controlled browser and confirm the T3 Code app loads. This browser navigation is required even when curl succeeds because browsers block some otherwise reachable ports before making a network request.
Expand Down
56 changes: 56 additions & 0 deletions .easignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Keep EAS project archives small. Mobile only needs the monorepo packages it
# resolves through pnpm — not vendored agent reference trees or desktop shells.

# Vendored reference repos (agents only; never imported by app code)
.repos/

# Desktop / electron / native host tooling
apps/desktop/
apps/vscode/
apps/discord-bot/
native/
release/
release-mock/
dist-electron/
.electron-runtime/

# Infra, docs, agent metadata
docs/
.agents/
.grok/
.github/
.claude/
.cursor/
.vscode/
infra/
artifacts/
.showcase/
apps/mobile/.showcase/

# Tests and snapshots (not needed for EAS bundle)
**/__screenshots__/
**/*.test.ts
**/*.test.tsx
**/*.spec.ts
**/*.spec.tsx
**/test-results/
**/playwright-report/
**/.vitest-*/

# Local / generated
node_modules/
.t3/
.turbo/
.alchemy/
.dir-deploy-n
.logs/
*.log
.DS_Store
.env
.env.*
!.env.example

# Git / IDE noise
.git/
.idea/
*.tsbuildinfo
21 changes: 21 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@
# Get this from your relay deployment. `infra/relay` deploys update it automatically.
# T3CODE_RELAY_URL=https://relay.example.com

# Optional: GitHub App bridge for continuing an existing worktree-backed T3 thread
# from a pull-request comment. See docs/integrations/github-app-setup.md.
# The webhook route stays disabled unless all four required values are set.
# T3CODE_GITHUB_APP_ID=123456
# T3CODE_GITHUB_APP_PRIVATE_KEY_PATH=/absolute/path/to/private-key.pem
# T3CODE_GITHUB_WEBHOOK_SECRET=replace-with-a-random-secret
# T3CODE_GITHUB_APP_MENTION=t3-code-dev
# T3CODE_GITHUB_ALLOWED_REPOSITORIES=owner/repository,owner/another-repository
# T3CODE_GITHUB_MIN_PERMISSION=write
# T3CODE_GITHUB_TURN_TIMEOUT_MS=1800000

# Optional: hosted app origin used by the CLI's out-of-band OAuth flow.
# Defaults to https://app.t3.codes; override to test against a staging deployment.
# T3CODE_HOSTED_APP_URL=https://nightly.app.t3.codes
Expand All @@ -26,3 +37,13 @@
# T3CODE_MOBILE_OTLP_TRACES_URL=https://api.axiom.co/v1/traces
# T3CODE_MOBILE_OTLP_TRACES_DATASET=t3-code-mobile-traces-dev
# T3CODE_MOBILE_OTLP_TRACES_TOKEN=xaat-...

# Optional: sign and publish the mobile app from your own Expo and Apple teams.
# Development and preview builds append .dev and .preview to the bundle identifier.
# T3CODE_MOBILE_IOS_TEAM_ID=ABC1234567
# T3CODE_MOBILE_IOS_BUNDLE_IDENTIFIER=com.example.t3code
# Set to 1 only for free Xcode Personal Team builds. This disables paid-only
# widgets, push capabilities, App Groups, associated domains, and EAS updates.
# T3CODE_MOBILE_IOS_PERSONAL_TEAM=1
# T3CODE_MOBILE_EAS_PROJECT_ID=00000000-0000-0000-0000-000000000000
# T3CODE_MOBILE_EXPO_OWNER=your-expo-username
9 changes: 9 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Prefer the repo gh policy shim so coding agents cannot undraft with raw
# `gh pr ready` (use `pnpm pr:ready`). Installed by scripts/install-git-hooks.mjs.
PATH_add .tools/bin

# Default bare `gh` commands to the fork, not gh's upstream-parent default
# (`pingdotgg/t3code`). Without this, `gh pr view`/`create`/`checks` resolve
# against upstream and miss the fork's PRs. Explicit `--repo` always overrides,
# so the stack tooling (which always passes `--repo`) is unaffected.
export GH_REPO="${T3CODE_FORK_REPOSITORY:-patroza/t3code}"
41 changes: 41 additions & 0 deletions .githooks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Native Git hooks

`pnpm install` configures `core.hooksPath=.githooks`. The tracked hooks exist
immediately in every linked worktree; `post-checkout` reconciles dependencies
after branch checkout and worktree creation before Git returns. T3 configures
the hook path and triggers that checkout once for a fresh clone, before exposing
the repository to the user.

## `post-checkout`

### 1. Clear TypeScript project emit (always on branch / worktree checkout)

Composite packages and build outputs leave gitignored `dist/` and
`*.tsbuildinfo`. After a branch switch those artifacts can still belong to
another tree while sources follow HEAD. That produces phantom type errors (or
stale emit consumers) that disappear after a clean rebuild — same class of
failure as [scanner#1495](https://github.com/macs-holding/scanner/pull/1495) /
[scanner#2166](https://github.com/macs-holding/scanner/pull/2166) and upstream
typescript-go incremental gaps.

On every **branch** checkout (flag `1`), this hook deletes:

- `apps/*/dist`, `apps/*/dist-electron`, `packages/*/dist`
- any remaining `*.tsbuildinfo` outside `node_modules` / `.git` / `.vite-plus`

File-only checkouts (flag `0`) are left alone.

**This is a workaround.** Remove when TypeScript/tsgo incremental invalidation
is reliable ([typescript-go#2666](https://github.com/microsoft/typescript-go/issues/2666),
[#4664](https://github.com/microsoft/typescript-go/issues/4664),
[#4262](https://github.com/microsoft/typescript-go/issues/4262)). Do not
re-enable cross-tree dist reuse without an exact source-identity key.

### 2. Seed copy + pnpm install

Successful reconciliation records the package/lockfile state under
`node_modules`, so T3's explicit handoff invocation does not repeat an install
which Git already completed. Explicit invocation from the target is required
for bare or stale source repositories.

Lefthook may later orchestrate parallel jobs, but is intentionally unused now.
149 changes: 149 additions & 0 deletions .githooks/post-checkout
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#!/bin/sh
# Reconcile packages after branch checkout and prepare linked git worktrees.
#
# Canonical hook: scripts/install-git-hooks.mjs installs this into the shared
# hooks dir (core.hooksPath) on EVERY host via `pnpm install`, so a raw
# `git worktree add` sets up node_modules identically on smart and the t3vm
# guest -- not only when a worktree is created through the T3 app / t3.json.
#
# Strategy (metadata-safe):
# 1. Drop TypeScript project emit (dist / tsbuildinfo) so composite/incremental
# builds never typecheck against foreign-tree .d.ts after a branch switch.
# 2. Copy *small* gitignored seeds from .worktreeinclude (CLAUDE.md, .nuxt, …)
# via reflink/hardlink when available. NEVER clone node_modules -- that
# creates millions of inodes per worktree on btrfs.
# 3. Populate node_modules with `pnpm install --frozen-lockfile --prefer-offline`
# against the shared store (hardlinks -> one inode per package file).
#
# Idempotent: never overwrites existing seed paths; pnpm is safe to re-run.

# Host-agnostic: pick up pnpm/mise from the invoking user's home on either host.
PATH="$HOME/.local/bin:$HOME/.local/share/pnpm:$HOME/.local/share/mise/shims:/run/current-system/sw/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:$PATH"
export PATH

# post-checkout also runs after file-only checkouts; those do not change packages.
[ "${3:-0}" = "1" ] || exit 0

main_wt=$(git worktree list --porcelain | sed -n '1s/^worktree //p')
wt_root=$(git rev-parse --show-toplevel 2>/dev/null)
[ -n "$wt_root" ] || exit 0

# --- TS build-cache wipe (every branch / worktree checkout) -----------------
#
# Composite/incremental emit (and leftover dist from builds) can outlive a
# branch switch. Foreign .tsbuildinfo / .d.ts produce phantom type errors that
# vanish after clean rebuild — same class as macs-holding/scanner#1495 / #2166
# and typescript-go incremental gaps (#2666, #4664, #4262).
# Workaround until upstream invalidation is solid; see .githooks/README.md.
#
clean_ts_project_emit() {
root=$1
removed=0

for d in \
"$root"/apps/*/dist \
"$root"/apps/*/dist-electron \
"$root"/packages/*/dist
do
[ -e "$d" ] || continue
rm -rf "$d"
removed=1
done

if [ -d "$root" ]; then
# Prune by basename so nested apps/*/node_modules are skipped too.
tsbuild_files=$(
find "$root" \
\( -name node_modules -o -name .git -o -name .vite-plus \) -prune -o \
-type f -name '*.tsbuildinfo' -print 2>/dev/null || true
)
if [ -n "$tsbuild_files" ]; then
printf '%s\n' "$tsbuild_files" | while IFS= read -r f; do
[ -n "$f" ] || continue
rm -f "$f"
done
removed=1
fi
fi

if [ "$removed" = 1 ]; then
echo "post-checkout: cleared TypeScript project emit (dist / tsbuildinfo) under $root" >&2
echo "post-checkout: workaround for tsgo/tsc stale incremental cache after tree switch — see .githooks/README.md (remove when upstream fixed)" >&2
fi
}

clean_ts_project_emit "$wt_root"

if [ -n "$main_wt" ] && [ "$main_wt" != "$wt_root" ]; then
# Effective include: repo .worktreeinclude if present, else nothing to seed-copy.
include=""
if [ -f "$main_wt/.worktreeinclude" ]; then
include="$main_wt/.worktreeinclude"
fi

# Probe once: reflink (CoW fs) > hard link (same fs) > plain copy (cross-device).
probe="$main_wt/.git-hook-clone-probe.$$"
probe_dst="$wt_root/.clone-probe.$$"
: >"$probe"
if cp --reflink=always "$probe" "$probe_dst" 2>/dev/null; then
clone() { cp -a --reflink=always "$1" "$2"; }
elif ln "$probe" "$probe_dst" 2>/dev/null; then
clone() { cp -al "$1" "$2"; }
else
clone() { cp -a "$1" "$2"; }
fi
rm -f "$probe" "$probe_dst"

# True if path is node_modules or under one (never clone these).
is_node_modules_path() {
case "/$1/" in
*/node_modules/*) return 0 ;;
*) return 1 ;;
esac
}

if [ -n "$include" ] && [ -f "$include" ]; then
git -C "$main_wt" ls-files --others --ignored --exclude-from="$include" --directory |
while IFS= read -r rel; do
rel=${rel%/}
[ -n "$rel" ] || continue
is_node_modules_path "$rel" && continue
src="$main_wt/$rel"
dst="$wt_root/$rel"
[ -e "$dst" ] && continue
[ -e "$src" ] || continue
mkdir -p "$(dirname "$dst")"
if [ -d "$src" ]; then
clone "$src" "$dst"
else
cp "$src" "$dst"
fi
done
fi
fi

# Shared-store hardlink install: fast when the store is warm, no inode clone storm.
[ -f "$wt_root/package.json" ] || exit 0
[ -f "$wt_root/pnpm-lock.yaml" ] || {
echo "post-checkout: package.json without pnpm-lock.yaml; skip install" >&2
exit 0
}
state_file="$wt_root/node_modules/.pnpm-checkout-state"
state=$(cksum "$wt_root/package.json" "$wt_root/pnpm-lock.yaml" | cksum | awk '{print $1 ":" $2}')
if [ -f "$wt_root/node_modules/.modules.yaml" ] && [ "$(cat "$state_file" 2>/dev/null)" = "$state" ]; then
exit 0
fi
command -v pnpm >/dev/null 2>&1 || {
echo "post-checkout: pnpm not on PATH; node_modules not installed" >&2
exit 0
}

export CI=1
echo "post-checkout: pnpm install (hardlink from store) in $wt_root" >&2
cd "$wt_root" || exit 1
pnpm install \
--frozen-lockfile \
--prefer-offline \
--config.package-import-method=hardlink \
--config.confirmModulesPurge=false || exit $?
printf '%s\n' "$state" >"$state_file"
8 changes: 8 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/sh
root=$(git rev-parse --show-toplevel 2>/dev/null) || exit 1
if [ ! -x "$root/node_modules/.bin/lint-staged" ]; then
echo "pre-commit: worktree preparation is incomplete (lint-staged is missing)" >&2
echo "pre-commit: T3/manual checkout must finish post-checkout before commit" >&2
exit 1
fi
exec pnpm lint-staged
16 changes: 16 additions & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Agent-only ship gate (humans: no-op). See scripts/agent-pre-push.mjs.
# Draft / no PR: static gate (vp check + typecheck). Ready PR: + unit tests.
# Publish: pnpm pr:ready, or raw `gh pr ready` — the shim runs the same full gate first.
#
# Humans: SKIP_AGENT_PREPUSH=1 git push
# Agents: never SKIP_AGENT_PREPUSH / never --no-verify
# Nested Git commands must discover their own repositories, not inherit this
# hook's GIT_DIR/GIT_WORK_TREE from the outer push.
for name in $(git rev-parse --local-env-vars); do
unset "$name"
done
# Plain `node`, not `pnpm exec node`: pnpm runs a dependency-status check first
# and will try to purge node_modules when the lockfile moved (a rebase does it),
# which aborts without a TTY — the hook then fails with a pnpm error instead of
# anything about the gate. The gate puts node_modules/.bin on PATH itself.
node scripts/agent-pre-push.mjs
35 changes: 0 additions & 35 deletions .github/VOUCHED.td

This file was deleted.

Loading
Loading