diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 2b3e2d6..15e0415 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -7,14 +7,15 @@ body: - type: markdown attributes: value: | - Thanks for helping improve Relay. Remove private credentials and proprietary source before posting. + Thanks for helping me improve Relay. A small reproduction makes it much easier for me to understand what happened. + Remove private credentials and proprietary source before posting. Relay reports are advisory and must not be treated as permission to operate physical machinery. - type: input id: version attributes: label: Relay version description: Run `relay --version`. - placeholder: relay 0.1.1 + placeholder: relay 0.1.2 validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 538d5f0..a56daf9 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -4,6 +4,10 @@ title: "[Feature]: " labels: - enhancement body: + - type: markdown + attributes: + value: | + I appreciate ideas that explain the real problem first. That context helps me decide whether Relay needs a new rule, better parsing, or clearer documentation. - type: textarea id: problem attributes: diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a36fb4f..f3e54fb 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,10 +1,11 @@ ## Summary -Describe what changed and why. +Tell me what you changed and what led you to it. ## User impact -Explain how this affects findings, compatibility, performance, reports, or documentation. +Explain how this affects findings, compatibility, performance, reports, or documentation. If +nothing changes for users, say that directly. ## Validation diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e8e395..85f821e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## 0.1.2 — 2026-07-29 + +- Added the personal story behind Relay and a narrative walkthrough of how analysis moves from + source discovery to findings and timing estimates. +- Reworked tutorials, architecture, configuration, timing, limitations, security, support, + contribution, conduct, and roadmap introductions in the maintainer's voice. +- Kept commands, rule definitions, safety boundaries, and compatibility statements concise and + technically unchanged. +- Updated GitHub issue and pull-request guidance to be more welcoming and direct. +- No analyser rules, report schemas, public Python APIs, or CLI behaviour changed in this + documentation-focused release. + ## 0.1.1 — 2026-07-29 - Centralized package versioning in `relay.__version__` so CLI and distribution metadata cannot diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 4c23ff9..28983e4 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,7 +1,7 @@ # Code of conduct -Relay contributors must help maintain a welcoming, technically rigorous, and safety-conscious -community. +I want Relay to stay welcoming, technically rigorous, and honest about safety. Everyone +participating in the project shares responsibility for that. ## Expected behaviour @@ -19,9 +19,9 @@ disruptive bad-faith behaviour are not accepted. Report security problems through [GitHub private security advisories](https://github.com/devkyato/Relay/security/advisories/new). -Report other conduct concerns privately to the repository owner through their GitHub profile. -Maintainers may edit or remove contributions and temporarily or permanently restrict participation -when needed to protect the community. +Report other conduct concerns privately to me through my GitHub profile. I may edit or remove +contributions and temporarily or permanently restrict participation when needed to protect the +community. Enforcement decisions should be proportionate, documented privately, and focused on community safety. This code applies in project spaces and when someone publicly represents the project. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 920c9cf..ebdfea4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,8 @@ # Contributing +Thanks for taking a look at Relay. I keep the project intentionally small and reviewable, so a +focused change with a clear reason is more useful than a broad rewrite. + Create a virtual environment, install `python -m pip install -e ".[dev]"`, then run: ```console @@ -14,3 +17,7 @@ Rules must keep stable IDs, deterministic ordering, exact-line fixtures, and exp Add false-positive and malformed-input tests with every detector change. Never execute analysed source in a test or implementation. Changes involving physical control safety should document assumptions and avoid claiming proof. + +When proposing a new rule, tell me what you noticed in real code, what Relay should report, and +where the heuristic could be wrong. That last part matters: I would rather document uncertainty +than make a confident claim the analyser cannot support. diff --git a/README.md b/README.md index ca32964..4c35007 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,16 @@ Arduino, ESP32, embedded C++, MicroPython, and Python control programs. Version alpha: useful for review and teaching, but intentionally cautious and not a safety certification. Analysis never executes, imports, compiles, or uploads the source being inspected. +## Why I built Relay + +I kept coming back to one awkward question while reading control code: if this call waits here, +what quietly stops running somewhere else? A plain warning about `delay()` was not enough for me. +I wanted to see the reachable call path, the time involved, and the tasks whose timing contracts +could be missed. + +That thought became Relay. I built it as a local-first project because firmware and control code +can be sensitive, and a review tool should not need to upload that source just to be useful. + ## Install Relay supports Python 3.9–3.14. @@ -27,7 +37,7 @@ relay --version On Linux or macOS, activate with `source .venv/bin/activate`. Normal analysis is entirely offline after installation. -## Five-minute demonstration +## Try it in five minutes ```console relay check examples @@ -38,7 +48,8 @@ relay rules relay doctor . ``` -Typical output: +I usually start with `relay check examples`, then narrow the command to one file once a finding +looks interesting. Typical output looks like this: ```text HIGH RLY101 blocking_robot.ino:16 @@ -56,6 +67,17 @@ Exit status is non-zero when a finding reaches `--fail-on` (default: `warning`). `--suggestions-out relay-suggestions.md` for reviewable patterns; Relay never edits source in 0.1.x and never claims a suggestion is automatically safe for machinery. +## How it works + +Relay discovers supported source files, parses their structure without running them, and looks +for blocking or timing-sensitive patterns. It then connects direct calls into an estimated call +graph and compares reachable blocking time with any timing contracts you configured. + +Oh—on this part, I deliberately kept facts and estimates separate. A source location is a fact; +an inferred call path or missed-execution count is an estimate. Every finding includes severity, +confidence, evidence, and a suggested direction so you can decide what holds up on the real +target. + ## Timing contracts Copy `relay.toml.example` to `relay.toml`, or run `relay init` (which refuses to overwrite an @@ -104,10 +126,12 @@ The public `AnalysisResult`, `Finding`, `Severity`, and `Confidence` models are ## What Relay is not -Relay is not a compiler, hardware simulator, formal-verification system, replacement for tests -on real devices, or a guarantee of real-time behaviour. It cannot see interrupt timing, library -internals, dynamic dispatch, electrical conditions, scheduler details, or worst-case execution -time. Its timeline is a conservative scheduling estimate, never a cycle-accurate simulation. +I thought carefully about this boundary: Relay should explain suspicious timing paths, not pretend +to certify them. It is not a compiler, hardware simulator, formal-verification system, +replacement for tests on real devices, or a guarantee of real-time behaviour. It cannot see +interrupt timing, library internals, dynamic dispatch, electrical conditions, scheduler details, +or worst-case execution time. Its timeline is a conservative scheduling estimate, never a +cycle-accurate simulation. ## Security, contributing, and licence @@ -117,4 +141,4 @@ analysed source or a symlink with a report. See [security](docs/security.md), [l [roadmap](docs/roadmap.md), [support](SUPPORT.md), [contributing](CONTRIBUTING.md), and [SECURITY.md](SECURITY.md). -Relay is copyright devkyato and available under the [MIT License](LICENSE). +This is a personal open-source project by devkyato, shared under the [MIT License](LICENSE). diff --git a/SECURITY.md b/SECURITY.md index f22add0..cbafa8c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,8 +1,8 @@ # Security policy -Relay 0.1.x receives best-effort security fixes. Report vulnerabilities privately through the -GitHub repository's security advisory feature; do not include sensitive source files in a public -issue. +Relay is a personal project, but I still want security reports handled carefully. Relay 0.1.x +receives best-effort security fixes. Report vulnerabilities privately through the GitHub +repository's security advisory feature; do not include sensitive source files in a public issue. Relay parses untrusted text but does not execute, import, compile, or upload it. Keep analysis offline. A Relay report is advice, not permission to deploy control code to physical machinery. diff --git a/SUPPORT.md b/SUPPORT.md index b39b481..a189b42 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -1,12 +1,15 @@ # Support -Relay is an early open-source project maintained on a best-effort basis. +Relay is a personal open-source project that I maintain on a best-effort basis. I may not answer +immediately, but a small reproducible example gives me the best chance of understanding what you +ran into. - Read the [README](README.md) and [documentation](docs/) first. -- Use the bug-report form for reproducible crashes or incorrect findings. -- Use the feature-request form for rule, parser, timing, or report proposals. +- Use the bug-report form when Relay crashes or reports something incorrectly. +- Use the feature-request form when you have an idea for a rule, parser, timing, or report change. - Report vulnerabilities through [GitHub private security advisories](https://github.com/devkyato/Relay/security/advisories/new). Include `relay --version`, Python and operating-system versions, the exact command, and a minimal -sanitised source sample. Do not post credentials, private firmware, or machinery control secrets. +sanitised source sample. Oh—and please do not post credentials, private firmware, or machinery +control secrets. diff --git a/docs/architecture.md b/docs/architecture.md index 02e902d..5715b1b 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,9 +1,16 @@ # Architecture -`discovery` performs bounded traversal. `lexer` masks C-family comments and strings while -preserving offsets; `parser` adds balanced blocks, calls, loops, functions, and constants. -Python uses `ast.parse` without importing the target. `callgraph` links simple direct calls. -`rules` emits immutable findings, `timing` logic applies contracts, and `reports`/`timeline` -present deterministic results. `analyser.analyse_path` is the public orchestration boundary. +I split Relay into small stages so I can reason about what each stage knows—and, just as +importantly, what it does not know. -No phase invokes a compiler, interpreter, hardware tool, network service, or target source. +1. `discovery` walks the requested path with explicit file-count and size bounds. +2. `lexer` masks C-family comments and strings while preserving source offsets. +3. `parser` identifies balanced blocks, calls, loops, functions, and simple constants. Python + uses `ast.parse` without importing the target. +4. `callgraph` connects simple direct calls, and `rules` emits immutable findings. +5. `timing` compares reachable blocking estimates with configured contracts. +6. `reports` and `timeline` present the result in deterministic order. + +`analyser.analyse_path` is the public orchestration boundary. Oh—one design choice I do not want +to blur: no stage invokes a compiler, interpreter, hardware tool, network service, or target +source. diff --git a/docs/configuration.md b/docs/configuration.md index 7309ad5..1885897 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,5 +1,8 @@ # Configuration +I kept configuration explicit and local to the project so a report can be traced back to the +assumptions that produced it. + Relay searches from the analysed path upward for `relay.toml`; `--config FILE` overrides this. The Python API uses the `RelayConfig` passed by its caller. diff --git a/docs/limitations.md b/docs/limitations.md index a29b5d5..c533a98 100644 --- a/docs/limitations.md +++ b/docs/limitations.md @@ -1,5 +1,8 @@ # Limitations +This is the page I would want someone to read before treating a finding as a conclusion. Relay is +useful because it is conservative, but that also means context can prove a warning harmless. + Relay's C-family parser is structural, not a complete C++ compiler. Macros, templates, overloads, function pointers, virtual dispatch, conditional compilation, and calls hidden in libraries can obscure behaviour. Python dynamic dispatch and monkey-patching are not resolved. Some polling, diff --git a/docs/releases/0.1.2.md b/docs/releases/0.1.2.md new file mode 100644 index 0000000..3bd1eb5 --- /dev/null +++ b/docs/releases/0.1.2.md @@ -0,0 +1,48 @@ +# Relay 0.1.2 + +Relay started with a question I kept asking while reading control code: when a call waits here, +what quietly stops running somewhere else? + +Version 0.1.2 tells that story more clearly. I rewrote the public documentation in the voice I +use when explaining the project to another person—direct, personal, and honest about what the +analysis can and cannot prove. + +## What changed + +- The README now explains why I built Relay and walks through how an analysis works. +- Tutorials connect each command to the reason I would use it during a review. +- Architecture, configuration, timing, and limitation pages explain the decisions behind their + technical details. +- Support, contributing, security, conduct, roadmap, and GitHub templates now sound like a + maintainer speaking directly to a contributor. +- Commands, rule meanings, report formats, and safety boundaries remain precise and unchanged. + +Oh—and that last point is important. This release changes how I explain Relay, not what Relay +claims to know. Findings are still conservative review prompts; timing values are still estimates; +and source is still analysed locally without being executed, imported, compiled, or uploaded. + +## How Relay works + +Relay first discovers supported files within explicit bounds. It parses Python with the standard +AST and C-family sources with a position-preserving structural parser. From there, it identifies +blocking patterns, connects simple direct calls, and compares reachable delays with any timing +contracts you provide. The output keeps source facts, inferred paths, and timing estimates +separate so each conclusion can be reviewed. + +## Compatibility + +- Python 3.9–3.14 +- Arduino, ESP32, embedded C++, MicroPython, and Python sources +- Local and offline operation after installation +- No analyser rule, report schema, Python API, or CLI behaviour changes from 0.1.1 + +## Install + +```console +python -m pip install relay_lint-0.1.2-py3-none-any.whl +relay --version +relay check examples +``` + +Relay does not guarantee real-time or physical-machine safety. Test every change on the actual +target before deployment. diff --git a/docs/roadmap.md b/docs/roadmap.md index 3852614..853e6e6 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,8 +1,10 @@ # Roadmap -Relay 0.1.x establishes the safe, local-first structural analyser and timing-impact model. +Relay 0.1.x is the foundation I wanted first: a safe, local-first structural analyser with an +honest timing-impact model. I am keeping the next steps focused on places where better context +can make the output more useful without making it sound more certain than it is. -Priorities for 0.2.0 are: +For 0.2.0, I am thinking about: - reduce false positives through context-aware network timeout and polling analysis; - add source-level suppression directives with auditable reasons; @@ -10,4 +12,6 @@ Priorities for 0.2.0 are: - prototype optional Clang enrichment without making it a core dependency; - expand timing contracts and machine-readable schemas without implying cycle accuracy. -Roadmap work is tracked in GitHub issues and may change based on reproducible user feedback. +Each item is tracked in GitHub issues. The order may change when a reproducible example shows +that another problem matters more; that is one of the nice parts of growing this as an open +personal project. diff --git a/docs/rules.md b/docs/rules.md index 0d9a9cc..573c45e 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -1,6 +1,8 @@ # Rule reference -Every rule reports evidence, location, severity, confidence, remediation, and this local reference. +I keep rule IDs stable so reports remain comparable across runs. Every rule reports evidence, +location, severity, confidence, remediation, and this local reference. The short descriptions +below explain what each rule notices; they are review prompts, not proof of unsafe behaviour. ## RLY101 Blocking Arduino `delay()`. **High / high confidence.** Use rollover-safe `millis()` scheduling. diff --git a/docs/security.md b/docs/security.md index 5b7a717..ac60b6c 100644 --- a/docs/security.md +++ b/docs/security.md @@ -1,5 +1,7 @@ # Secure analysis +My baseline for Relay is simple: reading a project should not mean running that project. + Relay reads source as bounded UTF-8 text with replacement for malformed bytes. It never imports analysed Python, invokes a build tool, compiles C++, follows directory symlinks, or makes a background network request. Default limits are 2 MB per file and 10,000 files. diff --git a/docs/timing-model.md b/docs/timing-model.md index 0fea447..47ac840 100644 --- a/docs/timing-model.md +++ b/docs/timing-model.md @@ -1,5 +1,9 @@ # Timing model +The question I want this model to answer is not “exactly how long will the hardware take?” Relay +cannot know that statically. The useful question is “if this visible wait is reachable, which +declared timing expectations could it disrupt?” + Relay evaluates literal durations and simple named numeric constants. A blocking duration is compared with each reachable task contract. Approximate missed executions are `floor(block duration / task period)`; latency excess is `block duration - maximum latency`. diff --git a/docs/tutorials.md b/docs/tutorials.md index 321ed21..72f7223 100644 --- a/docs/tutorials.md +++ b/docs/tutorials.md @@ -1,16 +1,23 @@ # Tutorials +These are the short workflows I use when showing Relay to someone for the first time. Start with +the smallest one that matches what you are reviewing, then follow the evidence back into the +source. + ## Review an Arduino sketch Run `relay check sketch.ino --suggest`. Start with high-confidence RLY101, RLY107, and RLY109 -findings, then inspect estimated call paths. Convert one blocking sequence at a time and rerun. +findings, then inspect estimated call paths. I prefer changing one blocking sequence at a time +and rerunning Relay so the effect stays easy to explain. ## Add deadlines Run `relay init`, map each task name to its actual function, and specify realistic periods or latency budgets. Use `relay timeline PATH --duration 5s` to communicate the conservative impact. +I thought about making contracts automatic, but explicit names and budgets are easier to audit. ## CI Use `relay check src --format sarif --output relay.sarif --fail-on high`. A status of 1 means a -finding met the threshold; 2 means invocation or configuration failed. +finding met the threshold; 2 means invocation or configuration failed. This distinction lets CI +separate “Relay found something” from “Relay could not complete the analysis.” diff --git a/src/relay/__init__.py b/src/relay/__init__.py index 92cfbe9..1dbabab 100644 --- a/src/relay/__init__.py +++ b/src/relay/__init__.py @@ -12,4 +12,4 @@ "Severity", "analyse_path", ] -__version__ = "0.1.1" +__version__ = "0.1.2"