Skip to content

Commit 760d8d4

Browse files
Merge pull request #25 from runtimeverification/refactor/rpc-logic-into-k
refactor: move RPC logic into K, slim the Python shim
2 parents 95cc69c + cbfc111 commit 760d8d4

20 files changed

Lines changed: 1705 additions & 1190 deletions

File tree

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
---
2+
name: writing-documentation
3+
description: Write, edit, refine, or review documentation and explanatory prose — README files, docs/ pages, design docs, module/class doc comments, and architecture write-ups. Use this whenever the user asks to improve, clarify, simplify, tighten, proofread, or rewrite docs, or to remove jargon, empty phrases, vague wording, or sentence fragments. Apply it even when the request looks like a small wording tweak, because the same standards apply at any size.
4+
---
5+
6+
# Writing and refining documentation
7+
8+
The goal of documentation is to transfer understanding to a reader as quickly and reliably as possible. Every sentence should either tell the reader something they can act on or remove a question they would otherwise have. Judge prose by how much it informs, not by how it sounds.
9+
10+
These standards apply both when you write new documentation and when you refine someone else's. When in doubt, prefer fewer words that say something concrete over more words that gesture at it.
11+
12+
## Match the abstraction level to the audience
13+
14+
Before you write or edit a passage, decide who reads it and at what level it should speak. Two questions settle this, and they shape every later choice about what to include.
15+
16+
- **Is the reader a user of the system or a contributor to it?** End-user documentation explains how to operate an interface: what to call, what to pass, and what comes back. Contributor documentation explains how the system works inside, so that someone can change it safely. The same fact often belongs in one and not the other, so identify the audience first and write to it consistently.
17+
- **Does this passage describe an interface or an implementation detail?** An interface is the contract a reader can depend on. An implementation detail is how that contract happens to be met today. Keep the two clearly separated, and when it is not obvious which one you are describing, say so.
18+
19+
Once you know the level, hold it steady:
20+
21+
- In user-facing documentation, leave out implementation details. A reader who wants to call a method does not need to know how it is built, and the extra mechanism buries what they came for. The one exception is a detail that would otherwise create a wrong expectation — for example, an operation that looks atomic but is not, or a default that is about to change. Surface that detail, because hiding it misleads the reader.
22+
- In contributor documentation, implementation details are essential, but they still need a budget. Include the detail that helps a reader understand or change the code, and leave out the rest. Too much mechanism drowns the main point as surely as too little starves it, so give each passage the amount of detail its context calls for and no more.
23+
24+
A mismatch in level is itself a defect, even when every sentence is individually correct. A paragraph that slides from interface to internals and back forces the reader to keep re-orienting, which is the opposite of what the documentation is for.
25+
26+
## Writing standards
27+
28+
1. **Write to inform, not to impress.** Do not reach for elevated vocabulary, clever framing, or an authoritative tone for its own sake. If a plain word works, use the plain word. Prose that tries to sound smart usually hides that it is saying little.
29+
30+
2. **Keep jargon to a minimum.** Jargon is any term whose meaning depends on insider knowledge. Some is unavoidable in technical writing, but every term you keep is a small toll the reader pays. Spend that toll only when the term earns it.
31+
32+
3. **Make sure every technical term is either well understood by the target audience or defined where it first appears.** Before using a term, ask who reads this document and whether they already share its meaning. A term like "shim" is a bad sign: it has no agreed definition, so it lets the writer feel precise while telling the reader almost nothing. Either name the concrete thing the term stands for ("the long-running process that holds the socket and persists state") or define it on first use.
33+
34+
4. **Write in full, grammatically complete sentences.** Avoid sentence fragments and half-finished thoughts. A fragment forces the reader to reconstruct the missing subject or verb, which is exactly the work good documentation should do for them. See [Repairing sentence fragments](#repairing-sentence-fragments) below for the common shapes and how to fix them.
35+
36+
5. **Prefer active voice, but do not force it.** "Python decodes the envelope" reads more directly than "the envelope is decoded by Python." Active voice names who does what, which removes ambiguity. Where the actor is genuinely unknown or irrelevant, passive voice is fine — do not contort a sentence to avoid it.
37+
38+
6. **Replace empty phrases with real information, or delete them.** When you find a phrase that carries little meaning, first try to replace it with the fact it was standing in for. If there is no such fact, remove the phrase entirely. See [Spotting empty phrases](#spotting-empty-phrases).
39+
40+
7. **State objective facts, not subjective claims.** Documentation describes what the system is and does; it does not argue that the system is good. The reader came to understand the tool, not to be persuaded of its quality, and praise from its own documentation carries no weight anyway. Avoid value judgments and promotional words such as "powerful", "blazing fast", "simple", "elegant", "robust", and "seamless". When you find one, replace it with the concrete, verifiable property behind it: instead of "a fast, lightweight server", write "a single-threaded HTTP server that runs each request in one interpreter process", and let the reader judge. If a characterization has no fact behind it, drop it.
41+
42+
## Spotting empty phrases
43+
44+
An empty phrase occupies space without changing what the reader knows. Common kinds:
45+
46+
- **Undefined jargon**, as in standard 3 above.
47+
- **Contrasts that do not explain themselves.** "Rather than running a real validator, it ..." sets up a difference but never says what the difference is, so the reader learns nothing. Either explain the contrast concretely (for example, "real Stellar RPC is built around a mempool and ledger close, so ...") or drop it. A contrast is worth keeping only when the same sentence makes clear what is being contrasted and why it matters.
48+
- **Filler preambles and intensifiers**: "It is worth noting that", "Of course", "Simply", "Essentially", "A guiding constraint:". These announce a thought instead of delivering it. Cut them and start with the thought.
49+
- **Restatements** that repeat the previous clause in new words, and **vacuous qualifiers** ("now", "actually", "in practice") that hint at a comparison the reader cannot see.
50+
51+
Watch for words like "now survive restarts" or "those now live in K" in standalone documentation: "now" silently compares against an earlier design the reader does not know about.
52+
53+
## Repairing sentence fragments
54+
55+
Three shapes show up again and again in reference-style docs:
56+
57+
- **Label openers**: "The long-running process." or "The XDR boundary." followed by a separate sentence. Fold the label into a real sentence with a subject: "`StellarRpcServer` is the long-running process around the semantics."
58+
- **Verb-first lines with no subject**: "Decodes the envelope and returns a pair." Give it the subject it describes: "`build_tx_request` decodes the envelope and returns a pair."
59+
- **Noun-phrase or participle fragments**: "A helper that pretty-prints the config." or "Used by `demo.py` to render each step." Turn each into a full sentence, and prefer active voice for the participle form: "`demo.py` uses it to render each step."
60+
61+
An em-dash is a useful warning sign. An em-dash inside a complete sentence is fine, but an em-dash followed by a trailing fragment ("... and returns a pair — for the interpreter to splice in") often marks an underdeveloped thought that should become its own sentence or fold into the main clause. Treat a trailing em-dash as a prompt to check whether the thought after it is complete.
62+
63+
## What to leave alone
64+
65+
Restraint matters as much as correction. Do not turn every list into prose. These constructs are conventional and clear, and rewriting them as full sentences usually hurts readability:
66+
67+
- Tables and code blocks.
68+
- Glossary or reference lists in `name — short description` form (an API method index, a flags table, a list of file roles).
69+
- Rosters under a heading that already supplies the predicate, such as a "What's not yet implemented" list whose every item is implicitly "is not implemented."
70+
- Numbered procedure steps written as imperatives ("Write the request file.", "Parse the state."), which are already complete sentences.
71+
72+
A self-explaining contrast, a passive sentence with an irrelevant actor, and a deliberately terse reference entry are all fine. Change something only when the change makes the reader's job easier.
73+
74+
## How to run a refinement pass
75+
76+
When asked to clean up documentation, the user usually gives one example of a problem. Treat that example as one instance of a whole class, and handle the class.
77+
78+
1. **Read the whole document set, not just the flagged spot.** The same problem almost always recurs across files. Read every doc in scope before editing.
79+
2. **Find every instance of the class.** After reading, use `grep` to catch recurring patterns mechanically — for example, search for verb-first line starts, filler words, or contrast phrases — so you do not miss any.
80+
3. **Judge each candidate.** Separate genuine problems from acceptable constructs (see [What to leave alone](#what-to-leave-alone)). Do not invent problems to fix.
81+
4. **Fix each one in place**, keeping the original meaning. Replace empty phrases with the fact behind them, give fragments a subject, and prefer active voice.
82+
5. **Verify the docs against reality when they describe behavior.** A confident but stale sentence is worse than a wordy one. If a doc claims the code does X, confirm the code still does X. (In this codebase, that check has already caught a doc describing a `chdir` the code no longer performs.)
83+
6. **Verify your pass.** Re-run the `grep` scans to confirm no instances of the class remain, and reread the edited sections to make sure each still flows.
84+
7. **Summarize for the user.** Give a short table of the meaningful changes (before → after, with a one-line reason), and state plainly what you deliberately left unchanged and why. The "left unchanged" part shows your judgment and lets the user catch anything you misjudged.
85+
86+
## Audit prose you write, not just prose you inherit
87+
88+
[The refinement pass above](#how-to-run-a-refinement-pass) is framed around cleaning up existing text, and that framing hides a trap: it is easy to scan inherited prose for these problems while treating a sentence you just wrote as finished. The standards apply equally to both. Before you consider a passage you authored done — whether a whole new document or a single replacement sentence — run the same checks against it (abstraction level, empty phrases, fragments, and the rest) exactly as you would on someone else's draft.
89+
90+
Two failures show up most often in freshly written prose, so check for them every time:
91+
92+
- **A first sentence that announces a thought instead of delivering it.** "What makes it different is the execution engine." promises a difference without naming it — a filler preamble disguised as a topic sentence. Cut it and start the paragraph with the concrete fact.
93+
- **A clause that describes how the system is built, in user-facing prose.** Mechanism leaks in most easily here, because explaining the internals feels like supplying substance. Ask of each clause whether it tells the reader something they can act on or only how the machinery works, and move the latter to the contributor docs — unless it prevents a wrong expectation (see [Match the abstraction level](#match-the-abstraction-level-to-the-audience)).
94+
95+
Then read the passage once as its target reader and ask of each sentence: does this inform me, or does it only sound like it should? Delete or replace whatever fails.
96+
97+
## Scope discipline
98+
99+
Stay close to the class of change the user asked for. If you notice an adjacent issue (a factual error, a confusing structure, a missing section), mention it in your summary and offer to address it, rather than silently expanding the edit. Change code or behavior only when fixing a factual inaccuracy in the documentation itself, and call that out explicitly when you do.

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,14 @@
22
__pycache__/
33
.coverage
44
.direnv/
5+
6+
# Runtime artifacts written by the server / interpreter in the io dir
7+
metadata.json
8+
response.json
9+
state.kore
10+
trace.jsonl
11+
transactions.json
12+
13+
# Claude Code local artifacts (keep skills, ignore per-user/runtime files)
14+
.claude/settings.local.json
15+
.claude/scheduled_tasks.lock

README.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,20 @@
1616

1717
## 🌟 Overview
1818

19-
`komet-node` extends the standard Stellar RPC with a `traceTransaction` method that provides instruction-level execution traces. The node's ledger state can be saved to and restored from a single file, allowing the same ledger state to be reproduced and transactions to be replayed.
19+
`komet-node` is a Stellar testnet node you run on your own machine. It serves the standard [Stellar RPC](https://developers.stellar.org/docs/data/apis/rpc) API, so the SDKs, wallets, and tooling you already use with Stellar work against it unchanged — you point them at `localhost` instead of a public network.
20+
21+
It is built for developing, testing, and debugging Soroban contracts locally, and adds two capabilities a public Stellar network does not offer:
22+
23+
- **Instruction-level traces.** The `traceTransaction` method runs a transaction and returns a step-by-step record of every WebAssembly instruction the contract executed, so you can see exactly what happened — and where it went wrong.
24+
- **Reproducible, replayable state.** The ledger state is persisted to disk, so you can stop and restart the node, save a state, and replay transactions against it to reproduce a result.
2025

2126
## 🚀 Quick Start
2227

2328
### Installation
2429

2530
#### Install with kup
2631

27-
`komet-node` is distributed through [`kup`](https://github.com/runtimeverification/kup), Runtime Verification's Nix-based package manager. It pulls prebuilt binaries (including the matching K Framework and kompiled semantics) from RV's binary cache, so there is nothing to compile.
32+
`komet-node` is distributed through [`kup`](https://github.com/runtimeverification/kup), Runtime Verification's Nix-based package manager. It pulls prebuilt binaries (including the matching K Framework and compiled semantics) from RV's binary cache, so there is nothing to compile.
2833

2934
```bash
3035
# 1. Install the kup package manager (one time)
@@ -41,7 +46,7 @@ To upgrade later, run `kup update komet-node`.
4146

4247
#### Run with Docker
4348

44-
Alternatively, a prebuilt image is published to Docker Hub for each release. It bundles K, the kompiled semantics, and `komet-node` ready to serve.
49+
Alternatively, a prebuilt image is published to Docker Hub for each release. It bundles K, the compiled semantics, and `komet-node` ready to serve.
4550

4651
```bash
4752
# Pull the image (replace the tag with the release you want)
@@ -75,7 +80,7 @@ komet-node --trace # enable instruction-level execution tracing
7580
| `--state-file` | `state.kore` | Path to the persistent state file |
7681
| `--trace` | off | Enable instruction-level execution tracing |
7782

78-
On first start the server creates an empty `state.kore`. Delete that file to reset the chain, or point `--state-file` at a pre-built configuration to resume from a snapshot.
83+
On first start the server creates `state.kore` in the state file's directory — along with two small bookkeeping files, `metadata.json` and `transactions.json` — and begins from an empty chain. The state persists across restarts, so stopping and restarting the node resumes the same chain. To start over from an empty chain, delete `state.kore`; to resume from a chain you saved earlier, point `--state-file` at it.
7984

8085
#### Verify the server with `curl`
8186

@@ -168,13 +173,13 @@ The bundled demo deploys and invokes a Soroban contract end-to-end (create accou
168173
uv run python -m komet_node.demo src/tests/integration/data/wasm/empty.wat
169174
```
170175

171-
This produces `state.kore` plus `state_<n>_<step>.pretty` files under `./out`, letting you inspect exactly how the formal state evolves. (Requires `wat2wasm` from [`wabt`](https://github.com/WebAssembly/wabt) on your `PATH`.)
176+
This produces `state.kore` plus `state_<n>_<step>.pretty` files under `./out`, letting you inspect exactly how the ledger state evolves at each step. (Requires `wat2wasm` from [`wabt`](https://github.com/WebAssembly/wabt) on your `PATH`.)
172177

173178
---
174179

175180
## For Developers
176181

177-
Prerequisites: `python >= 3.10`, [`uv`](https://docs.astral.sh/uv/), [`wabt`](https://github.com/WebAssembly/wabt) (for `wat2wasm`), and the K Framework. The [Dev Container](#for-developers) provisions all of these for you.
182+
Prerequisites: `python >= 3.10`, [`uv`](https://docs.astral.sh/uv/), [`wabt`](https://github.com/WebAssembly/wabt) (for `wat2wasm`), and the K Framework. The Dev Container provisions all of these for you.
178183

179184
1. Install [VS Code](https://code.visualstudio.com/) and the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers).
180185
2. Open this repository in VS Code and choose **Reopen in Container** when prompted.
@@ -201,16 +206,18 @@ Common tasks are driven by `make` (see the [Makefile](Makefile) for the complete
201206
To build the node from source use:
202207

203208
```bash
209+
make build-kdist
204210
make build
205211
pip install dist/*.whl
206212
```
207213

208214
### Documentation
209215

210216
- [Architecture overview](docs/architecture.md) — how the pieces fit together
211-
- [Server](docs/server.md) — the RPC layer, state lifecycle, and full method reference
212-
- [Interpreter](docs/interpreter.md) — transaction → K step translation
213-
- [K semantics](docs/node-semantics.md) — the on-chain execution model
217+
- [Server](docs/server.md) — the long-running HTTP server that wraps the K interpreter, plus the state lifecycle and the full method reference
218+
- [Transaction encoding](docs/transaction.md) — Stellar XDR → K request envelope
219+
- [Interpreter](docs/interpreter.md) — running request envelopes through the K semantics
220+
- [K semantics](docs/node-semantics.md) — the on-chain RPC dispatch and execution model
214221

215222
---
216223

0 commit comments

Comments
 (0)