@nepopsx/cli 0.0.1
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/bin/opsx.mjs +2 -0
- package/dist/commands/activate.d.ts +6 -0
- package/dist/commands/activate.d.ts.map +1 -0
- package/dist/commands/activate.js +50 -0
- package/dist/commands/activate.js.map +1 -0
- package/dist/commands/decode.d.ts +2 -0
- package/dist/commands/decode.d.ts.map +1 -0
- package/dist/commands/decode.js +57 -0
- package/dist/commands/decode.js.map +1 -0
- package/dist/commands/doctor.d.ts +6 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +133 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +385 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install.d.ts +6 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +29 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/server.d.ts +4 -0
- package/dist/commands/server.d.ts.map +1 -0
- package/dist/commands/server.js +35 -0
- package/dist/commands/server.js.map +1 -0
- package/dist/commands/sync.d.ts +8 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +352 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/config/api-config.d.ts +12 -0
- package/dist/config/api-config.d.ts.map +1 -0
- package/dist/config/api-config.js +67 -0
- package/dist/config/api-config.js.map +1 -0
- package/dist/generator/builtin-templates.d.ts +12 -0
- package/dist/generator/builtin-templates.d.ts.map +1 -0
- package/dist/generator/builtin-templates.js +251 -0
- package/dist/generator/builtin-templates.js.map +1 -0
- package/dist/generator/philosophy.d.ts +12 -0
- package/dist/generator/philosophy.d.ts.map +1 -0
- package/dist/generator/philosophy.js +106 -0
- package/dist/generator/philosophy.js.map +1 -0
- package/dist/generator/render.d.ts +74 -0
- package/dist/generator/render.d.ts.map +1 -0
- package/dist/generator/render.js +229 -0
- package/dist/generator/render.js.map +1 -0
- package/dist/generator/writer.d.ts +19 -0
- package/dist/generator/writer.d.ts.map +1 -0
- package/dist/generator/writer.js +59 -0
- package/dist/generator/writer.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/licensing/fingerprint.d.ts +48 -0
- package/dist/licensing/fingerprint.d.ts.map +1 -0
- package/dist/licensing/fingerprint.js +163 -0
- package/dist/licensing/fingerprint.js.map +1 -0
- package/dist/licensing/index.d.ts +7 -0
- package/dist/licensing/index.d.ts.map +1 -0
- package/dist/licensing/index.js +7 -0
- package/dist/licensing/index.js.map +1 -0
- package/dist/licensing/license-manager.d.ts +44 -0
- package/dist/licensing/license-manager.d.ts.map +1 -0
- package/dist/licensing/license-manager.js +311 -0
- package/dist/licensing/license-manager.js.map +1 -0
- package/dist/licensing/template-fetch.d.ts +31 -0
- package/dist/licensing/template-fetch.d.ts.map +1 -0
- package/dist/licensing/template-fetch.js +92 -0
- package/dist/licensing/template-fetch.js.map +1 -0
- package/dist/security/agent-validator.d.ts +20 -0
- package/dist/security/agent-validator.d.ts.map +1 -0
- package/dist/security/agent-validator.js +67 -0
- package/dist/security/agent-validator.js.map +1 -0
- package/dist/security/index.d.ts +7 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +7 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/integrity.d.ts +28 -0
- package/dist/security/integrity.d.ts.map +1 -0
- package/dist/security/integrity.js +87 -0
- package/dist/security/integrity.js.map +1 -0
- package/dist/security/scanner.d.ts +43 -0
- package/dist/security/scanner.d.ts.map +1 -0
- package/dist/security/scanner.js +172 -0
- package/dist/security/scanner.js.map +1 -0
- package/dist/utils/detect.d.ts +7 -0
- package/dist/utils/detect.d.ts.map +1 -0
- package/dist/utils/detect.js +227 -0
- package/dist/utils/detect.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builtin templates that are generated for every workspace regardless of agents.
|
|
3
|
+
* These provide the base workspace context files.
|
|
4
|
+
*/
|
|
5
|
+
export function getBuiltinTemplates() {
|
|
6
|
+
return [
|
|
7
|
+
{
|
|
8
|
+
outputPath: '.github/copilot-instructions.md',
|
|
9
|
+
template: COPILOT_INSTRUCTIONS_TEMPLATE,
|
|
10
|
+
source: 'builtin:copilot-instructions',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
outputPath: 'AGENTS.md',
|
|
14
|
+
template: AGENTS_MD_TEMPLATE,
|
|
15
|
+
source: 'builtin:agents-md',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
outputPath: 'Makefile',
|
|
19
|
+
template: MAKEFILE_TEMPLATE,
|
|
20
|
+
source: 'builtin:makefile',
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
}
|
|
24
|
+
// ─── copilot-instructions.md ────────────────────────────────
|
|
25
|
+
const COPILOT_INSTRUCTIONS_TEMPLATE = `# {{config.workspace.name}} — Copilot Instructions
|
|
26
|
+
|
|
27
|
+
<!-- Auto-generated by OPSX CLI ({{timestamp}}). Do not edit manually. -->
|
|
28
|
+
<!-- Regenerate with: npx @nepopsx/cli sync -->
|
|
29
|
+
|
|
30
|
+
## Architecture Overview
|
|
31
|
+
|
|
32
|
+
{{#if config.workspace.description}}
|
|
33
|
+
{{config.workspace.description}}
|
|
34
|
+
|
|
35
|
+
{{/if}}
|
|
36
|
+
### Services
|
|
37
|
+
|
|
38
|
+
| Service | Language | Framework | Path | Maturity |
|
|
39
|
+
|---------|----------|-----------|------|----------|
|
|
40
|
+
{{#each config.services}}
|
|
41
|
+
| {{name}} | {{language}} | {{#if framework}}{{framework}}{{else}}—{{/if}} | \`{{path}}/\` | {{maturityBadge maturity}} |
|
|
42
|
+
{{/each}}
|
|
43
|
+
|
|
44
|
+
{{#if config.execution_order}}
|
|
45
|
+
### Multi-Service Change Order
|
|
46
|
+
|
|
47
|
+
When a feature spans multiple services, modify in this order:
|
|
48
|
+
|
|
49
|
+
{{#each config.execution_order}}
|
|
50
|
+
{{idx @index}}. **{{this}}**
|
|
51
|
+
{{/each}}
|
|
52
|
+
{{/if}}
|
|
53
|
+
|
|
54
|
+
{{#if config.databases}}
|
|
55
|
+
### Databases
|
|
56
|
+
|
|
57
|
+
| Name | Type | Description |
|
|
58
|
+
|------|------|-------------|
|
|
59
|
+
{{#each config.databases}}
|
|
60
|
+
| {{name}} | {{type}} | {{#if description}}{{description}}{{else}}—{{/if}} |
|
|
61
|
+
{{/each}}
|
|
62
|
+
{{/if}}
|
|
63
|
+
|
|
64
|
+
## Coding Standards
|
|
65
|
+
|
|
66
|
+
{{#hasLanguage config.services "typescript"}}
|
|
67
|
+
### TypeScript
|
|
68
|
+
- Strict TypeScript — explicit return types on exported functions
|
|
69
|
+
- Prefer functional patterns, const assertions
|
|
70
|
+
- Use path aliases where configured
|
|
71
|
+
{{/hasLanguage}}
|
|
72
|
+
|
|
73
|
+
{{#hasLanguage config.services "python"}}
|
|
74
|
+
### Python
|
|
75
|
+
- Type hints on public functions
|
|
76
|
+
- Follow PEP 8 with project formatter (Black/Ruff)
|
|
77
|
+
{{/hasLanguage}}
|
|
78
|
+
|
|
79
|
+
{{#hasLanguage config.services "go"}}
|
|
80
|
+
### Go
|
|
81
|
+
- Standard project layout: cmd/, internal/, pkg/
|
|
82
|
+
- Wrap errors with context, return errors (don't panic)
|
|
83
|
+
- Table-driven tests
|
|
84
|
+
{{/hasLanguage}}
|
|
85
|
+
|
|
86
|
+
{{#hasLanguage config.services "rust"}}
|
|
87
|
+
### Rust
|
|
88
|
+
- Use clippy for linting
|
|
89
|
+
- Prefer Result over unwrap/expect in library code
|
|
90
|
+
{{/hasLanguage}}
|
|
91
|
+
|
|
92
|
+
{{#hasLanguage config.services "java"}}
|
|
93
|
+
### Java/Kotlin
|
|
94
|
+
- Follow framework conventions (Spring Boot, etc.)
|
|
95
|
+
- Use dependency injection
|
|
96
|
+
{{/hasLanguage}}
|
|
97
|
+
|
|
98
|
+
## Conventions
|
|
99
|
+
|
|
100
|
+
{{#if config.conventions}}
|
|
101
|
+
- **Branch naming**: \`{{config.conventions.branching}}\`
|
|
102
|
+
- **Commits**: {{config.conventions.commits}}
|
|
103
|
+
- **Default branch**: {{config.conventions.default_branch}}
|
|
104
|
+
{{#if config.conventions.pr_required}}- **PRs required** before merge{{/if}}
|
|
105
|
+
{{#if config.conventions.test_required}}- **Tests required** before merge{{/if}}
|
|
106
|
+
{{/if}}
|
|
107
|
+
|
|
108
|
+
{{#if config.safety}}
|
|
109
|
+
## Safety Protocol
|
|
110
|
+
|
|
111
|
+
{{#if config.safety.branch_isolation}}- Agents must work on feature branches only — never modify \`{{config.conventions.default_branch}}\` directly{{/if}}
|
|
112
|
+
{{#if config.safety.checkpoint_before_destructive}}- Auto-commit checkpoint before destructive operations (deletions, migrations, force flags){{/if}}
|
|
113
|
+
{{#if config.safety.confirm_destructive}}- Ask user confirmation before file deletions, database migrations, CI/CD changes{{/if}}
|
|
114
|
+
{{#if config.safety.scope_restriction}}- Agents may only modify files within declared service paths:
|
|
115
|
+
{{#each config.services}}
|
|
116
|
+
- \`{{path}}/\`
|
|
117
|
+
{{/each}}
|
|
118
|
+
{{#if config.safety.allowed_paths}}
|
|
119
|
+
Additional allowed paths:
|
|
120
|
+
{{#each config.safety.allowed_paths}}
|
|
121
|
+
- \`{{this}}\`
|
|
122
|
+
{{/each}}
|
|
123
|
+
{{/if}}
|
|
124
|
+
{{/if}}
|
|
125
|
+
{{#if config.safety.blocked_commands}}- Blocked commands: {{#each config.safety.blocked_commands}}\`{{this}}\`{{#unless @last}}, {{/unless}}{{/each}}{{/if}}
|
|
126
|
+
{{/if}}
|
|
127
|
+
`;
|
|
128
|
+
// ─── AGENTS.md ──────────────────────────────────────────────
|
|
129
|
+
const AGENTS_MD_TEMPLATE = `# AI Agent Instructions — {{config.workspace.name}}
|
|
130
|
+
|
|
131
|
+
<!-- Auto-generated by OPSX CLI ({{timestamp}}). Do not edit manually. -->
|
|
132
|
+
|
|
133
|
+
## Services
|
|
134
|
+
|
|
135
|
+
| Service | Language | Framework | Path | Port | Maturity |
|
|
136
|
+
|---------|----------|-----------|------|------|----------|
|
|
137
|
+
{{#each config.services}}
|
|
138
|
+
| {{name}} | {{language}} | {{#if framework}}{{framework}}{{else}}—{{/if}} | \`{{path}}/\` | {{#if port}}{{port}}{{else}}—{{/if}} | {{maturityBadge maturity}} |
|
|
139
|
+
{{/each}}
|
|
140
|
+
|
|
141
|
+
## Common Commands
|
|
142
|
+
|
|
143
|
+
{{#each config.services}}
|
|
144
|
+
### {{name}} ({{language}}{{#if framework}} / {{framework}}{{/if}})
|
|
145
|
+
|
|
146
|
+
\`\`\`bash
|
|
147
|
+
cd {{path}}
|
|
148
|
+
{{#if commands.dev}}
|
|
149
|
+
# Development
|
|
150
|
+
{{commands.dev}}
|
|
151
|
+
{{/if}}
|
|
152
|
+
{{#if commands.build}}
|
|
153
|
+
# Build
|
|
154
|
+
{{commands.build}}
|
|
155
|
+
{{/if}}
|
|
156
|
+
{{#if commands.test}}
|
|
157
|
+
# Test
|
|
158
|
+
{{commands.test}}
|
|
159
|
+
{{/if}}
|
|
160
|
+
{{#if commands.lint}}
|
|
161
|
+
# Lint
|
|
162
|
+
{{commands.lint}}
|
|
163
|
+
{{/if}}
|
|
164
|
+
\`\`\`
|
|
165
|
+
|
|
166
|
+
{{/each}}
|
|
167
|
+
|
|
168
|
+
{{#if config.execution_order}}
|
|
169
|
+
## Cross-Service Change Order
|
|
170
|
+
|
|
171
|
+
{{#each config.execution_order}}
|
|
172
|
+
{{idx @index}}. {{this}}
|
|
173
|
+
{{/each}}
|
|
174
|
+
{{/if}}
|
|
175
|
+
|
|
176
|
+
{{#if config.databases}}
|
|
177
|
+
## Databases
|
|
178
|
+
|
|
179
|
+
{{#each config.databases}}
|
|
180
|
+
- **{{name}}** ({{type}}){{#if description}} — {{description}}{{/if}}
|
|
181
|
+
{{/each}}
|
|
182
|
+
{{/if}}
|
|
183
|
+
|
|
184
|
+
## Service Ports
|
|
185
|
+
|
|
186
|
+
| Service | Port |
|
|
187
|
+
|---------|------|
|
|
188
|
+
{{#each config.services}}
|
|
189
|
+
{{#if port}}
|
|
190
|
+
| {{name}} | {{port}} |
|
|
191
|
+
{{/if}}
|
|
192
|
+
{{/each}}
|
|
193
|
+
`;
|
|
194
|
+
// ─── Makefile ───────────────────────────────────────────────
|
|
195
|
+
const MAKEFILE_TEMPLATE = `.PHONY: help
|
|
196
|
+
help: ## Show this help
|
|
197
|
+
\t@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\\033[36m%-20s\\033[0m %s\\n", $$1, $$2}'
|
|
198
|
+
|
|
199
|
+
# ─── Build ──────────────────────────────────────────────────
|
|
200
|
+
|
|
201
|
+
{{#each config.services}}
|
|
202
|
+
{{#if commands.build}}
|
|
203
|
+
build-{{name}}: ## Build {{name}}
|
|
204
|
+
\tcd {{path}} && {{commands.build}}
|
|
205
|
+
|
|
206
|
+
{{/if}}
|
|
207
|
+
{{/each}}
|
|
208
|
+
build-all: {{#each config.services}}{{#if commands.build}}build-{{name}} {{/if}}{{/each}}## Build all services
|
|
209
|
+
|
|
210
|
+
# ─── Test ───────────────────────────────────────────────────
|
|
211
|
+
|
|
212
|
+
{{#each config.services}}
|
|
213
|
+
{{#if commands.test}}
|
|
214
|
+
test-{{name}}: ## Test {{name}}
|
|
215
|
+
\tcd {{path}} && {{commands.test}}
|
|
216
|
+
|
|
217
|
+
{{/if}}
|
|
218
|
+
{{/each}}
|
|
219
|
+
test-all: {{#each config.services}}{{#if commands.test}}test-{{name}} {{/if}}{{/each}}## Test all services
|
|
220
|
+
|
|
221
|
+
# ─── Lint ───────────────────────────────────────────────────
|
|
222
|
+
|
|
223
|
+
{{#each config.services}}
|
|
224
|
+
{{#if commands.lint}}
|
|
225
|
+
lint-{{name}}: ## Lint {{name}}
|
|
226
|
+
\tcd {{path}} && {{commands.lint}}
|
|
227
|
+
|
|
228
|
+
{{/if}}
|
|
229
|
+
{{/each}}
|
|
230
|
+
lint-all: {{#each config.services}}{{#if commands.lint}}lint-{{name}} {{/if}}{{/each}}## Lint all services
|
|
231
|
+
|
|
232
|
+
# ─── Dev ────────────────────────────────────────────────────
|
|
233
|
+
|
|
234
|
+
{{#each config.services}}
|
|
235
|
+
{{#if commands.dev}}
|
|
236
|
+
dev-{{name}}: ## Start {{name}} dev server
|
|
237
|
+
\tcd {{path}} && {{commands.dev}}
|
|
238
|
+
|
|
239
|
+
{{/if}}
|
|
240
|
+
{{/each}}
|
|
241
|
+
|
|
242
|
+
# ─── Status ─────────────────────────────────────────────────
|
|
243
|
+
|
|
244
|
+
env-state: ## Check service ports
|
|
245
|
+
{{#each config.services}}
|
|
246
|
+
{{#if port}}
|
|
247
|
+
\t@timeout 1 nc -zv localhost {{port}} 2>&1 | grep -q succeeded && echo "{{name}} ({{port}}): UP" || echo "{{name}} ({{port}}): DOWN"
|
|
248
|
+
{{/if}}
|
|
249
|
+
{{/each}}
|
|
250
|
+
`;
|
|
251
|
+
//# sourceMappingURL=builtin-templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtin-templates.js","sourceRoot":"","sources":["../../src/generator/builtin-templates.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,UAAU,mBAAmB;IACjC,OAAO;QACL;YACE,UAAU,EAAE,iCAAiC;YAC7C,QAAQ,EAAE,6BAA6B;YACvC,MAAM,EAAE,8BAA8B;SACvC;QACD;YACE,UAAU,EAAE,WAAW;YACvB,QAAQ,EAAE,kBAAkB;YAC5B,MAAM,EAAE,mBAAmB;SAC5B;QACD;YACE,UAAU,EAAE,UAAU;YACtB,QAAQ,EAAE,iBAAiB;YAC3B,MAAM,EAAE,kBAAkB;SAC3B;KACF,CAAC;AACJ,CAAC;AAED,+DAA+D;AAE/D,MAAM,6BAA6B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsGrC,CAAC;AAEF,+DAA+D;AAE/D,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgE1B,CAAC;AAEF,+DAA+D;AAE/D,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuDzB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Philosophy-to-instructions mapping.
|
|
3
|
+
* Translates each workspace.yaml philosophy axis value into concrete
|
|
4
|
+
* directives that get injected into agent templates.
|
|
5
|
+
*/
|
|
6
|
+
import type { Philosophy } from '@nepopsx/core';
|
|
7
|
+
/**
|
|
8
|
+
* Convert a Philosophy config into a markdown block of concrete instructions.
|
|
9
|
+
* Returns empty string if no philosophy is configured.
|
|
10
|
+
*/
|
|
11
|
+
export declare function philosophyToInstructions(philosophy: Philosophy | undefined): string;
|
|
12
|
+
//# sourceMappingURL=philosophy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"philosophy.d.ts","sourceRoot":"","sources":["../../src/generator/philosophy.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAmFhD;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CA6BnF"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// ─── Axis Mappings ──────────────────────────────────────────
|
|
2
|
+
const ERROR_HANDLING = {
|
|
3
|
+
'result-types': `Prefer Result/Either types over try-catch. Return errors as values. Only use try-catch at system boundaries (HTTP handlers, CLI entry points, top-level event handlers).`,
|
|
4
|
+
'try-catch': `Use try-catch for error handling. Catch specific error types, never bare catch. Always include meaningful error messages and re-throw when appropriate.`,
|
|
5
|
+
'error-boundaries': `Use error boundaries for UI error handling. For backend, use middleware-level error catchers. Individual functions should throw typed errors caught by the boundary layer.`,
|
|
6
|
+
'mixed': `Use the error handling approach that best fits each context: Result types for business logic, try-catch for I/O operations, error boundaries for UI components.`,
|
|
7
|
+
};
|
|
8
|
+
const STATE_MANAGEMENT = {
|
|
9
|
+
'immutable': `Prefer immutable data structures and patterns. Use spread operators, Object.freeze, or immutable libraries. Never mutate function arguments. Use map/filter/reduce over for-loops that mutate accumulators.`,
|
|
10
|
+
'mutable': `Mutable state is acceptable when it improves readability. Prefer direct mutation over creating unnecessary copies. Use classes with encapsulated mutable state where appropriate.`,
|
|
11
|
+
'mixed': `Use immutable patterns for shared state and data flowing between components. Mutable state is acceptable for local/temporary variables and performance-critical paths.`,
|
|
12
|
+
};
|
|
13
|
+
const TESTING_PHILOSOPHY = {
|
|
14
|
+
'tdd': `Follow Test-Driven Development: write tests BEFORE implementation. Red → Green → Refactor cycle. Every public function must have a test. Aim for >80% coverage on critical paths.`,
|
|
15
|
+
'test-after': `Write tests after implementation. Focus on testing behavior, not implementation details. Every feature should have corresponding tests before the task is marked complete.`,
|
|
16
|
+
'integration-first': `Prioritize integration tests over unit tests. Test the system through its public interfaces (API endpoints, UI interactions). Unit tests only for complex algorithms or business logic.`,
|
|
17
|
+
'minimal': `Write tests only for critical business logic, complex algorithms, and regression-prone code. Don't test simple CRUD, getters/setters, or framework boilerplate.`,
|
|
18
|
+
};
|
|
19
|
+
const ABSTRACTION_LEVEL = {
|
|
20
|
+
'explicit': `Prefer explicit, verbose code over clever abstractions. Repeat yourself rather than creating premature abstractions. Inline small utility functions. Favor readability over DRY.`,
|
|
21
|
+
'dry': `Follow DRY (Don't Repeat Yourself) strictly. Extract shared logic into helper functions, base classes, or shared modules. Create abstractions when a pattern appears twice.`,
|
|
22
|
+
'pragmatic': `Extract shared code when a pattern appears three or more times (Rule of Three). For two occurrences, tolerate some duplication. Balance readability with reuse.`,
|
|
23
|
+
};
|
|
24
|
+
const DEPENDENCY_INJECTION = {
|
|
25
|
+
'constructor': `Use constructor injection for dependencies. Pass dependencies explicitly via constructor parameters. This makes dependencies visible, testable, and refactor-safe.`,
|
|
26
|
+
'container': `Use a dependency injection container (IoC container). Register services in a central module. Resolve dependencies via decorators or container lookups.`,
|
|
27
|
+
'none': `Avoid dependency injection frameworks. Import modules directly. For testing, use module mocking (jest.mock, monkey-patching, etc.) rather than DI abstractions.`,
|
|
28
|
+
};
|
|
29
|
+
const API_STYLE = {
|
|
30
|
+
'rest-resource': `Design REST APIs around resources. Use nouns for endpoints (/users, /orders). Standard HTTP methods: GET (read), POST (create), PUT (full update), PATCH (partial update), DELETE. Return consistent envelope: { data, meta }.`,
|
|
31
|
+
'rest-rpc': `Design REST APIs as RPC-style actions. Use verbs for endpoints (/calculatePrice, /sendNotification). POST for mutations, GET for queries. Group by domain, not by resource.`,
|
|
32
|
+
'graphql': `Use GraphQL for API design. Define schema-first with types and resolvers. Use queries for reads, mutations for writes. Implement DataLoader for N+1 prevention.`,
|
|
33
|
+
};
|
|
34
|
+
const COMPONENT_PATTERN = {
|
|
35
|
+
'functional': `Use functional components exclusively. Use hooks for state and side effects. Prefer composition via custom hooks. No class components unless wrapping legacy code.`,
|
|
36
|
+
'class': `Use class components with clear lifecycle methods. Encapsulate state and behavior in classes. Use inheritance sparingly, prefer composition.`,
|
|
37
|
+
'mixed': `Use functional components with hooks for new code. Class components are acceptable for complex stateful components. Choose whichever is clearer for each use case.`,
|
|
38
|
+
};
|
|
39
|
+
const ORM_USAGE = {
|
|
40
|
+
'repository': `Use the Repository pattern. Separate database access into repository classes/modules. Business logic should not contain SQL or ORM queries directly.`,
|
|
41
|
+
'active-record': `Use Active Record pattern. Models contain both data and database operations. Keep queries close to the model they operate on.`,
|
|
42
|
+
'raw-sql': `Use raw SQL for database queries. Parameterize all inputs. Keep SQL in dedicated query files or constants, not inline in business logic.`,
|
|
43
|
+
'query-builder': `Use a query builder (Knex, Prisma, TypeORM QueryBuilder) for type-safe query construction. Prefer the query builder over raw SQL for maintainability.`,
|
|
44
|
+
};
|
|
45
|
+
const DOCUMENTATION = {
|
|
46
|
+
'jsdoc-all': `Document ALL exported functions, classes, types, and interfaces with JSDoc/docstrings. Include @param, @returns, @throws, and @example where non-obvious.`,
|
|
47
|
+
'jsdoc-on-public': `Document public API surfaces only: exported functions, class methods, and module interfaces. Internal/private helpers don't need documentation unless complex.`,
|
|
48
|
+
'minimal': `Document only non-obvious behavior. If the function name and types make the intent clear, skip the docstring. Focus on "why" comments, not "what" comments.`,
|
|
49
|
+
'none': `Code should be self-documenting. Use descriptive names instead of comments. Only add comments for workarounds, edge cases, or business rule explanations.`,
|
|
50
|
+
};
|
|
51
|
+
const PR_SIZE = {
|
|
52
|
+
'small': `Keep PRs small: target <300 lines of code changed. Break large features into sequential PRs. Prefer more, smaller PRs over fewer, larger ones.`,
|
|
53
|
+
'medium': `Keep PRs under ~800 lines of code changed. A single task from the implementation plan should map to one PR. Split only when crossing service boundaries.`,
|
|
54
|
+
'large': `PR size is not limited. Prefer completing a full feature in one PR for atomic review. Only split if different reviewers are needed for different services.`,
|
|
55
|
+
};
|
|
56
|
+
// ─── Public API ─────────────────────────────────────────────
|
|
57
|
+
const AXIS_MAP = {
|
|
58
|
+
error_handling: ERROR_HANDLING,
|
|
59
|
+
state_management: STATE_MANAGEMENT,
|
|
60
|
+
testing_philosophy: TESTING_PHILOSOPHY,
|
|
61
|
+
abstraction_level: ABSTRACTION_LEVEL,
|
|
62
|
+
dependency_injection: DEPENDENCY_INJECTION,
|
|
63
|
+
api_style: API_STYLE,
|
|
64
|
+
component_pattern: COMPONENT_PATTERN,
|
|
65
|
+
orm_usage: ORM_USAGE,
|
|
66
|
+
documentation: DOCUMENTATION,
|
|
67
|
+
pr_size: PR_SIZE,
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Convert a Philosophy config into a markdown block of concrete instructions.
|
|
71
|
+
* Returns empty string if no philosophy is configured.
|
|
72
|
+
*/
|
|
73
|
+
export function philosophyToInstructions(philosophy) {
|
|
74
|
+
if (!philosophy)
|
|
75
|
+
return '';
|
|
76
|
+
const lines = [];
|
|
77
|
+
lines.push('## Team Coding Philosophy');
|
|
78
|
+
lines.push('');
|
|
79
|
+
lines.push('These are the team\'s coding preferences. Follow them when writing or reviewing code.');
|
|
80
|
+
lines.push('');
|
|
81
|
+
for (const [axis, mapping] of Object.entries(AXIS_MAP)) {
|
|
82
|
+
const value = philosophy[axis];
|
|
83
|
+
if (typeof value === 'string' && mapping[value]) {
|
|
84
|
+
lines.push(`- **${formatAxisName(axis)}:** ${mapping[value]}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Custom freeform rules
|
|
88
|
+
if (philosophy.custom && philosophy.custom.length > 0) {
|
|
89
|
+
lines.push('');
|
|
90
|
+
lines.push('### Additional Team Rules');
|
|
91
|
+
lines.push('');
|
|
92
|
+
for (const rule of philosophy.custom) {
|
|
93
|
+
lines.push(`- ${rule}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Only return if there are actual directives (beyond header)
|
|
97
|
+
const hasDirectives = lines.some((l) => l.startsWith('- '));
|
|
98
|
+
return hasDirectives ? lines.join('\n') : '';
|
|
99
|
+
}
|
|
100
|
+
function formatAxisName(axis) {
|
|
101
|
+
return axis
|
|
102
|
+
.split('_')
|
|
103
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
104
|
+
.join(' ');
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=philosophy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"philosophy.js","sourceRoot":"","sources":["../../src/generator/philosophy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { WorkspaceConfig, WatermarkData } from '@nepopsx/core';
|
|
2
|
+
/**
|
|
3
|
+
* Parsed custom instruction file.
|
|
4
|
+
*/
|
|
5
|
+
export interface CustomInstruction {
|
|
6
|
+
content: string;
|
|
7
|
+
applies_to?: string[];
|
|
8
|
+
scope?: string;
|
|
9
|
+
source: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Set the philosophy markdown block for the current sync run.
|
|
13
|
+
*/
|
|
14
|
+
export declare function setPhilosophyBlock(block: string): void;
|
|
15
|
+
/**
|
|
16
|
+
* Set the custom instructions for the current sync run.
|
|
17
|
+
*/
|
|
18
|
+
export declare function setCustomInstructions(customs: CustomInstruction[]): void;
|
|
19
|
+
export interface RenderContext {
|
|
20
|
+
config: WorkspaceConfig;
|
|
21
|
+
agent?: {
|
|
22
|
+
name: string;
|
|
23
|
+
version: string;
|
|
24
|
+
};
|
|
25
|
+
timestamp: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Register all partials from an agent package's partials/ directory.
|
|
29
|
+
* .hbs partials are pre-rendered with config context; .md partials are included as-is.
|
|
30
|
+
*/
|
|
31
|
+
export declare function registerAgentPartials(partialsDir: string, config: WorkspaceConfig, agentMeta?: {
|
|
32
|
+
name: string;
|
|
33
|
+
version: string;
|
|
34
|
+
}): void;
|
|
35
|
+
/**
|
|
36
|
+
* Unregister all partials (call between agent packages to avoid cross-contamination).
|
|
37
|
+
*/
|
|
38
|
+
export declare function clearPartials(partialsDir: string): void;
|
|
39
|
+
/**
|
|
40
|
+
* Register partials from a remote template map keyed by relative file path.
|
|
41
|
+
* Returns the partial names so they can be unregistered after rendering.
|
|
42
|
+
*/
|
|
43
|
+
export declare function registerAgentPartialsFromMap(templateMap: Record<string, string>, config: WorkspaceConfig, agentMeta?: {
|
|
44
|
+
name: string;
|
|
45
|
+
version: string;
|
|
46
|
+
}): string[];
|
|
47
|
+
export declare function clearPartialNames(partialNames: string[]): void;
|
|
48
|
+
/**
|
|
49
|
+
* Render a Handlebars template string with workspace config context.
|
|
50
|
+
* Context is sanitized to prevent prototype pollution attacks.
|
|
51
|
+
*/
|
|
52
|
+
export declare function renderTemplate(templateSource: string, config: WorkspaceConfig, agentMeta?: {
|
|
53
|
+
name: string;
|
|
54
|
+
version: string;
|
|
55
|
+
}): string;
|
|
56
|
+
/**
|
|
57
|
+
* Render a template file.
|
|
58
|
+
*/
|
|
59
|
+
export declare function renderTemplateFile(templatePath: string, config: WorkspaceConfig, agentMeta?: {
|
|
60
|
+
name: string;
|
|
61
|
+
version: string;
|
|
62
|
+
}): string;
|
|
63
|
+
/**
|
|
64
|
+
* Set watermark data for the current sync run.
|
|
65
|
+
* When set, every rendered file gets a watermark header + steganographic fingerprint.
|
|
66
|
+
* Pass null to disable (e.g., dev mode / free tier).
|
|
67
|
+
*/
|
|
68
|
+
export declare function setWatermarkData(data: WatermarkData | null): void;
|
|
69
|
+
/**
|
|
70
|
+
* Apply watermark header + steganographic fingerprint to rendered content.
|
|
71
|
+
* Should be called AFTER Handlebars rendering, on the final output.
|
|
72
|
+
*/
|
|
73
|
+
export declare function applyLicenseWatermark(content: string): string;
|
|
74
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/generator/render.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAW,aAAa,EAAE,MAAM,eAAe,CAAC;AAyE7E;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAKD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEtD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAExE;AAyCD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,eAAe,CAAC;IACxB,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAqBvI;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAQvD;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,MAAM,EAAE,eAAe,EACvB,SAAS,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC5C,MAAM,EAAE,CAoBV;AAED,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CAI9D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAUrI;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAGvI;AAMD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,GAAG,IAAI,CAEjE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAW7D"}
|