3 Commits
Author SHA1 Message Date
ZacharyZhang-NY 2c29d3ecd5 Bump version to 0.1.2
Release / build (aarch64-apple-darwin) (push) Waiting to run
Release / build (x86_64-apple-darwin) (push) Waiting to run
Release / build (aarch64-unknown-linux-gnu) (push) Waiting to run
Release / build (x86_64-pc-windows-msvc) (push) Waiting to run
Release / publish GitHub Release (push) Blocked by required conditions
Release / build (x86_64-unknown-linux-gnu) (push) Failing after 7s
2026-07-18 20:25:51 -04:00
ZacharyZhang-NY de534582c1 Drop the CI workflow; gates run locally, builds only on release tags 2026-07-18 20:25:51 -04:00
ZacharyZhang-NY 54c9177ce2 Texture the welcome moon with lunar maria
Small scattered mare spots: dark holes on the sunlit disc, faint gray
patches on the dark limb.
2026-07-18 20:25:51 -04:00
4 changed files with 135 additions and 150 deletions
-79
View File
@@ -1,79 +0,0 @@
name: CI
on:
push:
branches: [main]
pull_request:
env:
CARGO_TERM_COLOR: always
jobs:
gates:
name: check / clippy / fmt / deny (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [macos-14, ubuntu-24.04]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Install toolchain (rust-toolchain.toml)
run: rustup show
- name: Install dotslash (protoc launcher)
run: cargo install dotslash --locked
- uses: Swatinem/rust-cache@v2
- name: cargo fmt
run: cargo fmt --all --check
- name: cargo check
run: cargo check --workspace --all-targets --locked
- name: cargo clippy
run: cargo clippy --workspace --all-targets --locked -- -D warnings
- name: Install cargo-deny
run: cargo install cargo-deny --locked
- name: cargo deny advisories
run: cargo deny check advisories
test:
name: test (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [macos-14, ubuntu-24.04]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Install toolchain (rust-toolchain.toml)
run: rustup show
- name: Install dotslash (protoc launcher)
run: cargo install dotslash --locked
- uses: Swatinem/rust-cache@v2
- name: cargo test
run: cargo test --workspace --locked
perf:
name: performance budgets (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [macos-14, ubuntu-24.04]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Install toolchain (rust-toolchain.toml)
run: rustup show
- name: Install dotslash (protoc launcher)
run: cargo install dotslash --locked
- uses: Swatinem/rust-cache@v2
- name: Install hyperfine (macOS)
if: runner.os == 'macOS'
run: brew install hyperfine
- name: Install hyperfine (Linux)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y hyperfine
- name: Build release binaries
run: |
cargo build --release -p kigi-bin --locked
cargo build --release -p kigi-pager-pty-harness --bin pty-scenario --locked
- name: Enforce performance budgets
run: scripts/bench.sh target/release/kigi
Generated
+62 -62
View File
@@ -5442,7 +5442,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-acp-lib" name = "kigi-acp-lib"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"agent-client-protocol", "agent-client-protocol",
"async-trait", "async-trait",
@@ -5456,7 +5456,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-agent" name = "kigi-agent"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"chrono", "chrono",
"dirs 6.0.0", "dirs 6.0.0",
@@ -5486,7 +5486,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-agent-lifecycle" name = "kigi-agent-lifecycle"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"tokio", "tokio",
@@ -5495,7 +5495,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-auth" name = "kigi-auth"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"http 1.4.2", "http 1.4.2",
@@ -5508,7 +5508,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-bin" name = "kigi-bin"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
@@ -5543,7 +5543,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-chat-state" name = "kigi-chat-state"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"kigi-compaction", "kigi-compaction",
@@ -5560,7 +5560,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-codebase-graph" name = "kigi-codebase-graph"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"ahash", "ahash",
"clap", "clap",
@@ -5596,7 +5596,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-compaction" name = "kigi-compaction"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@@ -5609,7 +5609,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-config" name = "kigi-config"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"base64", "base64",
"blake3", "blake3",
@@ -5632,7 +5632,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-config-types" name = "kigi-config-types"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"agent-client-protocol", "agent-client-protocol",
"indexmap", "indexmap",
@@ -5646,7 +5646,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-crash-handler" name = "kigi-crash-handler"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"libc", "libc",
@@ -5657,7 +5657,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-env" name = "kigi-env"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"tracing", "tracing",
"url", "url",
@@ -5665,7 +5665,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-fast-worktree" name = "kigi-fast-worktree"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@@ -5697,7 +5697,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-file-utils" name = "kigi-file-utils"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"aws-config", "aws-config",
@@ -5721,7 +5721,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-fsnotify" name = "kigi-fsnotify"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"criterion", "criterion",
"dunce", "dunce",
@@ -5742,7 +5742,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-gix-status" name = "kigi-gix-status"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"gix", "gix",
"kigi-test-utils", "kigi-test-utils",
@@ -5752,7 +5752,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-hooks" name = "kigi-hooks"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"fastrand", "fastrand",
"kigi-config", "kigi-config",
@@ -5771,7 +5771,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-hooks-plugins-types" name = "kigi-hooks-plugins-types"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
@@ -5779,7 +5779,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-http" name = "kigi-http"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"kigi-auth", "kigi-auth",
"kigi-log", "kigi-log",
@@ -5794,7 +5794,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-hunk-tracker" name = "kigi-hunk-tracker"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"chrono", "chrono",
"dunce", "dunce",
@@ -5815,14 +5815,14 @@ dependencies = [
[[package]] [[package]]
name = "kigi-interjection-core" name = "kigi-interjection-core"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"serde", "serde",
] ]
[[package]] [[package]]
name = "kigi-log" name = "kigi-log"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
@@ -5840,7 +5840,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-markdown" name = "kigi-markdown"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"anstyle-lossy", "anstyle-lossy",
@@ -5864,14 +5864,14 @@ dependencies = [
[[package]] [[package]]
name = "kigi-markdown-core" name = "kigi-markdown-core"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"pulldown-cmark", "pulldown-cmark",
] ]
[[package]] [[package]]
name = "kigi-mcp" name = "kigi-mcp"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"agent-client-protocol", "agent-client-protocol",
"async-trait", "async-trait",
@@ -5908,7 +5908,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-memory" name = "kigi-memory"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arc-swap", "arc-swap",
@@ -5942,7 +5942,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-mermaid" name = "kigi-mermaid"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"fontdb", "fontdb",
"image", "image",
@@ -5960,7 +5960,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-models" name = "kigi-models"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"kigi-env", "kigi-env",
"serde", "serde",
@@ -5969,7 +5969,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-pager-minimal" name = "kigi-pager-minimal"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"chrono", "chrono",
"crossterm", "crossterm",
@@ -5986,7 +5986,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-pager-pty-harness" name = "kigi-pager-pty-harness"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"alacritty_terminal", "alacritty_terminal",
"anyhow", "anyhow",
@@ -6011,7 +6011,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-pager-render" name = "kigi-pager-render"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"agent-client-protocol", "agent-client-protocol",
"anstyle", "anstyle",
@@ -6063,7 +6063,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-paths" name = "kigi-paths"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"camino", "camino",
"serde", "serde",
@@ -6073,7 +6073,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-prompt-queue" name = "kigi-prompt-queue"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
@@ -6081,7 +6081,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-proto-build" name = "kigi-proto-build"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"pbjson-build", "pbjson-build",
@@ -6092,7 +6092,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-ratatui-inline" name = "kigi-ratatui-inline"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"ansi-width", "ansi-width",
"anstyle-parse 0.2.7", "anstyle-parse 0.2.7",
@@ -6109,7 +6109,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-ratatui-textarea" name = "kigi-ratatui-textarea"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"arboard", "arboard",
"chrono", "chrono",
@@ -6130,7 +6130,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-sampler" name = "kigi-sampler"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"async-openai", "async-openai",
"async-stream", "async-stream",
@@ -6153,7 +6153,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-sampling-types" name = "kigi-sampling-types"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"assert_matches", "assert_matches",
"async-openai", "async-openai",
@@ -6169,7 +6169,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-sandbox" name = "kigi-sandbox"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
@@ -6190,7 +6190,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-secrets" name = "kigi-secrets"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"regex", "regex",
"serde_json", "serde_json",
@@ -6228,7 +6228,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-shell" name = "kigi-shell"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"agent-client-protocol", "agent-client-protocol",
"anyhow", "anyhow",
@@ -6365,7 +6365,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-shell-base" name = "kigi-shell-base"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
@@ -6390,7 +6390,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-sqlite-journal" name = "kigi-sqlite-journal"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"libc", "libc",
"rusqlite", "rusqlite",
@@ -6401,7 +6401,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-subagent-resolution" name = "kigi-subagent-resolution"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"kigi-sampling-types", "kigi-sampling-types",
"kigi-tool-types", "kigi-tool-types",
@@ -6416,7 +6416,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-system-power" name = "kigi-system-power"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.59.0",
"zbus", "zbus",
@@ -6424,7 +6424,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-test-support" name = "kigi-test-support"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"agent-client-protocol", "agent-client-protocol",
"anyhow", "anyhow",
@@ -6446,7 +6446,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-test-utils" name = "kigi-test-utils"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"runfiles", "runfiles",
"tracing", "tracing",
@@ -6455,11 +6455,11 @@ dependencies = [
[[package]] [[package]]
name = "kigi-token-estimation" name = "kigi-token-estimation"
version = "0.1.1" version = "0.1.2"
[[package]] [[package]]
name = "kigi-tool-protocol" name = "kigi-tool-protocol"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"kigi-tool-types", "kigi-tool-types",
"serde", "serde",
@@ -6470,7 +6470,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-tool-runtime" name = "kigi-tool-runtime"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
@@ -6488,7 +6488,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-tool-types" name = "kigi-tool-types"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"minijinja", "minijinja",
"schemars 1.2.1", "schemars 1.2.1",
@@ -6498,7 +6498,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-tools" name = "kigi-tools"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arc-swap", "arc-swap",
@@ -6575,7 +6575,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-tools-api" name = "kigi-tools-api"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"kigi-proto-build", "kigi-proto-build",
"kigi-tool-protocol", "kigi-tool-protocol",
@@ -6588,11 +6588,11 @@ dependencies = [
[[package]] [[package]]
name = "kigi-tracing-macros" name = "kigi-tracing-macros"
version = "0.1.1" version = "0.1.2"
[[package]] [[package]]
name = "kigi-tty-utils" name = "kigi-tty-utils"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"libc", "libc",
"nix 0.30.1", "nix 0.30.1",
@@ -6602,7 +6602,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-tui" name = "kigi-tui"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"agent-client-protocol", "agent-client-protocol",
"ansi-to-tui", "ansi-to-tui",
@@ -6689,7 +6689,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-update" name = "kigi-update"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"dunce", "dunce",
@@ -6718,14 +6718,14 @@ dependencies = [
[[package]] [[package]]
name = "kigi-version" name = "kigi-version"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"semver", "semver",
] ]
[[package]] [[package]]
name = "kigi-workspace" name = "kigi-workspace"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"agent-client-protocol", "agent-client-protocol",
"anyhow", "anyhow",
@@ -6804,7 +6804,7 @@ dependencies = [
[[package]] [[package]]
name = "kigi-workspace-types" name = "kigi-workspace-types"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"base64", "base64",
"chrono", "chrono",
@@ -8838,7 +8838,7 @@ dependencies = [
[[package]] [[package]]
name = "ptyctl" name = "ptyctl"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"alacritty_terminal", "alacritty_terminal",
"anyhow", "anyhow",
@@ -8856,7 +8856,7 @@ dependencies = [
[[package]] [[package]]
name = "ptyctl-cli" name = "ptyctl-cli"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"axum", "axum",
+1 -1
View File
@@ -76,7 +76,7 @@ members = [
] ]
[workspace.package] [workspace.package]
version = "0.1.1" version = "0.1.2"
edition = "2024" edition = "2024"
license = "Apache-2.0" license = "Apache-2.0"
@@ -7,7 +7,8 @@
//! phase model: the terminator is the ellipse `x = cos(2πp)·√(1y²)`, with //! phase model: the terminator is the ellipse `x = cos(2πp)·√(1y²)`, with
//! sunlight arriving from the right while waxing and from the left while //! sunlight arriving from the right while waxing and from the left while
//! waning. The dark limb keeps a faint outline ring so the silhouette never //! waning. The dark limb keeps a faint outline ring so the silhouette never
//! disappears at new moon. //! disappears at new moon. A fixed map of lunar maria textures the disc:
//! dark blotches on the sunlit side, faint gray patches on the dark limb.
//! //!
//! Hidden entirely on legacy Windows consoles: the U+2800 braille block is //! Hidden entirely on legacy Windows consoles: the U+2800 braille block is
//! not covered by the ConHost raster fonts and would render as tofu. //! not covered by the ConHost raster fonts and would render as tofu.
@@ -52,6 +53,30 @@ const PULSE_SECS: f32 = 5.0;
/// Squared inner radius (normalized) of the dark-limb outline ring. /// Squared inner radius (normalized) of the dark-limb outline ring.
const RING_INNER_SQ: f32 = 0.82; const RING_INNER_SQ: f32 = 0.82;
/// Lunar maria as `(cx, cy, radius²)` in normalized disc coordinates
/// (x right, y down), loosely after the near side's real maria. On the
/// sunlit disc a mare dot is drawn in the resting gray (a dark blotch);
/// on the dark limb it is drawn in the same gray, which reads as a faint
/// light patch against the empty limb.
const MARIA: &[(f32, f32, f32)] = &[
(-0.40, -0.42, 0.018), // Imbrium
(0.12, -0.50, 0.008), // Serenitatis
(0.40, -0.22, 0.012), // Tranquillitatis
(0.55, 0.20, 0.005), // Fecunditatis
(0.62, -0.42, 0.004), // Crisium
(-0.58, 0.05, 0.010), // Procellarum
(-0.28, 0.40, 0.006), // Nubium
(0.08, 0.12, 0.004), // Vaporum
];
fn in_mare(dx: f32, dy: f32) -> bool {
MARIA.iter().any(|&(mx, my, r_sq)| {
let ex = dx - mx;
let ey = dy - my;
ex * ex + ey * ey <= r_sq
})
}
/// One logo size tier, in braille cells. /// One logo size tier, in braille cells.
#[derive(Clone, Copy, PartialEq, Eq, Debug)] #[derive(Clone, Copy, PartialEq, Eq, Debug)]
struct MoonSize { struct MoonSize {
@@ -152,8 +177,8 @@ fn moon_cells(size: MoonSize, p: f32) -> Vec<Vec<Option<MoonCell>>> {
.map(|cell_row| { .map(|cell_row| {
(0..size.cols as i32) (0..size.cols as i32)
.map(|cell_col| { .map(|cell_col| {
let mut mask = 0u32; let mut lit_mask = 0u32;
let mut lit = false; let mut dark_mask = 0u32;
for (dot_col, col_bits) in DOT_BITS.iter().enumerate() { for (dot_col, col_bits) in DOT_BITS.iter().enumerate() {
for (dot_row, bit) in col_bits.iter().enumerate() { for (dot_row, bit) in col_bits.iter().enumerate() {
let x = cell_col * 2 + dot_col as i32; let x = cell_col * 2 + dot_col as i32;
@@ -164,15 +189,28 @@ fn moon_cells(size: MoonSize, p: f32) -> Vec<Vec<Option<MoonCell>>> {
if d_sq > 1.0 { if d_sq > 1.0 {
continue; continue;
} }
let mare = in_mare(dx, dy);
if dot_lit(dx, dy, p) { if dot_lit(dx, dy, p) {
mask |= bit; if mare {
lit = true; // Dark blotch on the sunlit disc.
} else if d_sq >= RING_INNER_SQ { dark_mask |= bit;
// Dark limb: keep the outline ring visible. } else {
mask |= bit; lit_mask |= bit;
}
} else if mare || d_sq >= RING_INNER_SQ {
// Dark limb: outline ring plus faint maria.
dark_mask |= bit;
} }
} }
} }
// A braille cell holds a single color, so a cell with any
// sunlit dots renders only those (mare dots in it stay
// background-dark); otherwise its dark dots render gray.
let (mask, lit) = if lit_mask != 0 {
(lit_mask, true)
} else {
(dark_mask, false)
};
(mask != 0).then(|| MoonCell { (mask != 0).then(|| MoonCell {
ch: char::from_u32(0x2800 + mask).expect("braille block"), ch: char::from_u32(0x2800 + mask).expect("braille block"),
lit, lit,
@@ -407,6 +445,32 @@ mod tests {
); );
} }
#[test]
fn maria_texture_the_disc_in_both_extremes() {
// Full moon: mare dots stay dark, so the drawn glyphs must cover
// fewer dots than the geometric disc (lit_dots ignores maria).
let full = moon_cells(FULL, 0.5);
let drawn_dots: u32 = full
.iter()
.flatten()
.flatten()
.map(|c| (c.ch as u32 - 0x2800).count_ones())
.sum();
assert!(
(drawn_dots as usize) < lit_dots(0.5),
"full moon must keep dark maria holes"
);
// New moon: maria show as drawn (gray) cells well inside the outline
// ring — Procellarum sits around cell (5, 4) on the full-size grid.
let new = moon_cells(FULL, 0.0);
assert!(
new[5][4].is_some(),
"new moon must show maria inside the ring"
);
assert!(in_mare(-0.58, 0.05), "Procellarum anchors the maria map");
assert!(!in_mare(0.0, 0.85), "south pole stays mare-free");
}
#[test] #[test]
fn moon_raster_is_round_and_fills_the_grid() { fn moon_raster_is_round_and_fills_the_grid() {
// The disc must span (nearly) the whole cell grid in both axes at // The disc must span (nearly) the whole cell grid in both axes at