Skip to content

Commit 4128cac

Browse files
authored
docs(core): add Basic Machines agent style guidance (#921)
Signed-off-by: phernandez <paul@basicmachines.co>
1 parent 9b53d78 commit 4128cac

4 files changed

Lines changed: 157 additions & 3 deletions

File tree

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
name: basic-machines-review
3+
description: Use when reviewing Basic Machines code for house style, architecture risk, pre-merge hardening, or whether a change fits basic-memory/basic-memory-cloud conventions.
4+
license: MIT
5+
---
6+
7+
# Basic Machines Review
8+
9+
Use this skill for repo-local review passes where ordinary code review needs Basic Machines
10+
house style and architecture judgment. Report findings only; do not edit code unless the user
11+
asks you to fix specific findings.
12+
13+
## Scope
14+
15+
Review the current diff or named files against:
16+
17+
- The repo's `AGENTS.md` / `CLAUDE.md`
18+
- `docs/ENGINEERING_STYLE.md`
19+
- The touched code paths and tests
20+
21+
Apply only the guidance for the active repo. In `basic-memory`, prioritize local-first
22+
file/database/MCP boundaries. In `basic-memory-cloud`, prioritize tenant/workspace isolation,
23+
cloud worker behavior, and web-v2 state/runtime boundaries.
24+
25+
## Review Rubric
26+
27+
Report only concrete, falsifiable risks:
28+
29+
- **Cognitive load:** Is the change harder to understand than the problem requires?
30+
- **Change propagation:** Will one product change force edits across unrelated layers?
31+
- **Knowledge duplication:** Is the same rule encoded in multiple places that can drift?
32+
- **Accidental complexity:** Did the change add abstractions, fallbacks, or state without need?
33+
- **Dependency direction:** Are API/MCP/CLI, services, repositories, and UI stores respecting
34+
their intended boundaries?
35+
- **Domain model distortion:** Do names and types still match the product concept, or did a
36+
transport/storage detail leak into the domain?
37+
- **Test oracle quality:** Would the tests fail for the bug or regression the change claims to
38+
protect against?
39+
40+
## House Rules To Check Explicitly
41+
42+
- No speculative `getattr(obj, "attr", default)` for unknown model shapes.
43+
- No broad exception swallowing, warning-only failure paths, or hidden fallback behavior.
44+
- No casts or `Any` that hide an unclear type relationship.
45+
- Dataclasses for internal value/result objects; Pydantic at validation/serialization
46+
boundaries.
47+
- Narrow `Protocol`s when only a capability is needed.
48+
- Explicit async/resource ownership, cancellation, and cleanup.
49+
- Meaningful regression tests or verification for risky changes.
50+
- Comments explain why, not what.
51+
52+
## Reporting Format
53+
54+
Lead with findings ordered by severity. Each finding should include:
55+
56+
| Severity | Use for |
57+
| -------- | ------- |
58+
| `high` | A likely correctness, security, data-loss, or tenant/workspace isolation failure |
59+
| `medium` | A concrete maintainability or boundary risk that can cause future defects |
60+
| `low` | A minor consistency issue, ambiguous guidance, or review-only cleanup |
61+
62+
```text
63+
severity | file:line | risk category | claim
64+
Why: concrete behavior or code path that proves the risk.
65+
Fix: smallest practical change, or "none obvious" if the risk needs product input.
66+
```
67+
68+
If there are no findings, say so and note any verification gaps that remain.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../.agents/skills/basic-machines-review

AGENTS.md

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,34 @@ Before opening or updating a PR, run the checks that mirror the common required
108108
- Follow the repository pattern for data access
109109
- Tools communicate to api routers via the httpx ASGI client (in process)
110110

111+
### Programming Style
112+
113+
See [docs/ENGINEERING_STYLE.md](docs/ENGINEERING_STYLE.md) for the fuller house style. The
114+
short version for agents:
115+
116+
- Prefer type-safe, explicit designs over object-heavy indirection. Use Python 3.12 `type`
117+
aliases, full annotations, and narrow `Protocol`s when a caller only needs a capability.
118+
- Use dataclasses for internal value objects and operation results; use Pydantic v2 at API,
119+
CLI, MCP, and persistence boundaries where validation and serialization matter.
120+
- Keep async boundaries obvious. Resource-owning code should use context managers, propagate
121+
cancellation, and avoid hidden background work unless the lifecycle is explicit.
122+
- Fail fast. Do not add silent fallback logic, broad exception swallowing, speculative
123+
`getattr`, or casts that hide an unclear model shape.
124+
- Keep control flow simple and local. Push branching decisions up, keep leaf helpers focused,
125+
and name values after the domain concept they carry.
126+
- Use evidence-first testing. Add or update meaningful regression tests for bugs and risky
127+
behavior, prefer real code paths over mocks, and run the narrowest command that proves the
128+
change before widening verification.
129+
- Comments should explain why a branch, invariant, or constraint exists. Avoid comments that
130+
merely narrate obvious code.
131+
111132
### Code Change Guidelines
112133

113134
- **Full file read before edits**: Before editing any file, read it in full first to ensure complete context; partial reads lead to corrupted edits
114135
- **Minimize diffs**: Prefer the smallest change that satisfies the request. Avoid unrelated refactors or style rewrites unless necessary for correctness
115-
- **No speculative getattr**: Never use `getattr(obj, "attr", default)` when unsure about attribute names. Check the class definition or source code first
116-
- **Fail fast**: Write code with fail-fast logic by default. Do not swallow exceptions with errors or warnings
117-
- **No fallback logic**: Do not add fallback logic unless explicitly told to and agreed with the user
136+
- **House style is canonical**: Follow the Programming Style section above for type-safe,
137+
fail-fast code; do not hide unclear models with speculative attributes, broad exception
138+
handling, casts, or unapproved fallback logic
118139
- **No guessing**: Do not say "The issue is..." before you actually know what the issue is. Investigate first.
119140

120141
### Literate Programming Style

docs/ENGINEERING_STYLE.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Basic Memory Engineering Style
2+
3+
Style is how we make code easier to verify. Prefer explicit, typed, local-first code that
4+
preserves the file system as the source of truth while keeping the database, API, and MCP
5+
surfaces in sync.
6+
7+
## Design Center
8+
9+
- Basic Memory is local-first. Markdown files are the durable source; SQLite/Postgres indexes
10+
are derived state that should be rebuilt or reconciled from files when needed.
11+
- Keep the existing boundary order: CLI/MCP/API entrypoints compose dependencies, services own
12+
business behavior, repositories own database access, and file services own filesystem writes.
13+
- MCP tools should remain atomic and composable. They should call API routers through typed MCP
14+
clients, not reach around into services.
15+
- Prefer small, explicit abstractions that match a real domain boundary. Avoid object
16+
hierarchies when a function, dataclass, type alias, or protocol describes the concept better.
17+
18+
## Types And Data
19+
20+
- Use full type annotations and Python 3.12 syntax. Introduce `type` aliases for repeated
21+
structured shapes, callback signatures, or domain concepts that would otherwise become
22+
anonymous `dict[str, Any]` values.
23+
- Use dataclasses for internal values, operation inputs, and service results. Prefer
24+
`frozen=True` when the value should not change and `slots=True` when identity/dynamic
25+
attributes are not needed.
26+
- Use Pydantic v2 at boundaries that validate, serialize, or deserialize data: API payloads,
27+
CLI/MCP schemas, configuration, and persistence-adjacent schemas.
28+
- Use narrow `Protocol`s when a caller needs a capability rather than a concrete repository or
29+
service. Keep protocols small enough that fake implementations in tests are obvious.
30+
- Avoid speculative `getattr`, broad casts, or `Any` as a way to paper over uncertainty. Read
31+
the model or schema definition and make the type relationship explicit.
32+
33+
## Control Flow And Resources
34+
35+
- Fail fast when an invariant is broken. Do not swallow exceptions, add warning-only error
36+
handling, or introduce fallback behavior unless the user explicitly agrees to that behavior.
37+
- Keep control flow simple and close to the domain decision. Push `if` statements up into the
38+
function that owns orchestration; keep leaf helpers focused on computation or one side effect.
39+
- Make async/resource boundaries visible with context managers and explicit lifecycles. Do not
40+
start background work without a clear owner, cancellation story, and verification path.
41+
- Keep file mutations centralized through the existing file utilities/services so checksum,
42+
atomic write, and index synchronization behavior stays coherent.
43+
44+
## Testing And Verification
45+
46+
- Use evidence-first testing, not mechanical TDD. For bugs and risky behavior, add or update a
47+
regression test that would catch the failure. For small documentation-only edits, use the
48+
relevant doc/repo hygiene checks.
49+
- Prefer tests that exercise real code paths. Use mocks, doubles, or `monkeypatch` only when
50+
the external boundary would be slow, nondeterministic, or impossible to trigger directly.
51+
- Keep coverage at 100% for new code. Use `# pragma: no cover` only for code that would require
52+
disproportionate mocking and is covered through an integration or runtime path.
53+
- Start with targeted commands, then widen as risk grows: focused pytest, `just fast-check`,
54+
`just doctor`, package checks for agent packaging changes, and full SQLite/Postgres gates
55+
when behavior crosses shared boundaries.
56+
57+
## Comments And Names
58+
59+
- Name values after the domain concept they carry: project, entity, permalink, tenant, route,
60+
checksum, observation, relation, batch, or index state.
61+
- Comments should say why a branch, invariant, retry, lifecycle, or compatibility constraint
62+
exists. Section headers are useful when a function or file has clear phases.
63+
- Avoid comments that restate the code. If a comment cannot explain a decision, simplify the
64+
code or improve the name instead.

0 commit comments

Comments
 (0)