diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 335eec59..8ff3fa8d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -138,7 +138,7 @@ jobs: run: | FAILED=0 for V in packages/extension/amicode-linux-x64.vsix packages/extension/amicode-linux-arm64.vsix packages/extension/amicode-darwin-arm64.vsix packages/extension/amicode-win32-x64.vsix packages/extension/amicode-win32-arm64.vsix packages/extension/amicode-darwin-x64.vsix; do - OUTPUT=$(npx --yes @vscode/vsce publish --packagePath "$V" 2>&1) && { echo "$OUTPUT"; continue; } + OUTPUT=$(npx --yes --package @vscode/vsce vsce publish --packagePath "$V" 2>&1) && { echo "$OUTPUT"; continue; } echo "$OUTPUT" echo "$OUTPUT" | grep -q "already exists" || FAILED=1 done diff --git a/packages/extension/src/amicode_service_runner.ts b/packages/extension/src/amicode_service_runner.ts index 1319e2cf..ad81ec62 100644 --- a/packages/extension/src/amicode_service_runner.ts +++ b/packages/extension/src/amicode_service_runner.ts @@ -117,7 +117,7 @@ export interface AmicodeServiceRunnerOptions { * writes the handshake record after the engine is healthy AND the service is * up, and removes it on shutdown (BEFORE killing the engine — order matters: * the extension must not read a handshake for a dying engine). The handshake - * carries the UNARMED_PASSWORD sentinel (the hub engine is unarmed, so the + * carries the UNARMED_SENTINEL sentinel (the hub engine is unarmed, so the * password challenge is vacuously true). Default: undefined (no handshake — * backward compatible, same pattern as pidFile). */ handshakePath?: string; diff --git a/packages/extension/src/extension.ts b/packages/extension/src/extension.ts index 353e801c..e3a26aeb 100644 --- a/packages/extension/src/extension.ts +++ b/packages/extension/src/extension.ts @@ -117,7 +117,7 @@ import { buildDeviceStatus, nextActions, capabilityHint, type DriveLine } from " import { SchusterJobServer } from "./qick_client"; import { adoptOrSpawn, buildLiveDeps, isPidAlive, reclaimOrphanPort, auditAdoptedEngine, restartAdoptedEngine, readoptHubInPlace, sweepStrayEngines, listOpencodeEngines, hasLiveClient, reclaimEnginePid, planEngineRestart, planServerActivation, adoptedTheHub, probeUnarmedHub, shouldRideDeterministicHub, planHubYieldBack } from "./server_lifecycle"; import { hubEnginePortFor } from "./amicode_service/fleet_hub_service"; -import { handshakePath, readHandshake, deleteHandshake, serverLogPath, coldSpawnHandshakeHook, hashFile, hashString, UNARMED_PASSWORD, isUnarmedHandshake } from "./server_handshake"; +import { handshakePath, readHandshake, deleteHandshake, serverLogPath, coldSpawnHandshakeHook, hashFile, hashString, UNARMED_SENTINEL, isUnarmedHandshake } from "./server_handshake"; import { startKeepalive, stopKeepalive, readGraceSeconds, pingKeepalive } from "./server_keepalive"; import { FleetPollHysteresis } from "./fleet_poll_hysteresis"; import { FleetPostureStateWriter } from "./fleet_posture_state"; @@ -1553,7 +1553,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { adoptedPort = hubEnginePort; adoptedPid = hubPid; adoptedUnarmed = true; - serverPassword = UNARMED_PASSWORD; + serverPassword = UNARMED_SENTINEL; serverAuthHeaders.Authorization = serverAuthHeader(serverPassword); opencodeReadyUrl = new URL(`http://127.0.0.1:${hubEnginePort}`); opencodeChannel.appendLine( @@ -1577,7 +1577,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { adoptedPort = lifecycleResult.port; adoptedPid = lifecycleResult.pid; adoptedHashes = lifecycleResult.adoptedHashes; - adoptedUnarmed = lifecycleResult.password === UNARMED_PASSWORD; + adoptedUnarmed = lifecycleResult.password === UNARMED_SENTINEL; // Replace the minted password with the recorded one — the surviving // server was spawned with it, so every auth surface must carry it. serverPassword = lifecycleResult.password; diff --git a/packages/extension/src/server_handshake.ts b/packages/extension/src/server_handshake.ts index 61e5d922..a6fa17d3 100644 --- a/packages/extension/src/server_handshake.ts +++ b/packages/extension/src/server_handshake.ts @@ -75,11 +75,11 @@ export function writeHandshake(record: HandshakeRecord, filePath?: string): void * password is meaningless. The sentinel tells the adoption gate that the * "password challenge" for this server is vacuously true — the health check IS * the ownership proof for an unarmed engine behind the SSH tunnel. */ -export const UNARMED_PASSWORD = "__hub_unarmed__"; +export const UNARMED_SENTINEL = "__hub_unarmed__"; /** True when the handshake record was written by an unarmed hub engine. */ export function isUnarmedHandshake(record: HandshakeRecord): boolean { - return record.password === UNARMED_PASSWORD; + return record.password === UNARMED_SENTINEL; } /** Default PID-liveness probe (signal 0 = existence check, no signal sent). @@ -106,7 +106,7 @@ export interface WriteHubHandshakeOpts { } /** Write the hub engine's handshake record after it passes its health check. - * The hub is unarmed, so the password field carries the UNARMED_PASSWORD + * The hub is unarmed, so the password field carries the UNARMED_SENTINEL * sentinel. The adoption gate verifies reachability-only for unarmed engines * (the SSH tunnel is the auth boundary). Generates startedAt and stamps * PROTOCOL_VERSION automatically. */ @@ -116,7 +116,7 @@ export function writeHubHandshake(opts: WriteHubHandshakeOpts): void { port: opts.port, pid: opts.pid, startedAt: new Date().toISOString(), - password: UNARMED_PASSWORD, + password: UNARMED_SENTINEL, binaryHash: opts.binaryHash, configHash: opts.configHash, protocolVersion: PROTOCOL_VERSION, diff --git a/packages/extension/test/adopt_live_server.test.ts b/packages/extension/test/adopt_live_server.test.ts index a68ff543..b52cc507 100644 --- a/packages/extension/test/adopt_live_server.test.ts +++ b/packages/extension/test/adopt_live_server.test.ts @@ -10,7 +10,7 @@ import { adoptOrSpawn, buildLiveDeps, } from "../src/server_lifecycle"; -import { coldSpawnHandshakeHook, readHandshake, writeHandshake, writeHubHandshake, UNARMED_PASSWORD, PROTOCOL_VERSION } from "../src/server_handshake"; +import { coldSpawnHandshakeHook, readHandshake, writeHandshake, writeHubHandshake, UNARMED_SENTINEL, PROTOCOL_VERSION } from "../src/server_handshake"; import { serverAuthHeader } from "../src/server_auth"; import { windowModeFromRemoteName } from "../src/fleet_window_mode_state"; import { divertToFleetRelay, type FleetTopologyState } from "../src/fleet_topology"; @@ -291,7 +291,7 @@ async function startUnarmedHub(): Promise<{ port: number; close: () => Promise new Promise((resolve) => server.close(() => resolve())) }; } -/** Sentinel password for the unarmed hub engine — matches UNARMED_PASSWORD +/** Sentinel password for the unarmed hub engine — matches UNARMED_SENTINEL * from server_handshake.ts (imported above). */ /** Plant a hub-style handshake (unarmed sentinel password, current protocol). */ @@ -306,7 +306,7 @@ function plantHubHandshake( port, pid: overrides.pid ?? process.pid, startedAt: new Date().toISOString(), - password: UNARMED_PASSWORD, + password: UNARMED_SENTINEL, binaryHash: "hub-bin", configHash: "hub-cfg", protocolVersion: overrides.protocolVersion, @@ -410,7 +410,7 @@ describe("#1576 hub engine adoption — editor adopts the hub, no rival engine", if (hs.status !== "ok") return; expect(hs.record.port).toBe(12345); expect(hs.record.pid).toBe(999); - expect(hs.record.password).toBe(UNARMED_PASSWORD); + expect(hs.record.password).toBe(UNARMED_SENTINEL); expect(hs.record.protocolVersion).toBe(PROTOCOL_VERSION); expect(hs.record.dbPath).toBe(DB); }); diff --git a/packages/extension/test/amicode_service_runner.test.ts b/packages/extension/test/amicode_service_runner.test.ts index 77c93e09..f3489389 100644 --- a/packages/extension/test/amicode_service_runner.test.ts +++ b/packages/extension/test/amicode_service_runner.test.ts @@ -36,7 +36,7 @@ import { serverAuthHeader, serverAuthToken } from "../src/server_auth"; import { readHandshake, classifyGate, - UNARMED_PASSWORD, + UNARMED_SENTINEL, PROTOCOL_VERSION, } from "../src/server_handshake"; @@ -872,7 +872,7 @@ createServer((_req, res) => { return dir; } - it("AC1: on boot, the handshake file exists and contains port, password (UNARMED_PASSWORD), and dbPath", async () => { + it("AC1: on boot, the handshake file exists and contains port, password (UNARMED_SENTINEL), and dbPath", async () => { const dir = mkdtempSync(join(tmpdir(), "amicode-runner-handshake-write-")); const hsPath = join(dir, "handshake.json"); const dbPath = "/tmp/fake-db.db"; @@ -896,7 +896,7 @@ createServer((_req, res) => { // The record must carry the right fields. expect(result.record.port).toBeGreaterThan(0); - expect(result.record.password).toBe(UNARMED_PASSWORD); + expect(result.record.password).toBe(UNARMED_SENTINEL); expect(result.record.dbPath).toBe(dbPath); expect(result.record.pid).toBe(boot.engine.pid); expect(result.record.protocolVersion).toBe(PROTOCOL_VERSION);