main.tri (4446B)
1 !import prelude * 2 !import io * 3 !import consumers_module as M 4 !import consumers_link as CL 5 !import consumers_text_summary as T 6 !import source_resolve as Resolve 7 !export * 8 -- From the repository root, after `nix build .#`: 9 -- result/bin/tricu eval demos/consumers/source-linked-summary/main.tri \ 10 -- --store "$(mktemp -d)" --unsafe-io --io --format tree 11 -- Expect `lines: 4` from sample.txt (fourth line has no trailing newline). 12 -- The bootstrap IO command prints a final `t` after the application output. 13 -- Focused fresh-store check: bash test/consumer_source_link_demo.sh result/bin/tricu 14 -- 15 -- countLines.scp counts records with compact naturals using succ.scp; 16 -- entry.scp requests named ReadText and keeps its worker; receiver.scp 17 -- handles success/failure and calls the counter only on success. The four 18 -- authored sources are copied from the separately tested library/client. 19 -- This entrypoint stages their exact source bytes, pins their digests in a 20 -- tricu-owned CAS import descriptor, resolves verified objects, publishes and 21 -- reloads original IR sidecars, then compiles successor and three client workers. 22 -- The effect driver owns file IO. No Python embeds the sources or interprets 23 -- them. The printed hashes identify the import descriptor and IR manifest, 24 -- not an attestation or a packed worker artifact. `run path` accepts another 25 -- file; inputFile selects the direct-entrypoint sample. 26 27 -- This explicit source CAS root is separate from the bootstrap `--store` 28 -- module-import store. A changed source makes a new pinned descriptor; 29 -- previously pinned descriptors keep identifying their original source bytes. 30 sourceStore = "/tmp/tricu-scp-summary-demo.v1" 31 sourceDirectory = "demos/consumers/source-linked-summary/" 32 inputFile = "demos/consumers/source-linked-summary/sample.txt" 33 importRow alias hash name = pair alias (pair hash name) 34 35 -- Filesystem access is limited to initial source staging and the explicit 36 -- ReadText application effect. cmLoad below resolves exclusively from CAS. 37 stage = do onOk_ 38 succSource <- readFile (append sourceDirectory "succ.scp") 39 succHash <- M.cmPutSource sourceStore succSource 40 countSource <- readFile (append sourceDirectory "countLines.scp") 41 countHash <- M.cmPutSource sourceStore countSource 42 entrySource <- readFile (append sourceDirectory "entry.scp") 43 entryHash <- M.cmPutSource sourceStore entrySource 44 receiverSource <- readFile (append sourceDirectory "receiver.scp") 45 receiverHash <- M.cmPutSource sourceStore receiverSource 46 M.cmPutImports sourceStore [ 47 (importRow "successor" succHash "succBinary") 48 (importRow "counter" countHash "countLines") 49 (importRow "entry" entryHash "summaryEntry") 50 (importRow "receiver" receiverHash "summaryReceiver")] 51 52 -- Compile the verified successor first, then inject its executable descriptor 53 -- into the counter's initial state. Both rounds resolve the same pinned source 54 -- descriptor; the initial worker graph is explicit application policy. 55 prepare descriptor = (onResult_ 56 (CL.clPrepare sourceStore descriptor [(pair "successor" t)]) 57 (problem : pure (err problem t)) 58 (prepared : lazyMaybe 59 (_ : pure (err "missing successor" t)) 60 (successor : CL.clPrepare sourceStore descriptor [ 61 (pair "counter" (T.counterState successor)) 62 (pair "entry" t) 63 (pair "receiver" t)]) 64 (Resolve.sourceFindExternal (fst (snd prepared)) "successor"))) 65 lookupWorker workers alias = 66 (lazyMaybe (_ : err (append "missing worker: " alias) t) 67 (worker : ok worker t) (Resolve.sourceFindExternal workers alias)) 68 selectWorkers workers = (bindResult (lookupWorker workers "counter") (counter _ : 69 bindResult (lookupWorker workers "entry") (entry _ : 70 bindResult (lookupWorker workers "receiver") (receiver _ : 71 ok (pair counter (pair entry receiver)) t)))) 72 73 run path = (onOk_ stage (descriptor : onOk_ (prepare descriptor) (prepared : 74 lazyResult 75 (problem _ : pure (err problem t)) 76 (selected _ : bind (T.summaryLexical (fst selected) 77 (fst (snd selected)) (snd (snd selected)) path) 78 (outcome : pure (ok (pair descriptor (pair (fst prepared) outcome)) t))) 79 (selectWorkers (fst (snd prepared)))))) 80 main = io (onResult_ (run inputFile) 81 (problem : putStrLn "source-linked summary failed") 82 (report : do bind 83 _ <- putStrLn (append "imports=" (fst report)) 84 _ <- putStrLn (append "sidecars=" (fst (snd report))) 85 putStrLn (T.render (snd (snd report)))))