Project P171

Alert rules

Three monitors on one service: an alert on the crossing pages once while the disk fills for three days, a spike falls between two reads of a gauge, and minutes with no sample are recorded as zero.

2 modules · 2 recorded sessionstext-menu UI in the terminalupdated 2026-10-19

Every screen below was recorded under CPython. When this page was built, the EML interpreter replayed each session from the same input and printed the same bytes.

About

Three monitors on one service, each right about what it measures, and what each one does not report.

  • main.eml - the menu, the monitors, the disk alert, a spike between reads, the minutes an exporter was down, and a read interval of your own
  • alerts.eml - free space over three days, the pages each rule sends, the load second by second, which reads land in a spike, and the load minute by minute with the exporter's outage

How each part works:

  • As in the corpus case the-alert-fired-once-and-the-condition-held-for-days, the disk alert holds below 15.0% free, and free space falls from 14.0% to 3.0% over 72 hours, 864 evaluations. On the crossing only: 1 page. On every evaluation: 864. On the crossing and every 4 hours after: 18. The edge rule did what it was written to do, and nothing it sends says the disk went on filling.
  • As in the-spike-fit-between-two-samples, the load is read once a minute, and a 20-second spike to 2,000 requests a second starts at 1815 s, between the reads at 1800 and 1860: every read shows 300, and the service drops 20,000 requests over its capacity of 1,000. A read of the highest value since the last read reports the 2,000.
  • As in the-missing-metric-was-read-as-zero, the exporter is down for minutes 30 to 47 while the real load is 1,400, over the threshold of 500; the 18 minutes are recorded as 0, and the alert stays quiet.
  • For a read every n seconds, a spike of n seconds or more always holds a read, and a shorter one can fall between two.

What is checked: menu choices 1 to 6; a read every 1 to 600 seconds, a spike starting at second 0 to 3599 and lasting 1 to 600 seconds. An empty answer cancels.

Sessions: sessions/basic.in gives: - the monitors, the disk alert, the spike and the missing minutes; - your own: reads every 60 s and every 15 s around the spike, and a 60-second spike from 1790 s.

sessions/bad-input.in gives: - menu choices 0 and x; - intervals: a cancel, 0, 601 and x; starts: a cancel, 3600 and x; lengths: a cancel, 0, 601 and x; - a read every second, and every 300 s with a 299-second spike.

Built on the verified corpus cases the-alert-fired-once-and-the-condition-held-for-days (a disk alert that fires on the crossing), the-spike-fit-between-two-samples (a gauge sampled every 60 seconds and a 20-second spike) and the-missing-metric-was-read-as-zero (an exporter outage recorded as zero).

Recorded sessions

What the screen shows while someone uses the program. Each typed line appears after its prompt, the way a terminal shows it.

bad-input

interpreter: byte-equal
== Alert rules ==
Three monitors, each right about what it measures, and what each one does not report.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 0
Pick a number from 1 to 6.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> x
Pick a number from 1 to 6.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 
Cancelled.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 0
Type a whole number from 1 to 600.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 601
Type a whole number from 1 to 600.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> x
Type a whole number from 1 to 600.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 30
spike starts at second (0 to 3599)> 
Cancelled.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 30
spike starts at second (0 to 3599)> 3600
Type a whole number from 0 to 3599.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 30
spike starts at second (0 to 3599)> x
Type a whole number from 0 to 3599.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 30
spike starts at second (0 to 3599)> 100
spike lasts seconds (1 to 600)> 
Cancelled.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 30
spike starts at second (0 to 3599)> 100
spike lasts seconds (1 to 600)> 0
Type a whole number from 1 to 600.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 30
spike starts at second (0 to 3599)> 100
spike lasts seconds (1 to 600)> 601
Type a whole number from 1 to 600.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 30
spike starts at second (0 to 3599)> 100
spike lasts seconds (1 to 600)> x
Type a whole number from 1 to 600.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 1
spike starts at second (0 to 3599)> 100
spike lasts seconds (1 to 600)> 3
Reads every 1 s: the spike from 100 s for 3 s holds 3 reads, from 100 s.
With a read every second, every spike holds a read.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 300
spike starts at second (0 to 3599)> 3550
spike lasts seconds (1 to 600)> 299
Reads every 300 s: the spike from 3550 s for 299 s holds 1 read, at 3600 s.
A spike of 300 seconds or more always holds a read; a shorter one can fall between two.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 6
Bye.
What was typed (44 lines)
0
x
5

