|
1 | | -Code style and structure: |
2 | | - |
3 | | -- Write concise, accurate JavaScript/TypeScript with modern ES Module syntax. |
4 | | -- Always use TypeScript unless otherwise specified. |
5 | | -- Use a class-based structure where applicable. |
6 | | -- Use `harden()` from `@endo/ses` for object security. |
7 | | -- Use object capability (ocap) design patterns. |
8 | | -- Use `@metamask/superstruct` for validation. |
9 | | -- Use TypeDoc for documentation. |
10 | | -- Use the following naming conventions: |
11 | | - - camelCase for functions and variables. |
12 | | - - PascalCase for classes, types, interfaces, and enums. |
13 | | - - kebab-case for package and file names (`@ocap/test-utils`, `kernel-worker.js`, `vat.js`). |
14 | | - - Nouns for variable names (e.g. `isKernelActive`, `hasVatAccess`, `unresolvedMessages`) |
15 | | - - Verbs for function names (e.g. `startVat`, `stopKernel`) |
16 | | -- Use explicit return types for all functions. |
17 | | - |
18 | | -Testing and debugging: |
19 | | - |
20 | | -- Use `vitest` for testing. |
21 | | -- Prefer `toStrictEqual()` for deep object comparisons in tests. |
22 | | -- Use `it.each()` for parameterized tests. |
23 | | -- Use descriptive test blocks with proper nesting. |
24 | | -- Test titles should use concise verb forms without "should" (e.g., `it('creates and starts libp2p node', ...)` not `it('should create and start libp2p node', ...)`). |
25 | | -- For negative cases, use "does not" instead of "should not" (e.g., `it('does not duplicate relays', ...)`). |
26 | | -- Mock functions with `vi.fn()` and explicit return types. |
27 | | -- Aim for high test coverage, including unit and integration tests. |
28 | | -- Mock external dependencies using vitest's `vi.mock()`. |
29 | | - |
30 | | -TypeScript usage: |
| 1 | +Documentation: |
31 | 2 |
|
32 | | -- Use types for defining message structures and data contracts. Do not use `interface` declarations. |
33 | | -- Leverage union types and type guards for robust runtime checks. |
34 | | -- Use `Readonly<T>` for immutable data structures. |
35 | | -- Follow strict mode settings for TypeScript. |
36 | | -- Never use the `any` type. |
37 | | -- Prefer `#` private fields over `private` class fields. |
| 3 | +- Check the [glossary](./docs/glossary.md) for definitions of unclear terms. |
38 | 4 |
|
39 | | -File and directory structure: |
| 5 | +Development workflows: |
40 | 6 |
|
41 | | -- Maintain a monorepo structure using Yarn workspaces. |
42 | | -- Place package source files under `<package-root>/src/`. |
43 | | -- Co-locate a package's unit tests with their covered source files in the `<package-root>/src/` directory (e.g. `ocap-kernel/src/kernel-worker.ts` should be tested in `ocap-kernel/src/kernel-worker.test.ts`). |
44 | | -- Test utilities used by a single package should be separated into that package's `<package-root>/test/` directory. |
45 | | - - If the utility is small, it can be in-lined in the test file. |
46 | | -- Test utilities used by multiple packages should be relocated into the dedicated `test-utils` package. |
| 7 | +- Use `yarn` and `yarn workspace` to run package scripts: |
| 8 | + - `lint:fix` for linting |
| 9 | + - `test:dev` for unit tests, `test` to include coverage |
| 10 | + - e2e tests invoked separately via `test:e2e`, if available |
| 11 | + - `build` from root is cached using Turborepo |
47 | 12 |
|
48 | | -Kernel architecture: |
| 13 | +General conventions: |
49 | 14 |
|
50 | | -- Ensure clear separation of concerns between Kernel, Vat, and Supervisor components. |
51 | | -- Use streams from the `streams` package for message passing / IPC. |
| 15 | +- Use `@metamask/superstruct` for runtime type checking and to define object types |
| 16 | +- Use TypeDoc for documentation |
| 17 | +- Naming conventions: |
| 18 | + - Nouns for variable names (e.g. `isKernelActive`, `hasVatAccess`, `unresolvedMessages`) |
| 19 | + - Verbs for function names (e.g. `startVat`, `stopKernel`) |
| 20 | + - kebab-case for package and file names (`@ocap/test-utils`, `kernel-worker.js`, `vat.js`) |
| 21 | + - Factory methods: `X.make()` |
| 22 | + - Factory functions: `makeX()` |
| 23 | +- If a function has more than two arguments or could be expected to grow thereto, |
| 24 | + give it an options bag (i.e. named parameters) |
| 25 | + |
| 26 | +Object capability (ocap) patterns: |
| 27 | + |
| 28 | +- Production code should run under "lockdown" from `@endo/lockdown` |
| 29 | + - Lockdown must be the first thing that runs in the given JavaScript realm for it to work |
| 30 | +- Use `harden()` from `@endo/ses` for immutability where feasible |
| 31 | + - Including object literals, class instances, class prototypes, etc. |
| 32 | +- Use `E()` from `@endo/eventual-send` to: |
| 33 | + - Communicate with objects between vats or between processes with a CapTP connection |
| 34 | + - Queue messages on a promise (that resolves to some object with methods) |
| 35 | +- If an object is to be made remotable, turn it into an exo using the internal `makeDefaultExo` |
| 36 | + which builds on `@endo/exo` |
| 37 | + - Do not use `Far` from `@endo/far` |
| 38 | + - It's fine to use `E()` on local objects that aren't exos |
| 39 | + |
| 40 | +Testing: |
| 41 | + |
| 42 | +- Use `vitest` for testing |
| 43 | +- Always use `toStrictEqual()` for deep object comparisons |
| 44 | +- Use `it.each()` for parameterized tests |
| 45 | +- Use logically nested `describe()` blocks |
| 46 | +- Test titles should use concise verb forms without "should" (e.g., `it('creates and starts libp2p node', ...)` not `it('should create and start libp2p node', ...)`) |
| 47 | +- Avoid negative cases, but if you must, use "does not" instead of "should not" (e.g., `it('does not duplicate relays', ...)`) |
| 48 | +- Mock functions with `vi.fn()` and explicit return types |
| 49 | +- Mock external dependencies using vitest's `vi.mock()` |
| 50 | +- Aim for complete unit test coverage when writing tests |
| 51 | + |
| 52 | +TypeScript: |
| 53 | + |
| 54 | +- Prefer `type`; do not use `interface` declarations |
| 55 | +- Prefer `#` private fields over `private` class fields |
| 56 | +- Never use the `any` type |
| 57 | +- Never use `enum`:s; always use string literal unions instead |
52 | 58 |
|
53 | | -Web extensions: |
| 59 | +File and directory structure: |
54 | 60 |
|
55 | | -- Use the latest manifest version (v3) for Chrome. |
56 | | -- Minimize permissions in `manifest.json`, using optional permissions where feasible. |
57 | | -- Apply Content Security Policies (CSP) in `manifest.json`. |
| 61 | +- Maintain a monorepo structure using Yarn workspaces |
| 62 | +- Place package source files under `<package-root>/src/` |
| 63 | +- Co-locate a package's unit tests with their covered source files in the `<package-root>/src/` directory (e.g. `ocap-kernel/src/kernel-worker.ts` should be tested in `ocap-kernel/src/kernel-worker.test.ts`) |
| 64 | +- Test utilities used by a single package should be separated into that package's `<package-root>/test/` directory |
| 65 | +- Test utilities used by multiple packages should be relocated into the dedicated `test-utils` package |
58 | 66 |
|
59 | 67 | UI and styling: |
60 | 68 |
|
61 | | -- Create responsive designs for UI components like popups or settings. |
62 | | -- Use Flexbox or CSS Grid for layout consistency. |
63 | | -- Use plain CSS, HTML, and JavaScript for UI components. Do not use React or other frameworks. |
64 | | -- For React UI components, prefer CSS classes (e.g., `className="bg-section p-4 rounded mb-4"`) over inline styles. |
65 | | -- Use inline styles only for dynamic values or when CSS classes are not available. |
66 | | -- Structure layouts with semantic containers and proper spacing. |
67 | | -- Use design system components (BadgeStatus, TextComponent, etc.) consistently. |
68 | | -- Group related UI elements in logical sections with descriptive comments. |
69 | | -- Maintain consistent spacing patterns (e.g., `gap-12`, `mb-4`, `mt-2`). |
70 | | -- Use responsive classes and proper flex layouts for different screen sizes. |
| 69 | +- For React UI components, prefer CSS classes (e.g., `className="bg-section p-4 rounded mb-4"`) over inline styles |
| 70 | +- Use design system components (BadgeStatus, TextComponent, etc.) consistently |
| 71 | +- Maintain consistent spacing patterns (e.g., `gap-12`, `mb-4`, `mt-2`) |
71 | 72 |
|
72 | 73 | Cross-environment compatibility: |
73 | 74 |
|
74 | | -- Libraries should be platform-agnostic and run in any environment unless otherwise specified. |
75 | | -- Packages like `extension` (browser) and `cli` (Node.js) are platform-specific. |
76 | | -- Implement graceful degradation for environment-specific features. |
77 | | - |
78 | | -Type safety: |
79 | | - |
80 | | -- Prefer `@metamask/superstruct` when defining object types. |
81 | | -- Use runtime type guards, not type assertions, when type narrowing is required. |
82 | | -- Define object types for all data structures. |
83 | | -- Avoid redundant type declarations. |
84 | | - |
85 | | -Error handling: |
86 | | - |
87 | | -- Use structured error classes with inheritance, error codes, and messages. |
88 | | -- Implement error marshaling and unmarshaling. |
89 | | -- Use type guards for error checking. |
90 | | - |
91 | | -Documentation: |
92 | | - |
93 | | -- Check the [glossary](./docs/glossary.md) for definitions of unclear terms. |
94 | | -- Use JSDoc and TypeDoc for public APIs. |
95 | | -- Include examples and document error cases. |
96 | | -- When adding glossary entries: |
97 | | - - Include links to relevant implementation files using `[term](../path/to/file.ts)` syntax |
98 | | - - Use cross-references with `[term](#term)` syntax to link related concepts |
99 | | - - Consider how new terms relate to existing architectural concepts |
100 | | - |
101 | | -PR review: |
102 | | - |
103 | | -- Check if new terms, concepts, or architectural patterns are introduced that should be added to the glossary for AI agent accessibility. |
104 | | -- Consider adding glossary entries for: |
105 | | - - New technical terms or abbreviations |
106 | | - - Core architectural components |
107 | | - - Important data structures or types |
108 | | - - Communication patterns or protocols |
109 | | - - System operations or processes |
110 | | -- Include links to relevant implementation files when adding glossary entries. |
111 | | - |
112 | | -Changelog management: |
113 | | - |
114 | | -- Follow Keep a Changelog v1.0.0 format (https://keepachangelog.com/en/1.0.0/) for all CHANGELOG.md files. |
115 | | -- For release PRs, categorize "### Uncategorized" entries into: |
116 | | - - "### Added" for new features and functionality (entries starting with "feat:") |
117 | | - - "### Changed" for changes to existing functionality (entries starting with "chore:" or breaking changes) |
118 | | - - "### Deprecated" for soon-to-be removed features |
119 | | - - "### Removed" for now removed features |
120 | | - - "### Fixed" for bug fixes and corrections (entries starting with "fix:" or "refactor:") |
121 | | - - "### Security" in case of vulnerabilities |
122 | | -- Each changelog should describe changes specific to that package |
123 | | -- Skip dependency updates unless they cause downstream changes; if so, describe the actual changes instead |
124 | | -- Remove prefixes like "feat:", "chore:", "fix:", "refactor:" from changelog entries |
125 | | -- Use clean, descriptive language without technical prefixes |
126 | | -- When running in agent mode, fetch GitHub PR descriptions to better understand: |
127 | | - - The actual impact of each change on the specific package |
128 | | - - Whether dependency updates introduce breaking changes or new functionality |
129 | | - - More context for writing accurate, descriptive changelog entries |
130 | | -- Use PR descriptions to determine if changes should be: |
131 | | - - Skipped entirely (pure dependency bumps with no package impact) |
132 | | - - Rewritten to focus on user-facing changes rather than implementation details |
133 | | - - Moved to different categories based on actual impact |
134 | | -- Example transformations: |
135 | | - - "feat(ocap-kernel): Add kernel command 'revoke'" → "Add kernel command 'revoke'" |
136 | | - - "chore: bump endo dependencies" → Remove (unless it causes package-specific changes) |
137 | | - - "fix: make Revoke button refresh object registry" → "Make Revoke button refresh object registry" |
138 | | - |
139 | | -Context-aware development: |
140 | | - |
141 | | -- Align new code with existing project structure for consistency. |
142 | | -- Prioritize modular, reusable components. |
143 | | - |
144 | | -Code output: |
145 | | - |
146 | | -- Provide complete, self-contained examples. |
147 | | -- Include necessary imports and context for code snippets. |
148 | | -- Document significant changes, especially for Endo-specific patterns or Chrome APIs. |
| 75 | +- Libraries should be platform-agnostic and run in any environment unless otherwise specified |
| 76 | +- Packages like `extension` (browser) and `cli` (Node.js) are platform-specific |
0 commit comments