skillware 0.2.7__tar.gz → 0.2.9__tar.gz

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 (81) hide show
  1. {skillware-0.2.7/skillware.egg-info → skillware-0.2.9}/PKG-INFO +32 -7
  2. {skillware-0.2.7 → skillware-0.2.9}/README.md +13 -2
  3. {skillware-0.2.7 → skillware-0.2.9}/pyproject.toml +28 -5
  4. skillware-0.2.9/skills/dev_tools/__init__.py +1 -0
  5. skillware-0.2.9/skills/dev_tools/issue_resolver/__init__.py +1 -0
  6. skillware-0.2.9/skills/dev_tools/issue_resolver/card.json +33 -0
  7. skillware-0.2.9/skills/dev_tools/issue_resolver/instructions.md +104 -0
  8. skillware-0.2.9/skills/dev_tools/issue_resolver/manifest.yaml +55 -0
  9. skillware-0.2.9/skills/dev_tools/issue_resolver/skill.py +138 -0
  10. skillware-0.2.9/skills/dev_tools/issue_resolver/test_skill.py +185 -0
  11. skillware-0.2.9/skillware/cli.py +162 -0
  12. {skillware-0.2.7 → skillware-0.2.9/skillware.egg-info}/PKG-INFO +32 -7
  13. {skillware-0.2.7 → skillware-0.2.9}/skillware.egg-info/SOURCES.txt +10 -0
  14. skillware-0.2.9/skillware.egg-info/entry_points.txt +2 -0
  15. skillware-0.2.9/skillware.egg-info/requires.txt +32 -0
  16. skillware-0.2.9/tests/test_cli.py +140 -0
  17. skillware-0.2.7/skillware.egg-info/requires.txt +0 -12
  18. {skillware-0.2.7 → skillware-0.2.9}/LICENSE +0 -0
  19. {skillware-0.2.7 → skillware-0.2.9}/MANIFEST.in +0 -0
  20. {skillware-0.2.7 → skillware-0.2.9}/setup.cfg +0 -0
  21. {skillware-0.2.7 → skillware-0.2.9}/skills/__init__.py +0 -0
  22. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/__init__.py +0 -0
  23. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/mica_module/__init__.py +0 -0
  24. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/mica_module/card.json +0 -0
  25. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/mica_module/instructions.md +0 -0
  26. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/mica_module/manifest.yaml +0 -0
  27. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/mica_module/mica_corpus.json +0 -0
  28. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/mica_module/skill.py +0 -0
  29. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/pii_masker/__init__.py +0 -0
  30. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/pii_masker/card.json +0 -0
  31. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/pii_masker/instructions.md +0 -0
  32. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/pii_masker/manifest.yaml +0 -0
  33. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/pii_masker/skill.py +0 -0
  34. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/tos_evaluator/__init__.py +0 -0
  35. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/tos_evaluator/card.json +0 -0
  36. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/tos_evaluator/instructions.md +0 -0
  37. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/tos_evaluator/manifest.yaml +0 -0
  38. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/tos_evaluator/skill.py +0 -0
  39. {skillware-0.2.7 → skillware-0.2.9}/skills/compliance/tos_evaluator/test_skill.py +0 -0
  40. {skillware-0.2.7 → skillware-0.2.9}/skills/data_engineering/__init__.py +0 -0
  41. {skillware-0.2.7 → skillware-0.2.9}/skills/data_engineering/synthetic_generator/__init__.py +0 -0
  42. {skillware-0.2.7 → skillware-0.2.9}/skills/data_engineering/synthetic_generator/card.json +0 -0
  43. {skillware-0.2.7 → skillware-0.2.9}/skills/data_engineering/synthetic_generator/instructions.md +0 -0
  44. {skillware-0.2.7 → skillware-0.2.9}/skills/data_engineering/synthetic_generator/manifest.yaml +0 -0
  45. {skillware-0.2.7 → skillware-0.2.9}/skills/data_engineering/synthetic_generator/skill.py +0 -0
  46. {skillware-0.2.7 → skillware-0.2.9}/skills/finance/__init__.py +0 -0
  47. {skillware-0.2.7 → skillware-0.2.9}/skills/finance/wallet_screening/__init__.py +0 -0
  48. {skillware-0.2.7 → skillware-0.2.9}/skills/finance/wallet_screening/card.json +0 -0
  49. {skillware-0.2.7 → skillware-0.2.9}/skills/finance/wallet_screening/data/entities.ftm.json +0 -0
  50. {skillware-0.2.7 → skillware-0.2.9}/skills/finance/wallet_screening/data/malicious_scs_2025.json +0 -0
  51. {skillware-0.2.7 → skillware-0.2.9}/skills/finance/wallet_screening/data/normalized_fbi_lazarus_20250722_180019.json +0 -0
  52. {skillware-0.2.7 → skillware-0.2.9}/skills/finance/wallet_screening/data/normalized_israel_nbctf_20250722_180019.json +0 -0
  53. {skillware-0.2.7 → skillware-0.2.9}/skills/finance/wallet_screening/data/normalized_uniswap_trm.json +0 -0
  54. {skillware-0.2.7 → skillware-0.2.9}/skills/finance/wallet_screening/instructions.md +0 -0
  55. {skillware-0.2.7 → skillware-0.2.9}/skills/finance/wallet_screening/maintenance/normalization_tool.py +0 -0
  56. {skillware-0.2.7 → skillware-0.2.9}/skills/finance/wallet_screening/maintenance/normalize_uniswap_trm.py +0 -0
  57. {skillware-0.2.7 → skillware-0.2.9}/skills/finance/wallet_screening/manifest.yaml +0 -0
  58. {skillware-0.2.7 → skillware-0.2.9}/skills/finance/wallet_screening/skill.py +0 -0
  59. {skillware-0.2.7 → skillware-0.2.9}/skills/office/__init__.py +0 -0
  60. {skillware-0.2.7 → skillware-0.2.9}/skills/office/pdf_form_filler/__init__.py +0 -0
  61. {skillware-0.2.7 → skillware-0.2.9}/skills/office/pdf_form_filler/card.json +0 -0
  62. {skillware-0.2.7 → skillware-0.2.9}/skills/office/pdf_form_filler/instructions.md +0 -0
  63. {skillware-0.2.7 → skillware-0.2.9}/skills/office/pdf_form_filler/manifest.yaml +0 -0
  64. {skillware-0.2.7 → skillware-0.2.9}/skills/office/pdf_form_filler/skill.py +0 -0
  65. {skillware-0.2.7 → skillware-0.2.9}/skills/office/pdf_form_filler/utils.py +0 -0
  66. {skillware-0.2.7 → skillware-0.2.9}/skills/optimization/__init__.py +0 -0
  67. {skillware-0.2.7 → skillware-0.2.9}/skills/optimization/prompt_rewriter/__init__.py +0 -0
  68. {skillware-0.2.7 → skillware-0.2.9}/skills/optimization/prompt_rewriter/card.json +0 -0
  69. {skillware-0.2.7 → skillware-0.2.9}/skills/optimization/prompt_rewriter/instructions.md +0 -0
  70. {skillware-0.2.7 → skillware-0.2.9}/skills/optimization/prompt_rewriter/manifest.yaml +0 -0
  71. {skillware-0.2.7 → skillware-0.2.9}/skills/optimization/prompt_rewriter/skill.py +0 -0
  72. {skillware-0.2.7 → skillware-0.2.9}/skillware/__init__.py +0 -0
  73. {skillware-0.2.7 → skillware-0.2.9}/skillware/core/__init__.py +0 -0
  74. {skillware-0.2.7 → skillware-0.2.9}/skillware/core/base_skill.py +0 -0
  75. {skillware-0.2.7 → skillware-0.2.9}/skillware/core/env.py +0 -0
  76. {skillware-0.2.7 → skillware-0.2.9}/skillware/core/loader.py +0 -0
  77. {skillware-0.2.7 → skillware-0.2.9}/skillware.egg-info/dependency_links.txt +0 -0
  78. {skillware-0.2.7 → skillware-0.2.9}/skillware.egg-info/top_level.txt +0 -0
  79. {skillware-0.2.7 → skillware-0.2.9}/tests/test_loader.py +0 -0
  80. {skillware-0.2.7 → skillware-0.2.9}/tests/test_mica_module.py +0 -0
  81. {skillware-0.2.7 → skillware-0.2.9}/tests/test_skill_issuer.py +0 -0
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: skillware
3
- Version: 0.2.7
3
+ Version: 0.2.9
4
4
  Summary: A framework for modular, self-contained AI skills.
