From 7691985ec90a07f837872baa9f8804aca901be52 Mon Sep 17 00:00:00 2001 From: swapnil <78632212+swapnilpaliwal-sd@users.noreply.github.com> Date: Sun, 27 Sep 2026 22:50:29 -0700 Subject: [PATCH 1/3] windows: the launcher finds its package from a backslash path, not the current directory On Windows bin/axiomcode.js starts bash with path.join(__dirname, 'axiomcode'), a path with only backslashes. The root walk takes the parent by `${self%/*}` since the query-latency change, which splits on '/' only: it found no directory in $0, started the walk at the current directory, and a run from inside a checkout took the checkout for the package. The installed e2e on win32-x64 failed that way on the 0.1.3 release push (`parser not built at /parser/dist/index.js`), so main was not tagged. `dirname`, before that change, split on either. bin/axiomcode turns backslashes into '/' before the walk. tests/latency.py runs the launcher through a file named with the same backslash string from a directory that looks like a package root: it fails without the fix, and a slash path (the control) finds the same root before and after. Co-authored-by: axiomcode-bot[bot] <334110751+axiomcode-bot[bot]@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 (1M context) --- bin/axiomcode | 5 +++++ tests/latency.py | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/bin/axiomcode b/bin/axiomcode index e01ccc31b..fa44d4bbb 100755 --- a/bin/axiomcode +++ b/bin/axiomcode @@ -60,6 +60,11 @@ fi # NO PROGRAM IS STARTED TO FIND IT: the parent of a path is taken by parameter expansion, not `dirname`. Every query goes # through here, and under Git Bash on Windows each program started is a fork emulation that costs tens of milliseconds # idle and far more on a busy machine; the walk used to start one per level, the verb check below four more. +# ON WINDOWS $0 HAS BACKSLASHES: bin/axiomcode.js starts bash with path.join(__dirname, 'axiomcode'), which is +# D:\...\bin\axiomcode. `dirname` split on either separator; the expansion below splits on '/' only, so without this +# it finds no directory in $0, starts the walk at the CURRENT directory, and a run from inside a checkout takes the +# checkout for the package (`parser not built at /parser/dist/index.js`). +self="${self//\\//}" case "$self" in */*) d="${self%/*}";; *) d=.;; esac d="$(cd "${d:-/}" && pwd)" while [ "$d" != / ] && { [ ! -f "$d/package.json" ] || [ ! -d "$d/graph" ]; }; do d="${d%/*}"; d="${d:-/}"; done diff --git a/tests/latency.py b/tests/latency.py index 51b89e0f6..897b9fd56 100644 --- a/tests/latency.py +++ b/tests/latency.py @@ -176,6 +176,27 @@ def verbs_checks(): not before_verb, before_verb) finally: shutil.rmtree(work, ignore_errors=True) + # On Windows bin/axiomcode.js hands bash a backslash path. Here the same string names a file (a backslash is an + # ordinary character on POSIX), run from a directory that looks like a package root, as a CI checkout does: the + # root must be the package the path names, never the current directory. + work = os.path.realpath(tempfile.mkdtemp(prefix='axiomcode-root-')) + try: + for d in ('pkg/bin', 'pkg/graph', 'graph', 'src'): os.makedirs(os.path.join(work, d)) + for d in ('pkg', ''): write(work, os.path.join(d, 'package.json'), '{}') + launcher = 'pkg\\bin\\axiomcode' + shutil.copy(os.path.join(ROOT, 'bin', 'axiomcode'), os.path.join(work, launcher)) + shutil.copy(os.path.join(ROOT, 'bin', 'axiomcode'), os.path.join(work, 'pkg', 'bin', 'axiomcode')) + env = {k: v for k, v in os.environ.items() if k != 'AXIOM_PARSER'} + said = {} + for how, argv0 in (('backslash', launcher), ('slash', 'pkg/bin/axiomcode')): + r = subprocess.run(['bash', argv0, 'src', 'out'], cwd=work, capture_output=True, text=True, env=env) + said[how] = next((l.split(' at ', 1)[1].split(' ')[0] for l in r.stderr.splitlines() if 'parser not built at' in l), r.stderr) + want = os.path.join(work, 'pkg', 'parser', 'dist', 'index.js') + check("root: a backslash path to bin/axiomcode (Windows' node launcher) finds the package it names, not the " + "current directory", said['backslash'] == want, said) + check("root: a slash path still finds the package it names (control)", said['slash'] == want, said) + finally: + shutil.rmtree(work, ignore_errors=True) # ── python ──────────────────────────────────────────────────────────────────────────────────────────────────────── From 46c3817a33369ccbba09e68396c4e71c700f8741 Mon Sep 17 00:00:00 2001 From: swapnil <78632212+swapnilpaliwal-sd@users.noreply.github.com> Date: Sun, 27 Sep 2026 22:50:29 -0700 Subject: [PATCH 2/3] windows: the launcher finds its package from a backslash path, not the current directory On Windows bin/axiomcode.js starts bash with path.join(__dirname, 'axiomcode'), a path with only backslashes. The root walk takes the parent by `${self%/*}` since the query-latency change, which splits on '/' only: it found no directory in $0, started the walk at the current directory, and a run from inside a checkout took the checkout for the package. The installed e2e on win32-x64 failed that way on the 0.1.3 release push (`parser not built at /parser/dist/index.js`), so main was not tagged. `dirname`, before that change, split on either. bin/axiomcode turns backslashes into '/' before the walk. tests/latency.py runs the launcher through a file named with the same backslash string from a directory that looks like a package root: it fails without the fix, and a slash path (the control) finds the same root before and after. Co-authored-by: axiomcode-bot[bot] <334110751+axiomcode-bot[bot]@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 (1M context) --- bin/axiomcode | 5 +++++ tests/latency.py | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/bin/axiomcode b/bin/axiomcode index e01ccc31b..fa44d4bbb 100755 --- a/bin/axiomcode +++ b/bin/axiomcode @@ -60,6 +60,11 @@ fi # NO PROGRAM IS STARTED TO FIND IT: the parent of a path is taken by parameter expansion, not `dirname`. Every query goes # through here, and under Git Bash on Windows each program started is a fork emulation that costs tens of milliseconds # idle and far more on a busy machine; the walk used to start one per level, the verb check below four more. +# ON WINDOWS $0 HAS BACKSLASHES: bin/axiomcode.js starts bash with path.join(__dirname, 'axiomcode'), which is +# D:\...\bin\axiomcode. `dirname` split on either separator; the expansion below splits on '/' only, so without this +# it finds no directory in $0, starts the walk at the CURRENT directory, and a run from inside a checkout takes the +# checkout for the package (`parser not built at /parser/dist/index.js`). +self="${self//\\//}" case "$self" in */*) d="${self%/*}";; *) d=.;; esac d="$(cd "${d:-/}" && pwd)" while [ "$d" != / ] && { [ ! -f "$d/package.json" ] || [ ! -d "$d/graph" ]; }; do d="${d%/*}"; d="${d:-/}"; done diff --git a/tests/latency.py b/tests/latency.py index 51b89e0f6..897b9fd56 100644 --- a/tests/latency.py +++ b/tests/latency.py @@ -176,6 +176,27 @@ def verbs_checks(): not before_verb, before_verb) finally: shutil.rmtree(work, ignore_errors=True) + # On Windows bin/axiomcode.js hands bash a backslash path. Here the same string names a file (a backslash is an + # ordinary character on POSIX), run from a directory that looks like a package root, as a CI checkout does: the + # root must be the package the path names, never the current directory. + work = os.path.realpath(tempfile.mkdtemp(prefix='axiomcode-root-')) + try: + for d in ('pkg/bin', 'pkg/graph', 'graph', 'src'): os.makedirs(os.path.join(work, d)) + for d in ('pkg', ''): write(work, os.path.join(d, 'package.json'), '{}') + launcher = 'pkg\\bin\\axiomcode' + shutil.copy(os.path.join(ROOT, 'bin', 'axiomcode'), os.path.join(work, launcher)) + shutil.copy(os.path.join(ROOT, 'bin', 'axiomcode'), os.path.join(work, 'pkg', 'bin', 'axiomcode')) + env = {k: v for k, v in os.environ.items() if k != 'AXIOM_PARSER'} + said = {} + for how, argv0 in (('backslash', launcher), ('slash', 'pkg/bin/axiomcode')): + r = subprocess.run(['bash', argv0, 'src', 'out'], cwd=work, capture_output=True, text=True, env=env) + said[how] = next((l.split(' at ', 1)[1].split(' ')[0] for l in r.stderr.splitlines() if 'parser not built at' in l), r.stderr) + want = os.path.join(work, 'pkg', 'parser', 'dist', 'index.js') + check("root: a backslash path to bin/axiomcode (Windows' node launcher) finds the package it names, not the " + "current directory", said['backslash'] == want, said) + check("root: a slash path still finds the package it names (control)", said['slash'] == want, said) + finally: + shutil.rmtree(work, ignore_errors=True) # ── python ──────────────────────────────────────────────────────────────────────────────────────────────────────── From 51c5e8e151b8ff5af2220f2a7709bce011877822 Mon Sep 17 00:00:00 2001 From: Swapnil <78632212+swapnilpaliwal-sd@users.noreply.github.com> Date: Mon, 28 Sep 2026 09:25:47 -0700 Subject: [PATCH 3/3] parser: 0.1.2, for the parser changes on 0.1.4 The vendored parser keeps its own version and moves once per release, only when parser code changed. dev and main ship it at 0.1.1. On 0.1.4, four merged changes touched parser/: #1592 (a concise arrow body is owned by the arrow), #1616 (generated-output detection), #1621 (a package's published API is rooted from package.json) and #1625 (the Java walk and build directories). So 0.1.2, one bump for the release. --- parser/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parser/package.json b/parser/package.json index 6c9395caa..eac08e048 100644 --- a/parser/package.json +++ b/parser/package.json @@ -1,6 +1,6 @@ { "name": "@axiomcode/parser", - "version": "0.1.1", + "version": "0.1.2", "description": "AxiomCode Parser — compiles source code and build configuration into a relational intermediate representation.", "main": "dist/extract.js", "types": "dist/extract.d.ts",