Repository: hashintel/hash
Pull request #7189: H-4579: Cleanup `test:unit` command
Author: login: indietyp
Labels: name: area/libs > error-stack
description: Affects the `error-stack` crate (library)
name: area/libs
description: Relates to first-party libraries/crates/packages (area)
name: type/eng > backend
description: Owned by the @backend team
name: area/tests
description: New or updated tests
Created: 2025-05-19T08:34:06Z | Merged: 2025-05-19T10:21:39Z

## 🌟 What is the purpose of this PR?

Enable `test:unit` for `hash-graph-authorization` and `hash-graph-postgres-store`, as these need special nextest flags they currently can't make use of the mise `test:unit` task. Change this by adding the required options to the task.

Additionally cleans up several aspects of the initial script, centralizing most of the handling and enabling new use-cases.

## Pre-Merge Checklist 🚀

### 🚢 Has this modified a publishable library?

<!-- Confirm you have taken the necessary action to record a changeset or publish a change, as appropriate -->
<!-- Tick AT LEAST ONE box and delete the rest. Do not delete this section! see libs/README.md for info on publishing -->

This PR:

- [x] does not modify any publishable blocks or libraries, or modifications do not need publishing


### 📜 Does this require a change to the docs?

<!-- If this adds a user facing feature or modifies how an existing feature is used, it likely needs a docs change. -->
<!-- Tick ONE box and delete the rest. Do not delete this section! -->

The changes in this PR:

- [x] are internal and do not require a docs change


### 🕸️ Does this require a change to the Turbo Graph?

<!-- If this adds or moves an existing package, modifies `scripts` in a `package.json`, it likely needs a turbo graph change. -->
<!-- Tick ONE box and delete the rest. Do not delete this section! -->

The changes in this PR:

- [x] do not affect the execution graph



Diff:
diff --git a/.config/mise/tasks/test/unit.sh b/.config/mise/tasks/test/unit.sh
index dc9f4d97a65..78366106e10 100755
--- a/.config/mise/tasks/test/unit.sh
+++ b/.config/mise/tasks/test/unit.sh
@@ -3,14 +3,16 @@
 set -euo pipefail
 
 #USAGE flag "--coverage" negate="--no-coverage" default="false" help="Run unit tests with coverage, also reads `$TEST_COVERAGE`"
-#USAGE flag "--powerset" negate="--no-powerset" default="false" help="Run unit tests with powerset, also reads `$TEST_POWERSET`"
+#USAGE flag "--test-strategy <strategy>" default="all" help="The test strategy to use, use all if you just want to test with all features enabled (default), extremes if you want to test against all features and no features enabled, powerset if you want to test against all possible combinations of features" {
+#USAGE          choices "all" "extremes" "powerset"
+#USAGE }
 #USAGE arg "<package>" help="The package to run unit tests for"
 #USAGE arg "[arguments]..." double_dash="required" default="" help="Additional arguments to pass to the test runner"
 
 PACKAGE=$usage_package
 COVERAGE=$usage_coverage
-POWERSET=$usage_powerset
-ARGUMENTS=$usage_arguments
+STRATEGY=$usage_test_strategy
+declare -a "ARGUMENTS=($usage_arguments)" # We're using "declare -a" here to allow for quoted arguments to be properly parsed as single array elements
 
 # Check if the package argument starts with `@rust/` if that isn't the case exit out
 if [[ $PACKAGE != "@rust/"* ]]; then
@@ -21,6 +23,37 @@ fi
 # Remove the package namespace from the package to get the crate name
 CRATE=${PACKAGE#*@rust/}
 
+declare -a COMMON_ARGUMENTS
+COMMON_ARGUMENTS+=("-p" "$CRATE")
+
+declare -a HACK_ARGUMENTS
+HACK_ARGUMENTS+=("${COMMON_ARGUMENTS[@]}")
+
+declare -a NEXTEST_ARGUMENTS
+NEXTEST_ARGUMENTS+=("${COMMON_ARGUMENTS[@]}")
+
+declare -a LLVM_COV_ARGUMENTS
+LLVM_COV_ARGUMENTS+=("${COMMON_ARGUMENTS[@]}")
+
+case $STRATEGY in
+    "all")
+        NEXTEST_ARGUMENTS+=("--all-features")
+        ;;
+    "extremes")
+        # find the features for this crate, so that we can enable all
+        FEATURES=$(cargo metadata --format-version=1 --no-deps | jq -r --arg crate "$CRATE" '.packages[] | select(.name == $crate) | .features | keys | join(",")')
+
+        HACK_ARGUMENTS+=("--feature-powerset" "--depth=1" "--group-features" "$FEATURES")
+        ;;
+    "powerset")
+        HACK_ARGUMENTS+=("--optional-deps" "--feature-powerset")
+        ;;
+    *)
+        echo "Error: Invalid strategy '$STRATEGY'"
+        exit 1
+        ;;
+esac
+
 # Run coverage instead of unit tests if `TEST_COVERAGE` is set to `true` or `1`
 if [[ $COVERAGE == "true" || ${TEST_COVERAGE:-false} == 'true' || ${TEST_COVERAGE:-false} == '1' ]]; then
     # Exclude any crates that are not the current crate, this is required due to a limitation of llvm-cov, which doesn't allow
