openplanr 2.2640.3 → 2.2640.4

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 (25) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/lib/host-packages/adapter-registry.json +5 -5
  3. package/lib/host-packages/capability-map.json +1 -1
  4. package/lib/host-packages/claude/.claude-plugin/marketplace.json +2 -2
  5. package/lib/host-packages/claude/openplanr/.claude-plugin/plugin.json +1 -1
  6. package/lib/host-packages/claude/openplanr/.openplanr-content.json +7 -7
  7. package/lib/host-packages/claude/openplanr/README.md +1 -1
  8. package/lib/host-packages/claude/openplanr/skills/design/scripts/design-share.mjs +105 -5
  9. package/lib/host-packages/claude/openplanr/skills/design-loop/scripts/design-share.mjs +105 -5
  10. package/lib/host-packages/claude/openplanr/skills/design-review/scripts/design-share.mjs +105 -5
  11. package/lib/host-packages/claude/openplanr/skills/plan/scripts/design-share.mjs +105 -5
  12. package/lib/host-packages/cursor/openplanr/.openplanr-content.json +6 -6
  13. package/lib/host-packages/cursor/openplanr/manifest.json +1 -1
  14. package/lib/host-packages/cursor/openplanr/rules/planr-design/scripts/design-share.mjs +105 -5
  15. package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/scripts/design-share.mjs +105 -5
  16. package/lib/host-packages/cursor/openplanr/rules/planr-design-review/scripts/design-share.mjs +105 -5
  17. package/lib/host-packages/cursor/openplanr/rules/planr-plan/scripts/design-share.mjs +105 -5
  18. package/lib/host-packages/openai/.claude-plugin/marketplace.json +2 -2
  19. package/lib/host-packages/openai/openplanr/.codex-plugin/plugin.json +1 -1
  20. package/lib/host-packages/openai/openplanr/.openplanr-content.json +6 -6
  21. package/lib/host-packages/openai/openplanr/skills/design/scripts/design-share.mjs +105 -5
  22. package/lib/host-packages/openai/openplanr/skills/design-loop/scripts/design-share.mjs +105 -5
  23. package/lib/host-packages/openai/openplanr/skills/design-review/scripts/design-share.mjs +105 -5
  24. package/lib/host-packages/openai/openplanr/skills/plan/scripts/design-share.mjs +105 -5
  25. package/package.json +2 -2
@@ -8,7 +8,7 @@
8
8
  "files": [
9
9
  {
10
10
  "path": "manifest.json",
11
- "digest": "sha256:af1b0d20bf5b236a58bd867d217b2fd31d788bd45a6b9ab251cedec0fbcd6cf8"
11
+ "digest": "sha256:775afdf0d1ae0c10fb9187ba7f71d02da2c63af64fe116d9f0de2a4c177ea5aa"
12
12
  },
13
13
  {
14
14
  "path": "rules/planr-artifact.mdc",
@@ -272,7 +272,7 @@
272
272
  },
273
273
  {
274
274
  "path": "rules/planr-design-loop/scripts/design-share.mjs",
275
- "digest": "sha256:b10d7ce9cdb3eb48b9aca803e4d2ecc4f8e477e91f4a0c6a3ae17a1f7985aa06"
275
+ "digest": "sha256:11de427bd02b89fdf6df5b3d8eaffa7c2025ab841712c7dfc0da6e5a3e41ca36"
276
276
  },
277
277
  {
278
278
  "path": "rules/planr-design-loop/scripts/design.mjs",
@@ -480,7 +480,7 @@
480
480
  },
481
481
  {
482
482
  "path": "rules/planr-design-review/scripts/design-share.mjs",
483
- "digest": "sha256:b10d7ce9cdb3eb48b9aca803e4d2ecc4f8e477e91f4a0c6a3ae17a1f7985aa06"
483
+ "digest": "sha256:11de427bd02b89fdf6df5b3d8eaffa7c2025ab841712c7dfc0da6e5a3e41ca36"
484
484
  },
485
485
  {
486
486
  "path": "rules/planr-design-review/scripts/design.mjs",
@@ -688,7 +688,7 @@
688
688
  },
689
689
  {
690
690
  "path": "rules/planr-design/scripts/design-share.mjs",
691
- "digest": "sha256:b10d7ce9cdb3eb48b9aca803e4d2ecc4f8e477e91f4a0c6a3ae17a1f7985aa06"
691
+ "digest": "sha256:11de427bd02b89fdf6df5b3d8eaffa7c2025ab841712c7dfc0da6e5a3e41ca36"
692
692
  },
693
693
  {
694
694
  "path": "rules/planr-design/scripts/design.mjs",
@@ -928,7 +928,7 @@
928
928
  },
929
929
  {
930
930
  "path": "rules/planr-plan/scripts/design-share.mjs",
931
- "digest": "sha256:b10d7ce9cdb3eb48b9aca803e4d2ecc4f8e477e91f4a0c6a3ae17a1f7985aa06"
931
+ "digest": "sha256:11de427bd02b89fdf6df5b3d8eaffa7c2025ab841712c7dfc0da6e5a3e41ca36"
932
932
  },
933
933
  {
934
934
  "path": "rules/planr-plan/scripts/design.mjs",
@@ -1139,5 +1139,5 @@
1139
1139
  "digest": "sha256:005397d703d8df70f346a789d15c665a44329449418b39e807bb0dff927153da"
1140
1140
  }
1141
1141
  ],