5
0
5
601
5
x
5
30

5
30
3600
5
30
x
5
30
100

5
30
100
0
5
30
100
601
5
30
100
x
5
1
100
3
5
300
3550
299
6

basic

interpreter: byte-equal
== Alert rules ==
Three monitors, each right about what it measures, and what each one does not report.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 1
Three monitors on one service:
  disk      free space, read every 5 minutes; the alert holds below 15.0%
  load      requests a second, read once a minute; the alert fires over 500, and the service drops what is over 1,000
  exporter  the load reaches the monitor through an exporter; a minute without a sample is recorded as 0

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 2
Free space after it crossed below 15.0%, while a cleanup fails to keep up:
  hour   free
  0      14.0%
  12     12.2%
  24     10.4%
  36     8.5%
  48     6.7%
  60     4.9%
  72     3.0%
The condition held for all 72 hours, 864 evaluations. Pages sent:
  on the crossing only                      1 page
  on every evaluation                    864 pages
  on the crossing, then every 4 hours     18 pages
The edge rule did what it was written to do: one page. Nothing it sends says that the disk went on filling for three days.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 3
The hour's load, read once a minute, around the half hour:
  read at   requests a second
  1740 s    300
  1800 s    300
  1860 s    300
  1920 s    300
The highest of the 60 reads: 300. The highest second of the hour: 2,000, from 1815 s for 20 seconds, between the reads at 1800 and 1860.
Over capacity for those 20 seconds, the service dropped 20,000 requests, and no read was over the threshold.
Read as the highest value since the last read, the 1860 s read reports 2,000.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 4
The last hour, minute by minute: 42 minutes with a sample and 18 without, minutes 30 to 47, recorded as 0.
  minutes    real load  recorded
  0-29             300       300
  30-47          1,400         0
  48-59            300       300
The highest recorded minute: 300, under the threshold of 500, so the alert stayed quiet. The real load was 1,400 for those 18 minutes, 900 over it.
Recorded as missing rather than as 0, the same minutes raise a no-data alert at minute 30.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 60
spike starts at second (0 to 3599)> 1815
spike lasts seconds (1 to 600)> 20
Reads every 60 s: the spike from 1815 s for 20 s holds no read, and the gauge never sees it.
A spike of 60 seconds or more always holds a read; a shorter one can fall between two.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 15
spike starts at second (0 to 3599)> 1815
spike lasts seconds (1 to 600)> 20
Reads every 15 s: the spike from 1815 s for 20 s holds 2 reads, from 1815 s.
A spike of 15 seconds or more always holds a read; a shorter one can fall between two.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 5
read every how many seconds (1 to 600)> 60
spike starts at second (0 to 3599)> 1790
spike lasts seconds (1 to 600)> 60
Reads every 60 s: the spike from 1790 s for 60 s holds 1 read, at 1800 s.
A spike of 60 seconds or more always holds a read; a shorter one can fall between two.

1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit
choice> 6
Bye.
What was typed (17 lines)
1
2
3
4
5
60
1815
20
5
15
1815
20
5
60
1790
60
6

Modules

The program as written, entry module first. Each module transpiles to its own Python file, which is what eml project run executes.

main.eml(entry)

eml
# P171 alert rules: three monitors on one service - the disk alert over
# three days, a spike between two reads of a gauge, the minutes an exporter
# was down, and a read interval of your own.
import alerts

def plain(s):
    0 => i
    len(s) => j
    while i < j and s[i] == " ":
        i + 1 => i
    while j > i and s[j - 1] == " ":
        j - 1 => j
    return s[i:j]

def pad(s, n):
    s => out
    while len(out) < n:
        out + " " => out
    return out

def lpad(s, n):
    s => out
    while len(out) < n:
        " " + out => out
    return out

def digits(t):
    for c in t:
        if c < "0" or c > "9":
            return False
    return len(t) > 0

