opencode-skills-collection 3.0.46 → 3.0.48
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/bundled-skills/.antigravity-install-manifest.json +15 -1
- package/bundled-skills/2slides-ppt-generator/SKILL.md +1 -1
- package/bundled-skills/2slides-ppt-generator/scripts/create_pdf_slides.py +2 -1
- package/bundled-skills/2slides-ppt-generator/scripts/generate_narration.py +2 -1
- package/bundled-skills/2slides-ppt-generator/scripts/generate_slides.py +13 -7
- package/bundled-skills/accint-solve/SKILL.md +205 -0
- package/bundled-skills/android-cli/SKILL.md +239 -0
- package/bundled-skills/android-cli/references/interact.md +83 -0
- package/bundled-skills/android-cli/references/journeys.md +105 -0
- package/bundled-skills/android-dev/references/hybrid.md +7 -4
- package/bundled-skills/android-dev/references/react-native.md +5 -2
- package/bundled-skills/atlas-contract/SKILL.md +4 -4
- package/bundled-skills/atlas-ledger/SKILL.md +10 -7
- package/bundled-skills/bun-development/SKILL.md +1 -1
- package/bundled-skills/cloud-penetration-testing/SKILL.md +1 -1
- package/bundled-skills/codebase-to-wordpress-converter/SKILL.md +1 -0
- package/bundled-skills/codex-fable5/SKILL.md +154 -0
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/getting-started.md +1 -1
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/usage.md +4 -4
- package/bundled-skills/docs/users/visual-guide.md +4 -4
- package/bundled-skills/dos-verify-done-claims/SKILL.md +173 -0
- package/bundled-skills/ecl-harness-engineer/LICENSE +21 -0
- package/bundled-skills/ecl-harness-engineer/SKILL.md +714 -0
- package/bundled-skills/ecl-harness-engineer/agents/analyzer.md +119 -0
- package/bundled-skills/ecl-harness-engineer/agents/auditor.md +212 -0
- package/bundled-skills/ecl-harness-engineer/agents/creator-config.md +343 -0
- package/bundled-skills/ecl-harness-engineer/agents/creator-docs.md +201 -0
- package/bundled-skills/ecl-harness-engineer/agents/creator-linters.md +123 -0
- package/bundled-skills/ecl-harness-engineer/references/adapters/adapter-schema.md +204 -0
- package/bundled-skills/ecl-harness-engineer/references/adapters/generic.md +156 -0
- package/bundled-skills/ecl-harness-engineer/references/adapters/go.md +212 -0
- package/bundled-skills/ecl-harness-engineer/references/adapters/java.md +205 -0
- package/bundled-skills/ecl-harness-engineer/references/adapters/python.md +225 -0
- package/bundled-skills/ecl-harness-engineer/references/adapters/rust.md +220 -0
- package/bundled-skills/ecl-harness-engineer/references/adapters/typescript.md +245 -0
- package/bundled-skills/ecl-harness-engineer/references/architecture-diagrams.md +420 -0
- package/bundled-skills/ecl-harness-engineer/references/audit-templates.md +649 -0
- package/bundled-skills/ecl-harness-engineer/references/capability-registry.md +485 -0
- package/bundled-skills/ecl-harness-engineer/references/darwin-eval-prompts.md +373 -0
- package/bundled-skills/ecl-harness-engineer/references/documentation-templates.md +741 -0
- package/bundled-skills/ecl-harness-engineer/references/durability-patterns.md +423 -0
- package/bundled-skills/ecl-harness-engineer/references/ecl-harness.md +1431 -0
- package/bundled-skills/ecl-harness-engineer/references/environment-config-guide.md +534 -0
- package/bundled-skills/ecl-harness-engineer/references/environment-detection-guide.md +751 -0
- package/bundled-skills/ecl-harness-engineer/references/eval-templates.md +377 -0
- package/bundled-skills/ecl-harness-engineer/references/gc-templates.md +798 -0
- package/bundled-skills/ecl-harness-engineer/references/greenfield-templates.md +1385 -0
- package/bundled-skills/ecl-harness-engineer/references/linter-templates.md +448 -0
- package/bundled-skills/ecl-harness-engineer/references/observability-templates.md +315 -0
- package/bundled-skills/efficient-web-research/SKILL.md +320 -0
- package/bundled-skills/environment-setup-guide/SKILL.md +2 -2
- package/bundled-skills/evolution/SKILL.md +1 -1
- package/bundled-skills/gitops-workflow/SKILL.md +1 -1
- package/bundled-skills/linkerd-patterns/SKILL.md +1 -1
- package/bundled-skills/loki-mode/examples/todo-app-generated/frontend/package-lock.json +504 -1317
- package/bundled-skills/loki-mode/examples/todo-app-generated/frontend/package.json +2 -2
- package/bundled-skills/lovable-cleanup/SKILL.md +416 -0
- package/bundled-skills/monopoly/SKILL.md +397 -0
- package/bundled-skills/monopoly/patterns/SKILL.md +331 -0
- package/bundled-skills/monopoly/scale-benchmarks/SKILL.md +174 -0
- package/bundled-skills/monopoly/security-checklist/SKILL.md +69 -0
- package/bundled-skills/monopoly/tech-matrix/SKILL.md +268 -0
- package/bundled-skills/pagespeed-enhancer/SKILL.md +579 -0
- package/bundled-skills/polis-protocol/SKILL.md +6 -3
- package/bundled-skills/sharp-coder/SKILL.md +131 -0
- package/bundled-skills/unship/SKILL.md +11 -5
- package/bundled-skills/uv-package-manager/resources/implementation-playbook.md +1 -1
- package/bundled-skills/varlock/SKILL.md +2 -2
- package/package.json +1 -1
- package/skills_index.json +314 -4
|
@@ -0,0 +1,751 @@
|
|
|
1
|
+
# Environment Detection Guide
|
|
2
|
+
|
|
3
|
+
This document defines **environment.json** — the environment contract between ecl-harness-engineer and harness-executor — and explains how to detect, collect, and generate environment information for a project.
|
|
4
|
+
|
|
5
|
+
> **Key Insight**: Environment is not just configuration — it's the complete runtime ecosystem including databases, services, secrets, and the **executable scripts** to bring it all up.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. environment.json Overview
|
|
10
|
+
|
|
11
|
+
### 1.1 Purpose
|
|
12
|
+
|
|
13
|
+
| File | Purpose | Consumer |
|
|
14
|
+
|------|---------|----------|
|
|
15
|
+
| `environment.json` | "What the environment is" — full ecosystem description | `preflight.py`, `verifier subagent`, setup scripts |
|
|
16
|
+
|
|
17
|
+
`ecl-harness-engineer` creates `environment.json` only. Runtime verification plans such as
|
|
18
|
+
`verify.json` are generated later by harness-executor or another runtime from `environment.json`
|
|
19
|
+
plus the active task context.
|
|
20
|
+
|
|
21
|
+
### 1.2 Location
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
harness/
|
|
25
|
+
├── config/
|
|
26
|
+
│ └── environment.json # Environment ecosystem contract
|
|
27
|
+
└── scripts/
|
|
28
|
+
├── setup-env.sh # Start dependencies (DB, Redis, etc.)
|
|
29
|
+
├── start-server.sh # Start the application
|
|
30
|
+
├── teardown-env.sh # Stop and cleanup
|
|
31
|
+
└── seed-data.sh # Seed test data
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 1.3 When to Generate
|
|
35
|
+
|
|
36
|
+
| Mode | Trigger |
|
|
37
|
+
|------|---------|
|
|
38
|
+
| **Greenfield** | Always generate (scaffold includes environment.json) |
|
|
39
|
+
| **Create** | Always generate (detected from code analysis) |
|
|
40
|
+
| **Improve** | Generate if missing; audit and update if exists |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 2. environment.json Schema
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"version": "1.0",
|
|
49
|
+
"project_name": "my-project",
|
|
50
|
+
"generated_at": "2026-03-27T10:00:00Z",
|
|
51
|
+
"generated_by": "ecl-harness-engineer",
|
|
52
|
+
|
|
53
|
+
"runtime": {
|
|
54
|
+
"language": "go | typescript | python | java",
|
|
55
|
+
"version": "1.22+ | 20+ | 3.11+ | 21+",
|
|
56
|
+
"package_manager": "npm | pnpm | yarn | pip | poetry | maven | gradle",
|
|
57
|
+
"build_command": "go build ./... | npm run build | ...",
|
|
58
|
+
"dev_command": "go run cmd/server/main.go | npm run dev | ..."
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
"databases": [
|
|
62
|
+
{
|
|
63
|
+
"name": "primary_db",
|
|
64
|
+
"type": "postgres | mysql | mongodb | redis | sqlite",
|
|
65
|
+
"purpose": "Main application data store",
|
|
66
|
+
"required": true,
|
|
67
|
+
"connection": {
|
|
68
|
+
"host_env": "DB_HOST",
|
|
69
|
+
"port_env": "DB_PORT",
|
|
70
|
+
"default_port": 5432,
|
|
71
|
+
"user_env": "DB_USER",
|
|
72
|
+
"password_env": "DB_PASSWORD",
|
|
73
|
+
"database_env": "DB_NAME",
|
|
74
|
+
"url_env": "DATABASE_URL"
|
|
75
|
+
},
|
|
76
|
+
"setup": {
|
|
77
|
+
"docker_image": "postgres:16",
|
|
78
|
+
"docker_compose_service": "postgres",
|
|
79
|
+
"migration_command": "go run cmd/migrate/main.go up",
|
|
80
|
+
"seed_command": "go run cmd/seed/main.go"
|
|
81
|
+
},
|
|
82
|
+
"test_alternatives": {
|
|
83
|
+
"sqlite_in_memory": "DB_DRIVER=sqlite3 DB_URL=:memory:",
|
|
84
|
+
"docker": "docker run -d --name test-pg -p 5433:5432 -e POSTGRES_PASSWORD=test postgres:16"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
|
|
89
|
+
"services": [
|
|
90
|
+
{
|
|
91
|
+
"name": "redis_cache",
|
|
92
|
+
"type": "redis | http | grpc | kafka | rabbitmq | s3",
|
|
93
|
+
"purpose": "Session storage and caching",
|
|
94
|
+
"required": false,
|
|
95
|
+
"connection": {
|
|
96
|
+
"url_env": "REDIS_URL",
|
|
97
|
+
"default_url": "redis://localhost:6379"
|
|
98
|
+
},
|
|
99
|
+
"setup": {
|
|
100
|
+
"docker_image": "redis:7",
|
|
101
|
+
"docker_compose_service": "redis"
|
|
102
|
+
},
|
|
103
|
+
"fallback": "In-memory cache used when Redis unavailable"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "auth_service",
|
|
107
|
+
"type": "http",
|
|
108
|
+
"purpose": "External authentication provider",
|
|
109
|
+
"required": true,
|
|
110
|
+
"connection": {
|
|
111
|
+
"url_env": "AUTH_SERVICE_URL",
|
|
112
|
+
"health_endpoint": "/health"
|
|
113
|
+
},
|
|
114
|
+
"test_alternatives": {
|
|
115
|
+
"mock": "AUTH_SERVICE_URL=http://localhost:9999 (use mock server in test/mock/auth.go)"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
],
|
|
119
|
+
|
|
120
|
+
"secrets": [
|
|
121
|
+
{
|
|
122
|
+
"name": "JWT_SECRET",
|
|
123
|
+
"purpose": "Signs JWT tokens for authentication",
|
|
124
|
+
"required": true,
|
|
125
|
+
"test_value_ok": true,
|
|
126
|
+
"test_value": "test-jwt-secret-not-for-production"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "STRIPE_SECRET_KEY",
|
|
130
|
+
"purpose": "Payment processing",
|
|
131
|
+
"required": false,
|
|
132
|
+
"test_value_ok": false,
|
|
133
|
+
"skip_when_missing": "Payment features disabled in test mode"
|
|
134
|
+
}
|
|
135
|
+
],
|
|
136
|
+
|
|
137
|
+
"ports": [
|
|
138
|
+
{
|
|
139
|
+
"name": "http_server",
|
|
140
|
+
"env": "PORT",
|
|
141
|
+
"default": 8080,
|
|
142
|
+
"test_port": 8081,
|
|
143
|
+
"purpose": "Main HTTP server"
|
|
144
|
+
}
|
|
145
|
+
],
|
|
146
|
+
|
|
147
|
+
"files": {
|
|
148
|
+
"required": [
|
|
149
|
+
{ "path": ".env", "template": ".env.example", "purpose": "Local env config" }
|
|
150
|
+
],
|
|
151
|
+
"generated": [
|
|
152
|
+
{ "path": "internal/generated/schema.go", "command": "go generate ./...", "purpose": "Generated code" }
|
|
153
|
+
]
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
"functional_scenarios": [
|
|
157
|
+
{
|
|
158
|
+
"name": "user_registration_flow",
|
|
159
|
+
"description": "Register a new user, verify data stored, login with credentials",
|
|
160
|
+
"requires": ["primary_db", "JWT_SECRET"],
|
|
161
|
+
"category": "auth",
|
|
162
|
+
"steps_hint": [
|
|
163
|
+
"POST /api/v1/register with valid user data -> 201",
|
|
164
|
+
"GET /api/v1/users/{id} -> 200 with matching data",
|
|
165
|
+
"POST /api/v1/login with same credentials -> 200 with JWT token",
|
|
166
|
+
"GET /api/v1/profile with JWT token -> 200 with user info"
|
|
167
|
+
],
|
|
168
|
+
"priority": "high"
|
|
169
|
+
}
|
|
170
|
+
],
|
|
171
|
+
|
|
172
|
+
"test_environment": {
|
|
173
|
+
"env_vars": {
|
|
174
|
+
"ENV": "test",
|
|
175
|
+
"LOG_LEVEL": "error",
|
|
176
|
+
"PORT": "8081",
|
|
177
|
+
"DB_DRIVER": "sqlite3",
|
|
178
|
+
"DB_URL": ":memory:",
|
|
179
|
+
"JWT_SECRET": "test-jwt-secret-not-for-production"
|
|
180
|
+
},
|
|
181
|
+
"setup_commands": ["go mod download", "go generate ./..."],
|
|
182
|
+
"teardown_commands": []
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
"scripts": {
|
|
186
|
+
"setup_env": "harness/scripts/setup-env.sh",
|
|
187
|
+
"start_server": "harness/scripts/start-server.sh",
|
|
188
|
+
"teardown_env": "harness/scripts/teardown-env.sh",
|
|
189
|
+
"seed_data": "harness/scripts/seed-data.sh"
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 3. Environment Scripts Generation
|
|
197
|
+
|
|
198
|
+
Beyond the JSON configuration, ecl-harness-engineer must generate **executable scripts** that actually bring up the environment.
|
|
199
|
+
|
|
200
|
+
### 3.1 Script Templates
|
|
201
|
+
|
|
202
|
+
#### `harness/scripts/setup-env.sh`
|
|
203
|
+
|
|
204
|
+
Sets up all dependencies (databases, external services) using Docker or local services.
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
#!/bin/bash
|
|
208
|
+
# setup-env.sh - Start all required dependencies for local development
|
|
209
|
+
# Generated by ecl-harness-engineer from environment.json
|
|
210
|
+
set -e
|
|
211
|
+
|
|
212
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
213
|
+
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
|
214
|
+
cd "$PROJECT_ROOT"
|
|
215
|
+
|
|
216
|
+
echo "==> Setting up environment for ${PROJECT_NAME}..."
|
|
217
|
+
|
|
218
|
+
# --- Database: ${DB_NAME} ---
|
|
219
|
+
{{#if databases}}
|
|
220
|
+
{{#each databases}}
|
|
221
|
+
{{#if (eq type "postgres")}}
|
|
222
|
+
if ! docker ps -q -f name={{name}} | grep -q .; then
|
|
223
|
+
echo "Starting PostgreSQL ({{name}})..."
|
|
224
|
+
docker run -d \
|
|
225
|
+
--name {{name}} \
|
|
226
|
+
-p {{connection.default_port}}:5432 \
|
|
227
|
+
-e POSTGRES_USER=${{{connection.user_env}}:-postgres} \
|
|
228
|
+
-e POSTGRES_PASSWORD=${{{connection.password_env}}:-postgres} \
|
|
229
|
+
-e POSTGRES_DB=${{{connection.database_env}}:-{{../project_name}}} \
|
|
230
|
+
{{setup.docker_image}}
|
|
231
|
+
echo "Waiting for PostgreSQL to be ready..."
|
|
232
|
+
sleep 3
|
|
233
|
+
until docker exec {{name}} pg_isready -U postgres > /dev/null 2>&1; do
|
|
234
|
+
sleep 1
|
|
235
|
+
done
|
|
236
|
+
echo "PostgreSQL ready."
|
|
237
|
+
fi
|
|
238
|
+
{{/if}}
|
|
239
|
+
{{#if (eq type "mysql")}}
|
|
240
|
+
if ! docker ps -q -f name={{name}} | grep -q .; then
|
|
241
|
+
echo "Starting MySQL ({{name}})..."
|
|
242
|
+
docker run -d \
|
|
243
|
+
--name {{name}} \
|
|
244
|
+
-p {{connection.default_port}}:3306 \
|
|
245
|
+
-e MYSQL_ROOT_PASSWORD=${{{connection.password_env}}:-root} \
|
|
246
|
+
-e MYSQL_DATABASE=${{{connection.database_env}}:-{{../project_name}}} \
|
|
247
|
+
{{setup.docker_image}}
|
|
248
|
+
echo "Waiting for MySQL to be ready..."
|
|
249
|
+
sleep 5
|
|
250
|
+
until docker exec {{name}} mysqladmin ping -h localhost --silent; do
|
|
251
|
+
sleep 1
|
|
252
|
+
done
|
|
253
|
+
echo "MySQL ready."
|
|
254
|
+
fi
|
|
255
|
+
{{/if}}
|
|
256
|
+
{{/each}}
|
|
257
|
+
{{/if}}
|
|
258
|
+
|
|
259
|
+
# --- Services ---
|
|
260
|
+
{{#if services}}
|
|
261
|
+
{{#each services}}
|
|
262
|
+
{{#if (eq type "redis")}}
|
|
263
|
+
if ! docker ps -q -f name={{name}} | grep -q .; then
|
|
264
|
+
echo "Starting Redis ({{name}})..."
|
|
265
|
+
docker run -d --name {{name}} -p 6379:6379 {{setup.docker_image}}
|
|
266
|
+
echo "Redis started."
|
|
267
|
+
fi
|
|
268
|
+
{{/if}}
|
|
269
|
+
{{/each}}
|
|
270
|
+
{{/if}}
|
|
271
|
+
|
|
272
|
+
# --- Run migrations ---
|
|
273
|
+
{{#if databases}}
|
|
274
|
+
{{#each databases}}
|
|
275
|
+
{{#if setup.migration_command}}
|
|
276
|
+
echo "Running migrations for {{name}}..."
|
|
277
|
+
{{setup.migration_command}}
|
|
278
|
+
{{/if}}
|
|
279
|
+
{{/each}}
|
|
280
|
+
{{/if}}
|
|
281
|
+
|
|
282
|
+
echo "==> Environment setup complete!"
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
#### `harness/scripts/start-server.sh`
|
|
286
|
+
|
|
287
|
+
Starts the application with the correct environment variables.
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
#!/bin/bash
|
|
291
|
+
# start-server.sh - Start the application server
|
|
292
|
+
# Generated by ecl-harness-engineer from environment.json
|
|
293
|
+
set -e
|
|
294
|
+
|
|
295
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
296
|
+
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
|
297
|
+
cd "$PROJECT_ROOT"
|
|
298
|
+
|
|
299
|
+
# Load .env if exists
|
|
300
|
+
if [ -f .env ]; then
|
|
301
|
+
export $(grep -v '^#' .env | xargs)
|
|
302
|
+
fi
|
|
303
|
+
|
|
304
|
+
# Set defaults from environment.json
|
|
305
|
+
{{#each test_environment.env_vars}}
|
|
306
|
+
export {{@key}}=${{{@key}}:-{{this}}}
|
|
307
|
+
{{/each}}
|
|
308
|
+
|
|
309
|
+
# Build if needed
|
|
310
|
+
{{#if runtime.build_command}}
|
|
311
|
+
echo "Building..."
|
|
312
|
+
{{runtime.build_command}}
|
|
313
|
+
{{/if}}
|
|
314
|
+
|
|
315
|
+
# Start the server
|
|
316
|
+
echo "Starting server on port ${PORT:-8080}..."
|
|
317
|
+
{{runtime.dev_command}}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### `harness/scripts/teardown-env.sh`
|
|
321
|
+
|
|
322
|
+
Stops and cleans up all dependencies.
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
#!/bin/bash
|
|
326
|
+
# teardown-env.sh - Stop and cleanup environment
|
|
327
|
+
# Generated by ecl-harness-engineer from environment.json
|
|
328
|
+
set -e
|
|
329
|
+
|
|
330
|
+
echo "==> Tearing down environment..."
|
|
331
|
+
|
|
332
|
+
{{#if databases}}
|
|
333
|
+
{{#each databases}}
|
|
334
|
+
docker stop {{name}} 2>/dev/null || true
|
|
335
|
+
docker rm {{name}} 2>/dev/null || true
|
|
336
|
+
{{/each}}
|
|
337
|
+
{{/if}}
|
|
338
|
+
|
|
339
|
+
{{#if services}}
|
|
340
|
+
{{#each services}}
|
|
341
|
+
{{#if setup.docker_image}}
|
|
342
|
+
docker stop {{name}} 2>/dev/null || true
|
|
343
|
+
docker rm {{name}} 2>/dev/null || true
|
|
344
|
+
{{/if}}
|
|
345
|
+
{{/each}}
|
|
346
|
+
{{/if}}
|
|
347
|
+
|
|
348
|
+
echo "==> Teardown complete."
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
#### `harness/scripts/seed-data.sh`
|
|
352
|
+
|
|
353
|
+
Seeds the database with test data.
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
#!/bin/bash
|
|
357
|
+
# seed-data.sh - Seed database with test data
|
|
358
|
+
# Generated by ecl-harness-engineer from environment.json
|
|
359
|
+
set -e
|
|
360
|
+
|
|
361
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
362
|
+
PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
|
363
|
+
cd "$PROJECT_ROOT"
|
|
364
|
+
|
|
365
|
+
{{#if databases}}
|
|
366
|
+
{{#each databases}}
|
|
367
|
+
{{#if setup.seed_command}}
|
|
368
|
+
echo "Seeding {{name}}..."
|
|
369
|
+
{{setup.seed_command}}
|
|
370
|
+
{{/if}}
|
|
371
|
+
{{/each}}
|
|
372
|
+
{{/if}}
|
|
373
|
+
|
|
374
|
+
echo "==> Seeding complete."
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### 3.2 When to Generate Scripts
|
|
378
|
+
|
|
379
|
+
| Scenario | Generate Scripts? |
|
|
380
|
+
|----------|-------------------|
|
|
381
|
+
| Greenfield mode | Yes, always (part of scaffold) |
|
|
382
|
+
| Create mode with detected DB/services | Yes |
|
|
383
|
+
| Create mode with no dependencies | Minimal (just start-server.sh) |
|
|
384
|
+
| Improve mode, scripts missing | Yes, if dependencies detected |
|
|
385
|
+
| Improve mode, scripts exist | Keep existing, suggest updates if outdated |
|
|
386
|
+
|
|
387
|
+
### 3.3 Script vs docker-compose.yml
|
|
388
|
+
|
|
389
|
+
If project already has `docker-compose.yml`:
|
|
390
|
+
- **Do not generate duplicate scripts** that replicate docker-compose functionality
|
|
391
|
+
- Instead, generate thin wrapper scripts that call `docker-compose up -d` etc.
|
|
392
|
+
- Reference the docker-compose service names in environment.json
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
# setup-env.sh when docker-compose.yml exists
|
|
396
|
+
#!/bin/bash
|
|
397
|
+
set -e
|
|
398
|
+
docker-compose up -d postgres redis
|
|
399
|
+
echo "Waiting for services..."
|
|
400
|
+
sleep 5
|
|
401
|
+
docker-compose exec postgres pg_isready
|
|
402
|
+
echo "Services ready."
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## 4. Environment Detection Strategies
|
|
408
|
+
|
|
409
|
+
### 4.1 Code Dependency Analysis
|
|
410
|
+
|
|
411
|
+
Scan dependency files to detect what the project uses:
|
|
412
|
+
|
|
413
|
+
| Pattern | Detection | Implies |
|
|
414
|
+
|---------|-----------|---------|
|
|
415
|
+
| `go.mod`: `github.com/lib/pq`, `github.com/jackc/pgx` | PostgreSQL | Database, connection env vars |
|
|
416
|
+
| `go.mod`: `github.com/go-redis/redis` | Redis | Cache service |
|
|
417
|
+
| `package.json`: `pg`, `mysql2`, `mongoose` | DB drivers | Database dependencies |
|
|
418
|
+
| `package.json`: `@aws-sdk/*` | AWS services | Cloud service credentials |
|
|
419
|
+
| `requirements.txt`: `psycopg2`, `sqlalchemy` | PostgreSQL | Database |
|
|
420
|
+
| `requirements.txt`: `boto3` | AWS | Cloud credentials |
|
|
421
|
+
|
|
422
|
+
**Go detection patterns:**
|
|
423
|
+
```go
|
|
424
|
+
// Scan import statements
|
|
425
|
+
"github.com/lib/pq" // PostgreSQL
|
|
426
|
+
"github.com/jackc/pgx" // PostgreSQL
|
|
427
|
+
"github.com/go-sql-driver/mysql" // MySQL
|
|
428
|
+
"go.mongodb.org/mongo-driver" // MongoDB
|
|
429
|
+
"github.com/go-redis/redis" // Redis
|
|
430
|
+
"github.com/nats-io/nats.go" // NATS
|
|
431
|
+
"github.com/segmentio/kafka-go" // Kafka
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
**TypeScript/JavaScript patterns:**
|
|
435
|
+
```javascript
|
|
436
|
+
// package.json dependencies
|
|
437
|
+
"pg" // PostgreSQL
|
|
438
|
+
"mysql2" // MySQL
|
|
439
|
+
"mongodb" // MongoDB
|
|
440
|
+
"ioredis" // Redis
|
|
441
|
+
"kafkajs" // Kafka
|
|
442
|
+
"@aws-sdk/*" // AWS services
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
**Python patterns:**
|
|
446
|
+
```python
|
|
447
|
+
# requirements.txt or pyproject.toml
|
|
448
|
+
psycopg2 # PostgreSQL
|
|
449
|
+
mysql-connector-python # MySQL
|
|
450
|
+
pymongo # MongoDB
|
|
451
|
+
redis # Redis
|
|
452
|
+
boto3 # AWS
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### 4.2 Environment Variable Collection
|
|
456
|
+
|
|
457
|
+
Scan code for all environment variable references:
|
|
458
|
+
|
|
459
|
+
```go
|
|
460
|
+
// Go
|
|
461
|
+
os.Getenv("DB_HOST")
|
|
462
|
+
os.LookupEnv("REDIS_URL")
|
|
463
|
+
viper.GetString("jwt.secret") // with config binding
|
|
464
|
+
|
|
465
|
+
// TypeScript
|
|
466
|
+
process.env.DB_HOST
|
|
467
|
+
config.get('database.url')
|
|
468
|
+
|
|
469
|
+
// Python
|
|
470
|
+
os.environ.get("DB_HOST")
|
|
471
|
+
os.getenv("REDIS_URL")
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
Also check:
|
|
475
|
+
- `.env.example` / `.env.template` for expected variables
|
|
476
|
+
- Config struct definitions (Go struct tags, TypeScript interfaces)
|
|
477
|
+
- README mentions of required environment variables
|
|
478
|
+
|
|
479
|
+
### 4.3 Functional Scenario Inference
|
|
480
|
+
|
|
481
|
+
Analyze routes to infer functional scenarios:
|
|
482
|
+
|
|
483
|
+
**Route patterns → Scenarios:**
|
|
484
|
+
|
|
485
|
+
| Detected Routes | Inferred Scenario |
|
|
486
|
+
|-----------------|-------------------|
|
|
487
|
+
| `POST /register`, `POST /login`, `GET /profile` | `user_auth_flow` |
|
|
488
|
+
| `POST /users`, `GET /users/:id`, `PUT /users/:id`, `DELETE /users/:id` | `user_crud` |
|
|
489
|
+
| `POST /orders`, `GET /orders`, middleware `auth` | `authenticated_orders_flow` |
|
|
490
|
+
| `GET /health`, `GET /ready` | `health_check` (always include) |
|
|
491
|
+
|
|
492
|
+
**Middleware analysis:**
|
|
493
|
+
- Auth middleware on routes → scenario needs authentication first
|
|
494
|
+
- Rate limit middleware → include rate limit boundary test
|
|
495
|
+
|
|
496
|
+
**Data model analysis:**
|
|
497
|
+
- User model with password field → auth scenarios
|
|
498
|
+
- Relations (User has Orders) → relational query scenarios
|
|
499
|
+
|
|
500
|
+
### 4.4 Docker/K8s Manifest Analysis
|
|
501
|
+
|
|
502
|
+
If `docker-compose.yml` or Kubernetes manifests exist:
|
|
503
|
+
|
|
504
|
+
```yaml
|
|
505
|
+
# docker-compose.yml
|
|
506
|
+
services:
|
|
507
|
+
postgres:
|
|
508
|
+
image: postgres:16
|
|
509
|
+
ports:
|
|
510
|
+
- "5432:5432"
|
|
511
|
+
environment:
|
|
512
|
+
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
Extract:
|
|
516
|
+
- Service names → `databases[].setup.docker_compose_service`
|
|
517
|
+
- Images → `databases[].setup.docker_image`
|
|
518
|
+
- Port mappings → `databases[].connection.default_port`
|
|
519
|
+
- Environment variables → `databases[].connection.*_env`
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
## 5. Security Guidelines
|
|
524
|
+
|
|
525
|
+
### 5.1 Never Hardcode Secrets
|
|
526
|
+
|
|
527
|
+
```json
|
|
528
|
+
// WRONG - never do this
|
|
529
|
+
"secrets": [{ "value": "sk-abc123..." }]
|
|
530
|
+
|
|
531
|
+
// CORRECT - reference via environment variable
|
|
532
|
+
"secrets": [{ "name": "API_KEY", "purpose": "..." }]
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
### 5.2 Test Values
|
|
536
|
+
|
|
537
|
+
Only allow `test_value` for secrets that are:
|
|
538
|
+
- Self-contained (JWT signing key with no external dependency)
|
|
539
|
+
- Clearly marked as test-only
|
|
540
|
+
|
|
541
|
+
```json
|
|
542
|
+
{
|
|
543
|
+
"name": "JWT_SECRET",
|
|
544
|
+
"test_value_ok": true,
|
|
545
|
+
"test_value": "test-jwt-secret-not-for-production"
|
|
546
|
+
}
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
### 5.3 Sensitive Patterns
|
|
550
|
+
|
|
551
|
+
Detect and warn about:
|
|
552
|
+
- API keys: `sk-`, `pk-`, `api_`, `token_`
|
|
553
|
+
- Connection strings with passwords
|
|
554
|
+
- Private keys (RSA, EC)
|
|
555
|
+
|
|
556
|
+
When detected, prompt user to confirm before including in environment.json.
|
|
557
|
+
|
|
558
|
+
---
|
|
559
|
+
|
|
560
|
+
## 6. Integration with harness-executor
|
|
561
|
+
|
|
562
|
+
### 6.1 Relationship
|
|
563
|
+
|
|
564
|
+
ecl-harness-engineer generates `environment.json` to describe the runtime ecosystem. harness-executor consumes it at task runtime to dynamically generate `verify.json` for verification.
|
|
565
|
+
|
|
566
|
+
```
|
|
567
|
+
environment.json (ecl-harness-engineer) verify.json (harness-executor, runtime)
|
|
568
|
+
════════════════════════════════════ ═══════════════════════════════════════
|
|
569
|
+
databases[] prerequisites.database_checks[]
|
|
570
|
+
└─ auto-derived ─────────────────► (TCP connectivity)
|
|
571
|
+
|
|
572
|
+
services[] prerequisites.service_checks[]
|
|
573
|
+
└─ auto-derived ─────────────────► (HTTP health, TCP)
|
|
574
|
+
|
|
575
|
+
secrets[] prerequisites.env_checks[]
|
|
576
|
+
└─ auto-derived ─────────────────► (required env vars)
|
|
577
|
+
|
|
578
|
+
ports[] prerequisites.port_checks[]
|
|
579
|
+
└─ auto-derived ─────────────────► (port availability)
|
|
580
|
+
|
|
581
|
+
functional_scenarios[] (not in verify.json)
|
|
582
|
+
└─ consumed by ──────────────────► verifier subagent
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
> **Note**: ecl-harness-engineer does NOT generate `verify.json`. It only provides `environment.json` as the foundation. harness-executor dynamically generates `verify.json` at task runtime based on environment.json + task context.
|
|
586
|
+
|
|
587
|
+
### 6.2 Auto-Derivation Rules
|
|
588
|
+
|
|
589
|
+
When harness-executor generates `verify.json`, it automatically derives `prerequisites` from `environment.json`:
|
|
590
|
+
|
|
591
|
+
```python
|
|
592
|
+
def derive_prerequisites(env_config):
|
|
593
|
+
prereqs = {"database_checks": [], "service_checks": [], ...}
|
|
594
|
+
|
|
595
|
+
for db in env_config.get("databases", []):
|
|
596
|
+
if db["required"]:
|
|
597
|
+
prereqs["database_checks"].append({
|
|
598
|
+
"type": db["type"],
|
|
599
|
+
"host_env": db["connection"].get("host_env", "localhost"),
|
|
600
|
+
"port": db["connection"].get("default_port")
|
|
601
|
+
})
|
|
602
|
+
|
|
603
|
+
for svc in env_config.get("services", []):
|
|
604
|
+
if svc["required"]:
|
|
605
|
+
prereqs["service_checks"].append({
|
|
606
|
+
"type": svc["type"],
|
|
607
|
+
"url_env": svc["connection"].get("url_env"),
|
|
608
|
+
"health_endpoint": svc["connection"].get("health_endpoint")
|
|
609
|
+
})
|
|
610
|
+
|
|
611
|
+
for secret in env_config.get("secrets", []):
|
|
612
|
+
if secret["required"]:
|
|
613
|
+
prereqs["env_checks"].append({
|
|
614
|
+
"name": secret["name"],
|
|
615
|
+
"required": True
|
|
616
|
+
})
|
|
617
|
+
|
|
618
|
+
return prereqs
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
---
|
|
622
|
+
|
|
623
|
+
## 7. Checklist for Modes
|
|
624
|
+
|
|
625
|
+
### 7.1 Greenfield Mode
|
|
626
|
+
|
|
627
|
+
- [ ] Generate `environment.json` with detected/default values
|
|
628
|
+
- [ ] Generate all four scripts (setup-env, start-server, teardown-env, seed-data)
|
|
629
|
+
- [ ] Include at least `health_check` functional scenario
|
|
630
|
+
- [ ] Set up `test_environment` with safe defaults
|
|
631
|
+
|
|
632
|
+
### 7.2 Create Mode
|
|
633
|
+
|
|
634
|
+
- [ ] Analyze codebase for dependencies (Section 4.1)
|
|
635
|
+
- [ ] Collect all environment variables (Section 4.2)
|
|
636
|
+
- [ ] Infer functional scenarios from routes (Section 4.3)
|
|
637
|
+
- [ ] Check existing docker-compose.yml (Section 4.4)
|
|
638
|
+
- [ ] Generate `environment.json`
|
|
639
|
+
- [ ] Generate scripts (or thin wrappers if docker-compose exists)
|
|
640
|
+
- [ ] Validate security (no hardcoded secrets)
|
|
641
|
+
|
|
642
|
+
### 7.3 Improve Mode
|
|
643
|
+
|
|
644
|
+
- [ ] Check if `environment.json` exists
|
|
645
|
+
- If missing: run Create mode detection and generate
|
|
646
|
+
- If exists: audit for completeness
|
|
647
|
+
- [ ] Audit checklist:
|
|
648
|
+
- [ ] All detected DB drivers have corresponding `databases[]` entry
|
|
649
|
+
- [ ] All required env vars from code are in `secrets[]` or `test_environment`
|
|
650
|
+
- [ ] `functional_scenarios[]` covers main user flows
|
|
651
|
+
- [ ] Scripts exist and are executable
|
|
652
|
+
- [ ] Scripts match `environment.json` (not outdated)
|
|
653
|
+
- [ ] Generate missing components
|
|
654
|
+
- [ ] Update outdated components
|
|
655
|
+
|
|
656
|
+
---
|
|
657
|
+
|
|
658
|
+
## 8. Example: Complete Go Web API
|
|
659
|
+
|
|
660
|
+
Given a Go web API with PostgreSQL and Redis:
|
|
661
|
+
|
|
662
|
+
**Detected from code:**
|
|
663
|
+
- `go.mod`: `github.com/jackc/pgx/v5`, `github.com/go-redis/redis/v9`
|
|
664
|
+
- Env vars: `DATABASE_URL`, `REDIS_URL`, `JWT_SECRET`, `PORT`
|
|
665
|
+
- Routes: `/api/v1/register`, `/api/v1/login`, `/api/v1/users/:id`, `/health`
|
|
666
|
+
- Auth middleware on `/api/v1/users/:id`
|
|
667
|
+
|
|
668
|
+
**Generated environment.json:**
|
|
669
|
+
```json
|
|
670
|
+
{
|
|
671
|
+
"version": "1.0",
|
|
672
|
+
"project_name": "my-api",
|
|
673
|
+
"runtime": {
|
|
674
|
+
"language": "go",
|
|
675
|
+
"version": "1.22+",
|
|
676
|
+
"build_command": "go build -o bin/server ./cmd/server",
|
|
677
|
+
"dev_command": "go run ./cmd/server"
|
|
678
|
+
},
|
|
679
|
+
"databases": [{
|
|
680
|
+
"name": "primary_db",
|
|
681
|
+
"type": "postgres",
|
|
682
|
+
"purpose": "Main application database",
|
|
683
|
+
"required": true,
|
|
684
|
+
"connection": {
|
|
685
|
+
"url_env": "DATABASE_URL",
|
|
686
|
+
"default_port": 5432
|
|
687
|
+
},
|
|
688
|
+
"setup": {
|
|
689
|
+
"docker_image": "postgres:16",
|
|
690
|
+
"migration_command": "go run ./cmd/migrate up"
|
|
691
|
+
}
|
|
692
|
+
}],
|
|
693
|
+
"services": [{
|
|
694
|
+
"name": "cache",
|
|
695
|
+
"type": "redis",
|
|
696
|
+
"purpose": "Session and cache storage",
|
|
697
|
+
"required": false,
|
|
698
|
+
"connection": { "url_env": "REDIS_URL" },
|
|
699
|
+
"setup": { "docker_image": "redis:7" },
|
|
700
|
+
"fallback": "In-memory cache when Redis unavailable"
|
|
701
|
+
}],
|
|
702
|
+
"secrets": [{
|
|
703
|
+
"name": "JWT_SECRET",
|
|
704
|
+
"purpose": "JWT token signing",
|
|
705
|
+
"required": true,
|
|
706
|
+
"test_value_ok": true,
|
|
707
|
+
"test_value": "test-secret-do-not-use-in-production"
|
|
708
|
+
}],
|
|
709
|
+
"ports": [{
|
|
710
|
+
"name": "http_server",
|
|
711
|
+
"env": "PORT",
|
|
712
|
+
"default": 8080,
|
|
713
|
+
"test_port": 8081
|
|
714
|
+
}],
|
|
715
|
+
"functional_scenarios": [
|
|
716
|
+
{
|
|
717
|
+
"name": "user_auth_flow",
|
|
718
|
+
"description": "Register, login, access protected resource",
|
|
719
|
+
"requires": ["primary_db", "JWT_SECRET"],
|
|
720
|
+
"category": "auth",
|
|
721
|
+
"steps_hint": [
|
|
722
|
+
"POST /api/v1/register -> 201",
|
|
723
|
+
"POST /api/v1/login -> 200 with token",
|
|
724
|
+
"GET /api/v1/users/{id} with token -> 200"
|
|
725
|
+
],
|
|
726
|
+
"priority": "high"
|
|
727
|
+
},
|
|
728
|
+
{
|
|
729
|
+
"name": "health_check",
|
|
730
|
+
"description": "Basic health and readiness",
|
|
731
|
+
"requires": [],
|
|
732
|
+
"category": "infra",
|
|
733
|
+
"steps_hint": ["GET /health -> 200"],
|
|
734
|
+
"priority": "high"
|
|
735
|
+
}
|
|
736
|
+
],
|
|
737
|
+
"test_environment": {
|
|
738
|
+
"env_vars": {
|
|
739
|
+
"ENV": "test",
|
|
740
|
+
"PORT": "8081",
|
|
741
|
+
"DATABASE_URL": "postgres://postgres:postgres@localhost:5432/testdb?sslmode=disable",
|
|
742
|
+
"JWT_SECRET": "test-secret-do-not-use-in-production"
|
|
743
|
+
}
|
|
744
|
+
},
|
|
745
|
+
"scripts": {
|
|
746
|
+
"setup_env": "harness/scripts/setup-env.sh",
|
|
747
|
+
"start_server": "harness/scripts/start-server.sh",
|
|
748
|
+
"teardown_env": "harness/scripts/teardown-env.sh"
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
```
|