#!/bin/sh
trap 'printf "%s\n" "Boosthis scan: this copy of the script is incomplete, as if the download was cut off, so nothing was scanned. Download it again."; exit 4' EXIT
# Boosthis project scanner — https://www.boosthis.com/scan
#
# What it reads: file and folder names, and the contents of these manifest
# files only: package.json, project.json, build.gradle, build.gradle.kts,
# pom.xml, requirements.txt, requirements-*.txt, requirements/*.txt,
# pyproject.toml, Pipfile, go.mod, composer.json, *.csproj, *.fsproj,
# *.vbproj, Gemfile, Cargo.toml, mix.exs, pubspec.yaml, project.yml,
# Project.swift, Package.swift, host.json, template.yaml, template.yml,
# manifest.json. It never reads source code, and it prints which Boosthis kits
# the project needs.
#
# Privacy: everything runs on this machine. This script makes no network call,
# writes no files and uploads NOTHING.
#
# Needs a POSIX shell: macOS, Linux, WSL or Git Bash. Where there is none, the
# AI connection's “which kits” answer reaches the same verdict from the
# published file and marker names your assistant sends it.
#
# Usage: two steps, nothing piped into a shell:
#          curl -fsSL https://www.boosthis.com/scan -o boosthis-scan.sh
#          sh boosthis-scan.sh
#        (optional: pass a folder:  sh boosthis-scan.sh /path/to/project)
#
# Exit status: 0 = finished, having read the whole folder; 2 = the folder
# could not be scanned (the message says why); 3 = a home folder or the
# filesystem root, not scanned (the message says how to scan it anyway); 4 =
# the scan did not finish, or could not read part of the folder (the message
# says what it skipped), so the list may be missing a kit.
#
# This is the inventory view. Fetched with your Boosthis project key, the same
# scanner also prints each kit's install commands.
#
# How it is built: everything below only DEFINES functions and the last line
# runs them, so a copy cut off part-way runs nothing. One find walk lists file
# names, awk reads the manifests named above and decides, and the last line
# printed (BOOSTHIS-SCAN-RESULT) says the scan finished and read the whole
# folder.

boosthis_prog_lib() {
printf '%s\n' '# The shared part: byte table, display escaping, placeholder filling.
function boo_init(    i) {
  for (i = 1; i < 256; i++) ORD[sprintf("%c", i)] = i
  CHARMODE = (length("\303\251") == 1)
  SQ = sprintf("%c", 39)
  LRI = "\342\201\246"
  PDI = "\342\201\251"
  SPECIAL["\302\200"] = "<U+0080>"; SPECIAL["\302\201"] = "<U+0081>"
  SPECIAL["\302\202"] = "<U+0082>"; SPECIAL["\302\203"] = "<U+0083>"
  SPECIAL["\302\204"] = "<U+0084>"; SPECIAL["\302\205"] = "<U+0085>"
  SPECIAL["\302\206"] = "<U+0086>"; SPECIAL["\302\207"] = "<U+0087>"
  SPECIAL["\302\210"] = "<U+0088>"; SPECIAL["\302\211"] = "<U+0089>"
  SPECIAL["\302\212"] = "<U+008A>"; SPECIAL["\302\213"] = "<U+008B>"
  SPECIAL["\302\214"] = "<U+008C>"; SPECIAL["\302\215"] = "<U+008D>"
  SPECIAL["\302\216"] = "<U+008E>"; SPECIAL["\302\217"] = "<U+008F>"
  SPECIAL["\302\220"] = "<U+0090>"; SPECIAL["\302\221"] = "<U+0091>"
  SPECIAL["\302\222"] = "<U+0092>"; SPECIAL["\302\223"] = "<U+0093>"
  SPECIAL["\302\224"] = "<U+0094>"; SPECIAL["\302\225"] = "<U+0095>"
  SPECIAL["\302\226"] = "<U+0096>"; SPECIAL["\302\227"] = "<U+0097>"
  SPECIAL["\302\230"] = "<U+0098>"; SPECIAL["\302\231"] = "<U+0099>"
  SPECIAL["\302\232"] = "<U+009A>"; SPECIAL["\302\233"] = "<U+009B>"
  SPECIAL["\302\234"] = "<U+009C>"; SPECIAL["\302\235"] = "<U+009D>"
  SPECIAL["\302\236"] = "<U+009E>"; SPECIAL["\302\237"] = "<U+009F>"
  SPECIAL["\330\234"] = "<U+061C>"; SPECIAL["\342\200\216"] = "<U+200E>"
  SPECIAL["\342\200\217"] = "<U+200F>"; SPECIAL["\342\200\250"] = "<U+2028>"
  SPECIAL["\342\200\251"] = "<U+2029>"; SPECIAL["\342\200\252"] = "<U+202A>"
  SPECIAL["\342\200\253"] = "<U+202B>"; SPECIAL["\342\200\254"] = "<U+202C>"
  SPECIAL["\342\200\255"] = "<U+202D>"; SPECIAL["\342\200\256"] = "<U+202E>"
  SPECIAL["\342\201\246"] = "<U+2066>"; SPECIAL["\342\201\247"] = "<U+2067>"
  SPECIAL["\342\201\250"] = "<U+2068>"; SPECIAL["\342\201\251"] = "<U+2069>"
}
# A folder name as it is on disk, except control codes (\xHH), and C1
# controls, direction overrides and line separators (<U+XXXX>): a name can
# neither drive the terminal nor make a printed path read backwards. Bytes
# that are not UTF-8 show as \xHH too.
function esc(s,    out, i, n, c, o, len, k, b, ok, seq) {
  if (s !~ /[^ -~]/) return s
  out = ""
  n = length(s)
  i = 1
  while (i <= n) {
    c = substr(s, i, 1)
    if (CHARMODE) {
      if (c in SPECIAL) out = out SPECIAL[c]
      else if ((c in ORD) && (ORD[c] < 32 || ORD[c] == 127)) out = out sprintf("\\x%02X", ORD[c])
      else out = out c
      i++
      continue
    }
    o = ORD[c]
    if (o < 32 || o == 127) { out = out sprintf("\\x%02X", o); i++; continue }
    if (o < 128) { out = out c; i++; continue }
    len = 0
    if (o >= 194 && o <= 223) len = 2
    else if (o >= 224 && o <= 239) len = 3
    else if (o >= 240 && o <= 244) len = 4
    ok = (len > 0 && i + len - 1 <= n)
    for (k = 1; ok && k < len; k++) { b = ORD[substr(s, i + k, 1)]; if (b < 128 || b > 191) ok = 0 }
    if (ok) {
      b = ORD[substr(s, i + 1, 1)]
      if ((o == 224 && b < 160) || (o == 237 && b > 159) || (o == 240 && b < 144) || (o == 244 && b > 143)) ok = 0
    }
    if (!ok) { out = out sprintf("\\x%02X", o); i++; continue }
    seq = substr(s, i, len)
    if (seq in SPECIAL) out = out SPECIAL[seq]
    else out = out seq
    i += len
  }
  return out
}
function subf(s, ph, v,    out, p) {
  out = ""
  while ((p = index(s, ph)) > 0) { out = out substr(s, 1, p - 1) v; s = substr(s, p + length(ph)) }
  return out s
}
'
}

boosthis_prog_count() {
printf '%s\n' '# Counts what find could not read: a "W" is a name with a line break (not
# read, by a test in find itself); any other line is find saying it could not open
# a folder.
$0 == "W" { nl++; next }
$0 != "" { un++ }
END { printf "C01\t%d\nC02\t%d\n", un, nl }
'
}

