diff --git a/site/demo/issue.cast b/site/demo/issue.cast index c75d527..247919b 100644 --- a/site/demo/issue.cast +++ b/site/demo/issue.cast @@ -1,9 +1,194 @@ -{"version": 2, "width": 80, "height": 24, "timestamp": 1790342232, "env": {"SHELL": "/bin/zsh", "TERM": null}, "idle_time_limit": 2.0} -[0.015462, "o", "TERM environment variable not set.\r\n"] -[0.015727, "o", "$ ISSUE_ID=$(lex issue create --title \"add zip\" --shape typed_delta \\\r\n --api \"zip:(xs :: List[A], ys :: List[B]) -> List[(A, B)]\" \\\r\n --example \"zip([1,2],[\\\"a\\\",\\\"b\\\"]) => [(1,\\\"a\\\"),(2,\\\"b\\\")]\")\r\n"] -[0.023593, "o", "$ ./bin/lex-code \"--issue=$ISSUE_ID\" --ollama > /tmp/lex-code-issue-demo.log 2>&1\r\n"] -[2061.950497, "o", "$ grep \"^[ISSUE_VERDICT]\" /tmp/lex-code-issue-demo.log\r\n"] -[2061.965744, "o", "[ISSUE_VERDICT]\tverified\taea6613fc9e96953bb1c89fb3c45ac7200f62a379acdee2a47e29bab4c938ced\r\n"] -[2062.4771, "o", "$ awk '/^fn zip/,/^}/' src/list_lex.lex # what actually got written\r\n"] -[2062.4788280000002, "o", "fn zip[A, B](xs :: List[A], ys :: List[B]) -> List[(A, B)]\r\n examples {\r\n zip([1, 2], [\"a\", \"b\"]) => [(1, \"a\"), (2, \"b\")]\r\n }\r\n{\r\n let acc := list.fold(xs, ([], ys), fn (a :: (List[(A, B)], List[B]), x :: A) -> (List[(A, B)], List[B]) {\r\n match a {\r\n (out, rest) => match list.head(rest) {\r\n Some(y) => (list.cons((x, y), out), list.tail(rest)),\r\n"] -[2062.478845, "o", " None => (out, rest),\r\n },\r\n }\r\n })\r\n match acc {\r\n (out, _) => list.reverse(out),\r\n }\r\n}\r\n"] +{"version": 2, "width": 100, "height": 30, "timestamp": 1790366387, "env": {"SHELL": "/bin/zsh", "TERM": null}, "idle_time_limit": 2.0} +[0.026125, "o", "\u001b[3J\u001b[H\u001b[2J"] +[0.026344, "o", "\u001b[1;34m$ \u001b[0m"] +[0.038581, "o", "ISSUE_"] +[0.220303, "o", "ID=$(l"] +[0.314557, "o", "ex iss"] +[0.409768, "o", "ue cre"] +[0.501628, "o", "ate --"] +[0.591887, "o", "title "] +[0.685371, "o", "\"add q"] +[0.780362, "o", "uote a"] +[0.874194, "o", "pi\" --"] +[0.968372, "o", "shape "] +[1.060697, "o", "typed_"] +[1.155522, "o", "delta "] +[1.249473, "o", "\\"] +[1.252766, "o", "\r\n"] +[1.272099, "o", " --"] +[1.45833, "o", "body \""] +[1.550959, "o", "REST A"] +[1.641449, "o", "PI on "] +[1.734781, "o", ":8931 "] +[1.825212, "o", "— GE"] +[1.917042, "o", "T /hea"] +[2.007808, "o", "lth, G"] +[2.10141, "o", "ET /qu"] +[2.194529, "o", "ote/:t"] +[2.28648, "o", "opic ("] +[2.381457, "o", "JSON),"] +[2.47391, "o", " else "] +[2.661685, "o", "404."] +[2.664387, "o", "\r\n"] +[2.684939, "o", " "] +[2.869487, "o", " "] +[2.963265, "o", "Check "] +[3.058312, "o", "lex.to"] +[3.153341, "o", "ml for"] +[3.245966, "o", " somet"] +[3.340455, "o", "hing t"] +[3.434334, "o", "hat al"] +[3.525193, "o", "ready "] +[3.616237, "o", "does r"] +[3.70637, "o", "outing"] +[3.799465, "o", " befor"] +[3.890837, "o", "e hand"] +[3.985775, "o", "-rolli"] +[4.171565, "o", "ng it."] +[4.26657, "o", "\" \\"] +[4.267624, "o", "\r\n"] +[4.281207, "o", " --"] +[4.470339, "o", "api \"q"] +[4.565381, "o", "uote_f"] +[4.655855, "o", "or:(to"] +[4.750695, "o", "pic ::"] +[4.843148, "o", " Str) "] +[4.938272, "o", "-> Str"] +[5.028775, "o", "\" \\"] +[5.029955, "o", "\r\n"] +[5.046291, "o", " --"] +[5.234813, "o", "api \"m"] +[5.327305, "o", "ain:()"] +[5.421481, "o", " -> [n"] +[5.51664, "o", "et] Ni"] +[5.611748, "o", "l\" \\"] +[5.61432, "o", "\r\n"] +[5.634313, "o", " --"] +[5.822465, "o", "exampl"] +[5.915684, "o", "e \"quo"] +[6.007087, "o", "te_for"] +[6.10071, "o", "(\\\"cou"] +[6.195837, "o", "rage\\\""] +[6.286422, "o", ") => \\"] +[6.381516, "o", "\"Do on"] +[6.476611, "o", "e thin"] +[6.571658, "o", "g ever"] +[6.662525, "o", "y day "] +[6.753662, "o", "that s"] +[6.846472, "o", "cares "] +[6.941302, "o", "you.\\\""] +[7.122417, "o", "\")"] +[7.123818, "o", "\r\n"] +[7.148877, "o", "\r\n"] +[7.148959, "o", "\u001b[1;34m$ \u001b[0m"] +[7.15794, "o", "lex-co"] +[7.346622, "o", "de \"--"] +[7.439066, "o", "issue="] +[7.530615, "o", "$ISSUE"] +[7.621425, "o", "_ID\" -"] +[7.716517, "o", "-ollam"] +[7.810069, "o", "a | gr"] +[7.904085, "o", "ep -E "] +[7.996481, "o", "\"^\\[to"] +[8.087206, "o", "ol: |I"] +[8.182252, "o", "SSUE_V"] +[8.277457, "o", "ERDICT"] +[8.370191, "o", "\""] +[8.371316, "o", "\r\n"] +[37.221287, "o", "[tool: issue_show]\r\n"] +[37.548407, "o", "[tool: read]\r\n"] +[37.922018, "o", "[tool: glob]\r\n"] +[48.592724, "o", "[tool: grep]\r\n"] +[48.959167, "o", "[tool: read]\r\n"] +[81.881012, "o", "[tool: grep]\r\n"] +[82.277277, "o", "[tool: lex_stdlib]\r\n"] +[82.895755, "o", "[tool: glob]\r\n"] +[87.01346, "o", "[tool: bash]\r\n"] +[87.4263, "o", "[tool: lex_cli_help]\r\n"] +[438.060202, "o", "[tool: bash]\r\n"] +[476.650233, "o", "[tool: bash]\r\n"] +[477.16504, "o", "[tool: lex_guide]\r\n"] +[498.585221, "o", "[tool: lex_stdlib]\r\n"] +[501.336417, "o", "[tool: bash]\r\n"] +[787.84748, "o", "[tool: bash]\r\n"] +[796.823437, "o", "[tool: bash]\r\n"] +[816.308868, "o", "[tool: write]\r\n"] +[827.747232, "o", "[tool: edit]\r\n"] +[850.249565, "o", "[tool: edit]\r\n"] +[868.044565, "o", "[tool: write]\r\n"] +[893.397371, "o", "[tool: lex_run]\r\n"] +[895.559692, "o", "[tool: issue_verify]\r\n"] +[943.96841, "o", "[ISSUE_VERDICT]\tverified\t72fa4f17455dfb8d7624412a4449444cc85c747b09c2db423df32679e8f743ae\r\n"] +[943.995021, "o", "\r\n"] +[944.013733, "o", "\u001b[1;34m$ \u001b[0m"] +[944.022891, "o", "grep -"] +[944.212051, "o", "n 'imp"] +[944.307079, "o", "ort\\|^"] +[944.40208, "o", "fn ' s"] +[944.495827, "o", "rc/quo"] +[944.59085, "o", "te_api"] +[944.685886, "o", ".lex"] +[944.68657, "o", "\r\n"] +[944.689857, "o", "14:import \"std.net\" as net\r\n16:import \"std.str\" as str\r\n18:import \"lex-web/src/router\" as router\r\n20:import \"lex-web/src/ctx\" as ctx\r\n22:import \"lex-web/src/response\" as resp\r\n26:fn quote_for(topic :: Str) -> Str\r\n"] +[944.689869, "o", "48:fn handle_quote(c :: ctx.Ctx) -> resp.Response {\r\n57:fn build_router() -> router.Router {\r\n67:fn main() -> [net] Nil {\r\n"] +[944.690061, "o", "\r\n"] +[944.876647, "o", "\u001b[1;34m$ \u001b[0m"] +[944.883834, "o", "lex ru"] +[945.070347, "o", "n --al"] +[945.165359, "o", "low-ef"] +[945.260371, "o", "fects "] +[945.354052, "o", "approv"] +[945.448633, "o", "al,con"] +[945.542768, "o", "curren"] +[945.635042, "o", "t,cryp"] +[945.725312, "o", "to,fs_"] +[945.816489, "o", "read,f"] +[945.909902, "o", "s_writ"] +[946.003464, "o", "e,io,l"] +[946.098566, "o", "lm,net"] +[946.192669, "o", ",proc,"] +[946.28763, "o", "random"] +[946.476496, "o", ",sql,t"] +[946.567765, "o", "ime sr"] +[946.660557, "o", "c/quot"] +[946.752023, "o", "e_api."] +[946.844001, "o", "lex ma"] +[946.934841, "o", "in &"] +[946.937787, "o", "\r\n"] +[949.952311, "o", "\u001b[1;34m$ \u001b[0m"] +[949.963661, "o", "curl -"] +[950.153902, "o", "s loca"] +[950.245637, "o", "lhost:"] +[950.340618, "o", "8931/h"] +[950.43569, "o", "ealth"] +[950.437779, "o", "\r\n"] +[950.463486, "o", "{\"ok\":true}"] +[950.463867, "o", "\r\n"] +[950.463904, "o", "\u001b[1;34m$ \u001b[0m"] +[950.470258, "o", "curl -"] +[950.656505, "o", "s loca"] +[950.748068, "o", "lhost:"] +[950.841548, "o", "8931/q"] +[950.936631, "o", "uote/c"] +[951.031653, "o", "ourage"] +[951.032897, "o", "\r\n"] +[951.050176, "o", "{\"topic\":\"courage\",\"quote\":\"Do one thing every day that scares you.\"}"] +[951.050294, "o", "\r\n\u001b[1;34m$ \u001b[0m"] +[951.059177, "o", "curl -"] +[951.244931, "o", "s loca"] +[951.336761, "o", "lhost:"] +[951.429608, "o", "8931/q"] +[951.52437, "o", "uote/w"] +[951.615155, "o", "isdom"] +[951.617937, "o", "\r\n"] +[951.640659, "o", "{\"topic\":\"wisdom\",\"quote\":\"Every day is a fresh page.\"}"] +[951.641311, "o", "\r\n"] +[951.641367, "o", "\u001b[1;34m$ \u001b[0m"] +[951.65307, "o", "curl -"] +[951.841581, "o", "s loca"] +[951.934984, "o", "lhost:"] +[952.028596, "o", "8931/n"] +[952.123617, "o", "ope"] +[952.124881, "o", "\r\n"] +[952.139596, "o", "{\"error\":\"not found\"}"] +[952.140112, "o", "\r\n"] diff --git a/site/index.html b/site/index.html index 0783602..8c82022 100644 --- a/site/index.html +++ b/site/index.html @@ -134,19 +134,19 @@
Work as a declared, checkable contract instead of a paragraph of prose — an API shape and the examples that prove it, the acceptance a run either closes against or doesn't. Real output, the same issue used in "Try it" below:
-$ lex issue show aea6613fc9e96953bb1c89fb3c45ac7200f62a379acdee2a47e29bab4c938ced +$ lex issue show 72fa4f17455dfb8d7624412a4449444cc85c747b09c2db423df32679e8f743ae { "acceptance": { "api": [ - { "kind": "added", "name": "zip", - "signature": "(xs :: List[A], ys :: List[B]) -> List[(A, B)]" } + { "kind": "added", "name": "quote_for", "signature": "(topic :: Str) -> Str" }, + { "kind": "added", "name": "main", "signature": "() -> [net] Nil" } ], - "examples": [ "zip([1,2],[\"a\",\"b\"]) => [(1,\"a\"),(2,\"b\")]" ], + "examples": [ "quote_for(\"courage\") => \"Do one thing every day that scares you.\"" ], "shape": "typed_delta" }, - "created_at": 1790252464, - "issue_id": "aea6613fc9e96953bb1c89fb3c45ac7200f62a379acdee2a47e29bab4c938ced", - "title": "add zip" + "body": "Add a tiny REST API on port 8931: GET /health -> {\"ok\":true}, GET /quote/:topic -> a short quote for that topic as JSON, anything else -> 404. Check this project's own dependencies (lex.toml) for something that already does routing/responses before hand-rolling it.", + "issue_id": "72fa4f17455dfb8d7624412a4449444cc85c747b09c2db423df32679e8f743ae", + "title": "add quote api" }Issues live in Lex's own op-log VCS: every accepted change is a content-addressed, hash-chained op, and
lex issue verifychecks the acceptance against HEAD, not a @@ -174,23 +174,30 @@Try it
what that looks like live. For a result you can act on without reading the diff, hand it a typed issue instead — it closes by proof, not by a transcript claiming success: -ISSUE_ID=$(lex issue create --title "add zip" --shape typed_delta \ - --api 'zip:(xs :: List[A], ys :: List[B]) -> List[(A, B)]' \ - --example 'zip([1,2],["a","b"]) => [(1,"a"),(2,"b")]') +-ISSUE_ID=$(lex issue create --title "add quote api" --shape typed_delta \ + --body 'Add a tiny REST API on port 8931: GET /health, GET /quote/:topic (JSON), + else 404. Check lex.toml for something that already does routing + before hand-rolling it.' \ + --api 'quote_for:(topic :: Str) -> Str' \ + --api 'main:() -> [net] Nil' \ + --example 'quote_for("courage") => "Do one thing every day that scares you."') -lex-code "--issue=$ISSUE_ID" --ollama > /tmp/lex-code.log 2>&1 -grep '^\[ISSUE_VERDICT\]' /tmp/lex-code.log -# [ISSUE_VERDICT] verified <issue_id> - -awk '/^fn zip/,/^}/' src/list_lex.lex # what actually got written+lex-code "--issue=$ISSUE_ID" --ollama # streams what the agent does +# [ISSUE_VERDICT] verified <issue_id>The typed-issue flow above, live and unedited — same issue, - same run, ending in the same
+verifiedline, then the actual function it - wrote, not just the verdict.A real, unedited run on a fresh clone: about sixteen minutes of a + local model, played with idle gaps capped at two seconds. Then the code it wrote, the + server it started, and real
curlanswers.-Both commands above are copy-paste real — run verbatim against this repo - before shipping this page, closing
+verified.Nobody told it which package to use. The prompt says only "check +
+lex.tomlbefore hand-rolling it". The agent read this project's + dependencies, found lex-web, read its + source, and built the routes on its router —/quote/:topicincluded — then + closed the issue against the declared signatures and example.One honest wrinkle: the run command in the recording grants many effects. Importing + lex-web's router widens what the program needs at runtime well beyond its declared +
[net], and we're narrowing that.No key, no waitlist, no account: the install script above sets up the Lex toolchain too if you don't already have it, then you're running a real session in under a minute.
@@ -279,7 +286,7 @@OpenCode Go plan
poster: 'npt:0:01' }); AsciinemaPlayer.create('demo/issue.cast', document.getElementById('cast-issue'), { - cols: 100, rows: 24, theme: 'monokai', fit: 'width', preload: true, + cols: 100, rows: 30, theme: 'monokai', fit: 'width', preload: true, poster: 'npt:0:01' });