5
- Author-email: ARPA Hellenic Logic Systems <skillware-os@arpacorp.net>
5
+ Author-email: ARPA Hellenic Logical Systems <skillware-os@arpacorp.net>
6
6
  License: MIT License
7
7
 
8
8
  Copyright (c) 2026 ARPA Hellenic Logical Systems
@@ -35,15 +35,29 @@ Description-Content-Type: text/markdown
35
35
  License-File: LICENSE
36
36
  Requires-Dist: requests
37
37
  Requires-Dist: pyyaml
38
- Requires-Dist: anthropic
39
- Requires-Dist: google-generativeai
40
- Requires-Dist: pymupdf
38
+ Requires-Dist: python-dotenv
41
39
  Requires-Dist: beautifulsoup4
42
40
  Provides-Extra: dev
43
41
  Requires-Dist: pytest; extra == "dev"
44
42
  Requires-Dist: pytest-mock; extra == "dev"
45
43
  Requires-Dist: flake8; extra == "dev"
46
44
  Requires-Dist: black; extra == "dev"
45
+ Provides-Extra: cli
46
+ Requires-Dist: rich>=13.0; extra == "cli"
47
+ Provides-Extra: gemini
48
+ Requires-Dist: google-generativeai; extra == "gemini"
49
+ Provides-Extra: claude
50
+ Requires-Dist: anthropic; extra == "claude"
51
+ Provides-Extra: openai
52
+ Requires-Dist: openai; extra == "openai"
53
+ Provides-Extra: office
54
+ Requires-Dist: pymupdf; extra == "office"
55
+ Provides-Extra: all
56
+ Requires-Dist: rich>=13.0; extra == "all"
57
+ Requires-Dist: google-generativeai; extra == "all"
58
+ Requires-Dist: anthropic; extra == "all"
59
+ Requires-Dist: openai; extra == "all"
60
+ Requires-Dist: pymupdf; extra == "all"
47
61
  Dynamic: license-file
