@planu/cli 5.3.24 → 5.3.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/engine/planu-core.darwin-arm64.node.manifest.json +7 -7
  3. package/dist/engine/planu-core.darwin-arm64.node.sbom.json +4 -4
  4. package/dist/engine/planu-core.darwin-x64.node.manifest.json +7 -7
  5. package/dist/engine/planu-core.darwin-x64.node.sbom.json +4 -4
  6. package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +7 -7
  7. package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +4 -4
  8. package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +7 -7
  9. package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +4 -4
  10. package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +7 -7
  11. package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +4 -4
  12. package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +7 -7
  13. package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +4 -4
  14. package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +7 -7
  15. package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +4 -4
  16. package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +7 -7
  17. package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +4 -4
  18. package/dist/engine/safety/assert-within-project.d.ts +2 -0
  19. package/dist/engine/safety/assert-within-project.js +14 -0
  20. package/dist/storage/spec-store.js +6 -0
  21. package/dist/tools/export-spec.js +18 -15
  22. package/dist/tools/schema-generator-handler.js +3 -0
  23. package/dist/tools/spec-export-handler.js +21 -8
  24. package/dist/tools/storage-bundle-handler.js +35 -4
  25. package/package.json +9 -9
  26. package/planu-native.json +1 -1
  27. package/planu-plugin.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [5.3.25] - 2026-08-18
2
+
3
+ ### Bug Fixes
4
+ - fix(spec-1562,1568): contain client output paths across all writers and default spec array fields
5
+
6
+
1
7
  ## [5.3.24] - 2026-08-18
2
8
 
3
9
  ### Bug Fixes
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
- "cliVersion": "5.3.24",
4
- "engineVersion": "5.3.24",
5
- "buildId": "1-5.3.24-aarch64-apple-darwin",
3
+ "cliVersion": "5.3.25",
4
+ "engineVersion": "5.3.25",
5
+ "buildId": "1-5.3.25-aarch64-apple-darwin",
6
6
  "protocolAbi": 1,
7
7
  "capabilityAbi": 2,
8
8
  "nodeApiAbi": 4,
@@ -17,15 +17,15 @@
17
17
  "platform": "darwin",
18
18
  "arch": "arm64",
19
19
  "libc": null,
20
- "artifactSha256": "2df1b275f0d3987ef6fa75a7d46b274c798aece674ff001ab7fb7af169cfc1f3",
20
+ "artifactSha256": "f029e4a206f892b1ae565ef2acc29db91fe532fc2ec1c1965b7abf705471d192",
21
21
  "sbom": {
22
22
  "format": "CycloneDX-1.5",
23
23
  "path": "planu-core.darwin-arm64.node.sbom.json",
24
- "sha256": "9899ebee8d32c9b58992bd9a95647e85bd86ac76ee64c34f534f5ce18ec33c2c"
24
+ "sha256": "3e89bd16fa165d93341924d260832fd48754b9e3a5827507adc5377cdcc76026"
25
25
  },
26
26
  "provenance": {
27
27
  "builder": "scripts/build-rust-local.sh",
28
- "sourceCommit": "888ffb9504055a10ea38d0c31dd0c9881139e88c",
28
+ "sourceCommit": "d93395c02e0224530b5e52ffd7ec3a64ec462296",
29
29
  "sourceTreeDirty": false,
30
30
  "sourceDateEpoch": 1,
31
31
  "rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
@@ -34,6 +34,6 @@
34
34
  "signature": {
35
35
  "algorithm": "Ed25519",
36
36
  "keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
37
- "value": "0/ir1zotrdZMQ3fKgbpHGoU6fXXo8qZp+Ugs18Oslbxb6vVvRBuj2UoKofDsyPGjx2mHadvTUPX42B/EZd1SAg=="
37
+ "value": "C/IAeXfh4rVpzrLOYmcbO6TRbZBAXAf7UxAw/HWAPV1BY5xpH2bP9dGNcYkTu4HkWeFhLz+ePFeMzdGbDvaQDg=="
38
38
  }
39
39
  }
@@ -4,14 +4,14 @@
4
4
  "version": 1,
5
5
  "metadata": {
6
6
  "component": {
7
- "bom-ref": "pkg:cargo/planu-core@5.3.24",
7
+ "bom-ref": "pkg:cargo/planu-core@5.3.25",
8
8
  "type": "library",
9
9
  "name": "planu-core",
10
- "version": "5.3.24",
10
+ "version": "5.3.25",
11
11
  "hashes": [
12
12
  {
13
13
  "alg": "SHA-256",
14
- "content": "2df1b275f0d3987ef6fa75a7d46b274c798aece674ff001ab7fb7af169cfc1f3"
14
+ "content": "f029e4a206f892b1ae565ef2acc29db91fe532fc2ec1c1965b7abf705471d192"
15
15
  }
16
16
  ]
17
17
  }
@@ -1106,7 +1106,7 @@
1106
1106
  "dependsOn": []
1107
1107
  },
