141 lines
No EOL
5.1 KiB
Markdown
141 lines
No EOL
5.1 KiB
Markdown
## Documentation for agents
|
||
|
||
You **MUST** read each of these documents before contributing to this repository:
|
||
- Git workflow rules: `docs/agents/git-workflow.md`
|
||
- Repo interaction rules: `docs/agents/repo-instructions.md`
|
||
- Domain model & context rules: `docs/agents/domain.md`
|
||
|
||
---
|
||
|
||
## Critical Coding & Version Control Conduct
|
||
|
||
- **NEVER** commit directly to `master` or `testing without explicit human instruction.
|
||
- **NEVER** merge into `master` or `testing` without explict human instruction.
|
||
- **ALWAYS** create new branches when working on non-trivial coding tasks.
|
||
- **ALWAYS** commit self-contained logical unit of work.
|
||
|
||
---
|
||
|
||
## Issues, PRs, and Comments Conduct
|
||
- **ALWAYS** end your written contributions with `Written by AI agent working for @jtmorris. Model: <MODEL NAME>.`. Replace `<MODEL NAME>` with the LLM model, version, and, if relevant, number of parameters. For example: `Claude Sonnet 4.7`, `Grok 4.3`, `Qwen 3.6 27B`.
|
||
|
||
---
|
||
|
||
## Critical Design Rules
|
||
|
||
### 1. Only Store or Cache State When It Serves a Purpose
|
||
|
||
**Never store or cache state unless doing so meets at least one of:**
|
||
1. It is the authoritative source of truth owned by this component.
|
||
2. It delivers actionable feedback that meaningfully improves the user experience or a decision.
|
||
3. It provides a demonstrable and reasonably argued security or performance improvement (the burden of proof is on the proposer).
|
||
4. The information cannot be obtained at the moment it is needed and keeping it produces a clear net benefit.
|
||
|
||
Storing state creates a potential disconnect with reality. Managing that disconnect requires extra tests, defensive checks, and cognitive overhead. State should be added only when the benefit is obvious and defensible.
|
||
|
||
**Textbook Example (this repository – issue #11)**
|
||
Proposal: run `which tailscale` at startup, set a `binaryAvailable` boolean, and guard every `tailscale` invocation behind it.
|
||
|
||
**Why this was harmful**
|
||
1. Wrong solution to the actual problem. This project is a GUI wrapper around the `tailscale` binary. If the binary doesn’t exist, there is nothing to do except surface an error. Storing a flag and guarding UI actions adds state for no gain.
|
||
2. Creates a new class of edge cases that must be tested: the binary existed when the flag was set but later disappears. The code must now defend against both “flag is false” and “flag is wrong.”
|
||
3. Unreliable guard for a failure the code must handle anyway. A missing binary produces a clear exit-code failure on the real command. Checking the flag *and* handling the failure duplicates work.
|
||
Reference: #11.
|
||
|
||
|
||
## Code Style Guidance
|
||
|
||
### 1. **NEVER** Write Conditional and Loop Blocks Without Curly Braces
|
||
|
||
**ALWAYS** use curly braces, `{}`, for if, else, while, and for blocks, even when they contain only a single statement. This ensures that any future additions to the block remain within the intended control flow. Reference: `CVE-2014-1266`.
|
||
|
||
**GOOD** Examples:
|
||
```javascript
|
||
if (myvar) {
|
||
do_action();
|
||
}
|
||
```
|
||
```javascript
|
||
if (myvar) { do_action(); }
|
||
```
|
||
```javascript
|
||
while (myvar) {
|
||
do_action();
|
||
}
|
||
```
|
||
```javascript
|
||
while (myvar) { do_action(); }
|
||
```
|
||
|
||
**BAD** Examples:
|
||
```javascript
|
||
if (myvar)
|
||
do_action();
|
||
```
|
||
```javascript
|
||
if (myvar) do_action();
|
||
```
|
||
```javascript
|
||
while (myvar)
|
||
do_action();
|
||
```
|
||
```javascript
|
||
while (myvar) do_action();
|
||
```
|
||
|
||
### 2. ALWAYS Terminate JavaScript Statements with Semicolons
|
||
|
||
ALWAYS end every JavaScript statement with a semicolon (;).
|
||
|
||
Rationale: Semicolons make intent explicit, eliminate ASI surprises, improve readability, and produce clearer diffs and tooling output.
|
||
|
||
Scope:
|
||
- Applies to all JavaScript statements — inside signal handlers (onClicked: { ... }), custom methods (function foo() { ... }), arrow function bodies, standalone .js files, and test files.
|
||
- Does NOT apply to QML declarative property bindings (width: 100, text: "foo", anchors.centerIn: parent, model: myModel, etc.). These are not statements; adding ; after them is either a syntax error or non-idiomatic in QML.
|
||
- When multiple QML bindings are written on a single line for compactness, ; is used only as a separator between bindings (Qt/QML convention), not as a statement terminator.
|
||
|
||
GOOD (JavaScript statements):
|
||
```javascript
|
||
// Inside a QML signal handler or method
|
||
onClicked: {
|
||
root.toggleTailscale();
|
||
ToastService.showInfo("Toggled");
|
||
}
|
||
function buildCommand(hostname) {
|
||
if (hostname === "") {
|
||
return ["tailscale", "set", "--exit-node="];
|
||
}
|
||
return ["tailscale", "set", "--exit-node=" + hostname];
|
||
}
|
||
```
|
||
|
||
```javascript
|
||
// In a .js file
|
||
if (!peerMap) {
|
||
return [];
|
||
}
|
||
return Object.keys(peerMap).map(...);
|
||
```
|
||
|
||
BAD (missing semicolons on statements):
|
||
```javascript
|
||
if (condition) {
|
||
doAction()
|
||
}
|
||
return value
|
||
```
|
||
|
||
BAD (incorrect semicolon on QML binding — never do this):
|
||
```javascript
|
||
width: 360; // OK (separator on same line)
|
||
height: 400; // WRONG — this is a binding, not a statement
|
||
text: "Tailscale"; // WRONG
|
||
```
|
||
|
||
GOOD (correct QML binding style):
|
||
```javascript
|
||
width: 360
|
||
height: 400
|
||
text: "Tailscale"
|
||
Item { width: 1; height: 1; Layout.fillWidth: true } // ; only as separator
|
||
``` |