48
62
 
49
63
  <div align="center">
@@ -106,6 +120,7 @@ Skillware/
106
120
  │ ├── instructions.md # Cognitive map for the LLM
107
121
  │ └── test_skill.py # Unit tests & schema validation
108
122
  ├── skillware/ # Core Framework Package
123
+ │ ├── cli.py # Command-line interface
109
124
  │ └── core/
110
125
  │ ├── base_skill.py # Abstract Base Class for skills
111
126
  │ ├── env.py # Environment Management
@@ -135,7 +150,16 @@ pip install -e .
135
150
 
136
151
  > **Note**: Individual skills may have their own dependencies. The `SkillLoader` validates `manifest.yaml` and warns of missing packages (e.g., `requests`, `pandas`) upon loading a skill.
137
152
 
138
- ### 2. Configuration
153
+ ### 2. Verify your installation
154
+
155
+ ```bash
156
+ pip install "skillware[cli]"
157
+ skillware list
158
+ ```
159
+
160
+ This prints a table of all locally available skills and confirms the install and path resolution are working.
161
+
162
+ ### 3. Configuration
139
163
 
140
164
  Create a `.env` file with your API keys (e.g., Google Gemini API Key):
141
165
 
@@ -143,7 +167,7 @@ Create a `.env` file with your API keys (e.g., Google Gemini API Key):
143
167
  GOOGLE_API_KEY="your_key"
144
168
  ```
145
169
 
146
- ### 3. Usage Example (Gemini)
170
+ ### 4. Usage Example (Gemini)
147
171
 
148
172
  ```python
