bros-harness 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/README.md +183 -0
- package/SECURITY.md +16 -0
- package/assets/agents.manifest.json +55 -0
- package/assets/commands.manifest.json +35 -0
- package/assets/docs.manifest.json +20 -0
- package/assets/import-report.md +25 -0
- package/assets/manifest.json +799 -0
- package/assets/opencode/agents/README.md +3 -0
- package/assets/opencode/agents/bro-build.md +256 -0
- package/assets/opencode/agents/bro-design.md +77 -0
- package/assets/opencode/agents/bro-docs.md +72 -0
- package/assets/opencode/agents/bro-explore.md +143 -0
- package/assets/opencode/agents/bro-ops.md +195 -0
- package/assets/opencode/agents/bro-shield.md +77 -0
- package/assets/opencode/agents/bro-test.md +204 -0
- package/assets/opencode/agents/bro-ui.md +135 -0
- package/assets/opencode/agents/mighty-bro.md +252 -0
- package/assets/opencode/commands/README.md +3 -0
- package/assets/opencode/commands/bros-assemble.md +32 -0
- package/assets/opencode/commands/bros-build.md +58 -0
- package/assets/opencode/commands/bros-plan.md +83 -0
- package/assets/opencode/commands/bros-review.md +38 -0
- package/assets/opencode/commands/bros-status.md +26 -0
- package/assets/opencode/docs/README.md +3 -0
- package/assets/opencode/docs/bros-builtin-skills.md +63 -0
- package/assets/opencode/docs/bros-harness.md +194 -0
- package/assets/opencode/skills/README.md +3 -0
- package/assets/opencode/skills/agent-architecture-audit/SKILL.md +256 -0
- package/assets/opencode/skills/agent-harness-construction/.openskills.json +7 -0
- package/assets/opencode/skills/agent-harness-construction/SKILL.md +73 -0
- package/assets/opencode/skills/agent-introspection-debugging/.openskills.json +7 -0
- package/assets/opencode/skills/agent-introspection-debugging/SKILL.md +153 -0
- package/assets/opencode/skills/api-design/.openskills.json +7 -0
- package/assets/opencode/skills/api-design/agents/openai.yaml +7 -0
- package/assets/opencode/skills/architecture-decision-records/.openskills.json +7 -0
- package/assets/opencode/skills/architecture-decision-records/SKILL.md +179 -0
- package/assets/opencode/skills/article-writing/.openskills.json +7 -0
- package/assets/opencode/skills/article-writing/SKILL.md +79 -0
- package/assets/opencode/skills/article-writing/agents/openai.yaml +7 -0
- package/assets/opencode/skills/automation-audit-ops/.openskills.json +7 -0
- package/assets/opencode/skills/automation-audit-ops/SKILL.md +142 -0
- package/assets/opencode/skills/backend-patterns/.openskills.json +7 -0
- package/assets/opencode/skills/backend-patterns/SKILL.md +561 -0
- package/assets/opencode/skills/backend-patterns/agents/openai.yaml +7 -0
- package/assets/opencode/skills/benchmark/.openskills.json +7 -0
- package/assets/opencode/skills/benchmark/SKILL.md +93 -0
- package/assets/opencode/skills/bros-orchestrate/SKILL.md +455 -0
- package/assets/opencode/skills/browser-qa/.openskills.json +7 -0
- package/assets/opencode/skills/browser-qa/SKILL.md +87 -0
- package/assets/opencode/skills/canary-watch/.openskills.json +7 -0
- package/assets/opencode/skills/canary-watch/SKILL.md +107 -0
- package/assets/opencode/skills/code-review-expert/SKILL.md +155 -0
- package/assets/opencode/skills/code-review-expert/agents/agent.yaml +7 -0
- package/assets/opencode/skills/code-review-expert/references/code-quality-checklist.md +130 -0
- package/assets/opencode/skills/code-review-expert/references/removal-plan.md +52 -0
- package/assets/opencode/skills/code-review-expert/references/security-checklist.md +118 -0
- package/assets/opencode/skills/code-review-expert/references/solid-checklist.md +65 -0
- package/assets/opencode/skills/code-tour/.openskills.json +7 -0
- package/assets/opencode/skills/code-tour/SKILL.md +236 -0
- package/assets/opencode/skills/coding-standards/.openskills.json +7 -0
- package/assets/opencode/skills/coding-standards/SKILL.md +549 -0
- package/assets/opencode/skills/coding-standards/agents/openai.yaml +7 -0
- package/assets/opencode/skills/context-budget/.openskills.json +7 -0
- package/assets/opencode/skills/context-budget/SKILL.md +135 -0
- package/assets/opencode/skills/database-migrations/.openskills.json +7 -0
- package/assets/opencode/skills/database-migrations/SKILL.md +429 -0
- package/assets/opencode/skills/deployment-patterns/.openskills.json +7 -0
- package/assets/opencode/skills/deployment-patterns/SKILL.md +427 -0
- package/assets/opencode/skills/design-system/.openskills.json +7 -0
- package/assets/opencode/skills/design-system/SKILL.md +82 -0
- package/assets/opencode/skills/docker-patterns/.openskills.json +7 -0
- package/assets/opencode/skills/docker-patterns/SKILL.md +364 -0
- package/assets/opencode/skills/documentation-lookup/.openskills.json +7 -0
- package/assets/opencode/skills/documentation-lookup/SKILL.md +90 -0
- package/assets/opencode/skills/documentation-lookup/agents/openai.yaml +7 -0
- package/assets/opencode/skills/e2e-testing/.openskills.json +7 -0
- package/assets/opencode/skills/e2e-testing/SKILL.md +326 -0
- package/assets/opencode/skills/e2e-testing/agents/openai.yaml +7 -0
- package/assets/opencode/skills/error-handling/SKILL.md +376 -0
- package/assets/opencode/skills/frontend-design/.openskills.json +7 -0
- package/assets/opencode/skills/frontend-design/SKILL.md +145 -0
- package/assets/opencode/skills/frontend-design-direction/SKILL.md +92 -0
- package/assets/opencode/skills/frontend-patterns/.openskills.json +7 -0
- package/assets/opencode/skills/frontend-patterns/SKILL.md +642 -0
- package/assets/opencode/skills/frontend-patterns/agents/openai.yaml +7 -0
- package/assets/opencode/skills/gateguard/.openskills.json +7 -0
- package/assets/opencode/skills/gateguard/SKILL.md +125 -0
- package/assets/opencode/skills/git-master/SKILL.md +60 -0
- package/assets/opencode/skills/golang-patterns/.openskills.json +7 -0
- package/assets/opencode/skills/golang-patterns/SKILL.md +674 -0
- package/assets/opencode/skills/golang-testing/.openskills.json +7 -0
- package/assets/opencode/skills/golang-testing/SKILL.md +720 -0
- package/assets/opencode/skills/grafana-dashboard-design/SKILL.md +65 -0
- package/assets/opencode/skills/hexagonal-architecture/.openskills.json +7 -0
- package/assets/opencode/skills/hexagonal-architecture/SKILL.md +276 -0
- package/assets/opencode/skills/java-coding-standards/.openskills.json +7 -0
- package/assets/opencode/skills/java-coding-standards/SKILL.md +383 -0
- package/assets/opencode/skills/jpa-patterns/.openskills.json +7 -0
- package/assets/opencode/skills/jpa-patterns/SKILL.md +151 -0
- package/assets/opencode/skills/knowledge-ops/.openskills.json +7 -0
- package/assets/opencode/skills/knowledge-ops/SKILL.md +154 -0
- package/assets/opencode/skills/make-interfaces-feel-better/SKILL.md +151 -0
- package/assets/opencode/skills/mysql-patterns/SKILL.md +412 -0
- package/assets/opencode/skills/nestjs-patterns/.openskills.json +7 -0
- package/assets/opencode/skills/nestjs-patterns/SKILL.md +230 -0
- package/assets/opencode/skills/nextjs-turbopack/.openskills.json +7 -0
- package/assets/opencode/skills/nextjs-turbopack/SKILL.md +57 -0
- package/assets/opencode/skills/nextjs-turbopack/agents/openai.yaml +7 -0
- package/assets/opencode/skills/parallel-execution-optimizer/SKILL.md +72 -0
- package/assets/opencode/skills/postgres-patterns/.openskills.json +7 -0
- package/assets/opencode/skills/postgres-patterns/SKILL.md +147 -0
- package/assets/opencode/skills/prisma-patterns/SKILL.md +371 -0
- package/assets/opencode/skills/product-capability/.openskills.json +7 -0
- package/assets/opencode/skills/product-capability/SKILL.md +141 -0
- package/assets/opencode/skills/product-lens/.openskills.json +7 -0
- package/assets/opencode/skills/product-lens/SKILL.md +92 -0
- package/assets/opencode/skills/production-audit/SKILL.md +206 -0
- package/assets/opencode/skills/python-patterns/.openskills.json +7 -0
- package/assets/opencode/skills/python-patterns/SKILL.md +750 -0
- package/assets/opencode/skills/python-testing/.openskills.json +7 -0
- package/assets/opencode/skills/python-testing/SKILL.md +816 -0
- package/assets/opencode/skills/redis-patterns/SKILL.md +403 -0
- package/assets/opencode/skills/requirements-clarity/README.md +260 -0
- package/assets/opencode/skills/requirements-clarity/SKILL.md +324 -0
- package/assets/opencode/skills/rust-patterns/.openskills.json +7 -0
- package/assets/opencode/skills/rust-patterns/SKILL.md +499 -0
- package/assets/opencode/skills/rust-testing/.openskills.json +7 -0
- package/assets/opencode/skills/rust-testing/SKILL.md +500 -0
- package/assets/opencode/skills/safety-guard/.openskills.json +7 -0
- package/assets/opencode/skills/safety-guard/SKILL.md +75 -0
- package/assets/opencode/skills/search-first/.openskills.json +7 -0
- package/assets/opencode/skills/search-first/SKILL.md +181 -0
- package/assets/opencode/skills/security-review/.openskills.json +7 -0
- package/assets/opencode/skills/security-review/agents/openai.yaml +7 -0
- package/assets/opencode/skills/security-review/cloud-infrastructure-security.md +361 -0
- package/assets/opencode/skills/security-scan/.openskills.json +7 -0
- package/assets/opencode/skills/security-scan/SKILL.md +165 -0
- package/assets/opencode/skills/springboot-patterns/.openskills.json +7 -0
- package/assets/opencode/skills/springboot-patterns/SKILL.md +314 -0
- package/assets/opencode/skills/springboot-tdd/.openskills.json +7 -0
- package/assets/opencode/skills/springboot-tdd/SKILL.md +158 -0
- package/assets/opencode/skills/springboot-verification/.openskills.json +7 -0
- package/assets/opencode/skills/springboot-verification/SKILL.md +231 -0
- package/assets/opencode/skills/strategic-compact/.openskills.json +7 -0
- package/assets/opencode/skills/strategic-compact/SKILL.md +131 -0
- package/assets/opencode/skills/strategic-compact/agents/openai.yaml +7 -0
- package/assets/opencode/skills/strategic-compact/suggest-compact.sh +54 -0
- package/assets/opencode/skills/tdd-workflow/.openskills.json +7 -0
- package/assets/opencode/skills/tdd-workflow/SKILL.md +463 -0
- package/assets/opencode/skills/tdd-workflow/agents/openai.yaml +7 -0
- package/assets/opencode/skills/verification-loop/.openskills.json +7 -0
- package/assets/opencode/skills/verification-loop/SKILL.md +126 -0
- package/assets/opencode/skills/verification-loop/agents/openai.yaml +7 -0
- package/assets/opencode/skills/vite-patterns/SKILL.md +449 -0
- package/assets/opencode/skills/web-doc-search/SKILL.md +51 -0
- package/assets/opencode/templates/README.md +3 -0
- package/assets/opencode/templates/bros/adr.md +39 -0
- package/assets/opencode/templates/bros/delivery-report.md +71 -0
- package/assets/opencode/templates/bros/explorer-evidence-packet.md +51 -0
- package/assets/opencode/templates/bros/prd.md +72 -0
- package/assets/opencode/templates/bros/security-review.md +48 -0
- package/assets/opencode/templates/bros/status-board.md +33 -0
- package/assets/opencode/templates/bros/task-packet.md +94 -0
- package/assets/opencode/templates/bros/test-strategy.md +57 -0
- package/assets/opencode/templates/bros/ui-implementation-packet.md +64 -0
- package/assets/skills.manifest.json +650 -0
- package/assets/templates.manifest.json +55 -0
- package/bin/bros.mjs +122 -0
- package/docs/compatibility.md +9 -0
- package/docs/installation.md +66 -0
- package/docs/integrations/claude.md +5 -0
- package/docs/integrations/codex.md +5 -0
- package/docs/integrations/opencode.md +39 -0
- package/docs/migration/from-local-opencode-config.md +10 -0
- package/docs/release-process.md +11 -0
- package/docs/repository-structure.md +15 -0
- package/docs/roadmap.md +20 -0
- package/docs/security.md +18 -0
- package/docs/testing.md +9 -0
- package/examples/opencode/README.md +11 -0
- package/examples/opencode/opencode.example.jsonc +4 -0
- package/package.json +43 -0
- package/scripts/validate-assets.mjs +22 -0
- package/scripts/verify-no-secrets.mjs +38 -0
- package/src/plugin.mjs +98 -0
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: java-coding-standards
|
|
3
|
+
description: "Java coding standards for Spring Boot and Quarkus services: naming, immutability, Optional usage, streams, exceptions, generics, CDI, reactive patterns, and project layout. Automatically applies framework-specific conventions."
|
|
4
|
+
origin: ECC
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Java Coding Standards
|
|
8
|
+
|
|
9
|
+
Standards for readable, maintainable Java (17+) code in Spring Boot and Quarkus services.
|
|
10
|
+
|
|
11
|
+
## When to Use
|
|
12
|
+
|
|
13
|
+
- Writing or reviewing Java code in Spring Boot or Quarkus projects
|
|
14
|
+
- Enforcing naming, immutability, or exception handling conventions
|
|
15
|
+
- Working with records, sealed classes, or pattern matching (Java 17+)
|
|
16
|
+
- Reviewing use of Optional, streams, or generics
|
|
17
|
+
- Structuring packages and project layout
|
|
18
|
+
- **[QUARKUS]**: Working with CDI scopes, Panache entities, or reactive pipelines
|
|
19
|
+
|
|
20
|
+
## How It Works
|
|
21
|
+
|
|
22
|
+
### Framework Detection
|
|
23
|
+
|
|
24
|
+
Before applying standards, determine the framework from the build file:
|
|
25
|
+
|
|
26
|
+
- Build file contains `quarkus` → apply **[QUARKUS]** conventions
|
|
27
|
+
- Build file contains `spring-boot` → apply **[SPRING]** conventions
|
|
28
|
+
- Neither detected → apply shared conventions only
|
|
29
|
+
|
|
30
|
+
## Core Principles
|
|
31
|
+
|
|
32
|
+
- Prefer clarity over cleverness
|
|
33
|
+
- Immutable by default; minimize shared mutable state
|
|
34
|
+
- Fail fast with meaningful exceptions
|
|
35
|
+
- Consistent naming and package structure
|
|
36
|
+
- **[QUARKUS]**: Favor build-time over runtime processing; avoid runtime reflection where possible
|
|
37
|
+
|
|
38
|
+
## Examples
|
|
39
|
+
|
|
40
|
+
The sections below show concrete Spring Boot, Quarkus, and shared Java examples
|
|
41
|
+
for naming, immutability, dependency injection, reactive code, exceptions,
|
|
42
|
+
project layout, logging, configuration, and tests.
|
|
43
|
+
|
|
44
|
+
## Naming
|
|
45
|
+
|
|
46
|
+
```java
|
|
47
|
+
// PASS: Classes/Records: PascalCase
|
|
48
|
+
public class MarketService {}
|
|
49
|
+
public record Money(BigDecimal amount, Currency currency) {}
|
|
50
|
+
|
|
51
|
+
// PASS: Methods/fields: camelCase
|
|
52
|
+
private final MarketRepository marketRepository;
|
|
53
|
+
public Market findBySlug(String slug) {}
|
|
54
|
+
|
|
55
|
+
// PASS: Constants: UPPER_SNAKE_CASE
|
|
56
|
+
private static final int MAX_PAGE_SIZE = 100;
|
|
57
|
+
|
|
58
|
+
// PASS: [QUARKUS] JAX-RS resources named as *Resource, not *Controller
|
|
59
|
+
public class MarketResource {}
|
|
60
|
+
|
|
61
|
+
// PASS: [SPRING] REST controllers named as *Controller
|
|
62
|
+
public class MarketController {}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Immutability
|
|
66
|
+
|
|
67
|
+
```java
|
|
68
|
+
// PASS: Favor records and final fields
|
|
69
|
+
public record MarketDto(Long id, String name, MarketStatus status) {}
|
|
70
|
+
|
|
71
|
+
public class Market {
|
|
72
|
+
private final Long id;
|
|
73
|
+
private final String name;
|
|
74
|
+
// getters only, no setters
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// PASS: [QUARKUS] Panache active-record entities use public fields (Quarkus convention)
|
|
78
|
+
@Entity
|
|
79
|
+
public class Market extends PanacheEntity {
|
|
80
|
+
public String name;
|
|
81
|
+
public MarketStatus status;
|
|
82
|
+
// Panache generates accessors at build time; public fields are idiomatic here
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// PASS: [QUARKUS] Panache MongoDB entities
|
|
86
|
+
@MongoEntity(collection = "markets")
|
|
87
|
+
public class Market extends PanacheMongoEntity {
|
|
88
|
+
public String name;
|
|
89
|
+
public MarketStatus status;
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Optional Usage
|
|
94
|
+
|
|
95
|
+
```java
|
|
96
|
+
// PASS: Return Optional from find* methods
|
|
97
|
+
// [SPRING]
|
|
98
|
+
Optional<Market> market = marketRepository.findBySlug(slug);
|
|
99
|
+
|
|
100
|
+
// [QUARKUS] Panache
|
|
101
|
+
Optional<Market> market = Market.find("slug", slug).firstResultOptional();
|
|
102
|
+
|
|
103
|
+
// PASS: Map/flatMap instead of get()
|
|
104
|
+
return market
|
|
105
|
+
.map(MarketResponse::from)
|
|
106
|
+
.orElseThrow(() -> new EntityNotFoundException("Market not found"));
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Streams Best Practices
|
|
110
|
+
|
|
111
|
+
```java
|
|
112
|
+
// PASS: Use streams for transformations, keep pipelines short
|
|
113
|
+
List<String> names = markets.stream()
|
|
114
|
+
.map(Market::name)
|
|
115
|
+
.filter(Objects::nonNull)
|
|
116
|
+
.toList();
|
|
117
|
+
|
|
118
|
+
// FAIL: Avoid complex nested streams; prefer loops for clarity
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Dependency Injection
|
|
122
|
+
|
|
123
|
+
```java
|
|
124
|
+
// PASS: [SPRING] Constructor injection (preferred over @Autowired on fields)
|
|
125
|
+
@Service
|
|
126
|
+
public class MarketService {
|
|
127
|
+
private final MarketRepository marketRepository;
|
|
128
|
+
|
|
129
|
+
public MarketService(MarketRepository marketRepository) {
|
|
130
|
+
this.marketRepository = marketRepository;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// PASS: [QUARKUS] Constructor injection
|
|
135
|
+
@ApplicationScoped
|
|
136
|
+
public class MarketService {
|
|
137
|
+
private final MarketRepository marketRepository;
|
|
138
|
+
|
|
139
|
+
@Inject
|
|
140
|
+
public MarketService(MarketRepository marketRepository) {
|
|
141
|
+
this.marketRepository = marketRepository;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// PASS: [QUARKUS] Package-private field injection (acceptable in Quarkus — avoids proxy issues)
|
|
146
|
+
@ApplicationScoped
|
|
147
|
+
public class MarketService {
|
|
148
|
+
@Inject
|
|
149
|
+
MarketRepository marketRepository;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// FAIL: [SPRING] Field injection with @Autowired
|
|
153
|
+
@Autowired
|
|
154
|
+
private MarketRepository marketRepository; // use constructor injection
|
|
155
|
+
|
|
156
|
+
// FAIL: [QUARKUS] @Singleton when interception or lazy init is needed
|
|
157
|
+
@Singleton // non-proxyable — use @ApplicationScoped instead
|
|
158
|
+
public class MarketService {}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Reactive Patterns [QUARKUS]
|
|
162
|
+
|
|
163
|
+
```java
|
|
164
|
+
// PASS: Return Uni/Multi from reactive endpoints
|
|
165
|
+
@GET
|
|
166
|
+
@Path("/{slug}")
|
|
167
|
+
public Uni<Market> findBySlug(@PathParam("slug") String slug) {
|
|
168
|
+
return Market.find("slug", slug)
|
|
169
|
+
.<Market>firstResult()
|
|
170
|
+
.onItem().ifNull().failWith(() -> new MarketNotFoundException(slug));
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// PASS: Non-blocking pipeline composition
|
|
174
|
+
public Uni<OrderConfirmation> placeOrder(OrderRequest req) {
|
|
175
|
+
return validateOrder(req)
|
|
176
|
+
.chain(valid -> persistOrder(valid))
|
|
177
|
+
.chain(order -> notifyFulfillment(order));
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// FAIL: Blocking call inside a Uni/Multi pipeline
|
|
181
|
+
public Uni<Market> find(String slug) {
|
|
182
|
+
Market m = Market.find("slug", slug).firstResult(); // BLOCKING — breaks event loop
|
|
183
|
+
return Uni.createFrom().item(m);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// FAIL: Subscribing more than once to a shared Uni
|
|
187
|
+
Uni<Market> shared = fetchMarket(slug);
|
|
188
|
+
shared.subscribe().with(m -> log(m));
|
|
189
|
+
shared.subscribe().with(m -> cache(m)); // double subscribe — use Uni.memoize()
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Exceptions
|
|
193
|
+
|
|
194
|
+
- Use unchecked exceptions for domain errors; wrap technical exceptions with context
|
|
195
|
+
- Create domain-specific exceptions (e.g., `MarketNotFoundException`)
|
|
196
|
+
- Avoid broad `catch (Exception ex)` unless rethrowing/logging centrally
|
|
197
|
+
|
|
198
|
+
```java
|
|
199
|
+
throw new MarketNotFoundException(slug);
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Centralised Exception Handling
|
|
203
|
+
|
|
204
|
+
```java
|
|
205
|
+
// [SPRING]
|
|
206
|
+
@RestControllerAdvice
|
|
207
|
+
public class GlobalExceptionHandler {
|
|
208
|
+
@ExceptionHandler(MarketNotFoundException.class)
|
|
209
|
+
public ResponseEntity<ErrorResponse> handle(MarketNotFoundException ex) {
|
|
210
|
+
return ResponseEntity.status(404).body(ErrorResponse.from(ex));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// [QUARKUS] Option A: ExceptionMapper
|
|
215
|
+
@Provider
|
|
216
|
+
public class MarketNotFoundMapper implements ExceptionMapper<MarketNotFoundException> {
|
|
217
|
+
@Override
|
|
218
|
+
public Response toResponse(MarketNotFoundException ex) {
|
|
219
|
+
return Response.status(404).entity(ErrorResponse.from(ex)).build();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// [QUARKUS] Option B: @ServerExceptionMapper (RESTEasy Reactive)
|
|
224
|
+
@ServerExceptionMapper
|
|
225
|
+
public RestResponse<ErrorResponse> handle(MarketNotFoundException ex) {
|
|
226
|
+
return RestResponse.status(Status.NOT_FOUND, ErrorResponse.from(ex));
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Generics and Type Safety
|
|
231
|
+
|
|
232
|
+
- Avoid raw types; declare generic parameters
|
|
233
|
+
- Prefer bounded generics for reusable utilities
|
|
234
|
+
|
|
235
|
+
```java
|
|
236
|
+
public <T extends Identifiable> Map<Long, T> indexById(Collection<T> items) { ... }
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Project Structure
|
|
240
|
+
|
|
241
|
+
### [SPRING] Maven/Gradle
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
src/main/java/com/example/app/
|
|
245
|
+
config/
|
|
246
|
+
controller/
|
|
247
|
+
service/
|
|
248
|
+
repository/
|
|
249
|
+
domain/
|
|
250
|
+
dto/
|
|
251
|
+
util/
|
|
252
|
+
src/main/resources/
|
|
253
|
+
application.yml
|
|
254
|
+
src/test/java/... (mirrors main)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### [QUARKUS] Maven/Gradle
|
|
258
|
+
|
|
259
|
+
```
|
|
260
|
+
src/main/java/com/example/app/
|
|
261
|
+
config/ # @ConfigMapping, @ConfigProperty beans, Producers
|
|
262
|
+
resource/ # JAX-RS resources (not "controller")
|
|
263
|
+
service/
|
|
264
|
+
repository/ # PanacheRepository implementations (if not using active record)
|
|
265
|
+
domain/ # JPA/Panache entities, MongoDB entities
|
|
266
|
+
dto/
|
|
267
|
+
util/
|
|
268
|
+
mapper/ # MapStruct mappers (if used)
|
|
269
|
+
src/main/resources/
|
|
270
|
+
application.properties # Quarkus convention (YAML supported with quarkus-config-yaml)
|
|
271
|
+
import.sql # Hibernate auto-import for dev/test
|
|
272
|
+
src/test/java/... (mirrors main)
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Formatting and Style
|
|
276
|
+
|
|
277
|
+
- Use 2 or 4 spaces consistently (project standard)
|
|
278
|
+
- One public top-level type per file
|
|
279
|
+
- Keep methods short and focused; extract helpers
|
|
280
|
+
- Order members: constants, fields, constructors, public methods, protected, private
|
|
281
|
+
|
|
282
|
+
## Code Smells to Avoid
|
|
283
|
+
|
|
284
|
+
- Long parameter lists → use DTO/builders
|
|
285
|
+
- Deep nesting → early returns
|
|
286
|
+
- Magic numbers → named constants
|
|
287
|
+
- Static mutable state → prefer dependency injection
|
|
288
|
+
- Silent catch blocks → log and act or rethrow
|
|
289
|
+
- **[QUARKUS]**: `@Singleton` where `@ApplicationScoped` is intended — breaks proxying and interception
|
|
290
|
+
- **[QUARKUS]**: Mixing `quarkus-resteasy-reactive` and `quarkus-resteasy` (classic) — pick one stack
|
|
291
|
+
- **[QUARKUS]**: Panache active-record + repository pattern in the same bounded context — pick one
|
|
292
|
+
|
|
293
|
+
## Logging
|
|
294
|
+
|
|
295
|
+
```java
|
|
296
|
+
// [SPRING] SLF4J
|
|
297
|
+
private static final Logger log = LoggerFactory.getLogger(MarketService.class);
|
|
298
|
+
log.info("fetch_market slug={}", slug);
|
|
299
|
+
log.error("failed_fetch_market slug={}", slug, ex);
|
|
300
|
+
|
|
301
|
+
// [QUARKUS] JBoss Logging (default, zero-cost at build time)
|
|
302
|
+
private static final Logger log = Logger.getLogger(MarketService.class);
|
|
303
|
+
log.infof("fetch_market slug=%s", slug);
|
|
304
|
+
log.errorf(ex, "failed_fetch_market slug=%s", slug);
|
|
305
|
+
|
|
306
|
+
// [QUARKUS] Alternative: simplified logging with @Inject
|
|
307
|
+
@Inject
|
|
308
|
+
Logger log; // CDI-injected, scoped to declaring class
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Null Handling
|
|
312
|
+
|
|
313
|
+
- Accept `@Nullable` only when unavoidable; otherwise use `@NonNull`
|
|
314
|
+
- Use Bean Validation (`@NotNull`, `@NotBlank`) on inputs
|
|
315
|
+
- **[QUARKUS]**: Apply `@Valid` on `@BeanParam`, `@RestForm`, and request body parameters
|
|
316
|
+
|
|
317
|
+
## Configuration
|
|
318
|
+
|
|
319
|
+
```java
|
|
320
|
+
// [SPRING] @ConfigurationProperties
|
|
321
|
+
@ConfigurationProperties(prefix = "market")
|
|
322
|
+
public record MarketProperties(int maxPageSize, Duration cacheTtl) {}
|
|
323
|
+
|
|
324
|
+
// [QUARKUS] @ConfigMapping (type-safe, build-time validated)
|
|
325
|
+
@ConfigMapping(prefix = "market")
|
|
326
|
+
public interface MarketConfig {
|
|
327
|
+
int maxPageSize();
|
|
328
|
+
Duration cacheTtl();
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// [QUARKUS] Simple values with @ConfigProperty
|
|
332
|
+
@ConfigProperty(name = "market.max-page-size", defaultValue = "100")
|
|
333
|
+
int maxPageSize;
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## Testing Expectations
|
|
337
|
+
|
|
338
|
+
### Shared
|
|
339
|
+
- JUnit 5 + AssertJ for fluent assertions
|
|
340
|
+
- Mockito for mocking; avoid partial mocks where possible
|
|
341
|
+
- Favor deterministic tests; no hidden sleeps
|
|
342
|
+
|
|
343
|
+
### [SPRING]
|
|
344
|
+
- `@WebMvcTest` for controller slices, `@DataJpaTest` for repository slices
|
|
345
|
+
- `@SpringBootTest` reserved for full integration tests
|
|
346
|
+
- `@MockBean` for replacing beans in Spring context
|
|
347
|
+
|
|
348
|
+
### [QUARKUS]
|
|
349
|
+
- Plain JUnit 5 + Mockito for unit tests (no `@QuarkusTest`)
|
|
350
|
+
- `@QuarkusTest` reserved for CDI integration tests
|
|
351
|
+
- `@InjectMock` for replacing CDI beans in integration tests
|
|
352
|
+
- Dev Services for database/Kafka/Redis — avoid manual Testcontainers setup when Dev Services suffice
|
|
353
|
+
- `@QuarkusTestResource` for custom external service lifecycle
|
|
354
|
+
|
|
355
|
+
```java
|
|
356
|
+
// [SPRING] Controller test
|
|
357
|
+
@WebMvcTest(MarketController.class)
|
|
358
|
+
class MarketControllerTest {
|
|
359
|
+
@Autowired MockMvc mockMvc;
|
|
360
|
+
@MockBean MarketService marketService;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// [QUARKUS] Integration test
|
|
364
|
+
@QuarkusTest
|
|
365
|
+
class MarketResourceTest {
|
|
366
|
+
@InjectMock
|
|
367
|
+
MarketService marketService;
|
|
368
|
+
|
|
369
|
+
@Test
|
|
370
|
+
void should_return_404_when_market_not_found() {
|
|
371
|
+
given().when().get("/markets/unknown").then().statusCode(404);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// [QUARKUS] Unit test (no CDI, no @QuarkusTest)
|
|
376
|
+
@ExtendWith(MockitoExtension.class)
|
|
377
|
+
class MarketServiceTest {
|
|
378
|
+
@Mock MarketRepository marketRepository;
|
|
379
|
+
@InjectMocks MarketService marketService;
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
**Remember**: Keep code intentional, typed, and observable. Optimize for maintainability over micro-optimizations unless proven necessary.
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: jpa-patterns
|
|
3
|
+
description: JPA/Hibernate patterns for entity design, relationships, query optimization, transactions, auditing, indexing, pagination, and pooling in Spring Boot.
|
|
4
|
+
origin: ECC
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# JPA/Hibernate Patterns
|
|
8
|
+
|
|
9
|
+
Use for data modeling, repositories, and performance tuning in Spring Boot.
|
|
10
|
+
|
|
11
|
+
## When to Activate
|
|
12
|
+
|
|
13
|
+
- Designing JPA entities and table mappings
|
|
14
|
+
- Defining relationships (@OneToMany, @ManyToOne, @ManyToMany)
|
|
15
|
+
- Optimizing queries (N+1 prevention, fetch strategies, projections)
|
|
16
|
+
- Configuring transactions, auditing, or soft deletes
|
|
17
|
+
- Setting up pagination, sorting, or custom repository methods
|
|
18
|
+
- Tuning connection pooling (HikariCP) or second-level caching
|
|
19
|
+
|
|
20
|
+
## Entity Design
|
|
21
|
+
|
|
22
|
+
```java
|
|
23
|
+
@Entity
|
|
24
|
+
@Table(name = "markets", indexes = {
|
|
25
|
+
@Index(name = "idx_markets_slug", columnList = "slug", unique = true)
|
|
26
|
+
})
|
|
27
|
+
@EntityListeners(AuditingEntityListener.class)
|
|
28
|
+
public class MarketEntity {
|
|
29
|
+
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
30
|
+
private Long id;
|
|
31
|
+
|
|
32
|
+
@Column(nullable = false, length = 200)
|
|
33
|
+
private String name;
|
|
34
|
+
|
|
35
|
+
@Column(nullable = false, unique = true, length = 120)
|
|
36
|
+
private String slug;
|
|
37
|
+
|
|
38
|
+
@Enumerated(EnumType.STRING)
|
|
39
|
+
private MarketStatus status = MarketStatus.ACTIVE;
|
|
40
|
+
|
|
41
|
+
@CreatedDate private Instant createdAt;
|
|
42
|
+
@LastModifiedDate private Instant updatedAt;
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Enable auditing:
|
|
47
|
+
```java
|
|
48
|
+
@Configuration
|
|
49
|
+
@EnableJpaAuditing
|
|
50
|
+
class JpaConfig {}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Relationships and N+1 Prevention
|
|
54
|
+
|
|
55
|
+
```java
|
|
56
|
+
@OneToMany(mappedBy = "market", cascade = CascadeType.ALL, orphanRemoval = true)
|
|
57
|
+
private List<PositionEntity> positions = new ArrayList<>();
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- Default to lazy loading; use `JOIN FETCH` in queries when needed
|
|
61
|
+
- Avoid `EAGER` on collections; use DTO projections for read paths
|
|
62
|
+
|
|
63
|
+
```java
|
|
64
|
+
@Query("select m from MarketEntity m left join fetch m.positions where m.id = :id")
|
|
65
|
+
Optional<MarketEntity> findWithPositions(@Param("id") Long id);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Repository Patterns
|
|
69
|
+
|
|
70
|
+
```java
|
|
71
|
+
public interface MarketRepository extends JpaRepository<MarketEntity, Long> {
|
|
72
|
+
Optional<MarketEntity> findBySlug(String slug);
|
|
73
|
+
|
|
74
|
+
@Query("select m from MarketEntity m where m.status = :status")
|
|
75
|
+
Page<MarketEntity> findByStatus(@Param("status") MarketStatus status, Pageable pageable);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- Use projections for lightweight queries:
|
|
80
|
+
```java
|
|
81
|
+
public interface MarketSummary {
|
|
82
|
+
Long getId();
|
|
83
|
+
String getName();
|
|
84
|
+
MarketStatus getStatus();
|
|
85
|
+
}
|
|
86
|
+
Page<MarketSummary> findAllBy(Pageable pageable);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Transactions
|
|
90
|
+
|
|
91
|
+
- Annotate service methods with `@Transactional`
|
|
92
|
+
- Use `@Transactional(readOnly = true)` for read paths to optimize
|
|
93
|
+
- Choose propagation carefully; avoid long-running transactions
|
|
94
|
+
|
|
95
|
+
```java
|
|
96
|
+
@Transactional
|
|
97
|
+
public Market updateStatus(Long id, MarketStatus status) {
|
|
98
|
+
MarketEntity entity = repo.findById(id)
|
|
99
|
+
.orElseThrow(() -> new EntityNotFoundException("Market"));
|
|
100
|
+
entity.setStatus(status);
|
|
101
|
+
return Market.from(entity);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Pagination
|
|
106
|
+
|
|
107
|
+
```java
|
|
108
|
+
PageRequest page = PageRequest.of(pageNumber, pageSize, Sort.by("createdAt").descending());
|
|
109
|
+
Page<MarketEntity> markets = repo.findByStatus(MarketStatus.ACTIVE, page);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
For cursor-like pagination, include `id > :lastId` in JPQL with ordering.
|
|
113
|
+
|
|
114
|
+
## Indexing and Performance
|
|
115
|
+
|
|
116
|
+
- Add indexes for common filters (`status`, `slug`, foreign keys)
|
|
117
|
+
- Use composite indexes matching query patterns (`status, created_at`)
|
|
118
|
+
- Avoid `select *`; project only needed columns
|
|
119
|
+
- Batch writes with `saveAll` and `hibernate.jdbc.batch_size`
|
|
120
|
+
|
|
121
|
+
## Connection Pooling (HikariCP)
|
|
122
|
+
|
|
123
|
+
Recommended properties:
|
|
124
|
+
```
|
|
125
|
+
spring.datasource.hikari.maximum-pool-size=20
|
|
126
|
+
spring.datasource.hikari.minimum-idle=5
|
|
127
|
+
spring.datasource.hikari.connection-timeout=30000
|
|
128
|
+
spring.datasource.hikari.validation-timeout=5000
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
For PostgreSQL LOB handling, add:
|
|
132
|
+
```
|
|
133
|
+
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Caching
|
|
137
|
+
|
|
138
|
+
- 1st-level cache is per EntityManager; avoid keeping entities across transactions
|
|
139
|
+
- For read-heavy entities, consider second-level cache cautiously; validate eviction strategy
|
|
140
|
+
|
|
141
|
+
## Migrations
|
|
142
|
+
|
|
143
|
+
- Use Flyway or Liquibase; never rely on Hibernate auto DDL in production
|
|
144
|
+
- Keep migrations idempotent and additive; avoid dropping columns without plan
|
|
145
|
+
|
|
146
|
+
## Testing Data Access
|
|
147
|
+
|
|
148
|
+
- Prefer `@DataJpaTest` with Testcontainers to mirror production
|
|
149
|
+
- Assert SQL efficiency using logs: set `logging.level.org.hibernate.SQL=DEBUG` and `logging.level.org.hibernate.orm.jdbc.bind=TRACE` for parameter values
|
|
150
|
+
|
|
151
|
+
**Remember**: Keep entities lean, queries intentional, and transactions short. Prevent N+1 with fetch strategies and projections, and index for your read/write paths.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: knowledge-ops
|
|
3
|
+
description: Knowledge base management, ingestion, sync, and retrieval across multiple storage layers (local files, MCP memory, vector stores, Git repos). Use when the user wants to save, organize, sync, deduplicate, or search across their knowledge systems.
|
|
4
|
+
origin: ECC
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Knowledge Operations
|
|
8
|
+
|
|
9
|
+
Manage a multi-layered knowledge system for ingesting, organizing, syncing, and retrieving knowledge across multiple stores.
|
|
10
|
+
|
|
11
|
+
Prefer the live workspace model:
|
|
12
|
+
- code work lives in the real cloned repos
|
|
13
|
+
- active execution context lives in GitHub, Linear, and repo-local working-context files
|
|
14
|
+
- broader human-facing notes can live in a non-repo context/archive folder
|
|
15
|
+
- durable cross-machine memory belongs in the knowledge base, not in a shadow repo workspace
|
|
16
|
+
|
|
17
|
+
## When to Activate
|
|
18
|
+
|
|
19
|
+
- User wants to save information to their knowledge base
|
|
20
|
+
- Ingesting documents, conversations, or data into structured storage
|
|
21
|
+
- Syncing knowledge across systems (local files, MCP memory, Supabase, Git repos)
|
|
22
|
+
- Deduplicating or organizing existing knowledge
|
|
23
|
+
- User says "save this to KB", "sync knowledge", "what do I know about X", "ingest this", "update the knowledge base"
|
|
24
|
+
- Any knowledge management task beyond simple memory recall
|
|
25
|
+
|
|
26
|
+
## Knowledge Architecture
|
|
27
|
+
|
|
28
|
+
### Layer 1: Active execution truth
|
|
29
|
+
- **Sources:** GitHub issues, PRs, discussions, release notes, Linear issues/projects/docs
|
|
30
|
+
- **Use for:** the current operational state of the work
|
|
31
|
+
- **Rule:** if something affects an active engineering plan, roadmap, rollout, or release, prefer putting it here first
|
|
32
|
+
|
|
33
|
+
### Layer 2: Claude Code Memory (Quick Access)
|
|
34
|
+
- **Path:** `~/.claude/projects/*/memory/`
|
|
35
|
+
- **Format:** Markdown files with frontmatter
|
|
36
|
+
- **Types:** user preferences, feedback, project context, reference
|
|
37
|
+
- **Use for:** quick-access context that persists across conversations
|
|
38
|
+
- **Automatically loaded at session start**
|
|
39
|
+
|
|
40
|
+
### Layer 3: MCP Memory Server (Structured Knowledge Graph)
|
|
41
|
+
- **Access:** MCP memory tools (create_entities, create_relations, add_observations, search_nodes)
|
|
42
|
+
- **Use for:** Semantic search across all stored memories, relationship mapping
|
|
43
|
+
- **Cross-session persistence with queryable graph structure**
|
|
44
|
+
|
|
45
|
+
### Layer 4: Knowledge base repo / durable document store
|
|
46
|
+
- **Use for:** curated durable notes, session exports, synthesized research, operator memory, long-form docs
|
|
47
|
+
- **Rule:** this is the preferred durable store for cross-machine context when the content is not repo-owned code
|
|
48
|
+
|
|
49
|
+
### Layer 5: External Data Store (Supabase, PostgreSQL, etc.)
|
|
50
|
+
- **Use for:** Structured data, large document storage, full-text search
|
|
51
|
+
- **Good for:** Documents too large for memory files, data needing SQL queries
|
|
52
|
+
|
|
53
|
+
### Layer 6: Local context/archive folder
|
|
54
|
+
- **Use for:** human-facing notes, archived gameplans, local media organization, temporary non-code docs
|
|
55
|
+
- **Rule:** writable for information storage, but not a shadow code workspace
|
|
56
|
+
- **Do not use for:** active code changes or repo truth that should live upstream
|
|
57
|
+
|
|
58
|
+
## Ingestion Workflow
|
|
59
|
+
|
|
60
|
+
When new knowledge needs to be captured:
|
|
61
|
+
|
|
62
|
+
### 1. Classify
|
|
63
|
+
What type of knowledge is it?
|
|
64
|
+
- Business decision -> memory file (project type) + MCP memory
|
|
65
|
+
- Active roadmap / release / implementation state -> GitHub + Linear first
|
|
66
|
+
- Personal preference -> memory file (user/feedback type)
|
|
67
|
+
- Reference info -> memory file (reference type) + MCP memory
|
|
68
|
+
- Large document -> external data store + summary in memory
|
|
69
|
+
- Conversation/session -> knowledge base repo + short summary in memory
|
|
70
|
+
|
|
71
|
+
### 2. Deduplicate
|
|
72
|
+
Check if this knowledge already exists:
|
|
73
|
+
- Search memory files for existing entries
|
|
74
|
+
- Query MCP memory with relevant terms
|
|
75
|
+
- Check whether the information already exists in GitHub or Linear before creating another local note
|
|
76
|
+
- Do not create duplicates. Update existing entries instead.
|
|
77
|
+
|
|
78
|
+
### 3. Store
|
|
79
|
+
Write to appropriate layer(s):
|
|
80
|
+
- Always update Claude Code memory for quick access
|
|
81
|
+
- Use MCP memory for semantic searchability and relationship mapping
|
|
82
|
+
- Update GitHub / Linear first when the information changes live project truth
|
|
83
|
+
- Commit to the knowledge base repo for durable long-form additions
|
|
84
|
+
|
|
85
|
+
### 4. Index
|
|
86
|
+
Update any relevant indexes or summary files.
|
|
87
|
+
|
|
88
|
+
## Sync Operations
|
|
89
|
+
|
|
90
|
+
### Conversation Sync
|
|
91
|
+
Periodically sync conversation history into the knowledge base:
|
|
92
|
+
- Sources: Claude session files, Codex sessions, other agent sessions
|
|
93
|
+
- Destination: knowledge base repo
|
|
94
|
+
- Generate a session index for quick browsing
|
|
95
|
+
- Commit and push
|
|
96
|
+
|
|
97
|
+
### Workspace State Sync
|
|
98
|
+
Mirror important workspace configuration and scripts to the knowledge base:
|
|
99
|
+
- Generate directory maps
|
|
100
|
+
- Redact sensitive config before committing
|
|
101
|
+
- Track changes over time
|
|
102
|
+
- Do not treat the knowledge base or archive folder as the live code workspace
|
|
103
|
+
|
|
104
|
+
### GitHub / Linear Sync
|
|
105
|
+
When the information affects active execution:
|
|
106
|
+
- update the relevant GitHub issue, PR, discussion, release notes, or roadmap thread
|
|
107
|
+
- attach supporting docs to Linear when the work needs durable planning context
|
|
108
|
+
- only mirror a local note afterwards if it still adds value
|
|
109
|
+
|
|
110
|
+
### Cross-Source Knowledge Sync
|
|
111
|
+
Pull knowledge from multiple sources into one place:
|
|
112
|
+
- Claude/ChatGPT/Grok conversation exports
|
|
113
|
+
- Browser bookmarks
|
|
114
|
+
- GitHub activity events
|
|
115
|
+
- Write status summary, commit and push
|
|
116
|
+
|
|
117
|
+
## Memory Patterns
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
# Short-term: current session context
|
|
121
|
+
Use TodoWrite for in-session task tracking
|
|
122
|
+
|
|
123
|
+
# Medium-term: project memory files
|
|
124
|
+
Write to ~/.claude/projects/*/memory/ for cross-session recall
|
|
125
|
+
|
|
126
|
+
# Long-term: GitHub / Linear / KB
|
|
127
|
+
Put active execution truth in GitHub + Linear
|
|
128
|
+
Put durable synthesized context in the knowledge base repo
|
|
129
|
+
|
|
130
|
+
# Semantic layer: MCP knowledge graph
|
|
131
|
+
Use mcp__memory__create_entities for permanent structured data
|
|
132
|
+
Use mcp__memory__create_relations for relationship mapping
|
|
133
|
+
Use mcp__memory__add_observations for new facts about known entities
|
|
134
|
+
Use mcp__memory__search_nodes to find existing knowledge
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Best Practices
|
|
138
|
+
|
|
139
|
+
- Keep memory files concise. Archive old data rather than letting files grow unbounded.
|
|
140
|
+
- Use frontmatter (YAML) for metadata on all knowledge files.
|
|
141
|
+
- Deduplicate before storing. Search first, then create or update.
|
|
142
|
+
- Prefer one canonical home per fact set. Avoid parallel copies of the same plan across local notes, repo files, and tracker docs.
|
|
143
|
+
- Redact sensitive information (API keys, passwords) before committing to Git.
|
|
144
|
+
- Use consistent naming conventions for knowledge files (lowercase-kebab-case).
|
|
145
|
+
- Tag entries with topics/categories for easier retrieval.
|
|
146
|
+
|
|
147
|
+
## Quality Gate
|
|
148
|
+
|
|
149
|
+
Before completing any knowledge operation:
|
|
150
|
+
- no duplicate entries created
|
|
151
|
+
- sensitive data redacted from any Git-tracked files
|
|
152
|
+
- indexes and summaries updated
|
|
153
|
+
- appropriate storage layer chosen for the data type
|
|
154
|
+
- cross-references added where relevant
|