Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Kompass keeps AI coding agents on course with token-efficient, composable workfl

## Bundled Surface

- Commands cover direct work (`/ask`, `/commit`, `/merge`, `/skill/create`, `/skill/optimize`), orchestration (`/dev`, `/ship`, `/todo`), ticket planning/sync, and PR review/shipping flows.
- Commands cover direct work (`/ask`, `/commit`, `/merge`, `/skill/create`, `/skill/optimize`), orchestration (`/dev`, `/ship`, `/todo`, `/loop/pr/fix`), ticket planning/sync, and PR review/shipping flows.
- Agents are intentionally narrow: `worker` is generic, `planner` is no-edit planning, `navigator` owns multi-step orchestration, and `reviewer` is a no-edit review specialist.
- Structured tools keep workflows grounded in repo and GitHub state: `changes_load`, `command_expansion` (resolve a slash command and return the expanded prompt for immediate delegation), `pr_load`, `pr_sync`, `ticket_load`, `ticket_sync`.
- Reusable command-template components live in `packages/core/components/` and are documented in the components reference.
Expand Down
1 change: 1 addition & 0 deletions kompass.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"commit-and-push": { "enabled": true },
"dev": { "enabled": true },
"learn": { "enabled": true },
"loop/pr/fix": { "enabled": true },
"merge": { "enabled": true },
"pr/create": { "enabled": true },
"pr/fix": { "enabled": true },
Expand Down
5 changes: 5 additions & 0 deletions kompass.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
"learn": {
"$ref": "#/$defs/commandConfig"
},
"loop/pr/fix": {
"$ref": "#/$defs/commandConfig"
},
"merge": {
"$ref": "#/$defs/commandConfig"
},
Expand Down Expand Up @@ -106,6 +109,7 @@
"commit-and-push",
"dev",
"learn",
"loop/pr/fix",
"merge",
"pr/create",
"pr/fix",
Expand Down Expand Up @@ -136,6 +140,7 @@
"commit-and-push",
"dev",
"learn",
"loop/pr/fix",
"merge",
"pr/create",
"pr/fix",
Expand Down
7 changes: 6 additions & 1 deletion packages/core/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ export const commandDefinitions: Record<string, CommandDefinition> = {
templatePath: "commands/learn.md",
subtask: false,
},
"loop/pr/fix": {
description: "Watch PR CI and comments, repeatedly fixing both without approval prompts",
agent: "navigator",
templatePath: "commands/loop/pr/fix.md",
},
merge: {
description: "Merge a branch and auto-resolve conflicts best-effort",
agent: "worker",
Expand All @@ -62,7 +67,7 @@ export const commandDefinitions: Record<string, CommandDefinition> = {
templatePath: "commands/pr/create.md",
},
"pr/fix": {
description: "Fix PR feedback, push updates, and reply",
description: "Fix PR feedback or CI failures, push updates, and reply",
agent: "worker",
templatePath: "commands/pr/fix.md",
subtask: false,
Expand Down
93 changes: 93 additions & 0 deletions packages/core/commands/loop/pr/fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
## Goal

Continuously watch a pull request, fix CI failures and PR feedback, commit, push, reply, and repeat until the PR is clean.

## Additional Context

Use `<additional-context>` to constrain which feedback should be handled, how aggressive the fix pass should be, or which CI checks matter when the PR has optional checks.
- This command is intentionally non-interactive: do not ask for approval before delegated fix work, commits, pushes, or PR replies.
- CI failures are part of the loop: capture them as actionable work, fix them, push, then watch CI again.

## Workflow

### Arguments

<arguments>
$ARGUMENTS
</arguments>

### Interpret Arguments

- If `<arguments>` looks like a PR number or URL, store it as `<pr-ref>`
- If `<arguments>` includes extra fix guidance, CI guidance, or scope constraints, store it as `<additional-context>`
- If empty, leave `<pr-ref>` undefined and let `<%= it.config.tools.pr_load.name %>` resolve the default PR context
- Initialize `<completed-fix-passes>` as `0`

### Load PR Context

<%~ include("@load-pr", { config: it.config, ref: "<pr-ref>", result: "<pr-context>" }) %>

- Store `<pr-url>` as `<pr-context.pr.url>`
- Store `<pr-number>` as `<pr-context.pr.number>`
- STOP if `<pr-url>` or `<pr-number>` is unavailable

### Watch CI And Comments

- Run `gh pr checks <pr-number> --watch` to wait for the latest PR checks to finish
- If the command exits successfully, store `<ci-status>` as `green`
- If there are no checks configured for the PR, store `<ci-status>` as `no checks`
- If the command reports failing, cancelled, timed out, missing, or inconclusive checks, store `<ci-status>` with that state and capture the failing check names, URLs, and failure output as `<ci-failures>`
- Do not STOP only because CI failed; failed checks are actionable feedback for this loop

### Reload PR Feedback

Call `<%= it.config.tools.pr_load.name %>` with `<pr-url>` and store the refreshed result as `<fresh-pr-context>`.

- Review `<fresh-pr-context.threads>`, `<fresh-pr-context.reviews>`, and `<fresh-pr-context.issueComments>`
- Identify open, unresolved, actionable reviewer feedback that has not already been answered by the author or superseded by later commits
- Combine actionable reviewer feedback and `<ci-failures>` into `<actionable-work>`
- Store the number of actionable reviewer items as `<actionable-feedback-count>`
- Store the number of actionable CI failures as `<actionable-ci-count>`
- If `<actionable-feedback-count>` and `<actionable-ci-count>` are both `0`, continue to `### Output`

### Delegate Fix Pass

<delegate agent="<%= it.config.agents.worker.name %>" command="<%= it.config.commands["pr/fix"].name %>">
auto <pr-url>

Fix all actionable PR review feedback and CI failures from the latest loop pass.
CI status: <ci-status>
CI failures: <ci-failures>
Actionable work: <actionable-work>
Additional context: <additional-context>
</delegate>

- Store the delegated result as `<fix-result>`
- If `<fix-result>` is blocked, incomplete, reports failing validation, or reports that push or PR replies failed, STOP and report the fix blocker
- If `<fix-result>` reports that no changes were made for actionable work, STOP and report that manual follow-up is needed to avoid looping on unchanged CI or feedback
- Otherwise, increment `<completed-fix-passes>` by `1` and return to `### Load PR Context`

### Output

If stopped by a delegated fix blocker, display:
```
PR loop blocked for #<pr-number>

- CI status: <ci-status>
- Fix passes completed: <completed-fix-passes>
- Blocker: <fix-result>

No additional steps are required.
```

When complete, display:
```
PR loop complete for #<pr-number>

- CI status: <ci-status>
- CI failures remaining: 0
- Actionable feedback remaining: 0
- Fix passes completed: <completed-fix-passes>

No additional steps are required.
```
13 changes: 7 additions & 6 deletions packages/core/commands/pr/fix.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
## Goal

Address feedback on a pull request by making fixes and responding to review threads.
Address feedback or CI failures on a pull request by making fixes and responding to review threads.

## Additional Context

Use `<additional-context>` when prioritizing which review feedback to address first and when deciding how much scope to take on in this pass.
Use `<additional-context>` when prioritizing which review feedback or CI failure to address first and when deciding how much scope to take on in this pass.
- Default `/pr/fix` behavior is review-first: show the proposed fix, gather feedback, and loop until the user approves before committing, pushing, or replying on the PR.
- Treat `/pr/fix auto` as the explicit opt-in to skip the approval loop and proceed directly from passing validation to commit, push, and PR replies.

Expand Down Expand Up @@ -45,9 +45,10 @@ Call `<%= it.config.tools.changes_load.name %>` with `base: <pr-context.pr.baseR
Separate true course corrections from noise or already-resolved feedback:
1. Review `<pr-context.threads>` for open, unresolved conversations
2. Check `<pr-context.reviews>` for state changes (CHANGES_REQUESTED, etc.)
3. Use `<changes>` to understand the current PR diff before deciding what to adjust
4. Prioritize critical issues (bugs, security, broken contracts)
5. Identify which files need changes
3. Include any CI failures, logs, failing check names, or reproduction details provided in `<additional-context>` as actionable feedback
4. Use `<changes>` to understand the current PR diff before deciding what to adjust
5. Prioritize critical issues (bugs, security, broken contracts, failing required checks)
6. Identify which files need changes

Do not blindly follow every suggestion—some may lead you off course.

Expand Down Expand Up @@ -85,7 +86,7 @@ Run the most relevant available validation for the fixes:
- Keep custom answers enabled so the user can provide concrete feedback
- If `<changes-count>` is `0`, ask exactly one `question` with:
- header `Need Feedback`
- question `I did not make any changes for this PR feedback. What should I revise or investigate next?`
- question `I did not make any changes for this PR feedback or CI failure. What should I revise or investigate next?`
- options:
- `Revise` - provide feedback for another pass
- `Stop Here` - stop without committing, pushing, or replying on the PR
Expand Down
1 change: 1 addition & 0 deletions packages/core/kompass.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"commit-and-push": { "enabled": true },
"dev": { "enabled": true },
"learn": { "enabled": true },
"loop/pr/fix": { "enabled": true },
"merge": { "enabled": true },
"pr/create": { "enabled": true },
"pr/fix": { "enabled": true },
Expand Down
2 changes: 2 additions & 0 deletions packages/core/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const DEFAULT_COMMAND_NAMES = [
"commit-and-push",
"dev",
"learn",
"loop/pr/fix",
"merge",
"pr/create",
"pr/fix",
Expand Down Expand Up @@ -97,6 +98,7 @@ export interface KompassConfig {
"commit-and-push"?: CommandConfig;
dev?: CommandConfig;
learn?: CommandConfig;
"loop/pr/fix"?: CommandConfig;
merge?: CommandConfig;
"pr/create"?: CommandConfig;
"pr/fix"?: CommandConfig;
Expand Down
10 changes: 10 additions & 0 deletions packages/core/test/commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,14 @@ describe("resolveCommands", () => {
assert.match(template, /Do not inspect or modify local code for this PR until `<active-branch>` equals `<pr-branch>`/);
assert.doesNotMatch(template, /`<current-branch>` differs from `<pr-branch>` or `<current-head>` differs from `<pr-context\.pr\.headRefOid>`/);
});

test("orchestrates loop pr fix through ci and delegated auto fixes", async () => {
const commands = await resolveCommands(process.cwd());
const template = commands["loop/pr/fix"]?.template ?? "";

assert.match(template, /gh pr checks <pr-number> --watch/);
assert.match(template, /command="pr\/fix"/);
assert.match(template, /auto <pr-url>/);
assert.doesNotMatch(template, /question/);
});
});
108 changes: 108 additions & 0 deletions packages/opencode/.opencode/commands/loop/pr/fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
description: Watch PR CI and comments, repeatedly fixing both without approval prompts
agent: navigator
---

## Goal

Continuously watch a pull request, fix CI failures and PR feedback, commit, push, reply, and repeat until the PR is clean.

## Additional Context

Use `<additional-context>` to constrain which feedback should be handled, how aggressive the fix pass should be, or which CI checks matter when the PR has optional checks.
- This command is intentionally non-interactive: do not ask for approval before delegated fix work, commits, pushes, or PR replies.
- CI failures are part of the loop: capture them as actionable work, fix them, push, then watch CI again.

## Workflow

### Arguments

<arguments>
$ARGUMENTS
</arguments>

### Interpret Arguments

- If `<arguments>` looks like a PR number or URL, store it as `<pr-ref>`
- If `<arguments>` includes extra fix guidance, CI guidance, or scope constraints, store it as `<additional-context>`
- If empty, leave `<pr-ref>` undefined and let `kompass_pr_load` resolve the default PR context
- Initialize `<completed-fix-passes>` as `0`

### Load PR Context

- Use `kompass_pr_load` as the source of truth for PR selection
- If `<pr-ref>` is defined, call `kompass_pr_load` with `pr: <pr-ref>`
- Otherwise, call `kompass_pr_load` with no arguments
- Do not run separate git or GitHub commands just to discover the PR before calling `kompass_pr_load`
- Store the result as `<pr-context>`
- Store the PR head branch as `<pr-branch>` from `<pr-context>.pr.headRefName` when it is available
- Run `git branch --show-current` and store the trimmed result as `<current-branch>` when it is available
- Run `git rev-parse HEAD` and store the trimmed result as `<current-head>` when it is available
- Treat the loaded PR body, discussion, review history, and any attachments or linked artifacts returned by the loader as part of the source context
- Review attached images, screenshots, videos, PDFs, and other linked files whenever they can affect the requested fix, review outcome, reproduction steps, or acceptance criteria
- If any relevant attachment cannot be accessed, note that gap and continue only when the remaining PR context is still sufficient to proceed reliably

- Store `<pr-url>` as `<pr-context.pr.url>`
- Store `<pr-number>` as `<pr-context.pr.number>`
- STOP if `<pr-url>` or `<pr-number>` is unavailable

### Watch CI And Comments

- Run `gh pr checks <pr-number> --watch` to wait for the latest PR checks to finish
- If the command exits successfully, store `<ci-status>` as `green`
- If there are no checks configured for the PR, store `<ci-status>` as `no checks`
- If the command reports failing, cancelled, timed out, missing, or inconclusive checks, store `<ci-status>` with that state and capture the failing check names, URLs, and failure output as `<ci-failures>`
- Do not STOP only because CI failed; failed checks are actionable feedback for this loop

### Reload PR Feedback

Call `kompass_pr_load` with `<pr-url>` and store the refreshed result as `<fresh-pr-context>`.

- Review `<fresh-pr-context.threads>`, `<fresh-pr-context.reviews>`, and `<fresh-pr-context.issueComments>`
- Identify open, unresolved, actionable reviewer feedback that has not already been answered by the author or superseded by later commits
- Combine actionable reviewer feedback and `<ci-failures>` into `<actionable-work>`
- Store the number of actionable reviewer items as `<actionable-feedback-count>`
- Store the number of actionable CI failures as `<actionable-ci-count>`
- If `<actionable-feedback-count>` and `<actionable-ci-count>` are both `0`, continue to `### Output`

### Delegate Fix Pass

<delegate agent="worker" command="pr/fix">
auto <pr-url>

Fix all actionable PR review feedback and CI failures from the latest loop pass.
CI status: <ci-status>
CI failures: <ci-failures>
Actionable work: <actionable-work>
Additional context: <additional-context>
</delegate>

- Store the delegated result as `<fix-result>`
- If `<fix-result>` is blocked, incomplete, reports failing validation, or reports that push or PR replies failed, STOP and report the fix blocker
- If `<fix-result>` reports that no changes were made for actionable work, STOP and report that manual follow-up is needed to avoid looping on unchanged CI or feedback
- Otherwise, increment `<completed-fix-passes>` by `1` and return to `### Load PR Context`

### Output

If stopped by a delegated fix blocker, display:
```
PR loop blocked for #<pr-number>

- CI status: <ci-status>
- Fix passes completed: <completed-fix-passes>
- Blocker: <fix-result>

No additional steps are required.
```

When complete, display:
```
PR loop complete for #<pr-number>

- CI status: <ci-status>
- CI failures remaining: 0
- Actionable feedback remaining: 0
- Fix passes completed: <completed-fix-passes>

No additional steps are required.
```
15 changes: 8 additions & 7 deletions packages/opencode/.opencode/commands/pr/fix.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
---
description: Fix PR feedback, push updates, and reply
description: Fix PR feedback or CI failures, push updates, and reply
agent: worker
---

## Goal

Address feedback on a pull request by making fixes and responding to review threads.
Address feedback or CI failures on a pull request by making fixes and responding to review threads.

## Additional Context

Use `<additional-context>` when prioritizing which review feedback to address first and when deciding how much scope to take on in this pass.
Use `<additional-context>` when prioritizing which review feedback or CI failure to address first and when deciding how much scope to take on in this pass.
- Default `/pr/fix` behavior is review-first: show the proposed fix, gather feedback, and loop until the user approves before committing, pushing, or replying on the PR.
- Treat `/pr/fix auto` as the explicit opt-in to skip the approval loop and proceed directly from passing validation to commit, push, and PR replies.

Expand Down Expand Up @@ -60,9 +60,10 @@ Call `kompass_changes_load` with `base: <pr-context.pr.baseRefName>`, `head: <ac
Separate true course corrections from noise or already-resolved feedback:
1. Review `<pr-context.threads>` for open, unresolved conversations
2. Check `<pr-context.reviews>` for state changes (CHANGES_REQUESTED, etc.)
3. Use `<changes>` to understand the current PR diff before deciding what to adjust
4. Prioritize critical issues (bugs, security, broken contracts)
5. Identify which files need changes
3. Include any CI failures, logs, failing check names, or reproduction details provided in `<additional-context>` as actionable feedback
4. Use `<changes>` to understand the current PR diff before deciding what to adjust
5. Prioritize critical issues (bugs, security, broken contracts, failing required checks)
6. Identify which files need changes

Do not blindly follow every suggestion—some may lead you off course.

Expand Down Expand Up @@ -99,7 +100,7 @@ Run the most relevant available validation for the fixes:
- Keep custom answers enabled so the user can provide concrete feedback
- If `<changes-count>` is `0`, ask exactly one `question` with:
- header `Need Feedback`
- question `I did not make any changes for this PR feedback. What should I revise or investigate next?`
- question `I did not make any changes for this PR feedback or CI failure. What should I revise or investigate next?`
- options:
- `Revise` - provide feedback for another pass
- `Stop Here` - stop without committing, pushing, or replying on the PR
Expand Down
3 changes: 3 additions & 0 deletions packages/opencode/.opencode/kompass.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
"learn": {
"enabled": true
},
"loop/pr/fix": {
"enabled": true
},
"merge": {
"enabled": true
},
Expand Down
Loading
Loading