feat: provenance-safe actor substitutes + continuation anchors (revived) - #12
Merged
Merged
Conversation
Allow each frozen turn to pre-authorize same-role substitute actors and bounded reason codes while preserving legacy primary-only definitions. Keep the scheduled and actual identities distinct across claims, task briefings, runtime evidence, state, and exact Git metadata. Add structured continuation anchors and agent-final statuses without changing the owner decision boundary or final hard stop. Enforce canonical Hermes profile separation, append-only history, and event-specific metadata validation. Cover primary and substitute routes, compatibility, metadata rewriting, profile aliases, continuation mutation, and final-status grammar in the verify gate.
# Conflicts: # docs/technical-reference.md # schemas/protocol.schema.json # schemas/runtime-evidence.schema.json # src/multi_agent_dialogue/adapters/base.py # src/multi_agent_dialogue/config.py # src/multi_agent_dialogue/engine.py # src/multi_agent_dialogue/evidence.py # src/multi_agent_dialogue/runner.py
There was a problem hiding this comment.
Confidence Score: 4/5
Summary
Revives preauthorized substitute actors, continuation anchors, and agent final statuses onto hardened main; fail-closed checks are consistent across claim, evidence, state, and Git trailers. 351 tests and verify.py pass; only minor issues found.
Important Files Changed
| File | Overview |
|---|---|
| src/multi_agent_dialogue/config.py | Parses substitutes, reasons, continuation anchor, final statuses; role and profile checks |
| src/multi_agent_dialogue/engine.py | Selection resolution, trailer verification, continuation recheck, final-status gate |
| src/multi_agent_dialogue/runner.py | Substitute-aware context, briefing, launch; gates on selected actor's CLI |
| src/multi_agent_dialogue/evidence.py | Validates scheduled/actual identity and reason against claim |
| src/multi_agent_dialogue/gitops.py | Trailer parsing plus key/value injection guards |
| src/multi_agent_dialogue/cli.py | --substitution-reason flag; status/next expose legal routes |
| src/multi_agent_dialogue/unverified.py | claim/prepare accept substitution reason |
| src/multi_agent_dialogue/adapters/base.py | Evidence record carries selection identity fields |
| schemas/protocol.schema.json | Substitute/reason pairing conditionals, continuation, agent_final_statuses |
| schemas/runtime-evidence.schema.json | Adds scheduled_actor_id, actor_selection, substitution_reason |
| pyproject.toml | Adds jsonschema test extra |
| .github/workflows/ci.yml | Installs test extra in CI |
| CONTRIBUTING.md | Test-extra install instructions |
| README.md | Documents substitute routes |
| docs/technical-reference.md | Reference for new surfaces |
| examples/demo-common.sh | Updated wrong-actor error string |
| tests/test_config.py | Definition-level substitute/continuation rejection matrix |
| tests/test_engine.py | Claim routes, alias drift, final-status grammar |
| tests/test_evidence.py | Selection provenance requirements |
| tests/test_git_transactions.py | Trailer tamper and injection coverage |
| tests/test_adapters.py | Substitute launch identity preservation |
| tests/test_cli.py | Substitute CLI flag and error paths |
| tests/test_real_contracts.py | Substitute gated on its own CLI |
- 'none' is reserved at definition parse: it is the null sentinel in Madp-Substitution-Reason trailers, so it can never be a reason code; - continuation-anchor Git facts (content-addressed, immutable) are verified once per Dialogue instance instead of spawning several git subprocesses per state() read; the live artifact bytes are still re-hashed on EVERY read, so the tamper guard is unchanged; - the final-status line grammar tolerates CRLF artifacts; - a whitespace-only substitution_reason is rejected explicitly instead of collapsing to None and passing as a primary claim.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Revives the 2026-07-20 branch
feature/owner-authorized-actor-substitutes(5ad95db), merged onto the current hardened main (#4–#11).What the feature is
substitute_actor_idslist plus a boundedsubstitution_reasonsallowlist. A substitute must exist as a full actor with the SAME protocol role, keeps its own provider/model/session identity, and never impersonates the primary.run --actor SUB --substitution-reason CODE --launchselects it explicitly.scheduled_actor_id/actor_id/actor_selection/substitution_reasonstay distinct across claim, briefing, evidence, state, and Git metadata. This is preauthorization proof, not owner authentication and not automatic failover.continuation(artifact sha256, publication commit, original dialogue head, start_round), rechecked at init and on every state read.agent_final_statuses: optional frozen enum; the final artifact must carry exactly oneStatus: <VALUE>line; tokens never overlapowner_decisions; reaching one moves the dialogue toREADY_FOR_OWNERwithout creating an owner decision.Reconciliation with the hardened surface (the interesting part)
test_substitute_is_gated_on_its_own_cli).validate_evidenceruns both the evidence_version binding (feat(evidence): bind turn evidence_version to the frozen definition (issue #5 proposal 5) #7) and the substitution checks on every turn.madp reportrows now carry scheduled-vs-actual identity fields._ROOT_KEYSadmitsevidence_versions; both schemas admit the substitute fields (evidence:scheduled_actor_id,actor_selection,substitution_reason; protocol: turn-levelsubstitute_actor_ids/substitution_reasons, top-levelcontinuation,agent_final_statuses).Tests
The branch's own matrices (primary/substitute routes, metadata rewriting, profile aliases, continuation mutation, final-status grammar) plus today's full suite: 351 passed;
scripts/verify.py→{"ok": true}.