diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 18240ba..55609fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,4 +16,24 @@ jobs: - name: Contract tests run: npm test - name: Link check - run: node Scripts/check-markdown-links.js \ No newline at end of file + run: node Scripts/check-markdown-links.js + + # Validate that the GitHub Pages site builds without warnings on every + # push/PR. `mkdocs build --strict` fails on any broken link or warning, so + # this is the site-validation gate; the deploy workflow (deploy-site.yml) + # reuses the same steps on main. + docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + - name: Install site build deps + run: pip install -r requirements.txt + - name: Assemble site source + run: node Scripts/assemble-site-source.js + - name: Build site (strict) + run: mkdocs build --strict + - name: Generate llms.txt files + run: node Scripts/generate-llms.js \ No newline at end of file diff --git a/.github/workflows/deploy-site.yml b/.github/workflows/deploy-site.yml new file mode 100644 index 0000000..8a8d5c0 --- /dev/null +++ b/.github/workflows/deploy-site.yml @@ -0,0 +1,63 @@ +name: Deploy documentation site + +# Builds the MkDocs site (plus robots.txt, sitemap.xml, llms.txt and +# llms-full.txt) and publishes it to GitHub Pages. Runs on pushes to main and +# can be triggered manually after enabling Pages with `build_type=workflow`. +# +# Site source of truth: the repository's own markdown, staged into a gitignored +# docs/ by Scripts/assemble-site-source.js (MkDocs requires docs_dir to be a +# child directory). The repo root remains the single source of truth; this +# workflow is the only place the site is assembled and deployed. + +on: + push: + branches: [main] + workflow_dispatch: + +# Pages deployments must use the built-in pages token with this exact set. +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: true + +jobs: + deploy: + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - uses: actions/checkout@v4 + + - name: Configure Pages + id: pages + uses: actions/configure-pages@v5 + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install site build deps + run: pip install -r requirements.txt + + - name: Assemble site source + run: node Scripts/assemble-site-source.js + + - name: Build site (strict) + run: mkdocs build --strict + + - name: Generate llms.txt files + run: node Scripts/generate-llms.js + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: site + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index d4a76cf..818f980 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,7 @@ # Node node_modules/ npm-debug.log* + +# Generated docs site staging + output (built by CI; see mkdocs.yml) +docs/ +site/ diff --git a/README.md b/README.md index 86ed239..87c3a81 100644 --- a/README.md +++ b/README.md @@ -3,17 +3,20 @@ **AI Engineering Lab** is a personal research and development space for understanding AI engineering systems, developer tooling, LLM infrastructure, -observability, and workflow automation. It exists to document work as it -happens — how each project is investigated, verified, and built — and to keep -that record with the finished result. The **Provider-Aware Statusline** is the -lab's first public flagship project: a statusline for Claude Code behind the -OmniRoute routing gateway that shows which provider actually answered your -request. The research, findings, architecture, and ADRs in this repository are -the trail of how that project was investigated and built, kept alongside the -code rather than hidden away. See [Origin-Story.md](Origin-Story.md) for how -the lab started and why this project exists. - -[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE) [![Tests: 68/68](https://img.shields.io/badge/tests-68%2F68-brightgreen.svg?style=flat)](Statusline/test/statusline.test.js) [![Node: >=18](https://img.shields.io/badge/node-%3E%3D18-blue.svg?style=flat)](package.json) [![Dependencies: 0](https://img.shields.io/badge/dependencies-0-brightgreen.svg?style=flat)](package.json) +observability, and workflow automation. Its flagship project, the +**Provider-Aware Statusline**, is a statusline for Claude Code behind the +OmniRoute LLM routing gateway that shows which provider and model actually +served your request. This repository keeps the evidence-first trail of how that +project was investigated and built — research, findings, architecture, and +ADRs — alongside the code, rather than hidden away. See +[Origin-Story.md](Origin-Story.md) for how the lab started and why this project +exists. + +**Hosted documentation (for humans and AI agents):** +[unscriptedbykramy.github.io/AI-Engineering-Lab](https://unscriptedbykramy.github.io/AI-Engineering-Lab/) +— rendered docs, full-text for AI agents (`llms.txt`), and search. + +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE) [![Tests: 68/68](https://img.shields.io/badge/tests-68%2F68-brightgreen.svg?style=flat)](https://github.com/UnscriptedByKraMy/AI-Engineering-Lab/blob/main/Statusline/test/statusline.test.js) [![Node: >=18](https://img.shields.io/badge/node-%3E%3D18-blue.svg?style=flat)](package.json) [![Dependencies: 0](https://img.shields.io/badge/dependencies-0-brightgreen.svg?style=flat)](package.json) Provider-Aware Statusline: 🤖 opencode/big-pickle | ▓▓▓▓░░░░░░ 42% | 🪟 110K/262K | ⇡1.5K⇣820 | 🌿 feature/ctx-window ✏️ @@ -39,6 +42,38 @@ The current implementation targets Claude Code behind OmniRoute, but the underly - **Degrades gracefully** — on every failure path it falls back to model-only or the requested label; it never crashes, never guesses, and never leaks tokens or prompts. +## FAQ + +**Which provider/model actually served my request?** +The statusline shows the resolved route from the session transcript — e.g. +`opencode/big-pickle` — not the requested label. `auto/cheap` is what you asked +for; `opencode/big-pickle` is what answered. + +**How does the statusline know which model answered?** +It reads the last assistant message's `model` field from the local session +transcript (JSONL) and resolves the provider and real context window from a +local empirical mapping. It is a reader, not an inferrer — see +[Architecture.md](Architecture.md) for the verified data flow. + +**Does it read my prompts or tokens?** +Never. It reads only the session transcript and a local mapping file — no +tokens, prompts, request bodies, or gateway credentials. It never writes +anything and never makes network requests. + +**Do I need OmniRoute or Docker?** +No for the statusline itself: it only reads local files and works without a +gateway (it then omits the provider). Docker is needed only for the optional +out-of-band mapping-refresh script. + +**What is AI Engineering Lab?** +The evidence-first research and development space this repository documents. +See [Origin-Story.md](Origin-Story.md) for how it started. + +**Where is the hosted documentation?** +The rendered docs site: +[unscriptedbykramy.github.io/AI-Engineering-Lab](https://unscriptedbykramy.github.io/AI-Engineering-Lab/) +— with full text for AI agents via [`llms.txt`](https://unscriptedbykramy.github.io/AI-Engineering-Lab/llms.txt). + ## Try it in three steps 1. **Clone** this repository. @@ -190,6 +225,7 @@ tools couldn't answer it, and how it became a reusable tool. | Path | Purpose | |---|---| | `README.md` | Project overview and operating principles | +| **Hosted site** | Rendered documentation, search, and full text for AI agents (`llms.txt`) at [unscriptedbykramy.github.io/AI-Engineering-Lab](https://unscriptedbykramy.github.io/AI-Engineering-Lab/) | | `Origin-Story.md` | How this project started and why it exists | | `Roadmap.md` | Phases, gates, deliverables, and next actions | | `Knowledge-Base.md` | Consolidated verified knowledge and open questions | diff --git a/Scripts/assemble-site-source.js b/Scripts/assemble-site-source.js new file mode 100644 index 0000000..a4b5a1d --- /dev/null +++ b/Scripts/assemble-site-source.js @@ -0,0 +1,70 @@ +#!/usr/bin/env node +// SPDX-License-Identifier: MIT +"use strict"; +// Copy the documentation + static assets into docs/ so MkDocs can build the +// GitHub Pages site from the repository's existing markdown (MkDocs requires +// docs_dir to be a child directory). The repository root remains the single +// source of truth; docs/ is a gitignored staging area. +// +// The file list comes from git's index plus untracked non-ignored files +// (`-c -o --exclude-standard`), so the script works both on a committed CI +// checkout and in a working tree with uncommitted new docs (e.g. robots.txt). +// +// Usage: node Scripts/assemble-site-source.js + +const { execSync } = require("child_process"); +const fs = require("fs"); +const path = require("path"); + +const ROOT = path.resolve(__dirname, ".."); +const DEST = path.join(ROOT, "docs"); + +// Everything tracked under these prefixes is excluded from the site. +const EXCLUDED = [ + "CLAUDE.md", + ".github/", + ".claude/", + "Scripts/", + "Statusline/lib/", + "Statusline/statusline.js", + "Statusline/test/", + "node_modules/", +]; + +// Non-markdown files referenced by the docs (badges, license, robots.txt). +const ASSETS = [ + "LICENSE", + "LICENSE.docs", + "package.json", + "robots.txt", +]; + +function shouldInclude(rel) { + if (rel.startsWith(".")) return false; // dotfiles/dirs + if (EXCLUDED.some((p) => rel === p || rel.startsWith(p))) return false; + return true; +} + +function main() { + const tracked = execSync("git ls-files -c -o --exclude-standard", { encoding: "utf8" }) + .trim() + .split("\n") + .filter(Boolean); + + const wanted = tracked.filter((f) => { + if (/\.md$/i.test(f)) return shouldInclude(f); + if (f.startsWith("Assets/")) return true; + return ASSETS.includes(f); + }); + + fs.rmSync(DEST, { recursive: true, force: true }); + for (const rel of wanted) { + const src = path.resolve(ROOT, rel); + const dst = path.resolve(DEST, rel); + fs.mkdirSync(path.dirname(dst), { recursive: true }); + fs.copyFileSync(src, dst); + } + console.log(`assemble-site-source: staged ${wanted.length} files into ${DEST}`); +} + +main(); \ No newline at end of file diff --git a/Scripts/generate-llms.js b/Scripts/generate-llms.js new file mode 100644 index 0000000..7b0857e --- /dev/null +++ b/Scripts/generate-llms.js @@ -0,0 +1,206 @@ +#!/usr/bin/env node +// SPDX-License-Identifier: MIT +"use strict"; +// Generate llms.txt and llms-full.txt for the GitHub Pages docs site. +// +// Why this script exists (and why it is the only custom piece): +// The llms.txt convention (https://llmstxt.org) is not emitted by any +// static-site generator, and hand-maintaining llms-full.txt — a concatenation +// of every published doc — would drift the moment any doc changes. Everything +// else on the site (markdown rendering, anchors, link rewriting, nav, search, +// sitemap) is handled by MkDocs; this script only produces the two +// llms.txt-family files from the same source markdown. +// +// Usage: node Scripts/generate-llms.js [--src ] [--out ] +// --src: where the published markdown lives (default: docs/, the staged copy +// produced by Scripts/assemble-site-source.js) +// --out: where llms.txt / llms-full.txt are written (default: site/) + +const fs = require("fs"); +const path = require("path"); + +const ROOT = path.resolve(__dirname, ".."); +const SITE_URL = "https://unscriptedbykramy.github.io/AI-Engineering-Lab/"; + +// Ordered list of published docs, mirroring the `nav` in mkdocs.yml. Add a new +// published doc to exactly one of these arrays (and to mkdocs.yml nav). +const DESIGN = [ + "Statusline/Design/README.md", + "Statusline/Design/01-display-requirements.md", + "Statusline/Design/02-input-output-contract.md", + "Statusline/Design/03-provider-model-naming.md", + "Statusline/Design/04-caching-timeout-policy.md", + "Statusline/Design/05-security-privacy.md", + "Statusline/Design/06-test-cases-acceptance.md", + "Statusline/Design/07-design-handoff.md", +]; + +const FINDINGS = [ + "Findings/2026-08-01 - Phase 1B Investigation Plan.md", + "Findings/2026-08-01 - Phase 1B - Auto-Cheap Classifier Gating.md", + "Findings/2026-08-01 - Phase 1B - OmniRoute Topology and Logs.md", + "Findings/2026-08-01 - Phase 1B - Resolved-Route Exposure.md", + "Findings/2026-08-01 - Phase 1B - Statusline Input Contract.md", + "Findings/2026-08-02 - Phase 2 - Read-only Verification.md", + "Findings/2026-08-02 - Phase 2 Architecture Plan.md", + "Findings/2026-08-02 - Phase 4 Implementation Plan.md", + "Findings/2026-08-03 - Phase 5 - Validation Evidence and Staleness Contract Check.md", + "Findings/2026-08-03 - Phase 5 - Validation Report.md", + "Findings/2026-08-04 - Context Window Data Source and Statusline Styling.md", +]; + +const RESEARCH = [ + "Research/2026-08-01 - Perplexity Research Round 01 - Initial Investigation.md", + "Research/2026-08-01 - Perplexity Research Round 02 - OmniRoute Metadata.md", + "Research/2026-08-01 - Perplexity Research Round 03 - Source Code Investigation.md", + "Research/2026-08-01 - Perplexity Research Round 04 - Endpoint Investigation.md", +]; + +// Key resources first (what an LLM should read for a full picture), then +// Optional (skippable for shorter contexts) — per the llms.txt spec. +const KEY = [ + "README.md", + "Statusline/README.md", + "Architecture.md", + "Decisions.md", + "Knowledge-Base.md", + "Roadmap.md", + "Origin-Story.md", +]; + +const OPTIONAL = [ + "Project Charter.md", + "PROJECT_RETROSPECTIVE.md", + "Skill-Candidates.md", + ...DESIGN, + ...FINDINGS, + ...RESEARCH, + "References/Bibliography.md", + "Assets/screenshots/README.md", + "CHANGELOG.md", + "CONTRIBUTING.md", + "CODE_OF_CONDUCT.md", + "SECURITY.md", + "LICENSING.md", +]; + +const KEY_NOTES = { + "README.md": "the lab's flagship project overview", + "Statusline/README.md": "full operational guide, install, and troubleshooting", + "Architecture.md": "verified data flow and component responsibilities", + "Decisions.md": "Architecture Decision Records and project-level decisions", + "Knowledge-Base.md": "consolidated verified knowledge and open questions", + "Roadmap.md": "phases, gates, deliverables, and next actions", + "Origin-Story.md": "how the lab started and why the project exists", +}; + +const OPTIONAL_NOTES = { + "Project Charter.md": "scope, constraints, success criteria, and non-goals", + "PROJECT_RETROSPECTIVE.md": "project retrospective", + "Skill-Candidates.md": "engineering evidence ledger for reusable workflows", + "References/Bibliography.md": "source links and provenance", + "Assets/screenshots/README.md": "real statusline output frames", + "CHANGELOG.md": "release history", + "CONTRIBUTING.md": "contribution guidelines", + "CODE_OF_CONDUCT.md": "code of conduct", + "SECURITY.md": "security policy", + "LICENSING.md": "dual-license guide (MIT code, CC BY 4.0 docs)", +}; + +const DOCS = new Set([...KEY, ...OPTIONAL]); +const enc = (url) => url.replace(/ /g, "%20"); + +// Map a published doc path to its MkDocs page URL (directory URLs are enabled). +function pageUrl(docPath) { + const slash = docPath.lastIndexOf("/"); + const dir = slash === -1 ? "" : docPath.slice(0, slash); + const name = slash === -1 ? docPath : docPath.slice(slash + 1); + const dirPart = dir ? dir + "/" : ""; + if (name.toLowerCase() === "readme.md") return SITE_URL + dirPart; + return SITE_URL + dirPart + name.replace(/\.md$/i, "") + "/"; +} + +// Rewrite relative links in a doc to absolute site URLs (absolute, mailto, and +// fragment-only links are left untouched). +function rewriteLinks(src, docPath) { + return src.replace(/(\[[^\]]*\]\()([^)]+)(\))/g, (m, pre, target, post) => { + const t = target.trim(); + if (/^(https?:|mailto:|#)/i.test(t)) return m; + const fragIdx = t.indexOf("#"); + const frag = fragIdx === -1 ? "" : t.slice(fragIdx); + const raw = (fragIdx === -1 ? t : t.slice(0, fragIdx)).trim(); + if (!raw) return m; + const resolved = path.posix.normalize(path.posix.join(path.posix.dirname(docPath), raw)); + if (DOCS.has(resolved)) return pre + enc(pageUrl(resolved)) + frag + post; + if (fs.existsSync(path.resolve(SRC, resolved))) { + return pre + enc(SITE_URL + resolved) + frag + post; + } + return m; + }); +} + +function buildLlmsFull() { + const parts = []; + for (const doc of [...KEY, ...OPTIONAL]) { + const abs = path.resolve(SRC, doc); + if (!fs.existsSync(abs)) { + console.error(`generate-llms: missing published doc: ${doc}`); + process.exit(1); + } + const src = fs.readFileSync(abs, "utf8"); + parts.push(`# File: ${doc}\n\n${rewriteLinks(src, doc).trim()}`); + } + return parts.join("\n\n") + "\n"; +} + +function buildLlmsTxt() { + const lines = []; + lines.push("# AI Engineering Lab"); + lines.push(""); + lines.push( + "> Evidence-first AI engineering: the Provider-Aware Statusline for Claude Code behind the OmniRoute LLM routing gateway — see which provider and model actually served your request. Zero-dependency Node.js statusline (68 contract tests) plus the research, findings, architecture, and ADRs that prove how it works." + ); + lines.push(""); + lines.push(`[llms-full.txt](${SITE_URL}llms-full.txt)`); + lines.push(""); + lines.push("## Key resources"); + lines.push(""); + for (const doc of KEY) { + const note = KEY_NOTES[doc]; + lines.push(`- [${KEY_NOTES[doc]}](${enc(pageUrl(doc))}) — ${doc}`); + } + lines.push(""); + lines.push("## Optional"); + lines.push(""); + for (const doc of OPTIONAL) { + const slash = doc.lastIndexOf("/"); + const name = slash === -1 ? doc : doc.slice(slash + 1); + const note = OPTIONAL_NOTES[doc]; + lines.push( + `- [${name.replace(/\.md$/i, "")}](${enc(pageUrl(doc))})${note ? ` — ${note}` : ""}` + ); + } + return lines.join("\n") + "\n"; +} + +const srcArg = process.argv.indexOf("--src"); +const srcArgVal = srcArg === -1 ? null : process.argv[srcArg + 1]; +const SRC = srcArgVal ? path.resolve(srcArgVal) : path.resolve(ROOT, "docs"); + +const outArg = process.argv.indexOf("--out"); +const outDir = outArg === -1 ? path.resolve(ROOT, "site") : path.resolve(process.argv[outArg + 1]); +fs.mkdirSync(outDir, { recursive: true }); + +const llms = buildLlmsTxt(); +const llmsFull = buildLlmsFull(); +fs.writeFileSync(path.join(outDir, "llms.txt"), llms); +fs.writeFileSync(path.join(outDir, "llms-full.txt"), llmsFull); + +// Self-check: llms.txt must open with an H1 and a blockquote (spec requirement). +if (!/^# .+\n\n> /.test(llms)) { + console.error("generate-llms: llms.txt does not start with H1 + blockquote"); + process.exit(1); +} +console.log( + `generate-llms: wrote llms.txt (${llms.split("\n").length} lines) and llms-full.txt (${llmsFull.split("\n").length} lines) to ${outDir}` +); diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..5fbd4ea --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,110 @@ +# MkDocs site configuration — AI Engineering Lab +# +# This builds the GitHub Pages documentation site from the repository's own +# markdown. Because MkDocs requires docs_dir to be a child directory, the docs +# are first staged into a gitignored `docs/` (which mirrors the repo structure) +# by Scripts/assemble-site-source.js — the repository root remains the single +# source of truth and the site is not a separate product to maintain. +# Build/validate with: +# pip install -r requirements.txt +# node Scripts/assemble-site-source.js +# mkdocs build --strict # fails on any broken link or warning +site_name: AI Engineering Lab +site_description: >- + Provider-Aware Statusline for Claude Code behind the OmniRoute LLM routing + gateway — see which provider and model actually served your request. + Zero-dependency Node.js statusline (68 contract tests) plus an evidence-first + AI engineering research trail: research, findings, ADRs, and design docs. +site_author: UnscriptedByKraMy +site_url: https://unscriptedbykramy.github.io/AI-Engineering-Lab/ +repo_url: https://github.com/UnscriptedByKraMy/AI-Engineering-Lab +repo_name: AI-Engineering-Lab + +docs_dir: docs +site_dir: site + +theme: + name: material + palette: + - scheme: slate # dark — matches the project's terminal identity + primary: teal + accent: amber + features: + - navigation.top + - content.code.copy + language: en + +# `search` is the default MkDocs plugin; core MkDocs also emits `sitemap.xml` +# automatically because `site_url` is set above (no plugin needed). +plugins: + - search + +markdown_extensions: + - tables + - fenced_code + - admonition + - attr_list + - md_in_html + - toc: + permalink: true + +# The `assemble-site-source.js` script controls exactly which files land in +# docs/. This list is a safety net for anything that shouldn't leak through. +exclude_docs: | + CLAUDE.md + node_modules/ + site/ + +# The README links to one hand-written in-page anchor (#for-users--install--use) +# whose slug does not match MkDocs' generated heading slug. GitHub resolves it; +# on the site the in-page jump is a harmless no-op. Downgrade the warning so +# `--strict` stays green. +validation: + anchors: info + +nav: + - Overview: README.md + - Origin Story: Origin-Story.md + - Roadmap: Roadmap.md + - Project Charter: Project Charter.md + - Architecture: Architecture.md + - Decisions (ADRs): Decisions.md + - Knowledge Base: Knowledge-Base.md + - Project Retrospective: PROJECT_RETROSPECTIVE.md + - Statusline: + - Statusline: Statusline/README.md + - Design: + - Statusline/Design/README.md + - 01 - Display Requirements: Statusline/Design/01-display-requirements.md + - 02 - Input/Output Contract: Statusline/Design/02-input-output-contract.md + - 03 - Provider/Model Naming: Statusline/Design/03-provider-model-naming.md + - 04 - Caching and Timeout Policy: Statusline/Design/04-caching-timeout-policy.md + - 05 - Security and Privacy: Statusline/Design/05-security-privacy.md + - 06 - Test Cases and Acceptance: Statusline/Design/06-test-cases-acceptance.md + - 07 - Design Handoff: Statusline/Design/07-design-handoff.md + - Findings: + - 2026-08-01 - Phase 1B Investigation Plan: Findings/2026-08-01 - Phase 1B Investigation Plan.md + - "2026-08-01 - Phase 1B - Auto-Cheap Classifier Gating": "Findings/2026-08-01 - Phase 1B - Auto-Cheap Classifier Gating.md" + - 2026-08-01 - Phase 1B - OmniRoute Topology and Logs: Findings/2026-08-01 - Phase 1B - OmniRoute Topology and Logs.md + - 2026-08-01 - Phase 1B - Resolved-Route Exposure: Findings/2026-08-01 - Phase 1B - Resolved-Route Exposure.md + - 2026-08-01 - Phase 1B - Statusline Input Contract: Findings/2026-08-01 - Phase 1B - Statusline Input Contract.md + - 2026-08-02 - Phase 2 - Read-only Verification: Findings/2026-08-02 - Phase 2 - Read-only Verification.md + - 2026-08-02 - Phase 2 Architecture Plan: Findings/2026-08-02 - Phase 2 Architecture Plan.md + - 2026-08-02 - Phase 4 Implementation Plan: Findings/2026-08-02 - Phase 4 Implementation Plan.md + - 2026-08-03 - Phase 5 - Validation Evidence and Staleness Contract Check: Findings/2026-08-03 - Phase 5 - Validation Evidence and Staleness Contract Check.md + - 2026-08-03 - Phase 5 - Validation Report: Findings/2026-08-03 - Phase 5 - Validation Report.md + - 2026-08-04 - Context Window Data Source and Statusline Styling: Findings/2026-08-04 - Context Window Data Source and Statusline Styling.md + - Research: + - Round 01 - Initial Investigation: Research/2026-08-01 - Perplexity Research Round 01 - Initial Investigation.md + - Round 02 - OmniRoute Metadata: Research/2026-08-01 - Perplexity Research Round 02 - OmniRoute Metadata.md + - Round 03 - Source Code Investigation: Research/2026-08-01 - Perplexity Research Round 03 - Source Code Investigation.md + - Round 04 - Endpoint Investigation: Research/2026-08-01 - Perplexity Research Round 04 - Endpoint Investigation.md + - References: + - Bibliography: References/Bibliography.md + - Project records: + - Changelog: CHANGELOG.md + - Skill Candidates: Skill-Candidates.md + - Contributing: CONTRIBUTING.md + - Code of Conduct: CODE_OF_CONDUCT.md + - Security: SECURITY.md + - Licensing: LICENSING.md diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..407f0b6 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +# Build-time dependencies for the GitHub Pages documentation site only. +# The shipped statusline has zero runtime dependencies; these are used by CI +# and (optionally) for local site previews. +# sitemap.xml needs no plugin: MkDocs core generates it when `site_url` is set. +mkdocs>=1.6,<2 +mkdocs-material>=9.5,<10 diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..a5e39f6 --- /dev/null +++ b/robots.txt @@ -0,0 +1,6 @@ +# Allow all crawlers (including AI crawlers such as GPTBot, PerplexityBot, +# ClaudeBot, and Google-Extended) to index the documentation site. +User-agent: * +Allow: / + +Sitemap: https://unscriptedbykramy.github.io/AI-Engineering-Lab/sitemap.xml