diff --git a/BOOTSTRAP.md b/BOOTSTRAP.md
index 297cbae..80530a5 100644
--- a/BOOTSTRAP.md
+++ b/BOOTSTRAP.md
@@ -84,6 +84,7 @@ Optional but recommended:
|-------|---------|
| `tech-debt` | Gardener can promote these to `backlog` |
| `blocked` | Dev-agent marks issues with unmet dependencies |
+| `formula` | *(requires `feat/formula` merge)* Dev-agent uses a structured TOML formula instead of freeform. Issue body must include YAML front matter, e.g.:
`---`
`formula: upgrade-dependency`
`vars:`
` package: viem`
` ecosystem: npm`
`---` |
### Required: Branch protection
diff --git a/formulas/add-rpc-method.toml b/formulas/add-rpc-method.toml
new file mode 100644
index 0000000..f11e1f4
--- /dev/null
+++ b/formulas/add-rpc-method.toml
@@ -0,0 +1,88 @@
+# formulas/add-rpc-method.toml — Add a new JSON-RPC method to a server
+
+name = "add-rpc-method"
+description = "Add JSON-RPC method {{method_name}} to the server"
+version = 1
+
+[vars.method_name]
+description = "Full method name (e.g. eth_getBalance, harb_listPositions)"
+required = true
+
+[vars.params_spec]
+description = "Comma-separated parameter names and types (e.g. 'address: Address, blockTag: BlockTag')"
+required = false
+default = ""
+
+[vars.return_type]
+description = "Return type description (e.g. 'U256 balance', 'Vec')"
+required = false
+default = "result"
+
+[[steps]]
+id = "read-existing"
+title = "Read existing RPC methods for patterns"
+description = """
+Find and read 2-3 existing RPC method implementations in this codebase.
+Identify:
+- Where method handlers are defined (trait, module, file)
+- How methods are registered with the router/server
+- How params are deserialized and validated
+- How errors are returned (error type, codes)
+- How tests are structured for RPC methods
+Note the file paths so subsequent steps can follow the same patterns.
+"""
+
+[[steps]]
+id = "implement-handler"
+title = "Implement {{method_name}} handler"
+description = """
+Create the handler for {{method_name}} following the patterns found above.
+
+Method signature should accept: {{params_spec}}
+Return type: {{return_type}}
+
+Requirements:
+- Validate input parameters; return appropriate JSON-RPC error codes for invalid input
+- Implement the core logic
+- Add inline documentation describing the method's purpose and params
+- Follow the naming conventions and error-handling style of existing methods
+"""
+needs = ["read-existing"]
+
+[[steps]]
+id = "register-method"
+title = "Register {{method_name}} with the RPC router"
+description = """
+Add {{method_name}} to the server's method registry / router, following the
+same registration pattern used by existing methods.
+
+The namespace is the prefix of {{method_name}} before the underscore
+(e.g. "eth" for "eth_getBalance"). Verify the server's namespace filter or
+allowlist includes this namespace in the default configuration.
+"""
+needs = ["implement-handler"]
+
+[[steps]]
+id = "write-tests"
+title = "Write tests for {{method_name}}"
+description = """
+Add at least two tests for {{method_name}}:
+1. Happy path — valid input, expected {{return_type}} returned
+2. Error path — invalid or missing params, correct JSON-RPC error returned
+
+Follow the test patterns found in read-existing.
+Use any existing test fixtures or mock server helpers.
+"""
+needs = ["register-method"]
+
+[[steps]]
+id = "run-tests"
+title = "Run tests and verify"
+description = """
+Run the full test suite (e.g. cargo test, npm test, forge test).
+Confirm:
+- New tests pass
+- No existing tests were broken
+Fix any compilation errors or assertion failures before finishing.
+"""
+needs = ["write-tests"]
diff --git a/formulas/upgrade-dependency.toml b/formulas/upgrade-dependency.toml
new file mode 100644
index 0000000..76686c8
--- /dev/null
+++ b/formulas/upgrade-dependency.toml
@@ -0,0 +1,78 @@
+# formulas/upgrade-dependency.toml — Upgrade a package dependency
+
+name = "upgrade-dependency"
+description = "Upgrade {{package}} to {{to_version}}"
+version = 1
+
+[vars.package]
+description = "Package name to upgrade (e.g. viem, serde, forge-std)"
+required = true
+
+[vars.ecosystem]
+description = "Package ecosystem: npm, cargo, or forge"
+required = true
+
+[vars.from_version]
+description = "Current version (e.g. 1.2.3) — used for changelog lookup"
+required = false
+default = "current"
+
+[vars.to_version]
+description = "Target version (e.g. 2.0.0) — leave blank for latest"
+required = false
+default = "latest"
+
+[[steps]]
+id = "check-current"
+title = "Check current {{package}} version and changelog"
+description = """
+Identify the installed version of {{package}} in the lockfile or manifest.
+Look up the changelog or release notes between {{from_version}} and {{to_version}}.
+Note any breaking changes, deprecations, or migration steps required.
+"""
+
+[[steps]]
+id = "upgrade"
+title = "Run upgrade for {{ecosystem}}"
+description = """
+Run the appropriate upgrade command for ecosystem={{ecosystem}}:
+
+- npm: npm install {{package}}@{{to_version}} (or @latest)
+- cargo: cargo update -p {{package}} [--precise {{to_version}}]
+ Or bump version in Cargo.toml, then: cargo build
+- forge: forge update {{package}}
+ (Use forge install only if reinstalling from scratch after manually
+ editing the commit hash in .gitmodules or lib/)
+
+Confirm the lockfile / manifest now reflects {{to_version}}.
+"""
+needs = ["check-current"]
+
+[[steps]]
+id = "fix-breaking-changes"
+title = "Apply migration steps for breaking changes"
+description = """
+Based on the changelog reviewed in check-current, apply any required changes:
+- Rename renamed APIs or types
+- Update import paths if they moved
+- Adjust call sites for signature changes
+- Remove usage of deprecated symbols
+
+If no breaking changes were noted, verify a quick build still passes.
+"""
+needs = ["upgrade"]
+
+[[steps]]
+id = "run-tests"
+title = "Run tests and verify"
+description = """
+Run the full test suite appropriate for ecosystem={{ecosystem}}:
+
+- npm: npm test (or the project's test script)
+- cargo: cargo test
+- forge: forge test
+
+Confirm all tests pass. Fix any compilation errors or test failures introduced
+by the upgrade before declaring this done.
+"""
+needs = ["fix-breaking-changes"]