Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## Unreleased

- Upload only completed user/assistant text; exclude tool calls, tool results, system messages,
memory writes, session boundaries, provider scope, hashes, retention metadata, and duplicate
envelope fields.
- Batch historical dialogue up to the request-size limit instead of posting one message per
request, while retaining deterministic IDs and resumable checkpoints.

## 2.0.3

- Keep approved device polling active across transient hosted transport and edge failures.
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Tenant credentials are stored in native credential custody, with an owner-privat

- Implements Hermes provider lifecycle hooks and tools.
- Prefetches bounded cited `memory_card` results for automatic recall.
- Captures completed turns, memory writes, and session boundaries.
- Captures only completed user/assistant dialogue turns.
- Redacts credential-shaped values before durable local spooling or network transfer.
- Replays Hermes history with deterministic event IDs and durable checkpoints.
- Keeps spool/checkpoint state beneath the active `$HERMES_HOME/substrate_wiki` profile.
Expand All @@ -181,7 +181,7 @@ It does **not** expose arbitrary filesystem writes, include Substrate server cod

## Privacy boundary

Visible prompts, assistant output, tool calls, and tool results may be sent to the configured Substrate server after redaction. Redaction is defense in depth, not proof arbitrary sensitive prose is absent. Review the server's access and retention policy before enabling capture.
Visible prompts and assistant output may be sent to the configured Substrate server after redaction. Tool calls, tool results, system messages, memory-write events, session metadata, and provider scope are not uploaded. Redaction is defense in depth, not proof arbitrary sensitive prose is absent.

Local failed deliveries remain in a bounded owner-private spool until delivered or explicitly removed. Status, progress, and receipts are content-free.

