Release 0.2.0: graduation merge race fix + VITE_APP_NAME + versioning infrastructure
- Fix §13.3 step 4 race against Gitea's async mergeability computation: gitea.wait_for_mergeable polls the mergeable field before calling merge, and bot._merge_with_retry rides out the transient 'Please try again later' response. - Frontend now requires VITE_APP_NAME at build time (frontend/vite.config.js fails the build if unset). Header brand, landing H1, and browser title read the deployment's configured name. - Establish framework versioning: VERSION (canonical) + frontend/package.json#version mirror; CHANGELOG.md as the release log with RFC 2119 / 8174 normative-language upgrade-steps; SPEC.md §20 as the binding policy; CLAUDE.md capturing the separation-of-concerns rule; docs/DEPLOYMENTS.md as the downstream operating manual; docs/QUICKSTART-VISION.md staking the future one-command-deploy capability. - Surgical fix to SPEC.md opening so the spec no longer asserts OHM is the corpus the framework produces. - SPEC.md §19.2 gains the 'Deployment-supplied subject framing' candidate that drives the 0.3.0 release.
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
# Frontend build-time configuration. Copy to `frontend/.env` and fill in.
|
||||
#
|
||||
# Vite picks up VITE_* variables from these files at build (`npm run build`)
|
||||
# and dev (`npm run dev`) time. Real `.env` files are gitignored; only this
|
||||
# `.env.example` is committed.
|
||||
|
||||
# The user-visible name of this deployment. Used as the browser tab title,
|
||||
# the header brand, and the landing page H1. Required — the framework
|
||||
# ships no default on purpose so each deployment names itself. If unset,
|
||||
# `npm run build` fails with a clear message.
|
||||
#
|
||||
# Examples:
|
||||
# VITE_APP_NAME=Wiggleverse RFC
|
||||
# VITE_APP_NAME=Wiggleverse Open Human Model
|
||||
VITE_APP_NAME=
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Wiggleverse RFCs</title>
|
||||
<title>%VITE_APP_NAME%</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "rfc-app-frontend",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -84,7 +84,7 @@ export default function App() {
|
||||
<div className="app">
|
||||
<header className="app-header">
|
||||
<div className="app-brand">
|
||||
<Link to="/">Open Human Model</Link>
|
||||
<Link to="/">{import.meta.env.VITE_APP_NAME}</Link>
|
||||
</div>
|
||||
<div className="header-right">
|
||||
{/* §14.3: the persistent About link. One word, no badge, no
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
// Landing.jsx — §14.1's pre-login surface.
|
||||
//
|
||||
// This instance hosts the Open Human Model — the corpus the framework
|
||||
// produces, per PHILOSOPHY.md. The page's three jobs per §14.1 remain:
|
||||
// name what this thing is, pitch why someone would care, and offer
|
||||
// the sign-in affordance. Title and subtitle frame OHM-the-corpus;
|
||||
// the pitch (lifted from the top of PHILOSOPHY.md) does the argument;
|
||||
// a small attribution line below the deck names Wiggleverse RFC as
|
||||
// the underlying process so a reader can tell what's the corpus and
|
||||
// what's the software hosting it. The secondary link to `/philosophy`
|
||||
// is for the reader who is interested but needs more before signing in.
|
||||
// The page's three jobs per §14.1: name what this thing is, pitch why
|
||||
// someone would care, and offer the sign-in affordance. The deployment
|
||||
// supplies its display name via VITE_APP_NAME (see frontend/.env.example);
|
||||
// the subtitle and pitch below currently carry the corpus this instance
|
||||
// hosts and should be lifted into deployment config in a follow-up so
|
||||
// the framework source stays brand-neutral.
|
||||
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
@@ -16,7 +13,7 @@ export default function Landing() {
|
||||
return (
|
||||
<div className="landing">
|
||||
<div className="landing-inner">
|
||||
<h1>Open Human Model</h1>
|
||||
<h1>{import.meta.env.VITE_APP_NAME}</h1>
|
||||
<p className="subtitle">
|
||||
An open dictionary of the words humans and machines need to agree on.
|
||||
</p>
|
||||
|
||||
+40
-9
@@ -1,15 +1,46 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import { defineConfig, loadEnv } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
// In dev, the frontend runs on Vite's port and proxies the API
|
||||
// (and /auth/*, /api/webhooks/*) to the FastAPI process.
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
server: {
|
||||
port: 5173,
|
||||
proxy: {
|
||||
'/api': 'http://localhost:8000',
|
||||
'/auth': 'http://localhost:8000',
|
||||
//
|
||||
// VITE_APP_NAME is the user-visible name of this deployment — used in
|
||||
// the browser tab title, the header brand, and the landing page H1.
|
||||
// The framework intentionally ships no default: every deployment must
|
||||
// supply its own name via `frontend/.env` so a fresh build never ships
|
||||
// the wrong brand. See `frontend/.env.example`.
|
||||
export default defineConfig(({ mode }) => {
|
||||
const env = loadEnv(mode, process.cwd(), '')
|
||||
const appName = env.VITE_APP_NAME
|
||||
|
||||
if (!appName || !appName.trim()) {
|
||||
throw new Error(
|
||||
'VITE_APP_NAME is required but not set. Copy frontend/.env.example to ' +
|
||||
'frontend/.env and set VITE_APP_NAME=... before building. The framework ' +
|
||||
'ships no default on purpose — each deployment names itself.'
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
plugins: [
|
||||
react(),
|
||||
// Build-time HTML token substitution: `%VITE_APP_NAME%` inside
|
||||
// `index.html` becomes the configured name. Vite already does this
|
||||
// for env vars referenced as `%VITE_*%` in HTML, but we wire it
|
||||
// explicitly so the failure mode (token left in title) is loud.
|
||||
{
|
||||
name: 'inject-app-name',
|
||||
transformIndexHtml(html) {
|
||||
return html.replace(/%VITE_APP_NAME%/g, appName)
|
||||
},
|
||||
},
|
||||
],
|
||||
server: {
|
||||
port: 5173,
|
||||
proxy: {
|
||||
'/api': 'http://localhost:8000',
|
||||
'/auth': 'http://localhost:8000',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user