[{"data":1,"prerenderedAt":2313},["ShallowReactive",2],{"navigation_docs":3,"-cli-ci":500,"-cli-ci-surround":2308},[4,30,80,118,283,415,470],{"title":5,"path":6,"stem":7,"children":8,"page":29},"Start","\u002Fstart","1.start",[9,14,19,24],{"title":10,"path":11,"stem":12,"icon":13},"Introduction","\u002Fstart\u002Fintroduction","1.start\u002F1.introduction","i-lucide-info",{"title":15,"path":16,"stem":17,"icon":18},"Why start with evlog","\u002Fstart\u002Fwhy-evlog","1.start\u002F2.why-evlog","i-lucide-rocket",{"title":20,"path":21,"stem":22,"icon":23},"Installation","\u002Fstart\u002Finstallation","1.start\u002F3.installation","i-lucide-download",{"title":25,"path":26,"stem":27,"icon":28},"Quick Start","\u002Fstart\u002Fquick-start","1.start\u002F4.quick-start","i-lucide-zap",false,{"title":31,"path":32,"stem":33,"children":34,"page":29},"Learn","\u002Flearn","2.learn",[35,40,45,50,55,60,65,70,75],{"title":36,"path":37,"stem":38,"icon":39},"Overview","\u002Flearn\u002Foverview","2.learn\u002F0.overview","i-lucide-list",{"title":41,"path":42,"stem":43,"icon":44},"Simple Logging","\u002Flearn\u002Fsimple-logging","2.learn\u002F1.simple-logging","i-lucide-terminal",{"title":46,"path":47,"stem":48,"icon":49},"Wide Events","\u002Flearn\u002Fwide-events","2.learn\u002F2.wide-events","i-lucide-layers",{"title":51,"path":52,"stem":53,"icon":54},"Structured Errors","\u002Flearn\u002Fstructured-errors","2.learn\u002F3.structured-errors","i-lucide-shield-alert",{"title":56,"path":57,"stem":58,"icon":59},"Lifecycle","\u002Flearn\u002Flifecycle","2.learn\u002F4.lifecycle","i-lucide-arrow-right-left",{"title":61,"path":62,"stem":63,"icon":64},"Sampling","\u002Flearn\u002Fsampling","2.learn\u002F5.sampling","i-lucide-filter",{"title":66,"path":67,"stem":68,"icon":69},"Auto-Redaction","\u002Flearn\u002Fredaction","2.learn\u002F6.redaction","i-lucide-eye-off",{"title":71,"path":72,"stem":73,"icon":74},"Typed Fields","\u002Flearn\u002Ftyped-fields","2.learn\u002F7.typed-fields","i-simple-icons-typescript",{"title":76,"path":77,"stem":78,"icon":79},"Catalogs","\u002Flearn\u002Fcatalogs","2.learn\u002F8.catalogs","i-lucide-book-open",{"title":81,"path":82,"stem":83,"children":84,"page":29},"CLI","\u002Fcli","3.cli",[85,88,93,98,103,108,113],{"title":36,"path":86,"stem":87,"icon":44},"\u002Fcli\u002Foverview","3.cli\u002F0.overview",{"title":89,"path":90,"stem":91,"icon":92},"map","\u002Fcli\u002Fmap","3.cli\u002F1.map","i-lucide-radar",{"title":94,"path":95,"stem":96,"icon":97},"Rules","\u002Fcli\u002Frules","3.cli\u002F2.rules","i-lucide-list-checks",{"title":99,"path":100,"stem":101,"icon":102},"Scoring","\u002Fcli\u002Fscoring","3.cli\u002F3.scoring","i-lucide-gauge",{"title":104,"path":105,"stem":106,"icon":107},"CI","\u002Fcli\u002Fci","3.cli\u002F4.ci","i-lucide-git-pull-request",{"title":109,"path":110,"stem":111,"icon":112},"doctor","\u002Fcli\u002Fdoctor","3.cli\u002F5.doctor","i-lucide-stethoscope",{"title":114,"path":115,"stem":116,"icon":117},"telemetry","\u002Fcli\u002Ftelemetry","3.cli\u002F6.telemetry","i-lucide-bar-chart-3",{"title":119,"path":120,"stem":121,"children":122,"page":29},"Integrate","\u002Fintegrate","4.integrate",[123,127,195],{"title":36,"path":124,"stem":125,"icon":126},"\u002Fintegrate\u002Foverview","4.integrate\u002F0.overview","i-lucide-plug",{"title":128,"path":129,"stem":130,"children":131,"page":29},"Adapters","\u002Fintegrate\u002Fadapters","4.integrate\u002Fadapters",[132,135,175],{"title":36,"path":133,"stem":134,"icon":39},"\u002Fintegrate\u002Fadapters\u002Foverview","4.integrate\u002Fadapters\u002F01.overview",{"title":136,"path":137,"stem":138,"children":139,"page":29},"Cloud","\u002Fintegrate\u002Fadapters\u002Fcloud","4.integrate\u002Fadapters\u002Fcloud",[140,145,150,155,160,165,170],{"title":141,"path":142,"stem":143,"icon":144},"Axiom","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Faxiom","4.integrate\u002Fadapters\u002Fcloud\u002F01.axiom","i-custom-axiom",{"title":146,"path":147,"stem":148,"icon":149},"OTLP","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fotlp","4.integrate\u002Fadapters\u002Fcloud\u002F02.otlp","i-simple-icons-opentelemetry",{"title":151,"path":152,"stem":153,"icon":154},"PostHog","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fposthog","4.integrate\u002Fadapters\u002Fcloud\u002F03.posthog","i-simple-icons-posthog",{"title":156,"path":157,"stem":158,"icon":159},"Sentry","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fsentry","4.integrate\u002Fadapters\u002Fcloud\u002F04.sentry","i-simple-icons-sentry",{"title":161,"path":162,"stem":163,"icon":164},"Better Stack","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fbetter-stack","4.integrate\u002Fadapters\u002Fcloud\u002F05.better-stack","i-simple-icons-betterstack",{"title":166,"path":167,"stem":168,"icon":169},"Datadog","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fdatadog","4.integrate\u002Fadapters\u002Fcloud\u002F06.datadog","i-simple-icons-datadog",{"title":171,"path":172,"stem":173,"icon":174},"HyperDX","\u002Fintegrate\u002Fadapters\u002Fcloud\u002Fhyperdx","4.integrate\u002Fadapters\u002Fcloud\u002F07.hyperdx","i-custom-hyperdx",{"title":176,"path":177,"stem":178,"children":179,"page":29},"Self-Hosted","\u002Fintegrate\u002Fadapters\u002Fself-hosted","4.integrate\u002Fadapters\u002Fself-hosted",[180,185,190],{"title":181,"path":182,"stem":183,"icon":184},"File System","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Ffs","4.integrate\u002Fadapters\u002Fself-hosted\u002F01.fs","i-lucide-hard-drive",{"title":186,"path":187,"stem":188,"icon":189},"NuxtHub","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Fnuxthub","4.integrate\u002Fadapters\u002Fself-hosted\u002F02.nuxthub","i-simple-icons-nuxt",{"title":191,"path":192,"stem":193,"icon":194},"Memory","\u002Fintegrate\u002Fadapters\u002Fself-hosted\u002Fmemory","4.integrate\u002Fadapters\u002Fself-hosted\u002F03.memory","i-lucide-cpu",{"title":196,"path":197,"stem":198,"children":199,"page":29},"Frameworks","\u002Fintegrate\u002Fframeworks","4.integrate\u002Fframeworks",[200,204,209,214,219,224,229,234,239,244,249,254,259,264,268,273,278],{"title":36,"path":201,"stem":202,"icon":203},"\u002Fintegrate\u002Fframeworks\u002Foverview","4.integrate\u002Fframeworks\u002F00.overview","i-lucide-layout-grid",{"title":205,"path":206,"stem":207,"icon":208},"Nuxt","\u002Fintegrate\u002Fframeworks\u002Fnuxt","4.integrate\u002Fframeworks\u002F01.nuxt","i-simple-icons-nuxtdotjs",{"title":210,"path":211,"stem":212,"icon":213},"Next.js","\u002Fintegrate\u002Fframeworks\u002Fnextjs","4.integrate\u002Fframeworks\u002F02.nextjs","i-simple-icons-nextdotjs",{"title":215,"path":216,"stem":217,"icon":218},"SvelteKit","\u002Fintegrate\u002Fframeworks\u002Fsveltekit","4.integrate\u002Fframeworks\u002F03.sveltekit","i-simple-icons-svelte",{"title":220,"path":221,"stem":222,"icon":223},"Nitro","\u002Fintegrate\u002Fframeworks\u002Fnitro","4.integrate\u002Fframeworks\u002F04.nitro","i-custom-nitro",{"title":225,"path":226,"stem":227,"icon":228},"TanStack Start","\u002Fintegrate\u002Fframeworks\u002Ftanstack-start","4.integrate\u002Fframeworks\u002F05.tanstack-start","i-custom-tanstack",{"title":230,"path":231,"stem":232,"icon":233},"NestJS","\u002Fintegrate\u002Fframeworks\u002Fnestjs","4.integrate\u002Fframeworks\u002F06.nestjs","i-simple-icons-nestjs",{"title":235,"path":236,"stem":237,"icon":238},"Express","\u002Fintegrate\u002Fframeworks\u002Fexpress","4.integrate\u002Fframeworks\u002F07.express","i-simple-icons-express",{"title":240,"path":241,"stem":242,"icon":243},"Hono","\u002Fintegrate\u002Fframeworks\u002Fhono","4.integrate\u002Fframeworks\u002F08.hono","i-simple-icons-hono",{"title":245,"path":246,"stem":247,"icon":248},"Fastify","\u002Fintegrate\u002Fframeworks\u002Ffastify","4.integrate\u002Fframeworks\u002F09.fastify","i-simple-icons-fastify",{"title":250,"path":251,"stem":252,"icon":253},"Elysia","\u002Fintegrate\u002Fframeworks\u002Felysia","4.integrate\u002Fframeworks\u002F10.elysia","i-custom-elysia",{"title":255,"path":256,"stem":257,"icon":258},"React Router","\u002Fintegrate\u002Fframeworks\u002Freact-router","4.integrate\u002Fframeworks\u002F11.react-router","i-custom-reactrouter",{"title":260,"path":261,"stem":262,"icon":263},"Cloudflare Workers","\u002Fintegrate\u002Fframeworks\u002Fcloudflare-workers","4.integrate\u002Fframeworks\u002F12.cloudflare-workers","i-simple-icons-cloudflare",{"title":265,"path":266,"stem":267,"icon":74},"Standalone","\u002Fintegrate\u002Fframeworks\u002Fstandalone","4.integrate\u002Fframeworks\u002F13.standalone",{"title":269,"path":270,"stem":271,"icon":272},"Astro","\u002Fintegrate\u002Fframeworks\u002Fastro","4.integrate\u002Fframeworks\u002F14.astro","i-simple-icons-astro",{"title":274,"path":275,"stem":276,"icon":277},"oRPC","\u002Fintegrate\u002Fframeworks\u002Forpc","4.integrate\u002Fframeworks\u002F15.orpc","i-lucide-network",{"title":279,"path":280,"stem":281,"icon":282},"AWS Lambda","\u002Fintegrate\u002Fframeworks\u002Faws-lambda","4.integrate\u002Fframeworks\u002F16.aws-lambda","i-custom-lambda",{"title":284,"path":285,"stem":286,"children":287,"page":29},"Use Cases","\u002Fuse-cases","5.use-cases",[288,291,296,325,352,384,405,410],{"title":36,"path":289,"stem":290,"icon":97},"\u002Fuse-cases\u002Foverview","5.use-cases\u002F0.overview",{"title":292,"path":293,"stem":294,"icon":295},"Client Logging","\u002Fuse-cases\u002Fclient-logging","5.use-cases\u002F1.client-logging","i-lucide-monitor",{"title":297,"icon":298,"path":299,"stem":300,"children":301,"page":29},"AI SDK","i-simple-icons-vercel","\u002Fuse-cases\u002Fai-sdk","5.use-cases\u002F2.ai-sdk",[302,305,310,315,320],{"title":36,"path":303,"stem":304,"icon":39},"\u002Fuse-cases\u002Fai-sdk\u002Foverview","5.use-cases\u002F2.ai-sdk\u002F01.overview",{"title":306,"path":307,"stem":308,"icon":309},"Usage","\u002Fuse-cases\u002Fai-sdk\u002Fusage","5.use-cases\u002F2.ai-sdk\u002F02.usage","i-lucide-code",{"title":311,"path":312,"stem":313,"icon":314},"Options","\u002Fuse-cases\u002Fai-sdk\u002Foptions","5.use-cases\u002F2.ai-sdk\u002F03.options","i-lucide-sliders",{"title":316,"path":317,"stem":318,"icon":319},"Metadata","\u002Fuse-cases\u002Fai-sdk\u002Fmetadata","5.use-cases\u002F2.ai-sdk\u002F04.metadata","i-lucide-database",{"title":321,"path":322,"stem":323,"icon":324},"Telemetry","\u002Fuse-cases\u002Fai-sdk\u002Ftelemetry","5.use-cases\u002F2.ai-sdk\u002F05.telemetry","i-lucide-activity",{"title":326,"icon":327,"path":328,"stem":329,"children":330,"page":29},"Better Auth","i-simple-icons-betterauth","\u002Fuse-cases\u002Fbetter-auth","5.use-cases\u002F3.better-auth",[331,334,339,344,348],{"title":36,"path":332,"stem":333,"icon":39},"\u002Fuse-cases\u002Fbetter-auth\u002Foverview","5.use-cases\u002F3.better-auth\u002F01.overview",{"title":335,"path":336,"stem":337,"icon":338},"Identify User","\u002Fuse-cases\u002Fbetter-auth\u002Fidentify-user","5.use-cases\u002F3.better-auth\u002F02.identify-user","i-lucide-user-check",{"title":340,"path":341,"stem":342,"icon":343},"Middleware","\u002Fuse-cases\u002Fbetter-auth\u002Fmiddleware","5.use-cases\u002F3.better-auth\u002F03.middleware","i-lucide-shield",{"title":345,"path":346,"stem":347,"icon":295},"Client Sync","\u002Fuse-cases\u002Fbetter-auth\u002Fclient-sync","5.use-cases\u002F3.better-auth\u002F04.client-sync",{"title":349,"path":350,"stem":351,"icon":102},"Performance","\u002Fuse-cases\u002Fbetter-auth\u002Fperformance","5.use-cases\u002F3.better-auth\u002F05.performance",{"title":353,"icon":354,"path":355,"stem":356,"children":357,"page":29},"Audit Logs","i-lucide-shield-check","\u002Fuse-cases\u002Faudit","5.use-cases\u002F4.audit",[358,361,366,371,376,380],{"title":36,"path":359,"stem":360,"icon":39},"\u002Fuse-cases\u002Faudit\u002Foverview","5.use-cases\u002F4.audit\u002F01.overview",{"title":362,"path":363,"stem":364,"icon":365},"Schema","\u002Fuse-cases\u002Faudit\u002Fschema","5.use-cases\u002F4.audit\u002F02.schema","i-lucide-file-text",{"title":367,"path":368,"stem":369,"icon":370},"Recording","\u002Fuse-cases\u002Faudit\u002Frecording","5.use-cases\u002F4.audit\u002F03.recording","i-lucide-pen-line",{"title":372,"path":373,"stem":374,"icon":375},"Drains","\u002Fuse-cases\u002Faudit\u002Fpipeline","5.use-cases\u002F4.audit\u002F04.pipeline","i-lucide-link",{"title":377,"path":378,"stem":379,"icon":354},"Compliance","\u002Fuse-cases\u002Faudit\u002Fcompliance","5.use-cases\u002F4.audit\u002F05.compliance",{"title":381,"path":382,"stem":383,"icon":79},"Recipes","\u002Fuse-cases\u002Faudit\u002Frecipes","5.use-cases\u002F4.audit\u002F06.recipes",{"title":321,"icon":102,"path":385,"stem":386,"children":387,"page":29},"\u002Fuse-cases\u002Ftelemetry","5.use-cases\u002F4.telemetry",[388,391,396,401],{"title":36,"path":389,"stem":390,"icon":39},"\u002Fuse-cases\u002Ftelemetry\u002Foverview","5.use-cases\u002F4.telemetry\u002F01.overview",{"title":392,"path":393,"stem":394,"icon":395},"Setup","\u002Fuse-cases\u002Ftelemetry\u002Fsetup","5.use-cases\u002F4.telemetry\u002F02.setup","i-lucide-wrench",{"title":397,"path":398,"stem":399,"icon":400},"Ingest","\u002Fuse-cases\u002Ftelemetry\u002Fingest","5.use-cases\u002F4.telemetry\u002F03.ingest","i-lucide-server",{"title":402,"path":403,"stem":404,"icon":79},"Reference","\u002Fuse-cases\u002Ftelemetry\u002Freference","5.use-cases\u002F4.telemetry\u002F04.reference",{"title":406,"path":407,"stem":408,"icon":409},"Enrichers","\u002Fuse-cases\u002Fenrichers","5.use-cases\u002F5.enrichers","i-lucide-sparkles",{"title":411,"path":412,"stem":413,"icon":414},"eve","\u002Fuse-cases\u002Feve","5.use-cases\u002F5.eve","i-custom-eve",{"title":416,"path":417,"stem":418,"children":419,"page":29},"Extend","\u002Fextend","6.extend",[420,424,429,434,439,443,447,451,455,460,465],{"title":36,"path":421,"stem":422,"icon":423},"\u002Fextend\u002Foverview","6.extend\u002F0.overview","i-lucide-blocks",{"title":425,"path":426,"stem":427,"icon":428},"Stream","\u002Fextend\u002Fstream","6.extend\u002F1.stream","i-lucide-radio-tower",{"title":430,"path":431,"stem":432,"icon":433},"Custom framework","\u002Fextend\u002Fcustom-framework","6.extend\u002F10.custom-framework","i-lucide-puzzle",{"title":435,"path":436,"stem":437,"icon":438},"FS reader","\u002Fextend\u002Ffs-reader","6.extend\u002F2.fs-reader","i-lucide-folder-search",{"title":381,"path":440,"stem":441,"icon":442},"\u002Fextend\u002Fconsumer-recipes","6.extend\u002F3.consumer-recipes","i-lucide-chef-hat",{"title":444,"path":445,"stem":446,"icon":423},"Plugins","\u002Fextend\u002Fplugins","6.extend\u002F4.plugins",{"title":448,"path":449,"stem":450,"icon":409},"Custom enrichers","\u002Fextend\u002Fcustom-enrichers","6.extend\u002F5.custom-enrichers",{"title":452,"path":453,"stem":454,"icon":64},"Tail sampling","\u002Fextend\u002Ftail-sampling","6.extend\u002F6.tail-sampling",{"title":456,"path":457,"stem":458,"icon":459},"Identity headers","\u002Fextend\u002Fidentity-headers","6.extend\u002F7.identity-headers","i-lucide-fingerprint",{"title":461,"path":462,"stem":463,"icon":464},"Custom drains","\u002Fextend\u002Fcustom-drains","6.extend\u002F8.custom-drains","i-lucide-share-2",{"title":466,"path":467,"stem":468,"icon":469},"Drain pipeline","\u002Fextend\u002Fdrain-pipeline","6.extend\u002F9.drain-pipeline","i-lucide-workflow",{"title":402,"path":471,"stem":472,"children":473,"page":29},"\u002Freference","7.reference",[474,479,482,487,491,496],{"title":475,"path":476,"stem":477,"icon":478},"Configuration","\u002Freference\u002Fconfiguration","7.reference\u002F1.configuration","i-lucide-settings",{"title":349,"path":480,"stem":481,"icon":102},"\u002Freference\u002Fperformance","7.reference\u002F2.performance",{"title":483,"path":484,"stem":485,"icon":486},"Vite Plugin","\u002Freference\u002Fvite-plugin","7.reference\u002F3.vite-plugin","i-custom-vite",{"title":488,"path":489,"stem":490,"icon":354},"Best Practices","\u002Freference\u002Fbest-practices","7.reference\u002F4.best-practices",{"title":492,"path":493,"stem":494,"icon":495},"vs Other Loggers","\u002Freference\u002Fvs-other-loggers","7.reference\u002F5.vs-other-loggers","i-lucide-scale",{"title":497,"path":498,"stem":499,"icon":409},"Agent Skills","\u002Freference\u002Fagent-skills","7.reference\u002F6.agent-skills",{"id":501,"title":502,"body":503,"description":2298,"extension":2299,"links":2300,"meta":2304,"navigation":2305,"path":105,"seo":2306,"stem":106,"__hash__":2307},"docs\u002F3.cli\u002F4.ci.md","evlog map in CI",{"type":504,"value":505,"toc":2284},"minimark",[506,510,515,522,552,561,568,571,574,577,580,590,594,651,667,671,810,820,825,828,831,850,877,880,884,887,925,932,936,942,963,1251,1267,1776,1784,1801,1916,1922,1925,2107,2111,2123,2133,2139,2143,2149,2259,2262,2266,2280],[507,508,509],"p",{},"A score you look at once is a nice afternoon. A score in CI is what stops the next handler from shipping dark.",[511,512,514],"h2",{"id":513},"the-gate","The gate",[507,516,517,521],{},[518,519,520],"code",{},"--min-score \u003Cn>"," prints an explicit verdict and exits 1 when the project is below the threshold:",[523,524,530],"pre",{"className":525,"code":526,"filename":527,"language":528,"meta":529,"style":529},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","evlog map --min-score 80\n","Terminal","bash","",[518,531,532],{"__ignoreMap":529},[533,534,537,541,545,548],"span",{"class":535,"line":536},"line",1,[533,538,540],{"class":539},"sBMFI","evlog",[533,542,544],{"class":543},"sfazB"," map",[533,546,547],{"class":543}," --min-score",[533,549,551],{"class":550},"sbssI"," 80\n",[523,553,559],{"className":554,"code":556,"filename":557,"language":558,"meta":529},[555],"language-text"," GATE  score 76 is below --min-score 90 — exit code 1\nfix what is listed under FIX FIRST to pass · evlog.dev\u002Fcli\u002Fci\n","Below the threshold","text",[518,560,556],{"__ignoreMap":529},[523,562,566],{"className":563,"code":564,"filename":565,"language":558,"meta":529},[555]," GATE  score 76 meets --min-score 70 — exit code 0\n","At or above it",[518,567,564],{"__ignoreMap":529},[507,569,570],{},"The full report is printed either way, so a failed job tells you what to fix without a second run.",[507,572,573],{},"The threshold has to be a whole number between 0 and 100. Anything else — a typo, a stray unit, an unexpanded shell variable — stops the command rather than being read as \"no gate\", because a gate that quietly disables itself reports success for a bar nobody checked.",[507,575,576],{},"Which turns the score into something a pull request can move. One run says the app is short of the bar and names the three entry points responsible, the next one says it is over:",[578,579],"map-pr-gate",{},[581,582,584,589],"callout",{"color":583,"icon":354},"neutral",[585,586,588],"a",{"href":587},"\u002Fcli\u002Frules#opportunities","Opportunities"," never affect the score, so a gate can never fail because the CLI suggested you adopt a feature. Only requirements can fail a build.",[511,591,593],{"id":592},"exit-codes","Exit codes",[595,596,597,610],"table",{},[598,599,600],"thead",{},[601,602,603,607],"tr",{},[604,605,606],"th",{},"Code",[604,608,609],{},"Meaning",[611,612,613,624,638],"tbody",{},[601,614,615,621],{},[616,617,618],"td",{},[518,619,620],{},"0",[616,622,623],{},"Score met the threshold, or no threshold was given",[601,625,626,631],{},[616,627,628],{},[518,629,630],{},"1",[616,632,633,634,637],{},"Score below ",[518,635,636],{},"--min-score",", or the scan could not run",[601,639,640,645],{},[616,641,642],{},[518,643,644],{},"2",[616,646,647,648],{},"Usage error — unknown flag, or an invalid ",[518,649,650],{},"--framework",[652,653,654,655,658,659,662,663,666],"warning",{},"A pipe replaces ",[518,656,657],{},"$?"," with the exit code of the last command in it, so ",[518,660,661],{},"evlog map --min-score 90 \\| tee map.log"," always looks green. Add ",[518,664,665],{},"set -o pipefail"," to the step.",[511,668,670],{"id":669},"github-actions","GitHub Actions",[523,672,677],{"className":673,"code":674,"filename":675,"language":676,"meta":529,"style":529},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","name: Observability\n\non: pull_request\n\njobs:\n  map:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v5\n      - uses: actions\u002Fsetup-node@v5\n        with:\n          node-version: 22\n      - run: npx @evlog\u002Fcli map --min-score 80 --no-write\n",".github\u002Fworkflows\u002Fobservability.yml","yaml",[518,678,679,692,699,711,716,725,733,744,752,766,778,786,797],{"__ignoreMap":529},[533,680,681,685,689],{"class":535,"line":536},[533,682,684],{"class":683},"swJcz","name",[533,686,688],{"class":687},"sMK4o",":",[533,690,691],{"class":543}," Observability\n",[533,693,695],{"class":535,"line":694},2,[533,696,698],{"emptyLinePlaceholder":697},true,"\n",[533,700,702,706,708],{"class":535,"line":701},3,[533,703,705],{"class":704},"sfNiH","on",[533,707,688],{"class":687},[533,709,710],{"class":543}," pull_request\n",[533,712,714],{"class":535,"line":713},4,[533,715,698],{"emptyLinePlaceholder":697},[533,717,719,722],{"class":535,"line":718},5,[533,720,721],{"class":683},"jobs",[533,723,724],{"class":687},":\n",[533,726,728,731],{"class":535,"line":727},6,[533,729,730],{"class":683},"  map",[533,732,724],{"class":687},[533,734,736,739,741],{"class":535,"line":735},7,[533,737,738],{"class":683},"    runs-on",[533,740,688],{"class":687},[533,742,743],{"class":543}," ubuntu-latest\n",[533,745,747,750],{"class":535,"line":746},8,[533,748,749],{"class":683},"    steps",[533,751,724],{"class":687},[533,753,755,758,761,763],{"class":535,"line":754},9,[533,756,757],{"class":687},"      -",[533,759,760],{"class":683}," uses",[533,762,688],{"class":687},[533,764,765],{"class":543}," actions\u002Fcheckout@v5\n",[533,767,769,771,773,775],{"class":535,"line":768},10,[533,770,757],{"class":687},[533,772,760],{"class":683},[533,774,688],{"class":687},[533,776,777],{"class":543}," actions\u002Fsetup-node@v5\n",[533,779,781,784],{"class":535,"line":780},11,[533,782,783],{"class":683},"        with",[533,785,724],{"class":687},[533,787,789,792,794],{"class":535,"line":788},12,[533,790,791],{"class":683},"          node-version",[533,793,688],{"class":687},[533,795,796],{"class":550}," 22\n",[533,798,800,802,805,807],{"class":535,"line":799},13,[533,801,757],{"class":687},[533,803,804],{"class":683}," run",[533,806,688],{"class":687},[533,808,809],{"class":543}," npx @evlog\u002Fcli map --min-score 80 --no-write\n",[507,811,812,815,816,819],{},[518,813,814],{},"--no-write"," keeps the job from producing an ",[518,817,818],{},"evlog.map.json"," nobody will read.",[821,822,824],"h3",{"id":823},"pin-the-version","Pin the version",[507,826,827],{},"The CLI is young: rules are still being refined and new ones will be added, so a release can change a verdict on code nobody touched. On a gated job that shows up as a pull request failing for reasons its author cannot see in the diff.",[507,829,830],{},"Install the CLI as a dev dependency and let your lockfile hold it still:",[523,832,834],{"className":525,"code":833,"filename":527,"language":528,"meta":529,"style":529},"pnpm add -D @evlog\u002Fcli\n",[518,835,836],{"__ignoreMap":529},[533,837,838,841,844,847],{"class":535,"line":536},[533,839,840],{"class":539},"pnpm",[533,842,843],{"class":543}," add",[533,845,846],{"class":543}," -D",[533,848,849],{"class":543}," @evlog\u002Fcli\n",[523,851,853],{"className":673,"code":852,"filename":675,"language":676,"meta":529,"style":529},"      - run: pnpm install --frozen-lockfile\n      - run: pnpm evlog map --min-score 80 --no-write\n",[518,854,855,866],{"__ignoreMap":529},[533,856,857,859,861,863],{"class":535,"line":536},[533,858,757],{"class":687},[533,860,804],{"class":683},[533,862,688],{"class":687},[533,864,865],{"class":543}," pnpm install --frozen-lockfile\n",[533,867,868,870,872,874],{"class":535,"line":694},[533,869,757],{"class":687},[533,871,804],{"class":683},[533,873,688],{"class":687},[533,875,876],{"class":543}," pnpm evlog map --min-score 80 --no-write\n",[507,878,879],{},"Then a score change is always something you did, and upgrading the CLI is its own pull request — where a moved score is the point rather than a surprise.",[821,881,883],{"id":882},"ratchet-dont-cliff","Ratchet, don't cliff",[507,885,886],{},"Setting the threshold to 90 on an app that scores 41 fails every pull request and teaches the team to ignore the job. Set it to today's score, then raise it as you fix things:",[523,888,890],{"className":525,"code":889,"filename":527,"language":528,"meta":529,"style":529},"# what are we at right now?\nevlog map --json --no-write | jq '.map.score'\n",[518,891,892,898],{"__ignoreMap":529},[533,893,894],{"class":535,"line":536},[533,895,897],{"class":896},"sHwdD","# what are we at right now?\n",[533,899,900,902,904,907,910,913,916,919,922],{"class":535,"line":694},[533,901,540],{"class":539},[533,903,544],{"class":543},[533,905,906],{"class":543}," --json",[533,908,909],{"class":543}," --no-write",[533,911,912],{"class":687}," |",[533,914,915],{"class":539}," jq",[533,917,918],{"class":687}," '",[533,920,921],{"class":543},".map.score",[533,923,924],{"class":687},"'\n",[507,926,927,928,931],{},"Each pull request that raises the score raises the floor with it. The report already tells you what the next step is worth: ",[518,929,930],{},"▲ 76 → 86 by fixing the 3 above",".",[511,933,935],{"id":934},"the-json-contract","The JSON contract",[507,937,938,941],{},[518,939,940],{},"--json"," writes the whole map to stdout. The report goes to stderr, so the two never mix.",[523,943,945],{"className":525,"code":944,"filename":527,"language":528,"meta":529,"style":529},"evlog map --json --no-write > map.json\n",[518,946,947],{"__ignoreMap":529},[533,948,949,951,953,955,957,960],{"class":535,"line":536},[533,950,540],{"class":539},[533,952,544],{"class":543},[533,954,906],{"class":543},[533,956,909],{"class":543},[533,958,959],{"class":687}," >",[533,961,962],{"class":543}," map.json\n",[523,964,969],{"className":965,"code":966,"filename":967,"language":968,"meta":529,"style":529},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"schemaVersion\": 2,\n  \"environment\": \"production\",\n  \"map\": {\n    \"version\": 1,\n    \"generatedAt\": \"2026-07-25T18:42:10.114Z\",\n    \"framework\": \"nuxt\",\n    \"projectName\": \"evlog-playground\",\n    \"score\": 76,\n    \"routes\": []\n  },\n  \"summary\": { \"instrumented\": 19, \"partial\": 2, \"dark\": 8, \"exempt\": 0, \"suppressedChecks\": 0 },\n  \"mapPath\": \"\u002Fpath\u002Fto\u002Fapp\u002Fevlog.map.json\"\n}\n","Shape","json",[518,970,971,976,996,1017,1030,1047,1067,1087,1107,1123,1137,1142,1226,1245],{"__ignoreMap":529},[533,972,973],{"class":535,"line":536},[533,974,975],{"class":687},"{\n",[533,977,978,981,985,988,990,993],{"class":535,"line":694},[533,979,980],{"class":687},"  \"",[533,982,984],{"class":983},"spNyl","schemaVersion",[533,986,987],{"class":687},"\"",[533,989,688],{"class":687},[533,991,992],{"class":550}," 2",[533,994,995],{"class":687},",\n",[533,997,998,1000,1003,1005,1007,1010,1013,1015],{"class":535,"line":701},[533,999,980],{"class":687},[533,1001,1002],{"class":983},"environment",[533,1004,987],{"class":687},[533,1006,688],{"class":687},[533,1008,1009],{"class":687}," \"",[533,1011,1012],{"class":543},"production",[533,1014,987],{"class":687},[533,1016,995],{"class":687},[533,1018,1019,1021,1023,1025,1027],{"class":535,"line":713},[533,1020,980],{"class":687},[533,1022,89],{"class":983},[533,1024,987],{"class":687},[533,1026,688],{"class":687},[533,1028,1029],{"class":687}," {\n",[533,1031,1032,1035,1038,1040,1042,1045],{"class":535,"line":718},[533,1033,1034],{"class":687},"    \"",[533,1036,1037],{"class":539},"version",[533,1039,987],{"class":687},[533,1041,688],{"class":687},[533,1043,1044],{"class":550}," 1",[533,1046,995],{"class":687},[533,1048,1049,1051,1054,1056,1058,1060,1063,1065],{"class":535,"line":727},[533,1050,1034],{"class":687},[533,1052,1053],{"class":539},"generatedAt",[533,1055,987],{"class":687},[533,1057,688],{"class":687},[533,1059,1009],{"class":687},[533,1061,1062],{"class":543},"2026-07-25T18:42:10.114Z",[533,1064,987],{"class":687},[533,1066,995],{"class":687},[533,1068,1069,1071,1074,1076,1078,1080,1083,1085],{"class":535,"line":735},[533,1070,1034],{"class":687},[533,1072,1073],{"class":539},"framework",[533,1075,987],{"class":687},[533,1077,688],{"class":687},[533,1079,1009],{"class":687},[533,1081,1082],{"class":543},"nuxt",[533,1084,987],{"class":687},[533,1086,995],{"class":687},[533,1088,1089,1091,1094,1096,1098,1100,1103,1105],{"class":535,"line":746},[533,1090,1034],{"class":687},[533,1092,1093],{"class":539},"projectName",[533,1095,987],{"class":687},[533,1097,688],{"class":687},[533,1099,1009],{"class":687},[533,1101,1102],{"class":543},"evlog-playground",[533,1104,987],{"class":687},[533,1106,995],{"class":687},[533,1108,1109,1111,1114,1116,1118,1121],{"class":535,"line":754},[533,1110,1034],{"class":687},[533,1112,1113],{"class":539},"score",[533,1115,987],{"class":687},[533,1117,688],{"class":687},[533,1119,1120],{"class":550}," 76",[533,1122,995],{"class":687},[533,1124,1125,1127,1130,1132,1134],{"class":535,"line":768},[533,1126,1034],{"class":687},[533,1128,1129],{"class":539},"routes",[533,1131,987],{"class":687},[533,1133,688],{"class":687},[533,1135,1136],{"class":687}," []\n",[533,1138,1139],{"class":535,"line":780},[533,1140,1141],{"class":687},"  },\n",[533,1143,1144,1146,1149,1151,1153,1156,1158,1161,1163,1165,1168,1171,1173,1176,1178,1180,1182,1184,1186,1189,1191,1193,1196,1198,1200,1203,1205,1207,1210,1212,1214,1217,1219,1221,1223],{"class":535,"line":788},[533,1145,980],{"class":687},[533,1147,1148],{"class":983},"summary",[533,1150,987],{"class":687},[533,1152,688],{"class":687},[533,1154,1155],{"class":687}," {",[533,1157,1009],{"class":687},[533,1159,1160],{"class":539},"instrumented",[533,1162,987],{"class":687},[533,1164,688],{"class":687},[533,1166,1167],{"class":550}," 19",[533,1169,1170],{"class":687},",",[533,1172,1009],{"class":687},[533,1174,1175],{"class":539},"partial",[533,1177,987],{"class":687},[533,1179,688],{"class":687},[533,1181,992],{"class":550},[533,1183,1170],{"class":687},[533,1185,1009],{"class":687},[533,1187,1188],{"class":539},"dark",[533,1190,987],{"class":687},[533,1192,688],{"class":687},[533,1194,1195],{"class":550}," 8",[533,1197,1170],{"class":687},[533,1199,1009],{"class":687},[533,1201,1202],{"class":539},"exempt",[533,1204,987],{"class":687},[533,1206,688],{"class":687},[533,1208,1209],{"class":550}," 0",[533,1211,1170],{"class":687},[533,1213,1009],{"class":687},[533,1215,1216],{"class":539},"suppressedChecks",[533,1218,987],{"class":687},[533,1220,688],{"class":687},[533,1222,1209],{"class":550},[533,1224,1225],{"class":687}," },\n",[533,1227,1228,1230,1233,1235,1237,1239,1242],{"class":535,"line":799},[533,1229,980],{"class":687},[533,1231,1232],{"class":983},"mapPath",[533,1234,987],{"class":687},[533,1236,688],{"class":687},[533,1238,1009],{"class":687},[533,1240,1241],{"class":543},"\u002Fpath\u002Fto\u002Fapp\u002Fevlog.map.json",[533,1243,1244],{"class":687},"\"\n",[533,1246,1248],{"class":535,"line":1247},14,[533,1249,1250],{"class":687},"}\n",[507,1252,1253,1255,1256,1259,1260,1262,1263,1266],{},[518,1254,1232],{}," is ",[518,1257,1258],{},"null"," under ",[518,1261,814],{},". Each entry in ",[518,1264,1265],{},"map.routes"," looks like this:",[1268,1269,1270],"code-collapse",{},[523,1271,1274],{"className":965,"code":1272,"filename":1273,"language":968,"meta":529,"style":529},"{\n  \"framework\": \"nuxt\",\n  \"kind\": \"api\",\n  \"method\": \"POST\",\n  \"path\": \"\u002Fapi\u002Fauth\u002Flogin\",\n  \"file\": \"server\u002Fapi\u002Fauth\u002Flogin.post.ts\",\n  \"handler\": { \"line\": 1, \"column\": 0 },\n  \"id\": \"337325358269\",\n  \"checks\": {\n    \"wide-event\": { \"status\": \"pass\" },\n    \"context\": { \"status\": \"pass\" },\n    \"structured-errors\": { \"status\": \"n\u002Fa\" },\n    \"error-handling\": { \"status\": \"n\u002Fa\" },\n    \"audit\": {\n      \"status\": \"fail\",\n      \"message\": \"has logger + context but no log.audit() — sensitive route needs audit trail\",\n      \"evidence\": { \"file\": \"server\u002Fapi\u002Fauth\u002Flogin.post.ts\", \"line\": 1 }\n    }\n  },\n  \"suggestions\": {},\n  \"sensitivity\": { \"level\": \"high\", \"reasons\": [\"auth: path says \\\"auth\\\"\"] },\n  \"score\": 75\n}\n","One entry point",[518,1275,1276,1280,1298,1318,1338,1358,1378,1416,1436,1449,1480,1509,1539,1568,1581,1602,1623,1666,1672,1677,1692,1757,1771],{"__ignoreMap":529},[533,1277,1278],{"class":535,"line":536},[533,1279,975],{"class":687},[533,1281,1282,1284,1286,1288,1290,1292,1294,1296],{"class":535,"line":694},[533,1283,980],{"class":687},[533,1285,1073],{"class":983},[533,1287,987],{"class":687},[533,1289,688],{"class":687},[533,1291,1009],{"class":687},[533,1293,1082],{"class":543},[533,1295,987],{"class":687},[533,1297,995],{"class":687},[533,1299,1300,1302,1305,1307,1309,1311,1314,1316],{"class":535,"line":701},[533,1301,980],{"class":687},[533,1303,1304],{"class":983},"kind",[533,1306,987],{"class":687},[533,1308,688],{"class":687},[533,1310,1009],{"class":687},[533,1312,1313],{"class":543},"api",[533,1315,987],{"class":687},[533,1317,995],{"class":687},[533,1319,1320,1322,1325,1327,1329,1331,1334,1336],{"class":535,"line":713},[533,1321,980],{"class":687},[533,1323,1324],{"class":983},"method",[533,1326,987],{"class":687},[533,1328,688],{"class":687},[533,1330,1009],{"class":687},[533,1332,1333],{"class":543},"POST",[533,1335,987],{"class":687},[533,1337,995],{"class":687},[533,1339,1340,1342,1345,1347,1349,1351,1354,1356],{"class":535,"line":718},[533,1341,980],{"class":687},[533,1343,1344],{"class":983},"path",[533,1346,987],{"class":687},[533,1348,688],{"class":687},[533,1350,1009],{"class":687},[533,1352,1353],{"class":543},"\u002Fapi\u002Fauth\u002Flogin",[533,1355,987],{"class":687},[533,1357,995],{"class":687},[533,1359,1360,1362,1365,1367,1369,1371,1374,1376],{"class":535,"line":727},[533,1361,980],{"class":687},[533,1363,1364],{"class":983},"file",[533,1366,987],{"class":687},[533,1368,688],{"class":687},[533,1370,1009],{"class":687},[533,1372,1373],{"class":543},"server\u002Fapi\u002Fauth\u002Flogin.post.ts",[533,1375,987],{"class":687},[533,1377,995],{"class":687},[533,1379,1380,1382,1385,1387,1389,1391,1393,1395,1397,1399,1401,1403,1405,1408,1410,1412,1414],{"class":535,"line":735},[533,1381,980],{"class":687},[533,1383,1384],{"class":983},"handler",[533,1386,987],{"class":687},[533,1388,688],{"class":687},[533,1390,1155],{"class":687},[533,1392,1009],{"class":687},[533,1394,535],{"class":539},[533,1396,987],{"class":687},[533,1398,688],{"class":687},[533,1400,1044],{"class":550},[533,1402,1170],{"class":687},[533,1404,1009],{"class":687},[533,1406,1407],{"class":539},"column",[533,1409,987],{"class":687},[533,1411,688],{"class":687},[533,1413,1209],{"class":550},[533,1415,1225],{"class":687},[533,1417,1418,1420,1423,1425,1427,1429,1432,1434],{"class":535,"line":746},[533,1419,980],{"class":687},[533,1421,1422],{"class":983},"id",[533,1424,987],{"class":687},[533,1426,688],{"class":687},[533,1428,1009],{"class":687},[533,1430,1431],{"class":543},"337325358269",[533,1433,987],{"class":687},[533,1435,995],{"class":687},[533,1437,1438,1440,1443,1445,1447],{"class":535,"line":754},[533,1439,980],{"class":687},[533,1441,1442],{"class":983},"checks",[533,1444,987],{"class":687},[533,1446,688],{"class":687},[533,1448,1029],{"class":687},[533,1450,1451,1453,1456,1458,1460,1462,1464,1467,1469,1471,1473,1476,1478],{"class":535,"line":768},[533,1452,1034],{"class":687},[533,1454,1455],{"class":539},"wide-event",[533,1457,987],{"class":687},[533,1459,688],{"class":687},[533,1461,1155],{"class":687},[533,1463,1009],{"class":687},[533,1465,1466],{"class":550},"status",[533,1468,987],{"class":687},[533,1470,688],{"class":687},[533,1472,1009],{"class":687},[533,1474,1475],{"class":543},"pass",[533,1477,987],{"class":687},[533,1479,1225],{"class":687},[533,1481,1482,1484,1487,1489,1491,1493,1495,1497,1499,1501,1503,1505,1507],{"class":535,"line":780},[533,1483,1034],{"class":687},[533,1485,1486],{"class":539},"context",[533,1488,987],{"class":687},[533,1490,688],{"class":687},[533,1492,1155],{"class":687},[533,1494,1009],{"class":687},[533,1496,1466],{"class":550},[533,1498,987],{"class":687},[533,1500,688],{"class":687},[533,1502,1009],{"class":687},[533,1504,1475],{"class":543},[533,1506,987],{"class":687},[533,1508,1225],{"class":687},[533,1510,1511,1513,1516,1518,1520,1522,1524,1526,1528,1530,1532,1535,1537],{"class":535,"line":788},[533,1512,1034],{"class":687},[533,1514,1515],{"class":539},"structured-errors",[533,1517,987],{"class":687},[533,1519,688],{"class":687},[533,1521,1155],{"class":687},[533,1523,1009],{"class":687},[533,1525,1466],{"class":550},[533,1527,987],{"class":687},[533,1529,688],{"class":687},[533,1531,1009],{"class":687},[533,1533,1534],{"class":543},"n\u002Fa",[533,1536,987],{"class":687},[533,1538,1225],{"class":687},[533,1540,1541,1543,1546,1548,1550,1552,1554,1556,1558,1560,1562,1564,1566],{"class":535,"line":799},[533,1542,1034],{"class":687},[533,1544,1545],{"class":539},"error-handling",[533,1547,987],{"class":687},[533,1549,688],{"class":687},[533,1551,1155],{"class":687},[533,1553,1009],{"class":687},[533,1555,1466],{"class":550},[533,1557,987],{"class":687},[533,1559,688],{"class":687},[533,1561,1009],{"class":687},[533,1563,1534],{"class":543},[533,1565,987],{"class":687},[533,1567,1225],{"class":687},[533,1569,1570,1572,1575,1577,1579],{"class":535,"line":1247},[533,1571,1034],{"class":687},[533,1573,1574],{"class":539},"audit",[533,1576,987],{"class":687},[533,1578,688],{"class":687},[533,1580,1029],{"class":687},[533,1582,1584,1587,1589,1591,1593,1595,1598,1600],{"class":535,"line":1583},15,[533,1585,1586],{"class":687},"      \"",[533,1588,1466],{"class":550},[533,1590,987],{"class":687},[533,1592,688],{"class":687},[533,1594,1009],{"class":687},[533,1596,1597],{"class":543},"fail",[533,1599,987],{"class":687},[533,1601,995],{"class":687},[533,1603,1605,1607,1610,1612,1614,1616,1619,1621],{"class":535,"line":1604},16,[533,1606,1586],{"class":687},[533,1608,1609],{"class":550},"message",[533,1611,987],{"class":687},[533,1613,688],{"class":687},[533,1615,1009],{"class":687},[533,1617,1618],{"class":543},"has logger + context but no log.audit() — sensitive route needs audit trail",[533,1620,987],{"class":687},[533,1622,995],{"class":687},[533,1624,1626,1628,1631,1633,1635,1637,1639,1641,1643,1645,1647,1649,1651,1653,1655,1657,1659,1661,1663],{"class":535,"line":1625},17,[533,1627,1586],{"class":687},[533,1629,1630],{"class":550},"evidence",[533,1632,987],{"class":687},[533,1634,688],{"class":687},[533,1636,1155],{"class":687},[533,1638,1009],{"class":687},[533,1640,1364],{"class":683},[533,1642,987],{"class":687},[533,1644,688],{"class":687},[533,1646,1009],{"class":687},[533,1648,1373],{"class":543},[533,1650,987],{"class":687},[533,1652,1170],{"class":687},[533,1654,1009],{"class":687},[533,1656,535],{"class":683},[533,1658,987],{"class":687},[533,1660,688],{"class":687},[533,1662,1044],{"class":550},[533,1664,1665],{"class":687}," }\n",[533,1667,1669],{"class":535,"line":1668},18,[533,1670,1671],{"class":687},"    }\n",[533,1673,1675],{"class":535,"line":1674},19,[533,1676,1141],{"class":687},[533,1678,1680,1682,1685,1687,1689],{"class":535,"line":1679},20,[533,1681,980],{"class":687},[533,1683,1684],{"class":983},"suggestions",[533,1686,987],{"class":687},[533,1688,688],{"class":687},[533,1690,1691],{"class":687}," {},\n",[533,1693,1695,1697,1700,1702,1704,1706,1708,1711,1713,1715,1717,1720,1722,1724,1726,1729,1731,1733,1736,1738,1741,1745,1748,1750,1752,1755],{"class":535,"line":1694},21,[533,1696,980],{"class":687},[533,1698,1699],{"class":983},"sensitivity",[533,1701,987],{"class":687},[533,1703,688],{"class":687},[533,1705,1155],{"class":687},[533,1707,1009],{"class":687},[533,1709,1710],{"class":539},"level",[533,1712,987],{"class":687},[533,1714,688],{"class":687},[533,1716,1009],{"class":687},[533,1718,1719],{"class":543},"high",[533,1721,987],{"class":687},[533,1723,1170],{"class":687},[533,1725,1009],{"class":687},[533,1727,1728],{"class":539},"reasons",[533,1730,987],{"class":687},[533,1732,688],{"class":687},[533,1734,1735],{"class":687}," [",[533,1737,987],{"class":687},[533,1739,1740],{"class":543},"auth: path says ",[533,1742,1744],{"class":1743},"sTEyZ","\\\"",[533,1746,1747],{"class":543},"auth",[533,1749,1744],{"class":1743},[533,1751,987],{"class":687},[533,1753,1754],{"class":687},"]",[533,1756,1225],{"class":687},[533,1758,1760,1762,1764,1766,1768],{"class":535,"line":1759},22,[533,1761,980],{"class":687},[533,1763,1113],{"class":983},[533,1765,987],{"class":687},[533,1767,688],{"class":687},[533,1769,1770],{"class":550}," 75\n",[533,1772,1774],{"class":535,"line":1773},23,[533,1775,1250],{"class":687},[507,1777,1778,1780,1781,1783],{},[518,1779,1442],{}," holds requirements, ",[518,1782,1684],{}," holds opportunities. They are separate keys precisely so a consumer — or a CI script — can never mistake a suggestion for a failure. Rule ids are stable: the registry and the published id union are checked against each other at build time, so a release cannot silently change what you receive.",[507,1785,1786,1787,1255,1791,1793,1794,1797,1798,1800],{},"A check somebody ",[585,1788,1790],{"href":1789},"\u002Fcli\u002Frules#disabling-a-check","disabled with a comment",[518,1792,1534],{}," with ",[518,1795,1796],{},"\"suppressed\": true",", and its ",[518,1799,1630],{}," points at the comment rather than at the handler:",[523,1802,1805],{"className":965,"code":1803,"filename":1804,"language":968,"meta":529,"style":529},"\"wide-event\": {\n  \"status\": \"n\u002Fa\",\n  \"suppressed\": true,\n  \"message\": \"disabled at line 1 — liveness probe, deliberately silent\",\n  \"evidence\": { \"file\": \"server\u002Fapi\u002Fhealth.get.ts\", \"line\": 1 }\n}\n","A disabled check",[518,1806,1807,1820,1838,1852,1871,1912],{"__ignoreMap":529},[533,1808,1809,1811,1813,1815,1818],{"class":535,"line":536},[533,1810,987],{"class":687},[533,1812,1455],{"class":543},[533,1814,987],{"class":687},[533,1816,1817],{"class":1743},": ",[533,1819,975],{"class":687},[533,1821,1822,1824,1826,1828,1830,1832,1834,1836],{"class":535,"line":694},[533,1823,980],{"class":687},[533,1825,1466],{"class":983},[533,1827,987],{"class":687},[533,1829,688],{"class":687},[533,1831,1009],{"class":687},[533,1833,1534],{"class":543},[533,1835,987],{"class":687},[533,1837,995],{"class":687},[533,1839,1840,1842,1845,1847,1849],{"class":535,"line":701},[533,1841,980],{"class":687},[533,1843,1844],{"class":983},"suppressed",[533,1846,987],{"class":687},[533,1848,688],{"class":687},[533,1850,1851],{"class":687}," true,\n",[533,1853,1854,1856,1858,1860,1862,1864,1867,1869],{"class":535,"line":713},[533,1855,980],{"class":687},[533,1857,1609],{"class":983},[533,1859,987],{"class":687},[533,1861,688],{"class":687},[533,1863,1009],{"class":687},[533,1865,1866],{"class":543},"disabled at line 1 — liveness probe, deliberately silent",[533,1868,987],{"class":687},[533,1870,995],{"class":687},[533,1872,1873,1875,1877,1879,1881,1883,1885,1887,1889,1891,1893,1896,1898,1900,1902,1904,1906,1908,1910],{"class":535,"line":718},[533,1874,980],{"class":687},[533,1876,1630],{"class":983},[533,1878,987],{"class":687},[533,1880,688],{"class":687},[533,1882,1155],{"class":687},[533,1884,1009],{"class":687},[533,1886,1364],{"class":539},[533,1888,987],{"class":687},[533,1890,688],{"class":687},[533,1892,1009],{"class":687},[533,1894,1895],{"class":543},"server\u002Fapi\u002Fhealth.get.ts",[533,1897,987],{"class":687},[533,1899,1170],{"class":687},[533,1901,1009],{"class":687},[533,1903,535],{"class":539},[533,1905,987],{"class":687},[533,1907,688],{"class":687},[533,1909,1044],{"class":550},[533,1911,1665],{"class":687},[533,1913,1914],{"class":535,"line":727},[533,1915,1250],{"class":687},[507,1917,1918,1921],{},[518,1919,1920],{},"summary.suppressedChecks"," is the project total. It is the number to watch alongside the score: the gate only measures what the rules were allowed to look at.",[821,1923,381],{"id":1924},"recipes",[523,1926,1928],{"className":525,"code":1927,"filename":527,"language":528,"meta":529,"style":529},"# the score, for a badge or a comment\nevlog map --json --no-write | jq '.map.score'\n\n# every entry point with no event at all\nevlog map --json --no-write \\\n  | jq -r '.map.routes[] | select(.checks[\"wide-event\"].status == \"fail\") | .file'\n\n# every failure as file:line — message\nevlog map --json --no-write \\\n  | jq -r '.map.routes[].checks | to_entries[] | select(.value.status == \"fail\")\n           | \"\\(.value.evidence.file):\\(.value.evidence.line) — \\(.value.message)\"'\n\n# fail a script when anything is dark\ntest \"$(evlog map --json --no-write | jq '.summary.dark')\" -eq 0\n\n# how much of the score is disabled checks\nevlog map --json --no-write | jq '.summary.suppressedChecks'\n",[518,1929,1930,1935,1955,1959,1964,1977,1994,1998,2003,2015,2028,2035,2039,2044,2077,2081,2086],{"__ignoreMap":529},[533,1931,1932],{"class":535,"line":536},[533,1933,1934],{"class":896},"# the score, for a badge or a comment\n",[533,1936,1937,1939,1941,1943,1945,1947,1949,1951,1953],{"class":535,"line":694},[533,1938,540],{"class":539},[533,1940,544],{"class":543},[533,1942,906],{"class":543},[533,1944,909],{"class":543},[533,1946,912],{"class":687},[533,1948,915],{"class":539},[533,1950,918],{"class":687},[533,1952,921],{"class":543},[533,1954,924],{"class":687},[533,1956,1957],{"class":535,"line":701},[533,1958,698],{"emptyLinePlaceholder":697},[533,1960,1961],{"class":535,"line":713},[533,1962,1963],{"class":896},"# every entry point with no event at all\n",[533,1965,1966,1968,1970,1972,1974],{"class":535,"line":718},[533,1967,540],{"class":539},[533,1969,544],{"class":543},[533,1971,906],{"class":543},[533,1973,909],{"class":543},[533,1975,1976],{"class":1743}," \\\n",[533,1978,1979,1982,1984,1987,1989,1992],{"class":535,"line":727},[533,1980,1981],{"class":687},"  |",[533,1983,915],{"class":539},[533,1985,1986],{"class":543}," -r",[533,1988,918],{"class":687},[533,1990,1991],{"class":543},".map.routes[] | select(.checks[\"wide-event\"].status == \"fail\") | .file",[533,1993,924],{"class":687},[533,1995,1996],{"class":535,"line":735},[533,1997,698],{"emptyLinePlaceholder":697},[533,1999,2000],{"class":535,"line":746},[533,2001,2002],{"class":896},"# every failure as file:line — message\n",[533,2004,2005,2007,2009,2011,2013],{"class":535,"line":754},[533,2006,540],{"class":539},[533,2008,544],{"class":543},[533,2010,906],{"class":543},[533,2012,909],{"class":543},[533,2014,1976],{"class":1743},[533,2016,2017,2019,2021,2023,2025],{"class":535,"line":768},[533,2018,1981],{"class":687},[533,2020,915],{"class":539},[533,2022,1986],{"class":543},[533,2024,918],{"class":687},[533,2026,2027],{"class":543},".map.routes[].checks | to_entries[] | select(.value.status == \"fail\")\n",[533,2029,2030,2033],{"class":535,"line":780},[533,2031,2032],{"class":543},"           | \"\\(.value.evidence.file):\\(.value.evidence.line) — \\(.value.message)\"",[533,2034,924],{"class":687},[533,2036,2037],{"class":535,"line":788},[533,2038,698],{"emptyLinePlaceholder":697},[533,2040,2041],{"class":535,"line":799},[533,2042,2043],{"class":896},"# fail a script when anything is dark\n",[533,2045,2046,2050,2053,2055,2058,2061,2063,2065,2068,2071,2074],{"class":535,"line":1247},[533,2047,2049],{"class":2048},"s2Zo4","test",[533,2051,2052],{"class":687}," \"$(",[533,2054,540],{"class":539},[533,2056,2057],{"class":543}," map --json --no-write ",[533,2059,2060],{"class":687},"|",[533,2062,915],{"class":539},[533,2064,918],{"class":687},[533,2066,2067],{"class":543},".summary.dark",[533,2069,2070],{"class":687},"')\"",[533,2072,2073],{"class":543}," -eq",[533,2075,2076],{"class":550}," 0\n",[533,2078,2079],{"class":535,"line":1583},[533,2080,698],{"emptyLinePlaceholder":697},[533,2082,2083],{"class":535,"line":1604},[533,2084,2085],{"class":896},"# how much of the score is disabled checks\n",[533,2087,2088,2090,2092,2094,2096,2098,2100,2102,2105],{"class":535,"line":1625},[533,2089,540],{"class":539},[533,2091,544],{"class":543},[533,2093,906],{"class":543},[533,2095,909],{"class":543},[533,2097,912],{"class":687},[533,2099,915],{"class":539},[533,2101,918],{"class":687},[533,2103,2104],{"class":543},".summary.suppressedChecks",[533,2106,924],{"class":687},[511,2108,2110],{"id":2109},"the-map-file","The map file",[507,2112,2113,2114,2116,2117,2119,2120,2122],{},"Unless you pass ",[518,2115,814],{},", every run writes ",[518,2118,818],{}," to the project root. It holds the same data as ",[518,2121,940],{}," and is a build artifact, so ignore it:",[523,2124,2127],{"className":525,"code":2125,"filename":2126,"language":528,"meta":529,"style":529},"evlog.map.json\n",".gitignore",[518,2128,2129],{"__ignoreMap":529},[533,2130,2131],{"class":535,"line":536},[533,2132,2125],{"class":539},[507,2134,2135,2136,2138],{},"Track it instead if you want the diff in review — a pull request then shows exactly which entry points changed class, which is a useful thing to argue about. Just expect the file to churn on every run, since ",[518,2137,1053],{}," changes each time.",[511,2140,2142],{"id":2141},"monorepos","Monorepos",[507,2144,2145,2148],{},[518,2146,2147],{},"evlog map"," scans one app at a time. Gate each one:",[523,2150,2152],{"className":673,"code":2151,"filename":675,"language":676,"meta":529,"style":529},"jobs:\n  map:\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        app: [apps\u002Fweb, apps\u002Fadmin]\n    steps:\n      - uses: actions\u002Fcheckout@v5\n      - uses: actions\u002Fsetup-node@v5\n        with:\n          node-version: 22\n      - run: npx @evlog\u002Fcli map --cwd ${{ matrix.app }} --min-score 80 --no-write\n",[518,2153,2154,2160,2166,2174,2181,2188,2208,2214,2224,2234,2240,2248],{"__ignoreMap":529},[533,2155,2156,2158],{"class":535,"line":536},[533,2157,721],{"class":683},[533,2159,724],{"class":687},[533,2161,2162,2164],{"class":535,"line":694},[533,2163,730],{"class":683},[533,2165,724],{"class":687},[533,2167,2168,2170,2172],{"class":535,"line":701},[533,2169,738],{"class":683},[533,2171,688],{"class":687},[533,2173,743],{"class":543},[533,2175,2176,2179],{"class":535,"line":713},[533,2177,2178],{"class":683},"    strategy",[533,2180,724],{"class":687},[533,2182,2183,2186],{"class":535,"line":718},[533,2184,2185],{"class":683},"      matrix",[533,2187,724],{"class":687},[533,2189,2190,2193,2195,2197,2200,2202,2205],{"class":535,"line":727},[533,2191,2192],{"class":683},"        app",[533,2194,688],{"class":687},[533,2196,1735],{"class":687},[533,2198,2199],{"class":543},"apps\u002Fweb",[533,2201,1170],{"class":687},[533,2203,2204],{"class":543}," apps\u002Fadmin",[533,2206,2207],{"class":687},"]\n",[533,2209,2210,2212],{"class":535,"line":735},[533,2211,749],{"class":683},[533,2213,724],{"class":687},[533,2215,2216,2218,2220,2222],{"class":535,"line":746},[533,2217,757],{"class":687},[533,2219,760],{"class":683},[533,2221,688],{"class":687},[533,2223,765],{"class":543},[533,2225,2226,2228,2230,2232],{"class":535,"line":754},[533,2227,757],{"class":687},[533,2229,760],{"class":683},[533,2231,688],{"class":687},[533,2233,777],{"class":543},[533,2235,2236,2238],{"class":535,"line":768},[533,2237,783],{"class":683},[533,2239,724],{"class":687},[533,2241,2242,2244,2246],{"class":535,"line":780},[533,2243,791],{"class":683},[533,2245,688],{"class":687},[533,2247,796],{"class":550},[533,2249,2250,2252,2254,2256],{"class":535,"line":788},[533,2251,757],{"class":687},[533,2253,804],{"class":683},[533,2255,688],{"class":687},[533,2257,2258],{"class":543}," npx @evlog\u002Fcli map --cwd ${{ matrix.app }} --min-score 80 --no-write\n",[507,2260,2261],{},"Different apps can carry different thresholds, which is usually what you want: the app that takes payments should be held higher than the marketing site.",[511,2263,2265],{"id":2264},"next","Next",[2267,2268,2269,2275],"ul",{},[2270,2271,2272,2274],"li",{},[585,2273,94],{"href":95}," — what a failing check means and how to fix it",[2270,2276,2277,2279],{},[585,2278,99],{"href":100}," — how the number you are gating on is calculated",[2281,2282,2283],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":529,"searchDepth":694,"depth":694,"links":2285},[2286,2287,2288,2292,2295,2296,2297],{"id":513,"depth":694,"text":514},{"id":592,"depth":694,"text":593},{"id":669,"depth":694,"text":670,"children":2289},[2290,2291],{"id":823,"depth":701,"text":824},{"id":882,"depth":701,"text":883},{"id":934,"depth":694,"text":935,"children":2293},[2294],{"id":1924,"depth":701,"text":381},{"id":2109,"depth":694,"text":2110},{"id":2141,"depth":694,"text":2142},{"id":2264,"depth":694,"text":2265},"Gate a pull request on your observability score with --min-score, read the JSON contract, and keep the map file out of the way. Exit codes, GitHub Actions, and jq recipes.","md",[2301,2303],{"label":99,"icon":102,"to":100,"color":583,"variant":2302},"subtle",{"label":94,"icon":97,"to":95,"color":583,"variant":2302},{},{"title":104,"icon":107},{"title":502,"description":2298},"8RF-NaYlZjt-oqzxqHDXNKK53v4zfSn9rk3f79jEbkA",[2309,2311],{"title":99,"path":100,"stem":101,"description":2310,"icon":102,"children":-1},"How evlog map turns rule results into a score — per-entry weights, the weighted project average, grade thresholds, coverage classification, and how routes are flagged as money, auth, or PII.",{"title":109,"path":110,"stem":111,"description":2312,"icon":112,"children":-1},"Diagnose an evlog setup — Node version, project resolution, the installed evlog version, the detected framework, and whether local logs are being written.",1785091728148]