Expand Down
28 changes: 14 additions & 14 deletions docs/extraction-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"class": "standalone_repository_policy_or_test",
"path": "CHANGELOG.md",
"reason": "Required only by the independent public repository.",
"sha256": "57f9eb855dc41b263892d8229fa9fed046420da8a67d65fc34bd93f02c9eaa9c"
"sha256": "d20f1839056fdc49b98ed686a9a6747267bc62026eb13603577d90a6fbba4f9b"
},
{
"class": "standalone_repository_policy_or_test",
Expand All @@ -77,7 +77,7 @@
"class": "standalone_repository_policy_or_test",
"path": "README.md",
"reason": "Required only by the independent public repository.",
"sha256": "20ac49480369c8531e001466a6537a7dae310bbba7e6079bc217a6181e7d69d7"
"sha256": "1cce63f45c357df4710e24a8351835c4382a47751d57edf4207e234eb350807b"
},
{
"class": "standalone_repository_policy_or_test",
Expand Down Expand Up @@ -125,7 +125,7 @@
"class": "standalone_repository_policy_or_test",
"path": "scripts/verify_fresh_migration_run.py",
"reason": "Required only by the independent public repository.",
"sha256": "49fc5a2ee61eea6bd5d3d4f83ffd6b261bee10450ccbe8b2fde7c9873f89926d"
"sha256": "e185b0328bb7d684a53a57ce1029d8f2a845a608395b087ecff36d372a3ef210"
},
{
"class": "standalone_plugin_implementation",
Expand Down Expand Up @@ -353,23 +353,23 @@
{
"class": "build-and-install",
"destination": "scripts/verify_public_plugin_candidate.py",
"destination_sha256": "bcb89f657bc719e76f7873f71bf5bd302c06fbedd53a3162e6de64337e01b8db",
"destination_sha256": "e0241e4cc230dd50f88a01d23f4c22dac3aff54343e9f3b34ce2ca0906d57e92",
"source": "scripts/verify_public_plugin_candidate.py",
"source_sha256": "4130935d530075fce1758e2e89bd5d973a722e2293b5b1058cfe0d17f326172b",
"transformation": "modified_for_standalone"
},
{
"class": "plugin-package",
"destination": "src/substrate_wiki/README.md",
"destination_sha256": "44a11fda85d6d8170d772beadba2149bd114624479344b69a69cd49634309204",
"destination_sha256": "88d492b33ee537567bf85b63dcc7a470319212ac377f4857e27e504a3a1a05a3",
"source": "hermes-plugin/substrate_wiki/README.md",
"source_sha256": "21b6e60ef34e408fd87570334ba6d2811d2a9ea3c95d512e4d625f958b1cb0dc",
"transformation": "modified_for_standalone"
},
{
"class": "plugin-package",
"destination": "src/substrate_wiki/__init__.py",
"destination_sha256": "425cd191f723805bed85d965d2d74daeac272dd0660eadf6bac92f1fa02d6f4a",
"destination_sha256": "71c0c19d366759e67c7b999029777295cc8c25503d35fe9cfddc9460bcb34d5a",
"source": "hermes-plugin/substrate_wiki/__init__.py",
"source_sha256": "a4143022e05a7b93d3aa5799f4319601292e67069ad85d172770c3effe0e5e9d",
"transformation": "copied"
Expand Down Expand Up @@ -401,23 +401,23 @@
{
"class": "plugin-package",
"destination": "src/substrate_wiki/events.py",
"destination_sha256": "675ba567a391f6b86688876ae26d1cfd9b567fe3312d9ddc03620775596c88e9",
"destination_sha256": "f70c743866c88e3aa9add5746ae558adab175175c31918109fb3ea90dd52c662",
"source": "hermes-plugin/substrate_wiki/events.py",
"source_sha256": "675ba567a391f6b86688876ae26d1cfd9b567fe3312d9ddc03620775596c88e9",
"transformation": "copied"
},
{
"class": "plugin-package",
"destination": "src/substrate_wiki/history.py",
"destination_sha256": "7b2065ab5d7b3176b82d18d0a25b8c726c6d6311f9adf2fb2486bfdf8678df8f",
"destination_sha256": "aa4216c382ecd6816aa6b5633e7143a71fb8af66a218a0fafba9837a6d6da28d",
"source": "hermes-plugin/substrate_wiki/history.py",
"source_sha256": "d758d1b89dad334fc8c352b4e30f6e8e3c0788821c82ecc11bc7e7fcefdef16c",
"transformation": "copied"
},
{
"class": "plugin-package",
"destination": "src/substrate_wiki/plugin.yaml",
"destination_sha256": "0e1c680eb2822ca6c58315bd91a058468d107065fde0881ab39aafe54bd13690",
"destination_sha256": "e76721f0d7ba3d37958d15fa398ea47bb7c457388e0ad181df5471a1b2ede61c",
"source": "hermes-plugin/substrate_wiki/plugin.yaml",
"source_sha256": "5bfc8b20bfe99b8dd4fcb35616724e9a4a93bdfd1f3b270cfea1ccff18eaa116",
"transformation": "modified_for_standalone"
Expand Down Expand Up @@ -489,23 +489,23 @@
{
"class": "plugin-tests",
"destination": "tests/test_hardening.py",
"destination_sha256": "f5f87125f1edd37bff1d44301d6bb0f44cc7faf3ba6122bdbe7569f349fea7a3",
"destination_sha256": "bb9825c1889d919e29a90e43c2be48b84d846fcad813fa3896d194491cc8f386",
"source": "tests/contract/test_hermes_plugin_hardening.py",
"source_sha256": "6066ff88351167647dc6ffd368fcb2ad666ee722fcd16d2fc04600f274151b17",
"transformation": "modified_for_standalone"
},
{
"class": "plugin-tests",
"destination": "tests/test_history.py",
"destination_sha256": "3997fc5c3b538df4ded9e994781fd8384b6b3b42ac695e1f1450ac24f6a92e7c",
"destination_sha256": "15a6e7778a92e0d826ba1af61032f222dbf926b5ec2e189c48d7985a70824f19",
"source": "tests/contract/test_hermes_history_v12.py",
"source_sha256": "dc5cf0ceca8b8c0156bba330f51cc2186fdd2c409861752a7465f1b625228d69",
"transformation": "modified_for_standalone"
},
{
"class": "plugin-tests",
"destination": "tests/test_history_replay.py",
"destination_sha256": "87272a47ab814803a77a39cafeb1b193b48678bc889b49712b11bace8b7d8c87",
"destination_sha256": "226d30b1ad98ba7603bf3d8f7c86ac0857bf596bb75453d0dd57d677ec1405bd",
"source": "tests/contract/test_hermes_history_replay.py",
"source_sha256": "ef7636f612cc2d1023856fb8ff39dd7de2cca13336d20b86db5d25d944a3a212",
"transformation": "modified_for_standalone"
Expand All @@ -521,7 +521,7 @@
{
"class": "plugin-tests",
"destination": "tests/test_memory_provider.py",
"destination_sha256": "2c4517847dfad341063a69afcc737316a74574471fc98a45eaff21cfe4e271fd",
"destination_sha256": "cc967199b8e877a8088937a0c951e80f188ad4c7f29a98067bf649a2f8500b72",
"source": "tests/contract/test_hermes_memory_provider.py",
"source_sha256": "d95c3c68592e7c45d4eab3c96c8a23726e8ba54116b205b33f78c66239a4ba6e",
"transformation": "modified_for_standalone"
Expand All @@ -537,7 +537,7 @@
{
"class": "plugin-tests",
"destination": "tests/test_packaging.py",
"destination_sha256": "a3a24a5c987c939514866e72b70d01a32e34f5771089153e1fd12013829d8baf",
"destination_sha256": "9336c62a8011bf4b469574a27dfdee0abe3b1037a7d78baaf95f2840a16c6b51",
"source": "tests/contract/test_hermes_plugin_packaging.py",
"source_sha256": "c54967830788555b8d7bd5d2f871baeb6b98d7804a2bc7410ab297078bc20ee7",
"transformation": "modified_for_standalone"
Expand Down
7 changes: 6 additions & 1 deletion scripts/verify_fresh_migration_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,14 @@ def main() -> int:
if not isinstance(case_budget, dict):
failures.append(f"missing retained budget for case {case_id}")
continue
# The retained count reflects the former all-message payload. With the
# minimal user/assistant contract, redaction remains an integrity
# presence check rather than a historical message-volume floor.
current_budget = dict(case_budget)
current_budget["min_redacted_events"] = 1
failures.extend(
f"{case_id}/c{run['concurrency']}: {failure}"
for failure in evaluate_budget(run, case_budget)
for failure in evaluate_budget(run, current_budget)
)
if failures:
raise ValueError("; ".join(failures))
Expand Down
32 changes: 23 additions & 9 deletions scripts/verify_public_plugin_candidate.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"8510e5bbf41a3e79a6d5fee1f7816db734307fe7e2a7786b6a61c1ba280520a5",
"8793ef3bbab749be6e1089034ba627d24c8b733ffd4311951b590dae01d2ca02",
"c8eb7c5157ac7027dbf6ae86235e63dea6a2dd1faab46f0cbcbd536fbdd21ecf",
"1cce63f45c357df4710e24a8351835c4382a47751d57edf4207e234eb350807b",
}
),
"scripts/benchmark_migration.py": frozenset(
Expand All @@ -90,16 +91,28 @@
{"0cf55fa5cf91acdc164f2eb6936eb49af19ed9c432d060c475db4a9090cd169b"}
),
"tests/test_history.py": frozenset(
{"3997fc5c3b538df4ded9e994781fd8384b6b3b42ac695e1f1450ac24f6a92e7c"}
{
"3997fc5c3b538df4ded9e994781fd8384b6b3b42ac695e1f1450ac24f6a92e7c",
"15a6e7778a92e0d826ba1af61032f222dbf926b5ec2e189c48d7985a70824f19",
}
),
"tests/test_history_replay.py": frozenset(
{"87272a47ab814803a77a39cafeb1b193b48678bc889b49712b11bace8b7d8c87"}
{
"87272a47ab814803a77a39cafeb1b193b48678bc889b49712b11bace8b7d8c87",
"226d30b1ad98ba7603bf3d8f7c86ac0857bf596bb75453d0dd57d677ec1405bd",
}
),
"tests/test_hardening.py": frozenset(
{"91e53ca9b16ed43ebd49e7196bd6613f24c03cbf356f2bfc0ea03798cb065753"}
{
"91e53ca9b16ed43ebd49e7196bd6613f24c03cbf356f2bfc0ea03798cb065753",
"bb9825c1889d919e29a90e43c2be48b84d846fcad813fa3896d194491cc8f386",
}
),
"tests/test_memory_provider.py": frozenset(
{"c2edfbbe5a6320088f58db89b1880200b3e844ed3780885a02ef62d3218ab2b1"}
{
"c2edfbbe5a6320088f58db89b1880200b3e844ed3780885a02ef62d3218ab2b1",
"cc967199b8e877a8088937a0c951e80f188ad4c7f29a98067bf649a2f8500b72",
}
),
"tests/test_migration_baseline.py": frozenset(
{"0a3c7af6a761a1b22c5b94f7e1738d5d420e5f085f775d792728ed9ca684ac13"}
Expand Down Expand Up @@ -219,6 +232,7 @@
"87734abc087a4267e77aaeae7fb349d4c19f56dea2f7f3d173ab833dfb1da5e9",
"cdc48a8f8dbe1d68dfe329d5106c55895c5345924544c2cc4b3d7190c837705b",
"f139b1328c7884dfa664aa59b47d5d707b2a72894747911b8f99d5e89f6c7eca",
"1cce63f45c357df4710e24a8351835c4382a47751d57edf4207e234eb350807b",
}
),
'COMPATIBILITY.md': frozenset(
Expand All @@ -244,8 +258,8 @@
'docs/operation.md': frozenset({'fadd72791e097d878bbfbf338922d568f3c3d47958f26a41f53d3597471988fa'}),
'docs/public-boundary.json': frozenset({'976403a6a802832adddd5ab1ff56fdc2e4e4847a1fe37ea5e6a2d5f106bbbbe2', '648904170d6c66de6f15cfe51fb494225467730ff5167225d6fd427a6eac3571'}),
'docs/public-boundary.md': frozenset({'c9228e2abd22a8af558cd272988435c1caa69ad79c625cb08c8ef32e639eb0f3'}),
'src/substrate_wiki/README.md': frozenset({'44a11fda85d6d8170d772beadba2149bd114624479344b69a69cd49634309204'}),
'src/substrate_wiki/__init__.py': frozenset({'425cd191f723805bed85d965d2d74daeac272dd0660eadf6bac92f1fa02d6f4a'}),
'src/substrate_wiki/README.md': frozenset({'44a11fda85d6d8170d772beadba2149bd114624479344b69a69cd49634309204', '88d492b33ee537567bf85b63dcc7a470319212ac377f4857e27e504a3a1a05a3'}),
'src/substrate_wiki/__init__.py': frozenset({'425cd191f723805bed85d965d2d74daeac272dd0660eadf6bac92f1fa02d6f4a', '71c0c19d366759e67c7b999029777295cc8c25503d35fe9cfddc9460bcb34d5a'}),
'src/substrate_wiki/client.py': frozenset(
{
"082164ad24c879f6ca6434a8f28c251cd1ee7f4b413c5a788a70b351e2187f2a",
Expand All @@ -272,8 +286,8 @@
"72247d3537140098365350020cce29658c0743fee1aa738d7143db82316acce4",
}
),
'tests/test_hardening.py': frozenset({'f5f87125f1edd37bff1d44301d6bb0f44cc7faf3ba6122bdbe7569f349fea7a3'}),
'tests/test_memory_provider.py': frozenset({'2c4517847dfad341063a69afcc737316a74574471fc98a45eaff21cfe4e271fd'}),
'tests/test_hardening.py': frozenset({'f5f87125f1edd37bff1d44301d6bb0f44cc7faf3ba6122bdbe7569f349fea7a3', 'bb9825c1889d919e29a90e43c2be48b84d846fcad813fa3896d194491cc8f386'}),
'tests/test_memory_provider.py': frozenset({'2c4517847dfad341063a69afcc737316a74574471fc98a45eaff21cfe4e271fd', 'cc967199b8e877a8088937a0c951e80f188ad4c7f29a98067bf649a2f8500b72'}),
}
for _path, _digests in _HOSTED_ONBOARDING_EXACT_ALLOWLIST.items():
SYNTHETIC_FILE_SHA256_ALLOWLIST[_path] = (
Expand All @@ -288,7 +302,7 @@
"4b444b2583fbdd340b17d279fd169103c57f87a56dece39988d784b311222920"
)
TRUSTED_HISTORICAL_BLOB_POLICY_SHA256 = (
"d18f105fc482c28c9946f3f1bd21235821e9283ef76c48ce04cbfa756c20b09f"
"ec3a29f27ebe29ce65b7a70ac65311bfb4a31e54095709a7c69d2687e12d50e1"
)
SCANNER_PATH = "scripts/verify_public_plugin_candidate.py"
DESTINATION_MANIFEST_PATH = "docs/extraction-manifest.json"
Expand Down
8 changes: 4 additions & 4 deletions src/substrate_wiki/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ hermes substrate_wiki import-cancel --job-id <job-id> --yes --json

## Operation and privacy

Live completed turns and explicit memory writes are delivered asynchronously. Failed
Live completed user/assistant turns are delivered asynchronously. Failed
transient deliveries stay in a bounded owner-private spool and retry with capped backoff.
Authentication failures trigger automatic reconnect onboarding rather than exposing or
logging credentials. Status, receipts, checkpoints, and diagnostics are content-free.

Visible prompts, assistant output, tool calls, and tool results can be sent after redaction.
Redaction is defense in depth, not proof that arbitrary sensitive prose is absent. Raw capture
events declare a 90-day retention policy; curated wiki pages have their own lifecycle.
Visible prompts and assistant output can be sent after redaction. Tool calls, tool results,
system messages, memory-write events, and provider/session metadata are excluded. Redaction is
defense in depth, not proof that arbitrary sensitive prose is absent.

The provider exposes bounded cited wiki search/read/query/ingest/job tools and automatic
memory-card prefetch. It exposes no arbitrary filesystem-write tool.
Loading
Loading