v2 (c) Neutral reversal bridge: Echo types gate reversibility with a retained residue (Lean + Rust)#35
Merged
Conversation
Formalises the Bennett-style residue/token reversal (ADR-0007 D5/D6 Neutral tier), generalising reversibility beyond the Safe/group case. JtvTheorems (operational): - RevOp.execBackwardWithToken: restore the overwritten var from a retained token. - rev_forward_backward_with_token: forward then token-restore recovers the FULL state at every variable, UNCONDITIONALLY (no x ∉ e.freeVars needed) — the self-referential case that defeats rev_forward_backward. - rev_backward_naive_fails_self_ref: proves the naive inverse fails for x += x (0 ≠ 1), so the token is necessary. JtvEcho (effect contract for reversible{}->tok): - Echo.admissibleWithResidue: admits safe + neutral, rejects breaking. - admissibleWithResidue_iff, admissible_implies_admissibleWithResidue, neutral_residue_only, join_admissibleWithResidue. - blockEcho_admissibleWithResidue (block soundness) + breaking_blocks_residual_reversal. lake build green; 0 sorry/admit/axiom; 0 warnings. https://claude.ai/code/session_01BJmfoz1ZS1Pejy9LLMY742
Makes the Echo type system gate the language's reversal forms per ADR-0007 D5/D6, admitting the Neutral (token-recoverable) tier. echo.rs: reclassify self-reference (x += x) Breaking -> Neutral (token-recoverable, Bennett-style, not total erasure; in the addition-only group every overwrite can be tokenised, so Breaking is reserved for future non-group / tropical systems per D6). Add Echo::admissible_with_residue (admits Safe + Neutral, rejects Breaking). typechecker.rs: split the Echo gate. reversible{}->tok (token bound) uses the residue policy check_echo_admissible_with_residue admitting Neutral; reverse{} and tokenless reversible{} stay Safe-only. The token unlocks the Neutral tier. reversible.rs: RecordedOp::Snapshot residue op — a self-referential step records the overwritten value and inverts by RESTORING it (Bennett), not the wrong naive minus-value. Runtime counterpart of execBackwardWithToken. Tests green: 99 lib + integration; clippy -D warnings clean. https://claude.ai/code/session_01BJmfoz1ZS1Pejy9LLMY742
🔍 Hypatia Security ScanFindings: 54 issues detected
View findings[
{
"reason": "No test directory or test files found",
"type": "no_tests",
"file": "/home/runner/work/julia-the-viper/julia-the-viper",
"action": "flag",
"rule_module": "honest_completion",
"severity": "high",
"deduction": 20
},
{
"reason": "Issue in secret-scanner.yml",
"type": "missing_workflow",
"file": "secret-scanner.yml",
"action": "create",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Workflow executes remote script directly (curl/wget piped to shell). Download, verify checksum/signature, then execute.",
"type": "download_then_run",
"file": "proof-regression.yml",
"action": "verify_download_integrity",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Issue in scorecard.yml",
"type": "scorecard_wrapper_missing_job_permissions",
"file": "scorecard.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "unsafe block -- requires SAFETY comment (2 occurrences, CWE-676)",
"type": "unsafe_block",
"file": "/home/runner/work/julia-the-viper/julia-the-viper/crates/jtv-cli/src/rsr_check.rs",
"action": "flag",
"rule_module": "code_safety",
"severity": "medium"
},
{
"reason": "unwrap() without prior check -- DoS via panic (10 occurrences, CWE-754)",
"type": "unwrap_without_check",
"file": "/home/runner/work/julia-the-viper/julia-the-viper/crates/jtv-core/benches/interpreter_bench.rs",
"action": "flag",
"rule_module": "code_safety",
"severity": "high"
},
{
"reason": "unwrap() without prior check -- DoS via panic (6 occurrences, CWE-754)",
"type": "unwrap_without_check",
"file": "/home/runner/work/julia-the-viper/julia-the-viper/crates/jtv-core/benches/parser_bench.rs",
"action": "flag",
"rule_module": "code_safety",
"severity": "high"
},
{
"reason": "Download-and-execute pattern (curl|wget pipe to shell) -- verify integrity before execution (3 occurrences, CWE-494)",
"type": "shell_download_then_run",
"file": "/home/runner/work/julia-the-viper/julia-the-viper/setup.sh",
"action": "flag",
"rule_module": "code_safety",
"severity": "high"
},
{
"reason": "Js.Array2 deprecated -- use Array (3 occurrences)",
"type": "deprecated_api",
"file": "/home/runner/work/julia-the-viper/julia-the-viper/vscode-extension/src/Extension.res",
"action": "search_replace",
"rule_module": "migration_rules",
"severity": "high"
},
{
"reason": "Js.Promise deprecated -- use Promise (2 occurrences)",
"type": "deprecated_api",
"file": "/home/runner/work/julia-the-viper/julia-the-viper/vscode-extension/src/Extension.res",
"action": "module_replace",
"rule_module": "migration_rules",
"severity": "medium"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
hyperpolymath
marked this pull request as ready for review
June 15, 2026 19:02
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.
Implements the v2 (c) Neutral reversal bridge end-to-end (proofs + typechecker + runtime), per ADR-0007 D5/D6. This is the rung that makes Echo types actually gate the language's reversal forms beyond the Safe/group case — the user's core "echo types in the typesystem" ask.
The idea
The
reversible { } -> toktoken is exactly what unlocks the Neutral tier. A self-referential step likex += xis not total erasure — its original value is recoverable from a retained residue (Bennett's trick). So:reverse { }and tokenlessreversible { }→ Safe-only (no residue to invert from).reversible { } -> tok→ residue policy: admitsSafe+Neutral, rejects onlyBreaking.Breaking → Neutral. In the addition-only group every overwrite can be tokenised, soBreakingnever arises here — it's now reserved for future non-group / idempotent (tropical) systems (D6).Lean (
jtv_proofs/) —lake buildgreen, 0 sorry/admit/axiomJtvTheorems:RevOp.execBackwardWithToken+rev_forward_backward_with_token— restoringxfrom the saved token recovers the full state at every variable, unconditionally, even for self-referentialx += x(the case that defeatsrev_forward_backward). Plusrev_backward_naive_fails_self_ref— proves the naive-inverse genuinely fails (0 ≠ 1), so the token is necessary.JtvEcho:admissibleWithResidue(+_iff),admissible_implies_admissibleWithResidue(Safe-only ⊂ residue),neutral_residue_only,join_admissibleWithResidue, and block soundnessblockEcho_admissibleWithResidue/breaking_blocks_residual_reversal.Rust (
crates/jtv-core/) —cargo test+ clippy-D warningsgreenecho.rs: self-refBreaking → Neutral;Echo::admissible_with_residue.typechecker.rs: split gate —check_echo_admissible_with_residueforreversible { } -> tok; Safe-only otherwise.reversible.rs:RecordedOp::Snapshotrecords the overwritten value and inverts by restoring it (runtime counterpart ofexecBackwardWithToken), not the wrong naive subtraction.Tests (all green)
99 lib + integration tests pass. New:
self_reference_is_neutral,block_neutral_when_any_self_reference, residue-admissibility; typechecker admits self-ref with token / rejects without (andreverse{}rejects); runtime residue round-trip recoverytest_neutral_self_reference_recovered_via_residue.Next rung after this: (b) Echo as a first-class function effect; and number-system semantics (gap-005, the D6 tier classification). The
DataExpr.negopen tension (D2) also remains.https://claude.ai/code/session_01BJmfoz1ZS1Pejy9LLMY742
Generated by Claude Code