def commas(n):
    str(n) => s
    "" => out
    0 => k
    len(s) => i
    while i > 0:
        if k == 3:
            "," + out => out
            0 => k
        s[i - 1] + out => out
        k + 1 => k
        i - 1 => i
    return out

def pct(t):
    # tenths of a percent
    return str(int((t - t % 10) / 10)) + "." + str(t % 10) + "%"

def plural(n, word):
    if n == 1:
        return "1 " + word
    return commas(n) + " " + word + "s"

def show_monitors():
    "Three monitors on one service:" ^0
    ("  " + pad("disk", 10) + "free space, read every 5 minutes; the alert holds below " + pct(alerts.disk_threshold())) ^0
    ("  " + pad("load", 10) + "requests a second, read once a minute; the alert fires over " + commas(alerts.load_threshold()) + ", and the service drops what is over " + commas(alerts.capacity())) ^0
    ("  " + pad("exporter", 10) + "the load reaches the monitor through an exporter; a minute without a sample is recorded as 0") ^0

def show_disk():
    "Free space after it crossed below 15.0%, while a cleanup fails to keep up:" ^0
    ("  " + pad("hour", 7) + "free") ^0
    0 => h
    while h <= 72:
        ("  " + pad(str(h), 7) + pct(alerts.free(h))) ^0
        h + 12 => h
    ("The condition held for all 72 hours, " + commas(alerts.evaluations()) + " evaluations. Pages sent:") ^0
    ("  " + pad("on the crossing only", 38) + lpad(plural(alerts.pages("edge", 4), "page"), 10)) ^0
    ("  " + pad("on every evaluation", 38) + lpad(plural(alerts.pages("level", 4), "page"), 10)) ^0
    ("  " + pad("on the crossing, then every 4 hours", 38) + lpad(plural(alerts.pages("reminder", 4), "page"), 10)) ^0
    "The edge rule did what it was written to do: one page. Nothing it sends says that the disk went on filling for three days." ^0

def show_spike():
    "The hour's load, read once a minute, around the half hour:" ^0
    ("  " + pad("read at", 10) + "requests a second") ^0
    0 => most
    0 => s
    while s < 3600:
        if alerts.load(s) > most:
            alerts.load(s) => most
        if s >= 1740 and s <= 1920:
            ("  " + pad(str(s) + " s", 10) + commas(alerts.load(s))) ^0
        s + 60 => s
    0 => peak
    0 => dropped
    0 => t
    while t < 3600:
        if alerts.load(t) > peak:
            alerts.load(t) => peak
        if alerts.load(t) > alerts.capacity():
            dropped + alerts.load(t) - alerts.capacity() => dropped
        t + 1 => t
    ("The highest of the 60 reads: " + commas(most) + ". The highest second of the hour: " + commas(peak) + ", from 1815 s for 20 seconds, between the reads at 1800 and 1860.") ^0
    ("Over capacity for those 20 seconds, the service dropped " + commas(dropped) + " requests, and no read was over the threshold.") ^0
    ("Read as the highest value since the last read, the 1860 s read reports " + commas(peak) + ".") ^0

def show_missing():
    0 => up
    0 => recorded_max
    0 => m
    while m < 60:
        if alerts.exporter_up(m):
            up + 1 => up
            if alerts.minute_load(m) > recorded_max:
                alerts.minute_load(m) => recorded_max
        m + 1 => m
    ("The last hour, minute by minute: " + str(up) + " minutes with a sample and " + str(60 - up) + " without, minutes 30 to 47, recorded as 0.") ^0
    ("  " + pad("minutes", 10) + lpad("real load", 10) + lpad("recorded", 10)) ^0
    ("  " + pad("0-29", 10) + lpad(commas(alerts.minute_load(0)), 10) + lpad(commas(alerts.minute_load(0)), 10)) ^0
    ("  " + pad("30-47", 10) + lpad(commas(alerts.minute_load(30)), 10) + lpad("0", 10)) ^0
    ("  " + pad("48-59", 10) + lpad(commas(alerts.minute_load(48)), 10) + lpad(commas(alerts.minute_load(48)), 10)) ^0
    ("The highest recorded minute: " + commas(recorded_max) + ", under the threshold of " + commas(alerts.load_threshold()) + ", so the alert stayed quiet. The real load was " + commas(alerts.minute_load(30)) + " for those 18 minutes, " + commas(alerts.minute_load(30) - alerts.load_threshold()) + " over it.") ^0
    "Recorded as missing rather than as 0, the same minutes raise a no-data alert at minute 30." ^0

