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
12 changes: 6 additions & 6 deletions .github/workflows/spec-guards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,15 @@ jobs:
# gen/c/claw/gates.c is committed (force-added; gen/ is ignored but
# tracked) and the claw-drift step in gate-topology.yml feeds those
# COMMITTED bytes -- nothing else holds them to their spec. An edit to
# specs/claw/gates.t27 without a regen would drift silently: the
# committed C would keep answering for a spec it no longer lowers.
# Same shape as t27o-golden's check mode (#8996): regenerate, then
# diff --exit-code.
- name: committed gen/c/claw/gates.c and t27f_gate.c are what their specs lower to today
# specs/claw/gates.t27 without a regen would drift silently. So would the IGLA board's
# own_model event, which a Railway cron reposts from master's committed JSON (#10321).
# Same shape as t27o-golden's check mode (#8996): regenerate, then diff --exit-code.
- name: committed gen/c/claw/*.c and gen/json/igla/own_model_board.json are what their specs lower to today
run: |
./target/release/t27c gen-c specs/claw/gates.t27 > gen/c/claw/gates.c
./target/release/t27c gen-c specs/claw/t27f_gate.t27 > gen/c/claw/t27f_gate.c
git diff --exit-code -- gen/c/claw/gates.c gen/c/claw/t27f_gate.c
./target/release/t27c gen-json specs/igla/own_model_board.t27 > gen/json/igla/own_model_board.json
git diff --exit-code -- gen/c/claw/gates.c gen/c/claw/t27f_gate.c gen/json/igla/own_model_board.json

# #7565: test only the specs this change can affect. specs/ci/affected.t27 picks them (the
# changed specs and every spec that imports one through `use`, transitively); the graph is the
Expand Down
28 changes: 28 additions & 0 deletions .trinity/seals/crons_cron_t27_own_model_board.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"built_by": "t27c-bootstrap@0.5.2+79126608b",
"closure": [],
"config": "gen=c,rust,verilog,zig;tests=zig",
"gen_hash_c": "sha256:85795a37414e093c16332554b79f7de01d40e6a4111ad2bcff55c6c51dc51c59",
"gen_hash_rust": "sha256:aff9afd3ae6f0a87fdff5b0d722f17b27eb20edf9213b7f80dd6a966d9509aaa",
"gen_hash_verilog": "sha256:cd58d73af401293da1e1d909746c535f792224a36b2ecee76a653b450e8c8ff7",
"gen_hash_zig": "sha256:6d8b5e3d207ebd83d018fcb4949e80f69e478c5bbd3d769e49068d98d55010a0",
"module": "cron_t27_own_model_board",
"ring": 12,
"seal_schema": 2,
"sealed_at": "2026-10-18T08:54:26Z",
"sealed_by": "t27c-bootstrap@0.5.2",
"spec_hash": "sha256:3032ee2782ec57a66af46e64bb269d5185a8a08bacaeb2db26cb48cbe1f7f921",
"spec_path": "specs/crons/t27-own-model-board.t27",
"tests": {
"failed": 0,
"failing": [],
"forced": false,
"passed": 3,
"total": 3,
"vacuous": 0
},
"toolchain": {
"test_runner": "sha256:1982ae948e24d00c5d221ccec12dfce1eb01204b53e37b0f857f93b16d64629d",
"zig": "0.16.0"
}
}
1 change: 1 addition & 0 deletions gen/json/igla/own_model_board.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"job":"own_model","stage":"own_model","msg":"1 published, 17 verified, 8 drafts, 1 gaps; 61%","progress":0.61,"metrics":{"lens_pct":[65,70,48],"cells":[{"status":4,"pct":60},{"status":4,"pct":70},{"status":4,"pct":80},{"status":4,"pct":80},{"status":4,"pct":60},{"status":4,"pct":100},{"status":3,"pct":50},{"status":3,"pct":90},{"status":0,"pct":0},{"status":4,"pct":100},{"status":4,"pct":100},{"status":4,"pct":20},{"status":4,"pct":80},{"status":4,"pct":65},{"status":4,"pct":95},{"status":3,"pct":75},{"status":3,"pct":55},{"status":3,"pct":40},{"status":4,"pct":70},{"status":4,"pct":15},{"status":5,"pct":60},{"status":4,"pct":40},{"status":4,"pct":100},{"status":4,"pct":60},{"status":3,"pct":30},{"status":3,"pct":10},{"status":3,"pct":50}]}}
89 changes: 89 additions & 0 deletions specs/crons/t27-own-model-board.t27
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: Apache-2.0
; specs/crons/t27-own-model-board.t27 -- cron railway-cron/t27/own-model-board
; Source of truth for the job card on t27.ai (#/crons?cron=railway-cron/t27/own-model-board).
; The schedule lives on Railway service own-model-board in project igla-judge (the board's project,
; so the board's private port is reachable); the payload lives here, in gHashTag/t27 (#10321).
; What one fire does, in words: fetch master's gen/json/igla/own_model_board.json from
; raw.githubusercontent.com and POST it, unchanged, to http://board.railway.internal:8081/event.
; That file is `t27c gen-json specs/igla/own_model_board.t27`, held to its spec by spec-guards.yml
; (regenerate, then git diff --exit-code). So a spec change reaches the board at the next fire,
; and a board redeploy, which empties its live map, is repaired at the next fire too.
; The service is the public image curlimages/curl and holds no variable: the private port takes
; no token, and the public repository needs none.
; A cron CONTROLS skills: RUNS names the skill IDs it launches. It is empty
; unless the source evidently invokes one -- nothing here is inferred from a name.
; phi^2 + 1/phi^2 = 3 | TRINITY

module cron_t27_own_model_board;

pub const KIND : str = "cron";
pub const ID : str = "railway-cron/t27/own-model-board";
pub const NAME : str = "own-model-board";
pub const HOST : str = "railway-cron";
pub const REPO : str = "t27";
pub const SERVICE : str = "own-model-board";
pub const SUMMARY_EN : str = "Reposts the own_model event (the 27-cell map of specs/igla/own_model.t27) to the IGLA board, from the JSON t27c generates on master.";
; Four fires a day: an event that has not changed only refreshes its receive time, and the
; board keeps the last 200 events, so a tighter period would crowd out every other job.
pub const SCHEDULE : str = "17 */6 * * *";
pub const TZ : str = "UTC";
pub const RUNS : [0]str = [];
pub const RUNS_NOTE : str = "posts one board event; invokes no skill";
pub const ENABLED : bool = true;
pub const NOTE : str = "Railway project igla-judge, service own-model-board. The schedule is set on the service, not in a checkout; the payload is gen/json/igla/own_model_board.json on master.";
pub const ON_FAILURE : str = "log";
pub const CONTROL : str = "railway-dashboard";

