Skip to content
Merged
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
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,9 @@ if(Python3_Interpreter_FOUND)
add_test(NAME registry_gaps_fire COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tests/registry_gaps_test.py)
# a pin bump that did not regenerate the registry (only the gitlinks: no checkouts)
add_test(NAME registry_pins COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/registry_build.py --check-pins)
# the new-model watcher's alert contract (offline: synthetic batches against the
# committed registry), so a regression cannot leave the daily alert permanently green.
add_test(NAME census_watch COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tests/census_watch_test.py)
endif()

add_executable(npu_full_elf_test tests/npu_full_elf_test.cpp)
Expand Down
32 changes: 32 additions & 0 deletions docs/registry.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,36 @@ of those models was run. The unmapped architectures with the most models are
`Step1MoEForCausalLM` (2,882), `OPTForCausalLM` (2,097), `ParlerTTSForConditionalGeneration`
(1,586) and `GPTNeoForCausalLM` (1,565). `tools/census.py --pr-body` lists the top ten.

## The watch

The sweep is a snapshot, so a class that appears *tomorrow* moves the mapped share
quietly. `tools/census_watch.py` polls the newest text-generation models (createdAt
descending), reads each one's architecture class from the config inline in the listing,
and compares it against `registry/architectures.json` — the same read `census.py`'s
coverage() makes, so "uncovered" here means "not in the number the census reports". No
per-model fetch and no compiled probe: the registry is generated data, keyed by the HF
architecture class the census counts.

Exit 0 means every newest model is mapped; **exit 1 is the alert** — a class arrived that
no backend accepts. It is run daily at 04:30 UTC (ahead of the 05:17 sweep) by the systemd
timer on the development box (`scripts/1bit-census-watch.{service,timer}`, from the
`~/census-main` worktree that tracks `origin/main`). The timer marks its unit failed, and
every run lands in `~/.1bit/logs/census-watch-*.log`. A GitHub Actions path that files an
alert issue needs `issues: write`, so it waits for an RFC.

A class the watcher flags is one of two things, and the run says which:

- **new class** — map it in `registry/architectures.json`, but only when a pinned
backend's code really accepts the architecture (rule 3 in CONTRIBUTING.md: recognized
is not verified).
- **reviewed, not an alias** — already in `registry/significant.json`
([arch-gaps.md](arch-gaps.md)); it needs real engine support, and if a backend starts
accepting it, the reason is recorded as `mapped_ok`.

Gated repos (no config without a token) are reported as unverifiable and never fail the
run; derivatives (a quantized GGUF, a LoRA adapter) have no config by design and are
skipped, because the release they derive from carries the config and is what gets checked.

## Commands

```
Expand All @@ -119,4 +149,6 @@ tools/registry_build.py --check # exit 1 if it is stale
tools/registry_check.py build/1bit --models ~/models # run the checks on Strix Halo
tools/census.py # full HF sweep (about 420 pages)
tools/census.py --report # recompute coverage from the saved counts
tools/census_watch.py # newest models vs the registry; exit 1 on an uncovered class
scripts/census-watch.sh # the same, with the log file and the origin/main refresh
```
59 changes: 59 additions & 0 deletions scripts/1bit-census-watch.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Copyright 2026 bong-water-water-bong
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# 1bit-census-watch.service — run the daily HF new-model census watcher
#
# One-shot unit that runs tools/census_watch.py through scripts/census-watch.sh from a
# DEDICATED checkout that tracks origin/main (~/census-main, a worktree), so the watcher
# always reads the registry that is actually on main. Exit 1 (an uncovered architecture
# class) is the ALERT: systemd marks the unit failed, which a journald watch or health
# check can surface, and the full log lands in ~/.1bit/logs/census-watch-*.log. Exit 0
# means the newest HF models are all mapped — silent, as intended.
#
# Schedules via scripts/1bit-census-watch.timer (04:30 daily, persistent); can also be
# triggered manually:
# systemctl --user start 1bit-census-watch
#
# ── Install (user units, no sudo) ─────────────────────────────────────────
# git clone https://github.com/1bit-MONSTER/engine.git ~/engine
# git -C ~/engine worktree add --detach ~/census-main origin/main
# install -d ~/.config/systemd/user
# install -m644 ~/engine/scripts/1bit-census-watch.{service,timer} ~/.config/systemd/user/
# systemctl --user daemon-reload
# systemctl --user enable --now 1bit-census-watch.timer
# systemctl --user list-timers 1bit-census-watch
# journalctl --user -u 1bit-census-watch -f
#
# ── Paths ─────────────────────────────────────────────────────────────────
# %h/census-main must match your worktree (the checkout the watcher runs from). Change if
# it lives elsewhere. CENSUS_WATCH_REFRESH=1 fast-forwards that checkout to origin/main
# before each run; the script refuses a checkout that is on a branch or has local changes.
# Logs go to ~/.1bit/logs (override with CENSUS_WATCH_LOG_DIR).

