ctx-cc 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -12
- package/agents/ctx-debugger.md +39 -12
- package/agents/ctx-planner.md +53 -26
- package/agents/ctx-researcher.md +36 -23
- package/agents/ctx-verifier.md +103 -45
- package/bin/ctx.js +3 -3
- package/commands/help.md +64 -12
- package/commands/init.md +185 -9
- package/commands/plan.md +63 -31
- package/commands/verify.md +67 -17
- package/package.json +2 -2
- package/src/install.js +3 -3
- package/templates/PRD.json +77 -0
- package/templates/STATE.md +12 -2
- package/templates/ctx.gitignore +19 -0
- package/templates/env.template +61 -0
package/commands/plan.md
CHANGED
|
@@ -1,73 +1,104 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ctx:plan
|
|
3
|
-
description: Force research + planning phase
|
|
4
|
-
args:
|
|
3
|
+
description: Force research + planning phase for current PRD story
|
|
4
|
+
args: story_id (optional - specific story to plan, defaults to current)
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
<objective>
|
|
8
|
-
Force enter planning mode
|
|
9
|
-
|
|
8
|
+
Force enter planning mode for a PRD story. Reads acceptance criteria from PRD.json,
|
|
9
|
+
runs research (ArguSeek + ChunkHound), and creates atomic plan to satisfy the story.
|
|
10
10
|
</objective>
|
|
11
11
|
|
|
12
12
|
<usage>
|
|
13
13
|
```
|
|
14
|
-
/ctx plan
|
|
15
|
-
/ctx plan
|
|
14
|
+
/ctx plan # Plan for current story (from PRD.json)
|
|
15
|
+
/ctx plan S003 # Plan for specific story
|
|
16
16
|
```
|
|
17
17
|
</usage>
|
|
18
18
|
|
|
19
19
|
<workflow>
|
|
20
20
|
## Step 1: Validate Project
|
|
21
|
-
If `.ctx/STATE.md` doesn't exist:
|
|
21
|
+
If `.ctx/STATE.md` or `.ctx/PRD.json` doesn't exist:
|
|
22
22
|
- Error: "No project found. Run /ctx init first."
|
|
23
23
|
|
|
24
|
-
## Step 2:
|
|
25
|
-
|
|
26
|
-
- Use provided goal
|
|
27
|
-
- Create new phase if needed
|
|
24
|
+
## Step 2: Load Story from PRD
|
|
25
|
+
Read `.ctx/PRD.json`:
|
|
28
26
|
|
|
29
|
-
If
|
|
30
|
-
-
|
|
31
|
-
-
|
|
27
|
+
If story_id argument provided:
|
|
28
|
+
- Find story with matching id
|
|
29
|
+
- Error if not found
|
|
30
|
+
|
|
31
|
+
If no argument:
|
|
32
|
+
- Use `metadata.currentStory` from PRD.json
|
|
33
|
+
- If null, use first story where `passes: false`
|
|
34
|
+
|
|
35
|
+
**Story data provides:**
|
|
36
|
+
- `title` → Phase goal
|
|
37
|
+
- `description` → Context for research
|
|
38
|
+
- `acceptanceCriteria` → Verification checklist
|
|
32
39
|
|
|
33
40
|
## Step 3: Research Phase
|
|
34
|
-
Spawn **ctx-researcher** agent:
|
|
41
|
+
Spawn **ctx-researcher** agent with story context:
|
|
35
42
|
|
|
36
43
|
1. **ArguSeek Research**
|
|
37
|
-
- Best practices for goal
|
|
44
|
+
- Best practices for story goal
|
|
38
45
|
- Security considerations
|
|
39
|
-
- Common pitfalls
|
|
46
|
+
- Common pitfalls for acceptance criteria
|
|
40
47
|
- Performance patterns
|
|
41
48
|
|
|
42
49
|
2. **ChunkHound Analysis** (if available)
|
|
43
|
-
- Semantic search for related code
|
|
50
|
+
- Semantic search for story-related code
|
|
44
51
|
- Pattern detection
|
|
45
52
|
- Entry point mapping
|
|
46
53
|
|
|
47
|
-
3. **Output**: `.ctx/phases/{
|
|
54
|
+
3. **Output**: `.ctx/phases/{story_id}/RESEARCH.md`
|
|
48
55
|
|
|
49
56
|
## Step 4: Planning Phase
|
|
50
57
|
Spawn **ctx-planner** agent:
|
|
51
58
|
|
|
52
59
|
1. Read RESEARCH.md
|
|
53
|
-
2.
|
|
60
|
+
2. Map acceptance criteria to verification steps
|
|
54
61
|
3. Break into **2-3 atomic tasks** (strict limit)
|
|
55
|
-
4.
|
|
56
|
-
|
|
57
|
-
|
|
62
|
+
4. Each task contributes to passing acceptance criteria
|
|
63
|
+
5. Assign execution order
|
|
64
|
+
|
|
65
|
+
Output: `.ctx/phases/{story_id}/PLAN.md`
|
|
66
|
+
|
|
67
|
+
**Plan Format:**
|
|
68
|
+
```yaml
|
|
69
|
+
story: S001
|
|
70
|
+
title: "{{story_title}}"
|
|
71
|
+
acceptanceCriteria:
|
|
72
|
+
- criterion: "{{criterion_1}}"
|
|
73
|
+
tasks: [1]
|
|
74
|
+
- criterion: "{{criterion_2}}"
|
|
75
|
+
tasks: [1, 2]
|
|
76
|
+
tasks:
|
|
77
|
+
- id: 1
|
|
78
|
+
title: "{{task_title}}"
|
|
79
|
+
criteria: ["{{criterion_1}}", "{{criterion_2}}"]
|
|
80
|
+
```
|
|
58
81
|
|
|
59
82
|
## Step 5: Update State
|
|
60
83
|
Update STATE.md:
|
|
61
84
|
- Status: "executing"
|
|
62
|
-
- Current
|
|
63
|
-
- Phase goal: {
|
|
85
|
+
- Current Story: {story_id} - {title}
|
|
86
|
+
- Phase goal: {story_title}
|
|
64
87
|
- Total tasks: {count}
|
|
65
88
|
- Completed: 0
|
|
89
|
+
|
|
90
|
+
Update PRD.json:
|
|
91
|
+
- `metadata.currentStory`: {story_id}
|
|
66
92
|
</workflow>
|
|
67
93
|
|
|
68
94
|
<output_format>
|
|
69
95
|
```
|
|
70
|
-
[CTX Plan]
|
|
96
|
+
[CTX Plan] Story: {story_id} - {title}
|
|
97
|
+
|
|
98
|
+
Acceptance Criteria:
|
|
99
|
+
✓ {criterion_1}
|
|
100
|
+
✓ {criterion_2}
|
|
101
|
+
✓ {criterion_3}
|
|
71
102
|
|
|
72
103
|
Research:
|
|
73
104
|
ArguSeek: {n} findings
|
|
@@ -75,12 +106,11 @@ Research:
|
|
|
75
106
|
|
|
76
107
|
Plan Created:
|
|
77
108
|
Tasks: {count} (atomic)
|
|
78
|
-
Files: .ctx/phases/{
|
|
109
|
+
Files: .ctx/phases/{story_id}/PLAN.md
|
|
79
110
|
|
|
80
111
|
Tasks:
|
|
81
|
-
1. {task_1_title}
|
|
82
|
-
2. {task_2_title}
|
|
83
|
-
3. {task_3_title} (if exists)
|
|
112
|
+
1. {task_1_title} → [criteria 1, 2]
|
|
113
|
+
2. {task_2_title} → [criteria 2, 3]
|
|
84
114
|
|
|
85
115
|
Ready to execute. Run /ctx to start.
|
|
86
116
|
```
|
|
@@ -88,6 +118,8 @@ Ready to execute. Run /ctx to start.
|
|
|
88
118
|
|
|
89
119
|
<guardrails>
|
|
90
120
|
- Plans are ALWAYS atomic: 2-3 tasks maximum
|
|
91
|
-
-
|
|
121
|
+
- Each task must map to at least one acceptance criterion
|
|
122
|
+
- If story requires more tasks, ask user to split into smaller stories
|
|
92
123
|
- Research runs even if ChunkHound unavailable (ArguSeek only)
|
|
124
|
+
- Story acceptance criteria = verification checklist
|
|
93
125
|
</guardrails>
|
package/commands/verify.md
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ctx:verify
|
|
3
|
-
description: Force
|
|
3
|
+
description: Force verification of current story against PRD acceptance criteria
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
<objective>
|
|
7
|
-
|
|
8
|
-
Use when you want to verify work before smart router would normally trigger it.
|
|
7
|
+
Verify current story against PRD.json acceptance criteria. Runs three-level check + anti-pattern scan + browser verification. On success, marks story as `passes: true` in PRD.json.
|
|
9
8
|
</objective>
|
|
10
9
|
|
|
11
10
|
<usage>
|
|
@@ -17,17 +16,21 @@ Use when you want to verify work before smart router would normally trigger it.
|
|
|
17
16
|
|
|
18
17
|
<workflow>
|
|
19
18
|
## Step 1: Validate Project
|
|
20
|
-
If `.ctx/STATE.md` doesn't exist:
|
|
19
|
+
If `.ctx/STATE.md` or `.ctx/PRD.json` doesn't exist:
|
|
21
20
|
- Error: "No project found. Run /ctx init first."
|
|
22
21
|
|
|
23
|
-
If no current
|
|
24
|
-
-
|
|
22
|
+
If no current story (all `passes: true`):
|
|
23
|
+
- Info: "All stories verified! PRD complete."
|
|
25
24
|
|
|
26
25
|
## Step 2: Load Context
|
|
27
26
|
Read:
|
|
27
|
+
- `.ctx/PRD.json` - current story and acceptance criteria
|
|
28
28
|
- `.ctx/STATE.md` - current state
|
|
29
|
-
- `.ctx/phases/{
|
|
30
|
-
|
|
29
|
+
- `.ctx/phases/{story_id}/PLAN.md` - task-to-criteria mapping
|
|
30
|
+
|
|
31
|
+
**Key data:**
|
|
32
|
+
- `story.acceptanceCriteria` → What to verify
|
|
33
|
+
- `plan.tasks[].criteria` → How tasks map to criteria
|
|
31
34
|
|
|
32
35
|
## Step 3: Three-Level Verification
|
|
33
36
|
Spawn **ctx-verifier** agent:
|
|
@@ -75,18 +78,61 @@ If phase involves UI or `--browser` flag:
|
|
|
75
78
|
4. Take screenshot proof
|
|
76
79
|
5. Save to `.ctx/verify/phase-{id}.png`
|
|
77
80
|
|
|
78
|
-
## Step 6:
|
|
79
|
-
|
|
81
|
+
## Step 6: Verify Acceptance Criteria
|
|
82
|
+
For each criterion in story.acceptanceCriteria:
|
|
83
|
+
- Check if criterion is satisfied
|
|
84
|
+
- Map to three-level results
|
|
85
|
+
- Document evidence
|
|
86
|
+
|
|
87
|
+
## Step 7: Generate Report
|
|
88
|
+
Write `.ctx/phases/{story_id}/VERIFY.md`:
|
|
89
|
+
```yaml
|
|
90
|
+
story: S001
|
|
91
|
+
title: "{{story_title}}"
|
|
92
|
+
result: PASS|FAIL
|
|
93
|
+
criteria:
|
|
94
|
+
- criterion: "{{criterion_1}}"
|
|
95
|
+
status: PASS|FAIL
|
|
96
|
+
evidence: "{{what proved it}}"
|
|
97
|
+
- criterion: "{{criterion_2}}"
|
|
98
|
+
status: PASS|FAIL
|
|
99
|
+
evidence: "{{what proved it}}"
|
|
100
|
+
timestamp: "{{ISO8601}}"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Step 8: Update PRD.json
|
|
104
|
+
If ALL criteria pass:
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"stories[current].passes": true,
|
|
108
|
+
"stories[current].verifiedAt": "{{timestamp}}",
|
|
109
|
+
"metadata.passedStories": "{{increment}}",
|
|
110
|
+
"metadata.currentStory": "{{next_unpassed_story_id or null}}"
|
|
111
|
+
}
|
|
112
|
+
```
|
|
80
113
|
|
|
81
|
-
|
|
114
|
+
If ANY criterion fails:
|
|
115
|
+
- Keep `passes: false`
|
|
116
|
+
- Add failure notes to `stories[current].notes`
|
|
117
|
+
|
|
118
|
+
## Step 9: Update STATE.md
|
|
82
119
|
Based on results:
|
|
83
|
-
- **PASS**:
|
|
84
|
-
-
|
|
120
|
+
- **PASS**:
|
|
121
|
+
- Set status to "initializing" for next story
|
|
122
|
+
- Update current story reference
|
|
123
|
+
- **FAIL**:
|
|
124
|
+
- Create fix tasks
|
|
125
|
+
- Set status = "debugging" or "executing"
|
|
85
126
|
</workflow>
|
|
86
127
|
|
|
87
128
|
<output_format>
|
|
88
129
|
```
|
|
89
|
-
[CTX Verify]
|
|
130
|
+
[CTX Verify] Story: {story_id} - {title}
|
|
131
|
+
|
|
132
|
+
Acceptance Criteria:
|
|
133
|
+
✓ {criterion_1} - PASS
|
|
134
|
+
✓ {criterion_2} - PASS
|
|
135
|
+
✗ {criterion_3} - FAIL: {reason}
|
|
90
136
|
|
|
91
137
|
Three-Level Check:
|
|
92
138
|
✓ Exists: {pass}/{total}
|
|
@@ -101,17 +147,21 @@ Anti-Pattern Scan:
|
|
|
101
147
|
Browser Verification:
|
|
102
148
|
URL: {url}
|
|
103
149
|
Status: PASS/FAIL
|
|
104
|
-
Screenshot: .ctx/verify/
|
|
150
|
+
Screenshot: .ctx/verify/story-{id}.png
|
|
105
151
|
|
|
106
152
|
Overall: {PASS / FAIL}
|
|
107
153
|
|
|
108
154
|
{If FAIL:}
|
|
109
155
|
Fixes Required:
|
|
110
|
-
1. {fix_1}
|
|
156
|
+
1. {fix_1} → [criterion 3]
|
|
111
157
|
2. {fix_2}
|
|
112
158
|
|
|
113
159
|
{If PASS:}
|
|
114
|
-
|
|
160
|
+
✓ Story {story_id} verified!
|
|
161
|
+
PRD Progress: {passed}/{total} stories ({percent}%)
|
|
162
|
+
|
|
163
|
+
Next Story: {next_story_id} - {next_title}
|
|
164
|
+
Run /ctx to start planning.
|
|
115
165
|
```
|
|
116
166
|
</output_format>
|
|
117
167
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ctx-cc",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "CTX 2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
|
+
"description": "CTX 2.2 (Continuous Task eXecution) - PRD-driven workflow orchestration for Claude Code. Story-verified, debug loop until 100% fixed.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
7
7
|
"claude-code",
|
package/src/install.js
CHANGED
|
@@ -28,9 +28,9 @@ function printBanner() {
|
|
|
28
28
|
╚██████╗ ██║ ██╔╝ ██╗
|
|
29
29
|
╚═════╝ ╚═╝ ╚═╝ ╚═╝
|
|
30
30
|
`));
|
|
31
|
-
console.log(` ${bold('CTX 2.
|
|
32
|
-
console.log('
|
|
33
|
-
console.log(' 8 commands.
|
|
31
|
+
console.log(` ${bold('CTX 2.2')} ${dim(`v${VERSION}`)}`);
|
|
32
|
+
console.log(' PRD-driven workflow orchestration for Claude Code.');
|
|
33
|
+
console.log(' 8 commands. Story-verified. Debug loop.\n');
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
function copyDir(src, dest) {
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ctx.dev/schemas/prd.json",
|
|
3
|
+
"version": "2.0",
|
|
4
|
+
"project": {
|
|
5
|
+
"name": "{{project_name}}",
|
|
6
|
+
"description": "{{project_description}}",
|
|
7
|
+
"stack": "{{tech_stack}}",
|
|
8
|
+
"created": "{{timestamp}}"
|
|
9
|
+
},
|
|
10
|
+
"context": {
|
|
11
|
+
"problem": "{{what_problem_are_we_solving}}",
|
|
12
|
+
"targetUser": "{{who_is_this_for}}",
|
|
13
|
+
"successLooksLike": "{{how_will_we_know_its_done}}",
|
|
14
|
+
"outOfScope": [
|
|
15
|
+
"{{what_we_are_NOT_building}}"
|
|
16
|
+
],
|
|
17
|
+
"assumptions": [
|
|
18
|
+
"{{assumption_1}}",
|
|
19
|
+
"{{assumption_2}}"
|
|
20
|
+
],
|
|
21
|
+
"risks": [
|
|
22
|
+
"{{risk_1}}"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
"constitution": {
|
|
26
|
+
"principles": [
|
|
27
|
+
"Code quality over speed",
|
|
28
|
+
"Test before ship",
|
|
29
|
+
"No secrets in code"
|
|
30
|
+
],
|
|
31
|
+
"always": [
|
|
32
|
+
"Run tests before committing",
|
|
33
|
+
"Use TypeScript strict mode",
|
|
34
|
+
"Handle errors explicitly"
|
|
35
|
+
],
|
|
36
|
+
"never": [
|
|
37
|
+
"Commit secrets or credentials",
|
|
38
|
+
"Skip error handling",
|
|
39
|
+
"Leave TODO comments in production"
|
|
40
|
+
],
|
|
41
|
+
"askFirst": [
|
|
42
|
+
"Database schema changes",
|
|
43
|
+
"New dependencies",
|
|
44
|
+
"API contract changes"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
"testing": {
|
|
48
|
+
"requiresBrowser": false,
|
|
49
|
+
"requiresLogin": false,
|
|
50
|
+
"requiresAdmin": false,
|
|
51
|
+
"requiresAPI": false,
|
|
52
|
+
"notes": "{{testing_notes}}"
|
|
53
|
+
},
|
|
54
|
+
"stories": [
|
|
55
|
+
{
|
|
56
|
+
"id": "S001",
|
|
57
|
+
"title": "{{story_title}}",
|
|
58
|
+
"description": "{{story_description}}",
|
|
59
|
+
"acceptanceCriteria": [
|
|
60
|
+
"{{criterion_1}}",
|
|
61
|
+
"{{criterion_2}}",
|
|
62
|
+
"{{criterion_3}}"
|
|
63
|
+
],
|
|
64
|
+
"priority": 1,
|
|
65
|
+
"phase": 1,
|
|
66
|
+
"passes": false,
|
|
67
|
+
"verifiedAt": null,
|
|
68
|
+
"notes": ""
|
|
69
|
+
}
|
|
70
|
+
],
|
|
71
|
+
"metadata": {
|
|
72
|
+
"totalStories": 0,
|
|
73
|
+
"passedStories": 0,
|
|
74
|
+
"currentStory": null,
|
|
75
|
+
"lastUpdated": "{{timestamp}}"
|
|
76
|
+
}
|
|
77
|
+
}
|
package/templates/STATE.md
CHANGED
|
@@ -8,11 +8,21 @@
|
|
|
8
8
|
- **Stack**: {{tech_stack}}
|
|
9
9
|
- **Status**: {{status}} <!-- initializing | planning | executing | debugging | verifying | paused -->
|
|
10
10
|
|
|
11
|
+
## PRD Progress
|
|
12
|
+
- **Stories**: {{passed_stories}}/{{total_stories}} ({{percent}}%)
|
|
13
|
+
- **Current Story**: {{story_id}} - {{story_title}}
|
|
14
|
+
|
|
11
15
|
## Current Phase
|
|
12
|
-
- **ID**: {{phase_id}}
|
|
13
|
-
- **Goal**: {{
|
|
16
|
+
- **ID**: {{phase_id}} (maps to story {{story_id}})
|
|
17
|
+
- **Goal**: {{story_title}}
|
|
14
18
|
- **Progress**: {{completed_tasks}}/{{total_tasks}} tasks
|
|
15
19
|
|
|
20
|
+
## Acceptance Criteria (from PRD)
|
|
21
|
+
<!-- Current story's acceptance criteria -->
|
|
22
|
+
- [ ] {{criterion_1}}
|
|
23
|
+
- [ ] {{criterion_2}}
|
|
24
|
+
- [ ] {{criterion_3}}
|
|
25
|
+
|
|
16
26
|
## Active Task
|
|
17
27
|
- **Task**: {{current_task}}
|
|
18
28
|
- **Status**: {{task_status}} <!-- pending | in_progress | blocked | debugging | done -->
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# CTX Secrets - NEVER COMMIT
|
|
2
|
+
.env
|
|
3
|
+
*.env
|
|
4
|
+
.env.*
|
|
5
|
+
!.env.example
|
|
6
|
+
|
|
7
|
+
# Credential files
|
|
8
|
+
credentials.json
|
|
9
|
+
secrets.json
|
|
10
|
+
*.secrets
|
|
11
|
+
*.pem
|
|
12
|
+
*.key
|
|
13
|
+
|
|
14
|
+
# Debug screenshots may contain sensitive data
|
|
15
|
+
debug/*.png
|
|
16
|
+
debug/*.jpg
|
|
17
|
+
|
|
18
|
+
# Checkpoint data may contain state
|
|
19
|
+
checkpoints/*.json
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# CTX Test Credentials
|
|
2
|
+
# Generated by /ctx init
|
|
3
|
+
# WARNING: DO NOT COMMIT THIS FILE
|
|
4
|
+
|
|
5
|
+
# ===========================================
|
|
6
|
+
# APP CONFIGURATION
|
|
7
|
+
# ===========================================
|
|
8
|
+
|
|
9
|
+
# Local development URL
|
|
10
|
+
APP_URL=http://localhost:3000
|
|
11
|
+
|
|
12
|
+
# Staging/preview URL (optional)
|
|
13
|
+
STAGING_URL=
|
|
14
|
+
|
|
15
|
+
# Production URL (optional - for smoke tests)
|
|
16
|
+
PRODUCTION_URL=
|
|
17
|
+
|
|
18
|
+
# ===========================================
|
|
19
|
+
# TEST USER CREDENTIALS
|
|
20
|
+
# ===========================================
|
|
21
|
+
|
|
22
|
+
# Primary test user (for normal user flows)
|
|
23
|
+
TEST_USER_EMAIL=
|
|
24
|
+
TEST_USER_PASSWORD=
|
|
25
|
+
|
|
26
|
+
# Admin user (for admin features)
|
|
27
|
+
ADMIN_EMAIL=
|
|
28
|
+
ADMIN_PASSWORD=
|
|
29
|
+
|
|
30
|
+
# Secondary test user (for multi-user tests)
|
|
31
|
+
TEST_USER_2_EMAIL=
|
|
32
|
+
TEST_USER_2_PASSWORD=
|
|
33
|
+
|
|
34
|
+
# ===========================================
|
|
35
|
+
# API KEYS & TOKENS
|
|
36
|
+
# ===========================================
|
|
37
|
+
|
|
38
|
+
# Primary API key (if applicable)
|
|
39
|
+
API_KEY=
|
|
40
|
+
|
|
41
|
+
# OAuth tokens (if applicable)
|
|
42
|
+
OAUTH_CLIENT_ID=
|
|
43
|
+
OAUTH_CLIENT_SECRET=
|
|
44
|
+
|
|
45
|
+
# Third-party service keys
|
|
46
|
+
# STRIPE_TEST_KEY=
|
|
47
|
+
# SENDGRID_API_KEY=
|
|
48
|
+
# AWS_ACCESS_KEY_ID=
|
|
49
|
+
# AWS_SECRET_ACCESS_KEY=
|
|
50
|
+
|
|
51
|
+
# ===========================================
|
|
52
|
+
# DATABASE (if direct DB testing needed)
|
|
53
|
+
# ===========================================
|
|
54
|
+
|
|
55
|
+
DATABASE_URL=
|
|
56
|
+
|
|
57
|
+
# ===========================================
|
|
58
|
+
# CUSTOM SECRETS
|
|
59
|
+
# Add project-specific secrets below
|
|
60
|
+
# ===========================================
|
|
61
|
+
|