1108
1108
  {
1109
- "ref": "pkg:cargo/planu-core@5.3.24",
1109
+ "ref": "pkg:cargo/planu-core@5.3.25",
1110
1110
  "dependsOn": [
1111
1111
  "pkg:cargo/core-foundation@0.10.1",
1112
1112
  "pkg:cargo/hmac@0.12.1",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
- "cliVersion": "5.3.24",
4
- "engineVersion": "5.3.24",
5
- "buildId": "1-5.3.24-x86_64-apple-darwin",
3
+ "cliVersion": "5.3.25",
4
+ "engineVersion": "5.3.25",
5
+ "buildId": "1-5.3.25-x86_64-apple-darwin",
6
6
  "protocolAbi": 1,
7
7
  "capabilityAbi": 2,
8
8
  "nodeApiAbi": 4,
@@ -17,15 +17,15 @@
17
17
  "platform": "darwin",
18
18
  "arch": "x64",
19
19
  "libc": null,
20
- "artifactSha256": "136a1351ca4278942b7c5b0130eb7cdfee35b85b667888d4041bffcd0b213ace",
20
+ "artifactSha256": "74de1ccd509b59583491f317bacdd465244cd04e057113e8c221538b7cf6e212",
21
21
  "sbom": {
22
22
  "format": "CycloneDX-1.5",
23
23
  "path": "planu-core.darwin-x64.node.sbom.json",
24
- "sha256": "3f8f6cace3e98634bc5fb5b8debb71c45507b890b4aa918437358cf16b55d776"
24
+ "sha256": "d9878d394147e21656556756b3c0bd6a4a4bf7384af2563cd5876b2edff6c702"
25
25
  },
26
26
  "provenance": {
27
27
  "builder": "scripts/build-rust-local.sh",
28
- "sourceCommit": "888ffb9504055a10ea38d0c31dd0c9881139e88c",
28
+ "sourceCommit": "d93395c02e0224530b5e52ffd7ec3a64ec462296",
29
29
  "sourceTreeDirty": false,
30
30
  "sourceDateEpoch": 1,
31
31
  "rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
@@ -34,6 +34,6 @@
34
34
  "signature": {
35
35
  "algorithm": "Ed25519",
36
36
  "keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
37
- "value": "Aj0I1f16YmStyyCshvbh7h+leFhLBtGAOv5Jy8lCH5oXVc2RBirqfHNAU/4yQ1vFu3JTl3H5hIaa1Kc1LwQtCg=="
37
+ "value": "rnR72pEzRclpCkRqsxQmEKwC4OSaIQXLwUNq8n1IGqWSdZK3hw19Qd8upadJOjylbjUcTlDCQoNUWj3w/dY1BA=="
38
38
  }
39
39
  }
@@ -4,14 +4,14 @@
4
4
  "version": 1,
5
5
  "metadata": {
6
6
  "component": {
7
- "bom-ref": "pkg:cargo/planu-core@5.3.24",
7
+ "bom-ref": "pkg:cargo/planu-core@5.3.25",
8
8
  "type": "library",
9
9
  "name": "planu-core",
10
- "version": "5.3.24",
10
+ "version": "5.3.25",
11
11
  "hashes": [
12
12
  {
13
13
  "alg": "SHA-256",
14
- "content": "136a1351ca4278942b7c5b0130eb7cdfee35b85b667888d4041bffcd0b213ace"
14
+ "content": "74de1ccd509b59583491f317bacdd465244cd04e057113e8c221538b7cf6e212"
15
15
  }
16
16
  ]
17
17
  }
@@ -1106,7 +1106,7 @@
1106
1106
  "dependsOn": []
1107
1107
  },
1108
1108
  {
1109
- "ref": "pkg:cargo/planu-core@5.3.24",
1109
+ "ref": "pkg:cargo/planu-core@5.3.25",
1110
1110
  "dependsOn": [
1111
1111
  "pkg:cargo/core-foundation@0.10.1",
1112
1112
  "pkg:cargo/hmac@0.12.1",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
- "cliVersion": "5.3.24",
4
- "engineVersion": "5.3.24",
5
- "buildId": "1-5.3.24-aarch64-unknown-linux-gnu",
3
+ "cliVersion": "5.3.25",
4
+ "engineVersion": "5.3.25",
5
+ "buildId": "1-5.3.25-aarch64-unknown-linux-gnu",
6
6
  "protocolAbi": 1,
7
7
  "capabilityAbi": 2,
8
8
  "nodeApiAbi": 4,
@@ -16,15 +16,15 @@
16
16
  "platform": "linux",
17
17
  "arch": "arm64",
18
18
  "libc": "glibc",
19
- "artifactSha256": "5c16c2a04af25efc03e74eecfacaad43f5835dfb01f0a898f6d2b93efd9a3c33",
19
+ "artifactSha256": "3298a15365c6fcf78ff4f17273cefee80705f62d66297b5bf1e45e9e77941541",
20
20
  "sbom": {
21
21
  "format": "CycloneDX-1.5",
22
22
  "path": "planu-core.linux-arm64-gnu.node.sbom.json",
23
- "sha256": "48a3812ed288b4801a82bf40f37d02e48e014a90f58f7bc955c2b480749cd44e"
23
+ "sha256": "fe88f4bd3c03fdb6b2f5dcecab575bcdca01f2700e38bbf4b063a5c148eb9c69"
24
24
  },
25
25
  "provenance": {
26
26
  "builder": "scripts/build-rust-local.sh",
27
- "sourceCommit": "888ffb9504055a10ea38d0c31dd0c9881139e88c",
27
+ "sourceCommit": "d93395c02e0224530b5e52ffd7ec3a64ec462296",
28
28
  "sourceTreeDirty": false,
29
29
  "sourceDateEpoch": 1,
30
30
  "rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
@@ -33,6 +33,6 @@
33
33
  "signature": {
34
34
  "algorithm": "Ed25519",
35
35
  "keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
36
- "value": "ogNVi4bjUVYnZ3o32PbiLKjRM4FhpcRuLoWSBpHe+vMe/M+oL+aZAX3M86UdTHoxEtUm32rJJPBBXA3CpQzIBQ=="
36
+ "value": "rFZl0EaJjzy23IhkX8bq/yKJfWYjWEkKRE4yS6IQ2xlpCT16K7iGyM1y0r4RMor8sU9K5gHyxSSYGB0MmcRsBg=="
37
37
  }
38
38
  }
@@ -4,14 +4,14 @@
4
4
  "version": 1,
5
5
  "metadata": {
6
6
  "component": {
7
- "bom-ref": "pkg:cargo/planu-core@5.3.24",
7
+ "bom-ref": "pkg:cargo/planu-core@5.3.25",
8
8
  "type": "library",
9
9
  "name": "planu-core",
10
- "version": "5.3.24",
10
+ "version": "5.3.25",
11
11
  "hashes": [
12
12
  {
13
13
  "alg": "SHA-256",
14
- "content": "5c16c2a04af25efc03e74eecfacaad43f5835dfb01f0a898f6d2b93efd9a3c33"
14
+ "content": "3298a15365c6fcf78ff4f17273cefee80705f62d66297b5bf1e45e9e77941541"
15
15
  }
16
16
  ]
17
17
  }
@@ -1106,7 +1106,7 @@
1106
1106
  "dependsOn": []
1107
1107
  },
1108
1108
  {
1109
- "ref": "pkg:cargo/planu-core@5.3.24",
1109
+ "ref": "pkg:cargo/planu-core@5.3.25",
1110
1110
  "dependsOn": [
1111
1111
  "pkg:cargo/core-foundation@0.10.1",
1112
1112
  "pkg:cargo/hmac@0.12.1",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
- "cliVersion": "5.3.24",
4
- "engineVersion": "5.3.24",
5
- "buildId": "1-5.3.24-aarch64-unknown-linux-musl",
3
+ "cliVersion": "5.3.25",
4
+ "engineVersion": "5.3.25",
5
+ "buildId": "1-5.3.25-aarch64-unknown-linux-musl",
6
6
  "protocolAbi": 1,
7
7
  "capabilityAbi": 2,
8
8
  "nodeApiAbi": 4,
@@ -16,15 +16,15 @@
16
16
  "platform": "linux",
17
17
  "arch": "arm64",
18
18
  "libc": "musl",
19
- "artifactSha256": "8a4cd204fed117c35b4daea2d03d7f36c5ac2309967ed1d0f48e4291c19a705f",
19
+ "artifactSha256": "d6a25cf24a69de3409c46a2ae0c8f46a27e5906fb256371d3746bf56649048f4",
20
20
  "sbom": {
21
21
  "format": "CycloneDX-1.5",
22
22
  "path": "planu-core.linux-arm64-musl.node.sbom.json",
23
- "sha256": "812aeaa48a5c2d31b1b108a005eb47586f8a3cf48de44ee7a43b356d7626a286"
23
+ "sha256": "0e9cf4b53eeed5bf166ff88982155d90f6b766e6ab288d91a369e844a404a383"
24
24
  },
25
25
  "provenance": {
26
26
  "builder": "scripts/build-rust-local.sh",
27
- "sourceCommit": "888ffb9504055a10ea38d0c31dd0c9881139e88c",
27
+ "sourceCommit": "d93395c02e0224530b5e52ffd7ec3a64ec462296",
28
28
  "sourceTreeDirty": false,
29
29
  "sourceDateEpoch": 1,
30
30
  "rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
@@ -33,6 +33,6 @@
33
33
  "signature": {
34
34
  "algorithm": "Ed25519",
35
35
  "keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
36
- "value": "3w2XPj4GH8F/UdRBJMNWiOacR+v5h2H/aof6SqdJDADu5S2sGg0IEolD9m7sB3HE/ZgPL7iulY4KPckXGMNnAQ=="
36
+ "value": "MxlAtNKM78NgLWko4gNIASnqSrnFlqL03jxXpJkJoR7bh9kD7E2SzvIZeYkPrqFweKTvyyqLQlz3RCT4325+BA=="
37
37
  }
38
38
  }
@@ -4,14 +4,14 @@
4
4
  "version": 1,
5
5
  "metadata": {
6
6
  "component": {
7
- "bom-ref": "pkg:cargo/planu-core@5.3.24",
7
+ "bom-ref": "pkg:cargo/planu-core@5.3.25",
8
8
  "type": "library",
9
9
  "name": "planu-core",
10
- "version": "5.3.24",
10
+ "version": "5.3.25",
11
11
  "hashes": [
12
12
  {
13
13
  "alg": "SHA-256",
14
- "content": "8a4cd204fed117c35b4daea2d03d7f36c5ac2309967ed1d0f48e4291c19a705f"
14
+ "content": "d6a25cf24a69de3409c46a2ae0c8f46a27e5906fb256371d3746bf56649048f4"
15
15
  }
16
16
  ]
17
17
  }
@@ -1106,7 +1106,7 @@
1106
1106
  "dependsOn": []
1107
1107
  },
1108
1108
  {
1109
- "ref": "pkg:cargo/planu-core@5.3.24",
1109
+ "ref": "pkg:cargo/planu-core@5.3.25",
1110
1110
  "dependsOn": [
1111
1111
  "pkg:cargo/core-foundation@0.10.1",
1112
1112
  "pkg:cargo/hmac@0.12.1",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
- "cliVersion": "5.3.24",
4
- "engineVersion": "5.3.24",
5
- "buildId": "1-5.3.24-x86_64-unknown-linux-gnu",
3
+ "cliVersion": "5.3.25",
4
+ "engineVersion": "5.3.25",
5
+ "buildId": "1-5.3.25-x86_64-unknown-linux-gnu",
6
6
  "protocolAbi": 1,
7
7
  "capabilityAbi": 2,
8
8
  "nodeApiAbi": 4,
@@ -16,15 +16,15 @@
16
16
  "platform": "linux",
17
17
  "arch": "x64",
18
18
  "libc": "glibc",
19
- "artifactSha256": "a9158723fa6e3e5972ffc03b6115035c1f0dd6be8b109b4ae1f7f5dad54f9062",
19
+ "artifactSha256": "1d4bf6073483ae43635ac9815f566e323f03024d6156a5d6103df55933072caa",
20
20
  "sbom": {
21
21
  "format": "CycloneDX-1.5",
22
22
  "path": "planu-core.linux-x64-gnu.node.sbom.json",
23
- "sha256": "34a5c6540f4234a5ac3d4b3d1be2ff50e28b294161a4b4190996e28b3defc899"
23
+ "sha256": "b75911513d1837537c9913d9eaadfb6e3664709847e09e9850f05d24a9e17f96"
24
24
  },
25
25
  "provenance": {
26
26
  "builder": "scripts/build-rust-local.sh",
27
- "sourceCommit": "888ffb9504055a10ea38d0c31dd0c9881139e88c",
27
+ "sourceCommit": "d93395c02e0224530b5e52ffd7ec3a64ec462296",
28
28
  "sourceTreeDirty": false,
29
29
  "sourceDateEpoch": 1,
30
30
  "rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
@@ -33,6 +33,6 @@
33
33
  "signature": {
34
34
  "algorithm": "Ed25519",
35
35
  "keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
36
- "value": "Gz3e+x1vn4R0ppFCaBwO4vQH1RqrV3PvTp7/Zi6V0mu3u6o1GYmo7JrLvlmR4I34IWkfO+cG6Hk/Ls++j7dnBw=="
36
+ "value": "WzDGhTD3hlmreR0zaduJm5RHfqPVzQIjm4Y8X8XHaW9UpVirVllhvrg9A0wrL1Uiw+wrkqeAQAYdNcDcTmQBAg=="
37
37
  }
38
38
  }
@@ -4,14 +4,14 @@
4
4
  "version": 1,
5
5
  "metadata": {
6
6
  "component": {
7
- "bom-ref": "pkg:cargo/planu-core@5.3.24",
7
+ "bom-ref": "pkg:cargo/planu-core@5.3.25",
8
8
  "type": "library",
9
9
  "name": "planu-core",
10
- "version": "5.3.24",
10
+ "version": "5.3.25",
11
11
  "hashes": [
12
12
  {
13
13
  "alg": "SHA-256",
14
- "content": "a9158723fa6e3e5972ffc03b6115035c1f0dd6be8b109b4ae1f7f5dad54f9062"
14
+ "content": "1d4bf6073483ae43635ac9815f566e323f03024d6156a5d6103df55933072caa"
15
15
  }
16
16
  ]
17
17
  }
@@ -1106,7 +1106,7 @@
1106
1106
  "dependsOn": []
1107
1107
  },
1108
1108
  {
1109
- "ref": "pkg:cargo/planu-core@5.3.24",
1109
+ "ref": "pkg:cargo/planu-core@5.3.25",
1110
1110
  "dependsOn": [
1111
1111
  "pkg:cargo/core-foundation@0.10.1",
1112
1112
  "pkg:cargo/hmac@0.12.1",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
- "cliVersion": "5.3.24",
4
- "engineVersion": "5.3.24",
5
- "buildId": "1-5.3.24-x86_64-unknown-linux-musl",
3
+ "cliVersion": "5.3.25",
4
+ "engineVersion": "5.3.25",
5
+ "buildId": "1-5.3.25-x86_64-unknown-linux-musl",
6
6
  "protocolAbi": 1,
7
7
  "capabilityAbi": 2,
8
8
  "nodeApiAbi": 4,
@@ -16,15 +16,15 @@
16
16
  "platform": "linux",
17
17
  "arch": "x64",
18
18
  "libc": "musl",
19
- "artifactSha256": "165e48d9d7bb68965782b9f690af378cee9651c9c1b9ab31e6b9fa4bedad514a",
19
+ "artifactSha256": "e514123ce0f9194810a7735351dc4b07fa0247012e6409bc28e88f8cad001e8d",
20
20
  "sbom": {
21
21
  "format": "CycloneDX-1.5",
22
22
  "path": "planu-core.linux-x64-musl.node.sbom.json",
23
- "sha256": "101e2eca5854d33b36a9570a10e8f4816f43961ad899863110ba4d2596cf89dc"
23
+ "sha256": "b65fef60c2d7d93b54f6754185131fdf7983be8138c6553022b5871d926326df"
24
24
  },
25
25
  "provenance": {
26
26
  "builder": "scripts/build-rust-local.sh",
27
- "sourceCommit": "888ffb9504055a10ea38d0c31dd0c9881139e88c",
27
+ "sourceCommit": "d93395c02e0224530b5e52ffd7ec3a64ec462296",
28
28
  "sourceTreeDirty": false,
29
29
  "sourceDateEpoch": 1,
30
30
  "rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
@@ -33,6 +33,6 @@
33
33
  "signature": {
34
34
  "algorithm": "Ed25519",
35
35
  "keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
36
- "value": "bHo9hflPuXFXSTyWqcxf2rV+OlBmqGvUMOgp4WV7TfKOC1nCUV7Ay/1LJXlgqN/XykbfHC8821FpHWLXQSnJDQ=="
36
+ "value": "17L3oFyUCuAlRbQXvbmDqLUlAn01r3qpiy/1/yIcmzsM2cncFpMICDRNV9PUmP6ohFWagoLdv2dQdW4yNjN7Bg=="
37
37
  }
38
38
  }
@@ -4,14 +4,14 @@
4
4
  "version": 1,
5
5
  "metadata": {
6
6
  "component": {
7
- "bom-ref": "pkg:cargo/planu-core@5.3.24",
7
+ "bom-ref": "pkg:cargo/planu-core@5.3.25",
8
8
  "type": "library",
9
9
  "name": "planu-core",
10
- "version": "5.3.24",
10
+ "version": "5.3.25",
11
11
  "hashes": [
12
12
  {
13
13
  "alg": "SHA-256",
14
- "content": "165e48d9d7bb68965782b9f690af378cee9651c9c1b9ab31e6b9fa4bedad514a"
14
+ "content": "e514123ce0f9194810a7735351dc4b07fa0247012e6409bc28e88f8cad001e8d"
15
15
  }
16
16
  ]
17
17
  }
@@ -1106,7 +1106,7 @@
1106
1106
  "dependsOn": []
1107
1107
  },
1108
1108
  {
1109
- "ref": "pkg:cargo/planu-core@5.3.24",
1109
+ "ref": "pkg:cargo/planu-core@5.3.25",
1110
1110
  "dependsOn": [
1111
1111
  "pkg:cargo/core-foundation@0.10.1",
1112
1112
  "pkg:cargo/hmac@0.12.1",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
- "cliVersion": "5.3.24",
4
- "engineVersion": "5.3.24",
5
- "buildId": "1-5.3.24-aarch64-pc-windows-msvc",
3
+ "cliVersion": "5.3.25",
4
+ "engineVersion": "5.3.25",
5
+ "buildId": "1-5.3.25-aarch64-pc-windows-msvc",
6
6
  "protocolAbi": 1,
7
7
  "capabilityAbi": 2,
8
8
  "nodeApiAbi": 4,
@@ -16,15 +16,15 @@
16
16
  "platform": "win32",
17
17
  "arch": "arm64",
18
18
  "libc": null,
19
- "artifactSha256": "363abf41c92e4a6d5e4f7cc821185cca9a84fe5fb99006b8e01d16d106bbfa52",
19
+ "artifactSha256": "022e46d5af58ce074f52a5af2a0ed12ce77a5843081bdf63a5f00383913186f6",
20
20
  "sbom": {
21
21
  "format": "CycloneDX-1.5",
22
22
  "path": "planu-core.win32-arm64-msvc.node.sbom.json",
23
- "sha256": "5f31abd4a8f741b8a72701f428fa777b41a504c1c095f903bdf54b5ccd93b74e"
23
+ "sha256": "a86be9b721fbf785a899cf4789452f46c8b66833262aea97c50cb32d6d6713bb"
24
24
  },
25
25
  "provenance": {
26
26
  "builder": "scripts/build-rust-local.sh",
27
- "sourceCommit": "888ffb9504055a10ea38d0c31dd0c9881139e88c",
27
+ "sourceCommit": "d93395c02e0224530b5e52ffd7ec3a64ec462296",
28
28
  "sourceTreeDirty": false,
29
29
  "sourceDateEpoch": 1,
30
30
  "rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
@@ -33,6 +33,6 @@
33
33
  "signature": {
34
34
  "algorithm": "Ed25519",
35
35
  "keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
36
- "value": "Dj6P860+E1Yi4MGQd3lnA6OmAmf5EvL8mZqfiI81OwYH19GQwnKnBUi5vjh64I781B1lyOwUOPjU+jLpJ8lhCQ=="
36
+ "value": "Xoj5hhRXt8HU4v3XE+ryoCN3pkCkaUh0EFDpceRRICKuxDJ6AFrHg5aWb5FrxByPB1C/4G0lBiBtTGhZzCUqBg=="
37
37
  }
38
38
  }
@@ -4,14 +4,14 @@
4
4
  "version": 1,
5
5
  "metadata": {
6
6
  "component": {
7
- "bom-ref": "pkg:cargo/planu-core@5.3.24",
7
+ "bom-ref": "pkg:cargo/planu-core@5.3.25",
8
8
  "type": "library",
9
9
  "name": "planu-core",
10
- "version": "5.3.24",
10
+ "version": "5.3.25",
11
11
  "hashes": [
12
12
  {
13
13
  "alg": "SHA-256",
14
- "content": "363abf41c92e4a6d5e4f7cc821185cca9a84fe5fb99006b8e01d16d106bbfa52"
14
+ "content": "022e46d5af58ce074f52a5af2a0ed12ce77a5843081bdf63a5f00383913186f6"
15
15
  }
16
16
  ]
17
17
  }
@@ -1106,7 +1106,7 @@
1106
1106
  "dependsOn": []
1107
1107
  },
1108
1108
  {
1109
- "ref": "pkg:cargo/planu-core@5.3.24",
1109
+ "ref": "pkg:cargo/planu-core@5.3.25",
1110
1110
  "dependsOn": [
1111
1111
  "pkg:cargo/core-foundation@0.10.1",
1112
1112
  "pkg:cargo/hmac@0.12.1",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
- "cliVersion": "5.3.24",
4
- "engineVersion": "5.3.24",
5
- "buildId": "1-5.3.24-x86_64-pc-windows-msvc",
3
+ "cliVersion": "5.3.25",
4
+ "engineVersion": "5.3.25",
5
+ "buildId": "1-5.3.25-x86_64-pc-windows-msvc",
6
6
  "protocolAbi": 1,
7
7
  "capabilityAbi": 2,
8
8
  "nodeApiAbi": 4,
@@ -16,15 +16,15 @@
16
16
  "platform": "win32",
17
17
  "arch": "x64",
18
18
  "libc": null,
19
- "artifactSha256": "0b6374ac67d414e13e2e02be6be96a388ed9096f517587f812c533c5fb37992f",
19
+ "artifactSha256": "d3300aa064da7519867fbd9a13f008bfc6b66977f98ac477aa8230825b279a8a",
20
20
  "sbom": {
21
21
  "format": "CycloneDX-1.5",
22
22
  "path": "planu-core.win32-x64-msvc.node.sbom.json",
23
- "sha256": "aaaafe7c267638012a520782ad059014a0641b55005e2a09a5bace53a00d3d3e"
23
+ "sha256": "1726726fed651d4c936d048a34cbb213cb2039faff0fd880ed6102c9fbd585f1"
24
24
  },
25
25
  "provenance": {
26
26
  "builder": "scripts/build-rust-local.sh",
27
- "sourceCommit": "888ffb9504055a10ea38d0c31dd0c9881139e88c",
27
+ "sourceCommit": "d93395c02e0224530b5e52ffd7ec3a64ec462296",
28
28
  "sourceTreeDirty": false,
29
29
  "sourceDateEpoch": 1,
30
30
  "rustToolchain": "rustc 1.95.0 (59807616e 2026-04-14)",
@@ -33,6 +33,6 @@
33
33
  "signature": {
34
34
  "algorithm": "Ed25519",
35
35
  "keyId": "e2ee765cb5ad9fbdc433ece332bce26d746d5e350b3acde0721a4c8c6337ff7b",
36
- "value": "zUMqIwI3WSWZ0QbesWdiZfnIlwAnwkhfwN2Us0lmUCtoKOtQEkqckxNZCY7tuxbzhS091T5LUp7Y+HOUeUViCg=="
36
+ "value": "RJH3JCQyv8Er1ThOgl7Kp2MvxeHgjOqRNuf8JSQwLprkAx9rZZqIJQzd86HnhmxkOTVb7oAWuaABJga3NqBMAg=="
37
37
  }
38
38
  }
@@ -4,14 +4,14 @@
4
4
  "version": 1,
5
5
  "metadata": {
6
6
  "component": {
7
- "bom-ref": "pkg:cargo/planu-core@5.3.24",
7
+ "bom-ref": "pkg:cargo/planu-core@5.3.25",
8
8
  "type": "library",
9
9
  "name": "planu-core",
10
- "version": "5.3.24",
10
+ "version": "5.3.25",
11
11
  "hashes": [
12
12
  {
13
13
  "alg": "SHA-256",
14
- "content": "0b6374ac67d414e13e2e02be6be96a388ed9096f517587f812c533c5fb37992f"
14
+ "content": "d3300aa064da7519867fbd9a13f008bfc6b66977f98ac477aa8230825b279a8a"
15
15
  }
16
16
  ]
17
17
  }
@@ -1106,7 +1106,7 @@
1106
1106
  "dependsOn": []
1107
1107
  },
1108
1108
  {
1109
- "ref": "pkg:cargo/planu-core@5.3.24",
1109
+ "ref": "pkg:cargo/planu-core@5.3.25",
1110
1110
  "dependsOn": [
1111
1111
  "pkg:cargo/core-foundation@0.10.1",
1112
1112
  "pkg:cargo/hmac@0.12.1",
@@ -0,0 +1,2 @@
1
+ export declare function assertPathWithinBase(baseDir: string, candidatePath: string): string;
2
+ //# sourceMappingURL=assert-within-project.d.ts.map
@@ -0,0 +1,14 @@
1
+ import { isAbsolute, relative, resolve } from 'node:path';
2
+ export function assertPathWithinBase(baseDir, candidatePath) {
3
+ const resolvedBase = resolve(baseDir);
4
+ const resolvedCandidate = resolve(candidatePath);
5
+ const rel = relative(resolvedBase, resolvedCandidate);
6
+ if (rel === '') {
7
+ return resolvedCandidate;
8
+ }
9
+ if (rel.startsWith('..') || isAbsolute(rel)) {
10
+ throw new Error(`Path escapes the project directory: resolved candidate "${resolvedCandidate}" is not within base "${resolvedBase}".`);
11
+ }
12
+ return resolvedCandidate;
13
+ }
14
+ //# sourceMappingURL=assert-within-project.js.map
@@ -50,6 +50,12 @@ function normalizeSpec(raw) {
50
50
  }
51
51
  // SPEC-601: Lazy UUID migration — generate if missing
52
52
  spec.uuid ??= crypto.randomUUID();
53
+ if (!Array.isArray(raw.dependencies)) {
54
+ spec.dependencies = [];
55
+ }
56
+ if (!Array.isArray(raw.blockedBy)) {
57
+ spec.blockedBy = [];
58
+ }
53
59
  if (spec.uuidAliases !== undefined) {
54
60
  spec.uuidAliases = [
55
61
  ...new Set(spec.uuidAliases.filter((alias) => typeof alias === 'string' && alias)),
@@ -1,11 +1,12 @@
1
1
  // tools/export-spec.ts — MCP tool handler for export_spec (SPEC-097, SPEC-318)
2
2
  import { readFile, mkdir, writeFile } from 'node:fs/promises';
3
- import { join, resolve, relative } from 'node:path';
3
+ import { join } from 'node:path';
4
4
  import { specStore, knowledgeStore } from '../storage/index.js';
5
5
  import { hashProjectPath } from '../storage/base-store.js';
6
6
  import { exportToSpecKit } from '../engine/spec-kit-exporter.js';
7
7
  import { stripFrontmatter } from '../engine/frontmatter-parser.js';
8
8
  import { specToAgentReady, serializeAgentReady } from '../engine/agent-ready-exporter.js';
9
+ import { assertPathWithinBase } from '../engine/safety/assert-within-project.js';
9
10
  import { compactResult, formatKeyValue } from './output-formatter.js';
10
11
  async function readFileContent(filePath) {
11
12
  try {
@@ -65,15 +66,16 @@ export async function handleExportSpec(params) {
65
66
  const content = serializeAgentReady(agentSpec, target);
66
67
  let filePath;
67
68
  if (params.outputDir) {
68
- const resolvedOutput = resolve(params.outputDir);
69
- const resolvedProject = resolve(params.projectPath);
70
- const rel = relative(resolvedProject, resolvedOutput);
71
- if (rel.startsWith('..') || rel.startsWith('/')) {
69
+ let resolvedOutput;
70
+ try {
71
+ resolvedOutput = assertPathWithinBase(params.projectPath, params.outputDir);
72
+ }
73
+ catch (error) {
72
74
  return {
73
75
  content: [
74
76
  {
75
77
  type: 'text',
76
- text: `Invalid outputDir: path escapes the project directory. Resolved to "${resolvedOutput}".`,
78
+ text: `Invalid outputDir: ${error instanceof Error ? error.message : String(error)}`,
77
79
  },
78
80
  ],
79
81
  isError: true,
@@ -121,24 +123,25 @@ export async function handleExportSpec(params) {
121
123
  // Write to output directory
122
124
  const slug = toSlug(spec.title);
123
125
  const outputDir = params.outputDir ?? join(params.projectPath, 'planu', 'exports', slug);
124
- const resolvedOutput = resolve(outputDir);
125
- const resolvedProject = resolve(params.projectPath);
126
- const rel = relative(resolvedProject, resolvedOutput);
127
- if (rel.startsWith('..') || rel.startsWith('/')) {
126
+ let resolvedOutput;
127
+ try {
128
+ resolvedOutput = assertPathWithinBase(params.projectPath, outputDir);
129
+ }
130
+ catch (error) {
128
131
  return {
129
132
  content: [
130
133
  {
131
134
  type: 'text',
132
- text: `Invalid outputDir: path escapes the project directory. Resolved to "${resolvedOutput}".`,
135
+ text: `Invalid outputDir: ${error instanceof Error ? error.message : String(error)}`,
133
136
  },
134
137
  ],
135
138
  isError: true,
136
139
  };
137
140
  }
138
- await mkdir(outputDir, { recursive: true });
139
- const specMdPath = join(outputDir, 'spec.md');
140
- const planMdPath = join(outputDir, 'plan.md');
141
- const tasksMdPath = join(outputDir, 'tasks.md');
141
+ await mkdir(resolvedOutput, { recursive: true });
142
+ const specMdPath = join(resolvedOutput, 'spec.md');
143
+ const planMdPath = join(resolvedOutput, 'plan.md');
144
+ const tasksMdPath = join(resolvedOutput, 'tasks.md');
142
145
  await Promise.all([
143
146
  writeFile(specMdPath, result.specMd, 'utf-8'),
144
147
  writeFile(planMdPath, result.planMd, 'utf-8'),
@@ -5,6 +5,7 @@ import { dirname } from 'node:path';
5
5
  import { getSpec } from '../storage/spec-store.js';
6
6
  import { hashProjectPath } from '../storage/base-store.js';
7
7
  import { generateSchemas, generateApiClient } from '../engine/schema-generator.js';
8
+ import { assertPathWithinBase } from '../engine/safety/assert-within-project.js';
8
9
  async function readSpecText(spec) {
9
10
  const parts = [];
10
11
  if (spec.description !== undefined) {
@@ -51,6 +52,7 @@ export async function handleGenerateValidationSchema(input) {
51
52
  }
52
53
  // Write files if outputPath is provided
53
54
  if (outputPath !== undefined) {
55
+ assertPathWithinBase(projectPath, outputPath);
54
56
  for (const schema of result.schemas) {
55
57
  const ext = outputFormat === technologyValue('technology-typescript-969545') ? '.ts' : '.js';
56
58
  const libSuffix = library === 'all' ? `.${schema.library}` : '';
@@ -105,6 +107,7 @@ export async function handleGenerateApiClient(input) {
105
107
  };
106
108
  }
107
109
  if (outputPath !== undefined) {
110
+ assertPathWithinBase(projectPath, outputPath);
108
111
  await writeOutputFile(outputPath, result.code);
109
112
  }
110
113
  return {
@@ -3,10 +3,8 @@ import { writeFile } from 'node:fs/promises';
3
3
  import { listSpecs } from '../storage/spec-store.js';
4
4
  import { hashProjectPath } from '../storage/base-store.js';
5
5
  import { filterSpecs, specsToCsv, specsToMarkdownTable, ALL_COLUMNS, } from '../engine/spec-exporter.js';
6
+ import { assertPathWithinBase } from '../engine/safety/assert-within-project.js';
6
7
  import { formatSuccess, formatError, toolResult } from './response-helpers.js';
7
- // ---------------------------------------------------------------------------
8
- // Shared logic
9
- // ---------------------------------------------------------------------------
10
8
  async function buildExport(input, format) {
11
9
  const projectId = hashProjectPath(input.projectPath);
12
10
  const allSpecs = await listSpecs(projectId);
@@ -15,8 +13,15 @@ async function buildExport(input, format) {
15
13
  const content = format === 'csv' ? specsToCsv(filtered, columns) : specsToMarkdownTable(filtered, columns);
16
14
  let filePath;
17
15
  if (input.outputPath) {
18
- await writeFile(input.outputPath, content, 'utf8');
19
- filePath = input.outputPath;
16
+ let resolvedOutputPath;
17
+ try {
18
+ resolvedOutputPath = assertPathWithinBase(input.projectPath, input.outputPath);
19
+ }
20
+ catch (error) {
21
+ return { ok: false, message: error instanceof Error ? error.message : String(error) };
22
+ }
23
+ await writeFile(resolvedOutputPath, content, 'utf8');
24
+ filePath = resolvedOutputPath;
20
25
  }
21
26
  const result = {
22
27
  rowCount: filtered.length,
@@ -25,7 +30,7 @@ async function buildExport(input, format) {
25
30
  content,
26
31
  filePath,
27
32
  };
28
- return { text: content, result };
33
+ return { ok: true, text: content, result };
29
34
  }
30
35
  // ---------------------------------------------------------------------------
31
36
  // CSV handler
@@ -34,7 +39,11 @@ export async function handleExportSpecsCsv(args) {
34
39
  if (!args.projectPath || args.projectPath.trim().length === 0) {
35
40
  return toolResult(formatError('projectPath is required', 'Provide the absolute path to your project root.'), undefined, true);
36
41
  }
37
- const { text, result } = await buildExport(args, 'csv');
42
+ const built = await buildExport(args, 'csv');
43
+ if (!built.ok) {
44
+ return toolResult(formatError(`Invalid outputPath: ${built.message}`, 'Choose a path within projectPath.'), undefined, true);
45
+ }
46
+ const { text, result } = built;
38
47
  const summary = [
39
48
  `Exported ${String(result.rowCount)} specs to CSV`,
40
49
  `Columns: ${result.columns.join(', ')}`,
@@ -51,7 +60,11 @@ export async function handleExportSpecsMarkdown(args) {
51
60
  if (!args.projectPath || args.projectPath.trim().length === 0) {
52
61
  return toolResult(formatError('projectPath is required', 'Provide the absolute path to your project root.'), undefined, true);
53
62
  }
54
- const { text, result } = await buildExport(args, 'markdown');
63
+ const built = await buildExport(args, 'markdown');
64
+ if (!built.ok) {
65
+ return toolResult(formatError(`Invalid outputPath: ${built.message}`, 'Choose a path within projectPath.'), undefined, true);
66
+ }
67
+ const { text, result } = built;
55
68
  const summary = [
56
69
  `Exported ${String(result.rowCount)} specs to Markdown table`,
57
70
  `Columns: ${result.columns.join(', ')}`,
@@ -1,11 +1,27 @@
1
1
  import { exportStorageBundle, importStorageBundle } from '../storage/storage-bundle.js';
2
+ import { assertPathWithinBase } from '../engine/safety/assert-within-project.js';
2
3
  export async function handleStorageExport(input) {
3
- const bundle = await exportStorageBundle(input.projectId, input.outputPath);
4
+ let resolvedOutputPath;
5
+ try {
6
+ resolvedOutputPath = assertPathWithinBase(process.cwd(), input.outputPath);
7
+ }
8
+ catch (error) {
9
+ return {
10
+ content: [
11
+ {
12
+ type: 'text',
13
+ text: `Invalid outputPath: ${error instanceof Error ? error.message : String(error)}`,
14
+ },
15
+ ],
16
+ isError: true,
17
+ };
18
+ }
19
+ const bundle = await exportStorageBundle(input.projectId, resolvedOutputPath);
4
20
  const payload = {
5
21
  schemaVersion: 1,
6
22
  exported: true,
7
23
  projectId: bundle.projectId,
8
- outputPath: input.outputPath,
24
+ outputPath: resolvedOutputPath,
9
25
  checksum: bundle.checksum,
10
26
  };
11
27
  return {
@@ -14,12 +30,27 @@ export async function handleStorageExport(input) {
14
30
  };
15
31
  }
16
32
  export async function handleStorageImport(input) {
17
- const bundle = await importStorageBundle(input.inputPath);
33
+ let resolvedInputPath;
34
+ try {
35
+ resolvedInputPath = assertPathWithinBase(process.cwd(), input.inputPath);
36
+ }
37
+ catch (error) {
38
+ return {
39
+ content: [
40
+ {
41
+ type: 'text',
42
+ text: `Invalid inputPath: ${error instanceof Error ? error.message : String(error)}`,
43
+ },
44
+ ],
45
+ isError: true,
46
+ };
47
+ }
48
+ const bundle = await importStorageBundle(resolvedInputPath);
18
49
  const payload = {
19
50
  schemaVersion: 1,
20
51
  imported: true,
21
52
  projectId: bundle.projectId,
22
- inputPath: input.inputPath,
53
+ inputPath: resolvedInputPath,
23
54
  };
24
55
  return {
25
56
  content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planu/cli",
3
- "version": "5.3.24",
3
+ "version": "5.3.25",
4
4
  "description": "Planu — MCP Server for Spec Driven Development with native Rust acceleration for hot paths. Cross-platform (Linux/macOS/Windows, x64/arm64, glibc/musl).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -36,14 +36,14 @@
36
36
  "packageName": "@planu/core"
37
37
  },
38
38
  "optionalDependencies": {
39
- "@planu/core-darwin-arm64": "5.3.24",
40
- "@planu/core-darwin-x64": "5.3.24",
41
- "@planu/core-linux-arm64-gnu": "5.3.24",
42
- "@planu/core-linux-arm64-musl": "5.3.24",
43
- "@planu/core-linux-x64-gnu": "5.3.24",
44
- "@planu/core-linux-x64-musl": "5.3.24",
45
- "@planu/core-win32-arm64-msvc": "5.3.24",
46
- "@planu/core-win32-x64-msvc": "5.3.24"
39
+ "@planu/core-darwin-arm64": "5.3.25",
40
+ "@planu/core-darwin-x64": "5.3.25",
41
+ "@planu/core-linux-arm64-gnu": "5.3.25",
42
+ "@planu/core-linux-arm64-musl": "5.3.25",
43
+ "@planu/core-linux-x64-gnu": "5.3.25",
44
+ "@planu/core-linux-x64-musl": "5.3.25",
45
+ "@planu/core-win32-arm64-msvc": "5.3.25",
46
+ "@planu/core-win32-x64-msvc": "5.3.25"
47
47
  },
48
48
  "engines": {
49
49
  "node": ">=24.0.0"
package/planu-native.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dev.planu.native",
3
3
  "displayName": "Planu Native Lightweight Surface",
4
- "version": "5.3.24",
4
+ "version": "5.3.25",
5
5
  "packageName": "@planu/cli",
6
6
  "modes": {
7
7
  "lightweight": {
package/planu-plugin.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "dev.planu.cli",
3
3
  "displayName": "Planu — Spec Driven Development",
4
4
  "description": "Manage software specs, estimations, and autonomous SDD workflows. Language-agnostic MCP server for Claude Code.",
5
- "version": "5.3.24",
5
+ "version": "5.3.25",
6
6
  "icon": "assets/plugin/icon.svg",
7
7
  "command": ["npx", "@planu/cli@latest"],
8
8
  "packageName": "@planu/cli",