kenmark-skills 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.
- package/README.md +115 -0
- package/brain/CHANGELOG.md +48 -0
- package/package.json +46 -0
- package/skills/user-skills/commit-push/SKILL.md +225 -0
- package/skills/user-skills/init-brain/SKILL.md +425 -0
- package/skills/user-skills/issues-check/SKILL.md +121 -0
- package/skills/user-skills/issues-list/SKILL.md +180 -0
- package/skills/user-skills/issues-maintenance/SKILL.md +252 -0
- package/skills/user-skills/issues-scan/SKILL.md +226 -0
- package/skills/user-skills/issues-setup/SKILL.md +176 -0
- package/skills/user-skills/skill-router/SKILL.md +147 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issues-list
|
|
3
|
+
preamble-tier: 2
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
description: |
|
|
6
|
+
Display all open issues from brain/issues/ in a table grouped by area/type,
|
|
7
|
+
with columns for ID, Priority, and Title. Use when asked to "list issues",
|
|
8
|
+
"show issues", "issues dashboard", or "show all issues by type".
|
|
9
|
+
allowed-tools:
|
|
10
|
+
- Bash
|
|
11
|
+
- Read
|
|
12
|
+
- Grep
|
|
13
|
+
- Glob
|
|
14
|
+
triggers:
|
|
15
|
+
- list issues
|
|
16
|
+
- show issues
|
|
17
|
+
- issues dashboard
|
|
18
|
+
- show all issues by type
|
|
19
|
+
- issues by area
|
|
20
|
+
- issues by priority
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# Issues List — Grouped by Area/Type
|
|
24
|
+
|
|
25
|
+
## Purpose
|
|
26
|
+
|
|
27
|
+
Read all open issues from `brain/issues/INDEX.md` and display them in a
|
|
28
|
+
well-structured table grouped by area (api, database, security, ui, worker,
|
|
29
|
+
testing, maintainability, connectors, oauth, dsl), sorted by priority within
|
|
30
|
+
each group.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Step 1 — Read INDEX.md
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
ISSUES_DIR="$(git rev-parse --show-toplevel 2>/dev/null)/brain/issues"
|
|
38
|
+
cat "$ISSUES_DIR/INDEX.md"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Parse:
|
|
42
|
+
- Each issue's ID, severity (P0/P1/P2), area, and title
|
|
43
|
+
- Completed count from the overview table
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Step 2 — Display grouped table
|
|
48
|
+
|
|
49
|
+
Group issues by `area` tag. Within each area group, sort by priority
|
|
50
|
+
(P0 → P1 → P2), then by ID ascending.
|
|
51
|
+
|
|
52
|
+
Output format:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
ISSUES DASHBOARD — {date}
|
|
56
|
+
════════════════════════════════════════════════════════════════════
|
|
57
|
+
|
|
58
|
+
🔴 api (1 P0 | 0 P1 | 0 P2)
|
|
59
|
+
─────────────────────────────────────────────────────────────────
|
|
60
|
+
ID Prio Title
|
|
61
|
+
─── ──── ───────────────────────────────────────────────────────
|
|
62
|
+
001 P0 Client UI still calls deleted /api/connections routes
|
|
63
|
+
|
|
64
|
+
🟡 database (1 P0 | 3 P1 | 0 P2)
|
|
65
|
+
─────────────────────────────────────────────────────────────────
|
|
66
|
+
ID Prio Title
|
|
67
|
+
─── ──── ───────────────────────────────────────────────────────
|
|
68
|
+
013 P0 Prisma Credential model has no migration from legacy Connection table
|
|
69
|
+
014 P1 connector_poll_state migration uses connectionId; schema uses credentialId
|
|
70
|
+
021 P1 connector_event_deliveries migration indexes connectionId not credentialId
|
|
71
|
+
|
|
72
|
+
🔴 security (2 P0 | 5 P1 | 2 P2)
|
|
73
|
+
─────────────────────────────────────────────────────────────────
|
|
74
|
+
ID Prio Title
|
|
75
|
+
─── ──── ───────────────────────────────────────────────────────
|
|
76
|
+
016 P0 Connector-event HTTP ingest accepts unauthenticated POST when signatureScheme: 'none'
|
|
77
|
+
017 P0 Google OAuth callback allows open redirect via returnTo in signed state
|
|
78
|
+
018 P1 Connector-event HMAC verification stub always returns false
|
|
79
|
+
019 P1 connector-event verifyHmacSha256 weaker than webhook-service
|
|
80
|
+
020 P1 Connector-event ingest allows unbounded replay without Idempotency-Key
|
|
81
|
+
023 P2 Credential test API returns raw err.message in 500 responses
|
|
82
|
+
024 P1 Google OAuth callback always creates new credential (no dedupe by Google sub)
|
|
83
|
+
026 P2 Public connector-event ingest has no rate limiting beyond 5MB
|
|
84
|
+
|
|
85
|
+
🟡 worker (0 P0 | 3 P1 | 1 P2)
|
|
86
|
+
─────────────────────────────────────────────────────────────────
|
|
87
|
+
ID Prio Title
|
|
88
|
+
─── ──── ───────────────────────────────────────────────────────
|
|
89
|
+
012 P1 Worker still queries removed Prisma Connection model and encryptedCredentials
|
|
90
|
+
022 P1 Worker poller parses connectionId; web stores credentialId
|
|
91
|
+
025 P1 Worker FakePrisma still mocks connection; tests pass while typecheck fails
|
|
92
|
+
027 P2 Worker README and registry errors still describe Connection model
|
|
93
|
+
|
|
94
|
+
🟡 testing (1 P0 | 6 P1 | 3 P2)
|
|
95
|
+
─────────────────────────────────────────────────────────────────
|
|
96
|
+
ID Prio Title
|
|
97
|
+
─── ──── ───────────────────────────────────────────────────────
|
|
98
|
+
030 P0 E2E connections.spec.ts still calls deleted /api/connections
|
|
99
|
+
031 P1 Missing API route tests for GET/POST /api/credentials
|
|
100
|
+
032 P1 Missing API route tests for credentials/[id] DELETE and test POST
|
|
101
|
+
033 P1 credential-service.test.ts missing listCredentials/getCredential/setStatus/validate coverage
|
|
102
|
+
034 P1 FakePrisma credential.findMany ignores id: { in } filter
|
|
103
|
+
035 P2 connector-event ingest test passes connectionId not credentialId
|
|
104
|
+
036 P1 Missing HTTP tests for connector-events credentialId ingest route
|
|
105
|
+
037 P1 Missing route tests for Google OAuth callback and Sheets credential APIs
|
|
106
|
+
028 P2 credential-service update/test use Prisma where id only (defense in depth)
|
|
107
|
+
|
|
108
|
+
🟡 ui (1 P0 | 1 P1 | 22 P2)
|
|
109
|
+
─────────────────────────────────────────────────────────────────
|
|
110
|
+
ID Prio Title
|
|
111
|
+
─── ──── ───────────────────────────────────────────────────────
|
|
112
|
+
003 P0 CTAs link to /credentials/new but no App Router page exists
|
|
113
|
+
007 P1 App shell nav still labeled "Connections" with /connections href
|
|
114
|
+
008 P2 Workflow triggers empty state links to non-existent /credentials
|
|
115
|
+
009 P2 UI still uses Connection* component and type names for credentials
|
|
116
|
+
010 P2 Stale "connections" comments in OAuth routes and GoogleSheetsPicker
|
|
117
|
+
011 P2 connector-event-service retains ConnectionRow internal naming
|
|
118
|
+
038 P2 Event delivery run links use unsupported /runs?run= query
|
|
119
|
+
039 P2 Dashboard and connectors status chips use legacy "Connection" wording
|
|
120
|
+
040 P2 Dashboard connector library rows lack credential navigation
|
|
121
|
+
041 P2 Connectors catalog rows lack per-connector credential actions
|
|
122
|
+
042 P2 Google Sheets import picker Selects lack accessible labels
|
|
123
|
+
043 P2 Credential delete dialog confirm field has aria-label only
|
|
124
|
+
044 P2 Credential test button loses accessible name while loading
|
|
125
|
+
045 P2 Event deliveries panel sits outside credential detail layout shell
|
|
126
|
+
046 P2 Agent conversation tabs nest close buttons inside tab labels
|
|
127
|
+
047 P2 Credentials list page missing breadcrumb trail
|
|
128
|
+
048 P2 Dashboard hero CTA uses full-bleed primary card styling
|
|
129
|
+
049 P2 Dashboard misstates connector catalogue completeness
|
|
130
|
+
050 P2 List pages use CercliDataGrid vs raw table decision needed
|
|
131
|
+
051 P2 Runs table displays opaque UUIDs instead of friendly identifiers
|
|
132
|
+
052 P2 Trigger row icon buttons lack aria labels
|
|
133
|
+
053 P2 Agent page skips PageHeader breadcrumb
|
|
134
|
+
054 P2 Nav group labels appear below overline per spec
|
|
135
|
+
055 P2 Governance tables use icon-only actions without labels
|
|
136
|
+
056 P2 Dashboard runs display ISO timestamps instead of relative time
|
|
137
|
+
057 P2 Runs filter chips confusing remove vs navigate behavior
|
|
138
|
+
058 P2 Credentials empty state shows orphan card
|
|
139
|
+
|
|
140
|
+
🟡 dsl (0 P0 | 1 P1 | 0 P2)
|
|
141
|
+
─────────────────────────────────────────────────────────────────
|
|
142
|
+
ID Prio Title
|
|
143
|
+
─── ──── ───────────────────────────────────────────────────────
|
|
144
|
+
015 P1 Workflow DSL still uses connectionRef and missing_connection for credential IDs
|
|
145
|
+
|
|
146
|
+
🟡 connectors (0 P0 | 0 P1 | 1 P2)
|
|
147
|
+
─────────────────────────────────────────────────────────────────
|
|
148
|
+
ID Prio Title
|
|
149
|
+
─── ──── ───────────────────────────────────────────────────────
|
|
150
|
+
029 P2 Google Workspace connector comments reference removed Connection model
|
|
151
|
+
|
|
152
|
+
════════════════════════════════════════════════════════════════════
|
|
153
|
+
Total open: 54 | Completed: 4
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Area color coding:**
|
|
157
|
+
- 🔴 = area has any P0 issues (critical — fix first)
|
|
158
|
+
- 🟡 = area has P1/P2 only (high/medium priority)
|
|
159
|
+
- ⚪ = area has no open issues
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Step 3 — Workstream summary
|
|
164
|
+
|
|
165
|
+
At the bottom, show a compact workstream view grouping cross-area issues
|
|
166
|
+
by root cause:
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
WORKSTREAMS
|
|
170
|
+
─────────────────────────────────────────────────────────────────
|
|
171
|
+
Security (HMAC, open redirect, error leaks) 016, 017, 018, 019, 023, 024, 026
|
|
172
|
+
Worker package (stale model, poller mismatch) 012, 022, 025, 027
|
|
173
|
+
Database migrations (connectionId→credentialId) 013, 014, 021
|
|
174
|
+
DSL vocabulary (connectionRef rename) 015
|
|
175
|
+
UI rename (connections→credentials pages) 001, 003, 007, 008, 038, 039, 040, 041, 047, 048, 049, 050, 051, 052, 053, 054, 055, 056, 057, 058
|
|
176
|
+
UI component naming (stale Connection* names) 009, 010, 011
|
|
177
|
+
Test gaps (missing API, service, route tests) 028, 030, 031, 032, 033, 034, 035, 036, 037
|
|
178
|
+
Accessibility (a11y labels, contrast, layout) 042, 043, 044, 045, 046, 052, 054, 055
|
|
179
|
+
════════════════════════════════════════════════════════════════════
|
|
180
|
+
```
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issues-maintenance
|
|
3
|
+
preamble-tier: 2
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
description: |
|
|
6
|
+
Audit brain/issues/ for structural health: missing files, duplicate IDs across
|
|
7
|
+
open/completed, stale frontmatter (wrong status), INDEX.md drift from reality,
|
|
8
|
+
and orphaned completed issues never added to INDEX. Use when asked to
|
|
9
|
+
"check issues health", "audit issues", "fix issues tracking", or "issues maintenance".
|
|
10
|
+
allowed-tools:
|
|
11
|
+
- Bash
|
|
12
|
+
- Read
|
|
13
|
+
- Glob
|
|
14
|
+
- Grep
|
|
15
|
+
triggers:
|
|
16
|
+
- issues health
|
|
17
|
+
- check issues tracking
|
|
18
|
+
- audit issues
|
|
19
|
+
- fix issues tracking
|
|
20
|
+
- issues maintenance
|
|
21
|
+
- fix duplicate issues
|
|
22
|
+
- issues cleanup
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Issues Maintenance — Health Check & Repair
|
|
26
|
+
|
|
27
|
+
## Purpose
|
|
28
|
+
|
|
29
|
+
Audit and fix structural problems in `brain/issues/` tracking. This skill
|
|
30
|
+
catches the four categories of drift that accumulate over time:
|
|
31
|
+
|
|
32
|
+
1. **Duplicates** — same issue ID exists in both `brain/issues/` (open) and
|
|
33
|
+
`brain/issues/completed/` (completed) — one must be removed
|
|
34
|
+
2. **INDEX drift** — INDEX.md says an issue is completed but the file is still
|
|
35
|
+
in `brain/issues/`, or says open but file only exists in `completed/`
|
|
36
|
+
3. **Missing fronts matter** — issue files missing required frontmatter fields
|
|
37
|
+
(id, title, severity, area, status) or with invalid values
|
|
38
|
+
4. **Orphan completed** — files in `completed/` not listed in INDEX.md
|
|
39
|
+
Completed table
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Step 1 — Enumerate all issue IDs
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
ISSUES_DIR="$(git rev-parse --show-toplevel 2>/dev/null)/brain/issues"
|
|
47
|
+
|
|
48
|
+
# All IDs in open folder
|
|
49
|
+
ls "$ISSUES_DIR"/[0-9]*.md 2>/dev/null | xargs -I{} basename {} .md | \
|
|
50
|
+
sed 's/-.*//' | sort -n > /tmp/open_ids.txt
|
|
51
|
+
|
|
52
|
+
# All IDs in completed folder
|
|
53
|
+
ls "$ISSUES_DIR/completed"/[0-9]*.md 2>/dev/null | xargs -I{} basename {} .md | \
|
|
54
|
+
sed 's/-.*//' | sort -n > /tmp/completed_ids.txt
|
|
55
|
+
|
|
56
|
+
# IDs marked completed in INDEX.md
|
|
57
|
+
grep '^\[0' "$ISSUES_DIR/INDEX.md" | sed 's/.*\[\(.*\)\](.*/\1/' | \
|
|
58
|
+
sed 's/^0*//' | grep '^[0-9]' | sort -n > /tmp/index_completed_ids.txt
|
|
59
|
+
|
|
60
|
+
echo "OPEN count: $(wc -l < /tmp/open_ids.txt)"
|
|
61
|
+
echo "COMPLETED count: $(wc -l < /tmp/completed_ids.txt)"
|
|
62
|
+
echo "INDEX completed count: $(wc -l < /tmp/index_completed_ids.txt)"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Step 2 — Detect duplicate IDs (open AND completed)
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
comm -12 /tmp/open_ids.txt /tmp/completed_ids.txt
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Any output = that issue ID exists in both folders. This is the most common
|
|
74
|
+
drift. For each duplicate:
|
|
75
|
+
- If the issue is truly **completed**: the open file in `brain/issues/` is
|
|
76
|
+
wrong — delete it with `rm brain/issues/<file>`
|
|
77
|
+
- If the issue is truly **open**: the completed copy is wrong — delete it with
|
|
78
|
+
`rm brain/issues/completed/<file>`
|
|
79
|
+
- When in doubt, check the file's frontmatter `status:` field
|
|
80
|
+
|
|
81
|
+
If duplicates are found, after fixing run:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
git add -u brain/issues/completed/
|
|
85
|
+
git commit -m "fix(brain): remove duplicate completed issue files
|
|
86
|
+
|
|
87
|
+
The brain/issues/completed/ folder had accumulated duplicate copies of
|
|
88
|
+
issues that already existed in brain/issues/ (open issues being tracked).
|
|
89
|
+
Keep only truly completed issues in completed/; open issues remain in
|
|
90
|
+
brain/issues/ per the established structure."
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Step 3 — Check INDEX drift
|
|
96
|
+
|
|
97
|
+
Find IDs that INDEX says are completed but still have an open file:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
comm -12 /tmp/index_completed_ids.txt /tmp/open_ids.txt
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Find IDs that INDEX says are open but only exist in completed/ (forgot to
|
|
104
|
+
move to completed/ folder):
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
comm -23 /tmp/index_completed_ids.txt /tmp/open_ids.txt | \
|
|
108
|
+
while read id; do
|
|
109
|
+
if ! ls brain/issues/${id}*.md 2>/dev/null | grep -q .; then
|
|
110
|
+
echo "$id — in INDEX as completed but no open file (OK to leave)"
|
|
111
|
+
fi
|
|
112
|
+
done
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Find IDs in the open folder that are NOT in INDEX's active list (forgot to
|
|
116
|
+
close or add to completed):
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Get active IDs from INDEX P0/P1/P2 tables
|
|
120
|
+
grep '^\[0' "$ISSUES_DIR/INDEX.md" | grep -v 'completed/' | \
|
|
121
|
+
sed 's/.*\[\(.*\)\](.*/\1/' | sed 's/^0*//' | grep '^[0-9]' | \
|
|
122
|
+
sort -n > /tmp/index_active_ids.txt
|
|
123
|
+
|
|
124
|
+
comm -23 /tmp/open_ids.txt /tmp/index_active_ids.txt
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
These IDs are in the open folder but not listed as active in INDEX — either
|
|
128
|
+
they were completed and not moved to `completed/`, or they're brand new and
|
|
129
|
+
need adding to INDEX.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Step 4 — Frontmatter validation
|
|
134
|
+
|
|
135
|
+
For each issue file (both `brain/issues/` and `brain/issues/completed/`),
|
|
136
|
+
validate the frontmatter has required fields and valid values.
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
for f in brain/issues/[0-9]*.md brain/issues/completed/[0-9]*.md; do
|
|
140
|
+
id=$(basename "$f" .md | sed 's/-.*//')
|
|
141
|
+
status=$(grep '^status:' "$f" 2>/dev/null | awk '{print $2}')
|
|
142
|
+
severity=$(grep '^severity:' "$f" 2>/dev/null | awk '{print $2}')
|
|
143
|
+
area=$(grep '^area:' "$f" 2>/dev/null | awk '{print $2}')
|
|
144
|
+
|
|
145
|
+
# Check for missing fields
|
|
146
|
+
if [ -z "$status" ]; then echo "MISSING status: $f"; fi
|
|
147
|
+
if [ -z "$severity" ]; then echo "MISSING severity: $f"; fi
|
|
148
|
+
if [ -z "$area" ]; then echo "MISSING area: $f"; fi
|
|
149
|
+
|
|
150
|
+
# Validate severity values
|
|
151
|
+
if [ -n "$severity" ] && ! echo "$severity" | grep -qE '^(P0|P1|P2)$'; then
|
|
152
|
+
echo "INVALID severity '$severity': $f"
|
|
153
|
+
fi
|
|
154
|
+
|
|
155
|
+
# Validate status values
|
|
156
|
+
if [ -n "$status" ] && ! echo "$status" | grep -qE '^(open|completed)$'; then
|
|
157
|
+
echo "INVALID status '$status': $f"
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
# Cross-check: files in brain/issues/ should have status: open
|
|
161
|
+
if [[ "$f" == brain/issues/[0-9]*.md ]] && [ "$status" = "completed" ]; then
|
|
162
|
+
echo "STALE status=completed but in open folder: $f"
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
# Cross-check: files in brain/issues/completed/ should have status: completed
|
|
166
|
+
if [[ "$f" == brain/issues/completed/* ]]; then
|
|
167
|
+
if [ "$status" != "completed" ]; then
|
|
168
|
+
echo "WRONG status=$status (expected completed) in completed folder: $f"
|
|
169
|
+
fi
|
|
170
|
+
fi
|
|
171
|
+
done
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
For each finding:
|
|
175
|
+
- **MISSING**: Add the required frontmatter field
|
|
176
|
+
- **INVALID**: Fix the invalid value
|
|
177
|
+
- **STALE**: Move the file to `completed/` and update INDEX.md
|
|
178
|
+
- **WRONG**: Fix status to `completed`
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Step 5 — Orphan completed check (in INDEX but not in folder)
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
comm -23 /tmp/index_completed_ids.txt /tmp/completed_ids.txt
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Each ID in this list appears in INDEX.md as completed but has no file in
|
|
189
|
+
`completed/`. This means the file was deleted or never migrated. Either:
|
|
190
|
+
- Create the completed issue file by moving from open (if it was fixed but
|
|
191
|
+
file not moved)
|
|
192
|
+
- Or the issue was already fixed and the completed file was deleted — no action
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Step 6 — Summary report
|
|
197
|
+
|
|
198
|
+
After all checks, print a structured summary:
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
ISSUES MAINTENANCE REPORT — {date}
|
|
202
|
+
════════════════════════════════════════════════════════════════════
|
|
203
|
+
Open issues: {N} (brain/issues/)
|
|
204
|
+
Completed issues: {N} (brain/issues/completed/)
|
|
205
|
+
INDEX active: {N} (from INDEX.md P0/P1/P2 tables)
|
|
206
|
+
INDEX completed: {N} (from INDEX.md completed table)
|
|
207
|
+
|
|
208
|
+
HEALTH:
|
|
209
|
+
Duplicates (open+completed): {N} — FIX or IGNORE
|
|
210
|
+
INDEX drift (open but marked completed): {N} — FIX
|
|
211
|
+
Missing frontmatter fields: {N} — FIX
|
|
212
|
+
Invalid field values: {N} — FIX
|
|
213
|
+
Orphan completed (in INDEX, no file): {N} — REVIEW
|
|
214
|
+
Untracked open (not in INDEX): {N} — ADD TO INDEX or COMPLETE
|
|
215
|
+
|
|
216
|
+
RECOMMENDED ACTIONS:
|
|
217
|
+
1. [list of specific fix commands or file-level actions]
|
|
218
|
+
════════════════════════════════════════════════════════════════════
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Step 7 — Apply fixes
|
|
224
|
+
|
|
225
|
+
For each fixable issue from the report:
|
|
226
|
+
|
|
227
|
+
- **Duplicate removal**: `rm brain/issues/<file>` or `rm brain/issues/completed/<file>`
|
|
228
|
+
- **Status fix**: Edit the frontmatter `status:` field
|
|
229
|
+
- **Move to completed**: `mv brain/issues/<file> brain/issues/completed/`
|
|
230
|
+
- **INDEX update**: Edit `brain/issues/INDEX.md` to move issue ID from active table
|
|
231
|
+
to completed table (add completed date)
|
|
232
|
+
|
|
233
|
+
After fixing, commit with:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
git add -u brain/issues/
|
|
237
|
+
git commit -m "fix(brain): issues maintenance — {brief description of what was fixed}"
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Hard Rules
|
|
243
|
+
|
|
244
|
+
1. **Never delete an issue file without understanding why it exists** — if an
|
|
245
|
+
ID appears in both folders, one is wrong, not both
|
|
246
|
+
2. **INDEX.md is the source of truth for counts** — if the INDEX and reality
|
|
247
|
+
disagree, trust what you observe in the files and fix INDEX to match
|
|
248
|
+
3. **Always commit completed issue file moves separately** from code fixes so
|
|
249
|
+
the brain/ history is clean and reviewable
|
|
250
|
+
4. **Do not touch open issue files** — the maintenance skill only moves,
|
|
251
|
+
renames, or updates completed issues; open issues are owned by whoever is
|
|
252
|
+
actively working on them
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: issues-scan
|
|
3
|
+
preamble-tier: 2
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
description: |
|
|
6
|
+
Scan the codebase for new issues matching the connections→credentials migration
|
|
7
|
+
pattern. Detect bugs, gaps, and inconsistencies and create new issue files in
|
|
8
|
+
brain/issues/ with unique IDs. Use when asked to "scan for new issues",
|
|
9
|
+
"find new issues", or "discover issues".
|
|
10
|
+
allowed-tools:
|
|
11
|
+
- Bash
|
|
12
|
+
- Read
|
|
13
|
+
- Write
|
|
14
|
+
- Edit
|
|
15
|
+
- Grep
|
|
16
|
+
- Glob
|
|
17
|
+
- AskUserQuestion
|
|
18
|
+
triggers:
|
|
19
|
+
- scan for new issues
|
|
20
|
+
- find new issues
|
|
21
|
+
- discover issues
|
|
22
|
+
- new issues
|
|
23
|
+
- scan issues
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
# Issues Scan — Discover New Issues from Codebase
|
|
27
|
+
|
|
28
|
+
## Purpose
|
|
29
|
+
|
|
30
|
+
Scan the codebase for bugs, gaps, and inconsistencies that warrant new issues.
|
|
31
|
+
Assign unique IDs (next available in the 3-digit sequence), populate with
|
|
32
|
+
evidence, and optionally update INDEX.md.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Step 1 — Read existing issues to avoid duplicates
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
ISSUES_DIR="$(git rev-parse --show-toplevel 2>/dev/null)/brain/issues"
|
|
40
|
+
echo "=== Existing issue IDs ==="
|
|
41
|
+
find "$ISSUES_DIR" -maxdepth 1 -name "*.md" -not -name "INDEX.md" -not -path "*/completed/*" | \
|
|
42
|
+
sed 's/.*\///' | sed 's/-.*//' | sort -n
|
|
43
|
+
echo "=== Highest ID ==="
|
|
44
|
+
find "$ISSUES_DIR" -maxdepth 1 -name "*.md" -not -name "INDEX.md" -not -path "*/completed/*" | \
|
|
45
|
+
sed 's/.*\///' | sed 's/-.*//' | sort -n | tail -1
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The next ID is the highest existing ID + 1, zero-padded to 3 digits.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Step 2 — Scan patterns by workstream
|
|
53
|
+
|
|
54
|
+
Run targeted Grep searches for common issue patterns. For each search,
|
|
55
|
+
check if the finding matches an already-filed issue before creating a new one.
|
|
56
|
+
|
|
57
|
+
### 2a — API routes (stale /connections references)
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Returns lines referencing old connection API paths
|
|
61
|
+
grep -rn "/api/connections" --include="*.ts" --include="*.tsx" \
|
|
62
|
+
"$(git rev-parse --show-toplevel)/apps"2>/dev/null | grep -v "node_modules"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 2b — Worker package (old Connection model references)
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
grep -rn "connection\|Connection" --include="*.ts" \
|
|
69
|
+
"$(git rev-parse --show-toplevel)/apps/worker/src"2>/dev/null | \
|
|
70
|
+
grep -v "connectionId\|ConnectionRow\|connections\|test" | head -30
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 2c — DSL/schema (connectionRef vocabulary)
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
grep -rn "connectionRef\|missing_connection\|connection_ref" --include="*.ts" \
|
|
77
|
+
"$(git rev-parse --show-toplevel)/packages/dsl" 2>/dev/null
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 2d — UI components (stale naming)
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
grep -rn "Connection\|connection" --include="*.tsx" \
|
|
84
|
+
"$(git rev-parse --show-toplevel)/apps/web/src/app"2>/dev/null | \
|
|
85
|
+
grep -v "connectionId\|ConnectionRow\|test\|connectionString\|ConnectionsTable\|NewConnectionForm\|ConnectionDetail" | head -30
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 2e — Database migrations (connectionId vs credentialId)
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
grep -rn "connectionId\|connection_id" --include="*.sql" \
|
|
92
|
+
"$(git rev-parse --show-toplevel)/packages/db" 2>/dev/null
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 2f — Security patterns (HMAC, rate limiting, error messages)
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# HMAC stub always returns false
|
|
99
|
+
grep -rn "verifyHmac\|hmac\|HMAC" --include="*.ts" \
|
|
100
|
+
"$(git rev-parse --show-toplevel)/apps/web/src"2>/dev/null | head -20
|
|
101
|
+
|
|
102
|
+
# Raw error.message in 500 responses
|
|
103
|
+
grep -rn "err\.message\|error\.message" --include="*.ts" \
|
|
104
|
+
"$(git rev-parse --show-toplevel)/apps/web/src/app/api" 2>/dev/null | head -20
|
|
105
|
+
|
|
106
|
+
# Missing rate limiting
|
|
107
|
+
grep -rn "rateLimit\|rate_limit\|RateLimit" --include="*.ts" \
|
|
108
|
+
"$(git rev-parse --show-toplevel)/apps/web/src" 2>/dev/null | head -10
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 2g — Missing test coverage
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# API routes without test files
|
|
115
|
+
find "$(git rev-parse --show-toplevel)/apps/web/src/app/api" -name "route.ts" | sort | \
|
|
116
|
+
while read route; do
|
|
117
|
+
test_file="${route%.ts}.test.ts"
|
|
118
|
+
[ -f "$test_file" ] || echo "NO TEST: $route"
|
|
119
|
+
done
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 2h — OAuth flows
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
grep -rn "returnTo\|redirect\|oauth\|OAuth" --include="*.ts" \
|
|
126
|
+
"$(git rev-parse --show-toplevel)/apps/web/src/app/api/oauth" 2>/dev/null | head -20
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Step 3 — Deduplicate against existing issues
|
|
132
|
+
|
|
133
|
+
Before creating any new issue, cross-check against existing titles and evidence:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
ISSUES_DIR="$(git rev-parse --show-toplevel 2>/dev/null)/brain/issues"
|
|
137
|
+
# List all existing issue titles
|
|
138
|
+
grep -h "^title:" "$ISSUES_DIR"/*.md 2>/dev/null | sort -u
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
If a finding matches an existing issue (same file, same bug pattern), skip it.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Step 4 — Create new issue files
|
|
146
|
+
|
|
147
|
+
For each unique finding, create a file at `brain/issues/{id}-{slug}.md`:
|
|
148
|
+
|
|
149
|
+
```markdown
|
|
150
|
+
---
|
|
151
|
+
id: {next-id}
|
|
152
|
+
title: {concise one-liner}
|
|
153
|
+
severity: P0|P1|P2
|
|
154
|
+
area: api|database|security|ui|worker|testing|maintainability|connectors|oauth|dsl
|
|
155
|
+
source: issues-scan
|
|
156
|
+
status: open
|
|
157
|
+
created: {YYYY-MM-DD}
|
|
158
|
+
files:
|
|
159
|
+
- path/to/file1
|
|
160
|
+
- path/to/file2
|
|
161
|
+
related:
|
|
162
|
+
- related-issue-id
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Summary
|
|
166
|
+
|
|
167
|
+
{2-3 sentences: what is wrong, where, and why it matters.}
|
|
168
|
+
|
|
169
|
+
## Evidence
|
|
170
|
+
|
|
171
|
+
- `file:line` — description of the finding
|
|
172
|
+
- `file:line` — description of the finding
|
|
173
|
+
|
|
174
|
+
## Suggested fix
|
|
175
|
+
|
|
176
|
+
{Concrete steps to fix the issue.}
|
|
177
|
+
|
|
178
|
+
## Acceptance criteria
|
|
179
|
+
|
|
180
|
+
- [ ] {criterion 1}
|
|
181
|
+
- [ ] {criterion 2}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Slug rules:** lowercase, hyphens, no numbers in the slug part.
|
|
185
|
+
**ID sequence:** 001, 002, ... 058, 059, ... (always 3 digits, zero-padded).
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Step 4.5 — Closing completed issues
|
|
190
|
+
|
|
191
|
+
When an issue is resolved, **move it to `brain/issues/completed/` instead of deleting it**.
|
|
192
|
+
This preserves the audit trail and allows the INDEX.md completed table to link to the file.
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Move a resolved issue to completed/
|
|
196
|
+
mv brain/issues/042-google-sheets-picker-selects-missing-accessible-labels.md \
|
|
197
|
+
brain/issues/completed/042-google-sheets-picker-selects-missing-accessible-labels.md
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Then update `brain/issues/INDEX.md`:
|
|
201
|
+
1. Move the issue entry from the active priority table to the Completed table
|
|
202
|
+
2. Add `completed: YYYY-MM-DD` to the issue frontmatter (edit the file directly)
|
|
203
|
+
3. Decrement "Active issues" count, increment "Completed" count
|
|
204
|
+
|
|
205
|
+
**Rule: Never delete an issue file. Always move it to completed/.**
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Step 5 — Update INDEX.md
|
|
210
|
+
|
|
211
|
+
After creating new issues or closing completed ones, update `brain/issues/INDEX.md`:
|
|
212
|
+
|
|
213
|
+
1. Increment "Active issues" count (new issues) or decrement (closed issues)
|
|
214
|
+
2. Add new issues to the correct priority table (P0/P1/P2)
|
|
215
|
+
3. Move closed issues to the Completed table with today's date
|
|
216
|
+
4. Re-sort by ID within each priority section
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Step 6 — Report
|
|
221
|
+
|
|
222
|
+
Report:
|
|
223
|
+
- How many scans performed
|
|
224
|
+
- How many new issues created
|
|
225
|
+
- Which IDs were assigned
|
|
226
|
+
- Any findings that were deduplicated against existing issues
|