149
173
  import google.generativeai as genai
@@ -184,6 +208,7 @@ print(response.text)
184
208
  * **[Usage Guide: Ollama](docs/usage/ollama.md)**: Native integration for local models via Ollama.
185
209
  * **[API Keys for Skills](docs/usage/api_keys.md)**: Environment variables, cloud/CI setup, and security for skills that call external APIs.
186
210
  * **[Skill Library](docs/skills/README.md)**: Available capabilities.
211
+ * **[CLI Reference](docs/usage/cli.md)**: Discover and inspect locally installed skills from the terminal.
187
212
 
188
213
  ## Contributing
189
214
 
@@ -58,6 +58,7 @@ Skillware/
58
58
  │ ├── instructions.md # Cognitive map for the LLM
59
59
  │ └── test_skill.py # Unit tests & schema validation
60
60
  ├── skillware/ # Core Framework Package
61
+ │ ├── cli.py # Command-line interface
61
62
  │ └── core/
62
63
  │ ├── base_skill.py # Abstract Base Class for skills
63
64
  │ ├── env.py # Environment Management
@@ -87,7 +88,16 @@ pip install -e .
87
88
 
88
89
  > **Note**: Individual skills may have their own dependencies. The `SkillLoader` validates `manifest.yaml` and warns of missing packages (e.g., `requests`, `pandas`) upon loading a skill.
89
90
 
90
- ### 2. Configuration
91
+ ### 2. Verify your installation
92
+
93
+ ```bash
94
+ pip install "skillware[cli]"
95
+ skillware list
96
+ ```
97
+
98
+ This prints a table of all locally available skills and confirms the install and path resolution are working.
99
+
100
+ ### 3. Configuration
91
101
 
92
102
  Create a `.env` file with your API keys (e.g., Google Gemini API Key):
93
103
 
@@ -95,7 +105,7 @@ Create a `.env` file with your API keys (e.g., Google Gemini API Key):
95
105
  GOOGLE_API_KEY="your_key"
96
106
  ```
97
107
 
98
- ### 3. Usage Example (Gemini)
108
+ ### 4. Usage Example (Gemini)
99
109
 
100
110
  ```python
101
111
  import google.generativeai as genai
@@ -136,6 +146,7 @@ print(response.text)
136
146
  * **[Usage Guide: Ollama](docs/usage/ollama.md)**: Native integration for local models via Ollama.
137
147
  * **[API Keys for Skills](docs/usage/api_keys.md)**: Environment variables, cloud/CI setup, and security for skills that call external APIs.
138
148
  * **[Skill Library](docs/skills/README.md)**: Available capabilities.
149
+ * **[CLI Reference](docs/usage/cli.md)**: Discover and inspect locally installed skills from the terminal.
139
150
 
140
151
  ## Contributing
141
152
 
@@ -4,11 +4,11 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "skillware"
7
- version = "0.2.7"
7
+ version = "0.2.9"
8
8
  description = "A framework for modular, self-contained AI skills."
9
9
  readme = "README.md"
10
10
  authors = [
11
- { name = "ARPA Hellenic Logic Systems", email = "skillware-os@arpacorp.net" },
11
+ { name = "ARPA Hellenic Logical Systems", email = "skillware-os@arpacorp.net" },
12
12
  ]
13
13
  urls = { "Homepage" = "https://arpacorp.net", "Repository" = "https://github.com/arpahls/skillware" }
14
14
  license = { file = "LICENSE" }
