@deftai/directive-content 0.55.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/.agents/skills/deft/SKILL.md +6 -0
- package/.agents/skills/deft-directive-article-review/SKILL.md +11 -0
- package/.agents/skills/deft-directive-build/SKILL.md +10 -0
- package/.agents/skills/deft-directive-cost/SKILL.md +12 -0
- package/.agents/skills/deft-directive-debug/SKILL.md +13 -0
- package/.agents/skills/deft-directive-gh-arch/SKILL.md +11 -0
- package/.agents/skills/deft-directive-gh-slice/SKILL.md +10 -0
- package/.agents/skills/deft-directive-glossary/SKILL.md +10 -0
- package/.agents/skills/deft-directive-interview/SKILL.md +9 -0
- package/.agents/skills/deft-directive-pre-pr/SKILL.md +9 -0
- package/.agents/skills/deft-directive-refinement/SKILL.md +10 -0
- package/.agents/skills/deft-directive-release/SKILL.md +12 -0
- package/.agents/skills/deft-directive-review-cycle/SKILL.md +10 -0
- package/.agents/skills/deft-directive-setup/SKILL.md +10 -0
- package/.agents/skills/deft-directive-swarm/SKILL.md +10 -0
- package/.agents/skills/deft-directive-sync/SKILL.md +9 -0
- package/.agents/skills/deft-directive-triage/SKILL.md +9 -0
- package/.agents/skills/deft-directive-write-skill/SKILL.md +9 -0
- package/LICENSE.md +22 -0
- package/QUICK-START.md +167 -0
- package/UPGRADING.md +517 -0
- package/coding/build-output.md +28 -0
- package/coding/coding.md +235 -0
- package/coding/debugging.md +110 -0
- package/coding/holzmann.md +96 -0
- package/coding/hygiene.md +127 -0
- package/coding/security.md +158 -0
- package/coding/testing.md +162 -0
- package/coding/toolchain.md +44 -0
- package/commands.md +300 -0
- package/context/context.md +57 -0
- package/context/deterministic-split.md +67 -0
- package/context/examples.md +26 -0
- package/context/fractal-summaries.md +69 -0
- package/context/long-horizon.md +46 -0
- package/context/spec-deltas.md +177 -0
- package/context/tool-design.md +34 -0
- package/context/working-memory.md +62 -0
- package/contracts/boundary-maps.md +65 -0
- package/contracts/deterministic-questions.md +59 -0
- package/contracts/hierarchy.md +77 -0
- package/conventions/content-manifest.json +399 -0
- package/conventions/machine-generated-banner.md +130 -0
- package/conventions/references.md +120 -0
- package/conventions/rule-ownership.json +382 -0
- package/conventions/task-caching.md +43 -0
- package/conventions/vbrief-filenames.md +70 -0
- package/deployments/README.md +37 -0
- package/deployments/agentuity/README.md +138 -0
- package/deployments/agentuity/via-cli.md +380 -0
- package/deployments/agentuity/via-cloud.md +425 -0
- package/deployments/agentuity/via-github-actions.md +664 -0
- package/deployments/agentuity/via-gravity-network.md +606 -0
- package/deployments/agentuity/via-vpc.md +607 -0
- package/deployments/aws/README.md +38 -0
- package/deployments/aws/via-app-runner.md +612 -0
- package/deployments/aws/via-ecs-fargate.md +561 -0
- package/deployments/aws/via-elastic-beanstalk.md +628 -0
- package/deployments/aws/via-lambda.md +649 -0
- package/deployments/azure/README.md +37 -0
- package/deployments/azure/via-aks.md +390 -0
- package/deployments/azure/via-app-service.md +564 -0
- package/deployments/azure/via-container-apps.md +599 -0
- package/deployments/azure/via-functions.md +552 -0
- package/deployments/cloud-gov/README.md +63 -0
- package/deployments/cloud-gov/agents/compliance-docs.md +154 -0
- package/deployments/cloud-gov/agents.md +39 -0
- package/deployments/cloud-gov/cicd.md +64 -0
- package/deployments/cloud-gov/deployment.md +150 -0
- package/deployments/cloud-gov/logging.md +43 -0
- package/deployments/cloud-gov/manifest.md +121 -0
- package/deployments/cloud-gov/overview.md +58 -0
- package/deployments/cloud-gov/security.md +46 -0
- package/deployments/cloud-gov/services.md +72 -0
- package/deployments/cloud-gov/upstream/README.md +18 -0
- package/deployments/cloudflare/README.md +33 -0
- package/deployments/cloudflare/via-dashboard.md +83 -0
- package/deployments/cloudflare/via-git.md +90 -0
- package/deployments/cloudflare/via-github-actions.md +185 -0
- package/deployments/cloudflare/via-terraform.md +157 -0
- package/deployments/cloudflare/via-wrangler.md +165 -0
- package/deployments/fly-io/README.md +37 -0
- package/deployments/fly-io/via-dockerfile.md +648 -0
- package/deployments/fly-io/via-flyctl.md +653 -0
- package/deployments/fly-io/via-github-actions.md +695 -0
- package/deployments/fly-io/via-multi-region.md +598 -0
- package/deployments/google/README.md +34 -0
- package/deployments/google/via-app-engine.md +42 -0
- package/deployments/google/via-cloud-functions.md +23 -0
- package/deployments/google/via-cloud-run.md +330 -0
- package/deployments/google/via-gke.md +23 -0
- package/deployments/netlify/README.md +99 -0
- package/deployments/netlify/via-cli.md +17 -0
- package/deployments/netlify/via-functions.md +19 -0
- package/deployments/netlify/via-git.md +25 -0
- package/deployments/vercel/README.md +90 -0
- package/deployments/vercel/via-api.md +16 -0
- package/deployments/vercel/via-cli.md +17 -0
- package/deployments/vercel/via-git.md +24 -0
- package/docs/BROWNFIELD.md +179 -0
- package/docs/getting-started.md +137 -0
- package/docs/good-agents-md.md +137 -0
- package/events/README.md +89 -0
- package/events/event-record.schema.json +26 -0
- package/events/registry.json +166 -0
- package/events/registry.schema.json +71 -0
- package/glossary.md +145 -0
- package/incidents/README.md +81 -0
- package/incidents/_template.md +38 -0
- package/interfaces/cli.md +104 -0
- package/interfaces/rest.md +212 -0
- package/interfaces/tui.md +242 -0
- package/interfaces/web.md +123 -0
- package/languages/6502-DASM.md +132 -0
- package/languages/c.md +235 -0
- package/languages/commands.md +23 -0
- package/languages/cpp.md +132 -0
- package/languages/csharp.md +259 -0
- package/languages/dart.md +183 -0
- package/languages/delphi.md +218 -0
- package/languages/elixir.md +208 -0
- package/languages/go.md +78 -0
- package/languages/java.md +278 -0
- package/languages/javascript.md +163 -0
- package/languages/julia.md +175 -0
- package/languages/kotlin.md +193 -0
- package/languages/markdown.md +168 -0
- package/languages/mermaid.md +146 -0
- package/languages/officejs.md +392 -0
- package/languages/python.md +209 -0
- package/languages/r.md +163 -0
- package/languages/rust.md +216 -0
- package/languages/sql.md +216 -0
- package/languages/swift.md +153 -0
- package/languages/typescript.md +132 -0
- package/languages/vba.md +279 -0
- package/languages/vhdl.md +180 -0
- package/languages/visual-basic.md +151 -0
- package/languages/zig.md +196 -0
- package/meta/SOUL.md +27 -0
- package/meta/code-field.md +44 -0
- package/meta/morals.md +40 -0
- package/meta/philosophy.md +39 -0
- package/meta/project.md +49 -0
- package/meta/ralph.md +223 -0
- package/meta/security.md +80 -0
- package/meta/versioning.md +326 -0
- package/package.json +22 -0
- package/packs/lessons/lessons-pack-0.1.json +553 -0
- package/packs/patterns/patterns-pack-0.1.json +57 -0
- package/packs/rules/rules-pack-0.1.json +4767 -0
- package/packs/skills/skills-pack-0.1.json +262 -0
- package/packs/strategies/strategies-pack-0.1.json +167 -0
- package/packs/swarm-spec/swarm-spec-pack-0.1.json +17 -0
- package/patterns/executor-layer-credentials.md +227 -0
- package/patterns/llm-app.md +156 -0
- package/patterns/multi-agent.md +278 -0
- package/patterns/prompt-assembly-layer-ordering.md +154 -0
- package/patterns/role-as-overlay.md +179 -0
- package/platforms/2600.md +137 -0
- package/platforms/unity.md +329 -0
- package/references/composer-skill-porting.md +152 -0
- package/references/cost-models.md +163 -0
- package/references/ip-risk.md +246 -0
- package/references/plain-english-ux.md +275 -0
- package/resilience/context-pruning.md +67 -0
- package/resilience/continue-here.md +62 -0
- package/scm/changelog.md +276 -0
- package/scm/git.md +139 -0
- package/scm/github.md +265 -0
- package/secrets/.gitkeep +0 -0
- package/skills/deft-build/SKILL.md +20 -0
- package/skills/deft-directive-article-review/SKILL.md +156 -0
- package/skills/deft-directive-build/SKILL.md +302 -0
- package/skills/deft-directive-cost/SKILL.md +201 -0
- package/skills/deft-directive-debug/SKILL.md +140 -0
- package/skills/deft-directive-decompose/SKILL.md +96 -0
- package/skills/deft-directive-gh-arch/SKILL.md +160 -0
- package/skills/deft-directive-gh-slice/SKILL.md +199 -0
- package/skills/deft-directive-glossary/SKILL.md +118 -0
- package/skills/deft-directive-interview/SKILL.md +528 -0
- package/skills/deft-directive-pre-pr/SKILL.md +131 -0
- package/skills/deft-directive-probe/SKILL.md +127 -0
- package/skills/deft-directive-refinement/SKILL.md +403 -0
- package/skills/deft-directive-release/SKILL.md +266 -0
- package/skills/deft-directive-review-cycle/SKILL.md +401 -0
- package/skills/deft-directive-setup/SKILL.md +717 -0
- package/skills/deft-directive-swarm/SKILL.md +989 -0
- package/skills/deft-directive-sync/SKILL.md +288 -0
- package/skills/deft-directive-triage/SKILL.md +137 -0
- package/skills/deft-directive-write-skill/SKILL.md +169 -0
- package/skills/deft-interview/SKILL.md +16 -0
- package/skills/deft-pre-pr/SKILL.md +16 -0
- package/skills/deft-review-cycle/SKILL.md +16 -0
- package/skills/deft-roadmap-refresh/SKILL.md +16 -0
- package/skills/deft-setup/SKILL.md +20 -0
- package/skills/deft-swarm/SKILL.md +16 -0
- package/skills/deft-sync/SKILL.md +16 -0
- package/strategies/README.md +83 -0
- package/strategies/artifact-guards.md +85 -0
- package/strategies/bdd.md +115 -0
- package/strategies/brownfield.md +7 -0
- package/strategies/discuss.md +129 -0
- package/strategies/emit-hints.md +69 -0
- package/strategies/enterprise.md +193 -0
- package/strategies/interview.md +551 -0
- package/strategies/map.md +179 -0
- package/strategies/probe.md +151 -0
- package/strategies/rapid.md +155 -0
- package/strategies/research.md +155 -0
- package/strategies/roadmap.md +9 -0
- package/strategies/speckit.md +437 -0
- package/strategies/v0-20-contract.md +134 -0
- package/strategies/yolo.md +169 -0
- package/swarm/swarm.md +300 -0
- package/templates/COST-ESTIMATE.md +114 -0
- package/templates/PULL_REQUEST_TEMPLATE.md +35 -0
- package/templates/agent-prompt-preamble.md +409 -0
- package/templates/agents-entry.md +211 -0
- package/templates/agents-entry.placeholders.md +75 -0
- package/templates/embed.go +20 -0
- package/templates/embed_test.go +36 -0
- package/templates/make-spec-example.md +9 -0
- package/templates/make-spec.md +246 -0
- package/templates/project.md.template +52 -0
- package/templates/specification.md +1 -0
- package/templates/swarm-greptile-poller-prompt.md +556 -0
- package/templates/user.md.template +31 -0
- package/tools/RWLDL.md +80 -0
- package/tools/greptile.md +141 -0
- package/tools/installer.md +23 -0
- package/tools/taskfile-migration.md +32 -0
- package/tools/taskfile.md +185 -0
- package/tools/telemetry.md +285 -0
- package/vbrief/schemas/cache-meta.schema.json +137 -0
- package/vbrief/schemas/candidates.schema.json +130 -0
- package/vbrief/schemas/codebase-map.schema.json +213 -0
- package/vbrief/schemas/lessons-pack.schema.json +134 -0
- package/vbrief/schemas/patterns-pack.schema.json +84 -0
- package/vbrief/schemas/rules-pack.schema.json +105 -0
- package/vbrief/schemas/skills-pack.schema.json +94 -0
- package/vbrief/schemas/slices.schema.json +87 -0
- package/vbrief/schemas/strategies-pack.schema.json +89 -0
- package/vbrief/schemas/swarm-spec-pack.schema.json +84 -0
- package/vbrief/schemas/vbrief-core.schema.json +1022 -0
- package/vbrief/vbrief.md +684 -0
- package/verification/integration.md +76 -0
- package/verification/plan-checking.md +85 -0
- package/verification/uat.md +60 -0
- package/verification/verification.md +117 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# JavaScript Standards
|
|
2
|
+
|
|
3
|
+
Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
|
|
4
|
+
|
|
5
|
+
**⚠️ See also**: [main.md](../../main.md) | [PROJECT.md](../../PROJECT.md) | [telemetry.md](../tools/telemetry.md)
|
|
6
|
+
|
|
7
|
+
**Stack**: ES2022+, Node 20+; Build: Vite/esbuild; Testing: Vitest/Jest; Lint: ESLint + Prettier; Web: React/Next.js
|
|
8
|
+
|
|
9
|
+
**Note**: For TypeScript projects, prefer [typescript.md](./typescript.md). Use JavaScript only when TypeScript is not feasible.
|
|
10
|
+
|
|
11
|
+
## Standards
|
|
12
|
+
|
|
13
|
+
### Documentation
|
|
14
|
+
- ! JSDoc comments for all exported functions, classes, and constants
|
|
15
|
+
- ! Document `@param`, `@returns`, `@throws` on public functions
|
|
16
|
+
- ~ Use `@typedef` and `@type` for complex shapes when not using TypeScript
|
|
17
|
+
|
|
18
|
+
### Testing
|
|
19
|
+
See [testing.md](../coding/testing.md).
|
|
20
|
+
|
|
21
|
+
- ! Use Vitest (or Jest) + coverage
|
|
22
|
+
- Files: `*.spec.js` or `*.test.js`
|
|
23
|
+
|
|
24
|
+
### Coverage
|
|
25
|
+
- ! ≥85% coverage
|
|
26
|
+
- ! Count src/\*
|
|
27
|
+
- ! Exclude entry points, scripts, generated code, config files
|
|
28
|
+
|
|
29
|
+
### Style
|
|
30
|
+
- ! Use ESLint + Prettier (project configs required, checked in)
|
|
31
|
+
- ! Use `"use strict"` in CommonJS; ESM is strict by default
|
|
32
|
+
- ~ Prefer ESM (`import`/`export`) over CommonJS (`require`/`module.exports`)
|
|
33
|
+
|
|
34
|
+
### Types & Safety
|
|
35
|
+
- ! Use `===` / `!==`; ⊗ `==` / `!=` (type coercion bugs)
|
|
36
|
+
- ! Use `const` by default; `let` when reassignment needed; ⊗ `var`
|
|
37
|
+
- ! Use template literals over string concatenation
|
|
38
|
+
- ~ Use optional chaining (`?.`) and nullish coalescing (`??`)
|
|
39
|
+
- ⊗ Rely on implicit type coercion for logic (truthiness traps)
|
|
40
|
+
- ~ Use JSDoc + `// @ts-check` for type-checked JavaScript when TS is not available
|
|
41
|
+
|
|
42
|
+
### Error Handling
|
|
43
|
+
- ! Use `try..catch` for async operations; always handle promise rejections
|
|
44
|
+
- ! Throw `Error` instances (or subclasses), not strings or plain objects
|
|
45
|
+
- ⊗ Swallow errors (empty catch blocks)
|
|
46
|
+
- ~ Create domain-specific error classes extending `Error`
|
|
47
|
+
- ~ Use `.catch()` or `try..catch` with `await`; ⊗ unhandled promise rejections
|
|
48
|
+
|
|
49
|
+
### Async
|
|
50
|
+
- ! Use `async`/`await` over raw Promises/callbacks for readability
|
|
51
|
+
- ! Handle all promise rejections
|
|
52
|
+
- ⊗ Mix callbacks and promises in the same API
|
|
53
|
+
- ⊗ Use `new Promise()` when `async`/`await` suffices (promise constructor anti-pattern)
|
|
54
|
+
- ~ Use `AbortController` / `AbortSignal` for cancellable operations
|
|
55
|
+
- ~ Use `Promise.allSettled()` when partial failures are acceptable
|
|
56
|
+
|
|
57
|
+
### Modules & Imports
|
|
58
|
+
- ! One module per file; name file after the primary export
|
|
59
|
+
- ! Use named exports for most cases; default exports for React components / main entry
|
|
60
|
+
- ⊗ Circular imports
|
|
61
|
+
- ~ Use barrel files (`index.js`) sparingly — only for public API surfaces
|
|
62
|
+
|
|
63
|
+
### Security
|
|
64
|
+
- ⊗ Use `eval()`, `Function()`, or `innerHTML` with untrusted data
|
|
65
|
+
- ⊗ Hardcode secrets in source
|
|
66
|
+
- ! Sanitize/validate all external input
|
|
67
|
+
- ~ Use Content Security Policy (CSP) headers in web applications
|
|
68
|
+
|
|
69
|
+
### Telemetry
|
|
70
|
+
- See [telemetry.md](../tools/telemetry.md)
|
|
71
|
+
- ~ Structured logging (pino, winston) for production
|
|
72
|
+
- ~ Sentry.io for error tracking
|
|
73
|
+
- ? OpenTelemetry for distributed tracing
|
|
74
|
+
|
|
75
|
+
## Commands
|
|
76
|
+
|
|
77
|
+
See [commands.md](./commands.md).
|
|
78
|
+
|
|
79
|
+
## Patterns
|
|
80
|
+
|
|
81
|
+
### Testing
|
|
82
|
+
```javascript
|
|
83
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
84
|
+
import { createUser } from "./user-service.js";
|
|
85
|
+
|
|
86
|
+
describe("createUser", () => {
|
|
87
|
+
const mockRepo = { save: vi.fn() };
|
|
88
|
+
|
|
89
|
+
beforeEach(() => { vi.clearAllMocks(); });
|
|
90
|
+
|
|
91
|
+
it("saves user and returns id", async () => {
|
|
92
|
+
mockRepo.save.mockResolvedValue({ id: 42 });
|
|
93
|
+
const result = await createUser(mockRepo, { name: "Alice" });
|
|
94
|
+
expect(result.id).toBe(42);
|
|
95
|
+
expect(mockRepo.save).toHaveBeenCalledWith({ name: "Alice" });
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("throws on invalid name", async () => {
|
|
99
|
+
await expect(createUser(mockRepo, { name: "" }))
|
|
100
|
+
.rejects.toThrow("name is required");
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Error Handling
|
|
106
|
+
```javascript
|
|
107
|
+
class NotFoundError extends Error {
|
|
108
|
+
constructor(entity, id) {
|
|
109
|
+
super(`${entity} not found: ${id}`); this.name = "NotFoundError";
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async function getUser(id) {
|
|
114
|
+
const res = await fetch(`/api/users/${id}`, { signal: AbortSignal.timeout(5000) });
|
|
115
|
+
if (!res.ok) throw new NotFoundError("User", id);
|
|
116
|
+
return await res.json();
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Modern Patterns
|
|
121
|
+
```javascript
|
|
122
|
+
function createConfig({ host = "localhost", port = 3000, debug = false } = {}) { return { host, port, debug }; }
|
|
123
|
+
const city = user?.address?.city ?? "Unknown";
|
|
124
|
+
const [users, orders] = await Promise.all([fetchUsers(), fetchOrders()]);
|
|
125
|
+
const activeEmails = users.filter(u => u.active).map(u => u.email);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Anti-Patterns
|
|
129
|
+
|
|
130
|
+
Items marked ⊗ in Standards above are not repeated here.
|
|
131
|
+
|
|
132
|
+
- ≉ **`for...in` on arrays**: Use `for...of` or array methods
|
|
133
|
+
- ≉ **Barrel re-exports everywhere**: Hurts tree-shaking
|
|
134
|
+
- ≉ **God modules**: Keep files <300 lines
|
|
135
|
+
|
|
136
|
+
## Hygiene
|
|
137
|
+
|
|
138
|
+
**Types:**
|
|
139
|
+
- ~ Use JSDoc `@type` annotations or `// @ts-check` to surface weak types without migrating to TypeScript
|
|
140
|
+
- ⊗ Untyped `.json()` parse results passed directly to callers without shape validation
|
|
141
|
+
|
|
142
|
+
**Error handling:**
|
|
143
|
+
- ⊗ Empty `catch` blocks — handle the specific error or re-throw
|
|
144
|
+
- ⊗ Unhandled promise rejections — every `Promise` must be `.catch()`-ed or returned
|
|
145
|
+
- ⊗ `catch (e) { console.log(e) }` without re-throw — log-and-continue hides failures from callers
|
|
146
|
+
|
|
147
|
+
**Dead code:**
|
|
148
|
+
- ~ Run `knip` to detect unused exports, files, and dependencies
|
|
149
|
+
- ~ Add `knip` as a `task hygiene` target
|
|
150
|
+
|
|
151
|
+
**Circular dependencies:**
|
|
152
|
+
- ~ Run `madge --circular --exit-code src/` to detect cycles
|
|
153
|
+
- ⊗ Circular imports — restructure or extract shared code to a lower-level module
|
|
154
|
+
|
|
155
|
+
## Compliance Checklist
|
|
156
|
+
|
|
157
|
+
- ! JSDoc on all exported APIs
|
|
158
|
+
- ! See [testing.md](../coding/testing.md) for testing requirements
|
|
159
|
+
- ! ESLint + Prettier configured and enforced
|
|
160
|
+
- ! `const`/`let` only; `===`/`!==` only
|
|
161
|
+
- ! All promises handled; `async`/`await` for I/O
|
|
162
|
+
- ⊗ `var`, `eval()`, loose equality, unhandled rejections
|
|
163
|
+
- ! Run `task check` before commit
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Julia Standards
|
|
2
|
+
|
|
3
|
+
Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
|
|
4
|
+
|
|
5
|
+
**⚠️ See also**: [main.md](../../main.md) | [PROJECT.md](../../PROJECT.md)
|
|
6
|
+
|
|
7
|
+
**Stack**: Julia 1.10+; Packages: Pkg.jl; Testing: `Test` stdlib + Aqua.jl; Docs: Documenter.jl; Format: JuliaFormatter.jl; Lint: JET.jl / Aqua.jl
|
|
8
|
+
|
|
9
|
+
## Standards
|
|
10
|
+
|
|
11
|
+
### Documentation
|
|
12
|
+
- ! Docstrings (triple-quoted `"""..."""`) on all exported functions, types, and modules
|
|
13
|
+
- ! Document arguments, return values, and examples in docstrings
|
|
14
|
+
- ! Use Documenter.jl for package documentation with `makedocs()`
|
|
15
|
+
- ~ Use `jldoctest` blocks for testable examples in docstrings
|
|
16
|
+
- ~ Cross-reference with `` [`OtherFunction`](@ref) `` syntax
|
|
17
|
+
|
|
18
|
+
### Testing
|
|
19
|
+
See [testing.md](../coding/testing.md).
|
|
20
|
+
|
|
21
|
+
- ! Use `Test` standard library (`@test`, `@testset`, `@test_throws`)
|
|
22
|
+
- ! Place tests in `test/runtests.jl` (entry point) with modular test files
|
|
23
|
+
- ! Test type stability with `@inferred` for performance-critical functions
|
|
24
|
+
- ~ Use Aqua.jl for package quality checks (ambiguities, unbound args, piracy)
|
|
25
|
+
- ~ Use `@test_logs` for testing logging output
|
|
26
|
+
|
|
27
|
+
### Coverage
|
|
28
|
+
- ! ≥80% coverage (measured via Coverage.jl or Codecov integration)
|
|
29
|
+
- ! Count src/**
|
|
30
|
+
- ! Exclude scripts, notebooks, generated code
|
|
31
|
+
|
|
32
|
+
### Style
|
|
33
|
+
- ! Use JuliaFormatter.jl with project `.JuliaFormatter.toml` checked in
|
|
34
|
+
- ! 4-space indentation
|
|
35
|
+
- ! Line length ≤92 characters (Julia convention)
|
|
36
|
+
- ! Follow [Julia Style Guide](https://docs.julialang.org/en/v1/manual/style-guide/)
|
|
37
|
+
- ~ Use `BlueStyle` or `SciMLStyle` formatting preset
|
|
38
|
+
|
|
39
|
+
### Naming Conventions
|
|
40
|
+
- ! `snake_case` for functions and variables: `compute_mean`, `max_iterations`
|
|
41
|
+
- ! `PascalCase` for types (structs), modules, and abstract types: `DataProcessor`, `AbstractModel`
|
|
42
|
+
- ! `SCREAMING_SNAKE_CASE` for global constants
|
|
43
|
+
- ! Mutating functions end with `!`: `sort!`, `push!`, `normalize!`
|
|
44
|
+
- ! Predicate functions start with `is`/`has`: `isvalid`, `haskey`
|
|
45
|
+
- ! Type parameters: single uppercase letters or short descriptive: `T`, `S`, `ElType`
|
|
46
|
+
- ⊗ Prefixing types with `Abstract` — use `Abstract` as a prefix for abstract types only
|
|
47
|
+
|
|
48
|
+
### Type System
|
|
49
|
+
- ! Use abstract types to define interfaces and hierarchies
|
|
50
|
+
- ! Use parametric types for generic data structures
|
|
51
|
+
- ! Annotate function arguments with types for public API (dispatch + documentation)
|
|
52
|
+
- ! Use `Union{T, Nothing}` instead of sentinel values for optional data
|
|
53
|
+
- ~ Use `Val{x}` for compile-time dispatch on values
|
|
54
|
+
- ≉ Over-constraining argument types — accept the broadest useful type
|
|
55
|
+
- ≉ Type annotations on local variables (let inference work)
|
|
56
|
+
|
|
57
|
+
### Multiple Dispatch
|
|
58
|
+
- ! Design functions around multiple dispatch: define methods for different type combinations
|
|
59
|
+
- ! Keep method signatures specific; avoid `::Any` arguments in exported functions
|
|
60
|
+
- ! Use dispatch instead of `if typeof(x) == ...` branches
|
|
61
|
+
- ⊗ Type piracy (adding methods to types you don't own for functions you don't own)
|
|
62
|
+
- ~ Use trait-based dispatch patterns for interface polymorphism
|
|
63
|
+
|
|
64
|
+
### Performance
|
|
65
|
+
- ! Write type-stable functions (verify with `@code_warntype`)
|
|
66
|
+
- ! Avoid global variables in hot paths; use `const` or pass as arguments
|
|
67
|
+
- ! Pre-allocate output arrays; use in-place operations (`mul!`, `ldiv!`)
|
|
68
|
+
- ! Use `@views` for array slicing to avoid copies
|
|
69
|
+
- ~ Use `@inbounds` only after bounds-checking correctness is verified
|
|
70
|
+
- ~ Profile with `@time`, `@allocated`, `BenchmarkTools.@btime`
|
|
71
|
+
- ≉ Abstract-typed containers (`Vector{Any}`) in performance-critical code
|
|
72
|
+
- ⊗ Type-unstable code in inner loops
|
|
73
|
+
|
|
74
|
+
### Modules & Packages
|
|
75
|
+
- ! One module per package; module name matches package name
|
|
76
|
+
- ! Use `export` for public API; keep internal functions unexported
|
|
77
|
+
- ! Use `Pkg.jl` for dependency management; `Project.toml` + `Manifest.toml`
|
|
78
|
+
- ! Specify compat bounds in `Project.toml` for all dependencies
|
|
79
|
+
- ~ Use submodules for large packages
|
|
80
|
+
- ⊗ `using PackageName` in package code — use `import` or qualified access
|
|
81
|
+
|
|
82
|
+
### Error Handling
|
|
83
|
+
- ! Use exceptions (`throw`, `error`) for exceptional conditions
|
|
84
|
+
- ! Define custom exception types inheriting from `Exception`
|
|
85
|
+
- ! Use `try`/`catch`/`finally` with specific exception types
|
|
86
|
+
- ⊗ Catching `Exception` broadly without rethrowing
|
|
87
|
+
- ~ Use return values (`nothing`, `Union{T, Nothing}`) for expected missing data
|
|
88
|
+
|
|
89
|
+
### Reproducibility
|
|
90
|
+
- ! Commit `Manifest.toml` for applications (not for packages)
|
|
91
|
+
- ! Use `Pkg.instantiate()` for reproducible environments
|
|
92
|
+
- ! Set random seeds (`Random.seed!`) for stochastic code; document in scripts
|
|
93
|
+
- ~ Use DrWatson.jl for scientific project management
|
|
94
|
+
|
|
95
|
+
### Security
|
|
96
|
+
- ⊗ Hardcode secrets or credentials in source
|
|
97
|
+
- ! Validate all external inputs (file paths, user data, network)
|
|
98
|
+
- ~ Use environment variables for secrets (`ENV["API_KEY"]`)
|
|
99
|
+
|
|
100
|
+
### Telemetry
|
|
101
|
+
- ~ Use `Logging` stdlib (`@info`, `@warn`, `@error`) with structured messages
|
|
102
|
+
- ~ Use `LoggingExtras.jl` for log routing and formatting
|
|
103
|
+
- ? OpenTelemetry via HTTP/REST bridge for distributed systems
|
|
104
|
+
|
|
105
|
+
## Commands
|
|
106
|
+
|
|
107
|
+
See [commands.md](./commands.md).
|
|
108
|
+
|
|
109
|
+
## Patterns
|
|
110
|
+
|
|
111
|
+
### Multiple Dispatch
|
|
112
|
+
```julia
|
|
113
|
+
struct Circle radius::Float64 end
|
|
114
|
+
struct Rectangle width::Float64; height::Float64 end
|
|
115
|
+
|
|
116
|
+
area(c::Circle) = π * c.radius^2
|
|
117
|
+
area(r::Rectangle) = r.width * r.height
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Testing
|
|
121
|
+
```julia
|
|
122
|
+
using Test
|
|
123
|
+
@testset "area" begin
|
|
124
|
+
@test area(Circle(1.0)) ≈ π
|
|
125
|
+
@test area(Rectangle(3.0, 4.0)) == 12.0
|
|
126
|
+
@inferred area(Circle(1.0)) # type stability
|
|
127
|
+
end
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Parametric Types
|
|
131
|
+
```julia
|
|
132
|
+
struct BoundedBuffer{T}
|
|
133
|
+
data::Vector{T}; capacity::Int
|
|
134
|
+
function BoundedBuffer{T}(cap::Int) where {T}
|
|
135
|
+
cap > 0 || throw(ArgumentError("capacity must be positive"))
|
|
136
|
+
new{T}(Vector{T}(), cap)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
function push!(buf::BoundedBuffer{T}, item::T) where {T}
|
|
141
|
+
length(buf.data) >= buf.capacity && throw(OverflowError("buffer full"))
|
|
142
|
+
Base.push!(buf.data, item)
|
|
143
|
+
end
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### In-Place Operations
|
|
147
|
+
```julia
|
|
148
|
+
"Normalize vector `v` in-place."
|
|
149
|
+
function normalize!(v::AbstractVector{<:AbstractFloat})
|
|
150
|
+
n = norm(v)
|
|
151
|
+
n == 0 && throw(ArgumentError("cannot normalize zero vector"))
|
|
152
|
+
v ./= n
|
|
153
|
+
end
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Anti-Patterns
|
|
157
|
+
|
|
158
|
+
Items marked ⊗ in Standards above are not repeated here.
|
|
159
|
+
|
|
160
|
+
- ≉ **Over-constrained argument types**: Accept broadest useful type
|
|
161
|
+
- ≉ **`eval`/`@eval` at runtime**: Prefer compile-time metaprogramming
|
|
162
|
+
- ≉ **Non-`const` globals**: Forces runtime type checks
|
|
163
|
+
- ≉ **Array slicing without `@views`**: Creates unnecessary copies
|
|
164
|
+
|
|
165
|
+
## Compliance Checklist
|
|
166
|
+
|
|
167
|
+
- ! Docstrings on all exported functions/types with examples
|
|
168
|
+
- ! See [testing.md](../coding/testing.md) for testing requirements
|
|
169
|
+
- ! `Test` stdlib + Aqua.jl; ≥80% coverage
|
|
170
|
+
- ! JuliaFormatter + JET.jl enforced
|
|
171
|
+
- ! Julia style guide; `snake_case` functions; `!` suffix for mutating
|
|
172
|
+
- ! Type-stable code; verified with `@code_warntype`
|
|
173
|
+
- ! Compat bounds in `Project.toml` for all dependencies
|
|
174
|
+
- ⊗ Type piracy, type-unstable loops, `Vector{Any}`, `using` in packages
|
|
175
|
+
- ! Run `task check` before commit
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# Kotlin Standards
|
|
2
|
+
|
|
3
|
+
Legend (from RFC2119): !=MUST, ~=SHOULD, ≉=SHOULD NOT, ⊗=MUST NOT, ?=MAY.
|
|
4
|
+
|
|
5
|
+
**⚠️ See also**: [main.md](../../main.md) | [PROJECT.md](../../PROJECT.md)
|
|
6
|
+
|
|
7
|
+
**Stack**: Kotlin 2.0+; Build: Gradle (Kotlin DSL); Testing: JUnit 5 + kotest; Lint: detekt; Format: ktfmt/ktlint; Docs: KDoc
|
|
8
|
+
|
|
9
|
+
## Standards
|
|
10
|
+
|
|
11
|
+
### Documentation
|
|
12
|
+
- ! KDoc (`/** */`) on all public classes, functions, properties, and interfaces
|
|
13
|
+
- ! Document `@param`, `@return`, `@throws`, `@sample` for public API
|
|
14
|
+
- ! Module-level `package-info.kt` or `README.md` per module
|
|
15
|
+
- ~ Use `@see` for cross-references; `@sample` for linking to example code
|
|
16
|
+
|
|
17
|
+
### Testing
|
|
18
|
+
See [testing.md](../coding/testing.md).
|
|
19
|
+
|
|
20
|
+
- ! Use JUnit 5 (`@Test`, assertions) or kotest (spec-style)
|
|
21
|
+
- ! Place tests in `src/test/kotlin/` mirroring source package structure
|
|
22
|
+
- ! Test edge cases: nulls, empty collections, boundary values
|
|
23
|
+
- ~ Use MockK for mocking; avoid PowerMock
|
|
24
|
+
- ~ Use kotest property-based testing for algorithmic code
|
|
25
|
+
|
|
26
|
+
### Coverage
|
|
27
|
+
- ! ≥80% coverage (measured via JaCoCo or Kover)
|
|
28
|
+
- ! Count src/main/kotlin/**
|
|
29
|
+
- ! Exclude entry points, generated code, DI configuration
|
|
30
|
+
|
|
31
|
+
### Style
|
|
32
|
+
- ! Follow [Kotlin Coding Conventions](https://kotlinlang.org/docs/coding-conventions.html)
|
|
33
|
+
- ! Use detekt for static analysis (project `detekt.yml` checked in)
|
|
34
|
+
- ! Use ktfmt or ktlint for formatting
|
|
35
|
+
- ! 4-space indentation, no tabs
|
|
36
|
+
- ! Line length ≤120 characters
|
|
37
|
+
|
|
38
|
+
### Naming Conventions
|
|
39
|
+
- ! `camelCase` for functions, properties, local variables, parameters
|
|
40
|
+
- ! `PascalCase` for classes, interfaces, objects, type aliases, enums
|
|
41
|
+
- ! `SCREAMING_SNAKE_CASE` for `const val` and compile-time constants
|
|
42
|
+
- ! `camelCase` for enum values (Kotlin convention) or `SCREAMING_SNAKE_CASE` if Java-interop heavy
|
|
43
|
+
- ! Prefix backing properties with `_`: `private val _items` → `val items`
|
|
44
|
+
- ⊗ Hungarian notation or type prefixes (`strName`, `iCount`)
|
|
45
|
+
|
|
46
|
+
### Null Safety
|
|
47
|
+
- ! Use Kotlin's type system: `T` for non-null, `T?` for nullable
|
|
48
|
+
- ! Prefer safe calls (`?.`) and Elvis (`?:`) over `!!`
|
|
49
|
+
- ⊗ `!!` (non-null assertion) in production code without precondition check
|
|
50
|
+
- ! Use `requireNotNull()` / `checkNotNull()` with descriptive messages
|
|
51
|
+
- ~ Use `let`/`also`/`run` scoping functions for null-safe chaining
|
|
52
|
+
- ≉ Platform types (`T!`) leaking into public API — annotate explicitly
|
|
53
|
+
|
|
54
|
+
### Idiomatic Kotlin
|
|
55
|
+
- ! Use data classes for value objects (immutable DTOs)
|
|
56
|
+
- ! Use sealed classes/interfaces for restricted hierarchies
|
|
57
|
+
- ! Use `when` expression (exhaustive) over `if-else` chains for type/enum dispatch
|
|
58
|
+
- ! Use extension functions to add behavior without inheritance
|
|
59
|
+
- ! Use `val` (immutable) by default; `var` only when mutation is required
|
|
60
|
+
- ! Use scope functions (`let`, `apply`, `with`, `run`, `also`) appropriately
|
|
61
|
+
- ⊗ Java-style getters/setters — use Kotlin properties
|
|
62
|
+
- ≉ `companion object` as a dumping ground — extract to top-level or utility
|
|
63
|
+
|
|
64
|
+
### Coroutines & Concurrency
|
|
65
|
+
- ! Use structured concurrency: `coroutineScope`, `supervisorScope`
|
|
66
|
+
- ! Never launch unstructured coroutines (`GlobalScope.launch`)
|
|
67
|
+
- ! Use `Dispatchers.IO` for I/O, `Dispatchers.Default` for CPU
|
|
68
|
+
- ! Use `Flow` for reactive streams; `StateFlow`/`SharedFlow` for state
|
|
69
|
+
- ⊗ `GlobalScope` — always use a structured scope
|
|
70
|
+
- ⊗ `runBlocking` in production code (except at top-level entry points)
|
|
71
|
+
- ~ Use `withContext` for dispatcher switching inside a coroutine
|
|
72
|
+
- ~ Cancel coroutines cooperatively; check `isActive` in long computations
|
|
73
|
+
|
|
74
|
+
### Error Handling
|
|
75
|
+
- ! Use exceptions for exceptional conditions; `Result` or sealed classes for expected failures
|
|
76
|
+
- ! Define custom exception hierarchies for domain errors
|
|
77
|
+
- ! Always catch specific exceptions, not `Exception` or `Throwable`
|
|
78
|
+
- ⊗ Catching `Throwable` (swallows `CancellationException`, `OutOfMemoryError`)
|
|
79
|
+
- ⊗ Empty catch blocks
|
|
80
|
+
- ~ Use `runCatching` for functional error handling where appropriate
|
|
81
|
+
|
|
82
|
+
### Dependencies
|
|
83
|
+
- ! Use Gradle Kotlin DSL (`build.gradle.kts`)
|
|
84
|
+
- ! Pin dependency versions via version catalogs (`libs.versions.toml`)
|
|
85
|
+
- ! Minimize transitive dependencies; use `implementation` not `api` by default
|
|
86
|
+
- ~ Use `dependencyUpdates` plugin for version management
|
|
87
|
+
- ⊗ `compile` (deprecated) — use `implementation` or `api`
|
|
88
|
+
|
|
89
|
+
### Interop (Java)
|
|
90
|
+
- ! Annotate public API with `@JvmStatic`, `@JvmOverloads`, `@JvmField` where Java callers exist
|
|
91
|
+
- ! Use `@Nullable` / `@NotNull` annotations on Java code consumed by Kotlin
|
|
92
|
+
- ~ Keep Java interop surface minimal in Kotlin-first projects
|
|
93
|
+
|
|
94
|
+
### Security
|
|
95
|
+
- ⊗ Hardcode secrets or credentials in source
|
|
96
|
+
- ! Validate all external inputs
|
|
97
|
+
- ~ Use sealed classes for security-sensitive state machines (auth, permissions)
|
|
98
|
+
|
|
99
|
+
### Telemetry
|
|
100
|
+
- ~ Use SLF4J + Logback (or kotlin-logging) for structured logging
|
|
101
|
+
- ~ Use Micrometer for metrics
|
|
102
|
+
- ? OpenTelemetry for distributed tracing
|
|
103
|
+
|
|
104
|
+
## Commands
|
|
105
|
+
|
|
106
|
+
See [commands.md](./commands.md).
|
|
107
|
+
|
|
108
|
+
## Patterns
|
|
109
|
+
|
|
110
|
+
### Data Class + Sealed Hierarchy
|
|
111
|
+
```kotlin
|
|
112
|
+
data class User(val id: Long, val email: String, val name: String, val role: Role)
|
|
113
|
+
|
|
114
|
+
sealed interface Result<out T> {
|
|
115
|
+
data class Success<T>(val data: T) : Result<T>
|
|
116
|
+
data class Failure(val error: DomainError) : Result<Nothing>
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
sealed class DomainError(val message: String) {
|
|
120
|
+
class NotFound(msg: String) : DomainError(msg)
|
|
121
|
+
class Validation(msg: String) : DomainError(msg)
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Coroutines & Testing
|
|
126
|
+
```kotlin
|
|
127
|
+
class UserService(private val userRepo: UserRepository, private val audit: AuditLogService) {
|
|
128
|
+
suspend fun getUser(id: Long): User = coroutineScope {
|
|
129
|
+
val user = async { userRepo.findById(id) }
|
|
130
|
+
val log = async { audit.log("user:read", id) }
|
|
131
|
+
log.await(); user.await() ?: throw UserNotFoundException(id)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// MockK test
|
|
136
|
+
class UserServiceTest {
|
|
137
|
+
private val userRepo = mockk<UserRepository>()
|
|
138
|
+
private val audit = mockk<AuditLogService>(relaxed = true)
|
|
139
|
+
private val sut = UserService(userRepo, audit)
|
|
140
|
+
|
|
141
|
+
@Test fun `returns user when found`() = runTest {
|
|
142
|
+
coEvery { userRepo.findById(1L) } returns User(1L, "a@b.com", "Vis", Role.ADMIN)
|
|
143
|
+
assertEquals("Vis", sut.getUser(1L).name)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@Test fun `throws when not found`() = runTest {
|
|
147
|
+
coEvery { userRepo.findById(99L) } returns null
|
|
148
|
+
assertThrows<UserNotFoundException> { sut.getUser(99L) }
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Extension Functions
|
|
154
|
+
```kotlin
|
|
155
|
+
fun String.toSlug() = lowercase().replace(Regex("[^a-z0-9\\s-]"), "").replace(Regex("\\s+"), "-").trim('-')
|
|
156
|
+
fun <T> List<T>.secondOrNull(): T? = if (size >= 2) this[1] else null
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Anti-Patterns
|
|
160
|
+
|
|
161
|
+
Items marked ⊗ in Standards above are not repeated here.
|
|
162
|
+
|
|
163
|
+
- ≉ **`var` by default**: Use `val`; mutate only when necessary
|
|
164
|
+
- ≉ **`companion object` as dumping ground**: Use top-level functions
|
|
165
|
+
- ≉ **`if-else` for sealed dispatch**: Use exhaustive `when`
|
|
166
|
+
- ≉ **String templates in logging**: Use parameterized logging
|
|
167
|
+
|
|
168
|
+
## Hygiene
|
|
169
|
+
|
|
170
|
+
**Types:**
|
|
171
|
+
- ⊗ `Any` as parameter or return type where a concrete type or bounded generic is knowable
|
|
172
|
+
- ⊗ `!!` (non-null assertion) outside tests without a documented invariant proving non-null at that point
|
|
173
|
+
- ~ Use sealed classes/interfaces over `Any`-typed discriminated unions
|
|
174
|
+
|
|
175
|
+
**Error handling:**
|
|
176
|
+
- ⊗ Empty `catch` blocks or catching `Throwable` — already in Standards; treat as a hygiene blocker in review
|
|
177
|
+
- ⊗ `runCatching { }.getOrNull()` to silently discard failures — inspect the `Failure` case
|
|
178
|
+
|
|
179
|
+
**Dead code:**
|
|
180
|
+
- ~ detekt rules `UnusedPrivateMember` and `UnusedImports` detect dead code; enable in CI
|
|
181
|
+
- ~ Run `gradle dependencies` to audit unused or duplicate dependencies
|
|
182
|
+
- ⊗ `@Suppress("unused")` to hide dead code from detekt instead of deleting it
|
|
183
|
+
|
|
184
|
+
## Compliance Checklist
|
|
185
|
+
|
|
186
|
+
- ! KDoc on all public API
|
|
187
|
+
- ! See [testing.md](../coding/testing.md) for testing requirements
|
|
188
|
+
- ! JUnit 5 or kotest; ≥80% coverage via Kover/JaCoCo
|
|
189
|
+
- ! detekt + ktfmt/ktlint configured and enforced
|
|
190
|
+
- ! Kotlin coding conventions; null safety via type system
|
|
191
|
+
- ! Structured concurrency; no `GlobalScope`
|
|
192
|
+
- ⊗ `!!`, `GlobalScope`, catching `Throwable`, empty catches, `var` by default
|
|
193
|
+
- ! Run `task check` before commit
|