logicsrc/apps/logicsrc-web/src/lib/page-markup.ts
Anthony Ettinger df57b54bde
Some checks are pending
CI / build (push) Waiting to run
test / test (push) Waiting to run
Breadcrumbs on every page, and a sidebar that unfolds to where you are (#170)
Anthony: "this needs a cookie crumb navbar, all pages need this with the
new IA" and "broad and drill down, I'm not seeing that in the sidebar".

lib/crumbs.ts derives the trail from the path and the spec registry, so
no page declares it: /openthreat is Home > Specs > Catalogs a site serves
about itself > OpenThreat, /opencpu adds OpenServer before OpenCPU,
/docs/openthreat ends in Specification, /docs/cli is Home > Docs > CLI,
a blog post passes its title as the leaf. components/breadcrumbs.tsx
renders it (server-rendered, with a BreadcrumbList JSON-LD) at the top
of every SiteShell page; the SPA routes rendered by page-markup.ts get
the same trail as a string.

components/side-nav.tsx replaces the flat sidebar: the four groups stay,
and under Specs the family the current page belongs to unfolds to its
specs, and the spec to its blocks, marked active. The home page string
marks the active entry for the SPA routes too.


Claude-Session: https://claude.ai/code/session_014cmNRtR2vL1p89dbVQ7FZJ

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-12 21:04:02 -07:00

436 lines
24 KiB
TypeScript

// Server-rendered markup for the LogicSRC single-page site. This is a faithful
// port of the legacy Vite `main.ts` innerHTML template: same data, same markup,
// same class hooks — now rendered on the server for SEO instead of in the
// browser. Interactivity (hire-us form, CoinPay button, section scroll) lives in
// the `home-interactivity` client component.
import { renderInstallCommand } from "./install-command";
import { renderNavHtml } from "./nav";
import { renderCrumbsHtml } from "./crumbs";
import { FAMILIES, familyTree } from "./specs";
const schemas = [
{ name: "logicsrc-task", path: "packages/schemas/schemas/logicsrc-task.schema.json" },
{ name: "logicsrc-agent", path: "packages/schemas/schemas/logicsrc-agent.schema.json" },
{ name: "logicsrc-run", path: "packages/schemas/schemas/logicsrc-run.schema.json" },
{ name: "logicsrc-event", path: "packages/schemas/schemas/logicsrc-event.schema.json" },
{ name: "logicsrc-plugin", path: "packages/schemas/schemas/logicsrc-plugin.schema.json" },
{ name: "logicsrc-openontology-claim", path: "packages/schemas/schemas/logicsrc-openontology-claim.schema.json" }
];
const implementations = [
{ name: "LogicSRC CLI", detail: "`logicsrc` is the canonical OpenStandards CLI for schemas, specs, plugins, and audits." },
{ name: "TUI and PWA", detail: "Terminal and browser reference surfaces mirror the same open contracts." },
{ name: "SDKs", detail: "`@logicsrc/sdk` defines contract types now; Rust, Bun, Node, Python, and curl surfaces mirror the same resources." },
{ name: "Reference API", detail: "Sample REST API available under `/api/*` for contract testing." },
{ name: "Plugins", detail: "Open plugin contracts let external products consume LogicSRC without LogicSRC calling proprietary tools." }
];
const upcoming = [
{ name: "Model routing", detail: "Switch across major AI model providers from one open spec interface." },
{ name: "Cost controls", detail: "Prefer the cheapest capable model, or rotate providers by price, latency, and task fit." },
{ name: "Master/slave agent workflows", detail: "Fan out a bug report from a master agent into scoped slave agents for reproduction, patching, review, and evidence." },
{ name: "GitHub integration", detail: "Target Profullstack repos, create issues and branches, and keep task history auditable." }
];
const agentByteSurfaces = [
{ name: "CLI", detail: "`logicsrc agentbyte` for plans, sessions, scorecards, audits, and artifacts." },
{ name: "TUI", detail: "Terminal panes for live transcripts, policy events, model use, evidence, and scorecards." },
{ name: "SDKs", detail: "Rust, Bun, Node, Python, and curl surfaces with the same screening session API." },
{ name: "PWA", detail: "Plan builder, candidate intake, live screening room, artifact review, and decision packet." }
];
const credentialProviders = [
{ name: "Team vaults", detail: "Share secrets with teammates by email instead of pasting <code>.env</code> files into chat — a hosted, end-to-end-encrypted vault addressed as <code>team:&lt;team&gt;/&lt;vault&gt;</code>." },
{ name: ".env", detail: "Parse, diff, redact, and write local env files without leaking values into logs." },
{ name: "Doppler", detail: "Sync project/config scoped secrets through provider adapters and auditable key fingerprints." },
{ name: "Railway", detail: "Read and write service variables as a deployment target with explicit approval gates." },
{ name: "GitHub Secrets", detail: "Manage repo, organization, and environment secrets through provider-neutral operations." },
{ name: "sh1pt", detail: "Sync the distribution credential vault — App Store Connect, Play, npm, Docker, and Cloudflare tokens — through the sh1pt CLI." }
];
const credentialSurfaces = [
{ name: "CLI", detail: "`logicsrc credentials` ships provider listing, dry-run plans, diffs, approvals, sync, rollback, and audit exports today." },
{ name: "SDK", detail: "`createCredentialEngine()` in `@logicsrc/plugin-credential-sharing` exposes the same source, target, policy, and audit objects for Node/TS." },
{ name: "TUI", detail: "A Credential Sharing panel reviews key diffs, providers, approval prompts, fingerprints, and failure states without showing raw secrets." },
{ name: "PWA", detail: "Planned: provider connection health, dry-run previews, approval history, and redacted sync evidence." }
];
const hireUsWork = [
{ name: "AI agent workflow specs", detail: "Open schemas, repo-local plans, AgentSwarm flows, AgentByte screening contracts, and MCP resources." },
{ name: "Reference implementations", detail: "CLI, TUI, SDK, PWA, API, curl, and provider-neutral plugin surfaces that prove the spec can be used." },
{ name: "Integration hardening", detail: "GitHub, CoinPay, model providers, webhooks, audit logs, permissions, and deployment-ready contracts." },
{ name: "Open infrastructure", detail: "Portable code and specs first: no closed workflow lock-in, no one-off agent scripts that cannot be audited." }
];
// The stable top-level routes, each a real page. `id` is the route segment, so
// the card links straight to it. The rendered article ids are prefixed
// (`page-docs`) because three of these -- openspec, credential-sharing, hire-us
// -- are also section ids further up this same document, and duplicate ids made
// the in-page scroll targets ambiguous.
const pages = [
{ id: "docs", title: "Docs", detail: "Specification guides, CLI conventions, schemas, plugin contracts, SDK conventions, and MCP resources." },
{ id: "blog", title: "Blog", detail: "Project notes for LogicSRC, AgentSwarm, AgentByte, OpenSpec workflows, and reference implementations." },
{ id: "openspec", title: "OpenSpec", detail: "Comparison and compatibility notes for OpenSpec.dev-style repo-local specs, proposals, tasks, and deltas." },
{ id: "credential-sharing", title: "Credential Sharing", detail: "Open replacement architecture for portable secret sync across end-to-end-encrypted team vaults, .env, Doppler, Railway variables, GitHub Secrets, and sh1pt." },
{ id: "hire-us", title: "Hire Us", detail: "$400/hour LogicSRC work on open infrastructure, specs, AI agent workflows, and reference implementations paid through CoinPay after project acceptance." },
{ id: "about", title: "About", detail: "LogicSRC is the Profullstack open specification project for human and AI agent coordination." },
{ id: "terms", title: "Terms", detail: "Terms of engagement: the $400/hour rate, what is billable, how approved hours are invoiced, the 10-hour minimum, cancellation, acceptable use, and reference implementation boundaries." },
{ id: "privacy", title: "Privacy", detail: "What this site collects and what it does not: analytics, the Hire Us form, the CoinPay sign-in cookie, and where credential data does and does not go." }
];
const comparisonRows = [
{
area: "Primary scope",
logicsrc: "Open coordination standards for humans, agents, plugins, payments, hosted products, and reference implementations.",
openspec: "Lightweight spec-driven planning for code changes and agent work."
},
{
area: "Artifacts",
logicsrc: "Schemas, plugin manifests, task/agent/run docs, event contracts, `@logicsrc/sdk`, MCP resources, CLI/TUI/PWA/API surfaces.",
openspec: "Repo-local specs, proposals, design docs, implementation tasks, and spec deltas."
},
{
area: "Agents",
logicsrc: "Agent profiles, runs, audit logs, model routing, AgentSwarm orchestration, and provider-neutral execution records.",
openspec: "Persistent requirements and planning context for coding agents."
},
{
area: "CLI",
logicsrc: "`logicsrc` as the canonical OpenStandards CLI.",
openspec: "`@fission-ai/openspec` plus native coding-tool slash command integrations."
},
{
area: "MCP",
logicsrc: "Standards MCP server with schemas, validation tools, and prompts.",
openspec: "OpenSpec.dev currently positions itself as no-MCP."
},
{
area: "Compatibility",
logicsrc: "`--openspec` should read/write OpenSpec.dev-style repo-local planning artifacts where useful.",
openspec: "Can remain the lightweight planning layer inside repos."
}
];
export function renderPageMarkup(path = "/"): string {
return `
<main class="shell">
<aside class="rail">
<div class="brand">
<span class="mark">LS</span>
<div>
<strong>LogicSRC</strong>
<small>Open coordination standards</small>
</div>
</div>
${renderInstallCommand("rail")}
<nav aria-label="LogicSRC sections">${renderNavHtml(path)}</nav>
</aside>
<section class="workspace">
${renderCrumbsHtml(path)}
<header id="overview" class="hero">
<div>
<p class="eyebrow">Profullstack open spec project</p>
<h1>LogicSRC</h1>
<p class="lede">Open schemas, primitives, and conventions for coordination between humans, AI agents, plugins, payment systems, and hosted products.</p>
${renderInstallCommand("hero")}
<div class="hero-actions">
<a class="button-primary" href="/api/oauth/coinpay/start">Connect CoinPay</a>
</div>
</div>
<div class="status-grid" aria-label="Project status">
<span><strong>0.1</strong>draft spec</span>
<span><strong>5</strong>schemas</span>
<span><strong>3</strong>reference plugins</span>
</div>
</header>
<section class="band">
<div class="section-head">
<h2>Standards Surface</h2>
<p>Four families of specifications. LogicSRC defines the shared language; products implement it without owning the standard.</p>
</div>
<div class="primitive-grid">
${FAMILIES.map((family) => `
<article class="tile">
<h3><a href="/specs/${family.slug}">${family.name}</a></h3>
<p>${family.line}.</p>
<p class="tile-specs">${familyTree(family).map(({ spec }) => `<a href="${spec.landing ?? spec.doc ?? "/specs"}">${spec.name}</a>`).join(" · ")}</p>
</article>
`).join("")}
</div>
<p class="section-foot"><a href="/specs">Every spec, by family →</a></p>
</section>
<section id="agent-swarm" class="band coming-soon">
<div class="section-head">
<h2>AgentSwarm</h2>
<p>An open spec AI agent platform for routing work across models, tools, providers, and repositories.</p>
</div>
<div class="soon-layout">
<article class="soon-lead">
<span>slug: agent-swarm</span>
<h3>Provider-neutral agent orchestration</h3>
<p>LogicSRC is adding model-provider integration primitives so a CLI or agent runtime can switch between major AI models, choose the cheapest capable option, or rotate models automatically for resilience and cost control.</p>
<pre><code>logicsrc agentswarm --yolo \\
--repo profullstack/logicsrc \\
--agents reproduce,patch,review</code></pre>
</article>
<div class="soon-grid">
${upcoming.map((item) => `
<article>
<h3>${item.name}</h3>
<p>${item.detail}</p>
</article>
`).join("")}
</div>
</div>
</section>
<section id="openontology" class="band two-col">
<div>
<div class="section-head">
<h2>OpenOntology</h2>
<p>An open contract for durable, source-backed domain knowledge shared by humans and AI agents.</p>
</div>
<p>Define the things in a domain, connect them with typed claims, preserve where each fact came from, and let agents query or propose changes through governed interfaces. Storage-agnostic, model-provider-neutral, and usable with no account.</p>
<p><a class="button-primary" href="/openontology">Read the specification</a> <a href="/openontology/explore">Explore the example</a></p>
</div>
<div class="cli-panel">
<h2>Five nouns</h2>
<pre><code>Type Person, Project, Codebase
Entity eth:person:avery-lindqvist
Claim Avery --worksOn--&gt; ZK Prover
Source the commit it came from
ChangeSet a reviewable proposal</code></pre>
<p>Claims are append-only. Agents propose; humans apply.</p>
</div>
</section>
<section id="agentbyte" class="band coming-soon agentbyte">
<div class="section-head">
<h2>AgentByte</h2>
<p>A coming-soon LogicSRC plugin spec for AI-era screening, assessments, interviews, and auditable agent-assisted answers.</p>
</div>
<div class="soon-layout">
<article class="soon-lead">
<span>slug: agentbyte</span>
<h3>Screening where AI use is declared, measured, and auditable</h3>
<p>AgentByte defines open screening sessions for humans, AI-assisted humans, autonomous agents, and human-agent pairs. Instead of pretending AI is absent, the spec records model use, tools, artifacts, scorecards, policy decisions, and evidence.</p>
<pre><code>logicsrc agentbyte plan create \\
--role "AI Engineer" \\
--repo profullstack/logicsrc
logicsrc agentbyte session audit \\
--session ssn_123 \\
--format markdown</code></pre>
</article>
<div class="soon-grid">
${agentByteSurfaces.map((item) => `
<article>
<h3>${item.name}</h3>
<p>${item.detail}</p>
</article>
`).join("")}
</div>
</div>
</section>
<section id="schemas" class="band two-col">
<div>
<div class="section-head">
<h2>Open Schemas</h2>
<p>Versioned JSON Schema files are the contract source for tasks, agents, runs, events, and plugins.</p>
</div>
<div class="schema-list">
${schemas.map((schema) => `
<article>
<strong>${schema.name}</strong>
<code>${schema.path}</code>
</article>
`).join("")}
</div>
</div>
<div id="cli" class="cli-panel">
<h2>CLI Validation</h2>
<pre><code>npm install
npm run schemas:validate
npm --workspace @logicsrc/cli run dev -- \\
task validate ./task.yaml</code></pre>
<p>The CLI belongs here as standards tooling: validate schemas, inspect objects, drive SDK/TUI/PWA/MCP contracts, and exercise compatible implementations.</p>
</div>
</section>
<section id="credential-sharing" class="band credentials">
<div class="section-head">
<h2>Credential Sharing</h2>
<p>An available LogicSRC OpenSpec for replacing closed credential-sharing workflows with auditable, provider-neutral secret sync — including end-to-end-encrypted team vaults you can share by email. Shipped in <code>@logicsrc/plugin-credential-sharing</code>.</p>
</div>
<div class="soon-layout">
<article class="soon-lead">
<span>slug: credential-sharing</span>
<h3>Open replacement architecture for secrets</h3>
<p>LogicSRC defines the credential source, target, diff, approval, sync, rollback, and audit objects. External tools can consume the contract, but LogicSRC remains the open standards CLI and does not call out to proprietary product commands.</p>
<pre><code>logicsrc credentials providers
logicsrc credentials diff --from env --from-path .env --to railway \\
--to-project &lt;projectId&gt; --to-config &lt;environmentId&gt;
logicsrc credentials plan --from env --from-path .env --to doppler \\
--to-project &lt;project&gt; --to-config &lt;config&gt;
logicsrc credentials sync --plan &lt;planId&gt; # dry-run, no writes
logicsrc credentials sync --plan &lt;planId&gt; --approve # writes to the target
logicsrc credentials audit --run &lt;runId&gt; --format markdown
logicsrc credentials rollback --run &lt;runId&gt;</code></pre>
<h3>Team sharing, end to end encrypted</h3>
<p>Teams ship today. The server is a zero-knowledge relay for secret values: it stores member X25519 public keys, the vault data-encryption key sealed once per member, and ciphertext. Plaintext values and the raw DEK never leave a member&rsquo;s machine, and granting access re-seals the key to the new member rather than revealing it. When someone leaves, rotation re-keys the vault and drops their access.</p>
<pre><code>logicsrc login # registers this device's identity key
logicsrc teams create acme --name "Acme Inc"
logicsrc teams push acme web prod --env .env # encrypt + upload
logicsrc teams invite acme teammate@example.com # emails an accept link
logicsrc teams grant acme web prod teammate@example.com
logicsrc teams pull acme web prod --env .env # download + decrypt
logicsrc credentials rotate acme web prod --approve</code></pre>
<h3>SSH keys, not just environment variables</h3>
<p>Not every secret is a <code>KEY=VALUE</code> line. <code>~/.ssh</code> is a directory of files whose permission bits are load-bearing &mdash; a private key restored world-readable is one OpenSSH will refuse to use. The ssh provider moves that directory through the same end-to-end-encrypted vault as everything else and puts each file back with its mode intact, so a new machine is set up rather than merely populated. Restored SSH keys can go straight into <code>ssh-agent</code> instead of onto disk.</p>
<pre><code>logicsrc secrets ssh push profullstack # back up ~/.ssh to vault ssh--&lt;you&gt;
logicsrc secrets ssh list profullstack # what the vault holds: paths, kinds, modes
logicsrc secrets ssh pull profullstack # restore on another machine, permissions and all
logicsrc secrets ssh agent profullstack # load into ssh-agent, never onto disk</code></pre>
</article>
<div class="soon-grid">
${credentialProviders.map((item) => `
<article>
<h3>${item.name}</h3>
<p>${item.detail}</p>
</article>
`).join("")}
</div>
</div>
<div class="surface-strip" aria-label="Credential sharing reference surfaces">
${credentialSurfaces.map((item) => `
<article>
<h3>${item.name}</h3>
<p>${item.detail}</p>
</article>
`).join("")}
</div>
</section>
<section id="openspec" class="band">
<div class="section-head">
<h2>LogicSRC vs OpenSpec.dev</h2>
<p>OpenSpec.dev is adjacent: it focuses on lightweight repo-local planning artifacts. LogicSRC is the broader coordination standard and can support OpenSpec-compatible workflows.</p>
</div>
<div class="compare-table" role="table" aria-label="LogicSRC and OpenSpec.dev comparison">
<div class="compare-row compare-head" role="row">
<strong role="columnheader">Area</strong>
<strong role="columnheader">LogicSRC.com</strong>
<strong role="columnheader">OpenSpec.dev</strong>
</div>
${comparisonRows.map((row) => `
<div class="compare-row" role="row">
<strong role="cell">${row.area}</strong>
<p role="cell">${row.logicsrc}</p>
<p role="cell">${row.openspec}</p>
</div>
`).join("")}
</div>
<div class="cli-panel compare-note">
<h2>Compatibility Mode</h2>
<pre><code>logicsrc --openspec agentswarm --yolo \\
--repo profullstack/logicsrc</code></pre>
<p><code>--openspec</code> enables OpenSpec.dev-compatible repo-local specs, proposals, tasks, and deltas where supported. <code>openspec import</code> and <code>openspec export</code> summarize those artifacts for LogicSRC workflows. <code>--openspec-only</code> restricts work to LogicSRC-published contracts.</p>
</div>
</section>
<section id="reference" class="band">
<div class="section-head">
<h2>Reference Implementations</h2>
<p>These prove the standard, but they are not the LogicSRC identity.</p>
</div>
<div class="implementation-list">
${implementations.map((item) => `
<article>
<span></span>
<div>
<h3>${item.name}</h3>
<p>${item.detail}</p>
</div>
</article>
`).join("")}
</div>
</section>
<section id="hire-us" class="band hire-us">
<div class="section-head">
<h2>Hire Us</h2>
<p>$400/hour for accepted LogicSRC work using open infrastructure and open specs for AI agent systems.</p>
</div>
<div class="hire-layout">
<article class="hire-panel">
<p class="eyebrow">Profullstack standards work</p>
<h3>Open-spec AI agent implementation help</h3>
<p>Hire us to turn agent ideas into portable LogicSRC specs, CLIs, SDKs, MCP resources, PWAs, APIs, and provider-neutral plugin workflows. We prioritize auditable contracts, repo-local artifacts, and integrations that can move between model providers and infrastructure.</p>
<div class="price-row">
<strong>$400</strong>
<span>per hour</span>
</div>
<p class="price-terms">Billed against actual hours worked, invoiced after you approve them. Ten-hour minimum engagement; cancel any time with one week&rsquo;s notice and pay only for hours already approved. See <a href="/terms">Terms</a>.</p>
<form id="project-request-form" class="project-request-form">
<label>
<span>Contact</span>
<input id="project-contact" name="contact" type="email" autocomplete="email" placeholder="you@example.com" required />
</label>
<label>
<span>Project</span>
<textarea id="project-description" name="project" rows="6" minlength="20" placeholder="Describe the agent workflow, spec, CLI, plugin, API, or integration you want help with." required></textarea>
</label>
<div class="cta-row">
<button id="project-request-button" class="button-primary" type="submit">Request review</button>
<a class="button-secondary" href="/docs">Read specs</a>
</div>
</form>
<div id="project-request-result" class="coinpay-result" aria-live="polite"></div>
</article>
<div class="hire-stack">
<div class="hire-grid">
${hireUsWork.map((item) => `
<article>
<h3>${item.name}</h3>
<p>${item.detail}</p>
</article>
`).join("")}
</div>
<article id="coinpay-setup" class="coinpay-panel">
<h3>CoinPay hourly invoice</h3>
<p>After we accept the project, we invoice approved hours at $400/hour through CoinPay without exposing merchant credentials to the browser.</p>
<pre><code>COINPAY_ORG=profullstack
COINPAY_PRODUCT=logicsrc-hire-us
COINPAY_RATE_USD_PER_HOUR=400
COINPAY_BILLING=metered_hours
COINPAY_MINIMUM_HOURS=10
COINPAY_STATUS=pending_acceptance</code></pre>
</article>
</div>
</div>
</section>
<section id="pages" class="band">
<div class="section-head">
<h2>Top-Level Pages</h2>
<p>LogicSRC.com should expose stable project pages for docs, publishing, company context, and legal basics.</p>
</div>
<div class="implementation-list">
${pages.map((page) => `
<article id="page-${page.id}">
<span></span>
<div>
<h3><a href="/${page.id}">/${page.id} · ${page.title}</a></h3>
<p>${page.detail}</p>
</div>
</article>
`).join("")}
</div>
</section>
</section>
</main>
`;
}