Commit Graph

98 Commits

Author SHA1 Message Date
09fc7288d5 art: a varied cast + warmer room (4.6.0)
Honest take on 'better character art': the standard LPC bodies in the kit
are nude bases (only pants, no shirt/hair-grid), so they're not an upgrade
over the complete clothed chibi sprites. Instead, added real variety:
- targeted recolor (preserves skin/hair, retints only armour/cloth) →
  guard-green/crimson/violet + host-rose/emerald sheets in public/scene2d/lpc
- NPCs now wear distinct colours; each visitor gets a stable distinct sprite
  derived from their id, so the tavern feels populated
- richer room: candlelit tables with mugs/plates, flickering wall torches
- fixed the stale preload (was preloading the removed painted hero)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 21:20:57 +08:00
3ba0c9c47e rpg: full-window 2x camera world + click-to-move + prominent bubbles (4.5.0)
Visual overhaul per user direction:
- canvas fills the whole window (under the topbar); render at 2x through a
  camera that follows the player across a bigger (28x18), more decorated
  hall (more tables/rugs/paintings/fireplace/shelves/props)
- click-to-move: click the floor and the avatar walks there (keyboard still
  works); click an adjacent NPC/fixture to interact
- prominent glowing interaction bubble above the nearest target + clickable
  bottom prompt
- names over every head (NPCs gold, visitors cyan, you teal) + drop-shadows
- serious value-prop + door CTAs overlaid on the game (it looks like a
  game, but stays a cloud agent tool)
- verified: full-window sizing, click-to-move, camera follow, the
  '✦ What is amerc?' bubble over the host

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 21:06:50 +08:00
9bc77fcc57 emotes + spawn memory (4.4.0)
- quick emotes: press 1-4 (or the side buttons) to pop 👋 ❤️   above
  your avatar ~2.4s; carried in the presence record so others see it
- the tavern remembers your last position (localStorage) and spawns you there
- verified across two browsers: A's wave appeared above A in B's view

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 16:13:58 +08:00
3b92827563 chat: player-to-player tavern chat (4.3.0)
- backend: in-memory ring buffer POST/GET /agents/tavern-chat
  {id,name,text}, last ~60, control-char sanitized
- RpgTavern: Enter/T (or 💬) opens a chat bar; your line floats as a
  canvas speech bubble above your avatar for ~5.5s AND lands in a small
  chat log; others' bubbles render above their avatars (keyed by presence
  id); typing freezes movement
- verified across two browsers: A's message appeared in B's log and as a
  bubble over A's avatar

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 15:43:08 +08:00
a22e5407ab world: distinct names, richer NPC dialog, reduced-motion (4.2.0)
- each logged-out player gets a random fantasy name (Bold Dwarf, Lucky
  Elf...) stored in localStorage; click the name badge to set your own
- NPC dialog is now multi-line, advanced with E/tap (the patrons have
  flavor to share); movement freezes while a dialog is open
- NPC idle bustle holds still under prefers-reduced-motion
- verified: random name badge, 3-line dwarf dialog advancing then closing

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 15:17:59 +08:00
84531acf55 online: multiplayer presence in the tavern (4.1.0)
- backend: in-memory public presence lobby — POST/GET /agents/presence
  (id,name,x,y,dir,frame,sheet; 6s TTL; POST returns other live players)
- RpgTavern: broadcast my position ~600ms, render other visitors'
  chibi avatars (smooth-interpolated) with name labels, depth-sorted;
  a '👥 N in the tavern' counter
- verified: two browsers each show the other's named avatar walking, both
  report 2 online

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 15:05:44 +08:00
b5283aba99 rpg: a playable top-down tavern replaces the static hero (4.0.0)
Per user pivot — the home is now an actual Pokemon-style 2D RPG, not a
static illustration. src/RpgTavern.jsx: canvas top-down tavern (LPC tiles
+ 64px chibi character sheets), a controllable player (arrows/WASD + an
on-screen dpad/A button on phones) with 4-dir walk animation and tile
collision, depth-sorted NPCs, and proximity interactions — walk up to the
barkeep (sign in / Legion), elf host (tour), roster board (Browse), banner
(Legion) or estate door (Mansion) and press E; patrons have flavor dialog.
Verified: movement, collision, prompt, and E->opens-feature all work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 14:54:55 +08:00
33d89c6b4a polish: reduced-motion guard + sign-in host greeter (3.3.0)
- prefers-reduced-motion stills the painted scene's float/flicker/bob
  loops (ptbob/flicker/pulse, gm-bub-float, solbob, life pulse, cursor
  blink, apb drop, villa twinkle/flicker/wave, scroll reveals)
