298 Commits

Author SHA1 Message Date
will.anderson 46f4be83fd ci: add sudo to apt-get (runner is non-root) 2026-05-05 09:13:18 -05:00
will.anderson aa6c354d58 ci: fix elc link flags (libcurl install + gcc ordering) 2026-05-05 09:09:55 -05:00
will.anderson 14cae0dcb5 ci: compile elc.c from El repo source for linux/amd64 support
The El repo only has a darwin arm64 elc binary. The v1.2.1 linux
binary predates native HTML template syntax. Compile elc.c (the
committed C source of the El compiler) on linux/amd64 in CI to
get a native binary that supports the new syntax.
2026-05-05 09:07:45 -05:00
will.anderson 62f0fc054f ci: clone El repo for native HTML template support
v1.2.1 elc (282KB) cannot compile native HTML template syntax
introduced in feat/native-el-templates. Clone El repo depth=1
to get the latest elc (486KB) that supports it. Set EL_HOME
to lang/ subdir.
2026-05-05 06:45:07 -05:00
will.anderson 6cfd6e4b56 feat: native El HTML templates — remove all HTML string literals
Converts all El source files in src/ from HTML string literals to native
El template syntax. Part of the el rewrite tracked in PR #4.
2026-05-05 11:11:04 +00:00
will.anderson 28c47c11c9 ci: fix EL_HOME to use lang/ subdirectory for El repo clone
El repo is organized under lang/ — runtime and dist/platform binaries
are at lang/el-compiler/runtime/ and lang/dist/platform/, not at root.
Setting EL_HOME=$DEST/lang makes RUNTIME_SRC resolve correctly so
build-stage.sh can cp el_runtime.{c,h,js} from the right location.
2026-05-05 11:01:47 +00:00
will.anderson 9d264cb506 ci: download el_runtime.js from El SDK v1.2.1 release 2026-05-05 10:49:56 +00:00
Will Anderson 5cb13d67f7 feat: convert web El source to native HTML template syntax
Replace all return "..." HTML string literals with native El templates —
removes all \" escapes, converts + interpolations to {expr}/{raw(expr)},
and replaces conditional string concatenation with {#if}/{#else}/{/if}.
No functional changes; output is identical.
2026-05-05 05:21:19 -05:00
will.anderson 1127dcd278 fix(ci): download El SDK from release assets instead of cloning repo 2026-05-05 09:52:51 +00:00
will.anderson 7c8bf444ca fix(ci): ensure dist/platform dir exists before elc download 2026-05-05 09:49:20 +00:00
Will Anderson 8a8762ad4f ci: trigger stage CI after API merge 2026-05-05 04:46:30 -05:00
Will Anderson a936d2ebb7 ci: trigger stage build after API merge 2026-05-05 04:45:07 -05:00
will.anderson c49a838aad Merge pull request 'promote: dev → stage' (#2) from dev into stage
promote: dev to stage
2026-05-05 09:40:51 +00:00
will.anderson 7e72bdd083 Merge pull request 'fix: gallery layout, OTP auth, account sign-up, rate limiting, Google Ads, web demo key' (#1) from fix/gallery-layout-account-otp into dev
fix: gallery layout, OTP auth, rate limiting, Google Ads, web demo key
2026-05-05 09:37:46 +00:00
Will Anderson 70820cf078 feat(chat): IP-keyed daily rate limit (10/day), live reset countdown, web_demo Anthropic key 2026-05-05 04:10:22 -05:00
Will Anderson 9b69783306 Ignore all emitted HTML files via wildcard 2026-05-05 03:52:56 -05:00
Will Anderson 7a3dc94dec Ignore .elh emitted files 2026-05-05 03:52:11 -05:00
Will Anderson 260ea4edaa Remove letter.html 2026-05-05 03:51:30 -05:00
Will Anderson 566cd568b7 Add Google Ads conversion tracking (AW-18140150015) 2026-05-05 03:49:14 -05:00
Will Anderson 94f6e749a0 Add El source files for all client-side JS
Recovers original JS from git history and ports it into proper El source
files under src/js/. Each file wraps the original JS in a native_js call
inside a main() function, making it valid El that compiles to a
self-contained IIFE via elc --target=js --bundle.

Files added:
  src/js/account-auth.el       - Supabase OTP magic-link (sendMagicLink)
  src/js/account-dashboard.el  - Account dashboard: session, plan card, family
  src/js/chat-widget.el        - Demo chat widget (neuronDemoToggle/Send/Reset)
  src/js/checkout-auth.el      - Checkout auth: OAuth, email sign-in/up
  src/js/checkout-free.el      - Free plan: auth-badge watch -> payment reveal
  src/js/checkout-stripe.el    - Stripe Payment Element (reads NEURON_CFG)
  src/js/enterprise.el         - Enterprise inquiry form + headcount filter
  src/js/environmental.el      - Efficiency calculator slider
  src/js/gallery.el            - Gallery nav, search/sort, Supabase voting
  src/js/main.el               - Share page voting + copyForPlatform
  src/js/marketplace.el        - Developer interest form
  src/js/nav.el                - Nav hamburger + Mission dropdown
  src/js/styles.el             - Landing: nav scroll, reveal, founding counter
2026-05-04 11:23:21 -05:00
Will Anderson 246a5f0967 Fix gallery HTML structure bug and replace email auth with OTP flow
Gallery: remove <a> from share allowlist. Gallery cards wrap content in
<a class="gal-link">; allowing <a> in sanitized answer HTML causes nested
anchors that the HTML5 adoption agency algorithm resolves by restructuring
the DOM, producing mismatched </div> tags that leave gallery-grid open and
pull sibling elements into the grid as spurious grid columns.

Account: replace email+password sign-up/sign-in with magic-link OTP.
supabase.auth.signInWithOtp handles both new and existing users in one
flow. Existing onAuthStateChange listener (dadeb8ddb9a8.js) retained for
post-redirect dashboard display. sendMagicLink added to extract-js
RESERVED_GLOBALS so the obfuscator does not mangle the onclick reference.
2026-05-04 10:04:22 -05:00
will.anderson 6075f49e8a Merge pull request 'feat(account): email/password sign-up on account page' (#2) from dev into stage
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 2m47s
2026-05-04 14:05:04 +00:00
Will Anderson 0e51225564 ci: trigger dev smoke test on any workflow file change
Dev — Build & local smoke test / build-smoke (push) Successful in 2m50s
2026-05-04 09:01:25 -05:00
Will Anderson 23ba7b8ec5 ci: enforce branch protection + source-branch rules
- Gitea branch protection enabled on stage and main:
  - Direct pushes disabled (non-admin)
  - stage requires "Dev — Build & local smoke test / build-smoke" to pass
  - main requires "Stage — Build, push & deploy to marketing-stage / deploy-stage" to pass

- Enforcement step added to stage.yaml and deploy.yaml:
  - stage only accepts merges from dev
  - main only accepts merges from stage
  - workflow_dispatch exempt (allows manual redeploy)
  - Direct non-admin pushes are blocked at the Gitea layer before CI runs
2026-05-04 08:18:09 -05:00
Will Anderson 42f0786f97 feat(account): add email/password sign-up to account page
Dev — Build & local smoke test / build-smoke (push) Successful in 2m34s
The sign-in form only offered social auth and a link to /checkout.
Users wanting to create an account directly had no path.

Changes:
- "No account? Create one" toggle replaces the old "Choose a plan" link
- switchToSignUp() / switchToSignIn() toggle button label, placeholder,
  and autocomplete between sign-in and sign-up modes
- Explicit signUpWithEmail() calls signUp() directly; with autoconfirm
  enabled it returns a session immediately and reloads into the dashboard
- signInWithEmail() simplified: no silent sign-up fallback, clean errors
- Re-extract account JS (6dafc1586705 -> dadeb8ddb9a8)
- Re-extract styles chat JS (de72b8b61d75 -> 02ecc8cf6542) as side effect
  of extract-js.py run
2026-05-04 08:16:20 -05:00
Will Anderson 0508cd77fd fix(chat): raise history cap and add 30s frontend timeout
Deploy marketing to Cloud Run / deploy (push) Successful in 3m43s
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 3m26s
Dev — Build & local smoke test / build-smoke (push) Successful in 2m29s
The demo chat was silently dropping conversation context past 40 turns
and leaving the thinking bubble spinning forever when the soul backend
hung — visitors saw a frozen UI with no way to know what went wrong.

Changes:
  - Stored history cap raised from 40 → 200 messages so longer
    conversations actually persist across page refreshes.
  - History sent to backend per turn raised from 20 → 50 messages.
  - 30s AbortController timeout on the /api/demo fetch — surfaces a
    distinct "Took too long to respond" error instead of hanging.
  - Restore script (restore-chat-js-with-preview.py) is now correctly
    idempotent in both directions: detects when modal HTML is inlined
    but chat JS got extracted to an asset, and re-injects fresh source
    so extract-js picks up changes on the next build.
2026-05-04 01:57:38 -05:00
Will Anderson 4c5d4b3c84 fix(chat): restore history on Turnstile verification
Turnstile callback unconditionally showed the greeting message, wiping
session history for returning visitors who hadn't verified yet.

Callback now uses the same restoreOrGreet pattern as neuronDemoToggle:
replays prior messages if session.messages is non-empty, else shows the
greeting once and marks session.greeted.

Also extracts the gallery voting inline script (a49ca0a129e8.js) as a
side effect of re-running extract-js.py. Chat JS rebuilds to de72b8b61d75.js.
2026-05-03 19:51:59 -05:00
Will Anderson 047be5ae02 Remove chat with Neuron links from gallery page
Deploy marketing to Cloud Run / deploy (push) Successful in 3m57s
Dev — Build & local smoke test / build-smoke (push) Successful in 2m19s
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 2m34s
2026-05-03 19:12:35 -05:00
Will Anderson c75d8a9563 ci: add gitflow — dev/stage/main branches with CI workflows
Dev — Build & local smoke test / build-smoke (push) Successful in 2m51s
Stage — Build, push & deploy to marketing-stage / deploy-stage (push) Successful in 2m52s
Deploy marketing to Cloud Run / deploy (push) Successful in 3m37s
- dev.yaml: build + local docker smoke test only (no push, no deploy)
- stage.yaml: build + push + deploy to marketing-stage + smoke test (stops here)
- deploy.yaml: add HTML placeholder touch step before docker build

Proper human gate between stage and prod: the stage→main merge decision.
2026-05-03 11:28:43 -05:00
Will Anderson 102343c8fe fix(gallery): implement voting JS + fix change-vote server path
Voting was completely broken: gallery.el referenced d8251f5e5aa1.js
which was never written. Buttons rendered disabled with no JS to
enable them, load vote state, or call /api/vote.

Fix 1 — client: inline the voting script directly in gallery.el.
Initializes Supabase client from window.NEURON_CFG, calls
/api/vote-state/<id> on load (with JWT if signed in) to populate
scores and active states, wires vote buttons with toggle logic
(same direction = undo/none), handles sign-in modal with magic-link
flow, re-loads all vote states on auth state change.

Fix 2 — server: replace supabase_upsert_user (upsert via user JWT)
with delete-then-insert. Upsert requires both INSERT + UPDATE RLS
policies; the UPDATE policy is typically absent on share_votes.
Delete (user JWT, RLS-safe) + insert (service key, user already
auth-validated) is reliable for both new votes and vote changes.
2026-05-03 11:19:09 -05:00
Will Anderson 254afd2fb2 fix(ci+chat): drop docker buildx flags + style chat code blocks
Deploy marketing to Cloud Run / deploy (push) Failing after 2m27s
CI: gitea runner ships docker without the buildx plugin, so
`docker buildx build --platform linux/amd64 --load` exits 125
("unknown flag: --platform") in both the full build (build-stage.sh)
and the asset-only fast path (deploy.yaml). Runner host is already
linux/amd64, so explicit --platform is redundant. Switch both call
sites to plain `docker build`. This unblocks the pipeline — every
run since the workflow was added (~26 runs) has failed at this
exact step.

Chat: the live chat bubble renders marked.parse() output via
innerHTML, but .demo-msg-ai .demo-msg-bubble only had CSS rules
for p/ul/ol/li/strong. Fenced code blocks rendered as <pre><code>
with no styling — they appeared as wrapped plaintext, hard to
distinguish from prose. Add rules for code (inline and block),
pre, blockquote, em, h1-h4, and a, mirroring the share-card
styling (which always had them) so chat code blocks finally get
the monospace + tinted-background treatment users expect.
2026-05-03 10:15:24 -05:00
Will Anderson 8cd07b9107 fix: copilot svg - strip xml declaration so runtime detects image/svg+xml
Deploy marketing to Cloud Run / deploy (push) Failing after 11s
2026-05-03 04:03:02 -05:00
Will Anderson 22d2dab19b fix: copilot logo - use svg (already deployed) instead of missing png
Deploy marketing to Cloud Run / deploy (push) Failing after 37s
2026-05-03 03:57:02 -05:00
Will Anderson d9eeed9767 fix: replace broken copilot logo with correct PNG
Deploy marketing to Cloud Run / deploy (push) Failing after 18s
2026-05-03 03:52:54 -05:00
Will Anderson 44c7621c85 ci: use neuron-marketing-sa for stage service (fixes secret access)
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
2026-05-03 03:52:17 -05:00
Will Anderson cac0b0d9dc ci: use pre-built elc-linux-amd64 from El SDK v1.2.1 release
Deploy marketing to Cloud Run / deploy (push) Failing after 48s
Replaces the three-step apt install + GCS cache probe + gcc build sequence
with a single curl download of the pre-built binary. Eliminates build-time
C toolchain dependency and shaves ~2-3 minutes off every full build.
2026-05-03 02:02:29 -05:00
Will Anderson 8704f7cdfc update el runtime to v1.2.0, refactor checkout script to external asset
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
2026-05-03 01:13:25 -05:00
Will Anderson adf780b1a6 ci: add test Stripe publishable key to stage env vars
Deploy marketing to Cloud Run / deploy (push) Failing after 51m20s
2026-05-02 19:26:56 -05:00
Will Anderson 12ec770392 ci: gate prod deploy behind stage smoke test
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
Nothing reaches prod without deploying to marketing-stage first and
passing a 90s HTTP smoke test. Stage uses test Stripe keys
(stripe-secret-key-stage) so checkout can be exercised safely.

Set STRIPE_PUBLISHABLE_KEY on the stage service manually once:
  gcloud run services update marketing-stage --region us-central1 \
    --project neuron-785695 \
    --update-env-vars STRIPE_PUBLISHABLE_KEY=pk_test_...
2026-05-02 19:02:17 -05:00
Will Anderson 88ee3d53de fix: free tier shows payment form only after account created (auth-badge reveal)
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
2026-05-02 18:48:38 -05:00
Will Anderson 6702fb7f9a fix: free tier checkout - full Stripe form with SetupIntent (card saved, no charge)
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
2026-05-02 18:38:51 -05:00
Will Anderson d2908099c4 fix: add sign-up form to free tier checkout - was showing text with no form
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
2026-05-02 18:23:28 -05:00
Will Anderson baba6fbb71 ci: add asset-only fast path (<5min for PNG changes)
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
- Detect asset-only changes (src/assets/, src/shares/, static HTML, llms.txt)
  and skip El compilation, C build deps, and Docker full build entirely
- Fast path pulls :latest as base and rebuilds only the assets layer
- Gate clone-el, install-C-deps, elc-cache, build-elc, build-image, push-image
  behind asset_only != 'true'; deploy steps run unconditionally
- Switch build-stage.sh from registry cache driver (requires docker-container
  buildx driver) to inline cache backed by :latest — compatible with default
  docker driver on the runner
2026-05-02 18:08:43 -05:00
Will Anderson b83504c837 ci: raise timeout to 60min for cold elc cache warm-up
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
2026-05-02 17:31:49 -05:00
Will Anderson a185b8ae69 ci: cache elc binary + Docker layers, asset changes from 42min to ~5min
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
- deploy.yaml: restore elc from GCS (gs://neuron-ci-cache) keyed on
  source SHA; only compile on cache miss, then upload for future runs
- Dockerfile.stage: pre-compile el_runtime.o as its own layer so the
  expensive object is cached when only main.c changes between runs
- build-stage.sh: add --cache-from/--cache-to pointing at Artifact
  Registry so apt-get + compilation layers survive across cold builds
2026-05-02 17:30:18 -05:00
Will Anderson 2e73fce3b3 assets: use official Copilot PNG in comparison table
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
2026-05-02 16:43:11 -05:00
Will Anderson 15105b665a assets: add Copilot icon to social assets
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
2026-05-02 16:42:34 -05:00
Will Anderson 5bf7b18f06 ci: update el repo clone URL (engram-lang renamed to el)
Deploy marketing to Cloud Run / deploy (push) Has been cancelled
2026-05-02 15:14:34 -05:00
Will Anderson 609a123012 assets: serve social icons locally, remove simpleicons CDN dependency
LinkedIn, X, Facebook, WhatsApp, TikTok, Snapchat icons now served from
/assets/social/ instead of cdn.simpleicons.org. LinkedIn uses the official
brand PNG from Downloads; remaining icons are scraped SVGs.
2026-05-02 15:11:38 -05:00
Will Anderson afcd03ea31 soul-demo.c: ship the history-aware Claude call source
Deploy marketing to Cloud Run / deploy (push) Failing after 51m19s
Compiled artifact for the soul-history fix that landed in prod
on tag fix-soul-history-1314. Source was built but the .c artifact
didn't get committed alongside the binary deploy. This is the
canonical compiled output of dist/soul-demo.el at HEAD; required
for clean rebuilds via Dockerfile.stage.
2026-05-02 13:21:31 -05:00