[Unit]
Description=1bit census: watch HF for new model classes the registry does not map
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
WorkingDirectory=%h/census-main
Environment=CENSUS_WATCH_REFRESH=1
ExecStart=%h/census-main/scripts/census-watch.sh
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=default.target
35 changes: 35 additions & 0 deletions scripts/1bit-census-watch.timer
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Copyright 2026 bong-water-water-bong
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# 1bit-census-watch.timer — 04:30 UTC daily, persisted across downtime.
#
# UTC explicitly, because that is what the census-watch workflow's cron uses: the box
# run and the CI run then see the same day's arrivals. (A bare 04:30 is the machine's
# local time, which on the development box is three hours later.) The census sweep
# itself follows at 05:17 UTC (census.yml).
#
# systemctl --user enable --now 1bit-census-watch.timer
# systemctl --user list-timers 1bit-census-watch

[Unit]
Description=Daily 1bit census: new HF model classes are covered

[Timer]
OnCalendar=*-*-* 04:30:00 UTC
Persistent=true
Unit=1bit-census-watch.service

[Install]
WantedBy=timers.target
83 changes: 83 additions & 0 deletions scripts/census-watch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env bash
# Copyright 2026 bong-water-water-bong
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# census-watch.sh — daily HF new-model watcher entry point
#
# Wraps tools/census_watch.py so the daily watch is one command, usable from the systemd
# units (scripts/1bit-census-watch.{service,timer}) or by hand. The automation is reproducible from the repo
# instead of living ad-hoc on one box.
#
# What it does: polls the newest HF text-generation models, reads each one's architecture
# class from the config inline in the listing, and compares it against the generated
# registry (registry/architectures.json) — the same read tools/census.py's coverage()
# makes. Any new class the registry does not map is the alert: that is the one thing that
# silently moves the mapped share the census reports.
#
# Exit codes (same contract as tools/census_watch.py):
# 0 no uncovered classes among the newest models
# 1 an uncovered class arrived (the alert)
# 2 the refresh step refused to touch the checkout
# * runtime failure (no network, unreadable registry, ...)
#
# Usage:
# scripts/census-watch.sh [--limit N] # N newest models, default 120
#
# Every run is appended to $CENSUS_WATCH_LOG_DIR (default ~/.1bit/logs) AND echoed to
# stdout, so systemd/journald/CI all see the same output. Watcher state (the model ids
# already classified) lives at $CENSUS_WATCH_STATE, outside the checkout.
#
# CENSUS_WATCH_REFRESH=1 fast-forwards the checkout to origin/main before each run. It
# refuses to touch a checkout that is on a branch or has local changes, so pointing this
# at a working lane can never wipe it. It is meant for the ~/census-main worktree, which
# is a `git worktree add --detach ~/census-main origin/main`.

set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
LOG_DIR="${CENSUS_WATCH_LOG_DIR:-${HOME}/.1bit/logs}"
STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
LOG="${LOG_DIR}/census-watch-${STAMP}.log"

mkdir -p "${LOG_DIR}"

if [ "${CENSUS_WATCH_REFRESH:-0}" = "1" ]; then
branch="$(git -C "${ROOT}" rev-parse --abbrev-ref HEAD)"
if [ "${branch}" != "HEAD" ]; then
echo "census-watch: refusing to refresh: ${ROOT} is on branch ${branch}" >&2
exit 2
fi
if ! git -C "${ROOT}" diff --quiet || ! git -C "${ROOT}" diff --cached --quiet; then
echo "census-watch: refusing to refresh: ${ROOT} has local changes" >&2
exit 2
fi
git -C "${ROOT}" fetch -q origin main
git -C "${ROOT}" reset -q --hard origin/main
echo "census-watch: refreshed ${ROOT} to origin/main ($(git -C "${ROOT}" rev-parse --short HEAD))"
fi

echo "== census-watch $(date -u +%FT%TZ) ==" | tee "${LOG}"

set +e
python3 "${ROOT}/tools/census_watch.py" "$@" 2>&1 | tee -a "${LOG}"
RC=${PIPESTATUS[0]}
set -e

if [ "${RC}" -ne 0 ]; then
echo "census-watch: EXIT ${RC} (an uncovered class needs a registry mapping;" \
"full log: ${LOG})" | tee -a "${LOG}"
fi

exit "${RC}"
Loading
Loading