mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-01 22:45:02 +01:00
v1.92.18.0 fix(install): --project resolves to its git toplevel and refuses a repo slug (GST-743) (#3783)
* test(install): a --project repo slug is a usage error, not a project-less verdict (GST-743, failing first) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(install): --project refuses a value that is not a directory (GST-743) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (GST-743: key --project by its git toplevel, refuse a non-directory before cloning, ignore CDPATH) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (GST-743: --project resolves to its git toplevel for pins and the key; an unenterable directory is refused) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * changelog: GST-743 fragment names the subpackage-pin and admission-key behavior Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: capy-install names how --project resolves (GST-743) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
3f1741ddb4
commit
93d73bf755
7 files changed
+39
-5
No files matched your search
@@ -1,5 +1,9 @@
|
||||
# Changelog
|
||||
|
||||
## [1.92.18.0] - 2026-11-01
|
||||
|
||||
- `install.sh --project` (through `gstack-capy-install`) resolves the directory it names to its git toplevel, which is where pregate admission looks for the install verdict. `--project <repo>/<subdir>` now writes, and reads pins from, the same place as `--project <repo>`, so a Bun pin declared only in a subpackage no longer applies. A value that isn't a directory, such as a repo slug or a directory this shell can't enter, is a usage error that asks for the checkout's path, and it stops before anything is cloned or installed. Before this change, a slug or a subdirectory keyed the verdict somewhere admission never looks, so a later pregate admission check read a stale verdict (GST-743).
|
||||
|
||||
## [1.92.17.0] - 2026-11-01
|
||||
|
||||
- `gstack-review-dispatch pass` takes the readers' diff base from the merge base with `origin/<base>`, the same base the review plan scores and the targeted reader checks. Before, a local `<base>` branch that lagged `origin/<base>` gave every brief the stale merge base, so reviewers read upstream commits the branch only inherited (GST-716).
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# gstack digest v1.92.17.0 — regenerate/re-copy after upgrading gstack
|
||||
# gstack digest v1.92.18.0 — regenerate/re-copy after upgrading gstack
|
||||
|
||||
Behavioral rules from gstack (https://github.com/garrytan/gstack), compressed
|
||||
for agent hosts without a full skill install. The full skills add workflows,
|
||||
|
||||
@@ -70,6 +70,7 @@ while [ $# -gt 0 ]; do
|
||||
done
|
||||
[ -n "$FOR" ] && [ -n "$REQUIRE" ] && { echo "gstack-capy-install: --for and --require are exclusive" >&2; exit 2; }
|
||||
[ -z "$FOR" ] && [ -z "$REQUIRE" ] && REQUIRE="claude,codex,patch"
|
||||
[ -z "$PROJECT" ] || { _given=$PROJECT; PROJECT=$(CDPATH= cd -- "$_given" 2>/dev/null && { git rev-parse --show-toplevel 2>/dev/null || pwd -P; }) || { echo "gstack-capy-install: --project takes a directory path; '$_given' is not a directory (pass the project checkout's path, not a repo slug)" >&2; exit 2; }; }
|
||||
|
||||
say() { echo "gstack-capy-install: $*"; }
|
||||
stop() { # CODE MESSAGE FIX — print and exit 3 before ./setup
|
||||
@@ -148,7 +149,7 @@ STORE=$(gstack_bun_store "$GSTACK_STATE_ROOT")
|
||||
done
|
||||
INSTALL_VERSION=$(gstack_bun_install_version) || stop BUN_INSTALL_VERSION_INVALID "GSTACK_BUN_INSTALL_VERSION=$INSTALL_VERSION is not a verified Bun at or above gstack's supported minimum $GSTACK_BUN_TESTED (verified archives: $GSTACK_BUN_VERIFIED)" "unset GSTACK_BUN_INSTALL_VERSION, or set it to one of: $GSTACK_BUN_VERIFIED"
|
||||
[ -n "$PROJECT" ] || { PROJECT=$(cd "$ORIG_PWD" && git rev-parse --show-toplevel 2>/dev/null || true); [ "$(cd "${PROJECT:-/nonexistent}" 2>/dev/null && pwd -P)" = "$ROOT_REAL" ] && PROJECT=""; }
|
||||
PROJECT_REAL=""; [ -n "$PROJECT" ] && PROJECT_REAL=$(cd "$PROJECT" 2>/dev/null && pwd -P)
|
||||
PROJECT_REAL=""; [ -n "$PROJECT" ] && PROJECT_REAL=$(cd "$PROJECT" && pwd -P) && [ "$PROJECT_REAL" = "$ROOT_REAL" ] && PROJECT_REAL=""
|
||||
VERDICT=$(gstack_install_verdict_path "$GSTACK_STATE_ROOT" "$ROOT_REAL" "$PROJECT_REAL")
|
||||
REC_BUN="" REC_VER="" REC_RULE="" REC_BUN_INSTALL="" REC_FOR=""
|
||||
if [ -f "$VERDICT" ]; then
|
||||
|
||||
@@ -241,7 +241,12 @@ keeps the lease. `bin/gstack-lease list` shows `alive|dead|stale`, and
|
||||
clone too, through `GSTACK_CAPY_CLONED`).
|
||||
2. Preflight: `git`, `curl`, `node`, `jq`, then Bun. The project's pins
|
||||
(`--project <path>`, default the git toplevel of the current directory) are
|
||||
read with the doctor's own parser (`bin/gstack-runtime-pins.ts`: engines,
|
||||
read (a `--project` inside a repository resolves to that repository's git
|
||||
toplevel, so `--project <repo>/<subdir>` means `<repo>`; outside a repository
|
||||
it resolves to the directory's real path, and a value that is not a
|
||||
directory, such as a repo slug, exits 2 with a usage error before anything
|
||||
runs; the pins, the doctor and the install verdict all use the resolved
|
||||
directory) with the doctor's own parser (`bin/gstack-runtime-pins.ts`: engines,
|
||||
packageManager, `.tool-versions`, `.bun-version` and CI `bun-version:` lanes
|
||||
for this platform). CI exact pins for this platform are alternatives: a
|
||||
repository may test several Bun versions (gstack's own CI pins 1.4.2 and
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gstack",
|
||||
"version": "1.92.17",
|
||||
"version": "1.92.18",
|
||||
"description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
|
||||
@@ -156,6 +156,30 @@ describe('gstack-capy-install', () => {
|
||||
expect(run(f, ['--revision']).status).toBe(2);
|
||||
});
|
||||
|
||||
// Value: protects=--project names the project the verdict and launch file are keyed to;
|
||||
// fails_when=a repo slug (owner/name) that is no directory silently keys the verdict to no project, so a later check reads a stale one;
|
||||
// why_new=GST-743, HARN-12 lost three pregate runs to it; seam=bin/gstack-capy-install --project; no_claim=resolving slugs
|
||||
test('--project that is not a directory (a repo slug) is a usage error: exit 2, no setup, no verdict', () => {
|
||||
const f = fixture();
|
||||
const r = run(f, ['--for', 'ship', '--project', 'garrytan/harness-evals']);
|
||||
expect([r.status, r.stderr.trim()]).toEqual([2, "gstack-capy-install: --project takes a directory path; 'garrytan/harness-evals' is not a directory (pass the project checkout's path, not a repo slug)"]);
|
||||
expect(f.calls().filter(l => l.startsWith('setup') || l.startsWith('doctor '))).toEqual([]);
|
||||
expect(fs.existsSync(path.join(f.home, '.gstack-state/install-verdicts'))).toBe(false);
|
||||
});
|
||||
|
||||
// Value: protects=the installer keys the verdict by the project's git toplevel, the key pregate admission reads (lib/install-verdict.ts installProject);
|
||||
// fails_when=--project <repo>/<subdir> writes a verdict at the subdirectory's key, which admission never reads; seam=bin/gstack-capy-install --project
|
||||
test('--project names a subdirectory: the verdict is keyed by its git toplevel, the same file --project <toplevel> writes', () => {
|
||||
const f = fixture();
|
||||
const project = path.join(f.base, 'proj');
|
||||
fs.mkdirSync(path.join(project, 'packages/x'), { recursive: true });
|
||||
sh('git init -q', project);
|
||||
const verdictOf = (r: { stdout: string; status: number | null; stderr: string }) => { expect(r.status, r.stdout + r.stderr).toBe(0); return r.stdout.match(/GSTACK_INSTALL_VERDICT=(\S+)/)![1]!; };
|
||||
const sub = verdictOf(run(f, ['--for', 'autoplan', '--project', path.join(project, 'packages/x')]));
|
||||
expect(sub).toBe(verdictOf(run(f, ['--for', 'autoplan', '--project', project])));
|
||||
expect(JSON.parse(fs.readFileSync(sub, 'utf8')).project).toBe(fs.realpathSync(project));
|
||||
});
|
||||
|
||||
test('preflight: a missing tool stops with exit 3 and INSTALL_PREFLIGHT_FAILED before ./setup runs', () => {
|
||||
const f = fixture({ jq: false });
|
||||
const r = run(f);
|
||||
|
||||
Reference in new issue
Block a user