@@ -33,34 +66,23 @@ if [[ $COVERAGE == "true" || ${TEST_COVERAGE:-false} == 'true' || ${TEST_COVERAG
             | paste -sd "|" -
     )
 
+    LLVM_COV_ARGUMENTS+=("--ignore-filename-regex" "$EXCLUSIONS" "--branch")
+
+    declare -a LLVM_COV_REPORT_ARGUMENTS
+
     # under CI we use LCOV
     if [[ ${CI:-0} == "1" || ${CI:-0} == "true" ]]; then
-        REPORT_FLAGS="--lcov --output-path lcov.info"
-    else
-        REPORT_FLAGS="--html --open"
-    fi
-
-    if [[ $POWERSET == "true" || ${TEST_POWERSET:-false} == 'true' || ${TEST_POWERSET:-false} == '1' ]]; then
-        CARGO_COMMAND="hack --optional-deps --feature-powerset"
-        NEXTEST_ARGS=""
+        LLVM_COV_REPORT_ARGUMENTS+=("--lcov" "--output-path" "lcov.info")
     else
-        CARGO_COMMAND=""
-        NEXTEST_ARGS="--all-features"
+        LLVM_COV_REPORT_ARGUMENTS+=("--html" "--open")
     fi
 
     cargo llvm-cov clean --workspace
-    cargo $CARGO_COMMAND llvm-cov --ignore-filename-regex "$EXCLUSIONS" -p "$CRATE" --branch --no-report nextest $NEXTEST_ARGS --all-targets --cargo-profile coverage $ARGUMENTS
-    cargo llvm-cov --ignore-filename-regex "$EXCLUSIONS" -p "$CRATE" --branch --no-clean $REPORT_FLAGS --doctests test --all-features --profile coverage --doc
-
-    exit 0
-fi
+    cargo hack "${HACK_ARGUMENTS[@]}" llvm-cov "${LLVM_COV_ARGUMENTS[@]}" --no-report nextest "${NEXTEST_ARGUMENTS[@]}" --cargo-profile coverage "${ARGUMENTS[@]}"
+    cargo llvm-cov "${LLVM_COV_ARGUMENTS[@]}" "${LLVM_COV_REPORT_ARGUMENTS[@]}" --no-clean --doctests test "${COMMON_ARGUMENTS[@]}" --all-features --profile coverage --doc
 
-# Run unit tests with powerset if `TEST_POWERSET` is set to `true` or `1`
-if [[ $POWERSET == "true" || ${TEST_POWERSET:-false} == 'true' || ${TEST_POWERSET:-false} == '1' ]]; then
-    cargo hack --optional-deps --feature-powerset nextest run -p "$CRATE" --all-targets $ARGUMENTS
-    cargo test --all-features --doc -p "$CRATE"
     exit 0
 fi
 
-cargo nextest run -p "$CRATE" --all-features --all-targets $ARGUMENTS
-cargo test --all-features --doc -p "$CRATE"
+cargo hack "${HACK_ARGUMENTS[@]}" nextest run "${NEXTEST_ARGUMENTS[@]}" "${ARGUMENTS[@]}"
+cargo test "${COMMON_ARGUMENTS[@]}" --all-features --doc
diff --git a/libs/@local/graph/authorization/package.json b/libs/@local/graph/authorization/package.json
index a216b749d51..ecba245d817 100644
--- a/libs/@local/graph/authorization/package.json
+++ b/libs/@local/graph/authorization/package.json
@@ -21,7 +21,7 @@
     "lint:clippy": "just clippy",
     "lint:tsc": "tsc --noEmit",
     "test:integration": "cargo hack nextest run --feature-powerset --all-targets --filterset \"kind(test) | kind(bench)\"",
-    "test:unit": "cargo hack nextest run --feature-powerset --all-targets --filterset \"not kind(test) & not kind(bench)\" && cargo test --all-features --doc"
+    "test:unit": "mise run test:unit @rust/hash-graph-authorization --test-strategy=powerset -- --all-targets --filterset 'not kind(test) & not kind(bench)'"
   },
   "dependencies": {
     "@blockprotocol/type-system-rs": "0.0.0-private",
diff --git a/libs/@local/graph/postgres-store/package.json b/libs/@local/graph/postgres-store/package.json
index 4c4843b3a0f..e95fe0db32c 100644
--- a/libs/@local/graph/postgres-store/package.json
+++ b/libs/@local/graph/postgres-store/package.json
@@ -8,7 +8,7 @@
     "fix:clippy": "just clippy --fix",
     "lint:clippy": "just clippy",
     "test:integration": "cargo hack nextest run --feature-powerset --tests",
-    "test:unit": "cargo hack nextest run --feature-powerset --lib && cargo test --all-features --doc"
+    "test:unit": "mise run test:unit @rust/hash-graph-postgres-store --test-strategy=powerset -- --lib"
   },
   "dependencies": {
     "@blockprotocol/type-system-rs": "0.0.0-private",
diff --git a/libs/error-stack/.justfile b/libs/error-stack/.justfile
old mode 100755
new mode 100644
index 9cf39b5954d..d7944c6197b
--- a/libs/error-stack/.justfile
+++ b/libs/error-stack/.justfile
@@ -14,37 +14,3 @@ repo := `git rev-parse --show-toplevel`
 clippy *arguments:
   @CLIPPY_CONF_DIR={{repo}} just in-pr cargo clippy --profile {{profile}} --all-features --all-targets --no-deps {{arguments}}
   @CLIPPY_CONF_DIR={{repo}} just not-in-pr cargo hack --optional-deps --feature-powerset {{cargo-hack-groups}} --ignore-unknown-features clippy --profile {{profile}} --all-targets --no-deps {{arguments}}
-
-[private]
-test *arguments:
-  RUST_BACKTRACE=1 cargo nextest run --all-features --all-targets {{arguments}}
-  RUST_BACKTRACE=1 cargo nextest run --no-default-features --all-targets {{arguments}}
-  RUST_BACKTRACE=1 cargo test --all-features --doc {{arguments}}
-
-[private]
-coverage *arguments:
-  RUST_BACKTRACE=1 cargo llvm-cov nextest --workspace --all-features --all-targets --cargo-profile coverage {{arguments}}
-  RUST_BACKTRACE=1 cargo llvm-cov --workspace --all-features --profile coverage --doc {{arguments}}
-
-# Snapshot Tests
-# ==============
-#
-# Several features make use of snapshots for acceptance/integration tests, these are files
-# with expected output for a specific input.
-# We use insta for tests https://github.com/mitsuhiko/insta and expect-test https://docs.rs/expect-test/latest/expect_test/ for doc tests.
-# expect-test enables us to directly include the snapshot in documentation, while insta provides a more complete feature-set.
-#
-# You should invoke this task whenever you change `test_debug`, a file which includes a doctest with `expect_test`, or change the formatting of a `Report`.
-#
-# Reviewing Tests
-# ---------------
-#
-# To review snapshots generated by insta install `cargo-insta` (https://github.com/mitsuhiko/insta) and invoke `cargo insta review`,
-# you will be led through all changes one-by-one and need to compare them to see if they are what you expected the outcome to be.
-#
-# To review snapshots generated by expect-test use gits diffing capabilities.
-
-# Runs the test suite and asks to update the snapshots if they don't match.
-update-snapshots:
-  @INSTA_FORCE_PASS=1 INSTA_UPDATE=new UPDATE_EXPECT=1 just test
-  @cargo insta review
diff --git a/libs/error-stack/package.json b/libs/error-stack/package.json
index d75dd8ad3ea..d6fd675fb81 100644
--- a/libs/error-stack/package.json
+++ b/libs/error-stack/package.json
@@ -8,7 +8,8 @@
     "fix:clippy": "just clippy --fix",
     "lint:clippy": "just clippy",
     "test:miri": "just miri",
-    "test:unit": "RUST_BACKTRACE=1 mise run test:unit @rust/error-stack"
+    "test:unit": "RUST_BACKTRACE=1 mise run test:unit @rust/error-stack --test-strategy=extremes",
+    "update-snapshots": "INSTA_FORCE_PASS=1 INSTA_UPDATE=new UPDATE_EXPECT=1 yarn test:unit"
   },
   "dependencies": {
     "@rust/error-stack-macros": "0.0.0-reserved-private"


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR updates the `test:unit` task across several Rust packages to use the centralized `mise` script with configurable test strategies, removes an old `justfile` in `error-stack`, and refactors the `unit.sh` script to handle coverage, powerset, and extremes strategies uniformly.

- Switch `test:unit` in multiple `package.json` files to invoke `mise run test:unit` with `--test-strategy`
- Remove the legacy `.justfile` from `error-stack` and consolidate logic into `unit.sh`
- Enhance `unit.sh` to parse a `--test-strategy` flag and build cargo/nextest arguments dynamically

### Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

<details>
<summary>Show a summary per file</summary>

| File                                               | Description                                          |
| -------------------------------------------------- | ---------------------------------------------------- |
| libs/error-stack/package.json                      | Updated `test:unit` to use `mise` with `extremes` strategy; adjusted snapshot script |
| libs/error-stack/.justfile                         | Removed legacy Justfile, migrating all tasks to `mise` |
| libs/@local/graph/postgres-store/package.json      | Updated `test:unit` to use `mise` with `powerset`    |
| libs/@local/graph/authorization/package.json       | Updated `test:unit` to use `mise` with `powerset`    |
| .config/mise/tasks/test/unit.sh                    | Refactored to handle `--test-strategy`, consolidated args arrays, updated coverage/run logic |
</details>



<details>
<summary>Comments suppressed due to low confidence (2)</summary>

**libs/error-stack/.justfile:1**
* [nitpick] The entire Justfile was removed. Please verify that no CI workflows or documentation still reference the old `just` commands and that all tasks have been fully migrated to `mise`.
```
-#!/usr/bin/env just --justfile
```
**.config/mise/tasks/test/unit.sh:15**
* The usage of quotes around the entire declaration will cause a syntax error. It should be:

declare -a ARGUMENTS=( $usage_arguments )

or to preserve arguments with spaces:

declare -a ARGUMENTS=("${usage_arguments[@]}")
```
declare -a "ARGUMENTS=($usage_arguments)"
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T09:00:55Z
user: login: indietyp
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-19T09:01:35Z
user: login: hashdotai
body: This PR is an excellent cleanup of the test:unit command implementation. The refactoring brings several benefits:

1. Better organization with clear separation of concerns using arrays for different argument groups
2. More robust handling of command-line arguments by using proper array syntax
3. Improved flexibility with the new strategy-based approach that accommodates different testing needs
4. Consistent command structure across different execution paths
5. Successfully enables the `test:unit` command for packages that previously couldn't use it

The introduction of the three test strategies (all, extremes, powerset) provides a flexible framework for different testing needs while maintaining consistency. The code is now more maintainable with centralized handling and reduced duplication.

The only suggestions I have are minor and mostly related to documentation that would help future developers understand the design choices. Overall, this is a well-executed refactoring that improves the developer experience.
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-19T09:10:21Z
user: login: indietyp
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-19T09:14:00Z
user: login: indietyp
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-19T09:14:06Z
user: login: TimDiekmann
body: Thank you very much for this!

Is there a way to avoid this CI output? If not it's not a real issue, just a nicety
<img width="1234" alt="image" src="https://github.com/user-attachments/assets/ac1be28b-10e7-4399-9976-6dfe3bceda72" />

state: DISMISSED
author_association: MEMBER
submitted_at: 2025-05-19T09:27:39Z
user: login: indietyp
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-19T09:32:32Z
user: login: indietyp
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-19T09:35:02Z
user: login: indietyp
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-19T09:36:21Z
user: login: TimDiekmann
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-19T09:41:59Z

Review comments:
diff_hunk: @@ -8,7 +8,8 @@
     "fix:clippy": "just clippy --fix",
     "lint:clippy": "just clippy",
     "test:miri": "just miri",
-    "test:unit": "RUST_BACKTRACE=1 mise run test:unit @rust/error-stack"
+    "test:unit": "RUST_BACKTRACE=1 mise run test:unit @rust/error-stack --test-strategy=extremes",
+    "update-snapshots": "INSTA_FORCE_PASS=1 INSTA_UPDATE=new UPDATE_EXPECT=1 yarn test:unit"
path: libs/error-stack/package.json
user: login: Copilot
body: [nitpick] This package’s snapshot update script uses `yarn test:unit` rather than `mise run test:unit @rust/error-stack`. For consistency with other packages, consider invoking the centralized `mise` task instead of `yarn` directly.
```suggestion
    "update-snapshots": "INSTA_FORCE_PASS=1 INSTA_UPDATE=new UPDATE_EXPECT=1 mise run test:unit @rust/error-stack"
```
created_at: 2025-05-19T09:00:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,7 +8,8 @@
     "fix:clippy": "just clippy --fix",
     "lint:clippy": "just clippy",
     "test:miri": "just miri",
-    "test:unit": "RUST_BACKTRACE=1 mise run test:unit @rust/error-stack"
+    "test:unit": "RUST_BACKTRACE=1 mise run test:unit @rust/error-stack --test-strategy=extremes",
+    "update-snapshots": "INSTA_FORCE_PASS=1 INSTA_UPDATE=new UPDATE_EXPECT=1 yarn test:unit"
path: libs/error-stack/package.json
user: login: indietyp
body: that's intended, so that we don't duplicate the test arguments...
created_at: 2025-05-19T09:01:35Z
author_association: MEMBER
diff_hunk: @@ -3,14 +3,16 @@
 set -euo pipefail
 
 #USAGE flag "--coverage" negate="--no-coverage" default="false" help="Run unit tests with coverage, also reads `$TEST_COVERAGE`"
-#USAGE flag "--powerset" negate="--no-powerset" default="false" help="Run unit tests with powerset, also reads `$TEST_POWERSET`"
+#USAGE flag "--test-strategy <strategy>" default="all" help="The test strategy to use" {
+#USAGE          choices "all" "extremes" "powerset"
+#USAGE }
 #USAGE arg "<package>" help="The package to run unit tests for"
 #USAGE arg "[arguments]..." double_dash="required" default="" help="Additional arguments to pass to the test runner"
 
 PACKAGE=$usage_package
 COVERAGE=$usage_coverage
-POWERSET=$usage_powerset
-ARGUMENTS=$usage_arguments
+STRATEGY=$usage_test_strategy
+declare -a "ARGUMENTS=($usage_arguments)"
path: .config/mise/tasks/test/unit.sh
user: login: hashdotai
body: Consider adding a comment explaining what the `declare -a` is doing here and why it's different from the previous implementation. This syntax creates an array from the arguments, which is more robust for handling spaces in arguments.
created_at: 2025-05-19T09:10:20Z
author_association: MEMBER
diff_hunk: @@ -21,6 +23,37 @@ fi
 # Remove the package namespace from the package to get the crate name
 CRATE=${PACKAGE#*@rust/}
 
+declare -a COMMON_ARGUMENTS
+COMMON_ARGUMENTS+=("-p" "$CRATE")
+
+declare -a HACK_ARGUMENTS
+HACK_ARGUMENTS+=("${COMMON_ARGUMENTS[@]}")
+
+declare -a NEXTEST_ARGUMENTS
+NEXTEST_ARGUMENTS+=("${COMMON_ARGUMENTS[@]}")
+
+declare -a LLVM_COV_ARGUMENTS
+LLVM_COV_ARGUMENTS+=("${COMMON_ARGUMENTS[@]}")
+
+case $STRATEGY in
+    "all")
+        NEXTEST_ARGUMENTS+=("--all-features")
+        ;;
+    "extremes")
+        # find the features for this crate, so that we can enable all
+        FEATURES=$(cargo metadata --format-version=1 --no-deps | jq -r --arg crate "$CRATE" '.packages[] | select(.name == $crate) | .features | keys | join(",")')
+
+        HACK_ARGUMENTS+=("--feature-powerset" "--depth=1" "--group-features" "$FEATURES")
+        ;;
+    "powerset")
+        HACK_ARGUMENTS+=("--optional-deps" "--feature-powerset")
+        ;;
+    *)
+        echo "Error: Invalid strategy '$STRATEGY'"
+        exit 1
+        ;;
+esac
path: .config/mise/tasks/test/unit.sh
user: login: hashdotai
body: The strategy implementation is a good improvement, but it would be helpful to have a brief comment at the top of the file explaining the different strategies and when each should be used.
created_at: 2025-05-19T09:10:20Z
author_association: MEMBER
diff_hunk: @@ -33,34 +66,23 @@ if [[ $COVERAGE == "true" || ${TEST_COVERAGE:-false} == 'true' || ${TEST_COVERAG
             | paste -sd "|" -
     )
 
+    LLVM_COV_ARGUMENTS+=("--ignore-filename-regex" "$EXCLUSIONS" "--branch")
+
+    declare -a LLVM_COV_REPORT_ARGUMENTS
+
     # under CI we use LCOV
     if [[ ${CI:-0} == "1" || ${CI:-0} == "true" ]]; then
-        REPORT_FLAGS="--lcov --output-path lcov.info"
-    else
-        REPORT_FLAGS="--html --open"
-    fi
-
-    if [[ $POWERSET == "true" || ${TEST_POWERSET:-false} == 'true' || ${TEST_POWERSET:-false} == '1' ]]; then
-        CARGO_COMMAND="hack --optional-deps --feature-powerset"
-        NEXTEST_ARGS=""
+        LLVM_COV_REPORT_ARGUMENTS+=("--lcov" "--output-path" "lcov.info")
     else
-        CARGO_COMMAND=""
-        NEXTEST_ARGS="--all-features"
+        LLVM_COV_REPORT_ARGUMENTS+=("--html" "--open")
     fi
 
     cargo llvm-cov clean --workspace
-    cargo $CARGO_COMMAND llvm-cov --ignore-filename-regex "$EXCLUSIONS" -p "$CRATE" --branch --no-report nextest $NEXTEST_ARGS --all-targets --cargo-profile coverage $ARGUMENTS
-    cargo llvm-cov --ignore-filename-regex "$EXCLUSIONS" -p "$CRATE" --branch --no-clean $REPORT_FLAGS --doctests test --all-features --profile coverage --doc
-
-    exit 0
-fi
+    cargo hack "${HACK_ARGUMENTS[@]}" llvm-cov "${LLVM_COV_ARGUMENTS[@]}" --no-report nextest "${NEXTEST_ARGUMENTS[@]}" --cargo-profile coverage "${ARGUMENTS[@]}"
path: .config/mise/tasks/test/unit.sh
user: login: hashdotai
body: This refactoring significantly improves readability and maintainability by using consistent array variable references rather than string concatenation. Great improvement!
created_at: 2025-05-19T09:10:21Z
author_association: MEMBER
diff_hunk: @@ -33,34 +66,23 @@ if [[ $COVERAGE == "true" || ${TEST_COVERAGE:-false} == 'true' || ${TEST_COVERAG
             | paste -sd "|" -
     )
 
+    LLVM_COV_ARGUMENTS+=("--ignore-filename-regex" "$EXCLUSIONS" "--branch")
+
+    declare -a LLVM_COV_REPORT_ARGUMENTS
+
     # under CI we use LCOV
     if [[ ${CI:-0} == "1" || ${CI:-0} == "true" ]]; then
-        REPORT_FLAGS="--lcov --output-path lcov.info"
-    else
-        REPORT_FLAGS="--html --open"
-    fi
-
-    if [[ $POWERSET == "true" || ${TEST_POWERSET:-false} == 'true' || ${TEST_POWERSET:-false} == '1' ]]; then
-        CARGO_COMMAND="hack --optional-deps --feature-powerset"
-        NEXTEST_ARGS=""
+        LLVM_COV_REPORT_ARGUMENTS+=("--lcov" "--output-path" "lcov.info")
     else
-        CARGO_COMMAND=""
-        NEXTEST_ARGS="--all-features"
+        LLVM_COV_REPORT_ARGUMENTS+=("--html" "--open")
     fi
 
     cargo llvm-cov clean --workspace
-    cargo $CARGO_COMMAND llvm-cov --ignore-filename-regex "$EXCLUSIONS" -p "$CRATE" --branch --no-report nextest $NEXTEST_ARGS --all-targets --cargo-profile coverage $ARGUMENTS
-    cargo llvm-cov --ignore-filename-regex "$EXCLUSIONS" -p "$CRATE" --branch --no-clean $REPORT_FLAGS --doctests test --all-features --profile coverage --doc
-
-    exit 0
-fi
+    cargo hack "${HACK_ARGUMENTS[@]}" llvm-cov "${LLVM_COV_ARGUMENTS[@]}" --no-report nextest "${NEXTEST_ARGUMENTS[@]}" --cargo-profile coverage "${ARGUMENTS[@]}"
+    cargo llvm-cov "${LLVM_COV_ARGUMENTS[@]}" "${LLVM_COV_REPORT_ARGUMENTS[@]}" --no-clean --doctests test "${COMMON_ARGUMENTS[@]}" --all-features --profile coverage --doc
 
-# Run unit tests with powerset if `TEST_POWERSET` is set to `true` or `1`
-if [[ $POWERSET == "true" || ${TEST_POWERSET:-false} == 'true' || ${TEST_POWERSET:-false} == '1' ]]; then
-    cargo hack --optional-deps --feature-powerset nextest run -p "$CRATE" --all-targets $ARGUMENTS
-    cargo test --all-features --doc -p "$CRATE"
     exit 0
 fi
 
-cargo nextest run -p "$CRATE" --all-features --all-targets $ARGUMENTS
-cargo test --all-features --doc -p "$CRATE"
+cargo hack "${HACK_ARGUMENTS[@]}" nextest run "${NEXTEST_ARGUMENTS[@]}" "${ARGUMENTS[@]}"
path: .config/mise/tasks/test/unit.sh
user: login: hashdotai
body: The consistency achieved by using the same pattern for all test commands is excellent. This will make future maintenance much easier.
created_at: 2025-05-19T09:10:21Z
author_association: MEMBER
diff_hunk: @@ -8,7 +8,8 @@
     "fix:clippy": "just clippy --fix",
     "lint:clippy": "just clippy",
     "test:miri": "just miri",
-    "test:unit": "RUST_BACKTRACE=1 mise run test:unit @rust/error-stack"
+    "test:unit": "RUST_BACKTRACE=1 mise run test:unit @rust/error-stack --test-strategy=extremes",
path: libs/error-stack/package.json
user: login: hashdotai
body: Good choice using the `extremes` strategy here. It makes sense given the feature structure of error-stack with its many feature combinations.
created_at: 2025-05-19T09:10:21Z
author_association: MEMBER
diff_hunk: @@ -21,6 +23,37 @@ fi
 # Remove the package namespace from the package to get the crate name
 CRATE=${PACKAGE#*@rust/}
 
+declare -a COMMON_ARGUMENTS
+COMMON_ARGUMENTS+=("-p" "$CRATE")
+
+declare -a HACK_ARGUMENTS
+HACK_ARGUMENTS+=("${COMMON_ARGUMENTS[@]}")
+
+declare -a NEXTEST_ARGUMENTS
+NEXTEST_ARGUMENTS+=("${COMMON_ARGUMENTS[@]}")
+
+declare -a LLVM_COV_ARGUMENTS
+LLVM_COV_ARGUMENTS+=("${COMMON_ARGUMENTS[@]}")
+
+case $STRATEGY in
+    "all")
+        NEXTEST_ARGUMENTS+=("--all-features")
+        ;;
+    "extremes")
+        # find the features for this crate, so that we can enable all
+        FEATURES=$(cargo metadata --format-version=1 --no-deps | jq -r --arg crate "$CRATE" '.packages[] | select(.name == $crate) | .features | keys | join(",")')
+
+        HACK_ARGUMENTS+=("--feature-powerset" "--depth=1" "--group-features" "$FEATURES")
+        ;;
+    "powerset")
+        HACK_ARGUMENTS+=("--optional-deps" "--feature-powerset")
+        ;;
+    *)
+        echo "Error: Invalid strategy '$STRATEGY'"
+        exit 1
+        ;;
+esac
path: .config/mise/tasks/test/unit.sh
user: login: indietyp
body: thanks bud, done in [373f376](https://github.com/hashintel/hash/pull/7189/commits/373f3769c1a275cc5ce66317f236fd9d8095dff3)
created_at: 2025-05-19T09:14:00Z
author_association: MEMBER
diff_hunk: @@ -3,14 +3,16 @@
 set -euo pipefail
 
 #USAGE flag "--coverage" negate="--no-coverage" default="false" help="Run unit tests with coverage, also reads `$TEST_COVERAGE`"
-#USAGE flag "--powerset" negate="--no-powerset" default="false" help="Run unit tests with powerset, also reads `$TEST_POWERSET`"
+#USAGE flag "--test-strategy <strategy>" default="all" help="The test strategy to use" {
+#USAGE          choices "all" "extremes" "powerset"
+#USAGE }
 #USAGE arg "<package>" help="The package to run unit tests for"
 #USAGE arg "[arguments]..." double_dash="required" default="" help="Additional arguments to pass to the test runner"
 
 PACKAGE=$usage_package
 COVERAGE=$usage_coverage
-POWERSET=$usage_powerset
-ARGUMENTS=$usage_arguments
+STRATEGY=$usage_test_strategy
+declare -a "ARGUMENTS=($usage_arguments)"
path: .config/mise/tasks/test/unit.sh
user: login: indietyp
body: thanks done in [373f376](https://github.com/hashintel/hash/pull/7189/commits/373f3769c1a275cc5ce66317f236fd9d8095dff3)
created_at: 2025-05-19T09:14:06Z
author_association: MEMBER
path: libs/error-stack/.justfile
user: login: TimDiekmann
body: Will the deletion of this file be an issue for the `clippy` commands?
created_at: 2025-05-19T09:19:43Z
author_association: MEMBER
path: libs/error-stack/.justfile
user: login: indietyp
body: I don't think we're actually not relying on `lint:clippy` in CI, the only difference would be that when executing `just lint:clippy` locally it'll use the powerset without the groupings. I can re-add the file though if desired!
created_at: 2025-05-19T09:32:32Z
author_association: MEMBER
path: libs/error-stack/.justfile
user: login: indietyp
body: actually, it'll be an issue in the merge-queue!
created_at: 2025-05-19T09:35:02Z
author_association: MEMBER
path: libs/error-stack/.justfile
user: login: indietyp
body: reverted deletion for clippy in [02f2a9b](https://github.com/hashintel/hash/pull/7189/commits/02f2a9b6ddc04c519f28ac449727bcce011d0466)
created_at: 2025-05-19T09:36:21Z
author_association: MEMBER

PR comments:
user: login: codecov[bot]
created_at: 2025-05-19T08:42:11Z
body: ## [Codecov](https://app.codecov.io/gh/hashintel/hash/pull/7189?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hashintel) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 54.36%. Comparing base [(`9cdaaec`)](https://app.codecov.io/gh/hashintel/hash/commit/9cdaaeca48e921a0e03b87c54c6afdc70b07db4d?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hashintel) to head [(`fab596d`)](https://app.codecov.io/gh/hashintel/hash/commit/fab596d115ad458f066c4e7e440a85f75be56666?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hashintel).
> Report is 3 commits behind head on main.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #7189      +/-   ##
==========================================
- Coverage   61.85%   54.36%   -7.49%     
==========================================
  Files         926     1038     +112     
  Lines       74420    93328   +18908     
  Branches     4121     4263     +142     
==========================================
+ Hits        46033    50739    +4706     
- Misses      27576    41712   +14136     
- Partials      811      877      +66     
```

| [Flag](https://app.codecov.io/gh/hashintel/hash/pull/7189/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hashintel) | Coverage Δ | |
|---|---|---|
| [rust.hash-graph-api](https://app.codecov.io/gh/hashintel/hash/pull/7189/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hashintel) | `5.09% <ø> (ø)` | |
| [rust.hash-graph-authorization](https://app.codecov.io/gh/hashintel/hash/pull/7189/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hashintel) | `28.83% <ø> (?)` | |
| [rust.hash-graph-postgres-store](https://app.codecov.io/gh/hashintel/hash/pull/7189/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hashintel) | `22.28% <ø> (?)` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hashintel#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/hashintel/hash/pull/7189?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hashintel).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=hashintel).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE
user: login: indietyp
created_at: 2025-05-19T09:32:52Z
body: re: output - sadly not I need to give it all of the mappings, there's no way around it :/
author_association: MEMBER
user: login: github-actions[bot]
created_at: 2025-05-19T10:23:27Z
body: <!-- add-pr-comment:benchmark-results -->

## Benchmark results
<details><summary><h2>@rust/hash-graph-benches – Integrations</h2></summary>

## scaling_read_entity_complete_one_depth

| Function | Value | Mean | Flame graphs | 
|----------|-------|------|--------------|
| entity_by_id | 25 entities | $$183 \mathrm{ms} \pm 917 \mathrm{μs}\left({\color{gray}2.72 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_complete_one_depth/entity_by_id/25+entities/flamegraph.svg) |
| entity_by_id | 10 entities | $$57.7 \mathrm{ms} \pm 203 \mathrm{μs}\left({\color{gray}1.30 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_complete_one_depth/entity_by_id/10+entities/flamegraph.svg) |
| entity_by_id | 50 entities | $$272 \mathrm{ms} \pm 2.90 \mathrm{ms}\left({\color{lightgreen}-94.984 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_complete_one_depth/entity_by_id/50+entities/flamegraph.svg) |
| entity_by_id | 1 entities | $$21.2 \mathrm{ms} \pm 63.8 \mathrm{μs}\left({\color{gray}-1.741 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_complete_one_depth/entity_by_id/1+entities/flamegraph.svg) |
| entity_by_id | 5 entities | $$27.9 \mathrm{ms} \pm 278 \mathrm{μs}\left({\color{gray}0.236 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_complete_one_depth/entity_by_id/5+entities/flamegraph.svg) |


## scaling_read_entity_linkless

| Function | Value | Mean | Flame graphs | 
|----------|-------|------|--------------|
| entity_by_id | 10000 entities | $$9.18 \mathrm{ms} \pm 88.7 \mathrm{μs}\left({\color{gray}-1.550 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_linkless/entity_by_id/10000+entities/flamegraph.svg) |
| entity_by_id | 1000 entities | $$2.99 \mathrm{ms} \pm 12.6 \mathrm{μs}\left({\color{gray}-3.396 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_linkless/entity_by_id/1000+entities/flamegraph.svg) |
| entity_by_id | 10 entities | $$2.08 \mathrm{ms} \pm 9.72 \mathrm{μs}\left({\color{gray}0.808 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_linkless/entity_by_id/10+entities/flamegraph.svg) |
| entity_by_id | 1 entities | $$2.05 \mathrm{ms} \pm 7.85 \mathrm{μs}\left({\color{gray}-0.684 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_linkless/entity_by_id/1+entities/flamegraph.svg) |
| entity_by_id | 100 entities | $$2.25 \mathrm{ms} \pm 9.18 \mathrm{μs}\left({\color{gray}-0.476 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_linkless/entity_by_id/100+entities/flamegraph.svg) |


## representative_read_multiple_entities

| Function | Value | Mean | Flame graphs | 
|----------|-------|------|--------------|
| entity_by_property | depths: DT=0, PT=0, ET=2, E=2 | $$48.4 \mathrm{ms} \pm 249 \mathrm{μs}\left({\color{gray}-1.177 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_multiple_entities/entity_by_property/depths_+DT=0,+PT=0,+ET=2,+E=2/flamegraph.svg) |
| entity_by_property | depths: DT=255, PT=255, ET=255, E=255 | $$66.4 \mathrm{ms} \pm 474 \mathrm{μs}\left({\color{gray}-1.138 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_multiple_entities/entity_by_property/depths_+DT=255,+PT=255,+ET=255,+E=255/flamegraph.svg) |
| entity_by_property | depths: DT=0, PT=0, ET=0, E=2 | $$42.3 \mathrm{ms} \pm 349 \mathrm{μs}\left({\color{gray}-1.951 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_multiple_entities/entity_by_property/depths_+DT=0,+PT=0,+ET=0,+E=2/flamegraph.svg) |
| entity_by_property | depths: DT=0, PT=0, ET=0, E=0 | $$37.8 \mathrm{ms} \pm 421 \mathrm{μs}\left({\color{gray}-0.642 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_multiple_entities/entity_by_property/depths_+DT=0,+PT=0,+ET=0,+E=0/flamegraph.svg) |
| entity_by_property | depths: DT=0, PT=2, ET=2, E=2 | $$53.2 \mathrm{ms} \pm 347 \mathrm{μs}\left({\color{gray}-0.157 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_multiple_entities/entity_by_property/depths_+DT=0,+PT=2,+ET=2,+E=2/flamegraph.svg) |
| entity_by_property | depths: DT=2, PT=2, ET=2, E=2 | $$56.7 \mathrm{ms} \pm 434 \mathrm{μs}\left({\color{gray}-0.856 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_multiple_entities/entity_by_property/depths_+DT=2,+PT=2,+ET=2,+E=2/flamegraph.svg) |
| link_by_source_by_property | depths: DT=0, PT=0, ET=2, E=2 | $$82.4 \mathrm{ms} \pm 942 \mathrm{μs}\left({\color{gray}0.383 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_multiple_entities/link_by_source_by_property/depths_+DT=0,+PT=0,+ET=2,+E=2/flamegraph.svg) |
| link_by_source_by_property | depths: DT=255, PT=255, ET=255, E=255 | $$99.2 \mathrm{ms} \pm 599 \mathrm{μs}\left({\color{gray}0.612 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_multiple_entities/link_by_source_by_property/depths_+DT=255,+PT=255,+ET=255,+E=255/flamegraph.svg) |
| link_by_source_by_property | depths: DT=0, PT=0, ET=0, E=2 | $$73.5 \mathrm{ms} \pm 424 \mathrm{μs}\left({\color{gray}0.349 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_multiple_entities/link_by_source_by_property/depths_+DT=0,+PT=0,+ET=0,+E=2/flamegraph.svg) |
| link_by_source_by_property | depths: DT=0, PT=0, ET=0, E=0 | $$36.8 \mathrm{ms} \pm 218 \mathrm{μs}\left({\color{gray}-1.078 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_multiple_entities/link_by_source_by_property/depths_+DT=0,+PT=0,+ET=0,+E=0/flamegraph.svg) |
| link_by_source_by_property | depths: DT=0, PT=2, ET=2, E=2 | $$86.4 \mathrm{ms} \pm 959 \mathrm{μs}\left({\color{gray}-0.563 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_multiple_entities/link_by_source_by_property/depths_+DT=0,+PT=2,+ET=2,+E=2/flamegraph.svg) |
| link_by_source_by_property | depths: DT=2, PT=2, ET=2, E=2 | $$90.8 \mathrm{ms} \pm 731 \mathrm{μs}\left({\color{gray}0.452 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_multiple_entities/link_by_source_by_property/depths_+DT=2,+PT=2,+ET=2,+E=2/flamegraph.svg) |


## representative_read_entity_type

| Function | Value | Mean | Flame graphs | 
|----------|-------|------|--------------|
| get_entity_type_by_id | Account ID: `d4e16033-c281-4cde-aa35-9085bf2e7579` | $$2.13 \mathrm{ms} \pm 7.16 \mathrm{μs}\left({\color{gray}0.072 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_entity_type/get_entity_type_by_id/Account+ID_+`d4e16033-c281-4cde-aa35-9085bf2e7579`/flamegraph.svg) |


## scaling_read_entity_complete_zero_depth

| Function | Value | Mean | Flame graphs | 
|----------|-------|------|--------------|
| entity_by_id | 25 entities | $$3.34 \mathrm{ms} \pm 8.79 \mathrm{μs}\left({\color{red}19.5 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_complete_zero_depth/entity_by_id/25+entities/flamegraph.svg) |
| entity_by_id | 10 entities | $$2.28 \mathrm{ms} \pm 10.3 \mathrm{μs}\left({\color{gray}-0.414 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_complete_zero_depth/entity_by_id/10+entities/flamegraph.svg) |
| entity_by_id | 50 entities | $$4.24 \mathrm{ms} \pm 21.0 \mathrm{μs}\left({\color{red}5.88 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_complete_zero_depth/entity_by_id/50+entities/flamegraph.svg) |
| entity_by_id | 1 entities | $$2.04 \mathrm{ms} \pm 11.1 \mathrm{μs}\left({\color{gray}-0.067 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_complete_zero_depth/entity_by_id/1+entities/flamegraph.svg) |
| entity_by_id | 5 entities | $$2.05 \mathrm{ms} \pm 15.0 \mathrm{μs}\left({\color{gray}-1.152 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/scaling_read_entity_complete_zero_depth/entity_by_id/5+entities/flamegraph.svg) |


## representative_read_entity

| Function | Value | Mean | Flame graphs | 
|----------|-------|------|--------------|
| entity_by_id | entity type ID: `https://blockprotocol.org/@alice/types/entity-type/uk-address/v/1` | $$15.9 \mathrm{ms} \pm 197 \mathrm{μs}\left({\color{lightgreen}-5.353 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_entity/entity_by_id/entity+type+ID_+`https___blockprotocol.org_@alice_types_entity-t_5/flamegraph.svg) |
| entity_by_id | entity type ID: `https://blockprotocol.org/@alice/types/entity-type/block/v/1` | $$15.6 \mathrm{ms} \pm 178 \mathrm{μs}\left({\color{gray}-3.405 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_entity/entity_by_id/entity+type+ID_+`https___blockprotocol.org_@alice_types_entity-t_6/flamegraph.svg) |
| entity_by_id | entity type ID: `https://blockprotocol.org/@alice/types/entity-type/person/v/1` | $$17.0 \mathrm{ms} \pm 204 \mathrm{μs}\left({\color{gray}4.48 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_entity/entity_by_id/entity+type+ID_+`https___blockprotocol.org_@alice_types_entity-t_8/flamegraph.svg) |
| entity_by_id | entity type ID: `https://blockprotocol.org/@alice/types/entity-type/song/v/1` | $$16.3 \mathrm{ms} \pm 185 \mathrm{μs}\left({\color{gray}-4.155 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_entity/entity_by_id/entity+type+ID_+`https___blockprotocol.org_@alice_types_entity-t_4/flamegraph.svg) |
| entity_by_id | entity type ID: `https://blockprotocol.org/@alice/types/entity-type/organization/v/1` | $$16.9 \mathrm{ms} \pm 230 \mathrm{μs}\left({\color{lightgreen}-26.300 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_entity/entity_by_id/entity+type+ID_+`https___blockprotocol.org_@alice_types_entity-t_2/flamegraph.svg) |
| entity_by_id | entity type ID: `https://blockprotocol.org/@alice/types/entity-type/page/v/2` | $$16.2 \mathrm{ms} \pm 170 \mathrm{μs}\left({\color{lightgreen}-29.649 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_entity/entity_by_id/entity+type+ID_+`https___blockprotocol.org_@alice_types_entity-t/flamegraph.svg) |
| entity_by_id | entity type ID: `https://blockprotocol.org/@alice/types/entity-type/book/v/1` | $$16.3 \mathrm{ms} \pm 166 \mathrm{μs}\left({\color{gray}0.946 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_entity/entity_by_id/entity+type+ID_+`https___blockprotocol.org_@alice_types_entity-t_7/flamegraph.svg) |
| entity_by_id | entity type ID: `https://blockprotocol.org/@alice/types/entity-type/building/v/1` | $$16.7 \mathrm{ms} \pm 192 \mathrm{μs}\left({\color{gray}2.06 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_entity/entity_by_id/entity+type+ID_+`https___blockprotocol.org_@alice_types_entity-t_9/flamegraph.svg) |
| entity_by_id | entity type ID: `https://blockprotocol.org/@alice/types/entity-type/playlist/v/1` | $$17.0 \mathrm{ms} \pm 190 \mathrm{μs}\left({\color{red}6.88 \mathrm{\\%}}\right) $$ | [Flame Graph](https://benchmarks.hash.dev/fab596d115ad458f066c4e7e440a85f75be56666/representative_read_entity/entity_by_id/entity+type+ID_+`https___blockprotocol.org_@alice_types_entity-t_3/flamegraph.svg) |

</details>

author_association: CONTRIBUTOR