@@ -20,13 +20,14 @@ classifiers = [
20
20
  dependencies = [
21
21
  "requests",
22
22
  "pyyaml",
23
- "anthropic",
24
- "google-generativeai",
25
- "pymupdf",
23
+ "python-dotenv",
26
24
  "beautifulsoup4",
27
25
  ]
28
26
  requires-python = ">=3.10"
29
27
 
28
+ [project.scripts]
29
+ skillware = "skillware.cli:main"
30
+
30
31
  [project.optional-dependencies]
31
32
  dev = [
32
33
  "pytest",
@@ -34,6 +35,28 @@ dev = [
34
35
  "flake8",
35
36
  "black",
36
37
  ]
38
+ cli = [
39
+ "rich>=13.0",
40
+ ]
41
+ gemini = [
42
+ "google-generativeai",
43
+ ]
44
+ claude = [
45
+ "anthropic",
46
+ ]
47
+ openai = [
48
+ "openai",
49
+ ]
50
+ office = [
51
+ "pymupdf",
52
+ ]
53
+ all = [
54
+ "rich>=13.0",
55
+ "google-generativeai",
56
+ "anthropic",
57
+ "openai",
58
+ "pymupdf",
59
+ ]
37
60
 
38
61
  [tool.setuptools]
39
62
  include-package-data = true
@@ -0,0 +1 @@
1
+ # dev_tools skill category.
@@ -0,0 +1 @@
1
+ # Issue Resolver skill package.
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "Issue Resolver",
3
+ "description": "Analyzes any GitHub issue against its target repository and produces a structured resolution plan with ranked implementation options, affected files, and caveats.",
4
+ "issuer": {
5
+ "name": "Ross Peili",
6
+ "email": "vpeilivanidis@gmail.com",
7
+ "github": "rosspeili",
8
+ "org": "ARPAHLS"
9
+ },
10
+ "icon": "git-pull-request",
11
+ "color": "#6E57E0",
12
+ "ui_schema": {
13
+ "type": "card",
14
+ "fields": [
15
+ {
16
+ "key": "status",
17
+ "label": "Status"
18
+ },
19
+ {
20
+ "key": "issue.number",
21
+ "label": "Issue"
22
+ },
23
+ {
24
+ "key": "issue.repo",
25
+ "label": "Repository"
26
+ },
27
+ {
28
+ "key": "auth.token_provided",
29
+ "label": "Authenticated"
30
+ }
31
+ ]
32
+ }
33
+ }
@@ -0,0 +1,104 @@
1
+ # Issue Resolver
2
+
3
+ You are using the `dev_tools/issue_resolver` skill.
4
+
5
+ Load this skill when the user provides a GitHub issue URL and asks you to understand, plan, or begin resolving it. The skill applies to any public GitHub repository. It is model-agnostic and does not assume any particular project's conventions.
6
+
7
+ ## When to use this skill
8
+
9
+ - The user supplies a GitHub issue URL (with or without additional instructions).
10
+ - The user asks you to analyse an issue, understand its scope, or produce an implementation plan.
11
+ - The user wants to know which files will be affected before any code is written.
12
+ - The user wants ranked options and a recommended approach before committing to implementation.
13
+
14
+ ## Workflow you must follow after receiving the skill payload
15
+
16
+ The skill's `execute()` call returns a `status: ready` payload containing pre-computed URLs. Use those URLs with your available tools to carry out the following stages in order. Do not skip stages.
17
+
18
+ ### Stage 1 — Fetch the issue
19
+
20
+ Using the `issue.api_url` from the payload:
21
+
22
+ 1. Fetch the issue via the GitHub API. If `auth.token_provided` is true, include the `Authorization: Bearer <token>` header.
23
+ 2. Extract: title, body, labels, state, assignees, milestone.
24
+ 3. Fetch any linked comments (`issue.api_url/comments`) and skim for decisions, constraints, or acceptance criteria that are not in the body.
25
+ 4. Check for linked pull requests or referenced issues in the body.
26
+
27
+ ### Stage 2 — Understand the repository
28
+
29
+ Using the `repository` URLs from the payload:
30
+
31
+ 1. Fetch and read `repository.readme_url`. Identify: project purpose, tech stack, install instructions, any stated conventions.
32
+ 2. Fetch and read `repository.contributing_url` if it exists (do not fail if it returns 404). Identify: contribution workflow, code style, PR requirements, any skill or module standards.
33
+ 3. Fetch the directory tree via `repository.tree_api_url`. Identify the top-level structure: key source directories, test directories, docs directories, CI configuration, and any existing analogues to what the issue requests.
34
+ 4. If the issue references specific files or directories, fetch and inspect their current contents.
35
+
36
+ ### Stage 3 — Analyse
37
+
38
+ Produce a structured internal analysis covering:
39
+
40
+ - **Problem statement**: what the issue is actually asking for, including unstated implications.
41
+ - **Acceptance criteria**: verifiable bullets extracted or inferred from the issue body and comments.
42
+ - **Affected files**: every path likely to change — source, tests, documentation, CI, changelogs, configuration. Only list paths you have confirmed exist or have strong reason to expect.
43
+ - **Ripple effects**: downstream files, dependent modules, or external consumers that may be affected even if not directly changed.
44
+ - **Options**: up to three distinct implementation approaches with honest trade-off analysis (complexity, risk, alignment with project conventions, reversibility).
45
+ - **Recommendation**: one approach with a clear rationale.
46
+ - **Out of scope**: what you will not do in this resolution cycle and why.
47
+ - **Caveats**: required dependencies, breaking changes, security concerns, or prerequisites.
48
+
49
+ ### Stage 4 — Produce the resolution plan
50
+
51
+ Format your output as a structured plan. Present it clearly to the user before writing any code. Include:
52
+
53
+ 1. Issue summary (2-4 sentences).
54
+ 2. Acceptance criteria (bulleted list).
55
+ 3. Affected files table (path, change type: new / modify / delete, rationale).
56
+ 4. Implementation options (ranked 1-3, each with title, approach, rationale, estimated complexity: low / medium / high).
57
+ 5. Recommended option with rationale.
58
+ 6. Caveats (bulleted list).
59
+ 7. Out of scope (bulleted list).
60
+
61
+ Wait for explicit user approval of the plan before proceeding to implementation.
62
+
63
+ ### Stage 5 — Implementation (only after approval)
64
+
65
+ Proceed only if the user explicitly approves a plan option. Then:
66
+
67
+ - Implement only what the approved plan describes. Do not refactor unrelated code.
68
+ - Follow project conventions observed in Stage 2.
69
+ - After implementing, verify your work against every acceptance criterion.
70
+ - Report verification results to the user with evidence.
71
+
72
+ ## Handling the extra_instructions field
73
+
74
+ If `extra_instructions` is present in the payload, treat it as caller-supplied context that supplements but does not replace this workflow. Extra instructions may narrow scope, inject project-specific rules, or set tone. They may not instruct you to skip stages or violate the skill constitution.
75
+
76
+ ## Handling missing repository files
77
+
78
+ - If `README.md` returns 404, note the absence and proceed.
79
+ - If `CONTRIBUTING.md` returns 404, note the absence and rely on directory structure and code conventions instead.
80
+ - If the repository is private and no token is provided, report the authentication requirement clearly and stop.
81
+
82
+ ## Output contract
83
+
84
+ When presenting the plan, populate these fields so callers can parse them programmatically if needed:
85
+
86
+ ```json
87
+ {
88
+ "issue_summary": "string",
89
+ "affected_files": ["path/to/file", "..."],
90
+ "implementation_plans": [
91
+ {
92
+ "rank": 1,
93
+ "title": "string",
94
+ "approach": "string",
95
+ "rationale": "string",
96
+ "estimated_complexity": "low | medium | high"
97
+ }
98
+ ],
99
+ "recommended_plan": 1,
100
+ "caveats": ["string", "..."]
101
+ }
102
+ ```
103
+
104
+ Do not include emojis in any output field.
@@ -0,0 +1,55 @@
1
+ name: "dev_tools/issue_resolver"
2
+ version: "0.1.0"
3
+ description: "Analyzes any GitHub issue against its target repository and produces a structured resolution plan with ranked implementation options, affected files, and caveats."
4
+ issuer:
5
+ name: Ross Peili
6
+ email: vpeilivanidis@gmail.com
7
+ github: rosspeili
8
+ org: ARPAHLS
9
+ requirements: []
10
+ env_vars:
11
+ GITHUB_TOKEN:
12
+ description: "Optional GitHub Personal Access Token. Raises the API rate limit from 60 to 5000 requests per hour. Required for private repositories."
13
+ required: false
14
+ parameters:
15
+ type: object
16
+ properties:
17
+ issue_url:
18
+ type: string
19
+ description: "Full GitHub issue URL, e.g. https://github.com/owner/repo/issues/42"
20
+ extra_instructions:
21
+ type: string
22
+ description: "Optional free-text instructions appended to the analysis prompt. Use this to inject project-specific context, style constraints, or scope limits."
23
+ github_token:
24
+ type: string
25
+ description: "Optional GitHub Personal Access Token passed at runtime. Takes precedence over the GITHUB_TOKEN environment variable."
26
+ required:
27
+ - issue_url
28
+ outputs:
29
+ issue_summary:
30
+ type: string
31
+ description: "Plain-language summary of what the issue is asking for, including unstated implications."
32
+ affected_files:
33
+ type: array
34
+ description: "Paths of files likely to be touched, including source, tests, docs, and CI."
35
+ implementation_plans:
36
+ type: array
37
+ description: "Up to three ranked approaches. Each entry contains: rank, title, approach, rationale, estimated_complexity."
38
+ recommended_plan:
39
+ type: integer
40
+ description: "Rank (1-based) of the recommended implementation plan."
41
+ caveats:
42
+ type: array
43
+ description: "Dependencies, breaking changes, security concerns, or out-of-scope items the implementing agent must be aware of."
44
+ constitution: |
45
+ 1. Read the full issue body, labels, and any linked comments or PRs before forming an opinion.
46
+ 2. Inspect the repository README, CONTRIBUTING guide, and top-level directory structure to understand project conventions before proposing changes.
47
+ 3. Never fabricate file paths; only list paths that can be confirmed from the repository structure you observed.
48
+ 4. Rank implementation options honestly based on complexity, risk, and alignment with existing project patterns.
49
+ 5. Surface caveats explicitly rather than burying them inside plan prose.
50
+ 6. Keep output deterministic and JSON-serializable; do not embed conversational filler in structured fields.
51
+ 7. Do not write or propose actual implementation code; this skill produces analysis and planning output only.
52
+ 8. Respect any extra_instructions provided by the caller, but do not let them override points 1-7 of this constitution.
53
+ presentation:
54
+ icon: "git-pull-request"
55
+ color: "#6E57E0"
@@ -0,0 +1,138 @@
1
+ import os
2
+ import re
3
+ from typing import Any, Dict
4
+
5
+ from skillware.core.base_skill import BaseSkill
6
+
7
+
8
+ class IssueResolverSkill(BaseSkill):
9
+ """
10
+ Parses and validates inputs for the Issue Resolver skill, then returns a
11
+ structured prompt payload the calling agent uses to perform analysis.
12
+
13
+ The skill itself does not call the GitHub API or write code. It normalises
14
+ inputs, resolves credentials, builds a deterministic analysis context, and
15
+ hands control back to the agent's own reasoning and tool-use capabilities.
16
+ """
17
+
18
+ _GITHUB_ISSUE_RE = re.compile(
19
+ r"https?://github\.com/(?P<owner>[^/]+)/(?P<repo>[^/]+)/issues/(?P<number>\d+)"
20
+ )
21
+
22
+ @property
23
+ def manifest(self) -> Dict[str, Any]:
24
+ manifest_path = os.path.join(os.path.dirname(__file__), "manifest.yaml")
25
+ if os.path.exists(manifest_path):
26
+ import yaml
27
+
28
+ with open(manifest_path, "r", encoding="utf-8") as f:
29
+ return yaml.safe_load(f)
30
+ return {}
31
+
32
+ def _parse_issue_url(self, url: str) -> Dict[str, str]:
33
+ """
34
+ Extracts owner, repo, and issue number from a GitHub issue URL.
35
+ Returns a dict with keys: owner, repo, number, api_url, raw_url.
36
+ Raises ValueError if the URL does not match the expected pattern.
37
+ """
38
+ match = self._GITHUB_ISSUE_RE.match(url.strip())
39
+ if not match:
40
+ raise ValueError(
41
+ f"issue_url does not match the expected GitHub issue URL pattern: {url!r}. "
42
+ "Expected format: https://github.com/<owner>/<repo>/issues/<number>"
43
+ )
44
+ owner = match.group("owner")
45
+ repo = match.group("repo")
46
+ number = match.group("number")
47
+ return {
48
+ "owner": owner,
49
+ "repo": repo,
50
+ "number": number,
51
+ "api_url": f"https://api.github.com/repos/{owner}/{repo}/issues/{number}",
52
+ "raw_url": url.strip(),
53
+ "repo_api_url": f"https://api.github.com/repos/{owner}/{repo}",
54
+ "repo_html_url": f"https://github.com/{owner}/{repo}",
55
+ }
56
+
57
+ def _resolve_token(self, params: Dict[str, Any]) -> str:
58
+ """
59
+ Returns the GitHub token to use, preferring the runtime parameter over
60
+ the environment variable. Returns an empty string if neither is set.
61
+ """
62
+ token = (params.get("github_token") or "").strip()
63
+ if not token:
64
+ token = (
65
+ self.config.get("GITHUB_TOKEN") or os.environ.get("GITHUB_TOKEN") or ""
66
+ )
67
+ return token
68
+
69
+ def execute(self, params: Dict[str, Any]) -> Dict[str, Any]:
70
+ """
71
+ Validates inputs and returns a structured analysis context.
72
+
73
+ The returned dict contains everything the calling agent needs to begin
74
+ the resolution workflow using its own tools (HTTP fetching, file
75
+ inspection, reasoning). The agent should follow the instructions in
76
+ instructions.md when interpreting this payload.
77
+ """
78
+ issue_url = (params.get("issue_url") or "").strip()
79
+ if not issue_url:
80
+ return {
81
+ "status": "error",
82
+ "message": "issue_url is required and must not be empty.",
83
+ }
84
+
85
+ try:
86
+ parsed = self._parse_issue_url(issue_url)
87
+ except ValueError as exc:
88
+ return {"status": "error", "message": str(exc)}
89
+
90
+ token = self._resolve_token(params)
91
+ extra_instructions = (params.get("extra_instructions") or "").strip()
92
+
93
+ auth_header_note = (
94
+ "Include the Authorization header: Bearer <GITHUB_TOKEN>."
95
+ if token
96
+ else (
97
+ "No GITHUB_TOKEN is configured. The GitHub API will apply the "
98
+ "unauthenticated rate limit (60 requests per hour). For private "
99
+ "repositories or high-volume usage, set GITHUB_TOKEN."
100
+ )
101
+ )
102
+
103
+ return {
104
+ "status": "ready",
105
+ "issue": {
106
+ "url": parsed["raw_url"],
107
+ "api_url": parsed["api_url"],
108
+ "owner": parsed["owner"],
109
+ "repo": parsed["repo"],
110
+ "number": parsed["number"],
111
+ },
112
+ "repository": {
113
+ "html_url": parsed["repo_html_url"],
114
+ "api_url": parsed["repo_api_url"],
115
+ "readme_url": (
116
+ f"https://raw.githubusercontent.com/{parsed['owner']}"
117
+ f"/{parsed['repo']}/HEAD/README.md"
118
+ ),
119
+ "contributing_url": (
120
+ f"https://raw.githubusercontent.com/{parsed['owner']}"
121
+ f"/{parsed['repo']}/HEAD/CONTRIBUTING.md"
122
+ ),
123
+ "tree_api_url": (
124
+ f"https://api.github.com/repos/{parsed['owner']}/{parsed['repo']}"
125
+ "/git/trees/HEAD?recursive=1"
126
+ ),
127
+ },
128
+ "auth": {
129
+ "token_provided": bool(token),
130
+ "note": auth_header_note,
131
+ },
132
+ "extra_instructions": extra_instructions or None,
133
+ "next_step": (
134
+ "Follow the workflow in instructions.md. Fetch the issue, "
135
+ "read the repository context, then produce the structured "
136
+ "resolution plan as described."
137
+ ),
138
+ }