Repository navigation
fix(pstack): bring the statechart skill up to date with six fixes - #776
Merged
Merged
Conversation
TLC 1.8.0 extracts the standard modules into its own folder inside java.io.tmpdir, so the statechart test that checks each TLC run's temp folder now accepts any path under it. Co-authored-by: lauren <poteto@users.noreply.github.com>
- Stop when the label map reads a variable or field that the --fixed or --against model does not have, in place of giving it the current model's start value. - Add --config, --fixed-config, and --against-config. The agreed spec is never checked with the config of the code model, and a missing config error lists the configs beside the spec. - Mark a rule that the agreed config does not check as "not checked" in the stories, in place of saying the agreed spec keeps it. Co-authored-by: lauren <poteto@users.noreply.github.com>
- When TLC finds a broken rule and then throws a Java exception while it reports it, keep the paths TLC printed, mark the rule broken, and warn that the charts can miss states. - On a filesystem that cannot rename into the output folder (ENOSYS, EXDEV, EISDIR, such as FUSE mounts), copy the files into place. - Write the label map scaffold before TLC runs, and check the inputs again before --png renders. Co-authored-by: lauren <poteto@users.noreply.github.com>
…s in statechart - TLC checks each rule with one worker per CPU. When a rule is broken, TLC checks it again with one worker, which finds the shortest bug paths, the same on every run. The command prints how many times TLC ran and how long that took. - Each PROPERTY in the config gets its own TLC run, and --expect-broken accepts it. The charts draw only INVARIANT rules, so a broken PROPERTY names TLC's counterexample file. pstack finds TLC through TLA2TOOLS and JAVA only, so the repo-pinned TLC install and its tests are not part of this change. Co-authored-by: lauren <poteto@users.noreply.github.com>
…cited conditions in statechart - With --against, each story says whether a config beside the agreed spec expects TLC to break the bug's rule, from its "\* expect:" and "\* module:" lines, and summary.json records it. The command warns when no config has an expect line for that module. - With --fixed or --against, the command lists each condition of an action that no comment ties to a file and line, as in \* pay.ts:120, when a rule holds, and summary.json records them. - SKILL.md asks for those citations, defines a valid replay, and asks the hand-off to say whether the spec already lists each bug. Co-authored-by: lauren <poteto@users.noreply.github.com>
…RIANT and PROPERTY - A rule that the config lists as both INVARIANT and PROPERTY gets one TLC run, as the INVARIANT, so its bug is charted once. - Report a broken PROPERTY in each form TLC uses: an invariant for [](P), an action property for [][A]_v, a property of the initial state for a bare predicate, and a temporal property otherwise. - The test that kills a run no longer fails when the process has already exited (ESRCH). Co-authored-by: lauren <poteto@users.noreply.github.com>
cursor
Bot
force-pushed
the
lauren/statechart-fixes-port-bf8f
branch
from
October 22, 2026 16:50
d2c7bf7 to
52faf12
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
Reviewed by Cursor Bugbot for commit 52faf12. Configure here.
| from.push(`--${other.role}-dot`, other.dot, "--spec", other.spec); | ||
| from.push(...other.traces.flatMap((t) => [`--${other.role}-traces`, t.file])); | ||
| if (other.traces.length) | ||
| from.push(`--${other.role}-rules`, other.traces.map((t) => t.rule).join(",")); |
There was a problem hiding this comment.
PROPERTY-only rules marked unchecked
Medium Severity · Logic Bug
--against-rules and warnUnchecked look only at INVARIANT results. A rule the agreed spec actually checks as a PROPERTY is still treated as unchecked, so stories say the spec does not check it even though this run already printed that it holds or is broken.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit 52faf12. Configure here.
kpeez
added a commit
to kpeez/agent-toolbox
that referenced
this pull request
Oct 22, 2026
…pt rules (#198) ## Summary Sync swe with pstack `d457567..7698375` (cursor/plugins#729, cursor/plugins#741, cursor/plugins#776). swe 1.21.19. - Add `/swe:statechart`, imported verbatim with its Node scripts. All 12 files are class `copied`, so later syncs 3-way merge them. - `typescript-best-practices` now loads on its own: `paths: ["**/*.ts", "**/*.tsx"]` in Claude Code, description match in Codex. It was user-invoked only. - Add `agents/openai.yaml` to both formal-verification skills, so Codex treats them as user-invoked like every other such skill. - Move the pin and the README Credits link to `7698375`. ## Step 4 review - `sharpen/SKILL.md`: skipped. Upstream now returns only the rewritten prompt. `go-deeper` keeps the four questions, runs the rewritten task, and already has a prompt-only mode. - guide 02, guide 10, poteto-help recipes: skipped. Sharpen wording only. - guide 06, poteto-help, README: ported the statechart section and rows. ## Step 5 - `skills/statechart/`: imported (Kyle approved). ## Verification - `pstack_sync.py check`: 184 pinned files covered. - `node --test scripts/test/statechart.test.mjs` with TLC 1.8.0: 66 of 67 pass. One upstream failure: TLC 1.8.0 prints `Temporal property X was violated.`, and `lib.mjs` only matches the older `Temporal properties were violated.` Not patched, because the files stay verbatim. - `claude plugin validate --strict` on the root and `plugins/swe`: pass. - `skill_eval.py validate`: pass. Relative links in changed Markdown resolve. Manifests and `openai.yaml` files parse.
caelaxie
added a commit
to pstack-ports/devin-pstack
that referenced
this pull request
Oct 23, 2026
<!-- CURSOR_AGENT_PR_BODY_BEGIN --> synced to [`4ec7ffa`](cursor/plugins@4ec7ffa). compared `88d4751..4ec7ffa` for `pstack/`. later commits on upstream `main` through [`9b93e81`](cursor/plugins@9b93e81) do not touch `pstack/`. version is `0.15.30` in `plugin.json`, `.devin-plugin/plugin.json`, and the readme marker. ported: - [`eb4db2b`](cursor/plugins@eb4db2b) ([#741](cursor/plugins#741)) add the statechart skill. guide page 6, poteto-help, and the readme skill table match. slash commands keep the `/pstack:` prefix. `disable-model-invocation: true` stays `triggers: [user]`. - [`7698375`](cursor/plugins@7698375) ([#776](cursor/plugins#776)) six fixes to the statechart skill. scripts copied verbatim. - [`4ec7ffa`](cursor/plugins@4ec7ffa) ([#779](cursor/plugins#779)) delete statechart comments that repeat the code, and rename helpers. the version bumps to `0.15.30`. the same bump is in `.devin-plugin/plugin.json` and the readme marker, which is where this repo records the version. skipped: - `harness/pstack/claude-code/` copies in [#741](cursor/plugins#741), [#776](cursor/plugins#776), and [#779](cursor/plugins#779). this port does not carry the generated claude code tree. - [#741](cursor/plugins#741) `pstack/.cursor-plugin/plugin.json`. cursor packaging. the version bump lands in `.devin-plugin/plugin.json` instead. - [#741](cursor/plugins#741) `.github/workflows/validate-plugins.yml` test step. that workflow belongs to the cursor/plugins monorepo and also checks generated harness trees. this repo's ci is separate, so the step was not copied. `node --test skills/statechart/scripts/test/*.test.mjs` passed locally (67 tests, with tlc). harness proof (install, `devin plugins list`, exercising `/pstack:statechart` and `/pstack:poteto-mode`) will follow as a comment. the devin cli can't log in from this cloud environment. <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-00f3aebc-53ad-54ad-9327-63073f2102cb?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-00f3aebc-53ad-54ad-9327-63073f2102cb&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Kaitian Xie <caelaxie@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Why
The statechart skill has six fixes since the version in pstack. Before them, a run can give a wrong chart or a wrong exit code and not say so: a second model with different variables, a crash in TLC, or a rule that the config lists as both
INVARIANTandPROPERTY. A failed publish can lose the run's work. APROPERTYline stays in every TLC run, so a brokenPROPERTYis reported as a break of anINVARIANTthat holds, and--expect-brokendoes not accept aPROPERTY. This change brings the skill up to its current version.What changed
Each commit is one fix, in the order in which the fixes landed:
test(pstack): accept Naturals.tla anywhere under the run's temp folder. TLC 1.8.0 writes the standard modules one folder deeper inside the run's temp folder. The test accepts any path under that folder. This is the one failure that feat(pstack): add the statechart skill to draw TLA+ models as charts #741 found with a TLC nightly build.fix(pstack): stop three silent wrong outputs in statechart--fixedor--againstmodel does not have. Before, it gave that variable the current model's start value.--config,--fixed-config, and--against-config. The agreed spec is never checked with the code model's config. When a config does not exist, the error lists the configs beside the spec.fix(pstack): keep statechart work when TLC or publishing failsENOSYS,EXDEV, orEISDIR, as on FUSE mounts), the command copies the files into place.--pngrenders.feat(pstack): check every rule with all CPUs, and check PROPERTY rules in statechartPROPERTYgets its own TLC run, and--expect-brokenaccepts it. The charts draw onlyINVARIANTrules, so a brokenPROPERTYnames TLC's counterexample file.feat(pstack): say whether the agreed spec lists each bug, and flag uncited conditions in statechart--against, each story says whether a config beside the agreed spec expects TLC to break the bug's rule, from the config's\* expect:and\* module:lines.summary.jsonrecords this.--fixedor--against, the command lists each condition of an action that has no\* file:linecomment, when a rule holds. A rule can hold only because the model waits for a condition that the code does not check.fix(pstack): report the bug when a config lists one rule as both INVARIANT and PROPERTYINVARIANT.PROPERTYthat TLC prints: invariant, action property, property of the initial state, and temporal property.Adapted or left out
TLA2TOOLSandJAVA, as in feat(pstack): add the statechart skill to draw TLA+ models as charts #741. The source of item 4 also installs a repo-pinned TLC on demand, with tests for that. This repo pins no TLC version, so that part is not in this change. The help text and the "no TLC" message stay as in feat(pstack): add the statechart skill to draw TLA+ models as charts #741.Blast radius
Only
pstack/skills/statechart/and its generated copy inharness/pstack/claude-code/skills/statechart/change. Nothing outside the skill imports its scripts. The pstack version stays at 0.15.30. A separate PR bumps it.Verification
generate-pstack-harness-trees.mjs --check.INVARIANT PaidMeansChargedandPROPERTY ChargedAtMostOnceon the payment model below, the current skill says "PaidMeansCharged is broken". With this change, it says thatPaidMeansChargedholds andChargedAtMostOnceis broken, and it names the counterexample file.validate-plugins.mjs,check-pstack-docs.mjs, andgenerate-pstack-harness-trees.mjs --checkpass. A scan for internal paths, names, and model ids finds 0 hits in the patch.from-spec PayCode.tla --against Pay.tla --against-config PayChecked.cfg --expect-broken NoDoubleCharge,ChargedAtMostOncefirst writes the mapping scaffold and exits 2. After the labels are filled in, it exits 0. It finds the double charge, checksNoDoubleChargeonce although the config lists it as bothINVARIANTandPROPERTY, and says thatPayRetry.cfgbeside the agreed spec expects this bug. It also flags the one condition that has no code citation, and publishes the folder by copy.