From 186ea329c0ecaef7b014567d0d7edeff886e9e44 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 13 May 2026 01:22:51 -0400 Subject: [PATCH 1/7] WIP: Path (a) full-stack omni-emission visceral demo: write dsl/demos/todo_se --- dsl/demos/todo_service.dag | 145 ++++++++++++++++++ .../m1_5_omni_shape_b_openapi_test.rs | 131 ++++++++++++++++ 2 files changed, 276 insertions(+) create mode 100644 dsl/demos/todo_service.dag diff --git a/dsl/demos/todo_service.dag b/dsl/demos/todo_service.dag new file mode 100644 index 00000000000..22f9dc15af2 --- /dev/null +++ b/dsl/demos/todo_service.dag @@ -0,0 +1,145 @@ +// demos/todo_service — minimal TODO domain + REST operation table for omni-emission demos. +// +// Exercises Shape B projections in `omni_shape_b_openapi.rs` (OpenAPI 3.1 YAML, +// Markdown drift-lock, SQL DDL route schema, runnable Rust backend) plus Shape A +// `emit_rust` on one shared `compile_to_dag` result (r3-program-plan §1.8 #25–#28). +// +// Domain carriers are type-authority only; route exposure follows the canonical +// `List<{ endpoint: RestEndpointBinding }>` row shape from `v3.std.services`. + +module demos.todo_service + +import std.types { GET, POST, PUT, PATCH, DELETE, Int, String, Bool } +import std.effects { PathTemplate, LiteralToken, ParamToken } +import v3.std.services { RestEndpointBinding } + +let todo_service_emit_anchor: Int = 0 + +type User { + id: String + display_name: String +} + +type TodoItem { + id: String + list_id: String + title: String + completed: Bool +} + +type TodoList { + id: String + owner_id: String + title: String +} + +type TodoServiceOperation { + endpoint: RestEndpointBinding +} + +data todo_service_operations: List = [ + { + endpoint: { + method: GET, + path: { tokens: [LiteralToken { text: "users" }] } + } + }, + { + endpoint: { + method: POST, + path: { tokens: [LiteralToken { text: "users" }] } + } + }, + { + endpoint: { + method: GET, + path: { + tokens: [LiteralToken { text: "users/" }, ParamToken { name: "userId" }] + } + } + }, + { + endpoint: { + method: PUT, + path: { + tokens: [LiteralToken { text: "users/" }, ParamToken { name: "userId" }] + } + } + }, + { + endpoint: { + method: DELETE, + path: { + tokens: [LiteralToken { text: "users/" }, ParamToken { name: "userId" }] + } + } + }, + { + endpoint: { + method: GET, + path: { + tokens: [ + LiteralToken { text: "users/" }, + ParamToken { name: "userId" }, + LiteralToken { text: "/todos" } + ] + } + } + }, + { + endpoint: { + method: POST, + path: { + tokens: [ + LiteralToken { text: "users/" }, + ParamToken { name: "userId" }, + LiteralToken { text: "/todos" } + ] + } + } + }, + { + endpoint: { + method: GET, + path: { + tokens: [LiteralToken { text: "todos/" }, ParamToken { name: "todoId" }] + } + } + }, + { + endpoint: { + method: PATCH, + path: { + tokens: [LiteralToken { text: "todos/" }, ParamToken { name: "todoId" }] + } + } + }, + { + endpoint: { + method: DELETE, + path: { + tokens: [LiteralToken { text: "todos/" }, ParamToken { name: "todoId" }] + } + } + }, + { + endpoint: { + method: GET, + path: { + tokens: [LiteralToken { text: "lists/" }, ParamToken { name: "listId" }] + } + } + }, + { + endpoint: { + method: POST, + path: { + tokens: [ + LiteralToken { text: "lists/" }, + ParamToken { name: "listId" }, + LiteralToken { text: "/todos" } + ] + } + } + } +] diff --git a/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs b/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs index 230c7de7ee5..5e7178c0988 100644 --- a/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs +++ b/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs @@ -129,6 +129,9 @@ import std.types { Int } let omni_emit_anchor: Int = 0 "#; +const TODO_SERVICE_REPOSITORY_SOURCE: &str = + include_str!("../../../../../dsl/demos/todo_service.dag"); + fn compile_omni_service_fixture() -> v3_compiler::Dag { std::thread::Builder::new() .name("m1_5_openapi_fixture_compile".to_string()) @@ -161,6 +164,87 @@ fn compile_empty_omni_service_fixture() -> v3_compiler::Dag { .expect("larger-stack compile thread completes") } +fn compile_todo_service_repository_fixture() -> v3_compiler::Dag { + std::thread::Builder::new() + .name("m1_5_todo_service_repository_compile".to_string()) + .stack_size(32 * 1024 * 1024) + .spawn(|| { + compile_to_dag( + TODO_SERVICE_REPOSITORY_SOURCE, + "dsl/demos/todo_service.dag", + ) + .expect("repository todo_service.dag demo compiles") + }) + .expect("spawn larger-stack compile thread") + .join() + .expect("larger-stack compile thread completes") +} + +fn expected_todo_service_routes() -> BTreeSet { + BTreeSet::from([ + RestRoute { + method: "DELETE".to_string(), + path: "/todos/{todoId}".to_string(), + path_parameters: vec!["todoId".to_string()], + }, + RestRoute { + method: "DELETE".to_string(), + path: "/users/{userId}".to_string(), + path_parameters: vec!["userId".to_string()], + }, + RestRoute { + method: "GET".to_string(), + path: "/lists/{listId}".to_string(), + path_parameters: vec!["listId".to_string()], + }, + RestRoute { + method: "GET".to_string(), + path: "/todos/{todoId}".to_string(), + path_parameters: vec!["todoId".to_string()], + }, + RestRoute { + method: "GET".to_string(), + path: "/users".to_string(), + path_parameters: vec![], + }, + RestRoute { + method: "GET".to_string(), + path: "/users/{userId}".to_string(), + path_parameters: vec!["userId".to_string()], + }, + RestRoute { + method: "GET".to_string(), + path: "/users/{userId}/todos".to_string(), + path_parameters: vec!["userId".to_string()], + }, + RestRoute { + method: "PATCH".to_string(), + path: "/todos/{todoId}".to_string(), + path_parameters: vec!["todoId".to_string()], + }, + RestRoute { + method: "POST".to_string(), + path: "/lists/{listId}/todos".to_string(), + path_parameters: vec!["listId".to_string()], + }, + RestRoute { + method: "POST".to_string(), + path: "/users".to_string(), + path_parameters: vec![], + }, + RestRoute { + method: "POST".to_string(), + path: "/users/{userId}/todos".to_string(), + path_parameters: vec!["userId".to_string()], + }, + RestRoute { + method: "PUT".to_string(), + path: "/users/{userId}".to_string(), + path_parameters: vec!["userId".to_string()], + }, + ]) +} + fn expected_routes() -> BTreeSet { BTreeSet::from([ RestRoute { @@ -700,3 +784,50 @@ fn openapi_projection_ignores_same_shape_non_service_endpoint_binding() { an OpenAPI route unless its field type is the canonical RestEndpointBinding." ); } + +/// Repository `dsl/demos/todo_service.dag` visceral demo: one `compile_to_dag` feeds the +/// four Shape B projections (OpenAPI YAML, Markdown, SQL DDL, Rust backend) plus Shape A +/// `emit_rust`, matching r3-program-plan §1.8 #25–#28 structural discipline. +#[test] +fn todo_service_repository_demo_omni_layers_share_one_node_tree() { + let mut compile_count = 0usize; + let dag = { + compile_count += 1; + compile_todo_service_repository_fixture() + }; + + let canonical = extract_rest_routes(&dag).expect("canonical route projection extracts"); + assert_eq!(canonical, expected_todo_service_routes()); + + let openapi = project_openapi_yaml(&dag).expect("Shape B OpenAPI projects from shared DAG"); + assert!(openapi.starts_with("openapi: 3.1.0\n")); + assert_eq!(openapi_yaml_routes(&openapi), canonical); + + let markdown = project_markdown_documentation(&dag).expect("Markdown projects from shared DAG"); + assert_eq!(markdown_documentation_routes(&markdown), canonical); + + let ddl = project_sql_ddl_schema(&dag).expect("SQL DDL projects from shared DAG"); + let ddl_routes = sql_ddl_routes(&ddl); + let canonical_without_parameters: BTreeSet<_> = canonical + .iter() + .map(|route| RestRoute { + method: route.method.clone(), + path: route.path.clone(), + path_parameters: vec![], + }) + .collect(); + assert_eq!(ddl_routes, canonical_without_parameters); + assert!(ddl.contains(" CHECK (method IN (")); + assert!(ddl.contains("'DELETE'")); + assert!(ddl.contains("'PATCH'")); + assert!(ddl.contains("'PUT'")); + + let _backend = + project_rust_backend_service(&dag).expect("backend service projects from shared DAG"); + let _rust = emit_rust(&dag).expect("Shape A Rust emit consumes shared DAG"); + + assert_eq!( + compile_count, 1, + "Shape A + Shape B layers must consume the same compile_to_dag result for the repository demo" + ); +} From 7705b84b4ca9ba362e5098411583e7caf08e5c7e Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 13 May 2026 05:23:15 +0000 Subject: [PATCH 2/7] chore: apply cargo fmt (todo_service omni test) Co-authored-by: Cursor --- .../tests/integration/m1_5_omni_shape_b_openapi_test.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs b/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs index 5e7178c0988..cd411416213 100644 --- a/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs +++ b/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs @@ -169,11 +169,8 @@ fn compile_todo_service_repository_fixture() -> v3_compiler::Dag { .name("m1_5_todo_service_repository_compile".to_string()) .stack_size(32 * 1024 * 1024) .spawn(|| { - compile_to_dag( - TODO_SERVICE_REPOSITORY_SOURCE, - "dsl/demos/todo_service.dag", - ) - .expect("repository todo_service.dag demo compiles") + compile_to_dag(TODO_SERVICE_REPOSITORY_SOURCE, "dsl/demos/todo_service.dag") + .expect("repository todo_service.dag demo compiles") }) .expect("spawn larger-stack compile thread") .join() From fd3ec71e8a6b4a0e0cb1b760e03e770888ef210b Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 13 May 2026 01:29:03 -0400 Subject: [PATCH 3/7] WIP: Path (a) full-stack omni-emission visceral demo: write dsl/demos/todo_se --- dsl/demos/todo_service.dag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsl/demos/todo_service.dag b/dsl/demos/todo_service.dag index 22f9dc15af2..744f8e3c97c 100644 --- a/dsl/demos/todo_service.dag +++ b/dsl/demos/todo_service.dag @@ -10,7 +10,7 @@ module demos.todo_service import std.types { GET, POST, PUT, PATCH, DELETE, Int, String, Bool } -import std.effects { PathTemplate, LiteralToken, ParamToken } +import std.effects { LiteralToken, ParamToken } import v3.std.services { RestEndpointBinding } let todo_service_emit_anchor: Int = 0 From 2e78620674f71626316a1bd6b8d7e1faf47a4498 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 13 May 2026 06:04:21 +0000 Subject: [PATCH 4/7] test(omni): use counted compile helper for todo_service demo (parity with gate #28) Co-authored-by: Cursor --- .../integration/m1_5_omni_shape_b_openapi_test.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs b/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs index cd411416213..52151618a4b 100644 --- a/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs +++ b/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs @@ -177,6 +177,11 @@ fn compile_todo_service_repository_fixture() -> v3_compiler::Dag { .expect("larger-stack compile thread completes") } +fn compile_todo_service_repository_fixture_counted(count: &mut usize) -> v3_compiler::Dag { + *count += 1; + compile_todo_service_repository_fixture() +} + fn expected_todo_service_routes() -> BTreeSet { BTreeSet::from([ RestRoute { @@ -788,10 +793,7 @@ fn openapi_projection_ignores_same_shape_non_service_endpoint_binding() { #[test] fn todo_service_repository_demo_omni_layers_share_one_node_tree() { let mut compile_count = 0usize; - let dag = { - compile_count += 1; - compile_todo_service_repository_fixture() - }; + let dag = compile_todo_service_repository_fixture_counted(&mut compile_count); let canonical = extract_rest_routes(&dag).expect("canonical route projection extracts"); assert_eq!(canonical, expected_todo_service_routes()); From 75146e4ff2c683cbaa1ffdade24d3400cf06b455 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 13 May 2026 06:38:50 +0000 Subject: [PATCH 5/7] demo(todo_service): add example data rows so domain types are inhabited Co-authored-by: Cursor --- dsl/demos/todo_service.dag | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/dsl/demos/todo_service.dag b/dsl/demos/todo_service.dag index 744f8e3c97c..20ac21e52f9 100644 --- a/dsl/demos/todo_service.dag +++ b/dsl/demos/todo_service.dag @@ -4,8 +4,9 @@ // Markdown drift-lock, SQL DDL route schema, runnable Rust backend) plus Shape A // `emit_rust` on one shared `compile_to_dag` result (r3-program-plan §1.8 #25–#28). // -// Domain carriers are type-authority only; route exposure follows the canonical -// `List<{ endpoint: RestEndpointBinding }>` row shape from `v3.std.services`. +// Domain carriers are illustrated with small `data` inhabitants (human-facing +// demo context). Omni route extraction still keys only on +// `List<{ endpoint: RestEndpointBinding }>` rows (`v3.std.services`). module demos.todo_service @@ -37,6 +38,24 @@ type TodoServiceOperation { endpoint: RestEndpointBinding } +data todo_domain_example_user: User = { + id: "demo-user", + display_name: "Demo User" +} + +data todo_domain_example_item: TodoItem = { + id: "demo-todo", + list_id: "demo-list", + title: "Wire domain carriers to example rows", + completed: false +} + +data todo_domain_example_list: TodoList = { + id: "demo-list", + owner_id: "demo-user", + title: "Demo backlog" +} + data todo_service_operations: List = [ { endpoint: { From ba37963b4b1e84c87ef2cfe4448584bb743bff67 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 13 May 2026 07:04:05 +0000 Subject: [PATCH 6/7] test(omni): rustc+probe todo_service backend against canonical routes Co-authored-by: Cursor --- .../m1_5_omni_shape_b_openapi_test.rs | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs b/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs index 52151618a4b..e1a6d44c2ea 100644 --- a/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs +++ b/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs @@ -821,8 +821,27 @@ fn todo_service_repository_demo_omni_layers_share_one_node_tree() { assert!(ddl.contains("'PATCH'")); assert!(ddl.contains("'PUT'")); - let _backend = + let backend_source = project_rust_backend_service(&dag).expect("backend service projects from shared DAG"); + let (_tmp_dir, backend_bin) = compile_backend_service(&backend_source); + for route in &canonical { + let concrete_path = route + .path + .replace("{userId}", "42") + .replace("{todoId}", "99") + .replace("{listId}", "7"); + assert_eq!( + backend_probe(&backend_bin, &route.method, &concrete_path), + "200", + "generated backend accepts route {} {}", + route.method, + concrete_path + ); + } + assert_eq!(backend_probe(&backend_bin, "GET", "/missing"), "404"); + assert_eq!(backend_probe(&backend_bin, "DELETE", "/users"), "404"); + assert_eq!(backend_probe(&backend_bin, "GET", "/users/"), "404"); + let _rust = emit_rust(&dag).expect("Shape A Rust emit consumes shared DAG"); assert_eq!( From ce9ea9872b082e8a6316a3ca209d904b236086d0 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 13 May 2026 03:28:49 -0400 Subject: [PATCH 7/7] WIP: Path (a) full-stack omni-emission visceral demo: write dsl/demos/todo_se --- dsl/demos/todo_service.dag | 3 +++ .../tests/integration/m1_5_omni_shape_b_openapi_test.rs | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/dsl/demos/todo_service.dag b/dsl/demos/todo_service.dag index 20ac21e52f9..5694eb809c4 100644 --- a/dsl/demos/todo_service.dag +++ b/dsl/demos/todo_service.dag @@ -14,6 +14,9 @@ import std.types { GET, POST, PUT, PATCH, DELETE, Int, String, Bool } import std.effects { LiteralToken, ParamToken } import v3.std.services { RestEndpointBinding } +// Trivial root `let` so the module is not purely type-level (same cadence as +// `omni_emit_anchor` in `m1_5_omni_shape_b_openapi_test` inline fixtures). Unused by route +// extractors; keeps demo symmetry with other omni Shape B receipts. let todo_service_emit_anchor: Int = 0 type User { diff --git a/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs b/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs index e1a6d44c2ea..7cd818a0dcb 100644 --- a/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs +++ b/src/v3/compiler/tests/integration/m1_5_omni_shape_b_openapi_test.rs @@ -792,6 +792,10 @@ fn openapi_projection_ignores_same_shape_non_service_endpoint_binding() { /// `emit_rust`, matching r3-program-plan §1.8 #25–#28 structural discipline. #[test] fn todo_service_repository_demo_omni_layers_share_one_node_tree() { + // `compile_count` mirrors `omni_layers_share_one_node_tree`: one shared `Dag` is already + // enforced structurally because every projection takes `&dag`. The counter still ratchets + // accidental double acquisition via `compile_*_counted` (e.g. a duplicated helper call + // during edits), matching the §1.8 #28 receipt style in this module. let mut compile_count = 0usize; let dag = compile_todo_service_repository_fixture_counted(&mut compile_count);