Skip to content

Add back pre-2025-11-28 old format import support#8556

Open
kube wants to merge 13 commits intomainfrom
cf/petrinaut-old-format-support
Open

Add back pre-2025-11-28 old format import support#8556
kube wants to merge 13 commits intomainfrom
cf/petrinaut-old-format-support

Conversation

@kube
Copy link
Collaborator

@kube kube commented Mar 17, 2026

🌟 What is the purpose of this PR?

Re-adds support for importing SDCPN files saved in the pre-2025-11-28 format, which used different field names (type instead of colorId, differentialEquationCode instead of differentialEquationId, iconId instead of iconSlug, etc.).

🔗 Related links

🔍 What does this change?

  • Adds old-format.ts — a single consolidated file containing the Zod schema, types, and conversion logic for the pre-2025-11-28 format (previously spread across 4 files)
  • Integrates as last-resort fallback in parseSDCPNFile — tried after versioned and legacy formats both fail

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • does not modify any publishable blocks or libraries, or modifications do not need publishing

📜 Does this require a change to the docs?

The changes in this PR:

  • are internal and do not require a docs change

🕸️ Does this require a change to the Turbo Graph?

The changes in this PR:

  • do not affect the execution graph

❓ How to test this?

  1. Export a net in the current format
  2. Manually edit the JSON to use old field names (type instead of colorId, etc.)
  3. Import — should successfully parse and convert

kube and others added 11 commits March 17, 2026 22:05
- Move file format code into `src/file-format/` (export, import, remove-visual-info, old-formats)
- Replace manual type guards with Zod schemas for import validation, matching clipboard types pattern
- Add versioned file format envelope (version, meta.generator) to exports
- Fix stale closure bug: run ELK layout before createNewNet so positions are baked into the data
- Add `onlyMissingPositions` option to calculateGraphLayout for partial re-layout
- Add ImportErrorDialog showing Zod validation errors with "Create empty net" fallback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Zod schema required iconSlug and displayColor on color types, but
these fields are stripped by "export without visual info". Make them
optional in the schema and fill defaults on import, matching how
missing x/y positions are already handled.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move old format Zod schema into old-formats/pre-2025-11-28/
- Integrate old format parsing into parseSDCPNFile so pre-2025-11-28
  files are validated and converted during import (previously dead code)
- Reject versioned files from legacy fallback path to prevent silently
  accepting unsupported future versions
- Remove dead convertOldFormatToSDCPN call from editor-view
- Remove unnecessary useCallback (React Compiler handles memoization)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move the unsupported-version rejection from a Zod .refine() (which
never worked because z.object() strips unknown keys first) into
parseSDCPNFile where we can inspect the raw data. Remove unused
SDCPNFileFormat type export.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Cap Open submenu height using --available-height CSS var
- Sort Open menu by most recently updated net
- Clean up empty nets from storage when switching away
- Update lastUpdated timestamp on net mutation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix export spread order so explicit title cannot be overwritten
- Fix stale closure in loadPetriNet by moving check inside updater
- Show actual Zod errors for supported version with invalid structure
- Split hasMissingPositions from type visual info check
- Remove pre-2025-11-28 old format import support
- Add 19 unit tests for parseSDCPNFile

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove old-formats directory and all related exports/types
- Simplify localStorage types (no more OldFormat union)
- Remove old format conversion logic from init effect
- Remove onlyMissingPositions from calculateGraphLayout, always do full layout

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link

vercel bot commented Mar 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hash Ready Ready Preview, Comment Mar 17, 2026 11:38pm
petrinaut Ready Ready Preview, Comment Mar 17, 2026 11:38pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
hashdotdesign Ignored Ignored Preview Mar 17, 2026 11:38pm
hashdotdesign-tokens Ignored Ignored Preview Mar 17, 2026 11:38pm

@cursor
Copy link

cursor bot commented Mar 17, 2026

PR Summary

Medium Risk
Adds another JSON parsing fallback path and field-mapping conversion during SDCPN import, which could accept previously-invalid inputs or mis-map fields if the old schema is incomplete. Impact is limited to client-side file import behavior and data shape normalization.

