STANDING ORDERS — FULL REFERENCE
Lua — the full reference
Tiger Style for Lua
Safety first. Performance second. Developer experience third.
Version: 1.0
Primary targets: Lua 5.4+, LuaJIT, Neovim Lua, embedded Lua
Recommended maximum line width: 100 columns
Recommended ordinary function review threshold: 70 lines
This guide applies Tiger Style engineering ideas to Lua without pretending that Lua is Zig. Lua is dynamically typed, garbage-collected, highly embeddable, and intentionally permissive. Tiger Style Lua therefore emphasizes explicit runtime contracts, bounded work, narrow data shapes, disciplined resource ownership, predictable mutation, direct process APIs, deterministic behavior, and testing at boundaries.
Correctness, invariants, bounds, ownership.
Predictable resource use, batching, measured hot paths.
Clarity, reviewability, maintainability, tooling.
Table of Contents
- The Tiger Style Contract
- Lua Runtime Assumptions
- File and Module Layout
- Assertions, Preconditions, and Postconditions
- Bound Everything
- Control Flow
- Error Handling
- Nil, False, and Defaults
- Numbers, Integers, Counts, and Units
- Tables
- State and Mutation
- Function Design
- Scope
- Resource Lifetime
- Memory and Allocation
- Performance
- Determinism
- Security
- Filesystem Safety
- Processes and Shells
- Coroutines and Async Work
- Naming
- Formatting
- Comments and Documentation
- Dependencies
- Neovim Lua
- Arch Linux Development
- Testing
- Review Checklist
- Anti-Patterns
- Reference Module
- Images
- HTML
- CSS
- SVG Diagrams
- Video
- JavaScript
- LaTeX and Mathematics
- Renderer Compatibility
- Suggested Repository Layout
- Sources
1. The Tiger Style Contract
Tiger Style is not merely formatting. It is a hierarchy of engineering priorities.
[ \boxed{\text{Safety} ;>; \text{Performance} ;>; \text{Developer Experience}} ]
When goals conflict:
- Do not sacrifice an invariant for convenience.
- Do not permit unbounded behavior for a small performance improvement.
- Do not hide failure merely to make an API look simpler.
- Do not optimize code whose correctness model is unclear.
- Do not add abstraction when explicit code is safer to audit.
The working principle
Make invalid states hard to construct, easy to detect, and impossible to silently preserve.
A Tiger Style Lua function should make these questions easy to answer
- What inputs are permitted?
- What inputs are rejected?
- What is the maximum amount of work?
- What state may change?
- Who owns each resource?
- What happens on failure?
- Which postconditions must be true when the function returns?
- Can asynchronous state become stale?
- Is output deterministic?
- What external capability does this code invoke?
2. Lua Runtime Assumptions
Lua implementations differ.
Do not write a module that silently assumes one of these unless the project declares it:
- Lua 5.1
- Lua 5.2
- Lua 5.3
- Lua 5.4+
- LuaJIT
- Neovim's Lua environment
- OpenResty
- an embedded Lua runtime
local M = {}
M.runtime = {
lua_version = _VERSION,
has_jit = type(jit) == "table",
has_neovim = type(vim) == "table",
}
return M
Runtime-sensitive areas
- integer representation;
- bit operations;
utf8;table.unpackversusunpack;load()signatures;- garbage-collector behavior;
- LuaJIT FFI;
- filesystem/process APIs supplied by the host;
- coroutine scheduling;
- C-module ABI compatibility.
Tiger Style rule:
Put runtime-specific behavior behind a small, explicit boundary.
3. File and Module Layout
A Lua module should read top-to-bottom.
Recommended order:
- header and purpose;
- standard/host API aliases;
- module table;
- constants;
- LuaCATS types;
- validation helpers;
- private leaf helpers;
- orchestration functions;
setup()when required;return M.
-- /project/lua/tiger/example.lua
local api = vim.api
local fs = vim.fs
local M = {}
local ITEM_COUNT_MAX = 4096
---@class TigerOptions
---@field root string
---@field item_count_max integer?
local function validate_options(options)
assert(type(options) == "table")
assert(type(options.root) == "string")
end
local function collect_items(options)
-- Leaf implementation.
end
function M.run(options)
validate_options(options)
return collect_items(options)
end
return M
Avoid import clutter
Alias frequently used APIs only when it improves clarity:
local api = vim.api
local fn = vim.fn
local fs = vim.fs
local uv = vim.uv
Do not alias everything merely to save characters.
4. Assertions, Preconditions, and Postconditions
Assertions are executable design documentation.
Use assertions for programmer errors and violated internal invariants.
Use normal error returns for expected operating failures.
Good assertion targets
- type assumptions;
- index bounds;
- count bounds;
- state-machine state;
- internal ownership assumptions;
- postconditions;
- impossible branches.
local function copy_slice(values, first_index, item_count)
assert(type(values) == "table")
assert(type(first_index) == "number")
assert(type(item_count) == "number")
assert(first_index % 1 == 0)
assert(item_count % 1 == 0)
assert(first_index >= 1)
assert(item_count >= 0)
local final_index = first_index + item_count - 1
if item_count > 0 then
assert(final_index <= #values)
end
local result = {}
for offset = 0, item_count - 1 do
result[#result + 1] = values[first_index + offset]
end
assert(#result == item_count)
return result
end
Split compound assertions
Prefer:
assert(index >= 1)
assert(index <= count)
over:
assert(index >= 1 and index <= count)
The first form identifies the violated invariant more precisely.
Do not misuse assertions for external input
Bad:
assert(user_path ~= "")
Better:
if type(user_path) ~= "string" then
return nil, "path must be a string"
end
if user_path == "" then
return nil, "path must not be empty"
end
5. Bound Everything
Every system has finite resources.
Encode those limits deliberately.
Bound
- loops;
- retries;
- recursion;
- queues;
- caches;
- diagnostics;
- files;
- captured stdout/stderr;
- request bodies;
- concurrent jobs;
- timers;
- pending callbacks;
- nested parsing depth;
- history;
- log retention.
local RETRY_COUNT_MAX = 4
local function run_with_retry(operation)
assert(type(operation) == "function")
for attempt = 1, RETRY_COUNT_MAX do
local ok, result = operation(attempt)
if ok then
return result, nil
end
if attempt == RETRY_COUNT_MAX then
return nil, "retry budget exhausted"
end
end
error("unreachable")
end
Explicit infinite loops
If a process genuinely runs forever, the lifecycle still needs a bound or an external termination invariant.
while service.running do
assert(service.generation == generation)
service_step(service)
end
Do not write an unexplained:
while true do
end
6. Control Flow
Prefer control flow that can be verified locally.
Rules
- push
ifdecisions upward; - push
forloops downward; - keep leaf loops branch-light;
- avoid clever short-circuit side effects;
- avoid recursion for attacker-controlled/deep structures;
- prefer positive conditions;
- make impossible states explicit.
local function process_input(config, input)
validate_config(config)
validate_input(input)
if input.kind == "file" then
return process_file(config, input)
end
if input.kind == "buffer" then
return process_buffer(config, input)
end
return nil, "unsupported input kind"
end
Do not use boolean operators as statement syntax
Avoid:
ready and start()
Prefer:
if ready then
start()
end
7. Error Handling
Every fallible operation must have a deliberate failure path.
Simple leaf convention
return value, nil
or:
return nil, "descriptive error"
Never silently discard pcall
Bad:
pcall(do_work)
Better:
local ok, result = pcall(do_work)
if not ok then
return nil, "do_work failed: " .. tostring(result)
end
return result, nil
Preserve context
A good error describes the failed operation, not merely the low-level symptom.
local file, open_error = io.open(path, "rb")
if file == nil then
return nil, "failed to open configuration: " .. tostring(open_error)
end
8. Nil, False, and Defaults
nil and false are both falsey.
That makes this dangerous when false is a valid setting:
local enabled = options.enabled or true
Use:
local enabled
if options.enabled == nil then
enabled = true
else
enabled = options.enabled
end
Give nil one documented meaning
Do not let nil ambiguously mean all of:
- absent;
- unknown;
- disabled;
- error;
- default;
- not initialized.
Use a richer state representation when multiple meanings are required.
9. Numbers, Integers, Counts, and Units
The runtime may use the same numeric type for semantically different values.
Your code should not.
Distinguish
item_indexitem_countbuffer_size_bytesoffset_bytescapacitytimeout_msretry_countgeneration_id
local function is_integer(value)
if type(value) ~= "number" then
return false
end
if value ~= value then
return false
end
if value == math.huge or value == -math.huge then
return false
end
return value % 1 == 0
end
Name units last
Prefer:
timeout_ms
timeout_ms_max
payload_size_bytes
cache_size_bytes_max
over ambiguous names such as:
timeout
size
max
len
10. Tables
Lua tables are arrays, maps, records, sets, objects, and namespaces.
That flexibility needs discipline.
Rules
- do not mix array/map semantics accidentally;
- do not rely on
#tablefor sparse arrays; - do not rely on
pairs()ordering; - avoid fields that change type over time;
- prefer constructors;
- keep table invariants documented;
- use metatables only when the semantic gain is substantial.
local function new_queue(capacity)
assert(type(capacity) == "number")
assert(capacity % 1 == 0)
assert(capacity > 0)
return {
capacity = capacity,
count = 0,
first_index = 1,
values = {},
}
end
Deterministic map traversal
local function sorted_keys(values)
local keys = {}
for key in pairs(values) do
keys[#keys + 1] = key
end
table.sort(keys)
return keys
end
11. State and Mutation
Mutable state should have a clear owner.
Prefer this model
input
│
▼
validate
│
▼
control function
│
├────> pure/bounded leaf work
│
▼
validate delta
│
▼
single commit point
Rules
- mutate at a small number of obvious points;
- separate computation from mutation;
- document valid state transitions;
- copy caller-owned configuration if later mutation is possible;
- avoid shared module state as a hidden message bus;
- avoid implicitly coupled globals.
12. Function Design
Ordinary functions should be small enough to understand without scrolling through multiple conceptual phases.
Recommended threshold
[ L_{\text{function}} \le 70 ]
where (L_{\text{function}}) is the function's physical source-line count.
This is a review threshold, not an excuse to fragment cohesive logic into dozens of trivial functions.
Prefer named option tables
Risky:
copy_range(source, target, 10, 20, true, false)
Better:
copy_range({
source = source,
target = target,
first_index = 10,
item_count = 20,
overwrite = true,
preserve_metadata = false,
})
13. Scope
Make variable lifetime visually obvious.
for index = 1, #items do
local item = items[index]
assert(item ~= nil)
local normalized = normalize_item(item)
emit(normalized)
end
Rules
- declare locals near first use;
- compute derived values near consumption;
- do not carry mutable derived values across async boundaries;
- minimize closure captures;
- avoid shadowing when it harms reviewability.
14. Resource Lifetime
Every resource should have one clear owner.
Examples:
- files;
- sockets;
vim.uvhandles;- subprocesses;
- timers;
- temporary directories;
- temporary files;
- FFI allocations;
- registrations/autocmds with lifecycle semantics.
local file, open_error = io.open(path, "rb")
if file == nil then
return nil, open_error
end
local data, read_error = file:read("*a")
file:close()
if data == nil then
return nil, read_error
end
return data, nil
Prefer idempotent teardown
local function close_handle(state)
if state.handle == nil then
return
end
if not state.handle:is_closing() then
state.handle:close()
end
state.handle = nil
end
15. Memory and Allocation
Lua is garbage-collected, so the original static-allocation idea cannot be translated literally.
Translate the intent:
Memory use should be predictable, bounded, and visible.
Rules
- cap caches;
- cap histories;
- cap queues;
- remove references to large finished objects;
- avoid accidental closure retention;
- avoid repeated giant table copies;
- avoid repeated giant string concatenation;
- treat LuaJIT FFI allocations as manual resources;
- do not force GC in hot paths without measurements.
For large string generation:
local fragments = {}
for index = 1, #items do
fragments[index] = render_item(items[index])
end
local output = table.concat(fragments, "\n")
16. Performance
Performance starts with design.
Consider
[ T_{\text{total}}
T_{\text{network}} + T_{\text{disk}} + T_{\text{memory}} + T_{\text{cpu}} + T_{\text{coordination}} ]
The largest meaningful term deserves attention first.
Rules
- batch system calls;
- batch RPC;
- batch diagnostics;
- batch redraw work;
- avoid repeated filesystem probing;
- separate control plane from data plane;
- make hot loops simple;
- avoid unnecessary allocations in measured hot loops;
- profile after implementation;
- do not postpone basic capacity/resource modeling until profiling.
17. Determinism
Determinism improves testing, reproducibility, and debugging.
Rules
- sort map keys before serialization;
- never rely on
pairs()order; - normalize platform-sensitive output;
- pass explicit options;
- seed pseudo-random tests;
- make locale/timezone assumptions explicit;
- pin external tool behavior when output parsing depends on versions.
local function stable_pairs(values)
local keys = sorted_keys(values)
local index = 0
return function()
index = index + 1
local key = keys[index]
if key == nil then
return nil
end
return key, values[key]
end
end
18. Security
Lua can invoke highly privileged capabilities.
Treat these as security boundaries:
os.execute;io.popen;load;loadfile;dofile;requirefrom writable/untrusted search paths;package.loadlib;- LuaJIT FFI;
- Neovim
vim.system; - filesystem writes;
- shell command construction;
- dynamic plugin loading.
Never concatenate untrusted values into a shell command
Bad:
os.execute("git status -- " .. user_path)
Good in Neovim:
local result = vim.system({
"git",
"status",
"--porcelain=v1",
"--",
user_path,
}, {
text = true,
}):wait()
if result.code ~= 0 then
return nil, result.stderr
end
return result.stdout, nil
Capability rule
Untrusted Lua should not receive arbitrary access to:
os
io
debug
package
ffi
vim.system
vim.uv
An empty environment passed to load() is not a complete security sandbox.
19. Filesystem Safety
Validate filesystem paths before privileged use.
local function validate_path(path)
if type(path) ~= "string" then
return nil, "path must be a string"
end
if path == "" then
return nil, "path must not be empty"
end
if path:find("%z") ~= nil then
return nil, "path contains NUL"
end
return true, nil
end
Rules
- normalize paths before policy checks;
- define symlink behavior;
- do not implement containment with naive string prefixes;
- use controlled temporary directories;
- prefer write-temp + atomic rename for important file replacement;
- avoid overwriting sensitive files accidentally;
- use exclusive creation where appropriate.
20. Processes and Shells
Prefer direct process execution.
Good model
vim.system({
"clang-tidy",
"--quiet",
"--",
filename,
}, {
cwd = root,
text = true,
})
Process checklist
- executable is explicit;
- each argv element is separate;
- user path is behind
--if supported; - cwd is explicit;
- timeout is defined where hangs matter;
- output is bounded where possible;
- exit code is checked;
- signal is checked where exposed;
- stderr is not mistaken for failure by itself;
- machine-readable output is preferred.
21. Coroutines and Async Work
A precondition can become false after a yield or callback delay.
Use generation tokens.
local generation = 0
local function refresh()
generation = generation + 1
local request_generation = generation
start_async(function(result)
if request_generation ~= generation then
return
end
apply_result(result)
end)
end
Async rules
- bound outstanding work;
- reject stale callbacks;
- cancel owned work during teardown;
- revalidate buffers/windows/files after asynchronous delay;
- minimize callback captures;
- avoid mutation of deleted Neovim resources.
22. Naming
Use snake_case.
Prefer domain language over abbreviations.
Good
request_count
diagnostic_count
buffer_size_bytes
timeout_ms_max
retry_count
generation_id
source_path
target_path
Avoid
n
sz
tm
x
tmp2
data2
stuff
obj
Short names are acceptable for tiny conventional local roles such as a compact loop index, but the surrounding code must remain obvious.
23. Formatting
Recommended:
- 4-space indentation;
- maximum 100 columns;
- one statement per line;
- trailing commas in multiline structures;
- blank lines between conceptual phases;
- deterministic formatter output.
Example stylua.toml:
column_width = 100
indent_type = "Spaces"
indent_width = 4
line_endings = "Unix"
quote_style = "AutoPreferSingle"
call_parentheses = "Always"
Formatting invariant
[ C_{\text{line}} \le 100 ]
for ordinary source lines.
24. Comments and Documentation
Comments explain why, how, constraints, and invariants.
Bad:
-- Increment count.
count = count + 1
Better:
-- Increment only after insertion succeeds so count remains a committed-item count.
count = count + 1
LuaCATS
Use structured annotations where supported:
---@class TigerConfig
---@field root string
---@field timeout_ms integer
---@field notify boolean
---@param config TigerConfig
---@return boolean? ok
---@return string? error
local function validate_config(config)
-- ...
end
25. Dependencies
Every dependency increases:
- supply-chain surface;
- compatibility surface;
- startup work;
- installation complexity;
- update burden;
- transitive risk.
Add a dependency only when it earns its cost
Prefer:
- Lua standard library;
- trusted host APIs;
- small audited internal code;
- mature external dependency.
Pin versions or commits when reproducibility matters.
Do not download executable dependencies at runtime in trusted paths unless that behavior is explicitly part of the product's security design.
26. Neovim Lua
For modern Neovim configurations:
- prefer
vim.api; - prefer
vim.fs; - prefer
vim.system; - prefer
vim.uv; - avoid deprecated APIs;
- keep
setup()idempotent; - group autocmds;
- clear/recreate owned groups intentionally;
- validate asynchronous buffer/window handles.
local group = vim.api.nvim_create_augroup("TigerLua", {
clear = true,
})
vim.api.nvim_create_autocmd("BufWritePost", {
group = group,
pattern = "*.lua",
callback = function(event)
assert(type(event) == "table")
assert(type(event.buf) == "number")
if not vim.api.nvim_buf_is_valid(event.buf) then
return
end
validate_buffer(event.buf)
end,
})
Module rule
require("module") should preferably load definitions rather than unexpectedly
perform large global side effects.
27. Arch Linux Development
For an Arch Linux development environment:
stylua --check .
luacheck .
lua tests/run.lua
Rules
- use
pacmanfor system packages when suitable; - review AUR
PKGBUILDfiles for security-sensitive tooling; - never run project language package managers with
sudo; - do not build ordinary project dependencies as root;
- keep repository tooling reproducible;
- prefer argv-safe direct invocation over shell pipelines in application code.
28. Testing
Test boundaries before happy-path permutations.
For a maximum (M), test:
[ {0,;1,;M-1,;M,;M+1} ]
when those values are meaningful.
Test
- zero;
- one;
- maximum;
- maximum plus one;
nil;false;- malformed input;
- cancellation;
- retry exhaustion;
- stale callbacks;
- cleanup after failure;
- invalid state transitions;
- deterministic ordering;
- partial external output.
local function test_capacity_boundary()
local queue = new_queue(2)
assert(queue_push(queue, "a"))
assert(queue_push(queue, "b"))
local ok, push_error = queue_push(queue, "c")
assert(ok == nil)
assert(push_error == "queue capacity exhausted")
assert(queue.count == 2)
end
29. Review Checklist
- Safety outranks performance and developer convenience.
- External input is validated before privileged use.
- Internal invariants use meaningful assertions.
- Loops over externally influenced data are bounded.
- Retries have a maximum.
- Queues/caches/histories have capacity limits.
-
nilandfalsesemantics are deliberate. - Index/count/size/unit semantics are explicit.
- Every resource has one clear owner.
- Cleanup paths exist for failure.
- Errors are not discarded.
- Shell command strings do not contain interpolated untrusted input.
- External commands use argv arrays where possible.
- State mutation is centralized.
- Async callbacks reject stale results.
- Output is deterministic where persistence/testing requires it.
- Dependencies are justified.
- Ordinary functions stay near or below 70 lines.
- Ordinary lines stay at or below 100 columns.
- Comments explain intent rather than syntax.
- Tests cover boundaries and failure cleanup.
30. Anti-Patterns
-- Hidden global mutation.
state = state or {}
-- Shell injection surface.
os.execute("tool " .. user_input)
-- Swallowed failure.
pcall(do_work)
-- Unbounded retry.
while true do
if try_again() then
break
end
end
-- False is accidentally replaced by true.
local enabled = options.enabled or true
-- Sparse-table length assumption.
local count = #possibly_sparse
-- Untrusted code execution.
local chunk = load(user_text)
chunk()
31. Reference Module
local M = {}
local ITEM_COUNT_MAX = 1024
local function validate_items(items)
if type(items) ~= "table" then
return nil, "items must be a table"
end
if #items > ITEM_COUNT_MAX then
return nil, "item limit exceeded"
end
return true, nil
end
local function transform_items(items)
assert(type(items) == "table")
assert(#items <= ITEM_COUNT_MAX)
local transformed = {}
for index = 1, #items do
local item = items[index]
assert(type(item) == "string")
transformed[index] = string.upper(item)
end
assert(#transformed == #items)
return transformed
end
function M.run(items)
local valid, validation_error = validate_items(items)
if not valid then
return nil, validation_error
end
return transform_items(items), nil
end
return M
Multimedia and Rich Markdown
The following sections make this file useful as both a coding standard and a rendering test document.
32. Images
Standard Markdown image

The examples in this section are templates, not included media: this collection bundles no image or video files, so the rendered forms are omitted rather than pointed at assets that do not exist.
HTML image with explicit dimensions
<img
src="assets/tiger-style-lua.webp"
alt="Tiger Style Lua architecture"
width="960"
loading="lazy"
decoding="async">
Responsive <picture>
<picture>
<source srcset="assets/tiger-style-lua.avif" type="image/avif">
<source srcset="assets/tiger-style-lua.webp" type="image/webp">
<img
src="assets/tiger-style-lua.png"
alt="Tiger Style Lua architecture"
loading="lazy">
</picture>
33. HTML
Markdown can contain raw HTML when the renderer permits it.
<details>
<summary>Tiger Style invariant</summary>
A successful operation must leave state internally consistent.
</details>
Tiger Style invariant
A successful operation must leave state internally consistent.
HTML table
| Priority | Question |
|---|---|
| Safety | Can this state become invalid or unbounded? |
| Performance | What resource dominates the workload? |
| Developer Experience | Can a reviewer understand the contract quickly? |
34. CSS
This Markdown document already contains a <style> block near its top.
A renderer that allows raw CSS can use classes such as:
<div class="tiger-card">
Styled content.
</div>
Security rule for documentation CSS
Do not depend on remote CSS from an untrusted origin merely to make technical documentation readable.
Documentation should remain semantically useful without styling.
35. SVG Diagrams
Inline SVG is useful for diagrams because it is:
- vector-based;
- text-searchable;
- resolution-independent;
- embeddable directly in Markdown/HTML;
- script-free when used carefully.
Tiger Style priority diagram
Tiger Style priority orderState flow diagram
Tiger Style Lua state flowExternal SVG image

36. Video
Markdown has no universal native video syntax, so use HTML5.
<video
controls
preload="metadata"
width="960"
poster="assets/tiger-style-demo-poster.webp">
<source src="assets/tiger-style-demo.webm" type="video/webm">
<source src="assets/tiger-style-demo.mp4" type="video/mp4">
Your renderer cannot play this video.
</video>
Recommended video policy
- default to
controls; - default to
preload="metadata"; - do not autoplay documentation videos;
- provide WebM and MP4 when broad browser compatibility matters;
- include a poster image;
- include explanatory text next to the video;
- never make video the only place where important documentation exists.
Optional direct link fallback
[Open the Tiger Style demo video](assets/tiger-style-demo.webm)
37. JavaScript
Important: GitHub and many secure Markdown renderers remove or disable
<script> elements. JavaScript in documentation should therefore be optional
progressive enhancement, never a requirement for understanding the guide.
A trusted local renderer that permits scripts can use:
<button id="tiger-toggle">Toggle Tiger Style note</button>
<div id="tiger-js-note">
JavaScript is optional. The documentation remains readable without it.
</div>
<script>
(() => {
"use strict";
const button = document.getElementById("tiger-toggle");
const note = document.getElementById("tiger-js-note");
if (!(button instanceof HTMLButtonElement)) {
return;
}
if (!(note instanceof HTMLElement)) {
return;
}
button.addEventListener("click", () => {
note.hidden = !note.hidden;
});
})();
</script>
JavaScript documentation rules
- Do not load arbitrary third-party scripts.
- Prefer no JavaScript when native HTML solves the problem.
- Use
<details>and<summary>for disclosure widgets. - Keep JavaScript isolated from the content model.
- Validate queried DOM elements before use.
- Avoid inline event attributes such as
onclick="...". - Use event listeners.
- Do not insert untrusted strings with
innerHTML. - Prefer
textContentfor text. - Keep documentation useful when scripting is disabled.
38. LaTeX and Mathematics
Many Markdown environments support LaTeX-style mathematics.
Inline math
Tiger Style priorities may be represented as (S > P > D), where (S) is safety, (P) performance, and (D) developer experience.
Display math
[ \text{Priority}(S) > \text{Priority}(P) > \text{Priority}(D) ]
Capacity invariant
For a bounded queue:
[ 0 \leq q_{\text{count}} \leq q_{\text{capacity}} ]
A push operation is permitted only when:
[ q_{\text{count}} < q_{\text{capacity}} ]
After a successful push:
[ q'{\text{count}} = q{\text{count}} + 1 ]
Slice invariant
For Lua's conventional one-based indexing:
[ 1 \leq i_{\text{first}} ]
[ 0 \leq n_{\text{items}} ]
For a non-empty slice:
[ i_{\text{first}} + n_{\text{items}} - 1 \leq n_{\text{array}} ]
Performance model
[ T_{\text{request}}
T_{\text{queue}} + T_{\text{I/O}} + T_{\text{compute}} + T_{\text{serialization}} ]
Bounded memory model
[ M_{\text{retained}} \leq M_{\text{cache,max}} + M_{\text{queue,max}} + M_{\text{active,max}} ]
The point is not mathematical decoration. The equations make invariants and capacity assumptions explicit.
39. Renderer Compatibility
No single Markdown engine supports every rich feature identically.
| Feature | Plain Markdown | GitHub/GFM | Trusted HTML-capable renderer |
|---|---|---|---|
| Headings/lists/code | Yes | Yes | Yes |
| Markdown images | Yes | Yes | Yes |
| Raw HTML | Renderer-dependent | Limited/sanitized | Usually |
<details> | No | Yes | Usually |
| Inline SVG | Renderer-dependent | Sanitized/limited | Usually |
HTML5 <video> | No | Limited | Usually |
<style> | No | Sanitized/removed | Usually |
<script> | No | Removed | Optional |
| LaTeX math | Extension | Supported contexts | Math extension/MathJax/KaTeX |
| Mermaid | Extension | Supported by some hosts | Plugin-dependent |
Best portability strategy
Use this hierarchy:
- semantic Markdown;
- standard links and images;
- accessible HTML;
- inline SVG;
- CSS as progressive enhancement;
- video with a link fallback;
- JavaScript only for optional behavior.
40. Suggested Repository Layout
docs/
├── TIGER_STYLE_LUA.md
└── assets/
├── tiger-style-lua.avif
├── tiger-style-lua.webp
├── tiger-style-lua.png
├── state-flow.svg
├── tiger-style-demo-poster.webp
├── tiger-style-demo.webm
└── tiger-style-demo.mp4
Arch Linux media conversion examples
Image:
magick input.png -strip -quality 82 docs/assets/tiger-style-lua.webp
Video:
ffmpeg \
-i input.mkv \
-map_metadata -1 \
-c:v libvpx-vp9 \
-crf 31 \
-b:v 0 \
-c:a libopus \
docs/assets/tiger-style-demo.webm
MP4 fallback:
ffmpeg \
-i input.mkv \
-map_metadata -1 \
-c:v libx264 \
-crf 22 \
-preset medium \
-pix_fmt yuv420p \
-c:a aac \
-movflags +faststart \
docs/assets/tiger-style-demo.mp4
Poster:
ffmpeg \
-ss 00:00:01 \
-i docs/assets/tiger-style-demo.mp4 \
-frames:v 1 \
docs/assets/tiger-style-demo-poster.webp
41. Sources
Primary conceptual source:
- TigerBeetle, Tiger Style
https://github.com/tigerbeetle/tigerbeetle/blob/main/docs/TIGER_STYLE.md
Lua language reference:
- Lua Reference Manuals
https://www.lua.org/manual/
Neovim API reference:
- Neovim Documentation
https://neovim.io/doc/
Compact Tiger Style Lua Card
Open the condensed rules
Safety
- Assert internal invariants.
- Validate external input.
- Bound loops, retries, queues, caches, and files.
- Keep resource ownership explicit.
- Centralize mutation.
- Reject stale asynchronous results.
- Never interpolate untrusted input into shell commands.
- Treat dynamic code loading and FFI as privileged.
Performance
- Design resource use before optimizing.
- Batch expensive work.
- Keep hot loops simple.
- Avoid unnecessary allocation in measured hot paths.
- Prefer deterministic, predictable algorithms.
- Measure the dominant resource.
Developer Experience
- Use consistent names.
- Use 4-space indentation.
- Keep lines at or below 100 columns.
- Keep ordinary functions near or below 70 lines.
- Use LuaCATS annotations where useful.
- Keep modules top-down and explicit.
- Make comments explain why.
- Keep documentation readable without CSS or JavaScript.
Final Rule
A Tiger Style Lua codebase should make correctness visible.
The reader should be able to identify the program's limits, invariants, state transitions, resource owners, failure behavior, and privileged operations without reconstructing them from hidden conventions.