app
Pup - the AI's own browser
Public Made by Adomby adom
pup gives your AI a real browser on your desktop that it drives completely, in the background, signed in as you: windows that never jump in front of your work, one shared profile that learns your logins, and every window labeled on the taskbar with its AI thread's name.
master
John Lauer
promote.sh stamps 'Promoted to public on <date>' into the release notes (pup-bridge#87 item 2)
6738513
2mo ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
#!/usr/bin/env bash
# promote.sh — move an INSIDERS build to the PUBLIC tier, on a human's exact words.
#
# tools/promote.sh <version> "<the human's exact attestation words>" --by "<name>"
#
# pup-bridge#86 / ab 2.0.99 release tiers: the public manifest (adom-bridge-puppeteer-manifest.json,
# the updateManifestUrl every non-insider desktop follows) moves ONLY through this script, and this
# script REFUSES without an attestation. An AI passes the human's words through verbatim or does
# not promote — never on its own judgment. The words travel IN the public manifest
# (promotion_attestation / promoted_by / promoted_at).
#
# The bytes are ALREADY on the product page: tools/ship.sh uploaded the zip as release <ver> on
# adom/pup-bridge and archived it under dist/<ver>/ with the insiders manifest. Promote just
# re-points the public manifest at that same asset (sha re-checked) and pushes it. Source + skills
# pkg were pushed/published at ship time.
set -euo pipefail
VER="${1:?usage: tools/promote.sh <version> \"<attestation words>\" --by <name>}"
ATTEST="${2:-}"
shift 2 || true
BY="${ADOM_PROMOTED_BY:-}"
while [ $# -gt 0 ]; do case "$1" in --by) BY="$2"; shift 2;; *) shift;; esac; done
REPO="$(cd "$(dirname "$0")/.." && pwd)"; cd "$REPO"
PUBLIC="adom/pup-bridge"
ZIP="adom-bridge-puppeteer-v${VER}.zip"
ARCH="dist/${VER}"
echo "== 0. attestation gate =="
A="$(printf '%s' "$ATTEST" | tr -s '[:space:]' ' ' | sed 's/^ //;s/ $//')"
if [ "${#A}" -lt 8 ] || printf '%s' "$A" | grep -qiE '^(ok|yes|promote|ship it|go|approved|test|placeholder|x+)$'; then
echo "REFUSED: promoting to the PUBLIC tier needs the human's exact words (>= 8 chars, not a placeholder)."
echo " e.g. tools/promote.sh $VER \"John: $VER is good on all three of my boxes, ship it to everyone\" --by \"John Lauer\""
exit 2
fi
[ -n "$BY" ] || { echo "REFUSED: say who promoted (--by \"<name>\" or ADOM_PROMOTED_BY)."; exit 2; }
echo " attested by: $BY"
echo " words: \"$A\""
echo "== 1. the archived insiders build =="
[ -f "$ARCH/$ZIP" ] || { echo "MISSING $ARCH/$ZIP — ship $VER to insiders first (tools/ship.sh $VER ...)"; exit 1; }
[ -f "$ARCH/insiders-manifest.json" ] || { echo "MISSING $ARCH/insiders-manifest.json — the insiders record for $VER"; exit 1; }
SHA_LOCAL=$(python3 -c "import hashlib,sys;print(hashlib.sha256(open(sys.argv[1],'rb').read()).hexdigest())" "$ARCH/$ZIP")
SHA_INS=$(python3 -c "import json,sys;print(json.load(open(sys.argv[1]))['sha256'])" "$ARCH/insiders-manifest.json")
[ "$SHA_LOCAL" = "$SHA_INS" ] || { echo "SHA MISMATCH: archived zip $SHA_LOCAL vs insiders manifest $SHA_INS — refusing"; exit 1; }
URL=$(python3 -c "import json,sys;print(json.load(open(sys.argv[1]))['url'])" "$ARCH/insiders-manifest.json")
REMOTE=$(curl -sL "$URL" | python3 -c "import hashlib,sys;print(hashlib.sha256(sys.stdin.buffer.read()).hexdigest())")
[ "$REMOTE" = "$SHA_LOCAL" ] || { echo "REMOTE ASSET MISMATCH: $URL serves sha $REMOTE, archive is $SHA_LOCAL — refusing to point the public tier at it"; exit 1; }
echo " $ZIP sha256=$SHA_LOCAL matches the insiders record AND the served release asset"
echo "== 2. public manifest =="
python3 - "$VER" "$ARCH" "$A" "$BY" <<'PY'
import json, sys, datetime, os
ver, arch, words, by = sys.argv[1:5]
ins = json.load(open(os.path.join(arch, 'insiders-manifest.json')))
now = datetime.datetime.now(datetime.timezone.utc).isoformat().replace('+00:00', 'Z')
m = json.load(open('adom-bridge-puppeteer-manifest.json'))
m.update({'version': ver, 'url': ins['url'], 'sha256': ins['sha256'], 'size': ins['size'], 'released_at': now,
'insiders_released_at': ins.get('released_at'),
'promotion_attestation': words, 'promoted_by': by, 'promoted_at': now})
m.pop('tier', None)
for k in ('rollback_attestation', 'rolled_back_by', 'rolled_back_at'): m.pop(k, None)
json.dump(m, open('adom-bridge-puppeteer-manifest.json', 'w'), indent=2); open('adom-bridge-puppeteer-manifest.json', 'a').write('\n')
json.dump(m, open(os.path.join(arch, 'public-manifest.json'), 'w'), indent=2)
print(f" public manifest -> {ins['url']}\n archived {arch}/public-manifest.json")
PY
echo "== 3a. mark the insiders release-log entry promoted =="
python3 - "dist/insiders-repo/pup-bridge/README.md" "$VER" "$A" "$BY" <<'PY'
import sys, datetime, re, os
path, ver, words, by = sys.argv[1:5]
if os.path.exists(path):
s = open(path).read()
pat = re.compile(r"(- \*\*" + re.escape(ver) + r"\*\* insiders, [0-9-]+\.)")
if pat.search(s) and 'Promoted to public' not in pat.search(s).group(0):
s = pat.sub(lambda m: m.group(1) + f" Promoted to public on {datetime.date.today().isoformat()} by {by}: \"{words}\".", s, count=1)
# the insiders-tier-publish convention: the entry says "Not promoted." until this moment
line_start = s.find(f"- **{ver}**"); line_end = s.find("\n", line_start)
s = s[:line_start] + s[line_start:line_end].replace(" Not promoted.", "") + s[line_end:]
open(path, 'w').write(s); print(f" release log: {ver} marked promoted")
else: print(f" release log: no insiders entry for {ver} to mark (or already marked)")
PY
( cd dist/insiders-repo && adom-wiki repo push adom/insiders --files pup-bridge/README.md -m "pup-bridge ${VER}: promoted to public — ${BY}" >/dev/null 2>&1 ) || echo " (insiders release-log push failed; the public promote continues)"
echo "== 3b. stamp the release notes on the product page (pattern: 'Promoted to public on <date>') =="
NOTES=$(adom-wiki release view "$PUBLIC" "$VER" --json 2>/dev/null | python3 -c "import sys,json; raw=sys.stdin.read(); i=raw.find('{'); d=json.loads(raw[i:]) if i>=0 else {}; r=d.get('data') or d; r=r.get('release') or r; print((r.get('changelog') or '').strip())" 2>/dev/null || true)
case "$NOTES" in *"Promoted to public"*) echo " release notes already stamped";; *)
adom-wiki release edit "$PUBLIC" "$VER" --changelog "${NOTES:+$NOTES }Promoted to public on $(date -u +%Y-%m-%d)." >/dev/null 2>&1 && echo " release notes stamped" || echo " (release notes stamp failed; promote continues)";; esac
echo "== 3. push the public manifest =="
adom-wiki repo push "$PUBLIC" --files adom-bridge-puppeteer-manifest.json \
-m "v${VER}: promoted to PUBLIC — ${BY}: ${A}" >/dev/null 2>&1 || {
[ "${FORCE_PUSH:-0}" = "1" ] || { echo " PUSH FAILED (set FORCE_PUSH=1 to retry)"; exit 1; }
}
echo "== 4. DIFF-VERIFY =="
MAN=$(python3 -c "import json;print(json.load(open('adom-bridge-puppeteer-manifest.json'))['version'])")
LIVE=$(curl -s https://wiki.adom.inc/api/v1/pages/pup-bridge/files/adom-bridge-puppeteer-manifest.json | python3 -c "import json,sys;print(json.load(sys.stdin).get('version'))" 2>/dev/null || echo '?')
[ "$MAN" = "$VER" ] && echo "PROMOTED $VER to PUBLIC (attested by $BY); live public manifest reads $LIVE" || { echo "PUBLIC MANIFEST NOT AT $VER (got $MAN)"; exit 1; }