- the elf host greets you with a face-cropped portrait on the sign-in gate

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 14:36:03 +08:00
39e87dfa6f pty: native web terminal replaces the relay iframe (3.2.0)
backend POST/GET /agents/instances/:id/input (keystroke queue, broker
long-polls, owner/accesskey only) + POST .../tui (broker frame push).
src/Pty.jsx PtyPanel: polls tui, ANSI-stripped terminal, sends keystrokes;
wired into soldier Terminal tab + UsePanel; dropped the relay iframe.
Verified end-to-end on prod via throwaway + simulated broker.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 14:23:56 +08:00
8c4729b4ea art: painted hero ambient + mobile (3.1.0)
- ambient life over the painted scene: flickering warm lantern glows +
  pulsing cool crystal/bar light (CSS, screen-blend, no JS)
- mobile: hide the tiny diegetic tabs/wood-bubbles, center the roster
  board, and add a clear Browse/Legion/Mansion tap-button row under the
  tagline so the tavern is usable on phones

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 14:05:17 +08:00
610b932140 art: painted tavern hero replaces the pixel tiles (3.0.0)
The home scene is now a layered hand-painted illustration — a clean
tavern backdrop with an elf host, orc bartender and dwarf patron cutouts
(the painted assets were already in assets/, just unused) — resized to
webp (258KB total, was ~5MB png). The diegetic UI sits on top: the roster
board with live stats, the barkeep sign-in bubble, the elf's tour bubble,
and Legion/Mansion side passages. Dropped the LPC canvas + tile preload.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 13:55:55 +08:00
8f00e7668a chat: render markdown inline (2.5.0)
Chat messages render markdown via marked (code blocks, lists, tables,
links) with a DOMParser-based sanitizer that strips script/style/iframe/
event-handlers and javascript:/data: URLs; links open in a new tab. The
agent owns its own links (netdisk, showcase, anywhere) as the user asked.
Verified: formatted agent reply renders, injected <script> stays inert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 13:41:46 +08:00
e4dba9d264 quartermaster: fold PM + company tools into one command post (2.4.0)
- new Quartermaster.jsx: the admin panel is now amerc's internal station —
  a command-post dashboard (live member/agent/online/session counts +
  quick links to git, docs, pm workspace, webagent, tavern) plus tabs for
  Tenants/keys/company (AdminConsole), Whiteboards, and Netdisk
- Scene2D #/admin renders Quartermaster (AdminConsole no longer imported
  directly); pm.amerc.ai stays as a standalone too
- verified locally: first signup=admin, all four tabs render

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 09:35:34 +08:00
6b83b661fa mansion: a moonlit villa estate (2.3.0)
My Mansion gets a CSS villa scene — dusk sky, glowing/flickering windows,
waving flag, garden hedge — with the live services (Showcase, File-mapper,
Net-disk) presented as 'chambers of the estate'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 09:30:06 +08:00
e308c9be4d legion: war camp — class banners + alive/fallen soldier instances (2.2.0)
- LegionDashboard 'war camp': each class is a pennant banner (click =
  detail dialog), each instance a soldier grouped under its banner —
  bobbing 🪖 when online, 🧍 pending, 💀 fallen when down
- SoldierDialog: command a soldier in an ornate dialog — chat with your
  own running agent (skills shown), a live terminal snapshot polled every
  5s (the heartbeat tui field), rouse instructions when down, stand-down