; The card held to the schema of specs/crons/README.md: ID is <host>/<repo>/<slug>; HOST,
; ON_FAILURE and CONTROL come from fixed vocabularies; RUNS, the control link, is empty unless
; the source evidently invokes a skill, and RUNS_NOTE then says why.
test id_is_host_repo_and_slug {
// HOST is one of the five hosts the README names.
assert HOST == "github-actions" or HOST == "inngest" or HOST == "railway-cron" or HOST == "timer" or HOST == "launchd";
// ID opens with HOST, a `/`, REPO and a `/`.
var i : usize = 0;
while (i < HOST.len) {
assert ID[i] == HOST[i];
i = i + 1;
}
assert ID[HOST.len] == '/';
var r : usize = 0;
while (r < REPO.len) {
assert ID[HOST.len + 1 + r] == REPO[r];
r = r + 1;
}
assert ID[HOST.len + 1 + REPO.len] == '/';
// The slug after it is one path segment, not empty, and names the Railway service.
assert ID.len == HOST.len + REPO.len + 2 + SERVICE.len;
var s : usize = 0;
while (s < SERVICE.len) {
assert ID[HOST.len + REPO.len + 2 + s] == SERVICE[s];
assert SERVICE[s] != '/' and SERVICE[s] != ' ';
s = s + 1;
}
}
test vocabularies_and_the_control_link {
assert KIND == "cron";
assert ON_FAILURE == "issue" or ON_FAILURE == "log" or ON_FAILURE == "unknown";
assert CONTROL == "github-actions-dispatch" or CONTROL == "railway-dashboard" or CONTROL == "inngest-dashboard" or CONTROL == "code-only";
// An empty RUNS carries its reason in RUNS_NOTE.
assert RUNS.len > 0 or RUNS_NOTE.len > 0;
}
test the_schedule_is_four_fires_a_day {
// Five fields separated by single spaces, no blank field.
var spaces : usize = 0;
var k : usize = 0;
while (k < SCHEDULE.len) {
if (SCHEDULE[k] == ' ') {
spaces = spaces + 1;
assert k > 0 and k + 1 < SCHEDULE.len and SCHEDULE[k + 1] != ' ';
}
k = k + 1;
}
assert spaces == 4;
// A fixed minute, not `*`: one fire per matching hour. Hour field `*/6`: four a day.
assert SCHEDULE[0] >= '0' and SCHEDULE[0] <= '9';
assert SCHEDULE[3] == '*' and SCHEDULE[4] == '/' and SCHEDULE[5] == '6';
assert TZ == "UTC";
assert ENABLED;
}
Loading