Skip to content
Merged
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
324 changes: 83 additions & 241 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -1,295 +1,137 @@
= odd-ssg
:toc: macro
:toc: auto
:toclevels: 2
:icons: font

Satellite SSG adapter provider with 30 MCP-compatible adapters for static site generators.
Static site generator in betlang.

image:https://img.shields.io/badge/license-AGPL--3.0--or--later-blue[License]
image:https://img.shields.io/badge/RSR-Gold-gold[RSR Compliance]
image:https://img.shields.io/badge/adapters-30-green[Adapters]
image:https://img.shields.io/badge/poly--ssg--mcp-integrated-purple[poly-ssg-mcp]
image:https://img.shields.io/badge/status-experimental-orange[Status]

toc::[]
_Let odds favor. Let ternaries decide. Let pages emerge._

== Overview
== Who Is This For?

odd-ssg is a satellite implementation in the hyperpolymath ecosystem that provides:
* **Probabilistic programming enthusiasts** seeking a practical application of ternary reasoning
* **Data-driven content strategists** wanting native A/B/C testing without external tools
* **Racket developers** building sites with functional elegance
* **Uncertainty modelers** who see content as weighted outcomes, not fixed artifacts

* **30 SSG Adapters** - MCP-compatible adapters for static site generators across 15+ languages
* **Mill-Based Synthesis Engine** - Template processing inspired by Ada Lovelace's Analytical Engine
* **NoteG Language Tooling** - Lexer, parser, and LSP for .noteg files
* **Accessibility First** - Native support for BSL, ASL, GSL, Makaton, and Easy Read
== Why odd-ssg?

== Quick Start
Static sites are traditionally deterministic—same input, same output. But content decisions are rarely binary. Should this hero image appear? Which call-to-action converts best? What tone suits this audience segment?

[source,bash]
----
# Clone repository
git clone https://github.com/hyperpolymath/odd-ssg
cd odd-ssg
odd-ssg embraces uncertainty. Built on https://github.com/hyperpolymath/betlang[betlang], a ternary probabilistic DSL for Racket, it treats content selection as a three-valued bet:

# Install dependencies (using asdf)
asdf install

# Run tests
just test

# Start MCP server
just mcp
[source,racket]
----
;; Content varies by weighted probability
(define hero-variant
(bet 0.5 "hero-bold.html" ; 50% - bold messaging
0.3 "hero-subtle.html" ; 30% - subtle approach
0.2 "hero-minimal.html")) ; 20% - minimal design

== Supported SSG Adapters

[cols="2,3,3"]
|===
|Language |SSGs |Status

|Rust
|Zola, Cobalt, mdBook
|✅ Complete

|Haskell
|Hakyll, Ema
|✅ Complete

|Elixir
|Serum, NimblePublisher, Tableau
|✅ Complete

|Clojure
|Cryogen, Perun, Babashka
|✅ Complete

|Racket
|Frog, Pollen
|✅ Complete

|Julia
|Franklin.jl, Documenter.jl, StaticWebPages.jl
|✅ Complete

|Scala
|Laika, ScalaTex
|✅ Complete

|OCaml
|YOCaml
|✅ Complete

|Swift
|Publish
|✅ Complete

|Kotlin
|Orchid
|✅ Complete

|Crystal
|Marmot
|✅ Complete

|Nim
|Nimrod
|✅ Complete

|D
|Reggae
|✅ Complete

|F#
|Fornax
|✅ Complete

|Erlang
|Zotonic
|✅ Complete

|Tcl
|Wub
|✅ Complete

|Common Lisp
|Coleslaw
|✅ Complete
|===
;; Conditional content based on audience signals
(define cta
(bet/when high-intent?
0.6 "buy-now"
0.3 "learn-more"
0.1 "subscribe"))
----

== Usage
Where traditional SSGs hardcode choices, odd-ssg lets probability guide them. Each build can explore the decision space, producing statistically varied outputs for testing, personalization, or creative exploration.

=== As MCP Server
== Getting Started

[source,bash]
----
# Start the MCP server
deno run --allow-read --allow-write --allow-run noteg-mcp/server.ts
# Requires Racket 8.0+ with betlang installed
raco pkg install betlang

# Or use just
just mcp
# Clone and build
git clone https://github.com/hyperpolymath/odd-ssg
cd odd-ssg
just build
----

=== As Library
== How It Works

[source,typescript]
----
import { Engine, loadAdapter, ADAPTERS } from "@hyperpolymath/odd-ssg";

// List available adapters
console.log("Available adapters:", ADAPTERS);

// Load and use an adapter
const zola = await loadAdapter("zola");
const connected = await zola.connect();

if (connected) {
const result = await zola.tools
.find(t => t.name === "zola_build")
.execute({ path: "./my-site" });
console.log(result);
}
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Source │────▶│ Parser │────▶│ Bet Engine │────▶│ Emitter │
│ (.noteg) │ │ (Racket) │ │ (betlang) │ │ (HTML/etc) │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
┌─────────────────────┐
│ Probability Store │
│ (reproducible via │
│ seed or sample) │
└─────────────────────┘
----

=== Build System
=== Core Concepts

[source,bash]
----
# Build commands
just build # Build the project
just build-drafts # Include drafts
just watch # Watch mode