- legion auto-refreshes every 15s so statuses stay live
- verified locally: 2 banners, 3 soldiers, ON DUTY chat dialog

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 09:22:56 +08:00
374440a392 browse: the roster door — mercenaries descend with bubble briefs (2.1.0)
- AgentBrowse is a doorway: a glowing open-door graphic, then mercs
  descend (staggered drop animation) hanging on wooden sign-bubbles that
  show each agent's brief; portraits carry a live/offline dot + managed crest
- ClassModal rebuilt on the shared GameDialog (extracted to GameDialog.jsx
  to avoid a Scene2D<->AgentPlatform circular import); instances render as
  a squad — living soldiers (online) vs fallen (down)
- verified locally against a seeded backend (6 mercs, squad dialog)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 09:14:10 +08:00
a350ae6884 home: the tavern becomes the interface (2.0.0)
Full-screen diegetic game home — the page IS the tavern:
- grand glowing door = Browse Agents; bar/barkeep = sign-in (greets a
  logged-in user by name); wall banners = My Legion; villa side-exit =
  My Mansion; dancer pitches the tour in a holographic panel
- persistent clickable speech bubbles (wood / holo / door variants),
  hover quips on patrons, live stats on the wall screen
- GameDialog: ornate gem-cornered dialog frame; the tour (HomeFeatures)
  and login (THE LEDGER) open in-game instead of navigating away
- stage scales to fill the viewport (768x432 buffer, pixelated upscale)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 03:33:28 +08:00
511bd25aa0 mansion: file-mapper + net-disk rooms; 100MB quota; broker jobs (1.3.0)
- file_maps table + agent fm register/list/delete; public GET /fm/:iid/:name
  relays the download live through the broker (consumer-first rendezvous,
  60s window, zero server storage); broker long-polls /instances/:id/jobs
- netdisk: 100MB per-account quota enforced on upload + /files/usage meter
- Mansion: File-mapper and Net-disk are live rooms (usage bar, embedded
  Netdisk browser); Netdisk relay soon-room retired
- kebab's real instance is ONLINE and replied 'pong' over native chat —
  gate path proven; jobs protocol spec sent to kebab

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 03:12:56 +08:00
b4b5df91f0 legion: agent cards reused + class runtime properties (1.2.0)
- AgentCard extracted; Browse and My Legion render the identical card;
  Legion cards open the same ClassModal (instances + Use + chat)
- class properties: managed (amerc-managed, loads amerc skills),
  terminal_mode new|shared per session, skills_reload for shared
  terminals — publish form, API create/patch, badges in the modal
- kebab coordination: broker spec delivered via TerminalMan 155; kebab
  already heartbeats instance 2 with the skills array (status lost ->
  stabilizing); monitor armed for online

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 02:58:51 +08:00
2941f14583 chat: native ChatPanel + chatlog + file relay UI (1.1.0)
- src/Chat.jsx: long-poll chat panel — skills-loaded chips, file/image
  send with streaming progress bar, expiring download links for received
  files, per-session chatlog with resume; no iframe, no external relay
- UsePanel: chatbox tab now uses the native panel (web-pty still rides
  the relay for now); Legion gains a 'My chatlog' card
- verified END-TO-END IN PRODUCTION via throwaway account + live broker:
  browser sent, broker echoed, skills rendered, chatlog listed; 2MB file
  relayed through nginx md5-identical with no server caching; all test
  data purged after

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 02:51:22 +08:00
c2a8616255 legion: rename My Booth -> My Legion, Mansion -> My Mansion (1.0.0)
Route 'legion' with a legacy '#/booth' alias; BoothDashboard -> LegionDashboard;
nav, footer, hotspots, WebMCP enum, gate copy all renamed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 02:33:41 +08:00
80d7140d1f booth: label every field in the publish form (0.99.0)
audited the Booth as a new publisher: the onboarding is good, but the publish
form was placeholder-only — and Kind (codex) + Launch command (codex --yolo)
come pre-filled, so their placeholders never show, leaving those two technical
fields with no visible label.

- added a persistent label above every field (Class name, Tags, Description,
  Kind, Visibility, Launch command) + clearer example placeholders
- a one-line hint explains the two technical fields
- verified live (throwaway account, cleaned up): all six labels render, form
  reads cleanly
