@sha3/code-standards 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/AGENTS.md +19 -0
- package/README.md +368 -0
- package/ai/adapters/codex.md +5 -0
- package/ai/adapters/copilot.md +5 -0
- package/ai/adapters/cursor.md +5 -0
- package/ai/adapters/windsurf.md +6 -0
- package/ai/constitution.md +9 -0
- package/bin/code-standards.mjs +1010 -0
- package/eslint/base.mjs +36 -0
- package/eslint/node.mjs +14 -0
- package/eslint/test.mjs +19 -0
- package/index.mjs +19 -0
- package/package.json +64 -0
- package/prettier/index.cjs +10 -0
- package/profiles/default.profile.json +38 -0
- package/profiles/schema.json +159 -0
- package/resources/ai/AGENTS.md +16 -0
- package/resources/ai/adapters/codex.md +5 -0
- package/resources/ai/adapters/copilot.md +5 -0
- package/resources/ai/adapters/cursor.md +5 -0
- package/resources/ai/adapters/windsurf.md +5 -0
- package/resources/ai/templates/adapters/codex.template.md +6 -0
- package/resources/ai/templates/adapters/copilot.template.md +6 -0
- package/resources/ai/templates/adapters/cursor.template.md +6 -0
- package/resources/ai/templates/adapters/windsurf.template.md +6 -0
- package/resources/ai/templates/agents.project.template.md +33 -0
- package/resources/ai/templates/rules/architecture.md +26 -0
- package/resources/ai/templates/rules/async.md +23 -0
- package/resources/ai/templates/rules/class-first.md +96 -0
- package/resources/ai/templates/rules/control-flow.md +19 -0
- package/resources/ai/templates/rules/errors.md +22 -0
- package/resources/ai/templates/rules/functions.md +27 -0
- package/resources/ai/templates/rules/readme.md +25 -0
- package/resources/ai/templates/rules/returns.md +33 -0
- package/resources/ai/templates/rules/testing.md +26 -0
- package/standards/architecture.md +24 -0
- package/standards/changelog-policy.md +12 -0
- package/standards/manifest.json +47 -0
- package/standards/readme.md +25 -0
- package/standards/schema.json +122 -0
- package/standards/style.md +48 -0
- package/standards/testing.md +18 -0
- package/standards/tooling.md +32 -0
- package/templates/node-lib/eslint.config.mjs +4 -0
- package/templates/node-lib/package.json +30 -0
- package/templates/node-lib/prettier.config.cjs +9 -0
- package/templates/node-lib/src/index.ts +3 -0
- package/templates/node-lib/test/smoke.test.ts +8 -0
- package/templates/node-lib/tsconfig.build.json +7 -0
- package/templates/node-lib/tsconfig.json +7 -0
- package/templates/node-service/eslint.config.mjs +4 -0
- package/templates/node-service/package.json +25 -0
- package/templates/node-service/prettier.config.cjs +9 -0
- package/templates/node-service/src/index.ts +17 -0
- package/templates/node-service/test/smoke.test.ts +37 -0
- package/templates/node-service/tsconfig.json +7 -0
- package/tsconfig/base.json +16 -0
- package/tsconfig/node-lib.json +12 -0
- package/tsconfig/node-service.json +10 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
### Function Structure (MUST)
|
|
2
|
+
|
|
3
|
+
- Functions and methods SHOULD stay under 30 lines.
|
|
4
|
+
- Functions MUST implement one responsibility.
|
|
5
|
+
- Long functions MUST be split into private helper methods.
|
|
6
|
+
- Types MUST be preferred over interfaces for local modeling unless a public contract requires an interface.
|
|
7
|
+
|
|
8
|
+
Good example:
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
private normalize(input: PaymentInput): PaymentDraft {
|
|
12
|
+
const amount: number = normalizeAmount(input.amount);
|
|
13
|
+
const currency: CurrencyCode = normalizeCurrency(input.currency);
|
|
14
|
+
const metadata: PaymentMetadata = sanitizeMetadata(input.metadata);
|
|
15
|
+
return { amount, currency, metadata };
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Bad example:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
private normalize(input: any): any {
|
|
23
|
+
// huge branchy function with parsing, IO, validation and persistence mixed together
|
|
24
|
+
// ... 80+ lines omitted
|
|
25
|
+
return input;
|
|
26
|
+
}
|
|
27
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
### README Quality Standard (MUST)
|
|
2
|
+
|
|
3
|
+
When creating or updating `README.md`, output MUST be top-tier and production-quality.
|
|
4
|
+
|
|
5
|
+
Mandatory requirements:
|
|
6
|
+
|
|
7
|
+
- README MUST clearly explain: what the project does, why it exists, and how to use it in under 60 seconds.
|
|
8
|
+
- README MUST include practical copy/paste examples that are runnable.
|
|
9
|
+
- README MUST include a fast path (`TL;DR` or `Quick Start`) and an in-depth reference section.
|
|
10
|
+
- README MUST include a section for AI usage (how to instruct assistants to follow local standards).
|
|
11
|
+
- README MUST avoid vague marketing language and focus on actionable guidance.
|
|
12
|
+
- README MUST be visually structured with clean headings, concise lists, and code blocks.
|
|
13
|
+
- README MUST be updated whenever behavior, commands, or setup steps change.
|
|
14
|
+
|
|
15
|
+
Good example characteristics:
|
|
16
|
+
|
|
17
|
+
- Starts with immediate value and one-command quick start.
|
|
18
|
+
- Shows exact commands and expected flow.
|
|
19
|
+
- Includes troubleshooting or FAQ for common confusion points.
|
|
20
|
+
|
|
21
|
+
Bad example characteristics:
|
|
22
|
+
|
|
23
|
+
- Only describes high-level ideas.
|
|
24
|
+
- Missing runnable commands.
|
|
25
|
+
- Forces reader to guess execution order.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
### Return Policy (MUST)
|
|
2
|
+
|
|
3
|
+
- Every function or method MUST have a single `return` statement.
|
|
4
|
+
- Early returns are not allowed.
|
|
5
|
+
- Conditional paths MUST assign to a local result variable and return once.
|
|
6
|
+
|
|
7
|
+
Good example:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
public toStatusLabel(status: InvoiceStatus): string {
|
|
11
|
+
let label: string;
|
|
12
|
+
|
|
13
|
+
if (status === "paid") {
|
|
14
|
+
label = "Paid";
|
|
15
|
+
} else if (status === "void") {
|
|
16
|
+
label = "Void";
|
|
17
|
+
} else {
|
|
18
|
+
label = "Pending";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return label;
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Bad example:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
public toStatusLabel(status: InvoiceStatus): string {
|
|
29
|
+
if (status === "paid") return "Paid";
|
|
30
|
+
if (status === "void") return "Void";
|
|
31
|
+
return "Pending";
|
|
32
|
+
}
|
|
33
|
+
```
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
### Testing and Comments (MUST)
|
|
2
|
+
|
|
3
|
+
- Any behavior change MUST include or update tests.
|
|
4
|
+
- Tests MUST validate behavior, not implementation details.
|
|
5
|
+
- Comments MUST be explicit and extensive when logic is non-trivial.
|
|
6
|
+
- Async workflows MUST use `async/await` style only.
|
|
7
|
+
|
|
8
|
+
Good example:
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
// Business rule: invoices older than 30 days are escalated for manual review.
|
|
12
|
+
public evaluateEscalation(invoice: Invoice, now: Date): EscalationDecision {
|
|
13
|
+
const ageInDays: number = daysBetween(invoice.issuedAt, now);
|
|
14
|
+
const decision: EscalationDecision =
|
|
15
|
+
ageInDays > 30 ? "manual-review" : "no-escalation";
|
|
16
|
+
return decision;
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Bad example:
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
public evaluateEscalation(invoice: any, now: Date): any {
|
|
24
|
+
return Promise.resolve(invoice).then((it) => (Date.now() - it.issuedAt > 0 ? "x" : "y"));
|
|
25
|
+
}
|
|
26
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Architecture Guide
|
|
2
|
+
|
|
3
|
+
Architecture strictness is **moderate**.
|
|
4
|
+
|
|
5
|
+
## Project Templates
|
|
6
|
+
|
|
7
|
+
Two templates are supported:
|
|
8
|
+
|
|
9
|
+
- `node-lib`
|
|
10
|
+
- `node-service`
|
|
11
|
+
|
|
12
|
+
## Default Layout
|
|
13
|
+
|
|
14
|
+
Both templates SHOULD keep this baseline structure:
|
|
15
|
+
|
|
16
|
+
- `src/` for implementation.
|
|
17
|
+
- `test/` for automated tests.
|
|
18
|
+
- `eslint.config.mjs`, `prettier.config.cjs`, and `tsconfig.json` at root.
|
|
19
|
+
|
|
20
|
+
## Boundary Rules
|
|
21
|
+
|
|
22
|
+
- Keep feature modules cohesive.
|
|
23
|
+
- Avoid cyclic dependencies.
|
|
24
|
+
- Keep configuration centralized at project root.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Changelog Policy
|
|
2
|
+
|
|
3
|
+
## Versioning
|
|
4
|
+
|
|
5
|
+
Use semantic versioning for the published `@sha3/code-standards` package.
|
|
6
|
+
|
|
7
|
+
## Rules
|
|
8
|
+
|
|
9
|
+
- Every release MUST include a concise changelog entry.
|
|
10
|
+
- Breaking changes MUST document migration steps.
|
|
11
|
+
- `npm run release:check` MUST pass before publishing.
|
|
12
|
+
- Use `npm run release:publish` to publish from repository root.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"version": "v1",
|
|
4
|
+
"scope": "@sha3",
|
|
5
|
+
"packageManager": "npm",
|
|
6
|
+
"moduleSystem": "esm"
|
|
7
|
+
},
|
|
8
|
+
"language": {
|
|
9
|
+
"runtime": "node",
|
|
10
|
+
"typescript": true,
|
|
11
|
+
"target": "ES2022"
|
|
12
|
+
},
|
|
13
|
+
"formatting": {
|
|
14
|
+
"prettier": true,
|
|
15
|
+
"lineLength": 100,
|
|
16
|
+
"semi": true,
|
|
17
|
+
"singleQuote": false
|
|
18
|
+
},
|
|
19
|
+
"naming": {
|
|
20
|
+
"files": "kebab-case",
|
|
21
|
+
"directories": "kebab-case",
|
|
22
|
+
"typescript": {
|
|
23
|
+
"types": "PascalCase",
|
|
24
|
+
"interfaces": "PascalCase",
|
|
25
|
+
"constants": "SCREAMING_SNAKE_CASE"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"architecture": {
|
|
29
|
+
"strictness": "moderate",
|
|
30
|
+
"templates": ["node-lib", "node-service"]
|
|
31
|
+
},
|
|
32
|
+
"testing": {
|
|
33
|
+
"runner": "node-test-runner",
|
|
34
|
+
"coverage": false,
|
|
35
|
+
"testLocation": "test/"
|
|
36
|
+
},
|
|
37
|
+
"tooling": {
|
|
38
|
+
"eslintConfig": "@sha3/code-standards/eslint/node",
|
|
39
|
+
"prettierConfig": "@sha3/code-standards/prettier",
|
|
40
|
+
"tsconfigPackage": "@sha3/code-standards/tsconfig/node-lib.json",
|
|
41
|
+
"enforcement": "local-strict"
|
|
42
|
+
},
|
|
43
|
+
"ai": {
|
|
44
|
+
"enabledByDefault": true,
|
|
45
|
+
"assistants": ["codex", "cursor", "copilot", "windsurf"]
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# README Guide
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Every repository README MUST be clear, actionable, and visually structured.
|
|
6
|
+
|
|
7
|
+
## Mandatory Sections
|
|
8
|
+
|
|
9
|
+
- Title and one-line value proposition.
|
|
10
|
+
- TL;DR or Quick Start with copy/paste commands.
|
|
11
|
+
- What it does and why it exists.
|
|
12
|
+
- Setup and usage examples.
|
|
13
|
+
- AI workflow section when the repository uses AI coding contracts.
|
|
14
|
+
- Troubleshooting or FAQ.
|
|
15
|
+
|
|
16
|
+
## Writing Rules
|
|
17
|
+
|
|
18
|
+
- Use concrete commands and expected execution order.
|
|
19
|
+
- Avoid vague claims without implementation detail.
|
|
20
|
+
- Keep headings and lists scannable.
|
|
21
|
+
- Update README with every behavior or command change.
|
|
22
|
+
|
|
23
|
+
## Quality Bar
|
|
24
|
+
|
|
25
|
+
A top-tier README lets a new engineer understand and run the project in under 5 minutes without asking additional questions.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://sha3.dev/code-standards/schema.json",
|
|
4
|
+
"title": "Code Standards Manifest",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": [
|
|
8
|
+
"meta",
|
|
9
|
+
"language",
|
|
10
|
+
"formatting",
|
|
11
|
+
"naming",
|
|
12
|
+
"architecture",
|
|
13
|
+
"testing",
|
|
14
|
+
"tooling",
|
|
15
|
+
"ai"
|
|
16
|
+
],
|
|
17
|
+
"properties": {
|
|
18
|
+
"meta": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"additionalProperties": false,
|
|
21
|
+
"required": ["version", "scope", "packageManager", "moduleSystem"],
|
|
22
|
+
"properties": {
|
|
23
|
+
"version": { "type": "string", "pattern": "^v[0-9]+$" },
|
|
24
|
+
"scope": { "type": "string", "const": "@sha3" },
|
|
25
|
+
"packageManager": { "type": "string", "const": "npm" },
|
|
26
|
+
"moduleSystem": { "type": "string", "enum": ["esm"] }
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"language": {
|
|
30
|
+
"type": "object",
|
|
31
|
+
"additionalProperties": false,
|
|
32
|
+
"required": ["runtime", "typescript", "target"],
|
|
33
|
+
"properties": {
|
|
34
|
+
"runtime": { "type": "string", "const": "node" },
|
|
35
|
+
"typescript": { "type": "boolean" },
|
|
36
|
+
"target": { "type": "string" }
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"formatting": {
|
|
40
|
+
"type": "object",
|
|
41
|
+
"additionalProperties": false,
|
|
42
|
+
"required": ["prettier", "lineLength", "semi", "singleQuote"],
|
|
43
|
+
"properties": {
|
|
44
|
+
"prettier": { "type": "boolean" },
|
|
45
|
+
"lineLength": { "type": "integer", "minimum": 80, "maximum": 140 },
|
|
46
|
+
"semi": { "type": "boolean" },
|
|
47
|
+
"singleQuote": { "type": "boolean" }
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"naming": {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"additionalProperties": false,
|
|
53
|
+
"required": ["files", "directories", "typescript"],
|
|
54
|
+
"properties": {
|
|
55
|
+
"files": { "type": "string", "enum": ["kebab-case"] },
|
|
56
|
+
"directories": { "type": "string", "enum": ["kebab-case"] },
|
|
57
|
+
"typescript": {
|
|
58
|
+
"type": "object",
|
|
59
|
+
"additionalProperties": false,
|
|
60
|
+
"required": ["types", "interfaces", "constants"],
|
|
61
|
+
"properties": {
|
|
62
|
+
"types": { "type": "string", "enum": ["PascalCase"] },
|
|
63
|
+
"interfaces": { "type": "string", "enum": ["PascalCase"] },
|
|
64
|
+
"constants": { "type": "string", "enum": ["SCREAMING_SNAKE_CASE"] }
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"architecture": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"additionalProperties": false,
|
|
72
|
+
"required": ["strictness", "templates"],
|
|
73
|
+
"properties": {
|
|
74
|
+
"strictness": { "type": "string", "enum": ["moderate"] },
|
|
75
|
+
"templates": {
|
|
76
|
+
"type": "array",
|
|
77
|
+
"items": { "type": "string", "enum": ["node-lib", "node-service"] },
|
|
78
|
+
"minItems": 2,
|
|
79
|
+
"uniqueItems": true
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
"testing": {
|
|
84
|
+
"type": "object",
|
|
85
|
+
"additionalProperties": false,
|
|
86
|
+
"required": ["runner", "coverage", "testLocation"],
|
|
87
|
+
"properties": {
|
|
88
|
+
"runner": { "type": "string", "const": "node-test-runner" },
|
|
89
|
+
"coverage": { "type": "boolean" },
|
|
90
|
+
"testLocation": { "type": "string", "enum": ["test/"] }
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"tooling": {
|
|
94
|
+
"type": "object",
|
|
95
|
+
"additionalProperties": false,
|
|
96
|
+
"required": ["eslintConfig", "prettierConfig", "tsconfigPackage", "enforcement"],
|
|
97
|
+
"properties": {
|
|
98
|
+
"eslintConfig": { "type": "string", "const": "@sha3/code-standards/eslint/node" },
|
|
99
|
+
"prettierConfig": { "type": "string", "const": "@sha3/code-standards/prettier" },
|
|
100
|
+
"tsconfigPackage": {
|
|
101
|
+
"type": "string",
|
|
102
|
+
"const": "@sha3/code-standards/tsconfig/node-lib.json"
|
|
103
|
+
},
|
|
104
|
+
"enforcement": { "type": "string", "enum": ["local-strict"] }
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
"ai": {
|
|
108
|
+
"type": "object",
|
|
109
|
+
"additionalProperties": false,
|
|
110
|
+
"required": ["enabledByDefault", "assistants"],
|
|
111
|
+
"properties": {
|
|
112
|
+
"enabledByDefault": { "type": "boolean" },
|
|
113
|
+
"assistants": {
|
|
114
|
+
"type": "array",
|
|
115
|
+
"items": { "type": "string", "enum": ["codex", "cursor", "copilot", "windsurf"] },
|
|
116
|
+
"minItems": 4,
|
|
117
|
+
"uniqueItems": true
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Style Guide
|
|
2
|
+
|
|
3
|
+
All code MUST follow the canonical rules in `standards/manifest.json`.
|
|
4
|
+
|
|
5
|
+
## Formatting
|
|
6
|
+
|
|
7
|
+
- Use Prettier for formatting.
|
|
8
|
+
- Use a max line length of 100.
|
|
9
|
+
- Use semicolons.
|
|
10
|
+
- Use double quotes for strings.
|
|
11
|
+
|
|
12
|
+
## TypeScript
|
|
13
|
+
|
|
14
|
+
- Use strict TypeScript mode.
|
|
15
|
+
- Avoid `any` unless there is no viable alternative.
|
|
16
|
+
- Prefer explicit return types for exported functions.
|
|
17
|
+
- Use type-only imports when possible.
|
|
18
|
+
- Always use braces in control flow (`if`, `else`, `for`, `while`, `do`).
|
|
19
|
+
|
|
20
|
+
## Naming
|
|
21
|
+
|
|
22
|
+
- Use `kebab-case` for files and directories.
|
|
23
|
+
- Use `PascalCase` for types and interfaces.
|
|
24
|
+
- Use `SCREAMING_SNAKE_CASE` for constants.
|
|
25
|
+
|
|
26
|
+
## Class File Comment Blocks
|
|
27
|
+
|
|
28
|
+
Class-oriented files MUST use `/** @section ... */` markers in this exact order:
|
|
29
|
+
|
|
30
|
+
1. `imports:externals`
|
|
31
|
+
2. `imports:internals`
|
|
32
|
+
3. `consts`
|
|
33
|
+
4. `types`
|
|
34
|
+
5. `private:attributes`
|
|
35
|
+
6. `private:properties`
|
|
36
|
+
7. `public:properties`
|
|
37
|
+
8. `constructor`
|
|
38
|
+
9. `static:properties`
|
|
39
|
+
10. `factory`
|
|
40
|
+
11. `private:methods`
|
|
41
|
+
12. `public:methods`
|
|
42
|
+
13. `static:methods`
|
|
43
|
+
|
|
44
|
+
All section blocks MUST be present even when empty. Empty sections MUST include:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
// empty
|
|
48
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Testing Guide
|
|
2
|
+
|
|
3
|
+
Projects MUST use the Node test runner.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
- Store tests under `test/`.
|
|
8
|
+
- Use `*.test.ts` or `*.test.js` naming.
|
|
9
|
+
|
|
10
|
+
## Commands
|
|
11
|
+
|
|
12
|
+
- `npm run test` MUST execute all automated tests.
|
|
13
|
+
- `npm run check` MUST include test execution.
|
|
14
|
+
|
|
15
|
+
## Assertions
|
|
16
|
+
|
|
17
|
+
- Prefer `node:assert/strict`.
|
|
18
|
+
- Keep tests deterministic and isolated.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Tooling Guide
|
|
2
|
+
|
|
3
|
+
All new projects MUST use this package and its subpath exports:
|
|
4
|
+
|
|
5
|
+
- `@sha3/code-standards/eslint/node`
|
|
6
|
+
- `@sha3/code-standards/eslint/test`
|
|
7
|
+
- `@sha3/code-standards/prettier`
|
|
8
|
+
- `@sha3/code-standards/tsconfig/node-lib.json` or `node-service.json`
|
|
9
|
+
|
|
10
|
+
## Behavioral Policy
|
|
11
|
+
|
|
12
|
+
In addition to tooling, each generated project MUST include profile-driven AI instructions:
|
|
13
|
+
|
|
14
|
+
- `AGENTS.md` generated from the active style profile
|
|
15
|
+
- `ai/codex.md`, `ai/cursor.md`, `ai/copilot.md`, `ai/windsurf.md`
|
|
16
|
+
|
|
17
|
+
The generated instructions are blocking rules and MUST be treated as the top local AI coding contract.
|
|
18
|
+
|
|
19
|
+
## Enforcement
|
|
20
|
+
|
|
21
|
+
Enforcement is local and strict.
|
|
22
|
+
|
|
23
|
+
Required scripts:
|
|
24
|
+
|
|
25
|
+
- `npm run check`
|
|
26
|
+
- `npm run fix`
|
|
27
|
+
- `npm run lint`
|
|
28
|
+
- `npm run format:check`
|
|
29
|
+
- `npm run typecheck`
|
|
30
|
+
- `npm run test`
|
|
31
|
+
|
|
32
|
+
No remote CI is required for v1.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{packageName}}",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc -p tsconfig.build.json",
|
|
13
|
+
"check": "npm run lint && npm run format:check && npm run typecheck && npm run test",
|
|
14
|
+
"fix": "npm run lint:fix && npm run format:write",
|
|
15
|
+
"lint": "eslint .",
|
|
16
|
+
"lint:fix": "eslint . --fix",
|
|
17
|
+
"format:check": "prettier --check .",
|
|
18
|
+
"format:write": "prettier --write .",
|
|
19
|
+
"typecheck": "tsc --noEmit",
|
|
20
|
+
"test": "node --import tsx --test"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@sha3/code-standards": "^0.1.0",
|
|
24
|
+
"@types/node": "^22.13.10",
|
|
25
|
+
"eslint": "^9.20.1",
|
|
26
|
+
"prettier": "^3.5.3",
|
|
27
|
+
"tsx": "^4.19.3",
|
|
28
|
+
"typescript": "^5.8.2"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{packageName}}",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "node --import tsx src/index.ts",
|
|
8
|
+
"check": "npm run lint && npm run format:check && npm run typecheck && npm run test",
|
|
9
|
+
"fix": "npm run lint:fix && npm run format:write",
|
|
10
|
+
"lint": "eslint .",
|
|
11
|
+
"lint:fix": "eslint . --fix",
|
|
12
|
+
"format:check": "prettier --check .",
|
|
13
|
+
"format:write": "prettier --write .",
|
|
14
|
+
"typecheck": "tsc --noEmit",
|
|
15
|
+
"test": "node --import tsx --test"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@sha3/code-standards": "^0.1.0",
|
|
19
|
+
"@types/node": "^22.13.10",
|
|
20
|
+
"eslint": "^9.20.1",
|
|
21
|
+
"prettier": "^3.5.3",
|
|
22
|
+
"tsx": "^4.19.3",
|
|
23
|
+
"typescript": "^5.8.2"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
|
|
3
|
+
export function buildServer() {
|
|
4
|
+
return createServer((_, response) => {
|
|
5
|
+
response.statusCode = 200;
|
|
6
|
+
response.setHeader("content-type", "application/json");
|
|
7
|
+
response.end(JSON.stringify({ ok: true }));
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (process.env.NODE_ENV !== "test") {
|
|
12
|
+
const port = Number(process.env.PORT ?? "3000");
|
|
13
|
+
const server = buildServer();
|
|
14
|
+
server.listen(port, () => {
|
|
15
|
+
console.log(`service listening on http://localhost:${port}`);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { buildServer } from "../src/index.js";
|
|
5
|
+
|
|
6
|
+
test("service responds with ok payload", async () => {
|
|
7
|
+
const server = buildServer();
|
|
8
|
+
|
|
9
|
+
await new Promise<void>((resolve) => {
|
|
10
|
+
server.listen(0, () => {
|
|
11
|
+
resolve();
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const address = server.address();
|
|
16
|
+
|
|
17
|
+
if (!address || typeof address === "string") {
|
|
18
|
+
throw new Error("failed to bind test server");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const response = await fetch(`http://127.0.0.1:${address.port}`);
|
|
22
|
+
const json = await response.json();
|
|
23
|
+
|
|
24
|
+
assert.equal(response.status, 200);
|
|
25
|
+
assert.deepEqual(json, { ok: true });
|
|
26
|
+
|
|
27
|
+
await new Promise<void>((resolve, reject) => {
|
|
28
|
+
server.close((error) => {
|
|
29
|
+
if (error) {
|
|
30
|
+
reject(error);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
resolve();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"module": "NodeNext",
|
|
6
|
+
"moduleResolution": "NodeNext",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noUncheckedIndexedAccess": true,
|
|
9
|
+
"exactOptionalPropertyTypes": true,
|
|
10
|
+
"useUnknownInCatchVariables": true,
|
|
11
|
+
"isolatedModules": true,
|
|
12
|
+
"esModuleInterop": false,
|
|
13
|
+
"forceConsistentCasingInFileNames": true,
|
|
14
|
+
"skipLibCheck": true
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
3
|
+
"extends": "./base.json",
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"declaration": true,
|
|
6
|
+
"declarationMap": true,
|
|
7
|
+
"sourceMap": true,
|
|
8
|
+
"outDir": "dist",
|
|
9
|
+
"rootDir": "src"
|
|
10
|
+
},
|
|
11
|
+
"include": ["src/**/*.ts", "test/**/*.ts"]
|
|
12
|
+
}
|