Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 10 additions & 9 deletions .agents/skills/verify-agent-tty/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,16 @@ It then copies each session's `session.json`, `events.jsonl` and `artifacts/` in

## Helpers

All scripts take the run's `env.sh` path, except `start-run.sh` and `stale-dist.sh`:

| Script | Use |
| ------------------------------ | --------------------------------------------------------------------------------- |
| `scripts/start-run.sh [name]` | Sync deps with the lockfile, build, make the run folder, print the `env.sh` path. |
| `scripts/stale-dist.sh` | Print why `dist/` is not a complete, current build of `src/`, or nothing. |
| `scripts/doctor.sh <env.sh>` | Check that the run is worth driving. Exit 0 or 1. |
| `scripts/run-pids.sh <env.sh>` | Print the PIDs this run started. Exit 2: no `/proc`. Exit 3: ledger error. |
| `scripts/cleanup.sh <env.sh>` | Tear the run down and keep the evidence. |
All scripts take the run's `env.sh` path, except `start-run.sh`, `stale-dist.sh` and `dependabot-resolve.sh`:

| Script | Use |
| ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `scripts/start-run.sh [name]` | Sync deps with the lockfile, build, make the run folder, print the `env.sh` path. |
| `scripts/stale-dist.sh` | Print why `dist/` is not a complete, current build of `src/`, or nothing. |
| `scripts/doctor.sh <env.sh>` | Check that the run is worth driving. Exit 0 or 1. |
| `scripts/run-pids.sh <env.sh>` | Print the PIDs this run started. Exit 2: no `/proc`. Exit 3: ledger error. |
| `scripts/cleanup.sh <env.sh>` | Tear the run down and keep the evidence. |
| `scripts/dependabot-resolve.sh [dep@version ...]` | Replay Dependabot's npm resolve on an empty pnpm store. Run it after a change to `package.json`, `pnpm-lock.yaml`, `pnpm-workspace.yaml` or `.github/dependabot.yml`. Exit 1: a dep fails. Exit 2: setup error. |

## Keep the map honest

Expand Down
47 changes: 47 additions & 0 deletions .agents/skills/verify-agent-tty/scripts/dependabot-resolve.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# Replays the resolve that a Dependabot npm version update runs on this
# checkout: `pnpm update <dep> --lockfile-only` with Dependabot's 7-day
# cooldown as the minimum release age, on copies of package.json,
# pnpm-lock.yaml and pnpm-workspace.yaml, against an empty pnpm store. A
# store that already holds the locked packages skips pnpm's trust check, so
# only an empty store shows what Dependabot sees. Needs the npm registry and
# the pnpm version that package.json's packageManager field pins.
#
# .agents/skills/verify-agent-tty/scripts/dependabot-resolve.sh [dep@version ...]
#
# Prints one line per dep and a count line. Exit 0 when every dep resolves,
# 1 when one fails, 2 on a setup error.
set -uo pipefail

repo=$(git -C "$(dirname "${BASH_SOURCE[0]}")" rev-parse --show-toplevel) || exit 2
pnpm=$(cd "$repo" && { mise which pnpm 2>/dev/null || command -v pnpm; }) || {
echo "dependabot-resolve.sh: pnpm is not on PATH; run 'mise install' first" >&2
exit 2
}
want=$(sed -n 's/^ *"packageManager": "pnpm@\([^"]*\)".*/\1/p' "$repo/package.json")
have=$(cd "$repo" && "$pnpm" --version 2>/dev/null)
if [ -z "$want" ] || [ "$have" != "$want" ]; then
echo "dependabot-resolve.sh: $pnpm is pnpm ${have:-unknown}, package.json pins ${want:-nothing}" >&2
exit 2
fi
[ "$#" -gt 0 ] || set -- commander@latest zod@latest vitest@latest
work=$(mktemp -d "${TMPDIR:-/tmp}/dependabot-resolve-XXXXXX") || exit 2
trap 'rm -rf "$work"' EXIT

failed=0
for dep in "$@"; do
rm -rf "$work/repo" "$work/store" "$work/cache"
mkdir "$work/repo"
cp "$repo/package.json" "$repo/pnpm-lock.yaml" "$repo/pnpm-workspace.yaml" "$work/repo/" || exit 2
if (cd "$work/repo" && "$pnpm" update "$dep" --lockfile-only \
--config.minimum-release-age=10080 \
--store-dir="$work/store" --cache-dir="$work/cache") >"$work/log" 2>&1; then
echo "ok $dep"
else
failed=$((failed + 1))
reason=$(grep -m1 -oE 'ERR_PNPM_[A-Z_]+.{0,160}' "$work/log" || tail -n 1 "$work/log")
echo "FAIL $dep: $reason"
fi
done
echo "dependabot-resolve: $(($# - failed)) of $# resolved"
[ "$failed" -eq 0 ]
9 changes: 8 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ updates:
# pnpm project (Dependabot detects pnpm from pnpm-lock.yaml and the
# packageManager field). The 7-day cooldown (zizmor's minimum) also exceeds
# pnpm-workspace.yaml's 1-day minimumReleaseAge, so version updates never
# propose a release pnpm would refuse to resolve.
# propose a release pnpm would refuse to resolve. Dependabot passes the
# cooldown to pnpm as its minimum release age, which pnpm checks against
# every locked package: a locked release younger than 7 days needs an
# exact-version minimumReleaseAgeExclude entry in pnpm-workspace.yaml.
# Dependabot also resolves on an empty store, where pnpm's trust check sees
# every locked package.
# .agents/skills/verify-agent-tty/scripts/dependabot-resolve.sh replays that
# resolve.
- package-ecosystem: npm
directory: /
schedule:
Expand Down
14 changes: 14 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
# resolver falls back to an older match), and reject versions whose publish
# trust evidence weakens between releases.
minimumReleaseAge: 1440
# Dependabot runs pnpm with its 7-day cooldown as the minimum release age, and
# pnpm applies that age to every locked package: while one locked release is
# younger than 7 days, every npm version update fails. Exclude only such
# exact versions, so newer releases of the same package stay behind both
# age checks.
minimumReleaseAgeExclude:
- '@coder/libghostty-vt-node@0.1.0-beta.7'
trustPolicy: no-downgrade

# Resolve optional platform dependencies for every platform devs and CI use,
Expand All @@ -27,3 +34,10 @@ trustPolicyExclude:
# CJS-only); octokit only publishes provenance attestations for the newer
# pure-ESM majors, so this exact version has no trust evidence to verify.
- '@octokit/endpoint@9.0.6'
# semver 5.7.2 (2023) is a backport release without provenance, published
# after 7.5.1 had it. release-please reaches it through
# conventional-changelog-writer > meow > read-pkg-up > read-pkg >
# normalize-package-data.
# A fresh resolve (Dependabot's `pnpm update` on an empty store) refuses it
# as a trust downgrade, and then every npm update fails.
- 'semver@5.7.2'
Loading