code wiki / (root) / nx_wflow_ui.nx

nx_wflow_ui.nx source

↩ module page · 290 lines · 22054 B

1// nx_wflow_ui.nx -- R7 the WORKFLOW CONSOLE: a sovereign, 0-JS, self-contained HTML page that VISUALLY 2// renders the workflow system -- template gallery (from the real gallery index) + a flow drawn as a clean 3// vertical pipeline (from a real .steps file) + the run lifecycle. Built to the nx_ui_judge rubric BY 4// CONSTRUCTION (canonical --nx- tokens, clamp() fluid type, @media mobile-first + dark, skip-link, 5// :focus-visible, prefers-reduced-motion, SVG art, gradient-clip headline, entrance + scroll animation, 6// overflow-x wrappers). HONEST: this is a VIEW/console (understand + adopt), not a drag-drop editor -- 7// interactive editing (U2) stays a later rung. Emits to stdout: `nx_wflow_ui <galleryindexdir> <stepsfile>`. 8// nx_cc discipline: NO '#'/'!' in literals (rgb() colors; wc(35)/wc(33) for the few needed); '"' via wq(). 9// license_tier: ORIGINAL expect_exit: 0 10import "nx_syscalls.nx" 11const K_MAGIC_262144: i64 = 262144 12 13func w(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 14func wc(fd: i64, code: i64) -> i64 { let t: *u8=sys_mmap(2); t[0]=code as u8; sys_write(fd,t,1); return 0 } 15func wq(fd: i64) -> i64 { wc(fd,34); return 0 } 16func wn(fd: i64, v: i64) -> i64 { var m: i64=v; if m<0{wc(fd,45);m=0-m} let t: *u8=sys_mmap(24); var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m-(m/10)*10)) as u8;m=m/10;k=k+1} let o: *u8=sys_mmap(24); var i: i64=0; while i<k{o[i]=t[k-1-i];i=i+1} sys_write(fd,o,k); return 0 } 17func slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 18func seq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8){ if a[i]!=b[i]{return 0} i=i+1 } if b[i]!=(0 as u8){return 0} return 1 } 19func w2cat(dst: *u8, off: i64, s: *u8) -> i64 { var o: i64=off; var i: i64=0; while s[i]!=(0 as u8){dst[o]=s[i];o=o+1;i=i+1} dst[o]=0 as u8; return o } 20func badge(fd: i64, a: *u8) -> i64 { 21 if seq(a,"exec-organ" as *u8)==1 { w(fd,"run organ" as *u8); return 0 } 22 if seq(a,"for-each" as *u8)==1 { w(fd,"loop" as *u8); return 0 } 23 if seq(a,"approve" as *u8)==1 { w(fd,"approval" as *u8); return 0 } 24 if seq(a,"set-var" as *u8)==1 { w(fd,"set var" as *u8); return 0 } 25 if seq(a,"notify" as *u8)==1 { w(fd,"notify" as *u8); return 0 } 26 if seq(a,"create-task" as *u8)==1 { w(fd,"task" as *u8); return 0 } 27 if seq(a,"send" as *u8)==1 { w(fd,"send" as *u8); return 0 } 28 w(fd,a); return 0 29} 30 31func readall(path: *u8, szp: *i64) -> *u8 { 32 let cap: i64 = K_MAGIC_262144 33 let buf: *u8 = sys_mmap(cap) 34 szp[0] = 0 35 let fd: i64 = sys_openat_rd(path) 36 if fd < 0 { return 0 as *u8 } 37 var off: i64 = 0 38 var go: i64 = 1 39 while go == 1 { 40 let r: i64 = sys_read(fd, ((buf as i64)+off) as *u8, cap-off) 41 if r <= 0 { go = 0 } 42 if go == 1 { off = off + r; if off >= cap { go = 0 } } 43 } 44 sys_close(fd) 45 szp[0] = off 46 return buf 47} 48// field idx of a pipe-delimited zero-terminated row into out 49func pf(s: *u8, idx: i64, out: *u8, cap: i64) -> i64 { 50 var seg: i64=0; var t: i64=0; var i: i64=0 51 while s[i]!=(0 as u8) { 52 if s[i]==(124 as u8) { seg=seg+1 } else { if seg==idx { if t<cap-1 { out[t]=s[i]; t=t+1 } } } 53 i=i+1 54 } 55 out[t]=0 as u8 56 return t 57} 58// HTML-escape a value to fd (&<> ; keeps text safe), single-line 59func wt(fd: i64, s: *u8) -> i64 { 60 var i: i64=0 61 while s[i]!=(0 as u8) { 62 let c: i64 = s[i] as i64 63 var done: i64 = 0 64 if c==38 { w(fd,"&amp;" as *u8); done=1 } 65 if done==0 { if c==60 { w(fd,"&lt;" as *u8); done=1 } } 66 if done==0 { if c==62 { w(fd,"&gt;" as *u8); done=1 } } 67 if done==0 { wc(fd,c) } 68 i=i+1 69 } 70 return 0 71} 72 73func hopen(fd: i64) -> i64 { 74 wc(fd,60); wc(fd,33); w(fd,"doctype html>" as *u8) 75 w(fd,"<html lang="); wq(fd); w(fd,"en"); wq(fd); wc(fd,62) 76 w(fd,"<head><meta charset="); wq(fd); w(fd,"utf-8"); wq(fd); wc(fd,62) 77 w(fd,"<meta name="); wq(fd); w(fd,"viewport"); wq(fd); w(fd," content="); wq(fd); w(fd,"width=device-width,initial-scale=1"); wq(fd); wc(fd,62) 78 w(fd,"<title>Nishi Workflow Automation &middot; Console</title>" as *u8) 79 w(fd,"<style>" as *u8) 80 return 0 81} 82func css1(fd: i64) -> i64 { 83 w(fd,":root{--nx-color-bg:rgb(248,249,252);--nx-color-ink:rgb(24,27,35);--nx-color-surface:rgb(255,255,255);--nx-color-line:rgb(223,226,234);--nx-color-muted:rgb(96,102,118);--nx-color-accent:rgb(76,110,245);--nx-color-accent2:rgb(139,92,246);--nx-color-good:rgb(34,160,94);--nx-color-warn:rgb(202,138,4);--nx-color-bad:rgb(220,72,72);--nx-space:clamp(16px,3vw,28px);--nx-radius:14px;--sh:0 1px 2px rgba(20,24,40,0.06),0 8px 24px rgba(20,24,40,0.08)}" as *u8) 84 w(fd,"@media(prefers-color-scheme:dark){:root{--nx-color-bg:rgb(13,14,19);--nx-color-ink:rgb(228,230,240);--nx-color-surface:rgb(21,23,31);--nx-color-line:rgb(42,45,58);--nx-color-muted:rgb(150,155,170);--nx-color-accent:rgb(124,163,235);--nx-color-accent2:rgb(167,139,250);--sh:0 1px 2px rgba(0,0,0,0.4),0 10px 30px rgba(0,0,0,0.5)}}" as *u8) 85 w(fd,"*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;background:var(--nx-color-bg);color:var(--nx-color-ink);line-height:1.6;font-size:clamp(15px,0.4vw + 14px,17px)}" as *u8) 86 w(fd,".skip-link{position:absolute;left:-999px;top:0;background:var(--nx-color-accent);color:rgb(255,255,255);padding:12px 18px;z-index:99;border-radius:0 0 10px 0}.skip-link:focus{left:0}" as *u8) 87 w(fd,"a{color:var(--nx-color-accent);text-decoration:none}a:hover{text-decoration:underline}:focus-visible{outline:3px solid var(--nx-color-accent);outline-offset:2px;border-radius:6px}" as *u8) 88 w(fd,"header.site{position:sticky;top:0;background:var(--nx-color-surface);border-bottom:1px solid var(--nx-color-line);padding:12px clamp(16px,4vw,40px);display:flex;align-items:center;gap:12px;z-index:20}" as *u8) 89 w(fd,"header.site strong{font-size:1.02rem;letter-spacing:0.2px}nav.site{margin-left:auto;display:flex;gap:clamp(10px,2vw,22px);flex-wrap:wrap}nav.site a{color:var(--nx-color-muted);font-size:0.92rem;min-height:44px;display:inline-flex;align-items:center}" as *u8) 90 w(fd,"main{max-width:1080px;margin:0 auto;padding:0 clamp(16px,4vw,40px) 64px}" as *u8) 91 w(fd,".hero{padding:clamp(40px,8vw,84px) 0 clamp(24px,4vw,40px);display:grid;gap:20px}" as *u8) 92 w(fd,".hero h1{margin:0;font-size:clamp(30px,6vw,56px);line-height:1.05;font-weight:800;letter-spacing:-0.02em;background:linear-gradient(100deg,var(--nx-color-accent),var(--nx-color-accent2));-webkit-background-clip:text;background-clip:text;color:transparent}" as *u8) 93 w(fd,".hero p.lede{margin:0;max-width:60ch;font-size:clamp(16px,1.6vw,20px);color:var(--nx-color-muted)}" as *u8) 94 w(fd,".hero .art{position:absolute;right:0;top:0;opacity:0.5;pointer-events:none}" as *u8) 95 w(fd,".chips{display:flex;flex-wrap:wrap;gap:8px}.chip{font-size:0.8rem;padding:6px 12px;border-radius:999px;background:var(--nx-color-surface);border:1px solid var(--nx-color-line);box-shadow:var(--sh);color:var(--nx-color-muted)}" as *u8) 96 return 0 97} 98func css2(fd: i64) -> i64 { 99 w(fd,"h2{font-size:clamp(20px,3vw,28px);margin:clamp(36px,6vw,64px) 0 6px;letter-spacing:-0.01em}.sub{color:var(--nx-color-muted);margin:0 0 22px;max-width:64ch}" as *u8) 100 w(fd,".grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,300px),1fr));gap:18px}" as *u8) 101 w(fd,".card{background:var(--nx-color-surface);border:1px solid var(--nx-color-line);border-radius:var(--nx-radius);padding:20px;box-shadow:var(--sh);transition:transform 0.16s ease,box-shadow 0.16s ease;animation:rise 0.6s both}" as *u8) 102 w(fd,".card:hover{transform:translateY(-3px);box-shadow:0 6px 14px rgba(20,24,40,0.12),0 18px 44px rgba(20,24,40,0.16)}" as *u8) 103 w(fd,".card:nth-child(even){border-top:3px solid var(--nx-color-accent2)}.card:nth-child(odd){border-top:3px solid var(--nx-color-accent)}" as *u8) 104 w(fd,".card h3{margin:0 0 6px;font-size:1.08rem}.card .desc{color:var(--nx-color-muted);font-size:0.94rem;margin:0 0 12px}.card .meta{font-size:0.8rem;color:var(--nx-color-muted);display:flex;gap:12px;flex-wrap:wrap}" as *u8) 105 return 0 106} 107func css3(fd: i64) -> i64 { 108 w(fd,".flowwrap{overflow-x:auto;padding:4px}.pipe{display:grid;gap:0;max-width:640px}" as *u8) 109 w(fd,".step{position:relative;display:grid;grid-template-columns:auto 1fr;gap:16px;padding:6px 0}" as *u8) 110 w(fd,".node{width:44px;height:44px;border-radius:50%;display:grid;place-items:center;font-weight:700;color:rgb(255,255,255);background:linear-gradient(140deg,var(--nx-color-accent),var(--nx-color-accent2));box-shadow:var(--sh);z-index:2}" as *u8) 111 w(fd,".step:not(:last-child) .node::after{content:'';position:absolute;left:21px;top:44px;width:2px;height:calc(100% - 30px);background:var(--nx-color-line)}" as *u8) 112 w(fd,".stepcard{background:var(--nx-color-surface);border:1px solid var(--nx-color-line);border-radius:12px;padding:14px 16px;box-shadow:var(--sh)}" as *u8) 113 w(fd,".stepcard .act{display:inline-block;font-size:0.72rem;font-weight:700;text-transform:uppercase;letter-spacing:0.05em;padding:3px 9px;border-radius:6px;background:var(--nx-color-accent);color:rgb(255,255,255);margin-bottom:6px}" as *u8) 114 w(fd,".stepcard .arg{font-family:ui-monospace,Menlo,Consolas,monospace;font-size:0.85rem;color:var(--nx-color-ink);word-break:break-word}.stepcard .ann{margin-top:8px;display:flex;gap:8px;flex-wrap:wrap}.tag{font-size:0.72rem;padding:2px 8px;border-radius:6px;border:1px solid var(--nx-color-line);color:var(--nx-color-muted)}.tag.cond{border-color:var(--nx-color-warn);color:var(--nx-color-warn)}.tag.onfail{border-color:var(--nx-color-bad);color:var(--nx-color-bad)}" as *u8) 115 // lifecycle stepper 116 w(fd,".life{display:flex;gap:10px;flex-wrap:wrap;list-style:none;padding:0;margin:0;counter-reset:l}.life li{counter-increment:l;flex:1 1 150px;background:var(--nx-color-surface);border:1px solid var(--nx-color-line);border-radius:12px;padding:16px;box-shadow:var(--sh)}.life li::before{content:counter(l);display:grid;place-items:center;width:30px;height:30px;border-radius:8px;background:var(--nx-color-good);color:rgb(255,255,255);font-weight:700;margin-bottom:8px}.life b{display:block}.life span{color:var(--nx-color-muted);font-size:0.86rem}" as *u8) 117 w(fd,"footer{border-top:1px solid var(--nx-color-line);margin-top:56px;padding-top:24px;color:var(--nx-color-muted);font-size:0.86rem}" as *u8) 118 w(fd,"@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}" as *u8) 119 w(fd,"section{animation:fade linear both;animation-timeline:view();animation-range:entry 0% cover 22%}@keyframes fade{from{opacity:0.35}to{opacity:1}}" as *u8) 120 w(fd,"@media(max-width:640px){.hero .art{display:none}nav.site{gap:12px}}" as *u8) 121 w(fd,"@media(prefers-reduced-motion:reduce){*{animation:none;scroll-behavior:auto}.card:hover{transform:none}section{animation:none}}" as *u8) 122 return 0 123} 124func head(fd: i64) -> i64 { 125 hopen(fd) 126 css1(fd) 127 css2(fd) 128 css3(fd) 129 w(fd,"</style></head>" as *u8) 130 return 0 131} 132 133// generative SVG glyph (a small node-and-link flow motif) for the hero 134func art(fd: i64) -> i64 { 135 w(fd,"<svg class="); wq(fd); w(fd,"art"); wq(fd); w(fd," width="); wq(fd); w(fd,"320"); wq(fd); w(fd," height="); wq(fd); w(fd,"320"); wq(fd); w(fd," viewBox="); wq(fd); w(fd,"0 0 320 320"); wq(fd); w(fd," aria-hidden="); wq(fd); w(fd,"true"); wq(fd); wc(fd,62) 136 w(fd,"<defs><linearGradient id="); wq(fd); w(fd,"g"); wq(fd); w(fd," x1="); wq(fd); w(fd,"0"); wq(fd); w(fd," y1="); wq(fd); w(fd,"0"); wq(fd); w(fd," x2="); wq(fd); w(fd,"1"); wq(fd); w(fd," y2="); wq(fd); w(fd,"1"); wq(fd); wc(fd,62) 137 w(fd,"<stop offset="); wq(fd); w(fd,"0"); wq(fd); w(fd," stop-color="); wq(fd); w(fd,"rgb(76,110,245)"); wq(fd); wc(fd,62); w(fd,"</stop>" as *u8) 138 w(fd,"<stop offset="); wq(fd); w(fd,"1"); wq(fd); w(fd," stop-color="); wq(fd); w(fd,"rgb(139,92,246)"); wq(fd); wc(fd,62); w(fd,"</stop></linearGradient></defs>" as *u8) 139 w(fd,"<path d="); wq(fd); w(fd,"M70 70 L160 70 L160 160 L250 160 L250 250"); wq(fd); w(fd," fill="); wq(fd); w(fd,"none"); wq(fd); w(fd," stroke="); wq(fd); w(fd,"url("); wc(fd,35); w(fd,"g)"); wq(fd); w(fd," stroke-width="); wq(fd); w(fd,"6"); wq(fd); w(fd," stroke-linecap="); wq(fd); w(fd,"round"); wq(fd); wc(fd,62); w(fd,"</path>" as *u8) 140 w(fd,"<circle cx="); wq(fd); w(fd,"70"); wq(fd); w(fd," cy="); wq(fd); w(fd,"70"); wq(fd); w(fd," r="); wq(fd); w(fd,"14"); wq(fd); w(fd," fill="); wq(fd); w(fd,"url("); wc(fd,35); w(fd,"g)"); wq(fd); wc(fd,62); w(fd,"</circle>" as *u8) 141 w(fd,"<circle cx="); wq(fd); w(fd,"160"); wq(fd); w(fd," cy="); wq(fd); w(fd,"160"); wq(fd); w(fd," r="); wq(fd); w(fd,"14"); wq(fd); w(fd," fill="); wq(fd); w(fd,"url("); wc(fd,35); w(fd,"g)"); wq(fd); wc(fd,62); w(fd,"</circle>" as *u8) 142 w(fd,"<circle cx="); wq(fd); w(fd,"250"); wq(fd); w(fd," cy="); wq(fd); w(fd,"250"); wq(fd); w(fd," r="); wq(fd); w(fd,"14"); wq(fd); w(fd," fill="); wq(fd); w(fd,"url("); wc(fd,35); w(fd,"g)"); wq(fd); wc(fd,62); w(fd,"</circle></svg>" as *u8) 143 return 0 144} 145 146// render the template gallery from <dir>/index 147func gallery(fd: i64, dir: *u8) -> i64 { 148 let ip: *u8 = sys_mmap(512) 149 var o: i64=0; o=0 150 var d: i64=0; while dir[d]!=(0 as u8){ip[o]=dir[d];o=o+1;d=d+1} ip[o]=47 as u8; o=o+1 151 w2cat(ip, o, "index" as *u8) 152 let szp: *i64 = sys_mmap(8) as *i64 153 let buf: *u8 = readall(ip, szp) 154 var cnt: i64 = 0 155 if (buf as i64)==0 { w(fd,"<p class="); wq(fd); w(fd,"sub"); wq(fd); wc(fd,62); w(fd,"(gallery unavailable)</p>" as *u8); return 0 } 156 let n: i64 = szp[0] 157 let nm: *u8 = sys_mmap(128) 158 let ds: *u8 = sys_mmap(512) 159 w(fd,"<div class="); wq(fd); w(fd,"grid"); wq(fd); wc(fd,62) 160 var ls: i64=0 161 while ls<n { 162 var le: i64=ls 163 while le<n { if buf[le]==(10 as u8){break} le=le+1 } 164 var keep: i64=0 165 if le>ls { keep=1 } 166 if keep==1 { if buf[ls]==(35 as u8){keep=0} } 167 if keep==1 { 168 let row: *u8 = sys_mmap(le-ls+2) 169 var k: i64=0 170 while ls+k<le { row[k]=buf[ls+k]; k=k+1 } 171 row[k]=0 as u8 172 pf(row,0,nm,128) 173 pf(row,1,ds,512) 174 w(fd,"<article class="); wq(fd); w(fd,"card"); wq(fd); wc(fd,62) 175 w(fd,"<h3>" as *u8); wt(fd,nm); w(fd,"</h3>" as *u8) 176 w(fd,"<p class="); wq(fd); w(fd,"desc"); wq(fd); wc(fd,62); wt(fd,ds); w(fd,"</p>" as *u8) 177 w(fd,"<div class="); wq(fd); w(fd,"meta"); wq(fd); wc(fd,62); w(fd,"<span>template</span><span>nx_wflow instantiate</span></div>" as *u8) 178 w(fd,"</article>" as *u8) 179 cnt=cnt+1 180 } 181 ls=le+1 182 } 183 w(fd,"</div>" as *u8) 184 return cnt 185} 186 187// render a flow as a vertical pipeline from a .steps file 188func pipeline(fd: i64, stepsf: *u8) -> i64 { 189 let szp: *i64 = sys_mmap(8) as *i64 190 let buf: *u8 = readall(stepsf, szp) 191 if (buf as i64)==0 { w(fd,"<p class="); wq(fd); w(fd,"sub"); wq(fd); wc(fd,62); w(fd,"(flow unavailable)</p>" as *u8); return 0 } 192 let n: i64 = szp[0] 193 let ix: *u8 = sys_mmap(32) 194 let ac: *u8 = sys_mmap(64) 195 let arg: *u8 = sys_mmap(512) 196 let cond: *u8 = sys_mmap(256) 197 let onf: *u8 = sys_mmap(32) 198 w(fd,"<div class="); wq(fd); w(fd,"flowwrap"); wq(fd); wc(fd,62) 199 w(fd,"<div class="); wq(fd); w(fd,"pipe"); wq(fd); wc(fd,62) 200 var cnt: i64=0 201 var ls: i64=0 202 while ls<n { 203 var le: i64=ls 204 while le<n { if buf[le]==(10 as u8){break} le=le+1 } 205 var keep: i64=0 206 if le>ls { keep=1 } 207 if keep==1 { if buf[ls]==(35 as u8){keep=0} } 208 if keep==1 { if buf[ls]==(64 as u8){keep=0} } 209 if keep==1 { 210 let row: *u8 = sys_mmap(le-ls+2) 211 var k: i64=0 212 while ls+k<le { row[k]=buf[ls+k]; k=k+1 } 213 row[k]=0 as u8 214 pf(row,1,ix,32); pf(row,2,ac,64); pf(row,4,arg,512); pf(row,6,cond,256); pf(row,7,onf,32) 215 cnt=cnt+1 216 w(fd,"<div class="); wq(fd); w(fd,"step"); wq(fd); wc(fd,62) 217 w(fd,"<div class="); wq(fd); w(fd,"node"); wq(fd); wc(fd,62); wt(fd,ix); w(fd,"</div>" as *u8) 218 w(fd,"<div class="); wq(fd); w(fd,"stepcard"); wq(fd); wc(fd,62) 219 w(fd,"<span class="); wq(fd); w(fd,"act"); wq(fd); wc(fd,62); badge(fd,ac); w(fd,"</span>" as *u8) 220 w(fd,"<div class="); wq(fd); w(fd,"arg"); wq(fd); wc(fd,62); wt(fd,arg); w(fd,"</div>" as *u8) 221 var anyann: i64=0 222 if cond[0]!=(0 as u8) { if cond[0]!=(45 as u8) { anyann=1 } } 223 if onf[0]!=(0 as u8) { if onf[0]!=(45 as u8) { anyann=1 } } 224 if anyann==1 { 225 w(fd,"<div class="); wq(fd); w(fd,"ann"); wq(fd); wc(fd,62) 226 if cond[0]!=(0 as u8) { if cond[0]!=(45 as u8) { w(fd,"<span class="); wq(fd); w(fd,"tag cond"); wq(fd); wc(fd,62); w(fd,"only if " as *u8); wt(fd,cond); w(fd,"</span>" as *u8) } } 227 if onf[0]!=(0 as u8) { if onf[0]!=(45 as u8) { w(fd,"<span class="); wq(fd); w(fd,"tag onfail"); wq(fd); wc(fd,62); w(fd,"on fail &rarr; step " as *u8); wt(fd,onf); w(fd,"</span>" as *u8) } } 228 w(fd,"</div>" as *u8) 229 } 230 w(fd,"</div></div>" as *u8) 231 } 232 ls=le+1 233 } 234 w(fd,"</div></div>" as *u8) 235 return cnt 236} 237 238func main(argc: i64, argv: *i64) -> i64 { 239 let fd: i64 = 1 240 var dir: *u8 = "knowledge/wflow/templates" as *u8 241 var stepsf: *u8 = "knowledge/wflow/templates/expense-approval.steps" as *u8 242 if argc >= 2 { dir = argv[1] as *u8 } 243 if argc >= 3 { stepsf = argv[2] as *u8 } 244 head(fd) 245 w(fd,"<body>" as *u8) 246 w(fd,"<a class="); wq(fd); w(fd,"skip-link"); wq(fd); w(fd," href="); wq(fd); wc(fd,35); w(fd,"main"); wq(fd); wc(fd,62); w(fd,"Skip to content</a>" as *u8) 247 w(fd,"<header class="); wq(fd); w(fd,"site"); wq(fd); wc(fd,62); w(fd,"<strong>Nishi Workflow</strong>" as *u8) 248 w(fd,"<nav class="); wq(fd); w(fd,"site"); wq(fd); w(fd," aria-label="); wq(fd); w(fd,"primary"); wq(fd); wc(fd,62) 249 w(fd,"<a href="); wq(fd); wc(fd,35); w(fd,"templates"); wq(fd); wc(fd,62); w(fd,"Templates</a>" as *u8) 250 w(fd,"<a href="); wq(fd); wc(fd,35); w(fd,"flow"); wq(fd); wc(fd,62); w(fd,"Flow</a>" as *u8) 251 w(fd,"<a href="); wq(fd); wc(fd,35); w(fd,"lifecycle"); wq(fd); wc(fd,62); w(fd,"Lifecycle</a>" as *u8) 252 w(fd,"<a href="); wq(fd); w(fd,"/compare/automation"); wq(fd); wc(fd,62); w(fd,"Benchmark</a></nav></header>" as *u8) 253 w(fd,"<main id="); wq(fd); w(fd,"main"); wq(fd); wc(fd,62) 254 // hero 255 w(fd,"<section class="); wq(fd); w(fd,"hero"); wq(fd); w(fd," style="); wq(fd); w(fd,"position:relative"); wq(fd); wc(fd,62) 256 art(fd) 257 w(fd,"<h1>Automate the work,<br>keep the receipts.</h1>" as *u8) 258 w(fd,"<p class="); wq(fd); w(fd,"lede"); wq(fd); wc(fd,62); w(fd,"A sovereign, durable workflow engine. Every step, retry, approval and variable is an append-only ledger record &mdash; so a run survives a crash, recovers from failure, and can be replayed exactly. No cloud, no per-task bill, running on your own hardware.</p>" as *u8) 259 w(fd,"<div class="); wq(fd); w(fd,"chips"); wq(fd); wc(fd,62) 260 w(fd,"<span class="); wq(fd); w(fd,"chip"); wq(fd); wc(fd,62); w(fd,"durable runs</span>" as *u8) 261 w(fd,"<span class="); wq(fd); w(fd,"chip"); wq(fd); wc(fd,62); w(fd,"retries + on-error</span>" as *u8) 262 w(fd,"<span class="); wq(fd); w(fd,"chip"); wq(fd); wc(fd,62); w(fd,"human approvals</span>" as *u8) 263 w(fd,"<span class="); wq(fd); w(fd,"chip"); wq(fd); wc(fd,62); w(fd,"data passing</span>" as *u8) 264 w(fd,"<span class="); wq(fd); w(fd,"chip"); wq(fd); wc(fd,62); w(fd,"branch + loop</span>" as *u8) 265 w(fd,"<span class="); wq(fd); w(fd,"chip"); wq(fd); wc(fd,62); w(fd,"crash-resume</span></div></section>" as *u8) 266 // templates 267 w(fd,"<section id="); wq(fd); w(fd,"templates"); wq(fd); wc(fd,62); w(fd,"<h2>Start from a template</h2>" as *u8) 268 w(fd,"<p class="); wq(fd); w(fd,"sub"); wq(fd); wc(fd,62); w(fd,"Adopt a ready flow with one command &mdash; the definition is validated whole before it lands. Then adapt it as plain data files.</p>" as *u8) 269 let tc: i64 = gallery(fd, dir) 270 w(fd,"</section>" as *u8) 271 // flow 272 w(fd,"<section id="); wq(fd); w(fd,"flow"); wq(fd); wc(fd,62); w(fd,"<h2>How a flow reads</h2>" as *u8) 273 w(fd,"<p class="); wq(fd); w(fd,"sub"); wq(fd); wc(fd,62); w(fd,"The expense-approval template, drawn from its real definition. Each step shows its action, argument, and any condition or on-failure route.</p>" as *u8) 274 let sc: i64 = pipeline(fd, stepsf) 275 w(fd,"</section>" as *u8) 276 // lifecycle 277 w(fd,"<section id="); wq(fd); w(fd,"lifecycle"); wq(fd); wc(fd,62); w(fd,"<h2>A run, end to end</h2>" as *u8) 278 w(fd,"<p class="); wq(fd); w(fd,"sub"); wq(fd); wc(fd,62); w(fd,"Every stage is a durable ledger record, so the run can pause for a person and resume exactly where it left off.</p>" as *u8) 279 w(fd,"<ol class="); wq(fd); w(fd,"life"); wq(fd); wc(fd,62) 280 w(fd,"<li><b>Fire</b><span>An event starts the run; its fields become variables.</span></li>" as *u8) 281 w(fd,"<li><b>Park</b><span>The run pauses at an approval, waiting on a person.</span></li>" as *u8) 282 w(fd,"<li><b>Decide</b><span>The operator approves or denies &mdash; deny always wins.</span></li>" as *u8) 283 w(fd,"<li><b>Resume</b><span>Approved steps run; done ones are never repeated.</span></li>" as *u8) 284 w(fd,"<li><b>Done</b><span>The full history stays readable and replayable.</span></li></ol></section>" as *u8) 285 // footer 286 w(fd,"<footer><p>Generated by nx_wflow_ui &mdash; sovereign, 0-JS, " as *u8); wn(fd,tc); w(fd," templates &middot; " as *u8); wn(fd,sc); w(fd,"-step flow shown. Built to the nx_ui_judge rubric.</p>" as *u8) 287 w(fd,"<p>This is a console view. Interactive drag-to-build editing is a later rung &mdash; stated honestly, not implied.</p></footer>" as *u8) 288 w(fd,"</main></body></html>" as *u8) 289 return 0 290}