boosthis_prog_extract() {
printf '%s\n' '# Reads the walk: matches each path to a published signal, reads the
# manifests whose contents decide, and prints one fact per file:
#   F <tab> folder <tab> signal <tab> markers   ("-" = contents not read)
BEGIN {
  boo_init()
  BOM = "\357\273\277"
  QRE = "[][ \t\"" SQ "]"
  DQRE = "\"[^\"]*\"|" SQ "[^" SQ "]*" SQ
  # The published signals, in the order a path is matched against them.
  NSIG = 155; SNAME[1] = "supabase/functions/*/index.ts"; SCN[1] = 4; SCONT[1] = 0
  SROLE[1] = "supafn"; SCP[1, 1] = "supabase"; SCG[1, 1] = 0; SCP[1, 2] = "functions"
  SCG[1, 2] = 0; SCP[1, 3] = "^.*$"; SCG[1, 3] = 1; SCP[1, 4] = "index.ts"
  SCG[1, 4] = 0; SNAME[2] = "supabase/functions/*/index.js"; SCN[2] = 4; SCONT[2] = 0
  SROLE[2] = "supafn"; SCP[2, 1] = "supabase"; SCG[2, 1] = 0; SCP[2, 2] = "functions"
  SCG[2, 2] = 0; SCP[2, 3] = "^.*$"; SCG[2, 3] = 1; SCP[2, 4] = "index.js"
  SCG[2, 4] = 0; SNAME[3] = "src/main/AndroidManifest.xml"; SCN[3] = 3; SCONT[3] = 0
  SROLE[3] = "amanifest"; SCP[3, 1] = "src"; SCG[3, 1] = 0; SCP[3, 2] = "main"
  SCG[3, 2] = 0; SCP[3, 3] = "AndroidManifest.xml"; SCG[3, 3] = 0; SNAME[4] = "src/bin/*.rs"
  SCN[4] = 3; SCONT[4] = 0; SROLE[4] = "rustbin"; SCP[4, 1] = "src"
  SCG[4, 1] = 0; SCP[4, 2] = "bin"; SCG[4, 2] = 0; SCP[4, 3] = "^.*[.]rs$"
  SCG[4, 3] = 1; SNAME[5] = "requirements/*.txt"; SCN[5] = 2; SCONT[5] = 1
  SROLE[5] = "py"; SCP[5, 1] = "requirements"; SCG[5, 1] = 0; SCP[5, 2] = "^.*[.]txt$"
  SCG[5, 2] = 1; SNAME[6] = "fastlane/Fastfile"; SCN[6] = 2; SCONT[6] = 0
  SROLE[6] = "nativetool"; SCP[6, 1] = "fastlane"; SCG[6, 1] = 0; SCP[6, 2] = "Fastfile"
  SCG[6, 2] = 0; SNAME[7] = "src/main.rs"; SCN[7] = 2; SCONT[7] = 0
  SROLE[7] = "rustbin"; SCP[7, 1] = "src"; SCG[7, 1] = 0; SCP[7, 2] = "main.rs"
  SCG[7, 2] = 0; SNAME[8] = "src-tauri/tauri.conf.*"; SCN[8] = 2; SCONT[8] = 0
  SROLE[8] = "shell"; SCP[8, 1] = "src-tauri"; SCG[8, 1] = 0; SCP[8, 2] = "^tauri[.]conf[.].*$"
  SCG[8, 2] = 1; SNAME[9] = "src-tauri/Tauri.toml"; SCN[9] = 2; SCONT[9] = 0
  SROLE[9] = "shell"; SCP[9, 1] = "src-tauri"; SCG[9, 1] = 0; SCP[9, 2] = "Tauri.toml"
  SCG[9, 2] = 0; SNAME[10] = "ProjectSettings/ProjectVersion.txt"; SCN[10] = 2; SCONT[10] = 0
  SROLE[10] = "shell"; SCP[10, 1] = "ProjectSettings"; SCG[10, 1] = 0; SCP[10, 2] = "ProjectVersion.txt"
  SCG[10, 2] = 0; SNAME[11] = "public/manifest.json"; SCN[11] = 2; SCONT[11] = 1
  SROLE[11] = "extmanifest"; SCP[11, 1] = "public"; SCG[11, 1] = 0; SCP[11, 2] = "manifest.json"
  SCG[11, 2] = 0; SNAME[12] = "src/manifest.json"; SCN[12] = 2; SCONT[12] = 1
  SROLE[12] = "extmanifest"; SCP[12, 1] = "src"; SCG[12, 1] = 0; SCP[12, 2] = "manifest.json"
  SCG[12, 2] = 0; SNAME[13] = "static/manifest.json"; SCN[13] = 2; SCONT[13] = 1
  SROLE[13] = "extmanifest"; SCP[13, 1] = "static"; SCG[13, 1] = 0; SCP[13, 2] = "manifest.json"
  SCG[13, 2] = 0; SNAME[14] = "package.json"; SCN[14] = 1; SCONT[14] = 1
  SROLE[14] = "npm"; SCP[14, 1] = "package.json"; SCG[14, 1] = 0; SNAME[15] = "pnpm-workspace.yaml"
  SCN[15] = 1; SCONT[15] = 0; SROLE[15] = "wsroot"; SCP[15, 1] = "pnpm-workspace.yaml"
  SCG[15, 1] = 0; SNAME[16] = "lerna.json"; SCN[16] = 1; SCONT[16] = 0
  SROLE[16] = "wsroot"; SCP[16, 1] = "lerna.json"; SCG[16, 1] = 0; SNAME[17] = "turbo.json"
  SCN[17] = 1; SCONT[17] = 0; SROLE[17] = "wsroot"; SCP[17, 1] = "turbo.json"
  SCG[17, 1] = 0; SNAME[18] = "nx.json"; SCN[18] = 1; SCONT[18] = 0
  SROLE[18] = "wsroot"; SCP[18, 1] = "nx.json"; SCG[18, 1] = 0; SNAME[19] = "rush.json"
  SCN[19] = 1; SCONT[19] = 0; SROLE[19] = "wsroot"; SCP[19, 1] = "rush.json"
  SCG[19, 1] = 0; SNAME[20] = "project.json"; SCN[20] = 1; SCONT[20] = 1
  SROLE[20] = "nx"; SCP[20, 1] = "project.json"; SCG[20, 1] = 0; SNAME[21] = "bun.lock"
  SCN[21] = 1; SCONT[21] = 0; SROLE[21] = "bun"; SCP[21, 1] = "bun.lock"
  SCG[21, 1] = 0; SNAME[22] = "bun.lockb"; SCN[22] = 1; SCONT[22] = 0
  SROLE[22] = "bun"; SCP[22, 1] = "bun.lockb"; SCG[22, 1] = 0; SNAME[23] = "bunfig.toml"
  SCN[23] = 1; SCONT[23] = 0; SROLE[23] = "bun"; SCP[23, 1] = "bunfig.toml"
  SCG[23, 1] = 0; SNAME[24] = "wrangler.toml"; SCN[24] = 1; SCONT[24] = 0
  SROLE[24] = "wrangler"; SCP[24, 1] = "wrangler.toml"; SCG[24, 1] = 0; SNAME[25] = "wrangler.json"
  SCN[25] = 1; SCONT[25] = 0; SROLE[25] = "wrangler"; SCP[25, 1] = "wrangler.json"
  SCG[25, 1] = 0; SNAME[26] = "wrangler.jsonc"; SCN[26] = 1; SCONT[26] = 0
  SROLE[26] = "wrangler"; SCP[26, 1] = "wrangler.jsonc"; SCG[26, 1] = 0; SNAME[27] = "deno.json"
  SCN[27] = 1; SCONT[27] = 0; SROLE[27] = "deno"; SCP[27, 1] = "deno.json"
  SCG[27, 1] = 0; SNAME[28] = "deno.jsonc"; SCN[28] = 1; SCONT[28] = 0
  SROLE[28] = "deno"; SCP[28, 1] = "deno.jsonc"; SCG[28, 1] = 0; SNAME[29] = "build.gradle"
  SCN[29] = 1; SCONT[29] = 1; SROLE[29] = "gradle"; SCP[29, 1] = "build.gradle"
  SCG[29, 1] = 0; SNAME[30] = "build.gradle.kts"; SCN[30] = 1; SCONT[30] = 1
  SROLE[30] = "gradle"; SCP[30, 1] = "build.gradle.kts"; SCG[30, 1] = 0; SNAME[31] = "settings.gradle"
  SCN[31] = 1; SCONT[31] = 0; SROLE[31] = "gsettings"; SCP[31, 1] = "settings.gradle"
  SCG[31, 1] = 0; SNAME[32] = "settings.gradle.kts"; SCN[32] = 1; SCONT[32] = 0
  SROLE[32] = "gsettings"; SCP[32, 1] = "settings.gradle.kts"; SCG[32, 1] = 0; SNAME[33] = "pom.xml"
  SCN[33] = 1; SCONT[33] = 1; SROLE[33] = "maven"; SCP[33, 1] = "pom.xml"
  SCG[33, 1] = 0; SNAME[34] = "requirements.txt"; SCN[34] = 1; SCONT[34] = 1
  SROLE[34] = "py"; SCP[34, 1] = "requirements.txt"; SCG[34, 1] = 0; SNAME[35] = "pyproject.toml"
  SCN[35] = 1; SCONT[35] = 1; SROLE[35] = "py"; SCP[35, 1] = "pyproject.toml"
  SCG[35, 1] = 0; SNAME[36] = "Pipfile"; SCN[36] = 1; SCONT[36] = 1
  SROLE[36] = "py"; SCP[36, 1] = "Pipfile"; SCG[36, 1] = 0; SNAME[37] = "setup.py"
  SCN[37] = 1; SCONT[37] = 0; SROLE[37] = "py"; SCP[37, 1] = "setup.py"
  SCG[37, 1] = 0; SNAME[38] = "setup.cfg"; SCN[38] = 1; SCONT[38] = 0
  SROLE[38] = "py"; SCP[38, 1] = "setup.cfg"; SCG[38, 1] = 0; SNAME[39] = "manage.py"
  SCN[39] = 1; SCONT[39] = 0; SROLE[39] = "pymanage"; SCP[39, 1] = "manage.py"
  SCG[39, 1] = 0; SNAME[40] = "go.mod"; SCN[40] = 1; SCONT[40] = 1
  SROLE[40] = "go"; SCP[40, 1] = "go.mod"; SCG[40, 1] = 0; SNAME[41] = "go.work"
  SCN[41] = 1; SCONT[41] = 0; SROLE[41] = "wsroot"; SCP[41, 1] = "go.work"
  SCG[41, 1] = 0; SNAME[42] = "composer.json"; SCN[42] = 1; SCONT[42] = 1
  SROLE[42] = "composer"; SCP[42, 1] = "composer.json"; SCG[42, 1] = 0; SNAME[43] = "index.php"
  SCN[43] = 1; SCONT[43] = 0; SROLE[43] = "phpindex"; SCP[43, 1] = "index.php"
  SCG[43, 1] = 0; SNAME[44] = "wp-config.php"; SCN[44] = 1; SCONT[44] = 0
  SROLE[44] = "wpconfig"; SCP[44, 1] = "wp-config.php"; SCG[44, 1] = 0; SNAME[45] = "artisan"
  SCN[45] = 1; SCONT[45] = 0; SROLE[45] = "artisan"; SCP[45, 1] = "artisan"
  SCG[45, 1] = 0; SNAME[46] = "Gemfile"; SCN[46] = 1; SCONT[46] = 1
  SROLE[46] = "gemfile"; SCP[46, 1] = "Gemfile"; SCG[46, 1] = 0; SNAME[47] = "config.ru"
  SCN[47] = 1; SCONT[47] = 0; SROLE[47] = "configru"; SCP[47, 1] = "config.ru"
  SCG[47, 1] = 0; SNAME[48] = "Podfile"; SCN[48] = 1; SCONT[48] = 0
  SROLE[48] = "nativetool"; SCP[48, 1] = "Podfile"; SCG[48, 1] = 0; SNAME[49] = "Cargo.toml"
  SCN[49] = 1; SCONT[49] = 1; SROLE[49] = "cargo"; SCP[49, 1] = "Cargo.toml"
  SCG[49, 1] = 0; SNAME[50] = "Trunk.toml"; SCN[50] = 1; SCONT[50] = 0
  SROLE[50] = "trunk"; SCP[50, 1] = "Trunk.toml"; SCG[50, 1] = 0; SNAME[51] = "mix.exs"
  SCN[51] = 1; SCONT[51] = 1; SROLE[51] = "mix"; SCP[51, 1] = "mix.exs"
  SCG[51, 1] = 0; SNAME[52] = "pubspec.yaml"; SCN[52] = 1; SCONT[52] = 1
  SROLE[52] = "pubspec"; SCP[52, 1] = "pubspec.yaml"; SCG[52, 1] = 0; SNAME[53] = "project.yml"
  SCN[53] = 1; SCONT[53] = 1; SROLE[53] = "xcodegen"; SCP[53, 1] = "project.yml"
  SCG[53, 1] = 0; SNAME[54] = "Project.swift"; SCN[54] = 1; SCONT[54] = 1
  SROLE[54] = "tuist"; SCP[54, 1] = "Project.swift"; SCG[54, 1] = 0; SNAME[55] = "Package.swift"
  SCN[55] = 1; SCONT[55] = 1; SROLE[55] = "swiftpm"; SCP[55, 1] = "Package.swift"
  SCG[55, 1] = 0; SNAME[56] = "vercel.json"; SCN[56] = 1; SCONT[56] = 0
  SROLE[56] = "host"; SCP[56, 1] = "vercel.json"; SCG[56, 1] = 0; SNAME[57] = "netlify.toml"
  SCN[57] = 1; SCONT[57] = 0; SROLE[57] = "host"; SCP[57, 1] = "netlify.toml"
  SCG[57, 1] = 0; SNAME[58] = "firebase.json"; SCN[58] = 1; SCONT[58] = 0
  SROLE[58] = "host"; SCP[58, 1] = "firebase.json"; SCG[58, 1] = 0; SNAME[59] = "host.json"
  SCN[59] = 1; SCONT[59] = 1; SROLE[59] = "hostprobe"; SCP[59, 1] = "host.json"
  SCG[59, 1] = 0; SNAME[60] = "serverless.yml"; SCN[60] = 1; SCONT[60] = 0
  SROLE[60] = "host"; SCP[60, 1] = "serverless.yml"; SCG[60, 1] = 0; SNAME[61] = "serverless.yaml"
  SCN[61] = 1; SCONT[61] = 0; SROLE[61] = "host"; SCP[61, 1] = "serverless.yaml"
  SCG[61, 1] = 0; SNAME[62] = "serverless.ts"; SCN[62] = 1; SCONT[62] = 0
  SROLE[62] = "host"; SCP[62, 1] = "serverless.ts"; SCG[62, 1] = 0; SNAME[63] = "samconfig.toml"
  SCN[63] = 1; SCONT[63] = 0; SROLE[63] = "host"; SCP[63, 1] = "samconfig.toml"
  SCG[63, 1] = 0; SNAME[64] = "template.yaml"; SCN[64] = 1; SCONT[64] = 1
  SROLE[64] = "hostprobe"; SCP[64, 1] = "template.yaml"; SCG[64, 1] = 0; SNAME[65] = "template.yml"
  SCN[65] = 1; SCONT[65] = 1; SROLE[65] = "hostprobe"; SCP[65, 1] = "template.yml"
  SCG[65, 1] = 0; SNAME[66] = "cdk.json"; SCN[66] = 1; SCONT[66] = 0
  SROLE[66] = "infra"; SCP[66, 1] = "cdk.json"; SCG[66, 1] = 0; SNAME[67] = "cdktf.json"
  SCN[67] = 1; SCONT[67] = 0; SROLE[67] = "infra"; SCP[67, 1] = "cdktf.json"
  SCG[67, 1] = 0; SNAME[68] = "Pulumi.yaml"; SCN[68] = 1; SCONT[68] = 0
  SROLE[68] = "infra"; SCP[68, 1] = "Pulumi.yaml"; SCG[68, 1] = 0; SNAME[69] = "Pulumi.yml"
  SCN[69] = 1; SCONT[69] = 0; SROLE[69] = "infra"; SCP[69, 1] = "Pulumi.yml"
  SCG[69, 1] = 0; SNAME[70] = "sst.config.ts"; SCN[70] = 1; SCONT[70] = 0
  SROLE[70] = "infra"; SCP[70, 1] = "sst.config.ts"; SCG[70, 1] = 0; SNAME[71] = "action.yml"
  SCN[71] = 1; SCONT[71] = 0; SROLE[71] = "ciaction"; SCP[71, 1] = "action.yml"
  SCG[71, 1] = 0; SNAME[72] = "action.yaml"; SCN[72] = 1; SCONT[72] = 0
  SROLE[72] = "ciaction"; SCP[72, 1] = "action.yaml"; SCG[72, 1] = 0; SNAME[73] = "foundry.toml"
  SCN[73] = 1; SCONT[73] = 0; SROLE[73] = "contract"; SCP[73, 1] = "foundry.toml"
  SCG[73, 1] = 0; SNAME[74] = "truffle-config.js"; SCN[74] = 1; SCONT[74] = 0
  SROLE[74] = "contract"; SCP[74, 1] = "truffle-config.js"; SCG[74, 1] = 0; SNAME[75] = "mkdocs.yml"
  SCN[75] = 1; SCONT[75] = 0; SROLE[75] = "ssg"; SCP[75, 1] = "mkdocs.yml"
  SCG[75, 1] = 0; SNAME[76] = "mkdocs.yaml"; SCN[76] = 1; SCONT[76] = 0
  SROLE[76] = "ssg"; SCP[76, 1] = "mkdocs.yaml"; SCG[76, 1] = 0; SNAME[77] = "_config.yml"
  SCN[77] = 1; SCONT[77] = 0; SROLE[77] = "ssg"; SCP[77, 1] = "_config.yml"
  SCG[77, 1] = 0; SNAME[78] = "hugo.toml"; SCN[78] = 1; SCONT[78] = 0
  SROLE[78] = "ssg"; SCP[78, 1] = "hugo.toml"; SCG[78, 1] = 0; SNAME[79] = "hugo.yaml"
  SCN[79] = 1; SCONT[79] = 0; SROLE[79] = "ssg"; SCP[79, 1] = "hugo.yaml"
  SCG[79, 1] = 0; SNAME[80] = "hugo.json"; SCN[80] = 1; SCONT[80] = 0
  SROLE[80] = "ssg"; SCP[80, 1] = "hugo.json"; SCG[80, 1] = 0; SNAME[81] = ".eleventy.js"
  SCN[81] = 1; SCONT[81] = 0; SROLE[81] = "ssg"; SCP[81, 1] = ".eleventy.js"
  SCG[81, 1] = 0; SNAME[82] = "pelicanconf.py"; SCN[82] = 1; SCONT[82] = 0
  SROLE[82] = "ssg"; SCP[82, 1] = "pelicanconf.py"; SCG[82, 1] = 0; SNAME[83] = "book.toml"
  SCN[83] = 1; SCONT[83] = 0; SROLE[83] = "ssg"; SCP[83, 1] = "book.toml"
  SCG[83, 1] = 0; SNAME[84] = "ionic.config.json"; SCN[84] = 1; SCONT[84] = 0
  SROLE[84] = "shell"; SCP[84, 1] = "ionic.config.json"; SCG[84, 1] = 0; SNAME[85] = "wails.json"
  SCN[85] = 1; SCONT[85] = 0; SROLE[85] = "shell"; SCP[85, 1] = "wails.json"
  SCG[85, 1] = 0; SNAME[86] = "project.godot"; SCN[86] = 1; SCONT[86] = 0
  SROLE[86] = "shell"; SCP[86, 1] = "project.godot"; SCG[86, 1] = 0; SNAME[87] = "manifest.json"
  SCN[87] = 1; SCONT[87] = 1; SROLE[87] = "extmanifest"; SCP[87, 1] = "manifest.json"
  SCG[87, 1] = 0; SNAME[88] = "build.sbt"; SCN[88] = 1; SCONT[88] = 0
  SROLE[88] = "lang"; SCP[88, 1] = "build.sbt"; SCG[88, 1] = 0; SNAME[89] = "build.sc"
  SCN[89] = 1; SCONT[89] = 0; SROLE[89] = "lang"; SCP[89, 1] = "build.sc"
  SCG[89, 1] = 0; SNAME[90] = "project.clj"; SCN[90] = 1; SCONT[90] = 0
  SROLE[90] = "lang"; SCP[90, 1] = "project.clj"; SCG[90, 1] = 0; SNAME[91] = "deps.edn"
  SCN[91] = 1; SCONT[91] = 0; SROLE[91] = "lang"; SCP[91, 1] = "deps.edn"
  SCG[91, 1] = 0; SNAME[92] = "rebar.config"; SCN[92] = 1; SCONT[92] = 0
  SROLE[92] = "lang"; SCP[92, 1] = "rebar.config"; SCG[92, 1] = 0; SNAME[93] = "gleam.toml"
  SCN[93] = 1; SCONT[93] = 0; SROLE[93] = "lang"; SCP[93, 1] = "gleam.toml"
  SCG[93, 1] = 0; SNAME[94] = "renv.lock"; SCN[94] = 1; SCONT[94] = 0
  SROLE[94] = "lang"; SCP[94, 1] = "renv.lock"; SCG[94, 1] = 0; SNAME[95] = "CMakeLists.txt"
  SCN[95] = 1; SCONT[95] = 0; SROLE[95] = "lang"; SCP[95, 1] = "CMakeLists.txt"
  SCG[95, 1] = 0; SNAME[96] = "meson.build"; SCN[96] = 1; SCONT[96] = 0
  SROLE[96] = "lang"; SCP[96, 1] = "meson.build"; SCG[96, 1] = 0; SNAME[97] = "conanfile.txt"
  SCN[97] = 1; SCONT[97] = 0; SROLE[97] = "lang"; SCP[97, 1] = "conanfile.txt"
  SCG[97, 1] = 0; SNAME[98] = "vcpkg.json"; SCN[98] = 1; SCONT[98] = 0
  SROLE[98] = "lang"; SCP[98, 1] = "vcpkg.json"; SCG[98, 1] = 0; SNAME[99] = "stack.yaml"
  SCN[99] = 1; SCONT[99] = 0; SROLE[99] = "lang"; SCP[99, 1] = "stack.yaml"
  SCG[99, 1] = 0; SNAME[100] = "cabal.project"; SCN[100] = 1; SCONT[100] = 0
  SROLE[100] = "lang"; SCP[100, 1] = "cabal.project"; SCG[100, 1] = 0; SNAME[101] = "dune-project"
  SCN[101] = 1; SCONT[101] = 0; SROLE[101] = "lang"; SCP[101, 1] = "dune-project"
  SCG[101, 1] = 0; SNAME[102] = "build.zig"; SCN[102] = 1; SCONT[102] = 0
  SROLE[102] = "lang"; SCP[102, 1] = "build.zig"; SCG[102, 1] = 0; SNAME[103] = "shard.yml"
  SCN[103] = 1; SCONT[103] = 0; SROLE[103] = "lang"; SCP[103, 1] = "shard.yml"
  SCG[103, 1] = 0; SNAME[104] = "Project.toml"; SCN[104] = 1; SCONT[104] = 0
  SROLE[104] = "lang"; SCP[104, 1] = "Project.toml"; SCG[104, 1] = 0; SNAME[105] = "cpanfile"
  SCN[105] = 1; SCONT[105] = 0; SROLE[105] = "lang"; SCP[105, 1] = "cpanfile"
  SCG[105, 1] = 0; SNAME[106] = "Makefile.PL"; SCN[106] = 1; SCONT[106] = 0
  SROLE[106] = "lang"; SCP[106, 1] = "Makefile.PL"; SCG[106, 1] = 0; SNAME[107] = "WORKSPACE"
  SCN[107] = 1; SCONT[107] = 0; SROLE[107] = "blind"; SCP[107, 1] = "WORKSPACE"
  SCG[107, 1] = 0; SNAME[108] = "WORKSPACE.bazel"; SCN[108] = 1; SCONT[108] = 0
  SROLE[108] = "blind"; SCP[108, 1] = "WORKSPACE.bazel"; SCG[108, 1] = 0; SNAME[109] = "MODULE.bazel"
  SCN[109] = 1; SCONT[109] = 0; SROLE[109] = "blind"; SCP[109, 1] = "MODULE.bazel"
  SCG[109, 1] = 0; SNAME[110] = "BUILD.bazel"; SCN[110] = 1; SCONT[110] = 0
  SROLE[110] = "blind"; SCP[110, 1] = "BUILD.bazel"; SCG[110, 1] = 0; SNAME[111] = "Dockerfile"
  SCN[111] = 1; SCONT[111] = 0; SROLE[111] = "blind"; SCP[111, 1] = "Dockerfile"
  SCG[111, 1] = 0; SNAME[112] = "Containerfile"; SCN[112] = 1; SCONT[112] = 0
  SROLE[112] = "blind"; SCP[112, 1] = "Containerfile"; SCG[112, 1] = 0; SNAME[113] = "requirements-*.txt"
  SCN[113] = 1; SCONT[113] = 1; SROLE[113] = "py"; SCP[113, 1] = "^requirements-.*[.]txt$"
  SCG[113, 1] = 1; SNAME[114] = "*.ipynb"; SCN[114] = 1; SCONT[114] = 0
  SROLE[114] = "notebook"; SCP[114, 1] = "^.*[.]ipynb$"; SCG[114, 1] = 1; SNAME[115] = "*.csproj"
  SCN[115] = 1; SCONT[115] = 1; SROLE[115] = "dotnet"; SCP[115, 1] = "^.*[.]csproj$"
  SCG[115, 1] = 1; SNAME[116] = "*.fsproj"; SCN[116] = 1; SCONT[116] = 1
  SROLE[116] = "dotnet"; SCP[116, 1] = "^.*[.]fsproj$"; SCG[116, 1] = 1; SNAME[117] = "*.vbproj"
  SCN[117] = 1; SCONT[117] = 1; SROLE[117] = "dotnet"; SCP[117, 1] = "^.*[.]vbproj$"
  SCG[117, 1] = 1; SNAME[118] = "*.sln"; SCN[118] = 1; SCONT[118] = 0
  SROLE[118] = "sln"; SCP[118, 1] = "^.*[.]sln$"; SCG[118, 1] = 1; SNAME[119] = "*.slnx"
  SCN[119] = 1; SCONT[119] = 0; SROLE[119] = "sln"; SCP[119, 1] = "^.*[.]slnx$"
  SCG[119, 1] = 1; SNAME[120] = "*.gemspec"; SCN[120] = 1; SCONT[120] = 0
  SROLE[120] = "gemspec"; SCP[120, 1] = "^.*[.]gemspec$"; SCG[120, 1] = 1; SNAME[121] = "*.xcodeproj"
  SCN[121] = 1; SCONT[121] = 0; SROLE[121] = "xcode"; SCP[121, 1] = "^.*[.]xcodeproj$"
  SCG[121, 1] = 1; SNAME[122] = "*.xcworkspace"; SCN[122] = 1; SCONT[122] = 0
  SROLE[122] = "xcode"; SCP[122, 1] = "^.*[.]xcworkspace$"; SCG[122, 1] = 1; SNAME[123] = "hardhat.config.*"
  SCN[123] = 1; SCONT[123] = 0; SROLE[123] = "contract"; SCP[123, 1] = "^hardhat[.]config[.].*$"
  SCG[123, 1] = 1; SNAME[124] = "eleventy.config.*"; SCN[124] = 1; SCONT[124] = 0
  SROLE[124] = "ssg"; SCP[124, 1] = "^eleventy[.]config[.].*$"; SCG[124, 1] = 1; SNAME[125] = "*.html"
  SCN[125] = 1; SCONT[125] = 0; SROLE[125] = "page"; SCP[125, 1] = "^.*[.]html$"
  SCG[125, 1] = 1; SNAME[126] = "*.htm"; SCN[126] = 1; SCONT[126] = 0
  SROLE[126] = "page"; SCP[126, 1] = "^.*[.]htm$"; SCG[126, 1] = 1; SNAME[127] = "*.erb"
  SCN[127] = 1; SCONT[127] = 0; SROLE[127] = "tpl"; SCP[127, 1] = "^.*[.]erb$"
  SCG[127, 1] = 1; SNAME[128] = "*.haml"; SCN[128] = 1; SCONT[128] = 0
  SROLE[128] = "tpl"; SCP[128, 1] = "^.*[.]haml$"; SCG[128, 1] = 1; SNAME[129] = "*.slim"
  SCN[129] = 1; SCONT[129] = 0; SROLE[129] = "tpl"; SCP[129, 1] = "^.*[.]slim$"
  SCG[129, 1] = 1; SNAME[130] = "*.blade.php"; SCN[130] = 1; SCONT[130] = 0
  SROLE[130] = "tpl"; SCP[130, 1] = "^.*[.]blade[.]php$"; SCG[130, 1] = 1; SNAME[131] = "*.twig"
  SCN[131] = 1; SCONT[131] = 0; SROLE[131] = "tpl"; SCP[131, 1] = "^.*[.]twig$"
  SCG[131, 1] = 1; SNAME[132] = "*.heex"; SCN[132] = 1; SCONT[132] = 0
  SROLE[132] = "tpl"; SCP[132, 1] = "^.*[.]heex$"; SCG[132, 1] = 1; SNAME[133] = "*.eex"
  SCN[133] = 1; SCONT[133] = 0; SROLE[133] = "tpl"; SCP[133, 1] = "^.*[.]eex$"
  SCG[133, 1] = 1; SNAME[134] = "*.cshtml"; SCN[134] = 1; SCONT[134] = 0
  SROLE[134] = "tpl"; SCP[134, 1] = "^.*[.]cshtml$"; SCG[134, 1] = 1; SNAME[135] = "*.razor"
  SCN[135] = 1; SCONT[135] = 0; SROLE[135] = "tpl"; SCP[135, 1] = "^.*[.]razor$"
  SCG[135, 1] = 1; SNAME[136] = "*.jinja"; SCN[136] = 1; SCONT[136] = 0
  SROLE[136] = "tpl"; SCP[136, 1] = "^.*[.]jinja$"; SCG[136, 1] = 1; SNAME[137] = "*.jinja2"
  SCN[137] = 1; SCONT[137] = 0; SROLE[137] = "tpl"; SCP[137, 1] = "^.*[.]jinja2$"
  SCG[137, 1] = 1; SNAME[138] = "*.j2"; SCN[138] = 1; SCONT[138] = 0
  SROLE[138] = "tpl"; SCP[138, 1] = "^.*[.]j2$"; SCG[138, 1] = 1; SNAME[139] = "*.hbs"
  SCN[139] = 1; SCONT[139] = 0; SROLE[139] = "tpl"; SCP[139, 1] = "^.*[.]hbs$"
  SCG[139, 1] = 1; SNAME[140] = "*.handlebars"; SCN[140] = 1; SCONT[140] = 0
  SROLE[140] = "tpl"; SCP[140, 1] = "^.*[.]handlebars$"; SCG[140, 1] = 1; SNAME[141] = "*.ejs"
  SCN[141] = 1; SCONT[141] = 0; SROLE[141] = "tpl"; SCP[141, 1] = "^.*[.]ejs$"
  SCG[141, 1] = 1; SNAME[142] = "*.pug"; SCN[142] = 1; SCONT[142] = 0
  SROLE[142] = "tpl"; SCP[142, 1] = "^.*[.]pug$"; SCG[142, 1] = 1; SNAME[143] = "*.njk"
  SCN[143] = 1; SCONT[143] = 0; SROLE[143] = "tpl"; SCP[143, 1] = "^.*[.]njk$"
  SCG[143, 1] = 1; SNAME[144] = "*.liquid"; SCN[144] = 1; SCONT[144] = 0
  SROLE[144] = "tpl"; SCP[144, 1] = "^.*[.]liquid$"; SCG[144, 1] = 1; SNAME[145] = "*.mustache"
  SCN[145] = 1; SCONT[145] = 0; SROLE[145] = "tpl"; SCP[145, 1] = "^.*[.]mustache$"
  SCG[145, 1] = 1; SNAME[146] = "*.gohtml"; SCN[146] = 1; SCONT[146] = 0
  SROLE[146] = "tpl"; SCP[146, 1] = "^.*[.]gohtml$"; SCG[146, 1] = 1; SNAME[147] = "*.tmpl"
  SCN[147] = 1; SCONT[147] = 0; SROLE[147] = "tpl"; SCP[147, 1] = "^.*[.]tmpl$"
  SCG[147, 1] = 1; SNAME[148] = "*.jsp"; SCN[148] = 1; SCONT[148] = 0
  SROLE[148] = "tpl"; SCP[148, 1] = "^.*[.]jsp$"; SCG[148, 1] = 1; SNAME[149] = "*.ftl"
  SCN[149] = 1; SCONT[149] = 0; SROLE[149] = "tpl"; SCP[149, 1] = "^.*[.]ftl$"
  SCG[149, 1] = 1; SNAME[150] = "capacitor.config.*"; SCN[150] = 1; SCONT[150] = 0
  SROLE[150] = "shell"; SCP[150, 1] = "^capacitor[.]config[.].*$"; SCG[150, 1] = 1; SNAME[151] = "nativescript.config.*"
  SCN[151] = 1; SCONT[151] = 0; SROLE[151] = "shell"; SCP[151, 1] = "^nativescript[.]config[.].*$"
  SCG[151, 1] = 1; SNAME[152] = "*.Rproj"; SCN[152] = 1; SCONT[152] = 0
  SROLE[152] = "lang"; SCP[152, 1] = "^.*[.]rproj$"; SCG[152, 1] = 1; SNAME[153] = "*.cabal"
  SCN[153] = 1; SCONT[153] = 0; SROLE[153] = "lang"; SCP[153, 1] = "^.*[.]cabal$"
  SCG[153, 1] = 1; SNAME[154] = "*.nimble"; SCN[154] = 1; SCONT[154] = 0
  SROLE[154] = "lang"; SCP[154, 1] = "^.*[.]nimble$"; SCG[154, 1] = 1; SNAME[155] = "*.rockspec"
  SCN[155] = 1; SCONT[155] = 0; SROLE[155] = "lang"; SCP[155, 1] = "^.*[.]rockspec$"
  SCG[155, 1] = 1
  # Dependency names a manifest may carry, and the marker each one means.
  DX["npm", "react-native"] = "react-native"; DX["npm", "expo"] = "expo"; DX["npm", "electron"] = "electron"
  DX["npm", "@nativescript/core"] = "@nativescript/core"; DX["npm", "@capacitor/core"] = "@capacitor/core"; DX["npm", "wxt"] = "wxt"
  DX["npm", "plasmo"] = "plasmo"; DX["npm", "@crxjs/vite-plugin"] = "@crxjs/vite-plugin"; DX["npm", "webextension-polyfill"] = "webextension-polyfill"
  DX["npm", "web-ext"] = "web-ext"; DX["npm", "next"] = "next"; DX["npm", "nuxt"] = "nuxt"
  DX["npm", "@sveltejs/kit"] = "@sveltejs/kit"; DX["npm", "@remix-run/node"] = "@remix-run/node"; DX["npm", "@remix-run/serve"] = "@remix-run/serve"
  DX["npm", "@remix-run/express"] = "@remix-run/express"; DX["npm", "@remix-run/react"] = "@remix-run/react"; DX["npm", "@angular/ssr"] = "@angular/ssr"
  DX["npm", "@nguniversal/express-engine"] = "@nguniversal/express-engine"; DX["npm", "@solidjs/start"] = "@solidjs/start"; DX["npm", "@analogjs/platform"] = "@analogjs/platform"
  DX["npm", "@tanstack/react-start"] = "@tanstack/react-start"; DX["npm", "@tanstack/start"] = "@tanstack/start"; DX["npm", "@builder.io/qwik-city"] = "@builder.io/qwik-city"
  DX["npm", "waku"] = "waku"; DX["npm", "react"] = "react"; DX["npm", "react-dom"] = "react-dom"
  DX["npm", "vue"] = "vue"; DX["npm", "svelte"] = "svelte"; DX["npm", "@angular/core"] = "@angular/core"
  DX["npm", "solid-js"] = "solid-js"; DX["npm", "preact"] = "preact"; DX["npm", "lit"] = "lit"
  DX["npm", "@builder.io/qwik"] = "@builder.io/qwik"; DX["npm", "ember-source"] = "ember-source"; DX["npm", "@redwoodjs/web"] = "@redwoodjs/web"
  DX["npm", "gatsby"] = "gatsby"; DX["npm", "astro"] = "astro"; DX["npm", "@docusaurus/core"] = "@docusaurus/core"
  DX["npm", "@11ty/eleventy"] = "@11ty/eleventy"; DX["npm", "vitepress"] = "vitepress"; DX["npm", "vuepress"] = "vuepress"
  DX["npm", "hexo"] = "hexo"; DX["npm", "vite"] = "vite"; DX["npm", "webpack"] = "webpack"
  DX["npm", "parcel"] = "parcel"; DX["npm", "@rspack/core"] = "@rspack/core"; DX["npm", "@rsbuild/core"] = "@rsbuild/core"
  DX["npm", "browserify"] = "browserify"; DX["npm", "snowpack"] = "snowpack"; DX["npm", "esbuild"] = "esbuild"
  DX["npm", "rollup"] = "rollup"; DX["npm", "express"] = "express"; DX["npm", "fastify"] = "fastify"
  DX["npm", "koa"] = "koa"; DX["npm", "@hapi/hapi"] = "@hapi/hapi"; DX["npm", "@nestjs/core"] = "@nestjs/core"
  DX["npm", "hono"] = "hono"; DX["npm", "restify"] = "restify"; DX["npm", "polka"] = "polka"
  DX["npm", "@adonisjs/core"] = "@adonisjs/core"; DX["npm", "sails"] = "sails"; DX["npm", "@feathersjs/feathers"] = "@feathersjs/feathers"
  DX["npm", "@loopback/core"] = "@loopback/core"; DX["npm", "h3"] = "h3"; DX["npm", "nitropack"] = "nitropack"
  DX["npm", "@apollo/server"] = "@apollo/server"; DX["npm", "apollo-server"] = "apollo-server"; DX["npm", "graphql-yoga"] = "graphql-yoga"
  DX["npm", "socket.io"] = "socket.io"; DX["npm", "micro"] = "micro"; DX["npm", "@redwoodjs/api"] = "@redwoodjs/api"
  DX["npm", "elysia"] = "elysia"; DP["npm", 1] = "@elysiajs/"; DPM["npm", 1] = "@elysiajs/*"
  DX["npm", "firebase-functions"] = "firebase-functions"; DX["npm", "@google-cloud/functions-framework"] = "@google-cloud/functions-framework"; DX["npm", "@azure/functions"] = "@azure/functions"
  DX["npm", "@netlify/functions"] = "@netlify/functions"; DX["npm", "@vercel/node"] = "@vercel/node"; DX["npm", "aws-cdk-lib"] = "aws-cdk-lib"
  DX["npm", "aws-cdk"] = "aws-cdk"; DX["npm", "cdktf"] = "cdktf"; DX["npm", "@pulumi/pulumi"] = "@pulumi/pulumi"
  DX["npm", "sst"] = "sst"; DX["npm", "hardhat"] = "hardhat"; DX["npm", "truffle"] = "truffle"
  DX["npm", "@playwright/test"] = "@playwright/test"; DX["npm", "playwright"] = "playwright"; DX["npm", "cypress"] = "cypress"
  DX["npm", "@wdio/cli"] = "@wdio/cli"; DX["npm", "webdriverio"] = "webdriverio"; DX["npm", "nightwatch"] = "nightwatch"
  DX["npm", "testcafe"] = "testcafe"; DX["npm", "detox"] = "detox"; DX["npm", "typescript"] = "typescript"
  DP["npm", 2] = "eslint"; DPM["npm", 2] = "eslint*"; DP["npm", 3] = "@eslint/"
  DPM["npm", 3] = "@eslint/*"; DP["npm", 4] = "@typescript-eslint/"; DPM["npm", 4] = "@typescript-eslint/*"
  DP["npm", 5] = "prettier"; DPM["npm", 5] = "prettier*"; DX["npm", "husky"] = "husky"
  DX["npm", "lint-staged"] = "lint-staged"; DP["npm", 6] = "@commitlint/"; DPM["npm", 6] = "@commitlint/*"
  DX["npm", "commitizen"] = "commitizen"; DP["npm", 7] = "cz-"; DPM["npm", 7] = "cz-*"
  DP["npm", 8] = "@changesets/"; DPM["npm", 8] = "@changesets/*"; DX["npm", "turbo"] = "turbo"
  DX["npm", "nx"] = "nx"; DP["npm", 9] = "@nx/"; DPM["npm", 9] = "@nx/*"
  DP["npm", 10] = "@nrwl/"; DPM["npm", 10] = "@nrwl/*"; DX["npm", "lerna"] = "lerna"
  DX["npm", "rimraf"] = "rimraf"; DP["npm", 11] = "npm-run-all"; DPM["npm", 11] = "npm-run-all*"
  DX["npm", "concurrently"] = "concurrently"; DX["npm", "cross-env"] = "cross-env"; DX["npm", "dotenv-cli"] = "dotenv-cli"
  DP["npm", 12] = "@types/"; DPM["npm", 12] = "@types/*"; DP["npm", 13] = "stylelint"
  DPM["npm", 13] = "stylelint*"; DP["npm", 14] = "@biomejs/"; DPM["npm", 14] = "@biomejs/*"
  DX["npm", "syncpack"] = "syncpack"; DX["npm", "knip"] = "knip"; DP["npm", 15] = "@manypkg/"
  DPM["npm", 15] = "@manypkg/*"; DX["npm", "tsup"] = "tsup"; DX["npm", "typedoc"] = "typedoc"
  DX["npm", "jest"] = "jest"; DX["npm", "vitest"] = "vitest"; DP["npm", 16] = "@vitest/"
  DPM["npm", 16] = "@vitest/*"; DX["npm", "mocha"] = "mocha"; DX["npm", "chai"] = "chai"
  DP["npm", 17] = "@testing-library/"; DPM["npm", 17] = "@testing-library/*"; DX["npm", "storybook"] = "storybook"
  DP["npm", 18] = "@storybook/"; DPM["npm", 18] = "@storybook/*"; DP["npm", 19] = "@tsconfig/"
  DPM["npm", 19] = "@tsconfig/*"; DP["npm", 20] = "@turbo/"; DPM["npm", 20] = "@turbo/*"
  DX["npm", "tsx"] = "tsx"; DX["npm", "ts-node"] = "ts-node"; DX["npm", "nodemon"] = "nodemon"
  DPN["npm"] = 20; DX["composer", "laravel/framework"] = "laravel"; DX["composer", "symfony/framework-bundle"] = "symfony"
  DX["composer", "symfony/symfony"] = "symfony"; DP["composer", 1] = "johnpbloch/wordpress"; DPM["composer", 1] = "wordpress"
  DP["composer", 2] = "roots/wordpress"; DPM["composer", 2] = "wordpress"; DX["composer", "slim/slim"] = "slim"
  DX["composer", "cakephp/cakephp"] = "cakephp"; DX["composer", "yiisoft/yii2"] = "yii"; DX["composer", "codeigniter4/framework"] = "codeigniter"
  DX["composer", "laminas/laminas-mvc"] = "laminas"; DP["composer", 3] = "drupal/core"; DPM["composer", 3] = "drupal"
  DP["composer", 4] = "magento/"; DPM["composer", 4] = "magento"; DPN["composer"] = 4
  DX["py", "django"] = "django"; DX["py", "flask"] = "flask"; DX["py", "fastapi"] = "fastapi"
  DX["py", "starlette"] = "starlette"; DX["py", "streamlit"] = "streamlit"; DX["py", "gradio"] = "gradio"
  DX["py", "dash"] = "dash"; DX["py", "aiohttp"] = "aiohttp"; DX["py", "tornado"] = "tornado"
  DX["py", "sanic"] = "sanic"; DX["py", "bottle"] = "bottle"; DX["py", "pyramid"] = "pyramid"
  DX["py", "litestar"] = "litestar"; DX["py", "quart"] = "quart"; DX["py", "falcon"] = "falcon"
  DX["py", "celery"] = "celery"; DX["py", "uvicorn"] = "uvicorn"; DX["py", "gunicorn"] = "gunicorn"
  DX["py", "panel"] = "panel"; DX["py", "nicegui"] = "nicegui"; DX["py", "reflex"] = "reflex"
  DX["py", "functions-framework"] = "functions-framework"; DX["py", "azure-functions"] = "azure-functions"; DX["py", "firebase-functions"] = "firebase-functions"
  DX["py", "chalice"] = "chalice"; DX["py", "zappa"] = "zappa"; DX["py", "mangum"] = "mangum"
  DX["py", "sphinx"] = "sphinx"; DX["py", "mkdocs"] = "mkdocs"; DX["py", "mkdocs-material"] = "mkdocs-material"
  DX["py", "pelican"] = "pelican"; DX["py", "jupyter"] = "jupyter"; DX["py", "notebook"] = "notebook"
  DX["py", "jupyterlab"] = "jupyterlab"; DX["py", "ipykernel"] = "ipykernel"; DX["py", "pytest"] = "pytest"
  DX["py", "selenium"] = "selenium"; DX["py", "playwright"] = "playwright"; DX["py", "behave"] = "behave"
  DX["py", "robotframework"] = "robotframework"; DX["py", "aws-cdk-lib"] = "aws-cdk-lib"; DX["py", "pulumi"] = "pulumi"
  DX["py", "cdktf"] = "cdktf"; DPN["py"] = 0; DX["gem", "rails"] = "rails"
  DX["gem", "sinatra"] = "sinatra"; DX["gem", "hanami"] = "hanami"; DX["gem", "roda"] = "roda"
  DX["gem", "grape"] = "grape"; DX["gem", "rack"] = "rack"; DX["gem", "padrino"] = "padrino"
  DX["gem", "puma"] = "puma"; DX["gem", "jekyll"] = "jekyll"; DX["gem", "middleman"] = "middleman"
  DX["gem", "cocoapods"] = "cocoapods"; DX["gem", "fastlane"] = "fastlane"; DX["gem", "rspec"] = "rspec"
  DX["gem", "capybara"] = "capybara"; DX["gem", "cucumber"] = "cucumber"; DX["gem", "minitest"] = "minitest"
  DPN["gem"] = 0; DX["cargo", "axum"] = "axum"; DX["cargo", "actix-web"] = "actix-web"
  DX["cargo", "rocket"] = "rocket"; DX["cargo", "warp"] = "warp"; DX["cargo", "poem"] = "poem"
  DX["cargo", "tide"] = "tide"; DX["cargo", "hyper"] = "hyper"; DX["cargo", "salvo"] = "salvo"
  DX["cargo", "tonic"] = "tonic"; DX["cargo", "lambda-runtime"] = "lambda_runtime"; DX["cargo", "yew"] = "yew"
  DX["cargo", "leptos"] = "leptos"; DX["cargo", "dioxus"] = "dioxus"; DX["cargo", "sycamore"] = "sycamore"
  DX["cargo", "seed"] = "seed"; DX["cargo", "tauri"] = "tauri"; DPN["cargo"] = 0
  DP["go", 1] = "github.com/gin-gonic/gin"; DPM["go", 1] = "gin"; DP["go", 2] = "github.com/labstack/echo"
  DPM["go", 2] = "echo"; DP["go", 3] = "github.com/gofiber/fiber"; DPM["go", 3] = "fiber"
  DP["go", 4] = "github.com/go-chi/chi"; DPM["go", 4] = "chi"; DP["go", 5] = "github.com/gorilla/mux"
  DPM["go", 5] = "gorilla-mux"; DP["go", 6] = "github.com/beego/beego"; DPM["go", 6] = "beego"
  DP["go", 7] = "github.com/gobuffalo/buffalo"; DPM["go", 7] = "buffalo"; DP["go", 8] = "connectrpc.com/connect"
  DPM["go", 8] = "connect"; DP["go", 9] = "github.com/aws/aws-lambda-go"; DPM["go", 9] = "aws-lambda-go"
  DP["go", 10] = "github.com/googlecloudplatform/functions-framework-go"; DPM["go", 10] = "functions-framework-go"; DP["go", 11] = "github.com/wailsapp/wails"
  DPM["go", 11] = "wails"; DPN["go"] = 11
  # Line rules: a marker is set when a lowercased line matches.
  LR["gradle", 1] = "android[._-]?application"; LRM["gradle", 1] = "android-app"
  LR["gradle", 2] = "android[._-]?(library|dynamic-feature|dynamicfeature)"; LRM["gradle", 2] = "android-lib"
  LR["gradle", 3] = "com\\.android\\.test|plugins\\.android\\.test"; LRM["gradle", 3] = "android-test"
  LR["gradle", 4] = "multiplatform"; LRM["gradle", 4] = "kmp"
  LR["gradle", 5] = "compose\\.desktop"; LRM["gradle", 5] = "compose-desktop"
  LR["gradle", 6] = "openjfx|javafx"; LRM["gradle", 6] = "javafx"
  LR["gradle", 7] = "java-library|java-platform|library-conventions|kotlin-library"; LRM["gradle", 7] = "jvm-lib"
  LR["gradle", 8] = "springframework\\.boot|io\\.ktor|ktor|micronaut|quarkus|vertx|javalin|dropwizard|helidon"; LRM["gradle", 8] = "jvm-server"
  LR["gradle", 9] = "[\"\047]application[\"\047]|^[ \t]*application[ \t]*([{(]|$)"; LRM["gradle", 9] = "jvm-app"
  LR["gradle", 10] = "kotlin-dsl"; LRM["gradle", 10] = "kotlin-dsl"
  LRN["gradle"] = 10; LR["maven", 1] = "<packaging>[ \t]*pom[ \t]*</packaging>"
  LRM["maven", 1] = "pom-packaging"; LR["maven", 2] = "<packaging>[ \t]*war[ \t]*</packaging>"
  LRM["maven", 2] = "war-packaging"; LR["maven", 3] = "openjfx"
  LRM["maven", 3] = "javafx"; LR["maven", 4] = "spring-boot|quarkus|micronaut|javalin|vertx|dropwizard|helidon|jetty|tomcat|jakarta\\.servlet|javax\\.servlet"
  LRM["maven", 4] = "jvm-server"; LRN["maven"] = 4
  LR["dotnet", 1] = "godot\\.net\\.sdk"; LRM["dotnet", 1] = "godot"
  LR["dotnet", 2] = "unityengine"; LRM["dotnet", 2] = "unity"
  LR["dotnet", 3] = "<usemaui>[ \t]*true"; LRM["dotnet", 3] = "maui"
  LR["dotnet", 4] = "sdk=\"microsoft\\.net\\.sdk\\.blazorwebassembly\""; LRM["dotnet", 4] = "blazor-wasm"
  LR["dotnet", 5] = "<usewpf>[ \t]*true"; LRM["dotnet", 5] = "wpf"
  LR["dotnet", 6] = "<usewindowsforms>[ \t]*true"; LRM["dotnet", 6] = "winforms"
  LR["dotnet", 7] = "microsoft\\.net\\.test\\.sdk|<istestproject>[ \t]*true|\"xunit|\"nunit|\"mstest"; LRM["dotnet", 7] = "test"
  LR["dotnet", 8] = "amazon\\.cdk|include=\"pulumi"; LRM["dotnet", 8] = "iac"
  LR["dotnet", 9] = "sdk=\"microsoft\\.net\\.sdk\\.web\""; LRM["dotnet", 9] = "web-sdk"
  LR["dotnet", 10] = "sdk=\"microsoft\\.net\\.sdk\\.worker\""; LRM["dotnet", 10] = "worker-sdk"
  LR["dotnet", 11] = "microsoft\\.net\\.sdk\\.functions|<azurefunctionsversion>|microsoft\\.azure\\.functions\\.worker"; LRM["dotnet", 11] = "functions"
  LR["dotnet", 12] = "microsoft\\.aspnetcore\\.app"; LRM["dotnet", 12] = "aspnet"
  LR["dotnet", 13] = "<outputtype>[ \t]*(win)?exe[ \t]*</outputtype>"; LRM["dotnet", 13] = "exe"
  LR["dotnet", 14] = "sdk=\"microsoft\\.net\\.sdk\\.razor\""; LRM["dotnet", 14] = "razor-sdk"
  LRN["dotnet"] = 14; LR["mix", 1] = "apps_path"
  LRM["mix", 1] = "umbrella"; LR["mix", 2] = "[{]:nerves[ \t]*,"
  LRM["mix", 2] = "nerves"; LR["mix", 3] = "[{]:phoenix[ \t]*,"
  LRM["mix", 3] = "phoenix"; LR["mix", 4] = "mod:[ \t]*[{]"
  LRM["mix", 4] = "app-module"; LR["mix", 5] = "[{]:(plug_cowboy|bandit|cowboy)[ \t]*,"
  LRM["mix", 5] = "plug-server"; LRN["mix"] = 5
  LR["pubspec", 1] = "^flutter:|sdk:[ \t]*flutter"; LRM["pubspec", 1] = "flutter"
  LR["pubspec", 2] = "^[ \t]+plugin:"; LRM["pubspec", 2] = "plugin"
  LRN["pubspec"] = 2; LR["xcodegen", 1] = "platform:.*(ios|tvos|watchos|visionos|macos)"
  LRM["xcodegen", 1] = "apple-platform"; LRN["xcodegen"] = 1
  LR["tuist", 1] = "import[ \t]+projectdescription"; LRM["tuist", 1] = "tuist"
  LRN["tuist"] = 1; LR["swiftpm", 1] = "\\.(ios|macos|tvos|watchos|visionos)[ \t]*\\("
  LRM["swiftpm", 1] = "apple-platform"; LR["swiftpm", 2] = "\\.executabletarget[ \t]*\\(|\\.executable[ \t]*\\(|\\.iosapplication[ \t]*\\("
  LRM["swiftpm", 2] = "executable"; LR["swiftpm", 3] = "\\.library[ \t]*\\("
  LRM["swiftpm", 3] = "library-product"; LR["swiftpm", 4] = "vapor|hummingbird|kitura"
  LRM["swiftpm", 4] = "swift-server"; LRN["swiftpm"] = 4
  LR["extmanifest", 1] = "\"manifest_version\"[ \t]*:"; LRM["extmanifest", 1] = "manifest-version"
  LRN["extmanifest"] = 1; LR["hostprobe", 1] = "extensionbundle|functiontimeout"
  LRM["hostprobe", 1] = "azure-functions"; LR["hostprobe", 2] = "aws::serverless"
  LRM["hostprobe", 2] = "aws-sam"; LRN["hostprobe"] = 2
  LR["nx", 1] = "\"projecttype\"[ \t]*:[ \t]*\"application\""; LRM["nx", 1] = "nx-app"
  LR["nx", 2] = "\"projecttype\"[ \t]*:[ \t]*\"library\""; LRM["nx", 2] = "nx-lib"
  LR["nx", 3] = "\"executor\"[ \t]*:[ \t]*\"[^\"]*(react-native|expo)"; LRM["nx", 3] = "nx-rn"
  LR["nx", 4] = "\"executor\"[ \t]*:[ \t]*\"@(nx|nrwl)/next:"; LRM["nx", 4] = "nx-next"
  LR["nx", 5] = "\"executor\"[ \t]*:[ \t]*\"[^\"]*(cypress|playwright)"; LRM["nx", 5] = "nx-e2e"
  LR["nx", 6] = "\"executor\"[ \t]*:[ \t]*\"[^\"]*(:node\"|node:execute|nest)"; LRM["nx", 6] = "nx-node"
  LR["nx", 7] = "\"executor\"[ \t]*:[ \t]*\"[^\"]*(dev-server|file-server)"; LRM["nx", 7] = "nx-web"
  LRN["nx"] = 7
  # Every marker a role can report, in the order the record lists them.
  MORD["npm", 1] = "react-native"; MORD["npm", 2] = "expo"; MORD["npm", 3] = "electron"; MORD["npm", 4] = "@nativescript/core"
  MORD["npm", 5] = "@capacitor/core"; MORD["npm", 6] = "wxt"; MORD["npm", 7] = "plasmo"; MORD["npm", 8] = "@crxjs/vite-plugin"
  MORD["npm", 9] = "webextension-polyfill"; MORD["npm", 10] = "web-ext"; MORD["npm", 11] = "next"; MORD["npm", 12] = "nuxt"
  MORD["npm", 13] = "@sveltejs/kit"; MORD["npm", 14] = "@remix-run/node"; MORD["npm", 15] = "@remix-run/serve"; MORD["npm", 16] = "@remix-run/express"
  MORD["npm", 17] = "@remix-run/react"; MORD["npm", 18] = "@angular/ssr"; MORD["npm", 19] = "@nguniversal/express-engine"; MORD["npm", 20] = "@solidjs/start"
  MORD["npm", 21] = "@analogjs/platform"; MORD["npm", 22] = "@tanstack/react-start"; MORD["npm", 23] = "@tanstack/start"; MORD["npm", 24] = "@builder.io/qwik-city"
  MORD["npm", 25] = "waku"; MORD["npm", 26] = "react"; MORD["npm", 27] = "react-dom"; MORD["npm", 28] = "vue"
  MORD["npm", 29] = "svelte"; MORD["npm", 30] = "@angular/core"; MORD["npm", 31] = "solid-js"; MORD["npm", 32] = "preact"
  MORD["npm", 33] = "lit"; MORD["npm", 34] = "@builder.io/qwik"; MORD["npm", 35] = "ember-source"; MORD["npm", 36] = "@redwoodjs/web"
  MORD["npm", 37] = "gatsby"; MORD["npm", 38] = "astro"; MORD["npm", 39] = "@docusaurus/core"; MORD["npm", 40] = "@11ty/eleventy"
  MORD["npm", 41] = "vitepress"; MORD["npm", 42] = "vuepress"; MORD["npm", 43] = "hexo"; MORD["npm", 44] = "vite"
  MORD["npm", 45] = "webpack"; MORD["npm", 46] = "parcel"; MORD["npm", 47] = "@rspack/core"; MORD["npm", 48] = "@rsbuild/core"
  MORD["npm", 49] = "browserify"; MORD["npm", 50] = "snowpack"; MORD["npm", 51] = "esbuild"; MORD["npm", 52] = "rollup"
  MORD["npm", 53] = "express"; MORD["npm", 54] = "fastify"; MORD["npm", 55] = "koa"; MORD["npm", 56] = "@hapi/hapi"
  MORD["npm", 57] = "@nestjs/core"; MORD["npm", 58] = "hono"; MORD["npm", 59] = "restify"; MORD["npm", 60] = "polka"
  MORD["npm", 61] = "@adonisjs/core"; MORD["npm", 62] = "sails"; MORD["npm", 63] = "@feathersjs/feathers"; MORD["npm", 64] = "@loopback/core"
  MORD["npm", 65] = "h3"; MORD["npm", 66] = "nitropack"; MORD["npm", 67] = "@apollo/server"; MORD["npm", 68] = "apollo-server"
  MORD["npm", 69] = "graphql-yoga"; MORD["npm", 70] = "socket.io"; MORD["npm", 71] = "micro"; MORD["npm", 72] = "@redwoodjs/api"
  MORD["npm", 73] = "elysia"; MORD["npm", 74] = "@elysiajs/*"; MORD["npm", 75] = "firebase-functions"; MORD["npm", 76] = "@google-cloud/functions-framework"
  MORD["npm", 77] = "@azure/functions"; MORD["npm", 78] = "@netlify/functions"; MORD["npm", 79] = "@vercel/node"; MORD["npm", 80] = "aws-cdk-lib"
  MORD["npm", 81] = "aws-cdk"; MORD["npm", 82] = "cdktf"; MORD["npm", 83] = "@pulumi/pulumi"; MORD["npm", 84] = "sst"
  MORD["npm", 85] = "hardhat"; MORD["npm", 86] = "truffle"; MORD["npm", 87] = "@playwright/test"; MORD["npm", 88] = "playwright"
  MORD["npm", 89] = "cypress"; MORD["npm", 90] = "@wdio/cli"; MORD["npm", 91] = "webdriverio"; MORD["npm", 92] = "nightwatch"
  MORD["npm", 93] = "testcafe"; MORD["npm", 94] = "detox"; MORD["npm", 95] = "typescript"; MORD["npm", 96] = "eslint*"
  MORD["npm", 97] = "@eslint/*"; MORD["npm", 98] = "@typescript-eslint/*"; MORD["npm", 99] = "prettier*"; MORD["npm", 100] = "husky"
  MORD["npm", 101] = "lint-staged"; MORD["npm", 102] = "@commitlint/*"; MORD["npm", 103] = "commitizen"; MORD["npm", 104] = "cz-*"
  MORD["npm", 105] = "@changesets/*"; MORD["npm", 106] = "turbo"; MORD["npm", 107] = "nx"; MORD["npm", 108] = "@nx/*"
  MORD["npm", 109] = "@nrwl/*"; MORD["npm", 110] = "lerna"; MORD["npm", 111] = "rimraf"; MORD["npm", 112] = "npm-run-all*"
  MORD["npm", 113] = "concurrently"; MORD["npm", 114] = "cross-env"; MORD["npm", 115] = "dotenv-cli"; MORD["npm", 116] = "@types/*"
  MORD["npm", 117] = "stylelint*"; MORD["npm", 118] = "@biomejs/*"; MORD["npm", 119] = "syncpack"; MORD["npm", 120] = "knip"
  MORD["npm", 121] = "@manypkg/*"; MORD["npm", 122] = "tsup"; MORD["npm", 123] = "typedoc"; MORD["npm", 124] = "jest"
  MORD["npm", 125] = "vitest"; MORD["npm", 126] = "@vitest/*"; MORD["npm", 127] = "mocha"; MORD["npm", 128] = "chai"
  MORD["npm", 129] = "@testing-library/*"; MORD["npm", 130] = "storybook"; MORD["npm", 131] = "@storybook/*"; MORD["npm", 132] = "@tsconfig/*"
  MORD["npm", 133] = "@turbo/*"; MORD["npm", 134] = "tsx"; MORD["npm", 135] = "ts-node"; MORD["npm", 136] = "nodemon"
  MORD["npm", 137] = "other"; MORD["npm", 138] = "run"; MORD["npm", 139] = "bin"; MORD["npm", 140] = "peers"
  MORD["npm", 141] = "private"; MORD["npm", 142] = "workspaces"; MORD["npm", 143] = "pm-bun"; MORD["npm", 144] = "vscode"
  MORD["npm", 145] = "lib-entry"; MORDN["npm"] = 145; MORD["nx", 1] = "nx-app"; MORD["nx", 2] = "nx-lib"
  MORD["nx", 3] = "nx-rn"; MORD["nx", 4] = "nx-next"; MORD["nx", 5] = "nx-e2e"; MORD["nx", 6] = "nx-node"
  MORD["nx", 7] = "nx-web"; MORDN["nx"] = 7; MORD["gradle", 1] = "android-app"; MORD["gradle", 2] = "android-lib"
  MORD["gradle", 3] = "android-test"; MORD["gradle", 4] = "kmp"; MORD["gradle", 5] = "compose-desktop"; MORD["gradle", 6] = "javafx"
  MORD["gradle", 7] = "jvm-lib"; MORD["gradle", 8] = "jvm-server"; MORD["gradle", 9] = "jvm-app"; MORD["gradle", 10] = "kotlin-dsl"
  MORDN["gradle"] = 10; MORD["maven", 1] = "pom-packaging"; MORD["maven", 2] = "war-packaging"; MORD["maven", 3] = "javafx"
  MORD["maven", 4] = "jvm-server"; MORDN["maven"] = 4; MORD["py", 1] = "django"; MORD["py", 2] = "flask"
  MORD["py", 3] = "fastapi"; MORD["py", 4] = "starlette"; MORD["py", 5] = "streamlit"; MORD["py", 6] = "gradio"
  MORD["py", 7] = "dash"; MORD["py", 8] = "aiohttp"; MORD["py", 9] = "tornado"; MORD["py", 10] = "sanic"
  MORD["py", 11] = "bottle"; MORD["py", 12] = "pyramid"; MORD["py", 13] = "litestar"; MORD["py", 14] = "quart"
  MORD["py", 15] = "falcon"; MORD["py", 16] = "celery"; MORD["py", 17] = "uvicorn"; MORD["py", 18] = "gunicorn"
  MORD["py", 19] = "panel"; MORD["py", 20] = "nicegui"; MORD["py", 21] = "reflex"; MORD["py", 22] = "functions-framework"
  MORD["py", 23] = "azure-functions"; MORD["py", 24] = "firebase-functions"; MORD["py", 25] = "chalice"; MORD["py", 26] = "zappa"
  MORD["py", 27] = "mangum"; MORD["py", 28] = "sphinx"; MORD["py", 29] = "mkdocs"; MORD["py", 30] = "mkdocs-material"
  MORD["py", 31] = "pelican"; MORD["py", 32] = "jupyter"; MORD["py", 33] = "notebook"; MORD["py", 34] = "jupyterlab"
  MORD["py", 35] = "ipykernel"; MORD["py", 36] = "pytest"; MORD["py", 37] = "selenium"; MORD["py", 38] = "playwright"
  MORD["py", 39] = "behave"; MORD["py", 40] = "robotframework"; MORD["py", 41] = "aws-cdk-lib"; MORD["py", 42] = "pulumi"
  MORD["py", 43] = "cdktf"; MORD["py", 44] = "other"; MORD["py", 45] = "project"; MORD["py", 46] = "uv-workspace"
  MORD["py", 47] = "tools-only"; MORD["py", 48] = "scripts"; MORDN["py"] = 48; MORD["go", 1] = "gin"
  MORD["go", 2] = "echo"; MORD["go", 3] = "fiber"; MORD["go", 4] = "chi"; MORD["go", 5] = "gorilla-mux"
  MORD["go", 6] = "beego"; MORD["go", 7] = "buffalo"; MORD["go", 8] = "connect"; MORD["go", 9] = "aws-lambda-go"
  MORD["go", 10] = "functions-framework-go"; MORD["go", 11] = "wails"; MORD["go", 12] = "other"; MORDN["go"] = 12
  MORD["composer", 1] = "laravel"; MORD["composer", 2] = "symfony"; MORD["composer", 3] = "wordpress"; MORD["composer", 4] = "slim"
  MORD["composer", 5] = "cakephp"; MORD["composer", 6] = "yii"; MORD["composer", 7] = "codeigniter"; MORD["composer", 8] = "laminas"
  MORD["composer", 9] = "drupal"; MORD["composer", 10] = "magento"; MORD["composer", 11] = "other"; MORD["composer", 12] = "library-type"
  MORDN["composer"] = 12; MORD["dotnet", 1] = "godot"; MORD["dotnet", 2] = "unity"; MORD["dotnet", 3] = "maui"
  MORD["dotnet", 4] = "blazor-wasm"; MORD["dotnet", 5] = "wpf"; MORD["dotnet", 6] = "winforms"; MORD["dotnet", 7] = "test"
  MORD["dotnet", 8] = "iac"; MORD["dotnet", 9] = "web-sdk"; MORD["dotnet", 10] = "worker-sdk"; MORD["dotnet", 11] = "functions"
  MORD["dotnet", 12] = "aspnet"; MORD["dotnet", 13] = "exe"; MORD["dotnet", 14] = "razor-sdk"; MORDN["dotnet"] = 14
  MORD["gemfile", 1] = "rails"; MORD["gemfile", 2] = "sinatra"; MORD["gemfile", 3] = "hanami"; MORD["gemfile", 4] = "roda"
  MORD["gemfile", 5] = "grape"; MORD["gemfile", 6] = "rack"; MORD["gemfile", 7] = "padrino"; MORD["gemfile", 8] = "puma"
  MORD["gemfile", 9] = "jekyll"; MORD["gemfile", 10] = "middleman"; MORD["gemfile", 11] = "cocoapods"; MORD["gemfile", 12] = "fastlane"
  MORD["gemfile", 13] = "rspec"; MORD["gemfile", 14] = "capybara"; MORD["gemfile", 15] = "cucumber"; MORD["gemfile", 16] = "minitest"
  MORD["gemfile", 17] = "other"; MORDN["gemfile"] = 17; MORD["cargo", 1] = "axum"; MORD["cargo", 2] = "actix-web"
  MORD["cargo", 3] = "rocket"; MORD["cargo", 4] = "warp"; MORD["cargo", 5] = "poem"; MORD["cargo", 6] = "tide"
  MORD["cargo", 7] = "hyper"; MORD["cargo", 8] = "salvo"; MORD["cargo", 9] = "tonic"; MORD["cargo", 10] = "lambda_runtime"
  MORD["cargo", 11] = "yew"; MORD["cargo", 12] = "leptos"; MORD["cargo", 13] = "dioxus"; MORD["cargo", 14] = "sycamore"
  MORD["cargo", 15] = "seed"; MORD["cargo", 16] = "tauri"; MORD["cargo", 17] = "other"; MORD["cargo", 18] = "workspace"
  MORD["cargo", 19] = "package"; MORD["cargo", 20] = "bin"; MORD["cargo", 21] = "lib"; MORDN["cargo"] = 21
  MORD["mix", 1] = "umbrella"; MORD["mix", 2] = "nerves"; MORD["mix", 3] = "phoenix"; MORD["mix", 4] = "app-module"
  MORD["mix", 5] = "plug-server"; MORDN["mix"] = 5; MORD["pubspec", 1] = "flutter"; MORD["pubspec", 2] = "plugin"
  MORDN["pubspec"] = 2; MORD["xcodegen", 1] = "apple-platform"; MORDN["xcodegen"] = 1; MORD["tuist", 1] = "tuist"
  MORDN["tuist"] = 1; MORD["swiftpm", 1] = "apple-platform"; MORD["swiftpm", 2] = "executable"; MORD["swiftpm", 3] = "library-product"
  MORD["swiftpm", 4] = "swift-server"; MORDN["swiftpm"] = 4; MORD["hostprobe", 1] = "azure-functions"; MORD["hostprobe", 2] = "aws-sam"
  MORDN["hostprobe"] = 2; MORD["extmanifest", 1] = "manifest-version"; MORDN["extmanifest"] = 1
  # composer.json types that say "not an app".
  CLIB["library"] = 1; CLIB["composer-plugin"] = 1; CLIB["metapackage"] = 1; CLIB["symfony-bundle"] = 1
  CLIB["wordpress-plugin"] = 1; CLIB["wordpress-theme"] = 1; CLIB["wordpress-muplugin"] = 1; CLIB["drupal-module"] = 1
}
/^C0/ { print; next }
{
  tag = substr($0, 1, 1)
  if (tag != "F" && tag != "L") next
  p = substr($0, 2)
  n = split(p, comp, "/")
  s = boo_sig(n)
  if (!s) next
  home = comp[1]
  for (i = 2; i <= n - SCN[s]; i++) home = home "/" comp[i]
  csv = ""
  if (SCONT[s]) csv = (tag == "L") ? "-" : boo_read(p, s)
  printf "F\t%s\t%s\t%s\n", esc(home), SNAME[s], csv
}
END { print "Z1" }
function boo_sig(n,    j, sc, c, real, ok) {
  for (j = 1; j <= NSIG; j++) {
    sc = SCN[j]
    if (n - 1 < sc) continue
    ok = 1
    for (c = 1; c <= sc && ok; c++) {
      real = comp[n - sc + c]
      if (SCG[j, c]) { if (tolower(real) !~ SCP[j, c]) ok = 0 }
      else if (real != SCP[j, c]) ok = 0
    }
    if (ok) return j
  }
  return 0
}
# Read a manifest into LN[1..NLN]: byte-order mark and Windows line endings
# removed. "-" when it cannot be read.
function boo_read(path, s,    r, line, total, role, nm) {
  NLN = 0
  total = 0
  while ((r = (getline line < path)) > 0) {
    NLN++
    if (NLN == 1 && index(line, BOM) == 1) line = substr(line, length(BOM) + 1)
    sub(/\r$/, "", line)
    LN[NLN] = line
    total += length(line) + 1
    if (total > 2100000) break
  }
  close(path)
  if (r < 0 && NLN == 0) return "-"
  delete MK
  role = SROLE[s]
  nm = SNAME[s]
  if (role == "npm") boo_json(0)
  else if (role == "composer") boo_json(1)
  else if (role == "py") { if (nm == "pyproject.toml") boo_pyproject(); else if (nm == "Pipfile") boo_pipfile(); else boo_req() }
  else if (role == "gemfile") boo_gem()
  else if (role == "cargo") boo_cargo()
  else if (role == "go") boo_go()
  else boo_lines(role)
  return boo_csv(role)
}
function boo_csv(role,    i, out, m) {
  out = ""
  for (i = 1; i <= MORDN[role]; i++) { m = MORD[role, i]; if (m in MK) out = out (out == "" ? "" : ",") m }
  return out
}
# A dependency name: exact first, then the first prefix in table order, else
# "other" — never the name itself.
function boo_dep(fam, name,    j) {
  if ((fam, name) in DX) return DX[fam, name]
  for (j = 1; j <= DPN[fam]; j++) if (index(name, DP[fam, j]) == 1) return DPM[fam, j]
  return "other"
}
# The lines joined, pairwise so a long file is not copied once per line.
function boo_join(    n, i, k) {
  if (NLN == 0) return ""
  for (i = 1; i <= NLN; i++) JN[i] = LN[i]
  n = NLN
  while (n > 1) {
    k = 0
    for (i = 1; i <= n; i += 2) { k++; JN[k] = (i < n) ? JN[i] "\n" JN[i + 1] : JN[i] }
    n = k
  }
  return JN[1] "\n"
}
function boo_oddbs(s,    n, l) {
  n = 0
  l = length(s)
  while (n < l && substr(s, l - n, 1) == "\\") n++
  return n % 2
}
# package.json and composer.json: strings and structure only. A string is a
# key when the text after it starts with a colon; KEY[d] is the key at depth d.
# The separator is a regular expression on purpose: the awk macOS ships splits
# on a one-character string AND on every line break, which loses the keys of
# any file written over several lines.
function boo_json(cmp,    S, np, parts, m, Q, i, str, d, idx, seg, j, c, nxt) {
  S = boo_join()
  np = split(S, parts, /"/)
  m = 0
  Q[++m] = parts[1]
  i = 2
  while (i <= np) {
    str = parts[i]
    while (boo_oddbs(str) && i < np) { i++; str = str "\"" parts[i] }
    Q[++m] = str
    i++
    Q[++m] = (i <= np) ? parts[i] : ""
    i++
  }
  d = 0
  for (idx = 1; idx <= m; idx++) {
    if (idx % 2 == 1) {
      seg = Q[idx]
      gsub(/[^][{}]/, "", seg)
      for (j = 1; j <= length(seg); j++) {
        c = substr(seg, j, 1)
        if (c == "{" || c == "[") { d++; KEY[d] = "" }
        else if (d > 0) d--
      }
      continue
    }
    str = Q[idx]
    nxt = (idx < m) ? Q[idx + 1] : ""
    if (nxt ~ /^[ \t\n]*:/) {
      KEY[d] = str
      if (cmp) boo_compkey(d, str)
      else boo_npmkey(d, str, nxt)
    } else if (cmp) boo_compval(d, str)
    else boo_npmval(d, str)
  }
}
function boo_npmkey(d, k, nxt,    par) {
  if (d == 1) {
    if (k == "workspaces") MK["workspaces"] = 1
    else if (k == "bin") MK["bin"] = 1
    else if (k == "exports" || k == "module" || k == "types" || k == "typings") MK["lib-entry"] = 1
    else if (k == "private" && nxt ~ /^[ \t\n]*:[ \t\n]*true/) MK["private"] = 1
    return
  }
  if (d != 2) return
  par = KEY[1]
  if (par == "dependencies" || par == "devDependencies" || par == "optionalDependencies") MK[boo_dep("npm", k)] = 1
  else if (par == "peerDependencies") MK["peers"] = 1
  else if (par == "scripts") { if (k == "start" || k == "dev" || k == "serve") MK["run"] = 1 }
  else if (par == "engines") { if (k == "vscode") MK["vscode"] = 1 }
}
function boo_npmval(d, v) {
  if (d == 1 && KEY[1] == "packageManager" && index(v, "bun@") == 1) MK["pm-bun"] = 1
}
function boo_compkey(d, k) {
  if (d == 2 && (KEY[1] == "require" || KEY[1] == "require-dev") && index(k, "/")) MK[boo_dep("composer", tolower(k))] = 1
}
function boo_compval(d, v) {
  if (d == 1 && KEY[1] == "type" && (tolower(v) in CLIB)) MK["library-type"] = 1
}
function boo_pyname(s) {
  s = tolower(s)
  gsub(/[-_.]+/, "-", s)
  return s
}
function boo_pystr(s,    v) {
  while (match(s, DQRE)) {
    v = substr(s, RSTART + 1, RLENGTH - 2)
    s = substr(s, RSTART + RLENGTH)
    if (match(v, /^[A-Za-z0-9._-]+/)) MK[boo_dep("py", boo_pyname(substr(v, 1, RLENGTH)))] = 1
  }
}
function boo_arrend(s) {
  gsub(DQRE, "", s)
  return index(s, "]") > 0
}
function boo_req(    i, l) {
  for (i = 1; i <= NLN; i++) {
    l = LN[i]
    sub(/^[ \t]+/, "", l)
    if (l == "" || substr(l, 1, 1) == "#" || substr(l, 1, 1) == "-" || index(l, "://")) continue
    if (match(l, /^[A-Za-z0-9._-]+/)) MK[boo_dep("py", boo_pyname(substr(l, 1, RLENGTH)))] = 1
  }
}
function boo_pyproject(    i, l, t, nt, inarr, rest, k, c1) {
  nt = 0
  t = ""
  inarr = 0
  for (i = 1; i <= NLN; i++) {
    l = LN[i]
    sub(/^[ \t]+/, "", l)
    if (inarr) {
      if (substr(l, 1, 1) == "#") continue
      boo_pystr(l)
      if (boo_arrend(l)) inarr = 0
      continue
    }
    if (l == "" || substr(l, 1, 1) == "#") continue
    if (substr(l, 1, 1) == "[") {
      t = l
      sub(/#.*$/, "", t)
      gsub(QRE, "", t)
      if (t == "project" || t == "tool.poetry") MK["project"] = 1
      if (t == "project.scripts" || t == "project.gui-scripts" || t == "tool.poetry.scripts") MK["scripts"] = 1
      if (t == "tool.uv.workspace") MK["uv-workspace"] = 1
      if (substr(t, 1, 5) != "tool." || substr(t, 1, 11) == "tool.poetry") nt++
      continue
    }
    if (t == "project") {
      if (l ~ /^dependencies[ \t]*=/) {
        rest = substr(l, index(l, "=") + 1)
        boo_pystr(rest)
        if (!boo_arrend(rest)) inarr = 1
      }
    } else if (t == "project.optional-dependencies" || t == "dependency-groups") {
      if (index(l, "=")) {
        rest = substr(l, index(l, "=") + 1)
        if (rest ~ /^[ \t]*\[/) { boo_pystr(rest); if (!boo_arrend(rest)) inarr = 1 }
      }
    } else if (t == "tool.poetry.dependencies" || t == "tool.poetry.dev-dependencies" || (substr(t, 1, 18) == "tool.poetry.group." && t ~ /[.]dependencies$/)) {
      c1 = substr(l, 1, 1)
      if (c1 == "\"" || c1 == SQ) l = substr(l, 2)
      if (index(l, "=") && match(l, /^[A-Za-z0-9._-]+/)) {
        k = boo_pyname(substr(l, 1, RLENGTH))
        if (k != "python") MK[boo_dep("py", k)] = 1
      }
    }
  }
  if (nt == 0) MK["tools-only"] = 1
}
function boo_pipfile(    i, l, t, c1) {
  t = ""
  for (i = 1; i <= NLN; i++) {
    l = LN[i]
    sub(/^[ \t]+/, "", l)
    if (l == "" || substr(l, 1, 1) == "#") continue
    if (substr(l, 1, 1) == "[") { t = l; sub(/#.*$/, "", t); gsub(QRE, "", t); continue }
    if (t != "packages" && t != "dev-packages") continue
    c1 = substr(l, 1, 1)
    if (c1 == "\"" || c1 == SQ) l = substr(l, 2)
    if (index(l, "=") && match(l, /^[A-Za-z0-9._-]+/)) MK[boo_dep("py", boo_pyname(substr(l, 1, RLENGTH)))] = 1
  }
}
function boo_gem(    i, l, q, p) {
  for (i = 1; i <= NLN; i++) {
    l = LN[i]
    sub(/^[ \t]+/, "", l)
    if (l !~ /^gem[ \t(]/) continue
    sub(/^gem[ \t(]+/, "", l)
    q = substr(l, 1, 1)
    if (q != "\"" && q != SQ) continue
    l = substr(l, 2)
    p = index(l, q)
    if (p > 1) MK[boo_dep("gem", tolower(substr(l, 1, p - 1)))] = 1
  }
}
function boo_crate(s) {
  s = tolower(s)
  gsub(/_/, "-", s)
  return s
}
function boo_cargo(    i, l, t, dt, nm, arr) {
  t = ""
  dt = 0
  for (i = 1; i <= NLN; i++) {
    l = LN[i]
    sub(/^[ \t]+/, "", l)
    if (l == "" || substr(l, 1, 1) == "#") continue
    if (substr(l, 1, 1) == "[") {
      arr = (substr(l, 1, 2) == "[[")
      t = l
      sub(/#.*$/, "", t)
      gsub(QRE, "", t)
      dt = 0
      if (arr) { if (t == "bin") MK["bin"] = 1; continue }
      if (t == "package") MK["package"] = 1
      else if (t == "workspace" || substr(t, 1, 10) == "workspace.") MK["workspace"] = 1
      else if (t == "lib") MK["lib"] = 1
      if (t ~ /^(target[.].*[.])?(dev-|build-)?dependencies$/) dt = 1
      else if (t ~ /^(target[.].*[.])?(dev-|build-)?dependencies[.][^.]+$/) {
        nm = t
        sub(/^.*dependencies[.]/, "", nm)
        MK[boo_dep("cargo", boo_crate(nm))] = 1
      }
      continue
    }
    if (dt && match(l, /^[A-Za-z0-9_-]+[ \t]*=/)) {
      nm = l
      sub(/[ \t]*=.*$/, "", nm)
      MK[boo_dep("cargo", boo_crate(nm))] = 1
    }
  }
}
function boo_go(    i, l, inb, w, n) {
  inb = 0
  for (i = 1; i <= NLN; i++) {
    l = LN[i]
    sub(/^[ \t]+/, "", l)
    if (l == "" || substr(l, 1, 2) == "//") continue
    if (inb) {
      if (substr(l, 1, 1) == ")") { inb = 0; continue }
      if (index(l, "// indirect")) continue
      n = split(l, w, " ")
      if (n > 0) { gsub(/"/, "", w[1]); MK[boo_dep("go", tolower(w[1]))] = 1 }
      continue
    }
    if (l ~ /^require[ \t]*[(]/) { inb = 1; continue }
    if (l ~ /^require[ \t]/) {
      if (index(l, "// indirect")) continue
      sub(/^require[ \t]+/, "", l)
      n = split(l, w, " ")
      if (n > 0) { gsub(/"/, "", w[1]); MK[boo_dep("go", tolower(w[1]))] = 1 }
    }
  }
}
# Line rules. Comment lines are not read, and a Gradle line that only
# DECLARES a plugin ("apply false") does not apply it.
function boo_lines(role,    i, lc, tr, j, nr) {
  nr = LRN[role]
  for (i = 1; i <= NLN; i++) {
    lc = tolower(LN[i])
    tr = lc
    sub(/^[ \t]+/, "", tr)
    if (substr(tr, 1, 2) == "//" || substr(tr, 1, 1) == "#" || substr(tr, 1, 2) == "/*" || substr(tr, 1, 1) == "*" || substr(tr, 1, 4) == "<!--") continue
    if (role == "gradle" && lc ~ /apply[ \t]+false/) continue
    for (j = 1; j <= nr; j++) if (lc ~ LR[role, j]) MK[LRM[role, j]] = 1
  }
}
'
}

boosthis_prog_decide() {
printf '%s\n' '# Decides, step for step as lib/scanEngine.decideScan does, and prints the
# sortable records the report is drawn from.
BEGIN {
  boo_init()
  FS = "\t"
  REC = (ENVIRON["BOOSTHIS_SCAN_RECORDS"] == "1")
  # The published signals: role, host, stack, and the markers a probe needs.
  SIGI["package.json"] = 1; SCONT[1] = 1; SPROBE[1] = 0; SROLE[1] = "npm"
  SIGI["pnpm-workspace.yaml"] = 2; SCONT[2] = 0; SPROBE[2] = 0; SROLE[2] = "wsroot"
  SIGI["lerna.json"] = 3; SCONT[3] = 0; SPROBE[3] = 0; SROLE[3] = "wsroot"
  SIGI["turbo.json"] = 4; SCONT[4] = 0; SPROBE[4] = 0; SROLE[4] = "wsroot"
  SIGI["nx.json"] = 5; SCONT[5] = 0; SPROBE[5] = 0; SROLE[5] = "wsroot"
  SIGI["rush.json"] = 6; SCONT[6] = 0; SPROBE[6] = 0; SROLE[6] = "wsroot"
  SIGI["project.json"] = 7; SCONT[7] = 1; SPROBE[7] = 1; SROLE[7] = "nx"
  PRB[7, 1] = "nx-app"; PRB[7, 2] = "nx-lib"; PRB[7, 3] = "nx-rn"; PRB[7, 4] = "nx-next"
  PRB[7, 5] = "nx-e2e"; PRB[7, 6] = "nx-node"; PRB[7, 7] = "nx-web"; PRBN[7] = 7
  SIGI["bun.lock"] = 8; SCONT[8] = 0; SPROBE[8] = 0; SROLE[8] = "bun"
  SIGI["bun.lockb"] = 9; SCONT[9] = 0; SPROBE[9] = 0; SROLE[9] = "bun"
  SIGI["bunfig.toml"] = 10; SCONT[10] = 0; SPROBE[10] = 0; SROLE[10] = "bun"
  SIGI["wrangler.toml"] = 11; SCONT[11] = 0; SPROBE[11] = 0; SROLE[11] = "wrangler"
  SHOST[11] = "cloudflare"; SIGI["wrangler.json"] = 12; SCONT[12] = 0; SPROBE[12] = 0
  SROLE[12] = "wrangler"; SHOST[12] = "cloudflare"; SIGI["wrangler.jsonc"] = 13; SCONT[13] = 0
  SPROBE[13] = 0; SROLE[13] = "wrangler"; SHOST[13] = "cloudflare"; SIGI["deno.json"] = 14
  SCONT[14] = 0; SPROBE[14] = 0; SROLE[14] = "deno"; SIGI["deno.jsonc"] = 15
  SCONT[15] = 0; SPROBE[15] = 0; SROLE[15] = "deno"; SIGI["supabase/functions/*/index.ts"] = 16
  SCONT[16] = 0; SPROBE[16] = 0; SROLE[16] = "supafn"; SHOST[16] = "supabase"
  SIGI["supabase/functions/*/index.js"] = 17; SCONT[17] = 0; SPROBE[17] = 0; SROLE[17] = "supafn"
  SHOST[17] = "supabase"; SIGI["build.gradle"] = 18; SCONT[18] = 1; SPROBE[18] = 0
  SROLE[18] = "gradle"; SIGI["build.gradle.kts"] = 19; SCONT[19] = 1; SPROBE[19] = 0
  SROLE[19] = "gradle"; SIGI["settings.gradle"] = 20; SCONT[20] = 0; SPROBE[20] = 0
  SROLE[20] = "gsettings"; SIGI["settings.gradle.kts"] = 21; SCONT[21] = 0; SPROBE[21] = 0
  SROLE[21] = "gsettings"; SIGI["src/main/AndroidManifest.xml"] = 22; SCONT[22] = 0; SPROBE[22] = 0
  SROLE[22] = "amanifest"; SIGI["pom.xml"] = 23; SCONT[23] = 1; SPROBE[23] = 0
  SROLE[23] = "maven"; SIGI["requirements.txt"] = 24; SCONT[24] = 1; SPROBE[24] = 0
  SROLE[24] = "py"; SIGI["requirements-*.txt"] = 25; SCONT[25] = 1; SPROBE[25] = 0
  SROLE[25] = "py"; SIGI["requirements/*.txt"] = 26; SCONT[26] = 1; SPROBE[26] = 0
  SROLE[26] = "py"; SIGI["pyproject.toml"] = 27; SCONT[27] = 1; SPROBE[27] = 0
  SROLE[27] = "py"; SIGI["Pipfile"] = 28; SCONT[28] = 1; SPROBE[28] = 0
  SROLE[28] = "py"; SIGI["setup.py"] = 29; SCONT[29] = 0; SPROBE[29] = 0
  SROLE[29] = "py"; SIGI["setup.cfg"] = 30; SCONT[30] = 0; SPROBE[30] = 0
  SROLE[30] = "py"; SIGI["manage.py"] = 31; SCONT[31] = 0; SPROBE[31] = 0
  SROLE[31] = "pymanage"; SIGI["*.ipynb"] = 32; SCONT[32] = 0; SPROBE[32] = 0
  SROLE[32] = "notebook"; SSTACK[32] = "notebook"; SIGI["go.mod"] = 33; SCONT[33] = 1
  SPROBE[33] = 0; SROLE[33] = "go"; SIGI["go.work"] = 34; SCONT[34] = 0
  SPROBE[34] = 0; SROLE[34] = "wsroot"; SIGI["composer.json"] = 35; SCONT[35] = 1
  SPROBE[35] = 0; SROLE[35] = "composer"; SIGI["index.php"] = 36; SCONT[36] = 0
  SPROBE[36] = 0; SROLE[36] = "phpindex"; SIGI["wp-config.php"] = 37; SCONT[37] = 0
  SPROBE[37] = 0; SROLE[37] = "wpconfig"; SIGI["artisan"] = 38; SCONT[38] = 0
  SPROBE[38] = 0; SROLE[38] = "artisan"; SIGI["*.csproj"] = 39; SCONT[39] = 1
  SPROBE[39] = 0; SROLE[39] = "dotnet"; SIGI["*.fsproj"] = 40; SCONT[40] = 1
  SPROBE[40] = 0; SROLE[40] = "dotnet"; SIGI["*.vbproj"] = 41; SCONT[41] = 1
  SPROBE[41] = 0; SROLE[41] = "dotnet"; SIGI["*.sln"] = 42; SCONT[42] = 0
  SPROBE[42] = 0; SROLE[42] = "sln"; SIGI["*.slnx"] = 43; SCONT[43] = 0
  SPROBE[43] = 0; SROLE[43] = "sln"; SIGI["Gemfile"] = 44; SCONT[44] = 1
  SPROBE[44] = 0; SROLE[44] = "gemfile"; SIGI["config.ru"] = 45; SCONT[45] = 0
  SPROBE[45] = 0; SROLE[45] = "configru"; SIGI["*.gemspec"] = 46; SCONT[46] = 0
  SPROBE[46] = 0; SROLE[46] = "gemspec"; SIGI["Podfile"] = 47; SCONT[47] = 0
  SPROBE[47] = 0; SROLE[47] = "nativetool"; SIGI["fastlane/Fastfile"] = 48; SCONT[48] = 0
  SPROBE[48] = 0; SROLE[48] = "nativetool"; SIGI["Cargo.toml"] = 49; SCONT[49] = 1
  SPROBE[49] = 0; SROLE[49] = "cargo"; SIGI["src/main.rs"] = 50; SCONT[50] = 0
  SPROBE[50] = 0; SROLE[50] = "rustbin"; SIGI["src/bin/*.rs"] = 51; SCONT[51] = 0
  SPROBE[51] = 0; SROLE[51] = "rustbin"; SIGI["Trunk.toml"] = 52; SCONT[52] = 0
  SPROBE[52] = 0; SROLE[52] = "trunk"; SSTACK[52] = "rust-wasm"; SIGI["mix.exs"] = 53
  SCONT[53] = 1; SPROBE[53] = 0; SROLE[53] = "mix"; SIGI["pubspec.yaml"] = 54
  SCONT[54] = 1; SPROBE[54] = 0; SROLE[54] = "pubspec"; SIGI["*.xcodeproj"] = 55
  SCONT[55] = 0; SPROBE[55] = 0; SROLE[55] = "xcode"; SIGI["*.xcworkspace"] = 56
  SCONT[56] = 0; SPROBE[56] = 0; SROLE[56] = "xcode"; SIGI["project.yml"] = 57
  SCONT[57] = 1; SPROBE[57] = 1; SROLE[57] = "xcodegen"; PRB[57, 1] = "apple-platform"
  PRBN[57] = 1; SIGI["Project.swift"] = 58; SCONT[58] = 1; SPROBE[58] = 1
  SROLE[58] = "tuist"; PRB[58, 1] = "tuist"; PRBN[58] = 1; SIGI["Package.swift"] = 59
  SCONT[59] = 1; SPROBE[59] = 0; SROLE[59] = "swiftpm"; SIGI["vercel.json"] = 60
  SCONT[60] = 0; SPROBE[60] = 0; SROLE[60] = "host"; SHOST[60] = "vercel"
  SIGI["netlify.toml"] = 61; SCONT[61] = 0; SPROBE[61] = 0; SROLE[61] = "host"
  SHOST[61] = "netlify"; SIGI["firebase.json"] = 62; SCONT[62] = 0; SPROBE[62] = 0
  SROLE[62] = "host"; SHOST[62] = "firebase"; SIGI["host.json"] = 63; SCONT[63] = 1
  SPROBE[63] = 1; SROLE[63] = "hostprobe"; SHOST[63] = "azure"; PRB[63, 1] = "azure-functions"
  PRBN[63] = 1; SIGI["serverless.yml"] = 64; SCONT[64] = 0; SPROBE[64] = 0
  SROLE[64] = "host"; SHOST[64] = "aws"; SIGI["serverless.yaml"] = 65; SCONT[65] = 0
  SPROBE[65] = 0; SROLE[65] = "host"; SHOST[65] = "aws"; SIGI["serverless.ts"] = 66
  SCONT[66] = 0; SPROBE[66] = 0; SROLE[66] = "host"; SHOST[66] = "aws"
  SIGI["samconfig.toml"] = 67; SCONT[67] = 0; SPROBE[67] = 0; SROLE[67] = "host"
  SHOST[67] = "aws"; SIGI["template.yaml"] = 68; SCONT[68] = 1; SPROBE[68] = 1
  SROLE[68] = "hostprobe"; SHOST[68] = "aws"; PRB[68, 1] = "aws-sam"; PRBN[68] = 1
  SIGI["template.yml"] = 69; SCONT[69] = 1; SPROBE[69] = 1; SROLE[69] = "hostprobe"
  SHOST[69] = "aws"; PRB[69, 1] = "aws-sam"; PRBN[69] = 1; SIGI["cdk.json"] = 70
  SCONT[70] = 0; SPROBE[70] = 0; SROLE[70] = "infra"; SIGI["cdktf.json"] = 71
  SCONT[71] = 0; SPROBE[71] = 0; SROLE[71] = "infra"; SIGI["Pulumi.yaml"] = 72
  SCONT[72] = 0; SPROBE[72] = 0; SROLE[72] = "infra"; SIGI["Pulumi.yml"] = 73
  SCONT[73] = 0; SPROBE[73] = 0; SROLE[73] = "infra"; SIGI["sst.config.ts"] = 74
  SCONT[74] = 0; SPROBE[74] = 0; SROLE[74] = "infra"; SHOST[74] = "aws"
  SIGI["action.yml"] = 75; SCONT[75] = 0; SPROBE[75] = 0; SROLE[75] = "ciaction"
  SIGI["action.yaml"] = 76; SCONT[76] = 0; SPROBE[76] = 0; SROLE[76] = "ciaction"
  SIGI["hardhat.config.*"] = 77; SCONT[77] = 0; SPROBE[77] = 0; SROLE[77] = "contract"
  SIGI["foundry.toml"] = 78; SCONT[78] = 0; SPROBE[78] = 0; SROLE[78] = "contract"
  SIGI["truffle-config.js"] = 79; SCONT[79] = 0; SPROBE[79] = 0; SROLE[79] = "contract"
  SIGI["mkdocs.yml"] = 80; SCONT[80] = 0; SPROBE[80] = 0; SROLE[80] = "ssg"
  SIGI["mkdocs.yaml"] = 81; SCONT[81] = 0; SPROBE[81] = 0; SROLE[81] = "ssg"
  SIGI["_config.yml"] = 82; SCONT[82] = 0; SPROBE[82] = 0; SROLE[82] = "ssg"
  SIGI["hugo.toml"] = 83; SCONT[83] = 0; SPROBE[83] = 0; SROLE[83] = "ssg"
  SIGI["hugo.yaml"] = 84; SCONT[84] = 0; SPROBE[84] = 0; SROLE[84] = "ssg"
  SIGI["hugo.json"] = 85; SCONT[85] = 0; SPROBE[85] = 0; SROLE[85] = "ssg"
  SIGI[".eleventy.js"] = 86; SCONT[86] = 0; SPROBE[86] = 0; SROLE[86] = "ssg"
  SIGI["eleventy.config.*"] = 87; SCONT[87] = 0; SPROBE[87] = 0; SROLE[87] = "ssg"
  SIGI["pelicanconf.py"] = 88; SCONT[88] = 0; SPROBE[88] = 0; SROLE[88] = "ssg"
  SIGI["book.toml"] = 89; SCONT[89] = 0; SPROBE[89] = 0; SROLE[89] = "ssg"
  SIGI["*.html"] = 90; SCONT[90] = 0; SPROBE[90] = 0; SROLE[90] = "page"
  SIGI["*.htm"] = 91; SCONT[91] = 0; SPROBE[91] = 0; SROLE[91] = "page"
  SIGI["*.erb"] = 92; SCONT[92] = 0; SPROBE[92] = 0; SROLE[92] = "tpl"
  SIGI["*.haml"] = 93; SCONT[93] = 0; SPROBE[93] = 0; SROLE[93] = "tpl"
  SIGI["*.slim"] = 94; SCONT[94] = 0; SPROBE[94] = 0; SROLE[94] = "tpl"
  SIGI["*.blade.php"] = 95; SCONT[95] = 0; SPROBE[95] = 0; SROLE[95] = "tpl"
  SIGI["*.twig"] = 96; SCONT[96] = 0; SPROBE[96] = 0; SROLE[96] = "tpl"
  SIGI["*.heex"] = 97; SCONT[97] = 0; SPROBE[97] = 0; SROLE[97] = "tpl"
  SIGI["*.eex"] = 98; SCONT[98] = 0; SPROBE[98] = 0; SROLE[98] = "tpl"
  SIGI["*.cshtml"] = 99; SCONT[99] = 0; SPROBE[99] = 0; SROLE[99] = "tpl"
  SIGI["*.razor"] = 100; SCONT[100] = 0; SPROBE[100] = 0; SROLE[100] = "tpl"
  SIGI["*.jinja"] = 101; SCONT[101] = 0; SPROBE[101] = 0; SROLE[101] = "tpl"
  SIGI["*.jinja2"] = 102; SCONT[102] = 0; SPROBE[102] = 0; SROLE[102] = "tpl"
  SIGI["*.j2"] = 103; SCONT[103] = 0; SPROBE[103] = 0; SROLE[103] = "tpl"
  SIGI["*.hbs"] = 104; SCONT[104] = 0; SPROBE[104] = 0; SROLE[104] = "tpl"
  SIGI["*.handlebars"] = 105; SCONT[105] = 0; SPROBE[105] = 0; SROLE[105] = "tpl"
  SIGI["*.ejs"] = 106; SCONT[106] = 0; SPROBE[106] = 0; SROLE[106] = "tpl"
  SIGI["*.pug"] = 107; SCONT[107] = 0; SPROBE[107] = 0; SROLE[107] = "tpl"
  SIGI["*.njk"] = 108; SCONT[108] = 0; SPROBE[108] = 0; SROLE[108] = "tpl"
  SIGI["*.liquid"] = 109; SCONT[109] = 0; SPROBE[109] = 0; SROLE[109] = "tpl"
  SIGI["*.mustache"] = 110; SCONT[110] = 0; SPROBE[110] = 0; SROLE[110] = "tpl"
  SIGI["*.gohtml"] = 111; SCONT[111] = 0; SPROBE[111] = 0; SROLE[111] = "tpl"
  SIGI["*.tmpl"] = 112; SCONT[112] = 0; SPROBE[112] = 0; SROLE[112] = "tpl"
  SIGI["*.jsp"] = 113; SCONT[113] = 0; SPROBE[113] = 0; SROLE[113] = "tpl"
  SIGI["*.ftl"] = 114; SCONT[114] = 0; SPROBE[114] = 0; SROLE[114] = "tpl"
  SIGI["capacitor.config.*"] = 115; SCONT[115] = 0; SPROBE[115] = 0; SROLE[115] = "shell"
  SSTACK[115] = "capacitor"; SIGI["ionic.config.json"] = 116; SCONT[116] = 0; SPROBE[116] = 0
  SROLE[116] = "shell"; SSTACK[116] = "capacitor"; SIGI["src-tauri/tauri.conf.*"] = 117; SCONT[117] = 0
  SPROBE[117] = 0; SROLE[117] = "shell"; SSTACK[117] = "tauri"; SIGI["src-tauri/Tauri.toml"] = 118
  SCONT[118] = 0; SPROBE[118] = 0; SROLE[118] = "shell"; SSTACK[118] = "tauri"
  SIGI["wails.json"] = 119; SCONT[119] = 0; SPROBE[119] = 0; SROLE[119] = "shell"
  SSTACK[119] = "wails"; SIGI["nativescript.config.*"] = 120; SCONT[120] = 0; SPROBE[120] = 0
  SROLE[120] = "shell"; SSTACK[120] = "nativescript"; SIGI["ProjectSettings/ProjectVersion.txt"] = 121; SCONT[121] = 0
  SPROBE[121] = 0; SROLE[121] = "shell"; SSTACK[121] = "unity"; SIGI["project.godot"] = 122
  SCONT[122] = 0; SPROBE[122] = 0; SROLE[122] = "shell"; SSTACK[122] = "godot"
  SIGI["manifest.json"] = 123; SCONT[123] = 1; SPROBE[123] = 1; SROLE[123] = "extmanifest"
  SSTACK[123] = "browser-extension"; PRB[123, 1] = "manifest-version"; PRBN[123] = 1; SIGI["public/manifest.json"] = 124
  SCONT[124] = 1; SPROBE[124] = 1; SROLE[124] = "extmanifest"; SSTACK[124] = "browser-extension"
  PRB[124, 1] = "manifest-version"; PRBN[124] = 1; SIGI["src/manifest.json"] = 125; SCONT[125] = 1
  SPROBE[125] = 1; SROLE[125] = "extmanifest"; SSTACK[125] = "browser-extension"; PRB[125, 1] = "manifest-version"
  PRBN[125] = 1; SIGI["static/manifest.json"] = 126; SCONT[126] = 1; SPROBE[126] = 1
  SROLE[126] = "extmanifest"; SSTACK[126] = "browser-extension"; PRB[126, 1] = "manifest-version"; PRBN[126] = 1
  SIGI["build.sbt"] = 127; SCONT[127] = 0; SPROBE[127] = 0; SROLE[127] = "lang"
  SSTACK[127] = "scala"; SIGI["build.sc"] = 128; SCONT[128] = 0; SPROBE[128] = 0
  SROLE[128] = "lang"; SSTACK[128] = "scala"; SIGI["project.clj"] = 129; SCONT[129] = 0
  SPROBE[129] = 0; SROLE[129] = "lang"; SSTACK[129] = "clojure"; SIGI["deps.edn"] = 130
  SCONT[130] = 0; SPROBE[130] = 0; SROLE[130] = "lang"; SSTACK[130] = "clojure"
  SIGI["rebar.config"] = 131; SCONT[131] = 0; SPROBE[131] = 0; SROLE[131] = "lang"
  SSTACK[131] = "erlang"; SIGI["gleam.toml"] = 132; SCONT[132] = 0; SPROBE[132] = 0
  SROLE[132] = "lang"; SSTACK[132] = "gleam"; SIGI["renv.lock"] = 133; SCONT[133] = 0
  SPROBE[133] = 0; SROLE[133] = "lang"; SSTACK[133] = "r"; SIGI["*.Rproj"] = 134
  SCONT[134] = 0; SPROBE[134] = 0; SROLE[134] = "lang"; SSTACK[134] = "r"
  SIGI["CMakeLists.txt"] = 135; SCONT[135] = 0; SPROBE[135] = 0; SROLE[135] = "lang"
  SSTACK[135] = "cpp"; SIGI["meson.build"] = 136; SCONT[136] = 0; SPROBE[136] = 0
  SROLE[136] = "lang"; SSTACK[136] = "cpp"; SIGI["conanfile.txt"] = 137; SCONT[137] = 0
  SPROBE[137] = 0; SROLE[137] = "lang"; SSTACK[137] = "cpp"; SIGI["vcpkg.json"] = 138
  SCONT[138] = 0; SPROBE[138] = 0; SROLE[138] = "lang"; SSTACK[138] = "cpp"
  SIGI["stack.yaml"] = 139; SCONT[139] = 0; SPROBE[139] = 0; SROLE[139] = "lang"
  SSTACK[139] = "haskell"; SIGI["cabal.project"] = 140; SCONT[140] = 0; SPROBE[140] = 0
  SROLE[140] = "lang"; SSTACK[140] = "haskell"; SIGI["*.cabal"] = 141; SCONT[141] = 0
  SPROBE[141] = 0; SROLE[141] = "lang"; SSTACK[141] = "haskell"; SIGI["dune-project"] = 142
  SCONT[142] = 0; SPROBE[142] = 0; SROLE[142] = "lang"; SSTACK[142] = "ocaml"
  SIGI["build.zig"] = 143; SCONT[143] = 0; SPROBE[143] = 0; SROLE[143] = "lang"
  SSTACK[143] = "zig"; SIGI["*.nimble"] = 144; SCONT[144] = 0; SPROBE[144] = 0
  SROLE[144] = "lang"; SSTACK[144] = "nim"; SIGI["shard.yml"] = 145; SCONT[145] = 0
  SPROBE[145] = 0; SROLE[145] = "lang"; SSTACK[145] = "crystal"; SIGI["Project.toml"] = 146
  SCONT[146] = 0; SPROBE[146] = 0; SROLE[146] = "lang"; SSTACK[146] = "julia"
  SIGI["cpanfile"] = 147; SCONT[147] = 0; SPROBE[147] = 0; SROLE[147] = "lang"
  SSTACK[147] = "perl"; SIGI["Makefile.PL"] = 148; SCONT[148] = 0; SPROBE[148] = 0
  SROLE[148] = "lang"; SSTACK[148] = "perl"; SIGI["*.rockspec"] = 149; SCONT[149] = 0
  SPROBE[149] = 0; SROLE[149] = "lang"; SSTACK[149] = "lua"; SIGI["WORKSPACE"] = 150
  SCONT[150] = 0; SPROBE[150] = 0; SROLE[150] = "blind"; SBLIND[150] = "bazel"
  SIGI["WORKSPACE.bazel"] = 151; SCONT[151] = 0; SPROBE[151] = 0; SROLE[151] = "blind"
  SBLIND[151] = "bazel"; SIGI["MODULE.bazel"] = 152; SCONT[152] = 0; SPROBE[152] = 0
  SROLE[152] = "blind"; SBLIND[152] = "bazel"; SIGI["BUILD.bazel"] = 153; SCONT[153] = 0
  SPROBE[153] = 0; SROLE[153] = "blind"; SBLIND[153] = "bazel"; SIGI["Dockerfile"] = 154
  SCONT[154] = 0; SPROBE[154] = 0; SROLE[154] = "blind"; SBLIND[154] = "dockerfile"
  SIGI["Containerfile"] = 155; SCONT[155] = 0; SPROBE[155] = 0; SROLE[155] = "blind"
  SBLIND[155] = "dockerfile"
  # Marker groups, hosts, and the app-shell markers in vocabulary order.
  MG["npm", "react-native"] = "rn"; MG["npm", "expo"] = "rn"; MG["npm", "electron"] = "shell"
  SHL["npm", 1] = "electron"; SHS["npm", 1] = "electron"; MG["npm", "@nativescript/core"] = "shell"
  SHL["npm", 2] = "@nativescript/core"; SHS["npm", 2] = "nativescript"; MG["npm", "@capacitor/core"] = "shell"
  SHL["npm", 3] = "@capacitor/core"; SHS["npm", 3] = "capacitor"; MG["npm", "wxt"] = "shell"
  SHL["npm", 4] = "wxt"; SHS["npm", 4] = "browser-extension"; MG["npm", "plasmo"] = "shell"
  SHL["npm", 5] = "plasmo"; SHS["npm", 5] = "browser-extension"; MG["npm", "@crxjs/vite-plugin"] = "shell"
  SHL["npm", 6] = "@crxjs/vite-plugin"; SHS["npm", 6] = "browser-extension"; MG["npm", "webextension-polyfill"] = "shell"
  SHL["npm", 7] = "webextension-polyfill"; SHS["npm", 7] = "browser-extension"; MG["npm", "web-ext"] = "shell"
  SHL["npm", 8] = "web-ext"; SHS["npm", 8] = "browser-extension"; MG["npm", "next"] = "webui ssr"
  MG["npm", "nuxt"] = "webui ssr"; MG["npm", "@sveltejs/kit"] = "webui ssr"; MG["npm", "@remix-run/node"] = "ssr"
  MG["npm", "@remix-run/serve"] = "ssr"; MG["npm", "@remix-run/express"] = "ssr"; MG["npm", "@remix-run/react"] = "webui"
  MG["npm", "@angular/ssr"] = "ssr"; MG["npm", "@nguniversal/express-engine"] = "ssr"; MG["npm", "@solidjs/start"] = "webui ssr"
  MG["npm", "@analogjs/platform"] = "webui ssr"; MG["npm", "@tanstack/react-start"] = "webui ssr"; MG["npm", "@tanstack/start"] = "webui ssr"
  MG["npm", "@builder.io/qwik-city"] = "webui ssr"; MG["npm", "waku"] = "webui ssr"; MG["npm", "react"] = "webui"
  MG["npm", "react-dom"] = "webui"; MG["npm", "vue"] = "webui"; MG["npm", "svelte"] = "webui"
  MG["npm", "@angular/core"] = "webui"; MG["npm", "solid-js"] = "webui"; MG["npm", "preact"] = "webui"
  MG["npm", "lit"] = "webui"; MG["npm", "@builder.io/qwik"] = "webui"; MG["npm", "ember-source"] = "webui"
  MG["npm", "@redwoodjs/web"] = "webui"; MG["npm", "gatsby"] = "ssg"; MG["npm", "astro"] = "ssg"
  MG["npm", "@docusaurus/core"] = "ssg"; MG["npm", "@11ty/eleventy"] = "ssg"; MG["npm", "vitepress"] = "ssg"
  MG["npm", "vuepress"] = "ssg"; MG["npm", "hexo"] = "ssg"; MG["npm", "vite"] = "bundler"
  MG["npm", "webpack"] = "bundler"; MG["npm", "parcel"] = "bundler"; MG["npm", "@rspack/core"] = "bundler"
  MG["npm", "@rsbuild/core"] = "bundler"; MG["npm", "browserify"] = "bundler"; MG["npm", "snowpack"] = "bundler"
  MG["npm", "esbuild"] = "assetbundler"; MG["npm", "rollup"] = "assetbundler"; MG["npm", "express"] = "server"
  MG["npm", "fastify"] = "server"; MG["npm", "koa"] = "server"; MG["npm", "@hapi/hapi"] = "server"
  MG["npm", "@nestjs/core"] = "server"; MG["npm", "hono"] = "server"; MG["npm", "restify"] = "server"
  MG["npm", "polka"] = "server"; MG["npm", "@adonisjs/core"] = "server"; MG["npm", "sails"] = "server"
  MG["npm", "@feathersjs/feathers"] = "server"; MG["npm", "@loopback/core"] = "server"; MG["npm", "h3"] = "server"
  MG["npm", "nitropack"] = "server"; MG["npm", "@apollo/server"] = "server"; MG["npm", "apollo-server"] = "server"
  MG["npm", "graphql-yoga"] = "server"; MG["npm", "socket.io"] = "server"; MG["npm", "micro"] = "server"
  MG["npm", "@redwoodjs/api"] = "server"; MG["npm", "elysia"] = "server bunfw"; MG["npm", "@elysiajs/*"] = "bunfw"
  MG["npm", "firebase-functions"] = "server"; MHOST["npm", "firebase-functions"] = "firebase"; MG["npm", "@google-cloud/functions-framework"] = "server"
  MHOST["npm", "@google-cloud/functions-framework"] = "gcf"; MG["npm", "@azure/functions"] = "server"; MHOST["npm", "@azure/functions"] = "azure"
  MG["npm", "@netlify/functions"] = "server"; MHOST["npm", "@netlify/functions"] = "netlify"; MG["npm", "@vercel/node"] = "server"
  MHOST["npm", "@vercel/node"] = "vercel"; MG["npm", "aws-cdk-lib"] = "infra"; MG["npm", "aws-cdk"] = "infra"
  MG["npm", "cdktf"] = "infra"; MG["npm", "@pulumi/pulumi"] = "infra"; MG["npm", "sst"] = "infra"
  MHOST["npm", "sst"] = "aws"; MG["npm", "hardhat"] = "contract"; MG["npm", "truffle"] = "contract"
  MG["npm", "@playwright/test"] = "e2e"; MG["npm", "playwright"] = "e2e"; MG["npm", "cypress"] = "e2e"
  MG["npm", "@wdio/cli"] = "e2e"; MG["npm", "webdriverio"] = "e2e"; MG["npm", "nightwatch"] = "e2e"
  MG["npm", "testcafe"] = "e2e"; MG["npm", "detox"] = "e2e"; MG["npm", "typescript"] = "tooling"
  MG["npm", "eslint*"] = "tooling"; MG["npm", "@eslint/*"] = "tooling"; MG["npm", "@typescript-eslint/*"] = "tooling"
  MG["npm", "prettier*"] = "tooling"; MG["npm", "husky"] = "tooling"; MG["npm", "lint-staged"] = "tooling"
  MG["npm", "@commitlint/*"] = "tooling"; MG["npm", "commitizen"] = "tooling"; MG["npm", "cz-*"] = "tooling"
  MG["npm", "@changesets/*"] = "tooling"; MG["npm", "turbo"] = "tooling"; MG["npm", "nx"] = "tooling"
  MG["npm", "@nx/*"] = "tooling"; MG["npm", "@nrwl/*"] = "tooling"; MG["npm", "lerna"] = "tooling"
  MG["npm", "rimraf"] = "tooling"; MG["npm", "npm-run-all*"] = "tooling"; MG["npm", "concurrently"] = "tooling"
  MG["npm", "cross-env"] = "tooling"; MG["npm", "dotenv-cli"] = "tooling"; MG["npm", "@types/*"] = "tooling"
  MG["npm", "stylelint*"] = "tooling"; MG["npm", "@biomejs/*"] = "tooling"; MG["npm", "syncpack"] = "tooling"
  MG["npm", "knip"] = "tooling"; MG["npm", "@manypkg/*"] = "tooling"; MG["npm", "tsup"] = "tooling"
  MG["npm", "typedoc"] = "tooling"; MG["npm", "jest"] = "tooling"; MG["npm", "vitest"] = "tooling"
  MG["npm", "@vitest/*"] = "tooling"; MG["npm", "mocha"] = "tooling"; MG["npm", "chai"] = "tooling"
  MG["npm", "@testing-library/*"] = "tooling"; MG["npm", "storybook"] = "tooling"; MG["npm", "@storybook/*"] = "tooling"
  MG["npm", "@tsconfig/*"] = "tooling"; MG["npm", "@turbo/*"] = "tooling"; MG["npm", "tsx"] = "tooling"
  MG["npm", "ts-node"] = "tooling"; MG["npm", "nodemon"] = "tooling"; SHLN["npm"] = 8
  MG["nx", "nx-app"] = "probe"; MG["nx", "nx-lib"] = "probe"; MG["nx", "nx-rn"] = "probe"
  MG["nx", "nx-next"] = "probe"; MG["nx", "nx-e2e"] = "probe"; MG["nx", "nx-node"] = "probe"
  MG["nx", "nx-web"] = "probe"; MG["gradle", "android-app"] = "kotlin"; MG["gradle", "android-lib"] = "library"
  MG["gradle", "android-test"] = "test"; MG["gradle", "kmp"] = "library"; MG["gradle", "compose-desktop"] = "shell"
  SHL["gradle", 1] = "compose-desktop"; SHS["gradle", 1] = "compose-desktop"; MG["gradle", "javafx"] = "shell"
  SHL["gradle", 2] = "javafx"; SHS["gradle", 2] = "javafx"; MG["gradle", "jvm-lib"] = "library"
  MG["gradle", "jvm-server"] = "server"; MG["gradle", "jvm-app"] = "server"; MG["gradle", "kotlin-dsl"] = "convention"
  SHLN["gradle"] = 2; MG["maven", "pom-packaging"] = "workspace"; MG["maven", "war-packaging"] = "server"
  MG["maven", "javafx"] = "shell"; SHL["maven", 1] = "javafx"; SHS["maven", 1] = "javafx"
  MG["maven", "jvm-server"] = "server"; SHLN["maven"] = 1; MG["py", "django"] = "server"
  MG["py", "flask"] = "server"; MG["py", "fastapi"] = "server"; MG["py", "starlette"] = "server"
  MG["py", "streamlit"] = "server"; MG["py", "gradio"] = "server"; MG["py", "dash"] = "server"
  MG["py", "aiohttp"] = "server"; MG["py", "tornado"] = "server"; MG["py", "sanic"] = "server"
  MG["py", "bottle"] = "server"; MG["py", "pyramid"] = "server"; MG["py", "litestar"] = "server"
  MG["py", "quart"] = "server"; MG["py", "falcon"] = "server"; MG["py", "celery"] = "server"
  MG["py", "uvicorn"] = "server"; MG["py", "gunicorn"] = "server"; MG["py", "panel"] = "server"
  MG["py", "nicegui"] = "server"; MG["py", "reflex"] = "server"; MG["py", "functions-framework"] = "server"
  MHOST["py", "functions-framework"] = "gcf"; MG["py", "azure-functions"] = "server"; MHOST["py", "azure-functions"] = "azure"
  MG["py", "firebase-functions"] = "server"; MHOST["py", "firebase-functions"] = "firebase"; MG["py", "chalice"] = "server"
  MHOST["py", "chalice"] = "aws"; MG["py", "zappa"] = "server"; MHOST["py", "zappa"] = "aws"
  MG["py", "mangum"] = "server"; MHOST["py", "mangum"] = "aws"; MG["py", "sphinx"] = "ssg"
  MG["py", "mkdocs"] = "ssg"; MG["py", "mkdocs-material"] = "ssg"; MG["py", "pelican"] = "ssg"
  MG["py", "jupyter"] = "notebook"; MG["py", "notebook"] = "notebook"; MG["py", "jupyterlab"] = "notebook"
  MG["py", "ipykernel"] = "notebook"; MG["py", "pytest"] = "test"; MG["py", "selenium"] = "test"
  MG["py", "playwright"] = "test"; MG["py", "behave"] = "test"; MG["py", "robotframework"] = "test"
  MG["py", "aws-cdk-lib"] = "infra"; MG["py", "pulumi"] = "infra"; MG["py", "cdktf"] = "infra"
  MG["go", "gin"] = "server"; MG["go", "echo"] = "server"; MG["go", "fiber"] = "server"
  MG["go", "chi"] = "server"; MG["go", "gorilla-mux"] = "server"; MG["go", "beego"] = "server"
  MG["go", "buffalo"] = "server"; MG["go", "connect"] = "server"; MG["go", "aws-lambda-go"] = "server"
  MHOST["go", "aws-lambda-go"] = "aws"; MG["go", "functions-framework-go"] = "server"; MHOST["go", "functions-framework-go"] = "gcf"
  MG["go", "wails"] = "shell"; SHL["go", 1] = "wails"; SHS["go", 1] = "wails"
  SHLN["go"] = 1; MG["composer", "laravel"] = "framework"; MG["composer", "symfony"] = "framework"
  MG["composer", "wordpress"] = "wordpress"; MG["composer", "slim"] = "framework"; MG["composer", "cakephp"] = "framework"
  MG["composer", "yii"] = "framework"; MG["composer", "codeigniter"] = "framework"; MG["composer", "laminas"] = "framework"
  MG["composer", "drupal"] = "framework"; MG["composer", "magento"] = "framework"; MG["dotnet", "godot"] = "shell"
  SHL["dotnet", 1] = "godot"; SHS["dotnet", 1] = "godot"; MG["dotnet", "unity"] = "shell"
  SHL["dotnet", 2] = "unity"; SHS["dotnet", 2] = "unity"; MG["dotnet", "maui"] = "shell"
  SHL["dotnet", 3] = "maui"; SHS["dotnet", 3] = "maui"; MG["dotnet", "blazor-wasm"] = "shell"
  SHL["dotnet", 4] = "blazor-wasm"; SHS["dotnet", 4] = "blazor-wasm"; MG["dotnet", "wpf"] = "shell"
  SHL["dotnet", 5] = "wpf"; SHS["dotnet", 5] = "wpf-winforms"; MG["dotnet", "winforms"] = "shell"
  SHL["dotnet", 6] = "winforms"; SHS["dotnet", 6] = "wpf-winforms"; MG["dotnet", "test"] = "test"
  MG["dotnet", "iac"] = "infra"; MG["dotnet", "web-sdk"] = "server"; MG["dotnet", "worker-sdk"] = "server"
  MG["dotnet", "functions"] = "server"; MHOST["dotnet", "functions"] = "azure"; MG["dotnet", "aspnet"] = "server"
  MG["dotnet", "exe"] = "server"; MG["dotnet", "razor-sdk"] = "library"; SHLN["dotnet"] = 6
  MG["gemfile", "rails"] = "server"; MG["gemfile", "sinatra"] = "server"; MG["gemfile", "hanami"] = "server"
  MG["gemfile", "roda"] = "server"; MG["gemfile", "grape"] = "server"; MG["gemfile", "rack"] = "server"
  MG["gemfile", "padrino"] = "server"; MG["gemfile", "puma"] = "server"; MG["gemfile", "jekyll"] = "ssg"
  MG["gemfile", "middleman"] = "ssg"; MG["gemfile", "cocoapods"] = "nativetool"; MG["gemfile", "fastlane"] = "nativetool"
  MG["gemfile", "rspec"] = "test"; MG["gemfile", "capybara"] = "test"; MG["gemfile", "cucumber"] = "test"
  MG["gemfile", "minitest"] = "test"; MG["cargo", "axum"] = "server"; MG["cargo", "actix-web"] = "server"
  MG["cargo", "rocket"] = "server"; MG["cargo", "warp"] = "server"; MG["cargo", "poem"] = "server"
  MG["cargo", "tide"] = "server"; MG["cargo", "hyper"] = "server"; MG["cargo", "salvo"] = "server"
  MG["cargo", "tonic"] = "server"; MG["cargo", "lambda_runtime"] = "server"; MHOST["cargo", "lambda_runtime"] = "aws"
  MG["cargo", "yew"] = "wasmui"; MG["cargo", "leptos"] = "wasmui"; MG["cargo", "dioxus"] = "wasmui"
  MG["cargo", "sycamore"] = "wasmui"; MG["cargo", "seed"] = "wasmui"; MG["cargo", "tauri"] = "shell"
  SHL["cargo", 1] = "tauri"; SHS["cargo", 1] = "tauri"; SHLN["cargo"] = 1
  MG["mix", "umbrella"] = "workspace"; MG["mix", "nerves"] = "shell"; SHL["mix", 1] = "nerves"
  SHS["mix", 1] = "nerves"; MG["mix", "phoenix"] = "server"; MG["mix", "app-module"] = "server"
  MG["mix", "plug-server"] = "server"; SHLN["mix"] = 1; MG["pubspec", "flutter"] = "flutter"
  MG["pubspec", "plugin"] = "library"; MG["xcodegen", "apple-platform"] = "apple"; MG["tuist", "tuist"] = "apple"
  MG["swiftpm", "apple-platform"] = "apple"; MG["swiftpm", "executable"] = "executable"; MG["swiftpm", "library-product"] = "library"
  MG["swiftpm", "swift-server"] = "server"; MG["hostprobe", "azure-functions"] = "probe"; MG["hostprobe", "aws-sam"] = "probe"
  MG["extmanifest", "manifest-version"] = "probe"
  # Folders, ranks, kit sets and the verdict of each kit for each host.
  CONVF["buildSrc"] = 1; CONVF["build-logic"] = 1; EXF["example"] = 1; EXF["examples"] = 1
  EXF["sample"] = 1; EXF["samples"] = 1; HRANK["vercel"] = 0; HRANK["netlify"] = 1
  HRANK["firebase"] = 2; HRANK["azure"] = 3; HRANK["gcf"] = 4; HRANK["aws"] = 5
  HRANK["cloudflare"] = 6; HRANK["supabase"] = 7; FLR["module"] = 0; FLR["layout"] = 1
  FLR["html"] = 2; FLR[""] = 3; FOLDR["ci-action"] = 0; FOLDR["contract"] = 1
  FOLDR["infra"] = 2; FOREIGN["python"] = 1; FOREIGN["java"] = 1; FOREIGN["go"] = 1
  FOREIGN["php"] = 1; FOREIGN["dotnet"] = 1; FOREIGN["ruby"] = 1; FOREIGN["rust"] = 1
  FOREIGN["elixir"] = 1; PAGEOWN["node"] = 1; PAGEOWN["bun"] = 1; PAGEOWN["python"] = 1
  PAGEOWN["java"] = 1; PAGEOWN["go"] = 1; PAGEOWN["php"] = 1; PAGEOWN["dotnet"] = 1
  PAGEOWN["ruby"] = 1; PAGEOWN["rust"] = 1; PAGEOWN["elixir"] = 1; PHONE["rn"] = 1
  PHONE["flutter"] = 1; PHONE["swift"] = 1; PHONE["kotlin"] = 1; NATF[1] = "android"
  NATF[2] = "ios"; NATF[3] = "macos"; NATF[4] = "windows"; NATF[5] = "linux"
  NATF[6] = "web"; NATF[7] = "fastlane"; NNAT = 7; KR["rn"] = "00"
  KO[1] = "rn"; KR["web"] = "01"; KO[2] = "web"; KR["node"] = "02"
  KO[3] = "node"; KR["bun"] = "03"; KO[4] = "bun"; KR["python"] = "04"
  KO[5] = "python"; KR["java"] = "05"; KO[6] = "java"; KR["go"] = "06"
  KO[7] = "go"; KR["php"] = "07"; KO[8] = "php"; KR["dotnet"] = "08"
  KO[9] = "dotnet"; KR["ruby"] = "09"; KO[10] = "ruby"; KR["flutter"] = "10"
  KO[11] = "flutter"; KR["swift"] = "11"; KO[12] = "swift"; KR["kotlin"] = "12"
  KO[13] = "kotlin"; KR["rust"] = "13"; KO[14] = "rust"; KR["elixir"] = "14"
  KO[15] = "elixir"; KR["edge"] = "15"; KO[16] = "edge"; NKIT = 16
  STR["capacitor"] = "00"; STR["tauri"] = "01"; STR["electron"] = "02"; STR["wails"] = "03"
  STR["nativescript"] = "04"; STR["maui"] = "05"; STR["blazor-wasm"] = "06"; STR["wpf-winforms"] = "07"
  STR["unity"] = "08"; STR["godot"] = "09"; STR["compose-desktop"] = "10"; STR["javafx"] = "11"
  STR["browser-extension"] = "12"; STR["notebook"] = "13"; STR["nerves"] = "14"; STR["rust-wasm"] = "15"
  STR["server-swift"] = "16"; STR["dart"] = "17"; STR["scala"] = "18"; STR["clojure"] = "19"
  STR["erlang"] = "20"; STR["gleam"] = "21"; STR["r"] = "22"; STR["cpp"] = "23"
  STR["haskell"] = "24"; STR["ocaml"] = "25"; STR["zig"] = "26"; STR["nim"] = "27"
  STR["crystal"] = "28"; STR["julia"] = "29"; STR["perl"] = "30"; STR["lua"] = "31"
  SAR["workspace-root"] = "00"; SAR["library"] = "01"; SAR["tooling"] = "02"; SAR["test"] = "03"
  SAR["extension"] = "04"; SAR["ci-action"] = "05"; SAR["infra"] = "06"; SAR["contract"] = "07"
  SAR["native-tooling"] = "08"; SAR["example"] = "09"; BR["bazel"] = "00"; BR["dockerfile"] = "01"
  HV["rn", "vercel"] = "not-covered"; HV["rn", "netlify"] = "not-covered"; HV["rn", "firebase"] = "not-covered"; HV["rn", "azure"] = "not-covered"
  HV["rn", "gcf"] = "not-covered"; HV["rn", "aws"] = "not-covered"; HV["rn", "cloudflare"] = "not-covered"; HV["rn", "supabase"] = "not-covered"
  HV["web", "vercel"] = "supported"; HV["web", "netlify"] = "supported"; HV["web", "firebase"] = "supported"; HV["web", "azure"] = "supported"
  HV["web", "gcf"] = "supported"; HV["web", "aws"] = "supported"; HV["web", "cloudflare"] = "supported"; HV["web", "supabase"] = "supported"
  HV["node", "vercel"] = "caveat"; HV["node", "netlify"] = "no-path"; HV["node", "firebase"] = "no-path"; HV["node", "azure"] = "no-path"
  HV["node", "gcf"] = "no-path"; HV["node", "aws"] = "caveat"; HV["node", "cloudflare"] = "no-path"; HV["node", "supabase"] = "no-path"
  HV["bun", "vercel"] = "not-covered"; HV["bun", "netlify"] = "not-covered"; HV["bun", "firebase"] = "not-covered"; HV["bun", "azure"] = "not-covered"
  HV["bun", "gcf"] = "not-covered"; HV["bun", "aws"] = "not-covered"; HV["bun", "cloudflare"] = "not-covered"; HV["bun", "supabase"] = "not-covered"
  HV["python", "vercel"] = "not-covered"; HV["python", "netlify"] = "not-covered"; HV["python", "firebase"] = "not-covered"; HV["python", "azure"] = "not-covered"
  HV["python", "gcf"] = "not-covered"; HV["python", "aws"] = "not-covered"; HV["python", "cloudflare"] = "not-covered"; HV["python", "supabase"] = "not-covered"
  HV["java", "vercel"] = "not-covered"; HV["java", "netlify"] = "not-covered"; HV["java", "firebase"] = "not-covered"; HV["java", "azure"] = "not-covered"
  HV["java", "gcf"] = "not-covered"; HV["java", "aws"] = "not-covered"; HV["java", "cloudflare"] = "not-covered"; HV["java", "supabase"] = "not-covered"
  HV["go", "vercel"] = "not-covered"; HV["go", "netlify"] = "not-covered"; HV["go", "firebase"] = "not-covered"; HV["go", "azure"] = "not-covered"
  HV["go", "gcf"] = "not-covered"; HV["go", "aws"] = "not-covered"; HV["go", "cloudflare"] = "not-covered"; HV["go", "supabase"] = "not-covered"
  HV["php", "vercel"] = "not-covered"; HV["php", "netlify"] = "not-covered"; HV["php", "firebase"] = "not-covered"; HV["php", "azure"] = "not-covered"
  HV["php", "gcf"] = "not-covered"; HV["php", "aws"] = "not-covered"; HV["php", "cloudflare"] = "not-covered"; HV["php", "supabase"] = "not-covered"
  HV["dotnet", "vercel"] = "not-covered"; HV["dotnet", "netlify"] = "not-covered"; HV["dotnet", "firebase"] = "not-covered"; HV["dotnet", "azure"] = "not-covered"
  HV["dotnet", "gcf"] = "not-covered"; HV["dotnet", "aws"] = "not-covered"; HV["dotnet", "cloudflare"] = "not-covered"; HV["dotnet", "supabase"] = "not-covered"
  HV["ruby", "vercel"] = "not-covered"; HV["ruby", "netlify"] = "not-covered"; HV["ruby", "firebase"] = "not-covered"; HV["ruby", "azure"] = "not-covered"
  HV["ruby", "gcf"] = "not-covered"; HV["ruby", "aws"] = "not-covered"; HV["ruby", "cloudflare"] = "not-covered"; HV["ruby", "supabase"] = "not-covered"
  HV["flutter", "vercel"] = "not-covered"; HV["flutter", "netlify"] = "not-covered"; HV["flutter", "firebase"] = "not-covered"; HV["flutter", "azure"] = "not-covered"
  HV["flutter", "gcf"] = "not-covered"; HV["flutter", "aws"] = "not-covered"; HV["flutter", "cloudflare"] = "not-covered"; HV["flutter", "supabase"] = "not-covered"
  HV["swift", "vercel"] = "not-covered"; HV["swift", "netlify"] = "not-covered"; HV["swift", "firebase"] = "not-covered"; HV["swift", "azure"] = "not-covered"
  HV["swift", "gcf"] = "not-covered"; HV["swift", "aws"] = "not-covered"; HV["swift", "cloudflare"] = "not-covered"; HV["swift", "supabase"] = "not-covered"
  HV["kotlin", "vercel"] = "not-covered"; HV["kotlin", "netlify"] = "not-covered"; HV["kotlin", "firebase"] = "not-covered"; HV["kotlin", "azure"] = "not-covered"
  HV["kotlin", "gcf"] = "not-covered"; HV["kotlin", "aws"] = "not-covered"; HV["kotlin", "cloudflare"] = "not-covered"; HV["kotlin", "supabase"] = "not-covered"
  HV["rust", "vercel"] = "not-covered"; HV["rust", "netlify"] = "not-covered"; HV["rust", "firebase"] = "not-covered"; HV["rust", "azure"] = "not-covered"
  HV["rust", "gcf"] = "not-covered"; HV["rust", "aws"] = "not-covered"; HV["rust", "cloudflare"] = "not-covered"; HV["rust", "supabase"] = "not-covered"
  HV["elixir", "vercel"] = "not-covered"; HV["elixir", "netlify"] = "not-covered"; HV["elixir", "firebase"] = "not-covered"; HV["elixir", "azure"] = "not-covered"
  HV["elixir", "gcf"] = "not-covered"; HV["elixir", "aws"] = "not-covered"; HV["elixir", "cloudflare"] = "not-covered"; HV["elixir", "supabase"] = "not-covered"
  HV["edge", "vercel"] = "not-covered"; HV["edge", "netlify"] = "caveat"; HV["edge", "firebase"] = "not-covered"; HV["edge", "azure"] = "not-covered"
  HV["edge", "gcf"] = "not-covered"; HV["edge", "aws"] = "not-covered"; HV["edge", "cloudflare"] = "supported"; HV["edge", "supabase"] = "supported"
}
$1 == "C01" || $1 == "C02" { print; next }
$1 == "Z1" { z1 = 1; next }
$1 == "F" {
  if (REC) print
  key = $2 SUBSEP $3
  if (!(key in FK)) { NFK++; FK[key] = NFK; FKH[NFK] = $2; FKS[NFK] = $3; FKR[NFK] = 0; FKML[NFK] = "" }
  o = FK[key]
  if ($4 != "-") {
    FKR[o] = 1
    if ($4 != "") {
      nm = split($4, ma, ",")
      for (i = 1; i <= nm; i++) if (!((o, ma[i]) in FKM)) { FKM[o, ma[i]] = 1; FKML[o] = FKML[o] " " ma[i] }
    }
  }
  next
}
END {
  boo_step0(); boo_step1(); boo_python(); boo_ruby(); boo_rust(); boo_main(); boo_npm(); boo_later(); boo_emit()
  if (z1) print "Z2"
}
function boo_add(t, k, h, f, app, lib, ab, host) {
  NE++
  ET[NE] = t; EK[NE] = k; EH[NE] = h; EF[NE] = f
  EA[NE] = app + 0; EL[NE] = lib + 0; EB[NE] = ab; EO[NE] = host; ED[NE] = 0
  return NE
}
function boo_parent(h,    p, q) {
  if (h == ".") return ""
  p = 0
  while ((q = index(substr(h, p + 1), "/")) > 0) p += q
  return substr(h, 1, p - 1)
}
# Is a folder at or above h (self = 1), or strictly above it (self = 0), in A?
function boo_anc(h, A, self,    x) {
  x = self ? h : boo_parent(h)
  while (x != "") { if (x in A) return 1; x = boo_parent(x) }
  return 0
}
function boo_deepest(h, A,    x) {
  x = h
  while (x != "") { if (x in A) return x; x = boo_parent(x) }
  return ""
}
function boo_flag(h, x) { return ((h, x) in FL) }
function boo_has(i, m) { return ((i, m) in XM) }
function boo_grp(i, g) { return ((i, g) in XG) }
function boo_folders(h, r) { if (!(h in FOLDS) || FOLDR[r] < FOLDR[FOLDS[h]]) FOLDS[h] = r }
function boo_hostfile(h, host) { if (!(h in HF) || HRANK[host] < HRANK[HF[h]]) HF[h] = host }
function boo_mark(i, m,    k, n, a, g) {
  XM[i, m] = 1
  XML[i] = XML[i] " " m
  k = XR[i] SUBSEP m
  if (k in MG) { n = split(MG[k], a, " "); for (g = 1; g <= n; g++) XG[i, a[g]] = 1 }
  if ((k in MHOST) && (XHOST[i] == "" || HRANK[MHOST[k]] < HRANK[XHOST[i]])) XHOST[i] = MHOST[k]
}
function boo_firststack(i,    r, k) {
  r = XR[i]
  for (k = 1; k <= SHLN[r]; k++) if ((i, SHL[r, k]) in XM) return SHS[r, k]
  return ""
}
function boo_bunhome(h,    x) {
  if (boo_flag(h, "bun")) return 1
  x = boo_parent(h)
  while (x != "") { if (boo_flag(x, "bun") && boo_flag(x, "ws")) return 1; x = boo_parent(x) }
  return 0
}
# An Nx root with Nx projects beneath it: its package.json holds the
# dependencies of every project, so it is the workspace, not an app.
function boo_nxbelow(h,    x) {
  if (!boo_flag(h, "nxroot")) return 0
  for (x in NXH) if (index(x, h "/") == 1) return 1
  return 0
}
function boo_pagenear(h) { return boo_flag(h, "page") || boo_flag(h "/public", "page") || boo_flag(h "/src", "page") }
# Step 0: one fact per folder and signal, the probe filter, convention
# folders and examples.
function boo_step0(    o, h, s, j, known, nc, pc, c, conv, ex, eh, n, a, q, ok, i) {
  for (o = 1; o <= NFK; o++) {
    h = FKH[o]
    s = FKS[o]
    if (!(s in SIGI)) continue
    j = SIGI[s]
    known = SCONT[j] ? FKR[o] : 1
    if (SPROBE[j] && known) {
      ok = 0
      for (q = 1; q <= PRBN[j]; q++) if ((o, PRB[j, q]) in FKM) ok = 1
      if (!ok) continue
    }
    nc = split(h, pc, "/")
    conv = 0
    for (c = 1; c <= nc; c++) if (pc[c] in CONVF) conv = 1
    if (conv) continue
    ex = 0
    for (c = 2; c <= nc; c++) if (pc[c] in EXF) { ex = c; break }
    if (ex) {
      eh = pc[1]
      for (c = 2; c <= ex; c++) eh = eh "/" pc[c]
      boo_add("S", "example", eh)
      continue
    }
    NX++
    XH[NX] = h; XS[NX] = s; XJ[NX] = j; XR[NX] = SROLE[j]; XK[NX] = known
    if (SCONT[j] && known) { n = split(FKML[o], a, " "); for (i = 1; i <= n; i++) boo_mark(NX, a[i]) }
  }
}
# Step 1: per-folder flags.
function boo_step1(    i, h, r, j) {
  for (i = 1; i <= NX; i++) {
    h = XH[i]; r = XR[i]; j = XJ[i]
    if (r == "bun") FL[h, "bun"] = 1
    if (r == "npm" && boo_has(i, "pm-bun")) FL[h, "bun"] = 1
    if (r == "wsroot") FL[h, "ws"] = 1
    if (XS[i] == "nx.json") FL[h, "nxroot"] = 1
    if (r == "nx") NXH[h] = 1
    if (r == "npm" && boo_has(i, "workspaces")) FL[h, "ws"] = 1
    if (r == "wrangler" || r == "deno" || r == "gradle" || r == "npm" || r == "gemspec" || r == "configru" || r == "rustbin" || r == "trunk" || r == "page") FL[h, r] = 1
    if (r == "gsettings") FL[h, "settings"] = 1
    if (r == "pymanage") FL[h, "manage"] = 1
    if ((r == "host" || r == "hostprobe" || r == "wrangler") && SHOST[j] != "" && (r != "hostprobe" || XK[i])) boo_hostfile(h, SHOST[j])
    if (r == "ciaction") boo_folders(h, "ci-action")
    if (r == "contract") boo_folders(h, "contract")
    if (r == "infra") boo_folders(h, "infra")
  }
}
function boo_pymark(h, m,    k, n, a, g) {
  PYM[h, m] = 1
  k = "py" SUBSEP m
  if (k in MG) { n = split(MG[k], a, " "); for (g = 1; g <= n; g++) PYG[h, a[g]] = 1 }
  if ((k in MHOST) && (PYHOST[h] == "" || HRANK[MHOST[k]] < HRANK[PYHOST[h]])) PYHOST[h] = MHOST[k]
}
# Step 2: Python, merged per folder.
function boo_python(    i, r, h, n, a, k, q, srv) {
  for (i = 1; i <= NX; i++) {
    r = XR[i]
    if (r != "py" && r != "pymanage") continue
    h = XH[i]
    if (!(h in PYS)) { PYS[h] = 1; PYN++; PYL[PYN] = h; PYALL[h] = 1; PYK[h] = 0 }
    if (SCONT[XJ[i]] && !XK[i]) { boo_add("U", XS[i], h); continue }
    PYK[h]++
    if (XS[i] != "pyproject.toml") PYALL[h] = 0
    if (XS[i] == "setup.py" || XS[i] == "setup.cfg") PYPKG[h] = 1
    n = split(XML[i], a, " ")
    for (k = 1; k <= n; k++) boo_pymark(h, a[k])
  }
  for (q = 1; q <= PYN; q++) {
    h = PYL[q]
    if (!PYK[h]) continue
    srv = ((h, "server") in PYG) || boo_flag(h, "manage")
    if (((h, "uv-workspace") in PYM) && !srv) { boo_add("S", "workspace-root", h, "", 0, 0, "weak"); continue }
    if (PYALL[h] && ((h, "tools-only") in PYM)) { boo_add("S", "tooling", h); continue }
    if (((h, "infra") in PYG) && !srv) { boo_folders(h, "infra"); continue }
    if (((h, "ssg") in PYG) && !srv) { boo_add("K", "web", h, "layout", 1, 0, "ssg"); continue }
    if (((h, "test") in PYG) && !srv && !(h in PYPKG) && !((h, "other") in PYM) && !((h, "project") in PYM) && !((h, "scripts") in PYM)) { boo_add("S", "test", h); continue }
    boo_add("K", "python", h, "", srv, !srv, "", PYHOST[h])
  }
}
# Step 2: Ruby, merged per folder.
function boo_ruby(    i, r, h, q, gi, hasM, srv) {
  for (i = 1; i <= NX; i++) {
    r = XR[i]
    if (r != "gemfile" && r != "configru" && r != "gemspec") continue
    h = XH[i]
    if (!(h in RBS)) { RBS[h] = 1; RBN++; RBL[RBN] = h }
    if (r == "gemfile" && !(h in RBG)) RBG[h] = i
  }
  for (q = 1; q <= RBN; q++) {
    h = RBL[q]
    if (boo_flag(h, "gemspec")) { boo_add("S", "library", h); continue }
    gi = (h in RBG) ? RBG[h] : 0
    if (gi && !XK[gi]) boo_add("U", XS[gi], h)
    hasM = (gi && XK[gi]) ? 1 : 0
    srv = (hasM && boo_grp(gi, "server")) || boo_flag(h, "configru")
    if (!hasM && !srv) continue
    if (hasM && boo_grp(gi, "ssg") && !srv) { boo_add("K", "web", h, "layout", 1, 0, "ssg"); continue }
    if (hasM && boo_grp(gi, "nativetool") && !srv) { boo_add("S", "native-tooling", h); continue }
    if (hasM && boo_grp(gi, "test") && !srv && !boo_has(gi, "other")) { boo_add("S", "test", h); continue }
    boo_add("K", "ruby", h, "", srv, !srv)
  }
}
# Step 2: Rust, merged per folder.
function boo_rust(    i, r, h, q, ci, hasM, srv, bin) {
  for (i = 1; i <= NX; i++) {
    r = XR[i]
    if (r != "cargo" && r != "rustbin" && r != "trunk") continue
    h = XH[i]
    if (!(h in RSS)) { RSS[h] = 1; RSN++; RSL[RSN] = h }
    if (r == "cargo" && !(h in RSC)) RSC[h] = i
  }
  for (q = 1; q <= RSN; q++) {
    h = RSL[q]
    ci = (h in RSC) ? RSC[h] : 0
    if (ci && !XK[ci]) boo_add("U", XS[ci], h)
    hasM = (ci && XK[ci]) ? 1 : 0
    if (hasM && boo_has(ci, "workspace") && !boo_has(ci, "package")) { boo_add("S", "workspace-root", h, "", 0, 0, "weak"); continue }
    if (hasM && boo_grp(ci, "shell")) { boo_add("N", "tauri", h, "", 0, 0, "tree"); continue }
    srv = (hasM && boo_grp(ci, "server")) ? 1 : 0
    if (boo_flag(h, "trunk") || (hasM && boo_grp(ci, "wasmui") && !srv)) { boo_add("N", "rust-wasm", h); continue }
    bin = boo_flag(h, "rustbin") || (hasM && boo_has(ci, "bin"))
    if (srv || bin) boo_add("K", "rust", h, "", srv, !srv, "", (hasM ? XHOST[ci] : ""))
    else if (hasM) boo_add("S", "library", h)
  }
}
# Step 2: every other manifest.
function boo_main(    i, h, r, kn, j, any, st, svc) {
  for (i = 1; i <= NX; i++) if (XR[i] == "composer" && XK[i] && boo_has(i, "library-type")) COMPLIB[XH[i]] = 1
  for (i = 1; i <= NX; i++) {
    h = XH[i]; r = XR[i]; kn = XK[i]; j = XJ[i]
    if (r == "gradle") {
      if (!kn) { boo_add("U", XS[i], h); continue }
      any = 0
      if (boo_has(i, "android-app")) { boo_add("K", "kotlin", h, "", 1); any = 1 }
      if (boo_has(i, "compose-desktop")) { boo_add("N", "compose-desktop", h); any = 1 }
      if (boo_has(i, "javafx")) { boo_add("N", "javafx", h); any = 1 }
      if (any) continue
      if (boo_has(i, "android-test")) boo_add("S", "test", h)
      else if (boo_has(i, "android-lib") || boo_has(i, "kmp") || boo_has(i, "jvm-lib")) boo_add("S", "library", h)
      else if (boo_has(i, "kotlin-dsl")) any = 0
      else if (boo_has(i, "jvm-server") || boo_has(i, "jvm-app")) boo_add("K", "java", h, "", 1)
      else if (boo_flag(h, "settings")) boo_add("S", "workspace-root", h, "", 0, 0, "weak")
      else boo_add("K", "java", h, "", 0, 1)
    } else if (r == "gsettings") {
      if (!boo_flag(h, "gradle")) boo_add("S", "workspace-root", h, "", 0, 0, "weak")
    } else if (r == "amanifest") {
      if (!boo_flag(h, "gradle")) boo_add("K", "kotlin", h, "", 1)
    } else if (r == "maven") {
      if (!kn) boo_add("U", XS[i], h)
      else if (boo_has(i, "pom-packaging")) boo_add("S", "workspace-root", h)
      else if (boo_has(i, "javafx")) boo_add("N", "javafx", h)
      else if (boo_grp(i, "server")) boo_add("K", "java", h, "", 1)
      else boo_add("K", "java", h, "", 0, 1)
    } else if (r == "go") {
      if (!kn) boo_add("U", XS[i], h)
      else if (boo_grp(i, "shell")) boo_add("N", "wails", h, "", 0, 0, "tree")
      else boo_add("K", "go", h, "", boo_grp(i, "server"), !boo_grp(i, "server"), "", XHOST[i])
    } else if (r == "composer") {
      if (!kn) boo_add("U", XS[i], h)
      else if (boo_has(i, "library-type")) boo_add("S", "library", h)
      else if (boo_has(i, "wordpress")) boo_add("K", "php", h, "", 1, 0, "tree")
      else boo_add("K", "php", h, "", 1)
    } else if (r == "phpindex") {
      if (!(h in COMPLIB)) boo_add("K", "php", h, "", 1)
    } else if (r == "artisan") {
      boo_add("K", "php", h, "", 1)
    } else if (r == "wpconfig") {
      boo_add("K", "php", h, "", 1, 0, "tree")
    } else if (r == "dotnet") {
      if (!kn) { boo_add("U", XS[i], h); continue }
      st = boo_firststack(i)
      svc = boo_has(i, "web-sdk") || boo_has(i, "worker-sdk") || boo_has(i, "functions") || boo_has(i, "aspnet")
      if (st != "") boo_add("N", st, h, "", 0, 0, "tree")
      else if (boo_has(i, "iac") && !svc) boo_folders(h, "infra")
      else if (boo_has(i, "test")) boo_add("S", "test", h)
      else if (boo_grp(i, "server")) boo_add("K", "dotnet", h, "", 1, 0, "", XHOST[i])
      else boo_add("S", "library", h)
    } else if (r == "sln" || r == "wsroot") {
      boo_add("S", "workspace-root", h, "", 0, 0, "weak")
    } else if (r == "mix") {
      if (!kn) boo_add("U", XS[i], h)
      else if (boo_has(i, "umbrella")) boo_add("S", "workspace-root", h)
      else if (boo_has(i, "nerves")) boo_add("N", "nerves", h, "", 0, 0, "tree")
      else if (boo_grp(i, "server")) boo_add("K", "elixir", h, "", 1)
      else boo_add("S", "library", h)
    } else if (r == "pubspec") {
      if (!kn) boo_add("U", XS[i], h)
      else if (boo_has(i, "flutter") && boo_has(i, "plugin")) boo_add("S", "library", h)
      else if (boo_has(i, "flutter")) boo_add("K", "flutter", h, "", 1, 0, "native")
      else boo_add("N", "dart", h)
    } else if (r == "xcode") {
      boo_add("K", "swift", h, "", 1)
    } else if (r == "xcodegen" || r == "tuist") {
      if (!kn) boo_add("U", XS[i], h)
      else boo_add("K", "swift", h, "", 1)
    } else if (r == "swiftpm") {
      if (!kn) boo_add("U", XS[i], h)
      else if (boo_has(i, "swift-server")) boo_add("N", "server-swift", h)
      else if (boo_has(i, "apple-platform") && boo_has(i, "executable")) boo_add("K", "swift", h, "", 1)
      else if (boo_has(i, "executable")) boo_add("N", "server-swift", h)
      else boo_add("S", "library", h)
    } else if (r == "deno") {
      boo_add("K", "edge", h, "", 1)
    } else if (r == "supafn") {
      boo_add("K", "edge", h "/supabase/functions", "", 1, 0, "tree", "supabase")
    } else if (r == "bun") {
      if (!boo_flag(h, "npm")) boo_add("K", "bun", h, "", 1)
    } else if (r == "nx") {
      if (!kn) { if (!boo_flag(h, "npm")) boo_add("U", XS[i], h) }
      else if (boo_has(i, "nx-e2e")) boo_add("S", "test", h)
      else if (boo_has(i, "nx-lib")) boo_add("S", "library", h)
      else if (boo_has(i, "nx-rn")) boo_add("K", "rn", h, "", 1, 0, "native")
      else if (boo_has(i, "nx-next")) { boo_add("K", "web", h, "module", 1); boo_add("K", "node", h, "", 1) }
      else if (boo_has(i, "nx-node")) boo_add("K", "node", h, "", 1)
      else if (boo_has(i, "nx-web")) boo_add("K", "web", h, "module", 1)
      else if (!boo_flag(h, "npm")) boo_add("U", XS[i], h)
    } else if (r == "ssg") {
      boo_add("K", "web", h, "layout", 1, 0, "ssg")
    } else if (r == "page") {
      boo_add("P", "html", h)
    } else if (r == "tpl") {
      boo_add("P", "tpl", h)
    } else if (r == "shell") {
      boo_add("N", (SSTACK[j] != "" ? SSTACK[j] : "capacitor"), h, "", 0, 0, "tree")
    } else if (r == "extmanifest") {
      if (!kn) boo_add("U", XS[i], h)
      else boo_add("N", "browser-extension", h, "", 0, 0, "tree")
    } else if (r == "hostprobe") {
      if (!kn) boo_add("U", XS[i], h)
    } else if (r == "notebook") {
      boo_add("N", "notebook", h)
    } else if (r == "lang") {
      boo_add("L", (SSTACK[j] != "" ? SSTACK[j] : "cpp"), h)
    } else if (r == "blind") {
      if (SBLIND[j] == "bazel") boo_add("B", "bazel", h)
      else boo_add("D", "dockerfile", h)
    } else if (r == "nativetool") {
      boo_add("S", "native-tooling", h)
    }
  }
}
# Step 3: package.json, knowing the other-language apps.
function boo_npm(    e, i, h, st, rn, wu, sg, srv, host, appish, web, half, kit) {
  for (e = 1; e <= NE; e++) if (!ED[e] && ET[e] == "K" && EA[e] && (EK[e] in FOREIGN)) FAPP[EH[e]] = 1
  for (i = 1; i <= NX; i++) if (XR[i] == "npm") FSNAP[XH[i]] = boo_anc(XH[i], FAPP, 1)
  for (i = 1; i <= NX; i++) {
    if (XR[i] != "npm") continue
    h = XH[i]
    if (!XK[i]) { boo_add("U", XS[i], h); continue }
    st = boo_firststack(i)
    if (st != "") { boo_add("N", st, h, "", 0, 0, "tree"); continue }
    if (boo_has(i, "vscode")) { boo_add("S", "extension", h); continue }
    rn = boo_grp(i, "rn"); wu = boo_grp(i, "webui"); sg = boo_grp(i, "ssg")
    srv = (boo_grp(i, "server") || boo_grp(i, "ssr")) ? 1 : 0
    host = XHOST[i]
    appish = rn || wu || sg || srv
    if (!appish && boo_grp(i, "contract")) { boo_folders(h, "contract"); continue }
    if (!appish && boo_grp(i, "infra")) { boo_folders(h, "infra"); continue }
    if (FSNAP[h] && !rn && !srv) {
      if (wu || sg || boo_grp(i, "bundler") || boo_grp(i, "assetbundler")) boo_add("K", "web", h, "module", 1)
      continue
    }
    if ((boo_flag(h, "ws") || boo_has(i, "workspaces")) && ((!rn && !wu && !srv && !sg) || boo_nxbelow(h))) { boo_add("S", "workspace-root", h, "", 0, 0, "weak"); continue }
    if ((boo_has(i, "peers") && !boo_has(i, "private")) || (boo_has(i, "lib-entry") && !boo_has(i, "run") && !boo_has(i, "bin"))) { boo_add("S", "library", h); continue }
    web = 0
    if (rn) boo_add("K", "rn", h, "", 1, 0, "native")
    if (sg) { boo_add("K", "web", h, "layout", 1, 0, "ssg"); web = 1 }
    else if (!rn && (wu || (boo_grp(i, "bundler") && boo_pagenear(h)))) { boo_add("K", "web", h, "module", 1); web = 1 }
    half = srv
    if (!rn && !web && !srv) {
      if (boo_grp(i, "e2e") && !boo_has(i, "run")) { boo_add("S", "test", h); continue }
      if (!boo_has(i, "other") && !boo_has(i, "run") && !boo_has(i, "bin")) { boo_add("S", "tooling", h); continue }
      half = 1
    }
    if (half) {
      if (boo_flag(h, "wrangler") || boo_flag(h, "deno")) kit = "edge"
      else if (boo_bunhome(h) || boo_grp(i, "bunfw")) kit = "bun"
      else kit = "node"
      boo_add("K", kit, h, "", srv, (!srv && !boo_has(i, "run")), "", host)
    }
  }
  for (e = 1; e <= NE; e++) if (!ED[e] && ET[e] == "K" && EK[e] == "edge") KEDGE[EH[e]] = 1
  for (i = 1; i <= NX; i++) if (XR[i] == "wrangler" && !(XH[i] in KEDGE)) { boo_add("K", "edge", XH[i], "", 1); KEDGE[XH[i]] = 1 }
}
# Steps 4 to 12.
function boo_later(    h, e, app, d, x, o, c, k, kk, st, skip) {
  # 4: whole-folder set-asides
  for (h in FOLDS) {
    app = 0
    for (e = 1; e <= NE; e++) if (!ED[e] && ET[e] == "K" && EA[e] && EH[e] == h) { app = 1; break }
    for (e = 1; e <= NE; e++) if (!ED[e] && EH[e] == h && !(app && ET[e] == "K" && EA[e])) ED[e] = 1
    if (!app) boo_add("S", FOLDS[h], h)
  }
  # 5: whole-subtree owners
  for (e = 1; e <= NE; e++) if (!ED[e] && EB[e] == "tree") { TREE[e] = 1; TREEH[EH[e]] = 1 }
  for (e in TREE) if (boo_anc(EH[e], TREEH, 0)) ED[e] = 1
  for (e in TREE) if (!ED[e]) LIVET[EH[e]] = 1
  for (e = 1; e <= NE; e++) if (!ED[e] && EB[e] != "tree" && boo_anc(EH[e], LIVET, 1)) ED[e] = 1
  # 6: the generated native folders of a phone app
  for (e = 1; e <= NE; e++) if (!ED[e] && EB[e] == "native") for (d = 1; d <= NNAT; d++) NATP[EH[e] "/" NATF[d]] = 1
  for (e = 1; e <= NE; e++) if (!ED[e] && boo_anc(EH[e], NATP, 1)) ED[e] = 1
  # 7: a site generator owns its page tree
  for (e = 1; e <= NE; e++) if (!ED[e] && EB[e] == "ssg") SSGH[EH[e]] = 1
  for (e = 1; e <= NE; e++) {
    if (ED[e]) continue
    if (ET[e] == "P" && boo_anc(EH[e], SSGH, 1)) ED[e] = 1
    else if (ET[e] == "K" && (EH[e] in SSGH) && !EA[e]) ED[e] = 1
  }
  # 8: one PHP project
  for (e = 1; e <= NE; e++) if (!ED[e] && ET[e] == "K" && EK[e] == "php") { PHPE[e] = 1; PHPH[EH[e]] = 1 }
  for (e in PHPE) if (boo_anc(EH[e], PHPH, 0)) ED[e] = 1
  # 9: notebooks, grouped at the topmost folder
  for (e = 1; e <= NE; e++) if (!ED[e] && ET[e] == "N" && EK[e] == "notebook") { NBE[e] = 1; NBH[EH[e]] = 1 }
  for (e in NBE) if (boo_anc(EH[e], NBH, 0)) ED[e] = 1
  for (e in NBE) if (!ED[e]) LIVENB[EH[e]] = 1
  for (e = 1; e <= NE; e++) if (!ED[e] && ET[e] == "K" && EK[e] == "python" && !EA[e] && (EH[e] in LIVENB)) ED[e] = 1
  # 10: a set-aside beside a named kit is part of that project
  for (e = 1; e <= NE; e++) if (!ED[e] && ET[e] == "K") KH[EH[e]] = 1
  for (e = 1; e <= NE; e++) if (!ED[e] && ET[e] == "S" && (EH[e] in KH)) ED[e] = 1
  # 11: pages, the templates of a server, or plain HTML
  for (e = 1; e <= NE; e++) {
    if (ED[e]) continue
    if (ET[e] == "K" || ET[e] == "N" || (ET[e] == "S" && EK[e] != "workspace-root")) OWNH[EH[e]] = 1
    if (ET[e] == "K") {
      if (EK[e] in PAGEOWN) KSRV[EH[e]] = 1
      if (EK[e] in PHONE) KPH[EH[e]] = 1
      if (EK[e] == "web") { x = EH[e]; while (x != "") { WEBANC[x] = 1; x = boo_parent(x) } }
    }
  }
  for (e = 1; e <= NE; e++) {
    if (ED[e] || ET[e] != "P") continue
    o = boo_deepest(EH[e], OWNH)
    if (o == "") { if (EK[e] == "html") HTMLC[EH[e]] = 1; continue }
    if ((o in KSRV) && !(o in KPH) && !(o in WEBANC)) LAYO[o] = 1
  }
  for (o in LAYO) boo_add("K", "web", o, "layout", 1)
  for (c in HTMLC) if (!boo_anc(c, HTMLC, 0)) boo_add("K", "web", c, "html", 1)
  # 12: languages with no kit, Dockerfiles, Bazel, only where nothing owns them
  for (e = 1; e <= NE; e++) if (!ED[e] && (ET[e] == "K" || ET[e] == "N" || (ET[e] == "S" && EK[e] != "workspace-root"))) OWN2[EH[e]] = 1
  for (e = 1; e <= NE; e++) {
    if (ED[e] || (ET[e] != "L" && ET[e] != "D")) continue
    if (boo_anc(EH[e], OWN2, 1)) continue
    if (ET[e] == "L") ULANG[EK[e], EH[e]] = 1
    else UDOCK[EH[e]] = 1
  }
  for (k in ULANG) {
    split(k, kk, SUBSEP)
    st = kk[1]
    h = kk[2]
    skip = 0
    x = boo_parent(h)
    while (x != "") { if ((st, x) in ULANG) { skip = 1; break }; x = boo_parent(x) }
    if (!skip) printf "N%s\t%s\t%s\n", STR[st], h, st
  }
  for (h in UDOCK) if (!boo_anc(h, UDOCK, 0)) printf "B%s\t%s\tdockerfile\n", BR["dockerfile"], h
  for (e = 1; e <= NE; e++) if (!ED[e] && ET[e] == "B") BZH[EH[e]] = 1
  for (h in BZH) if (!boo_anc(h, BZH, 0)) printf "B%s\t%s\tbazel\n", BR["bazel"], h
}
# A host file in a folder above that is not a project of its own (a SAM
# template above its functions) configures the projects beneath it.
function boo_inherit(h,    x) {
  x = boo_parent(h)
  while (x != "") { if (x in HF) return ((x in KHOME) ? "" : HF[x]); x = boo_parent(x) }
  return ""
}
# Step 13: one line per kit and folder, with its host note.
function boo_emit(    e, k, kk, kit, h, host, r, q) {
  for (e = 1; e <= NE; e++) {
    if (ED[e] || ET[e] != "K") continue
    k = EK[e] SUBSEP EH[e]
    KHOME[EH[e]] = 1
    if (!(k in KK)) { KK[k] = 1; KF[k] = ""; KLB[k] = 1; KHO[k] = "" }
    if (FLR[EF[e]] < FLR[KF[k]]) KF[k] = EF[e]
    if (!EL[e]) KLB[k] = 0
    if (EO[e] != "" && (KHO[k] == "" || HRANK[EO[e]] < HRANK[KHO[k]])) KHO[k] = EO[e]
    KITS[EK[e]] = 1
  }
  for (k in KK) {
    split(k, kk, SUBSEP)
    kit = kk[1]
    h = kk[2]
    printf "K%s\t%s\t%s\t%s\t%s\n", KR[kit], h, kit, (KF[k] == "" ? "-" : KF[k]), (KLB[k] ? "maybe-library" : "-")
    host = (h in HF) ? HF[h] : (KHO[k] != "" ? KHO[k] : boo_inherit(h))
    if (host != "") printf "H%s\t%s\t%s\t%s\t%s\n", KR[kit], h, kit, host, HV[kit, host]
  }
  for (e = 1; e <= NE; e++) {
    if (ED[e]) continue
    if (ET[e] == "N") printf "N%s\t%s\t%s\n", STR[EK[e]], EH[e], EK[e]
    else if (ET[e] == "S") printf "S%s\t%s\t%s\n", SAR[EK[e]], EH[e], EK[e]
    else if (ET[e] == "U") printf "U00\t%s\t%s\n", EH[e], EK[e]
  }
  r = ""
  for (q = 1; q <= NKIT; q++) if (KO[q] in KITS) r = r (r == "" ? "" : ",") KO[q]
  printf "R99\t%s\n", (r == "" ? "none" : r)
}
'
}

boosthis_prog_print() {
printf '%s\n' '# Prints the report: the coverage header first (before the walk has
# finished), then each section, then the result line — last, so its absence
# means the scan did not finish, or could not read the whole folder.
BEGIN {
  boo_init()
  FS = "\t"
  REC = (ENVIRON["BOOSTHIS_SCAN_RECORDS"] == "1")
  T_TITLE = "Boosthis project scanner"
  T_SCANNED = "Scanned: %F"
  T_SCANNED2 = "(file names and manifest contents only — no source code read, nothing uploaded)"
  T_COVER = "Boosthis has kits for: React Native / Expo apps; websites; Node.js; Bun;\nPython; Java / JVM servers; Go; PHP; ASP.NET Core, .NET workers and console\napps; Ruby; Flutter apps; Swift apps for Apple platforms; Android apps; Rust\nservers; Elixir; edge functions (Cloudflare Workers, Deno, Supabase).\nOther stacks have no Boosthis kit. The ones this scanner recognises are listed\nunder “Found, no kit”, so “nothing found” and “no kit for it” never look the\nsame.\nNot scanned: hidden folders (names starting with a dot, such as .git, .cache\nor .pythonlibs), and dependency, build-output, virtualenv, cache, coverage,\ntest-data and fixture folders — the script\047s find command lists every folder\nname it skips."
  T_KITS_HEAD = "Kits for this project — one Boosthis kit per runtime:"
  T_INST_HEAD = "      install (run in each folder above, with the same project key for every\n      kit):"
  T_SIGNOTE = "Each install checks the kit\047s signature before unpacking (the ssh-keygen and\nsha256sum lines). If a check fails, stop there: unpack nothing and delete the\ndownloaded files."
  T_NOKIT_HEAD = "Found, no kit — Boosthis has no kit for these, so there is nothing to install:"
  T_UNDEC_HEAD = "Undecided — these manifests could not be read (over 2 MB, or not readable), so\nno kit is named for them:"
  T_ASIDE = "Set aside as not a running app: %L."
  T_BLIND_HEAD = "Blind spots — builds this scanner cannot read:"
  T_UNREAD1 = "1 folder could not be read (permission denied), so what is inside it was not scanned."
  T_UNREADN = "%N folders could not be read (permission denied), so what is inside them was not scanned."
  T_NL1 = "1 file or folder name contains a line break, so it was not read."
  T_NLN = "%N file or folder names contain a line break, so they were not read."
  T_MORE = "… and %N more: "
  T_IN = "%N in %F"
  T_SEP = ", "
  T_NOTHING = "Nothing detected under %F: no file this scanner knows was found."
  T_PICK = "If this is a plain HTML site, or you would rather pick a runtime yourself (rn\n| web | node | bun | python | java | go | php | dotnet | ruby | flutter |\nswift | kotlin | rust | elixir | edge), the Setup page for your project key\nhas copy-paste instructions: https://www.boosthis.com/dashboard."
  T_NOKIT_END = "No Boosthis kit applies to what was found above."
  T_KITS_END = "That is the inventory: one Boosthis kit per runtime listed above.\n\nInstall steps are not published on the open web. Two ways to get them:\n  • Sign in at https://www.boosthis.com/dashboard — the Setup page for your\n    project key carries the exact command for each kit, key already filled in.\n  • Re-run this scanner with that key and it prints them here:\n\n      curl -fsSL -H \"Authorization: Bearer <your project key>\" https://www.boosthis.com/scan -o boosthis-scan.sh\n      sh boosthis-scan.sh"
  T_REACH = "What this scan reads: file and folder names, and the contents of these files\nonly: package.json, project.json, build.gradle, build.gradle.kts, pom.xml,\nrequirements.txt, requirements-*.txt, requirements/*.txt, pyproject.toml,\nPipfile, go.mod, composer.json, *.csproj, *.fsproj, *.vbproj, Gemfile,\nCargo.toml, mix.exs, pubspec.yaml, project.yml, Project.swift, Package.swift,\nhost.json, template.yaml, template.yml, manifest.json. It never reads source\ncode, and it cannot see a stack none of whose files it knows, so a stack\nmissing from the list proves nothing."
  T_INCOMPLETE = "The scan did not finish: a step of it failed, so this answer may be incomplete\nand no result line is printed."
  T_PARTIAL = "The scan is incomplete: it could not read everything in this folder (stated\nabove), so this project may need a kit that is not listed here, and no result\nline is printed. Make what it skipped readable, or scan a folder that leaves\nit out, then run the scan again."
  T_MAYBE = "        no server framework named: this may be a library or a tool rather than\n        a running service"
  RESULT_HEAD = "BOOSTHIS-SCAN-RESULT rules=2 kits="
  KEYED = 0
  CAP = 12
  AR = 0
  KLINE["rn"] = "  • Mobile app (React Native / Expo) kit  (runtime: rn)"
  KLINE["web"] = "  • Website (browser) kit  (runtime: web)"
  KLINE["node"] = "  • Node.js backend kit  (runtime: node)"
  KLINE["bun"] = "  • Bun backend kit  (runtime: bun)"
  KLINE["python"] = "  • Python backend kit  (runtime: python)"
  KLINE["java"] = "  • Java backend (JVM) kit  (runtime: java)"
  KLINE["go"] = "  • Go backend kit  (runtime: go)"
  KLINE["php"] = "  • PHP backend kit  (runtime: php)"
  KLINE["dotnet"] = "  • C# / .NET backend kit  (runtime: dotnet)"
  KLINE["ruby"] = "  • Ruby backend (Rails / Rack) kit  (runtime: ruby)"
  KLINE["flutter"] = "  • Mobile app (Flutter) kit  (runtime: flutter)"
  KLINE["swift"] = "  • Apple app (Swift) kit  (runtime: swift)"
  KLINE["kotlin"] = "  • Android app (Kotlin) kit  (runtime: kotlin)"
  KLINE["rust"] = "  • Rust backend kit  (runtime: rust)"
  KLINE["elixir"] = "  • Elixir backend (Phoenix / OTP) kit  (runtime: elixir)"
  KLINE["edge"] = "  • Edge functions (Cloudflare Workers, Deno, Supabase) kit  (runtime: edge)"
  FNOTE["module"] = "        bundled app: install the web kit as a module"
  FNOTE["layout"] = "        pages rendered from templates: add the one-line script to the layout\n        template"
  FNOTE["html"] = "        plain HTML pages: paste the one-line script into each page\047s <head>"
  HW[1] = "        configured for Vercel: this kit\047s guide does not cover this host"
  HNI["rn", "vercel"] = 1
  HW[2] = "        configured for Netlify: this kit\047s guide does not cover this host"
  HNI["rn", "netlify"] = 2
  HW[3] = "        configured for Firebase Functions: this kit\047s guide does not cover\n        this host"
  HNI["rn", "firebase"] = 3
  HW[4] = "        configured for Azure Functions: this kit\047s guide does not cover this\n        host"
  HNI["rn", "azure"] = 4
  HW[5] = "        configured for Google Cloud Functions: this kit\047s guide does not cover\n        this host"
  HNI["rn", "gcf"] = 5
  HW[6] = "        configured for AWS Lambda (SAM / Serverless / SST): this kit\047s guide\n        does not cover this host"
  HNI["rn", "aws"] = 6
  HW[7] = "        configured for Cloudflare Workers: this kit\047s guide does not cover\n        this host"
  HNI["rn", "cloudflare"] = 7
  HW[8] = "        configured for Supabase: this kit\047s guide does not cover this host"
  HNI["rn", "supabase"] = 8
  HW[9] = "        configured for Vercel: the browser kit is a tag on the page, so the\n        host does not change it"
  HNI["web", "vercel"] = 9
  HW[10] = "        configured for Netlify: the browser kit is a tag on the page, so the\n        host does not change it"
  HNI["web", "netlify"] = 10
  HW[11] = "        configured for Firebase Functions: the browser kit is a tag on the\n        page, so the host does not change it"
  HNI["web", "firebase"] = 11
  HW[12] = "        configured for Azure Functions: the browser kit is a tag on the page,\n        so the host does not change it"
  HNI["web", "azure"] = 12
  HW[13] = "        configured for Google Cloud Functions: the browser kit is a tag on the\n        page, so the host does not change it"
  HNI["web", "gcf"] = 13
  HW[14] = "        configured for AWS Lambda (SAM / Serverless / SST): the browser kit is\n        a tag on the page, so the host does not change it"
  HNI["web", "aws"] = 14
  HW[15] = "        configured for Cloudflare Workers: the browser kit is a tag on the\n        page, so the host does not change it"
  HNI["web", "cloudflare"] = 15
  HW[16] = "        configured for Supabase: the browser kit is a tag on the page, so the\n        host does not change it"
  HNI["web", "supabase"] = 16
  HW[17] = "        configured for Vercel: the Node kit\047s guide: Express and a plain Node\n        server are proven against this host\047s contract, not on a deployment;\n        Next.js, Fastify, Hono and NestJS have no path there"
  HNI["node", "vercel"] = 17
  HW[18] = "        configured for Netlify: the Node kit\047s guide: the kit refuses to start\n        on this host"
  HNI["node", "netlify"] = 18
  HW[19] = "        configured for Firebase Functions: Firebase Functions run on Google\n        Cloud Functions, where the Node kit\047s guide says the kit refuses to\n        start"
  HNI["node", "firebase"] = 19
  HW[20] = "        configured for Azure Functions: the Node kit\047s guide: the kit refuses\n        to start on this host"
  HNI["node", "azure"] = 20
  HW[21] = "        configured for Google Cloud Functions: the Node kit\047s guide: the kit\n        refuses to start on this host"
  HNI["node", "gcf"] = 21
  HW[22] = "        configured for AWS Lambda (SAM / Serverless / SST): the Node kit\047s\n        guide: Express and a plain Node server are proven against this host\047s\n        contract, not on a deployment; Next.js, Fastify, Hono and NestJS have\n        no path there"
  HNI["node", "aws"] = 22
  HW[23] = "        configured for Cloudflare Workers: a Worker is not a Node server, and\n        the Node kit\047s guide gives no path there; the edge kit is the one for\n        Workers"
  HNI["node", "cloudflare"] = 23
  HW[24] = "        configured for Supabase: Supabase functions run on Deno, not Node; the\n        edge kit is the one for them"
  HNI["node", "supabase"] = 24
  HNI["bun", "vercel"] = 1
  HNI["bun", "netlify"] = 2
  HNI["bun", "firebase"] = 3
  HNI["bun", "azure"] = 4
  HNI["bun", "gcf"] = 5
  HNI["bun", "aws"] = 6
  HNI["bun", "cloudflare"] = 7
  HNI["bun", "supabase"] = 8
  HNI["python", "vercel"] = 1
  HNI["python", "netlify"] = 2
  HNI["python", "firebase"] = 3
  HNI["python", "azure"] = 4
  HNI["python", "gcf"] = 5
  HNI["python", "aws"] = 6
  HNI["python", "cloudflare"] = 7
  HNI["python", "supabase"] = 8
  HNI["java", "vercel"] = 1
  HNI["java", "netlify"] = 2
  HNI["java", "firebase"] = 3
  HNI["java", "azure"] = 4
  HNI["java", "gcf"] = 5
  HNI["java", "aws"] = 6
  HNI["java", "cloudflare"] = 7
  HNI["java", "supabase"] = 8
  HNI["go", "vercel"] = 1
  HNI["go", "netlify"] = 2
  HNI["go", "firebase"] = 3
  HNI["go", "azure"] = 4
  HNI["go", "gcf"] = 5
  HNI["go", "aws"] = 6
  HNI["go", "cloudflare"] = 7
  HNI["go", "supabase"] = 8
  HNI["php", "vercel"] = 1
  HNI["php", "netlify"] = 2
  HNI["php", "firebase"] = 3
  HNI["php", "azure"] = 4
  HNI["php", "gcf"] = 5
  HNI["php", "aws"] = 6
  HNI["php", "cloudflare"] = 7
  HNI["php", "supabase"] = 8
  HNI["dotnet", "vercel"] = 1
  HNI["dotnet", "netlify"] = 2
  HNI["dotnet", "firebase"] = 3
  HNI["dotnet", "azure"] = 4
  HNI["dotnet", "gcf"] = 5
  HNI["dotnet", "aws"] = 6
  HNI["dotnet", "cloudflare"] = 7
  HNI["dotnet", "supabase"] = 8
  HNI["ruby", "vercel"] = 1
  HNI["ruby", "netlify"] = 2
  HNI["ruby", "firebase"] = 3
  HNI["ruby", "azure"] = 4
  HNI["ruby", "gcf"] = 5
  HNI["ruby", "aws"] = 6
  HNI["ruby", "cloudflare"] = 7
  HNI["ruby", "supabase"] = 8
  HNI["flutter", "vercel"] = 1
  HNI["flutter", "netlify"] = 2
  HNI["flutter", "firebase"] = 3
  HNI["flutter", "azure"] = 4
  HNI["flutter", "gcf"] = 5
  HNI["flutter", "aws"] = 6
  HNI["flutter", "cloudflare"] = 7
  HNI["flutter", "supabase"] = 8
  HNI["swift", "vercel"] = 1
  HNI["swift", "netlify"] = 2
  HNI["swift", "firebase"] = 3
  HNI["swift", "azure"] = 4
  HNI["swift", "gcf"] = 5
  HNI["swift", "aws"] = 6
  HNI["swift", "cloudflare"] = 7
  HNI["swift", "supabase"] = 8
  HNI["kotlin", "vercel"] = 1
  HNI["kotlin", "netlify"] = 2
  HNI["kotlin", "firebase"] = 3
  HNI["kotlin", "azure"] = 4
  HNI["kotlin", "gcf"] = 5
  HNI["kotlin", "aws"] = 6
  HNI["kotlin", "cloudflare"] = 7
  HNI["kotlin", "supabase"] = 8
  HNI["rust", "vercel"] = 1
  HNI["rust", "netlify"] = 2
  HNI["rust", "firebase"] = 3
  HNI["rust", "azure"] = 4
  HNI["rust", "gcf"] = 5
  HNI["rust", "aws"] = 6
  HNI["rust", "cloudflare"] = 7
  HNI["rust", "supabase"] = 8
  HNI["elixir", "vercel"] = 1
  HNI["elixir", "netlify"] = 2
  HNI["elixir", "firebase"] = 3
  HNI["elixir", "azure"] = 4
  HNI["elixir", "gcf"] = 5
  HNI["elixir", "aws"] = 6
  HNI["elixir", "cloudflare"] = 7
  HNI["elixir", "supabase"] = 8
  HNI["edge", "vercel"] = 1
  HW[25] = "        configured for Netlify: the edge kit\047s guide supports Deno-based\n        hosted functions and does not name Netlify Edge Functions"
  HNI["edge", "netlify"] = 25
  HNI["edge", "firebase"] = 3
  HNI["edge", "azure"] = 4
  HNI["edge", "gcf"] = 5
  HNI["edge", "aws"] = 6
  HW[26] = "        configured for Cloudflare Workers: the edge kit\047s guide supports\n        Cloudflare Workers"
  HNI["edge", "cloudflare"] = 26
  HW[27] = "        configured for Supabase: the edge kit\047s guide supports Supabase Edge\n        Functions"
  HNI["edge", "supabase"] = 27
  NLABEL["capacitor"] = "  • Capacitor / Ionic app shell"
  NLABEL["tauri"] = "  • Tauri desktop app"
  NLABEL["electron"] = "  • Electron desktop app"
  NLABEL["wails"] = "  • Wails desktop app"
  NLABEL["nativescript"] = "  • NativeScript app"
  NLABEL["maui"] = "  • .NET MAUI app"
  NLABEL["blazor-wasm"] = "  • Blazor WebAssembly app"
  NLABEL["wpf-winforms"] = "  • WPF / Windows Forms desktop app"
  NLABEL["unity"] = "  • Unity game"
  NLABEL["godot"] = "  • Godot game"
  NLABEL["compose-desktop"] = "  • Compose Desktop app"
  NLABEL["javafx"] = "  • JavaFX desktop app"
  NLABEL["browser-extension"] = "  • browser extension (extension stores forbid loading remote code, so the\n    hosted script is never offered)"
  NLABEL["notebook"] = "  • Jupyter notebooks"
  NLABEL["nerves"] = "  • Nerves firmware"
  NLABEL["rust-wasm"] = "  • Rust WebAssembly front end"
  NLABEL["server-swift"] = "  • server-side or command-line Swift"
  NLABEL["dart"] = "  • Dart without Flutter"
  NLABEL["scala"] = "  • Scala"
  NLABEL["clojure"] = "  • Clojure"
  NLABEL["erlang"] = "  • Erlang"
  NLABEL["gleam"] = "  • Gleam"
  NLABEL["r"] = "  • R"
  NLABEL["cpp"] = "  • C / C++"
  NLABEL["haskell"] = "  • Haskell"
  NLABEL["ocaml"] = "  • OCaml"
  NLABEL["zig"] = "  • Zig"
  NLABEL["nim"] = "  • Nim"
  NLABEL["crystal"] = "  • Crystal"
  NLABEL["julia"] = "  • Julia"
  NLABEL["perl"] = "  • Perl"
  NLABEL["lua"] = "  • Lua"
  BLABEL["bazel"] = "  • Bazel build: its targets are not read, so what it builds is not known"
  BLABEL["dockerfile"] = "  • Dockerfile with no manifest beside it: what the image runs is not read"
  SR1["workspace-root"] = "workspace root"
  SRN["workspace-root"] = "workspace roots"
  SR1["library"] = "library"
  SRN["library"] = "libraries"
  SR1["tooling"] = "tooling or config package"
  SRN["tooling"] = "tooling or config packages"
  SR1["test"] = "test package"
  SRN["test"] = "test packages"
  SR1["extension"] = "editor extension"
  SRN["extension"] = "editor extensions"
  SR1["ci-action"] = "CI action"
  SRN["ci-action"] = "CI actions"
  SR1["infra"] = "infrastructure-as-code folder"
  SRN["infra"] = "infrastructure-as-code folders"
  SR1["contract"] = "smart-contract tooling folder"
  SRN["contract"] = "smart-contract tooling folders"
  SR1["native-tooling"] = "CocoaPods / fastlane file"
  SRN["native-tooling"] = "CocoaPods / fastlane files"
  SR1["example"] = "example folder"
  SRN["example"] = "example folders"
  F = esc(ENVIRON["BOOSTHIS_F"])
  FD = boo_fd(F)
  if (!REC) {
    print T_TITLE
    print subf(T_SCANNED, "%F", FD)
    print T_SCANNED2
    print ""
    print T_COVER
    print ""
    fflush()
  }
}
REC { if ($0 == "Z2") z2 = 1; else print; next }
$0 == "Z2" { z2 = 1; next }
$1 == "C01" { CUN = $2 + 0; next }
$1 == "C02" { CNL = $2 + 0; next }
{ ty = substr($1, 1, 1) }
ty == "K" {
  kit = $3
  if (!(kit in KN)) { NKS++; KSEEN[NKS] = kit; KN[kit] = 0 }
  KN[kit]++
  KFH[kit, KN[kit]] = $2; KFF[kit, KN[kit]] = $4; KFL[kit, KN[kit]] = $5
  ANY = 1
  next
}
ty == "H" { HN[$3, $2] = $4; next }
ty == "N" {
  st = $3
  if (!(st in NN)) { NNS++; NSEEN[NNS] = st; NN[st] = 0 }
  NN[st]++
  NFH[st, NN[st]] = $2
  ANY = 1
  next
}
ty == "S" { if (!($3 in SN)) { NSS++; SORD[NSS] = $3; SN[$3] = 0 } SN[$3]++; ANY = 1; next }
ty == "U" { UN++; UH[UN] = $2; US[UN] = $3; ANY = 1; next }
ty == "B" {
  bk = $3
  if (!(bk in BN)) { NBS++; BSEEN[NBS] = bk; BN[bk] = 0 }
  BN[bk]++
  BFH[bk, BN[bk]] = $2
  ANY = 1
  next
}
ty == "R" { RES = $2; next }
END {
  if (REC) exit (z2 ? 0 : 4)
  if (!z2) { print ""; print T_INCOMPLETE; exit 4 }
  boo_report()
}
# A folder INSIDE an Arabic sentence is isolated so it reads left to right; a
# folder on a line of its own is printed exactly as it is on disk.
function boo_fd(h) { return AR ? LRI h PDI : h }
function boo_count(s, x,    n, p) {
  n = 0
  while ((p = index(s, x)) > 0) { n++; s = substr(s, p + length(x)) }
  return n
}
# Columns a line takes: UTF-8 continuation bytes and isolates take none.
function boo_w(s,    n, i, o, l) {
  n = 0
  l = length(s)
  for (i = 1; i <= l; i++) { o = ORD[substr(s, i, 1)]; if (o < 128 || o >= 192) n++ }
  return n - boo_count(s, LRI) - boo_count(s, PDI)
}
function boo_wrap(s, first, indent,    nw, wd, i, tok, d, cur, has, out, pre) {
  nw = split(s, wd, " ")
  out = ""
  cur = first
  has = 0
  tok = ""
  d = 0
  for (i = 1; i <= nw; i++) {
    tok = (tok == "" ? wd[i] : tok " " wd[i])
    d += boo_count(wd[i], LRI) - boo_count(wd[i], PDI)
    if (d > 0 && i < nw) continue
    pre = has ? cur " " : cur
    if (has && boo_w(pre tok) > 78) { out = out cur "\n"; cur = indent tok }
    else cur = pre tok
    has = 1
    tok = ""
    d = 0
  }
  return out cur
}
function boo_top(h,    p) {
  if (h == ".") return h
  p = index(substr(h, 3), "/")
  return p ? substr(h, 1, p + 1) : h
}
function boo_reason(r, n) { return n " " (n == 1 ? SR1[r] : SRN[r]) }
function boo_more(A, key, n,    i, t, nt, s, TC, TO) {
  nt = 0
  for (i = CAP + 1; i <= n; i++) {
    t = boo_top(A[key, i])
    if (!(t in TC)) { nt++; TO[nt] = t; TC[t] = 0 }
    TC[t]++
  }
  s = ""
  for (i = 1; i <= nt; i++) s = s (i > 1 ? T_SEP : "") subf(subf(T_IN, "%N", TC[TO[i]]), "%F", boo_fd(TO[i]))
  print "      " subf(T_MORE, "%N", n - CAP) s
}
function boo_list(A, key, n,    i, shown) {
  shown = (n > CAP) ? CAP : n
  for (i = 1; i <= shown; i++) print "      " A[key, i]
  if (n > CAP) boo_more(A, key, n)
}
function boo_kitlist(kit,    n, i, shown, h, f) {
  n = KN[kit]
  shown = (n > CAP) ? CAP : n
  for (i = 1; i <= shown; i++) {
    h = KFH[kit, i]
    print "      " h
    f = KFF[kit, i]
    if (f != "-") print FNOTE[f]
    if (KFL[kit, i] == "maybe-library") print T_MAYBE
    if ((kit, h) in HN) print HW[HNI[kit, HN[kit, h]]]
  }
  if (n > CAP) boo_more(KFH, kit, n)
}
function boo_install(kit,    i, mod, lay) {
  if (kit == "web") {
    mod = 0
    lay = 0
    for (i = 1; i <= KN[kit]; i++) { if (KFF[kit, i] == "module") mod = 1; else lay = 1 }
    if (mod) { print T_INST_HEAD; print INST[kit]; INSTALLED = 1 }
    if (lay) print T_SNIPPET
    return
  }
  print T_INST_HEAD
  print INST[kit]
  INSTALLED = 1
}
function boo_reportblock(    list, q, k, n) {
  print T_REPORT_HEAD
  print ""
  print T_REPORT_WHY
  print ""
  print T_REPORT_HOW
  print ""
  list = ""
  n = split((RES == "none" ? "" : RES), k, ",")
  for (q = 1; q <= n; q++) list = list (q > 1 ? ", " : "") "\"" k[q] "\""
  print T_CURL1
  print T_CURL2
  print T_CURL3
  print T_CURL4 list T_CURL5
  print ""
  if (n == 0) { print T_REPORT_EMPTY; print "" }
  print T_REPORT_TAIL
}
function boo_report(    q, kit, i, st, b, s) {
  if (NKS > 0) {
    print T_KITS_HEAD
    for (q = 1; q <= NKS; q++) {
      kit = KSEEN[q]
      print ""
      print KLINE[kit]
      boo_kitlist(kit)
      if (KEYED) boo_install(kit)
    }
    if (KEYED && INSTALLED) { print ""; print T_SIGNOTE }
    print ""
  }
  if (NNS > 0) {
    print T_NOKIT_HEAD
    for (q = 1; q <= NNS; q++) { st = NSEEN[q]; print NLABEL[st]; boo_list(NFH, st, NN[st]) }
    print ""
  }
  if (UN > 0) {
    print T_UNDEC_HEAD
    for (i = 1; i <= UN; i++) print "      " UH[i] "/" US[i]
    print ""
  }
  if (NSS > 0) {
    s = ""
    for (q = 1; q <= NSS; q++) s = s (q > 1 ? T_SEP : "") boo_reason(SORD[q], SN[SORD[q]])
    print boo_wrap(subf(T_ASIDE, "%L", s), "", "  ")
    print ""
  }
  if (NBS > 0) {
    print T_BLIND_HEAD
    for (q = 1; q <= NBS; q++) { b = BSEEN[q]; print BLABEL[b]; boo_list(BFH, b, BN[b]) }
    print ""
  }
  if (CUN > 0) { print boo_wrap((CUN == 1 ? T_UNREAD1 : subf(T_UNREADN, "%N", CUN)), "", ""); print "" }
  if (CNL > 0) { print boo_wrap((CNL == 1 ? T_NL1 : subf(T_NLN, "%N", CNL)), "", ""); print "" }
  # Anything left unread makes the walk partial (a folder, a name with a line
  # break, an undecided manifest): what was found is still listed, but no
  # report is offered and no result line is printed, and the exit status
  # says so, because the part skipped may hold a kit.
  INC = (CUN > 0 || CNL > 0 || UN > 0)
  if (!ANY) { print subf(boo_wrap(T_NOTHING, "", ""), "%F", FD); print T_PICK }
  else if (NKS == 0) { print T_NOKIT_END; print T_PICK }
  else print T_KITS_END
  print ""
  print T_REACH
  if (KEYED && !INC) { print ""; boo_reportblock() }
  print ""
  if (INC) { print T_PARTIAL; exit 4 }
  print RESULT_HEAD RES
}
'
}

boosthis_prog_say() {
printf '%s\n' '# Says why a folder was not scanned, on the error output.
BEGIN {
  boo_init()
  F = esc(ENVIRON["BOOSTHIS_F"])
  Q = boo_shq(F)
  
  a = 0
  if (boosthis_id == "extra") m = "Boosthis scan: give it one folder at most (a name with spaces goes in quotes).\nNothing was scanned."
  else if (boosthis_id == "empty") m = "Boosthis scan: the folder name is empty. Nothing was scanned."
  else if (boosthis_id == "missing") m = "Boosthis scan: %F does not exist. Nothing was scanned."
  else if (boosthis_id == "notdir") m = "Boosthis scan: %F is a file, not a folder. Nothing was scanned."
  else if (boosthis_id == "noenter") m = "Boosthis scan: %F cannot be opened (permission denied). Nothing was scanned."
  else if (boosthis_id == "noread") m = "Boosthis scan: %F cannot be read (permission denied). Nothing was scanned."
  else { m = "Boosthis scan: nothing was scanned. This is a home folder or the root of the\nfilesystem, so the scan would walk every project on the machine:" "\n  %F\n" "Scan one project\047s folder instead, or, to scan this one anyway:"; a = 1 }
  print subf(m, "%F", F)
  if (a) print subf("  BOOSTHIS_SCAN_ANY_FOLDER=1 sh boosthis-scan.sh %Q", "%Q", Q)
  print "Usage: sh boosthis-scan.sh [folder]   (no folder = the current one)"
}
# The folder as one shell word, for the command printed above.
function boo_shq(s,    out, p) {
  if (s ~ "^[-A-Za-z0-9._/]+$") return s
  out = ""
  while ((p = index(s, "\047")) > 0) { out = out substr(s, 1, p - 1) "\047\\\047\047"; s = substr(s, p + 1) }
  return "\047" out s "\047"
}
'
}

# The one walk. Each found path reaches printf as an argument, never as
# shell text. Folders skipped: every hidden folder (a name starting with a dot)
# and the dependency, build-output, virtualenv, cache, report and test-data
# folders named on the first test. A name with a line break is counted and not
# read; a manifest over 2 MB is listed as undecided, not read. Either one
# makes the scan partial (exit 4).
boosthis_walk() {
  boosthis_nl='
'
  find . \
    \( -type d \( -name '.?*' -o -name node_modules -o -name bower_components \
         -o -name jspm_packages -o -name web_modules -o -name vendor \
         -o -name Pods -o -name Carthage -o -name DerivedData -o -name deps \
         -o -name _build -o -name build -o -name dist -o -name out \
         -o -name target -o -name obj -o -name coverage -o -name htmlcov \
         -o -name test-results -o -name playwright-report \
         -o -name allure-results -o -name allure-report -o -name __pycache__ \
         -o -name __pypackages__ -o -name site-packages -o -name venv \
         -o -name env -o -name virtualenv -o -name testdata -o -name fixtures \
         -o -name __fixtures__ -o -name test-fixtures -o -name __snapshots__ \
         -o -name __mocks__ -o -name cdk.out -o -name storybook-static \
         -o -name elm-stuff -o -name tmp -o -name temp -o -name 'bazel-*' \
         -o -name 'cmake-build-*' \) -prune \) -o \
    \( -name "*$boosthis_nl*" -prune -exec sh -c 'echo W >&2' \; \) -o \
    \( -type d \( -name '*.[xX][cC][oO][dD][eE][pP][rR][oO][jJ]' \
         -o -name '*.[xX][cC][wW][oO][rR][kK][sS][pP][aA][cC][eE]' \) -prune -exec printf 'F%s\n' {} + \) -o \
    \( -type f -size +4000 \( -name package.json -o -name project.json -o -name build.gradle \
         -o -name build.gradle.kts -o -name pom.xml -o -name requirements.txt \
         -o -name '[rR][eE][qQ][uU][iI][rR][eE][mM][eE][nN][tT][sS]-*.[tT][xX][tT]' \
         -o -path '*/requirements/*.[tT][xX][tT]' -o -name pyproject.toml \
         -o -name Pipfile -o -name go.mod -o -name composer.json \
         -o -name '*.[cC][sS][pP][rR][oO][jJ]' \
         -o -name '*.[fF][sS][pP][rR][oO][jJ]' \
         -o -name '*.[vV][bB][pP][rR][oO][jJ]' -o -name Gemfile \
         -o -name Cargo.toml -o -name mix.exs -o -name pubspec.yaml \
         -o -name project.yml -o -name Project.swift -o -name Package.swift \
         -o -name host.json -o -name template.yaml -o -name template.yml \
         -o -name manifest.json \) -exec printf 'L%s\n' {} + \) -o \
    \( -type f \( -name package.json -o -name pnpm-workspace.yaml -o -name lerna.json \
         -o -name turbo.json -o -name nx.json -o -name rush.json \
         -o -name project.json -o -name bun.lock -o -name bun.lockb \
         -o -name bunfig.toml -o -name wrangler.toml -o -name wrangler.json \
         -o -name wrangler.jsonc -o -name deno.json -o -name deno.jsonc \
         -o -path '*/supabase/functions/*/index.ts' \
         -o -path '*/supabase/functions/*/index.js' -o -name build.gradle \
         -o -name build.gradle.kts -o -name settings.gradle \
         -o -name settings.gradle.kts -o -path '*/src/main/AndroidManifest.xml' \
         -o -name pom.xml -o -name requirements.txt \
         -o -name '[rR][eE][qQ][uU][iI][rR][eE][mM][eE][nN][tT][sS]-*.[tT][xX][tT]' \
         -o -path '*/requirements/*.[tT][xX][tT]' -o -name pyproject.toml \
         -o -name Pipfile -o -name setup.py -o -name setup.cfg \
         -o -name manage.py -o -name '*.[iI][pP][yY][nN][bB]' -o -name go.mod \
         -o -name go.work -o -name composer.json -o -name index.php \
         -o -name wp-config.php -o -name artisan \
         -o -name '*.[cC][sS][pP][rR][oO][jJ]' \
         -o -name '*.[fF][sS][pP][rR][oO][jJ]' \
         -o -name '*.[vV][bB][pP][rR][oO][jJ]' -o -name '*.[sS][lL][nN]' \
         -o -name '*.[sS][lL][nN][xX]' -o -name Gemfile -o -name config.ru \
         -o -name '*.[gG][eE][mM][sS][pP][eE][cC]' -o -name Podfile \
         -o -path '*/fastlane/Fastfile' -o -name Cargo.toml \
         -o -path '*/src/main.rs' -o -path '*/src/bin/*.[rR][sS]' \
         -o -name Trunk.toml -o -name mix.exs -o -name pubspec.yaml \
         -o -name project.yml -o -name Project.swift -o -name Package.swift \
         -o -name vercel.json -o -name netlify.toml -o -name firebase.json \
         -o -name host.json -o -name serverless.yml -o -name serverless.yaml \
         -o -name serverless.ts -o -name samconfig.toml -o -name template.yaml \
         -o -name template.yml -o -name cdk.json -o -name cdktf.json \
         -o -name Pulumi.yaml -o -name Pulumi.yml -o -name sst.config.ts \
         -o -name action.yml -o -name action.yaml \
         -o -name '[hH][aA][rR][dD][hH][aA][tT].[cC][oO][nN][fF][iI][gG].*' \
         -o -name foundry.toml -o -name truffle-config.js -o -name mkdocs.yml \
         -o -name mkdocs.yaml -o -name _config.yml -o -name hugo.toml \
         -o -name hugo.yaml -o -name hugo.json -o -name .eleventy.js \
         -o -name '[eE][lL][eE][vV][eE][nN][tT][yY].[cC][oO][nN][fF][iI][gG].*' \
         -o -name pelicanconf.py -o -name book.toml \
         -o -name '*.[hH][tT][mM][lL]' -o -name '*.[hH][tT][mM]' \
         -o -name '*.[eE][rR][bB]' -o -name '*.[hH][aA][mM][lL]' \
         -o -name '*.[sS][lL][iI][mM]' \
         -o -name '*.[bB][lL][aA][dD][eE].[pP][hH][pP]' \
         -o -name '*.[tT][wW][iI][gG]' -o -name '*.[hH][eE][eE][xX]' \
         -o -name '*.[eE][eE][xX]' -o -name '*.[cC][sS][hH][tT][mM][lL]' \
         -o -name '*.[rR][aA][zZ][oO][rR]' -o -name '*.[jJ][iI][nN][jJ][aA]' \
         -o -name '*.[jJ][iI][nN][jJ][aA]2' -o -name '*.[jJ]2' \
         -o -name '*.[hH][bB][sS]' \
         -o -name '*.[hH][aA][nN][dD][lL][eE][bB][aA][rR][sS]' \
         -o -name '*.[eE][jJ][sS]' -o -name '*.[pP][uU][gG]' \
         -o -name '*.[nN][jJ][kK]' -o -name '*.[lL][iI][qQ][uU][iI][dD]' \
         -o -name '*.[mM][uU][sS][tT][aA][cC][hH][eE]' \
         -o -name '*.[gG][oO][hH][tT][mM][lL]' -o -name '*.[tT][mM][pP][lL]' \
         -o -name '*.[jJ][sS][pP]' -o -name '*.[fF][tT][lL]' \
         -o -name '[cC][aA][pP][aA][cC][iI][tT][oO][rR].[cC][oO][nN][fF][iI][gG].*' \
         -o -name ionic.config.json \
         -o -path '*/src-tauri/[tT][aA][uU][rR][iI].[cC][oO][nN][fF].*' \
         -o -path '*/src-tauri/Tauri.toml' -o -name wails.json \
         -o -name '[nN][aA][tT][iI][vV][eE][sS][cC][rR][iI][pP][tT].[cC][oO][nN][fF][iI][gG].*' \
         -o -path '*/ProjectSettings/ProjectVersion.txt' -o -name project.godot \
         -o -name manifest.json -o -name build.sbt -o -name build.sc \
         -o -name project.clj -o -name deps.edn -o -name rebar.config \
         -o -name gleam.toml -o -name renv.lock \
         -o -name '*.[rR][pP][rR][oO][jJ]' -o -name CMakeLists.txt \
         -o -name meson.build -o -name conanfile.txt -o -name vcpkg.json \
         -o -name stack.yaml -o -name cabal.project \
         -o -name '*.[cC][aA][bB][aA][lL]' -o -name dune-project \
         -o -name build.zig -o -name '*.[nN][iI][mM][bB][lL][eE]' \
         -o -name shard.yml -o -name Project.toml -o -name cpanfile \
         -o -name Makefile.PL -o -name '*.[rR][oO][cC][kK][sS][pP][eE][cC]' \
         -o -name WORKSPACE -o -name WORKSPACE.bazel -o -name MODULE.bazel \
         -o -name BUILD.bazel -o -name Dockerfile -o -name Containerfile \) -exec printf 'F%s\n' {} + \)
}

boosthis_say() {
  BOOSTHIS_F=$2
  export BOOSTHIS_F
  awk -v boosthis_id="$1" "$(boosthis_prog_lib; boosthis_prog_say)" >&2
}

boosthis_is_home() {
  boosthis_h=
  case ${HOME:-} in
    /*)
      boosthis_h=$(CDPATH= cd -P "$HOME" 2>/dev/null && pwd -P && echo x)
      boosthis_h=${boosthis_h%?x}
      ;;
  esac
  if [ -n "$boosthis_h" ] && [ "$1" = "$boosthis_h" ]; then return 0; fi
  case $1 in
    /home/*/*|/Users/*/*|/mnt/?/Users/*/*|/?/Users/*/*) return 1 ;;
    /|/?|/home|/home/*|/Users|/Users/*|/root|/var/root|/mnt|/mnt/?) return 0 ;;
    /mnt/?/Users|/mnt/?/Users/*|/?/Users|/?/Users/*) return 0 ;;
  esac
  return 1
}

boosthis_main() {
  eval "boosthis_last=\${$#}"
  if [ "$boosthis_last" != boosthis-scan-end ]; then exit 4; fi
  trap - EXIT
  LC_ALL=C
  export LC_ALL
  exec </dev/null
  for boosthis_tool in awk find sort; do
    if ! command -v "$boosthis_tool" >/dev/null 2>&1; then
      printf 'Boosthis scan: this needs the standard tool %s, which was not found, so nothing was scanned.\n' "$boosthis_tool" >&2
      exit 4
    fi
  done
  if [ $# -gt 2 ]; then boosthis_say extra .; exit 2; fi
  if [ $# -eq 2 ]; then boosthis_path=$1; else boosthis_path=.; fi
  if [ -z "$boosthis_path" ]; then boosthis_say empty .; exit 2; fi
  case $boosthis_path in
    /*|./*|../*|.|..) boosthis_p=$boosthis_path ;;
    *) boosthis_p=./$boosthis_path ;;
  esac
  if [ ! -e "$boosthis_p" ]; then boosthis_say missing "$boosthis_path"; exit 2; fi
  if [ ! -d "$boosthis_p" ]; then boosthis_say notdir "$boosthis_path"; exit 2; fi
  if ! CDPATH= cd -P "$boosthis_p" 2>/dev/null; then boosthis_say noenter "$boosthis_path"; exit 2; fi
  if [ ! -r . ]; then boosthis_say noread "$boosthis_path"; exit 2; fi
  boosthis_here=$(pwd -P && echo x)
  boosthis_here=${boosthis_here%?x}
  if [ -z "$boosthis_here" ]; then boosthis_here=$boosthis_p; fi
  if [ "${BOOSTHIS_SCAN_ANY_FOLDER:-}" != 1 ] && boosthis_is_home "$boosthis_here"; then
    boosthis_say home "$boosthis_here"
    exit 3
  fi
  BOOSTHIS_F=$boosthis_here
  export BOOSTHIS_F
  { boosthis_walk 2>&1 >&3 3>&- | awk "$(boosthis_prog_count)" >&3 3>&-; } 3>&1 |
    awk "$(boosthis_prog_lib; boosthis_prog_extract)" |
    sort |
    awk "$(boosthis_prog_lib; boosthis_prog_decide)" |
    sort -u |
    awk "$(boosthis_prog_lib; boosthis_prog_print)"
}

boosthis_main "$@" boosthis-scan-end
