170
self.assertTrue(prompt_output_path.exists())
171
self.assertIn("Prefer durable signals.", prompt_output_path.read_text(encoding="utf-8"))
172
173
+ def test_main_handles_model_403_gracefully(self) -> None:
174
+ """When GitHub Models returns 403 (no model access), main exits 0 with a placeholder."""
175
+ tests_root = Path(__file__).resolve().parent
176
+ with tempfile.TemporaryDirectory(dir=tests_root) as tmpdir:
177
+ base = Path(tmpdir)
178
+ analyzed_dir = base / "data" / "analyzed"
179
+ snapshots_dir = base / "data" / "snapshots"
180
+ wisdom_path = base / ".squad" / "identity" / "wisdom.md"
181
+ skills_dir = base / ".squad" / "skills"
182
+ prompt_template = base / "reskill.md"
183
+ output_path = base / ".squad" / "reskill" / "2026-W21.md"
184
+ analyzed_dir.mkdir(parents=True)
185
+ snapshots_dir.mkdir(parents=True)
186
+ wisdom_path.parent.mkdir(parents=True)
187
+ skills_dir.mkdir(parents=True)
188
+ output_path.parent.mkdir(parents=True)
189
+ wisdom_path.write_text("# Wisdom\n\nPrefer durable signals.", encoding="utf-8")
190
+ prompt_template.write_text("{{WISDOM}}\n{{QUALITY_TREND}}", encoding="utf-8")
191
+
192
+ from urllib import error as urlerror
193
+ import io as _io
194
+
195
+ fake_body = _io.BytesIO(
196
+ b'{"error":{"code":"no_access","message":"No access to model: openai/gpt-4.1"}}'
197
+ )
198
+ http_err = urlerror.HTTPError(
199
+ url="https://models.github.ai",
200
+ code=403,
201
+ msg="Forbidden",
202
+ hdrs={}, # type: ignore[arg-type]
203
+ fp=fake_body,
204
+ )
205
+
206
+ with mock.patch.dict("os.environ", {"GITHUB_TOKEN": "token"}, clear=False), mock.patch.object(
207
+ reskill.request, "urlopen", side_effect=http_err
208
+ ):
209
+ exit_code = reskill.main(
210
+ [
211
+ "--current-datetime",
212
+ "2026-05-18T15:22:25.067+02:00",
213
+ "--prompt-template",
214
+ str(prompt_template),
215
+ "--analyzed-dir",
216
+ str(analyzed_dir),
217
+ "--snapshots-dir",
218
+ str(snapshots_dir),
219
+ "--wisdom-file",
220
+ str(wisdom_path),
221
+ "--skills-dir",
222
+ str(skills_dir),
223
+ "--output",
224
+ str(output_path),
225
+ ]
226
+ )
227
+
228
+ self.assertEqual(exit_code, 0)
229
+ content = output_path.read_text(encoding="utf-8")
230
+ self.assertIn("Reskill skipped", content)
231
+ self.assertIn("403", content)
232
+
233
234
if __name__ == "__main__":
235
unittest.main()