def number(prompt, lo, hi):
    # the whole number typed, or -1 after a cancel or a message
    plain(input(prompt + " (" + str(lo) + " to " + str(hi) + ")> ")) => t
    if t == "":
        "Cancelled." ^0
        return 0 - 1
    if len(t) > len(str(hi)) or not digits(t) or int(t) < lo or int(t) > hi:
        ("Type a whole number from " + str(lo) + " to " + str(hi) + ".") ^0
        return 0 - 1
    return int(t)

def own():
    number("read every how many seconds", 1, 600) => every
    if every < 0:
        return
    number("spike starts at second", 0, 3599) => start
    if start < 0:
        return
    number("spike lasts seconds", 1, 600) => length
    if length < 0:
        return
    alerts.samples_in(start, length, every) => got
    if len(got) == 0:
        ("Reads every " + str(every) + " s: the spike from " + str(start) + " s for " + str(length) + " s holds no read, and the gauge never sees it.") ^0
    elif len(got) == 1:
        ("Reads every " + str(every) + " s: the spike from " + str(start) + " s for " + str(length) + " s holds 1 read, at " + str(got[0]) + " s.") ^0
    else:
        ("Reads every " + str(every) + " s: the spike from " + str(start) + " s for " + str(length) + " s holds " + str(len(got)) + " reads, from " + str(got[0]) + " s.") ^0
    if every == 1:
        "With a read every second, every spike holds a read." ^0
    else:
        ("A spike of " + str(every) + " seconds or more always holds a read; a shorter one can fall between two.") ^0

"== Alert rules ==" ^0
"Three monitors, each right about what it measures, and what each one does not report." ^0
True => running
while running:
    "" ^0
    "1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit" ^0
    plain(input("choice> ")) => choice
    if choice == "1":
        show_monitors()
    elif choice == "2":
        show_disk()
    elif choice == "3":
        show_spike()
    elif choice == "4":
        show_missing()
    elif choice == "5":
        own()
    elif choice == "6":
        False => running
    else:
        "Pick a number from 1 to 6." ^0
"Bye." ^0
Python projection (main.py)
import alerts

def plain(s):
    i = 0
    j = len(s)
    while i < j and s[i] == " ":
        i = i + 1
    while j > i and s[j - 1] == " ":
        j = j - 1
    return s[i:j]

def pad(s, n):
    out = s
    while len(out) < n:
        out = out + " "
    return out

def lpad(s, n):
    out = s
    while len(out) < n:
        out = " " + out
    return out

def digits(t):
    for c in t:
        if c < "0" or c > "9":
            return False
    return len(t) > 0

def commas(n):
    s = str(n)
    out = ""
    k = 0
    i = len(s)
    while i > 0:
        if k == 3:
            out = "," + out
            k = 0
        out = s[i - 1] + out
        k = k + 1
        i = i - 1
    return out

def pct(t):
    return str(int((t - t % 10) / 10)) + "." + str(t % 10) + "%"

def plural(n, word):
    if n == 1:
        return "1 " + word
    return commas(n) + " " + word + "s"

def show_monitors():
    print("Three monitors on one service:")
    print("  " + pad("disk", 10) + "free space, read every 5 minutes; the alert holds below " + pct(alerts.disk_threshold()))
    print("  " + pad("load", 10) + "requests a second, read once a minute; the alert fires over " + commas(alerts.load_threshold()) + ", and the service drops what is over " + commas(alerts.capacity()))
    print("  " + pad("exporter", 10) + "the load reaches the monitor through an exporter; a minute without a sample is recorded as 0")

