@laitszkin/apollo-toolkit 3.13.2 → 3.14.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/AGENTS.md +7 -7
- package/CHANGELOG.md +27 -0
- package/CLAUDE.md +8 -8
- package/analyse-app-logs/SKILL.md +3 -3
- package/bin/apollo-toolkit.ts +7 -0
- package/codex/codex-memory-manager/SKILL.md +2 -2
- package/codex/learn-skill-from-conversations/SKILL.md +3 -3
- package/dist/bin/apollo-toolkit.d.ts +2 -0
- package/dist/bin/apollo-toolkit.js +7 -0
- package/dist/lib/cli.d.ts +41 -0
- package/dist/lib/cli.js +655 -0
- package/dist/lib/installer.d.ts +59 -0
- package/dist/lib/installer.js +404 -0
- package/dist/lib/tool-runner.d.ts +19 -0
- package/dist/lib/tool-runner.js +536 -0
- package/dist/lib/tools/architecture.d.ts +2 -0
- package/dist/lib/tools/architecture.js +34 -0
- package/dist/lib/tools/create-specs.d.ts +2 -0
- package/dist/lib/tools/create-specs.js +175 -0
- package/dist/lib/tools/docs-to-voice.d.ts +2 -0
- package/dist/lib/tools/docs-to-voice.js +705 -0
- package/dist/lib/tools/enforce-video-aspect-ratio.d.ts +2 -0
- package/dist/lib/tools/enforce-video-aspect-ratio.js +312 -0
- package/dist/lib/tools/extract-conversations.d.ts +2 -0
- package/dist/lib/tools/extract-conversations.js +105 -0
- package/dist/lib/tools/extract-pdf-text.d.ts +2 -0
- package/dist/lib/tools/extract-pdf-text.js +92 -0
- package/dist/lib/tools/filter-logs.d.ts +2 -0
- package/dist/lib/tools/filter-logs.js +94 -0
- package/dist/lib/tools/find-github-issues.d.ts +2 -0
- package/dist/lib/tools/find-github-issues.js +176 -0
- package/dist/lib/tools/generate-storyboard-images.d.ts +2 -0
- package/dist/lib/tools/generate-storyboard-images.js +419 -0
- package/dist/lib/tools/log-cli-utils.d.ts +35 -0
- package/dist/lib/tools/log-cli-utils.js +233 -0
- package/dist/lib/tools/open-github-issue.d.ts +2 -0
- package/dist/lib/tools/open-github-issue.js +750 -0
- package/dist/lib/tools/read-github-issue.d.ts +2 -0
- package/dist/lib/tools/read-github-issue.js +134 -0
- package/dist/lib/tools/render-error-book.d.ts +2 -0
- package/dist/lib/tools/render-error-book.js +265 -0
- package/dist/lib/tools/render-katex.d.ts +2 -0
- package/dist/lib/tools/render-katex.js +294 -0
- package/dist/lib/tools/review-threads.d.ts +2 -0
- package/dist/lib/tools/review-threads.js +491 -0
- package/dist/lib/tools/search-logs.d.ts +2 -0
- package/dist/lib/tools/search-logs.js +164 -0
- package/dist/lib/tools/sync-memory-index.d.ts +2 -0
- package/dist/lib/tools/sync-memory-index.js +113 -0
- package/dist/lib/tools/validate-openai-agent-config.d.ts +2 -0
- package/dist/lib/tools/validate-openai-agent-config.js +184 -0
- package/dist/lib/tools/validate-skill-frontmatter.d.ts +2 -0
- package/dist/lib/tools/validate-skill-frontmatter.js +118 -0
- package/dist/lib/types.d.ts +82 -0
- package/dist/lib/types.js +2 -0
- package/dist/lib/updater.d.ts +34 -0
- package/dist/lib/updater.js +112 -0
- package/dist/lib/utils/format.d.ts +2 -0
- package/dist/lib/utils/format.js +6 -0
- package/dist/lib/utils/terminal.d.ts +12 -0
- package/dist/lib/utils/terminal.js +26 -0
- package/docs-to-voice/SKILL.md +0 -1
- package/generate-spec/SKILL.md +1 -1
- package/katex/SKILL.md +1 -2
- package/lib/cli.ts +780 -0
- package/lib/installer.ts +466 -0
- package/lib/tool-runner.ts +561 -0
- package/lib/tools/architecture.ts +34 -0
- package/lib/tools/create-specs.ts +204 -0
- package/lib/tools/docs-to-voice.ts +799 -0
- package/lib/tools/enforce-video-aspect-ratio.ts +368 -0
- package/lib/tools/extract-conversations.ts +114 -0
- package/lib/tools/extract-pdf-text.ts +99 -0
- package/lib/tools/filter-logs.ts +118 -0
- package/lib/tools/find-github-issues.ts +211 -0
- package/lib/tools/generate-storyboard-images.ts +455 -0
- package/lib/tools/log-cli-utils.ts +262 -0
- package/lib/tools/open-github-issue.ts +930 -0
- package/lib/tools/read-github-issue.ts +179 -0
- package/lib/tools/render-error-book.ts +300 -0
- package/lib/tools/render-katex.ts +325 -0
- package/lib/tools/review-threads.ts +590 -0
- package/lib/tools/search-logs.ts +200 -0
- package/lib/tools/sync-memory-index.ts +114 -0
- package/lib/tools/validate-openai-agent-config.ts +209 -0
- package/lib/tools/validate-skill-frontmatter.ts +124 -0
- package/lib/types.ts +90 -0
- package/lib/updater.ts +165 -0
- package/lib/utils/format.ts +7 -0
- package/lib/utils/terminal.ts +22 -0
- package/open-github-issue/SKILL.md +2 -2
- package/optimise-skill/SKILL.md +1 -1
- package/package.json +13 -4
- package/resources/project-architecture/assets/architecture.css +764 -0
- package/resources/project-architecture/assets/viewer.client.js +144 -0
- package/resources/project-architecture/index.html +42 -0
- package/review-spec-related-changes/SKILL.md +1 -1
- package/solve-issues-found-during-review/SKILL.md +2 -1
- package/tsconfig.json +28 -0
- package/analyse-app-logs/scripts/__pycache__/filter_logs_by_time.cpython-312.pyc +0 -0
- package/analyse-app-logs/scripts/__pycache__/log_cli_utils.cpython-312.pyc +0 -0
- package/analyse-app-logs/scripts/__pycache__/search_logs.cpython-312.pyc +0 -0
- package/analyse-app-logs/scripts/filter_logs_by_time.py +0 -64
- package/analyse-app-logs/scripts/log_cli_utils.py +0 -112
- package/analyse-app-logs/scripts/search_logs.py +0 -137
- package/analyse-app-logs/tests/test_filter_logs_by_time.py +0 -95
- package/analyse-app-logs/tests/test_search_logs.py +0 -100
- package/codex/codex-memory-manager/scripts/extract_recent_conversations.py +0 -369
- package/codex/codex-memory-manager/scripts/sync_memory_index.py +0 -130
- package/codex/codex-memory-manager/tests/test_extract_recent_conversations.py +0 -177
- package/codex/codex-memory-manager/tests/test_memory_template.py +0 -37
- package/codex/codex-memory-manager/tests/test_sync_memory_index.py +0 -84
- package/codex/learn-skill-from-conversations/scripts/extract_recent_conversations.py +0 -369
- package/codex/learn-skill-from-conversations/tests/test_extract_recent_conversations.py +0 -177
- package/docs-to-voice/scripts/__pycache__/docs_to_voice.cpython-312.pyc +0 -0
- package/docs-to-voice/scripts/docs_to_voice.py +0 -1385
- package/docs-to-voice/scripts/docs_to_voice.sh +0 -11
- package/docs-to-voice/tests/test_docs_to_voice_api_max_chars.py +0 -210
- package/docs-to-voice/tests/test_docs_to_voice_sentence_timeline.py +0 -115
- package/docs-to-voice/tests/test_docs_to_voice_settings.py +0 -43
- package/docs-to-voice/tests/test_docs_to_voice_shell_wrapper.py +0 -51
- package/docs-to-voice/tests/test_docs_to_voice_speech_rate.py +0 -57
- package/generate-spec/scripts/__pycache__/create-specscpython-312.pyc +0 -0
- package/generate-spec/scripts/create-specs +0 -215
- package/generate-spec/tests/test_create_specs.py +0 -200
- package/init-project-html/scripts/architecture-bootstrap-render.js +0 -16
- package/init-project-html/scripts/architecture.js +0 -296
- package/katex/scripts/__pycache__/render_katex.cpython-312.pyc +0 -0
- package/katex/scripts/render_katex.py +0 -247
- package/katex/scripts/render_katex.sh +0 -11
- package/katex/tests/test_render_katex.py +0 -174
- package/learning-error-book/scripts/render_error_book_json_to_pdf.py +0 -590
- package/learning-error-book/tests/test_render_error_book_json_to_pdf.py +0 -134
- package/open-github-issue/scripts/__pycache__/open_github_issue.cpython-312.pyc +0 -0
- package/open-github-issue/scripts/open_github_issue.py +0 -705
- package/open-github-issue/tests/test_open_github_issue.py +0 -381
- package/openai-text-to-image-storyboard/scripts/generate_storyboard_images.py +0 -763
- package/openai-text-to-image-storyboard/tests/test_generate_storyboard_images.py +0 -177
- package/read-github-issue/scripts/__pycache__/find_issues.cpython-312.pyc +0 -0
- package/read-github-issue/scripts/__pycache__/read_issue.cpython-312.pyc +0 -0
- package/read-github-issue/scripts/find_issues.py +0 -148
- package/read-github-issue/scripts/read_issue.py +0 -108
- package/read-github-issue/tests/test_find_issues.py +0 -127
- package/read-github-issue/tests/test_read_issue.py +0 -109
- package/resolve-review-comments/scripts/__pycache__/review_threads.cpython-312.pyc +0 -0
- package/resolve-review-comments/scripts/review_threads.py +0 -425
- package/resolve-review-comments/tests/test_review_threads.py +0 -74
- package/scripts/validate_openai_agent_config.py +0 -209
- package/scripts/validate_skill_frontmatter.py +0 -131
- package/text-to-short-video/scripts/__pycache__/enforce_video_aspect_ratio.cpython-312.pyc +0 -0
- package/text-to-short-video/scripts/enforce_video_aspect_ratio.py +0 -350
- package/text-to-short-video/tests/test_enforce_video_aspect_ratio.py +0 -194
- package/weekly-financial-event-report/scripts/extract_pdf_text_pdfkit.swift +0 -99
- package/weekly-financial-event-report/tests/test_extract_pdf_text_pdfkit.py +0 -64
|
@@ -1,381 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import importlib.util
|
|
6
|
-
import io
|
|
7
|
-
import json
|
|
8
|
-
import tempfile
|
|
9
|
-
import unittest
|
|
10
|
-
from argparse import Namespace
|
|
11
|
-
from pathlib import Path
|
|
12
|
-
from unittest.mock import patch
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
SCRIPT_PATH = Path(__file__).resolve().parents[1] / "scripts" / "open_github_issue.py"
|
|
16
|
-
SPEC = importlib.util.spec_from_file_location("open_github_issue", SCRIPT_PATH)
|
|
17
|
-
MODULE = importlib.util.module_from_spec(SPEC)
|
|
18
|
-
SPEC.loader.exec_module(MODULE)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class OpenGitHubIssueTests(unittest.TestCase):
|
|
22
|
-
def test_validate_repo_rejects_invalid_format(self) -> None:
|
|
23
|
-
with self.assertRaises(SystemExit):
|
|
24
|
-
MODULE.validate_repo("owner-only")
|
|
25
|
-
|
|
26
|
-
def test_hydrate_args_loads_payload_file_with_literal_backticks(self) -> None:
|
|
27
|
-
with tempfile.TemporaryDirectory() as temp_dir:
|
|
28
|
-
payload_path = Path(temp_dir) / "issue.json"
|
|
29
|
-
payload_path.write_text(
|
|
30
|
-
json.dumps(
|
|
31
|
-
{
|
|
32
|
-
"title": "[Log] backticks",
|
|
33
|
-
"issue_type": MODULE.ISSUE_TYPE_PROBLEM,
|
|
34
|
-
"problem_description": (
|
|
35
|
-
"Expected Behavior (BDD)\n"
|
|
36
|
-
"Given markdown content contains code spans\n"
|
|
37
|
-
"When the issue is published\n"
|
|
38
|
-
"Then `printf should_not_run` remains literal\n\n"
|
|
39
|
-
"Current Behavior (BDD)\n"
|
|
40
|
-
"Given markdown content contains code spans\n"
|
|
41
|
-
"When the issue is published\n"
|
|
42
|
-
"Then `printf should_not_run` can be eaten by shell quoting\n\n"
|
|
43
|
-
"Behavior Gap\n"
|
|
44
|
-
"- Expected: `printf should_not_run` survives.\n"
|
|
45
|
-
"- Actual: inline shell args are fragile.\n"
|
|
46
|
-
"- Difference/Impact: issue evidence can be corrupted.\n"
|
|
47
|
-
),
|
|
48
|
-
"suspected_cause": "Shell command substitution happens before Python receives argv.",
|
|
49
|
-
}
|
|
50
|
-
),
|
|
51
|
-
encoding="utf-8",
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
args = Namespace(
|
|
55
|
-
payload_file=str(payload_path),
|
|
56
|
-
title=None,
|
|
57
|
-
issue_type=None,
|
|
58
|
-
problem_description=None,
|
|
59
|
-
suspected_cause=None,
|
|
60
|
-
reproduction=None,
|
|
61
|
-
proposal=None,
|
|
62
|
-
reason=None,
|
|
63
|
-
suggested_architecture=None,
|
|
64
|
-
impact=None,
|
|
65
|
-
evidence=None,
|
|
66
|
-
suggested_action=None,
|
|
67
|
-
severity=None,
|
|
68
|
-
affected_scope=None,
|
|
69
|
-
repo=None,
|
|
70
|
-
dry_run=False,
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
hydrated = MODULE.hydrate_args(args)
|
|
74
|
-
|
|
75
|
-
self.assertEqual(hydrated.title, "[Log] backticks")
|
|
76
|
-
self.assertIn("`printf should_not_run` remains literal", hydrated.problem_description)
|
|
77
|
-
self.assertEqual(hydrated.issue_type, MODULE.ISSUE_TYPE_PROBLEM)
|
|
78
|
-
|
|
79
|
-
def test_hydrate_args_reads_at_file_text_values(self) -> None:
|
|
80
|
-
with tempfile.TemporaryDirectory() as temp_dir:
|
|
81
|
-
description_path = Path(temp_dir) / "description.md"
|
|
82
|
-
description_path.write_text(
|
|
83
|
-
"Expected Behavior (BDD)\n"
|
|
84
|
-
"Given a markdown file contains backticks\n"
|
|
85
|
-
"When it is loaded with @file syntax\n"
|
|
86
|
-
"Then `literal` content survives\n\n"
|
|
87
|
-
"Current Behavior (BDD)\n"
|
|
88
|
-
"Given a markdown file contains backticks\n"
|
|
89
|
-
"When inline shell args are avoided\n"
|
|
90
|
-
"Then `literal` content reaches argparse unchanged\n\n"
|
|
91
|
-
"Behavior Gap\n"
|
|
92
|
-
"- Expected: file content is safe.\n"
|
|
93
|
-
"- Actual: inline shell content is fragile.\n"
|
|
94
|
-
"- Difference/Impact: safer invocation is needed.\n",
|
|
95
|
-
encoding="utf-8",
|
|
96
|
-
)
|
|
97
|
-
args = Namespace(
|
|
98
|
-
payload_file=None,
|
|
99
|
-
title="[Log] @file",
|
|
100
|
-
issue_type=MODULE.ISSUE_TYPE_PROBLEM,
|
|
101
|
-
problem_description=f"@{description_path}",
|
|
102
|
-
suspected_cause="Use @file for rich text fields.",
|
|
103
|
-
reproduction=None,
|
|
104
|
-
proposal=None,
|
|
105
|
-
reason=None,
|
|
106
|
-
suggested_architecture=None,
|
|
107
|
-
impact=None,
|
|
108
|
-
evidence=None,
|
|
109
|
-
suggested_action=None,
|
|
110
|
-
severity=None,
|
|
111
|
-
affected_scope=None,
|
|
112
|
-
repo="owner/repo",
|
|
113
|
-
dry_run=True,
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
hydrated = MODULE.hydrate_args(args)
|
|
117
|
-
|
|
118
|
-
self.assertIn("Then `literal` content survives", hydrated.problem_description)
|
|
119
|
-
|
|
120
|
-
def test_detect_issue_language_prefers_chinese_when_threshold_met(self) -> None:
|
|
121
|
-
readme = "這是一個中文專案說明。" * 10
|
|
122
|
-
|
|
123
|
-
self.assertEqual(MODULE.detect_issue_language(readme), "zh")
|
|
124
|
-
|
|
125
|
-
def test_detect_issue_language_defaults_to_english_for_sparse_chinese(self) -> None:
|
|
126
|
-
readme = "English README with only 少量中文 and mostly latin text." * 2
|
|
127
|
-
|
|
128
|
-
self.assertEqual(MODULE.detect_issue_language(readme), "en")
|
|
129
|
-
|
|
130
|
-
def test_build_issue_body_uses_default_reproduction_text(self) -> None:
|
|
131
|
-
zh_body = MODULE.build_issue_body(
|
|
132
|
-
issue_type=MODULE.ISSUE_TYPE_PROBLEM,
|
|
133
|
-
language="zh",
|
|
134
|
-
title="[Log] 問題",
|
|
135
|
-
problem_description="問題",
|
|
136
|
-
suspected_cause="原因",
|
|
137
|
-
reproduction=None,
|
|
138
|
-
proposal=None,
|
|
139
|
-
reason=None,
|
|
140
|
-
suggested_architecture=None,
|
|
141
|
-
)
|
|
142
|
-
en_body = MODULE.build_issue_body(
|
|
143
|
-
issue_type=MODULE.ISSUE_TYPE_PROBLEM,
|
|
144
|
-
language="en",
|
|
145
|
-
title="[Log] problem",
|
|
146
|
-
problem_description="problem",
|
|
147
|
-
suspected_cause="cause",
|
|
148
|
-
reproduction=None,
|
|
149
|
-
proposal=None,
|
|
150
|
-
reason=None,
|
|
151
|
-
suggested_architecture=None,
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
self.assertIn(MODULE.DEFAULT_REPRO_ZH, zh_body)
|
|
155
|
-
self.assertIn(MODULE.DEFAULT_REPRO_EN, en_body)
|
|
156
|
-
|
|
157
|
-
def test_build_issue_body_supports_feature_issue_sections(self) -> None:
|
|
158
|
-
zh_body = MODULE.build_issue_body(
|
|
159
|
-
issue_type=MODULE.ISSUE_TYPE_FEATURE,
|
|
160
|
-
language="zh",
|
|
161
|
-
title="[Feature] 匯出事故時間線",
|
|
162
|
-
problem_description=None,
|
|
163
|
-
suspected_cause=None,
|
|
164
|
-
reproduction=None,
|
|
165
|
-
proposal="新增事故時間線匯出功能",
|
|
166
|
-
reason="減少手動整理 postmortem 成本",
|
|
167
|
-
suggested_architecture="重用時間線查詢服務,新增共用匯出模組",
|
|
168
|
-
)
|
|
169
|
-
en_body = MODULE.build_issue_body(
|
|
170
|
-
issue_type=MODULE.ISSUE_TYPE_FEATURE,
|
|
171
|
-
language="en",
|
|
172
|
-
title="[Feature] Export incident timeline",
|
|
173
|
-
problem_description=None,
|
|
174
|
-
suspected_cause=None,
|
|
175
|
-
reproduction=None,
|
|
176
|
-
proposal="Allow exporting incident timelines",
|
|
177
|
-
reason="Support postmortem handoff",
|
|
178
|
-
suggested_architecture="Add shared exporters and UI action",
|
|
179
|
-
impact=None,
|
|
180
|
-
evidence=None,
|
|
181
|
-
suggested_action=None,
|
|
182
|
-
severity=None,
|
|
183
|
-
affected_scope=None,
|
|
184
|
-
)
|
|
185
|
-
|
|
186
|
-
self.assertIn("### 功能提案", zh_body)
|
|
187
|
-
self.assertIn("### 建議架構", zh_body)
|
|
188
|
-
self.assertIn("### Feature Proposal", en_body)
|
|
189
|
-
self.assertIn("### Suggested Architecture", en_body)
|
|
190
|
-
|
|
191
|
-
def test_build_issue_body_supports_security_issue_sections(self) -> None:
|
|
192
|
-
en_body = MODULE.build_issue_body(
|
|
193
|
-
issue_type=MODULE.ISSUE_TYPE_SECURITY,
|
|
194
|
-
language="en",
|
|
195
|
-
title="[Security] Missing auth",
|
|
196
|
-
problem_description="Endpoint misses admin check",
|
|
197
|
-
suspected_cause=None,
|
|
198
|
-
reproduction=None,
|
|
199
|
-
proposal=None,
|
|
200
|
-
reason=None,
|
|
201
|
-
suggested_architecture=None,
|
|
202
|
-
impact="Sensitive export may leak",
|
|
203
|
-
evidence="Reproduced request and code path review",
|
|
204
|
-
suggested_action="Add authz and tests",
|
|
205
|
-
severity="high",
|
|
206
|
-
affected_scope="/admin/export",
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
self.assertIn("### Security Risk", en_body)
|
|
210
|
-
self.assertIn("### Severity", en_body)
|
|
211
|
-
self.assertIn("### Suggested Mitigation", en_body)
|
|
212
|
-
|
|
213
|
-
def test_validate_issue_content_args_requires_feature_fields(self) -> None:
|
|
214
|
-
with self.assertRaises(SystemExit):
|
|
215
|
-
MODULE.validate_issue_content_args(
|
|
216
|
-
Namespace(
|
|
217
|
-
issue_type=MODULE.ISSUE_TYPE_FEATURE,
|
|
218
|
-
reason="",
|
|
219
|
-
suggested_architecture="shared module",
|
|
220
|
-
problem_description=None,
|
|
221
|
-
suspected_cause=None,
|
|
222
|
-
)
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
with self.assertRaises(SystemExit):
|
|
226
|
-
MODULE.validate_issue_content_args(
|
|
227
|
-
Namespace(
|
|
228
|
-
issue_type=MODULE.ISSUE_TYPE_FEATURE,
|
|
229
|
-
reason="important now",
|
|
230
|
-
suggested_architecture="",
|
|
231
|
-
problem_description=None,
|
|
232
|
-
suspected_cause=None,
|
|
233
|
-
)
|
|
234
|
-
)
|
|
235
|
-
|
|
236
|
-
MODULE.validate_issue_content_args(
|
|
237
|
-
Namespace(
|
|
238
|
-
issue_type=MODULE.ISSUE_TYPE_FEATURE,
|
|
239
|
-
reason="important now",
|
|
240
|
-
suggested_architecture="shared module",
|
|
241
|
-
problem_description=None,
|
|
242
|
-
suspected_cause=None,
|
|
243
|
-
impact=None,
|
|
244
|
-
evidence=None,
|
|
245
|
-
suggested_action=None,
|
|
246
|
-
severity=None,
|
|
247
|
-
affected_scope=None,
|
|
248
|
-
)
|
|
249
|
-
)
|
|
250
|
-
|
|
251
|
-
def test_validate_issue_content_args_requires_security_fields(self) -> None:
|
|
252
|
-
with self.assertRaises(SystemExit):
|
|
253
|
-
MODULE.validate_issue_content_args(
|
|
254
|
-
Namespace(
|
|
255
|
-
issue_type=MODULE.ISSUE_TYPE_SECURITY,
|
|
256
|
-
problem_description="auth missing",
|
|
257
|
-
affected_scope="",
|
|
258
|
-
impact="sensitive export may leak",
|
|
259
|
-
evidence="reproduced",
|
|
260
|
-
suggested_action="add authz",
|
|
261
|
-
severity="high",
|
|
262
|
-
reason=None,
|
|
263
|
-
suggested_architecture=None,
|
|
264
|
-
suspected_cause=None,
|
|
265
|
-
)
|
|
266
|
-
)
|
|
267
|
-
|
|
268
|
-
MODULE.validate_issue_content_args(
|
|
269
|
-
Namespace(
|
|
270
|
-
issue_type=MODULE.ISSUE_TYPE_SECURITY,
|
|
271
|
-
problem_description="auth missing",
|
|
272
|
-
affected_scope="/admin/export",
|
|
273
|
-
impact="sensitive export may leak",
|
|
274
|
-
evidence="reproduced",
|
|
275
|
-
suggested_action="add authz",
|
|
276
|
-
severity="high",
|
|
277
|
-
reason=None,
|
|
278
|
-
suggested_architecture=None,
|
|
279
|
-
suspected_cause=None,
|
|
280
|
-
)
|
|
281
|
-
)
|
|
282
|
-
|
|
283
|
-
def test_validate_issue_content_args_requires_problem_bdd_sections(self) -> None:
|
|
284
|
-
with self.assertRaises(SystemExit):
|
|
285
|
-
MODULE.validate_issue_content_args(
|
|
286
|
-
Namespace(
|
|
287
|
-
issue_type=MODULE.ISSUE_TYPE_PROBLEM,
|
|
288
|
-
reason=None,
|
|
289
|
-
suggested_architecture=None,
|
|
290
|
-
problem_description="Repeated timeout warnings escalated into request failures.",
|
|
291
|
-
suspected_cause="handler.py:12",
|
|
292
|
-
impact=None,
|
|
293
|
-
evidence=None,
|
|
294
|
-
suggested_action=None,
|
|
295
|
-
severity=None,
|
|
296
|
-
affected_scope=None,
|
|
297
|
-
)
|
|
298
|
-
)
|
|
299
|
-
|
|
300
|
-
MODULE.validate_issue_content_args(
|
|
301
|
-
Namespace(
|
|
302
|
-
issue_type=MODULE.ISSUE_TYPE_PROBLEM,
|
|
303
|
-
reason=None,
|
|
304
|
-
suggested_architecture=None,
|
|
305
|
-
problem_description=(
|
|
306
|
-
"Expected Behavior (BDD)\n"
|
|
307
|
-
"Given requests arrive during transient upstream latency\n"
|
|
308
|
-
"When the retry path runs\n"
|
|
309
|
-
"Then the request should recover without user-visible failure\n\n"
|
|
310
|
-
"Current Behavior (BDD)\n"
|
|
311
|
-
"Given requests arrive during transient upstream latency\n"
|
|
312
|
-
"When the retry path runs\n"
|
|
313
|
-
"Then the request still fails after immediate retries\n\n"
|
|
314
|
-
"Behavior Gap\n"
|
|
315
|
-
"- Expected: retries absorb transient slowness.\n"
|
|
316
|
-
"- Actual: retries amplify failures.\n"
|
|
317
|
-
"- Difference/Impact: users still receive errors.\n"
|
|
318
|
-
),
|
|
319
|
-
suspected_cause="handler.py:12",
|
|
320
|
-
impact=None,
|
|
321
|
-
evidence=None,
|
|
322
|
-
suggested_action=None,
|
|
323
|
-
severity=None,
|
|
324
|
-
affected_scope=None,
|
|
325
|
-
)
|
|
326
|
-
)
|
|
327
|
-
|
|
328
|
-
def test_main_dry_run_returns_structured_json_without_publish_attempt(self) -> None:
|
|
329
|
-
args = Namespace(
|
|
330
|
-
title="[Log] sample",
|
|
331
|
-
issue_type=MODULE.ISSUE_TYPE_PROBLEM,
|
|
332
|
-
problem_description=(
|
|
333
|
-
"Expected Behavior (BDD)\n"
|
|
334
|
-
"Given the issue is confirmed\n"
|
|
335
|
-
"When the issue body is rendered\n"
|
|
336
|
-
"Then the expected path should be explicit\n\n"
|
|
337
|
-
"Current Behavior (BDD)\n"
|
|
338
|
-
"Given the issue is confirmed\n"
|
|
339
|
-
"When the issue body is rendered\n"
|
|
340
|
-
"Then the current path should be explicit\n\n"
|
|
341
|
-
"Behavior Gap\n"
|
|
342
|
-
"- Expected: clear behavior diff.\n"
|
|
343
|
-
"- Actual: sample payload for dry run.\n"
|
|
344
|
-
"- Difference/Impact: contract stays structured.\n"
|
|
345
|
-
),
|
|
346
|
-
suspected_cause="handler.py:12",
|
|
347
|
-
reproduction=None,
|
|
348
|
-
proposal=None,
|
|
349
|
-
reason=None,
|
|
350
|
-
suggested_architecture=None,
|
|
351
|
-
repo="owner/repo",
|
|
352
|
-
dry_run=True,
|
|
353
|
-
impact=None,
|
|
354
|
-
evidence=None,
|
|
355
|
-
suggested_action=None,
|
|
356
|
-
severity=None,
|
|
357
|
-
affected_scope=None,
|
|
358
|
-
)
|
|
359
|
-
|
|
360
|
-
with patch.object(MODULE, "parse_args", return_value=args), patch.object(
|
|
361
|
-
MODULE, "has_gh_auth", return_value=False
|
|
362
|
-
), patch.object(MODULE, "get_token", return_value=None), patch.object(
|
|
363
|
-
MODULE, "fetch_remote_readme", return_value="中文說明" * 20
|
|
364
|
-
), patch.object(MODULE, "create_issue_with_gh") as create_with_gh, patch.object(
|
|
365
|
-
MODULE, "create_issue_with_token"
|
|
366
|
-
) as create_with_token, patch("sys.stdout", new_callable=io.StringIO) as stdout:
|
|
367
|
-
code = MODULE.main()
|
|
368
|
-
|
|
369
|
-
create_with_gh.assert_not_called()
|
|
370
|
-
create_with_token.assert_not_called()
|
|
371
|
-
self.assertEqual(code, 0)
|
|
372
|
-
|
|
373
|
-
payload = json.loads(stdout.getvalue())
|
|
374
|
-
self.assertEqual(payload["mode"], "dry-run")
|
|
375
|
-
self.assertEqual(payload["issue_type"], MODULE.ISSUE_TYPE_PROBLEM)
|
|
376
|
-
self.assertEqual(payload["language"], "zh")
|
|
377
|
-
self.assertIn("### 問題描述", payload["issue_body"])
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
if __name__ == "__main__":
|
|
381
|
-
unittest.main()
|