Rebrand: Nexus Terminal → Alchementary Link

Renames the product across the codebase: Go module path, config/data
paths, keychain service name, export file extension, build tooling,
docs, and UI text. Sidebar brand mark now reads ">_ AlchementaryLink"
with "Alchementary" in the connection-group gold accent colour, and
the window title is "Alchementary Link".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019T8bJS8BCtY5GeSG2HBj1n
This commit is contained in:
Andy Dixon
2026-09-03 16:41:23 +01:00
co-authored by Claude Sonnet 5
parent 114060127f
commit 1a380a0e99
135 changed files with 678 additions and 674 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
/**
* build.js — Build script for the Nexus Terminal frontend.
* build.js — Build script for the Alchementary Link frontend.
*
* In production mode (no flags): copies vendor assets, assembles the
* dist/ directory with all files needed by the Wails embed, and validates
+2 -2
View File
@@ -8,7 +8,7 @@ const frontendRoot = path.resolve(__dirname, "..");
const source = fs.readFileSync(path.join(frontendRoot, "src/js/irc.js"), "utf8");
const context = {
window: {
NexusTerminal: {
AlchementaryLink: {
createElement: () => {
throw new Error("formatting tests must not create DOM elements");
},
@@ -18,7 +18,7 @@ const context = {
vm.createContext(context);
vm.runInContext(source, context, { filename: "src/js/irc.js" });
const formatting = context.window.NexusTerminal.IRCFormatting;
const formatting = context.window.AlchementaryLink.IRCFormatting;
assert.ok(formatting, "IRC formatting helpers should be exported");
assert.strictEqual(
+8 -8
View File
@@ -143,7 +143,7 @@ assertContains(
assertContains(
"frontend/index.html",
"mode-leviathan",
"Leviathan mode toggle must be present beside Nexus Terminal",
"Leviathan mode toggle must be present beside Alchementary Link",
);
assertContains(
"frontend/index.html",
@@ -232,12 +232,12 @@ assertContains(
);
assertContains(
"frontend/src/js/app.js",
"window.NexusTerminal.VNCViewer?.destroyViewer(sessionId)",
"window.AlchementaryLink.VNCViewer?.destroyViewer(sessionId)",
"session teardown must disconnect and remove VNC viewers",
);
assertContains(
"frontend/src/js/app.js",
"window.NexusTerminal.IRCViewer?.destroyViewer(sessionId)",
"window.AlchementaryLink.IRCViewer?.destroyViewer(sessionId)",
"session teardown must dispose IRC terminals and resize observers",
);
assertContains(
@@ -262,7 +262,7 @@ assertContains(
);
assertContains(
"frontend/src/js/splitpane.js",
"await window.NexusTerminal.wailsService.DisconnectSession(sessionInfo.id)",
"await window.AlchementaryLink.wailsService.DisconnectSession(sessionInfo.id)",
"late split-pane connection results must be disconnected after their pane closes",
);
assertContains(
@@ -404,7 +404,7 @@ assertContains(
assertContains(
"internal/api/leviathan.go",
"LeviathanRunTool",
"Nexus API must expose the imported Leviathan engine",
"Link API must expose the imported Leviathan engine",
);
assertNotContains(
"internal/api/leviathan.go",
@@ -528,12 +528,12 @@ assertNotContains(
);
assertContains(
"build.sh",
"NEXUS_COMPRESS",
"LINK_COMPRESS",
"local builds must expose an explicit compression switch",
);
assertContains(
"scripts/build-common.sh",
"nexus_use_upx_for_target",
"link_use_upx_for_target",
"build scripts must share one UPX target-selection helper",
);
assertContains(
@@ -563,7 +563,7 @@ assertContains(
);
assertContains(
"Makefile",
"NEXUS_FORCE_MACOS_UPX",
"LINK_FORCE_MACOS_UPX",
"Makefile compressed builds must make macOS UPX opt-in",
);
assertTreeNotContains(
+12 -12
View File
@@ -14,7 +14,7 @@ function loadScript(relativePath, additions = {}) {
Set,
setTimeout,
clearTimeout,
window: { NexusTerminal: {} },
window: { AlchementaryLink: {} },
document: {
querySelector: () => null,
addEventListener: () => {},
@@ -32,7 +32,7 @@ function loadScript(relativePath, additions = {}) {
async function testRepeatedSplitCleanup() {
const context = loadScript("src/js/splitpane.js");
const SplitPaneManager = context.window.NexusTerminal.SplitPaneManager;
const SplitPaneManager = context.window.AlchementaryLink.SplitPaneManager;
const closed = [];
const app = {
closeSessionImmediate: async (sessionId, options) => {
@@ -100,7 +100,7 @@ async function testRepeatedSplitCleanup() {
function testClosedPaneRejectsLateConnection() {
const context = loadScript("src/js/splitpane.js");
const SplitPaneManager = context.window.NexusTerminal.SplitPaneManager;
const SplitPaneManager = context.window.AlchementaryLink.SplitPaneManager;
const manager = new SplitPaneManager({ closeSessionImmediate: async () => {} });
const pane = {
dataset: { paneId: "pane-1" },
@@ -128,7 +128,7 @@ function testClosedPaneRejectsLateConnection() {
function testPerSessionStoresReleaseIDs() {
const stateContext = loadScript("src/js/state.js");
const State = stateContext.window.NexusTerminal.State;
const State = stateContext.window.AlchementaryLink.State;
const state = new State();
state.addSession({ id: "session-1" });
state.broadcastTargets = new Set(["session-1"]);
@@ -138,7 +138,7 @@ function testPerSessionStoresReleaseIDs() {
const recordingContext = loadScript("src/js/recordings.js");
const RecordingManager =
recordingContext.window.NexusTerminal.RecordingManager;
recordingContext.window.AlchementaryLink.RecordingManager;
const recordings = new RecordingManager({});
recordings.activeSessions.add("session-1");
recordings.cleanup("session-1");
@@ -149,7 +149,7 @@ async function testCompleteAppTeardownIsImmediateAndIdempotent() {
let finishBackendClose;
let backendCloses = 0;
const context = loadScript("src/js/app.js");
const App = context.window.NexusTerminal.App;
const App = context.window.AlchementaryLink.App;
const app = Object.create(App.prototype);
const resources = {
sftp: new Set(["session-1"]),
@@ -195,10 +195,10 @@ async function testCompleteAppTeardownIsImmediateAndIdempotent() {
};
app.updateStatusBar = () => {};
context.window.NexusTerminal.GitHubViewer = drop("github");
context.window.NexusTerminal.VNCViewer = drop("vnc");
context.window.NexusTerminal.IRCViewer = drop("irc");
context.window.NexusTerminal.wailsService = {
context.window.AlchementaryLink.GitHubViewer = drop("github");
context.window.AlchementaryLink.VNCViewer = drop("vnc");
context.window.AlchementaryLink.IRCViewer = drop("irc");
context.window.AlchementaryLink.wailsService = {
DisconnectSession: () => {
backendCloses++;
return new Promise((resolve) => {
@@ -240,7 +240,7 @@ async function testLatencyPingIsSingleFlightAndIgnoresStaleResults() {
addEventListener: () => {},
},
});
const App = context.window.NexusTerminal.App;
const App = context.window.AlchementaryLink.App;
const app = Object.create(App.prototype);
app._latencySessionID = null;
app._latencyTimer = null;
@@ -248,7 +248,7 @@ async function testLatencyPingIsSingleFlightAndIgnoresStaleResults() {
app._latencyPingInFlight = false;
const pending = [];
context.window.NexusTerminal.wailsService = {
context.window.AlchementaryLink.wailsService = {
PingSession: (sessionID) =>
new Promise((resolve, reject) => {
pending.push({ sessionID, resolve, reject });