Overview
Re-adds support for importing pre-2025-11-28 SDCPN JSON by introducing old-format.ts, which validates the legacy field names via a Zod schema and converts them to the current SDCPN shape (e.g. typecolorId, differentialEquationCode.refIddifferentialEquationId, iconIdiconSlug).

parseSDCPNFile now tries this old-format parse as a last-resort fallback after versioned and legacy schemas fail, returning the converted SDCPN on success.

Written by Cursor Bugbot for commit 517e9c2. This will update automatically on new commits. Configure here.

@github-actions github-actions bot added area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team labels Mar 17, 2026
@augmentcode
Copy link

augmentcode bot commented Mar 17, 2026

🤖 Augment PR Summary

Summary: Restores import compatibility for SDCPN JSON files saved before 2025-11-28 by adding an explicit old-format schema + converter.

Changes:

  • Added old-format.ts containing Zod validation and conversion logic for pre-2025-11-28 field names
  • Updated parseSDCPNFile to attempt this old format as a last-resort fallback after versioned + legacy parsing fail

Technical Notes: Conversion maps renamed keys (e.g. typecolorId, iconIdiconSlug) and drops obsolete sizing fields during normalization.

🤖 Was this summary useful? React with 👍 or 👎

Copy link

@augmentcode augmentcode bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 3 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

}

// Try the pre-2025-11-28 old format (different field names)
const oldFormat = oldFormatFileSchema.safeParse(data);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are strong unit tests for the versioned/legacy parsing paths, but nothing that exercises this pre-2025-11-28 fallback. Without a test, regressions in oldFormatFileSchema/convertOldFormatToSDCPN (field renames, nullability) could slip through unnoticed.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

return {
ok: true,
sdcpn: converted,
hadMissingPositions: false,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This old-format branch hardcodes hadMissingPositions: false and returns converted without running through fillMissingVisualInfo. If old-format files can omit positions or type visual fields (like the legacy/versioned schemas allow), this could change import behavior in subtle ways—was that intentional?

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

dynamicsEnabled: z.boolean(),
differentialEquationCode: z.object({ refId: z.string() }).nullable(),
visualizerCode: z.string().optional(),
x: z.number(),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oldPlaceSchema requires x/y (and oldColorSchema requires iconId/colorCode), but the importer generally supports files exported without visual info by defaulting these later. If old-format exports could also omit this visual data, this schema may reject otherwise-importable files—does the old format guarantee these fields are always present?

Severity: medium

Other Locations
  • libs/@hashintel/petrinaut/src/file-format/old-format.ts:58
  • libs/@hashintel/petrinaut/src/file-format/old-format.ts:59
  • libs/@hashintel/petrinaut/src/file-format/old-format.ts:43
  • libs/@hashintel/petrinaut/src/file-format/old-format.ts:44

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

hadMissingPositions: false,
};
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error message shows irrelevant legacy format diagnostics

Low Severity

When all three parse attempts (versioned, legacy, old format) fail, the final error message still reports legacy.error.issues. A user providing a nearly-valid old-format file (e.g., with a minor field error) sees misleading diagnostics referencing legacy field names like colorId instead of the old-format names (type, differentialEquationCode) that their file actually uses. The insertion of the old-format fallback between the legacy failure and this error return changed the semantic context of the message without updating it.

Additional Locations (1)
Fix in Cursor Fix in Web

kube and others added 2 commits March 18, 2026 00:29
Consolidated old format schema, types, and conversion into a single
file (old-format.ts) and integrated it as a last-resort fallback in
parseSDCPNFile, after versioned and legacy formats fail.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@kube kube force-pushed the cf/petrinaut-old-format-support branch from 0d50cc9 to 517e9c2 Compare March 17, 2026 23:30
@graphite-app graphite-app bot requested a review from a team March 17, 2026 23:49
Base automatically changed from cf/petrinaut-better-export-import to main March 18, 2026 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team

Development

Successfully merging this pull request may close these issues.

1 participant