claude-termux 1.0.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.
Files changed (99) hide show
  1. package/CLAUDE.md +60 -0
  2. package/GEMINI.md +20 -0
  3. package/README.md +135 -0
  4. package/TERMUX.md +204 -0
  5. package/agents/accessibility-reviewer.md +96 -0
  6. package/agents/ai-prompt-optimizer.md +94 -0
  7. package/agents/api-tester.md +102 -0
  8. package/agents/code-generator.md +94 -0
  9. package/agents/code-reviewer.md +47 -0
  10. package/agents/component-generator.md +102 -0
  11. package/agents/doc-generator.md +91 -0
  12. package/agents/migration-generator.md +94 -0
  13. package/agents/performance-analyzer.md +90 -0
  14. package/agents/proactive-mode.md +91 -0
  15. package/agents/readme-generator.md +101 -0
  16. package/agents/security-auditor.md +86 -0
  17. package/agents/terraform-generator.md +94 -0
  18. package/agents/test-generator.md +76 -0
  19. package/commands/brainstorm.md +5 -0
  20. package/commands/execute-plan.md +5 -0
  21. package/commands/write-plan.md +5 -0
  22. package/hooks/auto-context.json +31 -0
  23. package/hooks/hooks.json +15 -0
  24. package/hooks/run-hook.cmd +19 -0
  25. package/hooks/session-start.sh +52 -0
  26. package/hooks/smart-session.sh +96 -0
  27. package/install.sh +210 -0
  28. package/lib/skills-core.js +208 -0
  29. package/mcp.json +34 -0
  30. package/package.json +49 -0
  31. package/plugins/README.md +47 -0
  32. package/plugins/installed_plugins.json +5 -0
  33. package/plugins/known_marketplaces.json +10 -0
  34. package/plugins/marketplace-info/marketplace.json +517 -0
  35. package/postinstall.js +238 -0
  36. package/settings.json +27 -0
  37. package/settings.local.json +25 -0
  38. package/skills/api-development/SKILL.md +11 -0
  39. package/skills/api-development/openapi/api-documentation.yaml +108 -0
  40. package/skills/brainstorming/SKILL.md +54 -0
  41. package/skills/code-quality/SKILL.md +196 -0
  42. package/skills/condition-based-waiting/SKILL.md +120 -0
  43. package/skills/condition-based-waiting/example.ts +158 -0
  44. package/skills/database-development/SKILL.md +11 -0
  45. package/skills/database-development/migrations/migration.template.sql +49 -0
  46. package/skills/defense-in-depth/SKILL.md +127 -0
  47. package/skills/deployment/SKILL.md +11 -0
  48. package/skills/deployment/ci-cd/github-actions.yml +95 -0
  49. package/skills/deployment/docker/Dockerfile.template +39 -0
  50. package/skills/dispatching-parallel-agents/SKILL.md +180 -0
  51. package/skills/documentation-generation/SKILL.md +8 -0
  52. package/skills/documentation-generation/templates/README.template.md +60 -0
  53. package/skills/error-handling/SKILL.md +267 -0
  54. package/skills/executing-plans/SKILL.md +76 -0
  55. package/skills/finishing-a-development-branch/SKILL.md +200 -0
  56. package/skills/frontend-design/frontend-design/SKILL.md +42 -0
  57. package/skills/integration-testing/SKILL.md +13 -0
  58. package/skills/integration-testing/examples/contract-test.py +317 -0
  59. package/skills/integration-testing/examples/e2e-test.js +147 -0
  60. package/skills/integration-testing/examples/test-isolation.md +94 -0
  61. package/skills/logging-monitoring/SKILL.md +66 -0
  62. package/skills/mobile-development/SKILL.md +11 -0
  63. package/skills/mobile-development/responsive/responsive.css +80 -0
  64. package/skills/performance-optimization/SKILL.md +9 -0
  65. package/skills/performance-optimization/profiling/profile.template.js +21 -0
  66. package/skills/receiving-code-review/SKILL.md +209 -0
  67. package/skills/refactoring/SKILL.md +11 -0
  68. package/skills/refactoring/code-smells/common-smells.md +115 -0
  69. package/skills/requesting-code-review/SKILL.md +105 -0
  70. package/skills/requesting-code-review/code-reviewer.md +146 -0
  71. package/skills/root-cause-tracing/SKILL.md +174 -0
  72. package/skills/root-cause-tracing/find-polluter.sh +63 -0
  73. package/skills/security-review/SKILL.md +11 -0
  74. package/skills/security-review/checklists/owasp-checklist.md +31 -0
  75. package/skills/sharing-skills/SKILL.md +194 -0
  76. package/skills/subagent-driven-development/SKILL.md +240 -0
  77. package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +20 -0
  78. package/skills/subagent-driven-development/implementer-prompt.md +78 -0
  79. package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  80. package/skills/systematic-debugging/CREATION-LOG.md +119 -0
  81. package/skills/systematic-debugging/SKILL.md +295 -0
  82. package/skills/systematic-debugging/test-academic.md +14 -0
  83. package/skills/systematic-debugging/test-pressure-1.md +58 -0
  84. package/skills/systematic-debugging/test-pressure-2.md +68 -0
  85. package/skills/systematic-debugging/test-pressure-3.md +69 -0
  86. package/skills/test-driven-development/SKILL.md +364 -0
  87. package/skills/testing-anti-patterns/SKILL.md +302 -0
  88. package/skills/testing-skills-with-subagents/SKILL.md +387 -0
  89. package/skills/testing-skills-with-subagents/examples/CLAUDE_MD_TESTING.md +189 -0
  90. package/skills/ui-ux-review/SKILL.md +13 -0
  91. package/skills/ui-ux-review/checklists/ux-heuristics.md +61 -0
  92. package/skills/using-git-worktrees/SKILL.md +213 -0
  93. package/skills/using-superpowers/SKILL.md +101 -0
  94. package/skills/verification-before-completion/SKILL.md +139 -0
  95. package/skills/writing-plans/SKILL.md +116 -0
  96. package/skills/writing-skills/SKILL.md +622 -0
  97. package/skills/writing-skills/anthropic-best-practices.md +1150 -0
  98. package/skills/writing-skills/graphviz-conventions.dot +172 -0
  99. package/skills/writing-skills/persuasion-principles.md +187 -0
