@openhands/extensions 0.0.1-alpha → 0.2.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/skills/custom-codereview-guide.md +25 -0
- package/.github/pull_request_template.md +38 -0
- package/.github/release.yml +14 -0
- package/.github/workflows/check-extensions.yml +72 -0
- package/.github/workflows/npm-publish.yml +89 -0
- package/.github/workflows/pr.yml +30 -0
- package/.github/workflows/release.yml +24 -0
- package/.github/workflows/tests.yml +25 -0
- package/.github/workflows/vulnerability-scan.yml +87 -0
- package/.release-please-manifest.json +3 -0
- package/AGENTS.md +132 -0
- package/README.md +10 -0
- package/analysis_results.md +162 -0
- package/marketplaces/large-codebase.json +66 -0
- package/marketplaces/openhands-extensions.json +682 -0
- package/package.json +4 -10
- package/plugins/README.md +30 -0
- package/plugins/city-weather/.plugin/plugin.json +13 -0
- package/plugins/city-weather/README.md +145 -0
- package/plugins/city-weather/commands/now.md +56 -0
- package/plugins/cobol-modernization/.plugin/plugin.json +19 -0
- package/plugins/cobol-modernization/README.md +201 -0
- package/plugins/cobol-modernization/references/troubleshooting.md +18 -0
- package/plugins/cobol-modernization/skills/build-setup/SKILL.md +78 -0
- package/plugins/cobol-modernization/skills/build-setup/scripts/install-gnucobol.sh +32 -0
- package/plugins/cobol-modernization/skills/cobol-modernization-overview/SKILL.md +113 -0
- package/plugins/cobol-modernization/skills/mainfraime-removal/SKILL.md +62 -0
- package/plugins/cobol-modernization/skills/mainfraime-removal/references/cics-transformation-examples.md +45 -0
- package/plugins/cobol-modernization/skills/mainframe-planning/SKILL.md +78 -0
- package/plugins/cobol-modernization/skills/to-java-migration/SKILL.md +59 -0
- package/plugins/cobol-modernization/skills/to-java-migration/references/cobol-to-java-example.md +58 -0
- package/plugins/cobol-modernization/skills/to-java-migration/references/datatype-mappings.md +19 -0
- package/plugins/issue-duplicate-checker/.plugin/plugin.json +13 -0
- package/plugins/issue-duplicate-checker/README.md +51 -0
- package/plugins/issue-duplicate-checker/action.yml +349 -0
- package/plugins/issue-duplicate-checker/scripts/auto_close_duplicate_issues.py +569 -0
- package/plugins/issue-duplicate-checker/scripts/issue_duplicate_check_openhands.py +681 -0
- package/plugins/issue-duplicate-checker/scripts/post_duplicate_notice.js +220 -0
- package/plugins/issue-duplicate-checker/scripts/remove_duplicate_candidate_label.js +27 -0
- package/plugins/magic-test/.plugin/plugin.json +13 -0
- package/plugins/magic-test/skills/magic-word/SKILL.md +33 -0
- package/plugins/migration-scoring/.plugin/plugin.json +19 -0
- package/plugins/migration-scoring/README.md +244 -0
- package/plugins/migration-scoring/skills/migration-mapping/SKILL.md +72 -0
- package/plugins/migration-scoring/skills/migration-report/SKILL.md +118 -0
- package/plugins/migration-scoring/skills/migration-scoring-overview/SKILL.md +126 -0
- package/plugins/migration-scoring/skills/score-quality/SKILL.md +54 -0
- package/plugins/migration-scoring/skills/score-quality/references/scoring-criteria.md +30 -0
- package/plugins/migration-scoring/skills/score-style/SKILL.md +106 -0
- package/plugins/onboarding/.plugin/plugin.json +20 -0
- package/plugins/onboarding/README.md +30 -0
- package/plugins/onboarding/references/criteria.md +144 -0
- package/plugins/onboarding/skills/agent-readiness-report/README.md +23 -0
- package/plugins/onboarding/skills/agent-readiness-report/SKILL.md +122 -0
- package/plugins/onboarding/skills/agent-readiness-report/scripts/scan_agent_instructions.sh +88 -0
- package/plugins/onboarding/skills/agent-readiness-report/scripts/scan_build_env.sh +114 -0
- package/plugins/onboarding/skills/agent-readiness-report/scripts/scan_feedback_loops.sh +133 -0
- package/plugins/onboarding/skills/agent-readiness-report/scripts/scan_policy.sh +113 -0
- package/plugins/onboarding/skills/agent-readiness-report/scripts/scan_workflows.sh +127 -0
- package/plugins/onboarding/skills/improve-agent-readiness/README.md +19 -0
- package/plugins/onboarding/skills/improve-agent-readiness/SKILL.md +167 -0
- package/plugins/onboarding/skills/setup-agents-md/README.md +15 -0
- package/plugins/onboarding/skills/setup-agents-md/SKILL.md +150 -0
- package/plugins/onboarding/skills/setup-openhands/README.md +20 -0
- package/plugins/onboarding/skills/setup-openhands/SKILL.md +56 -0
- package/plugins/onboarding/skills/setup-pr-review/README.md +23 -0
- package/plugins/onboarding/skills/setup-pr-review/SKILL.md +72 -0
- package/plugins/openhands/.plugin/plugin.json +13 -0
- package/plugins/openhands/README.md +52 -0
- package/plugins/openhands/SKILL.md +61 -0
- package/plugins/openhands/commands/create.md +55 -0
- package/plugins/openhands/commands/openhands-cloud.md +8 -0
- package/plugins/openhands/scripts/run.sh +69 -0
- package/plugins/pr-review/.plugin/plugin.json +13 -0
- package/plugins/pr-review/README.md +393 -0
- package/plugins/pr-review/action.yml +298 -0
- package/plugins/pr-review/scripts/agent_script.py +1282 -0
- package/plugins/pr-review/scripts/evaluate_review.py +655 -0
- package/plugins/pr-review/scripts/prompt.py +260 -0
- package/plugins/pr-review/workflows/pr-review-by-openhands.yml +51 -0
- package/plugins/pr-review/workflows/pr-review-evaluation.yml +85 -0
- package/plugins/qa-changes/.plugin/plugin.json +11 -0
- package/plugins/qa-changes/README.md +185 -0
- package/plugins/qa-changes/action.yml +181 -0
- package/plugins/qa-changes/scripts/agent_script.py +406 -0
- package/plugins/qa-changes/scripts/evaluate_qa_changes.py +385 -0
- package/plugins/qa-changes/scripts/prompt.py +174 -0
- package/plugins/qa-changes/workflows/qa-changes-by-openhands.yml +50 -0
- package/plugins/qa-changes/workflows/qa-changes-evaluation.yml +85 -0
- package/plugins/release-notes/.plugin/plugin.json +19 -0
- package/plugins/release-notes/README.md +283 -0
- package/plugins/release-notes/SKILL.md +83 -0
- package/plugins/release-notes/action.yml +117 -0
- package/plugins/release-notes/commands/release-notes.md +8 -0
- package/plugins/release-notes/scripts/agent_script.py +292 -0
- package/plugins/release-notes/scripts/generate_release_notes.py +733 -0
- package/plugins/release-notes/scripts/prompt.py +90 -0
- package/plugins/release-notes/scripts/validate_release_notes.py +328 -0
- package/plugins/release-notes/workflows/release-notes.yml +76 -0
- package/plugins/vulnerability-remediation/.plugin/plugin.json +19 -0
- package/plugins/vulnerability-remediation/README.md +217 -0
- package/plugins/vulnerability-remediation/action.yml +187 -0
- package/plugins/vulnerability-remediation/scripts/scan_and_remediate.py +561 -0
- package/plugins/vulnerability-remediation/workflows/vulnerability-scan.yml +87 -0
- package/pyproject.toml +12 -0
- package/release-please-config.json +16 -0
- package/scripts/sync_extensions.py +494 -0
- package/scripts/sync_openhands_sdk_skill.py +264 -0
- package/skills/README.md +159 -0
- package/skills/add-javadoc/.plugin/plugin.json +18 -0
- package/skills/add-javadoc/README.md +40 -0
- package/skills/add-javadoc/SKILL.md +35 -0
- package/skills/add-javadoc/references/example.md +32 -0
- package/skills/add-skill/.plugin/plugin.json +18 -0
- package/skills/add-skill/README.md +67 -0
- package/skills/add-skill/SKILL.md +47 -0
- package/skills/add-skill/scripts/fetch_skill.py +259 -0
- package/skills/agent-creator/.plugin/plugin.json +20 -0
- package/skills/agent-creator/README.md +104 -0
- package/skills/agent-creator/SKILL.md +190 -0
- package/skills/agent-creator/commands/agent-creator.md +8 -0
- package/skills/agent-creator/references/fallback.md +117 -0
- package/skills/agent-memory/.plugin/plugin.json +18 -0
- package/skills/agent-memory/README.md +35 -0
- package/skills/agent-memory/SKILL.md +30 -0
- package/skills/agent-memory/commands/remember.md +8 -0
- package/skills/agent-sdk-builder/.plugin/plugin.json +18 -0
- package/skills/agent-sdk-builder/README.md +40 -0
- package/skills/agent-sdk-builder/SKILL.md +37 -0
- package/skills/agent-sdk-builder/commands/agent-builder.md +8 -0
- package/skills/azure-devops/.plugin/plugin.json +18 -0
- package/skills/azure-devops/README.md +55 -0
- package/skills/azure-devops/SKILL.md +50 -0
- package/skills/bitbucket/.plugin/plugin.json +17 -0
- package/skills/bitbucket/README.md +50 -0
- package/skills/bitbucket/SKILL.md +45 -0
- package/skills/code-review/.plugin/plugin.json +19 -0
- package/skills/code-review/README.md +18 -0
- package/skills/code-review/SKILL.md +208 -0
- package/skills/code-review/commands/codereview-roasted.md +8 -0
- package/skills/code-review/commands/codereview.md +8 -0
- package/skills/code-review/references/risk-evaluation.md +41 -0
- package/skills/code-review/references/supply-chain-security.md +31 -0
- package/skills/code-simplifier/.plugin/plugin.json +21 -0
- package/skills/code-simplifier/README.md +30 -0
- package/skills/code-simplifier/SKILL.md +91 -0
- package/skills/code-simplifier/commands/simplify.md +8 -0
- package/skills/code-simplifier/references/code-quality-review.md +86 -0
- package/skills/code-simplifier/references/code-reuse-review.md +63 -0
- package/skills/code-simplifier/references/efficiency-review.md +81 -0
- package/skills/datadog/.plugin/plugin.json +19 -0
- package/skills/datadog/README.md +100 -0
- package/skills/datadog/SKILL.md +95 -0
- package/skills/deno/.plugin/plugin.json +18 -0
- package/skills/deno/README.md +5 -0
- package/skills/deno/SKILL.md +99 -0
- package/skills/deno/references/README.md +6 -0
- package/skills/discord/.plugin/plugin.json +18 -0
- package/skills/discord/README.md +31 -0
- package/skills/discord/SKILL.md +109 -0
- package/skills/discord/__init__.py +0 -0
- package/skills/discord/references/REFERENCE.md +78 -0
- package/skills/discord/scripts/__init__.py +0 -0
- package/skills/discord/scripts/_http.py +127 -0
- package/skills/discord/scripts/post_webhook.py +106 -0
- package/skills/discord/scripts/send_message.py +102 -0
- package/skills/docker/.plugin/plugin.json +17 -0
- package/skills/docker/README.md +34 -0
- package/skills/docker/SKILL.md +29 -0
- package/skills/evidence-based-citations/.plugin/plugin.json +20 -0
- package/skills/evidence-based-citations/README.md +31 -0
- package/skills/evidence-based-citations/SKILL.md +59 -0
- package/skills/flarglebargle/.plugin/plugin.json +16 -0
- package/skills/flarglebargle/README.md +14 -0
- package/skills/flarglebargle/SKILL.md +9 -0
- package/skills/frontend-design/.plugin/plugin.json +21 -0
- package/skills/frontend-design/LICENSE.txt +177 -0
- package/skills/frontend-design/README.md +42 -0
- package/skills/frontend-design/SKILL.md +42 -0
- package/skills/github/.plugin/plugin.json +19 -0
- package/skills/github/README.md +42 -0
- package/skills/github/SKILL.md +106 -0
- package/skills/github-pr-review/.plugin/plugin.json +18 -0
- package/skills/github-pr-review/README.md +145 -0
- package/skills/github-pr-review/SKILL.md +148 -0
- package/skills/github-pr-review/commands/github-pr-review.md +8 -0
- package/skills/github-pr-reviewer/.plugin/plugin.json +20 -0
- package/skills/github-pr-reviewer/README.md +34 -0
- package/skills/github-pr-reviewer/SKILL.md +89 -0
- package/skills/github-pr-reviewer/commands/pr-reviewer:setup.md +8 -0
- package/skills/github-repo-monitor/.plugin/plugin.json +22 -0
- package/skills/github-repo-monitor/README.md +70 -0
- package/skills/github-repo-monitor/SKILL.md +316 -0
- package/skills/github-repo-monitor/commands/github-monitor:poll.md +8 -0
- package/skills/github-repo-monitor/references/github-api.md +241 -0
- package/skills/github-repo-monitor/references/state-schema.md +160 -0
- package/skills/github-repo-monitor/scripts/main.py +915 -0
- package/skills/github-repo-monitor/tests/test_main.py +400 -0
- package/skills/gitlab/.plugin/plugin.json +17 -0
- package/skills/gitlab/README.md +37 -0
- package/skills/gitlab/SKILL.md +32 -0
- package/skills/incident-retrospective/.plugin/plugin.json +21 -0
- package/skills/incident-retrospective/README.md +34 -0
- package/skills/incident-retrospective/SKILL.md +98 -0
- package/skills/incident-retrospective/commands/incident-retro:setup.md +8 -0
- package/skills/iterate/.plugin/plugin.json +13 -0
- package/skills/iterate/README.md +25 -0
- package/skills/iterate/SKILL.md +399 -0
- package/skills/iterate/commands/babysit.md +8 -0
- package/skills/iterate/commands/iterate.md +8 -0
- package/skills/iterate/commands/verify.md +8 -0
- package/skills/iterate/references/heuristics.md +58 -0
- package/skills/iterate/references/verification.md +96 -0
- package/skills/jupyter/.plugin/plugin.json +18 -0
- package/skills/jupyter/README.md +55 -0
- package/skills/jupyter/SKILL.md +50 -0
- package/skills/kubernetes/.plugin/plugin.json +18 -0
- package/skills/kubernetes/README.md +53 -0
- package/skills/kubernetes/SKILL.md +48 -0
- package/skills/learn-from-code-review/.plugin/plugin.json +19 -0
- package/skills/learn-from-code-review/README.md +64 -0
- package/skills/learn-from-code-review/SKILL.md +186 -0
- package/skills/learn-from-code-review/commands/learn-from-reviews.md +8 -0
- package/skills/linear/.plugin/plugin.json +19 -0
- package/skills/linear/README.md +58 -0
- package/skills/linear/SKILL.md +213 -0
- package/skills/linear-triage/.plugin/plugin.json +21 -0
- package/skills/linear-triage/README.md +34 -0
- package/skills/linear-triage/SKILL.md +91 -0
- package/skills/linear-triage/commands/linear-triage:setup.md +8 -0
- package/skills/notion/.plugin/plugin.json +17 -0
- package/skills/notion/README.md +114 -0
- package/skills/notion/SKILL.md +109 -0
- package/skills/npm/.plugin/plugin.json +17 -0
- package/skills/npm/README.md +14 -0
- package/skills/npm/SKILL.md +9 -0
- package/skills/openhands-api/.plugin/plugin.json +22 -0
- package/skills/openhands-api/README.md +48 -0
- package/skills/openhands-api/SKILL.md +399 -0
- package/skills/openhands-api/references/README.md +33 -0
- package/skills/openhands-api/references/TROUBLESHOOTING.md +81 -0
- package/skills/openhands-api/references/example_prompt.md +12 -0
- package/skills/openhands-api/scripts/openhands_api.py +606 -0
- package/skills/openhands-api/scripts/openhands_api.ts +252 -0
- package/skills/openhands-automation/.plugin/plugin.json +19 -0
- package/skills/openhands-automation/README.md +89 -0
- package/skills/openhands-automation/SKILL.md +875 -0
- package/skills/openhands-automation/commands/automation:create.md +8 -0
- package/skills/openhands-automation/references/ab-testing.md +185 -0
- package/skills/openhands-automation/references/custom-automation.md +644 -0
- package/skills/openhands-sdk/.plugin/plugin.json +20 -0
- package/skills/openhands-sdk/README.md +22 -0
- package/skills/openhands-sdk/SKILL.md +229 -0
- package/skills/openhands-sdk/commands/sdk.md +8 -0
- package/skills/pdflatex/.plugin/plugin.json +18 -0
- package/skills/pdflatex/README.md +39 -0
- package/skills/pdflatex/SKILL.md +34 -0
- package/skills/prd/.plugin/plugin.json +19 -0
- package/skills/prd/README.md +28 -0
- package/skills/prd/SKILL.md +237 -0
- package/skills/prd/commands/prd.md +8 -0
- package/skills/qa-changes/README.md +18 -0
- package/skills/qa-changes/SKILL.md +229 -0
- package/skills/qa-changes/commands/qa-changes.md +8 -0
- package/skills/release-notes/README.md +24 -0
- package/skills/release-notes/SKILL.md +19 -0
- package/skills/release-notes/commands/release-notes.md +8 -0
- package/skills/research-brief/.plugin/plugin.json +20 -0
- package/skills/research-brief/README.md +34 -0
- package/skills/research-brief/SKILL.md +99 -0
- package/skills/research-brief/commands/research-brief:setup.md +8 -0
- package/skills/security/.plugin/plugin.json +18 -0
- package/skills/security/README.md +38 -0
- package/skills/security/SKILL.md +33 -0
- package/skills/skill-creator/.plugin/plugin.json +17 -0
- package/skills/skill-creator/LICENSE.txt +202 -0
- package/skills/skill-creator/README.md +182 -0
- package/skills/skill-creator/SKILL.md +545 -0
- package/skills/skill-creator/references/output-patterns.md +82 -0
- package/skills/skill-creator/references/workflows.md +28 -0
- package/skills/skill-creator/scripts/init_skill.py +303 -0
- package/skills/skill-creator/scripts/quick_validate.py +95 -0
- package/skills/slack-channel-monitor/.plugin/plugin.json +21 -0
- package/skills/slack-channel-monitor/README.md +91 -0
- package/skills/slack-channel-monitor/SKILL.md +276 -0
- package/skills/slack-channel-monitor/commands/slack-monitor:poll.md +8 -0
- package/skills/slack-channel-monitor/references/slack-api.md +207 -0
- package/skills/slack-channel-monitor/references/state-schema.md +180 -0
- package/skills/slack-channel-monitor/scripts/main.py +962 -0
- package/skills/slack-standup-digest/.plugin/plugin.json +21 -0
- package/skills/slack-standup-digest/README.md +34 -0
- package/skills/slack-standup-digest/SKILL.md +92 -0
- package/skills/slack-standup-digest/commands/standup-digest:setup.md +8 -0
- package/skills/spark-version-upgrade/.plugin/plugin.json +20 -0
- package/skills/spark-version-upgrade/README.md +54 -0
- package/skills/spark-version-upgrade/SKILL.md +233 -0
- package/skills/ssh/.plugin/plugin.json +18 -0
- package/skills/ssh/README.md +140 -0
- package/skills/ssh/SKILL.md +135 -0
- package/skills/swift-linux/.plugin/plugin.json +17 -0
- package/skills/swift-linux/README.md +86 -0
- package/skills/swift-linux/SKILL.md +81 -0
- package/skills/theme-factory/.plugin/plugin.json +19 -0
- package/skills/theme-factory/LICENSE.txt +202 -0
- package/skills/theme-factory/README.md +58 -0
- package/skills/theme-factory/SKILL.md +59 -0
- package/skills/theme-factory/theme-showcase.pdf +0 -0
- package/skills/theme-factory/themes/arctic-frost.md +19 -0
- package/skills/theme-factory/themes/botanical-garden.md +19 -0
- package/skills/theme-factory/themes/desert-rose.md +19 -0
- package/skills/theme-factory/themes/forest-canopy.md +19 -0
- package/skills/theme-factory/themes/golden-hour.md +19 -0
- package/skills/theme-factory/themes/midnight-galaxy.md +19 -0
- package/skills/theme-factory/themes/modern-minimalist.md +19 -0
- package/skills/theme-factory/themes/ocean-depths.md +19 -0
- package/skills/theme-factory/themes/sunset-boulevard.md +19 -0
- package/skills/theme-factory/themes/tech-innovation.md +19 -0
- package/skills/uv/.plugin/plugin.json +18 -0
- package/skills/uv/README.md +5 -0
- package/skills/uv/SKILL.md +95 -0
- package/skills/uv/references/README.md +5 -0
- package/skills/vercel/.plugin/plugin.json +18 -0
- package/skills/vercel/README.md +108 -0
- package/skills/vercel/SKILL.md +103 -0
- package/tests/test_add_skill_installs_to_agents_dir.py +42 -0
- package/tests/test_catalogs.py +109 -0
- package/tests/test_code_review_risk_evaluation.py +94 -0
- package/tests/test_issue_duplicate_checker.py +240 -0
- package/tests/test_openhands_api_python.py +152 -0
- package/tests/test_plugin_manifest.py +83 -0
- package/tests/test_pr_review_diff_payload.py +202 -0
- package/tests/test_pr_review_feedback.py +263 -0
- package/tests/test_pr_review_prompt.py +152 -0
- package/tests/test_pr_review_review_context.py +253 -0
- package/tests/test_qa_changes.py +232 -0
- package/tests/test_qa_changes_evaluation.py +259 -0
- package/tests/test_release_notes_generator.py +990 -0
- package/tests/test_sdk_loading.py +150 -0
- package/tests/test_skill_plugin_loading.py +149 -0
- package/tests/test_skills_have_readme.py +66 -0
- package/tests/test_sync_extensions.py +292 -0
- package/tests/test_workflow_sync.py +46 -0
- package/utils/analysis/README.md +7 -0
- package/utils/analysis/laminar_signals/README.md +211 -0
- package/utils/analysis/laminar_signals/analyze.py +780 -0
- package/utils/analysis/laminar_signals/templates/default.j2 +49 -0
- package/utils/analysis/laminar_signals/templates/pr_review.j2 +61 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
module.exports = async ({ github, context, core }) => {
|
|
2
|
+
const issueNumber = Number(process.env.ISSUE_NUMBER);
|
|
3
|
+
const summary = (process.env.SUMMARY || "").trim();
|
|
4
|
+
const classification = process.env.CLASSIFICATION || "no-match";
|
|
5
|
+
const autoClose = process.env.AUTO_CLOSE_CANDIDATE === "true";
|
|
6
|
+
const closeAfterDays = process.env.CLOSE_AFTER_DAYS || "3";
|
|
7
|
+
let candidates = [];
|
|
8
|
+
try {
|
|
9
|
+
candidates = JSON.parse(process.env.CANDIDATE_ISSUES_JSON || "[]");
|
|
10
|
+
} catch (error) {
|
|
11
|
+
core.setFailed(`Invalid candidate JSON: ${error.message}`);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (!Array.isArray(candidates)) {
|
|
15
|
+
core.setFailed("CANDIDATE_ISSUES_JSON is not an array");
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (candidates.length === 0) {
|
|
19
|
+
core.warning(`No candidate issues were returned for issue #${issueNumber}; skipping.`);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const canonicalIssueRaw = process.env.CANONICAL_ISSUE_NUMBER || candidates[0].number;
|
|
24
|
+
const canonicalIssueNumber = canonicalIssueRaw ? Number(canonicalIssueRaw) : Number.NaN;
|
|
25
|
+
const candidateLabel = "duplicate-candidate";
|
|
26
|
+
|
|
27
|
+
function parseDuplicateCheckMarker(body) {
|
|
28
|
+
if (!body) return null;
|
|
29
|
+
const match = body.match(/<!-- openhands-duplicate-check canonical=(\d+) auto-close=(true|false) -->/);
|
|
30
|
+
if (!match) return null;
|
|
31
|
+
return {
|
|
32
|
+
canonicalIssueNumber: Number(match[1]),
|
|
33
|
+
autoClose: match[2] === "true",
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function ensureCanonicalIssueIsOpenIssue() {
|
|
38
|
+
let canonicalIssue;
|
|
39
|
+
try {
|
|
40
|
+
({ data: canonicalIssue } = await github.rest.issues.get({
|
|
41
|
+
owner: context.repo.owner,
|
|
42
|
+
repo: context.repo.repo,
|
|
43
|
+
issue_number: canonicalIssueNumber,
|
|
44
|
+
}));
|
|
45
|
+
} catch (error) {
|
|
46
|
+
if (error.status === 404) {
|
|
47
|
+
core.setFailed(`Canonical issue #${canonicalIssueNumber} does not exist.`);
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
if (canonicalIssue.pull_request) {
|
|
53
|
+
core.setFailed(`Canonical issue #${canonicalIssueNumber} is a pull request, not an issue.`);
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
if (canonicalIssue.state !== "open" || canonicalIssue.locked) {
|
|
57
|
+
core.setFailed(`Canonical issue #${canonicalIssueNumber} must be an open, unlocked issue.`);
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function ensureCandidateLabelOnIssue() {
|
|
64
|
+
try {
|
|
65
|
+
await github.rest.issues.getLabel({
|
|
66
|
+
owner: context.repo.owner,
|
|
67
|
+
repo: context.repo.repo,
|
|
68
|
+
name: candidateLabel,
|
|
69
|
+
});
|
|
70
|
+
} catch (error) {
|
|
71
|
+
if (error.status !== 404) throw error;
|
|
72
|
+
await github.rest.issues.createLabel({
|
|
73
|
+
owner: context.repo.owner,
|
|
74
|
+
repo: context.repo.repo,
|
|
75
|
+
name: candidateLabel,
|
|
76
|
+
color: "f97316",
|
|
77
|
+
description: "Potential duplicate awaiting auto-close or maintainer review",
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const { data: issue } = await github.rest.issues.get({
|
|
82
|
+
owner: context.repo.owner,
|
|
83
|
+
repo: context.repo.repo,
|
|
84
|
+
issue_number: issueNumber,
|
|
85
|
+
});
|
|
86
|
+
const labelNames = (issue.labels || []).map((label) =>
|
|
87
|
+
typeof label === "string" ? label : label.name,
|
|
88
|
+
);
|
|
89
|
+
if (!labelNames.includes(candidateLabel)) {
|
|
90
|
+
await github.rest.issues.addLabels({
|
|
91
|
+
owner: context.repo.owner,
|
|
92
|
+
repo: context.repo.repo,
|
|
93
|
+
issue_number: issueNumber,
|
|
94
|
+
labels: [candidateLabel],
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function removeCandidateLabelFromIssue() {
|
|
100
|
+
try {
|
|
101
|
+
await github.rest.issues.removeLabel({
|
|
102
|
+
owner: context.repo.owner,
|
|
103
|
+
repo: context.repo.repo,
|
|
104
|
+
issue_number: issueNumber,
|
|
105
|
+
name: candidateLabel,
|
|
106
|
+
});
|
|
107
|
+
} catch (error) {
|
|
108
|
+
if (error.status !== 404) throw error;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (!Number.isInteger(canonicalIssueNumber) || canonicalIssueNumber <= 0) {
|
|
113
|
+
core.setFailed(`No canonical issue number was returned for issue #${issueNumber}.`);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (canonicalIssueNumber === issueNumber) {
|
|
117
|
+
core.setFailed(`Duplicate check cannot mark issue #${issueNumber} as a duplicate of itself.`);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!(await ensureCanonicalIssueIsOpenIssue())) return;
|
|
122
|
+
|
|
123
|
+
const marker = `<!-- openhands-duplicate-check canonical=${canonicalIssueNumber} auto-close=${autoClose ? "true" : "false"} -->`;
|
|
124
|
+
const header = candidates.length === 1
|
|
125
|
+
? "Found 1 possible duplicate issue:"
|
|
126
|
+
: `Found ${candidates.length} possible duplicate issues:`;
|
|
127
|
+
const candidateLines = candidates.map((candidate, index) =>
|
|
128
|
+
`${index + 1}. [#${candidate.number}](${candidate.url}) — ${candidate.title}`,
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
const sections = [];
|
|
132
|
+
if (summary) sections.push(summary, "");
|
|
133
|
+
sections.push(header, "", ...candidateLines);
|
|
134
|
+
|
|
135
|
+
if (classification === "overlapping-scope") {
|
|
136
|
+
sections.push(
|
|
137
|
+
"",
|
|
138
|
+
"These may not be exact duplicates, but the scope appears to overlap enough that keeping discussion in one place may be more useful.",
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (autoClose) {
|
|
143
|
+
sections.push(
|
|
144
|
+
"",
|
|
145
|
+
`This issue will be automatically closed as a duplicate in ${closeAfterDays} days.`,
|
|
146
|
+
"",
|
|
147
|
+
"- If your issue is a duplicate, please close it and 👍 the existing issue instead",
|
|
148
|
+
"- To prevent auto-closure, add a comment or 👎 this comment",
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
sections.push(
|
|
153
|
+
"",
|
|
154
|
+
marker,
|
|
155
|
+
"_This comment was created by an AI assistant (OpenHands) on behalf of the repository maintainer._",
|
|
156
|
+
);
|
|
157
|
+
const body = sections.join("\n").trim();
|
|
158
|
+
|
|
159
|
+
const maxCommentPages = 50;
|
|
160
|
+
let allComments = [];
|
|
161
|
+
let page = 1;
|
|
162
|
+
while (page <= maxCommentPages) {
|
|
163
|
+
const { data: comments } = await github.rest.issues.listComments({
|
|
164
|
+
owner: context.repo.owner,
|
|
165
|
+
repo: context.repo.repo,
|
|
166
|
+
issue_number: issueNumber,
|
|
167
|
+
per_page: 100,
|
|
168
|
+
page,
|
|
169
|
+
});
|
|
170
|
+
if (!comments || comments.length === 0) break;
|
|
171
|
+
allComments = allComments.concat(comments);
|
|
172
|
+
if (comments.length < 100) break;
|
|
173
|
+
page += 1;
|
|
174
|
+
}
|
|
175
|
+
if (page > maxCommentPages) {
|
|
176
|
+
core.setFailed(`Stopped loading comments for issue #${issueNumber} after ${maxCommentPages} pages.`);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const existing = allComments.find((comment) =>
|
|
181
|
+
comment.body && comment.body.includes("<!-- openhands-duplicate-check "),
|
|
182
|
+
);
|
|
183
|
+
if (existing) {
|
|
184
|
+
const existingMarker = parseDuplicateCheckMarker(existing.body);
|
|
185
|
+
if (existingMarker) {
|
|
186
|
+
if (
|
|
187
|
+
existingMarker.canonicalIssueNumber !== canonicalIssueNumber ||
|
|
188
|
+
existingMarker.autoClose !== autoClose
|
|
189
|
+
) {
|
|
190
|
+
await github.rest.issues.updateComment({
|
|
191
|
+
owner: context.repo.owner,
|
|
192
|
+
repo: context.repo.repo,
|
|
193
|
+
comment_id: existing.id,
|
|
194
|
+
body,
|
|
195
|
+
});
|
|
196
|
+
if (autoClose) await ensureCandidateLabelOnIssue();
|
|
197
|
+
else await removeCandidateLabelFromIssue();
|
|
198
|
+
core.info(`Updated existing duplicate check comment ${existing.id} on issue #${issueNumber}.`);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (autoClose) await ensureCandidateLabelOnIssue();
|
|
202
|
+
else await removeCandidateLabelFromIssue();
|
|
203
|
+
} else {
|
|
204
|
+
core.warning(
|
|
205
|
+
`Duplicate check comment already exists on issue #${issueNumber} but its marker could not be parsed; leaving label state unchanged.`,
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
core.info(`Duplicate check comment already exists on issue #${issueNumber}; skipping.`);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
await github.rest.issues.createComment({
|
|
213
|
+
owner: context.repo.owner,
|
|
214
|
+
repo: context.repo.repo,
|
|
215
|
+
issue_number: issueNumber,
|
|
216
|
+
body,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
if (autoClose) await ensureCandidateLabelOnIssue();
|
|
220
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module.exports = async ({ github, context, core }) => {
|
|
2
|
+
const issueNumber = context.issue.number;
|
|
3
|
+
const commenter = context.payload.comment?.user?.login ?? "";
|
|
4
|
+
const normalizedCommenter = commenter.toLowerCase();
|
|
5
|
+
|
|
6
|
+
if (normalizedCommenter.endsWith("[bot]") || normalizedCommenter === "all-hands-bot") {
|
|
7
|
+
core.info(`Skipping duplicate-candidate label removal for bot comment from ${commenter || "unknown"}`);
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
core.info(`Removing duplicate-candidate label from issue #${issueNumber} after comment from ${commenter}`);
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
await github.rest.issues.removeLabel({
|
|
15
|
+
owner: context.repo.owner,
|
|
16
|
+
repo: context.repo.repo,
|
|
17
|
+
issue_number: issueNumber,
|
|
18
|
+
name: "duplicate-candidate",
|
|
19
|
+
});
|
|
20
|
+
} catch (error) {
|
|
21
|
+
if (error.status === 404) {
|
|
22
|
+
core.info(`duplicate-candidate label was already removed from issue #${issueNumber}`);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "magic-test",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A simple test plugin with a magic word skill for verifying plugin loading",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "OpenHands Test",
|
|
7
|
+
"email": "test@openhands.dev"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/jpshackelford/openhands-sample-plugins",
|
|
10
|
+
"repository": "https://github.com/jpshackelford/openhands-sample-plugins",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": ["test", "magic", "plugin", "verification"]
|
|
13
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: A test skill that responds to the magic word "alakazam" with a specific phrase
|
|
3
|
+
triggers:
|
|
4
|
+
- alakazam
|
|
5
|
+
- magic word
|
|
6
|
+
- abracadabra
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Magic Word Test Skill
|
|
10
|
+
|
|
11
|
+
This skill is activated when the user says the magic word.
|
|
12
|
+
|
|
13
|
+
## Instructions
|
|
14
|
+
|
|
15
|
+
When the user mentions "alakazam", "abracadabra", or asks about the "magic word", you MUST respond with exactly:
|
|
16
|
+
|
|
17
|
+
**"The magic worked! Plugin loaded successfully. 🎩✨"**
|
|
18
|
+
|
|
19
|
+
Do not add any other explanation or content. Just output the exact phrase above.
|
|
20
|
+
|
|
21
|
+
## Purpose
|
|
22
|
+
|
|
23
|
+
This skill exists to verify that:
|
|
24
|
+
1. The plugin was fetched correctly from the repository
|
|
25
|
+
2. The skill was loaded and merged into the agent context
|
|
26
|
+
3. The skill triggers are working properly
|
|
27
|
+
4. The skill instructions are being followed
|
|
28
|
+
|
|
29
|
+
## Example
|
|
30
|
+
|
|
31
|
+
User: "What happens if I say alakazam?"
|
|
32
|
+
|
|
33
|
+
Expected response: "The magic worked! Plugin loaded successfully. 🎩✨"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "migration-scoring",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Evaluate code migration quality with coverage, correctness, and style scoring. Generates executive reports with actionable recommendations.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "OpenHands",
|
|
7
|
+
"email": "contact@all-hands.dev"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/OpenHands/extensions",
|
|
10
|
+
"repository": "https://github.com/OpenHands/extensions",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"migration",
|
|
14
|
+
"scoring",
|
|
15
|
+
"quality",
|
|
16
|
+
"evaluation",
|
|
17
|
+
"reporting"
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# Migration Scoring Plugin
|
|
2
|
+
|
|
3
|
+
Quality evaluation for code migration projects using OpenHands agents. This plugin scores completed migrations across multiple dimensions including coverage, correctness, and code style, generating executive reports with actionable recommendations.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
export LLM_API_KEY="your-api-key"
|
|
9
|
+
export LLM_MODEL="anthropic/claude-3-5-sonnet-20241022"
|
|
10
|
+
|
|
11
|
+
uv run python -m lc_sdk_examples.migration_scoring \
|
|
12
|
+
--src-path /path/to/migration/project \
|
|
13
|
+
--rubric-path /path/to/style_rubric.txt
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
- **Multi-Dimensional Scoring** — Evaluates coverage, correctness, and style separately
|
|
19
|
+
- **Source-to-Target Mapping** — Documents relationships between source and migrated files
|
|
20
|
+
- **Executive Reporting** — Generates summary reports with risk categorization
|
|
21
|
+
- **Custom Style Rubrics** — Supports project-specific style guidelines
|
|
22
|
+
- **Actionable Recommendations** — Prioritized list of improvements
|
|
23
|
+
|
|
24
|
+
## Prerequisites
|
|
25
|
+
|
|
26
|
+
- Completed migration with both source and target code present
|
|
27
|
+
- Python 3.13 with `uv`
|
|
28
|
+
- LLM API key (Anthropic or OpenAI)
|
|
29
|
+
- Optional: Custom style rubric file
|
|
30
|
+
|
|
31
|
+
## Plugin Contents
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
plugins/migration-scoring/
|
|
35
|
+
├── README.md # This file
|
|
36
|
+
└── skills/ # Workflow phase skills
|
|
37
|
+
├── migration-scoring-overview/ # Plugin overview
|
|
38
|
+
│ └── SKILL.md
|
|
39
|
+
├── migration-mapping/ # Phase 1: Source-to-target mapping
|
|
40
|
+
│ └── SKILL.md
|
|
41
|
+
├── score-quality/ # Phase 2: Coverage and correctness
|
|
42
|
+
│ ├── SKILL.md
|
|
43
|
+
│ └── references/
|
|
44
|
+
│ └── scoring-criteria.md
|
|
45
|
+
├── score-style/ # Phase 3: Code style evaluation
|
|
46
|
+
│ └── SKILL.md
|
|
47
|
+
└── migration-report/ # Phase 4: Executive report
|
|
48
|
+
└── SKILL.md
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Workflow Phases
|
|
52
|
+
|
|
53
|
+
### Phase 1: Migration Mapping
|
|
54
|
+
|
|
55
|
+
Creates a source→target file mapping:
|
|
56
|
+
|
|
57
|
+
- Identifies which target files implement each source file
|
|
58
|
+
- Supports many-to-many relationships
|
|
59
|
+
- Flags unmigrated source files
|
|
60
|
+
|
|
61
|
+
**Output:** `migration_mapping.json`
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"CALC001.cbl": ["InvoiceCalculator.java", "TaxCalculator.java"],
|
|
66
|
+
"CUST002.cbl": ["CustomerService.java"]
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Phase 2: Quality Scoring
|
|
71
|
+
|
|
72
|
+
Scores each source file on:
|
|
73
|
+
|
|
74
|
+
- **Coverage (1-5)**: How much functionality was migrated
|
|
75
|
+
- **Correctness (1-5)**: How accurately behavior was preserved
|
|
76
|
+
|
|
77
|
+
**Output:** `migration_score.json`
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"CALC001.cbl": {
|
|
82
|
+
"coverage": 4,
|
|
83
|
+
"correctness": 5,
|
|
84
|
+
"justification": "All calculation logic migrated..."
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Phase 3: Style Scoring
|
|
90
|
+
|
|
91
|
+
Evaluates target code against style guidelines:
|
|
92
|
+
|
|
93
|
+
- Naming conventions
|
|
94
|
+
- Code organization
|
|
95
|
+
- Error handling
|
|
96
|
+
- Documentation
|
|
97
|
+
- Idiomaticity
|
|
98
|
+
|
|
99
|
+
**Output:** `style_score.json`
|
|
100
|
+
|
|
101
|
+
### Phase 4: Executive Report
|
|
102
|
+
|
|
103
|
+
Generates a detailed report:
|
|
104
|
+
|
|
105
|
+
- Overall health assessment
|
|
106
|
+
- Score statistics and distribution
|
|
107
|
+
- Risk categorization (Green/Yellow/Red)
|
|
108
|
+
- Prioritized recommendations
|
|
109
|
+
|
|
110
|
+
**Output:** `final_report.md`
|
|
111
|
+
|
|
112
|
+
## Output Structure
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
your-project/
|
|
116
|
+
├── .lc-sdk/
|
|
117
|
+
│ ├── migration_mapping.json
|
|
118
|
+
│ ├── migration_score.json
|
|
119
|
+
│ ├── style_score.json
|
|
120
|
+
│ └── final_report.md
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Usage
|
|
124
|
+
|
|
125
|
+
### Running the Evaluation
|
|
126
|
+
|
|
127
|
+
1. **Ensure migration is complete**: Both source and target code should be present
|
|
128
|
+
2. **Set environment variables**:
|
|
129
|
+
```bash
|
|
130
|
+
export LLM_API_KEY="your-api-key"
|
|
131
|
+
export LLM_MODEL="anthropic/claude-3-5-sonnet-20241022"
|
|
132
|
+
```
|
|
133
|
+
3. **Run the scoring**:
|
|
134
|
+
```bash
|
|
135
|
+
uv run python -m lc_sdk_examples.migration_scoring \
|
|
136
|
+
--src-path /path/to/migration/project \
|
|
137
|
+
--rubric-path /path/to/style_rubric.txt
|
|
138
|
+
```
|
|
139
|
+
4. **Review the report**: Check `final_report.md` for results and recommendations
|
|
140
|
+
|
|
141
|
+
### Using a Custom Style Rubric
|
|
142
|
+
|
|
143
|
+
Create a text file with your style guidelines:
|
|
144
|
+
|
|
145
|
+
```text
|
|
146
|
+
# Style Rubric for Java Migration
|
|
147
|
+
|
|
148
|
+
## Naming Conventions
|
|
149
|
+
- Use camelCase for methods and variables
|
|
150
|
+
- Use PascalCase for classes
|
|
151
|
+
- Avoid Hungarian notation
|
|
152
|
+
|
|
153
|
+
## Code Organization
|
|
154
|
+
- One public class per file
|
|
155
|
+
- Group related methods together
|
|
156
|
+
- Maximum 500 lines per class
|
|
157
|
+
|
|
158
|
+
## Error Handling
|
|
159
|
+
- Use specific exception types
|
|
160
|
+
- Include meaningful error messages
|
|
161
|
+
- Log exceptions appropriately
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Then pass it using `--rubric-path`:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
uv run python -m lc_sdk_examples.migration_scoring \
|
|
168
|
+
--src-path /path/to/project \
|
|
169
|
+
--rubric-path ./my_style_rubric.txt
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Scoring Criteria
|
|
173
|
+
|
|
174
|
+
### Coverage Score (1-5)
|
|
175
|
+
|
|
176
|
+
| Score | Description |
|
|
177
|
+
|-------|-------------|
|
|
178
|
+
| 5 | 100% of source functionality migrated |
|
|
179
|
+
| 4 | 90%+ migrated, minor features missing |
|
|
180
|
+
| 3 | 70-90% migrated, some features missing |
|
|
181
|
+
| 2 | 50-70% migrated, significant gaps |
|
|
182
|
+
| 1 | Less than 50% migrated |
|
|
183
|
+
|
|
184
|
+
### Correctness Score (1-5)
|
|
185
|
+
|
|
186
|
+
| Score | Description |
|
|
187
|
+
|-------|-------------|
|
|
188
|
+
| 5 | Behavior exactly matches source |
|
|
189
|
+
| 4 | Minor edge case differences |
|
|
190
|
+
| 3 | Some behavioral differences |
|
|
191
|
+
| 2 | Significant behavioral changes |
|
|
192
|
+
| 1 | Major functionality broken |
|
|
193
|
+
|
|
194
|
+
### Risk Categories
|
|
195
|
+
|
|
196
|
+
- **Green**: All scores ≥ 4 — Migration is production-ready
|
|
197
|
+
- **Yellow**: Any score 3-4 — Needs review before production
|
|
198
|
+
- **Red**: Any score < 3 — Significant work required
|
|
199
|
+
|
|
200
|
+
## Troubleshooting
|
|
201
|
+
|
|
202
|
+
### Mapping Not Found
|
|
203
|
+
|
|
204
|
+
1. Verify directory structure matches expected layout
|
|
205
|
+
2. Check file extensions are recognized
|
|
206
|
+
3. Ensure source and target directories are accessible
|
|
207
|
+
|
|
208
|
+
### Low Coverage Scores
|
|
209
|
+
|
|
210
|
+
1. Review unmigrated files in the mapping
|
|
211
|
+
2. Check for split functionality across multiple target files
|
|
212
|
+
3. Verify all helper/utility functions are included
|
|
213
|
+
|
|
214
|
+
### Style Score Issues
|
|
215
|
+
|
|
216
|
+
1. Check that rubric file is valid
|
|
217
|
+
2. Verify target code files are readable
|
|
218
|
+
3. Review specific style violations in `style_score.json`
|
|
219
|
+
|
|
220
|
+
### Report Generation Fails
|
|
221
|
+
|
|
222
|
+
1. Ensure all previous phases completed successfully
|
|
223
|
+
2. Check that score JSON files are valid
|
|
224
|
+
3. Verify sufficient disk space for output
|
|
225
|
+
|
|
226
|
+
## Integration with COBOL Modernization
|
|
227
|
+
|
|
228
|
+
This plugin works seamlessly with the [COBOL Modernization Plugin](../cobol-modernization/README.md):
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# First, run the migration
|
|
232
|
+
uv run python -m lc_sdk_examples.cobol_modernization --src-path /path/to/cobol
|
|
233
|
+
|
|
234
|
+
# Then, score the results
|
|
235
|
+
uv run python -m lc_sdk_examples.migration_scoring --src-path /path/to/cobol
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Contributing
|
|
239
|
+
|
|
240
|
+
See the main [extensions repository](https://github.com/OpenHands/extensions) for contribution guidelines.
|
|
241
|
+
|
|
242
|
+
## License
|
|
243
|
+
|
|
244
|
+
This plugin is part of the OpenHands extensions repository. See [LICENSE](../../LICENSE) for details.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: migration-mapping
|
|
3
|
+
description: Create a mapping from source language files to target language files for code migrations. Use when evaluating or documenting a migration project.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Requires completed migration with source and target code
|
|
6
|
+
triggers:
|
|
7
|
+
- migration mapping
|
|
8
|
+
- source target mapping
|
|
9
|
+
- file mapping
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Create a mapping from source language files (e.g., COBOL) to target language files (e.g., Java) to document which target files implement the functionality of each source file.
|
|
13
|
+
|
|
14
|
+
## Task
|
|
15
|
+
|
|
16
|
+
Examine all source language files and identify the corresponding target language files that implement the same functionality. This mapping is essential for:
|
|
17
|
+
- Migration quality evaluation
|
|
18
|
+
- Traceability documentation
|
|
19
|
+
- Gap analysis
|
|
20
|
+
|
|
21
|
+
## Output Format
|
|
22
|
+
|
|
23
|
+
Save the mapping as a JSON file with this structure:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"source_file_1.cbl": ["target_file_a.java", "target_file_b.java"],
|
|
28
|
+
"source_file_2.cbl": ["target_file_c.java"],
|
|
29
|
+
"source_file_3.cbl": []
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Rules
|
|
34
|
+
|
|
35
|
+
1. **Many-to-many mapping**: A source file may map to multiple target files, and a target file may implement logic from multiple source files
|
|
36
|
+
2. **Complete coverage**: EVERY source file must appear as a key in the mapping
|
|
37
|
+
3. **Complete target coverage**: EVERY target file should appear as a value at least once
|
|
38
|
+
4. **Empty arrays**: If a source file has no corresponding target implementation, use an empty array `[]`
|
|
39
|
+
5. **Incremental**: If a mapping file already exists, update it rather than replacing it
|
|
40
|
+
|
|
41
|
+
## How to Identify Mappings
|
|
42
|
+
|
|
43
|
+
Look for:
|
|
44
|
+
- Matching class/program names
|
|
45
|
+
- Similar function/paragraph names
|
|
46
|
+
- Matching business logic patterns
|
|
47
|
+
- Comments referencing source files
|
|
48
|
+
- Import/include statements
|
|
49
|
+
- Data structure similarities
|
|
50
|
+
|
|
51
|
+
## Example
|
|
52
|
+
|
|
53
|
+
For a COBOL-to-Java migration:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"CALC001.cbl": ["InvoiceCalculator.java", "TaxCalculator.java"],
|
|
58
|
+
"CUST002.cbl": ["CustomerService.java", "CustomerRepository.java"],
|
|
59
|
+
"UTIL003.cbl": ["StringUtils.java"],
|
|
60
|
+
"SCREEN001.cbl": []
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Note: `SCREEN001.cbl` maps to nothing because UI code was not migrated.
|
|
65
|
+
|
|
66
|
+
## Verification
|
|
67
|
+
|
|
68
|
+
After creating the mapping:
|
|
69
|
+
- [ ] Every source file is a key
|
|
70
|
+
- [ ] No duplicate keys
|
|
71
|
+
- [ ] Target files are relative paths from project root
|
|
72
|
+
- [ ] JSON is valid and well-formatted
|