diff --git a/cli-src/porpid-cli.mjs b/cli-src/porpid-cli.mjs
index 67dee78..1fd8429 100644
--- a/cli-src/porpid-cli.mjs
+++ b/cli-src/porpid-cli.mjs
@@ -6,6 +6,7 @@ import { basename, dirname, isAbsolute, join, resolve } from "node:path";
import { createInterface } from "node:readline";
import { createGunzip } from "node:zlib";
import { Worker as NodeWorker } from "node:worker_threads";
+import packageInformation from "../package.json" with { type: "json" };
import { bytesToHex } from "@noble/hashes/utils.js";
import { classifyContamination } from "../src/contamination.ts";
@@ -22,7 +23,7 @@ import { createMafftRunner } from "./direct-mafft.mjs";
import { createMsaRunner } from "./direct-msa.mjs";
import { createIndependentPanelFilterRunner } from "./direct-panel-filter.mjs";
-const VERSION = "0.3.15";
+const VERSION = packageInformation.version;
const UPSTREAM_COMMIT = "201af7942029cfb7974880e41674be9f0ddfaf3b";
const CLI_DIRECTORY = dirname(new URL(import.meta.url).pathname);
diff --git a/cli/porpid-cli.mjs b/cli/porpid-cli.mjs
index e258aea..8765413 100755
--- a/cli/porpid-cli.mjs
+++ b/cli/porpid-cli.mjs
@@ -12,6 +12,9 @@ import { basename, dirname, isAbsolute, join, resolve } from "node:path";
import { createInterface } from "node:readline";
import { createGunzip } from "node:zlib";
import { Worker as Worker$1 } from "node:worker_threads";
+//#region package.json
+var version = "0.3.16";
+//#endregion
//#region src/contamination.ts
/** Samples without donor metadata remain separate biological self groups. */
function selfGroupsBySample(config) {
@@ -4753,7 +4756,7 @@ function createIndependentPanelFilterRunner(workerPath = new URL("../porpid-pane
}
//#endregion
//#region cli-src/porpid-cli.mjs
-const VERSION = "0.3.15";
+const VERSION = version;
const UPSTREAM_COMMIT = "201af7942029cfb7974880e41674be9f0ddfaf3b";
const CLI_DIRECTORY = dirname(new URL(import.meta.url).pathname);
function defaultCliAssets() {
diff --git a/package-lock.json b/package-lock.json
index 08c5bbc..4273ef6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "webporpid",
- "version": "0.3.15",
+ "version": "0.3.16",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "webporpid",
- "version": "0.3.15",
+ "version": "0.3.16",
"dependencies": {
"@biowasm/aioli": "3.2.3",
"@bjorn3/browser_wasi_shim": "0.4.2",
diff --git a/package.json b/package.json
index e83c034..6a0919b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "webporpid",
- "version": "0.3.15",
+ "version": "0.3.16",
"private": true,
"type": "module",
"scripts": {
diff --git a/src/components/results-explorer.tsx b/src/components/results-explorer.tsx
index 700e2ff..bd5b5ca 100644
--- a/src/components/results-explorer.tsx
+++ b/src/components/results-explorer.tsx
@@ -1,4 +1,5 @@
import { useEffect, useMemo, useRef, useState } from "react";
+import packageInformation from "../../package.json";
import {
ALIVIBE_BRIDGE_VERSION, ALIVIBE_SOURCE_REVISION, assertAlivibeInitialLoad, assertAlivibeRoundTripTarget,
getAlivibeBridge, loadAlivibeNucleotideFasta, readAlivibeNucleotideFasta, type AlivibeEditorWindow, type AlivibeMsaJob,
@@ -598,7 +599,7 @@ export function ResultsExplorer({ bundle, onSaveResults, onBundleChange }: { bun
const targetSample = sampleRef.current, current = effectiveAlignment(bundleRef.current, targetSample, variant); if (!current.fasta) return;
setAlignmentError(""); setAlignmentStatus("Opening the bundled Alivibe editor…");
const applicationBase = new URL(import.meta.env.BASE_URL, document.baseURI), editorUrl = new URL("tools/alivibe.html", applicationBase);
- editorUrl.searchParams.set("swigBridge", String(ALIVIBE_BRIDGE_VERSION)); editorUrl.searchParams.set("source", ALIVIBE_SOURCE_REVISION.slice(0, 12)); editorUrl.searchParams.set("release", "0.3.15");
+ editorUrl.searchParams.set("swigBridge", String(ALIVIBE_BRIDGE_VERSION)); editorUrl.searchParams.set("source", ALIVIBE_SOURCE_REVISION.slice(0, 12)); editorUrl.searchParams.set("release", packageInformation.version);
const token = globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`;
const popup = window.open(editorUrl.href, `webporpid-alivibe-${token}`, "popup,width=1500,height=920") as AlivibeEditorWindow | null;
if (!popup) { setAlignmentError("The browser blocked the Alivibe window. Allow pop-ups for this site and try again."); return; }
diff --git a/src/pipeline-worker.ts b/src/pipeline-worker.ts
index 214aba6..ba6685b 100644
--- a/src/pipeline-worker.ts
+++ b/src/pipeline-worker.ts
@@ -1,6 +1,7 @@
///
import { bytesToHex } from "@noble/hashes/utils.js";
+import packageInformation from "../package.json";
import coreWasmUrl from "/webporpid.wasm?url";
import { classifyContaminationAsync } from "./contamination";
import { runAlivibeMsa } from "./alivibe-msa-runtime";
@@ -114,7 +115,7 @@ async function run(request: RunRequest, signal: AbortSignal): Promise 0 ? "adaptive selected-read" : "all-read"} partition spool`,
`${now()} background execution aid: ${activeBackgroundMode ? "requested; quiet audible processing hum controlled by the browser UI" : "disabled"}`,
`${now()} parameters: error_rate=${request.config.parameters.errorRate}, lengths=(${request.config.parameters.minLength},${request.config.parameters.maxLength}), lda=${request.config.parameters.ldaThreshold}, panel_filter=${request.config.parameters.panelFilterMode ?? "mafft-batch"}`];
@@ -451,7 +452,7 @@ async function run(request: RunRequest, signal: AbortSignal): Promise