diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8825e7cc..d251a80b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,8 +48,11 @@ jobs: - name: Install run: npm install --ignore-scripts - - name: Unit tests - run: npm test + - name: Lint (Biome) + run: npm run lint + + - name: Unit tests (with coverage) + run: npm run test:coverage - name: Static check CLI entrypoint run: node --check bin/multiagent-safety.js diff --git a/biome.json b/biome.json new file mode 100644 index 00000000..f23eb815 --- /dev/null +++ b/biome.json @@ -0,0 +1,67 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": true, + "include": ["bin/**/*.js", "src/**/*.js", "scripts/**/*.js", "test/**/*.js"], + "ignore": [ + "**/node_modules/**", + "**/.next/**", + "frontend/**", + "templates/**", + "examples/**", + "**/*.min.js" + ] + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineWidth": 100 + }, + "javascript": { + "formatter": { + "quoteStyle": "single", + "semicolons": "always", + "trailingCommas": "none" + } + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "complexity": { + "noForEach": "off", + "useOptionalChain": "off", + "noMultipleSpacesInRegularExpressionLiterals": "off", + "useRegexLiterals": "off" + }, + "correctness": { + "noUnnecessaryContinue": "off" + }, + "performance": { + "noDelete": "off" + }, + "style": { + "noUselessElse": "off", + "useNodejsImportProtocol": "off", + "useTemplate": "off", + "noUnusedTemplateLiteral": "off", + "useConst": "off", + "useDefaultParameterLast": "off", + "useNumberNamespace": "off", + "noArguments": "off" + }, + "suspicious": { + "noExplicitAny": "off", + "noAssignInExpressions": "off", + "noRedundantUseStrict": "off", + "noControlCharactersInRegex": "off" + } + } + } +} diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index c45d4cf6..79f9d486 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -1,9 +1,112 @@ -import type { Metadata } from 'next' +import type { Metadata, Viewport } from 'next' import './globals.css' +// Canonical site origin. Override per-deployment with NEXT_PUBLIC_SITE_URL +// (e.g. the production domain). Falls back to the project home so OpenGraph +// and canonical URLs always resolve to a real, reachable page. +const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? 'https://github.com/recodeee/gitguardex' +const OG_IMAGE = 'https://raw.githubusercontent.com/recodeee/gitguardex/main/logo.png' + +const TITLE = 'GitGuardex — Guardian T-Rex for Multi-Agent Repos' +const DESCRIPTION = + 'GitGuardex gives parallel Codex, Claude, and human teammates isolated git worktrees, file locks, and PR-only merges so concurrent AI agents never overwrite each other’s work.' + export const metadata: Metadata = { - title: 'GitGuardex | How It Works', - description: 'A workflow-style GitGuardex onboarding preview built with Next.js.' + metadataBase: new URL(SITE_URL), + title: { + default: TITLE, + template: '%s | GitGuardex' + }, + description: DESCRIPTION, + applicationName: 'GitGuardex', + authors: [{ name: 'recodee', url: 'https://github.com/recodeee' }], + creator: 'recodee', + publisher: 'recodee', + category: 'developer tools', + keywords: [ + 'GitGuardex', + 'guardex', + 'multi-agent', + 'AI agents', + 'Codex', + 'Claude Code', + 'git worktree', + 'file locks', + 'branch guard', + 'agent safety', + 'pull request workflow', + 'OpenSpec', + 'developer tools', + 'CLI' + ], + alternates: { + canonical: '/' + }, + openGraph: { + type: 'website', + siteName: 'GitGuardex', + title: TITLE, + description: DESCRIPTION, + url: SITE_URL, + images: [ + { + url: OG_IMAGE, + width: 1200, + height: 630, + alt: 'GitGuardex — guardian T-Rex for multi-agent repos' + } + ] + }, + twitter: { + card: 'summary_large_image', + title: TITLE, + description: DESCRIPTION, + images: [OG_IMAGE] + }, + robots: { + index: true, + follow: true, + googleBot: { + index: true, + follow: true, + 'max-image-preview': 'large', + 'max-snippet': -1, + 'max-video-preview': -1 + } + } +} + +export const viewport: Viewport = { + themeColor: '#0b0e14', + colorScheme: 'dark light' +} + +// Structured data so search engines and generative engines (GEO) can model +// GitGuardex as an installable developer tool with a clear description. +const jsonLd = { + '@context': 'https://schema.org', + '@type': 'SoftwareApplication', + name: 'GitGuardex', + alternateName: 'guardex', + applicationCategory: 'DeveloperApplication', + operatingSystem: 'macOS, Linux, Windows', + description: DESCRIPTION, + url: SITE_URL, + image: OG_IMAGE, + license: 'https://opensource.org/licenses/MIT', + softwareHelp: 'https://github.com/recodeee/gitguardex#readme', + installUrl: 'https://www.npmjs.com/package/@imdeadpool/guardex', + downloadUrl: 'https://www.npmjs.com/package/@imdeadpool/guardex', + author: { + '@type': 'Organization', + name: 'recodee', + url: 'https://github.com/recodeee' + }, + offers: { + '@type': 'Offer', + price: '0', + priceCurrency: 'USD' + } } export default function RootLayout({ @@ -13,7 +116,14 @@ export default function RootLayout({ }>) { return ( -
{children} + + + {children} + ) } diff --git a/frontend/app/robots.ts b/frontend/app/robots.ts new file mode 100644 index 00000000..4700a66a --- /dev/null +++ b/frontend/app/robots.ts @@ -0,0 +1,14 @@ +import type { MetadataRoute } from 'next' + +const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? 'https://github.com/recodeee/gitguardex' + +export default function robots(): MetadataRoute.Robots { + return { + rules: { + userAgent: '*', + allow: '/' + }, + sitemap: `${SITE_URL}/sitemap.xml`, + host: SITE_URL + } +} diff --git a/frontend/app/sitemap.ts b/frontend/app/sitemap.ts new file mode 100644 index 00000000..961295c1 --- /dev/null +++ b/frontend/app/sitemap.ts @@ -0,0 +1,15 @@ +import type { MetadataRoute } from 'next' + +const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? 'https://github.com/recodeee/gitguardex' + +export default function sitemap(): MetadataRoute.Sitemap { + const now = new Date() + return [ + { + url: SITE_URL, + lastModified: now, + changeFrequency: 'weekly', + priority: 1 + } + ] +} diff --git a/frontend/public/llms.txt b/frontend/public/llms.txt new file mode 100644 index 00000000..7b921c30 --- /dev/null +++ b/frontend/public/llms.txt @@ -0,0 +1,43 @@ +# GitGuardex + +> Guardian T-Rex for multi-agent repos. GitGuardex gives parallel Codex, +> Claude, and human teammates isolated git worktrees, file locks, and +> PR-only merges so concurrent AI agents never overwrite each other's work. + +GitGuardex (CLI commands: `gx`, `guardex`, `gitguardex`) is an MIT-licensed +Node.js tool published to npm as `@imdeadpool/guardex`. It auto-wires Oh My +Codex, Oh My Claude, OpenSpec, and Caveman into a repository. + +## What it does + +- **Isolated worktrees** — every agent task runs on its own `agent/*` branch + in a dedicated git worktree, never on the protected base (`main`/`dev`). +- **File locks** — agents claim files before editing (`gx locks claim`) so two + agents cannot edit the same path concurrently. +- **PR-only merges** — completed work lands through pull requests via + `gx branch finish --via-pr --wait-for-merge --cleanup`, never direct pushes. +- **Multi-agent cockpit** — a tmux/kitty-style cockpit (`gx`) shows live agent + status, ownership, and conflicts across the repo. + +## Install + +```bash +npm i -g @imdeadpool/guardex +cd /path/to/your-repo +gx setup +``` + +## Key commands + +- `gx setup` — install hooks, state, and OMX / OpenSpec / Caveman wiring. +- `gx branch start "