|
4 | 4 | ## 1. SETUP & ENVIRONMENT (Items 1-60) |
5 | 5 |
|
6 | 6 | ### 1.1 Installation & Dependencies |
7 | | -[ ] 1. Python 3.10+ available |
8 | | -[ ] 2. pip install -e . succeeds |
9 | | -[ ] 3. All dependencies resolve (no conflicts) |
10 | | -[ ] 4. python -m ghdcbot --help shows usage |
11 | | -[ ] 5. --config required and enforced |
12 | | -[ ] 6. Invalid --config path exits with error |
13 | | -[ ] 7. Missing config file exits with clear message |
14 | | -[ ] 8. Config with wrong YAML syntax fails load |
15 | | -[ ] 9. Config with missing required key fails (e.g. runtime) |
16 | | -[ ] 10. Config with invalid type for a key fails (e.g. guild_id as int) |
17 | | -[ ] 11. .env or env vars for GITHUB_TOKEN work when referenced in config |
18 | | -[ ] 12. .env or env vars for DISCORD_TOKEN work when referenced in config |
19 | | -[ ] 13. Empty token in config fails or warns appropriately |
20 | | -[ ] 14. data_dir is created if missing when bot/run-once runs |
21 | | -[ ] 15. data_dir is used for state.db (SQLite) |
22 | | -[ ] 16. data_dir is used for audit_events.jsonl if applicable |
23 | | -[ ] 17. Log level DEBUG produces more output than INFO |
24 | | -[ ] 18. Log level WARNING suppresses INFO |
25 | | -[ ] 19. Log level ERROR suppresses WARNING |
26 | | -[ ] 20. Invalid log_level in config fails validation |
27 | | -[ ] 21. mode dry-run is default |
28 | | -[ ] 22. mode observer accepted |
29 | | -[ ] 23. mode active accepted |
30 | | -[ ] 24. Invalid mode value fails validation |
31 | | -[ ] 25. github_adapter plugin path loads |
32 | | -[ ] 26. discord_adapter plugin path loads |
33 | | -[ ] 27. storage_adapter plugin path loads |
34 | | -[ ] 28. Invalid adapter path fails with clear error |
35 | | -[ ] 29. Bot starts without Discord token (fails at runtime appropriately) |
36 | | -[ ] 30. Bot starts without GitHub token (fails at runtime appropriately) |
37 | | -[ ] 31. run-once with valid config completes without crash |
| 7 | +[x] 1. Python 3.10+ available |
| 8 | +[x] 2. pip install -e . succeeds |
| 9 | +[x] 3. All dependencies resolve (no conflicts) |
| 10 | +[x] 4. python -m ghdcbot --help shows usage |
| 11 | +[x] 5. --config required and enforced |
| 12 | +[x] 6. Invalid --config path exits with error |
| 13 | +[x] 7. Missing config file exits with clear message |
| 14 | +[x] 8. Config with wrong YAML syntax fails load |
| 15 | +[x] 9. Config with missing required key fails (e.g. runtime) |
| 16 | +[x] 10. Config with invalid type for a key fails (e.g. guild_id as int) |
| 17 | +[x] 11. .env or env vars for GITHUB_TOKEN work when referenced in config |
| 18 | +[x] 12. .env or env vars for DISCORD_TOKEN work when referenced in config |
| 19 | +[x] 13. Empty token in config fails or warns appropriately |
| 20 | +[x] 14. data_dir is created if missing when bot/run-once runs |
| 21 | +[x] 15. data_dir is used for state.db (SQLite) |
| 22 | +[x] 16. data_dir is used for audit_events.jsonl if applicable |
| 23 | +[x] 17. Log level DEBUG produces more output than INFO |
| 24 | +[x] 18. Log level WARNING suppresses INFO |
| 25 | +[x] 19. Log level ERROR suppresses WARNING |
| 26 | +[x] 20. Invalid log_level in config fails validation |
| 27 | +[x] 21. mode dry-run is default |
| 28 | +[x] 22. mode observer accepted |
| 29 | +[x] 23. mode active accepted |
| 30 | +[x] 24. Invalid mode value fails validation |
| 31 | +[x] 25. github_adapter plugin path loads |
| 32 | +[x] 26. discord_adapter plugin path loads |
| 33 | +[x] 27. storage_adapter plugin path loads |
| 34 | +[x] 28. Invalid adapter path fails with clear error |
| 35 | +[x] 29. Bot starts without Discord token (fails at runtime appropriately) |
| 36 | +[x] 30. Bot starts without GitHub token (fails at runtime appropriately) |
| 37 | +[x] 31. run-once with valid config completes without crash |
38 | 38 | [ ] 32. bot with valid config connects to Discord |
39 | 39 | [ ] 33. Slash commands sync to guild on ready |
40 | 40 | [ ] 34. Only configured guild_id receives command registration |
41 | 41 | [ ] 35. Second guild does not see commands (if applicable) |
42 | 42 | [ ] 36. Bot reconnects after network blip (resume session) |
43 | 43 | [ ] 37. Bot restart re-syncs commands |
44 | 44 | [ ] 38. Config change requires restart to take effect |
45 | | -[ ] 39. data_dir persists across restarts |
46 | | -[ ] 40. state.db survives bot restart |
| 45 | +[x] 39. data_dir persists across restarts |
| 46 | +[x] 40. state.db survives bot restart |
47 | 47 | [ ] 41. No corruption after kill -9 and restart |
48 | 48 | [ ] 42. Concurrent run-once and bot (same data_dir) - no DB lock errors or document behavior |
49 | | -[ ] 43. Read-only filesystem on data_dir fails gracefully |
| 49 | +[x] 43. Read-only filesystem on data_dir fails gracefully |
50 | 50 | [ ] 44. Full disk on data_dir fails gracefully |
51 | | -[ ] 45. UTF-8 config with non-ASCII (e.g. comments) loads |
52 | | -[ ] 46. Very long data_dir path handled |
53 | | -[ ] 47. Symlink data_dir works |
54 | | -[ ] 48. Relative path for data_dir resolved from CWD |
55 | | -[ ] 49. Absolute path for data_dir used as-is |
56 | | -[ ] 50. api_base URL with trailing slash accepted |
57 | | -[ ] 51. api_base URL without trailing slash accepted |
58 | | -[ ] 52. GitHub API base overridden (e.g. GitHub Enterprise) used for requests |
59 | | -[ ] 53. guild_id as string numeric accepted |
60 | | -[ ] 54. guild_id with leading zeros (if any) behavior |
61 | | -[ ] 55. repos.mode allow with empty names fails validation |
62 | | -[ ] 56. repos.mode deny with names filters repos |
63 | | -[ ] 57. repos.mode allow with names allows only those repos |
64 | | -[ ] 58. user_fallback true allows user repos when org repos fail |
65 | | -[ ] 59. user_fallback false uses only org repos |
66 | | -[ ] 60. github.permissions.read false prevents GitHub reads (run-once behavior) |
| 51 | +[x] 45. UTF-8 config with non-ASCII (e.g. comments) loads |
| 52 | +[x] 46. Very long data_dir path handled |
| 53 | +[x] 47. Symlink data_dir works |
| 54 | +[x] 48. Relative path for data_dir resolved from CWD |
| 55 | +[x] 49. Absolute path for data_dir used as-is |
| 56 | +[x] 50. api_base URL with trailing slash accepted |
| 57 | +[x] 51. api_base URL without trailing slash accepted |
| 58 | +[x] 52. GitHub API base overridden (e.g. GitHub Enterprise) used for requests |
| 59 | +[x] 53. guild_id as string numeric accepted |
| 60 | +[x] 54. guild_id with leading zeros (if any) behavior |
| 61 | +[x] 55. repos.mode allow with empty names fails validation |
| 62 | +[x] 56. repos.mode deny with names filters repos |
| 63 | +[x] 57. repos.mode allow with names allows only those repos |
| 64 | +[x] 58. user_fallback true allows user repos when org repos fail |
| 65 | +[x] 59. user_fallback false uses only org repos |
| 66 | +[x] 60. github.permissions.read false prevents GitHub reads (run-once behavior) |
67 | 67 |
|
68 | 68 | ## 2. CONFIGURATION VALIDATION (Items 61-150) |
69 | 69 |
|
70 | 70 | ### 2.1 Runtime |
71 | | -[ ] 61. runtime.mode required |
72 | | -[ ] 62. runtime.log_level default INFO |
73 | | -[ ] 63. runtime.data_dir required |
74 | | -[ ] 64. runtime.github_adapter required |
75 | | -[ ] 65. runtime.discord_adapter required |
76 | | -[ ] 66. runtime.storage_adapter required |
77 | | -[ ] 67. runtime with extra keys (ignore or error per implementation) |
| 71 | +[x] 61. runtime.mode required |
| 72 | +[x] 62. runtime.log_level default INFO |
| 73 | +[x] 63. runtime.data_dir required |
| 74 | +[x] 64. runtime.github_adapter required |
| 75 | +[x] 65. runtime.discord_adapter required |
| 76 | +[x] 66. runtime.storage_adapter required |
| 77 | +[x] 67. runtime with extra keys (ignore or error per implementation) |
78 | 78 |
|
79 | 79 | ### 2.2 GitHub |
80 | | -[ ] 68. github.org required |
81 | | -[ ] 69. github.token required |
82 | | -[ ] 70. github.api_base default https://api.github.com |
83 | | -[ ] 71. github.permissions.read default true |
84 | | -[ ] 72. github.permissions.write default false |
85 | | -[ ] 73. github.repos optional |
86 | | -[ ] 74. github.repos.mode only allow or deny |
87 | | -[ ] 75. github.repos.names non-empty when repos present |
| 80 | +[x] 68. github.org required |
| 81 | +[x] 69. github.token required |
| 82 | +[x] 70. github.api_base default https://api.github.com |
| 83 | +[x] 71. github.permissions.read default true |
| 84 | +[x] 72. github.permissions.write default false |
| 85 | +[x] 73. github.repos optional |
| 86 | +[x] 74. github.repos.mode only allow or deny |
| 87 | +[x] 75. github.repos.names non-empty when repos present |
88 | 88 |
|
89 | 89 | ### 2.3 Discord |
90 | | -[ ] 76. discord.guild_id required |
91 | | -[ ] 77. discord.token required |
92 | | -[ ] 78. discord.permissions.read default true |
93 | | -[ ] 79. discord.permissions.write default false |
94 | | -[ ] 80. discord.activity_channel_id optional null |
95 | | -[ ] 81. discord.pr_preview_channels optional list |
96 | | -[ ] 82. discord.notifications optional |
97 | | -[ ] 83. discord.notifications.enabled default true |
98 | | -[ ] 84. discord.notifications.issue_assignment default true |
99 | | -[ ] 85. discord.notifications.pr_review_requested default true |
100 | | -[ ] 86. discord.notifications.pr_review_result default true |
101 | | -[ ] 87. discord.notifications.pr_merged default true |
102 | | -[ ] 88. discord.notifications.channel_id optional null (DM) |
103 | | -[ ] 89. discord.notifications.coderabbit_reminders default false |
| 90 | +[x] 76. discord.guild_id required |
| 91 | +[x] 77. discord.token required |
| 92 | +[x] 78. discord.permissions.read default true |
| 93 | +[x] 79. discord.permissions.write default false |
| 94 | +[x] 80. discord.activity_channel_id optional null |
| 95 | +[x] 81. discord.pr_preview_channels optional list |
| 96 | +[x] 82. discord.notifications optional |
| 97 | +[x] 83. discord.notifications.enabled default true |
| 98 | +[x] 84. discord.notifications.issue_assignment default true |
| 99 | +[x] 85. discord.notifications.pr_review_requested default true |
| 100 | +[x] 86. discord.notifications.pr_review_result default true |
| 101 | +[x] 87. discord.notifications.pr_merged default true |
| 102 | +[x] 88. discord.notifications.channel_id optional null (DM) |
| 103 | +[x] 89. discord.notifications.coderabbit_reminders default false |
104 | 104 |
|
105 | 105 | ### 2.4 Scoring |
106 | | -[ ] 90. scoring.period_days required positive |
107 | | -[ ] 91. scoring.period_days 0 or negative fails |
108 | | -[ ] 92. scoring.weights required |
109 | | -[ ] 93. scoring.weights.issue_opened used |
110 | | -[ ] 94. scoring.weights.pr_opened used |
111 | | -[ ] 95. scoring.weights.pr_reviewed used |
112 | | -[ ] 96. scoring.weights.comment used |
113 | | -[ ] 97. scoring.difficulty_weights optional |
114 | | -[ ] 98. scoring.difficulty_weights negative value fails |
115 | | -[ ] 99. scoring.quality_adjustments optional |
116 | | -[ ] 100. scoring.quality_adjustments.penalties integer values |
| 106 | +[x] 90. scoring.period_days required positive |
| 107 | +[x] 91. scoring.period_days 0 or negative fails |
| 108 | +[x] 92. scoring.weights required |
| 109 | +[x] 93. scoring.weights.issue_opened used |
| 110 | +[x] 94. scoring.weights.pr_opened used |
| 111 | +[x] 95. scoring.weights.pr_reviewed used |
| 112 | +[x] 96. scoring.weights.comment used |
| 113 | +[x] 97. scoring.difficulty_weights optional |
| 114 | +[x] 98. scoring.difficulty_weights negative value fails |
| 115 | +[x] 99. scoring.quality_adjustments optional |
| 116 | +[x] 100. scoring.quality_adjustments.penalties integer values |
117 | 117 |
|
118 | 118 | ### 2.5 Roles & Assignments |
119 | | -[ ] 101. role_mappings required non-empty |
120 | | -[ ] 102. role_mappings[].discord_role required |
121 | | -[ ] 103. role_mappings[].min_score default 0 |
122 | | -[ ] 104. assignments.review_roles list |
123 | | -[ ] 105. assignments.issue_assignees list (mentor roles) |
124 | | -[ ] 106. assignments.issue_request_eligible_roles list |
125 | | -[ ] 107. merge_role_rules optional |
126 | | -[ ] 108. merge_role_rules.enabled default false |
127 | | -[ ] 109. merge_role_rules.rules[].discord_role required |
128 | | -[ ] 110. merge_role_rules.rules[].min_merged_prs non-negative |
129 | | -[ ] 111. identity_mappings optional list |
130 | | -[ ] 112. identity_mappings[].github_user required |
131 | | -[ ] 113. identity_mappings[].discord_user_id required |
132 | | -[ ] 114. identity.unlink_cooldown_hours optional default 24 |
133 | | -[ ] 115. identity.unlink_cooldown_hours negative fails |
134 | | -[ ] 116. identity.verified_max_age_days optional |
135 | | -[ ] 117. identity.verified_max_age_days positive when set |
136 | | -[ ] 118. snapshots optional |
137 | | -[ ] 119. snapshots.enabled default false |
138 | | -[ ] 120. snapshots.repo_path format owner/repo |
139 | | -[ ] 121. snapshots.branch optional |
140 | | -[ ] 122. Extra top-level keys in config (ignore or error) |
141 | | -[ ] 123. Empty role_mappings fails validation |
142 | | -[ ] 124. Duplicate discord_role in role_mappings allowed or documented |
143 | | -[ ] 125. Duplicate discord_role in merge_role_rules allowed or documented |
144 | | -[ ] 126. issue_assignees empty: mentor commands still exist but no one can run (check behavior) |
145 | | -[ ] 127. issue_request_eligible_roles empty: any verified user eligible (documented) |
146 | | -[ ] 128. issue_request_eligible_roles non-empty: only those roles eligible |
147 | | -[ ] 129. review_roles empty: no review assignment plans |
148 | | -[ ] 130. All notification flags false: no notifications sent |
149 | | -[ ] 131. pr_preview_channels empty: no PR preview on message |
150 | | -[ ] 132. pr_preview_channels with name: only that channel triggers preview |
151 | | -[ ] 133. activity_channel_id set: run-once can post summary (if implemented) |
152 | | -[ ] 134. Config file with tabs instead of spaces (YAML allows?) |
153 | | -[ ] 135. Config file with Windows line endings |
154 | | -[ ] 136. Config file with BOM |
155 | | -[ ] 137. Very long org name |
156 | | -[ ] 138. Org name with special characters |
157 | | -[ ] 139. repo_path with typo (wrong repo) - snapshot write fails gracefully |
158 | | -[ ] 140. branch with typo - snapshot write fails gracefully |
159 | | -[ ] 141. Multiple identity_mappings for same discord_user_id (last wins or documented) |
160 | | -[ ] 142. Multiple identity_mappings for same github_user (allowed or not) |
161 | | -[ ] 143. Discord role name with spaces |
162 | | -[ ] 144. Discord role name with special characters |
163 | | -[ ] 145. Discord role that doesn't exist on server - role add/remove no-op or error |
164 | | -[ ] 146. min_score negative in role_mappings (if allowed) |
165 | | -[ ] 147. weights with zero values |
166 | | -[ ] 148. weights with negative values (if allowed) |
167 | | -[ ] 149. period_days very large (e.g. 3650) |
168 | | -[ ] 150. period_days 1 |
| 119 | +[x] 101. role_mappings required non-empty |
| 120 | +[x] 102. role_mappings[].discord_role required |
| 121 | +[x] 103. role_mappings[].min_score default 0 |
| 122 | +[x] 104. assignments.review_roles list |
| 123 | +[x] 105. assignments.issue_assignees list (mentor roles) |
| 124 | +[x] 106. assignments.issue_request_eligible_roles list |
| 125 | +[x] 107. merge_role_rules optional |
| 126 | +[x] 108. merge_role_rules.enabled default false |
| 127 | +[x] 109. merge_role_rules.rules[].discord_role required |
| 128 | +[x] 110. merge_role_rules.rules[].min_merged_prs non-negative |
| 129 | +[x] 111. identity_mappings optional list |
| 130 | +[x] 112. identity_mappings[].github_user required |
| 131 | +[x] 113. identity_mappings[].discord_user_id required |
| 132 | +[x] 114. identity.unlink_cooldown_hours optional default 24 |
| 133 | +[x] 115. identity.unlink_cooldown_hours negative fails |
| 134 | +[x] 116. identity.verified_max_age_days optional |
| 135 | +[x] 117. identity.verified_max_age_days positive when set |
| 136 | +[x] 118. snapshots optional |
| 137 | +[x] 119. snapshots.enabled default false |
| 138 | +[x] 120. snapshots.repo_path format owner/repo |
| 139 | +[x] 121. snapshots.branch optional |
| 140 | +[x] 122. Extra top-level keys in config (ignore or error) |
| 141 | +[x] 123. Empty role_mappings fails validation |
| 142 | +[x] 124. Duplicate discord_role in role_mappings allowed or documented |
| 143 | +[x] 125. Duplicate discord_role in merge_role_rules allowed or documented |
| 144 | +[x] 126. issue_assignees empty: mentor commands still exist but no one can run (check behavior) |
| 145 | +[x] 127. issue_request_eligible_roles empty: any verified user eligible (documented) |
| 146 | +[x] 128. issue_request_eligible_roles non-empty: only those roles eligible |
| 147 | +[x] 129. review_roles empty: no review assignment plans |
| 148 | +[x] 130. All notification flags false: no notifications sent |
| 149 | +[x] 131. pr_preview_channels empty: no PR preview on message |
| 150 | +[x] 132. pr_preview_channels with name: only that channel triggers preview |
| 151 | +[x] 133. activity_channel_id set: run-once can post summary (if implemented) |
| 152 | +[x] 134. Config file with tabs instead of spaces (YAML allows?) |
| 153 | +[x] 135. Config file with Windows line endings |
| 154 | +[x] 136. Config file with BOM |
| 155 | +[x] 137. Very long org name |
| 156 | +[x] 138. Org name with special characters |
| 157 | +[x] 139. repo_path with typo (wrong repo) - snapshot write fails gracefully |
| 158 | +[x] 140. branch with typo - snapshot write fails gracefully |
| 159 | +[x] 141. Multiple identity_mappings for same discord_user_id (last wins or documented) |
| 160 | +[x] 142. Multiple identity_mappings for same github_user (allowed or not) |
| 161 | +[x] 143. Discord role name with spaces |
| 162 | +[x] 144. Discord role name with special characters |
| 163 | +[x] 145. Discord role that doesn't exist on server - role add/remove no-op or error |
| 164 | +[x] 146. min_score negative in role_mappings (if allowed) |
| 165 | +[x] 147. weights with zero values |
| 166 | +[x] 148. weights with negative values (if allowed) |
| 167 | +[x] 149. period_days very large (e.g. 3650) |
| 168 | +[x] 150. period_days 1 |
169 | 169 |
|
170 | 170 | ## 3. /link COMMAND (Items 151-230) |
171 | 171 |
|
|
0 commit comments