{"id":"891468e0-0d79-433c-8259-33cae97764fc","slug":"kairos-lang","kind":"mcp","name":"kairos-lang","summary":"Kairos — a schedule definition language: a composable time-stream DSL with first-class calendars, business days, windows & projections. 「月末3営業日前」を式で書けるスケジュール定義言語","owner":"azathothx","repoUrl":"https://github.com/azathothx/kairos-lang","license":"Apache-2.0","licenseTier":"permissive","trust":"community","stars":0,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-07-12T04:54:46.000Z","addedAt":"2026-10-16T06:21:49.660Z","logoUrl":"https://avatars.githubusercontent.com/u/1926603?u=028ce427ad7e7d681a96577593f2234ccd9bbbb7&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["productivity","utilities","cloud-infra"],"tags":["business-days","calendar","cron","datetime","domain-specific-language","dsl","holidays","icalendar"],"runtime":"node","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-16T06:22:41.081Z","sample":false,"url":"https://conduits.dev/tools/kairos-lang","language":"TypeScript","transports":["stdio"],"install":{"npm":"kairos-lang-mcp"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# <img src=\"assets/logo/kairos-mark.svg\" width=\"30\" height=\"30\" alt=\"\"> Kairos\n\n**English** | [日本語版 README](README.ja.md)（ドキュメントは日本語が正）\n\n> The **Japanese documentation is canonical**; the spec, the descriptor reference, and the stdlib\n> guides are **fully mirrored in English** under [`en/`](en/spec/README.md) (every page links its\n> counterpart). [`llms.txt`](llms.txt) carries the machine-readable overview. Requests and issues\n> in English are welcome — [open an issue](https://github.com/azathothx/kairos-lang/issues).\n\n**Kairos** is a **schedule definition language** — a small, composable DSL that defines *when things\nshould happen*. It goes beyond cron-style patterns: schedules like \"3 business days before month-end\",\n\"the first business day on or after February 1\", or dates derived from the lunisolar calendar are all\nfirst-class expressions.\n\n```text\npremise US { calendar-system: Gregorian; calendar: NYSE; tz: \"America/New_York\"; wkst: Sun }\n\n@US\nmonthEnd |> roll(Preceding, on: bizDay) |> shift(-3, unit: bizDay)   # 3 business days before month-end\n```\n\ncron and iCalendar RRULE can express \"N *calendar* days before month-end\", but no existing schedule\nlanguage lets you write \"the Nth *business* day\" inside an expression. The root limitation is not a\nmissing feature — **their expressions do not compose**: you cannot take the dates one rule derives and\nfeed them into the next rule. Kairos is built around this **closure** property (every expression is a\ntransformation from a time stream to a time stream), so substitute-holiday derivation, fiscal calendars,\nthe Japanese lunisolar calendar, and the 24 solar terms are all written with the same small operator family.\n\n<p align=\"center\"><img src=\"assets/figures/hero-two-layers.svg\" width=\"880\"\n  alt=\"The two-layer architecture: the premise layer defines calendars once (intension); evaluation is one-way into the body layer, which weaves them into a time stream whose points can be piped onward (closure).\"></p>\n\n## Highlights\n\n- **Business-day arithmetic in the language** — `roll(Preceding, on: bizDay)`, `shift(-3, unit: bizDay)`;\n  not a \"skip / shift\" flag bolted onto an external calendar object.\n- **Calendars are user-definable** — the Gregorian calendar itself is a transparent standard library\n  written in Kairos ([`stdlib/`](en/stdlib/)); fiscal years, ISO weeks, and the Japanese lunisolar calendar\n  (kyūreki) are ordinary definitions, not built-ins.\n- **Deriving, not enumerating** — Japan's substitute holidays and \"citizens' holidays\" are *derived* by\n  rule from the statutory holiday table alone; the rokuyō (六曜) cycle is derived from lunar months.\n- **Deterministic and auditable** — a definition denotes a set of instants. Missed fires during downtime\n  are enumerable; evaluation is reproducible.\n- **Staleness is observable** — when calendar data runs out, results carry machine-readable annotations\n  (`covering`) instead of silently degrading.\n- **Mistake-proofing as static checks** — timezone, granularity, and alignment mismatches, and missing\n  declarations (week start, roll convention, calendar) are errors, not silent misfires.\n\n## What an error looks like\n\nEvery diagnostic has three parts: `operator: what is wrong（how to fix it. where the rule lives）`. The text\nis Japanese (the canonical language); the trailing reference (I3, ADR-38, §3.3) is the spec's own numbering\nand can be looked up in the English mirror. Three real ones from the reference CLI 1.0.5:\n\n- `roll は規約が必要（I3）——位置引数で Following/Preceding を書くか前文で roll: を宣言` — \"roll: a convention\n  is required (I3) — write Following/Preceding as the positional argument, or declare roll: in the premise\".\n  Fix: `roll(Preceding, on: bizDay)`, or once in the preamble, `@JP roll: Preceding`.\n- `strideBy: 幅は正の量（0 幅は前進しない＝無限ループ。1s・1d のような正の幅を書く。ADR-38 判断 12）` — \"strideBy:\n  the width must be positive (a zero width never advances = an infinite loop; write a positive width such as\n  1s or 1d. ADR-38 decision 12)\". Fix: `strideBy(1d, from: 2026-01-01)`.\n- `stride: n は 1 以上の整数（0 は不可。ADR-38 判断 12）` — \"stride: n is an integer of 1 or more (0 is not\n  allowed. ADR-38 decision 12)\". It does not become a silent empty stream. Fix: `stride(2, from: 2026-01-05)`.\n\nThe CLI prints the message and exits with code 1; no result is emitted.\n\n## Comparison with cron, Quartz, and RRULE\n\n✓ = expressible in the language/definition · △ = partial (hacks, add-ons, implementation-specific) ·\n✗ = not expressible. \"BDC products\" = business schedulers with a business-day-calendar object plus\nshift flags. Full version with section pointers: [spec §1.2](en/spec/00-intro.md).\n\n<p align=\"center\"><img src=\"assets/figures/compare-composability.svg\" width=\"880\"\n  alt=\"Why composition matters: cron stops at fixed patterns, RRULE at recurrence rules; Kairos expressions compose — every result is a stream that pipes into the next definition (closure).\"></p>\n\n| Capability | cron | Quartz | RRULE | BDC products | Kairos |\n|---|---|---|---|---|---|\n| Fixed-time recurrence (daily at 9:00) | ✓ | ✓ | ✓ | ✓ | ✓ |\n| Nth weekday (2nd Monday) | △ (day/weekday OR trap) | ✓ (`#`) | ✓ (BYDAY + BYSETPOS) | ✓ | ✓ (`nth`) |\n| Month-end / N calendar days before it | ✗ (28–31 hack) | ✓ (`L`) | ✓ (BYMONTHDAY=-1) | ✓ | ✓ (<code>month &#124;> last &#124;> shift</code>) |\n| Business days (holiday-aware) | ✗ | △ (exclusion = skip only) | ✗ (static EXDATE) | ✓ | ✓ (calendar entity + derived `bizDay`) |\n| Business-day **arithmetic** (Nth business day) | ✗ | ✗ | ✗ | △ (shift flags only) | ✓ (`roll` / `shift(unit: bizDay)`) |\n| **Deriving** holidays by rule (substitute holidays) | ✗ | ✗ | ✗ | ✗ (enumeration only) | ✓ (cascade) |\n| User-defined calendars (fiscal, ISO week, lunisolar, solar terms) | ✗ | ✗ | △ (RFC 7529, rarely implemented) | △ (internal rules only; degrade to expanded lists across the API boundary) | ✓ (premise layer) |\n| Composition / closure (derived dates feed the next rule) | ✗ | ✗ | △ (RDATE/EXDATE only) | ✗ | ✓ (stream → stream) |\n| Cross-timezone composition (Tokyo × NY joint business days) | ✗ | ✗ | ✗ | ✗ | ✓ (`rebase` + alignment checks) |\n| DST semantics | △ (implementation-defined) | △ | ✓ (wall clock) | △ | ✓ (declared; gaps/overlaps are explicit errors) |\n| **Detecting** stale calendar data | ✗ | ✗ | ✗ | ✗ | ✓ (`covering` + out-of-coverage annotations) |\n| Determinism / audit (definition = set of instants) | ✗ (depends on current time) | ✗ | ✓ | △ | ✓ (missed fires enumerable) |\n| Static checks against silent mistakes | ✗ | ✗ | ✗ | ✗ | ✓ (alignment, granularity, tz, mandatory declarations) |\n\nWhat Kairos deliberately does **not** do: firing, retries, and execution management (the host runtime's\njob — the language stops at defining the set of instants); feedback on execution state (\"every 5 hours\nsince the last completion\" as one infinite stream — instead, computing the next fire *from an injected\ninstant* is in scope and pure, see [spec §7.7](en/spec/90-examples.md)); guaranteeing the authenticity\nof calendar data (provenance `source:` / `asof:` carries the evidence; the judgment is external);\nbranching on runtime conditions. (Count-based termination — RRULE `COUNT` — was on this list until\nADR-49: it is now covered by `take(n, from:)`.)\n\n## Runtime integration — how a scheduler consumes Kairos\n\nKairos deliberately stops at defining *the set of instants*. Your scheduler (the \"firing layer\") owns\ntimers, retries, and state, and the division of labor is one simple loop — evaluate over a rolling\nhorizon, register timers, repeat:\n\n```mermaid\nsequenceDiagram\n    participant R as Runtime (firing layer / out of scope)\n    participant K as Kairos (pure evaluation)\n    loop Rolling horizon\n        R->>K: evaluate definition over [from, to)\n        K-->>R: list of instants (+ coverage annotations)\n        R->>R: register timers → fire … (re-evaluate as \"to\" nears)\n    end\n    Note over R,K: every evaluation is a pure function<br/>overlapping ranges always agree (deterministic, auditable)\n```\n\n- **Determinism** — the same definition, range, and data always yield the same instants; advancing the\n  horizon never changes the overlap. Restarts, replays, and audits are safe.\n- **Missed fires** — evaluate over the downtime window [down, up) and you get exactly the instants\n  that should have fired, as a plain list.\n- **Operational signal** — instants beyond the calendar data's coverage carry machine-readable\n  annotations (\"your holiday data needs updating\"), instead of silently degrading.\n\nFeedback schedules (\"every 5 hours *since the last completion*\") are not a single infinite stream —\nthat would feed outputs back into the expression. Instead the runtime injects the last completion\ntime as data (exactly like a holiday table), and Kairos computes the next fire as a pure function of it:\n\n```text\n@US\nlastCompleted = [2026-07-09T14:23] covering: ..     # injected by the runtime (with source:/asof:)\nlastCompleted |> snapTo(day) |> roll(Following, on: bizDay) |> shift(+3, unit: bizDay)\n#=> 2026-07-14   (\"3 business days after the last completion\")\n```\n\nFull explanation with sequence diagrams and runnable doctests:\n[spec §7.7–7.8](en/spec/90-examples.md); the full worked study is\n[design/40-examples/07](design/40-examples/07-injected-origin.md) (Japanese). The conformance profile for\nfiring layers — what a Kairos-compatible runtime must satisfy (re-evaluation, at-least-once with idempotency\nkeys, wiring of operational signals) — is [spec appendix A](spec/60-firing-layer-profile.md) (Japanese).\n\n## Quick start (reference implementation)\n\n**Try it in your browser first**: the [Playground](https://kairos-lang.org/en/playground/) runs the\nreference implementation as-is — no install, nothing leaves your browser.\n\n**Install from npm** (Node.js 20+; zero runtime dependencies):\n\n```bash\nnpm i -g kairos-lang                             # or without installing: npx kairos-lang --version\nkairos list impl/examples/payday.kairos --from 2026-01-01 --to 2027-01-01\nkairos next -n 3 --json impl/examples/payday.kairos   # next 3 firings from today, machine-readable\n```\n\n(`impl/examples/` lives in this repository; the npm package ships the CLI and the stdlib. The block below runs\nthe TypeScript source directly, for development.)\n\nRuns TypeScript directly with Node.js 24+; zero runtime dependencies.\n\n```bash\ncd impl\nnpm install          # devDependencies only (typescript / vitest)\nnpm test             # spec examples, real-ephemeris cross-checks, doctests\n\nnode src/cli.ts list examples/payday.kairos      --from 2026-01-01 --to 2027-01-01\nnode src/cli.ts list examples/jp-holidays.kairos --from 2026-01-01 --to 2027-01-01\nnode src/cli.ts list examples/rokuyo.kairos      --from 2026-01-01 --to 2027-01-01\nnode src/cli.ts next -n 3 examples/payday.kairos   # next 3 firings from today (--json for machines)\n```\n\n`--lang en` switches the human-readable framing (headings, coverage summary, usage) to English;\nevaluator messages stay in Japanese — the implementation's canonical output — and `--json` is\nlanguage-neutral.\n\n`jp-holidays.kairos` derives Japan's substitute holidays and citizens' holidays from the statutory\nholiday table alone. `rokuyo.kairos` derives the rokuyō cycle (大安 and friends) from the lunisolar\ncalendar, cut by the National Astronomical Observatory of Japan's new-moon data.\n\n## Limits (what it does not do)\n\n- **Calendar model**: the proleptic Gregorian calendar as an idealisation (the leap-year rule is applied to\n  every year; the 1582 reform is not modelled). Other calendars are built on top of it in the premise layer\n  (spec §3.6).\n- **No leap seconds**: the base axis (chronos) is uniform; `23:59:60` is a lexical error (spec §5, ADR-33).\n- **Years have four digits** (0000–9999); `10000-01-01` is a lexical error.\n- **DST**: civil widths (`1d`) keep wall-clock time, so a civil day may be 23–25 hours; a time literal that\n  falls into a DST gap or overlap is an error, not a guess (spec §3.6, §5; ADR-33, ADR-51). A civil width is\n  a whole number of days (`1.5d` is an error; write `36h`).\n- **Reference implementation only, not the language**: the evaluation range starts at 1970-01-01 (an earlier\n  `--from` is an explicit error); points are materialised up to `to` + 400 days and a `horizon-clip` warning\n  marks that edge; a point that a stage moves out of `[from, to)` is not in the output and gets a\n  `window-clip` warning; there is no cap on the number of points — memory grows with the output, and the\n  caller chooses the range (a service front end should bound the range; the language does not); the time\n  resolution is 1 ms (a finer width or seconds fraction is a lexical error, not a silent rounding).\n- **Out of scope**: firing, retries, logging and job execution belong to the host (spec §7.8); `Modified`\n  roll conventions and the general composition of `everyInstant` are unimplemented (impl/README).\n\n## Status and documentation\n\n**Version 1.0 (declared 2026-09-14; addenda through no. 27, 2026-10-16).** Semantics, the operator family, grammar (EBNF), and lexis are\nfrozen; naming is final for every word (the last placeholder `shiftBoundary` was settled as `rephase` on 2026-07-26). Expressiveness\nis validated against 20 well-known schedule families and by a reference implementation (816 tests),\nincluding cross-checks against the official ephemeris of the National Astronomical Observatory of Japan.\n\n| Directory | Contents |\n|---|---|\n| [`spec/`](en/spec/) | **Language specification** (reviewable snapshot; start here — [日本語](spec/)) |\n| [`recipes/`](en/recipes/) | **Recipes** — the schedules cron/Quartz/RRULE can't express, one page per requirement with Playground links ([日本語](recipes/)) |\n| [`reference/`](en/reference/) | **Descriptor reference** — one page per operator; examples are doctested ([日本語](reference/)) |\n| [`stdlib/`](en/stdlib/) | Standard premises: `Gregorian`, `Fiscal`, `ISOWeek` ([日本語](stdlib/) — includes the Japanese-only `Kyureki`) |\n| [`impl/`](impl/) | Reference implementation (TypeScript, zero runtime deps; prototype — Japanese) |\n| [`mcp/`](mcp/) | MCP server `kairos-lang-mcp` — evaluate (list/next), validate and look up the reference from an MCP client; `tz` is required (English) |\n| [`design/`](design/) | Design records: 53 ADRs, domain model, expressiveness studies incl. the [\"impossible schedules\" catalog](en/design/40-examples/11-impossible-schedules.md) (Japanese; catalog mirrored in English) |\n\nStudy materials for the Kairos language exam — graded textbooks (reading, writing, operational\nsemantics) and sample questions, every example executed against the reference implementation — live at\n[exam.kairos-lang.org](https://exam.kairos-lang.org/) (Japanese).\n\n## License\n\n[Apache-2.0](LICENSE) (attribution in [NOTICE](NOTICE)). Contributions are accepted under Apache-2.0 §5\nwith a [DCO](https://developercertificate.org/) sign-off (`Signed-off-by:` line). The \"Kairos\" name and\nlogo ([assets/logo/](assets/logo/README.md)) are excluded from the license (Apache-2.0 §6).\n\n"}