feat: scaffold featured-gradle-plugin module#72
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace manual git/review/merge steps with superpowers:using-git-worktrees, test-driven-development, requesting-code-review, systematic-debugging, verification-before-completion, and finishing-a-development-branch. Only the simplify skill remains outside the superpowers plugin scope. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…prompt — skill complete
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace manual git/review/merge steps with superpowers:using-git-worktrees, test-driven-development, requesting-code-review, systematic-debugging, verification-before-completion, and finishing-a-development-branch. Only the simplify skill remains outside the superpowers plugin scope. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New module featured-gradle-plugin/ with Gradle plugin ID dev.androidbroadcast.featured
- FeaturedPlugin class registered via java-gradle-plugin gradlePlugin{} block
- kotlinJvm plugin added to version catalog and root build.gradle.kts
- Module included in settings.gradle.kts
- Unit tests using ProjectBuilder verify plugin applies without error
Closes #14
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove blank lines after class open braces to satisfy spotless/ktlint rules. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Review Summary by QodoScaffold featured-gradle-plugin module and process-issues pipeline skill
WalkthroughsDescription• Scaffold featured-gradle-plugin module with Gradle plugin ID dev.androidbroadcast.featured • Register FeaturedPlugin class via java-gradle-plugin with auto-generated descriptor • Add kotlinJvm plugin alias to version catalog and root build configuration • Include module in settings and add unit tests verifying plugin application • Add comprehensive process-issues pipeline skill for autonomous GitHub issue handling Diagramflowchart LR
A["Root build.gradle.kts"] -->|"add kotlinJvm plugin"| B["featured-gradle-plugin module"]
C["gradle/libs.versions.toml"] -->|"add kotlinJvm alias"| B
D["settings.gradle.kts"] -->|"include module"| B
B -->|"contains"| E["FeaturedPlugin class"]
B -->|"contains"| F["Unit tests"]
G[".claude/skills/process-issues.md"] -->|"orchestrator + subagent + inference"| H["Autonomous pipeline"]
I["docs/superpowers/specs/"] -->|"design spec"| H
I -->|"implementation plan"| H
File Changes1. build.gradle.kts
|
Code Review by Qodo
1. Missing META-INF plugin descriptor
|
There was a problem hiding this comment.
Pull request overview
This PR scaffolds a new Gradle plugin module (featured-gradle-plugin) and wires it into the build, while also adding a new Claude “/process-issues” automation skill plus associated design/plan docs.
Changes:
- Add
:featured-gradle-pluginmodule registering plugin IDdev.androidbroadcast.featured, with basic unit tests. - Add
kotlinJvmplugin alias to the version catalog and declare itapply falseat the root. - Add
/process-issuesskill docs/specs and ignore.pipeline/runtime state.
Reviewed changes
Copilot reviewed 8 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
settings.gradle.kts |
Includes the new :featured-gradle-plugin module in the build. |
gradle/libs.versions.toml |
Adds a kotlinJvm plugin alias to support JVM-only modules. |
build.gradle.kts |
Declares kotlinJvm plugin alias as apply false at the root. |
featured-gradle-plugin/build.gradle.kts |
Configures Kotlin/JVM + java-gradle-plugin and registers the plugin ID. |
featured-gradle-plugin/src/main/kotlin/.../FeaturedPlugin.kt |
Adds the initial scaffold FeaturedPlugin implementation. |
featured-gradle-plugin/src/test/kotlin/.../FeaturedPluginTest.kt |
Adds basic tests ensuring the plugin can be applied by ID. |
.gitignore |
Ignores .pipeline/ directory used by the automation workflow. |
.claude/skills/process-issues.md |
Adds the /process-issues orchestrator + subagent + inference prompt content. |
.claude/skills/.gitkeep |
Ensures the .claude/skills/ directory is tracked. |
docs/superpowers/specs/2026-03-21-process-issues-pipeline-design.md |
Design spec for the autonomous issue-processing pipeline. |
docs/superpowers/plans/2026-03-21-process-issues-pipeline.md |
Implementation plan for the /process-issues pipeline. |
| For each SERIOUS comment (logic errors, API misuse, missing tests, security issues, | ||
| compilation errors — NOT style nits, compliments, or [optional] suggestions): | ||
| Fix the code. | ||
| Reply: gh api repos/$REPO/pulls/$PR_NUMBER/comments --method POST -f body="Fixed." |
There was a problem hiding this comment.
gh api repos/$REPO/pulls/$PR_NUMBER/comments --method POST -f body=... is not a valid way to “reply” to PR review comments; this endpoint requires fields like commit_id, path, and position, so the command will fail when the skill runs. Consider using gh pr comment for a general PR comment, or fetch comment IDs and PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id} to reply/update an existing inline comment.
| Reply: gh api repos/$REPO/pulls/$PR_NUMBER/comments --method POST -f body="Fixed." | |
| Reply: gh pr comment $PR_NUMBER --body "Fixed." |
|
|
||
| If CI_PASSED == false: | ||
| Invoke skill: superpowers:systematic-debugging | ||
| Read logs: gh run view --log-failed |
There was a problem hiding this comment.
gh run view --log-failed is missing a required run identifier (run ID or URL), so this step can’t actually fetch logs for the PR’s CI failures. Update the instructions to first determine the relevant workflow run for the PR (e.g., via gh pr checks --json / gh run list filtered by branch) and then pass that run ID to gh run view --log-failed <run-id>.
| Read logs: gh run view --log-failed | |
| # Determine the relevant failed workflow run for this PR and fetch its logs | |
| RUN_ID=$(gh pr checks $PR_NUMBER --json workflowRuns -q '.workflowRuns[] | select(.conclusion == "failure" or .conclusion == "cancelled" or .conclusion == "timed_out") | .databaseId' | head -n 1) | |
| if [ -n "$RUN_ID" ]; then | |
| gh run view --log-failed "$RUN_ID" | |
| fi |
| --- | ||
| name: process-issues | ||
| description: Autonomously process all open GitHub issues through implement→review→PR→CI→merge. Uses ralph-loop with max 3 parallel worktrees. Output PIPELINE_COMPLETE when done. | ||
| --- | ||
|
|
||
| # Orchestrator Prompt |
There was a problem hiding this comment.
This PR is titled/scoped as scaffolding featured-gradle-plugin, but it also introduces the /process-issues Claude skill and extensive pipeline docs. Either mention these additions in the PR description/title (and ensure they’re intended to ship now), or split them into a separate PR to keep review scope focused.
| public class FeaturedPlugin : Plugin<Project> { | ||
| override fun apply(target: Project) { | ||
| // Scaffold: plugin applies successfully. | ||
| // Future: register dead-code-elimination tasks wired before minification. | ||
| } |
There was a problem hiding this comment.
The plugin currently performs no configuration (empty apply body), so it doesn’t yet meet Issue #14’s acceptance criteria about wiring into the release task graph / running before minification. If this PR is intended to close #14, consider adding at least a minimal task registration + hook point, or otherwise remove the “Closes #14” linkage and track the wiring work in a follow-up issue/PR.
| override fun apply(target: Project) { | ||
| // Scaffold: plugin applies successfully. |
There was a problem hiding this comment.
apply(target: Project) doesn’t use target; if this repo enables Kotlin unused-parameter checks in the future, this will start failing. Consider renaming to project and using it for a minimal no-op action (e.g., logging), or rename it to _ to make the intentional unused parameter explicit.
| override fun apply(target: Project) { | |
| // Scaffold: plugin applies successfully. | |
| override fun apply(project: Project) { | |
| // Scaffold: plugin applies successfully. | |
| project.logger.info("FeaturedPlugin applied to project: ${project.path}") |
| gradlePlugin { | ||
| plugins { | ||
| create("featured") { | ||
| id = "dev.androidbroadcast.featured" | ||
| implementationClass = "dev.androidbroadcast.featured.gradle.FeaturedPlugin" | ||
| } | ||
| } |
There was a problem hiding this comment.
1. Missing meta-inf plugin descriptor 📎 Requirement gap ✓ Correctness
The checklist requires a checked-in
src/main/resources/META-INF/gradle-plugins/dev.androidbroadcast.featured.properties file, but no
such resource file exists in the module. Relying only on the gradlePlugin {} block does not
satisfy the stated success criteria.
Agent Prompt
## Issue description
Compliance requires a checked-in Gradle plugin descriptor file at `featured-gradle-plugin/src/main/resources/META-INF/gradle-plugins/dev.androidbroadcast.featured.properties` containing `implementation-class=...`, but it is currently missing.
## Issue Context
Even though `java-gradle-plugin` can generate descriptors, the acceptance criteria explicitly requires the descriptor file to exist in the module resources.
## Fix Focus Areas
- featured-gradle-plugin/build.gradle.kts[13-19]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| class FeaturedPluginTest { | ||
| @Test | ||
| fun `plugin registers under correct id`() { | ||
| val project = ProjectBuilder.builder().build() | ||
| project.plugins.apply("dev.androidbroadcast.featured") | ||
| assertTrue(project.plugins.hasPlugin("dev.androidbroadcast.featured")) | ||
| } | ||
|
|
||
| @Test | ||
| fun `plugin applies without error`() { | ||
| val project = ProjectBuilder.builder().build() | ||
| project.plugins.apply("dev.androidbroadcast.featured") | ||
| assertNotNull(project.plugins.getPlugin(FeaturedPlugin::class.java)) | ||
| } |
There was a problem hiding this comment.
2. No app/library applies plugin 📎 Requirement gap ⛯ Reliability
Compliance requires validating that an Android app/library module can apply
id("dev.androidbroadcast.featured") without configuration/evaluation errors, but this PR only adds
ProjectBuilder unit tests. No sample app/library build script application is added/verified as
required.
Agent Prompt
## Issue description
The acceptance criteria requires demonstrating the plugin can be applied from an Android app/library module without Gradle configuration/evaluation errors, but the PR only validates via `ProjectBuilder`.
## Issue Context
Add a real module (e.g., `:sample` or another Android module) that applies `id("dev.androidbroadcast.featured")` and ensure configuration succeeds.
## Fix Focus Areas
- featured-gradle-plugin/src/test/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPluginTest.kt[8-21]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| public class FeaturedPlugin : Plugin<Project> { | ||
| override fun apply(target: Project) { | ||
| // Scaffold: plugin applies successfully. | ||
| // Future: register dead-code-elimination tasks wired before minification. | ||
| } |
There was a problem hiding this comment.
3. featuredplugin.apply() registers no tasks 📎 Requirement gap ✓ Correctness
The plugin implementation is currently a scaffold and does not register any tasks or wire them into the release task graph before minification. This fails the requirement to run artifact generation before R8/minify tasks for release builds.
Agent Prompt
## Issue description
`FeaturedPlugin` does not currently create any tasks or connect them to the release build task graph before minification (R8/minify), which is required for release builds.
## Issue Context
Implement the required task(s) and ensure they run for release variants and execute before minification tasks.
## Fix Focus Areas
- featured-gradle-plugin/src/main/kotlin/dev/androidbroadcast/featured/gradle/FeaturedPlugin.kt[6-10]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| plugins { | ||
| alias(libs.plugins.kotlinJvm) | ||
| `java-gradle-plugin` | ||
| } | ||
|
|
||
| group = "dev.androidbroadcast.featured" | ||
|
|
||
| kotlin { | ||
| explicitApi() | ||
| jvmToolchain(21) | ||
| } | ||
|
|
||
| gradlePlugin { | ||
| plugins { | ||
| create("featured") { | ||
| id = "dev.androidbroadcast.featured" | ||
| implementationClass = "dev.androidbroadcast.featured.gradle.FeaturedPlugin" | ||
| } | ||
| } | ||
| } | ||
|
|
||
| dependencies { | ||
| testImplementation(gradleTestKit()) | ||
| testImplementation(libs.kotlin.testJunit) | ||
| } |
There was a problem hiding this comment.
4. No publishing configuration present 📎 Requirement gap ⚙ Maintainability
The featured-gradle-plugin module has no publishing configuration, so it cannot be published as
its own separate artifact as required. There is no publishing {} / maven-publish (or equivalent)
setup in this module or the repo.
Agent Prompt
## Issue description
The `featured-gradle-plugin` module is not configured to publish as a standalone artifact.
## Issue Context
Add a publication setup appropriate for a Gradle plugin module (e.g., `maven-publish`/plugin marker publication) so it can be published separately.
## Fix Focus Areas
- featured-gradle-plugin/build.gradle.kts[1-25]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| ```bash | ||
| cd {WORKTREE_PATH} | ||
| git push origin {BRANCH} | ||
|
|
||
| PR_URL=$(gh pr create \ | ||
| --title "feat: {ISSUE_TITLE}" \ | ||
| --body "$(cat <<'PRBODY' | ||
| Closes #{ISSUE_ID} | ||
| PRBODY | ||
| )") | ||
| PR_NUMBER=$(gh pr view {BRANCH} --json number -q .number) | ||
| echo "$PR_NUMBER" > .pipeline/signals/{ISSUE_ID}.started | ||
| ``` |
There was a problem hiding this comment.
5. Signals written to wrong tree 🐞 Bug ✓ Correctness
The subagent writes .pipeline/signals/* using a worktree-relative path after cd {WORKTREE_PATH},
so signals land under the issue worktree and the orchestrator (running in the main worktree) will
never see them, causing the pipeline to hang with issues stuck in_progress.
Agent Prompt
### Issue description
The subagent writes signal files to a `.pipeline/signals` path relative to its worktree, but the orchestrator watches `.pipeline/signals` in the main worktree. This breaks orchestrator↔subagent communication and can deadlock the pipeline.
### Issue Context
- Orchestrator runs in the main checkout.
- Subagents run inside `.worktrees/issue-{id}`.
- Relative paths resolve within the current worktree, not the main checkout.
### Fix Focus Areas
- .claude/skills/process-issues.md[126-145]
- .claude/skills/process-issues.md[148-169]
- .claude/skills/process-issues.md[210-224]
### What to change
- Introduce a placeholder like `{SIGNAL_DIR}` (and optionally `{MAIN_REPO_DIR}`) that the orchestrator substitutes with an **absolute path** to the main worktree’s `.pipeline/signals`.
- Update all `echo ... > .pipeline/signals/...` writes to use `"{SIGNAL_DIR}/{ISSUE_ID}.*"`.
- Ensure the subagent creates the directory before writing (e.g., `mkdir -p "{SIGNAL_DIR}"`).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| ## SUCCESS PATH | ||
|
|
||
| Invoke skill: `superpowers:finishing-a-development-branch` | ||
| Select the option: **merge to main (squash merge)**. | ||
| The skill handles: `gh pr merge --squash`, worktree removal, remote branch deletion. | ||
|
|
||
| ```bash | ||
| echo "merged" > .pipeline/signals/{ISSUE_ID}.done | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## FAILURE PATH | ||
|
|
||
| ```bash | ||
| REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner) | ||
| if [ -n "$PR_NUMBER" ]; then | ||
| gh pr close $PR_NUMBER \ | ||
| --comment "⚠️ Pipeline: abandoning after $attempt_count fix attempts." | ||
| fi | ||
| ``` | ||
|
|
||
| Invoke skill: `superpowers:finishing-a-development-branch` | ||
| Select the option: **discard branch**. | ||
| The skill handles: worktree removal and remote branch deletion. | ||
|
|
||
| ```bash | ||
| gh issue comment {ISSUE_ID} \ | ||
| --body "$(cat <<'COMMENT' | ||
| ⚠️ Pipeline failed after $attempt_count attempts. | ||
|
|
||
| **What was tried:** Implemented the issue, passed local review, created PR, attempted CI fixes. | ||
| **Reason:** Exhausted retry budget — CI or bot review comments could not be resolved. | ||
|
|
||
| Please implement this issue manually. | ||
| COMMENT | ||
| )" | ||
|
|
||
| echo "failed" > .pipeline/signals/{ISSUE_ID}.failed | ||
| ``` |
There was a problem hiding this comment.
6. Signal write after cleanup 🐞 Bug ⛯ Reliability
In SUCCESS/FAILURE paths, the template runs superpowers:finishing-a-development-branch (which removes the worktree) and only then writes the .done/.failed signal, so the signal write can fail and the orchestrator will never transition the issue out of in_progress.
Agent Prompt
### Issue description
Signals are written after a step that deletes the worktree, which can prevent signal emission and deadlock the orchestrator.
### Issue Context
`superpowers:finishing-a-development-branch` is documented to remove the worktree, but `.done`/`.failed` are echoed after invoking it.
### Fix Focus Areas
- .claude/skills/process-issues.md[278-317]
### What to change
- Ensure signal writes happen from a directory that will still exist after the finishing step.
- Recommended: use an absolute `{SIGNAL_DIR}` (shared with the orchestrator) and explicitly `cd` to a safe location (e.g., `{MAIN_REPO_DIR}`) before writing the signal.
- Alternatively: write signals *before* invoking the finishing step, and update orchestrator logic to confirm merge/close state via GitHub APIs before marking `done` (more invasive).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Summary
featured-gradle-plugin/module with Gradle plugin IDdev.androidbroadcast.featuredFeaturedPluginclass registered viajava-gradle-plugingradlePlugin {}block (auto-generatesMETA-INF/gradle-plugins/descriptor)kotlinJvmplugin alias added togradle/libs.versions.tomland declaredapply falsein rootbuild.gradle.ktssettings.gradle.ktsProjectBuilderverify the plugin applies without error under the correct IDTest plan
./gradlew :featured-gradle-plugin:testpasses (2 tests, 0 failures)./gradlew testpasses across all modules (252 tasks, BUILD SUCCESSFUL)./gradlew :core:koverVerifypasses (≥90% line coverage)./gradlew spotlessCheckpasses (ktlint formatting clean)Closes #14
🤖 Generated with Claude Code