# Test commands
just test # All tests
just test-unit # Unit tests
just test-e2e # E2E tests
just test-bernoulli # Bernoulli verification

# Development
just dev # Development server
just lsp # Start language server
just lint # Lint code
just fmt # Format code
----
|===
|Concept |Description |Example

== Architecture
|**Ternary Bet**
|Three-way weighted choice
|`(bet 0.5 a 0.3 b 0.2 c)`

=== Mill-Based Synthesis Engine
|**Conditional Bet**
|Probability shifts based on predicate
|`(bet/when condition ...)`

The core engine implements Ada Lovelace's Analytical Engine paradigm:
|**Lazy Evaluation**
|Only selected branch computes
|Efficient for heavy templates

* **Operation Cards** - Template instructions
* **Variable Cards** - Data bindings
* **Mill** - Processing unit
* **Store** - Variable persistence
|**Seed Reproducibility**
|Same seed = same choices
|`--seed 42` for deterministic builds
|===

[source,typescript]
----
import { Engine, createMill, createStore } from "@hyperpolymath/odd-ssg";
== Features

const engine = new Engine();
engine.loadVariables([
{ name: "title", type: "string", value: "Hello World" }
]);
* **Native A/B/C testing** — Generate variant pages from single source
* **Weighted template selection** — Probability-driven layouts
* **Ternary content states** — Beyond draft/published: draft/review/live
* **Statistical sampling** — Monte Carlo builds for coverage analysis
* **Seed-locked reproducibility** — Deterministic output when needed
* **NoteG language support** — Custom notation with LSP integration

const result = await engine.execute([
{ operation: "load", operands: ["title"] },
{ operation: "emit", operands: [] }
]);
----
== poly-ssg-mcp Integration

odd-ssg is a satellite of the https://github.com/hyperpolymath/poly-ssg-mcp[poly-ssg-mcp] ecosystem, which provides unified MCP tooling across static site generators. Related projects:

=== MCP Protocol
* https://github.com/hyperpolymath/poly-container-mcp[poly-container-mcp] — Container management (nerdctl, podman, docker)
* https://github.com/hyperpolymath/poly-iac-mcp[poly-iac-mcp] — Infrastructure as Code (OpenTofu, Terraform, Pulumi)
* https://github.com/hyperpolymath/poly-k8s-mcp[poly-k8s-mcp] — Kubernetes orchestration

Adapters expose tools via the Model Context Protocol:
The ReScript adapter exposes odd-ssg to AI assistants via Model Context Protocol:

[source,json]
----
{
"tools": [
{
"name": "zola_build",
"description": "Build the Zola site",
"inputSchema": {
"type": "object",
"properties": {
"path": { "type": "string" },
"baseUrl": { "type": "string" },
"outputDir": { "type": "string" }
}
}
}
{ "name": "odd_build", "description": "Build with probability sampling" },
{ "name": "odd_variants", "description": "Generate N variant builds" },
{ "name": "odd_lock", "description": "Lock choices with seed" }
]
}
----

== Accessibility

odd-ssg provides native accessibility support:

* **BSL** - British Sign Language metadata
* **ASL** - American Sign Language metadata
* **GSL** - German Sign Language metadata
* **Makaton** - Symbol-based communication
* **Easy Read** - Simplified content versions

See link:a11y/schema.json[Accessibility Schema] for details.

== Project Structure

[source]
----
odd-ssg/
├── adapters/ # 30 SSG adapters
├── engine/src/ # Mill-based synthesis core
├── ssg/src/ # Site generation pipeline
├── noteg-lang/src/ # Language tooling (lexer, parser, LSP)
├── noteg-mcp/ # MCP server
├── a11y/ # Accessibility schemas
├── tests/ # Unit, E2E, Bernoulli tests
├── examples/ # Example content and config
├── *.scm # SCM configuration files
├── justfile # Task runner
├── Mustfile # Declarative requirements
├── Containerfile # Container build
└── cookbook.adoc # Recipes and workflows
----

== SCM Files

* link:META.scm[META.scm] - Architecture decisions, development practices
* link:ECOSYSTEM.scm[ECOSYSTEM.scm] - Ecosystem position, related projects
* link:STATE.scm[STATE.scm] - Current state, completion metrics
* link:PLAYBOOK.scm[PLAYBOOK.scm] - Operational runbooks
* link:AGENTIC.scm[AGENTIC.scm] - AI agent integration
* link:NEUROSYM.scm[NEUROSYM.scm] - Neuro-symbolic reasoning

== Security

* CodeQL analysis on all PRs
* SHA-pinned GitHub Actions
* Deno permission model for sandboxing
* No eval or shell injection
* Environment-only credentials

See link:SECURITY.md[Security Policy] for vulnerability reporting.

== Contributing
== Requirements

See link:CONTRIBUTING.md[Contributing Guide] for guidelines.

[source,bash]
----
# Pre-commit checks
just pre-commit

# Full CI simulation
just ci
----
* **Racket** 8.0 or later
* **betlang** — `raco pkg install betlang`
* **Deno** — For adapter and MCP server

== License

AGPL-3.0-or-later

Copyright 2025 Jonathan D.A. Jewell

== Links

* https://github.com/hyperpolymath/poly-ssg-mcp[poly-ssg-mcp] - Hub project
* https://github.com/hyperpolymath/rhodium-standard-repositories[RSR] - Compliance standard
Loading