From bbc17045d1d6a8910422ef65fcc8e9fa7ba06a4c Mon Sep 17 00:00:00 2001
From: Pavel Tkachyk
Date: Mon, 17 Aug 2026 01:11:30 -0400
Subject: [PATCH 1/4] Publish v2.0.2 installation instructions
Signed-off-by: Pavel Tkachyk
---
README.md | 22 +++++++++++-----------
SECURITY.md | 2 +-
docs/extraction-manifest.json | 10 +++++-----
docs/source-of-truth.md | 2 +-
scripts/verify_public_plugin_candidate.py | 7 ++++---
tests/test_packaging.py | 6 +++---
6 files changed, 25 insertions(+), 24 deletions(-)
diff --git a/README.md b/README.md
index 0da3268..688a71f 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,7 @@ Install the official Substrate plugin for my existing Hermes installation by fol
"Install with an agent" section of this README exactly.
Security and consent rules:
-- Install only immutable release v2.0.1 from Substrate-memory/hermes-substrate-wiki.
+- Install only immutable release v2.0.2 from Substrate-memory/hermes-substrate-wiki.
- Before executing downloaded code, independently verify the installer and plugin archive
against the exact SHA-256 values in the README. Never substitute a branch archive, CI
artifact, newer release, or checksum obtained only from the same download response.
@@ -69,7 +69,7 @@ install_dir="$(mktemp -d)"
chmod 700 "$install_dir"
cd "$install_dir"
-base='https://github.com/Substrate-memory/hermes-substrate-wiki/releases/download/v2.0.1'
+base='https://github.com/Substrate-memory/hermes-substrate-wiki/releases/download/v2.0.2'
curl --fail --location --proto '=https' --tlsv1.2 --remote-name "$base/install_hermes_plugin.py"
curl --fail --location --proto '=https' --tlsv1.2 --remote-name "$base/substrate_wiki.zip"
curl --fail --location --proto '=https' --tlsv1.2 --remote-name "$base/SHA256SUMS"
@@ -79,8 +79,8 @@ import hashlib
from pathlib import Path
expected = {
- "install_hermes_plugin.py": "33adb95c93f478a91991a97f0b9b6a1c9d2cee77e7894ed37fe331a4403b0bb8",
- "substrate_wiki.zip": "81d9edd1db1ea8466f8e2e209c0026b1b1ca6dad983309dce891b792105fa140",
+ "install_hermes_plugin.py": "4b34ee40d0d08ef24d03128e1cfc5ef73c69b39ca77b3fff59f4a4133cef76f2",
+ "substrate_wiki.zip": "6140d4f9baa9601e4adc9f75ef96eaf75e031a40767d76795fb08c412344a296",
}
for name, digest in expected.items():
actual = hashlib.sha256(Path(name).read_bytes()).hexdigest()
@@ -95,7 +95,7 @@ PY
python3 install_hermes_plugin.py \
--archive substrate_wiki.zip \
- --sha256 81d9edd1db1ea8466f8e2e209c0026b1b1ca6dad983309dce891b792105fa140 \
+ --sha256 6140d4f9baa9601e4adc9f75ef96eaf75e031a40767d76795fb08c412344a296 \
--yes --json
```
@@ -115,17 +115,17 @@ $installDir = Join-Path ([IO.Path]::GetTempPath()) ("substrate-wiki-" + [guid]::
New-Item -ItemType Directory -Path $installDir | Out-Null
Set-Location $installDir
-$base = 'https://github.com/Substrate-memory/hermes-substrate-wiki/releases/download/v2.0.1'
+$base = 'https://github.com/Substrate-memory/hermes-substrate-wiki/releases/download/v2.0.2'
Invoke-WebRequest "$base/install_hermes_plugin.py" -OutFile 'install_hermes_plugin.py'
Invoke-WebRequest "$base/substrate_wiki.zip" -OutFile 'substrate_wiki.zip'
Invoke-WebRequest "$base/SHA256SUMS" -OutFile 'SHA256SUMS'
$installerSha = (Get-FileHash -Algorithm SHA256 'install_hermes_plugin.py').Hash.ToLowerInvariant()
$archiveSha = (Get-FileHash -Algorithm SHA256 'substrate_wiki.zip').Hash.ToLowerInvariant()
-if ($installerSha -ne '33adb95c93f478a91991a97f0b9b6a1c9d2cee77e7894ed37fe331a4403b0bb8') {
+if ($installerSha -ne '4b34ee40d0d08ef24d03128e1cfc5ef73c69b39ca77b3fff59f4a4133cef76f2') {
throw 'Installer checksum mismatch'
}
-if ($archiveSha -ne '81d9edd1db1ea8466f8e2e209c0026b1b1ca6dad983309dce891b792105fa140') {
+if ($archiveSha -ne '6140d4f9baa9601e4adc9f75ef96eaf75e031a40767d76795fb08c412344a296') {
throw 'Plugin archive checksum mismatch'
}
$published = Get-Content 'SHA256SUMS' -Raw
@@ -136,7 +136,7 @@ if (($published -notmatch [regex]::Escape($installerSha)) -or
py -3 install_hermes_plugin.py `
--archive substrate_wiki.zip `
- --sha256 81d9edd1db1ea8466f8e2e209c0026b1b1ca6dad983309dce891b792105fa140 `
+ --sha256 6140d4f9baa9601e4adc9f75ef96eaf75e031a40767d76795fb08c412344a296 `
--yes --json
```
@@ -166,7 +166,7 @@ Then verify the content-free state:
hermes substrate_wiki onboarding-status --json
```
-Tenant credentials are stored in native credential custody, with an owner-private profile fallback; they never belong in ordinary configuration, logs, arguments, or diagnostics. See [configuration and operation](docs/operation.md) and the immutable [v2.0.1 release](https://github.com/Substrate-memory/hermes-substrate-wiki/releases/tag/v2.0.1).
+Tenant credentials are stored in native credential custody, with an owner-private profile fallback; they never belong in ordinary configuration, logs, arguments, or diagnostics. See [configuration and operation](docs/operation.md) and the immutable [v2.0.2 release](https://github.com/Substrate-memory/hermes-substrate-wiki/releases/tag/v2.0.2).
## What it does
@@ -189,7 +189,7 @@ Read [SECURITY.md](SECURITY.md), [the threat model](docs/threat-model.md), [the
## Open and paid boundary
-The open side is permissively licensed and includes the Hermes plugin/client, memory extraction and entity model, credential containment, privacy deletion, and policy compiler. This Hermes integration itself is hosted-only. [BOUNDARY.md](BOUNDARY.md) distinguishes the permanent commitment from the current `v2.0.1` implementation.
+The open side is permissively licensed and includes the Hermes plugin/client, memory extraction and entity model, credential containment, privacy deletion, and policy compiler. This Hermes integration itself is hosted-only. [BOUNDARY.md](BOUNDARY.md) distinguishes the permanent commitment from the current `v2.0.2` implementation.
The paid hosted tier covers hosted brokerage, multi-user operation, cross-organizational graph services, audit/attestation, and insurance-backed decisions. Its meter is per authorized action, never seats. This repository does not contain or license those held services.
diff --git a/SECURITY.md b/SECURITY.md
index c24e849..efe0ee8 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -2,7 +2,7 @@
## Supported versions
-The standalone `v2.0.0` and `v2.0.1` releases and pending `v2.0.2` patch target Hermes 0.20.x and the hosted service at `https://app.trysubstrate.co`.
+The standalone `v2.0.0`, `v2.0.1`, and `v2.0.2` releases target Hermes 0.20.x and the hosted service at `https://app.trysubstrate.co`.
Candidate CI artifacts are not supported releases.
## Report a vulnerability
diff --git a/docs/extraction-manifest.json b/docs/extraction-manifest.json
index 721d63a..c76f211 100644
--- a/docs/extraction-manifest.json
+++ b/docs/extraction-manifest.json
@@ -77,13 +77,13 @@
"class": "standalone_repository_policy_or_test",
"path": "README.md",
"reason": "Required only by the independent public repository.",
- "sha256": "cdc48a8f8dbe1d68dfe329d5106c55895c5345924544c2cc4b3d7190c837705b"
+ "sha256": "0d74ffbf410fe559478ee6a67e105f275d72d0477c71e86c81531798bc07e599"
},
{
"class": "standalone_repository_policy_or_test",
"path": "SECURITY.md",
"reason": "Required only by the independent public repository.",
- "sha256": "ef0cdf7a6c2fdc4ec7e781be15122f9b20331769929517a0f3c82ab15363480b"
+ "sha256": "48509dbbefd182381675499ff5636df18073411db580b05a1430e5eec1714df7"
},
{
"class": "standalone_repository_policy_or_test",
@@ -107,7 +107,7 @@
"class": "standalone_repository_policy_or_test",
"path": "docs/source-of-truth.md",
"reason": "Required only by the independent public repository.",
- "sha256": "52b02a52dce092e6e5d93c82ce2c152b8d1f62c1c9433a753884c98371a6b3a9"
+ "sha256": "3dd139a926518820a81b2ad239ce75028eee6517b717e41386fa1ecb51d02f29"
},
{
"class": "standalone_repository_policy_or_test",
@@ -353,7 +353,7 @@
{
"class": "build-and-install",
"destination": "scripts/verify_public_plugin_candidate.py",
- "destination_sha256": "880624feaf4bd5a0413928fd70cbcbb45ddde1b2df29758aa7c2fccf5cc69922",
+ "destination_sha256": "37f39f363cf41e9010b15d84bb9e9fa57ed26a86ba6f51fd4b22067c9c42c451",
"source": "scripts/verify_public_plugin_candidate.py",
"source_sha256": "4130935d530075fce1758e2e89bd5d973a722e2293b5b1058cfe0d17f326172b",
"transformation": "modified_for_standalone"
@@ -537,7 +537,7 @@
{
"class": "plugin-tests",
"destination": "tests/test_packaging.py",
- "destination_sha256": "8f8a81ff71d330dde6b0d9ca9d5b80f7236f5c13f6d930c92e734475e69a3d1f",
+ "destination_sha256": "f10483d8ee1882c5aa45d88e7c97008e174e2367aaff439c1e61f54c69a0719e",
"source": "tests/contract/test_hermes_plugin_packaging.py",
"source_sha256": "c54967830788555b8d7bd5d2f871baeb6b98d7804a2bc7410ab297078bc20ee7",
"transformation": "modified_for_standalone"
diff --git a/docs/source-of-truth.md b/docs/source-of-truth.md
index 317aa93..2a87fa1 100644
--- a/docs/source-of-truth.md
+++ b/docs/source-of-truth.md
@@ -2,7 +2,7 @@
## Decision
-`Substrate-memory/hermes-substrate-wiki` is the sole editable source for the Hermes `substrate_wiki` plugin. The protected default branch and immutable releases `v1.5.0`, `v2.0.0`, and `v2.0.1` have been read back successfully.
+`Substrate-memory/hermes-substrate-wiki` is the sole editable source for the Hermes `substrate_wiki` plugin. The protected default branch and immutable releases `v1.5.0`, `v2.0.0`, `v2.0.1`, and `v2.0.2` have been read back successfully.
Substrate-v2 owns only the server and pinned public release references; it must not vendor or modify plugin source.
diff --git a/scripts/verify_public_plugin_candidate.py b/scripts/verify_public_plugin_candidate.py
index 0dada42..cb74934 100644
--- a/scripts/verify_public_plugin_candidate.py
+++ b/scripts/verify_public_plugin_candidate.py
@@ -128,7 +128,8 @@
"bb4ba0542582cf3a89a37906651074c52bd1c28754b079bd67fd856c7fe24362",
"85320ec1e6a8c655b1f4e278b95c1087a6382bf3141366f1290c0933590f4645",
"99aed8e5a9a712f0fd2d9caa5223f0b332220f98699351565a3bb35a23d2848c",
- "ef0cdf7a6c2fdc4ec7e781be15122f9b20331769929517a0f3c82ab15363480b"
+ "ef0cdf7a6c2fdc4ec7e781be15122f9b20331769929517a0f3c82ab15363480b",
+ "48509dbbefd182381675499ff5636df18073411db580b05a1430e5eec1714df7"
}
),
"docs/api-ownership.json": frozenset(
@@ -204,9 +205,9 @@
# Hosted-origin and legacy-name references are accepted only at these exact reviewed
# file digests. Any byte change re-enables all endpoint and credential-name detectors.
_HOSTED_ONBOARDING_EXACT_ALLOWLIST = {
- 'README.md': frozenset({'87734abc087a4267e77aaeae7fb349d4c19f56dea2f7f3d173ab833dfb1da5e9', '6361beb1a5153f5dbcfca70740c1905096f3bc32ddfd4cc22157c6576c61b83a', 'f139b1328c7884dfa664aa59b47d5d707b2a72894747911b8f99d5e89f6c7eca', 'cdc48a8f8dbe1d68dfe329d5106c55895c5345924544c2cc4b3d7190c837705b'}),
+ 'README.md': frozenset({'87734abc087a4267e77aaeae7fb349d4c19f56dea2f7f3d173ab833dfb1da5e9', '6361beb1a5153f5dbcfca70740c1905096f3bc32ddfd4cc22157c6576c61b83a', 'f139b1328c7884dfa664aa59b47d5d707b2a72894747911b8f99d5e89f6c7eca', 'cdc48a8f8dbe1d68dfe329d5106c55895c5345924544c2cc4b3d7190c837705b', '0d74ffbf410fe559478ee6a67e105f275d72d0477c71e86c81531798bc07e599'}),
'COMPATIBILITY.md': frozenset({'e14a7a057ee64449041a2073590641a44cfe648cff696d4d20c58eed9e4509a3', '1f8fc410a88c7b410c4e72f4210226629b573a3c7f0cc410bc35939cd2317cfc', '1f18a49d552f2912872c10b0e41e93ff50ccd923d2fa9c108d35084dc5a5b22c'}),
- 'SECURITY.md': frozenset({'9cf9406266336996c57227413514cf97a04eb13264d80fa58c54d325fecf3d9f', '85320ec1e6a8c655b1f4e278b95c1087a6382bf3141366f1290c0933590f4645', '99aed8e5a9a712f0fd2d9caa5223f0b332220f98699351565a3bb35a23d2848c', 'ef0cdf7a6c2fdc4ec7e781be15122f9b20331769929517a0f3c82ab15363480b'}),
+ 'SECURITY.md': frozenset({'9cf9406266336996c57227413514cf97a04eb13264d80fa58c54d325fecf3d9f', '85320ec1e6a8c655b1f4e278b95c1087a6382bf3141366f1290c0933590f4645', '99aed8e5a9a712f0fd2d9caa5223f0b332220f98699351565a3bb35a23d2848c', 'ef0cdf7a6c2fdc4ec7e781be15122f9b20331769929517a0f3c82ab15363480b', '48509dbbefd182381675499ff5636df18073411db580b05a1430e5eec1714df7'}),
'docs/api-ownership.json': frozenset({'f1894c4653c51c6f02d23194617a3a1e9035d2cbe2b7c282f4cd6fbb26d8b65c'}),
'docs/operation.md': frozenset({'fadd72791e097d878bbfbf338922d568f3c3d47958f26a41f53d3597471988fa'}),
'docs/public-boundary.json': frozenset({'976403a6a802832adddd5ab1ff56fdc2e4e4847a1fe37ea5e6a2d5f106bbbbe2', '648904170d6c66de6f15cfe51fb494225467730ff5167225d6fd427a6eac3571'}),
diff --git a/tests/test_packaging.py b/tests/test_packaging.py
index 51fb270..f09e506 100644
--- a/tests/test_packaging.py
+++ b/tests/test_packaging.py
@@ -90,9 +90,9 @@ def test_root_readme_keeps_published_release_state_truthful() -> None:
assert boundary["repository"]["source_of_truth"] is True
assert boundary["legal"]["status"] == "published"
assert "canonical editable source" in readme
- assert "`v2.0.1` is not published yet" not in readme
- assert "releases/download/v2.0.1" in readme
- assert "81d9edd1db1ea8466f8e2e209c0026b1b1ca6dad983309dce891b792105fa140" in readme
+ assert "`v2.0.2` is not published yet" not in readme
+ assert "releases/download/v2.0.2" in readme
+ assert "6140d4f9baa9601e4adc9f75ef96eaf75e031a40767d76795fb08c412344a296" in readme
def test_release_workflow_keeps_dependency_execution_out_of_privileged_publisher() -> None:
From 195f7538ac578f7e2a80bb6c72b868b584163cbf Mon Sep 17 00:00:00 2001
From: Pavel Tkachyk
Date: Mon, 17 Aug 2026 01:11:58 -0400
Subject: [PATCH 2/4] Seal v2.0.2 documentation history
Signed-off-by: Pavel Tkachyk
---
docs/extraction-manifest.json | 2 +-
scripts/verify_public_plugin_candidate.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/extraction-manifest.json b/docs/extraction-manifest.json
index c76f211..24c851f 100644
--- a/docs/extraction-manifest.json
+++ b/docs/extraction-manifest.json
@@ -353,7 +353,7 @@
{
"class": "build-and-install",
"destination": "scripts/verify_public_plugin_candidate.py",
- "destination_sha256": "37f39f363cf41e9010b15d84bb9e9fa57ed26a86ba6f51fd4b22067c9c42c451",
+ "destination_sha256": "8cfc69fb0d12345b25e7be6099d301945da1bd8d00ebbcf0dc9bb0f3b7d4bc8e",
"source": "scripts/verify_public_plugin_candidate.py",
"source_sha256": "4130935d530075fce1758e2e89bd5d973a722e2293b5b1058cfe0d17f326172b",
"transformation": "modified_for_standalone"
diff --git a/scripts/verify_public_plugin_candidate.py b/scripts/verify_public_plugin_candidate.py
index cb74934..c3e4a33 100644
--- a/scripts/verify_public_plugin_candidate.py
+++ b/scripts/verify_public_plugin_candidate.py
@@ -233,7 +233,7 @@
"4b444b2583fbdd340b17d279fd169103c57f87a56dece39988d784b311222920"
)
TRUSTED_HISTORICAL_BLOB_POLICY_SHA256 = (
- "629d157372b343723f93d04b45d98c6bde9c7d31278082ba08a7a6124facc1d9"
+ "e74009470aa6a4e7273e4c0e4128a2a1bbeae1cd89220e019a9efb3a9758463a"
)
SCANNER_PATH = "scripts/verify_public_plugin_candidate.py"
DESTINATION_MANIFEST_PATH = "docs/extraction-manifest.json"
From 45cc23d29dac8532c8c19a032396662fd5126687 Mon Sep 17 00:00:00 2001
From: Pavel Tkachyk
Date: Mon, 17 Aug 2026 01:12:39 -0400
Subject: [PATCH 3/4] Correct v2.0.2 packaging inventory
Signed-off-by: Pavel Tkachyk
---
docs/extraction-manifest.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/extraction-manifest.json b/docs/extraction-manifest.json
index 24c851f..0a0c9dd 100644
--- a/docs/extraction-manifest.json
+++ b/docs/extraction-manifest.json
@@ -537,7 +537,7 @@
{
"class": "plugin-tests",
"destination": "tests/test_packaging.py",
- "destination_sha256": "f10483d8ee1882c5aa45d88e7c97008e174e2367aaff439c1e61f54c69a0719e",
+ "destination_sha256": "a5d10ca8098d0bc2bcc38aee4a0e0aa752a9aec4e0bd9f0041c2c566d45e8ef6",
"source": "tests/contract/test_hermes_plugin_packaging.py",
"source_sha256": "c54967830788555b8d7bd5d2f871baeb6b98d7804a2bc7410ab297078bc20ee7",
"transformation": "modified_for_standalone"
From f32b9cdfd7a86e17f440c3ba8a298c40d4b1bd69 Mon Sep 17 00:00:00 2001
From: Pavel Tkachyk
Date: Mon, 17 Aug 2026 01:13:08 -0400
Subject: [PATCH 4/4] Reseal corrected v2.0.2 documentation history
Signed-off-by: Pavel Tkachyk
---
docs/extraction-manifest.json | 2 +-
scripts/verify_public_plugin_candidate.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/extraction-manifest.json b/docs/extraction-manifest.json
index 0a0c9dd..4667671 100644
--- a/docs/extraction-manifest.json
+++ b/docs/extraction-manifest.json
@@ -353,7 +353,7 @@
{
"class": "build-and-install",
"destination": "scripts/verify_public_plugin_candidate.py",
- "destination_sha256": "8cfc69fb0d12345b25e7be6099d301945da1bd8d00ebbcf0dc9bb0f3b7d4bc8e",
+ "destination_sha256": "8de69ac64758975370bf149b27526170bc0f00c43b56d63f2d47f3f5f30c457f",
"source": "scripts/verify_public_plugin_candidate.py",
"source_sha256": "4130935d530075fce1758e2e89bd5d973a722e2293b5b1058cfe0d17f326172b",
"transformation": "modified_for_standalone"
diff --git a/scripts/verify_public_plugin_candidate.py b/scripts/verify_public_plugin_candidate.py
index c3e4a33..4845486 100644
--- a/scripts/verify_public_plugin_candidate.py
+++ b/scripts/verify_public_plugin_candidate.py
@@ -233,7 +233,7 @@
"4b444b2583fbdd340b17d279fd169103c57f87a56dece39988d784b311222920"
)
TRUSTED_HISTORICAL_BLOB_POLICY_SHA256 = (
- "e74009470aa6a4e7273e4c0e4128a2a1bbeae1cd89220e019a9efb3a9758463a"
+ "567036d3e914d8a3302589f978fe2482eeeff75a08b4e5aa631601d9ba0a5f1f"
)
SCANNER_PATH = "scripts/verify_public_plugin_candidate.py"
DESTINATION_MANIFEST_PATH = "docs/extraction-manifest.json"