From 094db053a0fb5e57ad9489cbb20a1f0181351ab8 Mon Sep 17 00:00:00 2001
From: Pavel Tkachyk
Date: Sun, 30 Aug 2026 23:16:54 -0400
Subject: [PATCH] Publish verified v2.0.4 install instructions
Signed-off-by: Pavel Tkachyk
---
README.md | 22 +++++++++++-----------
docs/extraction-manifest.json | 8 ++++----
docs/source-of-truth.md | 2 +-
scripts/verify_public_plugin_candidate.py | 5 ++++-
tests/test_packaging.py | 6 +++---
5 files changed, 23 insertions(+), 20 deletions(-)
diff --git a/README.md b/README.md
index f66d813..d75dd1d 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.3 from Substrate-memory/hermes-substrate-wiki.
+- Install only immutable release v2.0.4 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.3'
+base='https://github.com/Substrate-memory/hermes-substrate-wiki/releases/download/v2.0.4'
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": "72247d3537140098365350020cce29658c0743fee1aa738d7143db82316acce4",
- "substrate_wiki.zip": "dfaa786f68dd819e1313191bb26253caf6bc52fe4b0ab4f6f8c2e2ebcb62e1a3",
+ "install_hermes_plugin.py": "8e37991db874b306045623c5cba39ef995b53b7b6a1a6c6f0253e2ff12c0ebb8",
+ "substrate_wiki.zip": "333e8b49d34bac3ace3017d3460cb42ab08d990b016c4ab20ca3e624f4117064",
}
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 dfaa786f68dd819e1313191bb26253caf6bc52fe4b0ab4f6f8c2e2ebcb62e1a3 \
+ --sha256 333e8b49d34bac3ace3017d3460cb42ab08d990b016c4ab20ca3e624f4117064 \
--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.3'
+$base = 'https://github.com/Substrate-memory/hermes-substrate-wiki/releases/download/v2.0.4'
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 '72247d3537140098365350020cce29658c0743fee1aa738d7143db82316acce4') {
+if ($installerSha -ne '8e37991db874b306045623c5cba39ef995b53b7b6a1a6c6f0253e2ff12c0ebb8') {
throw 'Installer checksum mismatch'
}
-if ($archiveSha -ne 'dfaa786f68dd819e1313191bb26253caf6bc52fe4b0ab4f6f8c2e2ebcb62e1a3') {
+if ($archiveSha -ne '333e8b49d34bac3ace3017d3460cb42ab08d990b016c4ab20ca3e624f4117064') {
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 dfaa786f68dd819e1313191bb26253caf6bc52fe4b0ab4f6f8c2e2ebcb62e1a3 `
+ --sha256 333e8b49d34bac3ace3017d3460cb42ab08d990b016c4ab20ca3e624f4117064 `
--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.3 release](https://github.com/Substrate-memory/hermes-substrate-wiki/releases/tag/v2.0.3).
+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.4 release](https://github.com/Substrate-memory/hermes-substrate-wiki/releases/tag/v2.0.4).
## 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.3` 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.4` 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/docs/extraction-manifest.json b/docs/extraction-manifest.json
index 40d116b..95eac0a 100644
--- a/docs/extraction-manifest.json
+++ b/docs/extraction-manifest.json
@@ -77,7 +77,7 @@
"class": "standalone_repository_policy_or_test",
"path": "README.md",
"reason": "Required only by the independent public repository.",
- "sha256": "1cce63f45c357df4710e24a8351835c4382a47751d57edf4207e234eb350807b"
+ "sha256": "ac62cbf3799a35bbb239a0b951411491aab8ee0f2f2c33e66b8a3380a8c20e88"
},
{
"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": "73d848fd11aff7667f8bdc332ec1b1a872de9998039de0809cf07bd67c7a26e0"
+ "sha256": "91e0d6884025a9387b0c25cd02ecd1253e3bef00b5546fe7562f11924775c018"
},
{
"class": "standalone_repository_policy_or_test",
@@ -353,7 +353,7 @@
{
"class": "build-and-install",
"destination": "scripts/verify_public_plugin_candidate.py",
- "destination_sha256": "116652c7d6a675d9b140b655b03d9a095603350dbbe99b1f45a13e1c76fc50a1",
+ "destination_sha256": "169151e6ca769184881da61a823ff4f1d2b1c3df35f2e91049a9c800d173bb98",
"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": "5793b5b96793d08060dc7faf3c39d3ee4b0717272a297f865968e84d595f4023",
+ "destination_sha256": "e90c78ea6b182c558079c59752be07af1bc7937b69e06b66ee96a74bc8f7f0db",
"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 21dab91..da3c74f 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`, `v2.0.1`, and `v2.0.3` 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`, `v2.0.3`, and `v2.0.4` 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 106df8b..d04b276 100644
--- a/scripts/verify_public_plugin_candidate.py
+++ b/scripts/verify_public_plugin_candidate.py
@@ -82,6 +82,7 @@
"8793ef3bbab749be6e1089034ba627d24c8b733ffd4311951b590dae01d2ca02",
"c8eb7c5157ac7027dbf6ae86235e63dea6a2dd1faab46f0cbcbd536fbdd21ecf",
"1cce63f45c357df4710e24a8351835c4382a47751d57edf4207e234eb350807b",
+ "ac62cbf3799a35bbb239a0b951411491aab8ee0f2f2c33e66b8a3380a8c20e88",
}
),
"scripts/benchmark_migration.py": frozenset(
@@ -123,6 +124,7 @@
"c4033e38f9e832779062381b0d0dcf71eecc25554d8df9af383a2d0c334dcd78",
"c7a8e84d116319e62b0b7817c1a049225088c8b3baf59c42ad82cbefc3c172b5",
"5793b5b96793d08060dc7faf3c39d3ee4b0717272a297f865968e84d595f4023",
+ "e90c78ea6b182c558079c59752be07af1bc7937b69e06b66ee96a74bc8f7f0db",
}
),
"tests/test_publication_scanner.py": frozenset(
@@ -237,6 +239,7 @@
"cdc48a8f8dbe1d68dfe329d5106c55895c5345924544c2cc4b3d7190c837705b",
"f139b1328c7884dfa664aa59b47d5d707b2a72894747911b8f99d5e89f6c7eca",
"1cce63f45c357df4710e24a8351835c4382a47751d57edf4207e234eb350807b",
+ "ac62cbf3799a35bbb239a0b951411491aab8ee0f2f2c33e66b8a3380a8c20e88",
}
),
'COMPATIBILITY.md': frozenset(
@@ -311,7 +314,7 @@
"4b444b2583fbdd340b17d279fd169103c57f87a56dece39988d784b311222920"
)
TRUSTED_HISTORICAL_BLOB_POLICY_SHA256 = (
- "88e7743afb748d534413c182eb96e0575942659ce7192c0ea973ef56ed1b2790"
+ "b3ea73d46f3968b99d6695a14b954954826fbd7fa52abd5fd18cf951db8234e1"
)
SCANNER_PATH = "scripts/verify_public_plugin_candidate.py"
DESTINATION_MANIFEST_PATH = "docs/extraction-manifest.json"
diff --git a/tests/test_packaging.py b/tests/test_packaging.py
index 4bdf330..f446e47 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.3` is not published yet" not in readme
- assert "releases/download/v2.0.3" in readme
- assert "dfaa786f68dd819e1313191bb26253caf6bc52fe4b0ab4f6f8c2e2ebcb62e1a3" in readme
+ assert "`v2.0.4` is not published yet" not in readme
+ assert "releases/download/v2.0.4" in readme
+ assert "333e8b49d34bac3ace3017d3460cb42ab08d990b016c4ab20ca3e624f4117064" in readme
def test_release_workflow_keeps_dependency_execution_out_of_privileged_publisher() -> None: