← Commit history

Publish 0.19.7

Colby Knox ·c965dc80ac ·2mo ago ·parent 32fba40
3 files changed +33−4
package.json+1−1
@@ -2,7 +2,7 @@   "slug": "hero-studio",   "title": "Hero Studio",   "type": "app",-  "version": "0.19.6",+  "version": "0.19.7",   "description": "The hero-image lab with a human gate: `hero-studio pose <owner/slug>` opens the studio in front of the human, posed for their package, and blocks until they click Generate, producing the provenance-stamped 2000x1250 PNG the registry's hero gate requires. The image carries the title and artwork; the exported image also bakes the type pill (top right) and full wiki slug (bottom right); the page shows the hero bare, and only the homepage marquee overlays its own dynamic info. Adom-org pages get the house wordmark and palette automatically; every other owner brings their own accent and background colors, with placement fixed for all. The floating app window is the vitrine: it auto-loads a real screenshot from the package's wiki page (screenshots/, docs/), takes a manual import, or a full-hero import (the human-ratified re-stamp path for existing heroes). The pose gate opens in verification mode: per-item checklist (title, subtitle, vitrine, type match) and a Generate that unlocks only fully confirmed. Includes vitrine bleeds, brand tile themes, gradient angles, pixel-faithful wiki marquee and index-card previews, and a component-hero mode with a photo/raytrace/phong fallback ladder.",   "license": "MIT",   "tags": [
page.json+1−1
@@ -2,7 +2,7 @@   "slug": "hero-studio",   "title": "Hero Studio",   "type": "app",-  "version": "0.19.6",+  "version": "0.19.7",   "description": "The hero-image lab with a human gate: `hero-studio pose <owner/slug>` opens the studio in front of the human, posed for their package, and blocks until they click Generate, producing the provenance-stamped 2000x1250 PNG the registry's hero gate requires. The image carries the title and artwork; the exported image also bakes the type pill (top right) and full wiki slug (bottom right); the page shows the hero bare, and only the homepage marquee overlays its own dynamic info. Adom-org pages get the house wordmark and palette automatically; every other owner brings their own accent and background colors, with placement fixed for all. The floating app window is the vitrine: it auto-loads a real screenshot from the package's wiki page (screenshots/, docs/), takes a manual import, or a full-hero import (the human-ratified re-stamp path for existing heroes). The pose gate opens in verification mode: per-item checklist (title, subtitle, vitrine, type match) and a Generate that unlocks only fully confirmed. Includes vitrine bleeds, brand tile themes, gradient angles, pixel-faithful wiki marquee and index-card previews, and a component-hero mode with a photo/raytrace/phong fallback ladder.",   "license": "MIT",   "tags": [
server.js+31−2
@@ -310,11 +310,40 @@ function resolvedText() { // count feeds the pre-ticked checklist). Container-local v1; per-account // needs wiki identity (backend ask filed separately). const GATES_FILE = path.join(INSTANCES_DIR, 'gates.json');-function readGates() {+function readLocalGates() {   try { return JSON.parse(fs.readFileSync(GATES_FILE, 'utf8')).count || 0; } catch { return 0; } } function bumpGates() {-  try { fs.writeFileSync(GATES_FILE, JSON.stringify({ count: readGates() + 1, updated: new Date().toISOString() })); } catch {}+  try { fs.writeFileSync(GATES_FILE, JSON.stringify({ count: readLocalGates() + 1, updated: new Date().toISOString() })); } catch {}+  fetchRemoteGates(); // a fresh gate may tip the account over the threshold+}+// Per-ACCOUNT gate count from the wiki (their GET /api/users/:handle/+// hero-gates, derived server-side from studio-stamped heroes by author):+// stable across machines. The local file counts this container's gates the+// wiki cannot see yet (a gated hero not yet published); max() of the two is+// the honest number. Absent endpoint (pre-deploy) = local only.+let remoteGates = null;+async function fetchRemoteGates() {+  try {+    const REG = process.env.ADOM_WIKI_REGISTRY || 'https://wiki.adom.inc';+    const headers = {};+    try { headers.Authorization = 'Bearer ' + fs.readFileSync('/var/run/adom/api-key', 'utf8').trim(); } catch {}+    const who = await fetch(REG + '/api/me', { headers }).then((r) => (r.ok ? r.json() : null)).catch(() => null);+    const handle = who && (who.name || who.handle || (who.user && (who.user.name || who.user.handle)));+    if (!handle) return;+    const r = await fetch(REG + '/api/users/' + handle + '/hero-gates', { headers });+    if (!r.ok) return;+    const d = await r.json();+    if (typeof d.hero_gates === 'number') {+      remoteGates = { count: d.hero_gates, seasoned: !!d.seasoned, handle };+      logLine('info', 'account gate count: ' + d.hero_gates + ' (' + handle + ', seasoned=' + d.seasoned + ')');+      stateRev += 1;+    }+  } catch {}+}+fetchRemoteGates();+function readGates() {+  return Math.max(readLocalGates(), remoteGates ? remoteGates.count : 0); }  // Live wiki re-fetch for a page row, shared by /refresh-page, the dropdown,