diff --git a/.github/workflows/pr-lint.yml b/.github/workflows/pr-lint.yml
new file mode 100644
index 0000000..ee6160a
--- /dev/null
+++ b/.github/workflows/pr-lint.yml
@@ -0,0 +1,38 @@
+name: PR Lint
+
+on:
+ pull_request:
+ types: [opened, edited, synchronize, reopened]
+
+permissions:
+ pull-requests: read
+
+jobs:
+ conventional-commits:
+ name: Conventional commit title
+ runs-on: ubuntu-latest
+ steps:
+ - name: Validate PR title follows Conventional Commits
+ env:
+ PR_TITLE: ${{ github.event.pull_request.title }}
+ run: |
+ # Conventional Commits pattern: type(scope)!: description
+ # Types: feat, fix, docs, style, refactor, perf, test, chore, ci, build, revert
+ PATTERN='^(feat|fix|docs|style|refactor|perf|test|chore|ci|build|revert)(\(.+\))?!?: .{3,}'
+ if echo "$PR_TITLE" | grep -qE "$PATTERN"; then
+ echo "✅ PR title follows Conventional Commits format: $PR_TITLE"
+ else
+ echo "❌ PR title does not follow Conventional Commits format."
+ echo ""
+ echo "Expected format: type(scope): description"
+ echo "Examples:"
+ echo " feat(storage): add blob compression"
+ echo " fix(sync): handle disconnected peers gracefully"
+ echo " docs: update CONTRIBUTING guide"
+ echo " chore(deps): bump @plures/design-dojo to 0.10.6"
+ echo ""
+ echo "Valid types: feat, fix, docs, style, refactor, perf, test, chore, ci, build, revert"
+ echo ""
+ echo "Got: $PR_TITLE"
+ exit 1
+ fi
diff --git a/web/svelte/package-lock.json b/web/svelte/package-lock.json
index 555892a..6bf2aab 100644
--- a/web/svelte/package-lock.json
+++ b/web/svelte/package-lock.json
@@ -9,6 +9,7 @@
"version": "0.0.1",
"dependencies": {
"@monaco-editor/loader": "^1.5.0",
+ "@plures/design-dojo": "^0.10.6",
"cytoscape": "^3.29.3",
"cytoscape-cola": "^2.5.1",
"cytoscape-cose-bilkent": "^4.1.0",
@@ -561,7 +562,6 @@
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
@@ -572,7 +572,6 @@
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
@@ -583,7 +582,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
@@ -593,14 +591,12 @@
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.31",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
@@ -662,6 +658,20 @@
"state-local": "^1.0.6"
}
},
+ "node_modules/@plures/design-dojo": {
+ "version": "0.10.6",
+ "resolved": "https://registry.npmjs.org/@plures/design-dojo/-/design-dojo-0.10.6.tgz",
+ "integrity": "sha512-hGNgrKwAwbQsP5WeVC5faR/hF/5mTBxp0+9TSJAAxrLlaakMGeIig2k9WMDe6XIjzGUr4CHZ9njo5Sxb5XK/pQ==",
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.9.0",
+ "svelte": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@opentelemetry/api": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.59.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
@@ -1016,7 +1026,6 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.6.tgz",
"integrity": "sha512-4awhxtMh4cx9blePWl10HRHj8Iivtqj+2QdDCSMDzxG+XKa9+VCNupQuCuvzEhYPzZSrX+0gC+0lHA/0fFKKQQ==",
- "dev": true,
"license": "MIT",
"peerDependencies": {
"acorn": "^8.9.0"
@@ -1065,21 +1074,18 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
- "dev": true,
"license": "MIT"
},
"node_modules/@types/trusted-types": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
- "dev": true,
"license": "MIT"
},
"node_modules/acorn": {
"version": "8.15.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
- "dev": true,
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
@@ -1109,7 +1115,6 @@
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz",
"integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==",
- "dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
@@ -1119,7 +1124,6 @@
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
- "dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">= 0.4"
@@ -1129,7 +1133,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -1281,7 +1284,6 @@
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.3.tgz",
"integrity": "sha512-nc7XjUU/2Lb+SvEFVGcWLiKkzfw8+qHI7zn8WYXKkLMgfGSHbgCEaR6bJpev8Cm6Rmrb19Gfd/tZvGqx9is3wg==",
- "dev": true,
"license": "MIT"
},
"node_modules/esbuild": {
@@ -1330,14 +1332,12 @@
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
- "dev": true,
"license": "MIT"
},
"node_modules/esrap": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.3.tgz",
"integrity": "sha512-8fOS+GIGCQZl/ZIlhl59htOlms6U8NvX6ZYgYHpRU/b6tVSh3uHkOHZikl3D4cMbYM0JlpBe+p/BkZEi8J9XIQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
@@ -1413,7 +1413,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
"integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.6"
@@ -1436,7 +1435,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
- "dev": true,
"license": "MIT"
},
"node_modules/lodash": {
@@ -1449,7 +1447,6 @@
"version": "0.30.21",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.5"
@@ -1618,7 +1615,6 @@
"version": "5.53.5",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.53.5.tgz",
"integrity": "sha512-YkqERnF05g8KLdDZwZrF8/i1eSbj6Eoat8Jjr2IfruZz9StLuBqo8sfCSzjosNKd+ZrQ8DkKZDjpO5y3ht1Pow==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/remapping": "^2.3.4",
@@ -1777,7 +1773,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz",
"integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==",
- "dev": true,
"license": "MIT"
}
}
diff --git a/web/svelte/package.json b/web/svelte/package.json
index 59884af..b98aec1 100644
--- a/web/svelte/package.json
+++ b/web/svelte/package.json
@@ -22,6 +22,7 @@
},
"dependencies": {
"@monaco-editor/loader": "^1.5.0",
+ "@plures/design-dojo": "^0.10.6",
"cytoscape": "^3.29.3",
"cytoscape-cola": "^2.5.1",
"cytoscape-cose-bilkent": "^4.1.0",
diff --git a/web/svelte/src/App.svelte b/web/svelte/src/App.svelte
index e9dab0a..2bb8157 100644
--- a/web/svelte/src/App.svelte
+++ b/web/svelte/src/App.svelte
@@ -1,6 +1,9 @@
-