on master help sign in
feat(syntax): remove commas from relation literals; ctors take payload unparenthesized

Relation-literal and list-pattern elements are now SPACE-separated, matching record field syntax: [1 2 3] was [1, 2, 3] [{x 1} {x 2}] was [{x 1}, {x 2}] case xs of [a b c] was [a, b, c] Parser (parse_list_expr, parse_list_pat): elements parse with parse_postfix — the same non-greedy parse used for record field values — so one element cannot absorb the next as a function application. Complex expressions need parens: [(1 + 2) (f x)]. Commas inside [..] are now a parse error; commas inside nested {..} type signatures are unaffected (type records keep commas). parse_postfix: a postfix chain ending in an uppercase field (Type.Ctor) followed by a record literal now consumes the record as the ctor payload, so qualified constructors take their payload unparenthesized as a list element or record field value — [Maybe.Just {value 1} Maybe.Nothing {}] and m Maybe.Just {value 1} both work, matching the bare Just {..} form. Formatter emits space-separated lists (inline and block; multi-line lists drop the trailing comma, newline is the separator). Migrated examples/*.knot (18) and README/knot.md/stdlib.md relation literals; type signatures and show-output comments keep commas. Verified: 32/32 examples build, 75/75 tests pass.

commit09193634b4d534cc2dea9eb2b762c5e82f76bdcc authoriko <mail@iko.soy> dateTue 28 Jul 2026, 18:07 (2 months ago) parent9f50eef
23 files changed+277−257
README.md+9−9 crates/knot/src/format.rs+3−6 crates/knot/src/parser.rs+54−31 examples/arith_aggregate.knot+1−1 examples/builtins.knot+1−1 examples/cons_pattern.knot+2−2 examples/constraints.knot+1−1 examples/find_first.knot+1−1 examples/fold_stream.knot+4−4 examples/for_each.knot+2−2 examples/groupby.knot+4−4 examples/hash.knot+1−1 examples/hello.knot+1−1 examples/inline_pushdown.knot+4−4 examples/json.knot+1−1 examples/let_pushdown.knot+1−1 examples/nested.knot+2−2 examples/query_opt.knot+5−5 examples/recursive.knot+2−2 examples/showcase.knot+168−168 examples/stm_row_filter.knot+1−1 knot.md+3−3 stdlib.md+6−6
README.md+9−9
@@ -45,7 +45,7 @@ type Person = {name: Text, age: Int 1}
4545*people : [Person]
4646}
4747(do
48− replace *people = [{name "Alice" age 30}, {name "Bob" age 25}, {name "Carol" age 35}]
48+ replace *people = [{name "Alice" age 30} {name "Bob" age 25} {name "Carol" age 35}]
4949 seniors <- (do
5050 p <- *people
5151 where p.age > 27
@@ -160,9 +160,9 @@ the role other languages give to lists/arrays.
160160
161161```knot
162162with {
163−nums [1, 2, 3, 4]
163+nums [1 2 3 4]
164164empty [] -- the empty relation
165−people [{name "Ada" age 36}, {name "Grace" age 17}]
165+people [{name "Ada" age 36} {name "Grace" age 17}]
166166}
167167(do
168168 base.println (base.show (base.count nums)) -- "4"
@@ -279,7 +279,7 @@ sumList (\xs -> case xs of
279279 [] -> 0
280280 Cons h t -> h + sumList t)
281281}
282−(base.println (base.show (sumList [1, 2, 3, 4]))) -- "10"
282+(base.println (base.show (sumList [1 2 3 4]))) -- "10"
283283```
284284
285285`[]` matches the empty relation and `Cons h t` splits off one element `h`
@@ -322,7 +322,7 @@ type Todo = {title: Text, done: Int 1}
322322*todos : [Todo]
323323}
324324(do
325− replace *todos = [{title "write guide" done 0}, {title "ship it" done 0}]
325+ replace *todos = [{title "write guide" done 0} {title "ship it" done 0}]
326326
327327 -- a query comprehension: binds each row, filters, yields results
328328 open <- (do
@@ -368,8 +368,8 @@ with {
368368}
369369(do
370370 replace *manages = [
371− {manager "Alice" report "Bob"},
372− {manager "Alice" report "Carol"},
371+ {manager "Alice" report "Bob"}
372+ {manager "Alice" report "Carol"}
373373 {manager "Bob" report "Dave"}
374374 ]
375375 rows <- &directReports
@@ -491,8 +491,8 @@ annotations — they're inferred.
491491(do
492492 base.println (base.toUpper "knot") -- "KNOT"
493493 base.println (base.show (base.length "hi")) -- "2"
494− base.println (base.show (base.take 2 [9, 8, 7])) -- "[9, 8]"
495− base.println (base.show (base.sum [1, 2, 3])) -- "6"
494+ base.println (base.show (base.take 2 [9 8 7])) -- "[9, 8]"
495+ base.println (base.show (base.sum [1 2 3])) -- "6"
496496 base.println (base.show (base.min 3 7)) -- "3"
497497 base.println (base.show (base.max 3 7)) -- "7"
498498 yield {})
crates/knot/src/format.rs+3−6
@@ -629,7 +629,7 @@ fn render_expr_inline(e: &Expr, parent: Prec) -> String {
629629 let mut s = String::from("[");
630630 for (i, it) in items.iter().enumerate() {
631631 if i > 0 {
632− s.push_str(", ");
632+ s.push(' ');
633633 }
634634 s.push_str(&render_expr_inline(it, Prec::Lowest));
635635 }
@@ -1255,11 +1255,8 @@ fn render_list_block(p: &mut Printer, items: &[Expr]) {
12551255 p.write("[");
12561256 p.newline();
12571257 p.with_indent(|p| {
1258− for (i, it) in items.iter().enumerate() {
1258+ for it in items.iter() {
12591259 render_expr(p, it, Prec::Lowest);
1260− if i + 1 < items.len() {
1261− p.write(",");
1262− }
12631260 p.newline();
12641261 }
12651262 });
@@ -1435,7 +1432,7 @@ fn render_pat(p: &Pat) -> String {
14351432 let mut s = String::from("[");
14361433 for (i, it) in items.iter().enumerate() {
14371434 if i > 0 {
1438− s.push_str(", ");
1435+ s.push(' ');
14391436 }
14401437 s.push_str(&render_pat(it));
14411438 }
crates/knot/src/parser.rs+54−31
@@ -1857,7 +1857,36 @@ impl Parser {
18571857
18581858 fn parse_postfix(&mut self) -> Option<Expr> {
18591859 let expr = self.parse_constructor_or_atom()?;
1860− self.parse_postfix_from(expr)
1860+ let expr = self.parse_postfix_from(expr)?;
1861+ // A QUALIFIED constructor (`Maybe.Just`) parses as a `FieldAccess`, so
1862+ // the bare-ctor arg consumption in `parse_constructor_or_atom` never
1863+ // fires for it. Every constructor carries a record payload, so when a
1864+ // postfix chain ends in an uppercase field (`Type.Ctor`) and a record
1865+ // literal `{…}` follows, that record is the ctor's payload — consume it
1866+ // as the application argument here. This lets `Maybe.Just {value 1}`
1867+ // appear unparenthesized as a list element or record field value, just
1868+ // like the bare `Just {value 1}` form.
1869+ if let ExprKind::FieldAccess { field, .. } = &expr.node {
1870+ if field.chars().next().is_some_and(|c| c.is_uppercase())
1871+ && self.at(&TokenKind::LBrace)
1872+ {
1873+ if !self.enter_recursion() {
1874+ return None;
1875+ }
1876+ let arg = self.parse_postfix();
1877+ self.recursion_depth -= 1;
1878+ let arg = arg?;
1879+ let span = Span::new(expr.span.start, arg.span.end);
1880+ return Some(Spanned::new(
1881+ ExprKind::App {
1882+ func: Box::new(expr),
1883+ arg: Box::new(arg),
1884+ },
1885+ span,
1886+ ));
1887+ }
1888+ }
1889+ Some(expr)
18611890 }
18621891
18631892 /// Continue a field-access chain from an already-parsed head expression.
@@ -2875,25 +2904,23 @@ impl Parser {
28752904 }
28762905
28772906 fn parse_list_expr(&mut self, start: Span) -> Option<Expr> {
2878− // Already consumed `[`.
2907+ // Already consumed `[`. Elements are SPACE-separated (no commas), so
2908+ // each is parsed with `parse_postfix` — the same non-greedy parse used
2909+ // for record field values — so one element can't absorb the next as a
2910+ // function application. `[1 2 3]`, `[{x 1} {x 2}]`, and
2911+ // `[Just {value 1} Nothing {}]` all work; anything needing a binop or
2912+ // application must be parenthesized: `[(1 + 2) (f x)]`.
28792913 self.skip_newlines();
28802914 let mut elems = Vec::new();
2881− if !self.at(&TokenKind::RBracket) {
2882− loop {
2883− self.skip_newlines();
2884− let e = self.parse_expr()?;
2885− elems.push(e);
2886− self.skip_newlines();
2887− if !self.eat(&TokenKind::Comma) {
2888− break;
2889− }
2890− self.skip_newlines();
2891− if self.at(&TokenKind::RBracket) {
2892− break; // trailing comma
2893− }
2915+ loop {
2916+ self.skip_newlines();
2917+ if self.at(&TokenKind::RBracket) {
2918+ break;
28942919 }
2920+ let e = self.parse_postfix()?;
2921+ elems.push(e);
2922+ self.skip_newlines();
28952923 }
2896− self.skip_newlines();
28972924 let end_tok = self
28982925 .expect(&TokenKind::RBracket, "expected ']' to close list")
28992926 .ok()?;
@@ -3762,25 +3789,21 @@ impl Parser {
37623789 }
37633790
37643791 fn parse_list_pat(&mut self, start: Span) -> Option<Pat> {
3765− // Already consumed `[`.
3792+ // Already consumed `[`. Elements are SPACE-separated (no commas), like
3793+ // relation-literal expressions. `parse_pat` is non-greedy (patterns
3794+ // have no application), so `[p1 p2]` is two var patterns and
3795+ // `[Cons h t]` stays one constructor pattern.
37663796 self.skip_newlines();
37673797 let mut pats = Vec::new();
3768− if !self.at(&TokenKind::RBracket) {
3769− loop {
3770− self.skip_newlines();
3771− let p = self.parse_pat()?;
3772− pats.push(p);
3773− self.skip_newlines();
3774− if !self.eat(&TokenKind::Comma) {
3775− break;
3776− }
3777− self.skip_newlines();
3778− if self.at(&TokenKind::RBracket) {
3779− break; // trailing comma
3780− }
3798+ loop {
3799+ self.skip_newlines();
3800+ if self.at(&TokenKind::RBracket) {
3801+ break;
37813802 }
3803+ let p = self.parse_pat()?;
3804+ pats.push(p);
3805+ self.skip_newlines();
37823806 }
3783− self.skip_newlines();
37843807 let end_tok = self
37853808 .expect(&TokenKind::RBracket, "expected ']' to close list pattern")
37863809 .ok()?;
examples/arith_aggregate.knot+1−1
@@ -17,7 +17,7 @@ avgDemo (do
1717}
1818
1919do
20− replace *lines = [{product "widget" price 5 qty 2}, {product "gadget" price 9 qty 1}, {product "gizmo" price 5 qty 3}]
20+ replace *lines = [{product "widget" price 5 qty 2} {product "gadget" price 9 qty 1} {product "gizmo" price 5 qty 3}]
2121 totalDemo
2222 avgDemo
2323 yield {}
examples/builtins.knot+1−1
@@ -4,7 +4,7 @@ safeDiv (\x y -> case y == 0 of
44 Bool.True {} -> Maybe.Nothing {}
55 Bool.False {} -> Maybe.Just {value (x / y)})
66
7−nums [1, 2, 3, 4, 5]
7+nums [1 2 3 4 5]
88
99doubled (base.map (\n -> n * 2) nums)
1010total (base.fold (\acc n -> acc + n) 0 nums)
examples/cons_pattern.knot+2−2
@@ -9,8 +9,8 @@ firstOr (\xs default -> case xs of
99 Cons h _ -> h)
1010}
1111(do
12− base.println (base.show (sumList [1, 2, 3, 4]))
12+ base.println (base.show (sumList [1 2 3 4]))
1313 base.println (base.show (sumList []))
14− base.println (base.show (firstOr [10, 20, 30] 0))
14+ base.println (base.show (firstOr [10 20 30] 0))
1515 base.println (base.show (firstOr [] 99))
1616 yield {})
examples/constraints.knot+1−1
@@ -13,7 +13,7 @@ type Person = {name: Text, age: Int 1, email: Text}
1313}
1414(do
1515 -- Insert some people
16− replace *people = [{ name "Alice" age 30 email "alice@example.com" }, { name "Bob" age 25 email "bob@example.com" }]
16+ replace *people = [{ name "Alice" age 30 email "alice@example.com" } { name "Bob" age 25 email "bob@example.com" }]
1717
1818 -- Insert a valid order (Alice exists in people)
1919 replace *orders = [{ customer "Alice" amount 100 }]
examples/find_first.knot+1−1
@@ -1,3 +1,3 @@
11-- Test findFirst builtin.
22
3−with {r1 (base.findFirst [1, 2, 3, 4, 5] (\x -> x > 3))} (do with {r2 (base.findFirst [1, 2, 3] (\x -> x > 10))} (do with {r3 (base.findFirst [] (\x -> x > 0))} (do base.println (base.show r1); base.println (base.show r2); base.println (base.show r3); yield {})))
3+with {r1 (base.findFirst [1 2 3 4 5] (\x -> x > 3))} (do with {r2 (base.findFirst [1 2 3] (\x -> x > 10))} (do with {r3 (base.findFirst [] (\x -> x > 0))} (do base.println (base.show r1); base.println (base.show r2); base.println (base.show r3); yield {})))
examples/fold_stream.knot+4−4
@@ -5,10 +5,10 @@ type Sale = {item: Text, qty: Int 1, price: Int 1}
55}
66(do
77 replace *sales = [
8− { item "apple" qty 3 price 50 },
9− { item "banana" qty 7 price 20 },
10− { item "cherry" qty 2 price 120 },
11− { item "date" qty 5 price 80 },
8+ { item "apple" qty 3 price 50 }
9+ { item "banana" qty 7 price 20 }
10+ { item "cherry" qty 2 price 120 }
11+ { item "date" qty 5 price 80 }
1212 { item "fig" qty 4 price 30 }
1313 ]
1414
examples/for_each.knot+2−2
@@ -2,11 +2,11 @@
22
33(do
44 -- Basic case: print each integer
5− base.forEach [1, 2, 3] (\x -> base.println (base.show x))
5+ base.forEach [1 2 3] (\x -> base.println (base.show x))
66 -- Empty list: action shouldn't run
77 base.forEach [] (\x -> base.println (base.show x))
88 -- Strings
9− base.forEach ["a", "b", "c"] (\s -> base.println s)
9+ base.forEach ["a" "b" "c"] (\s -> base.println s)
1010 -- After forEach: subsequent actions still run
1111 base.println "done"
1212 yield {})
examples/groupby.knot+4−4
@@ -5,10 +5,10 @@ type Todo = {title: Text, owner: Text, done: Int 1}
55}
66(do
77 replace *todos = [
8− { title "Write parser" owner "Alice" done 0 },
9− { title "Write codegen" owner "Alice" done 0 },
10− { title "Write runtime" owner "Bob" done 0 },
11− { title "Fix bug" owner "Alice" done 1 },
8+ { title "Write parser" owner "Alice" done 0 }
9+ { title "Write codegen" owner "Alice" done 0 }
10+ { title "Write runtime" owner "Bob" done 0 }
11+ { title "Fix bug" owner "Alice" done 1 }
1212 { title "Deploy" owner "Bob" done 1 }
1313 ]
1414
examples/hash.knot+1−1
@@ -20,6 +20,6 @@
2020 -- Numbers, booleans, lists also work
2121 base.println (base.bytesToHex (base.hash 42))
2222 base.println (base.bytesToHex (base.hash (Bool.True {})))
23− base.println (base.bytesToHex (base.hash [1, 2, 3]))
23+ base.println (base.bytesToHex (base.hash [1 2 3]))
2424
2525 yield {})
examples/hello.knot+1−1
@@ -4,7 +4,7 @@ type Person = {name: Text, age: Int 1}
44*people : [Person]
55}
66(do
7− replace *people = [{name "Alice" age 30}, {name "Bob" age 25}, {name "Carol" age 35}]
7+ replace *people = [{name "Alice" age 30} {name "Bob" age 25} {name "Carol" age 35}]
88 p <- *people
99 where p.age > 27
1010 yield p.name)
examples/inline_pushdown.knot+4−4
@@ -36,10 +36,10 @@ case5 (do
3636}
3737(do
3838 replace *employees = [
39− {name "Alice" dept "Eng" salary 90},
40− {name "Bob" dept "Eng" salary 80},
41− {name "Carol" dept "Sales" salary 70},
42− {name "Dave" dept "Sales" salary 60},
39+ {name "Alice" dept "Eng" salary 90}
40+ {name "Bob" dept "Eng" salary 80}
41+ {name "Carol" dept "Sales" salary 70}
42+ {name "Dave" dept "Sales" salary 60}
4343 {name "Eve" dept "Eng" salary 100}
4444 ]
4545 c1 <- case1
examples/json.knot+1−1
@@ -9,7 +9,7 @@
99 base.println (base.toJson { name "Alice" age 30 })
1010
1111 -- Encode a relation (becomes JSON array)
12− with { nums [{ x 1 }, { x 2 }, { x 3 }] } (do
12+ with { nums [{ x 1 } { x 2 } { x 3 }] } (do
1313 base.println (base.toJson nums)
1414
1515 -- Round-trip: encode then decode. parseJson returns `Maybe a` so malformed
examples/let_pushdown.knot+1−1
@@ -26,7 +26,7 @@ pruneDemo (do
2626 with {kept (do i <- items; where i.price > 0; yield i)} *items = kept)
2727}
2828(do
29− replace *items = [{name "Alice" price 10}, {name "Bob" price 25}]
29+ replace *items = [{name "Alice" price 10} {name "Bob" price 25}]
3030 appendDemo
3131 rows1 <- *items
3232 base.println ("after append: " ++ base.show rows1)
examples/nested.knot+2−2
@@ -7,8 +7,8 @@ type Person = {name: Text, age: Int 1}
77}
88(do
99 replace *teams = [
10− { name "Engineering" members [{ name "Alice" age 30 }, { name "Bob" age 25 }, { name "Eve" age 22 }] },
11− { name "Design" members [{ name "Carol" age 35 }, { name "Eve" age 22 }] }
10+ { name "Engineering" members [{ name "Alice" age 30 } { name "Bob" age 25 } { name "Eve" age 22 }] }
11+ { name "Design" members [{ name "Carol" age 35 } { name "Eve" age 22 }] }
1212 ]
1313
1414 -- Read nested members: bind the team, then bind its members field.
examples/query_opt.knot+5−5
@@ -91,13 +91,13 @@ pipeCountWhere (do
9191}
9292(do
9393 replace *employees = [
94− {name "Alice" dept "Eng" salary 90},
95− {name "Bob" dept "Eng" salary 80},
96− {name "Carol" dept "Sales" salary 70},
97− {name "Dave" dept "Sales" salary 60},
94+ {name "Alice" dept "Eng" salary 90}
95+ {name "Bob" dept "Eng" salary 80}
96+ {name "Carol" dept "Sales" salary 70}
97+ {name "Dave" dept "Sales" salary 60}
9898 {name "Eve" dept "Eng" salary 100}
9999 ]
100− replace *departments = [{name "Eng" budget 500}, {name "Sales" budget 200}]
100+ replace *departments = [{name "Eng" budget 500} {name "Sales" budget 200}]
101101 countDemo
102102 filterDemo
103103 joinDemo
examples/recursive.knot+2−2
@@ -11,8 +11,8 @@ with {
1111}
1212(do
1313 replace *manages = [
14− {manager "Alice" report "Bob"},
15− {manager "Alice" report "Carol"},
14+ {manager "Alice" report "Bob"}
15+ {manager "Alice" report "Carol"}
1616 {manager "Bob" report "Dave"}
1717 ]
1818 base.println "Direct reports:"
examples/showcase.knot+168−168
@@ -53,38 +53,38 @@ type Metric = {name: Text, value: Float 1, tags: Text}
5353
5454seedEmployees (do
5555 replace *employees = [
56− {name "Alice Chen" age 34 salary 142000.0 dept (Department.Engineering {}) active (Active.Yes {})},
57− {name "Bob Martinez" age 28 salary 95000.0 dept (Department.Engineering {}) active (Active.Yes {})},
58− {name "Carol Davis" age 41 salary 155000.0 dept (Department.Engineering {}) active (Active.Yes {})},
59− {name "Dan Wilson" age 25 salary 78000.0 dept (Department.Engineering {}) active (Active.Yes {})},
60− {name "Eve Johnson" age 37 salary 130000.0 dept (Department.Design {}) active (Active.Yes {})},
61− {name "Frank Lee" age 45 salary 160000.0 dept (Department.Engineering {}) active (Active.Yes {})},
62− {name "Grace Kim" age 30 salary 112000.0 dept (Department.Marketing {}) active (Active.Yes {})},
63− {name "Hank Brown" age 52 salary 175000.0 dept (Department.Engineering {}) active (Active.No {})},
64− {name "Iris Patel" age 29 salary 98000.0 dept (Department.Support {}) active (Active.Yes {})},
65− {name "Jack Thompson" age 33 salary 125000.0 dept (Department.Sales {}) active (Active.Yes {})},
66− {name "Kate White" age 38 salary 140000.0 dept (Department.Design {}) active (Active.Yes {})},
67− {name "Leo Garcia" age 26 salary 85000.0 dept (Department.Engineering {}) active (Active.Yes {})},
68− {name "Mia Robinson" age 44 salary 168000.0 dept (Department.Engineering {}) active (Active.Yes {})},
69− {name "Noah Clark" age 31 salary 105000.0 dept (Department.Marketing {}) active (Active.Yes {})},
70− {name "Olivia Hall" age 36 salary 138000.0 dept (Department.Sales {}) active (Active.Yes {})},
71− {name "Pat Young" age 48 salary 152000.0 dept (Department.Support {}) active (Active.Yes {})},
72− {name "Quinn Adams" age 27 salary 92000.0 dept (Department.Design {}) active (Active.Yes {})},
73− {name "Rita Baker" age 39 salary 145000.0 dept (Department.Engineering {}) active (Active.Yes {})},
74− {name "Sam Torres" age 42 salary 158000.0 dept (Department.Marketing {}) active (Active.No {})},
56+ {name "Alice Chen" age 34 salary 142000.0 dept (Department.Engineering {}) active (Active.Yes {})}
57+ {name "Bob Martinez" age 28 salary 95000.0 dept (Department.Engineering {}) active (Active.Yes {})}
58+ {name "Carol Davis" age 41 salary 155000.0 dept (Department.Engineering {}) active (Active.Yes {})}
59+ {name "Dan Wilson" age 25 salary 78000.0 dept (Department.Engineering {}) active (Active.Yes {})}
60+ {name "Eve Johnson" age 37 salary 130000.0 dept (Department.Design {}) active (Active.Yes {})}
61+ {name "Frank Lee" age 45 salary 160000.0 dept (Department.Engineering {}) active (Active.Yes {})}
62+ {name "Grace Kim" age 30 salary 112000.0 dept (Department.Marketing {}) active (Active.Yes {})}
63+ {name "Hank Brown" age 52 salary 175000.0 dept (Department.Engineering {}) active (Active.No {})}
64+ {name "Iris Patel" age 29 salary 98000.0 dept (Department.Support {}) active (Active.Yes {})}
65+ {name "Jack Thompson" age 33 salary 125000.0 dept (Department.Sales {}) active (Active.Yes {})}
66+ {name "Kate White" age 38 salary 140000.0 dept (Department.Design {}) active (Active.Yes {})}
67+ {name "Leo Garcia" age 26 salary 85000.0 dept (Department.Engineering {}) active (Active.Yes {})}
68+ {name "Mia Robinson" age 44 salary 168000.0 dept (Department.Engineering {}) active (Active.Yes {})}
69+ {name "Noah Clark" age 31 salary 105000.0 dept (Department.Marketing {}) active (Active.Yes {})}
70+ {name "Olivia Hall" age 36 salary 138000.0 dept (Department.Sales {}) active (Active.Yes {})}
71+ {name "Pat Young" age 48 salary 152000.0 dept (Department.Support {}) active (Active.Yes {})}
72+ {name "Quinn Adams" age 27 salary 92000.0 dept (Department.Design {}) active (Active.Yes {})}
73+ {name "Rita Baker" age 39 salary 145000.0 dept (Department.Engineering {}) active (Active.Yes {})}
74+ {name "Sam Torres" age 42 salary 158000.0 dept (Department.Marketing {}) active (Active.No {})}
7575 {name "Tina Flores" age 35 salary 132000.0 dept (Department.Sales {}) active (Active.Yes {})}
7676 ]
7777 yield {})
7878
7979seedProjects (do
8080 replace *projects = [
81− {name "Phoenix" lead "Alice Chen" budget 500000.0 priority (Priority.Critical {})},
82− {name "Atlas" lead "Carol Davis" budget 350000.0 priority (Priority.High {})},
83− {name "Meridian" lead "Frank Lee" budget 200000.0 priority (Priority.Medium {})},
84− {name "Horizon" lead "Mia Robinson" budget 750000.0 priority (Priority.Critical {})},
85− {name "Compass" lead "Eve Johnson" budget 150000.0 priority (Priority.Low {})},
86− {name "Vanguard" lead "Rita Baker" budget 420000.0 priority (Priority.High {})},
87− {name "Echo" lead "Bob Martinez" budget 180000.0 priority (Priority.Medium {})},
81+ {name "Phoenix" lead "Alice Chen" budget 500000.0 priority (Priority.Critical {})}
82+ {name "Atlas" lead "Carol Davis" budget 350000.0 priority (Priority.High {})}
83+ {name "Meridian" lead "Frank Lee" budget 200000.0 priority (Priority.Medium {})}
84+ {name "Horizon" lead "Mia Robinson" budget 750000.0 priority (Priority.Critical {})}
85+ {name "Compass" lead "Eve Johnson" budget 150000.0 priority (Priority.Low {})}
86+ {name "Vanguard" lead "Rita Baker" budget 420000.0 priority (Priority.High {})}
87+ {name "Echo" lead "Bob Martinez" budget 180000.0 priority (Priority.Medium {})}
8888 {name "Nimbus" lead "Kate White" budget 280000.0 priority (Priority.High {})}
8989 ]
9090 yield {})
@@ -97,157 +97,157 @@ seedTickets (do
9797 status (Status.InProgress {assignee "Bob Martinez"})
9898 priority (Priority.Critical {})
9999 points 8
100− },
101− {title "Add dark mode" project "Phoenix" status (Status.Open {}) priority (Priority.Medium {}) points 5},
100+ }
101+ {title "Add dark mode" project "Phoenix" status (Status.Open {}) priority (Priority.Medium {}) points 5}
102102 {
103103 title "Optimize query planner"
104104 project "Phoenix"
105105 status (Status.InProgress {assignee "Alice Chen"})
106106 priority (Priority.High {})
107107 points 13
108− },
109− {title "Write API docs" project "Phoenix" status (Status.Done {}) priority (Priority.Low {}) points 3},
108+ }
109+ {title "Write API docs" project "Phoenix" status (Status.Done {}) priority (Priority.Low {}) points 3}
110110 {
111111 title "Database migration tool"
112112 project "Atlas"
113113 status (Status.Blocked {reason "Waiting for schema freeze"})
114114 priority (Priority.High {})
115115 points 8
116− },
117− {title "Add CSV export" project "Atlas" status (Status.Open {}) priority (Priority.Medium {}) points 5},
116+ }
117+ {title "Add CSV export" project "Atlas" status (Status.Open {}) priority (Priority.Medium {}) points 5}
118118 {
119119 title "Fix N+1 queries"
120120 project "Atlas"
121121 status (Status.InProgress {assignee "Dan Wilson"})
122122 priority (Priority.Critical {})
123123 points 8
124− },
125− {title "Update CI pipeline" project "Meridian" status (Status.Done {}) priority (Priority.Medium {}) points 3},
126− {title "Add rate limiting" project "Meridian" status (Status.Open {}) priority (Priority.High {}) points 5},
124+ }
125+ {title "Update CI pipeline" project "Meridian" status (Status.Done {}) priority (Priority.Medium {}) points 3}
126+ {title "Add rate limiting" project "Meridian" status (Status.Open {}) priority (Priority.High {}) points 5}
127127 {
128128 title "Redesign dashboard"
129129 project "Horizon"
130130 status (Status.InProgress {assignee "Eve Johnson"})
131131 priority (Priority.High {})
132132 points 13
133− },
133+ }
134134 {
135135 title "Mobile responsive layout"
136136 project "Horizon"
137137 status (Status.Open {})
138138 priority (Priority.Medium {})
139139 points 8
140− },
140+ }
141141 {
142142 title "Fix memory leak"
143143 project "Horizon"
144144 status (Status.Blocked {reason "Need profiler access"})
145145 priority (Priority.Critical {})
146146 points 5
147− },
148− {title "Logo redesign" project "Compass" status (Status.Done {}) priority (Priority.Low {}) points 2},
147+ }
148+ {title "Logo redesign" project "Compass" status (Status.Done {}) priority (Priority.Low {}) points 2}
149149 {
150150 title "Brand guidelines doc"
151151 project "Compass"
152152 status (Status.InProgress {assignee "Kate White"})
153153 priority (Priority.Low {})
154154 points 3
155− },
156− {title "Set up monitoring" project "Vanguard" status (Status.Open {}) priority (Priority.High {}) points 5},
155+ }
156+ {title "Set up monitoring" project "Vanguard" status (Status.Open {}) priority (Priority.High {}) points 5}
157157 {
158158 title "Implement caching layer"
159159 project "Vanguard"
160160 status (Status.InProgress {assignee "Carol Davis"})
161161 priority (Priority.Critical {})
162162 points 13
163− },
164− {title "Add search indexing" project "Vanguard" status (Status.Open {}) priority (Priority.Medium {}) points 8},
165− {title "Fix date parsing bug" project "Echo" status (Status.Done {}) priority (Priority.High {}) points 3},
166− {title "Add webhook support" project "Echo" status (Status.Open {}) priority (Priority.Medium {}) points 8},
163+ }
164+ {title "Add search indexing" project "Vanguard" status (Status.Open {}) priority (Priority.Medium {}) points 8}
165+ {title "Fix date parsing bug" project "Echo" status (Status.Done {}) priority (Priority.High {}) points 3}
166+ {title "Add webhook support" project "Echo" status (Status.Open {}) priority (Priority.Medium {}) points 8}
167167 {
168168 title "Migrate to new SDK"
169169 project "Echo"
170170 status (Status.Blocked {reason "SDK not released yet"})
171171 priority (Priority.Low {})
172172 points 5
173− },
173+ }
174174 {
175175 title "Design system components"
176176 project "Nimbus"
177177 status (Status.InProgress {assignee "Quinn Adams"})
178178 priority (Priority.High {})
179179 points 8
180− },
181− {title "Accessibility audit" project "Nimbus" status (Status.Open {}) priority (Priority.Medium {}) points 5},
182− {title "Performance benchmarks" project "Phoenix" status (Status.Open {}) priority (Priority.High {}) points 5},
183− {title "Implement SSO" project "Phoenix" status (Status.Open {}) priority (Priority.Critical {}) points 13},
180+ }
181+ {title "Accessibility audit" project "Nimbus" status (Status.Open {}) priority (Priority.Medium {}) points 5}
182+ {title "Performance benchmarks" project "Phoenix" status (Status.Open {}) priority (Priority.High {}) points 5}
183+ {title "Implement SSO" project "Phoenix" status (Status.Open {}) priority (Priority.Critical {}) points 13}
184184 {title "Add telemetry" project "Atlas" status (Status.Open {}) priority (Priority.Medium {}) points 5}
185185 ]
186186 yield {})
187187
188188seedCustomers (do
189189 replace *customers = [
190− {name "Acme Corp" email "admin@acme.com" tier (Tier.Enterprise {})},
191− {name "Widgets Inc" email "hello@widgets.io" tier (Tier.Pro {})},
192− {name "Startup Labs" email "team@startuplabs.dev" tier (Tier.Free {})},
193− {name "MegaTech" email "info@megatech.com" tier (Tier.Enterprise {})},
194− {name "Cloud Nine" email "ops@cloudnine.co" tier (Tier.Pro {})},
195− {name "DataFlow" email "admin@dataflow.io" tier (Tier.Pro {})},
196− {name "ByteWorks" email "hello@byteworks.dev" tier (Tier.Free {})},
197− {name "Quantum Systems" email "sales@quantumsys.com" tier (Tier.Enterprise {})},
198− {name "NexGen" email "support@nexgen.io" tier (Tier.Pro {})},
199− {name "TechVista" email "info@techvista.com" tier (Tier.Free {})},
200− {name "Alpine Digital" email "hello@alpine.digital" tier (Tier.Pro {})},
190+ {name "Acme Corp" email "admin@acme.com" tier (Tier.Enterprise {})}
191+ {name "Widgets Inc" email "hello@widgets.io" tier (Tier.Pro {})}
192+ {name "Startup Labs" email "team@startuplabs.dev" tier (Tier.Free {})}
193+ {name "MegaTech" email "info@megatech.com" tier (Tier.Enterprise {})}
194+ {name "Cloud Nine" email "ops@cloudnine.co" tier (Tier.Pro {})}
195+ {name "DataFlow" email "admin@dataflow.io" tier (Tier.Pro {})}
196+ {name "ByteWorks" email "hello@byteworks.dev" tier (Tier.Free {})}
197+ {name "Quantum Systems" email "sales@quantumsys.com" tier (Tier.Enterprise {})}
198+ {name "NexGen" email "support@nexgen.io" tier (Tier.Pro {})}
199+ {name "TechVista" email "info@techvista.com" tier (Tier.Free {})}
200+ {name "Alpine Digital" email "hello@alpine.digital" tier (Tier.Pro {})}
201201 {name "CoreStack" email "admin@corestack.io" tier (Tier.Enterprise {})}
202202 ]
203203 yield {})
204204
205205seedProducts (do
206206 replace *products = [
207− {name "Laptop Pro 16" price 2499.99 category (Category.Electronics {}) inStock (Active.Yes {})},
208− {name "Wireless Mouse" price 49.99 category (Category.Electronics {}) inStock (Active.Yes {})},
209− {name "USB-C Hub" price 79.99 category (Category.Electronics {}) inStock (Active.No {})},
210− {name "Mechanical KB" price 159.99 category (Category.Electronics {}) inStock (Active.Yes {})},
211− {name "4K Monitor" price 599.99 category (Category.Electronics {}) inStock (Active.Yes {})},
212− {name "Clean Code" price 39.99 category (Category.Books {}) inStock (Active.Yes {})},
213− {name "SICP" price 65.0 category (Category.Books {}) inStock (Active.Yes {})},
214− {name "The Art of SQL" price 45.5 category (Category.Books {}) inStock (Active.No {})},
215− {name "Hoodie (Black)" price 59.99 category (Category.Clothing {}) inStock (Active.Yes {})},
216− {name "T-Shirt (Logo)" price 24.99 category (Category.Clothing {}) inStock (Active.Yes {})},
217− {name "Coffee Beans 1kg" price 18.99 category (Category.Food {}) inStock (Active.Yes {})},
218− {name "Green Tea Box" price 12.5 category (Category.Food {}) inStock (Active.Yes {})},
219− {name "IDE License" price 199.99 category (Category.Software {}) inStock (Active.Yes {})},
220− {name "CI/CD Platform" price 499.99 category (Category.Software {}) inStock (Active.Yes {})},
207+ {name "Laptop Pro 16" price 2499.99 category (Category.Electronics {}) inStock (Active.Yes {})}
208+ {name "Wireless Mouse" price 49.99 category (Category.Electronics {}) inStock (Active.Yes {})}
209+ {name "USB-C Hub" price 79.99 category (Category.Electronics {}) inStock (Active.No {})}
210+ {name "Mechanical KB" price 159.99 category (Category.Electronics {}) inStock (Active.Yes {})}
211+ {name "4K Monitor" price 599.99 category (Category.Electronics {}) inStock (Active.Yes {})}
212+ {name "Clean Code" price 39.99 category (Category.Books {}) inStock (Active.Yes {})}
213+ {name "SICP" price 65.0 category (Category.Books {}) inStock (Active.Yes {})}
214+ {name "The Art of SQL" price 45.5 category (Category.Books {}) inStock (Active.No {})}
215+ {name "Hoodie (Black)" price 59.99 category (Category.Clothing {}) inStock (Active.Yes {})}
216+ {name "T-Shirt (Logo)" price 24.99 category (Category.Clothing {}) inStock (Active.Yes {})}
217+ {name "Coffee Beans 1kg" price 18.99 category (Category.Food {}) inStock (Active.Yes {})}
218+ {name "Green Tea Box" price 12.5 category (Category.Food {}) inStock (Active.Yes {})}
219+ {name "IDE License" price 199.99 category (Category.Software {}) inStock (Active.Yes {})}
220+ {name "CI/CD Platform" price 499.99 category (Category.Software {}) inStock (Active.Yes {})}
221221 {name "Monitoring Suite" price 299.99 category (Category.Software {}) inStock (Active.Yes {})}
222222 ]
223223 yield {})
224224
225225seedOrders (do
226226 replace *orders = [
227− {customer "Acme Corp" product "Laptop Pro 16" quantity 50 total 124999.5},
228− {customer "Acme Corp" product "4K Monitor" quantity 50 total 29999.5},
229− {customer "Acme Corp" product "IDE License" quantity 100 total 19999.0},
230− {customer "Widgets Inc" product "Mechanical KB" quantity 20 total 3199.8},
231− {customer "Widgets Inc" product "Wireless Mouse" quantity 20 total 999.8},
232− {customer "MegaTech" product "Laptop Pro 16" quantity 200 total 499998.0},
233− {customer "MegaTech" product "CI/CD Platform" quantity 1 total 499.99},
234− {customer "MegaTech" product "Monitoring Suite" quantity 1 total 299.99},
235− {customer "Cloud Nine" product "IDE License" quantity 15 total 2999.85},
236− {customer "Cloud Nine" product "Coffee Beans 1kg" quantity 5 total 94.95},
237− {customer "DataFlow" product "CI/CD Platform" quantity 1 total 499.99},
238− {customer "DataFlow" product "4K Monitor" quantity 10 total 5999.9},
239− {customer "Startup Labs" product "Coffee Beans 1kg" quantity 2 total 37.98},
240− {customer "Startup Labs" product "Clean Code" quantity 5 total 199.95},
241− {customer "ByteWorks" product "T-Shirt (Logo)" quantity 10 total 249.9},
242− {customer "Quantum Systems" product "Laptop Pro 16" quantity 100 total 249999.0},
243− {customer "Quantum Systems" product "Monitoring Suite" quantity 3 total 899.97},
244− {customer "NexGen" product "Hoodie (Black)" quantity 25 total 1499.75},
245− {customer "NexGen" product "SICP" quantity 10 total 650.0},
246− {customer "TechVista" product "Green Tea Box" quantity 20 total 250.0},
247− {customer "Alpine Digital" product "USB-C Hub" quantity 30 total 2399.7},
248− {customer "Alpine Digital" product "Mechanical KB" quantity 15 total 2399.85},
249− {customer "CoreStack" product "Laptop Pro 16" quantity 75 total 187499.25},
250− {customer "CoreStack" product "IDE License" quantity 75 total 14999.25},
227+ {customer "Acme Corp" product "Laptop Pro 16" quantity 50 total 124999.5}
228+ {customer "Acme Corp" product "4K Monitor" quantity 50 total 29999.5}
229+ {customer "Acme Corp" product "IDE License" quantity 100 total 19999.0}
230+ {customer "Widgets Inc" product "Mechanical KB" quantity 20 total 3199.8}
231+ {customer "Widgets Inc" product "Wireless Mouse" quantity 20 total 999.8}
232+ {customer "MegaTech" product "Laptop Pro 16" quantity 200 total 499998.0}
233+ {customer "MegaTech" product "CI/CD Platform" quantity 1 total 499.99}
234+ {customer "MegaTech" product "Monitoring Suite" quantity 1 total 299.99}
235+ {customer "Cloud Nine" product "IDE License" quantity 15 total 2999.85}
236+ {customer "Cloud Nine" product "Coffee Beans 1kg" quantity 5 total 94.95}
237+ {customer "DataFlow" product "CI/CD Platform" quantity 1 total 499.99}
238+ {customer "DataFlow" product "4K Monitor" quantity 10 total 5999.9}
239+ {customer "Startup Labs" product "Coffee Beans 1kg" quantity 2 total 37.98}
240+ {customer "Startup Labs" product "Clean Code" quantity 5 total 199.95}
241+ {customer "ByteWorks" product "T-Shirt (Logo)" quantity 10 total 249.9}
242+ {customer "Quantum Systems" product "Laptop Pro 16" quantity 100 total 249999.0}
243+ {customer "Quantum Systems" product "Monitoring Suite" quantity 3 total 899.97}
244+ {customer "NexGen" product "Hoodie (Black)" quantity 25 total 1499.75}
245+ {customer "NexGen" product "SICP" quantity 10 total 650.0}
246+ {customer "TechVista" product "Green Tea Box" quantity 20 total 250.0}
247+ {customer "Alpine Digital" product "USB-C Hub" quantity 30 total 2399.7}
248+ {customer "Alpine Digital" product "Mechanical KB" quantity 15 total 2399.85}
249+ {customer "CoreStack" product "Laptop Pro 16" quantity 75 total 187499.25}
250+ {customer "CoreStack" product "IDE License" quantity 75 total 14999.25}
251251 {customer "CoreStack" product "CI/CD Platform" quantity 2 total 999.98}
252252 ]
253253 yield {})
@@ -257,146 +257,146 @@ seedTeams (do
257257 {
258258 name "Platform"
259259 members [
260− {name "Alice Chen" role "Lead"},
261− {name "Bob Martinez" role "Senior"},
262− {name "Dan Wilson" role "Junior"},
260+ {name "Alice Chen" role "Lead"}
261+ {name "Bob Martinez" role "Senior"}
262+ {name "Dan Wilson" role "Junior"}
263263 {name "Leo Garcia" role "Junior"}
264264 ]
265− },
265+ }
266266 {
267267 name "Frontend"
268268 members [
269− {name "Eve Johnson" role "Lead"},
270− {name "Kate White" role "Senior"},
269+ {name "Eve Johnson" role "Lead"}
270+ {name "Kate White" role "Senior"}
271271 {name "Quinn Adams" role "Junior"}
272272 ]
273− },
273+ }
274274 {
275275 name "Infrastructure"
276276 members [
277− {name "Carol Davis" role "Lead"},
278− {name "Frank Lee" role "Senior"},
277+ {name "Carol Davis" role "Lead"}
278+ {name "Frank Lee" role "Senior"}
279279 {name "Rita Baker" role "Senior"}
280280 ]
281− },
281+ }
282282 {
283283 name "Growth"
284284 members [
285− {name "Grace Kim" role "Lead"},
286− {name "Noah Clark" role "Senior"},
287− {name "Jack Thompson" role "Senior"},
288− {name "Olivia Hall" role "Senior"},
285+ {name "Grace Kim" role "Lead"}
286+ {name "Noah Clark" role "Senior"}
287+ {name "Jack Thompson" role "Senior"}
288+ {name "Olivia Hall" role "Senior"}
289289 {name "Tina Flores" role "Senior"}
290290 ]
291− },
291+ }
292292 {
293293 name "Customer Success"
294− members [{name "Iris Patel" role "Lead"}, {name "Pat Young" role "Senior"}]
294+ members [{name "Iris Patel" role "Lead"} {name "Pat Young" role "Senior"}]
295295 }
296296 ]
297297 yield {})
298298
299299seedLogs (do
300300 replace *logs = [
301− {timestamp 1710900000 level (Level.Info {}) message "Server started on port 8080" source "main"},
301+ {timestamp 1710900000 level (Level.Info {}) message "Server started on port 8080" source "main"}
302302 {
303303 timestamp 1710900001
304304 level (Level.Info {})
305305 message "Database connection pool initialized (10)"
306306 source "db"
307− },
308− {timestamp 1710900005 level (Level.Debug {}) message "Loading configuration from env" source "config"},
307+ }
308+ {timestamp 1710900005 level (Level.Debug {}) message "Loading configuration from env" source "config"}
309309 {
310310 timestamp 1710900012
311311 level (Level.Info {})
312312 message "Health check endpoint registered"
313313 source "routes"
314− },
315− {timestamp 1710900030 level (Level.Warn {}) message "Slow query detected: 2340ms" source "db"},
314+ }
315+ {timestamp 1710900030 level (Level.Warn {}) message "Slow query detected: 2340ms" source "db"}
316316 {
317317 timestamp 1710900045
318318 level (Level.Info {})
319319 message "Request: GET /api/users (200, 45ms)"
320320 source "http"
321− },
321+ }
322322 {
323323 timestamp 1710900046
324324 level (Level.Info {})
325325 message "Request: POST /api/orders (201, 120ms)"
326326 source "http"
327− },
328− {timestamp 1710900047 level (Level.Debug {}) message "Cache miss for key: user:1234" source "cache"},
327+ }
328+ {timestamp 1710900047 level (Level.Debug {}) message "Cache miss for key: user:1234" source "cache"}
329329 {
330330 timestamp 1710900048
331331 level (Level.Info {})
332332 message "Request: GET /api/products (200, 32ms)"
333333 source "http"
334− },
334+ }
335335 {
336336 timestamp 1710900060
337337 level (Level.Error {})
338338 message "Connection refused: redis://localhost:6379"
339339 source "cache"
340− },
341− {timestamp 1710900061 level (Level.Warn {}) message "Falling back to in-memory cache" source "cache"},
340+ }
341+ {timestamp 1710900061 level (Level.Warn {}) message "Falling back to in-memory cache" source "cache"}
342342 {
343343 timestamp 1710900090
344344 level (Level.Info {})
345345 message "Request: PUT /api/users/42 (200, 88ms)"
346346 source "http"
347− },
347+ }
348348 {
349349 timestamp 1710900100
350350 level (Level.Error {})
351351 message "Timeout: external payment API (5000ms)"
352352 source "payments"
353− },
353+ }
354354 {
355355 timestamp 1710900101
356356 level (Level.Warn {})
357357 message "Retrying payment request (attempt 2/3)"
358358 source "payments"
359− },
359+ }
360360 {
361361 timestamp 1710900105
362362 level (Level.Info {})
363363 message "Payment processed: order #7821"
364364 source "payments"
365− },
366− {timestamp 1710900120 level (Level.Debug {}) message "GC pause: 12ms" source "runtime"},
365+ }
366+ {timestamp 1710900120 level (Level.Debug {}) message "GC pause: 12ms" source "runtime"}
367367 {
368368 timestamp 1710900150
369369 level (Level.Info {})
370370 message "Cron: daily report generation started"
371371 source "scheduler"
372− },
372+ }
373373 {
374374 timestamp 1710900180
375375 level (Level.Info {})
376376 message "Report generated: 1,247 rows exported"
377377 source "scheduler"
378− },
379− {timestamp 1710900200 level (Level.Warn {}) message "Disk usage at 82%" source "monitor"},
378+ }
379+ {timestamp 1710900200 level (Level.Warn {}) message "Disk usage at 82%" source "monitor"}
380380 {
381381 timestamp 1710900300
382382 level (Level.Info {})
383383 message "Request: DELETE /api/sessions/old (200)"
384384 source "http"
385− },
386− {timestamp 1710900301 level (Level.Info {}) message "Cleaned 847 expired sessions" source "auth"},
385+ }
386+ {timestamp 1710900301 level (Level.Info {}) message "Cleaned 847 expired sessions" source "auth"}
387387 {
388388 timestamp 1710900400
389389 level (Level.Error {})
390390 message "TLS certificate expires in 7 days"
391391 source "monitor"
392− },
392+ }
393393 {
394394 timestamp 1710900500
395395 level (Level.Info {})
396396 message "Backup completed: 2.4GB compressed"
397397 source "backup"
398− },
399− {timestamp 1710900600 level (Level.Debug {}) message "WebSocket connections: 142 active" source "ws"},
398+ }
399+ {timestamp 1710900600 level (Level.Debug {}) message "WebSocket connections: 142 active" source "ws"}
400400 {
401401 timestamp 1710900700
402402 level (Level.Info {})
@@ -408,35 +408,35 @@ seedLogs (do
408408
409409seedMetrics (do
410410 replace *metrics = [
411− {name "http_requests_total" value 48291.0 tags "method=GET,status=200"},
412− {name "http_requests_total" value 12847.0 tags "method=POST,status=201"},
413− {name "http_requests_total" value 342.0 tags "method=POST,status=400"},
414− {name "http_requests_total" value 89.0 tags "method=GET,status=404"},
415− {name "http_requests_total" value 23.0 tags "method=GET,status=500"},
416− {name "http_request_duration_ms" value 45.2 tags "endpoint=/api/users,p50"},
417− {name "http_request_duration_ms" value 120.8 tags "endpoint=/api/users,p95"},
418− {name "http_request_duration_ms" value 340.1 tags "endpoint=/api/users,p99"},
419− {name "http_request_duration_ms" value 12.4 tags "endpoint=/api/health,p50"},
420− {name "http_request_duration_ms" value 31.6 tags "endpoint=/api/products,p50"},
421− {name "http_request_duration_ms" value 88.9 tags "endpoint=/api/products,p95"},
422− {name "db_connections_active" value 8.0 tags "pool=primary"},
423− {name "db_connections_active" value 3.0 tags "pool=replica"},
424− {name "db_query_duration_ms" value 2.1 tags "query=select,table=users"},
425− {name "db_query_duration_ms" value 15.8 tags "query=select,table=orders"},
426− {name "db_query_duration_ms" value 0.8 tags "query=select,table=products"},
427− {name "memory_usage_bytes" value 524288000.0 tags "type=heap"},
428− {name "memory_usage_bytes" value 134217728.0 tags "type=stack"},
429− {name "cpu_usage_percent" value 34.5 tags "core=0"},
430− {name "cpu_usage_percent" value 67.2 tags "core=1"},
431− {name "cpu_usage_percent" value 22.1 tags "core=2"},
432− {name "cpu_usage_percent" value 45.8 tags "core=3"},
433− {name "cache_hit_ratio" value 0.847 tags "cache=redis"},
434− {name "cache_hit_ratio" value 0.923 tags "cache=local"},
435− {name "websocket_connections" value 142.0 tags ""},
436− {name "queue_depth" value 37.0 tags "queue=email"},
437− {name "queue_depth" value 12.0 tags "queue=webhook"},
438− {name "queue_depth" value 0.0 tags "queue=analytics"},
439− {name "disk_usage_percent" value 82.3 tags "mount=/data"},
411+ {name "http_requests_total" value 48291.0 tags "method=GET,status=200"}
412+ {name "http_requests_total" value 12847.0 tags "method=POST,status=201"}
413+ {name "http_requests_total" value 342.0 tags "method=POST,status=400"}
414+ {name "http_requests_total" value 89.0 tags "method=GET,status=404"}
415+ {name "http_requests_total" value 23.0 tags "method=GET,status=500"}
416+ {name "http_request_duration_ms" value 45.2 tags "endpoint=/api/users,p50"}
417+ {name "http_request_duration_ms" value 120.8 tags "endpoint=/api/users,p95"}
418+ {name "http_request_duration_ms" value 340.1 tags "endpoint=/api/users,p99"}
419+ {name "http_request_duration_ms" value 12.4 tags "endpoint=/api/health,p50"}
420+ {name "http_request_duration_ms" value 31.6 tags "endpoint=/api/products,p50"}
421+ {name "http_request_duration_ms" value 88.9 tags "endpoint=/api/products,p95"}
422+ {name "db_connections_active" value 8.0 tags "pool=primary"}
423+ {name "db_connections_active" value 3.0 tags "pool=replica"}
424+ {name "db_query_duration_ms" value 2.1 tags "query=select,table=users"}
425+ {name "db_query_duration_ms" value 15.8 tags "query=select,table=orders"}
426+ {name "db_query_duration_ms" value 0.8 tags "query=select,table=products"}
427+ {name "memory_usage_bytes" value 524288000.0 tags "type=heap"}
428+ {name "memory_usage_bytes" value 134217728.0 tags "type=stack"}
429+ {name "cpu_usage_percent" value 34.5 tags "core=0"}
430+ {name "cpu_usage_percent" value 67.2 tags "core=1"}
431+ {name "cpu_usage_percent" value 22.1 tags "core=2"}
432+ {name "cpu_usage_percent" value 45.8 tags "core=3"}
433+ {name "cache_hit_ratio" value 0.847 tags "cache=redis"}
434+ {name "cache_hit_ratio" value 0.923 tags "cache=local"}
435+ {name "websocket_connections" value 142.0 tags ""}
436+ {name "queue_depth" value 37.0 tags "queue=email"}
437+ {name "queue_depth" value 12.0 tags "queue=webhook"}
438+ {name "queue_depth" value 0.0 tags "queue=analytics"}
439+ {name "disk_usage_percent" value 82.3 tags "mount=/data"}
440440 {name "disk_usage_percent" value 45.1 tags "mount=/logs"}
441441 ]
442442 yield {})
examples/stm_row_filter.knot+1−1
@@ -29,7 +29,7 @@ credit (\aid amount -> atomic do
2929 (*accounts = setBalance aid amount rows))
3030}
3131(do
32− replace *accounts = [{id 1 balance 0}, {id 2 balance 0}, {id 3 balance 0}]
32+ replace *accounts = [{id 1 balance 0} {id 2 balance 0} {id 3 balance 0}]
3333 credit 1 100
3434 credit 2 50
3535 credit 3 25
knot.md+3−3
@@ -10,7 +10,7 @@ type Person = {name: Text, age: Int 1}
1010*people : [Person]
1111
1212main = do
13− *people = [{name "Alice" age 30}, {name "Bob" age 25}]
13+ *people = [{name "Alice" age 30} {name "Bob" age 25}]
1414 people <- *people
1515 with {result do
1616 p <- people
@@ -95,7 +95,7 @@ Note the two syntaxes differ: **values** are `{name "Alice" age 30}` (space-sepa
9595A relation `[T]` is a typed **set** of `T` values. No duplicates. No ordering guarantees.
9696
9797```knot
98−names = ["Alice", "Bob", "Carol"] -- [Text]
98+names = ["Alice" "Bob" "Carol"] -- [Text]
9999empty = [] -- [a]
100100people = [{name "Alice" age 30}] -- [{name: Text, age: Int 1}]
101101```
@@ -457,7 +457,7 @@ describe = \rel -> case rel of
457457| Pattern | Matches |
458458|---------|---------|
459459| `[]` | empty relation |
460−| `[p1, p2, ...]` | relation with exactly that many rows |
460+| `[p1 p2 ...]` | relation with exactly that many rows |
461461| `Cons head tail` | non-empty relation, `head` is one row, `tail` is the rest |
462462
463463`Cons` is also useful in recursive functions:
stdlib.md+6−6
@@ -138,7 +138,7 @@ Extract the single element of a relation. Returns `Just {value: x}` for a single
138138```knot
139139single [{name "Alice"}] -- Just {value {name "Alice"}}
140140single [] -- Nothing {}
141−single [1, 2] -- Nothing {}
141+single [1 2] -- Nothing {}
142142```
143143
144144### `count`
@@ -178,7 +178,7 @@ sum : [a] -> a
178178Sum of a numeric relation. Takes the relation directly — there is no projection argument. To sum a field of a record relation, project first with `map`. Works with `Int 1`, `Float 1`, and unit-annotated types — units are preserved.
179179
180180```knot
181−total = sum [10, 20, 30] -- 60
181+total = sum [10 20 30] -- 60
182182
183183-- Sum a record field by projecting first:
184184totalAge = sum (map (\p -> p.age) *people)
@@ -293,7 +293,7 @@ findFirst : [a] -> (a -> Bool) -> Maybe a
293293First row matching the predicate (left-to-right), or `Nothing {}` when no row matches. Stops at the first hit.
294294
295295```knot
296−findFirst [1, 2, 3, 4, 5] (\x -> x > 3) -- Just {value 4}
296+findFirst [1 2 3 4 5] (\x -> x > 3) -- Just {value 4}
297297```
298298
299299### `any` / `all`
@@ -534,9 +534,9 @@ drop : Int 1 -> [a] -> [a]
534534
535535```knot
536536take 3 "hello" -- "hel"
537−take 2 [10, 20, 30] -- [10, 20]
537+take 2 [10 20 30] -- [10, 20]
538538drop 3 "hello" -- "lo"
539−drop 1 [10, 20, 30] -- [20, 30]
539+drop 1 [10 20 30] -- [20, 30]
540540```
541541
542542### `contains`
@@ -639,7 +639,7 @@ forEach : [a] -> (a -> IO r {}) -> IO r {}
639639Sequence an IO action over each row of a relation. Iteration follows the relation's deterministic order (after any `sortBy`).
640640
641641```knot
642−forEach ["a", "b", "c"] (\s -> println s)
642+forEach ["a" "b" "c"] (\s -> println s)
643643```
644644
645645---