lgtm-specs 0.0.4
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/.claude/settings.local.json +14 -0
- package/.gemini/README.md +8 -0
- package/.gemini/config.yaml +20 -0
- package/.gemini/styleguide.md +35 -0
- package/.github/workflows/README.md +5 -0
- package/.github/workflows/release.yml +52 -0
- package/.github/workflows/validate.yml +27 -0
- package/.prettierignore +4 -0
- package/.prettierrc +1 -0
- package/AGENTS.md +151 -0
- package/README.md +98 -0
- package/VERSION +1 -0
- package/agents/README.md +73 -0
- package/agents/modes/README.md +9 -0
- package/agents/modes/build.md +88 -0
- package/agents/modes/hack.md +76 -0
- package/agents/modes/review.md +79 -0
- package/agents/roles/builder.md +75 -0
- package/agents/roles/counsel.md +96 -0
- package/agents/roles/explorer.md +77 -0
- package/agents/roles/lead.md +76 -0
- package/agents/roles/librarian.md +63 -0
- package/agents/roles/planner.md +75 -0
- package/agents/roles/reviewer/BASE.md +9 -0
- package/agents/roles/reviewer/OUTPUT_FORMAT.md +4 -0
- package/agents/roles/reviewer/README.md +48 -0
- package/agents/roles/reviewer/lite.md +51 -0
- package/agents/roles/reviewer/logic.md +48 -0
- package/agents/roles/reviewer/performance.md +45 -0
- package/agents/roles/reviewer/plan.md +52 -0
- package/agents/roles/reviewer/quality.md +49 -0
- package/agents/roles/reviewer/security.md +47 -0
- package/agents/roles/reviewer/test.md +48 -0
- package/agents/templates/README.md +6 -0
- package/agents/templates/mode.md +33 -0
- package/agents/templates/role.md +73 -0
- package/contribute/README.md +24 -0
- package/contribute/add-agent.md +29 -0
- package/contribute/add-ci.md +31 -0
- package/contribute/add-constitution.md +17 -0
- package/contribute/add-law.md +20 -0
- package/contribute/add-policy.md +27 -0
- package/contribute/checklist.md +42 -0
- package/contribute/maintenance.md +19 -0
- package/contribute/update-models.md +47 -0
- package/docs/README.md +13 -0
- package/docs/adr/0001-knowledge-engineering-workflow.md +22 -0
- package/docs/adr/0002-rule-hierarchy.md +25 -0
- package/docs/adr/0003-atomic-knowledge-graph.md +21 -0
- package/docs/adr/0004-identification-schema.md +22 -0
- package/docs/adr/0005-agent-specialization.md +39 -0
- package/docs/adr/0006-git-workflow-integrity.md +34 -0
- package/docs/adr/0007-operating-modes-and-gates.md +54 -0
- package/docs/adr/0008-rules-vs-workflows-boundary.md +64 -0
- package/docs/adr/README.md +14 -0
- package/docs/agent_architecture.md +164 -0
- package/docs/context_lifecycle.md +228 -0
- package/docs/engineering_principles.md +128 -0
- package/docs/local_policies.md +59 -0
- package/docs/meta/collaborative_dynamics.md +142 -0
- package/docs/meta/domains/README.md +8 -0
- package/docs/meta/domains/bitcoin/01-units.md +21 -0
- package/docs/meta/domains/bitcoin/02-broadcast-cancellation.md +20 -0
- package/docs/meta/domains/bitcoin/03-fee-rates-rounding.md +21 -0
- package/docs/meta/domains/bitcoin/04-confirmations-reorgs.md +20 -0
- package/docs/meta/domains/bitcoin/05-address-gap-limit.md +16 -0
- package/docs/meta/domains/bitcoin/06-relay-policy.md +27 -0
- package/docs/meta/domains/bitcoin/README.md +12 -0
- package/docs/meta/domains/git/01-workflow.md +89 -0
- package/docs/meta/domains/git/02-commits.md +57 -0
- package/docs/meta/domains/git/03-collaboration.md +40 -0
- package/docs/meta/domains/git/04-integrity.md +26 -0
- package/docs/meta/domains/git/05-configuration.md +209 -0
- package/docs/meta/domains/git/06-advanced.md +130 -0
- package/docs/meta/domains/git/README.md +29 -0
- package/docs/meta/industry_best_practices.md +555 -0
- package/docs/meta/languages/README.md +8 -0
- package/docs/meta/languages/go/01-concurrency.md +37 -0
- package/docs/meta/languages/go/02-api-design.md +30 -0
- package/docs/meta/languages/go/03-resilience.md +27 -0
- package/docs/meta/languages/go/04-errors.md +27 -0
- package/docs/meta/languages/go/05-performance.md +18 -0
- package/docs/meta/languages/go/06-safety.md +18 -0
- package/docs/meta/languages/go/07-testing.md +44 -0
- package/docs/meta/languages/go/08-config-layout.md +23 -0
- package/docs/meta/languages/go/README.md +14 -0
- package/docs/meta/languages/typescript/01-strictness.md +19 -0
- package/docs/meta/languages/typescript/02-immutability.md +15 -0
- package/docs/meta/languages/typescript/03-async.md +18 -0
- package/docs/meta/languages/typescript/04-design.md +19 -0
- package/docs/meta/languages/typescript/05-control-flow.md +11 -0
- package/docs/meta/languages/typescript/README.md +11 -0
- package/docs/meta/workflow.md +68 -0
- package/docs/philosophy.md +36 -0
- package/integrate/README.md +459 -0
- package/integrate/versioning.md +41 -0
- package/models/README.md +68 -0
- package/models/registry.yaml +55 -0
- package/package.json +11 -0
- package/rules/README.md +57 -0
- package/rules/RULE-00000-EXAMPLE.md +29 -0
- package/rules/constitution/CONS-00001-srp.md +40 -0
- package/rules/constitution/CONS-00002-ocp.md +43 -0
- package/rules/constitution/CONS-00003-lsp.md +44 -0
- package/rules/constitution/CONS-00004-isp.md +46 -0
- package/rules/constitution/CONS-00005-dip.md +37 -0
- package/rules/constitution/CONS-00006-dry.md +45 -0
- package/rules/constitution/CONS-00007-demeter.md +35 -0
- package/rules/constitution/CONS-00008-composition.md +44 -0
- package/rules/constitution/CONS-00009-deep-modules.md +39 -0
- package/rules/constitution/CONS-00010-kiss.md +47 -0
- package/rules/constitution/CONS-00011-yagni.md +49 -0
- package/rules/constitution/CONS-00012-cognitive-limits.md +28 -0
- package/rules/constitution/CONS-00013-boy-scout.md +27 -0
- package/rules/constitution/CONS-00014-broken-windows.md +35 -0
- package/rules/constitution/CONS-00015-safety.md +46 -0
- package/rules/constitution/CONS-00016-cqs.md +39 -0
- package/rules/constitution/CONS-00017-postel.md +35 -0
- package/rules/constitution/CONS-00018-cap.md +35 -0
- package/rules/constitution/CONS-00019-fallacies.md +37 -0
- package/rules/constitution/CONS-00020-shift-left.md +28 -0
- package/rules/constitution/CONS-00021-congruence.md +28 -0
- package/rules/constitution/CONS-00022-orthogonality.md +40 -0
- package/rules/constitution/CONS-00023-determinism.md +38 -0
- package/rules/constitution/CONS-00024-security.md +42 -0
- package/rules/constitution/CONS-00025-efficiency.md +38 -0
- package/rules/constitution/CONS-00026-resilience.md +41 -0
- package/rules/constitution/CONS-00027-transparency.md +40 -0
- package/rules/constitution/CONS-00028-evolvability.md +36 -0
- package/rules/constitution/CONS-00029-operability.md +36 -0
- package/rules/constitution/CONS-00030-rework-cycle.md +27 -0
- package/rules/constitution/CONS-00031-checklist.md +28 -0
- package/rules/constitution/CONS-00032-documentation.md +39 -0
- package/rules/constitution/README.md +52 -0
- package/rules/laws/README.md +15 -0
- package/rules/laws/bitcoin/BTC-00001-amounts-as-satoshis.md +39 -0
- package/rules/laws/bitcoin/BTC-00002-broadcast-not-cancelable.md +36 -0
- package/rules/laws/bitcoin/BTC-00003-fee-rate-math-rounding.md +37 -0
- package/rules/laws/bitcoin/BTC-00004-confirmations-and-reorgs.md +40 -0
- package/rules/laws/bitcoin/BTC-00005-address-gap-limit.md +37 -0
- package/rules/laws/bitcoin/BTC-00006-relay-is-policy-dependent.md +36 -0
- package/rules/laws/bitcoin/BTC-00007-dust-policy.md +36 -0
- package/rules/laws/bitcoin/BTC-00008-min-relay-fee.md +36 -0
- package/rules/laws/bitcoin/BTC-00009-feefilter.md +36 -0
- package/rules/laws/bitcoin/README.md +29 -0
- package/rules/laws/default.md +30 -0
- package/rules/laws/git/GIT-00001-atomic-commit.md +29 -0
- package/rules/laws/git/GIT-00002-imperative-subject.md +27 -0
- package/rules/laws/git/GIT-00003-formatting-50-72.md +28 -0
- package/rules/laws/git/GIT-00004-trunk-based.md +28 -0
- package/rules/laws/git/GIT-00005-public-immutability.md +26 -0
- package/rules/laws/git/GIT-00006-signing.md +27 -0
- package/rules/laws/git/GIT-00007-reviewer-capital.md +26 -0
- package/rules/laws/git/GIT-00008-patch-series.md +28 -0
- package/rules/laws/git/GIT-00009-branch-naming.md +28 -0
- package/rules/laws/git/GIT-00010-pr-hygiene.md +51 -0
- package/rules/laws/git/GIT-00011-merge-method.md +35 -0
- package/rules/laws/git/GIT-00012-conflict-resolution.md +35 -0
- package/rules/laws/git/GIT-00013-ignore-standards.md +38 -0
- package/rules/laws/git/GIT-00014-lfs-large-binaries.md +37 -0
- package/rules/laws/git/GIT-00015-git-hooks.md +35 -0
- package/rules/laws/git/GIT-00016-branch-protection.md +34 -0
- package/rules/laws/git/GIT-00017-secrets-management.md +34 -0
- package/rules/laws/git/GIT-00018-ci-enforcement.md +33 -0
- package/rules/laws/git/GIT-00019-review-checklist.md +39 -0
- package/rules/laws/git/GIT-00020-issue-references.md +34 -0
- package/rules/laws/git/GIT-00021-partial-staging.md +38 -0
- package/rules/laws/git/GIT-00022-feature-flags.md +33 -0
- package/rules/laws/git/GIT-00023-breaking-changes.md +41 -0
- package/rules/laws/git/GIT-00024-dependency-management.md +44 -0
- package/rules/laws/git/GIT-00025-large-repository-optimization.md +54 -0
- package/rules/laws/git/README.md +31 -0
- package/rules/laws/go/GO-00001-actor-model.md +51 -0
- package/rules/laws/go/GO-00002-api-design.md +37 -0
- package/rules/laws/go/GO-00003-error-handling.md +43 -0
- package/rules/laws/go/GO-00004-context.md +45 -0
- package/rules/laws/go/GO-00005-performance.md +40 -0
- package/rules/laws/go/GO-00006-packages.md +29 -0
- package/rules/laws/go/GO-00007-circuit-breakers.md +43 -0
- package/rules/laws/go/GO-00008-safety.md +39 -0
- package/rules/laws/go/GO-00009-table-driven-test.md +48 -0
- package/rules/laws/go/GO-00010-escape-analysis.md +37 -0
- package/rules/laws/go/GO-00011-retry.md +45 -0
- package/rules/laws/go/GO-00012-rate-limiting.md +42 -0
- package/rules/laws/go/GO-00013-io-buffering.md +43 -0
- package/rules/laws/go/GO-00014-memory-layout.md +41 -0
- package/rules/laws/go/GO-00015-aaa-pattern.md +49 -0
- package/rules/laws/go/GO-00016-test-libraries.md +35 -0
- package/rules/laws/go/GO-00017-comments.md +37 -0
- package/rules/laws/go/GO-00018-test-isolation.md +38 -0
- package/rules/laws/go/GO-00019-test-comments.md +36 -0
- package/rules/laws/go/GO-00020-mocking.md +36 -0
- package/rules/laws/go/GO-00021-configuration.md +36 -0
- package/rules/laws/go/GO-00022-observability.md +34 -0
- package/rules/laws/go/GO-00023-dependency-management.md +28 -0
- package/rules/laws/go/GO-00024-project-layout.md +30 -0
- package/rules/laws/go/GO-00025-concurrency-patterns.md +39 -0
- package/rules/laws/go/README.md +45 -0
- package/rules/laws/typescript/README.md +14 -0
- package/rules/laws/typescript/TS-00001-no-any.md +39 -0
- package/rules/laws/typescript/TS-00002-immutability.md +36 -0
- package/rules/laws/typescript/TS-00003-async.md +35 -0
- package/rules/laws/typescript/TS-00004-strict-null.md +38 -0
- package/rules/laws/typescript/TS-00005-unions.md +35 -0
- package/rules/laws/typescript/TS-00006-interface.md +38 -0
- package/rules/laws/typescript/TS-00007-generics.md +38 -0
- package/rules/laws/typescript/TS-00008-modules.md +28 -0
- package/rules/policies/README.md +12 -0
- package/rules/policies/default.md +28 -0
- package/scripts/README.md +45 -0
- package/scripts/generate_release_notes.py +376 -0
- package/scripts/validate_specs.py +730 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Test Libraries (GO-00016)
|
|
2
|
+
|
|
3
|
+
**Source**: [Unit Testing Guidelines](../../../docs/meta/languages/go/07-testing.md#4-libraries)
|
|
4
|
+
**Tags**: #operational #go #testing #libraries
|
|
5
|
+
**Related**: [Test Structure](GO-00015-aaa-pattern.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Use standard libraries to enforce fail-fast behavior.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Require over Assert**: Use `testify/require` by default. This stops the test immediately on failure, preventing noisy/invalid subsequent errors.
|
|
14
|
+
2. **Assert usage**: Use `testify/assert` ONLY when you explicitly want to collect multiple failures (e.g., checking 10 independent fields of a struct).
|
|
15
|
+
|
|
16
|
+
## Anti-Patterns
|
|
17
|
+
|
|
18
|
+
- **Manual Checks**: `if got != want { t.Errorf(...) }`. Use the library for better diffs.
|
|
19
|
+
- **Panic in Test**: Using `panic` instead of `t.Fatal`.
|
|
20
|
+
|
|
21
|
+
## Examples
|
|
22
|
+
|
|
23
|
+
**Bad:**
|
|
24
|
+
|
|
25
|
+
```go
|
|
26
|
+
assert.NoError(t, err) // Continues if err != nil, causing a panic later
|
|
27
|
+
result.DoSomething() // PANIC: result is nil
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Good:**
|
|
31
|
+
|
|
32
|
+
```go
|
|
33
|
+
require.NoError(t, err) // Stops test here
|
|
34
|
+
result.DoSomething() // Safe
|
|
35
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Comments & Godoc (GO-00017)
|
|
2
|
+
|
|
3
|
+
**Source**: [API Design](../../../docs/meta/languages/go/02-api-design.md#3-documentation-godoc)
|
|
4
|
+
**Tags**: #operational #go #documentation
|
|
5
|
+
**Related**: [Clean Packages](GO-00006-packages.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Go documentation is a contract. It must be complete, formatted, and readable by `godoc`.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Format**: Comments for `func Foo` must start with `// Foo ...`.
|
|
14
|
+
2. **Exported Symbols**: Every exported function, type, and constant MUST have a comment.
|
|
15
|
+
3. **Directives**: Use `//go:generate` or `//Deprecated:` on separate lines.
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **Stutter**: `// Foo does foo.` (Add value or don't comment).
|
|
20
|
+
- **Disconnect**: `// Returns error` when the function signature changed to return `bool`.
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
|
|
26
|
+
```go
|
|
27
|
+
// NewService ...
|
|
28
|
+
func NewService() *Service
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Good:**
|
|
32
|
+
|
|
33
|
+
```go
|
|
34
|
+
// NewService initializes the backend and connects to the DB.
|
|
35
|
+
// It returns ErrConfigMissing if the config is nil.
|
|
36
|
+
func NewService() *Service
|
|
37
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Test Isolation (GO-00018)
|
|
2
|
+
|
|
3
|
+
**Source**: [Unit Testing Guidelines](../../../docs/meta/languages/go/07-testing.md#3-standalone-tests)
|
|
4
|
+
**Tags**: #operational #go #testing #isolation
|
|
5
|
+
**Related**: [AAA Pattern](GO-00015-aaa-pattern.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Each test must verify a single concept and be independent.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **One Concept**: Verify one specific behavior or edge case per test function.
|
|
14
|
+
2. **Standalone**: Use separate `Test` functions when setup logic differs. Do not force disjoint cases into a single table.
|
|
15
|
+
3. **Independence**: Tests must not depend on state left by other tests.
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **Complex Tables**: Adding `if` statements inside a table loop to handle different mocks.
|
|
20
|
+
- **Coupling**: Relying on global state modified by a previous test.
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
|
|
26
|
+
```go
|
|
27
|
+
func TestProcess(t *testing.T) {
|
|
28
|
+
// Tests success AND failure in one function
|
|
29
|
+
// ...
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Good:**
|
|
34
|
+
|
|
35
|
+
```go
|
|
36
|
+
func TestProcess_Success(t *testing.T) { ... }
|
|
37
|
+
func TestProcess_Failure_Network(t *testing.T) { ... }
|
|
38
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Test Documentation (GO-00019)
|
|
2
|
+
|
|
3
|
+
**Source**: [Unit Testing Guidelines](../../../docs/meta/languages/go/07-testing.md#5-documentation)
|
|
4
|
+
**Tags**: #operational #go #testing #documentation
|
|
5
|
+
**Related**: [Documentation](../../constitution/CONS-00032-documentation.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Tests must document _how_ they verify the system.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Phase Comments**: Use `// Arrange`, `// Act`, `// Assert` (or descriptive equivalents) to label sections.
|
|
14
|
+
2. **Descriptive**: Prefer descriptive comments like `// Setup service with valid config` over just `// Arrange`.
|
|
15
|
+
3. **Docstring**: Complex tests should have a docstring explaining the scenario being tested.
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **Superficial**: Using `// Act` labels without explaining _what_ is being tested if the code isn't obvious.
|
|
20
|
+
- **No Comments**: A complex mock setup with no explanation of why those values were chosen.
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
|
|
26
|
+
```go
|
|
27
|
+
// Act
|
|
28
|
+
result := do()
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Good:**
|
|
32
|
+
|
|
33
|
+
```go
|
|
34
|
+
// Act: Attempt to run the main loop with a cancelled context
|
|
35
|
+
result := do(ctx)
|
|
36
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Mocking Strategy (GO-00020)
|
|
2
|
+
|
|
3
|
+
**Source**: [Unit Testing Guidelines](../../../docs/meta/languages/go/07-testing.md#6-mocking)
|
|
4
|
+
**Tags**: #operational #go #testing #mocking
|
|
5
|
+
**Related**: [Test Isolation](GO-00018-test-isolation.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Use mocks to isolate the unit under test from its dependencies.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Interfaces**: Mock at the interface level.
|
|
14
|
+
2. **Generation**: Use tools like `mockery` or `gomock` to generate mocks from interfaces.
|
|
15
|
+
3. **Expectations**: Explicitly define expected calls and return values in the Arrange phase.
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **Real IO**: Connecting to a real database in a unit test.
|
|
20
|
+
- **Partial Mocks**: Mocking only some methods of a struct (leads to flaky behavior).
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
|
|
26
|
+
```go
|
|
27
|
+
s := &Service{db: &RealDB{}} // Uses real DB
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Good:**
|
|
31
|
+
|
|
32
|
+
```go
|
|
33
|
+
mockDB := new(MockDB)
|
|
34
|
+
mockDB.On("Get", "id").Return(nil, nil)
|
|
35
|
+
s := &Service{db: mockDB}
|
|
36
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Configuration (GO-00021)
|
|
2
|
+
|
|
3
|
+
**Source**: [12-Factor App](../../../docs/meta/languages/go/08-config-layout.md#3-configuration-12-factor)
|
|
4
|
+
**Tags**: #operational #go #configuration
|
|
5
|
+
**Related**: [Clean Packages](GO-00006-packages.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Configuration should be strict, explicit, and sourced from the environment.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Environment Source**: Config comes from Env Vars, not hardcoded constants.
|
|
14
|
+
2. **Explicit Loading**: Use `viper` or `env` to load config into a struct at startup.
|
|
15
|
+
3. **Defaults**: Define sensible defaults in code.
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **Global Config**: `config.Get("key")` scattered in code. Pass config struct explicitly.
|
|
20
|
+
- **Hardcoded Secrets**: API keys committed in source.
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
|
|
26
|
+
```go
|
|
27
|
+
const Timeout = 30 * time.Second
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Good:**
|
|
31
|
+
|
|
32
|
+
```go
|
|
33
|
+
type Config struct {
|
|
34
|
+
Timeout time.Duration `env:"TIMEOUT" envDefault:"30s"`
|
|
35
|
+
}
|
|
36
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Observability (GO-00022)
|
|
2
|
+
|
|
3
|
+
**Source**: [Resilience Patterns](../../../docs/meta/languages/go/03-resilience.md#4-observability-slog)
|
|
4
|
+
**Tags**: #operational #go #logging #observability
|
|
5
|
+
**Related**: [Transparency](../../constitution/CONS-00027-transparency.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Use structured logging to provide machine-readable insights.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Library**: Use `log/slog` (Standard Library) or `zap`.
|
|
14
|
+
2. **Structure**: Log key-value pairs, not formatted strings.
|
|
15
|
+
3. **Levels**: Use `Info` for state changes, `Error` for failures requiring action, `Debug` for tracing.
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **Print Debugging**: `fmt.Println("here")`.
|
|
20
|
+
- **String Formatting**: `log.Printf("User %s failed", user)`. (Hard to query).
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
|
|
26
|
+
```go
|
|
27
|
+
log.Printf("Processed item %d in %v", id, duration)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Good:**
|
|
31
|
+
|
|
32
|
+
```go
|
|
33
|
+
slog.Info("item processed", "id", id, "duration", duration)
|
|
34
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Dependency Management (GO-00023)
|
|
2
|
+
|
|
3
|
+
**Source**: [Go Modules](../../../docs/meta/languages/go/08-config-layout.md#2-dependency-management)
|
|
4
|
+
**Tags**: #operational #go #modules #security
|
|
5
|
+
**Related**: [Clean Packages](GO-00006-packages.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Manage dependencies explicitly using Go Modules.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Modules**: Use `go.mod` and `go.sum` for reproducible builds.
|
|
14
|
+
2. **MVS**: Understand Minimal Version Selection. To upgrade, explicit `go get` is needed.
|
|
15
|
+
3. **Vendoring**: Use `go mod vendor` if hermetic builds are required (e.g., critical infra).
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **GOPATH**: Relying on legacy GOPATH workspace.
|
|
20
|
+
- **Direct Modification**: Editing `go.mod` manually without running `go mod tidy`.
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
Importing code from GitHub without a version tag in `go.mod`.
|
|
26
|
+
|
|
27
|
+
**Good:**
|
|
28
|
+
`require github.com/pkg/errors v0.9.1`
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Project Layout (GO-00024)
|
|
2
|
+
|
|
3
|
+
**Source**: [Standard Go Project Layout](../../../docs/meta/languages/go/08-config-layout.md#1-the-standard-layout)
|
|
4
|
+
**Tags**: #structural #go #architecture #layout
|
|
5
|
+
**Related**: [Clean Packages](GO-00006-packages.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Adhere to the Standard Go Project Layout to separate concerns and enforce visibility.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Cmd**: Entry points go in `/cmd/<appname>/main.go`. No business logic here.
|
|
14
|
+
2. **Internal**: Private logic goes in `/internal`. This compiler-enforced boundary prevents accidental API leakage.
|
|
15
|
+
3. **Pkg**: Public library code goes in `/pkg`. This is a commitment to stability.
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **Root Dump**: Putting `main.go`, `utils.go`, and `model.go` all in the root directory (except for trivial CLIs).
|
|
20
|
+
- **Src Folder**: Using a `/src` directory (Java/Node style). Go does not use this standard.
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
`/main.go`
|
|
26
|
+
`/utils/helper.go`
|
|
27
|
+
|
|
28
|
+
**Good:**
|
|
29
|
+
`/cmd/server/main.go`
|
|
30
|
+
`/internal/auth/login.go`
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Concurrency Patterns (GO-00025)
|
|
2
|
+
|
|
3
|
+
**Source**: [Concurrency Architecture](../../../docs/meta/languages/go/01-concurrency.md#2-patterns)
|
|
4
|
+
**Tags**: #runtime #go #concurrency #patterns
|
|
5
|
+
**Related**: [Actor Model](GO-00001-actor-model.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Use structured patterns to manage concurrency complexity.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Pipeline**: Break processing into linear stages connected by channels (`Source -> Process -> Sink`).
|
|
14
|
+
2. **Fan-Out**: Distribute work to a fixed pool of workers.
|
|
15
|
+
3. **Bounded**: All channels must be bounded (or the number of goroutines fixed) to prevent memory exhaustion.
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **Unbounded Goroutines**: `go func()` in a loop without a semaphore or worker pool.
|
|
20
|
+
- **Leaky Pipeline**: A stage that fails to close its output channel on exit, deadlocking the next stage.
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
|
|
26
|
+
```go
|
|
27
|
+
for job := range jobs {
|
|
28
|
+
go process(job) // Spawns infinite goroutines
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Good:**
|
|
33
|
+
|
|
34
|
+
```go
|
|
35
|
+
// Fan-out to 10 workers
|
|
36
|
+
for i := 0; i < 10; i++ {
|
|
37
|
+
go worker(jobs)
|
|
38
|
+
}
|
|
39
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# The Law of Go
|
|
2
|
+
|
|
3
|
+
These rules define the engineering standards for Go development within the LGTM organization.
|
|
4
|
+
|
|
5
|
+
## Index
|
|
6
|
+
|
|
7
|
+
### Concurrency & Core
|
|
8
|
+
|
|
9
|
+
- [GO-00001: The Actor Model](GO-00001-actor-model.md): Communicate via channels; isolate state in goroutines.
|
|
10
|
+
- [GO-00004: Context Propagation](GO-00004-context.md): First argument is `ctx`; use `errgroup` for management.
|
|
11
|
+
- [GO-00008: Concurrency Safety](GO-00008-safety.md): Maps/Slices are unsafe; use Mutex or Atomic.
|
|
12
|
+
- [GO-00025: Concurrency Patterns](GO-00025-concurrency-patterns.md): Pipelines, Fan-Out, and Bounded Concurrency.
|
|
13
|
+
|
|
14
|
+
### API & Architecture
|
|
15
|
+
|
|
16
|
+
- [GO-00002: API Design](GO-00002-api-design.md): Accept Interfaces, Return Structs.
|
|
17
|
+
- [GO-00006: Clean Packages](GO-00006-packages.md): Purpose-driven naming; no `utils`; use Standard Layout.
|
|
18
|
+
- [GO-00017: Comments & Godoc](GO-00017-comments.md): Document exported symbols; explain intent.
|
|
19
|
+
- [GO-00021: Configuration](GO-00021-configuration.md): Use Env Vars; explicit struct loading (12-Factor).
|
|
20
|
+
- [GO-00023: Dependency Management](GO-00023-dependency-management.md): Use Modules, MVS, and Vendoring.
|
|
21
|
+
- [GO-00024: Project Layout](GO-00024-project-layout.md): `/cmd`, `/internal`, `/pkg`.
|
|
22
|
+
|
|
23
|
+
### Resilience & Reliability
|
|
24
|
+
|
|
25
|
+
- [GO-00003: Error Handling](GO-00003-error-handling.md): Wrap with `%w`; check with `errors.Is`.
|
|
26
|
+
- [GO-00007: Circuit Breakers](GO-00007-circuit-breakers.md): Fail fast on external dependencies.
|
|
27
|
+
- [GO-00011: Retry Strategy](GO-00011-retry.md): Exponential backoff with jitter for transient errors.
|
|
28
|
+
- [GO-00012: Rate Limiting](GO-00012-rate-limiting.md): Protect resources with `rate.Limiter`.
|
|
29
|
+
- [GO-00022: Observability & Slog](GO-00022-observability.md): Structured key-value logging.
|
|
30
|
+
|
|
31
|
+
### Performance & Optimization
|
|
32
|
+
|
|
33
|
+
- [GO-00005: Runtime Performance](GO-00005-performance.md): Pre-allocate slices; reduce allocations.
|
|
34
|
+
- [GO-00010: Escape Analysis](GO-00010-escape-analysis.md): Keep variables on stack to reduce GC.
|
|
35
|
+
- [GO-00013: I/O Buffering](GO-00013-io-buffering.md): Use `bufio` to minimize system calls.
|
|
36
|
+
- [GO-00014: Memory Layout](GO-00014-memory-layout.md): Order structs largest-to-smallest for alignment.
|
|
37
|
+
|
|
38
|
+
### Testing
|
|
39
|
+
|
|
40
|
+
- [GO-00009: Table-Driven Tests](GO-00009-table-driven-test.md): Data-only structs; identical execution loop.
|
|
41
|
+
- [GO-00015: AAA Pattern](GO-00015-aaa-pattern.md): Arrange, Act, Assert structure.
|
|
42
|
+
- [GO-00016: Test Libraries](GO-00016-test-libraries.md): Use `testify/require` (Fail Fast).
|
|
43
|
+
- [GO-00018: Test Isolation](GO-00018-test-isolation.md): One concept per test; no shared state.
|
|
44
|
+
- [GO-00019: Test Documentation](GO-00019-test-comments.md): Descriptive phase comments.
|
|
45
|
+
- [GO-00020: Mocking Strategy](GO-00020-mocking.md): Mock interfaces; use generation tools.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# The Law of TypeScript
|
|
2
|
+
|
|
3
|
+
These rules define the engineering standards for TypeScript development within the LGTM organization.
|
|
4
|
+
|
|
5
|
+
## Index
|
|
6
|
+
|
|
7
|
+
- [TS-00001: Ban Any](TS-00001-no-any.md): Forbidden `any`; use `unknown` and narrowing.
|
|
8
|
+
- [TS-00002: Immutability](TS-00002-immutability.md): Use `const` and `readonly` by default.
|
|
9
|
+
- [TS-00003: Async Hygiene](TS-00003-async.md): `async/await` only; no floating promises.
|
|
10
|
+
- [TS-00004: Strict Null Checks](TS-00004-strict-null.md): Explicit handling of `null` and `undefined`.
|
|
11
|
+
- [TS-00005: Discriminated Unions](TS-00005-unions.md): Use `kind` field for exhaustive switching.
|
|
12
|
+
- [TS-00006: Interface vs Type](TS-00006-interface.md): Use `interface` for public APIs.
|
|
13
|
+
- [TS-00007: Generics](TS-00007-generics.md): Constrain generics (`T extends X`).
|
|
14
|
+
- [TS-00008: Module Organization](TS-00008-modules.md): Group by Feature, not Type; use Barrels.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Ban Any (TS-00001)
|
|
2
|
+
|
|
3
|
+
**Source**: [The Law of TypeScript](../../../docs/meta/languages/typescript/01-strictness.md#1-no-any)
|
|
4
|
+
**Tags**: #behavioral #typescript #safety #type-system
|
|
5
|
+
**Related**: [Safety](../../constitution/CONS-00015-safety.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
The usage of `any` is strictly forbidden. It defeats the purpose of the type system.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Unknown**: Use `unknown` for uncertain data.
|
|
14
|
+
2. **Validation**: Validate `unknown` with Zod or Type Guards before usage.
|
|
15
|
+
3. **Generics**: Use Generics for reusable functions, not `any`.
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **Lazy Typing**: `func(data: any)` because "I don't know the shape yet."
|
|
20
|
+
- **Implicit Any**: Disabling `noImplicitAny` in tsconfig.
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
function process(data: any) {
|
|
28
|
+
return data.id;
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Good:**
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
function process(data: unknown) {
|
|
36
|
+
if (isUser(data)) return data.id;
|
|
37
|
+
throw new Error("Invalid data");
|
|
38
|
+
}
|
|
39
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Immutability (TS-00002)
|
|
2
|
+
|
|
3
|
+
**Source**: [The Law of TypeScript](../../../docs/meta/languages/typescript/02-immutability.md#immutability--state)
|
|
4
|
+
**Tags**: #behavioral #typescript #state #safety
|
|
5
|
+
**Related**: [Safety](../../constitution/CONS-00015-safety.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Mutation is a common source of bugs. Default to immutability.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Const**: Use `const` by default. `let` is allowed only for counters/accumulators.
|
|
14
|
+
2. **Readonly**: Use `readonly` for array and object properties where possible.
|
|
15
|
+
3. **Spread**: Use spread syntax (`{...old, new}`) instead of mutation (`obj.key = val`).
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **Push**: `arr.push(x)` (mutates). Prefer `[...arr, x]`.
|
|
20
|
+
- **Var**: Never use `var`.
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
const list = [1, 2];
|
|
28
|
+
list.push(3);
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Good:**
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
const list = [1, 2];
|
|
35
|
+
const newList = [...list, 3];
|
|
36
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Async Hygiene (TS-00003)
|
|
2
|
+
|
|
3
|
+
**Source**: [The Law of TypeScript](../../../docs/meta/languages/typescript/03-async.md#1-asyncawait)
|
|
4
|
+
**Tags**: #runtime #typescript #async #control-flow
|
|
5
|
+
**Related**: [Deep Modules](../../constitution/CONS-00009-deep-modules.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Asynchronous code must be explicit and linear.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Async/Await**: Use `async/await` exclusively.
|
|
14
|
+
2. **No Floating Promises**: Do not leave promises un-awaited.
|
|
15
|
+
3. **Void**: Use `void` operator if the result is intentionally ignored.
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **Then Chains**: `.then().catch()` (Legacy).
|
|
20
|
+
- **Mix**: Mixing callbacks with Promises.
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
fetch(url).then((res) => res.json());
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Good:**
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
const res = await fetch(url);
|
|
34
|
+
const data = await res.json();
|
|
35
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Strict Null Checks (TS-00004)
|
|
2
|
+
|
|
3
|
+
**Source**: [The Law of TypeScript](../../../docs/meta/languages/typescript/01-strictness.md#2-strict-null-checks)
|
|
4
|
+
**Tags**: #behavioral #typescript #safety #null
|
|
5
|
+
**Related**: [Safety](../../constitution/CONS-00015-safety.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
`null` and `undefined` are distinct values and must be handled explicitly.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Strict Mode**: `strictNullChecks` must be enabled.
|
|
14
|
+
2. **No Bang**: Avoid non-null assertion (`!`) unless absolutely necessary.
|
|
15
|
+
3. **Optional Chaining**: Use `?.` for safe access.
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **Blind Access**: `user.address.city` when address can be undefined.
|
|
20
|
+
- **Implicit undefined**: Assuming a value exists because "it should be there."
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
function getLength(s: string | null) {
|
|
28
|
+
return s.length; // Error: Object is possibly 'null'
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Good:**
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
function getLength(s: string | null) {
|
|
36
|
+
return s?.length ?? 0;
|
|
37
|
+
}
|
|
38
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Discriminated Unions (TS-00005)
|
|
2
|
+
|
|
3
|
+
**Source**: [The Law of TypeScript](../../../docs/meta/languages/typescript/05-control-flow.md#1-discriminated-unions)
|
|
4
|
+
**Tags**: #structural #typescript #types #patterns
|
|
5
|
+
**Related**: [Safety](../../constitution/CONS-00015-safety.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Use a shared literal field to distinguish between variants of a union type.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Discriminant**: Add a `type` or `kind` field to every member of a union.
|
|
14
|
+
2. **Exhaustiveness**: Switch statements should cover all cases (or use `default: assertNever()`).
|
|
15
|
+
|
|
16
|
+
## Anti-Patterns
|
|
17
|
+
|
|
18
|
+
- **Type Guard Soup**: Checking `if ('prop' in obj)` to distinguish types.
|
|
19
|
+
- **Partial Unions**: Unions where members overlap ambiguously.
|
|
20
|
+
|
|
21
|
+
## Examples
|
|
22
|
+
|
|
23
|
+
**Bad:**
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
type Result = { data?: string; error?: Error }; // Ambiguous
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Good:**
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
type Result =
|
|
33
|
+
| { status: "success"; data: string }
|
|
34
|
+
| { status: "error"; error: Error };
|
|
35
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Interface vs Type (TS-00006)
|
|
2
|
+
|
|
3
|
+
**Source**: [The Law of TypeScript](../../../docs/meta/languages/typescript/04-design.md#1-interface-vs-type)
|
|
4
|
+
**Tags**: #structural #typescript #design
|
|
5
|
+
**Related**: [API Design](../go/GO-00002-api-design.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Use `interface` for object shapes and public APIs; use `type` for unions and primitives.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Interfaces**: Use for defining the shape of objects, classes, and service contracts.
|
|
14
|
+
2. **Types**: Use for Union types (`A | B`), Intersection types, and Primitives.
|
|
15
|
+
3. **Consistency**: Stick to one convention per project if not specified.
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **Empty Interface**: `interface Empty {}` (matches anything).
|
|
20
|
+
- **Type for Objects**: `type User = { id: string }` (Interfaces provide better error messages).
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
type Service = {
|
|
28
|
+
run(): void;
|
|
29
|
+
};
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Good:**
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
interface Service {
|
|
36
|
+
run(): void;
|
|
37
|
+
}
|
|
38
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Generics (TS-00007)
|
|
2
|
+
|
|
3
|
+
**Source**: [The Law of TypeScript](../../../docs/meta/languages/typescript/04-design.md#2-generics)
|
|
4
|
+
**Tags**: #structural #typescript #generics #reusability
|
|
5
|
+
**Related**: [DRY](../../constitution/CONS-00006-dry.md)
|
|
6
|
+
|
|
7
|
+
## Definition
|
|
8
|
+
|
|
9
|
+
Use generics to create reusable components, but constrain them to ensure safety.
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
1. **Constraints**: Always use `extends` to constrain generics (`T extends object`).
|
|
14
|
+
2. **Defaults**: Provide defaults (`T = string`) if appropriate.
|
|
15
|
+
3. **Naming**: Use meaningful names (`TData`, `TResponse`) or standard single letters (`T`, `U`) for abstract util types.
|
|
16
|
+
|
|
17
|
+
## Anti-Patterns
|
|
18
|
+
|
|
19
|
+
- **Unconstrained**: `func<T>(arg: T)` when `T` must have a `.id` property.
|
|
20
|
+
- **Over-Generic**: Making a function generic when it only accepts `string | number`.
|
|
21
|
+
|
|
22
|
+
## Examples
|
|
23
|
+
|
|
24
|
+
**Bad:**
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
function getId<T>(item: T) {
|
|
28
|
+
return item.id; // Error
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Good:**
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
function getId<T extends { id: string }>(item: T) {
|
|
36
|
+
return item.id;
|
|
37
|
+
}
|
|
38
|
+
```
|