Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ on:

jobs:
claude-review:
if: github.event.pull_request.head.repo.full_name == github.repository
# Optional: Filter by PR author
# if: |
# github.event.pull_request.user.login == 'external-contributor' ||
Expand Down Expand Up @@ -41,4 +42,3 @@ jobs:
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options

2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
cache: npm

- name: Install dependencies
run: npm ci
run: npm ci --force

- name: Run node test suite
run: npm test
106 changes: 106 additions & 0 deletions scripts/bench-ax-bfs-queue.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import Foundation

private struct Node {
let firstChild: Int
let childCount: Int
}

private let depthLimit = 8
private let branching = 3
private var nodes: [Node] = []
private var frontier: [(index: Int, depth: Int)] = [(0, 0)]

nodes.reserveCapacity(9_841)
nodes.append(Node(firstChild: -1, childCount: 0))

var frontierIndex = 0
while frontierIndex < frontier.count {
let (nodeIndex, depth) = frontier[frontierIndex]
frontierIndex += 1
guard depth < depthLimit else { continue }

let firstChild = nodes.count
for _ in 0..<branching {
nodes.append(Node(firstChild: -1, childCount: 0))
frontier.append((nodes.count - 1, depth + 1))
}
nodes[nodeIndex] = Node(firstChild: firstChild, childCount: branching)
}

private let roots = [0, 1, 2].filter { $0 < nodes.count }
private let maxDepth = 8
private let maxElements = 240
private let iterations = 20_000

@inline(never)
private func removeFirstTraversal() -> Int {
var queue = roots.map { ($0, 0) }
var inspected = 0
var checksum = 0

while let (nodeIndex, depth) = queue.first {
queue.removeFirst()
inspected += 1
if inspected > maxElements { break }

checksum &+= nodeIndex &+ depth
if depth >= maxDepth { continue }

let node = nodes[nodeIndex]
if node.childCount > 0 {
for offset in 0..<node.childCount {
queue.append((node.firstChild + offset, depth + 1))
}
}
}
return checksum
}

@inline(never)
private func cursorTraversal() -> Int {
var queue = roots.map { ($0, 0) }
var queueIndex = 0
var inspected = 0
var checksum = 0

while queueIndex < queue.count {
let (nodeIndex, depth) = queue[queueIndex]
queueIndex += 1
inspected += 1
if inspected > maxElements { break }

checksum &+= nodeIndex &+ depth
if depth >= maxDepth { continue }

let node = nodes[nodeIndex]
if node.childCount > 0 {
for offset in 0..<node.childCount {
queue.append((node.firstChild + offset, depth + 1))
}
}
}
return checksum
}

@inline(never)
private func measure(_ label: String, _ block: () -> Int) -> (label: String, ms: Double, checksum: Int) {
var checksum = 0
let start = DispatchTime.now().uptimeNanoseconds
for _ in 0..<iterations {
checksum &+= block()
}
let elapsed = DispatchTime.now().uptimeNanoseconds - start
return (label, Double(elapsed) / 1_000_000.0, checksum)
}

let removeFirstWarmup = removeFirstTraversal()
let cursorWarmup = cursorTraversal()
precondition(removeFirstWarmup == cursorWarmup)

let removeFirst = measure("removeFirst", removeFirstTraversal)
let cursor = measure("cursor", cursorTraversal)

print("nodes=\(nodes.count) roots=\(roots.count) maxDepth=\(maxDepth) maxElements=\(maxElements) iterations=\(iterations)")
print("\(removeFirst.label): \(String(format: "%.2f", removeFirst.ms)) ms checksum=\(removeFirst.checksum)")
print("\(cursor.label): \(String(format: "%.2f", cursor.ms)) ms checksum=\(cursor.checksum)")
print("speedup: \(String(format: "%.2fx", removeFirst.ms / cursor.ms))")
102 changes: 102 additions & 0 deletions scripts/test-aerospace-workspace.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/env node

import test from 'node:test';
import assert from 'node:assert/strict';
import path from 'node:path';
import { performance } from 'node:perf_hooks';
import { setTimeout as delay } from 'node:timers/promises';
import { fileURLToPath } from 'node:url';
import { importTs } from './lib/ts-import.mjs';

const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const { createAerospaceWorkspaceMover } = await importTs(path.join(root, 'src/main/aerospace-workspace.ts'));

test('AeroSpace workspace mover', async (t) => {
await t.test('coalesces concurrent move requests into one follow-up run', async () => {
const calls = [];
const mover = createAerospaceWorkspaceMover({
platform: 'darwin',
runCommand: async (args) => {
calls.push(args);
await delay(10);
if (args[0] === 'list-workspaces') return 'work\n';
if (args[0] === 'list-windows') return '42 other\n';
return '';
},
});

mover.requestMove();
mover.requestMove();
mover.requestMove();

await mover.whenIdle();

assert.deepEqual(
calls.map((args) => args[0]),
[
'list-workspaces',
'list-windows',
'move-node-to-workspace',
'list-workspaces',
'list-windows',
'move-node-to-workspace',
],
);
assert.deepEqual(mover.getState(), { available: true, inFlight: false, queued: false });
});

await t.test('marks missing aerospace binary unavailable and skips later requests', async () => {
let calls = 0;
const mover = createAerospaceWorkspaceMover({
platform: 'darwin',
runCommand: async () => {
calls += 1;
const error = new Error('spawn aerospace ENOENT');
error.code = 'ENOENT';
throw error;
},
});

mover.requestMove();
await mover.whenIdle();
mover.requestMove();
await delay(0);

assert.equal(calls, 1);
assert.deepEqual(mover.getState(), { available: false, inFlight: false, queued: false });
});

await t.test('does not block the event loop while slow commands are in flight', async () => {
const slowCommandDelayMs = 80;
const calls = [];
const mover = createAerospaceWorkspaceMover({
platform: 'darwin',
runCommand: async (args) => {
calls.push(args);
await delay(slowCommandDelayMs);
if (args[0] === 'list-workspaces') return 'work\n';
if (args[0] === 'list-windows') return '42 other\n';
return '';
},
});

const startedAt = performance.now();
let zeroDelayTimerFiredAfterMs = Number.POSITIVE_INFINITY;
const timerPromise = new Promise((resolve) => {
setTimeout(() => {
zeroDelayTimerFiredAfterMs = performance.now() - startedAt;
resolve();
}, 0);
});

mover.requestMove();
await timerPromise;
await mover.whenIdle();

assert.ok(calls.length >= 1, 'first command should start');
assert.ok(
zeroDelayTimerFiredAfterMs < slowCommandDelayMs,
`zero-delay timer fired after ${zeroDelayTimerFiredAfterMs}ms`,
);
});
});
Loading
Loading