1142
- "contentDigest": "sha256:8c04be716b9a8cffe2bfc101b825ddf9b5db76effc10cdb6d7dfcc31a0fbc5db"
1142
+ "contentDigest": "sha256:1c74fff7659fe485258b08e40c6f8c8ed0c3e57f3309d0467f580b1038ff0920"
1143
1143
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openplanr",
3
- "version": "2.2640.3",
3
+ "version": "2.2640.4",
4
4
  "ruleCount": 27,
5
5
  "rules": [
6
6
  "rules/planr-artifact.mdc",
@@ -870,6 +870,104 @@ async function unseal(value, rawKey, context, limit = DESIGN_WORKSPACE_MAX_BYTES
870
870
  );
871
871
  return JSON.parse(decoder.decode(plaintext));
872
872
  }
873
+ var PACKED_BUNDLE_KIND = "openplanr-design-review-bundle-packed";
874
+ var PACKED_BUNDLE_MAX_BYTES = 128 * 1024 * 1024;
875
+ var SHARED_BLOCK_MIN_LENGTH = 2048;
876
+ var sharedBlockPattern = /(<(script|style)\b[^>]*>)([\s\S]*?)<\/\2\s*>/gi;
877
+ async function deflateRaw(bytes) {
878
+ const stream = new Blob([bytes]).stream().pipeThrough(new CompressionStream("deflate-raw"));
879
+ return new Uint8Array(await new Response(stream).arrayBuffer());
880
+ }
881
+ async function inflateRaw(bytes, limit) {
882
+ const reader = new Blob([bytes]).stream().pipeThrough(new DecompressionStream("deflate-raw")).getReader();
883
+ const chunks = [];
884
+ let size = 0;
885
+ for (; ; ) {
886
+ const { done, value } = await reader.read();
887
+ if (done) break;
888
+ size += value.byteLength;
889
+ if (size > limit) {
890
+ await reader.cancel();
891
+ throw new RangeError("The shared design expands beyond its size limit.");
892
+ }
893
+ chunks.push(value);
894
+ }
895
+ const inflated = new Uint8Array(size);
896
+ let offset = 0;
897
+ for (const chunk of chunks) {
898
+ inflated.set(chunk, offset);
899
+ offset += chunk.byteLength;
900
+ }
901
+ return inflated;
902
+ }
903
+ async function packDesignReviewBundle(bundle) {
904
+ const pages = [];
905
+ const pageIndex = /* @__PURE__ */ new Map();
906
+ const blocks = [];
907
+ const blockIndex = /* @__PURE__ */ new Map();
908
+ const segmentsOf = (html) => {
909
+ const segments = [];
910
+ let offset = 0;
911
+ for (const match of html.matchAll(sharedBlockPattern)) {
912
+ const body = match[3];
913
+ if (body.length < SHARED_BLOCK_MIN_LENGTH) continue;
914
+ const start = match.index + match[1].length;
915
+ segments.push(html.slice(offset, start));
916
+ if (!blockIndex.has(body)) blockIndex.set(body, blocks.push(body) - 1);
917
+ segments.push(blockIndex.get(body));
918
+ offset = start + body.length;
919
+ }
920
+ segments.push(html.slice(offset));
921
+ return segments;
922
+ };
923
+ const artifactPages = [];
924
+ const artifacts = bundle.envelope.artifacts.map(({ html, ...artifact }) => {
925
+ if (!pageIndex.has(html)) pageIndex.set(html, pages.push(segmentsOf(html)) - 1);
926
+ artifactPages.push(pageIndex.get(html));
927
+ return artifact;
928
+ });
929
+ const packed = {
930
+ bundle: { ...bundle, envelope: { ...bundle.envelope, artifacts } },
931
+ artifactPages,
932
+ pages,
933
+ blocks
934
+ };
935
+ return {
936
+ kind: PACKED_BUNDLE_KIND,
937
+ version: 1,
938
+ data: encodeWorkspaceBytes(await deflateRaw(encoder.encode(JSON.stringify(packed))))
939
+ };
940
+ }
941
+ async function unpackDesignReviewBundle(value, { maxBytes = PACKED_BUNDLE_MAX_BYTES } = {}) {
942
+ if (value?.kind !== PACKED_BUNDLE_KIND) return value;
943
+ if (value.version !== 1 || typeof value.data !== "string")
944
+ throw new Error("The shared design uses an unsupported packing.");
945
+ const { bundle, artifactPages, pages, blocks } = JSON.parse(
946
+ decoder.decode(await inflateRaw(decodeWorkspaceBytes(value.data), maxBytes))
947
+ );
948
+ const invalid2 = () => new Error("The shared design packing is invalid.");
949
+ if (!Array.isArray(bundle?.envelope?.artifacts) || !Array.isArray(pages) || !Array.isArray(blocks) || !Array.isArray(artifactPages) || artifactPages.length !== bundle.envelope.artifacts.length)
950
+ throw invalid2();
951
+ let expanded = 0;
952
+ const html = pages.map((segments) => {
953
+ if (!Array.isArray(segments)) throw invalid2();
954
+ const page = segments.map((segment) => {
955
+ if (typeof segment === "string") return segment;
956
+ if (!Number.isInteger(segment) || typeof blocks[segment] !== "string") throw invalid2();
957
+ return blocks[segment];
958
+ }).join("");
959
+ expanded += page.length;
960
+ if (expanded > maxBytes)
961
+ throw new RangeError("The shared design expands beyond its size limit.");
962
+ return page;
963
+ });
964
+ const artifacts = bundle.envelope.artifacts.map((artifact, index) => {
965
+ const page = html[artifactPages[index]];
966
+ if (page === void 0) throw invalid2();
967
+ return { ...artifact, html: page };
968
+ });
969
+ return { ...bundle, envelope: { ...bundle.envelope, artifacts } };
970
+ }
873
971
  var keyringContext = (id, epoch) => ({ type: "keyring", workspaceId: id, epoch });