@@ -0,0 +1,120 @@
1
+ ---
2
+ name: condition-based-waiting
3
+ description: Use when tests have race conditions, timing dependencies, or inconsistent pass/fail behavior - replaces arbitrary timeouts with condition polling to wait for actual state changes, eliminating flaky tests from timing guesses
4
+ ---
5
+
6
+ # Condition-Based Waiting
7
+
8
+ ## Overview
9
+
10
+ Flaky tests often guess at timing with arbitrary delays. This creates race conditions where tests pass on fast machines but fail under load or in CI.
11
+
12
+ **Core principle:** Wait for the actual condition you care about, not a guess about how long it takes.
13
+
14
+ ## When to Use
15
+
16
+ ```dot
17
+ digraph when_to_use {
18
+ "Test uses setTimeout/sleep?" [shape=diamond];
19
+ "Testing timing behavior?" [shape=diamond];
20
+ "Document WHY timeout needed" [shape=box];
21
+ "Use condition-based waiting" [shape=box];
22
+
23
+ "Test uses setTimeout/sleep?" -> "Testing timing behavior?" [label="yes"];
24
+ "Testing timing behavior?" -> "Document WHY timeout needed" [label="yes"];
25
+ "Testing timing behavior?" -> "Use condition-based waiting" [label="no"];
26
+ }
27
+ ```
28
+
29
+ **Use when:**
30
+ - Tests have arbitrary delays (`setTimeout`, `sleep`, `time.sleep()`)
31
+ - Tests are flaky (pass sometimes, fail under load)
32
+ - Tests timeout when run in parallel
33
+ - Waiting for async operations to complete
34
+
35
+ **Don't use when:**
36
+ - Testing actual timing behavior (debounce, throttle intervals)
37
+ - Always document WHY if using arbitrary timeout
38
+
39
+ ## Core Pattern
40
+
41
+ ```typescript
42
+ // ❌ BEFORE: Guessing at timing
43
+ await new Promise(r => setTimeout(r, 50));
44
+ const result = getResult();
45
+ expect(result).toBeDefined();
46
+
47
+ // ✅ AFTER: Waiting for condition
48
+ await waitFor(() => getResult() !== undefined);
49
+ const result = getResult();
50
+ expect(result).toBeDefined();
51
+ ```
52
+
53
+ ## Quick Patterns
54
+
55
+ | Scenario | Pattern |
56
+ |----------|---------|
57
+ | Wait for event | `waitFor(() => events.find(e => e.type === 'DONE'))` |
58
+ | Wait for state | `waitFor(() => machine.state === 'ready')` |
59
+ | Wait for count | `waitFor(() => items.length >= 5)` |
60
+ | Wait for file | `waitFor(() => fs.existsSync(path))` |
61
+ | Complex condition | `waitFor(() => obj.ready && obj.value > 10)` |
62
+
63
+ ## Implementation
64
+
65
+ Generic polling function:
66
+ ```typescript
67
+ async function waitFor<T>(
68
+ condition: () => T | undefined | null | false,
69
+ description: string,
70
+ timeoutMs = 5000
71
+ ): Promise<T> {
72
+ const startTime = Date.now();
73
+
74
+ while (true) {
75
+ const result = condition();
76
+ if (result) return result;
77
+
78
+ if (Date.now() - startTime > timeoutMs) {
79
+ throw new Error(`Timeout waiting for ${description} after ${timeoutMs}ms`);
80
+ }
81
+
82
+ await new Promise(r => setTimeout(r, 10)); // Poll every 10ms
83
+ }
84
+ }
85
+ ```
86
+
87
+ See @example.ts for complete implementation with domain-specific helpers (`waitForEvent`, `waitForEventCount`, `waitForEventMatch`) from actual debugging session.
88
+
89
+ ## Common Mistakes
90
+
91
+ **❌ Polling too fast:** `setTimeout(check, 1)` - wastes CPU
92
+ **✅ Fix:** Poll every 10ms
93
+
94
+ **❌ No timeout:** Loop forever if condition never met
95
+ **✅ Fix:** Always include timeout with clear error
96
+
97
+ **❌ Stale data:** Cache state before loop
98
+ **✅ Fix:** Call getter inside loop for fresh data
99
+
100
+ ## When Arbitrary Timeout IS Correct
101
+
102
+ ```typescript
103
+ // Tool ticks every 100ms - need 2 ticks to verify partial output
104
+ await waitForEvent(manager, 'TOOL_STARTED'); // First: wait for condition
105
+ await new Promise(r => setTimeout(r, 200)); // Then: wait for timed behavior
106
+ // 200ms = 2 ticks at 100ms intervals - documented and justified
107
+ ```
108
+
109
+ **Requirements:**
110
+ 1. First wait for triggering condition
111
+ 2. Based on known timing (not guessing)
112
+ 3. Comment explaining WHY
113
+
114
+ ## Real-World Impact
115
+
116
+ From debugging session (2025-10-03):
117
+ - Fixed 15 flaky tests across 3 files
118
+ - Pass rate: 60% → 100%
119
+ - Execution time: 40% faster
120
+ - No more race conditions
@@ -0,0 +1,158 @@
1
+ // Complete implementation of condition-based waiting utilities
2
+ // From: Lace test infrastructure improvements (2025-10-03)
3
+ // Context: Fixed 15 flaky tests by replacing arbitrary timeouts
4
+
5
+ import type { ThreadManager } from '~/threads/thread-manager';
6
+ import type { LaceEvent, LaceEventType } from '~/threads/types';
7
+
8
+ /**
9
+ * Wait for a specific event type to appear in thread
10
+ *
11
+ * @param threadManager - The thread manager to query
12
+ * @param threadId - Thread to check for events
13
+ * @param eventType - Type of event to wait for
14
+ * @param timeoutMs - Maximum time to wait (default 5000ms)
15
+ * @returns Promise resolving to the first matching event
16
+ *
17
+ * Example:
18
+ * await waitForEvent(threadManager, agentThreadId, 'TOOL_RESULT');
19
+ */
20
+ export function waitForEvent(
21
+ threadManager: ThreadManager,
22
+ threadId: string,
23
+ eventType: LaceEventType,
24
+ timeoutMs = 5000
25
+ ): Promise<LaceEvent> {
26
+ return new Promise((resolve, reject) => {
27
+ const startTime = Date.now();
28
+
29
+ const check = () => {
30
+ const events = threadManager.getEvents(threadId);
31
+ const event = events.find((e) => e.type === eventType);
32
+
33
+ if (event) {
34
+ resolve(event);
35
+ } else if (Date.now() - startTime > timeoutMs) {
36
+ reject(new Error(`Timeout waiting for ${eventType} event after ${timeoutMs}ms`));
37
+ } else {
38
+ setTimeout(check, 10); // Poll every 10ms for efficiency
39
+ }
40
+ };
41
+
42
+ check();
43
+ });
44
+ }
45
+
46
+ /**
47
+ * Wait for a specific number of events of a given type
48
+ *
49
+ * @param threadManager - The thread manager to query
50
+ * @param threadId - Thread to check for events
51
+ * @param eventType - Type of event to wait for
52
+ * @param count - Number of events to wait for
53
+ * @param timeoutMs - Maximum time to wait (default 5000ms)
54
+ * @returns Promise resolving to all matching events once count is reached
55
+ *
56
+ * Example:
57
+ * // Wait for 2 AGENT_MESSAGE events (initial response + continuation)
58
+ * await waitForEventCount(threadManager, agentThreadId, 'AGENT_MESSAGE', 2);
59
+ */
60
+ export function waitForEventCount(
61
+ threadManager: ThreadManager,
62
+ threadId: string,
63
+ eventType: LaceEventType,
64
+ count: number,
65
+ timeoutMs = 5000
66
+ ): Promise<LaceEvent[]> {
67
+ return new Promise((resolve, reject) => {
68
+ const startTime = Date.now();
69
+
70
+ const check = () => {
71
+ const events = threadManager.getEvents(threadId);
72
+ const matchingEvents = events.filter((e) => e.type === eventType);
73
+
74
+ if (matchingEvents.length >= count) {
75
+ resolve(matchingEvents);
76
+ } else if (Date.now() - startTime > timeoutMs) {
77
+ reject(
78
+ new Error(
79
+ `Timeout waiting for ${count} ${eventType} events after ${timeoutMs}ms (got ${matchingEvents.length})`
80
+ )
81
+ );
82
+ } else {
83
+ setTimeout(check, 10);
84
+ }
85
+ };
86
+
87
+ check();
88
+ });
89
+ }
90
+
91
+ /**
92
+ * Wait for an event matching a custom predicate
93
+ * Useful when you need to check event data, not just type
94
+ *
95
+ * @param threadManager - The thread manager to query
96
+ * @param threadId - Thread to check for events
97
+ * @param predicate - Function that returns true when event matches
98
+ * @param description - Human-readable description for error messages
99
+ * @param timeoutMs - Maximum time to wait (default 5000ms)
100
+ * @returns Promise resolving to the first matching event
101
+ *
102
+ * Example:
103
+ * // Wait for TOOL_RESULT with specific ID
104
+ * await waitForEventMatch(
105
+ * threadManager,
106
+ * agentThreadId,
107
+ * (e) => e.type === 'TOOL_RESULT' && e.data.id === 'call_123',
108
+ * 'TOOL_RESULT with id=call_123'
109
+ * );
110
+ */
111
+ export function waitForEventMatch(
112
+ threadManager: ThreadManager,
113
+ threadId: string,
114
+ predicate: (event: LaceEvent) => boolean,
115
+ description: string,
116
+ timeoutMs = 5000
117
+ ): Promise<LaceEvent> {
118
+ return new Promise((resolve, reject) => {
119
+ const startTime = Date.now();
120
+
121
+ const check = () => {
122
+ const events = threadManager.getEvents(threadId);
123
+ const event = events.find(predicate);
124
+
125
+ if (event) {
126
+ resolve(event);
127
+ } else if (Date.now() - startTime > timeoutMs) {
128
+ reject(new Error(`Timeout waiting for ${description} after ${timeoutMs}ms`));
129
+ } else {
130
+ setTimeout(check, 10);
131
+ }
132
+ };
133
+
134
+ check();
135
+ });
136
+ }
137
+
138
+ // Usage example from actual debugging session:
139
+ //
140
+ // BEFORE (flaky):
141
+ // ---------------
142
+ // const messagePromise = agent.sendMessage('Execute tools');
143
+ // await new Promise(r => setTimeout(r, 300)); // Hope tools start in 300ms
144
+ // agent.abort();
145
+ // await messagePromise;
146
+ // await new Promise(r => setTimeout(r, 50)); // Hope results arrive in 50ms
147
+ // expect(toolResults.length).toBe(2); // Fails randomly
148
+ //
149
+ // AFTER (reliable):
150
+ // ----------------
151
+ // const messagePromise = agent.sendMessage('Execute tools');
152
+ // await waitForEventCount(threadManager, threadId, 'TOOL_CALL', 2); // Wait for tools to start
153
+ // agent.abort();
154
+ // await messagePromise;
155
+ // await waitForEventCount(threadManager, threadId, 'TOOL_RESULT', 2); // Wait for results
156
+ // expect(toolResults.length).toBe(2); // Always succeeds
157
+ //
158
+ // Result: 60% pass rate → 100%, 40% faster execution
@@ -0,0 +1,11 @@
1
+ database-development skill helps design efficient, scalable database schemas and manage database migrations effectively.
2
+
3
+ For code review, check that:
4
+ 1. Database schema follows normalization principles
5
+ 2. Proper indexes are created for query optimization
6
+ 3. Foreign key constraints are defined
7
+ 4. Migration files are reversible
8
+ 5. Connection pooling is implemented
9
+ 6. Query N+1 problems are avoided
10
+ 7. Database transactions are used appropriately
11
+ 8. Sensitive data is encrypted in database
@@ -0,0 +1,49 @@
1
+ -- Migration: [Description]
2
+ -- Created: [Date]
3
+ -- Author: [Author]
4
+
5
+ -- Enable transaction for safety
6
+ BEGIN;
7
+
8
+ -- Add new table
9
+ CREATE TABLE [table_name] (
10
+ id SERIAL PRIMARY KEY,
11
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
12
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
13
+ -- Add columns here
14
+ );
15
+
16
+ -- Add indexes if needed
17
+ CREATE INDEX [index_name] ON [table_name]([column_name]);
18
+
19
+ -- Add foreign key constraints
20
+ ALTER TABLE [table_name]
21
+ ADD CONSTRAINT [constraint_name]
22
+ FOREIGN KEY ([column_name])
23
+ REFERENCES [other_table]([column_name]);
24
+
25
+ -- Add columns to existing tables
26
+ ALTER TABLE [existing_table]
27
+ ADD COLUMN [column_name] [type] [constraints];
28
+
29
+ -- Update timestamp
30
+ CREATE OR REPLACE FUNCTION update_updated_at_column()
31
+ RETURNS TRIGGER AS $$
32
+ BEGIN
33
+ NEW.updated_at = CURRENT_TIMESTAMP;
34
+ RETURN NEW;
35
+ END;
36
+ $$ language 'plpgsql';
37
+
38
+ CREATE TRIGGER update_[table_name]_updated_at
39
+ BEFORE UPDATE ON [table_name]
40
+ FOR EACH ROW
41
+ EXECUTE FUNCTION update_updated_at_column();
42
+
43
+ COMMIT;
44
+
45
+ -- Rollback script (keep for reference):
46
+ -- BEGIN;
47
+ -- DROP TABLE IF EXISTS [table_name];
48
+ -- ALTER TABLE [existing_table] DROP COLUMN [column_name];
49
+ -- COMMIT;
@@ -0,0 +1,127 @@
1
+ ---
2
+ name: defense-in-depth
3
+ description: Use when invalid data causes failures deep in execution, requiring validation at multiple system layers - validates at every layer data passes through to make bugs structurally impossible
4
+ ---
5
+
6
+ # Defense-in-Depth Validation
7
+
8
+ ## Overview
9
+
10
+ When you fix a bug caused by invalid data, adding validation at one place feels sufficient. But that single check can be bypassed by different code paths, refactoring, or mocks.
11
+
12
+ **Core principle:** Validate at EVERY layer data passes through. Make the bug structurally impossible.
13
+
14
+ ## Why Multiple Layers
15
+
16
+ Single validation: "We fixed the bug"
17
+ Multiple layers: "We made the bug impossible"
18
+
19
+ Different layers catch different cases:
20
+ - Entry validation catches most bugs
21
+ - Business logic catches edge cases
22
+ - Environment guards prevent context-specific dangers
23
+ - Debug logging helps when other layers fail
24
+
25
+ ## The Four Layers
26
+
27
+ ### Layer 1: Entry Point Validation
28
+ **Purpose:** Reject obviously invalid input at API boundary
29
+
30
+ ```typescript
31
+ function createProject(name: string, workingDirectory: string) {
32
+ if (!workingDirectory || workingDirectory.trim() === '') {
33
+ throw new Error('workingDirectory cannot be empty');
34
+ }
35
+ if (!existsSync(workingDirectory)) {
36
+ throw new Error(`workingDirectory does not exist: ${workingDirectory}`);
37
+ }
38
+ if (!statSync(workingDirectory).isDirectory()) {
39
+ throw new Error(`workingDirectory is not a directory: ${workingDirectory}`);
40
+ }
41
+ // ... proceed
42
+ }
43
+ ```
44
+
45
+ ### Layer 2: Business Logic Validation
46
+ **Purpose:** Ensure data makes sense for this operation
47
+
48
+ ```typescript
49
+ function initializeWorkspace(projectDir: string, sessionId: string) {
50
+ if (!projectDir) {
51
+ throw new Error('projectDir required for workspace initialization');
52
+ }
53
+ // ... proceed
54
+ }
55
+ ```
56
+
57
+ ### Layer 3: Environment Guards
58
+ **Purpose:** Prevent dangerous operations in specific contexts
59
+
60
+ ```typescript
61
+ async function gitInit(directory: string) {
62
+ // In tests, refuse git init outside temp directories
63
+ if (process.env.NODE_ENV === 'test') {
64
+ const normalized = normalize(resolve(directory));
65
+ const tmpDir = normalize(resolve(tmpdir()));
66
+
67
+ if (!normalized.startsWith(tmpDir)) {
68
+ throw new Error(
69
+ `Refusing git init outside temp dir during tests: ${directory}`
70
+ );
71
+ }
72
+ }
73
+ // ... proceed
74
+ }
75
+ ```
76
+
77
+ ### Layer 4: Debug Instrumentation
78
+ **Purpose:** Capture context for forensics
79
+
80
+ ```typescript
81
+ async function gitInit(directory: string) {
82
+ const stack = new Error().stack;
83
+ logger.debug('About to git init', {
84
+ directory,
85
+ cwd: process.cwd(),
86
+ stack,
87
+ });
88
+ // ... proceed
89
+ }
90
+ ```
91
+
92
+ ## Applying the Pattern
93
+
94
+ When you find a bug:
95
+
96
+ 1. **Trace the data flow** - Where does bad value originate? Where used?
97
+ 2. **Map all checkpoints** - List every point data passes through
98
+ 3. **Add validation at each layer** - Entry, business, environment, debug
99
+ 4. **Test each layer** - Try to bypass layer 1, verify layer 2 catches it
100
+
101
+ ## Example from Session
102
+
103
+ Bug: Empty `projectDir` caused `git init` in source code
104
+
105
+ **Data flow:**
106
+ 1. Test setup → empty string
107
+ 2. `Project.create(name, '')`
108
+ 3. `WorkspaceManager.createWorkspace('')`
109
+ 4. `git init` runs in `process.cwd()`
110
+
111
+ **Four layers added:**
112
+ - Layer 1: `Project.create()` validates not empty/exists/writable
113
+ - Layer 2: `WorkspaceManager` validates projectDir not empty
114
+ - Layer 3: `WorktreeManager` refuses git init outside tmpdir in tests
115
+ - Layer 4: Stack trace logging before git init
116
+
117
+ **Result:** All 1847 tests passed, bug impossible to reproduce
118
+
119
+ ## Key Insight
120
+
121
+ All four layers were necessary. During testing, each layer caught bugs the others missed:
122
+ - Different code paths bypassed entry validation
123
+ - Mocks bypassed business logic checks
124
+ - Edge cases on different platforms needed environment guards
125
+ - Debug logging identified structural misuse
126
+
127
+ **Don't stop at one validation point.** Add checks at every layer.
@@ -0,0 +1,11 @@
1
+ deployment skill helps automate application deployment through containerization, CI/CD pipelines, and monitoring setup.
2
+
3
+ For code review, check that:
4
+ 1. Dockerfile follows best practices
5
+ 2. Multi-stage builds are used to reduce image size
6
+ 3. Health checks are implemented
7
+ 4. Environment variables are properly managed
8
+ 5. CI/CD pipeline tests all deployments
9
+ 6. Monitoring and logging are configured
10
+ 7. Rollback strategies are in place
11
+ 8. Zero-downtime deployment is considered
@@ -0,0 +1,95 @@
1
+ name: CI/CD Pipeline
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, develop ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ node-version: [18.x, 20.x]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Setup Node.js
20
+ uses: actions/setup-node@v4
21
+ with:
22
+ node-version: ${{ matrix.node-version }}
23
+ cache: 'npm'
24
+
25
+ - name: Install dependencies
26
+ run: npm ci
27
+
28
+ - name: Run linting
29
+ run: npm run lint
30
+
31
+ - name: Run type checking
32
+ run: npm run type-check
33
+
34
+ - name: Run tests
35
+ run: npm run test
36
+
37
+ - name: Run e2e tests
38
+ run: npm run test:e2e
39
+
40
+ security:
41
+ runs-on: ubuntu-latest
42
+ steps:
43
+ - uses: actions/checkout@v4
44
+
45
+ - name: Run security audit
46
+ run: npm audit --audit-level=high
47
+
48
+ - name: Run Snyk security scan
49
+ uses: snyk/actions/node@master
50
+ env:
51
+ SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
52
+
53
+ build:
54
+ needs: [test, security]
55
+ runs-on: ubuntu-latest
56
+
57
+ steps:
58
+ - uses: actions/checkout@v4
59
+
60
+ - name: Setup Node.js
61
+ uses: actions/setup-node@v4
62
+ with:
63
+ node-version: '20.x'
64
+ cache: 'npm'
65
+
66
+ - name: Install dependencies
67
+ run: npm ci
68
+
69
+ - name: Build application
70
+ run: npm run build
71
+
72
+ - name: Upload build artifacts
73
+ uses: actions/upload-artifact@v4
74
+ with:
75
+ name: build-artifacts
76
+ path: dist/
77
+
78
+ deploy:
79
+ needs: build
80
+ runs-on: ubuntu-latest
81
+ if: github.ref == 'refs/heads/main'
82
+
83
+ environment: production
84
+
85
+ steps:
86
+ - name: Download build artifacts
87
+ uses: actions/download-artifact@v4
88
+ with:
89
+ name: build-artifacts
90
+ path: dist/
91
+
92
+ - name: Deploy to production
93
+ run: |
94
+ echo "Deploy to production server"
95
+ # Add deployment commands here
@@ -0,0 +1,39 @@
1
+ # Multi-stage build for optimal image size
2
+ FROM node:18-alpine AS builder
3
+
4
+ WORKDIR /app
5
+ COPY package*.json ./
6
+ RUN npm ci --only=production
7
+
8
+ # Copy source code
9
+ COPY . .
10
+
11
+ # Build application
12
+ RUN npm run build
13
+
14
+ # Production stage
15
+ FROM node:18-alpine AS production
16
+
17
+ # Create app user
18
+ RUN addgroup -g 1001 -S nodejs
19
+ RUN adduser -S nextjs -u 1001
20
+
21
+ WORKDIR /app
22
+
23
+ # Copy built application
24
+ COPY --from=builder --chown=nextjs:nodejs /app/dist ./dist
25
+ COPY --from=builder /app/node_modules ./node_modules
26
+ COPY --from=builder /app/package.json ./package.json
27
+
28
+ # Health check
29
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
30
+ CMD curl -f http://localhost:3000/health || exit 1
31
+
32
+ USER nextjs
33
+
34
+ EXPOSE 3000
35
+
36
+ ENV NODE_ENV=production
37
+ ENV PORT=3000
38
+
39
+ CMD ["npm", "start"]