@laitszkin/apollo-toolkit 2.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.
Files changed (204) hide show
  1. package/AGENTS.md +62 -0
  2. package/CHANGELOG.md +100 -0
  3. package/LICENSE +21 -0
  4. package/README.md +144 -0
  5. package/align-project-documents/SKILL.md +94 -0
  6. package/align-project-documents/agents/openai.yaml +4 -0
  7. package/analyse-app-logs/LICENSE +21 -0
  8. package/analyse-app-logs/README.md +126 -0
  9. package/analyse-app-logs/SKILL.md +121 -0
  10. package/analyse-app-logs/agents/openai.yaml +4 -0
  11. package/analyse-app-logs/references/investigation-checklist.md +58 -0
  12. package/analyse-app-logs/references/log-signal-patterns.md +52 -0
  13. package/answering-questions-with-research/SKILL.md +46 -0
  14. package/answering-questions-with-research/agents/openai.yaml +4 -0
  15. package/bin/apollo-toolkit.js +7 -0
  16. package/commit-and-push/LICENSE +21 -0
  17. package/commit-and-push/README.md +26 -0
  18. package/commit-and-push/SKILL.md +70 -0
  19. package/commit-and-push/agents/openai.yaml +4 -0
  20. package/commit-and-push/references/branch-naming.md +15 -0
  21. package/commit-and-push/references/commit-messages.md +19 -0
  22. package/deep-research-topics/LICENSE +21 -0
  23. package/deep-research-topics/README.md +43 -0
  24. package/deep-research-topics/SKILL.md +84 -0
  25. package/deep-research-topics/agents/openai.yaml +4 -0
  26. package/develop-new-features/LICENSE +21 -0
  27. package/develop-new-features/README.md +52 -0
  28. package/develop-new-features/SKILL.md +105 -0
  29. package/develop-new-features/agents/openai.yaml +4 -0
  30. package/develop-new-features/references/testing-e2e.md +35 -0
  31. package/develop-new-features/references/testing-integration.md +42 -0
  32. package/develop-new-features/references/testing-property-based.md +44 -0
  33. package/develop-new-features/references/testing-unit.md +37 -0
  34. package/discover-edge-cases/CHANGELOG.md +19 -0
  35. package/discover-edge-cases/LICENSE +21 -0
  36. package/discover-edge-cases/README.md +87 -0
  37. package/discover-edge-cases/SKILL.md +124 -0
  38. package/discover-edge-cases/agents/openai.yaml +4 -0
  39. package/discover-edge-cases/references/architecture-edge-cases.md +41 -0
  40. package/discover-edge-cases/references/code-edge-cases.md +46 -0
  41. package/docs-to-voice/.env.example +106 -0
  42. package/docs-to-voice/CHANGELOG.md +71 -0
  43. package/docs-to-voice/LICENSE +21 -0
  44. package/docs-to-voice/README.md +118 -0
  45. package/docs-to-voice/SKILL.md +107 -0
  46. package/docs-to-voice/agents/openai.yaml +4 -0
  47. package/docs-to-voice/scripts/docs_to_voice.py +1385 -0
  48. package/docs-to-voice/scripts/docs_to_voice.sh +11 -0
  49. package/docs-to-voice/tests/test_docs_to_voice_api_max_chars.py +210 -0
  50. package/docs-to-voice/tests/test_docs_to_voice_sentence_timeline.py +115 -0
  51. package/docs-to-voice/tests/test_docs_to_voice_settings.py +43 -0
  52. package/docs-to-voice/tests/test_docs_to_voice_speech_rate.py +57 -0
  53. package/enhance-existing-features/CHANGELOG.md +35 -0
  54. package/enhance-existing-features/LICENSE +21 -0
  55. package/enhance-existing-features/README.md +54 -0
  56. package/enhance-existing-features/SKILL.md +120 -0
  57. package/enhance-existing-features/agents/openai.yaml +4 -0
  58. package/enhance-existing-features/references/e2e-tests.md +25 -0
  59. package/enhance-existing-features/references/integration-tests.md +30 -0
  60. package/enhance-existing-features/references/property-based-tests.md +33 -0
  61. package/enhance-existing-features/references/unit-tests.md +29 -0
  62. package/feature-propose/LICENSE +21 -0
  63. package/feature-propose/README.md +23 -0
  64. package/feature-propose/SKILL.md +107 -0
  65. package/feature-propose/agents/openai.yaml +4 -0
  66. package/feature-propose/references/enhancement-features.md +25 -0
  67. package/feature-propose/references/important-features.md +25 -0
  68. package/feature-propose/references/mvp-features.md +25 -0
  69. package/feature-propose/references/performance-features.md +25 -0
  70. package/financial-research/SKILL.md +208 -0
  71. package/financial-research/agents/openai.yaml +4 -0
  72. package/financial-research/assets/weekly_market_report_template.md +45 -0
  73. package/fix-github-issues/SKILL.md +98 -0
  74. package/fix-github-issues/agents/openai.yaml +4 -0
  75. package/fix-github-issues/scripts/list_issues.py +148 -0
  76. package/fix-github-issues/tests/test_list_issues.py +127 -0
  77. package/generate-spec/LICENSE +21 -0
  78. package/generate-spec/README.md +61 -0
  79. package/generate-spec/SKILL.md +96 -0
  80. package/generate-spec/agents/openai.yaml +4 -0
  81. package/generate-spec/references/templates/checklist.md +78 -0
  82. package/generate-spec/references/templates/spec.md +55 -0
  83. package/generate-spec/references/templates/tasks.md +35 -0
  84. package/generate-spec/scripts/create-specs +123 -0
  85. package/harden-app-security/CHANGELOG.md +27 -0
  86. package/harden-app-security/LICENSE +21 -0
  87. package/harden-app-security/README.md +46 -0
  88. package/harden-app-security/SKILL.md +127 -0
  89. package/harden-app-security/agents/openai.yaml +4 -0
  90. package/harden-app-security/references/agent-attack-catalog.md +117 -0
  91. package/harden-app-security/references/common-software-attack-catalog.md +168 -0
  92. package/harden-app-security/references/red-team-extreme-scenarios.md +81 -0
  93. package/harden-app-security/references/risk-checklist.md +78 -0
  94. package/harden-app-security/references/security-test-patterns-agent.md +101 -0
  95. package/harden-app-security/references/security-test-patterns-finance.md +88 -0
  96. package/harden-app-security/references/test-snippets.md +73 -0
  97. package/improve-observability/SKILL.md +114 -0
  98. package/improve-observability/agents/openai.yaml +4 -0
  99. package/learn-skill-from-conversations/CHANGELOG.md +15 -0
  100. package/learn-skill-from-conversations/LICENSE +22 -0
  101. package/learn-skill-from-conversations/README.md +47 -0
  102. package/learn-skill-from-conversations/SKILL.md +85 -0
  103. package/learn-skill-from-conversations/agents/openai.yaml +4 -0
  104. package/learn-skill-from-conversations/scripts/extract_recent_conversations.py +369 -0
  105. package/learn-skill-from-conversations/tests/test_extract_recent_conversations.py +176 -0
  106. package/learning-error-book/SKILL.md +112 -0
  107. package/learning-error-book/agents/openai.yaml +4 -0
  108. package/learning-error-book/assets/error_book_template.md +66 -0
  109. package/learning-error-book/scripts/render_markdown_to_pdf.py +367 -0
  110. package/lib/cli.js +338 -0
  111. package/lib/installer.js +225 -0
  112. package/maintain-project-constraints/SKILL.md +109 -0
  113. package/maintain-project-constraints/agents/openai.yaml +4 -0
  114. package/maintain-skill-catalog/README.md +18 -0
  115. package/maintain-skill-catalog/SKILL.md +66 -0
  116. package/maintain-skill-catalog/agents/openai.yaml +4 -0
  117. package/novel-to-short-video/CHANGELOG.md +53 -0
  118. package/novel-to-short-video/LICENSE +21 -0
  119. package/novel-to-short-video/README.md +63 -0
  120. package/novel-to-short-video/SKILL.md +233 -0
  121. package/novel-to-short-video/agents/openai.yaml +4 -0
  122. package/novel-to-short-video/references/plan-template.md +71 -0
  123. package/novel-to-short-video/references/roles-json.md +41 -0
  124. package/open-github-issue/LICENSE +21 -0
  125. package/open-github-issue/README.md +97 -0
  126. package/open-github-issue/SKILL.md +119 -0
  127. package/open-github-issue/agents/openai.yaml +4 -0
  128. package/open-github-issue/scripts/open_github_issue.py +380 -0
  129. package/open-github-issue/tests/test_open_github_issue.py +159 -0
  130. package/open-source-pr-workflow/CHANGELOG.md +32 -0
  131. package/open-source-pr-workflow/LICENSE +21 -0
  132. package/open-source-pr-workflow/README.md +23 -0
  133. package/open-source-pr-workflow/SKILL.md +123 -0
  134. package/open-source-pr-workflow/agents/openai.yaml +4 -0
  135. package/openai-text-to-image-storyboard/.env.example +10 -0
  136. package/openai-text-to-image-storyboard/CHANGELOG.md +49 -0
  137. package/openai-text-to-image-storyboard/LICENSE +21 -0
  138. package/openai-text-to-image-storyboard/README.md +99 -0
  139. package/openai-text-to-image-storyboard/SKILL.md +107 -0
  140. package/openai-text-to-image-storyboard/agents/openai.yaml +4 -0
  141. package/openai-text-to-image-storyboard/scripts/generate_storyboard_images.py +763 -0
  142. package/package.json +36 -0
  143. package/record-spending/SKILL.md +113 -0
  144. package/record-spending/agents/openai.yaml +4 -0
  145. package/record-spending/references/account-format.md +33 -0
  146. package/record-spending/references/workbook-layout.md +84 -0
  147. package/resolve-review-comments/SKILL.md +122 -0
  148. package/resolve-review-comments/agents/openai.yaml +4 -0
  149. package/resolve-review-comments/references/adoption-criteria.md +23 -0
  150. package/resolve-review-comments/scripts/review_threads.py +425 -0
  151. package/resolve-review-comments/tests/test_review_threads.py +74 -0
  152. package/review-change-set/LICENSE +21 -0
  153. package/review-change-set/README.md +55 -0
  154. package/review-change-set/SKILL.md +103 -0
  155. package/review-change-set/agents/openai.yaml +4 -0
  156. package/review-codebases/LICENSE +21 -0
  157. package/review-codebases/README.md +67 -0
  158. package/review-codebases/SKILL.md +109 -0
  159. package/review-codebases/agents/openai.yaml +4 -0
  160. package/scripts/install_skills.ps1 +283 -0
  161. package/scripts/install_skills.sh +262 -0
  162. package/scripts/validate_openai_agent_config.py +194 -0
  163. package/scripts/validate_skill_frontmatter.py +110 -0
  164. package/specs-to-project-docs/LICENSE +21 -0
  165. package/specs-to-project-docs/README.md +57 -0
  166. package/specs-to-project-docs/SKILL.md +111 -0
  167. package/specs-to-project-docs/agents/openai.yaml +4 -0
  168. package/specs-to-project-docs/references/templates/architecture.md +29 -0
  169. package/specs-to-project-docs/references/templates/configuration.md +29 -0
  170. package/specs-to-project-docs/references/templates/developer-guide.md +33 -0
  171. package/specs-to-project-docs/references/templates/docs-index.md +39 -0
  172. package/specs-to-project-docs/references/templates/features.md +25 -0
  173. package/specs-to-project-docs/references/templates/getting-started.md +38 -0
  174. package/specs-to-project-docs/references/templates/readme.md +49 -0
  175. package/systematic-debug/LICENSE +21 -0
  176. package/systematic-debug/README.md +81 -0
  177. package/systematic-debug/SKILL.md +59 -0
  178. package/systematic-debug/agents/openai.yaml +4 -0
  179. package/text-to-short-video/.env.example +36 -0
  180. package/text-to-short-video/LICENSE +21 -0
  181. package/text-to-short-video/README.md +82 -0
  182. package/text-to-short-video/SKILL.md +221 -0
  183. package/text-to-short-video/agents/openai.yaml +4 -0
  184. package/text-to-short-video/scripts/enforce_video_aspect_ratio.py +350 -0
  185. package/version-release/CHANGELOG.md +53 -0
  186. package/version-release/LICENSE +21 -0
  187. package/version-release/README.md +28 -0
  188. package/version-release/SKILL.md +94 -0
  189. package/version-release/agents/openai.yaml +4 -0
  190. package/version-release/references/branch-naming.md +15 -0
  191. package/version-release/references/changelog-writing.md +8 -0
  192. package/version-release/references/commit-messages.md +19 -0
  193. package/version-release/references/readme-writing.md +12 -0
  194. package/version-release/references/semantic-versioning.md +12 -0
  195. package/video-production/CHANGELOG.md +104 -0
  196. package/video-production/LICENSE +18 -0
  197. package/video-production/README.md +68 -0
  198. package/video-production/SKILL.md +213 -0
  199. package/video-production/agents/openai.yaml +4 -0
  200. package/video-production/references/plan-template.md +54 -0
  201. package/video-production/references/roles-json.md +41 -0
  202. package/weekly-financial-event-report/SKILL.md +195 -0
  203. package/weekly-financial-event-report/agents/openai.yaml +4 -0
  204. package/weekly-financial-event-report/assets/financial_event_report_template.md +53 -0
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: fix-github-issues
3
+ description: Resolve issues from remote GitHub repositories via GitHub CLI (`gh`), implement and validate fixes locally, then open a pull request through `open-source-pr-workflow` (or `open-pr-workflow` in environments that use that alias). Use when users ask to list remote issues, pick one or more issues to fix, and submit a PR linked to those issues.
4
+ ---
5
+
6
+ # Fix GitHub Issues
7
+
8
+ ## Dependencies
9
+
10
+ - Required: `systematic-debug` for diagnosis and validated fixes, plus `open-source-pr-workflow` (or `open-pr-workflow`) for PR submission.
11
+ - Conditional: none.
12
+ - Optional: none.
13
+ - Fallback: If a required workflow dependency is unavailable, stop and report the blocked handoff instead of improvising a different flow.
14
+
15
+ ## Standards
16
+
17
+ - Evidence: Verify repository context, fetch remote issue details, and derive expected behavior from issue text before coding.
18
+ - Execution: Select the issue, open an isolated worktree by default, fix it through `systematic-debug`, validate locally, then hand off to the PR workflow.
19
+ - Quality: Keep scope limited to the selected issue, capture exact validation commands, and preserve issue linkage in the final PR.
20
+ - Output: Open the PR against the correct repository and clean up the temporary worktree when the work is complete.
21
+
22
+ ## Overview
23
+
24
+ Use this skill to run an end-to-end issue-fixing loop with `gh`: discover open issues, select a target, implement and test the fix, and delegate PR creation to `open-source-pr-workflow` (or `open-pr-workflow` alias).
25
+
26
+ ## Prerequisites
27
+
28
+ - `gh` is installed and authenticated (`gh auth status`).
29
+ - The current directory is a git repository with the correct `origin`.
30
+ - The repository has test or validation commands that can prove the fix.
31
+
32
+ ## Workflow
33
+
34
+ ### 1) Verify repository and remote context
35
+
36
+ - Run `gh repo view --json nameWithOwner,isPrivate,defaultBranchRef` to confirm target repo.
37
+ - If the user specifies another repository, always use `--repo <owner>/<repo>` in issue commands.
38
+ - Run `git fetch --all --prune` before implementation.
39
+
40
+ ### 2) List remote issues with GitHub CLI
41
+
42
+ - Preferred command:
43
+
44
+ ```bash
45
+ python3 scripts/list_issues.py --limit 50 --state open
46
+ ```
47
+
48
+ - Optional filters:
49
+ - `--repo owner/name`
50
+ - `--label bug`
51
+ - `--search "panic in parser"`
52
+ - If the issue target is still unclear, present top candidates and ask the user which issue number to fix.
53
+
54
+ ### 3) Read issue details before coding
55
+
56
+ - Run `gh issue view <issue-number> --comments` (plus `--repo` when needed).
57
+ - Identify expected behavior, edge cases, and acceptance signals from issue text/comments.
58
+ - Do not guess missing requirements; ask the user when critical details are ambiguous.
59
+
60
+ ### 4) Open worktree by default after issue selection
61
+
62
+ - Immediately create and enter an isolated worktree once the issue number is selected and confirmed.
63
+ - Use a compliant branch name (`codex/{change_type}/{changes}`) and keep all edits in that worktree.
64
+ - If the user explicitly asks to stay in the current tree, follow that request; otherwise worktree is the default path.
65
+
66
+ ### 5) Implement the fix with `systematic-debug`
67
+
68
+ - Execute the `systematic-debug` workflow: inspect, reproduce with tests, diagnose, then apply minimal fix.
69
+ - Keep scope limited to the selected issue.
70
+ - Reuse existing code patterns and avoid unrelated refactors.
71
+
72
+ ### 6) Validate the fix
73
+
74
+ - Run focused tests/lint/build relevant to the touched area.
75
+ - Capture exact commands and outcomes; these will be reused in the PR body.
76
+ - Ensure the change can be linked back to the issue number.
77
+
78
+ ### 7) Open PR via dependency skill
79
+
80
+ - After code is ready, invoke `open-source-pr-workflow` (or `open-pr-workflow` if that alias exists in the environment).
81
+ - Provide required PR context:
82
+ - issue number or link
83
+ - motivation and engineering decisions
84
+ - executed test commands and results
85
+ - Include issue-closing reference (for example, `Closes #<issue-number>`).
86
+
87
+ ### 8) Clean up the temporary worktree after PR creation
88
+
89
+ - Once the PR is opened and no more work is needed in that isolated tree, remove the worktree you created for the fix.
90
+ - Also clean up the matching local branch reference if it is no longer needed locally.
91
+
92
+ ## Included Script
93
+
94
+ ### `scripts/list_issues.py`
95
+
96
+ - Purpose: consistent remote issue listing via `gh issue list`.
97
+ - Outputs a readable table by default, or JSON with `--output json`.
98
+ - Uses only GitHub CLI so it reflects remote GitHub state.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Fix GitHub Issues"
3
+ short_description: "Resolve remote GitHub issues and open linked PRs"
4
+ default_prompt: "Use $fix-github-issues to verify the target GitHub repository with gh, list and inspect remote issues, create an isolated worktree and compliant branch after issue selection, use $systematic-debug to reproduce and fix the issue with tests, validate the result, open a linked PR through $open-source-pr-workflow, then delete the temporary worktree when PR setup is complete."
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env python3
2
+ import argparse
3
+ import json
4
+ import subprocess
5
+ import sys
6
+ from typing import Any
7
+
8
+ ISSUE_FIELDS = "number,title,state,updatedAt,url,labels,assignees"
9
+
10
+
11
+ def positive_int(raw: str) -> int:
12
+ value = int(raw)
13
+ if value <= 0:
14
+ raise argparse.ArgumentTypeError("limit must be a positive integer")
15
+ return value
16
+
17
+
18
+ def parse_args() -> argparse.Namespace:
19
+ parser = argparse.ArgumentParser(
20
+ description="List remote GitHub issues with gh CLI and display table or JSON output."
21
+ )
22
+ parser.add_argument("--repo", help="Target repository in owner/name format.")
23
+ parser.add_argument("--state", default="open", choices=["open", "closed", "all"])
24
+ parser.add_argument("--limit", type=positive_int, default=50)
25
+ parser.add_argument(
26
+ "--label",
27
+ action="append",
28
+ default=[],
29
+ help="Label filter (repeat for multiple labels).",
30
+ )
31
+ parser.add_argument("--search", help="Search query for issue list filtering.")
32
+ parser.add_argument(
33
+ "--output",
34
+ choices=["table", "json"],
35
+ default="table",
36
+ help="Output format.",
37
+ )
38
+ return parser.parse_args()
39
+
40
+
41
+ def build_command(args: argparse.Namespace) -> list[str]:
42
+ cmd = [
43
+ "gh",
44
+ "issue",
45
+ "list",
46
+ "--state",
47
+ args.state,
48
+ "--limit",
49
+ str(args.limit),
50
+ "--json",
51
+ ISSUE_FIELDS,
52
+ ]
53
+
54
+ if args.repo:
55
+ cmd.extend(["--repo", args.repo])
56
+ for label in args.label:
57
+ cmd.extend(["--label", label])
58
+ if args.search:
59
+ cmd.extend(["--search", args.search])
60
+
61
+ return cmd
62
+
63
+
64
+ def truncate(text: str, width: int) -> str:
65
+ if len(text) <= width:
66
+ return text
67
+ if width <= 3:
68
+ return text[:width]
69
+ return text[: width - 3] + "..."
70
+
71
+
72
+ def format_labels(issue: dict[str, Any]) -> str:
73
+ labels = issue.get("labels", [])
74
+ names = [item.get("name", "") for item in labels if item.get("name")]
75
+ return ",".join(names)
76
+
77
+
78
+ def format_assignees(issue: dict[str, Any]) -> str:
79
+ assignees = issue.get("assignees", [])
80
+ logins = [item.get("login", "") for item in assignees if item.get("login")]
81
+ return ",".join(logins) if logins else "-"
82
+
83
+
84
+ def print_table(issues: list[dict[str, Any]]) -> None:
85
+ columns = {
86
+ "number": 7,
87
+ "title": 54,
88
+ "labels": 22,
89
+ "assignees": 18,
90
+ "updated": 20,
91
+ }
92
+
93
+ header = (
94
+ f"{'NUMBER':<{columns['number']}} "
95
+ f"{'TITLE':<{columns['title']}} "
96
+ f"{'LABELS':<{columns['labels']}} "
97
+ f"{'ASSIGNEES':<{columns['assignees']}} "
98
+ f"{'UPDATED':<{columns['updated']}}"
99
+ )
100
+ print(header)
101
+ print("-" * len(header))
102
+
103
+ for issue in issues:
104
+ number = f"#{issue.get('number', '')}"
105
+ title = truncate(str(issue.get("title", "")), columns["title"])
106
+ labels = truncate(format_labels(issue), columns["labels"])
107
+ assignees = truncate(format_assignees(issue), columns["assignees"])
108
+ updated = truncate(str(issue.get("updatedAt", "")), columns["updated"])
109
+
110
+ row = (
111
+ f"{number:<{columns['number']}} "
112
+ f"{title:<{columns['title']}} "
113
+ f"{labels:<{columns['labels']}} "
114
+ f"{assignees:<{columns['assignees']}} "
115
+ f"{updated:<{columns['updated']}}"
116
+ )
117
+ print(row)
118
+
119
+
120
+ def main() -> int:
121
+ args = parse_args()
122
+ cmd = build_command(args)
123
+
124
+ try:
125
+ result = subprocess.run(cmd, check=True, capture_output=True, text=True)
126
+ except FileNotFoundError:
127
+ print("Error: gh CLI is not installed or not in PATH.", file=sys.stderr)
128
+ return 1
129
+ except subprocess.CalledProcessError as exc:
130
+ print(exc.stderr.strip() or "gh issue list failed.", file=sys.stderr)
131
+ return exc.returncode
132
+
133
+ try:
134
+ issues = json.loads(result.stdout)
135
+ except json.JSONDecodeError:
136
+ print("Error: unable to parse gh output as JSON.", file=sys.stderr)
137
+ return 1
138
+
139
+ if args.output == "json":
140
+ print(json.dumps(issues, indent=2))
141
+ return 0
142
+
143
+ print_table(issues)
144
+ return 0
145
+
146
+
147
+ if __name__ == "__main__":
148
+ sys.exit(main())
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env python3
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import importlib.util
7
+ import io
8
+ import json
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" / "list_issues.py"
16
+ SPEC = importlib.util.spec_from_file_location("list_issues", SCRIPT_PATH)
17
+ MODULE = importlib.util.module_from_spec(SPEC)
18
+ SPEC.loader.exec_module(MODULE)
19
+
20
+
21
+ class ListIssuesTests(unittest.TestCase):
22
+ def test_build_command_with_filters(self) -> None:
23
+ args = Namespace(
24
+ repo="owner/repo",
25
+ state="open",
26
+ limit=25,
27
+ label=["bug", "needs-triage"],
28
+ search="panic parser",
29
+ output="table",
30
+ )
31
+
32
+ cmd = MODULE.build_command(args)
33
+
34
+ self.assertEqual(
35
+ cmd,
36
+ [
37
+ "gh",
38
+ "issue",
39
+ "list",
40
+ "--state",
41
+ "open",
42
+ "--limit",
43
+ "25",
44
+ "--json",
45
+ MODULE.ISSUE_FIELDS,
46
+ "--repo",
47
+ "owner/repo",
48
+ "--label",
49
+ "bug",
50
+ "--label",
51
+ "needs-triage",
52
+ "--search",
53
+ "panic parser",
54
+ ],
55
+ )
56
+
57
+ def test_positive_int_rejects_zero(self) -> None:
58
+ with self.assertRaises(argparse.ArgumentTypeError):
59
+ MODULE.positive_int("0")
60
+
61
+ def test_truncate_handles_small_width(self) -> None:
62
+ self.assertEqual(MODULE.truncate("abcdef", 2), "ab")
63
+
64
+ def test_print_table_handles_missing_fields(self) -> None:
65
+ with patch("sys.stdout", new_callable=io.StringIO) as stdout:
66
+ MODULE.print_table([
67
+ {
68
+ "number": 42,
69
+ "title": "Fix formatter fallback",
70
+ }
71
+ ])
72
+
73
+ output = stdout.getvalue()
74
+ self.assertIn("NUMBER", output)
75
+ self.assertIn("#42", output)
76
+
77
+ def test_main_returns_error_when_gh_missing(self) -> None:
78
+ args = Namespace(
79
+ repo=None,
80
+ state="open",
81
+ limit=50,
82
+ label=[],
83
+ search=None,
84
+ output="table",
85
+ )
86
+
87
+ with patch.object(MODULE, "parse_args", return_value=args), patch(
88
+ "subprocess.run", side_effect=FileNotFoundError
89
+ ), patch("sys.stderr", new_callable=io.StringIO) as stderr:
90
+ code = MODULE.main()
91
+
92
+ self.assertEqual(code, 1)
93
+ self.assertIn("not in PATH", stderr.getvalue())
94
+
95
+ def test_main_json_output(self) -> None:
96
+ args = Namespace(
97
+ repo=None,
98
+ state="open",
99
+ limit=50,
100
+ label=[],
101
+ search=None,
102
+ output="json",
103
+ )
104
+ payload = [
105
+ {
106
+ "number": 1,
107
+ "title": "Fix bug",
108
+ "labels": [],
109
+ "assignees": [],
110
+ "updatedAt": "2026-02-26T00:00:00Z",
111
+ }
112
+ ]
113
+
114
+ class Result:
115
+ stdout = json.dumps(payload)
116
+
117
+ with patch.object(MODULE, "parse_args", return_value=args), patch(
118
+ "subprocess.run", return_value=Result()
119
+ ), patch("sys.stdout", new_callable=io.StringIO) as stdout:
120
+ code = MODULE.main()
121
+
122
+ self.assertEqual(code, 0)
123
+ self.assertEqual(json.loads(stdout.getvalue()), payload)
124
+
125
+
126
+ if __name__ == "__main__":
127
+ unittest.main()
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lai Tsz Kin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,61 @@
1
+ # generate-spec
2
+
3
+ A shared planning skill for feature work. It centralizes creation and maintenance of `spec.md`, `tasks.md`, and `checklist.md` so other skills can reuse one consistent approval-gated spec workflow.
4
+
5
+ ## Core capabilities
6
+
7
+ - Generates `docs/plans/{YYYY-MM-DD}_{change_name}/spec.md`, `tasks.md`, and `checklist.md` in one step.
8
+ - Uses shared templates so spec-first and brownfield workflows follow the same planning structure.
9
+ - Requires clarification handling and explicit user approval before implementation starts.
10
+ - Backfills task and checklist status after implementation and testing.
11
+ - Keeps requirement, task, and test coverage mapping traceable.
12
+
13
+ ## Repository layout
14
+
15
+ ```text
16
+ .
17
+ ├── SKILL.md
18
+ ├── README.md
19
+ ├── LICENSE
20
+ ├── agents/
21
+ │ └── openai.yaml
22
+ ├── references/
23
+ │ └── templates/
24
+ │ ├── spec.md
25
+ │ ├── tasks.md
26
+ │ └── checklist.md
27
+ └── scripts/
28
+ └── create-specs
29
+ ```
30
+
31
+ ## Quick start
32
+
33
+ ```bash
34
+ SKILL_ROOT=/path/to/generate-spec
35
+ WORKSPACE_ROOT=/path/to/target-project
36
+ python3 "$SKILL_ROOT/scripts/create-specs" "Membership upgrade flow" \
37
+ --change-name membership-upgrade-flow \
38
+ --template-dir "$SKILL_ROOT/references/templates" \
39
+ --output-dir "$WORKSPACE_ROOT/docs/plans"
40
+ ```
41
+
42
+ Default output:
43
+
44
+ ```text
45
+ docs/plans/<today>_membership-upgrade-flow/
46
+ ├── spec.md
47
+ ├── tasks.md
48
+ └── checklist.md
49
+ ```
50
+
51
+ ## Authoring rules
52
+
53
+ - `spec.md`: use BDD keywords `GIVEN / WHEN / THEN / AND / Requirements`.
54
+ - `tasks.md`: use `## **Task N: ...**`, `- N. [ ]`, and `- N.x [ ]`.
55
+ - `checklist.md`: use `- [ ]` only, adapt items to real scope, and record actual results.
56
+ - If clarification responses change the plan, update the docs and obtain approval again before coding.
57
+
58
+ ## Notes
59
+
60
+ - `scripts/...` and `references/...` are skill-folder paths, not project-folder paths.
61
+ - The generator replaces `[YYYY-MM-DD]`, `[Feature Name]`, `[功能名稱]`, and `[change_name]` placeholders.
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: generate-spec
3
+ description: Generate and maintain shared feature planning artifacts (`spec.md`, `tasks.md`, `checklist.md`) from standard templates with clarification tracking, approval gating, and post-implementation backfill. Use when a workflow needs specs before coding, or when another skill needs to create/update `docs/plans/{YYYY-MM-DD}_{change_name}/` planning docs.
4
+ ---
5
+
6
+ # Generate Spec
7
+
8
+ ## Dependencies
9
+
10
+ - Required: none.
11
+ - Conditional: none.
12
+ - Optional: none.
13
+ - Fallback: not applicable.
14
+
15
+ ## Standards
16
+
17
+ - Evidence: Review the relevant code, configs, and authoritative docs before filling requirements or test plans.
18
+ - Execution: Generate the planning files first, complete them with traceable requirements and risks, handle clarification updates, then wait for explicit approval before implementation.
19
+ - Quality: Keep `spec.md`, `tasks.md`, and `checklist.md` synchronized and map each planned test to a concrete risk or requirement.
20
+ - Output: Store planning artifacts under `docs/plans/{YYYY-MM-DD}_{change_name}/` and keep them concise, executable, and easy to update.
21
+
22
+ ## Goal
23
+
24
+ Own the shared planning-doc lifecycle for feature work so other skills can reuse one consistent spec-generation workflow.
25
+
26
+ ## Workflow
27
+
28
+ ### 1) Gather inputs and evidence
29
+
30
+ - Confirm the target workspace root, feature name, and a kebab-case `change_name`.
31
+ - Review only the code, configuration, and external docs needed to understand the requested behavior.
32
+ - Record the references that should appear in `spec.md`.
33
+
34
+ ### 2) Generate the planning files
35
+
36
+ - Resolve paths from this skill directory, not the target project directory.
37
+ - Use:
38
+ - `SKILL_ROOT=<path_to_generate-spec_skill>`
39
+ - `WORKSPACE_ROOT=<target_project_root>`
40
+ - `python3 "$SKILL_ROOT/scripts/create-specs" "<feature_name>" --change-name <kebab-case> --template-dir "$SKILL_ROOT/references/templates" --output-dir "$WORKSPACE_ROOT/docs/plans"`
41
+ - Always generate:
42
+ - `references/templates/spec.md`
43
+ - `references/templates/tasks.md`
44
+ - `references/templates/checklist.md`
45
+ - Save files under `docs/plans/{YYYY-MM-DD}_{change_name}/`.
46
+
47
+ ### 3) Fill `spec.md`
48
+
49
+ - Keep the goal and scope concrete.
50
+ - Write functional behaviors in BDD form with `GIVEN`, `WHEN`, `THEN`, `AND`, and `Requirements`.
51
+ - Make each requirement testable.
52
+ - Cover boundaries, authorization, external dependency states, abuse/adversarial paths, failure handling, and any relevant idempotency/concurrency/data-integrity risks.
53
+ - If requirements are unclear, list 3-5 clarification questions; otherwise write `None`.
54
+
55
+ ### 4) Fill `tasks.md`
56
+
57
+ - Use `## **Task N: [Task Title]**` for each main task.
58
+ - Describe each task's purpose and the related requirement IDs.
59
+ - Use `- N. [ ]` for tasks and `- N.x [ ]` for subtasks.
60
+ - Include explicit tasks for testing, mocks/fakes, regression coverage, and adversarial or edge-case hardening when relevant.
61
+
62
+ ### 5) Fill `checklist.md`
63
+
64
+ - Use checkbox format `- [ ]` only.
65
+ - Treat the template as a starting point and adapt it to the actual scope.
66
+ - Map observable behaviors to requirement IDs and real test case IDs.
67
+ - Record risk class, oracle/assertion focus, dependency strategy, and test results.
68
+ - Property-based coverage is required for business-logic changes unless a concrete `N/A` reason is recorded.
69
+
70
+ ### 6) Process clarifications and approval
71
+
72
+ - When the user answers clarification questions, first update the clarification and approval section in `checklist.md`.
73
+ - Review whether `spec.md`, `tasks.md`, and `checklist.md` must be updated.
74
+ - After any clarification-driven update, obtain explicit approval on the updated spec set again.
75
+ - Do not modify implementation code before approval.
76
+
77
+ ### 7) Backfill after implementation and testing
78
+
79
+ - Mark completed tasks in `tasks.md`.
80
+ - Update `checklist.md` with real test outcomes, `N/A` reasons, and any scope adjustments.
81
+ - Remove stale placeholders or template-only guidance once the documents are finalized.
82
+
83
+ ## Working Rules
84
+
85
+ - By default, write planning docs in the user's language.
86
+ - Keep requirement IDs, task IDs, and test IDs traceable across all three files.
87
+ - Prefer realistic coverage over boilerplate: add or remove checklist items based on actual risk.
88
+ - Use kebab-case for `change_name`; avoid spaces and special characters.
89
+ - Path rule: `scripts/...` and `references/...` in this file always mean paths under the current skill folder, not the target project root.
90
+
91
+ ## References
92
+
93
+ - `scripts/create-specs`: shared planning file generator.
94
+ - `references/templates/spec.md`: BDD requirement template.
95
+ - `references/templates/tasks.md`: task breakdown template.
96
+ - `references/templates/checklist.md`: behavior-to-test alignment template.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "generate-spec"
3
+ short_description: "Generate shared feature spec, task, and checklist docs before coding"
4
+ default_prompt: "Use $generate-spec to create or update docs/plans/<date>_<change_name>/{spec.md,tasks.md,checklist.md} from shared templates, fill BDD requirements and risk-driven test planning, process clarification updates, and wait for explicit approval before implementation."
@@ -0,0 +1,78 @@
1
+ # Checklist: [Feature Name]
2
+
3
+ - Date: [YYYY-MM-DD]
4
+ - Feature: [Feature Name]
5
+
6
+ ## Usage Notes
7
+ - This checklist is a starter template. Add, remove, or rewrite items based on actual scope.
8
+ - Use `- [ ]` for all items; mark completed items as `- [x]`.
9
+ - If an item is not applicable, keep `N/A` with a concrete reason.
10
+ - Suggested test result values: `PASS / FAIL / BLOCKED / NOT RUN / N/A`.
11
+ - For business-logic changes, property-based coverage is required unless a concrete `N/A` reason is recorded.
12
+ - Each checklist item should map to a distinct risk; avoid repeating shallow happy-path cases.
13
+
14
+ ## Clarification & Approval Gate (required when clarification replies exist)
15
+ - [ ] User clarification responses are recorded (map to `spec.md`; if none, mark `N/A`).
16
+ - [ ] Affected specs are reviewed/updated (`spec.md` / `tasks.md` / `checklist.md`; if no updates needed, mark `N/A` + reason).
17
+ - [ ] Explicit user approval on updated specs is obtained (date/conversation reference: [to be filled]).
18
+
19
+ ## Behavior-to-Test Checklist (customizable)
20
+
21
+ - [ ] CL-01 [Observable behavior]
22
+ - Requirement mapping: [R1.x]
23
+ - Actual test case IDs: [UT/PBT/IT/E2E-xx]
24
+ - Test level: [Unit / Property-based / Integration / E2E]
25
+ - Risk class: [boundary / authorization / concurrency / external failure / data integrity / adversarial abuse / regression]
26
+ - Property/matrix focus: [invariant / generated business input space / external state matrix / adversarial case]
27
+ - External dependency strategy: [none / mocked service states / near-real dependency]
28
+ - Oracle/assertion focus: [exact output / persisted state / side effects / no partial write / compensation / emitted event / permission denial]
29
+ - Test result: `PASS / FAIL / BLOCKED / NOT RUN / N/A`
30
+ - Notes (optional): [risk, limitation, observation]
31
+
32
+ - [ ] CL-02 [Observable behavior]
33
+ - Requirement mapping: [R?.?]
34
+ - Actual test case IDs: [UT/PBT/IT/E2E-xx]
35
+ - Test level: [Unit / Property-based / Integration / E2E]
36
+ - Risk class: [boundary / authorization / concurrency / external failure / data integrity / adversarial abuse / regression]
37
+ - Property/matrix focus: [invariant / generated business input space / external state matrix / adversarial case]
38
+ - External dependency strategy: [none / mocked service states / near-real dependency]
39
+ - Oracle/assertion focus: [exact output / persisted state / side effects / no partial write / compensation / emitted event / permission denial]
40
+ - Test result: `PASS / FAIL / BLOCKED / NOT RUN / N/A`
41
+ - Notes (optional): [risk, limitation, observation]
42
+
43
+ - [ ] CL-03 [Observable behavior]
44
+ - Requirement mapping: [R?.?]
45
+ - Actual test case IDs: [UT/PBT/IT/E2E-xx]
46
+ - Test level: [Unit / Property-based / Integration / E2E]
47
+ - Risk class: [boundary / authorization / concurrency / external failure / data integrity / adversarial abuse / regression]
48
+ - Property/matrix focus: [invariant / generated business input space / external state matrix / adversarial case]
49
+ - External dependency strategy: [none / mocked service states / near-real dependency]
50
+ - Oracle/assertion focus: [exact output / persisted state / side effects / no partial write / compensation / emitted event / permission denial]
51
+ - Test result: `PASS / FAIL / BLOCKED / NOT RUN / N/A`
52
+ - Notes (optional): [risk, limitation, observation]
53
+
54
+ ## Required Hardening Records
55
+ - [ ] Regression tests are added/updated for bug-prone or high-risk behavior, or `N/A` is recorded with a concrete reason.
56
+ - [ ] Property-based coverage is added/updated for changed business logic, or `N/A` is recorded with a concrete reason.
57
+ - [ ] External services in the business logic chain are mocked/faked for scenario testing, or `N/A` is recorded with a concrete reason.
58
+ - [ ] Adversarial/penetration-style cases are added/updated for abuse paths and edge combinations, or `N/A` is recorded with a concrete reason.
59
+ - [ ] Authorization, invalid transition, replay/idempotency, and concurrency risks are evaluated; uncovered items are marked `N/A` with concrete reasons.
60
+ - [ ] Assertions verify business outcomes and side effects/no-side-effects, not only "returns 200" or "does not throw".
61
+ - [ ] Test fixtures are reproducible (fixed seed/clock/fixtures) or `N/A` is recorded with a concrete reason.
62
+
63
+ ## E2E Decision Record (pick one or customize)
64
+ - [ ] Build E2E (case: [E2E-xx]; reason: [importance/complexity/cross-layer risk]).
65
+ - [ ] Do not build E2E; cover with integration tests instead (alternative case: [IT-xx]; reason: [stability/cost/environment limitation]).
66
+ - [ ] No additional E2E/integration hardening required (reason: [existing coverage already addresses risk]).
67
+
68
+ ## Execution Summary (fill with actual results)
69
+ - [ ] Unit tests: `PASS / FAIL / NOT RUN / N/A`
70
+ - [ ] Regression tests: `PASS / FAIL / NOT RUN / N/A`
71
+ - [ ] Property-based tests: `PASS / FAIL / NOT RUN / N/A`
72
+ - [ ] Integration tests: `PASS / FAIL / NOT RUN / N/A`
73
+ - [ ] E2E tests: `PASS / FAIL / NOT RUN / N/A`
74
+ - [ ] External service mock scenarios: `PASS / FAIL / NOT RUN / N/A`
75
+ - [ ] Adversarial/penetration-style cases: `PASS / FAIL / NOT RUN / N/A`
76
+
77
+ ## Completion Rule
78
+ - [ ] Agent has updated checkboxes, test outcomes, and necessary notes based on real execution (including added/removed items).