874
972
  var revisionContext = (id, revision) => ({
875
973
  type: "revision",
@@ -914,7 +1012,7 @@ async function prepareRevision(custody, bundle) {
914
1012
  {
915
1013
  ...header,
916
1014
  ...await seal(
917
- bundle,
1015
+ await packDesignReviewBundle(bundle),
918
1016
  decodeWorkspaceBytes(custody.keys[custody.epoch]),
919
1017
  revisionContext(custody.id, header)
920
1018
  )
@@ -1084,10 +1182,12 @@ async function decryptWorkspaceRevision(access, revisionId = access.currentRevis
1084
1182
  throw new Error("The published design signature is invalid.");
1085
1183
  if (!access.keys[revision.epoch]) throw new Error("The access token cannot open this revision.");
1086
1184
  const bundle = assertDesignReviewBundle(
1087
- await unseal(
1088
- revision,
1089
- decodeWorkspaceBytes(access.keys[revision.epoch]),
1090
- revisionContext(access.id, revision)
1185
+ await unpackDesignReviewBundle(
1186
+ await unseal(
1187
+ revision,
1188
+ decodeWorkspaceBytes(access.keys[revision.epoch]),
1189
+ revisionContext(access.id, revision)
1190
+ )
1091
1191
  )
1092
1192
  );
1093
1193
  if (workspaceEnvelopeDigest(bundle.envelope) !== revision.reviewOf)
@@ -870,6 +870,104 @@ async function unseal(value, rawKey, context, limit = DESIGN_WORKSPACE_MAX_BYTES
870
870
  );
871
871
  return JSON.parse(decoder.decode(plaintext));
872
872
  }
873
+ var PACKED_BUNDLE_KIND = "openplanr-design-review-bundle-packed";
874
+ var PACKED_BUNDLE_MAX_BYTES = 128 * 1024 * 1024;
875
+ var SHARED_BLOCK_MIN_LENGTH = 2048;
876
+ var sharedBlockPattern = /(<(script|style)\b[^>]*>)([\s\S]*?)<\/\2\s*>/gi;
877
+ async function deflateRaw(bytes) {
878
+ const stream = new Blob([bytes]).stream().pipeThrough(new CompressionStream("deflate-raw"));
879
+ return new Uint8Array(await new Response(stream).arrayBuffer());
880
+ }
881
+ async function inflateRaw(bytes, limit) {
882
+ const reader = new Blob([bytes]).stream().pipeThrough(new DecompressionStream("deflate-raw")).getReader();
883
+ const chunks = [];
884
+ let size = 0;
885
+ for (; ; ) {
886
+ const { done, value } = await reader.read();
887
+ if (done) break;
888
+ size += value.byteLength;
889
+ if (size > limit) {
890
+ await reader.cancel();
891
+ throw new RangeError("The shared design expands beyond its size limit.");
892
+ }
893
+ chunks.push(value);
894
+ }
895
+ const inflated = new Uint8Array(size);
896
+ let offset = 0;
897
+ for (const chunk of chunks) {
898
+ inflated.set(chunk, offset);
899
+ offset += chunk.byteLength;
900
+ }
901
+ return inflated;
902
+ }
903
+ async function packDesignReviewBundle(bundle) {
904
+ const pages = [];
905
+ const pageIndex = /* @__PURE__ */ new Map();
906
+ const blocks = [];
907
+ const blockIndex = /* @__PURE__ */ new Map();
908
+ const segmentsOf = (html) => {
909
+ const segments = [];
910
+ let offset = 0;
911
+ for (const match of html.matchAll(sharedBlockPattern)) {
912
+ const body = match[3];
913
+ if (body.length < SHARED_BLOCK_MIN_LENGTH) continue;
914
+ const start = match.index + match[1].length;
915
+ segments.push(html.slice(offset, start));
916
+ if (!blockIndex.has(body)) blockIndex.set(body, blocks.push(body) - 1);
917
+ segments.push(blockIndex.get(body));
918
+ offset = start + body.length;
919
+ }
920
+ segments.push(html.slice(offset));
921
+ return segments;
922
+ };
923
+ const artifactPages = [];
924
+ const artifacts = bundle.envelope.artifacts.map(({ html, ...artifact }) => {
925
+ if (!pageIndex.has(html)) pageIndex.set(html, pages.push(segmentsOf(html)) - 1);
926
+ artifactPages.push(pageIndex.get(html));
927
+ return artifact;
928
+ });
929
+ const packed = {
930
+ bundle: { ...bundle, envelope: { ...bundle.envelope, artifacts } },
931
+ artifactPages,
932
+ pages,
933
+ blocks
934
+ };
935
+ return {
936
+ kind: PACKED_BUNDLE_KIND,
937
+ version: 1,
938
+ data: encodeWorkspaceBytes(await deflateRaw(encoder.encode(JSON.stringify(packed))))
939
+ };
940
+ }
941
+ async function unpackDesignReviewBundle(value, { maxBytes = PACKED_BUNDLE_MAX_BYTES } = {}) {
942
+ if (value?.kind !== PACKED_BUNDLE_KIND) return value;
943
+ if (value.version !== 1 || typeof value.data !== "string")
944
+ throw new Error("The shared design uses an unsupported packing.");
945
+ const { bundle, artifactPages, pages, blocks } = JSON.parse(
946
+ decoder.decode(await inflateRaw(decodeWorkspaceBytes(value.data), maxBytes))
947
+ );
948
+ const invalid2 = () => new Error("The shared design packing is invalid.");
949
+ if (!Array.isArray(bundle?.envelope?.artifacts) || !Array.isArray(pages) || !Array.isArray(blocks) || !Array.isArray(artifactPages) || artifactPages.length !== bundle.envelope.artifacts.length)
950
+ throw invalid2();
951
+ let expanded = 0;
952
+ const html = pages.map((segments) => {
953
+ if (!Array.isArray(segments)) throw invalid2();
954
+ const page = segments.map((segment) => {
955
+ if (typeof segment === "string") return segment;
956
+ if (!Number.isInteger(segment) || typeof blocks[segment] !== "string") throw invalid2();
957
+ return blocks[segment];
958
+ }).join("");
959
+ expanded += page.length;
960
+ if (expanded > maxBytes)
961
+ throw new RangeError("The shared design expands beyond its size limit.");
962
+ return page;
963
+ });
964
+ const artifacts = bundle.envelope.artifacts.map((artifact, index) => {
965
+ const page = html[artifactPages[index]];
966
+ if (page === void 0) throw invalid2();
967
+ return { ...artifact, html: page };
968
+ });
969
+ return { ...bundle, envelope: { ...bundle.envelope, artifacts } };
970
+ }
873
971
  var keyringContext = (id, epoch) => ({ type: "keyring", workspaceId: id, epoch });
874
972
  var revisionContext = (id, revision) => ({
875
973
  type: "revision",
@@ -914,7 +1012,7 @@ async function prepareRevision(custody, bundle) {
914
1012
  {
915
1013
  ...header,
916
1014
  ...await seal(
917
- bundle,
1015
+ await packDesignReviewBundle(bundle),
918
1016
  decodeWorkspaceBytes(custody.keys[custody.epoch]),
919
1017
  revisionContext(custody.id, header)
920
1018
  )
@@ -1084,10 +1182,12 @@ async function decryptWorkspaceRevision(access, revisionId = access.currentRevis
1084
1182
  throw new Error("The published design signature is invalid.");
1085
1183
  if (!access.keys[revision.epoch]) throw new Error("The access token cannot open this revision.");
1086
1184
  const bundle = assertDesignReviewBundle(
1087
- await unseal(
1088
- revision,
1089
- decodeWorkspaceBytes(access.keys[revision.epoch]),
1090
- revisionContext(access.id, revision)
1185
+ await unpackDesignReviewBundle(
1186
+ await unseal(
1187
+ revision,
1188
+ decodeWorkspaceBytes(access.keys[revision.epoch]),
1189
+ revisionContext(access.id, revision)
1190
+ )
1091
1191
  )
1092
1192
  );
1093
1193
  if (workspaceEnvelopeDigest(bundle.envelope) !== revision.reviewOf)
@@ -870,6 +870,104 @@ async function unseal(value, rawKey, context, limit = DESIGN_WORKSPACE_MAX_BYTES
870
870
  );
871
871
  return JSON.parse(decoder.decode(plaintext));
872
872
  }
873
+ var PACKED_BUNDLE_KIND = "openplanr-design-review-bundle-packed";
874
+ var PACKED_BUNDLE_MAX_BYTES = 128 * 1024 * 1024;
875
+ var SHARED_BLOCK_MIN_LENGTH = 2048;
876
+ var sharedBlockPattern = /(<(script|style)\b[^>]*>)([\s\S]*?)<\/\2\s*>/gi;
877
+ async function deflateRaw(bytes) {
878
+ const stream = new Blob([bytes]).stream().pipeThrough(new CompressionStream("deflate-raw"));
879
+ return new Uint8Array(await new Response(stream).arrayBuffer());
880
+ }
881
+ async function inflateRaw(bytes, limit) {
882
+ const reader = new Blob([bytes]).stream().pipeThrough(new DecompressionStream("deflate-raw")).getReader();
883
+ const chunks = [];
884
+ let size = 0;
885
+ for (; ; ) {
886
+ const { done, value } = await reader.read();
887
+ if (done) break;
888
+ size += value.byteLength;
889
+ if (size > limit) {
890
+ await reader.cancel();
891
+ throw new RangeError("The shared design expands beyond its size limit.");
892
+ }
893
+ chunks.push(value);
894
+ }
895
+ const inflated = new Uint8Array(size);
896
+ let offset = 0;
897
+ for (const chunk of chunks) {
898
+ inflated.set(chunk, offset);
899
+ offset += chunk.byteLength;
900
+ }
901
+ return inflated;
902
+ }
903
+ async function packDesignReviewBundle(bundle) {
904
+ const pages = [];
905
+ const pageIndex = /* @__PURE__ */ new Map();
906
+ const blocks = [];
907
+ const blockIndex = /* @__PURE__ */ new Map();
908
+ const segmentsOf = (html) => {
909
+ const segments = [];
910
+ let offset = 0;
911
+ for (const match of html.matchAll(sharedBlockPattern)) {
912
+ const body = match[3];
913
+ if (body.length < SHARED_BLOCK_MIN_LENGTH) continue;
914
+ const start = match.index + match[1].length;
915
+ segments.push(html.slice(offset, start));
916
+ if (!blockIndex.has(body)) blockIndex.set(body, blocks.push(body) - 1);
917
+ segments.push(blockIndex.get(body));
918
+ offset = start + body.length;
919
+ }
920
+ segments.push(html.slice(offset));
921
+ return segments;
922
+ };
923
+ const artifactPages = [];
924
+ const artifacts = bundle.envelope.artifacts.map(({ html, ...artifact }) => {
925
+ if (!pageIndex.has(html)) pageIndex.set(html, pages.push(segmentsOf(html)) - 1);
926
+ artifactPages.push(pageIndex.get(html));
927
+ return artifact;
928
+ });
929
+ const packed = {
930
+ bundle: { ...bundle, envelope: { ...bundle.envelope, artifacts } },
931
+ artifactPages,
932
+ pages,
933
+ blocks
934
+ };
935
+ return {
936
+ kind: PACKED_BUNDLE_KIND,
937
+ version: 1,
938
+ data: encodeWorkspaceBytes(await deflateRaw(encoder.encode(JSON.stringify(packed))))
939
+ };
940
+ }
941
+ async function unpackDesignReviewBundle(value, { maxBytes = PACKED_BUNDLE_MAX_BYTES } = {}) {
942
+ if (value?.kind !== PACKED_BUNDLE_KIND) return value;
943
+ if (value.version !== 1 || typeof value.data !== "string")
944
+ throw new Error("The shared design uses an unsupported packing.");
945
+ const { bundle, artifactPages, pages, blocks } = JSON.parse(
946
+ decoder.decode(await inflateRaw(decodeWorkspaceBytes(value.data), maxBytes))
947
+ );
948
+ const invalid2 = () => new Error("The shared design packing is invalid.");
949
+ if (!Array.isArray(bundle?.envelope?.artifacts) || !Array.isArray(pages) || !Array.isArray(blocks) || !Array.isArray(artifactPages) || artifactPages.length !== bundle.envelope.artifacts.length)
950
+ throw invalid2();
951
+ let expanded = 0;
952
+ const html = pages.map((segments) => {
953
+ if (!Array.isArray(segments)) throw invalid2();
954
+ const page = segments.map((segment) => {
955
+ if (typeof segment === "string") return segment;
956
+ if (!Number.isInteger(segment) || typeof blocks[segment] !== "string") throw invalid2();
957
+ return blocks[segment];
958
+ }).join("");
959
+ expanded += page.length;
960
+ if (expanded > maxBytes)
961
+ throw new RangeError("The shared design expands beyond its size limit.");
962
+ return page;
963
+ });
964
+ const artifacts = bundle.envelope.artifacts.map((artifact, index) => {
965
+ const page = html[artifactPages[index]];
966
+ if (page === void 0) throw invalid2();
967
+ return { ...artifact, html: page };
968
+ });
969
+ return { ...bundle, envelope: { ...bundle.envelope, artifacts } };
970
+ }
873
971
  var keyringContext = (id, epoch) => ({ type: "keyring", workspaceId: id, epoch });
874
972
  var revisionContext = (id, revision) => ({
875
973
  type: "revision",
@@ -914,7 +1012,7 @@ async function prepareRevision(custody, bundle) {
914
1012
  {
915
1013
  ...header,
916
1014
  ...await seal(
917
- bundle,
1015
+ await packDesignReviewBundle(bundle),
918
1016
  decodeWorkspaceBytes(custody.keys[custody.epoch]),
919
1017
  revisionContext(custody.id, header)
920
1018
  )
@@ -1084,10 +1182,12 @@ async function decryptWorkspaceRevision(access, revisionId = access.currentRevis
1084
1182
  throw new Error("The published design signature is invalid.");
1085
1183
  if (!access.keys[revision.epoch]) throw new Error("The access token cannot open this revision.");
1086
1184
  const bundle = assertDesignReviewBundle(
1087
- await unseal(
1088
- revision,
1089
- decodeWorkspaceBytes(access.keys[revision.epoch]),
1090
- revisionContext(access.id, revision)
1185
+ await unpackDesignReviewBundle(
1186
+ await unseal(
1187
+ revision,
1188
+ decodeWorkspaceBytes(access.keys[revision.epoch]),
1189
+ revisionContext(access.id, revision)
1190
+ )
1091
1191
  )
1092
1192
  );
1093
1193
  if (workspaceEnvelopeDigest(bundle.envelope) !== revision.reviewOf)
@@ -870,6 +870,104 @@ async function unseal(value, rawKey, context, limit = DESIGN_WORKSPACE_MAX_BYTES
870
870
  );
871
871
  return JSON.parse(decoder.decode(plaintext));
872
872
  }
873
+ var PACKED_BUNDLE_KIND = "openplanr-design-review-bundle-packed";
874
+ var PACKED_BUNDLE_MAX_BYTES = 128 * 1024 * 1024;
875
+ var SHARED_BLOCK_MIN_LENGTH = 2048;
876
+ var sharedBlockPattern = /(<(script|style)\b[^>]*>)([\s\S]*?)<\/\2\s*>/gi;
877
+ async function deflateRaw(bytes) {
878
+ const stream = new Blob([bytes]).stream().pipeThrough(new CompressionStream("deflate-raw"));
879
+ return new Uint8Array(await new Response(stream).arrayBuffer());
880
+ }
881
+ async function inflateRaw(bytes, limit) {
882
+ const reader = new Blob([bytes]).stream().pipeThrough(new DecompressionStream("deflate-raw")).getReader();
883
+ const chunks = [];
884
+ let size = 0;
885
+ for (; ; ) {
886
+ const { done, value } = await reader.read();
887
+ if (done) break;
888
+ size += value.byteLength;
889
+ if (size > limit) {
890
+ await reader.cancel();
891
+ throw new RangeError("The shared design expands beyond its size limit.");
892
+ }
893
+ chunks.push(value);
894
+ }
895
+ const inflated = new Uint8Array(size);
896
+ let offset = 0;
897
+ for (const chunk of chunks) {
898
+ inflated.set(chunk, offset);
899
+ offset += chunk.byteLength;
900
+ }
901
+ return inflated;
902
+ }
903
+ async function packDesignReviewBundle(bundle) {
904
+ const pages = [];
905
+ const pageIndex = /* @__PURE__ */ new Map();
906
+ const blocks = [];
907
+ const blockIndex = /* @__PURE__ */ new Map();
908
+ const segmentsOf = (html) => {
909
+ const segments = [];
910
+ let offset = 0;
911
+ for (const match of html.matchAll(sharedBlockPattern)) {
912
+ const body = match[3];
913
+ if (body.length < SHARED_BLOCK_MIN_LENGTH) continue;
914
+ const start = match.index + match[1].length;
915
+ segments.push(html.slice(offset, start));
916
+ if (!blockIndex.has(body)) blockIndex.set(body, blocks.push(body) - 1);
917
+ segments.push(blockIndex.get(body));
918
+ offset = start + body.length;
919
+ }
920
+ segments.push(html.slice(offset));
921
+ return segments;
922
+ };
923
+ const artifactPages = [];
924
+ const artifacts = bundle.envelope.artifacts.map(({ html, ...artifact }) => {
925
+ if (!pageIndex.has(html)) pageIndex.set(html, pages.push(segmentsOf(html)) - 1);
926
+ artifactPages.push(pageIndex.get(html));
927
+ return artifact;
928
+ });
929
+ const packed = {
930
+ bundle: { ...bundle, envelope: { ...bundle.envelope, artifacts } },
931
+ artifactPages,
932
+ pages,
933
+ blocks
934
+ };
935
+ return {
936
+ kind: PACKED_BUNDLE_KIND,
937
+ version: 1,
938
+ data: encodeWorkspaceBytes(await deflateRaw(encoder.encode(JSON.stringify(packed))))
939
+ };
940
+ }
941
+ async function unpackDesignReviewBundle(value, { maxBytes = PACKED_BUNDLE_MAX_BYTES } = {}) {
942
+ if (value?.kind !== PACKED_BUNDLE_KIND) return value;
943
+ if (value.version !== 1 || typeof value.data !== "string")
944
+ throw new Error("The shared design uses an unsupported packing.");
945
+ const { bundle, artifactPages, pages, blocks } = JSON.parse(
946
+ decoder.decode(await inflateRaw(decodeWorkspaceBytes(value.data), maxBytes))
947
+ );
948
+ const invalid2 = () => new Error("The shared design packing is invalid.");
949
+ if (!Array.isArray(bundle?.envelope?.artifacts) || !Array.isArray(pages) || !Array.isArray(blocks) || !Array.isArray(artifactPages) || artifactPages.length !== bundle.envelope.artifacts.length)
950
+ throw invalid2();
951
+ let expanded = 0;
952
+ const html = pages.map((segments) => {
953
+ if (!Array.isArray(segments)) throw invalid2();
954
+ const page = segments.map((segment) => {
955
+ if (typeof segment === "string") return segment;
956
+ if (!Number.isInteger(segment) || typeof blocks[segment] !== "string") throw invalid2();
957
+ return blocks[segment];
958
+ }).join("");
959
+ expanded += page.length;
960
+ if (expanded > maxBytes)
961
+ throw new RangeError("The shared design expands beyond its size limit.");
962
+ return page;
963
+ });
964
+ const artifacts = bundle.envelope.artifacts.map((artifact, index) => {
965
+ const page = html[artifactPages[index]];
966
+ if (page === void 0) throw invalid2();
967
+ return { ...artifact, html: page };
968
+ });
969
+ return { ...bundle, envelope: { ...bundle.envelope, artifacts } };
970
+ }
873
971
  var keyringContext = (id, epoch) => ({ type: "keyring", workspaceId: id, epoch });
874
972
  var revisionContext = (id, revision) => ({
875
973
  type: "revision",
@@ -914,7 +1012,7 @@ async function prepareRevision(custody, bundle) {
914
1012
  {
915
1013
  ...header,
916
1014
  ...await seal(
917
- bundle,
1015
+ await packDesignReviewBundle(bundle),
918
1016
  decodeWorkspaceBytes(custody.keys[custody.epoch]),
919
1017
  revisionContext(custody.id, header)
920
1018
  )
@@ -1084,10 +1182,12 @@ async function decryptWorkspaceRevision(access, revisionId = access.currentRevis
1084
1182
  throw new Error("The published design signature is invalid.");
1085
1183
  if (!access.keys[revision.epoch]) throw new Error("The access token cannot open this revision.");
1086
1184
  const bundle = assertDesignReviewBundle(
1087
- await unseal(
1088
- revision,
1089
- decodeWorkspaceBytes(access.keys[revision.epoch]),
1090
- revisionContext(access.id, revision)
1185
+ await unpackDesignReviewBundle(
1186
+ await unseal(
1187
+ revision,
1188
+ decodeWorkspaceBytes(access.keys[revision.epoch]),
1189
+ revisionContext(access.id, revision)
1190
+ )
1091
1191
  )
1092
1192
  );
1093
1193
  if (workspaceEnvelopeDigest(bundle.envelope) !== revision.reviewOf)
@@ -4,14 +4,14 @@
4
4
  "name": "OpenPlanr"
5
5
  },
6
6
  "metadata": {
7
- "version": "2.2640.3",
7
+ "version": "2.2640.4",
8
8
  "description": "Generated local OpenPlanr package."
9
9
  },
10
10
  "plugins": [
11
11
  {
12
12
  "name": "planr",
13
13
  "source": "./openplanr",
14
- "version": "2.2640.3",
14
+ "version": "2.2640.4",
15
15
  "description": "Close the loop from intent to delivery. Plan, design, build, review, and operate from durable context in your repository.",
16
16
  "strict": true
17
17
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "planr",
3
- "version": "2.2640.3",
3
+ "version": "2.2640.4",
4
4
  "description": "Close the loop from intent to delivery. Plan, design, build, review, and operate from durable context in your repository.",
5
5
  "author": {
6
6
  "name": "OpenPlanr",
@@ -8,7 +8,7 @@
8
8
  "files": [
9
9
  {
10
10
  "path": ".codex-plugin/plugin.json",
11
- "digest": "sha256:ea83220e864463636d46980c966cd739ce594e150a36700a554f7fe659132e21"
11
+ "digest": "sha256:437eb0e6b5c4d08bd00c86db0d537c7253f0aead4b73157bef4fcea76b2fb706"
12
12
  },
13
13
  {
14
14
  "path": "skills/artifact/agents/openai.yaml",
@@ -356,7 +356,7 @@
356
356
  },
357
357
  {
358
358
  "path": "skills/design-loop/scripts/design-share.mjs",
359
- "digest": "sha256:b10d7ce9cdb3eb48b9aca803e4d2ecc4f8e477e91f4a0c6a3ae17a1f7985aa06"
359
+ "digest": "sha256:11de427bd02b89fdf6df5b3d8eaffa7c2025ab841712c7dfc0da6e5a3e41ca36"
360
360
  },
361
361
  {
362
362
  "path": "skills/design-loop/scripts/design.mjs",
@@ -572,7 +572,7 @@
572
572
  },
573
573
  {
574
574
  "path": "skills/design-review/scripts/design-share.mjs",
575
- "digest": "sha256:b10d7ce9cdb3eb48b9aca803e4d2ecc4f8e477e91f4a0c6a3ae17a1f7985aa06"
575
+ "digest": "sha256:11de427bd02b89fdf6df5b3d8eaffa7c2025ab841712c7dfc0da6e5a3e41ca36"
576
576
  },
577
577
  {
578
578
  "path": "skills/design-review/scripts/design.mjs",
@@ -788,7 +788,7 @@
788
788
  },
789
789
  {
790
790
  "path": "skills/design/scripts/design-share.mjs",
791
- "digest": "sha256:b10d7ce9cdb3eb48b9aca803e4d2ecc4f8e477e91f4a0c6a3ae17a1f7985aa06"
791
+ "digest": "sha256:11de427bd02b89fdf6df5b3d8eaffa7c2025ab841712c7dfc0da6e5a3e41ca36"
792
792
  },
793
793
  {
794
794
  "path": "skills/design/scripts/design.mjs",
@@ -1092,7 +1092,7 @@
1092
1092
  },
1093
1093
  {
1094
1094
  "path": "skills/plan/scripts/design-share.mjs",
1095
- "digest": "sha256:b10d7ce9cdb3eb48b9aca803e4d2ecc4f8e477e91f4a0c6a3ae17a1f7985aa06"
1095
+ "digest": "sha256:11de427bd02b89fdf6df5b3d8eaffa7c2025ab841712c7dfc0da6e5a3e41ca36"
1096
1096
  },
1097
1097
  {
1098
1098
  "path": "skills/plan/scripts/design.mjs",
@@ -1355,5 +1355,5 @@
1355
1355
  "digest": "sha256:06048f24128098919931db60272e0e14fe51bcbeba4b499db587e3b89d7bb3b9"
1356
1356
  }
1357
1357
  ],
1358
- "contentDigest": "sha256:d0db0f58a2795daac47409b796c89ff4eb00e30e1e70f83b9b227ba668915775"
1358
+ "contentDigest": "sha256:73a9e02cd409d49ef4b92f87c00840c4692ff23d6298210e50d92f80e7c91115"
1359
1359
  }