Skip to content

Replace SOMA with the LexCAT lexical runtime (v0.0.14) #6

Replace SOMA with the LexCAT lexical runtime (v0.0.14)

Replace SOMA with the LexCAT lexical runtime (v0.0.14) #6

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Node ${{ matrix.node }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node: [22, 24]
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node }}
cache: npm
cache-dependency-path: package-lock.json
- name: Install root dependencies
run: npm ci
- name: Run offline checks
run: npm run check:offline
lexcat-runtimes:
name: LexCAT ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- name: Linux x64
os: ubuntu-latest
platform: linux
arch: x64
archive: lexcat-v0.0.14-linux-x86_64.tar.gz
executable: lexcat
- name: Linux arm64
os: ubuntu-24.04-arm
platform: linux
arch: arm64
archive: lexcat-v0.0.14-linux-arm64.tar.gz
executable: lexcat
- name: macOS arm64
os: macos-15
platform: darwin
arch: arm64
archive: lexcat-v0.0.14-macos-arm64.tar.gz
executable: lexcat
- name: Windows x64
os: windows-latest
platform: win32
arch: x64
archive: lexcat-v0.0.14-windows-x86_64.zip
executable: lexcat.exe
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24
- name: Exercise shipped LexCAT binary
shell: bash
run: |
set -euo pipefail
runtime_dir="$RUNNER_TEMP/lexcat-runtime"
mkdir -p "$runtime_dir/corpus"
archive="vendor/lexcat/${{ matrix.archive }}"
if [[ "$archive" == *.zip ]]; then
7z x "$archive" -o"$runtime_dir"
else
tar -xzf "$archive" -C "$runtime_dir"
fi
chmod +x "$runtime_dir/${{ matrix.executable }}"
# 0.0.14 stamps the real release version into the binary (upstream #234),
# so --version pins both the release number and the index schema, on top
# of the manifest checksum verified above.
node -e '
const { createHash } = require("node:crypto");
const { readFileSync } = require("node:fs");
const manifest = JSON.parse(readFileSync("vendor/lexcat/manifest.json", "utf8"));
const artifact = manifest.artifacts.find((entry) => entry.platform === process.argv[2] && entry.arch === process.argv[3]);
if (!artifact) throw new Error("no vendored artifact for " + process.argv[2] + "/" + process.argv[3]);
const digest = createHash("sha256").update(readFileSync(process.argv[1])).digest("hex");
if (digest !== artifact.executable_sha256) throw new Error("executable checksum mismatch: " + digest);
' "$runtime_dir/${{ matrix.executable }}" "${{ matrix.platform }}" "${{ matrix.arch }}"
schema="$(node -p 'JSON.parse(require("node:fs").readFileSync("vendor/lexcat/manifest.json","utf8")).index_schema_version')"
version="$(node -p 'JSON.parse(require("node:fs").readFileSync("vendor/lexcat/manifest.json","utf8")).version')"
"$runtime_dir/${{ matrix.executable }}" --version | grep -q "index schema $schema"
"$runtime_dir/${{ matrix.executable }}" --version | grep -q "lexcat $version"
cp -R wiki-mirror/. "$runtime_dir/corpus/"
cd "$runtime_dir"
# Mirrors how WikiKB indexes: no config file, counts read out of the
# machine-readable report. An empty corpus and a collapsed vocabulary
# both build and query at exit 0, so both counts are asserted here.
"./${{ matrix.executable }}" --index ci-smoke.db build corpus --json > build.json
cat build.json
node -e '
const { readFileSync } = require("node:fs");
const report = JSON.parse(readFileSync("build.json", "utf8"));
if (!(report.chunks > 0)) throw new Error("build indexed no chunks: " + JSON.stringify(report));
if (!(report.terms > 0)) throw new Error("build indexed no terms: " + JSON.stringify(report));
'
test -f ci-smoke.db
- name: Exercise LexCAT retrieval
shell: bash
run: |
set -euo pipefail
runtime_dir="$RUNNER_TEMP/lexcat-runtime"
cd "$runtime_dir"
"./${{ matrix.executable }}" --index ci-smoke.db query "agentic workflows" --n 10 --json > hits.json
# --json carries each hit's chunk text, which is how WikiKB reads
# results, so the assertion never touches the on-disk schema.
node -e '
const { readFileSync } = require("node:fs");
const { hits } = JSON.parse(readFileSync("hits.json", "utf8"));
if (!Array.isArray(hits) || hits.length === 0) throw new Error("LexCAT returned no hits");
const matched = hits.some((hit) => String(hit.text ?? "").toLowerCase().includes("agentic workflow"));
if (!matched) throw new Error("no retrieved chunk contained the query terms");
'
- name: Exercise incremental reindex
shell: bash
run: |
set -euo pipefail
runtime_dir="$RUNNER_TEMP/lexcat-runtime"
cd "$runtime_dir"
printf -- '---\ntitle: "CI Delta"\nwikikb_path: "concepts/ci-delta.md"\n---\n\n# CI Delta\n\nA sentinel page mentioning vermiculite telemetry.\n' > corpus/ci-delta.md
"./${{ matrix.executable }}" --index ci-smoke.db sync corpus --json > sync.json
cat sync.json
node -e '
const { readFileSync } = require("node:fs");
const report = JSON.parse(readFileSync("sync.json", "utf8"));
if (!(report.chunks > 0) || !(report.terms > 0)) throw new Error("sync left an unsearchable index: " + JSON.stringify(report));
if (!(report.added >= 1)) throw new Error("sync did not report the added page: " + JSON.stringify(report));
'
"./${{ matrix.executable }}" --index ci-smoke.db query "vermiculite telemetry" --n 5 --json > delta.json
# Frontmatter staged with a document must come back on the hit payload,
# because that is where WikiKB reads a result's wiki path and title.
node -e '
const { readFileSync } = require("node:fs");
const { hits } = JSON.parse(readFileSync("delta.json", "utf8"));
const hit = hits.find((entry) => String(entry.doc_id ?? "") === "ci-delta.md");
if (!hit) throw new Error("incremental sync did not make the new page retrievable");
if (hit.payload?.fields?.wikikb_path !== "concepts/ci-delta.md") {
throw new Error("frontmatter payload missing: " + JSON.stringify(hit.payload));
}
'
- name: Exercise WikiKB runtime integration
shell: bash
run: |
set -euo pipefail
npm ci
npm run build:wkb
node --test \
--test-name-pattern='vendored LexCAT indexes|concurrent retrieval' \
tools/wikikb-local/test/smoke.mjs
workflows:
name: Workflows and shell scripts
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Lint GitHub Actions workflows
uses: docker://rhysd/actionlint:1.7.12@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667
with:
args: >-
-ignore
unexpected.key.*queue.*concurrency
- name: Lint shell scripts
run: >-
shellcheck
tools/kb-search.sh
tools/wikikb-local/install.sh
tools/wikikb-local/wkb
gh-wikikb