- changelog entry (0.99) added with the bump
2026-06-10 15:19:04 +08:00
9c1aa73742 home: turn the API peek into a live console (0.98.0)
the agent-native callout's API peek showed a curl line + the JSON, but felt
static. made it feel like a real API client:

- after each call it shows the response status and timing (green dot, '200 OK
  · 47 ms') measured with performance.now() — the visitor's actual request time
- a '↻ run' button re-fetches the current endpoint (running… -> new status)
- endpoint tabs still switch (stats / roster / activity), all read-only & no-auth
- verified live: status '200 OK · 683 ms', run re-fetches (running… -> 200 OK),
  green dot on success
- changelog entry (0.98) added with the bump
2026-06-10 15:08:26 +08:00
d05a5b110c auth: clearer sign-in copy on the conversion gate (0.97.0)
the join form used confusing labels at the exact moment a visitor commits:
- the email field was labelled 'Guild handle email' (it is just an email)
- the password field was 'Access sigil'
- the login button was 'Enter Booth' (logging in does not go to the Booth)
- the card eyebrow was 'OPEN BOOTH' (publisher-biased; you might sign in to browse)

now: Email / Password, a clear 'Log in' button, and a neutral 'ONE ACCOUNT'
eyebrow that reinforces the single sign-on. theme stays in the heading
('Join the tavern', 'Welcome, mercenary') and the benefit points.

verified live: login shows Email/Password -> Log in; signup shows
Email/Display name/Password -> Create Account.
2026-06-10 15:01:44 +08:00
0775b79a1b home: fit the hero value prop above the fold (0.96.0)
on common laptops (1366x768, 1280x720, 1440x900) the tavern canvas reserved
only 210px for the topbar + caption, so the tagline + CTAs landed at the very
bottom edge and the live stats sat ~40px BELOW the fold — a visitor had to
scroll to see the value prop and the action buttons.

- reserve 290px instead of 210, so the canvas is sized to leave room for the
  full caption; the tavern is still the large, vivid centrepiece (478px tall
  at 768, down from 558)
- desktop-only: the canvas is width-capped (94vw) on phones, so mobile is
  untouched
- verified across all three laptop sizes: CTA ~80px clearance, stats ~40px
  clearance (was 40px below the fold)
- added the matching changelog entry (0.96) alongside the bump
2026-06-10 14:43:19 +08:00
22c7e4209f changelog: catch up to the version badge (0.95.0)
the in-app CHANGELOG array stopped at v0.89 while the badge (which links to it)
read v0.94 — five shipped versions missing: linkable agents, mobile docs nav,
the live API peek, full-text docs search, and the key 'try it' curl.

- added entries 0.90-0.95 so the changelog's newest version matches RELEASE
- verified live: badge v0.95, changelog tops out at v0.95 (37 entries)

(also saved a project note to add a CHANGELOG entry alongside each version bump —
this has now drifted 5 versions behind twice.)
2026-06-10 14:31:29 +08:00
63b1087042 account: show a runnable curl when you mint a key (0.94.0)
minting an agent key showed the key once with no hint of what to do with it —
you had to go dig through the docs to make your first call. great API products
hand you a working example right there.

- after minting, show a ready-to-run curl with YOUR key inlined, hitting a real
  read-only endpoint (GET /agents/classes), plus a one-click copy and a link to
  the API reference
- completes the get-key -> call-the-API loop and reinforces the agent-native pitch
- verified live (throwaway account, cleaned up after): the curl renders with the
  real minted key, copy button + api-reference link present
2026-06-10 14:16:26 +08:00
66ccd54d21 docs: full-text search with snippets + peek a11y (0.93.0)
the docs search only matched titles/folders, so searching a term that lives in
a doc's body (e.g. 'heartbeat') returned nothing — you had to already know
which doc to open.

- search now matches title AND body across all docs; results show the title
  plus a context snippet with the query highlighted (<mark>)
- doc bodies are fetched once on first search and cached (invalidated when the
  doc list changes); in-flight searches cancel on a new query
- clicking a result opens the doc (and updates the URL); clearing returns the
  folder tree
- a11y: the homepage API peek used role=tablist/tab without tabpanels (an
  incomplete ARIA pattern) — switched to a labeled button group with aria-pressed
- verified live: 'heartbeat' -> 3 body matches with highlighted snippets,
  click opens Connect-your-broker, clear restores the tree
2026-06-10 14:08:19 +08:00
ce9d2336f7 home: live API peek in the agent-native callout (0.92.0)
the callout claimed 'drive the whole platform over JSON' but only said it.
now it shows it: a compact terminal with tabs for the public read-only
endpoints (stats / roster / activity) that fetches the LIVE response and
pretty-prints it with JSON syntax highlighting.

- proves the agent-native differentiator with real data, not a mockup
- read-only public endpoints, no auth; switching tabs updates the curl line
  and refetches; cancels in-flight on unmount
- small self-contained jsonHl() highlighter (keys/strings/numbers/bools),
  output escaped before highlighting so it's injection-safe
- verified live: stats shows {classes:1,online:1,...}, roster shows
  Kebab Webagent, 9 key + 7 number spans highlighted, tabs refetch
2026-06-10 13:44:25 +08:00
e5e79d75aa docs: collapsible doc nav on mobile (0.91.0)
a mobile audit (no overflow anywhere; agent modal + on-this-page TOC both fine)
turned up one weak spot: on phones the doc tree was a cramped 210px scroll area
pinned above every page, and it never scrolled the active doc into view — so
you couldn't tell which doc you were reading or reach half of them easily.

- the sidebar now collapses to a compact bar showing the CURRENT doc + a
  chevron; tap to reveal the full tree (active doc highlighted), tap a doc to
  navigate and auto-collapse
- desktop is byte-for-byte unchanged: the collapsible wrapper is display:contents
  off-mobile, so the tree stays a normal flex child (sidebar still 280px)
- verified live: mobile collapsed shows 'API reference', expands to 8 docs,
  selecting Quickstart navigates + collapses + relabels; desktop toggle hidden,
  tree intact
2026-06-10 13:35:07 +08:00
0fd1ed2b5c agents: shareable per-agent URLs (0.90.0)
opening an agent only lived in component state, so you couldn't link to one,
and a refresh dropped the open agent — inconsistent with the now-shareable
docs. each agent modal now has a URL: amerc.ai/#/agents/<slug>.

- the hash router keys off the first path segment, so #/agents/<slug> still
  routes to Browse while exposing the slug as a sub-path (backward compatible)
- opening a card pushes #/agents/<slug>; loading that URL opens the modal;
  closing returns to #/agents; browser back/forward open & close it
- verified live: click updates URL + opens, Escape closes to #/agents, a fresh
  deep-link opens 'Kebab Webagent', back closes

also recorded a project memory: sandbox->amerc network path is slow (~0.65s
TLS) but the server is fast (~13ms loopback) — don't trust sandbox-measured
latency or Lighthouse-from-sandbox as the real user experience.
2026-06-10 13:23:35 +08:00
cd9c7f7e8c changelog: bring the trail up to date (0.89.0)
the changelog page stopped at v0.51 while the site shipped to v0.88 — so the
version badge (which links to the changelog) advertised ~37 versions that the
'trail' never showed, directly undercutting its 'ships continuously' line.

reconstructed the real history from git and added 17 curated milestones
(0.54 -> 0.89): the agent-native/WebMCP work, the accessibility & caching
sweeps, instant paint, the OG share card, docs routing + section nav, the
error boundary, mobile nav, lean build, and more.

- verified live: 31 entries, newest v0.89, matches the v0.89 badge
2026-06-10 13:02:57 +08:00
0e3c567c97 docs: on-this-page TOC + section deep links + heading anchors (0.88.0)
builds on per-doc routing: long docs (API reference has 6 sections, Roadmap 4)
are now navigable and section-shareable.

- each h2/h3 gets a slug id + a hover '#' anchor; URL form is
  #/<doc-slug>/<section-slug> (e.g. #/api-reference/keys-self-service)
- an 'On this page' TOC renders for docs with >=3 headings; click or deep-link
  scrolls to the section; browser back/forward still work
- decorations (anchors, ids, code copy buttons, syntax highlighting) are now
  baked into the memoized HTML string instead of mutated in post-render DOM

  WHY: the post-render mutation approach was being wiped. setToc() inside the
  decorate effect triggered a re-render that re-applied dangerouslySetInnerHTML,
  resetting the article's children and dropping every decoration, with the
  effect never re-running (deps unchanged). Doing it at the string level makes
  the markup self-contained and immune to re-injection. Copy buttons use event
  delegation; anchors are real links (work without JS).

- verified live: 6/6 heading ids + anchors on API reference, TOC navigates,
  3 copy buttons + highlighting on Connect-your-broker, deep-links land and
  scroll to the section, TOC hidden on short docs
2026-06-10 12:50:31 +08:00
60d045b55f docs: shareable URLs per document (0.87.0)
the docs site kept the selected document only in React state, so you couldn't
bookmark, share, or refresh-into a specific doc, and browser back/forward did
nothing — a real gap for a developer docs site people want to link into.

- each doc now has a slug URL: docs.amerc.ai/#/connect-your-broker
- selecting a doc pushes the slug to the URL (history.pushState)
- loading a #/<slug> URL lands directly on that doc; unknown/empty falls back
  to Quickstart as before
- hashchange + popstate listeners make browser back/forward switch docs
- the browser tab title now reflects the open doc (<title> · Docs · amerc)
- verified live on docs.amerc.ai: click updates URL+view+title, deep-links
  land correctly, back/forward navigate between docs
2026-06-10 12:22:10 +08:00
f0c8ea22cf share: purpose-built Open Graph card (0.86.0)
sharing amerc.ai in Slack/Discord/X/etc. showed a raw pixel-art tavern
screenshot — distinctive but cluttered at thumbnail size and missing the
wordmark and tagline. replaced it with a designed 1200x630 OG card:
gem + 'amerc' wordmark, the 'Hire agents like mercenaries.' tagline, a
one-line description, amerc.ai, and the three delivery modes — on the
brand's dark/cyan/gold palette over a deeply dimmed tavern backdrop.

- rendered headless at 1200x630 (Page.captureScreenshot, jpeg q88, 58KB)
- point og:image + twitter:image at /og-card.jpg, fix width/height to 1200x630
- verified live: meta tags resolve, image serves 200 image/jpeg
2026-06-10 12:16:41 +08:00
5e0eeb79c6 perf: paint branded loading screen from static HTML (0.85.0)
the <div id=root> was empty until the JS bundle downloaded and React mounted,
so the page was blank for ~2.4s (FCP). put the branded loading screen (pulsing
gem + 'amerc') directly in the static HTML, with its critical CSS inlined in
<head>, so it paints as soon as the CSS loads instead of waiting for JS.

- React's createRoot replaces #root on mount; the Suspense fallback renders the
  identical markup, so the static->React handoff is seamless (no flicker)
- inlined .app-loading critical CSS mirrors styles.css exactly + dark body bg
  so there's no white flash during load
- verified live: FCP 2.4s -> 1.4s, performance 86 -> 90, TBT 50 -> 0ms;
  app mounts cleanly, static loader replaced, 0 console errors
2026-06-10 12:09:50 +08:00
522ce6ec83 quality: fix heading order + asset caching (0.84.0)
measured the LIVE site with Lighthouse (best-practices 100, seo 100,
agentic-browsing 100; a11y 98, perf 86) and fixed two real flags:
- heading-order: the footer column labels were <h5> following an <h3>
  (skipping h4) — changed to <h4> so the page heading order is sequential;
  a11y 98 -> 100
- caching: every static asset was served with no cache lifetime (0s).
  added nginx cache locations on the amerc.ai vhost (server-side, not in repo):
  /assets/ -> 1y immutable (content-hashed chunks), /scene2d/ -> 30d;
  index.html stays uncached so it always points at the latest assets.
  repeat visitors now serve JS/CSS/images from cache. cache-insight -> PASS
- verified live: a11y 100, heading-order + cache-insight PASS, cache headers
  present on assets and absent on index.html
2026-06-10 12:02:06 +08:00
40624a2e30 home: agent-native callout (0.83.0)
- amerc is genuinely agent-native now (JSON API + self-service keys + WebMCP
  browser tools + llms.txt) but the home page never said so
- add a concise callout after the session preview: 'Agent-native by design —
  mint an API key and drive it over JSON, get callable WebMCP tools on the
  page, read llms.txt for the map. Agents can hire agents.'
- a real, differentiating positioning point, not filler; cyan-accented card,
  scroll-reveal, links to /llms.txt, stacks on mobile
- verified live: callout renders and reveals
2026-06-10 11:52:44 +08:00
c5fb9631c5 agent docs: surface WebMCP tools (0.82.0)
- llms.txt: add a 'Browser tools (WebMCP)' section listing the four callable
  tools (amerc_browse_agents / platform_stats / get_agent / open) so agents
  reading the file know they can act on the tavern, not just read about it
- footer: add a 'For agents ↗' link to /llms.txt so humans can discover
  amerc's agent-facing guide (keys, JSON API, WebMCP)
- verified live: llms.txt WebMCP section served, footer link in the bundle
2026-06-10 11:47:38 +08:00
b94ebb0962 WebMCP: make amerc agent-actionable as callable tools (0.81.0)
amerc is the agent mercenary tavern — so expose it to AI agents browsing the
page via Web Model Context Protocol (navigator.modelContext), the W3C browser
tool API. An agent on amerc.ai can now act on tools instead of scraping the DOM:
- amerc_browse_agents (query/tag) — list the roster
- amerc_platform_stats — live classes/online/sessions
- amerc_get_agent (id) — full class details + instances
- amerc_open (section) — navigate the tavern
- each has a valid JSON-Schema inputSchema; read tools carry readOnlyHint
- registered only on the main domain, feature-detected ('modelContext' in
  navigator) + try/catch, so it no-ops with zero risk where unsupported
- verified (polyfilled modelContext): all 4 tools register with valid schemas
  and their execute() calls hit the live API correctly
refs: W3C webmcp proposal, webfuse WebMCP cheat sheet
2026-06-10 11:43:24 +08:00
7cf9293bab agent-ready: llms.txt + charset — agentic-browsing 67->100 (0.80.0)
ran full Lighthouse: perf 97, a11y 100, best-practices 92->96, SEO 100,
and the new agentic-browsing category 67->100. amerc is for agents, so this
category matters most — its only fail was a missing llms.txt.
- add /llms.txt (llmstxt.org format): an agent-facing index of amerc — the
  class/instance/session model, the JSON API (base, auth, key endpoints),
  links to docs + source, and a 'for agents' note. genuinely on-brand for
  the agent mercenary tavern and useful for agents driving amerc via API
- add <meta charset=utf-8> as the first head element (was missing)
- re-ran Lighthouse: agentic-browsing 100, charset + llms-txt PASS
- verified live: /llms.txt 200 text/plain
2026-06-10 11:36:10 +08:00
c5e16205c5 a11y: fix Lighthouse-flagged issues — accessibility 93->100 (0.79.0)
ran Lighthouse (local preview): SEO 100, a11y 93->100, best-practices 92
(its one fail was console errors from the backend-less preview — a false
positive; live has 0 console errors). fixed the 3 real a11y flags:
- color-contrast: '.gm-scrollcue' was 4.33:1 (needs 4.5) — lightened the
  'how it works' cue colour and dropped the opacity dimming
- label-in-name: the logo button's aria-label='amerc home' didn't contain its
  visible text — removed it so the accessible name = visible text (+ title=Home)
- skip-link: the href='#content' had no target — gave the content host
  id='content' + tabindex=-1 so it's a valid focusable target
- re-ran Lighthouse: accessibility 100, all three audits pass
2026-06-10 11:31:00 +08:00
dbe3c383e3 branded app loading screen (0.78.0)
- the Suspense fallback (shown on every cold load while the app chunk loads,
  longer on slow/mobile connections) was a plain monospace 'Loading amerc…'
- replace with a branded screen: a pulsing cyan gem over 'amerc' in gold
  Georgia on a dark radial background, matching the logo + error-boundary look
- respects prefers-reduced-motion
- also audited the public mobile surfaces (agent modal, status, changelog) —
  all mobile-safe (modal is width:min(640px,96vw) + scroll)
- verified the loading screen renders (blocked the app chunk to capture it)
2026-06-10 11:20:37 +08:00
f063e9ae80 docs: responsive mobile layout (0.77.0)
- on phones the docs kept the desktop sidebar+content row, squeezing the prose
  into ~240px (sidebar ate the rest) — poor reading on a public docs surface
- stack on mobile (<=760px): sidebar becomes a compact scrollable doc-picker
  on top (max 210px), content goes full-width below with comfortable padding
- verified live (390px): layout column, content full-width (390 vs old 240),
  no horizontal overflow
2026-06-10 11:14:46 +08:00
1e387c270c docs: land on Quickstart instead of an empty pane (0.76.0)
- visiting docs.amerc.ai showed a blank 'Select or create a document' main
  area — a poor first impression for the public docs/onboarding surface
- auto-select a sensible default on load (Quickstart -> a 'start here' doc ->
  first doc) without overriding a user's later selection
- verified live: docs.amerc.ai lands on Quickstart, sidebar highlights it
2026-06-10 11:09:09 +08:00
9636545fb7 a11y/ux: modals close on Escape (0.75.0)
- the agent ClassModal and the booth 'instance created' modal could only be
  dismissed by clicking the backdrop or the X — no Escape, a standard
  keyboard/UX expectation
- add a keydown(Escape) -> close to both (ClassModal listens while mounted;
  the booth modal attaches the listener only while newInst is set)
- verified live: agent modal opens then closes on Escape
2026-06-10 11:05:16 +08:00
8542a98500 deps: drop lucide-react, inline the 2 icons (0.74.0)
- lucide-react was a runtime dependency used only for the mobile menu's
  hamburger + close icons in Scene2D.jsx
- replaced with two tiny inline SVG components (lucide's exact Menu/X paths),
  removed lucide-react from package.json — aligns with the project's
  minimal-dependency philosophy (zero-dep backend)
- build is clean with no lucide in the bundle; icons render identically
- (deploy note: re-deployed after a transient fail2ban block from this
  session's rapid deploy cadence — site stayed healthy on 0.73 throughout)
2026-06-10 10:58:49 +08:00
d9d652dfd5 browse: correct no-search-results state (0.73.0)
- searching (or tag-filtering) with no matches wrongly showed the 'No agents
  here yet — be the first' onboarding, implying the whole marketplace was
  empty even when agents exist
- now distinguishes: a query/tag with no matches shows 'No mercenaries match
  <term>' + a Clear search button; the be-the-first onboarding only shows when
  the roster is genuinely empty (no query, no tag)
- verified live: 'zzznomatch' shows the no-match state, Clear restores results
2026-06-10 10:41:03 +08:00
0f9d553deb a11y: skip-to-content link (0.72.0)
- keyboard/screen-reader users had to tab through the whole topbar before
  reaching page content (WCAG 2.4.1 Bypass Blocks gap)
- add a skip link as the first focusable element: hidden until focused, slides
  in as a cyan pill, and on activation focuses the visible content container
  (works with the persistent-home structure, and avoids the hash-route conflict
  by focusing programmatically instead of via href)
- verified live: Tab focuses it, it becomes visible, activation focuses content
2026-06-10 10:30:16 +08:00
696d727e44 dynamic per-route + per-subdomain document titles (0.71.0)
- the SPA had one static title, so every tavern route and the docs/pm
  subdomains all read 'amerc — hire agents like mercenaries' in the tab
- tavern now sets a descriptive title per route (Browse Agents · amerc,
  System status · amerc, etc.); docs/pm set 'Docs · amerc' / 'PM · amerc'
- clearer browser tabs, bookmarks and history
- verified live across home/agents/status + docs + pm
2026-06-10 09:36:44 +08:00