mirror of
https://github.com/merlinhu1/truthmark.git
synced 2026-08-25 07:53:25 +02:00
1454 lines
53 KiB
HTML
1454 lines
53 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<script>document.documentElement.classList.add('js');</script>
|
|
<title>Truthmark — the branch explains itself</title>
|
|
<meta name="description" content="Truthmark helps AI-assisted branches carry accurate, reviewable repository truth alongside code changes.">
|
|
<meta property="og:title" content="Truthmark — the branch explains itself">
|
|
<meta property="og:description" content="A repository-native review layer for code, decisions, and current truth.">
|
|
<meta property="og:type" content="website">
|
|
<meta name="theme-color" content="#07131f">
|
|
<style>
|
|
:root {
|
|
color-scheme: dark;
|
|
--ink: #07131f;
|
|
--ink-2: #0a1a2a;
|
|
--ink-3: #102236;
|
|
--paper: #f5f7ef;
|
|
--paper-2: #e8f2dd;
|
|
--text: #f8fbf2;
|
|
--muted: #b9c7d6;
|
|
--dim: #7f90a3;
|
|
--green: #8ee66b;
|
|
--green-2: #58bf43;
|
|
--lime-glow: rgba(142, 230, 107, 0.2);
|
|
--cyan: #77d9ff;
|
|
--amber: #f1c765;
|
|
--rose: #ff8d9a;
|
|
--line: rgba(220, 236, 255, 0.16);
|
|
--line-strong: rgba(220, 236, 255, 0.28);
|
|
--panel: rgba(255, 255, 255, 0.045);
|
|
--panel-2: rgba(255, 255, 255, 0.075);
|
|
--shadow: 0 30px 90px rgba(0, 0, 0, 0.36);
|
|
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
}
|
|
|
|
* { box-sizing: border-box; }
|
|
html { scroll-behavior: smooth; }
|
|
|
|
body {
|
|
margin: 0;
|
|
min-height: 100vh;
|
|
color: var(--text);
|
|
background:
|
|
radial-gradient(circle at 18% 6%, rgba(142, 230, 107, 0.18), transparent 28rem),
|
|
radial-gradient(circle at 82% 10%, rgba(119, 217, 255, 0.13), transparent 32rem),
|
|
radial-gradient(circle at 50% 56%, rgba(241, 199, 101, 0.06), transparent 38rem),
|
|
linear-gradient(180deg, #020812 0%, var(--ink) 36%, #050b12 100%);
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
body::before {
|
|
content: "";
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: -1;
|
|
background-image:
|
|
linear-gradient(rgba(255,255,255,0.035) 1px, transparent 1px),
|
|
linear-gradient(90deg, rgba(255,255,255,0.035) 1px, transparent 1px);
|
|
background-size: 48px 48px;
|
|
mask-image: linear-gradient(180deg, rgba(0,0,0,0.75), transparent 72%);
|
|
}
|
|
|
|
a { color: inherit; }
|
|
|
|
.shell {
|
|
width: min(1240px, calc(100% - 48px));
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.nav {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 50;
|
|
border-bottom: 1px solid rgba(220,236,255,0.08);
|
|
background: rgba(3, 10, 18, 0.78);
|
|
backdrop-filter: blur(18px);
|
|
}
|
|
|
|
.nav-inner {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
min-height: 74px;
|
|
}
|
|
|
|
.brand {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
text-decoration: none;
|
|
font-weight: 780;
|
|
letter-spacing: -0.03em;
|
|
}
|
|
|
|
.glyph {
|
|
position: relative;
|
|
display: grid;
|
|
place-items: center;
|
|
width: 38px;
|
|
height: 38px;
|
|
border: 1px solid rgba(142,230,107,0.55);
|
|
border-radius: 13px;
|
|
background: linear-gradient(145deg, rgba(142,230,107,0.2), rgba(119,217,255,0.1));
|
|
box-shadow: 0 0 30px rgba(142,230,107,0.18);
|
|
}
|
|
|
|
.glyph-mark {
|
|
width: 23px;
|
|
height: 23px;
|
|
fill: none;
|
|
stroke: var(--green);
|
|
stroke-width: 2.8;
|
|
stroke-linecap: round;
|
|
stroke-linejoin: round;
|
|
filter: drop-shadow(0 0 6px rgba(142,230,107,0.5));
|
|
}
|
|
|
|
.page-tabs {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
padding: 5px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 999px;
|
|
background: rgba(255,255,255,0.035);
|
|
color: var(--muted);
|
|
font-size: 0.88rem;
|
|
font-weight: 620;
|
|
}
|
|
|
|
.page-tab {
|
|
min-height: 36px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 0 14px;
|
|
border-radius: 999px;
|
|
text-decoration: none;
|
|
white-space: nowrap;
|
|
transition: color 150ms ease, background 150ms ease, box-shadow 150ms ease;
|
|
}
|
|
|
|
.page-tab:hover { color: var(--text); }
|
|
|
|
.page-tab[aria-selected="true"] {
|
|
color: #06110a;
|
|
background: var(--green);
|
|
box-shadow: 0 8px 24px rgba(142,230,107,0.2);
|
|
}
|
|
|
|
.nav-github {
|
|
color: var(--muted);
|
|
font-size: 0.88rem;
|
|
font-weight: 720;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.nav-github:hover { color: var(--text); }
|
|
|
|
.page-view { scroll-margin-top: 88px; }
|
|
.js .page-view { display: none; }
|
|
.js .page-view.active { display: block; animation: page-enter 220ms ease-out; }
|
|
|
|
@keyframes page-enter {
|
|
from { opacity: 0; transform: translateY(6px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
.button {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
min-height: 44px;
|
|
padding: 0 17px;
|
|
border: 1px solid var(--line-strong);
|
|
border-radius: 999px;
|
|
background: rgba(255,255,255,0.045);
|
|
color: var(--text);
|
|
font-weight: 720;
|
|
text-decoration: none;
|
|
box-shadow: 0 12px 34px rgba(0,0,0,0.22);
|
|
}
|
|
|
|
.button.primary {
|
|
color: #06110a;
|
|
border-color: rgba(142,230,107,0.92);
|
|
background: linear-gradient(180deg, #a4f483, #62c94b);
|
|
}
|
|
|
|
.hero {
|
|
display: grid;
|
|
grid-template-columns: 0.9fr 1.1fr;
|
|
gap: 52px;
|
|
align-items: center;
|
|
min-height: calc(100vh - 74px);
|
|
padding: 76px 0 88px;
|
|
}
|
|
|
|
.eyebrow {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 7px 12px;
|
|
border: 1px solid rgba(142,230,107,0.28);
|
|
border-radius: 999px;
|
|
background: rgba(142,230,107,0.09);
|
|
color: #d9ffd0;
|
|
font-size: 0.9rem;
|
|
font-weight: 760;
|
|
letter-spacing: -0.01em;
|
|
}
|
|
|
|
.pulse {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 999px;
|
|
background: var(--green);
|
|
box-shadow: 0 0 16px rgba(142,230,107,0.8);
|
|
}
|
|
|
|
h1 {
|
|
margin: 22px 0 20px;
|
|
font-size: clamp(3.35rem, 6.7vw, 6.6rem);
|
|
line-height: 0.91;
|
|
letter-spacing: -0.078em;
|
|
text-wrap: balance;
|
|
}
|
|
|
|
.lead {
|
|
max-width: 740px;
|
|
margin: 0;
|
|
color: var(--muted);
|
|
font-size: clamp(1.18rem, 1.55vw, 1.48rem);
|
|
line-height: 1.58;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
|
|
.hero-actions {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 14px;
|
|
margin-top: 32px;
|
|
}
|
|
|
|
.signals {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: 12px;
|
|
margin-top: 34px;
|
|
margin-bottom: 0;
|
|
padding: 0;
|
|
list-style: none;
|
|
max-width: 690px;
|
|
}
|
|
|
|
.signal {
|
|
padding: 15px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 16px;
|
|
background: var(--panel);
|
|
}
|
|
|
|
.signal strong { display: block; margin-bottom: 6px; letter-spacing: -0.025em; }
|
|
.signal span { color: var(--dim); font-size: 0.92rem; line-height: 1.42; }
|
|
|
|
.stage {
|
|
position: relative;
|
|
min-height: 680px;
|
|
border: 1px solid var(--line-strong);
|
|
border-radius: 34px;
|
|
background:
|
|
radial-gradient(circle at 70% 16%, rgba(142,230,107,0.17), transparent 18rem),
|
|
radial-gradient(circle at 22% 80%, rgba(119,217,255,0.1), transparent 20rem),
|
|
rgba(255,255,255,0.045);
|
|
box-shadow: var(--shadow);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.stage::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 42px;
|
|
border: 1px dashed rgba(220,236,255,0.13);
|
|
border-radius: 999px;
|
|
transform: rotate(-14deg);
|
|
}
|
|
|
|
.orbit {
|
|
position: absolute;
|
|
border: 1px solid var(--line);
|
|
background: rgba(4, 12, 22, 0.78);
|
|
backdrop-filter: blur(8px);
|
|
box-shadow: 0 18px 60px rgba(0,0,0,0.28);
|
|
}
|
|
|
|
.orbit.core {
|
|
left: 50%; top: 50%; transform: translate(-50%, -50%);
|
|
width: min(390px, 72%);
|
|
border-radius: 28px;
|
|
padding: 26px;
|
|
z-index: 4;
|
|
}
|
|
|
|
.core h2 {
|
|
margin: 0 0 12px;
|
|
font-size: 2rem;
|
|
line-height: 1.04;
|
|
letter-spacing: -0.055em;
|
|
}
|
|
|
|
.core p { margin: 0; color: var(--muted); line-height: 1.55; }
|
|
|
|
.route-line {
|
|
display: grid;
|
|
grid-template-columns: 18px 1fr auto;
|
|
gap: 10px;
|
|
align-items: center;
|
|
margin-top: 18px;
|
|
padding: 12px;
|
|
border: 1px solid rgba(220,236,255,0.12);
|
|
border-radius: 14px;
|
|
color: #dfe9f6;
|
|
font: 0.86rem/1.4 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
background: rgba(255,255,255,0.035);
|
|
}
|
|
|
|
.route-line i {
|
|
display: block;
|
|
width: 11px;
|
|
height: 11px;
|
|
border-radius: 999px;
|
|
background: var(--green);
|
|
box-shadow: 0 0 14px rgba(142,230,107,0.6);
|
|
}
|
|
|
|
.route-line em { color: var(--dim); font-style: normal; }
|
|
|
|
.node {
|
|
position: absolute;
|
|
width: 172px;
|
|
padding: 16px;
|
|
border-radius: 20px;
|
|
}
|
|
|
|
.node strong { display: block; margin-bottom: 7px; letter-spacing: -0.02em; }
|
|
.node span { display: block; color: var(--dim); font-size: 0.86rem; line-height: 1.38; }
|
|
.node.a { top: 44px; left: 54px; }
|
|
.node.b { top: 88px; right: 42px; }
|
|
.node.c { left: 42px; bottom: 76px; }
|
|
.node.d { right: 58px; bottom: 52px; }
|
|
|
|
.rail {
|
|
position: absolute;
|
|
height: 2px;
|
|
background: linear-gradient(90deg, transparent, rgba(142,230,107,0.62), transparent);
|
|
transform-origin: left center;
|
|
opacity: 0.7;
|
|
}
|
|
|
|
.rail.r1 { width: 260px; top: 206px; left: 180px; transform: rotate(24deg); }
|
|
.rail.r2 { width: 230px; top: 224px; right: 170px; transform: rotate(145deg); }
|
|
.rail.r3 { width: 260px; bottom: 214px; left: 180px; transform: rotate(-22deg); }
|
|
.rail.r4 { width: 230px; bottom: 202px; right: 184px; transform: rotate(205deg); }
|
|
|
|
.section {
|
|
padding: 92px 0;
|
|
border-top: 1px solid rgba(220,236,255,0.08);
|
|
}
|
|
|
|
.section-header {
|
|
max-width: 860px;
|
|
margin-bottom: 34px;
|
|
}
|
|
|
|
h2.section-title,
|
|
.section-header h2 {
|
|
margin: 0 0 14px;
|
|
font-size: clamp(2.35rem, 4.5vw, 4.6rem);
|
|
line-height: 0.96;
|
|
letter-spacing: -0.068em;
|
|
text-wrap: balance;
|
|
}
|
|
|
|
.section-header p {
|
|
margin: 0;
|
|
color: var(--muted);
|
|
font-size: 1.16rem;
|
|
line-height: 1.62;
|
|
letter-spacing: -0.015em;
|
|
}
|
|
|
|
.page-intro {
|
|
display: grid;
|
|
grid-template-columns: 0.8fr 1.2fr;
|
|
gap: 42px;
|
|
align-items: end;
|
|
padding: 76px 0 44px;
|
|
}
|
|
|
|
.page-intro h1,
|
|
.page-intro h2 {
|
|
margin: 0;
|
|
font-size: clamp(2.7rem, 5.5vw, 5.4rem);
|
|
line-height: 0.94;
|
|
letter-spacing: -0.072em;
|
|
text-wrap: balance;
|
|
}
|
|
|
|
.page-intro-copy {
|
|
max-width: 720px;
|
|
padding-bottom: 6px;
|
|
}
|
|
|
|
.page-intro-copy p {
|
|
margin: 14px 0 0;
|
|
color: var(--muted);
|
|
font-size: 1.16rem;
|
|
line-height: 1.62;
|
|
}
|
|
|
|
.page-note {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
color: var(--green);
|
|
font-size: 0.78rem;
|
|
font-weight: 820;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.workflow-deck {
|
|
display: grid;
|
|
grid-template-columns: repeat(12, minmax(0, 1fr));
|
|
gap: 14px;
|
|
}
|
|
|
|
.workflow-card {
|
|
grid-column: span 4;
|
|
min-height: 260px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding: 22px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 22px;
|
|
background: var(--panel);
|
|
}
|
|
|
|
.workflow-card:nth-child(4),
|
|
.workflow-card:nth-child(5) { grid-column: span 6; }
|
|
|
|
.workflow-card .mode {
|
|
align-self: flex-start;
|
|
margin-bottom: 42px;
|
|
padding: 5px 9px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 999px;
|
|
color: var(--dim);
|
|
font-size: 0.72rem;
|
|
font-weight: 780;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.workflow-card h3 {
|
|
margin: auto 0 9px;
|
|
font-size: 1.55rem;
|
|
letter-spacing: -0.045em;
|
|
}
|
|
|
|
.workflow-card p { margin: 0; color: var(--muted); line-height: 1.52; }
|
|
.workflow-card code { color: var(--green); font-size: 0.82rem; }
|
|
|
|
.workflow-card.sync {
|
|
border-color: rgba(142,230,107,0.38);
|
|
background: linear-gradient(145deg, rgba(142,230,107,0.11), rgba(255,255,255,0.035));
|
|
}
|
|
|
|
.truth-anatomy {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 14px;
|
|
margin-top: 18px;
|
|
}
|
|
|
|
.anatomy-card {
|
|
position: relative;
|
|
min-height: 230px;
|
|
padding: 22px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 22px;
|
|
background: var(--panel);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.anatomy-card::before {
|
|
content: attr(data-step);
|
|
position: absolute;
|
|
right: 18px;
|
|
top: 10px;
|
|
color: rgba(248,251,242,0.08);
|
|
font-size: 4rem;
|
|
font-weight: 850;
|
|
letter-spacing: -0.08em;
|
|
}
|
|
|
|
.anatomy-card h3 { position: relative; margin: 54px 0 10px; font-size: 1.45rem; letter-spacing: -0.04em; }
|
|
.anatomy-card p { position: relative; margin: 0; color: var(--muted); line-height: 1.55; }
|
|
|
|
.start-grid {
|
|
display: grid;
|
|
grid-template-columns: 1.05fr 0.95fr;
|
|
gap: 18px;
|
|
margin-top: 18px;
|
|
}
|
|
|
|
.start-card {
|
|
padding: 24px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 24px;
|
|
background: var(--panel);
|
|
}
|
|
|
|
.start-card h3 { margin: 0 0 10px; font-size: 1.55rem; letter-spacing: -0.045em; }
|
|
.start-card p { margin: 0; color: var(--muted); line-height: 1.58; }
|
|
.start-list { display: grid; gap: 10px; margin-top: 20px; }
|
|
|
|
.start-item {
|
|
display: grid;
|
|
grid-template-columns: 32px minmax(0, 1fr);
|
|
gap: 12px;
|
|
padding: 13px;
|
|
border: 1px solid rgba(220,236,255,0.11);
|
|
border-radius: 14px;
|
|
background: rgba(255,255,255,0.028);
|
|
}
|
|
|
|
.start-item b {
|
|
width: 30px;
|
|
height: 30px;
|
|
display: grid;
|
|
place-items: center;
|
|
border-radius: 10px;
|
|
color: #07131f;
|
|
background: var(--green);
|
|
}
|
|
|
|
.start-item strong { display: block; margin-bottom: 4px; }
|
|
.start-item span { color: var(--dim); font-size: 0.9rem; line-height: 1.42; }
|
|
|
|
.host-cloud { display: flex; flex-wrap: wrap; gap: 8px; margin: 20px 0 0; padding: 0; list-style: none; }
|
|
.host-chip { padding: 7px 10px; border: 1px solid var(--line); border-radius: 999px; color: var(--muted); font-size: 0.82rem; }
|
|
|
|
.boundary-card {
|
|
margin-top: 18px;
|
|
padding: 22px;
|
|
border: 1px solid rgba(119,217,255,0.25);
|
|
border-radius: 22px;
|
|
background: linear-gradient(135deg, rgba(119,217,255,0.09), rgba(255,255,255,0.03));
|
|
}
|
|
|
|
.boundary-card strong { display: block; margin-bottom: 8px; font-size: 1.1rem; }
|
|
.boundary-card p { margin: 0; color: var(--muted); line-height: 1.55; }
|
|
|
|
.map-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
gap: 14px;
|
|
}
|
|
|
|
.surface-card {
|
|
position: relative;
|
|
min-height: 250px;
|
|
padding: 22px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 22px;
|
|
background: var(--panel);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.surface-card::after {
|
|
content: attr(data-index);
|
|
position: absolute;
|
|
right: 18px;
|
|
bottom: 12px;
|
|
color: rgba(248,251,242,0.08);
|
|
font-size: 4.8rem;
|
|
font-weight: 800;
|
|
letter-spacing: -0.08em;
|
|
}
|
|
|
|
.surface-card:hover { border-color: rgba(142,230,107,0.38); background: var(--panel-2); }
|
|
|
|
.surface-card h3 {
|
|
position: relative;
|
|
margin: 0 0 10px;
|
|
font-size: 1.35rem;
|
|
line-height: 1.08;
|
|
letter-spacing: -0.04em;
|
|
z-index: 1;
|
|
}
|
|
|
|
.surface-card p {
|
|
position: relative;
|
|
margin: 0;
|
|
color: var(--muted);
|
|
line-height: 1.55;
|
|
z-index: 1;
|
|
}
|
|
|
|
.mini-kicker {
|
|
display: inline-flex;
|
|
margin-bottom: 18px;
|
|
padding: 5px 9px;
|
|
border: 1px solid rgba(142,230,107,0.32);
|
|
border-radius: 999px;
|
|
color: var(--green);
|
|
background: rgba(142,230,107,0.08);
|
|
font-size: 0.72rem;
|
|
font-weight: 820;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.timeline {
|
|
display: grid;
|
|
grid-template-columns: 310px 1fr;
|
|
gap: 18px;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.tabs {
|
|
display: grid;
|
|
gap: 12px;
|
|
}
|
|
|
|
.tab {
|
|
width: 100%;
|
|
padding: 18px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 18px;
|
|
background: var(--panel);
|
|
color: var(--muted);
|
|
text-align: left;
|
|
cursor: pointer;
|
|
font: inherit;
|
|
}
|
|
|
|
.tab strong {
|
|
display: block;
|
|
margin-bottom: 7px;
|
|
color: var(--text);
|
|
font-size: 1.04rem;
|
|
letter-spacing: -0.03em;
|
|
}
|
|
|
|
.tab[aria-selected="true"] {
|
|
border-color: rgba(142,230,107,0.56);
|
|
background: rgba(142,230,107,0.12);
|
|
color: #dcefd7;
|
|
}
|
|
|
|
.panel {
|
|
display: none;
|
|
min-height: 640px;
|
|
border: 1px solid var(--line-strong);
|
|
border-radius: 26px;
|
|
background: rgba(4, 12, 22, 0.74);
|
|
box-shadow: var(--shadow);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.panel.active { display: block; }
|
|
|
|
.panel-head {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 16px;
|
|
padding: 18px 22px;
|
|
border-bottom: 1px solid var(--line);
|
|
}
|
|
|
|
.panel-head strong { letter-spacing: -0.03em; }
|
|
|
|
.status-pill {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 5px 9px;
|
|
border: 1px solid rgba(142,230,107,0.36);
|
|
border-radius: 999px;
|
|
color: var(--green);
|
|
background: rgba(142,230,107,0.09);
|
|
font-size: 0.76rem;
|
|
font-weight: 820;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
}
|
|
|
|
.panel-grid {
|
|
display: grid;
|
|
grid-template-columns: 0.9fr 1.1fr;
|
|
min-height: 590px;
|
|
}
|
|
|
|
.evidence,
|
|
.truth-sheet {
|
|
padding: 24px;
|
|
}
|
|
|
|
.evidence {
|
|
border-right: 1px solid var(--line);
|
|
background: rgba(255,255,255,0.025);
|
|
}
|
|
|
|
.label {
|
|
display: block;
|
|
margin-bottom: 14px;
|
|
color: var(--green);
|
|
font-size: 0.78rem;
|
|
font-weight: 850;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.evidence-list { display: grid; gap: 11px; }
|
|
|
|
.file-row,
|
|
.claim-row {
|
|
padding: 12px 13px;
|
|
border: 1px solid rgba(220,236,255,0.11);
|
|
border-radius: 12px;
|
|
background: rgba(255,255,255,0.035);
|
|
color: #dfe9f6;
|
|
font: 0.88rem/1.42 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
}
|
|
|
|
.truth-sheet h3 {
|
|
margin: 0 0 12px;
|
|
font-size: 1.48rem;
|
|
line-height: 1.1;
|
|
letter-spacing: -0.045em;
|
|
}
|
|
|
|
.truth-sheet h4 {
|
|
margin: 18px 0 8px;
|
|
color: var(--green);
|
|
font-size: 0.96rem;
|
|
letter-spacing: -0.01em;
|
|
}
|
|
|
|
.truth-sheet p,
|
|
.truth-sheet li { color: var(--muted); line-height: 1.55; }
|
|
.truth-sheet ul { margin: 8px 0 0; padding-left: 18px; }
|
|
|
|
.add { color: #b8f5a4; }
|
|
.edit { color: #f5d37d; }
|
|
.move { color: #9fdcff; }
|
|
.quiet { color: #9dafc4; }
|
|
|
|
.split-view {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: 18px;
|
|
}
|
|
|
|
.lane {
|
|
padding: 26px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 24px;
|
|
background: var(--panel);
|
|
}
|
|
|
|
.lane h3 {
|
|
margin: 0 0 12px;
|
|
font-size: 1.7rem;
|
|
letter-spacing: -0.055em;
|
|
}
|
|
|
|
.lane p,
|
|
.lane li { color: var(--muted); line-height: 1.58; }
|
|
.lane ul { padding-left: 18px; }
|
|
|
|
.diagram {
|
|
margin-top: 28px;
|
|
padding: 24px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 26px;
|
|
background:
|
|
linear-gradient(135deg, rgba(142,230,107,0.08), transparent 38%),
|
|
rgba(255,255,255,0.035);
|
|
}
|
|
|
|
.diagram-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
|
gap: 12px;
|
|
align-items: center;
|
|
}
|
|
|
|
.diagram-cell {
|
|
min-height: 118px;
|
|
display: grid;
|
|
place-items: center;
|
|
padding: 14px;
|
|
border: 1px solid rgba(220,236,255,0.13);
|
|
border-radius: 18px;
|
|
background: rgba(4,12,22,0.58);
|
|
text-align: center;
|
|
color: var(--muted);
|
|
line-height: 1.38;
|
|
}
|
|
|
|
.diagram-cell strong { color: var(--text); display: block; margin-bottom: 6px; }
|
|
.arrow { color: var(--green); font-size: 1.8rem; text-align: center; }
|
|
|
|
.install {
|
|
display: grid;
|
|
grid-template-columns: 0.85fr 1.15fr;
|
|
gap: 22px;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.terminal {
|
|
border: 1px solid var(--line-strong);
|
|
border-radius: 24px;
|
|
background: rgba(3,9,18,0.78);
|
|
box-shadow: var(--shadow);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.terminal-top {
|
|
display: flex;
|
|
gap: 8px;
|
|
padding: 16px 18px;
|
|
border-bottom: 1px solid var(--line);
|
|
background: rgba(255,255,255,0.035);
|
|
}
|
|
|
|
.term-dot { width: 10px; height: 10px; border-radius: 999px; background: #5f6b7a; }
|
|
.term-dot:nth-child(2) { background: #94a0ae; }
|
|
.term-dot:nth-child(3) { background: var(--green); }
|
|
|
|
pre {
|
|
margin: 0;
|
|
padding: 25px;
|
|
color: #dfe9f6;
|
|
white-space: pre-wrap;
|
|
font: 500 0.97rem/1.78 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
}
|
|
|
|
.prompt { color: var(--green); }
|
|
.comment { color: var(--dim); }
|
|
|
|
.footer {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 24px;
|
|
padding: 44px 0 64px;
|
|
border-top: 1px solid rgba(220,236,255,0.08);
|
|
color: var(--dim);
|
|
}
|
|
|
|
.footer a { color: var(--text); text-decoration: none; }
|
|
|
|
@media (max-width: 1080px) {
|
|
.hero,
|
|
.timeline,
|
|
.panel-grid,
|
|
.split-view,
|
|
.install,
|
|
.page-intro,
|
|
.start-grid { grid-template-columns: 1fr; }
|
|
|
|
.page-intro { gap: 20px; }
|
|
.workflow-card { grid-column: span 6; }
|
|
.workflow-card:nth-child(5) { grid-column: span 12; }
|
|
|
|
.stage {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: 12px;
|
|
min-height: auto;
|
|
padding: 14px;
|
|
}
|
|
|
|
.stage::before,
|
|
.rail { display: none; }
|
|
|
|
.orbit {
|
|
position: relative;
|
|
inset: auto;
|
|
transform: none;
|
|
width: 100%;
|
|
box-shadow: 0 14px 34px rgba(0,0,0,0.2);
|
|
}
|
|
|
|
.orbit.core {
|
|
grid-column: 1 / -1;
|
|
left: auto;
|
|
top: auto;
|
|
order: -1;
|
|
transform: none;
|
|
width: 100%;
|
|
}
|
|
|
|
.node.a,
|
|
.node.b,
|
|
.node.c,
|
|
.node.d {
|
|
top: auto;
|
|
right: auto;
|
|
bottom: auto;
|
|
left: auto;
|
|
}
|
|
|
|
.map-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
.diagram-grid { grid-template-columns: 1fr; }
|
|
.arrow { transform: rotate(90deg); }
|
|
.evidence { border-right: 0; border-bottom: 1px solid var(--line); }
|
|
|
|
.nav-inner {
|
|
flex-wrap: wrap;
|
|
gap: 8px 14px;
|
|
padding: 10px 0 8px;
|
|
}
|
|
|
|
.page-tabs {
|
|
order: 3;
|
|
width: 100%;
|
|
overflow-x: auto;
|
|
border-radius: 16px;
|
|
scrollbar-width: none;
|
|
}
|
|
|
|
.page-tabs::-webkit-scrollbar { display: none; }
|
|
}
|
|
|
|
@media (max-width: 680px) {
|
|
body {
|
|
background:
|
|
radial-gradient(circle at 28% 0%, rgba(142, 230, 107, 0.15), transparent 19rem),
|
|
linear-gradient(180deg, #020812 0%, var(--ink) 42%, #050b12 100%);
|
|
}
|
|
|
|
body::before { background-size: 34px 34px; }
|
|
|
|
.shell { width: min(100% - 28px, 1240px); }
|
|
|
|
.nav-inner { min-height: 62px; }
|
|
.brand { gap: 10px; font-size: 0.98rem; }
|
|
.glyph { width: 32px; height: 32px; border-radius: 11px; }
|
|
.glyph-mark { width: 19px; height: 19px; }
|
|
|
|
.page-tab { min-height: 40px; padding: 0 13px; }
|
|
.nav-github { font-size: 0.82rem; }
|
|
|
|
.hero {
|
|
min-height: auto;
|
|
padding: 38px 0 54px;
|
|
gap: 28px;
|
|
}
|
|
|
|
.eyebrow {
|
|
max-width: 100%;
|
|
white-space: normal;
|
|
align-items: flex-start;
|
|
border-radius: 18px;
|
|
font-size: 0.82rem;
|
|
line-height: 1.35;
|
|
}
|
|
|
|
h1 {
|
|
margin: 18px 0 16px;
|
|
font-size: clamp(2.65rem, 14vw, 3.65rem);
|
|
line-height: 0.98;
|
|
letter-spacing: -0.058em;
|
|
}
|
|
|
|
.lead {
|
|
font-size: 1.04rem;
|
|
line-height: 1.52;
|
|
}
|
|
|
|
.hero-actions {
|
|
display: grid;
|
|
grid-template-columns: 1fr;
|
|
gap: 10px;
|
|
margin-top: 24px;
|
|
}
|
|
|
|
.button { width: 100%; min-height: 48px; }
|
|
|
|
.signals,
|
|
.map-grid,
|
|
.split-view,
|
|
.truth-anatomy { grid-template-columns: 1fr; }
|
|
|
|
.page-intro { padding: 44px 0 24px; }
|
|
.page-intro h1,
|
|
.page-intro h2 { font-size: clamp(2.45rem, 12vw, 3.4rem); }
|
|
.page-intro-copy p { font-size: 1rem; line-height: 1.55; }
|
|
|
|
.workflow-card,
|
|
.workflow-card:nth-child(4),
|
|
.workflow-card:nth-child(5) {
|
|
grid-column: span 12;
|
|
min-height: 220px;
|
|
padding: 18px;
|
|
border-radius: 18px;
|
|
}
|
|
|
|
.workflow-card .mode { margin-bottom: 30px; }
|
|
.anatomy-card { min-height: 190px; padding: 18px; border-radius: 18px; }
|
|
.anatomy-card h3 { margin-top: 42px; }
|
|
.start-card { padding: 18px; border-radius: 18px; }
|
|
.boundary-card { padding: 18px; border-radius: 18px; }
|
|
|
|
.signals { margin-top: 24px; gap: 10px; }
|
|
.signal { padding: 13px; border-radius: 14px; }
|
|
|
|
.stage {
|
|
grid-template-columns: 1fr;
|
|
padding: 14px;
|
|
border-radius: 24px;
|
|
}
|
|
|
|
.orbit.core {
|
|
padding: 18px;
|
|
border-radius: 20px;
|
|
}
|
|
|
|
.core h2 { font-size: 1.55rem; }
|
|
.core p { font-size: 0.96rem; }
|
|
|
|
.node {
|
|
width: 100%;
|
|
padding: 13px;
|
|
border-radius: 16px;
|
|
}
|
|
|
|
.route-line {
|
|
grid-template-columns: 12px minmax(0, 1fr);
|
|
gap: 8px;
|
|
padding: 10px;
|
|
font-size: 0.76rem;
|
|
}
|
|
|
|
.route-line span,
|
|
.route-line em {
|
|
min-width: 0;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.route-line em { grid-column: 2; }
|
|
|
|
.section { padding: 54px 0; }
|
|
.section-header { margin-bottom: 22px; }
|
|
|
|
h2.section-title,
|
|
.section-header h2 {
|
|
font-size: clamp(2.05rem, 11vw, 3rem);
|
|
line-height: 1.02;
|
|
letter-spacing: -0.055em;
|
|
}
|
|
|
|
.section-header p {
|
|
font-size: 1rem;
|
|
line-height: 1.55;
|
|
}
|
|
|
|
.surface-card {
|
|
min-height: auto;
|
|
padding: 18px;
|
|
border-radius: 18px;
|
|
}
|
|
|
|
.surface-card::after {
|
|
right: 14px;
|
|
bottom: 8px;
|
|
font-size: 3.2rem;
|
|
}
|
|
|
|
.timeline { gap: 12px; }
|
|
.tabs { gap: 9px; }
|
|
.tab { padding: 14px; border-radius: 15px; }
|
|
|
|
.panel {
|
|
min-height: auto;
|
|
border-radius: 20px;
|
|
}
|
|
|
|
.panel-head {
|
|
display: grid;
|
|
gap: 10px;
|
|
padding: 16px;
|
|
}
|
|
|
|
.panel-grid { min-height: auto; }
|
|
|
|
.evidence,
|
|
.truth-sheet { padding: 16px; }
|
|
|
|
.file-row,
|
|
.claim-row {
|
|
font-size: 0.78rem;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.truth-sheet h3 { font-size: 1.3rem; }
|
|
.truth-sheet p,
|
|
.truth-sheet li { line-height: 1.5; }
|
|
|
|
.lane { padding: 18px; border-radius: 18px; }
|
|
.lane h3 { font-size: 1.42rem; }
|
|
|
|
.diagram { padding: 16px; border-radius: 20px; }
|
|
.diagram-cell { min-height: auto; padding: 13px; }
|
|
|
|
.install { gap: 14px; }
|
|
.terminal { border-radius: 18px; }
|
|
.terminal-top { padding: 13px 15px; }
|
|
pre { padding: 16px; font-size: 0.8rem; line-height: 1.62; }
|
|
|
|
.footer {
|
|
flex-direction: column;
|
|
padding: 34px 0 46px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 420px) {
|
|
.shell { width: min(100% - 22px, 1240px); }
|
|
h1 { font-size: clamp(2.4rem, 13.6vw, 3.25rem); }
|
|
.stage { padding: 10px; }
|
|
.orbit.core,
|
|
.node,
|
|
.surface-card,
|
|
.lane,
|
|
.diagram { border-radius: 16px; }
|
|
.route-line { font-size: 0.72rem; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header class="nav">
|
|
<div class="shell nav-inner">
|
|
<a class="brand" href="#top" aria-label="Truthmark home">
|
|
<span class="glyph" aria-hidden="true">
|
|
<svg class="glyph-mark" viewBox="0 0 24 24"><path d="m5.5 12.4 4.1 4.1 8.9-9"></path></svg>
|
|
</span>
|
|
<span>Truthmark</span>
|
|
</a>
|
|
<nav class="page-tabs" role="tablist" aria-label="Truthmark pages">
|
|
<a class="page-tab" id="page-tab-overview" role="tab" aria-selected="true" aria-controls="page-overview" href="#overview" data-page-tab="overview">Overview</a>
|
|
<a class="page-tab" id="page-tab-workflows" role="tab" aria-selected="false" aria-controls="page-workflows" href="#workflows" data-page-tab="workflows">Workflows</a>
|
|
<a class="page-tab" id="page-tab-truth-model" role="tab" aria-selected="false" aria-controls="page-truth-model" href="#truth-model" data-page-tab="truth-model">Truth model</a>
|
|
<a class="page-tab" id="page-tab-get-started" role="tab" aria-selected="false" aria-controls="page-get-started" href="#get-started" data-page-tab="get-started">Get started</a>
|
|
</nav>
|
|
<a class="nav-github" href="https://github.com/merlinhu1/truthmark">GitHub ↗</a>
|
|
</div>
|
|
</header>
|
|
|
|
<main id="top">
|
|
<div class="page-view active" id="page-overview" role="tabpanel" aria-labelledby="page-tab-overview" data-page="overview">
|
|
<section class="shell hero">
|
|
<div>
|
|
<div class="eyebrow"><span class="pulse"></span>Repository truth carried by the branch</div>
|
|
<h1>The branch should explain itself.</h1>
|
|
<p class="lead">Truthmark gives AI-assisted work a reviewable truth layer: current claims, ownership routes, product promises, and implementation facts travel with the same Git branch as the code.</p>
|
|
<div class="hero-actions">
|
|
<a class="button primary" href="https://github.com/merlinhu1/truthmark">View on GitHub</a>
|
|
<a class="button" href="#workflows" data-page-link="workflows">Explore the workflows</a>
|
|
</div>
|
|
<ul class="signals">
|
|
<li class="signal"><strong>Checkout-native</strong><span>After setup, normal agent work can proceed from committed repository files.</span></li>
|
|
<li class="signal"><strong>Claim-level review</strong><span>Docs change as small, source-backed claims instead of anonymous summaries.</span></li>
|
|
<li class="signal"><strong>Topology aware</strong><span>When truth gets too broad, ownership gets repaired rather than hidden.</span></li>
|
|
<li class="signal"><strong>Host-shaped</strong><span>Instructions meet agents in their existing coding environments.</span></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<aside class="stage" aria-label="Original Truthmark concept illustration">
|
|
<div class="rail r1"></div><div class="rail r2"></div><div class="rail r3"></div><div class="rail r4"></div>
|
|
<div class="orbit node a"><strong>Code delta</strong><span>Changed files enter through the active checkout.</span></div>
|
|
<div class="orbit node b"><strong>Route owner</strong><span>The repo says which truth surface owns the claim.</span></div>
|
|
<div class="orbit node c"><strong>Human review</strong><span>Truth diffs sit beside implementation diffs.</span></div>
|
|
<div class="orbit node d"><strong>Agent host</strong><span>Codex, Claude Code, Copilot, Cursor, OpenCode, and peers read local guidance.</span></div>
|
|
<div class="orbit core">
|
|
<h2>Branch truth ledger</h2>
|
|
<p>A compact view of what this branch changed, which claims are affected, and which docs need curation before handoff.</p>
|
|
<div class="route-line"><i></i><span>src/webhooks/retry.ts</span><em>engineering/webhook-delivery.md</em></div>
|
|
<div class="route-line"><i></i><span>README reliability copy</span><em>product/webhook-reliability.md</em></div>
|
|
<div class="route-line"><i></i><span>operator replay UI</span><em>engineering/webhook-replay.md</em></div>
|
|
</div>
|
|
</aside>
|
|
</section>
|
|
|
|
<section id="surface-map" class="shell section">
|
|
<div class="section-header">
|
|
<h2>More than a docs generator.</h2>
|
|
<p>Truthmark is best understood as a repository-truth workflow surface. The value is not one feature; it is how several constraints reinforce each other.</p>
|
|
</div>
|
|
<div class="map-grid">
|
|
<article class="surface-card" data-index="01"><span class="mini-kicker">Operation</span><h3>No resident service in the critical path</h3><p>Helpers can validate and refresh, but the daily closeout path is designed to remain readable from the checkout.</p></article>
|
|
<article class="surface-card" data-index="02"><span class="mini-kicker">Continuity</span><h3>Truth is maintained after the first draft</h3><p>Code changes keep revisiting the mapped docs, so documentation becomes a living review artifact rather than a launch-week export.</p></article>
|
|
<article class="surface-card" data-index="03"><span class="mini-kicker">Architecture</span><h3>Routes make ownership explicit</h3><p>Files, areas, and truth docs are connected by committed routing metadata instead of implicit tribal knowledge.</p></article>
|
|
<article class="surface-card" data-index="04"><span class="mini-kicker">Governance</span><h3>Product truth and mechanics do not collapse together</h3><p>User-facing promises can link to implementation reality without becoming the same document.</p></article>
|
|
<article class="surface-card" data-index="05"><span class="mini-kicker">Review</span><h3>Claims are small enough for Git</h3><p>The desired unit is a durable claim per line or bullet, making truth updates easy to inspect in pull requests.</p></article>
|
|
<article class="surface-card" data-index="06"><span class="mini-kicker">Portability</span><h3>Agent guidance follows the repo</h3><p>Generated skills, prompts, commands, and instruction blocks are committed where the agent can read them.</p></article>
|
|
<article class="surface-card" data-index="07"><span class="mini-kicker">Repair</span><h3>Overgrown docs trigger structure work</h3><p>When a file starts mixing owners, Truth Structure is the product answer, not a larger paragraph.</p></article>
|
|
<article class="surface-card" data-index="08"><span class="mini-kicker">Boundary</span><h3>Repository files outrank session memory</h3><p>Current truth lives where maintainers can diff, revert, blame, and review it.</p></article>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<div class="page-view" id="page-workflows" role="tabpanel" aria-labelledby="page-tab-workflows" data-page="workflows">
|
|
<section class="shell page-intro">
|
|
<div><span class="page-note">Workflow field guide</span><h2>Five workflows. One reviewable loop.</h2></div>
|
|
<div class="page-intro-copy"><p>Truthmark does not turn every activity into a command. Three workflows are clear user entry points; Sync closes functional code changes; Structure appears only when ownership needs repair.</p></div>
|
|
</section>
|
|
|
|
<section class="shell section">
|
|
<div class="workflow-deck">
|
|
<article class="workflow-card"><span class="mode">You start · truth writes</span><code>/truthmark-document</code><h3>Document what already exists</h3><p>Read implementation and tests, then create or update bounded truth docs without changing functional code.</p></article>
|
|
<article class="workflow-card"><span class="mode">You start · code writes</span><code>/truthmark-realize</code><h3>Turn accepted truth into code</h3><p>Use product truth as requirements and engineering truth as implementation context. The source docs remain unchanged.</p></article>
|
|
<article class="workflow-card"><span class="mode">You start · read only</span><code>/truthmark-check</code><h3>Audit before review</h3><p>Inspect routing, evidence, lane shape, and truth health without authorizing writes.</p></article>
|
|
<article class="workflow-card sync"><span class="mode">Agent finish-time · truth writes</span><code>Truth Sync</code><h3>Close the branch honestly</h3><p>After functional code changes, review mapped truth, capture supported decisions, and update or explicitly leave claims unchanged with evidence.</p></article>
|
|
<article class="workflow-card"><span class="mode">Only when needed · topology</span><code>Truth Structure</code><h3>Repair ownership before adding prose</h3><p>Split broad routes and overgrown docs when the repository can no longer identify a bounded owner.</p></article>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="storyboard" class="shell section">
|
|
<div class="section-header">
|
|
<h2>A truth document over time.</h2>
|
|
<p>This demo is fictional, but the workflow is concrete: create the right doc, update it when behavior changes, and split it when ownership gets crowded.</p>
|
|
</div>
|
|
<div class="timeline">
|
|
<div class="tabs" role="tablist" aria-label="Truth document curation timeline">
|
|
<button class="tab" type="button" role="tab" aria-selected="true" aria-controls="panel-1" id="tab-1"><strong>Episode 1 · New invariant</strong>A retry policy appears in code and needs a current-state owner.</button>
|
|
<button class="tab" type="button" role="tab" aria-selected="false" aria-controls="panel-2" id="tab-2"><strong>Episode 2 · Promise pressure</strong>Marketing copy changes; product truth and engineering truth diverge.</button>
|
|
<button class="tab" type="button" role="tab" aria-selected="false" aria-controls="panel-3" id="tab-3"><strong>Episode 3 · Ownership split</strong>Replay, delivery, audit, and alerts no longer belong in one file.</button>
|
|
<button class="tab" type="button" role="tab" aria-selected="false" aria-controls="panel-4" id="tab-4"><strong>Episode 4 · Reviewer packet</strong>The pull request shows implementation, evidence, and truth changes together.</button>
|
|
</div>
|
|
|
|
<article class="panel active" role="tabpanel" id="panel-1" aria-labelledby="tab-1">
|
|
<div class="panel-head"><strong>Truth Document creates a narrow engineering owner.</strong><span class="status-pill">created</span></div>
|
|
<div class="panel-grid">
|
|
<div class="evidence"><span class="label">Evidence read</span><div class="evidence-list"><div class="file-row">src/webhooks/retry-policy.ts</div><div class="file-row">tests/webhooks/retry-policy.test.ts</div><div class="file-row">config/webhook-delivery.yml</div></div></div>
|
|
<div class="truth-sheet"><span class="label">Created doc</span><h3>Webhook delivery behavior</h3><h4>Current behavior</h4><ul><li class="add">Failed deliveries are retried three times.</li><li class="add">Backoff starts at 30 seconds and doubles per attempt.</li><li class="add">Manual replay remains available after automatic retries stop.</li></ul><h4>Non-goals</h4><ul><li class="quiet">The service does not claim exactly-once delivery.</li></ul></div>
|
|
</div>
|
|
</article>
|
|
|
|
<article class="panel" role="tabpanel" id="panel-2" aria-labelledby="tab-2">
|
|
<div class="panel-head"><strong>Truth Sync separates a user promise from runtime mechanics.</strong><span class="status-pill">curated</span></div>
|
|
<div class="panel-grid">
|
|
<div class="evidence"><span class="label">Branch changes</span><div class="evidence-list"><div class="file-row">README.md adds operator reliability copy</div><div class="file-row">src/webhooks/replay-audit.ts</div><div class="file-row">tests/webhooks/replay-audit.test.ts</div></div></div>
|
|
<div class="truth-sheet"><span class="label">Two updated surfaces</span><h3>Product promise vs implementation fact</h3><h4>Product truth</h4><ul><li class="add">Operators can inspect failed delivery history before replay.</li><li class="add">The product presents replay as an operator recovery tool, not an automatic guarantee.</li></ul><h4>Engineering truth</h4><ul><li class="edit">Replay writes an audit row with actor, delivery id, and timestamp.</li><li class="quiet">The retry limit remains unchanged.</li></ul></div>
|
|
</div>
|
|
</article>
|
|
|
|
<article class="panel" role="tabpanel" id="panel-3" aria-labelledby="tab-3">
|
|
<div class="panel-head"><strong>Truth Structure changes the shape before prose gets heavier.</strong><span class="status-pill">split</span></div>
|
|
<div class="panel-grid">
|
|
<div class="evidence"><span class="label">Topology pressure</span><div class="evidence-list"><div class="file-row">delivery retries + manual replay + alert thresholds + export audit</div><div class="file-row">one doc now has four owners</div><div class="file-row">future edits would be ambiguous</div></div></div>
|
|
<div class="truth-sheet"><span class="label">New ownership map</span><h3>Owned docs after split</h3><ul><li class="move">engineering/webhook-delivery.md owns retry and delivery lifecycle.</li><li class="move">engineering/webhook-replay.md owns operator replay behavior.</li><li class="move">engineering/webhook-audit.md owns audit rows and export format.</li><li class="move">product/webhook-reliability.md owns customer-facing recovery promises.</li></ul></div>
|
|
</div>
|
|
</article>
|
|
|
|
<article class="panel" role="tabpanel" id="panel-4" aria-labelledby="tab-4">
|
|
<div class="panel-head"><strong>The reviewer sees a small packet, not a mystery transcript.</strong><span class="status-pill">review</span></div>
|
|
<div class="panel-grid">
|
|
<div class="evidence"><span class="label">Pull request surface</span><div class="evidence-list"><div class="file-row">code diff: retry + replay behavior</div><div class="file-row">test diff: replay audit coverage</div><div class="file-row">truth diff: product + engineering docs</div><div class="file-row">route diff: ownership split</div></div></div>
|
|
<div class="truth-sheet"><span class="label">Reviewer questions</span><h3>What the PR now answers</h3><ul><li class="add">Which user promise changed?</li><li class="add">Which implementation behavior supports it?</li><li class="add">Which files own future updates?</li><li class="add">Which claims should be rejected if the code changes again?</li></ul></div>
|
|
</div>
|
|
</article>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<div class="page-view" id="page-truth-model" role="tabpanel" aria-labelledby="page-tab-truth-model" data-page="truth-model">
|
|
<section class="shell page-intro">
|
|
<div><span class="page-note">Repository truth model</span><h2>Keep the promise and the mechanism in different rooms.</h2></div>
|
|
<div class="page-intro-copy"><p>Truthmark links what users can rely on to how the repository currently realizes it. The relationship is explicit, but neither document inherits authority from the other.</p></div>
|
|
</section>
|
|
|
|
<section id="lanes" class="shell section">
|
|
<div class="section-header"><h2>Two lanes, linked on purpose.</h2><p>Truthmark can let product and engineering documents reference each other without forcing them into the same voice or authority level.</p></div>
|
|
<div class="split-view">
|
|
<article class="lane"><span class="mini-kicker">Promise lane</span><h3>What the project says users can rely on</h3><p>This lane is for product capabilities, boundaries, acceptance criteria, and non-goals.</p><ul><li>Operators can inspect replay history.</li><li>The workflow is repository-native by default.</li><li>Generated presentation pages are not canonical truth.</li></ul></article>
|
|
<article class="lane"><span class="mini-kicker">Mechanics lane</span><h3>What the current implementation actually does</h3><p>This lane is for runtime behavior, contracts, operations, architecture, and failure modes.</p><ul><li>Backoff doubles after each failed delivery attempt.</li><li>GitHub Pages deploys the committed static site under site/**.</li><li>Generated surfaces refresh when rendered content changes.</li></ul></article>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="shell section">
|
|
<div class="section-header"><h2>Three committed layers make the handoff legible.</h2><p>The route map decides ownership, truth docs preserve current claims, and host-native guidance tells the coding agent when each surface may change.</p></div>
|
|
<div class="truth-anatomy">
|
|
<article class="anatomy-card" data-step="01"><span class="mini-kicker">Route</span><h3>Find the bounded owner</h3><p>Changed paths map to an area and its canonical product or engineering truth docs.</p></article>
|
|
<article class="anatomy-card" data-step="02"><span class="mini-kicker">Truth</span><h3>Preserve the claim</h3><p>Human-facing Markdown records current behavior, rationale, boundaries, and evidence in the right lane.</p></article>
|
|
<article class="anatomy-card" data-step="03"><span class="mini-kicker">Guidance</span><h3>Meet the agent in its host</h3><p>Committed skills, prompts, commands, and instruction blocks carry write boundaries into normal coding work.</p></article>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="review-path" class="shell section">
|
|
<div class="section-header"><h2>The workflow is deliberately boring at runtime.</h2><p>Truthmark's ambition is in the repository model, not in requiring every contributor to adopt a new always-on system.</p></div>
|
|
<div class="diagram">
|
|
<div class="diagram-grid" role="img" aria-label="Truthmark workflow diagram">
|
|
<div class="diagram-cell"><strong>1. Setup</strong><span>Configure routes and install agent-facing surfaces.</span></div>
|
|
<div class="arrow">→</div>
|
|
<div class="diagram-cell"><strong>2. Work</strong><span>Agent changes code in its normal host.</span></div>
|
|
<div class="arrow">→</div>
|
|
<div class="diagram-cell"><strong>3. Closeout</strong><span>Mapped truth docs are checked, edited, split, or left unchanged with evidence.</span></div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
|
|
<div class="page-view" id="page-get-started" role="tabpanel" aria-labelledby="page-tab-get-started" data-page="get-started">
|
|
<section class="shell page-intro">
|
|
<div><span class="page-note">Adoption path</span><h2>Install the contract, then get out of the way.</h2></div>
|
|
<div class="page-intro-copy"><p>Choose the agent host your team already uses. Truthmark commits its guidance, routes, and truth docs to the repository, so the next branch can continue without a background service.</p></div>
|
|
</section>
|
|
|
|
<section id="install" class="shell section install">
|
|
<div class="section-header"><h2>Start with the repo, not a server.</h2><p>Install once, commit the workflow surface, and let future branches carry their truth updates through normal review.</p></div>
|
|
<section class="terminal" aria-label="Install commands"><div class="terminal-top"><span class="term-dot"></span><span class="term-dot"></span><span class="term-dot"></span></div><pre><span class="prompt">$</span> cd /path/to/your-repo
|
|
<span class="prompt">$</span> npm install -g truthmark
|
|
<span class="prompt">$</span> truthmark config
|
|
<span class="comment"># Add the host you use to .truthmark/config.yml, for example: platforms: [codex]</span>
|
|
<span class="prompt">$</span> truthmark init
|
|
<span class="prompt">$</span> truthmark check
|
|
|
|
<span class="comment"># After setup, agent guidance and truth routes live in the checkout.</span></pre></section>
|
|
</section>
|
|
|
|
<section class="shell section">
|
|
<div class="start-grid">
|
|
<article class="start-card">
|
|
<span class="mini-kicker">What lands in the repo</span>
|
|
<h3>A small contract with visible parts</h3>
|
|
<p>Every durable surface can be reviewed, blamed, reverted, and carried by the branch.</p>
|
|
<div class="start-list">
|
|
<div class="start-item"><b>1</b><div><strong>Config and routes</strong><span>Choose platforms and map code areas to bounded truth owners.</span></div></div>
|
|
<div class="start-item"><b>2</b><div><strong>Human-facing truth</strong><span>Keep product capabilities and engineering reality separate but linked.</span></div></div>
|
|
<div class="start-item"><b>3</b><div><strong>Host-native guidance</strong><span>Install the workflow shape where your coding agent already looks.</span></div></div>
|
|
</div>
|
|
</article>
|
|
<article class="start-card">
|
|
<span class="mini-kicker">Choose your first move</span>
|
|
<h3>Begin with one bounded area</h3>
|
|
<p>Document one implemented behavior with code and test evidence. Then keep coding normally and let finish-time Sync review future changes.</p>
|
|
<ul class="host-cloud">
|
|
<li class="host-chip">Codex</li><li class="host-chip">Claude Code</li><li class="host-chip">GitHub Copilot</li><li class="host-chip">OpenCode</li><li class="host-chip">Antigravity</li><li class="host-chip">Cursor</li>
|
|
</ul>
|
|
<div class="hero-actions"><a class="button primary" href="https://github.com/merlinhu1/truthmark#-quick-start-running-locally-in-five-minutes">Read the quick start</a><a class="button" href="https://github.com/merlinhu1/truthmark/blob/main/docs/user-guide.md">Open the user guide</a></div>
|
|
</article>
|
|
</div>
|
|
<div class="boundary-card"><strong>Presentation is not authority.</strong><p>This website explains the product. Canonical behavior remains in the repository's README, routed truth docs, source, tests, and configuration. Truthmark adds no required daemon, database, hosted service, or hidden memory layer.</p></div>
|
|
</section>
|
|
</div>
|
|
</main>
|
|
|
|
<footer class="shell footer"><div>Truthmark keeps current repository truth reviewable where code review already happens.</div><div><a href="https://github.com/merlinhu1/truthmark">GitHub</a> · <a href="https://github.com/merlinhu1/truthmark/blob/main/docs/user-guide.md">User guide</a></div></footer>
|
|
|
|
<script>
|
|
const pageTabs = Array.from(document.querySelectorAll('[data-page-tab]'));
|
|
const pageViews = Array.from(document.querySelectorAll('[data-page]'));
|
|
const pageLinks = Array.from(document.querySelectorAll('[data-page-link]'));
|
|
const pageTitles = {
|
|
overview: 'Truthmark — the branch explains itself',
|
|
workflows: 'Truthmark workflows — a reviewable loop',
|
|
'truth-model': 'Truthmark truth model — routes, lanes, and guidance',
|
|
'get-started': 'Get started with Truthmark'
|
|
};
|
|
|
|
function activatePage(name, { updateHash = false, focus = false, scroll = false } = {}) {
|
|
const selectedName = pageViews.some((view) => view.dataset.page === name) ? name : 'overview';
|
|
pageTabs.forEach((tab) => {
|
|
const selected = tab.dataset.pageTab === selectedName;
|
|
tab.setAttribute('aria-selected', String(selected));
|
|
tab.tabIndex = selected ? 0 : -1;
|
|
if (selected && focus) tab.focus();
|
|
});
|
|
pageViews.forEach((view) => {
|
|
const selected = view.dataset.page === selectedName;
|
|
view.classList.toggle('active', selected);
|
|
view.hidden = !selected;
|
|
});
|
|
document.title = pageTitles[selectedName];
|
|
const selectedTab = pageTabs.find((tab) => tab.dataset.pageTab === selectedName);
|
|
if (selectedTab && window.innerWidth <= 1080) {
|
|
requestAnimationFrame(() => selectedTab.scrollIntoView({ block: 'nearest', inline: 'center' }));
|
|
}
|
|
if (updateHash) history.pushState(null, '', `#${selectedName}`);
|
|
if (scroll) window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
}
|
|
|
|
pageTabs.forEach((tab) => {
|
|
tab.addEventListener('click', (event) => {
|
|
event.preventDefault();
|
|
activatePage(tab.dataset.pageTab, { updateHash: true, scroll: true });
|
|
});
|
|
tab.addEventListener('keydown', (event) => {
|
|
const index = pageTabs.indexOf(tab);
|
|
let nextIndex = null;
|
|
if (event.key === 'ArrowRight') nextIndex = (index + 1) % pageTabs.length;
|
|
if (event.key === 'ArrowLeft') nextIndex = (index - 1 + pageTabs.length) % pageTabs.length;
|
|
if (event.key === 'Home') nextIndex = 0;
|
|
if (event.key === 'End') nextIndex = pageTabs.length - 1;
|
|
if (nextIndex === null) return;
|
|
event.preventDefault();
|
|
activatePage(pageTabs[nextIndex].dataset.pageTab, { updateHash: true, focus: true, scroll: true });
|
|
});
|
|
});
|
|
|
|
pageLinks.forEach((link) => {
|
|
link.addEventListener('click', (event) => {
|
|
event.preventDefault();
|
|
activatePage(link.dataset.pageLink, { updateHash: true, scroll: true });
|
|
});
|
|
});
|
|
|
|
window.addEventListener('hashchange', () => activatePage(location.hash.slice(1)));
|
|
activatePage(location.hash.slice(1));
|
|
|
|
const storyTabs = Array.from(document.querySelectorAll('.timeline [role="tab"]'));
|
|
const storyPanels = Array.from(document.querySelectorAll('.timeline [role="tabpanel"]'));
|
|
|
|
function selectStoryTab(tab) {
|
|
storyTabs.forEach((item) => item.setAttribute('aria-selected', String(item === tab)));
|
|
storyPanels.forEach((panel) => panel.classList.toggle('active', panel.id === tab.getAttribute('aria-controls')));
|
|
}
|
|
|
|
storyTabs.forEach((tab) => {
|
|
tab.addEventListener('click', () => selectStoryTab(tab));
|
|
tab.addEventListener('keydown', (event) => {
|
|
const index = storyTabs.indexOf(tab);
|
|
if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {
|
|
event.preventDefault();
|
|
const next = storyTabs[(index + 1) % storyTabs.length];
|
|
next.focus();
|
|
selectStoryTab(next);
|
|
}
|
|
if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {
|
|
event.preventDefault();
|
|
const previous = storyTabs[(index - 1 + storyTabs.length) % storyTabs.length];
|
|
previous.focus();
|
|
selectStoryTab(previous);
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|