240 lines
5.5 KiB
Markdown
240 lines
5.5 KiB
Markdown
# Coding Conventions
|
|
|
|
**Analysis Date:** 2026-03-12
|
|
|
|
## Language
|
|
|
|
**Primary:** JavaScript (Node.js)
|
|
- All source files use CommonJS (`.cjs` extension)
|
|
- ESM imports used in test files with `.test.cjs` extension
|
|
|
|
## File Naming
|
|
|
|
**Pattern:** kebab-case
|
|
- Commands: `allow-read-config.cjs`, `get-profile.cjs`, `set-profile.cjs`
|
|
- Libraries: `oc-core.cjs`, `oc-config.cjs`, `oc-models.cjs`
|
|
- Tests: `get-profile.test.cjs`, `allow-read-config.test.cjs`
|
|
|
|
**Directories:**
|
|
- Commands: `bin/gsd-oc-commands/`
|
|
- Libraries: `bin/gsd-oc-lib/` or `bin/lib/`
|
|
- Tests: `bin/test/`
|
|
|
|
## Code Style
|
|
|
|
### Formatting
|
|
|
|
**No explicit formatter configured.** Code uses:
|
|
- 2-space indentation
|
|
- Consistent brace placement
|
|
- Max line length ~100 characters
|
|
|
|
**Example from `bin/gsd-oc-commands/get-profile.cjs`:**
|
|
```javascript
|
|
function getProfile(cwd, args) {
|
|
const verbose = args.includes('--verbose');
|
|
const raw = args.includes('--raw');
|
|
const log = verbose ? (...args) => console.error('[get-profile]', ...args) : () => {};
|
|
// ...
|
|
}
|
|
```
|
|
|
|
### Linting
|
|
|
|
**No ESLint or Prettier configuration detected.**
|
|
|
|
## Import Organization
|
|
|
|
**Order in source files:**
|
|
1. Node.js built-ins (`fs`, `path`, `os`)
|
|
2. Local modules relative paths
|
|
|
|
**Example from `bin/gsd-oc-commands/allow-read-config.cjs`:**
|
|
```javascript
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const os = require('os');
|
|
const { output, error, createBackup } = require('../gsd-oc-lib/oc-core.cjs');
|
|
```
|
|
|
|
## Function Design
|
|
|
|
### Naming
|
|
|
|
- Commands: lowercase with hyphens (e.g., `getProfile`, `allowReadConfig`)
|
|
- Helper functions: camelCase
|
|
- Error code constants: UPPER_SNAKE_CASE
|
|
|
|
### Documentation
|
|
|
|
**Every file includes a JSDoc-style header:**
|
|
```javascript
|
|
/**
|
|
* get-profile.cjs — Retrieve profile definitions from oc_config.json
|
|
*
|
|
* Command module that exports getProfile(cwd, args) function with two operation modes:
|
|
* 1. No parameters: Returns current profile definition
|
|
* 2. Profile name parameter: Returns specified profile definition
|
|
*
|
|
* Output format: JSON envelope {success: true, data: {...}}
|
|
* Flags: --raw (output raw JSON without envelope), --verbose (output diagnostics to stderr)
|
|
*
|
|
* Usage: node get-profile.cjs [profile-name] [--raw] [--verbose]
|
|
*/
|
|
```
|
|
|
|
**Function JSDoc:**
|
|
```javascript
|
|
/**
|
|
* Main command function
|
|
*
|
|
* @param {string} cwd - Current working directory
|
|
* @param {string[]} args - Command line arguments
|
|
*/
|
|
function getProfile(cwd, args) {
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
### Error Codes
|
|
|
|
**Pattern:** Constant object with error codes, used with custom error function
|
|
|
|
From `bin/gsd-oc-lib/oc-profile-config.cjs`:
|
|
```javascript
|
|
const ERROR_CODES = {
|
|
CONFIG_NOT_FOUND: 'CONFIG_NOT_FOUND',
|
|
INVALID_JSON: 'INVALID_JSON',
|
|
PROFILE_NOT_FOUND: 'PROFILE_NOT_FOUND',
|
|
INVALID_MODELS: 'INVALID_MODELS',
|
|
INCOMPLETE_PROFILE: 'INCOMPLETE_PROFILE',
|
|
WRITE_FAILED: 'WRITE_FAILED',
|
|
APPLY_FAILED: 'APPLY_FAILED',
|
|
ROLLBACK_FAILED: 'ROLLBACK_FAILED'
|
|
};
|
|
```
|
|
|
|
### Output Pattern
|
|
|
|
**Success output:** JSON envelope with `success: true` and `data`
|
|
```javascript
|
|
output({ success: true, data: result });
|
|
```
|
|
|
|
**Error output:** Uses centralized `error()` function from `oc-core.cjs`
|
|
```javascript
|
|
error('current_oc_profile not set in oc_config.json', 'MISSING_CURRENT_PROFILE');
|
|
```
|
|
|
|
From `bin/gsd-oc-lib/oc-core.cjs`:
|
|
```javascript
|
|
function error(message, code = 'UNKNOWN_ERROR') {
|
|
const errorEnvelope = {
|
|
success: false,
|
|
error: {
|
|
code,
|
|
message
|
|
}
|
|
};
|
|
console.error(JSON.stringify(errorEnvelope, null, 2));
|
|
process.exit(1);
|
|
}
|
|
```
|
|
|
|
## Return Patterns
|
|
|
|
### Result Objects
|
|
|
|
**Pattern:** Return object with `success: boolean` and either `data` or `error`
|
|
|
|
From `bin/gsd-oc-lib/oc-profile-config.cjs`:
|
|
```javascript
|
|
function loadOcProfileConfig(cwd) {
|
|
try {
|
|
const configPath = path.join(cwd, '.planning', 'oc_config.json');
|
|
if (!fs.existsSync(configPath)) {
|
|
return {
|
|
success: false,
|
|
error: {
|
|
code: ERROR_CODES.CONFIG_NOT_FOUND,
|
|
message: `.planning/oc_config.json not found at ${configPath}`
|
|
}
|
|
};
|
|
}
|
|
return { success: true, config, configPath };
|
|
} catch (err) {
|
|
// ...
|
|
}
|
|
}
|
|
```
|
|
|
|
## Module Design
|
|
|
|
### Exports
|
|
|
|
**Pattern:** Single function export via `module.exports`
|
|
```javascript
|
|
module.exports = getProfile;
|
|
```
|
|
|
|
### Command Module Structure
|
|
|
|
1. JSDoc header with description
|
|
2. Require statements
|
|
3. Error code constants
|
|
4. Helper functions
|
|
5. Main command function
|
|
6. `module.exports`
|
|
|
|
## CLI Patterns
|
|
|
|
### Flag Handling
|
|
|
|
**Pattern:** Simple array filtering
|
|
```javascript
|
|
const verbose = args.includes('--verbose');
|
|
const raw = args.includes('--raw');
|
|
const profileArgs = args.filter(arg => !arg.startsWith('--'));
|
|
```
|
|
|
|
### Output Functions
|
|
|
|
From `bin/gsd-oc-lib/oc-core.cjs`:
|
|
```javascript
|
|
function output(result, raw = false, rawValue = null) {
|
|
let outputStr;
|
|
if (raw && rawValue !== null) {
|
|
outputStr = rawValue;
|
|
} else {
|
|
outputStr = JSON.stringify(result, null, 2);
|
|
}
|
|
// Large payload handling (>50KB)
|
|
if (outputStr.length > 50 * 1024) {
|
|
const tempFile = path.join(require('os').tmpdir(), `gsd-oc-${Date.now()}.json`);
|
|
fs.writeFileSync(tempFile, outputStr, 'utf8');
|
|
console.log(`@file:${tempFile}`);
|
|
} else {
|
|
console.log(outputStr);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Logging
|
|
|
|
### Verbose Logging Pattern
|
|
|
|
**Conditional logging based on flag:**
|
|
```javascript
|
|
const log = verbose ? (...args) => console.error('[get-profile]', ...args) : () => {};
|
|
log('Loading oc_config.json');
|
|
log(`Config loaded from ${configPath}`);
|
|
```
|
|
|
|
## Testing Conventions
|
|
|
|
Tests co-located in `bin/test/` directory with `.test.cjs` suffix.
|
|
|
|
---
|
|
|
|
*Convention analysis: 2026-03-12*
|