Skip to content

statechart: a relative TLA2TOOLS or JAVA path fails, because TLC runs in the snapshot folder #973

Open

Description

@dameronma-ma

What happens

findTlc in pstack/skills/statechart/scripts/tlc-tools.mjs checks that TLA2TOOLS and JAVA exist from the caller's working directory, then returns them as given. tlc() in statechart.mjs starts java with cwd set to the folder of the spec's snapshot copy under $TMPDIR/statechart-inputs-*/. Java resolves a relative -cp against that folder, so it cannot find the jar, and from-spec exits with cannot run TLC. A relative JAVA with a slash, such as ./jdk/bin/java, starts from the same folder.

Reproduce

Tested at 9e88dad on macOS with Node 25.8.0. The stand-in java prints the folder it runs in and whether it can see the -cp jar.

mkdir repro && cd repro && mkdir tools && touch tools/tla2tools.jar
cat > fake-java <<'EOF'
#!/bin/sh
cp=""; prev=""; for a in "$@"; do [ "$prev" = "-cp" ] && cp="$a"; prev="$a"; done
echo "java runs in: $PWD" >&2
if [ -e "$cp" ]; then echo "jar $cp: found" >&2; else echo "jar $cp: not found" >&2; fi
exit 1
EOF
chmod +x fake-java
printf -- '---- MODULE Spec ----\nEXTENDS Naturals\nVARIABLE x\nInit == x = 0\nNext == x'"'"' = x\n====\n' > Spec.tla
printf 'INIT Init\nNEXT Next\n' > Spec.cfg
S=/path/to/pstack/skills/statechart/scripts/statechart.mjs
export JAVA=$PWD/fake-java
TLA2TOOLS=tools/tla2tools.jar node $S from-spec Spec.tla   # writes Spec.map.mjs
TLA2TOOLS=tools/tla2tools.jar node $S from-spec Spec.tla
TLA2TOOLS=$PWD/tools/tla2tools.jar node $S from-spec Spec.tla

With the relative path:

cannot run TLC with .../fake-java -cp tools/tla2tools.jar: java exited 1:
  java runs in: $TMPDIR/statechart-inputs-B8EIpr/<absolute path of repro>
  jar tools/tla2tools.jar: not found

With the absolute path, java runs in the same snapshot folder and prints jar <absolute path>: found.

Expected

A TLA2TOOLS or JAVA path that exists from the caller's directory, which findTlc already checks, also works when TLC runs.

Activity

  1. deanrie commented on Oct 27, 2026

    @deanrie

    Hey @dameronma-ma, this survived the rewrite in #977. The files you name are gone, but the same shape is in scripts/run.ts on main 164ced1: findTlc returns TLA2TOOLS and JAVA exactly as given (line 195), and runJava spawns java with cwd set to the fresh temp folder (line 296), so a relative -cp is resolved against $TMPDIR/statechart-*/ and a relative JAVA with a slash is looked up there too.

    Your repro adapted to the new entry point (statechart Spec.tla --out DIR, Node 25.9, macOS):

    TLA2TOOLS=tools/tla2tools.jar statechart Spec.tla --out out1
    SANY could not read Spec.tla (exit 1):
    java runs in: $TMPDIR/statechart-Pc5OaK/statechart-Jz7wRH
    jar tools/tla2tools.jar: not found
    
    TLA2TOOLS=$PWD/tools/tla2tools.jar statechart Spec.tla --out out2
    java runs in: $TMPDIR/statechart-onBAXJ/statechart-mKJ0xm
    jar /…/tools/tla2tools.jar: found
    

    The message now comes from the SANY step rather than TLC, since that is the first java call, but the cause is the same. path.resolve() on both values in findTlc when they contain a path separator would close it; the mise branch already returns absolute paths.

  2. kairan commented on Oct 31, 2026

    @kairan

    Confirming from our side on macOS (Node 25.x): still reproducible on main at 4dd1d05 with the current entry point.

    We use the statechart skill from a user-level install (npx skills / ~/.agents/skills) when redrawing NapTap sleep charts. Setting TLA2TOOLS=tools/tla2tools.jar (relative to the cwd) fails because runJava uses cwd: dir under $TMPDIR/statechart-*/, so the relative -cp jar is not found. An absolute TLA2TOOLS=$PWD/tools/tla2tools.jar works.

    Same minimal repro as @deanrie’s comment, adapted to statechart Spec.tla --out out:

    mkdir repro && cd repro && mkdir tools && touch tools/tla2tools.jar
    # fake-java that prints PWD and whether the -cp path exists (same as issue body)
    …
    TLA2TOOLS=tools/tla2tools.jar statechart Spec.tla --out out1   # jar not found
    TLA2TOOLS=$PWD/tools/tla2tools.jar statechart Spec.tla --out out2   # ok

    We closed kairan/NapTap#110 (vendoring the skill) partly because this upstream behavior makes a repo-local relative jar path unreliable unless findTlc resolves env paths against the caller’s cwd before spawning Java.

    Would be great if findTlc returned path.resolve(cwd, TLA2TOOLS) (and similarly for relative JAVA with a slash) when env overrides are set.

  3. Ehsan-hash commented on Oct 31, 2026

    @Ehsan-hash
    Contributor

    Thanks @kairan for confirming this with the current entry point. #1017 addresses the same case: it resolves relative TLA2TOOLS and path-shaped JAVA values against the caller's directory before Java starts in the temporary directory. It is still awaiting maintainer review, so using an absolute path remains the workaround on main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions