Skip to content

Commit 1890519

Browse files
Merge pull request #1951 from AxiomCodeAI/dev
Release 0.1.11
2 parents afafae2 + 64b8206 commit 1890519

28 files changed

Lines changed: 342 additions & 71 deletions

‎.github/scripts/e2e-cases.sh‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/usr/bin/env bash
2+
# ─────────────────────────────────────────────────────────────────────────────
3+
# The query cases (tests/run.py), every language, answered by the INSTALLED packages.
4+
#
5+
# e2e-cases.sh <engines-dir> <platform> [tests/run.py args...]
6+
#
7+
# e2e-install.sh proves an install answers every verb on one case per language. That is a smoke test: 0.1.10
8+
# passed it on Windows while 43 of the cases' 1,844 checks failed there — tests not linked through a file path,
9+
# an absolute file:line refused, any argument holding ' or " mangled on its way into Git Bash. None of it is
10+
# platform-specific code; all of it is how Windows writes paths and command lines. So the cases run here, from
11+
# this checkout's plugin scripts, with the engine and parser of the packages a user installs (AXIOMCODE_ENGINE),
12+
# souffle hidden as it is for a user.
13+
#
14+
# CODEGRAPH_TGZ is the packed @axiomcode/code-graph, as for e2e-install.sh.
15+
# ─────────────────────────────────────────────────────────────────────────────
16+
set -uo pipefail
17+
18+
engines="${1:?usage: e2e-cases.sh <engines-dir> <platform> [tests/run.py args...]}"; platform="${2:?platform}"; shift 2
19+
root="$(cd "$(dirname "$0")/../.." && pwd)"
20+
engines="$(cd "$engines" && pwd)"
21+
W="$(mktemp -d)"; SHADOW=""; trap 'rm -rf "$W" ${SHADOW:+"$SHADOW"}' EXIT
22+
fail() { echo "::error::e2e cases: $*"; exit 1; }
23+
[ -n "${CODEGRAPH_TGZ:-}" ] || fail "CODEGRAPH_TGZ is not set"
24+
25+
version="$(node "$root/.github/scripts/version.mjs" get)"
26+
bash "$root/packaging/assemble-engine-package.sh" "$platform" "$version" "$engines" "$W/engine" >/dev/null \
27+
|| fail "the engine package did not assemble"
28+
mkdir -p "$W/tgz" "$W/proj"
29+
( cd "$W/engine" && npm pack --silent --pack-destination "$W/tgz" >/dev/null ) || fail "npm pack of the engine package failed"
30+
cp "$CODEGRAPH_TGZ" "$W/tgz/" || fail "no code-graph tarball at $CODEGRAPH_TGZ"
31+
( cd "$W/proj" && npm init -y >/dev/null && npm install --no-audit --no-fund --loglevel=error "$W"/tgz/*.tgz ) \
32+
|| fail "npm install of the packed tarballs failed"
33+
export AXIOMCODE_ENGINE="$W/proj/node_modules/@axiomcode/code-graph"
34+
[ -d "$AXIOMCODE_ENGINE/graph" ] || fail "the installed package has no graph/ at $AXIOMCODE_ENGINE"
35+
36+
. "$root/graph/test/tools/hide-souffle.sh"
37+
py="$(command -v python3 || command -v python)" || fail "no python"
38+
# the bash a native program starts, as the CLI hands it on: on Windows a bare `bash` is System32's WSL launcher
39+
command -v cygpath >/dev/null 2>&1 && export AXIOMCODE_BASH="${AXIOMCODE_BASH:-$(cygpath -m "$BASH")}"
40+
# and Python in UTF-8, as every launcher of the product sets it (the dispatcher, find-python.js): some tests start a
41+
# verb's script directly, and an answer's → is not cp1252
42+
export PYTHONUTF8=1
43+
rc=0
44+
PATH="$SANDBOX_PATH" "$py" "$root/tests/run.py" "$@" || rc=1
45+
# what only Windows can show for real: its separators, its exec, its symlinks, its command lines
46+
for t in mixed_separators no_symlink no_exec windows_argv; do
47+
PATH="$SANDBOX_PATH" "$py" "$root/tests/$t.py" > "$W/$t.log" 2>&1 && echo "$t: $(tail -1 "$W/$t.log")" \
48+
|| { echo "::error::e2e cases: tests/$t.py failed"; tail -30 "$W/$t.log"; rc=1; }
49+
done
50+
exit $rc

‎.github/workflows/ci.yml‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ jobs:
551551
- { os: macos-15, platform: darwin-arm64 }
552552
- { os: macos-15-intel, platform: darwin-x64 }
553553
runs-on: ${{ matrix.target.os }}
554-
timeout-minutes: 45
554+
timeout-minutes: 90
555555
steps:
556556
- uses: actions/checkout@v4
557557
- uses: actions/setup-node@v4
@@ -581,6 +581,21 @@ jobs:
581581
bash .github/scripts/e2e-install.sh artifacts/engines "$PLATFORM" "$lang" "$case_dir"
582582
echo "::endgroup::"
583583
done
584+
# The smoke test above is one case per language; Windows writes paths and command lines differently enough that
585+
# a release passed it there with 43 case checks failing (tests not linked through a file path, an absolute
586+
# file:line refused, ' and " mangled into Git Bash). Every query case, answered by the installed packages.
587+
- name: every query case, installed from the tarballs, no Soufflé (Windows)
588+
if: matrix.target.platform == 'win32-x64'
589+
shell: bash
590+
env:
591+
PLATFORM: ${{ matrix.target.platform }}
592+
run: |
593+
set -euo pipefail
594+
# the decompilers `--library auto` uses for a Java class jar and a NuGet package, as the engine job installs them
595+
mvn -q dependency:get -Dartifact=org.vineflower:vineflower:1.10.1
596+
dotnet tool install -g ilspycmd --version 8.2.0.7535 && export PATH="$USERPROFILE/.dotnet/tools:$PATH"
597+
export CODEGRAPH_TGZ="$(ls "$PWD"/artifacts/tgz/*.tgz)"
598+
bash .github/scripts/e2e-cases.sh artifacts/engines "$PLATFORM" --jobs 4
584599
585600
# A single job the branch ruleset can require. Without it, every new matrix
586601
# entry has to be added to the protection rules by hand, and a matrix job that

‎bin/axiomcode‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@
4949
# build option above.)
5050
# ─────────────────────────────────────────────────────────────────────────────
5151
set -eu
52+
# Windows: a native caller (bin/axiomcode.js, the MCP server, ax_exec.bash_argv) hands the arguments over in
53+
# AXIOMCODE_ARGV, each ended by \x1f, because msys misparses them on a command line. Taken once, so a script this one
54+
# starts gets its own.
55+
if [ -n "${AXIOMCODE_ARGV+x}" ]; then
56+
set --; while IFS= read -r -d $'\x1f' _a; do set -- "$@" "$_a"; done < <(printf '%s' "$AXIOMCODE_ARGV"); unset AXIOMCODE_ARGV _a
57+
fi
5258
# RESOLVE $0 THROUGH SYMLINKS BEFORE THE WALK. npm installs a `bin` entry as a link in
5359
# node_modules/.bin, so under `npx axiomcode` or a global install $0 is that link and
5460
# dirname "$0" is .bin/, a directory this package does not live under. The walk below then

‎bin/axiomcode.js‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,12 @@ if (error) fail(error);
5050
const py = findPython();
5151
// AXIOMCODE_BASH too, for the builds Python starts: a bare `bash` from Python on Windows is WSL's or nothing.
5252
const env = { ...(py.exe ? withPython(process.env, py) : process.env), AXIOMCODE_BASH: bash };
53-
const r = spawnSync(bash, [path.join(__dirname, 'axiomcode'), ...args], { stdio: 'inherit', env });
53+
// On Windows the arguments travel in AXIOMCODE_ARGV, each ended by \x1f, not on the command line: Git Bash parses a
54+
// command line by msys rules, where `'` quotes too and `\"` is no escape, so `context "the user's cart"` lost every
55+
// argument after the apostrophe and a quoted string arrived as \Key\. bin/axiomcode turns them back into "$@".
56+
const win = process.platform === 'win32';
57+
const r = spawnSync(bash, [path.join(__dirname, 'axiomcode'), ...(win ? [] : args)],
58+
{ stdio: 'inherit', env: win ? { ...env, AXIOMCODE_ARGV: args.map((a) => `${a}\x1f`).join('') } : env });
5459
if (r.error) fail(`could not start bash: ${r.error.message}`);
5560
// Die of the same signal the CLI died of, so a caller sees what really happened.
5661
if (r.signal) process.kill(process.pid, r.signal);

‎gemini-extension.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "axiomcode",
3-
"version": "0.1.10",
3+
"version": "0.1.11",
44
"description": "Ask your repository how its code connects: who calls this, what breaks if I change it, which tests an edit reaches, how A reaches B. Answers come from a resolved call graph and are verified against it; nothing is guessed.",
55
"contextFileName": "plugins/axiomcode/AGENTS.md",
66
"mcpServers": {

‎package.json‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@axiomcode/code-graph",
3-
"version": "0.1.10",
3+
"version": "0.1.11",
44
"description": "AxiomCode Graph: a resolved call graph of your codebase grounded in formal methods, so you and your coding agents can see who calls what, what a change breaks, and which tests it reaches.",
55
"repository": {
66
"type": "git",
@@ -31,11 +31,11 @@
3131
],
3232
"license": "FSL-1.1-Apache-2.0",
3333
"optionalDependencies": {
34-
"@axiomcode/engine-darwin-arm64": "0.1.10",
35-
"@axiomcode/engine-darwin-x64": "0.1.10",
36-
"@axiomcode/engine-linux-x64": "0.1.10",
37-
"@axiomcode/engine-linux-arm64": "0.1.10",
38-
"@axiomcode/engine-win32-x64": "0.1.10"
34+
"@axiomcode/engine-darwin-arm64": "0.1.11",
35+
"@axiomcode/engine-darwin-x64": "0.1.11",
36+
"@axiomcode/engine-linux-x64": "0.1.11",
37+
"@axiomcode/engine-linux-arm64": "0.1.11",
38+
"@axiomcode/engine-win32-x64": "0.1.11"
3939
},
4040
"bin": {
4141
"axiomcode": "bin/axiomcode.js"

‎parser/src/workflows/csharp/csharp-project-analyzer.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ export class CSharpProjectAnalyzer {
223223
continue;
224224
}
225225
context.seen.add(absoluteFilePath);
226-
const relativePath = path.relative(options.baseMservPath, absoluteFilePath);
226+
// `/` on every platform, as the graph stores a file: on Windows `Shop\Pricer.cs` matched no rule joining paths
227+
const relativePath = path.relative(options.baseMservPath, absoluteFilePath).split(path.sep).join('/');
227228

228229
// THE GOVERNING PROJECT decides the framework and the symbols, unless the
229230
// caller fixed them. See cs-project-config.ts for why this is read at all.
@@ -498,7 +499,7 @@ function readProjectConfigFor(
498499
defineConstants: config.defineConstants,
499500
implicitFrameworkDefines: config.implicitFrameworkDefines,
500501
langVersion: config.langVersion,
501-
projectPath: path.relative(baseMservPath, config.projectFile),
502+
projectPath: path.relative(baseMservPath, config.projectFile).split(path.sep).join('/'),
502503
implicitUsings: config.implicitUsings,
503504
usings: config.usings,
504505
};

‎parser/src/workflows/python/python-project-analyzer.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -572,11 +572,14 @@ export class PythonProjectAnalyzer {
572572
rootDir: string,
573573
baseMservPath: string
574574
): string {
575-
const fromMserv = path.relative(baseMservPath, filePath);
575+
// Written with `/` on every platform, as the other languages' IR writes it: the rules join a module's directory to a
576+
// string (`os.path.join(HERE, 'graph-core.py')`, `include("shop.urls")`) with `/`, and on Windows `pkg\changed.py`
577+
// matched none of them.
578+
const fromMserv = path.relative(baseMservPath, filePath).split(path.sep).join('/');
576579
if (fromMserv !== '' && !fromMserv.startsWith('..') && !path.isAbsolute(fromMserv)) {
577580
return fromMserv;
578581
}
579-
return path.relative(rootDir, filePath) || path.basename(filePath);
582+
return path.relative(rootDir, filePath).split(path.sep).join('/') || path.basename(filePath);
580583
}
581584

582585
/** The directory names above a module's top-level package, outermost first (see ProjectModuleFacts.outerDirs). */

‎plugins/axiomcode/.claude-plugin/plugin.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "axiomcode",
33
"description": "Ask your repository how its code connects: who calls this, what breaks if I change it, which tests an edit reaches, how A reaches B. Answers come from a resolved call graph and are verified against it; nothing is guessed.",
4-
"version": "0.1.10",
4+
"version": "0.1.11",
55
"author": {
66
"name": "AxiomCode"
77
}

‎plugins/axiomcode/.codex-plugin/plugin.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "axiomcode",
3-
"version": "0.1.10",
3+
"version": "0.1.11",
44
"description": "Ask your repository how its code connects: who calls this, what breaks if I change it, which tests an edit reaches, how A reaches B. Answers come from a resolved call graph and are verified against it; nothing is guessed.",
55
"author": { "name": "AxiomCode", "url": "https://github.com/AxiomCodeAI/axiomcodegraph" },
66
"homepage": "https://github.com/AxiomCodeAI/axiomcodegraph",

0 commit comments

Comments
 (0)