You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Readiness: needs-decision on the two points under Decisions. The rest of the scope is settled. Also blocked on #433, since exact identifier spans are required.
Problem
Wright advertises four edit operations. None of them succeeds on real input.
validateEditTransaction and semanticRename cannot succeed by construction. In crates/wright-driver/src/edit.rs, validate_source_kind rejects raw Workshop with edit-unsupported-kind. For OPY, both functions end in an unconditional refusal(vec![source_provider_unavailable()]) once every precondition has passed. I reproduced this on main (0.3.0): a well-formed transaction against overpy-cake.ws returns edit-unsupported-kind.
providerValidateEdit and providerSemanticRename have a real implementation in crates/wright-driver/src/provider_edit.rs, but it is tested only against a mock provider. The shipped opy-provider does not implement LPP rename or edit validation yet (Implement LPP rename and edit validation in opy-provider opy-rs#403 is open).
Tests lock in the refusal: crates/wright-cli/tests/serve.rs asserts ok == false for both non-provider operations, and crates/wright-driver/tests/edit.rs asserts source-provider-unavailable.
So today Wright has no working validated source edit for any language. Yet goal.md principle 5 names "apply targeted edits" as core to agent workflows, and #134 lists "validated source-oriented mutation" in the 1.0 contract.
Raw Workshop is the one language where Wright can close this gap with no provider. workshop-rs owns parsing and validation, Program::edit_source produces checked source edits, and #433 provides exact identifier spans.
Why rename first, not lint fixes
None of the six current lint rules has a behavior-preserving mechanical fix:
min-wait-loop and while-without-wait: any fix changes timing.
repeated-value: extracting the value needs a new variable slot and proof that the value is pure.
expensive-loop-check and ongoing-condition-hot-path: these are heuristics, with no single correct edit.
Rename preserves behavior by definition, and textual replace cannot do it safely. A global variable and a player variable may share a name, and a name can appear as a substring of another name or inside a string. Rename is the edit where Wright's semantic knowledge is the whole difference, for humans and agents alike.
Scope
Edit validation for raw Workshop: apply the transaction to the supplied sources, then load the result again through the session's own workshop-rs parse and validation path. The transaction is ok only if no error diagnostic results. The existing precondition, overlap, and atomicity rules apply unchanged.
Semantic rename for raw Workshop covers global variables, player variables, and subroutines:
CLI:wright rename <NAME> <NEW_NAME> [INPUT], a shared human/agent surface with a wright-result/v1 envelope under --format json. Write behavior is decision D2.
Update docs/agent-contract.md, docs/cli/commands.md, and docs/architecture/tooling.md for the raw Workshop edit path.
Decisions
D1. Which operations carry raw Workshop edits. Recommended: the non-provider validateEditTransaction and semanticRename become the raw Workshop path, owned by Wright and backed by workshop-rs. The provider* operations remain the source-language path. OPY input sent to a non-provider operation gets a structured refusal that names the provider operation. The change is additive in behavior: inputs that were always refused can now succeed, and no schema member changes. The alternative is a new operation pair, which would leave two permanently dead operations advertised.
D2. Whether wright rename writes files. Recommended: by default it prints the validated change as a diff and writes nothing, and --write applies it atomically after validation. --write refuses if any source's identity changed since it was read. This would make rename the first Wright command that modifies user source. Since the agent contract says "Wright proposes and validates; a caller remains responsible for applying them", --write puts the CLI in the caller's role while leaving the agent operation unchanged. The alternative, preview only, keeps Wright read-only but leaves humans applying diffs by hand.
Non-goals
wright lint --fix and lint suggestions. No current rule admits a safe fix (see above). Revisit when one does.
Renaming rules. Rule names are strings with no references.
Changes to the provider* operations.
Any fallback to textual search and replace.
Acceptance criteria
Renaming cakePos to cakePosition in overpy-cake.ws returns an ok transaction. The transaction edits the declaration and all 17 references, and each edit replaces exactly the identifier. A test applies the transaction and asserts that the only changed text is those identifiers.
The renamed program passes check, and the renamed symbol has the same reference count and kinds as before the rename. Covered by a test.
Renaming to a name already used in the same namespace (cakePos to i2) is refused with a stable diagnostic code and no transaction. Covered by a test.
A global and a player variable with the same name: renaming one leaves every reference to the other untouched. Covered by a test.
A new name that does not survive reparsing is refused with no transaction. Covered by a test.
validateEditTransaction on raw Workshop returns ok with previews for an edit that keeps the program valid. It returns a refusal carrying the reparse diagnostics for an edit that breaks the program. Covered by tests.
OPY input to a non-provider edit operation returns a structured refusal that names the provider operation. Covered by a test.
wright rename behaves as D2 decides. If D2 is accepted: without --write the input file's bytes are unchanged; with --write the file matches the validated preview; and a file modified between read and write is refused, with the file left untouched. Tests cover all three.
The tests that asserted unconditional refusal for raw Workshop edits are replaced by the behavior above. The PR states that this expectation change is intentional.
capabilities advertises the same operation list, and the agent-contract schema tests pass.
Ablation: removing the post-edit reference-count check makes a test that injects a mismatching edit fail.
Readiness:
needs-decisionon the two points under Decisions. The rest of the scope is settled. Also blocked on #433, since exact identifier spans are required.Problem
Wright advertises four edit operations. None of them succeeds on real input.
validateEditTransactionandsemanticRenamecannot succeed by construction. Incrates/wright-driver/src/edit.rs,validate_source_kindrejects raw Workshop withedit-unsupported-kind. For OPY, both functions end in an unconditionalrefusal(vec![source_provider_unavailable()])once every precondition has passed. I reproduced this onmain(0.3.0): a well-formed transaction againstoverpy-cake.wsreturnsedit-unsupported-kind.providerValidateEditandproviderSemanticRenamehave a real implementation incrates/wright-driver/src/provider_edit.rs, but it is tested only against a mock provider. The shippedopy-providerdoes not implement LPP rename or edit validation yet (Implement LPP rename and edit validation in opy-provider opy-rs#403 is open).crates/wright-cli/tests/serve.rsassertsok == falsefor both non-provider operations, andcrates/wright-driver/tests/edit.rsassertssource-provider-unavailable.So today Wright has no working validated source edit for any language. Yet
goal.mdprinciple 5 names "apply targeted edits" as core to agent workflows, and #134 lists "validated source-oriented mutation" in the 1.0 contract.Raw Workshop is the one language where Wright can close this gap with no provider.
workshop-rsowns parsing and validation,Program::edit_sourceproduces checked source edits, and #433 provides exact identifier spans.Why rename first, not lint fixes
None of the six current lint rules has a behavior-preserving mechanical fix:
min-wait-loopandwhile-without-wait: any fix changes timing.repeated-value: extracting the value needs a new variable slot and proof that the value is pure.expensive-loop-checkandongoing-condition-hot-path: these are heuristics, with no single correct edit.duplicate-condition: it reports false positives (duplicate-condition reports independent If blocks as unreachable with exact evidence #432), and deleting a branch is not safe to automate.Rename preserves behavior by definition, and textual replace cannot do it safely. A global variable and a player variable may share a name, and a name can appear as a substring of another name or inside a string. Rename is the edit where Wright's semantic knowledge is the whole difference, for humans and agents alike.
Scope
workshop-rsparse and validation path. The transaction isokonly if no error diagnostic results. The existing precondition, overlap, and atomicity rules apply unchanged.wright rename <NAME> <NEW_NAME> [INPUT], a shared human/agent surface with awright-result/v1envelope under--format json. Write behavior is decision D2.docs/agent-contract.md,docs/cli/commands.md, anddocs/architecture/tooling.mdfor the raw Workshop edit path.Decisions
D1. Which operations carry raw Workshop edits. Recommended: the non-provider
validateEditTransactionandsemanticRenamebecome the raw Workshop path, owned by Wright and backed byworkshop-rs. Theprovider*operations remain the source-language path. OPY input sent to a non-provider operation gets a structured refusal that names the provider operation. The change is additive in behavior: inputs that were always refused can now succeed, and no schema member changes. The alternative is a new operation pair, which would leave two permanently dead operations advertised.D2. Whether
wright renamewrites files. Recommended: by default it prints the validated change as a diff and writes nothing, and--writeapplies it atomically after validation.--writerefuses if any source's identity changed since it was read. This would makerenamethe first Wright command that modifies user source. Since the agent contract says "Wright proposes and validates; a caller remains responsible for applying them",--writeputs the CLI in the caller's role while leaving the agent operation unchanged. The alternative, preview only, keeps Wright read-only but leaves humans applying diffs by hand.Non-goals
wright lint --fixand lint suggestions. No current rule admits a safe fix (see above). Revisit when one does.provider*operations.Acceptance criteria
cakePostocakePositioninoverpy-cake.wsreturns anoktransaction. The transaction edits the declaration and all 17 references, and each edit replaces exactly the identifier. A test applies the transaction and asserts that the only changed text is those identifiers.check, and the renamed symbol has the same reference count and kinds as before the rename. Covered by a test.cakePostoi2) is refused with a stable diagnostic code and no transaction. Covered by a test.validateEditTransactionon raw Workshop returnsokwith previews for an edit that keeps the program valid. It returns a refusal carrying the reparse diagnostics for an edit that breaks the program. Covered by tests.wright renamebehaves as D2 decides. If D2 is accepted: without--writethe input file's bytes are unchanged; with--writethe file matches the validated preview; and a file modified between read and write is refused, with the file left untouched. Tests cover all three.capabilitiesadvertises the same operation list, and the agent-contract schema tests pass.Dependencies / ownership
wright-driver,wright-cli, docs).