Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,24 @@ jobs:
- name: Contract tests
run: npm test
- name: Link check
run: node Scripts/check-markdown-links.js
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
63 changes: 63 additions & 0 deletions .github/workflows/deploy-site.yml
Original file line number Diff line number Diff line change
@@ -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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@
# Node
node_modules/
npm-debug.log*

# Generated docs site staging + output (built by CI; see mkdocs.yml)
docs/
site/
58 changes: 47 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

<img src="Assets/screenshots/hero.png" alt="Provider-Aware Statusline: 🤖 opencode/big-pickle | ▓▓▓▓░░░░░░ 42% | 🪟 110K/262K | ⇡1.5K⇣820 | 🌿 feature/ctx-window ✏️" width="836" />

Expand All @@ -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.
Expand Down Expand Up @@ -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 |
Expand Down
70 changes: 70 additions & 0 deletions Scripts/assemble-site-source.js
Original file line number Diff line number Diff line change
@@ -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();
Loading
Loading