def show_disk():
    print("Free space after it crossed below 15.0%, while a cleanup fails to keep up:")
    print("  " + pad("hour", 7) + "free")
    h = 0
    while h <= 72:
        print("  " + pad(str(h), 7) + pct(alerts.free(h)))
        h = h + 12
    print("The condition held for all 72 hours, " + commas(alerts.evaluations()) + " evaluations. Pages sent:")
    print("  " + pad("on the crossing only", 38) + lpad(plural(alerts.pages("edge", 4), "page"), 10))
    print("  " + pad("on every evaluation", 38) + lpad(plural(alerts.pages("level", 4), "page"), 10))
    print("  " + pad("on the crossing, then every 4 hours", 38) + lpad(plural(alerts.pages("reminder", 4), "page"), 10))
    print("The edge rule did what it was written to do: one page. Nothing it sends says that the disk went on filling for three days.")

def show_spike():
    print("The hour's load, read once a minute, around the half hour:")
    print("  " + pad("read at", 10) + "requests a second")
    most = 0
    s = 0
    while s < 3600:
        if alerts.load(s) > most:
            most = alerts.load(s)
        if s >= 1740 and s <= 1920:
            print("  " + pad(str(s) + " s", 10) + commas(alerts.load(s)))
        s = s + 60
    peak = 0
    dropped = 0
    t = 0
    while t < 3600:
        if alerts.load(t) > peak:
            peak = alerts.load(t)
        if alerts.load(t) > alerts.capacity():
            dropped = dropped + alerts.load(t) - alerts.capacity()
        t = t + 1
    print("The highest of the 60 reads: " + commas(most) + ". The highest second of the hour: " + commas(peak) + ", from 1815 s for 20 seconds, between the reads at 1800 and 1860.")
    print("Over capacity for those 20 seconds, the service dropped " + commas(dropped) + " requests, and no read was over the threshold.")
    print("Read as the highest value since the last read, the 1860 s read reports " + commas(peak) + ".")

def show_missing():
    up = 0
    recorded_max = 0
    m = 0
    while m < 60:
        if alerts.exporter_up(m):
            up = up + 1
            if alerts.minute_load(m) > recorded_max:
                recorded_max = alerts.minute_load(m)
        m = m + 1
    print("The last hour, minute by minute: " + str(up) + " minutes with a sample and " + str(60 - up) + " without, minutes 30 to 47, recorded as 0.")
    print("  " + pad("minutes", 10) + lpad("real load", 10) + lpad("recorded", 10))
    print("  " + pad("0-29", 10) + lpad(commas(alerts.minute_load(0)), 10) + lpad(commas(alerts.minute_load(0)), 10))
    print("  " + pad("30-47", 10) + lpad(commas(alerts.minute_load(30)), 10) + lpad("0", 10))
    print("  " + pad("48-59", 10) + lpad(commas(alerts.minute_load(48)), 10) + lpad(commas(alerts.minute_load(48)), 10))
    print("The highest recorded minute: " + commas(recorded_max) + ", under the threshold of " + commas(alerts.load_threshold()) + ", so the alert stayed quiet. The real load was " + commas(alerts.minute_load(30)) + " for those 18 minutes, " + commas(alerts.minute_load(30) - alerts.load_threshold()) + " over it.")
    print("Recorded as missing rather than as 0, the same minutes raise a no-data alert at minute 30.")

def number(prompt, lo, hi):
    t = plain(input(prompt + " (" + str(lo) + " to " + str(hi) + ")> "))
    if t == "":
        print("Cancelled.")
        return 0 - 1
    if len(t) > len(str(hi)) or not digits(t) or int(t) < lo or int(t) > hi:
        print("Type a whole number from " + str(lo) + " to " + str(hi) + ".")
        return 0 - 1
    return int(t)

def own():
    every = number("read every how many seconds", 1, 600)
    if every < 0:
        return
    start = number("spike starts at second", 0, 3599)
    if start < 0:
        return
    length = number("spike lasts seconds", 1, 600)
    if length < 0:
        return
    got = alerts.samples_in(start, length, every)
    if len(got) == 0:
        print("Reads every " + str(every) + " s: the spike from " + str(start) + " s for " + str(length) + " s holds no read, and the gauge never sees it.")
    elif len(got) == 1:
        print("Reads every " + str(every) + " s: the spike from " + str(start) + " s for " + str(length) + " s holds 1 read, at " + str(got[0]) + " s.")
    else:
        print("Reads every " + str(every) + " s: the spike from " + str(start) + " s for " + str(length) + " s holds " + str(len(got)) + " reads, from " + str(got[0]) + " s.")
    if every == 1:
        print("With a read every second, every spike holds a read.")
    else:
        print("A spike of " + str(every) + " seconds or more always holds a read; a shorter one can fall between two.")

