This page defines how Fluxon user docs, developer docs, and design docs should be written. The goals are simple:
- Let readers reach the stable conclusion as quickly as possible.
- Keep docs aligned with code, public contracts, and actual behavior.
1. General Rules
- Lead with the conclusion, then expand. A reader should know what the page answers within the first 30 seconds.
- Prefer natural engineering terms. Avoid invented or template-heavy wording such as
root object,first-level branch, orauthority objectunless the term is truly necessary. - Write for readers, not as a dump of the author’s thinking process. Remove template filler such as “this section does not discuss” or “why this branch belongs to the previous layer.”
- If a paragraph can become a table, list, or diagram, do that instead of forcing a long linear explanation.
- API names, type signatures, and return semantics in docs must match the code exactly.
- Examples and quick starts must use the stable public contract. Do not expose internal compatibility layers, probing logic, or legacy usage in user-facing paths.
- Performance claims must be scoped. State the workload, baseline, and boundary of the conclusion instead of writing abstract claims like “faster.”
- Rules should be reusable methods, not a retelling of the current case. Concrete technical facts, incident lessons, and benchmark numbers belong in examples, counterexamples, or review checklists.
- For behavior, ownership, or performance claims, define the observation scope first: abstraction level, covered path, preconditions, and exclusions.
- Do not lift a local fact into a system-level conclusion without tracing the full path at the same abstraction level.
2. Design Docs
Design docs should default to an RFC or ADR style. Prefer this main structure:
- Background and goals
- Non-goals
- Core modules or roles
- Architecture diagram or sequence diagram
- Detailed design by dataflow or call flow
- Constraints, invariants, and failure conditions
- Key conclusions
Design docs should especially follow these rules:
- For cross-language boundaries, lifetime management, async sequencing, or ownership transfer, add a diagram by default. Readers rarely build a stable model from text alone.
- Organize by how data moves, not by the author’s internal tree structure.
- Separate public contracts, current implementation, and specialized fast paths explicitly.
- For conclusions that are easy to overgeneralize, verify the full chain at one abstraction level: how input is formed, how the boundary is crossed, how downstream consumes it, and how the lifetime ends.
- If multiple paths exist, such as a
putpointer path and anrpc_call(payload)bytes path, compare them side by side instead of switching back and forth inside the prose. - If one path only optimizes part of the operation, mark the remaining steps explicitly so readers do not mistake a local optimization for a whole-path result.
3. User Docs
- Lead with the stable usage pattern, then explain constraints and common pitfalls.
- Default to answering “how to use it,” not “how it works internally.”
- Commands, arguments, return objects, and prerequisites must be directly actionable.
- Do not introduce internal reserved fields, temporary adapters, or statements that are only true for the current implementation details.
- If an interface has a strong contract, such as
FlatDict,MemHolder, orFuture.wait(), the doc should use that contract directly instead of suggesting loosely typed alternatives.
4. Developer Docs
- Only include what maintainers actually need: entry scripts, key directories, artifacts, commands, and rerun conditions.
- For process docs, prefer
command + artifact + when to rerun. - For code-tour docs, prefer
module responsibility + boundary + invariant. - Do not put one-off debugging notes, temporary operator steps, or personal environment paths into long-lived docs.
5. Expression Rules
- Avoid empty claims such as “improves maintainability” or “improves extensibility” unless you also name the object and mechanism.
- Avoid
not ... but ...by default. Use it only when both sides are already established in context and the contrast materially helps at that exact spot. - Avoid overly long paragraphs. Large blocks of prose usually want to become a diagram, table, or list.
- When a term first appears, anchor it to a real code module, struct, public type, or reserved field.
- For important boundaries, prefer tables that state
supported / not supported / why.
6. Examples and Counterexamples
The items below are examples and counterexamples only, not the rule itself. They exist to show why the rules matter:
- Writing “zero-copy for the whole call chain” when the system is only zero-copy across one language boundary.
- Writing “multi-part protocol payloads are naturally zero-copy” when only a single field is borrowable.
- Writing “the underlying buffer is reusable” as if upper-layer object construction had no cost.
- Writing “no extra memcpy on the data plane” as if the control plane, scheduling, locks, or the GIL also had no cost.
The common failure behind these mistakes is:
- The scope of the conclusion was never defined first.
- Facts from different abstraction levels were mixed together.
- A local observation was used in place of a full end-to-end argument.
7. Pre-Publish Checklist
Before landing a doc, check at least these items:
- The opening already states the goal and scope of the page.
- API names, paths, and type names in the text really exist.
- Public contracts and internal specialized paths are not mixed together.
- A local optimization is not being presented as an end-to-end conclusion.
- Remaining costs such as encoding, assembly, materialization, locks, GIL overhead, or downstream reconstruction are not silently omitted.
- A diagram or table has not been omitted where it would clearly reduce reader effort.
- The writing does not contain obvious template tone, filler, or unnatural terms.