print("== Alert rules ==")
print("Three monitors, each right about what it measures, and what each one does not report.")
running = True
while running:
    print("")
    print("1) the monitors  2) the disk alert  3) a spike between reads  4) missing minutes  5) a read interval of your own  6) quit")
    choice = plain(input("choice> "))
    if choice == "1":
        show_monitors()
    elif choice == "2":
        show_disk()
    elif choice == "3":
        show_spike()
    elif choice == "4":
        show_missing()
    elif choice == "5":
        own()
    elif choice == "6":
        running = False
    else:
        print("Pick a number from 1 to 6.")
print("Bye.")

alerts.eml

eml
# P171 alert rules - three monitors, each correct on its own terms. As in
# the corpus case the-alert-fired-once-and-the-condition-held-for-days, an
# alert on the crossing pages once, and the condition it reports goes on
# for three days. As in the-spike-fit-between-two-samples, a gauge read once
# a minute never sees a spike that starts and ends between two reads. And as
# in the-missing-metric-was-read-as-zero, a minute with no sample recorded
# as zero is a minute under every threshold.

def disk_threshold():
    # free space, in tenths of a percent, below which the disk alert holds
    return 150

def free(h):
    # free space at hour h of the three days, in tenths of a percent
    return 140 - int(110 * h / 72)

def evaluations():
    # the rule is evaluated every 5 minutes for the 72 hours
    return 72 * 12

def pages(rule, every):
    # pages sent over the 72 hours: "edge" on the crossing only, "level" on
    # every evaluation that finds the condition, "reminder" on the crossing
    # and again every `every` hours while it holds
    0 => n
    0 => k
    while k < evaluations():
        int((k - k % 12) / 12) => h
        if free(h) < disk_threshold():
            if rule == "level":
                n + 1 => n
            elif k == 0:
                n + 1 => n
            elif rule == "reminder" and k % (12 * every) == 0:
                n + 1 => n
        k + 1 => k
    return n

def load(s):
    # requests a second at second s of the hour: a 20-second spike at 1815
    if s >= 1815 and s < 1835:
        return 2000
    return 300

def capacity():
    return 1000

def samples_in(start, length, every):
    # the reads, one every `every` seconds from second 0, that land in the
    # seconds start .. start + length - 1
    [] => out
    start + every - 1 => first
    first - first % every => s
    while s < start + length:
        out + [s] => out
        s + every => s
    return out

def load_threshold():
    return 500

def minute_load(m):
    # the real requests a second in minute m; the exporter is down 30 - 47
    if m >= 30 and m < 48:
        return 1400
    return 300

def exporter_up(m):
    return m < 30 or m >= 48
Python projection (alerts.py)
def disk_threshold():
    return 150

def free(h):
    return 140 - int(110 * h / 72)

def evaluations():
    return 72 * 12

def pages(rule, every):
    n = 0
    k = 0
    while k < evaluations():
        h = int((k - k % 12) / 12)
        if free(h) < disk_threshold():
            if rule == "level":
                n = n + 1
            elif k == 0:
                n = n + 1
            elif rule == "reminder" and k % (12 * every) == 0:
                n = n + 1
        k = k + 1
    return n

def load(s):
    if s >= 1815 and s < 1835:
        return 2000
    return 300

def capacity():
    return 1000

def samples_in(start, length, every):
    out = []
    first = start + every - 1
    s = first - first % every
    while s < start + length:
        out = out + [s]
        s = s + every
    return out

def load_threshold():
    return 500

def minute_load(m):
    if m >= 30 and m < 48:
        return 1400
    return 300

def exporter_up(m):
    return m < 30 or m >= 48

Built on these corpus cases

ΣEML 2026

Efficient New Language — a high-density semantic overlay for humans and AI agents.

This site’s demos run on the real EML toolchain, in your browser.

© 2026 EveMissLab (一言諾科技有限公司) / Neo.K. All rights reserved.